1 class TraceController < ApplicationController
4 before_filter :authorize_web
5 before_filter :authorize, :only => [:api_details, :api_data, :api_create]
6 before_filter :check_database_availability, :except => [:api_details, :api_data, :api_create]
7 before_filter :check_read_availability, :only => [:api_details, :api_data, :api_create]
9 # Counts and selects pages of GPX traces for various criteria (by user, tags, public etc.).
10 # target_user - if set, specifies the user to fetch traces for. if not set will fetch all traces
11 def list(target_user = nil, action = "list")
12 # from display name, pick up user id if one user's traces only
13 display_name = params[:display_name]
14 if target_user.nil? and !display_name.blank?
15 target_user = User.find(:first, :conditions => [ "visible = ? and display_name = ?", true, display_name])
20 @title = "Public GPS traces"
21 elsif @user and @user == target_user
22 @title = "Your GPS traces"
24 @title = "Public GPS traces from #{target_user.display_name}"
27 @title += " tagged with #{params[:tag]}" if params[:tag]
30 # 1 - all traces, logged in = all public traces + all user's (i.e + all mine)
31 # 2 - all traces, not logged in = all public traces
32 # 3 - user's traces, logged in as same user = all user's traces
33 # 4 - user's traces, not logged in as that user = all user's public traces
34 if target_user.nil? # all traces
36 conditions = ["(gpx_files.public = ? OR gpx_files.user_id = ?)", true, @user.id] #1
38 conditions = ["gpx_files.public = ?", true] #2
41 if @user and @user == target_user
42 conditions = ["gpx_files.user_id = ?", @user.id] #3 (check vs user id, so no join + can't pick up non-public traces by changing name)
44 conditions = ["gpx_files.public = ? AND gpx_files.user_id = ?", true, target_user.id] #4
50 conditions[0] += " AND EXISTS (SELECT * FROM gpx_file_tags AS gft WHERE gft.gpx_id = gpx_files.id AND gft.tag = ?)"
54 conditions[0] += " AND gpx_files.visible = ?"
57 @trace_pages, @traces = paginate(:traces,
58 :include => [:user, :tags],
59 :conditions => conditions,
60 :order => "gpx_files.timestamp DESC",
63 # put together SET of tags across traces, for related links
66 @traces.each do |trace|
67 trace.tags.reload if params[:tag] # if searched by tag, ActiveRecord won't bring back other tags, so do explicitly here
68 trace.tags.each do |tag|
69 tagset[tag.tag] = tag.tag
74 # final helper vars for view
76 @display_name = target_user.display_name if target_user
77 @all_tags = tagset.values
83 unless @user.trace_public_default.nil?
88 list(@user, "mine") unless @user.nil?
90 redirect_to :controller => 'user', :action => 'login', :referer => request.request_uri
95 @trace = Trace.find(params[:id])
97 if @trace and @trace.visible? and
98 (@trace.public? or @trace.user == @user)
99 @title = "Viewing trace #{@trace.name}"
101 flash[:notice] = "Trace not found!"
102 redirect_to :controller => 'trace', :action => 'list'
104 rescue ActiveRecord::RecordNotFound
105 flash[:notice] = "Trace not found!"
106 redirect_to :controller => 'trace', :action => 'list'
110 logger.info(params[:trace][:gpx_file].class.name)
111 if params[:trace][:gpx_file].respond_to?(:read)
112 do_create(params[:trace][:gpx_file], params[:trace][:tagstring],
113 params[:trace][:description], params[:trace][:public])
116 logger.info("id is #{@trace.id}")
117 flash[:notice] = "Your GPX file has been uploaded and is awaiting insertion in to the database. This will usually happen within half an hour, and an email will be sent to you on completion."
119 redirect_to :action => 'mine'
122 @trace = Trace.new({:name => "Dummy",
123 :tagstring => params[:trace][:tagstring],
124 :description => params[:trace][:description],
125 :public => params[:trace][:public],
126 :inserted => false, :user => @user,
127 :timestamp => Time.now})
129 @trace.errors.add(:gpx_file, "can't be blank")
134 trace = Trace.find(params[:id])
136 if trace.visible? and (trace.public? or (@user and @user == trace.user))
137 if request.format == Mime::XML
138 send_file(trace.xml_file, :filename => "#{trace.id}.xml", :type => Mime::XML.to_s, :disposition => 'attachment')
140 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
143 render :nothing, :status => :not_found
145 rescue ActiveRecord::RecordNotFound
146 render :nothing => true, :status => :not_found
150 @trace = Trace.find(params[:id])
152 if @user and @trace.user == @user
154 @trace.description = params[:trace][:description]
155 @trace.tagstring = params[:trace][:tagstring]
157 redirect_to :action => 'view'
161 render :nothing, :status => :forbidden
163 rescue ActiveRecord::RecordNotFound
164 render :nothing => true, :status => :not_found
168 trace = Trace.find(params[:id])
170 if @user and trace.user == @user
171 if request.post? and trace.visible?
172 trace.visible = false
174 flash[:notice] = 'Track scheduled for deletion'
175 redirect_to :controller => 'traces', :action => 'mine'
177 render :nothing, :status => :bad_request
180 render :nothing, :status => :forbidden
182 rescue ActiveRecord::RecordNotFound
183 render :nothing => true, :status => :not_found
187 trace = Trace.find(params[:id])
189 if @user and trace.user == @user
190 if request.post? and !trace.public?
193 flash[:notice] = 'Track made public'
194 redirect_to :controller => 'trace', :action => 'view', :id => params[:id]
196 render :nothing, :status => :bad_request
199 render :nothing, :status => :forbidden
201 rescue ActiveRecord::RecordNotFound
202 render :nothing => true, :status => :not_found
206 conditions = ["gpx_files.public = ?", true]
208 if params[:display_name]
209 conditions[0] += " AND users.display_name = ?"
210 conditions << params[:display_name]
214 conditions[0] += " AND EXISTS (SELECT * FROM gpx_file_tags AS gft WHERE gft.gpx_id = gpx_files.id AND gft.tag = ?)"
215 conditions << params[:tag]
218 traces = Trace.find(:all, :include => :user, :conditions => conditions,
219 :order => "timestamp DESC", :limit => 20)
221 rss = OSM::GeoRSS.new
223 traces.each do |trace|
224 rss.add(trace.latitude, trace.longitude, trace.name, trace.user.display_name, url_for({:controller => 'trace', :action => 'view', :id => trace.id, :display_name => trace.user.display_name}), "<img src='#{url_for({:controller => 'trace', :action => 'icon', :id => trace.id, :user_login => trace.user.display_name})}'> GPX file with #{trace.size} points from #{trace.user.display_name}", trace.timestamp)
227 render :text => rss.to_s, :content_type => "application/rss+xml"
231 trace = Trace.find(params[:id])
234 if trace.public? or (@user and @user == trace.user)
235 send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => 'image/gif', :disposition => 'inline')
237 render :nothing, :status => :forbidden
240 render :nothing => true, :status => :not_found
242 rescue ActiveRecord::RecordNotFound
243 render :nothing => true, :status => :not_found
247 trace = Trace.find(params[:id])
250 if trace.public? or (@user and @user == trace.user)
251 send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => 'image/gif', :disposition => 'inline')
253 render :nothing, :status => :forbidden
256 render :nothing => true, :status => :not_found
258 rescue ActiveRecord::RecordNotFound
259 render :nothing => true, :status => :not_found
263 trace = Trace.find(params[:id])
265 if trace.public? or trace.user == @user
266 render :text => trace.to_xml.to_s, :content_type => "text/xml"
268 render :nothing => true, :status => :forbidden
270 rescue ActiveRecord::RecordNotFound
271 render :nothing => true, :status => :not_found
275 trace = Trace.find(params[:id])
277 if trace.public? or trace.user == @user
278 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
280 render :nothing => true, :status => :forbidden
282 rescue ActiveRecord::RecordNotFound
283 render :nothing => true, :status => :not_found
288 do_create(params[:file], params[:tags], params[:description], params[:public])
291 render :text => @trace.id.to_s, :content_type => "text/plain"
293 render :nothing => true, :status => :internal_server_error
295 render :nothing => true, :status => :bad_request
298 render :nothing => true, :status => :method_not_allowed
304 def do_create(file, tags, description, public)
305 name = file.original_filename.gsub(/[^a-zA-Z0-9.]/, '_')
306 filename = "/tmp/#{rand}"
308 File.open(filename, "w") { |f| f.write(file.read) }
310 @trace = Trace.new({:name => name, :tagstring => tags,
311 :description => description, :public => public})
312 @trace.inserted = false
314 @trace.timestamp = Time.now
317 FileUtils.mv(filename, @trace.trace_name)
319 FileUtils.rm_f(filename)
322 # Finally save whether the user marked the trace as being public
324 if @user.trace_public_default.nil?
325 @user.preferences.create(:k => "gps.trace.public", :v => "default")
328 pref = @user.trace_public_default
329 pref.destroy unless pref.nil?