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 = 1" #FIXME: use boolean true as parameter to active record
56 @trace_pages, @traces = paginate(:traces,
57 :include => [:user, :tags],
58 :conditions => conditions,
59 :order => "gpx_files.timestamp DESC",
62 # put together SET of tags across traces, for related links
65 @traces.each do |trace|
66 trace.tags.reload if params[:tag] # if searched by tag, ActiveRecord won't bring back other tags, so do explicitly here
67 trace.tags.each do |tag|
68 tagset[tag.tag] = tag.tag
73 # final helper vars for view
75 @display_name = target_user.display_name if target_user
76 @all_tags = tagset.values
81 list(@user, "mine") unless @user.nil?
83 redirect_to :controller => 'user', :action => 'login', :referer => request.request_uri
88 @trace = Trace.find(params[:id])
90 if @trace and @trace.visible? and
91 (@trace.public? or @trace.user == @user)
92 @title = "Viewing trace #{@trace.name}"
94 flash[:notice] = "Trace not found!"
95 redirect_to :controller => 'trace', :action => 'list'
97 rescue ActiveRecord::RecordNotFound
98 flash[:notice] = "Trace not found!"
99 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})
122 @trace.errors.add(:gpx_file, "can't be blank")
127 trace = Trace.find(params[:id])
129 if trace.visible? and (trace.public? or (@user and @user == trace.user))
130 if request.format == Mime::XML
131 send_file(trace.xml_file, :filename => "#{trace.id}.xml", :type => Mime::XML.to_s, :disposition => 'attachment')
133 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
136 render :nothing, :status => :not_found
138 rescue ActiveRecord::RecordNotFound
139 render :nothing => true, :status => :not_found
143 @trace = Trace.find(params[:id])
145 if @user and @trace.user == @user
147 @trace.description = params[:trace][:description]
148 @trace.tagstring = params[:trace][:tagstring]
150 redirect_to :action => 'view'
154 render :nothing, :status => :forbidden
156 rescue ActiveRecord::RecordNotFound
157 render :nothing => true, :status => :not_found
161 trace = Trace.find(params[:id])
163 if @user and trace.user == @user
164 if request.post? and trace.visible?
165 trace.visible = false
167 flash[:notice] = 'Track scheduled for deletion'
168 redirect_to :controller => 'traces', :action => 'mine'
170 render :nothing, :status => :bad_request
173 render :nothing, :status => :forbidden
175 rescue ActiveRecord::RecordNotFound
176 render :nothing => true, :status => :not_found
180 trace = Trace.find(params[:id])
182 if @user and trace.user == @user
183 if request.post? and !trace.public?
186 flash[:notice] = 'Track made public'
187 redirect_to :controller => 'trace', :action => 'view', :id => params[:id]
189 render :nothing, :status => :bad_request
192 render :nothing, :status => :forbidden
194 rescue ActiveRecord::RecordNotFound
195 render :nothing => true, :status => :not_found
199 conditions = ["gpx_files.public = 1"]
201 if params[:display_name]
202 conditions[0] += " AND users.display_name = ?"
203 conditions << params[:display_name]
207 conditions[0] += " AND EXISTS (SELECT * FROM gpx_file_tags AS gft WHERE gft.gpx_id = gpx_files.id AND gft.tag = ?)"
208 conditions << params[:tag]
211 traces = Trace.find(:all, :include => :user, :conditions => conditions,
212 :order => "timestamp DESC", :limit => 20)
214 rss = OSM::GeoRSS.new
216 traces.each do |trace|
217 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)
220 render :text => rss.to_s, :content_type => "application/rss+xml"
224 trace = Trace.find(params[:id])
227 if trace.public? or (@user and @user == trace.user)
228 send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => 'image/gif', :disposition => 'inline')
230 render :nothing, :status => :forbidden
233 render :nothing => true, :status => :not_found
235 rescue ActiveRecord::RecordNotFound
236 render :nothing => true, :status => :not_found
240 trace = Trace.find(params[:id])
243 if trace.public? or (@user and @user == trace.user)
244 send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => 'image/gif', :disposition => 'inline')
246 render :nothing, :status => :forbidden
249 render :nothing => true, :status => :not_found
251 rescue ActiveRecord::RecordNotFound
252 render :nothing => true, :status => :not_found
256 trace = Trace.find(params[:id])
258 if trace.public? or trace.user == @user
259 render :text => trace.to_xml.to_s, :content_type => "text/xml"
261 render :nothing => true, :status => :forbidden
263 rescue ActiveRecord::RecordNotFound
264 render :nothing => true, :status => :not_found
268 trace = Trace.find(params[:id])
270 if trace.public? or trace.user == @user
271 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
273 render :nothing => true, :status => :forbidden
275 rescue ActiveRecord::RecordNotFound
276 render :nothing => true, :status => :not_found
281 do_create(params[:file], params[:tags], params[:description], params[:public])
284 render :text => @trace.id.to_s, :content_type => "text/plain"
286 render :nothing => true, :status => :internal_server_error
288 render :nothing => true, :status => :bad_request
291 render :nothing => true, :status => :method_not_allowed
297 def do_create(file, tags, description, public)
298 name = file.original_filename.gsub(/[^a-zA-Z0-9.]/, '_')
299 filename = "/tmp/#{rand}"
301 File.open(filename, "w") { |f| f.write(file.read) }
303 @trace = Trace.new({:name => name, :tagstring => tags,
304 :description => description, :public => public})
305 @trace.inserted = false
307 @trace.timestamp = Time.now
310 FileUtils.mv(filename, @trace.trace_name)
312 FileUtils.rm_f(filename)