]> git.openstreetmap.org Git - rails.git/commitdiff
Parse each GPX file in an archive separately
authorTom Hughes <tom@compton.nu>
Tue, 11 Jun 2019 11:57:00 +0000 (12:57 +0100)
committerTom Hughes <tom@compton.nu>
Tue, 11 Jun 2019 11:57:00 +0000 (12:57 +0100)
Fixes #2253

Gemfile
Gemfile.lock
app/models/trace.rb
lib/gpx.rb

diff --git a/Gemfile b/Gemfile
index dc1615ffc47508cecd75556cd260902d0a366b46..0e02c231172ab049fd3050ab599727388feb884e 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -118,6 +118,9 @@ gem "canonical-rails"
 gem "logstasher"
 
 # Used to generate images for traces
 gem "logstasher"
 
 # Used to generate images for traces
+gem "mimemagic"
+gem "ffi-libarchive"
+gem "bzip2-ffi"
 gem "gd2-ffij", ">= 0.4.0"
 
 # Used for browser detection
 gem "gd2-ffij", ">= 0.4.0"
 
 # Used for browser detection
index 4798189389fd0e70d89c2011ad14788e2c14c9df..f9a0af7d4ed2ce9e2108be9ced7cd3b77217c3ba 100644 (file)
@@ -79,6 +79,8 @@ GEM
       msgpack (~> 1.0)
     browser (2.5.3)
     builder (3.2.3)
       msgpack (~> 1.0)
     browser (2.5.3)
     builder (3.2.3)
+    bzip2-ffi (1.0.0)
+      ffi (~> 1.0)
     cancancan (3.0.1)
     canonical-rails (0.2.5)
       rails (>= 4.1, < 6.1)
     cancancan (3.0.1)
     canonical-rails (0.2.5)
       rails (>= 4.1, < 6.1)
@@ -177,6 +179,8 @@ GEM
     faraday (0.15.4)
       multipart-post (>= 1.2, < 3)
     ffi (1.11.1)
     faraday (0.15.4)
       multipart-post (>= 1.2, < 3)
     ffi (1.11.1)
+    ffi-libarchive (0.4.6)
+      ffi (~> 1.0)
     fspath (3.1.1)
     gd2-ffij (0.4.0)
       ffi (>= 1.0.0)
     fspath (3.1.1)
     gd2-ffij (0.4.0)
       ffi (>= 1.0.0)
@@ -455,6 +459,7 @@ DEPENDENCIES
   binding_of_caller
   bootsnap (>= 1.1.0)
   browser
   binding_of_caller
   bootsnap (>= 1.1.0)
   browser
+  bzip2-ffi
   cancancan
   canonical-rails
   capybara (~> 2.13)
   cancancan
   canonical-rails
   capybara (~> 2.13)
@@ -471,6 +476,7 @@ DEPENDENCIES
   factory_bot_rails
   fakefs
   faraday
   factory_bot_rails
   fakefs
   faraday
+  ffi-libarchive
   gd2-ffij (>= 0.4.0)
   geoip
   htmlentities
   gd2-ffij (>= 0.4.0)
   geoip
   htmlentities
@@ -485,6 +491,7 @@ DEPENDENCIES
   libxml-ruby (>= 2.0.5)
   listen
   logstasher
   libxml-ruby (>= 2.0.5)
   listen
   logstasher
+  mimemagic
   minitest (~> 5.1)
   oauth-plugin (>= 0.5.1)
   omniauth
   minitest (~> 5.1)
   oauth-plugin (>= 0.5.1)
   omniauth
index 7c97b4e96b64cc2c672ebafb9ebd4511b6a69dce..9d710d1ceca99b540065aa6822be470c40cb3702 100644 (file)
@@ -275,7 +275,7 @@ class Trace < ActiveRecord::Base
   def import
     logger.info("GPX Import importing #{name} (#{id}) from #{user.email}")
 
   def import
     logger.info("GPX Import importing #{name} (#{id}) from #{user.email}")
 
-    gpx = ::GPX::File.new(xml_file)
+    gpx = ::GPX::File.new(trace_name)
 
     f_lat = 0
     f_lon = 0
 
     f_lat = 0
     f_lon = 0
index 1b1c17ac7876f3bad65a40ba476daa6201ee0d55..068b8481563dad0ae568a00d294eefb88cc71fda 100644 (file)
@@ -12,17 +12,7 @@ module GPX
       @file = file
     end
 
       @file = file
     end
 
-    def points
-      return enum_for(:points) unless block_given?
-
-      @possible_points = 0
-      @actual_points = 0
-      @tracksegs = 0
-
-      @file.rewind
-
-      reader = XML::Reader.io(@file)
-
+    def parse_file(reader)
       point = nil
 
       while reader.read
       point = nil
 
       while reader.read
@@ -47,6 +37,29 @@ module GPX
       end
     end
 
       end
     end
 
+    def points(&block)
+      return enum_for(:points) unless block_given?
+
+      @possible_points = 0
+      @actual_points = 0
+      @tracksegs = 0
+
+      begin
+        Archive::Reader.open_filename(@file).each_entry_with_data do |_entry, data|
+          parse_file(XML::Reader.string(data), &block)
+        end
+      rescue Archive::Error
+        io = ::File.open(@file)
+
+        case MimeMagic.by_magic(io).type
+        when "application/gzip" then io = Zlib::GzipReader.open(@file)
+        when "application/x-bzip" then io = Bzip2::FFI::Reader.open(@file)
+        end
+
+        parse_file(XML::Reader.io(io), &block)
+      end
+    end
+
     def picture(min_lat, min_lon, max_lat, max_lon, num_points)
       nframes = 10
       width = 250
     def picture(min_lat, min_lon, max_lat, max_lon, num_points)
       nframes = 10
       width = 250