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 logger.info(params[:trace][:gpx_file].class.name)
98 if params[:trace][:gpx_file].respond_to?(:read)
99 do_create(params[:trace][:gpx_file], params[:trace][:tagstring],
100 params[:trace][:description], params[:trace][:public])
103 logger.info("id is #{@trace.id}")
104 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."
106 redirect_to :action => 'mine'
109 @trace = Trace.new({:name => "Dummy",
110 :tagstring => params[:trace][:tagstring],
111 :description => params[:trace][:description],
112 :public => params[:trace][:public],
113 :inserted => false, :user => @user,
114 :timestamp => Time.now})
116 @trace.errors.add(:gpx_file, "can't be blank")
121 trace = Trace.find(params[:id])
123 if trace.visible? and (trace.public? or (@user and @user == trace.user))
124 if request.format == Mime::XML
125 send_file(trace.xml_file, :filename => "#{trace.id}.xml", :type => Mime::XML.to_s, :disposition => 'attachment')
127 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
130 render :nothing, :status => :not_found
132 rescue ActiveRecord::RecordNotFound
133 render :nothing => true, :status => :not_found
137 @trace = Trace.find(params[:id])
139 if @user and @trace.user == @user
141 @trace.description = params[:trace][:description]
142 @trace.tagstring = params[:trace][:tagstring]
144 redirect_to :action => 'view'
148 render :nothing, :status => :forbidden
150 rescue ActiveRecord::RecordNotFound
151 render :nothing => true, :status => :not_found
155 trace = Trace.find(params[:id])
157 if @user and trace.user == @user
158 if request.post? and trace.visible?
159 trace.visible = false
161 flash[:notice] = 'Track scheduled for deletion'
162 redirect_to :controller => 'traces', :action => 'mine'
164 render :nothing, :status => :bad_request
167 render :nothing, :status => :forbidden
169 rescue ActiveRecord::RecordNotFound
170 render :nothing => true, :status => :not_found
174 trace = Trace.find(params[:id])
176 if @user and trace.user == @user
177 if request.post? and !trace.public?
180 flash[:notice] = 'Track made public'
181 redirect_to :controller => 'trace', :action => 'view', :id => params[:id]
183 render :nothing, :status => :bad_request
186 render :nothing, :status => :forbidden
188 rescue ActiveRecord::RecordNotFound
189 render :nothing => true, :status => :not_found
193 conditions = ["gpx_files.public = 1"]
195 if params[:display_name]
196 conditions[0] += " AND users.display_name = ?"
197 conditions << params[:display_name]
201 conditions[0] += " AND EXISTS (SELECT * FROM gpx_file_tags AS gft WHERE gft.gpx_id = gpx_files.id AND gft.tag = ?)"
202 conditions << params[:tag]
205 traces = Trace.find(:all, :include => :user, :conditions => conditions,
206 :order => "timestamp DESC", :limit => 20)
208 rss = OSM::GeoRSS.new
210 traces.each do |trace|
211 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)
214 render :text => rss.to_s, :content_type => "application/rss+xml"
218 trace = Trace.find(params[:id])
221 if trace.public? or (@user and @user == trace.user)
222 send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => 'image/gif', :disposition => 'inline')
224 render :nothing, :status => :forbidden
227 render :nothing => true, :status => :not_found
229 rescue ActiveRecord::RecordNotFound
230 render :nothing => true, :status => :not_found
234 trace = Trace.find(params[:id])
237 if trace.public? or (@user and @user == trace.user)
238 send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => 'image/gif', :disposition => 'inline')
240 render :nothing, :status => :forbidden
243 render :nothing => true, :status => :not_found
245 rescue ActiveRecord::RecordNotFound
246 render :nothing => true, :status => :not_found
250 trace = Trace.find(params[:id])
252 if trace.public? or trace.user == @user
253 render :text => trace.to_xml.to_s, :content_type => "text/xml"
255 render :nothing => true, :status => :forbidden
257 rescue ActiveRecord::RecordNotFound
258 render :nothing => true, :status => :not_found
262 trace = Trace.find(params[:id])
264 if trace.public? or trace.user == @user
265 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
267 render :nothing => true, :status => :forbidden
269 rescue ActiveRecord::RecordNotFound
270 render :nothing => true, :status => :not_found
275 do_create(params[:file], params[:tags], params[:description], params[:public])
278 render :text => @trace.id.to_s, :content_type => "text/plain"
280 render :nothing => true, :status => :internal_server_error
282 render :nothing => true, :status => :bad_request
285 render :nothing => true, :status => :method_not_allowed
291 def do_create(file, tags, description, public)
292 name = file.original_filename.gsub(/[^a-zA-Z0-9.]/, '_')
293 filename = "/tmp/#{rand}"
295 File.open(filename, "w") { |f| f.write(file.read) }
297 @trace = Trace.new({:name => name, :tagstring => tags,
298 :description => description, :public => public})
299 @trace.inserted = false
301 @trace.timestamp = Time.now
304 File.rename(filename, @trace.trace_name)
306 FileUtils.rm_f(filename)