# Copyright (C) 2003, 2004 Gregoire Lejeune <gregoire.lejeune@free.fr>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA

# See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemWeb.asp

module Asp
  class Request
    require 'asp/params'
    require 'asp/common'

    public
    # Returns the value of the input of name used in a form with POST method.
    def form( key )
      if @oApacheRequest.request_method == "POST" 
        if @params[key].nil? == false and @params[key].size > 0
          if @params[key].size == 1
            return @params[key][0]
          else
            return @params[key]
          end
        else
          return nil
        end
      end
    end
  
    # Returns the value of the input of name used in a form with GET method.
    def queryString( key )
      if @oApacheRequest.request_method == "GET" or
         @oApacheRequest.request_method == "HEAD"
        if @params[key].nil? == false and @params[key].size > 0
          if @params[key].size == 1
            return @params[key][0]
          else
            return @params[key]
          end
        else
          return nil
        end
      end
    end

    # API extension. Returns the unparsed query string.
    def query
      @param.getQuery( )
    end

    # Returns the value of the Cookie with name. If a key is specified, then a 
    # lookup will be done on the cookie as if it were a query string.
    def cookies( name=nil, key=nil )
      if name.nil? == true
        return @cookies
      elsif key.nil? == true and @cookies[name].nil? == false
        return @cookies[name]
      elsif String( @cookies[name].class ) == "Hash" and @cookies[name][key].nil? == false
        return @cookies[name][key]
      end

      return nil
    end

    # API extension. Returns the client HTTP request method, as in GET or POST.
    def method
      return @oApacheRequest.request_method
    end

    # The amount of data sent by the client in the body of the request, usually 
    # the length of the form data. This is the same value as
    #     $Request.serverVariables('CONTENT_LENGTH')
    def totalBytes
      return @oApacheRequest.headers_in["Content-Length"] || 0
    end

    # Returns the value of the server variable / environment variable with name name. 
    # If name is not specified, returns a ref to a hash of all the server / environment 
    # variables data. The following would be a common use of this method:
    # 
    #     env = $Request.serverVariables();
    #     # env here would be equivalent to the ENV.
    def serverVariables( name=nil )
      if name.nil? == true
        return @oApacheRequest.subprocess_env
        #return ENV.untaint
      else
        return @oApacheRequest.subprocess_env.get( name )
        #return ENV[name].untaint
      end
    end

    # Returns a string array of client-supported MIME accept types.
    def acceptTypes 
      ## -> string[]
      return @oApacheRequest.headers_in["Accept"].split( %r{,\s*} )
    end

    # Returns the ASP application's virtual application root path on the server.
    def applicationPath 
      ## -> string
    end

    # Returns information about the requesting client's browser capabilities.
    def browser
      ## -> System.Web.HttpBrowserCapabilities
    end

    # Returns the current request's client security certificate.
    def clientCertificate
      ## -> System.Web.HttpClientCertificate
    end

    # Returns the character set of the entity-body.
    def contentEncoding
      ## -> System.Text.Encoding
    end

    alias :contentLength :totalBytes
  
    # Returns the MIME content type of the incoming request.
    def contentType
      ## -> string
    end
  
    # Returns the virtual path of the current request.
    def currentExecutionFilePath
      ## -> string TO BE CORRECTED
      return serverVariables( 'REQUEST_URI' )
    end

    alias :filePath :currentExecutionFilePath

    # Returns the collection of client-uploaded files (Multipart MIME format).
    def files
      ## -> System.Web.HttpFileCollection
    end
  
    # Returns or sets the filter to use when reading the current input stream.
    def filter
      ## -> stream
    end

    # Returns a collection of HTTP headers.
    def headers( xName = nil )
      if xName.nil? == false 
        if @oApacheRequest.headers_in[xName]
          return @oApacheRequest.headers_in[xName]
        else
          return nil
        end
      end  
      
      return @oApacheRequest.headers_in
    end

    alias :httpMethod :method

    # Returns the contents of the incoming HTTP entity body.
    def inputStream
      ## -> stream
    end
  
    # Returns a value indicating whether the user has been authenticated.
    def isAuthenticated
      ## -> bool
      if @oApacheRequest.auth_name
        return true
      end
      
      return false
    end

    # Returns a value indicting whether the HTTP connection uses secure sockets (that is, HTTPS).
    def isSecureConnection
      ## -> bool
    end

    # TODO
    def item( xKey )
      ## -> string
    end

    # Returns a combined collection of QueryString, Form, ServerVariables, and Cookies items.
    def params
      ## -> System.Collections.Specialized.NameValueCollection
    end

    alias :path :currentExecutionFilePath

    # Returns additional path information for a resource with a URL extension.
    def pathInfo
      ## -> string
    end

    # Returns the physical file system path of the currently executing server application's root directory.
    def physicalApplicationPath
      ## -> string
    end

    # Returns the physical file system path corresponding to the requested URL.
    def physicalPath
      ## -> string TO BE CORRECTED
      return( serverVariables( 'DOCUMENT_ROOT' ) + serverVariables( "SCRIPT_NAME" ) )
    end

    alias :rawUrl :currentExecutionFilePath

    alias :requestType :method

    # Returns Information about the URL of the current request.
    def url
      ## -> System.Uri
    end

    # Returns information about the URL of the client's previous request that linked to the current URL.
    def urlReferrer
      ## -> System.Uri
    end

    # Returns the raw user agent string of the client browser.
    def userAgent
      ## -> string
      return @oApacheRequest.headers_in['User-Agent']
    end

    # Returns the IP host address of the remote client.
    def userHostAddress
      ## -> string
      # return @oApacheRequest.remote_host( )
      return @oApacheRequest.connection.remote_ip
    end
  
    # Returns the DNS name of the remote client.
    def userHostName
      # return @oApacheRequest.headers_in['Host']
      return @oApacheRequest.connection.remote_host
    end

    # Returns a sorted string array of client language preferences.
    def userLanguages
      ## -> string[]
      return @oApacheRequest.headers_in["Accept-Language"].split( %r{,\s*} )
    end

    # Performs a binary read of a specified number of bytes from the current input stream.
    def binaryRead( iCount )
      ## -> bytes[]
    end

    # Maps an incoming image-field form parameter to appropriate x/y coordinate values.
    def mapImageCoordinates( xImageFileName )
      ## -> int[]
    end
  
    # Maps the specified virtual path to a physical path.
    def mapPath( xVirtualPath, xBaseVirtualDir = nil, bAllowCrossAppMapping = nil )
      ## -> string
    end

    # Saves an HTTP request to disk.
    def saveAs( xFilename, bIncludeHeaders )
      ## -> void
    end

    # Validates data submitted by a client browser and raises an exception if potentially dangerous data is present.
    def validateInput( )
      ## -> void
    end

    private 
    def getCookies
      cookiesStr = @oApacheRequest.headers_in['Cookie']
      cookies = Hash::new

      if cookiesStr.nil? == false
        parts = cookiesStr.split( /;\s*/ )
        parts.each { |v|
          name, value = v.split( /\=/, 2 )
          name = Asp::Common::url_decode( name )
          next if name == Asp::Common::sessionID
          next if cookies[name].nil? == false
          if /\=/ =~ value
            cookies[name] = Asp::Common::parseCookie( value )
          else
            cookies[name] = Asp::Common::url_decode( value )
          end
        }
      end

      return cookies
    end
    
    def initialize( r, oAspError, aspHandler )
      @oApacheRequest = r
      @oAspError = oAspError
      @oAspHandler = aspHandler
      
      @param = Asp::Params::new( @oApacheRequest )
      @params = @param.params
      @cookies = getCookies
    end
  
  end
end
