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 logger.info(params[:trace][:gpx_file].class.name)
98 if params[:trace][:gpx_file].respond_to?(:read)
99 do_create(params[:trace][:gpx_file], params[:trace][:tagstring],
100 params[:trace][:description], params[:trace][:public])
103 logger.info("id is #{@trace.id}")
104 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."
106 redirect_to :action => 'mine'
109 @trace = Trace.new({:name => "Dummy",
110 :tagstring => params[:trace][:tagstring],
111 :description => params[:trace][:description],
112 :public => params[:trace][:public],
113 :inserted => false, :user => @user,
114 :timestamp => Time.now})
116 @trace.errors.add(:gpx_file, "can't be blank")
121 trace = Trace.find(params[:id])
123 if trace.visible? and (trace.public? or (@user and @user == trace.user))
124 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
126 render :nothing, :status => :not_found
128 rescue ActiveRecord::RecordNotFound
129 render :nothing => true, :status => :not_found
133 @trace = Trace.find(params[:id])
135 if @user and @trace.user == @user
137 @trace.description = params[:trace][:description]
138 @trace.tagstring = params[:trace][:tagstring]
140 redirect_to :action => 'view'
144 render :nothing, :status => :forbidden
146 rescue ActiveRecord::RecordNotFound
147 render :nothing => true, :status => :not_found
151 trace = Trace.find(params[:id])
153 if @user and trace.user == @user
154 if request.post? and trace.visible?
155 trace.visible = false
157 flash[:notice] = 'Track scheduled for deletion'
158 redirect_to :controller => 'traces', :action => 'mine'
160 render :nothing, :status => :bad_request
163 render :nothing, :status => :forbidden
165 rescue ActiveRecord::RecordNotFound
166 render :nothing => true, :status => :not_found
170 trace = Trace.find(params[:id])
172 if @user and trace.user == @user
173 if request.post? and !trace.public?
176 flash[:notice] = 'Track made public'
177 redirect_to :controller => 'trace', :action => 'view', :id => params[:id]
179 render :nothing, :status => :bad_request
182 render :nothing, :status => :forbidden
184 rescue ActiveRecord::RecordNotFound
185 render :nothing => true, :status => :not_found
189 conditions = ["gpx_files.public = 1"]
191 if params[:display_name]
192 conditions[0] += " AND users.display_name = ?"
193 conditions << params[:display_name]
197 conditions[0] += " AND EXISTS (SELECT * FROM gpx_file_tags AS gft WHERE gft.gpx_id = gpx_files.id AND gft.tag = ?)"
198 conditions << params[:tag]
201 traces = Trace.find(:all, :include => :user, :conditions => conditions,
202 :order => "timestamp DESC", :limit => 20)
204 rss = OSM::GeoRSS.new
206 traces.each do |trace|
207 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)
210 render :text => rss.to_s, :content_type => "application/rss+xml"
214 trace = Trace.find(params[:id])
217 if trace.public? or (@user and @user == trace.user)
218 send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => 'image/gif', :disposition => 'inline')
220 render :nothing, :status => :forbidden
223 render :nothing => true, :status => :not_found
225 rescue ActiveRecord::RecordNotFound
226 render :nothing => true, :status => :not_found
230 trace = Trace.find(params[:id])
233 if trace.public? or (@user and @user == trace.user)
234 send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => 'image/gif', :disposition => 'inline')
236 render :nothing, :status => :forbidden
239 render :nothing => true, :status => :not_found
241 rescue ActiveRecord::RecordNotFound
242 render :nothing => true, :status => :not_found
246 trace = Trace.find(params[:id])
248 if trace.public? or trace.user == @user
249 render :text => trace.to_xml.to_s, :content_type => "text/xml"
251 render :nothing => true, :status => :forbidden
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 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
263 render :nothing => true, :status => :forbidden
265 rescue ActiveRecord::RecordNotFound
266 render :nothing => true, :status => :not_found
271 do_create(params[:file], params[:tags], params[:description], params[:public])
274 render :text => @trace.id.to_s, :content_type => "text/plain"
276 render :nothing => true, :status => :internal_server_error
278 render :nothing => true, :status => :bad_request
281 render :nothing => true, :status => :method_not_allowed
287 def do_create(file, tags, description, public)
288 name = file.original_filename.gsub(/[^a-zA-Z0-9.]/, '_')
289 filename = "/tmp/#{rand}"
291 File.open(filename, "w") { |f| f.write(file.read) }
293 @trace = Trace.new({:name => name, :tagstring => tags,
294 :description => description, :public => public})
295 @trace.inserted = false
297 @trace.timestamp = Time.now
300 File.rename(filename, @trace.trace_name)
302 FileUtils.rm_f(filename)