1 class TraceController < ApplicationController
2 before_filter :authorize_web
3 before_filter :authorize, :only => [:api_details, :api_data, :api_create]
6 # Counts and selects pages of GPX traces for various criteria (by user, tags, public etc.).
7 # target_user - if set, specifies the user to fetch traces for. if not set will fetch all traces
8 def list(target_user = nil, action = "list")
9 # from display name, pick up user id if one user's traces only
10 display_name = params[:display_name]
11 if target_user.nil? and !display_name.blank?
12 target_user = User.find(:first, :conditions => [ "display_name = ?", display_name])
17 @title = "Public GPS traces"
18 elsif @user and @user.id == target_user.id
19 @title = "Your GPS traces"
21 @title = "Public GPS traces from #{target_user.display_name}"
24 @title += " tagged with #{params[:tag]}" if params[:tag]
27 # 1 - all traces, logged in = all public traces + all user's (i.e + all mine)
28 # 2 - all traces, not logged in = all public traces
29 # 3 - user's traces, logged in as same user = all user's traces
30 # 4 - user's traces, not logged in as that user = all user's public traces
31 if target_user.nil? # all traces
33 conditions = ["(gpx_files.public = 1 OR gpx_files.user_id = ?)", @user.id] #1
35 conditions = ["gpx_files.public = 1"] #2
38 if @user and @user.id == target_user.id
39 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)
41 conditions = ["gpx_files.public = 1 AND gpx_files.user_id = ?", target_user.id] #4
47 conditions[0] += " AND EXISTS (SELECT * FROM gpx_file_tags AS gft WHERE gft.gpx_id = gpx_files.id AND gft.tag = ?)"
51 conditions[0] += " AND gpx_files.visible = 1"
53 @trace_pages, @traces = paginate(:traces,
54 :include => [:user, :tags],
55 :conditions => conditions,
56 :order => "gpx_files.timestamp DESC",
59 # put together SET of tags across traces, for related links
62 @traces.each do |trace|
63 trace.tags.reload if params[:tag] # if searched by tag, ActiveRecord won't bring back other tags, so do explicitly here
64 trace.tags.each do |tag|
65 tagset[tag.tag] = tag.tag
70 # final helper vars for view
72 @display_name = target_user.display_name if target_user
73 @all_tags = tagset.values
78 list(@user, "mine") unless @user.nil?
80 redirect_to :controller => 'user', :action => 'login', :referer => request.request_uri
85 @trace = Trace.find(params[:id])
88 flash[:notice] = "OH NOES! Trace not found!"
89 redirect_to :controller => 'trace', :action => 'list'
93 @title = "Viewing trace #{@trace.name}"
95 render :nothing => true, :status => :not_found
96 elsif !@trace.public? and @trace.user.id != @user.id
97 render :nothing => true, :status => :forbidden
99 rescue ActiveRecord::RecordNotFound
100 flash[:notice] = "GPX file not found"
101 redirect_to :controller => 'trace', :action => 'list'
105 logger.info(params[:trace][:gpx_file].class.name)
106 if params[:trace][:gpx_file].respond_to?(:read)
107 do_create(params[:trace][:gpx_file], params[:trace][:tagstring],
108 params[:trace][:description], params[:trace][:public])
111 logger.info("id is #{@trace.id}")
112 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."
114 redirect_to :action => 'mine'
117 @trace = Trace.new({:name => "Dummy",
118 :tagstring => params[:trace][:tagstring],
119 :description => params[:trace][:description],
120 :public => params[:trace][:public],
121 :inserted => false, :user => @user,
122 :timestamp => Time.now})
124 @trace.errors.add(:gpx_file, "can't be blank")
129 trace = Trace.find(params[:id])
131 if trace.visible? and (trace.public? or (@user and @user == trace.user))
132 if request.format == Mime::XML
133 send_file(trace.xml_file, :filename => "#{trace.id}.xml", :type => Mime::XML.to_s, :disposition => 'attachment')
135 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
138 render :nothing, :status => :not_found
140 rescue ActiveRecord::RecordNotFound
141 render :nothing => true, :status => :not_found
145 @trace = Trace.find(params[:id])
147 if @user and @trace.user == @user
149 @trace.description = params[:trace][:description]
150 @trace.tagstring = params[:trace][:tagstring]
152 redirect_to :action => 'view'
156 render :nothing, :status => :forbidden
158 rescue ActiveRecord::RecordNotFound
159 render :nothing => true, :status => :not_found
163 trace = Trace.find(params[:id])
165 if @user and trace.user == @user
166 if request.post? and trace.visible?
167 trace.visible = false
169 flash[:notice] = 'Track scheduled for deletion'
170 redirect_to :controller => 'traces', :action => 'mine'
172 render :nothing, :status => :bad_request
175 render :nothing, :status => :forbidden
177 rescue ActiveRecord::RecordNotFound
178 render :nothing => true, :status => :not_found
182 trace = Trace.find(params[:id])
184 if @user and trace.user == @user
185 if request.post? and !trace.public?
188 flash[:notice] = 'Track made public'
189 redirect_to :controller => 'trace', :action => 'view', :id => params[:id]
191 render :nothing, :status => :bad_request
194 render :nothing, :status => :forbidden
196 rescue ActiveRecord::RecordNotFound
197 render :nothing => true, :status => :not_found
201 conditions = ["gpx_files.public = 1"]
203 if params[:display_name]
204 conditions[0] += " AND users.display_name = ?"
205 conditions << params[:display_name]
209 conditions[0] += " AND EXISTS (SELECT * FROM gpx_file_tags AS gft WHERE gft.gpx_id = gpx_files.id AND gft.tag = ?)"
210 conditions << params[:tag]
213 traces = Trace.find(:all, :include => :user, :conditions => conditions,
214 :order => "timestamp DESC", :limit => 20)
216 rss = OSM::GeoRSS.new
218 traces.each do |trace|
219 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)
222 render :text => rss.to_s, :content_type => "application/rss+xml"
226 trace = Trace.find(params[:id])
229 if trace.public? or (@user and @user == trace.user)
230 send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => 'image/gif', :disposition => 'inline')
232 render :nothing, :status => :forbidden
235 render :nothing => true, :status => :not_found
237 rescue ActiveRecord::RecordNotFound
238 render :nothing => true, :status => :not_found
242 trace = Trace.find(params[:id])
245 if trace.public? or (@user and @user == trace.user)
246 send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => 'image/gif', :disposition => 'inline')
248 render :nothing, :status => :forbidden
251 render :nothing => true, :status => :not_found
253 rescue ActiveRecord::RecordNotFound
254 render :nothing => true, :status => :not_found
258 trace = Trace.find(params[:id])
260 if trace.public? or trace.user == @user
261 render :text => trace.to_xml.to_s, :content_type => "text/xml"
263 render :nothing => true, :status => :forbidden
265 rescue ActiveRecord::RecordNotFound
266 render :nothing => true, :status => :not_found
270 trace = Trace.find(params[:id])
272 if trace.public? or trace.user == @user
273 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
275 render :nothing => true, :status => :forbidden
277 rescue ActiveRecord::RecordNotFound
278 render :nothing => true, :status => :not_found
283 do_create(params[:file], params[:tags], params[:description], params[:public])
286 render :text => @trace.id.to_s, :content_type => "text/plain"
288 render :nothing => true, :status => :internal_server_error
290 render :nothing => true, :status => :bad_request
293 render :nothing => true, :status => :method_not_allowed
299 def do_create(file, tags, description, public)
300 name = file.original_filename.gsub(/[^a-zA-Z0-9.]/, '_')
301 filename = "/tmp/#{rand}"
303 File.open(filename, "w") { |f| f.write(file.read) }
305 @trace = Trace.new({:name => name, :tagstring => tags,
306 :description => description, :public => public})
307 @trace.inserted = false
309 @trace.timestamp = Time.now
312 FileUtils.mv(filename, @trace.trace_name)
314 FileUtils.rm_f(filename)