1 class TraceController < ApplicationController
4 before_filter :authorize_web
5 before_filter :require_user, :only => [:mine, :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'
102 logger.info(params[:trace][:gpx_file].class.name)
103 if params[:trace][:gpx_file].respond_to?(:read)
104 do_create(params[:trace][:gpx_file], params[:trace][:tagstring],
105 params[:trace][:description], params[:trace][:public])
108 logger.info("id is #{@trace.id}")
109 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."
111 redirect_to :action => 'mine'
114 @trace = Trace.new({:name => "Dummy",
115 :tagstring => params[:trace][:tagstring],
116 :description => params[:trace][:description],
117 :public => params[:trace][:public],
118 :inserted => false, :user => @user,
119 :timestamp => Time.now})
121 @trace.errors.add(:gpx_file, "can't be blank")
126 trace = Trace.find(params[:id])
128 if trace.visible? and (trace.public? or (@user and @user == trace.user))
129 if request.format == Mime::XML
130 send_file(trace.xml_file, :filename => "#{trace.id}.xml", :type => Mime::XML.to_s, :disposition => 'attachment')
132 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
135 render :nothing => true, :status => :not_found
137 rescue ActiveRecord::RecordNotFound
138 render :nothing => true, :status => :not_found
142 @trace = Trace.find(params[:id])
144 if @user and @trace.user == @user
146 @trace.description = params[:trace][:description]
147 @trace.tagstring = params[:trace][:tagstring]
149 redirect_to :action => 'view'
153 render :nothing => true, :status => :forbidden
155 rescue ActiveRecord::RecordNotFound
156 render :nothing => true, :status => :not_found
160 trace = Trace.find(params[:id])
162 if @user and trace.user == @user
163 if request.post? and trace.visible?
164 trace.visible = false
166 flash[:notice] = 'Track scheduled for deletion'
167 redirect_to :controller => 'traces', :action => 'mine'
169 render :nothing => true, :status => :bad_request
172 render :nothing => true, :status => :forbidden
174 rescue ActiveRecord::RecordNotFound
175 render :nothing => true, :status => :not_found
179 trace = Trace.find(params[:id])
181 if @user and trace.user == @user
182 if request.post? and !trace.public?
185 flash[:notice] = 'Track made public'
186 redirect_to :controller => 'trace', :action => 'view', :id => params[:id]
188 render :nothing => true, :status => :bad_request
191 render :nothing => true, :status => :forbidden
193 rescue ActiveRecord::RecordNotFound
194 render :nothing => true, :status => :not_found
198 conditions = ["gpx_files.public = ?", true]
200 if params[:display_name]
201 conditions[0] += " AND users.display_name = ?"
202 conditions << params[:display_name]
206 conditions[0] += " AND EXISTS (SELECT * FROM gpx_file_tags AS gft WHERE gft.gpx_id = gpx_files.id AND gft.tag = ?)"
207 conditions << params[:tag]
210 traces = Trace.find(:all, :include => :user, :conditions => conditions,
211 :order => "timestamp DESC", :limit => 20)
213 rss = OSM::GeoRSS.new
215 traces.each do |trace|
216 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)
219 render :text => rss.to_s, :content_type => "application/rss+xml"
223 trace = Trace.find(params[:id])
226 if trace.public? or (@user and @user == trace.user)
227 send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => 'image/gif', :disposition => 'inline')
229 render :nothing => true, :status => :forbidden
232 render :nothing => true, :status => :not_found
234 rescue ActiveRecord::RecordNotFound
235 render :nothing => true, :status => :not_found
239 trace = Trace.find(params[:id])
242 if trace.public? or (@user and @user == trace.user)
243 send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => 'image/gif', :disposition => 'inline')
245 render :nothing => true, :status => :forbidden
248 render :nothing => true, :status => :not_found
250 rescue ActiveRecord::RecordNotFound
251 render :nothing => true, :status => :not_found
255 trace = Trace.find(params[:id])
257 if trace.public? or trace.user == @user
258 render :text => trace.to_xml.to_s, :content_type => "text/xml"
260 render :nothing => true, :status => :forbidden
262 rescue ActiveRecord::RecordNotFound
263 render :nothing => true, :status => :not_found
267 trace = Trace.find(params[:id])
269 if trace.public? or trace.user == @user
270 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
272 render :nothing => true, :status => :forbidden
274 rescue ActiveRecord::RecordNotFound
275 render :nothing => true, :status => :not_found
280 do_create(params[:file], params[:tags], params[:description], params[:public])
283 render :text => @trace.id.to_s, :content_type => "text/plain"
285 render :nothing => true, :status => :internal_server_error
287 render :nothing => true, :status => :bad_request
290 render :nothing => true, :status => :method_not_allowed
296 def do_create(file, tags, description, public)
297 name = file.original_filename.gsub(/[^a-zA-Z0-9.]/, '_')
298 filename = "/tmp/#{rand}"
300 File.open(filename, "w") { |f| f.write(file.read) }
302 @trace = Trace.new({:name => name, :tagstring => tags,
303 :description => description, :public => public})
304 @trace.inserted = false
306 @trace.timestamp = Time.now
309 FileUtils.mv(filename, @trace.trace_name)
311 FileUtils.rm_f(filename)
314 # Finally save whether the user marked the trace as being public
316 if @user.trace_public_default.nil?
317 @user.preferences.create(:k => "gps.trace.public", :v => "default")
320 pref = @user.trace_public_default
321 pref.destroy unless pref.nil?