=begin

= https.rb -- SSL/TLS enhancement for Net::HTTP.

  Copyright (C) 2001 GOTOU Yuuzou <gotoyuzo@notwork.org>

  This program requires Net 1.2.0 or higher version.
  You can get it from RAA or Ruby's CVS repository.

  $IPR: https.rb,v 1.5 2001/07/15 22:24:05 gotoyuzo Exp $

  2001/11/06: Contiributed to Ruby/OpenSSL project.
  $Id: https.rb,v 1.5 2003/07/16 07:03:00 gotoyuzo Exp $

== class Net::HTTP

== Example

Simple HTTP client is here:

    require 'net/http'
    host, port, path = "localhost", 80, "/"
    if %r!http://(.*?)(?::(\d+))?(/.*)! =~ ARGV[0]
      host   = $1
      port   = $2.to_i if $2
      path   = $3
    end
    h = Net::HTTP.new(host, port)
    h.get2(path){ |resp| print resp.body }

It can be replaced by follow one:

    require 'net/https'
    host, port, path = "localhost", 80, "/"
    if %r!(https?)://(.*?)(?::(\d+))?(/.*)! =~ ARGV[0]
      scheme = $1
      host   = $2
      port   = $3 ? $3.to_i : ((scheme == "http") ? 80 : 443)
      path   = $4
    end
    h = Net::HTTP.new(host, port)
    h.use_ssl = true if scheme == "https" # enable SSL/TLS
    h.get2(path){ |resp| print resp.body }

=== Instance Methods

: use_ssl
    returns ture if use SSL/TLS with HTTP.

: use_ssl=((|true_or_false|))
    sets use_ssl.

: peer_cert
    return the X.509 certificates the server presented.

: key=((|key|))
    Sets an OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
    (This method is appeared in Michal Rokos's OpenSSL extention.)

: key_file=((|path|))
    Sets a private key file to use in PEM format.

: cert=((|cert|))
    Sets an OpenSSL::X509::Certificate object as client certificate.
    (This method is appeared in Michal Rokos's OpenSSL extention.)

: cert_file=((|path|))
    Sets pathname of a X.509 certification file in PEM format.

: ca_cert=((|cert|))
    Sets an OpenSSL::X509::Certificate object as specific CA certifacate.
    (This method is appeared in Michal Rokos's OpenSSL extention.)

: ca_file=((|path|))
    Sets path of a CA certification file in PEM format.
    The file can contrain several CA certificats.

: ca_path=((|path|))
    Sets path of a CA certification directory containing certifications
    in PEM format.

: verify_mode=((|mode|))
    Sets the flags for server the certification verification at
    begining of SSL/TLS session.

: verify_callback=((|proc|))
    Sets the verify callback for the server certification verification.

: verify_depth=((|num|))
    Sets the maximum depth for the certificate chain verification.

=end

require 'net/protocols'
require 'net/http'

module Net
  class HTTP
    def HTTP.socket_type
      ::Net::NetPrivate::SSLSocket
    end

    attr_accessor :use_ssl
    attr_writer :key, :cert, :key_file, :cert_file
    attr_writer :ca_file, :ca_path, :timeout
    attr_writer :verify_mode, :verify_callback, :verify_depth
    attr_reader :peer_cert

    def on_connect
      if use_ssl
        if proxy?
          @socket.writeline(
              sprintf('CONNECT %s:%s HTTP/%s', @address, @port, "1.0"))
          @socket.writeline ''
          begin
            resp = HTTPResponse.read_new(@socket)      # ruby 1.8
          rescue ArgumentError
            resp = HTTPResponse.read_new(@socket, nil) # ruby 1.6
          end
          if resp.code != '200'
            raise resp.message
          end
        end
        @socket.key             = @key       if @key
        @socket.key_file        = @key_file  if @key_file
        @socket.cert            = @cert      if @cert
        @socket.cert_file       = @cert_file if @cert_file
        @socket.ca_file         = @ca_file
        @socket.ca_path         = @ca_path
        @socket.verify_mode     = @verify_mode
        @socket.verify_callback = @verify_callback
        @socket.verify_depth    = @verify_depth
        @socket.timeout         = @timeout
        @socket.ssl_connect
        if @socket.socket.verify_mode != OpenSSL::SSL::VERIFY_NONE
          @socket.socket.post_connection_check(@address)
        end
        @peer_cert = @socket.peer_cert
      end
    end

    module ProxyMod
      def edit_path( path )
        if use_ssl
          'https://' + addr_port + path
        else
          'http://' + addr_port + path
        end
      end
    end

  end
end
