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
127 if request.post? and trace.visible?
128 trace.visible = false
130 flash[:notice] = 'Track scheduled for deletion'
131 redirect_to :controller => 'traces', :action => 'mine'
133 render :nothing, :status => :bad_request
136 render :nothing, :status => :forbidden
138 rescue ActiveRecord::RecordNotFound
139 render :nothing => true, :status => :not_found
143 trace = Trace.find(params[:id])
145 if @user and trace.user == @user
146 if request.post? and !trace.public?
149 flash[:notice] = 'Track made public'
150 redirect_to :controller => 'trace', :action => 'view', :id => params[:id]
152 render :nothing, :status => :bad_request
155 render :nothing, :status => :forbidden
157 rescue ActiveRecord::RecordNotFound
158 render :nothing => true, :status => :not_found
162 conditions = ["gpx_files.public = 1"]
164 if params[:display_name]
165 conditions[0] += " AND users.display_name = ?"
166 conditions << params[:display_name]
170 conditions[0] += " AND EXISTS (SELECT * FROM gpx_file_tags AS gft WHERE gft.gpx_id = gpx_files.id AND gft.tag = ?)"
171 conditions << params[:tag]
174 traces = Trace.find(:all, :include => :user, :conditions => conditions,
175 :order => "timestamp DESC", :limit => 20)
177 rss = OSM::GeoRSS.new
179 traces.each do |trace|
180 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)
183 render :text => rss.to_s, :content_type => "application/rss+xml"
187 trace = Trace.find(params[:id])
190 if trace.public? or (@user and @user == trace.user)
191 send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => 'image/gif', :disposition => 'inline')
193 render :nothing, :status => :forbidden
196 render :nothing => true, :status => :not_found
198 rescue ActiveRecord::RecordNotFound
199 render :nothing => true, :status => :not_found
203 trace = Trace.find(params[:id])
206 if trace.public? or (@user and @user == trace.user)
207 send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => 'image/gif', :disposition => 'inline')
209 render :nothing, :status => :forbidden
212 render :nothing => true, :status => :not_found
214 rescue ActiveRecord::RecordNotFound
215 render :nothing => true, :status => :not_found
219 trace = Trace.find(params[:id])
221 if trace.public? or trace.user == @user
222 render :text => trace.to_xml.to_s, :content_type => "text/xml"
224 render :nothing => true, :status => :forbidden
226 rescue ActiveRecord::RecordNotFound
227 render :nothing => true, :status => :not_found
231 trace = Trace.find(params[:id])
233 if trace.public? or trace.user == @user
234 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
236 render :nothing => true, :status => :forbidden
238 rescue ActiveRecord::RecordNotFound
239 render :nothing => true, :status => :not_found
244 name = params[:file].original_filename.gsub(/[^a-zA-Z0-9.]/, '_') # This makes sure filenames are sane
246 do_create(name, params[:tags], params[:description], params[:public]) do |f|
247 f.write(params[:file].read)
251 render :text => @trace.id.to_s, :content_type => "text/plain"
253 render :nothing => true, :status => :internal_server_error
255 render :nothing => true, :status => :bad_request
258 render :nothing => true, :status => :method_not_allowed
264 def do_create(name, tags, description, public)
265 filename = "/tmp/#{rand}"
267 File.open(filename, "w") { |f| yield f }
269 @trace = Trace.new({:name => name, :tagstring => tags,
270 :description => description, :public => public})
271 @trace.inserted = false
273 @trace.timestamp = Time.now
276 File.rename(filename, @trace.trace_name)
278 FileUtils.rm_f(filename)