# 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

module Asp
  class Response
    require 'asp/common'
    require 'asp/compile'
    
    attr_accessor :charset,:contentType,:expires,:expiresAbsolute,:bEnd
  
    public
    
	def binaryWrite( data )
	  $stdout.binmode
	  print data
	end

    def write( data )
      print data
    end
    
    def addHeader( name, value )
      @hxHeader.store( name, value )
    end
  
    def appendToLog( message )
      @oApacheRequest.server.log_error( "[Ruby/ASP] [%d] %s", $$, message )
    end
  
    def end
      @bEnd = 1
      goto :e
    end
  
## -- ##     def include( filename, *args )
## -- ##       funcname = "i__"+rand( Time::new.to_i ).to_s+"__"+rand( Time::new.to_i ).to_s
## -- ##       code = compile(filename.untaint)
## -- ##       totalcode = "def " + funcname + "( args=nil )\n" + code + "\nend\n"
## -- ##       
## -- ##       tmpdir = Asp::Common::stateDir
## -- ##       file = Tempfile.new(File.basename(filename) + ".", tmpdir).untaint
## -- ##       begin
## -- ##         file.print(totalcode)
## -- ##         file.close
## -- ##         #load(file.path, true)
## -- ##         load(file.path)
## -- ##         eval( funcname + "( args )" )
## -- ##       ensure
## -- ##         file.close(true)
## -- ##       end
## -- ##     end
    def include( filename, *args )
      funcname = "i__"+rand( Time::new.to_i ).to_s+"__"+rand( Time::new.to_i ).to_s
      code = compile(filename)
      totalcode = "def " + funcname + "( args=nil )\n" + code + "\nend\n"
    
      @oAspHandler.load_code( totalcode, nil )
      eval( "@oAspHandler." + funcname + "( args )" )
    end

    def trapInclude( filename, *args )
      funcname = "i__"+rand( Time::new.to_i ).to_s+"__"+rand( Time::new.to_i ).to_s
      code = compile(filename)
      totalcode = "def " + funcname + "( args=nil )\n" + code + "\nend\n"
      o = Asp::Eval::new( totalcode, funcname, args )
      return o.get
    end
  
    def redirect( url )
      self.addHeader( "location", url )
      @oApacheRequest.status = 302
    end
    
    #
    # $Response.cookies('name', 'value');
    # --> Set-Cookie: name=value; path=/
    # 
    # $Response.cookies("Test", "data1", "test value");
    # $Response.cookies("Test", "data2", "more test");      
    # $Response.cookies("Test", "Expires", &HTTP::Date::time2str(time+86400)); 
    # $Response.cookies("Test", "Secure", 1);               
    # $Response.cookies("Test", "Path", "/");
    # $Response.cookies("Test", "Domain", "host.com");
    # --> Set-Cookie:Test=data1=test%20value&data2=more%20test;    \
    #            expires=Fri, 23 Apr 1999 07:19:52 GMT;        \
    #            path=/; domain=host.com; secure
    def cookies( name, key, value=nil )
      if @hvCookies[name].nil? == true
        @hvCookies[name] = Hash::new
      end
      
      if value.nil? == false 
        @hvCookies[name][key] = String( value )
      else
        # we are assigning cookie with name the value of key
        @hvCookies[name]['Value'] = String( key )
      end 
    end

    ## -- Reserved for Ruby/ASP internal use --
    def getHeader
      xTime = nil
      if @expires != nil
        xTime = Asp::Common::time2str( Time::now + @expires )
      elsif @expiresAbsolute != nil
        xTime = Asp::Common::str2time( @expiresAbsolute )
      end
      if xTime != nil
        @hxHeader.store( "Expires", xTime )
      end
      return @hxHeader
    end
    
    def addCookiesHeader
      cookie_header = Array::new
      
      @hvCookies.each_key { |name| 
        value = Array::new
  
        #if name == "session-id"
        if name == Asp::Common::sessionID
          self.appendToLog( format( "You can't use %s for a cookie name since it is reserved for session management", Asp::Common::sessionID ) )
        else
          cookie = @hvCookies[name]
          cookie['Path'] ||= "/"
  
          cookie.each_pair { |k,v|
            case k.downcase
            when "expires"
              value[1] = "expires=#{v}"
            when "path"
              value[2] = "path=#{v}"
            when "domain"
              value[3] = "domain=#{v}"
            when "secure"
              value[4] = "secure"
            when "value"
              # we set the value later, nothing for now
            else
              if String( @hvCookies[name]['Value'].class ) != "String"
                if @hvCookies[name]['Value'].nil? == true
                  @hvCookies[name]['Value'] = Hash::new
                end
                @hvCookies[name]['Value'][k] = v
              end
            end
          }
 
          if String( @hvCookies[name]['Value'].class ) == "Hash"
            dict = Array::new
            @hvCookies[name]['Value'].each_pair { |k,v|
              dict.push( format( "%s=%s", Asp::Common::url_encode( k ), Asp::Common::url_encode( v ) ) )
            }
            value[0] = dict.join( "&" )
          else
            value[0] = Asp::Common::url_encode( @hvCookies[name]['Value'] )
          end
          value[0] = Asp::Common::url_encode( name )+"="+value[0]
          
          cookie = Array::new
          [0,1,2,3,4].each { |iCpt|
            next unless value[iCpt].nil? == false
            cookie.push( value[iCpt] )
          }
    
          cookie_header.push( cookie.join( "; " ) )
        end
      }

      return( cookie_header )
    end

    private 
    
    def compile(filename)
      open(filename) do |f|
        return @compiler.compile(f.read)
      end
    end   

    def initialize( r, oAspError, aspHandler )
      @oApacheRequest = r
      @oAspError = oAspError
      @oAspHandler = aspHandler

      @charset = "iso-8859-1"
      @contentType = "text/html"
      @expires = nil
      @expiresAbsolute = nil
      @bEnd = 0
      @hxHeader = Hash::new
      @hvCookies = Hash::new

      @compiler = AspCompiler.new
      @compiler.put_cmd = 'print'
    end
  
  end

  class Eval
    def initialize( code, funcname, args=nil )
      code += "\n" + funcname + "( args )\n" 
      @data = ""
      keep = $defout
      $defout = self
      eval( code.untaint ).untaint
      $defout = keep
    end

    def write( x )
      @data += String( x )
    end
  
    def get
      @data
    end
  end

end
