]> git.openstreetmap.org Git - rails.git/commitdiff
Merge changes from trunk 7673:8632.
authorShaun McDonald <shaun@shaunmcdonald.me.uk>
Thu, 3 Jul 2008 13:06:24 +0000 (13:06 +0000)
committerShaun McDonald <shaun@shaunmcdonald.me.uk>
Thu, 3 Jul 2008 13:06:24 +0000 (13:06 +0000)
1  2 
app/controllers/api_controller.rb
app/controllers/application.rb
app/models/old_relation.rb
app/models/old_way.rb
app/models/relation.rb
app/models/way.rb
config/environment.rb
config/routes.rb

index d7937cb01d8db241072e1de2d1b841486fce84b4,9cf8977d332de0bfbf246ca126308cc1192160e2..05dfb0133ae6ca9bafdf05a97025ea7059e322ac
@@@ -120,12 -120,10 +120,10 @@@ class ApiController < ApplicationContro
        return
      end
      if node_ids.length == 0
 -      render :text => "<osm version='0.5'></osm>", :content_type => "text/xml"
 +      render :text => "<osm version='#{API_VERSION}'></osm>", :content_type => "text/xml"
        return
      end
  
-     relations = Array.new
      doc = OSM::API.new.get_xml_doc
  
      # get ways
        end
      end 
  
-     relations = Relation.find_for_nodes_and_ways(visible_nodes.keys, way_ids)
+     relations = visible_nodes.values.collect { |node| node.containing_relations.visible }.flatten +
+                 way_ids.collect { |id| Way.find(id).containing_relations.visible }.flatten
  
      # we do not normally return the "other" partners referenced by an relation, 
      # e.g. if we return a way A that is referenced by relation X, and there's 
      # another way B also referenced, that is not returned. But we do make 
      # an exception for cases where an relation references another *relation*; 
      # in that case we return that as well (but we don't go recursive here)
-     relation_ids = relations.collect { |relation| relation.id }
-     if relation_ids.length > 0
-         relations += Relation.find_by_sql("select e.* from current_relations e,current_relation_members em where " +
-             "e.visible=1 and " +
-             "em.id = e.id and em.member_type='relation' and em.member_id in (#{relation_ids.join(',')})")
-     end
+     relations += relations.collect { |relation| relation.containing_relations.visible }.flatten
  
      # this "uniq" may be slightly inefficient; it may be better to first collect and output
      # all node-related relations, then find the *not yet covered* way-related ones etc.
  
      api = XML::Node.new 'api'
      version = XML::Node.new 'version'
 -    version['minimum'] = '0.5';
 -    version['maximum'] = '0.5';
 +    version['minimum'] = "#{API_VERSION}";
 +    version['maximum'] = "#{API_VERSION}";
      api << version
      area = XML::Node.new 'area'
      area['maximum'] = MAX_REQUEST_AREA.to_s;
index 8d082c2ca0efd7f3743f3ecad3816aad9c8bf02e,918e4b617822610bcd33c23ae5c48660af7e8b08..68359585e0eeb60d64c498a64b965af5791e87f4
@@@ -2,6 -2,10 +2,10 @@@
  # Likewise, all the methods added will be available for all controllers.
  class ApplicationController < ActionController::Base
  
+   if OSM_STATUS == :database_offline
+     session :off
+   end
    def authorize_web
      if session[:user]
        @user = User.find(session[:user])
      end 
    end 
  
+   def check_database_availability(need_api = false)
+     if OSM_STATUS == :database_offline or (need_api and OSM_STATUS == :api_offline)
+       redirect_to :controller => 'site', :action => 'offline'
+     end
+   end
    def check_read_availability
-     if API_STATUS == :offline
+     if OSM_STATUS == :database_offline or OSM_STATUS == :api_offline
        response.headers['Error'] = "Database offline for maintenance"
        render :nothing => true, :status => :service_unavailable
        return false
@@@ -48,7 -58,7 +58,7 @@@
    end
  
    def check_write_availability
-     if API_STATUS == :offline or API_STATUS == :readonly
+     if OSM_STATUS == :database_offline or OSM_STATUS == :api_offline or OSM_STATUS == :api_readonly
        response.headers['Error'] = "Database offline for maintenance"
        render :nothing => true, :status => :service_unavailable
        return false
@@@ -61,7 -71,7 +71,7 @@@
    #  phrase from that, we can also put the error message into the status
    #  message. For now, rails won't let us)
    def report_error(message)
 -    render :nothing => true, :status => :bad_request
 +    render :text => message, :status => :bad_request
      # Todo: some sort of escaping of problem characters in the message
      response.headers['Error'] = message
    end
@@@ -72,8 -82,6 +82,8 @@@ privat
    def get_auth_data 
      if request.env.has_key? 'X-HTTP_AUTHORIZATION'          # where mod_rewrite might have put it 
        authdata = request.env['X-HTTP_AUTHORIZATION'].to_s.split 
 +    elsif request.env.has_key? 'REDIRECT_X_HTTP_AUTHORIZATION'          # mod_fcgi 
 +      authdata = request.env['REDIRECT_X_HTTP_AUTHORIZATION'].to_s.split 
      elsif request.env.has_key? 'HTTP_AUTHORIZATION'         # regular location
        authdata = request.env['HTTP_AUTHORIZATION'].to_s.split
      end 
index 03d5aebfff3006eaa91036b5efa26118835b7223,bac03c4d2eff6811a9dc4b5d2c32e3bb988e76b3..f5885f39ffb59adc799f4b5ea7832066f9654f5a
@@@ -9,7 -9,6 +9,7 @@@ class OldRelation < ActiveRecord::Bas
      old_relation.user_id = relation.user_id
      old_relation.timestamp = relation.timestamp
      old_relation.id = relation.id
 +    old_relation.version = relation.version
      old_relation.members = relation.members
      old_relation.tags = relation.tags
      return old_relation
@@@ -92,7 -91,6 +92,7 @@@
      el1['visible'] = self.visible.to_s
      el1['timestamp'] = self.timestamp.xmlschema
      el1['user'] = self.user.display_name if self.user.data_public?
 +    el1['version'] = self.version.to_s
      
      self.old_members.each do |member|
        e = XML::Node.new 'member'
        el1 << e
      end
      return el1
-   end 
+   end
+   # Temporary method to match interface to nodes
+   def tags_as_hash
+     return self.tags
+   end
+   # Temporary method to match interface to relations
+   def relation_members
+     return self.old_members
+   end
+   # Pretend we're not in any relations
+   def containing_relation_members
+     return []
+   end
  end
diff --combined app/models/old_way.rb
index 136e647938122d69a83ed5669521dbe4e64f54ec,1abb23bbbac13292b4f5f6949781b5cd4b55ff8f..edf66aac324922d26ea8090ba88062954e40df15
@@@ -9,7 -9,6 +9,7 @@@ class OldWay < ActiveRecord::Bas
      old_way.user_id = way.user_id
      old_way.timestamp = way.timestamp
      old_way.id = way.id
 +    old_way.version = way.version
      old_way.nds = way.nds
      old_way.tags = way.tags
      return old_way
@@@ -95,7 -94,6 +95,7 @@@
      el1['visible'] = self.visible.to_s
      el1['timestamp'] = self.timestamp.xmlschema
      el1['user'] = self.user.display_name if self.user.data_public?
 +    el1['version'] = self.version.to_s
      
      self.old_nodes.each do |nd| # FIXME need to make sure they come back in the right order
        e = XML::Node.new 'nd'
        el1 << e
      end
      return el1
-   end 
+   end
+   # Temporary method to match interface to nodes
+   def tags_as_hash
+     return self.tags
+   end
+   # Temporary method to match interface to ways
+   def way_nodes
+     return self.old_nodes
+   end
+   # Pretend we're not in any relations
+   def containing_relation_members
+     return []
+   end
  end
diff --combined app/models/relation.rb
index 984732c71c98f6b0bc9c1463029135fb2345f64a,9ee118f6e0c22fb26f4bff0012e30e3cb2c92173..eb3b06a130bc1a22c0f27170aabb0d2dc21c6c0b
@@@ -1,14 -1,17 +1,17 @@@
  class Relation < ActiveRecord::Base
    require 'xml/libxml'
    
+   set_table_name 'current_relations'
    belongs_to :user
  
+   has_many :old_relations, :foreign_key => 'id', :order => 'version'
    has_many :relation_members, :foreign_key => 'id'
    has_many :relation_tags, :foreign_key => 'id'
  
-   has_many :old_relations, :foreign_key => 'id', :order => 'version'
-   set_table_name 'current_relations'
+   has_many :containing_relation_members, :class_name => "RelationMember", :as => :member
+   has_many :containing_relations, :class_name => "Relation", :through => :containing_relation_members, :source => :relation, :extend => ObjectFinder
  
    def self.from_xml(xml, create=false)
      begin
        p.string = xml
        doc = p.parse
  
 -      relation = Relation.new
 -
        doc.find('//osm/relation').each do |pt|
 -        if !create and pt['id'] != '0'
 -          relation.id = pt['id'].to_i
 -        end
 +      return Relation.from_xml_node(pt, create)
 +      end
 +    rescue
 +      return nil
 +    end
 +  end
  
 -        if create
 -          relation.timestamp = Time.now
 -          relation.visible = true
 -        else
 -          if pt['timestamp']
 -            relation.timestamp = Time.parse(pt['timestamp'])
 -          end
 -        end
 +  def self.from_xml_node(pt, create=false)
 +    relation = Relation.new
  
 -        pt.find('tag').each do |tag|
 -          relation.add_tag_keyval(tag['k'], tag['v'])
 -        end
 +    if !create and pt['id'] != '0'
 +      relation.id = pt['id'].to_i
 +    end
  
 -        pt.find('member').each do |member|
 -          relation.add_member(member['type'], member['ref'], member['role'])
 -        end
 +    relation.version = pt['version']
 +
 +    if create
 +      relation.timestamp = Time.now
 +      relation.visible = true
 +    else
 +      if pt['timestamp']
 +      relation.timestamp = Time.parse(pt['timestamp'])
        end
 -    rescue
 -      relation = nil
 +    end
 +
 +    pt.find('tag').each do |tag|
 +      relation.add_tag_keyval(tag['k'], tag['v'])
 +    end
 +
 +    pt.find('member').each do |member|
 +      relation.add_member(member['type'], member['ref'], member['role'])
      end
  
      return relation
@@@ -64,7 -61,6 +67,7 @@@
      el1['id'] = self.id.to_s
      el1['visible'] = self.visible.to_s
      el1['timestamp'] = self.timestamp.xmlschema
 +    el1['version'] = self.version.to_s
  
      user_display_name_cache = {} if user_display_name_cache.nil?
      
      return el1
    end 
  
-     
-   # collect relationships. currently done in one big block at the end;
-   # may need to move this upwards if people want automatic completion of
-   # relationships, i.e. deliver referenced objects like we do with ways... 
-   # FIXME: rip out the fucking SQL
-   def self.find_for_nodes_and_ways(node_ids, way_ids)
-     relations = []
-     if node_ids.length > 0
-       relations += Relation.find_by_sql("select e.* from current_relations e,current_relation_members em where " +
-             "e.visible=1 and " +
-             "em.id = e.id and em.member_type='node' and em.member_id in (#{node_ids.join(',')})")
-     end
-     if way_ids.length > 0
-       relations += Relation.find_by_sql("select e.* from current_relations e,current_relation_members em where " +
-             "e.visible=1 and " +
-             "em.id = e.id and em.member_type='way' and em.member_id in (#{way_ids.join(',')})")
-     end
-     relations # if you don't do this then it returns nil and not []
-   end
    # FIXME is this really needed?
    def members
      unless @members
    def save_with_history!
      Relation.transaction do
        t = Time.now
 +      self.version += 1
        self.timestamp = t
        self.save!
  
        tags = self.tags
 -
        RelationTag.delete_all(['id = ?', self.id])
 -
        tags.each do |k,v|
          tag = RelationTag.new
          tag.k = k
        end
  
        members = self.members
 -
        RelationMember.delete_all(['id = ?', self.id])
 -
        members.each do |n|
          mem = RelationMember.new
          mem.id = self.id
      end
    end
  
 +  def delete_with_history(user)
 +    if self.visible
 +      if RelationMember.find(:first, :joins => "INNER JOIN current_relations ON current_relations.id=current_relation_members.id", :conditions => [ "visible = 1 AND member_type='relation' and member_id=?", self.id ])
 +      raise OSM::APIPreconditionFailedError.new
 +      else
 +      self.user_id = user.id
 +      self.tags = []
 +      self.members = []
 +      self.visible = false
 +      save_with_history!
 +      end
 +    else
 +      raise OSM::APIAlreadyDeletedError.new
 +    end
 +  end
 +
 +  def update_from(new_relation, user)
 +    if !new_relation.preconditions_ok?
 +      raise OSM::APIPreconditionFailedError.new
 +    elsif new_relation.version != version
 +      raise OSM::APIVersionMismatchError.new(new_relation.version, version)
 +    else
 +      self.user_id = user.id
 +      self.tags = new_relation.tags
 +      self.members = new_relation.members
 +      self.visible = true
 +      save_with_history!
 +    end
 +  end
 +
    def preconditions_ok?
+     # These are hastables that store an id in the index of all 
+     # the nodes/way/relations that have already been added.
+     # Once we know the id of the node/way/relation exists
+     # we check to see if it is already existing in the hashtable
+     # if it does, then we return false. Otherwise
+     # we add it to the relevant hash table, with the value true..
+     # Thus if you have nodes with the ids of 50 and 1 already in the
+     # relation, then the hash table nodes would contain:
+     # => {50=>true, 1=>true}
+     nodes = Hash.new
+     ways = Hash.new
+     relations = Hash.new
      self.members.each do |m|
        if (m[0] == "node")
          n = Node.find(:first, :conditions => ["id = ?", m[1]])
          unless n and n.visible 
            return false
          end
+         if nodes[m[1]]
+           return false
+         else
+           nodes[m[1]] = true
+         end
        elsif (m[0] == "way")
          w = Way.find(:first, :conditions => ["id = ?", m[1]])
          unless w and w.visible and w.preconditions_ok?
            return false
          end
+         if ways[m[1]]
+           return false
+         else
+           ways[m[1]] = true
+         end
        elsif (m[0] == "relation")
          e = Relation.find(:first, :conditions => ["id = ?", m[1]])
          unless e and e.visible and e.preconditions_ok?
            return false
          end
+         if relations[m[1]]
+           return false
+         else
+           relations[m[1]] = true
+         end
        else
          return false
        end
      return false
    end
  
+   # Temporary method to match interface to nodes
+   def tags_as_hash
+     return self.tags
+   end
  end
diff --combined app/models/way.rb
index ea027fb47908d2148ae7d07476843972aeeebd86,64b11cf672aabebe946e5473a7da601a500d7201..34afc6585041e7fa3c723dc08bde40a8b24af83c
@@@ -1,15 -1,19 +1,19 @@@
  class Way < ActiveRecord::Base
    require 'xml/libxml'
  
+   set_table_name 'current_ways'
    belongs_to :user
  
-   has_many :nodes, :through => :way_nodes, :order => 'sequence_id'
+   has_many :old_ways, :foreign_key => 'id', :order => 'version'
    has_many :way_nodes, :foreign_key => 'id', :order => 'sequence_id'
-   has_many :way_tags, :foreign_key => 'id'
+   has_many :nodes, :through => :way_nodes, :order => 'sequence_id'
  
-   has_many :old_ways, :foreign_key => 'id', :order => 'version'
+   has_many :way_tags, :foreign_key => 'id'
  
-   set_table_name 'current_ways'
+   has_many :containing_relation_members, :class_name => "RelationMember", :as => :member
+   has_many :containing_relations, :class_name => "Relation", :through => :containing_relation_members, :source => :relation, :extend => ObjectFinder
  
    def self.from_xml(xml, create=false)
      begin
        p.string = xml
        doc = p.parse
  
 -      way = Way.new
 -
        doc.find('//osm/way').each do |pt|
 -        if !create and pt['id'] != '0'
 -          way.id = pt['id'].to_i
 -        end
 +      return Way.from_xml_node(pt, create)
 +      end
 +    rescue
 +      return nil
 +    end
 +  end
  
 -        if create
 -          way.timestamp = Time.now
 -          way.visible = true
 -        else
 -          if pt['timestamp']
 -            way.timestamp = Time.parse(pt['timestamp'])
 -          end
 -        end
 +  def self.from_xml_node(pt, create=false)
 +    way = Way.new
  
 -        pt.find('tag').each do |tag|
 -          way.add_tag_keyval(tag['k'], tag['v'])
 -        end
 +    if !create and pt['id'] != '0'
 +      way.id = pt['id'].to_i
 +    end
 +    
 +    way.version = pt['version']
  
 -        pt.find('nd').each do |nd|
 -          way.add_nd_num(nd['ref'])
 -        end
 +    if create
 +      way.timestamp = Time.now
 +      way.visible = true
 +    else
 +      if pt['timestamp']
 +      way.timestamp = Time.parse(pt['timestamp'])
        end
 -    rescue
 -      way = nil
 +    end
 +
 +    pt.find('tag').each do |tag|
 +      way.add_tag_keyval(tag['k'], tag['v'])
 +    end
 +
 +    pt.find('nd').each do |nd|
 +      way.add_nd_num(nd['ref'])
      end
  
      return way
@@@ -76,7 -74,6 +80,7 @@@
      el1['id'] = self.id.to_s
      el1['visible'] = self.visible.to_s
      el1['timestamp'] = self.timestamp.xmlschema
 +    el1['version'] = self.version.to_s
  
      user_display_name_cache = {} if user_display_name_cache.nil?
  
      t = Time.now
  
      Way.transaction do
 +      self.version += 1
        self.timestamp = t
        self.save!
 -    end
  
 -    WayTag.transaction do
        tags = self.tags
 -
        WayTag.delete_all(['id = ?', self.id])
 -
        tags.each do |k,v|
          tag = WayTag.new
          tag.k = k
          tag.id = self.id
          tag.save!
        end
 -    end
  
 -    WayNode.transaction do
        nds = self.nds
 -
        WayNode.delete_all(['id = ?', self.id])
 -
        sequence = 1
        nds.each do |n|
          nd = WayNode.new
          nd.save!
          sequence += 1
        end
 +
 +      old_way = OldWay.from_way(self)
 +      old_way.timestamp = t
 +      old_way.save_with_dependencies!
      end
 +  end
  
 -    old_way = OldWay.from_way(self)
 -    old_way.timestamp = t
 -    old_way.save_with_dependencies!
 +  def update_from(new_way, user)
 +    if !new_way.preconditions_ok?
 +      raise OSM::APIPreconditionFailedError.new
 +    elsif new_way.version != version
 +      raise OSM::APIVersionMismatchError.new(new_way.version, version)
 +    else
 +      self.user_id = user.id
 +      self.tags = new_way.tags
 +      self.nds = new_way.nds
 +      self.visible = true
 +      save_with_history!
 +    end
    end
  
    def preconditions_ok?
      return true
    end
  
 -  # Delete the way and it's relations, but don't really delete it - set its visibility to false and update the history etc to maintain wiki-like functionality.
 -  def delete_with_relations_and_history(user)
 +  def delete_with_history(user)
      if self.visible
          # FIXME
          # this should actually delete the relations,
          # not just throw a PreconditionFailed if it's a member of a relation!!
 +
 +      # FIXME: this should probably renamed to delete_with_history
        if RelationMember.find(:first, :joins => "INNER JOIN current_relations ON current_relations.id=current_relation_members.id",
                               :conditions => [ "visible = 1 AND member_type='way' and member_id=?", self.id])
          raise OSM::APIPreconditionFailedError
    end
  
    # delete a way and it's nodes that aren't part of other ways, with history
 +
 +  # FIXME: merge the potlatch code to delete the relations
    def delete_with_relations_and_nodes_and_history(user)
      
      node_ids = self.nodes.collect {|node| node.id }
      
      self.user_id = user.id
  
 -    self.delete_with_relations_and_history(user)
 +    self.delete_with_history(user)
  
    end
+   # Temporary method to match interface to nodes
+   def tags_as_hash
+     return self.tags
+   end
  end
diff --combined config/environment.rb
index 8aaab730289311ff083812694406de99cf4ec8ce,495f94d80a63f08b22f639bdcbaaace8c6d946e0..fb7573d2a5b13b7177c6381435f77e25c98ec3db
@@@ -5,18 -5,22 +5,22 @@@
  ENV['RAILS_ENV'] ||= 'production'
  
  # Specifies gem version of Rails to use when vendor/rails is not present
- # DO NOT BUMP THIS TO 2.0.2 AS THE LIVE SERVERS CAN'T RUN THAT
- RAILS_GEM_VERSION = '2.0.1' unless defined? RAILS_GEM_VERSION
+ RAILS_GEM_VERSION = '2.0.2' unless defined? RAILS_GEM_VERSION
  
  # Set the server URL
  SERVER_URL = ENV['OSM_SERVER_URL'] || 'www.openstreetmap.org'
  
  # Application constants needed for routes.rb - must go before Initializer call
 -API_VERSION = ENV['OSM_API_VERSION'] || '0.5'
 +API_VERSION = ENV['OSM_API_VERSION'] || '0.6'
  
- # Set to :readonly to put the API in read-only mode or :offline to
- # take it completely offline
- API_STATUS = :online
+ # Set application status - possible settings are:
+ #
+ #   :online - online and operating normally
+ #   :api_readonly - site online but API in read-only mode
+ #   :api_offline - site online but API offline
+ #   :database_offline - database offline with site in emergency mode
+ #
+ OSM_STATUS = :online
  
  # Bootstrap the Rails environment, frameworks, and default configuration
  require File.join(File.dirname(__FILE__), 'boot')
@@@ -29,7 -33,9 +33,9 @@@ Rails::Initializer.run do |config
  
    # Skip frameworks you're not going to use (only works if using vendor/rails).
    # To use Rails without a database, you must remove the Active Record framework
-   # config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
+   if OSM_STATUS == :database_offline
+     config.frameworks -= [ :active_record ]
+   end
  
    # Only load the plugins named here, in the order given. By default, all plugins 
    # in vendor/plugins are loaded in alphabetical order.
diff --combined config/routes.rb
index 5ca4f5a5362efd90b288a636827732a174691cc8,854e7f00364370c8fd4e41c743324761f27103ef..592178474286fd009d36522163112fc4fe48baa0
@@@ -1,11 -1,6 +1,11 @@@
  ActionController::Routing::Routes.draw do |map|
  
    # API
 +  map.connect "api/#{API_VERSION}/changeset/create", :controller => 'changeset', :action => 'create'
 +  map.connect "api/#{API_VERSION}/changeset/upload", :controller => 'changeset', :action => 'upload'
 +  map.connect "api/#{API_VERSION}/changeset/:id", :controller => 'changeset', :action => 'read', :id => /\d+/
 +  map.connect "api/#{API_VERSION}/changeset/:id/close", :controller => 'changeset', :action => 'close', :id =>/\d+/
 +  
    map.connect "api/#{API_VERSION}/node/create", :controller => 'node', :action => 'create'
    map.connect "api/#{API_VERSION}/node/:id/ways", :controller => 'way', :action => 'ways_for_node', :id => /\d+/
    map.connect "api/#{API_VERSION}/node/:id/relations", :controller => 'relation', :action => 'relations_for_node', :id => /\d+/
    
    # Potlatch API
    
 +  map.connect "api/0.5/amf", :controller =>'amf', :action =>'talk'
    map.connect "api/#{API_VERSION}/amf", :controller =>'amf', :action =>'talk'
    map.connect "api/#{API_VERSION}/swf/trackpoints", :controller =>'swf', :action =>'trackpoints'
    
+   # Data browsing
+   map.connect '/browse', :controller => 'browse', :action => 'index'
+   map.connect '/browse/start', :controller => 'browse', :action => 'start'
+   map.connect '/browse/way/:id', :controller => 'browse', :action => 'way', :id => /\d+/
+   map.connect '/browse/way/:id/history', :controller => 'browse', :action => 'way_history', :id => /\d+/
+   map.connect '/browse/node/:id', :controller => 'browse', :action => 'node', :id => /\d+/
+   map.connect '/browse/node/:id/history', :controller => 'browse', :action => 'node_history', :id => /\d+/
+   map.connect '/browse/relation/:id', :controller => 'browse', :action => 'relation', :id => /\d+/
+   map.connect '/browse/relation/:id/history', :controller => 'browse', :action => 'relation_history', :id => /\d+/
+   
    # web site
  
    map.connect '/', :controller => 'site', :action => 'index'
@@@ -70,6 -74,7 +80,7 @@@
    map.connect '/export', :controller => 'site', :action => 'export'
    map.connect '/login', :controller => 'user', :action => 'login'
    map.connect '/logout', :controller => 'user', :action => 'logout'
+   map.connect '/offline', :controller => 'site', :action => 'offline'
    map.connect '/user/new', :controller => 'user', :action => 'new'
    map.connect '/user/save', :controller => 'user', :action => 'save'
    map.connect '/user/confirm', :controller => 'user', :action => 'confirm'
    map.connect '/message/read/:message_id', :controller => 'message', :action => 'read'
    map.connect '/message/mark/:message_id', :controller => 'message', :action => 'mark'
    map.connect '/message/reply/:message_id', :controller => 'message', :action => 'reply'
-   map.connect '/message/delete/:message_id', :controller => 'message', :action => 'destroy'
  
    # fall through
    map.connect ':controller/:id/:action'