1 class TraceController < ApplicationController
4 before_filter :authorize_web
5 before_filter :require_user, :only => [:mine, :create, :edit, :delete, :make_public]
6 before_filter :authorize, :only => [:api_details, :api_data, :api_create]
7 before_filter :check_database_availability, :except => [:api_details, :api_data, :api_create]
8 before_filter :check_read_availability, :only => [:api_details, :api_data, :api_create]
10 # Counts and selects pages of GPX traces for various criteria (by user, tags, public etc.).
11 # target_user - if set, specifies the user to fetch traces for. if not set will fetch all traces
12 def list(target_user = nil, action = "list")
13 # from display name, pick up user id if one user's traces only
14 display_name = params[:display_name]
15 if target_user.nil? and !display_name.blank?
16 target_user = User.find(:first, :conditions => [ "visible = ? and display_name = ?", true, display_name])
21 @title = "Public GPS traces"
22 elsif @user and @user == target_user
23 @title = "Your GPS traces"
25 @title = "Public GPS traces from #{target_user.display_name}"
28 @title += " tagged with #{params[:tag]}" if params[:tag]
31 # 1 - all traces, logged in = all public traces + all user's (i.e + all mine)
32 # 2 - all traces, not logged in = all public traces
33 # 3 - user's traces, logged in as same user = all user's traces
34 # 4 - user's traces, not logged in as that user = all user's public traces
35 if target_user.nil? # all traces
37 conditions = ["(gpx_files.public = ? OR gpx_files.user_id = ?)", true, @user.id] #1
39 conditions = ["gpx_files.public = ?", true] #2
42 if @user and @user == target_user
43 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)
45 conditions = ["gpx_files.public = ? AND gpx_files.user_id = ?", true, target_user.id] #4
52 files = Tracetag.find_all_by_tag(params[:tag]).collect { |tt| tt.gpx_id }
53 conditions[0] += " AND gpx_files.id IN (#{files.join(',')})"
56 conditions[0] += " AND gpx_files.visible = ?"
59 @trace_pages, @traces = paginate(:traces,
60 :include => [:user, :tags],
61 :conditions => conditions,
62 :order => "gpx_files.timestamp DESC",
65 # put together SET of tags across traces, for related links
68 @traces.each do |trace|
69 trace.tags.reload if params[:tag] # if searched by tag, ActiveRecord won't bring back other tags, so do explicitly here
70 trace.tags.each do |tag|
71 tagset[tag.tag] = tag.tag
76 # final helper vars for view
78 @display_name = target_user.display_name if target_user
79 @all_tags = tagset.values
87 @trace = Trace.find(params[:id])
89 if @trace and @trace.visible? and
90 (@trace.public? or @trace.user == @user)
91 @title = "Viewing trace #{@trace.name}"
93 flash[:notice] = "Trace not found!"
94 redirect_to :controller => 'trace', :action => 'list'
96 rescue ActiveRecord::RecordNotFound
97 flash[:notice] = "Trace not found!"
98 redirect_to :controller => 'trace', :action => 'list'
103 logger.info(params[:trace][:gpx_file].class.name)
104 if params[:trace][:gpx_file].respond_to?(:read)
105 do_create(params[:trace][:gpx_file], params[:trace][:tagstring],
106 params[:trace][:description], params[:trace][:public])
109 logger.info("id is #{@trace.id}")
110 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."
112 redirect_to :action => 'mine'
115 @trace = Trace.new({:name => "Dummy",
116 :tagstring => params[:trace][:tagstring],
117 :description => params[:trace][:description],
118 :public => params[:trace][:public],
119 :inserted => false, :user => @user,
120 :timestamp => Time.now.getutc})
122 @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 => true, :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 => true, :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 => true, :status => :bad_request
174 render :nothing => true, :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 => true, :status => :bad_request
193 render :nothing => true, :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 => true, :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 => true, :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 tags = params[:tags] || ""
283 description = params[:description] || ""
284 pub = params[:public] || false
286 if params[:file].respond_to?(:read)
287 do_create(params[:file], tags, description, pub)
290 render :text => @trace.id.to_s, :content_type => "text/plain"
292 render :nothing => true, :status => :internal_server_error
294 render :nothing => true, :status => :bad_request
297 render :nothing => true, :status => :bad_request
300 render :nothing => true, :status => :method_not_allowed
306 def do_create(file, tags, description, public)
307 name = file.original_filename.gsub(/[^a-zA-Z0-9.]/, '_')
308 filename = "/tmp/#{rand}"
310 File.open(filename, "w") { |f| f.write(file.read) }
312 @trace = Trace.new({:name => name, :tagstring => tags,
313 :description => description, :public => public})
314 @trace.inserted = false
316 @trace.timestamp = Time.now.getutc
319 FileUtils.mv(filename, @trace.trace_name)
321 FileUtils.rm_f(filename)
324 # Finally save whether the user marked the trace as being public
326 if @user.trace_public_default.nil?
327 @user.preferences.create(:k => "gps.trace.public", :v => "default")
330 pref = @user.trace_public_default
331 pref.destroy unless pref.nil?