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')
 
  11     page_index = params[:page] ? params[:page].to_i - 1 : 0 # nice 1-based page -> 0-based page index
 
  13     # from display name, pick up user id if one user's traces only
 
  14     display_name = params[:display_name]
 
  15     if target_user.nil? and display_name and display_name != ''
 
  16       @paging_action = 'view'
 
  17       @display_name = display_name
 
  18       target_user = User.find(:first, :conditions => [ "display_name = ?", display_name])
 
  22     opt[:include] = [:user, :tags] # load users and tags from db at same time as traces
 
  25     # 1 - all traces, logged in = all public traces + all user's (i.e + all mine)
 
  26     # 2 - all traces, not logged in = all public traces
 
  27     # 3 - user's traces, logged in as same user = all user's traces 
 
  28     # 4 - user's traces, not logged in as that user = all user's public traces
 
  29     if target_user.nil? # all traces
 
  31         conditions = ["(public = 1 OR user_id = ?)", @user.id] #1
 
  33         conditions  = ["public = 1"] #2
 
  36       if @user and @user.id == target_user.id
 
  37         conditions = ["user_id = ?", @user.id] #3 (check vs user id, so no join + can't pick up non-public traces by changing name)
 
  39         conditions = ["public = 1 AND user_id = ?", target_user.id] #4
 
  42     conditions[0] += " AND users.display_name != ''" # users need to set display name before traces will be exposed
 
  44     opt[:order] = 'timestamp DESC'
 
  47       conditions[0] += " AND gpx_file_tags.tag = ?"
 
  51     opt[:conditions] = conditions
 
  53     # count traces using all options except limit
 
  54     @max_trace = Trace.count(opt)
 
  55     @max_page = Integer((@max_trace + 1) / @traces_per_page) 
 
  57     # last step before fetch - add paging options
 
  58     opt[:limit] = @traces_per_page
 
  60       opt[:offset] = @traces_per_page * page_index
 
  63     @traces = Trace.find(:all , opt)
 
  65     # put together SET of tags across traces, for related links
 
  68       @traces.each do |trace|
 
  69         trace.tags.reload if params[:tag] # if searched by tag, ActiveRecord won't bring back other tags, so do explicitly here
 
  70         trace.tags.each do |tag|
 
  71           tagset[tag.tag] = tag.tag
 
  76     # final helper vars for view
 
  77     @display_name = display_name
 
  78     @all_tags = tagset.values
 
  79     @paging_action = paging_action # the action that paging requests should route back to, e.g. 'list' or 'mine'
 
  80     @page = page_index + 1 # nice 1-based external page numbers
 
  85       list(@user, 'mine') unless @user.nil?
 
  87       redirect_to :controller => 'user', :action => 'login', :referer => request.request_uri
 
  92     @trace = Trace.find(params[:id])
 
  95         render :nothing, :status => 401 if @trace.user.id != @user.id
 
 101     filename = "/tmp/#{rand}"
 
 103     File.open(filename, "w") { |f| f.write(params[:trace][:gpx_file].read) }
 
 104     params[:trace][:name] = params[:trace][:gpx_file].original_filename.gsub(/[^a-zA-Z0-9.]/, '_') # This makes sure filenames are sane
 
 105     params[:trace].delete('gpx_file') # remove the field from the hash, because there's no such field in the DB
 
 106     @trace = Trace.new(params[:trace])
 
 107     @trace.inserted = false
 
 109     @trace.timestamp = Time.now
 
 112       saved_filename = "/home/osm/gpx/#{@trace.id}.gpx"
 
 113       File.rename(filename, saved_filename)
 
 115       logger.info("id is #{@trace.id}")
 
 116       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."
 
 117       redirect_to :action => 'mine'
 
 122     trace = Trace.find(params[:id])
 
 123     if trace and (trace.public? or (@user and @user == trace.user))
 
 124       send_file(trace.trace_name, :filename => "#{trace.id}.gpx", :type => trace.mime_type, :disposition => 'attachment')
 
 126       render :nothing, :status => 404
 
 131     trace = Trace.find(params[:id])
 
 132     if @user and trace.user == @user and !trace.public
 
 135       flash[:notice] = 'Track made public'
 
 136       redirect_to :controller => 'trace', :action => 'view', :id => params[:id]
 
 141     traces = Trace.find(:all, :conditions => ['public = true'], :order => 'timestamp DESC', :limit => 20)
 
 143     rss = OSM::GeoRSS.new
 
 145     #def add(latitude=0, longitude=0, title_text='dummy title', url='http://www.example.com/', description_text='dummy description', timestamp=Time.now)
 
 146     traces.each do |trace|
 
 147       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)
 
 150     response.headers["Content-Type"] = 'application/rss+xml'
 
 152     render :text => rss.to_s
 
 156     trace = Trace.find(params[:id])
 
 157     if trace and (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 => 404
 
 165     trace = Trace.find(params[:id])
 
 166     if trace and (trace.public? or (@user and @user == trace.user))
 
 167       send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => 'image/gif', :disposition => 'inline')
 
 169       render :nothing, :status => 404
 
 174     trace = Trace.find(params[:id])
 
 175     doc = OSM::API.new.get_xml_doc
 
 176     doc.root << trace.to_xml_node() if trace.public? or trace.user == @user
 
 177     render :text => doc.to_s
 
 181     render :action => 'data'
 
 185     #FIXME merge this code with create as they're pretty similar?
 
 187     filename = "/tmp/#{rand}"
 
 188     File.open(filename, "w") { |f| f.write(request.raw_post) }
 
 190     params[:trace][:name] = params[:filename]
 
 191     params[:trace][:tagstring] = params[:tags]
 
 192     params[:trace][:description] = params[:description]
 
 193     @trace = Trace.new(params[:trace])
 
 194     @trace.inserted = false
 
 196     @trace.timestamp = Time.now
 
 199       saved_filename = "/home/osm/gpx/#{@trace.id}.gpx"
 
 200       File.rename(filename, saved_filename)
 
 201       logger.info("id is #{@trace.id}")
 
 202       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."
 
 203       render :nothing => true
 
 205       render :nothing => true, :status => 400 # er FIXME what fricking code to return?