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 # paging_action - the action that will be linked back to from view
9 def list (target_user = nil, paging_action = 'list')
10 @title = 'public GPS traces'
11 @title += " tagged with #{params[:tag]}" if params[:tag]
13 page_index = params[:page] ? params[:page].to_i - 1 : 0 # nice 1-based page -> 0-based page index
15 # from display name, pick up user id if one user's traces only
16 display_name = params[:display_name]
17 if target_user.nil? and display_name and display_name != ''
18 @paging_action = 'view'
19 @display_name = display_name
20 @title += " from #{@display_name}"
21 target_user = User.find(:first, :conditions => [ "display_name = ?", display_name])
25 opt[:include] = [:user, :tags] # load users and tags from db at same time as traces
28 # 1 - all traces, logged in = all public traces + all user's (i.e + all mine)
29 # 2 - all traces, not logged in = all public traces
30 # 3 - user's traces, logged in as same user = all user's traces
31 # 4 - user's traces, not logged in as that user = all user's public traces
32 if target_user.nil? # all traces
34 conditions = ["(public = 1 OR user_id = ?)", @user.id] #1
36 conditions = ["public = 1"] #2
39 if @user and @user.id == target_user.id
40 conditions = ["user_id = ?", @user.id] #3 (check vs user id, so no join + can't pick up non-public traces by changing name)
42 conditions = ["public = 1 AND user_id = ?", target_user.id] #4
45 conditions[0] += " AND users.display_name != ''" # users need to set display name before traces will be exposed
47 opt[:order] = 'timestamp DESC'
50 conditions[0] += " AND gpx_file_tags.tag = ?"
54 opt[:conditions] = conditions
56 # count traces using all options except limit
57 @max_trace = Trace.count(opt)
58 @max_page = Integer((@max_trace + 1) / @traces_per_page)
60 # last step before fetch - add paging options
61 opt[:limit] = @traces_per_page
63 opt[:offset] = @traces_per_page * page_index
66 @traces = Trace.find(:all , opt)
68 # put together SET of tags across traces, for related links
71 @traces.each do |trace|
72 trace.tags.reload if params[:tag] # if searched by tag, ActiveRecord won't bring back other tags, so do explicitly here
73 trace.tags.each do |tag|
74 tagset[tag.tag] = tag.tag
79 # final helper vars for view
80 @display_name = display_name
81 @all_tags = tagset.values
82 @paging_action = paging_action # the action that paging requests should route back to, e.g. 'list' or 'mine'
83 @page = page_index + 1 # nice 1-based external page numbers
88 list(@user, 'mine') unless @user.nil?
90 redirect_to :controller => 'user', :action => 'login', :referer => request.request_uri
95 @trace = Trace.find(params[:id])
98 render :nothing, :status => :forbidden if @trace.user.id != @user.id
104 name = params[:trace][:gpx_file].original_filename.gsub(/[^a-zA-Z0-9.]/, '_') # This makes sure filenames are sane
106 do_create(name, params[:trace][:tagstring], params[:trace][:description]) do |f|
107 f.write(params[:trace][:gpx_file].read)
111 logger.info("id is #{@trace.id}")
112 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."
114 redirect_to :action => 'mine'
119 trace = Trace.find(params[:id])
120 if trace and (trace.public? or (@user and @user == trace.user))
121 send_file(trace.trace_name, :filename => "#{trace.id}.gpx", :type => trace.mime_type, :disposition => 'attachment')
123 render :nothing, :status => :not_found
128 trace = Trace.find(params[:id])
129 if @user and trace.user == @user and !trace.public
132 flash[:notice] = 'Track made public'
133 redirect_to :controller => 'trace', :action => 'view', :id => params[:id]
138 traces = Trace.find(:all, :conditions => ['public = true'], :order => 'timestamp DESC', :limit => 20)
140 rss = OSM::GeoRSS.new
142 #def add(latitude=0, longitude=0, title_text='dummy title', url='http://www.example.com/', description_text='dummy description', timestamp=Time.now)
143 traces.each do |trace|
144 rss.add(trace.latitude, trace.longitude, trace.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)
147 render :text => rss.to_s, :content_type => "application/rss+xml"
152 trace = Trace.find(params[:id])
154 if trace.public? or (@user and @user == trace.user)
155 send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => 'image/gif', :disposition => 'inline')
157 render :nothing, :status => :forbidden
159 rescue ActiveRecord::RecordNotFound
160 render :nothing => true, :status => :not_found
162 render :nothing => true, :status => :internal_server_error
168 trace = Trace.find(params[:id])
170 if trace.public? or (@user and @user == trace.user)
171 send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => 'image/gif', :disposition => 'inline')
173 render :nothing, :status => :forbidden
175 rescue ActiveRecord::RecordNotFound
176 render :nothing => true, :status => :not_found
178 render :nothing => true, :status => :internal_server_error
184 trace = Trace.find(params[:id])
186 if trace.public? or trace.user == @user
187 render :text => trace.to_xml.to_s, :content_type => "text/xml"
189 render :nothing => true, :status => :forbidden
191 rescue ActiveRecord::RecordNotFound
192 render :nothing => true, :status => :not_found
194 render :nothing => true, :status => :internal_server_error
199 render :action => 'data'
203 do_create(params[:filename], params[:tags], params[:description]) do |f|
204 f.write(request.raw_post)
208 render :nothing => true
210 render :nothing => true, :status => :internal_server_error
216 def do_create(name, tags, description)
217 filename = "/tmp/#{rand}"
219 File.open(filename, "w") { |f| yield f }
221 @trace = Trace.new({:name => name, :tagstring => tags, :description => description})
222 @trace.inserted = false
224 @trace.timestamp = Time.now
227 File.rename(filename, @trace.trace_name)
229 FileUtils.rm_f(filename)