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])
87 if @trace and @trace.visible? and
88 (@trace.public? or @trace.user.id == @user.id)
89 @title = "Viewing trace #{@trace.name}"
91 flash[:notice] = "Trace not found!"
92 redirect_to :controller => 'trace', :action => 'list'
94 rescue ActiveRecord::RecordNotFound
95 flash[:notice] = "Trace not found!"
96 redirect_to :controller => 'trace', :action => 'list'
100 logger.info(params[:trace][:gpx_file].class.name)
101 if params[:trace][:gpx_file].respond_to?(:read)
102 do_create(params[:trace][:gpx_file], params[:trace][:tagstring],
103 params[:trace][:description], params[:trace][:public])
106 logger.info("id is #{@trace.id}")
107 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."
109 redirect_to :action => 'mine'
112 @trace = Trace.new({:name => "Dummy",
113 :tagstring => params[:trace][:tagstring],
114 :description => params[:trace][:description],
115 :public => params[:trace][:public],
116 :inserted => false, :user => @user,
117 :timestamp => Time.now})
119 @trace.errors.add(:gpx_file, "can't be blank")
124 trace = Trace.find(params[:id])
126 if trace.visible? and (trace.public? or (@user and @user == trace.user))
127 if request.format == Mime::XML
128 send_file(trace.xml_file, :filename => "#{trace.id}.xml", :type => Mime::XML.to_s, :disposition => 'attachment')
130 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
133 render :nothing, :status => :not_found
135 rescue ActiveRecord::RecordNotFound
136 render :nothing => true, :status => :not_found
140 @trace = Trace.find(params[:id])
142 if @user and @trace.user == @user
144 @trace.description = params[:trace][:description]
145 @trace.tagstring = params[:trace][:tagstring]
147 redirect_to :action => 'view'
151 render :nothing, :status => :forbidden
153 rescue ActiveRecord::RecordNotFound
154 render :nothing => true, :status => :not_found
158 trace = Trace.find(params[:id])
160 if @user and trace.user == @user
161 if request.post? and trace.visible?
162 trace.visible = false
164 flash[:notice] = 'Track scheduled for deletion'
165 redirect_to :controller => 'traces', :action => 'mine'
167 render :nothing, :status => :bad_request
170 render :nothing, :status => :forbidden
172 rescue ActiveRecord::RecordNotFound
173 render :nothing => true, :status => :not_found
177 trace = Trace.find(params[:id])
179 if @user and trace.user == @user
180 if request.post? and !trace.public?
183 flash[:notice] = 'Track made public'
184 redirect_to :controller => 'trace', :action => 'view', :id => params[:id]
186 render :nothing, :status => :bad_request
189 render :nothing, :status => :forbidden
191 rescue ActiveRecord::RecordNotFound
192 render :nothing => true, :status => :not_found
196 conditions = ["gpx_files.public = 1"]
198 if params[:display_name]
199 conditions[0] += " AND users.display_name = ?"
200 conditions << params[:display_name]
204 conditions[0] += " AND EXISTS (SELECT * FROM gpx_file_tags AS gft WHERE gft.gpx_id = gpx_files.id AND gft.tag = ?)"
205 conditions << params[:tag]
208 traces = Trace.find(:all, :include => :user, :conditions => conditions,
209 :order => "timestamp DESC", :limit => 20)
211 rss = OSM::GeoRSS.new
213 traces.each do |trace|
214 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)
217 render :text => rss.to_s, :content_type => "application/rss+xml"
221 trace = Trace.find(params[:id])
224 if trace.public? or (@user and @user == trace.user)
225 send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => 'image/gif', :disposition => 'inline')
227 render :nothing, :status => :forbidden
230 render :nothing => true, :status => :not_found
232 rescue ActiveRecord::RecordNotFound
233 render :nothing => true, :status => :not_found
237 trace = Trace.find(params[:id])
240 if trace.public? or (@user and @user == trace.user)
241 send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => 'image/gif', :disposition => 'inline')
243 render :nothing, :status => :forbidden
246 render :nothing => true, :status => :not_found
248 rescue ActiveRecord::RecordNotFound
249 render :nothing => true, :status => :not_found
253 trace = Trace.find(params[:id])
255 if trace.public? or trace.user == @user
256 render :text => trace.to_xml.to_s, :content_type => "text/xml"
258 render :nothing => true, :status => :forbidden
260 rescue ActiveRecord::RecordNotFound
261 render :nothing => true, :status => :not_found
265 trace = Trace.find(params[:id])
267 if trace.public? or trace.user == @user
268 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
270 render :nothing => true, :status => :forbidden
272 rescue ActiveRecord::RecordNotFound
273 render :nothing => true, :status => :not_found
278 do_create(params[:file], params[:tags], params[:description], params[:public])
281 render :text => @trace.id.to_s, :content_type => "text/plain"
283 render :nothing => true, :status => :internal_server_error
285 render :nothing => true, :status => :bad_request
288 render :nothing => true, :status => :method_not_allowed
294 def do_create(file, tags, description, public)
295 name = file.original_filename.gsub(/[^a-zA-Z0-9.]/, '_')
296 filename = "/tmp/#{rand}"
298 File.open(filename, "w") { |f| f.write(file.read) }
300 @trace = Trace.new({:name => name, :tagstring => tags,
301 :description => description, :public => public})
302 @trace.inserted = false
304 @trace.timestamp = Time.now
307 FileUtils.mv(filename, @trace.trace_name)
309 FileUtils.rm_f(filename)