# Web::Cookie
# Copyright(c) 2002 MoonWolf <moonwolf@moonwolf.com>
require "web/common"
require 'time'

module Web
  class Cookie
    def self.parse(header,req)
      cookies = []
      cookie = nil
      until header.empty?
        case header
        when /\A\s*;\s*/
          header = $'
        when /\A\s*,\s*/
          header = $'
          if cookie
            if cookie.domain == nil
              cookie.domain = req.server_name.downcase
            end
            cookies << cookie
          end
          cookie = nil
        when /\Aexpires\s*=\s*(?:"(\w+, \d\d-\w+-\d+ \d+:\d+:\d+ GMT)"|(\w+, \d\d-\w+-\d+ \d+:\d+:\d+ GMT))/i
          header = $'
          cookie.expires = $1 || $2
        when /\A([^\000-\040\042\073\075\177]+)(?:\s*=\s*(?:([^ ,;]*)|"(.*?)"))?/
          header = $'
          value = $2 || $3
          name  = $1
          case name
          when 'comment'
            cookie.comment = value
          when 'domain'
            cookie.domain  = value.sub(/\A\./,'')
          when 'path'
            cookie.path    = value
          when 'secure'
            cookie.secure  = true
          when 'version'
            cookie.version = value
          when /^\$/
            #
          else
            if cookie
              if cookie.domain == nil
                cookie.domain = req.server_name.downcase
              end
              cookies << cookie
            end
            cookie = Cookie.new(name, value)
          end
        when /\A[\000-\377]/n
          header = $'
        end
      end
      if cookie
        if cookie.domain == nil
          cookie.domain = req.server_name.downcase
        end
        cookies << cookie
      end
      cookies
    end

    def initialize(name, value='')
      @name    = name
      @value   = value
      @comment = nil
      @domain  = nil
      @expires = nil
      @path    = nil
      @secure  = nil
      @version = nil
    end
    attr_accessor :name, :value, :comment, :domain, :path, :secure, :version
    attr_reader :expires
    
    def expires=(tm)
      if Time === tm
        @expires = tm
      elsif tm==nil
        @expires = nil
      else
        @expires = Time.parse(tm)
      end
    end
    
    def to_request_header
      "#{@name}=#{@value}"
    end
    
    def to_response_header
      value = @value.to_s
      ary = []
      ary << "#{@name}=#{value}"
      ary << "comment=#{@comment}" if @comment
      ary << "domain=#{@domain}" if @domain
      if @expires
        ary << "expires=#{Common::rfc1123date(@expires)}"
      end
      ary << "path=#{@path}" if @path
      ary << "secure" if @secure
      ary << "version=#{@version}" if @version
      ary.join("; ")
    end
    
    class Cookies < Web::Common::ParamHash
      def initialize(header=nil)
        super()
        parse(header) if header
      end
      
      def parse(header, req)
        Web::Cookie::parse(header, req).each {|cookie|
          self.add(cookie.name, cookie)
        }
        self
      end
    end # Cookies
  end # Cookie
end # Web
