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])
111 if trace and (trace.public? or (@user and @user == trace.user))
112 send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => 'attachment')
114 render :nothing, :status => :not_found
119 trace = Trace.find(params[:id])
120 if @user and trace.user == @user and !trace.public
123 flash[:notice] = 'Track made public'
124 redirect_to :controller => 'trace', :action => 'view', :id => params[:id]
129 conditions = ["gpx_files.public = 1"]
131 if params[:display_name]
132 conditions[0] += " AND users.display_name = ?"
133 conditions << params[:display_name]
137 conditions[0] += " AND EXISTS (SELECT * FROM gpx_file_tags AS gft WHERE gft.gpx_id = gpx_files.id AND gft.tag = ?)"
138 conditions << params[:tag]
141 traces = Trace.find(:all, :include => :user, :conditions => conditions,
142 :order => "timestamp DESC", :limit => 20)
144 rss = OSM::GeoRSS.new
146 traces.each do |trace|
147 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)
150 render :text => rss.to_s, :content_type => "application/rss+xml"
155 trace = Trace.find(params[:id])
157 if trace.public? or (@user and @user == trace.user)
158 send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => 'image/gif', :disposition => 'inline')
160 render :nothing, :status => :forbidden
162 rescue ActiveRecord::RecordNotFound
163 render :nothing => true, :status => :not_found
165 render :nothing => true, :status => :internal_server_error
171 trace = Trace.find(params[:id])
173 if trace.public? or (@user and @user == trace.user)
174 send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => 'image/gif', :disposition => 'inline')
176 render :nothing, :status => :forbidden
178 rescue ActiveRecord::RecordNotFound
179 render :nothing => true, :status => :not_found
181 render :nothing => true, :status => :internal_server_error
187 trace = Trace.find(params[:id])
189 if trace.public? or trace.user == @user
190 render :text => trace.to_xml.to_s, :content_type => "text/xml"
192 render :nothing => true, :status => :forbidden
194 rescue ActiveRecord::RecordNotFound
195 render :nothing => true, :status => :not_found
197 render :nothing => true, :status => :internal_server_error
202 render :action => 'data'
206 do_create(params[:filename], params[:tags], params[:description], true) do |f|
207 f.write(request.raw_post)
211 render :nothing => true
213 render :nothing => true, :status => :internal_server_error
219 def do_create(name, tags, description, public)
220 filename = "/tmp/#{rand}"
222 File.open(filename, "w") { |f| yield f }
224 @trace = Trace.new({:name => name, :tagstring => tags,
225 :description => description, :public => public})
226 @trace.inserted = false
228 @trace.timestamp = Time.now
231 File.rename(filename, @trace.trace_name)
233 FileUtils.rm_f(filename)