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 filename = "/tmp/#{rand}"
106 File.open(filename, "w") { |f| f.write(params[:trace][:gpx_file].read) }
107 params[:trace][:name] = params[:trace][:gpx_file].original_filename.gsub(/[^a-zA-Z0-9.]/, '_') # This makes sure filenames are sane
108 params[:trace].delete('gpx_file') # remove the field from the hash, because there's no such field in the DB
109 @trace = Trace.new(params[:trace])
110 @trace.inserted = false
112 @trace.timestamp = Time.now
115 saved_filename = "/home/osm/gpx/#{@trace.id}.gpx"
116 File.rename(filename, saved_filename)
118 logger.info("id is #{@trace.id}")
119 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."
120 redirect_to :action => 'mine'
125 trace = Trace.find(params[:id])
126 if trace and (trace.public? or (@user and @user == trace.user))
127 send_file(trace.trace_name, :filename => "#{trace.id}.gpx", :type => trace.mime_type, :disposition => 'attachment')
129 render :nothing, :status => :not_found
134 trace = Trace.find(params[:id])
135 if @user and trace.user == @user and !trace.public
138 flash[:notice] = 'Track made public'
139 redirect_to :controller => 'trace', :action => 'view', :id => params[:id]
144 traces = Trace.find(:all, :conditions => ['public = true'], :order => 'timestamp DESC', :limit => 20)
146 rss = OSM::GeoRSS.new
148 #def add(latitude=0, longitude=0, title_text='dummy title', url='http://www.example.com/', description_text='dummy description', timestamp=Time.now)
149 traces.each do |trace|
150 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)
153 render :text => rss.to_s, :content_type => "application/rss+xml"
158 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
165 rescue ActiveRecord::RecordNotFound
166 render :nothing => true, :status => :not_found
168 render :nothing => true, :status => :internal_server_error
174 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
181 rescue ActiveRecord::RecordNotFound
182 render :nothing => true, :status => :not_found
184 render :nothing => true, :status => :internal_server_error
190 trace = Trace.find(params[:id])
192 if trace.public? or trace.user == @user
193 render :text => trace.to_xml.to_s, :content_type => "text/xml"
195 render :nothing => true, :status => :forbidden
197 rescue ActiveRecord::RecordNotFound
198 render :nothing => true, :status => :not_found
200 render :nothing => true, :status => :internal_server_error
205 render :action => 'data'
209 #FIXME merge this code with create as they're pretty similar?
211 filename = "/tmp/#{rand}"
212 File.open(filename, "w") { |f| f.write(request.raw_post) }
214 params[:trace][:name] = params[:filename]
215 params[:trace][:tagstring] = params[:tags]
216 params[:trace][:description] = params[:description]
217 @trace = Trace.new(params[:trace])
218 @trace.inserted = false
220 @trace.timestamp = Time.now
223 saved_filename = "/home/osm/gpx/#{@trace.id}.gpx"
224 File.rename(filename, saved_filename)
225 logger.info("id is #{@trace.id}")
226 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."
227 render :nothing => true
229 render :nothing => true, :status => :internal_server_error