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])
86 @title = "Viewing trace #{@trace.name}"
88 render :nothing => true, :status => :not_found
89 elsif !@trace.public? and @trace.user.id != @user.id
90 render :nothing => true, :status => :forbidden
92 rescue ActiveRecord::RecordNotFound
93 render :nothing => true, :status => :not_found
97 name = params[:trace][:gpx_file].original_filename.gsub(/[^a-zA-Z0-9.]/, '_') # This makes sure filenames are sane
99 do_create(name, params[:trace][:tagstring], params[:trace][:description], params[:trace][:public]) do |f|
100 f.write(params[:trace][:gpx_file].read)
104 logger.info("id is #{@trace.id}")
105 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."
107 redirect_to :action => 'mine'
112 trace = Trace.find(params[:id])
114 if trace.visible? and (trace.public? or (@user and @user == trace.user))
115 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
117 render :nothing, :status => :not_found
119 rescue ActiveRecord::RecordNotFound
120 render :nothing => true, :status => :not_found
124 @trace = Trace.find(params[:id])
126 if @user and @trace.user == @user
128 @trace.description = params[:trace][:description]
129 @trace.tagstring = params[:trace][:tagstring]
131 redirect_to :action => 'view'
135 render :nothing, :status => :forbidden
137 rescue ActiveRecord::RecordNotFound
138 render :nothing => true, :status => :not_found
142 trace = Trace.find(params[:id])
144 if @user and trace.user == @user
145 if request.post? and trace.visible?
146 trace.visible = false
148 flash[:notice] = 'Track scheduled for deletion'
149 redirect_to :controller => 'traces', :action => 'mine'
151 render :nothing, :status => :bad_request
154 render :nothing, :status => :forbidden
156 rescue ActiveRecord::RecordNotFound
157 render :nothing => true, :status => :not_found
161 trace = Trace.find(params[:id])
163 if @user and trace.user == @user
164 if request.post? and !trace.public?
167 flash[:notice] = 'Track made public'
168 redirect_to :controller => 'trace', :action => 'view', :id => params[:id]
170 render :nothing, :status => :bad_request
173 render :nothing, :status => :forbidden
175 rescue ActiveRecord::RecordNotFound
176 render :nothing => true, :status => :not_found
180 conditions = ["gpx_files.public = 1"]
182 if params[:display_name]
183 conditions[0] += " AND users.display_name = ?"
184 conditions << params[:display_name]
188 conditions[0] += " AND EXISTS (SELECT * FROM gpx_file_tags AS gft WHERE gft.gpx_id = gpx_files.id AND gft.tag = ?)"
189 conditions << params[:tag]
192 traces = Trace.find(:all, :include => :user, :conditions => conditions,
193 :order => "timestamp DESC", :limit => 20)
195 rss = OSM::GeoRSS.new
197 traces.each do |trace|
198 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)
201 render :text => rss.to_s, :content_type => "application/rss+xml"
205 trace = Trace.find(params[:id])
208 if trace.public? or (@user and @user == trace.user)
209 send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => 'image/gif', :disposition => 'inline')
211 render :nothing, :status => :forbidden
214 render :nothing => true, :status => :not_found
216 rescue ActiveRecord::RecordNotFound
217 render :nothing => true, :status => :not_found
221 trace = Trace.find(params[:id])
224 if trace.public? or (@user and @user == trace.user)
225 send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.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])
239 if trace.public? or trace.user == @user
240 render :text => trace.to_xml.to_s, :content_type => "text/xml"
242 render :nothing => true, :status => :forbidden
244 rescue ActiveRecord::RecordNotFound
245 render :nothing => true, :status => :not_found
249 trace = Trace.find(params[:id])
251 if trace.public? or trace.user == @user
252 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
254 render :nothing => true, :status => :forbidden
256 rescue ActiveRecord::RecordNotFound
257 render :nothing => true, :status => :not_found
262 name = params[:file].original_filename.gsub(/[^a-zA-Z0-9.]/, '_') # This makes sure filenames are sane
264 do_create(name, params[:tags], params[:description], params[:public]) do |f|
265 f.write(params[:file].read)
269 render :text => @trace.id.to_s, :content_type => "text/plain"
271 render :nothing => true, :status => :internal_server_error
273 render :nothing => true, :status => :bad_request
276 render :nothing => true, :status => :method_not_allowed
282 def do_create(name, tags, description, public)
283 filename = "/tmp/#{rand}"
285 File.open(filename, "w") { |f| yield f }
287 @trace = Trace.new({:name => name, :tagstring => tags,
288 :description => description, :public => public})
289 @trace.inserted = false
291 @trace.timestamp = Time.now
294 File.rename(filename, @trace.trace_name)
296 FileUtils.rm_f(filename)