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 @trace_pages, @traces = paginate(:traces,
52 :include => [:user, :tags],
53 :conditions => conditions,
54 :order => "gpx_files.timestamp DESC",
57 # put together SET of tags across traces, for related links
60 @traces.each do |trace|
61 trace.tags.reload if params[:tag] # if searched by tag, ActiveRecord won't bring back other tags, so do explicitly here
62 trace.tags.each do |tag|
63 tagset[tag.tag] = tag.tag
68 # final helper vars for view
70 @display_name = target_user.display_name if target_user
71 @all_tags = tagset.values
76 list(@user, "mine") unless @user.nil?
78 redirect_to :controller => 'user', :action => 'login', :referer => request.request_uri
83 @trace = Trace.find(params[:id])
84 @title = "Viewing trace #{@trace.name}"
87 render :nothing, :status => :forbidden if @trace.user.id != @user.id
90 rescue ActiveRecord::RecordNotFound
91 render :nothing => true, :status => :not_found
95 name = params[:trace][:gpx_file].original_filename.gsub(/[^a-zA-Z0-9.]/, '_') # This makes sure filenames are sane
97 do_create(name, params[:trace][:tagstring], params[:trace][:description], params[:trace][:public]) do |f|
98 f.write(params[:trace][:gpx_file].read)
102 logger.info("id is #{@trace.id}")
103 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."
105 redirect_to :action => 'mine'
110 trace = Trace.find(params[:id])
112 if trace.public? or (@user and @user == trace.user)
113 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
115 render :nothing, :status => :not_found
117 rescue ActiveRecord::RecordNotFound
118 render :nothing => true, :status => :not_found
122 trace = Trace.find(params[:id])
123 if @user and trace.user == @user and !trace.public
126 flash[:notice] = 'Track made public'
127 redirect_to :controller => 'trace', :action => 'view', :id => params[:id]
132 conditions = ["gpx_files.public = 1"]
134 if params[:display_name]
135 conditions[0] += " AND users.display_name = ?"
136 conditions << params[:display_name]
140 conditions[0] += " AND EXISTS (SELECT * FROM gpx_file_tags AS gft WHERE gft.gpx_id = gpx_files.id AND gft.tag = ?)"
141 conditions << params[:tag]
144 traces = Trace.find(:all, :include => :user, :conditions => conditions,
145 :order => "timestamp DESC", :limit => 20)
147 rss = OSM::GeoRSS.new
149 traces.each do |trace|
150 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)
153 render :text => rss.to_s, :content_type => "application/rss+xml"
157 trace = Trace.find(params[:id])
160 if trace.public? or (@user and @user == trace.user)
161 send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => 'image/gif', :disposition => 'inline')
163 render :nothing, :status => :forbidden
166 render :nothing => true, :status => :not_found
168 rescue ActiveRecord::RecordNotFound
169 render :nothing => true, :status => :not_found
173 trace = Trace.find(params[:id])
176 if trace.public? or (@user and @user == trace.user)
177 send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => 'image/gif', :disposition => 'inline')
179 render :nothing, :status => :forbidden
182 render :nothing => true, :status => :not_found
184 rescue ActiveRecord::RecordNotFound
185 render :nothing => true, :status => :not_found
189 trace = Trace.find(params[:id])
191 if trace.public? or trace.user == @user
192 render :text => trace.to_xml.to_s, :content_type => "text/xml"
194 render :nothing => true, :status => :forbidden
196 rescue ActiveRecord::RecordNotFound
197 render :nothing => true, :status => :not_found
201 trace = Trace.find(params[:id])
203 if trace.public? or trace.user == @user
204 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
206 render :nothing => true, :status => :forbidden
208 rescue ActiveRecord::RecordNotFound
209 render :nothing => true, :status => :not_found
214 name = params[:file].original_filename.gsub(/[^a-zA-Z0-9.]/, '_') # This makes sure filenames are sane
216 do_create(name, params[:tags], params[:description], params[:public]) do |f|
217 f.write(params[:file].read)
221 render :text => @trace.id.to_s, :content_type => "text/plain"
223 render :nothing => true, :status => :internal_server_error
225 render :nothing => true, :status => :bad_request
228 render :nothing => true, :status => :method_not_allowed
234 def do_create(name, tags, description, public)
235 filename = "/tmp/#{rand}"
237 File.open(filename, "w") { |f| yield f }
239 @trace = Trace.new({:name => name, :tagstring => tags,
240 :description => description, :public => public})
241 @trace.inserted = false
243 @trace.timestamp = Time.now
246 File.rename(filename, @trace.trace_name)
248 FileUtils.rm_f(filename)