1 class TraceController < ApplicationController
4 before_filter :authorize_web
5 before_filter :authorize, :only => [:api_details, :api_data, :api_create]
6 before_filter :check_database_availability, :except => [:api_details, :api_data, :api_create]
7 before_filter :check_read_availability, :only => [:api_details, :api_data, :api_create]
9 # Counts and selects pages of GPX traces for various criteria (by user, tags, public etc.).
10 # target_user - if set, specifies the user to fetch traces for. if not set will fetch all traces
11 def list(target_user = nil, action = "list")
12 # from display name, pick up user id if one user's traces only
13 display_name = params[:display_name]
14 if target_user.nil? and !display_name.blank?
15 target_user = User.find(:first, :conditions => [ "visible = ? and display_name = ?", true, display_name])
20 @title = "Public GPS traces"
21 elsif @user and @user == target_user
22 @title = "Your GPS traces"
24 @title = "Public GPS traces from #{target_user.display_name}"
27 @title += " tagged with #{params[:tag]}" if params[:tag]
30 # 1 - all traces, logged in = all public traces + all user's (i.e + all mine)
31 # 2 - all traces, not logged in = all public traces
32 # 3 - user's traces, logged in as same user = all user's traces
33 # 4 - user's traces, not logged in as that user = all user's public traces
34 if target_user.nil? # all traces
36 conditions = ["(gpx_files.public = ? OR gpx_files.user_id = ?)", true, @user.id] #1
38 conditions = ["gpx_files.public = ?", true] #2
41 if @user and @user == target_user
42 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)
44 conditions = ["gpx_files.public = ? AND gpx_files.user_id = ?", true, target_user.id] #4
50 conditions[0] += " AND EXISTS (SELECT * FROM gpx_file_tags AS gft WHERE gft.gpx_id = gpx_files.id AND gft.tag = ?)"
54 conditions[0] += " AND gpx_files.visible = ?"
57 @trace_pages, @traces = paginate(:traces,
58 :include => [:user, :tags],
59 :conditions => conditions,
60 :order => "gpx_files.timestamp DESC",
63 # put together SET of tags across traces, for related links
66 @traces.each do |trace|
67 trace.tags.reload if params[:tag] # if searched by tag, ActiveRecord won't bring back other tags, so do explicitly here
68 trace.tags.each do |tag|
69 tagset[tag.tag] = tag.tag
74 # final helper vars for view
76 @display_name = target_user.display_name if target_user
77 @all_tags = tagset.values
82 list(@user, "mine") unless @user.nil?
84 redirect_to :controller => 'user', :action => 'login', :referer => request.request_uri
89 @trace = Trace.find(params[:id])
91 if @trace and @trace.visible? and
92 (@trace.public? or @trace.user == @user)
93 @title = "Viewing trace #{@trace.name}"
95 flash[:notice] = "Trace not found!"
96 redirect_to :controller => 'trace', :action => 'list'
98 rescue ActiveRecord::RecordNotFound
99 flash[:notice] = "Trace not found!"
100 redirect_to :controller => 'trace', :action => 'list'
104 logger.info(params[:trace][:gpx_file].class.name)
105 if params[:trace][:gpx_file].respond_to?(:read)
106 do_create(params[:trace][:gpx_file], params[:trace][:tagstring],
107 params[:trace][:description], params[:trace][:public])
110 logger.info("id is #{@trace.id}")
111 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."
113 redirect_to :action => 'mine'
116 @trace = Trace.new({:name => "Dummy",
117 :tagstring => params[:trace][:tagstring],
118 :description => params[:trace][:description],
119 :public => params[:trace][:public],
120 :inserted => false, :user => @user,
121 :timestamp => Time.now})
123 @trace.errors.add(:gpx_file, "can't be blank")
128 trace = Trace.find(params[:id])
130 if trace.visible? and (trace.public? or (@user and @user == trace.user))
131 if request.format == Mime::XML
132 send_file(trace.xml_file, :filename => "#{trace.id}.xml", :type => Mime::XML.to_s, :disposition => 'attachment')
134 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
137 render :nothing, :status => :not_found
139 rescue ActiveRecord::RecordNotFound
140 render :nothing => true, :status => :not_found
144 @trace = Trace.find(params[:id])
146 if @user and @trace.user == @user
148 @trace.description = params[:trace][:description]
149 @trace.tagstring = params[:trace][:tagstring]
151 redirect_to :action => 'view'
155 render :nothing, :status => :forbidden
157 rescue ActiveRecord::RecordNotFound
158 render :nothing => true, :status => :not_found
162 trace = Trace.find(params[:id])
164 if @user and trace.user == @user
165 if request.post? and trace.visible?
166 trace.visible = false
168 flash[:notice] = 'Track scheduled for deletion'
169 redirect_to :controller => 'traces', :action => 'mine'
171 render :nothing, :status => :bad_request
174 render :nothing, :status => :forbidden
176 rescue ActiveRecord::RecordNotFound
177 render :nothing => true, :status => :not_found
181 trace = Trace.find(params[:id])
183 if @user and trace.user == @user
184 if request.post? and !trace.public?
187 flash[:notice] = 'Track made public'
188 redirect_to :controller => 'trace', :action => 'view', :id => params[:id]
190 render :nothing, :status => :bad_request
193 render :nothing, :status => :forbidden
195 rescue ActiveRecord::RecordNotFound
196 render :nothing => true, :status => :not_found
200 conditions = ["gpx_files.public = ?", true]
202 if params[:display_name]
203 conditions[0] += " AND users.display_name = ?"
204 conditions << params[:display_name]
208 conditions[0] += " AND EXISTS (SELECT * FROM gpx_file_tags AS gft WHERE gft.gpx_id = gpx_files.id AND gft.tag = ?)"
209 conditions << params[:tag]
212 traces = Trace.find(:all, :include => :user, :conditions => conditions,
213 :order => "timestamp DESC", :limit => 20)
215 rss = OSM::GeoRSS.new
217 traces.each do |trace|
218 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)
221 render :text => rss.to_s, :content_type => "application/rss+xml"
225 trace = Trace.find(params[:id])
228 if trace.public? or (@user and @user == trace.user)
229 send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => 'image/gif', :disposition => 'inline')
231 render :nothing, :status => :forbidden
234 render :nothing => true, :status => :not_found
236 rescue ActiveRecord::RecordNotFound
237 render :nothing => true, :status => :not_found
241 trace = Trace.find(params[:id])
244 if trace.public? or (@user and @user == trace.user)
245 send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => 'image/gif', :disposition => 'inline')
247 render :nothing, :status => :forbidden
250 render :nothing => true, :status => :not_found
252 rescue ActiveRecord::RecordNotFound
253 render :nothing => true, :status => :not_found
257 trace = Trace.find(params[:id])
259 if trace.public? or trace.user == @user
260 render :text => trace.to_xml.to_s, :content_type => "text/xml"
262 render :nothing => true, :status => :forbidden
264 rescue ActiveRecord::RecordNotFound
265 render :nothing => true, :status => :not_found
269 trace = Trace.find(params[:id])
271 if trace.public? or trace.user == @user
272 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
274 render :nothing => true, :status => :forbidden
276 rescue ActiveRecord::RecordNotFound
277 render :nothing => true, :status => :not_found
282 do_create(params[:file], params[:tags], params[:description], params[:public])
285 render :text => @trace.id.to_s, :content_type => "text/plain"
287 render :nothing => true, :status => :internal_server_error
289 render :nothing => true, :status => :bad_request
292 render :nothing => true, :status => :method_not_allowed
298 def do_create(file, tags, description, public)
299 name = file.original_filename.gsub(/[^a-zA-Z0-9.]/, '_')
300 filename = "/tmp/#{rand}"
302 File.open(filename, "w") { |f| f.write(file.read) }
304 @trace = Trace.new({:name => name, :tagstring => tags,
305 :description => description, :public => public})
306 @trace.inserted = false
308 @trace.timestamp = Time.now
311 FileUtils.mv(filename, @trace.trace_name)
313 FileUtils.rm_f(filename)