add smusher dep

This commit is contained in:
tdreyno 2009-11-17 11:13:32 -08:00
parent 45ba469b70
commit ed83154945
50 changed files with 9376 additions and 50 deletions

1
.gitignore vendored
View file

@ -26,3 +26,4 @@ bin/spec
bin/sprocketize
bin/thin
bin/tt
bin/smusher

View file

@ -11,6 +11,7 @@ gem "rack-test"
gem "yui-compressor"
gem "haml"
gem "compass"
gem "smusher"
gem "rspec"
gem "sdoc"

View file

@ -21,6 +21,7 @@ begin
gem.add_dependency("sinatra-content-for")
gem.add_dependency("rack-test")
gem.add_dependency("yui-compressor")
gem.add_dependency("smusher")
gem.add_dependency("haml", ">=2.1.0")
gem.add_dependency("compass")
gem.add_development_dependency("rspec")

View file

@ -26,9 +26,9 @@ configure :build do
# Shrink/smush PNG/JPEGs on build
# enable :smush_pngs
# Enable cache buster
# enable :cache_buster
# Or use a different image path
# set :http_path, "/Content/images/"
# Disable cache buster
# disable :cache_buster
end

BIN
vendor/gems/cache/httpclient-2.1.5.2.gem vendored Normal file

Binary file not shown.

BIN
vendor/gems/cache/smusher-0.4.2.gem vendored Normal file

Binary file not shown.

View file

@ -6,64 +6,68 @@ module Bundler
ENV["PATH"] = "#{dir}/../../bin:#{ENV["PATH"]}"
ENV["RUBYOPT"] = "-r#{file} #{ENV["RUBYOPT"]}"
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rdoc-2.4.3/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rdoc-2.4.3/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/configuration-1.1.0/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/configuration-1.1.0/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/builder-2.1.2/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/builder-2.1.2/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/daemons-1.0.10/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/daemons-1.0.10/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/extlib-0.9.13/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/extlib-0.9.13/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/json-1.2.0/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/json-1.2.0/ext/json/ext")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/json-1.2.0/ext")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/json-1.2.0/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/eventmachine-0.12.10/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/eventmachine-0.12.10/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rack-1.0.1/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rack-1.0.1/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/shotgun-0.4/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/shotgun-0.4/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rack-test-0.5.2/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rack-test-0.5.2/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sinatra-0.9.4/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sinatra-0.9.4/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/thin-1.2.5/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/thin-1.2.5/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sdoc-0.2.14.1/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sdoc-0.2.14.1/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/yui-compressor-0.9.1/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/yui-compressor-0.9.1/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/polyglot-0.2.9/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/polyglot-0.2.9/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/treetop-1.4.2/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/treetop-1.4.2/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rake-0.8.7/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rake-0.8.7/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/launchy-0.3.3/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/launchy-0.3.3/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sprockets-1.0.2/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sprockets-1.0.2/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/haml-2.2.13/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/haml-2.2.13/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/diff-lcs-1.1.2/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/diff-lcs-1.1.2/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rspec-1.2.9/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rspec-1.2.9/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/highline-1.5.1/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/highline-1.5.1/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/templater-1.0.0/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/templater-1.0.0/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/term-ansicolor-1.0.4/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/term-ansicolor-1.0.4/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/extlib-0.9.13/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/extlib-0.9.13/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/highline-1.5.1/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/highline-1.5.1/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/diff-lcs-1.1.2/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/diff-lcs-1.1.2/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/cucumber-0.4.4/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/cucumber-0.4.4/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sinatra-content-for-0.2/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sinatra-content-for-0.2/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rspec-1.2.9/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rspec-1.2.9/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/templater-1.0.0/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/templater-1.0.0/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/eventmachine-0.12.10/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/eventmachine-0.12.10/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/daemons-1.0.10/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/daemons-1.0.10/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/haml-2.2.13/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/haml-2.2.13/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/httpclient-2.1.5.2/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/httpclient-2.1.5.2/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/json-1.2.0/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/json-1.2.0/ext/json/ext")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/json-1.2.0/ext")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/json-1.2.0/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rake-0.8.7/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rake-0.8.7/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sprockets-1.0.2/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sprockets-1.0.2/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rack-1.0.1/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rack-1.0.1/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/thin-1.2.5/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/thin-1.2.5/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rack-test-0.5.2/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rack-test-0.5.2/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/configuration-1.1.0/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/configuration-1.1.0/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/launchy-0.3.3/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/launchy-0.3.3/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/shotgun-0.4/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/shotgun-0.4/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sinatra-0.9.4/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sinatra-0.9.4/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/smusher-0.4.2/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/smusher-0.4.2/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rdoc-2.4.3/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rdoc-2.4.3/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sdoc-0.2.14.1/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sdoc-0.2.14.1/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/compass-0.8.17/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/compass-0.8.17/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sinatra-content-for-0.2/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sinatra-content-for-0.2/lib")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/yui-compressor-0.9.1/bin")
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/yui-compressor-0.9.1/lib")
@gemfile = "#{dir}/../../Gemfile"
@ -134,7 +138,7 @@ end
# Define all the Gem errors for gems that reference them.
module Gem
def self.ruby ; "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby" ; end
def self.ruby ; "/Users/tdreyno/homebrew/Cellar/ruby/1.9.1-p243/bin/ruby" ; end
class LoadError < ::LoadError; end
class Exception < RuntimeError; end
class CommandLineError < Exception; end

View file

@ -0,0 +1,53 @@
# HTTPAccess2 - HTTP accessing library.
# Copyright (C) 2000-2007 NAKAMURA, Hiroshi <nakahiro@sarion.co.jp>.
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
# redistribute it and/or modify it under the same terms of Ruby's license;
# either the dual license version in 2003, or any later version.
# http-access2.rb is based on http-access.rb in http-access/0.0.4. Some part
# of code in http-access.rb was recycled in http-access2.rb. Those part is
# copyrighted by Maehashi-san.
require 'httpclient'
module HTTPAccess2
VERSION = ::HTTPClient::VERSION
RUBY_VERSION_STRING = ::HTTPClient::RUBY_VERSION_STRING
SSLEnabled = ::HTTPClient::SSLEnabled
SSPIEnabled = ::HTTPClient::SSPIEnabled
DEBUG_SSL = true
Util = ::HTTPClient::Util
class Client < ::HTTPClient
class RetryableResponse < StandardError
end
end
SSLConfig = ::HTTPClient::SSLConfig
BasicAuth = ::HTTPClient::BasicAuth
DigestAuth = ::HTTPClient::DigestAuth
NegotiateAuth = ::HTTPClient::NegotiateAuth
AuthFilterBase = ::HTTPClient::AuthFilterBase
WWWAuth = ::HTTPClient::WWWAuth
ProxyAuth = ::HTTPClient::ProxyAuth
Site = ::HTTPClient::Site
Connection = ::HTTPClient::Connection
SessionManager = ::HTTPClient::SessionManager
SSLSocketWrap = ::HTTPClient::SSLSocketWrap
DebugSocket = ::HTTPClient::DebugSocket
class Session < ::HTTPClient::Session
class Error < StandardError
end
class InvalidState < Error
end
class BadResponse < Error
end
class KeepAliveDisconnected < Error
end
end
end

View file

@ -0,0 +1 @@
require 'httpclient/cookie'

View file

@ -0,0 +1 @@
require 'httpclient/http'

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,522 @@
# HTTPClient - HTTP client library.
# Copyright (C) 2000-2009 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
#
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
# redistribute it and/or modify it under the same terms of Ruby's license;
# either the dual license version in 2003, or any later version.
require 'digest/md5'
require 'httpclient/session'
class HTTPClient
begin
require 'net/ntlm'
NTLMEnabled = true
rescue LoadError
NTLMEnabled = false
end
begin
require 'win32/sspi'
SSPIEnabled = true
rescue LoadError
SSPIEnabled = false
end
# Common abstract class for authentication filter.
#
# There are 2 authentication filters.
# WWWAuth:: Authentication filter for handling authentication negotiation
# between Web server. Parses 'WWW-Authentication' header in
# response and generates 'Authorization' header in request.
# ProxyAuth:: Authentication filter for handling authentication negotiation
# between Proxy server. Parses 'Proxy-Authentication' header in
# response and generates 'Proxy-Authorization' header in request.
class AuthFilterBase
private
def parse_authentication_header(res, tag)
challenge = res.header[tag]
return nil unless challenge
challenge.collect { |c| parse_challenge_header(c) }.compact
end
def parse_challenge_header(challenge)
scheme, param_str = challenge.scan(/\A(\S+)(?:\s+(.*))?\z/)[0]
return nil if scheme.nil?
return scheme, param_str
end
end
# Authentication filter for handling authentication negotiation between
# Web server. Parses 'WWW-Authentication' header in response and
# generates 'Authorization' header in request.
#
# Authentication filter is implemented using request filter of HTTPClient.
# It traps HTTP response header and maintains authentication state, and
# traps HTTP request header for inserting necessary authentication header.
#
# WWWAuth has sub filters (BasicAuth, DigestAuth, NegotiateAuth and
# SSPINegotiateAuth) and delegates some operations to it.
# NegotiateAuth requires 'ruby/ntlm' module.
# SSPINegotiateAuth requires 'win32/sspi' module.
class WWWAuth < AuthFilterBase
attr_reader :basic_auth
attr_reader :digest_auth
attr_reader :negotiate_auth
attr_reader :sspi_negotiate_auth
# Creates new WWWAuth.
def initialize
@basic_auth = BasicAuth.new
@digest_auth = DigestAuth.new
@negotiate_auth = NegotiateAuth.new
@sspi_negotiate_auth = SSPINegotiateAuth.new
# sort authenticators by priority
@authenticator = [@negotiate_auth, @sspi_negotiate_auth, @digest_auth, @basic_auth]
end
# Resets challenge state. See sub filters for more details.
def reset_challenge
@authenticator.each do |auth|
auth.reset_challenge
end
end
# Set authentication credential. See sub filters for more details.
def set_auth(uri, user, passwd)
@authenticator.each do |auth|
auth.set(uri, user, passwd)
end
reset_challenge
end
# Filter API implementation. Traps HTTP request and insert
# 'Authorization' header if needed.
def filter_request(req)
@authenticator.each do |auth|
if cred = auth.get(req)
req.header.set('Authorization', auth.scheme + " " + cred)
return
end
end
end
# Filter API implementation. Traps HTTP response and parses
# 'WWW-Authenticate' header.
def filter_response(req, res)
command = nil
if res.status == HTTP::Status::UNAUTHORIZED
if challenge = parse_authentication_header(res, 'www-authenticate')
uri = req.header.request_uri
challenge.each do |scheme, param_str|
@authenticator.each do |auth|
if scheme.downcase == auth.scheme.downcase
challengeable = auth.challenge(uri, param_str)
command = :retry if challengeable
end
end
end
# ignore unknown authentication scheme
end
end
command
end
end
# Authentication filter for handling authentication negotiation between
# Proxy server. Parses 'Proxy-Authentication' header in response and
# generates 'Proxy-Authorization' header in request.
#
# Authentication filter is implemented using request filter of HTTPClient.
# It traps HTTP response header and maintains authentication state, and
# traps HTTP request header for inserting necessary authentication header.
#
# ProxyAuth has sub filters (BasicAuth, NegotiateAuth, and SSPINegotiateAuth)
# and delegates some operations to it.
# NegotiateAuth requires 'ruby/ntlm' module.
# SSPINegotiateAuth requires 'win32/sspi' module.
class ProxyAuth < AuthFilterBase
attr_reader :basic_auth
attr_reader :negotiate_auth
attr_reader :sspi_negotiate_auth
# Creates new ProxyAuth.
def initialize
@basic_auth = BasicAuth.new
@negotiate_auth = NegotiateAuth.new
@sspi_negotiate_auth = SSPINegotiateAuth.new
# sort authenticators by priority
@authenticator = [@negotiate_auth, @sspi_negotiate_auth, @basic_auth]
end
# Resets challenge state. See sub filters for more details.
def reset_challenge
@authenticator.each do |auth|
auth.reset_challenge
end
end
# Set authentication credential. See sub filters for more details.
def set_auth(user, passwd)
@authenticator.each do |auth|
auth.set(nil, user, passwd)
end
reset_challenge
end
# Filter API implementation. Traps HTTP request and insert
# 'Proxy-Authorization' header if needed.
def filter_request(req)
@authenticator.each do |auth|
if cred = auth.get(req)
req.header.set('Proxy-Authorization', auth.scheme + " " + cred)
return
end
end
end
# Filter API implementation. Traps HTTP response and parses
# 'Proxy-Authenticate' header.
def filter_response(req, res)
command = nil
if res.status == HTTP::Status::PROXY_AUTHENTICATE_REQUIRED
if challenge = parse_authentication_header(res, 'proxy-authenticate')
uri = req.header.request_uri
challenge.each do |scheme, param_str|
@authenticator.each do |auth|
if scheme.downcase == auth.scheme.downcase
challengeable = auth.challenge(uri, param_str)
command = :retry if challengeable
end
end
end
# ignore unknown authentication scheme
end
end
command
end
end
# Authentication filter for handling BasicAuth negotiation.
# Used in WWWAuth and ProxyAuth.
class BasicAuth
# Authentication scheme.
attr_reader :scheme
# Creates new BasicAuth filter.
def initialize
@cred = nil
@auth = {}
@challengeable = {}
@scheme = "Basic"
end
# Resets challenge state. Do not send '*Authorization' header until the
# server sends '*Authentication' again.
def reset_challenge
@challengeable.clear
end
# Set authentication credential.
# uri == nil for generic purpose (allow to use user/password for any URL).
def set(uri, user, passwd)
if uri.nil?
@cred = ["#{user}:#{passwd}"].pack('m').tr("\n", '')
else
uri = Util.uri_dirname(uri)
@auth[uri] = ["#{user}:#{passwd}"].pack('m').tr("\n", '')
end
end
# Response handler: returns credential.
# It sends cred only when a given uri is;
# * child page of challengeable(got *Authenticate before) uri and,
# * child page of defined credential
def get(req)
target_uri = req.header.request_uri
return nil unless @challengeable.find { |uri, ok|
Util.uri_part_of(target_uri, uri) and ok
}
return @cred if @cred
Util.hash_find_value(@auth) { |uri, cred|
Util.uri_part_of(target_uri, uri)
}
end
# Challenge handler: remember URL for response.
def challenge(uri, param_str)
@challengeable[uri] = true
true
end
end
# Authentication filter for handling DigestAuth negotiation.
# Used in WWWAuth.
class DigestAuth
# Authentication scheme.
attr_reader :scheme
# Creates new DigestAuth filter.
def initialize
@auth = {}
@challenge = {}
@nonce_count = 0
@scheme = "Digest"
end
# Resets challenge state. Do not send '*Authorization' header until the
# server sends '*Authentication' again.
def reset_challenge
@challenge.clear
end
# Set authentication credential.
# uri == nil is ignored.
def set(uri, user, passwd)
if uri
uri = Util.uri_dirname(uri)
@auth[uri] = [user, passwd]
end
end
# Response handler: returns credential.
# It sends cred only when a given uri is;
# * child page of challengeable(got *Authenticate before) uri and,
# * child page of defined credential
def get(req)
target_uri = req.header.request_uri
param = Util.hash_find_value(@challenge) { |uri, v|
Util.uri_part_of(target_uri, uri)
}
return nil unless param
user, passwd = Util.hash_find_value(@auth) { |uri, auth_data|
Util.uri_part_of(target_uri, uri)
}
return nil unless user
uri = req.header.request_uri
calc_cred(req.header.request_method, uri, user, passwd, param)
end
# Challenge handler: remember URL and challenge token for response.
def challenge(uri, param_str)
@challenge[uri] = parse_challenge_param(param_str)
true
end
private
# this method is implemented by sromano and posted to
# http://tools.assembla.com/breakout/wiki/DigestForSoap
# Thanks!
# supported algorithm: MD5 only for now
def calc_cred(method, uri, user, passwd, param)
a_1 = "#{user}:#{param['realm']}:#{passwd}"
a_2 = "#{method}:#{uri.path}"
nonce = param['nonce']
cnonce = generate_cnonce()
@nonce_count += 1
message_digest = []
message_digest << Digest::MD5.hexdigest(a_1)
message_digest << nonce
message_digest << ('%08x' % @nonce_count)
message_digest << cnonce
message_digest << param['qop']
message_digest << Digest::MD5.hexdigest(a_2)
header = []
header << "username=\"#{user}\""
header << "realm=\"#{param['realm']}\""
header << "nonce=\"#{nonce}\""
header << "uri=\"#{uri.path}\""
header << "cnonce=\"#{cnonce}\""
header << "nc=#{'%08x' % @nonce_count}"
header << "qop=\"#{param['qop']}\""
header << "response=\"#{Digest::MD5.hexdigest(message_digest.join(":"))}\""
header << "algorithm=\"MD5\""
header << "opaque=\"#{param['opaque']}\"" if param.key?('opaque')
header.join(", ")
end
# cf. WEBrick::HTTPAuth::DigestAuth#generate_next_nonce(aTime)
def generate_cnonce
now = "%012d" % Time.now.to_i
pk = Digest::MD5.hexdigest([now, self.__id__, Process.pid, rand(65535)].join)[0, 32]
[now + ':' + pk].pack('m*').chop
end
def parse_challenge_param(param_str)
param = {}
param_str.scan(/\s*([^\,]+(?:\\.[^\,]*)*)/).each do |str|
key, value = str[0].scan(/\A([^=]+)=(.*)\z/)[0]
if /\A"(.*)"\z/ =~ value
value = $1.gsub(/\\(.)/, '\1')
end
param[key] = value
end
param
end
end
# Authentication filter for handling Negotiate/NTLM negotiation.
# Used in WWWAuth and ProxyAuth.
#
# NegotiateAuth depends on 'ruby/ntlm' module.
class NegotiateAuth
# Authentication scheme.
attr_reader :scheme
# NTLM opt for ruby/ntlm. {:ntlmv2 => true} by default.
attr_reader :ntlm_opt
# Creates new NegotiateAuth filter.
def initialize
@auth = {}
@auth_default = nil
@challenge = {}
@scheme = "Negotiate"
@ntlm_opt = {
:ntlmv2 => true
}
end
# Resets challenge state. Do not send '*Authorization' header until the
# server sends '*Authentication' again.
def reset_challenge
@challenge.clear
end
# Set authentication credential.
# uri == nil for generic purpose (allow to use user/password for any URL).
def set(uri, user, passwd)
if uri
uri = Util.uri_dirname(uri)
@auth[uri] = [user, passwd]
else
@auth_default = [user, passwd]
end
end
# Response handler: returns credential.
# See ruby/ntlm for negotiation state transition.
def get(req)
return nil unless NTLMEnabled
target_uri = req.header.request_uri
domain_uri, param = @challenge.find { |uri, v|
Util.uri_part_of(target_uri, uri)
}
return nil unless param
user, passwd = Util.hash_find_value(@auth) { |uri, auth_data|
Util.uri_part_of(target_uri, uri)
}
unless user
user, passwd = @auth_default
end
return nil unless user
state = param[:state]
authphrase = param[:authphrase]
case state
when :init
t1 = Net::NTLM::Message::Type1.new
return t1.encode64
when :response
t2 = Net::NTLM::Message.decode64(authphrase)
t3 = t2.response({:user => user, :password => passwd}, @ntlm_opt.dup)
@challenge.delete(domain_uri)
return t3.encode64
end
nil
end
# Challenge handler: remember URL and challenge token for response.
def challenge(uri, param_str)
return false unless NTLMEnabled
if param_str.nil? or @challenge[uri].nil?
c = @challenge[uri] = {}
c[:state] = :init
c[:authphrase] = ""
else
c = @challenge[uri]
c[:state] = :response
c[:authphrase] = param_str
end
true
end
end
# Authentication filter for handling Negotiate/NTLM negotiation.
# Used in ProxyAuth.
#
# SSPINegotiateAuth depends on 'win32/sspi' module.
class SSPINegotiateAuth
# Authentication scheme.
attr_reader :scheme
# Creates new SSPINegotiateAuth filter.
def initialize
@challenge = {}
@scheme = "Negotiate"
end
# Resets challenge state. Do not send '*Authorization' header until the
# server sends '*Authentication' again.
def reset_challenge
@challenge.clear
end
# Set authentication credential.
# NOT SUPPORTED: username and necessary data is retrieved by win32/sspi.
# See win32/sspi for more details.
def set(uri, user, passwd)
# not supported
end
# Response handler: returns credential.
# See win32/sspi for negotiation state transition.
def get(req)
return nil unless SSPIEnabled
target_uri = req.header.request_uri
domain_uri, param = @challenge.find { |uri, v|
Util.uri_part_of(target_uri, uri)
}
return nil unless param
state = param[:state]
authenticator = param[:authenticator]
authphrase = param[:authphrase]
case state
when :init
authenticator = param[:authenticator] = Win32::SSPI::NegotiateAuth.new
return authenticator.get_initial_token(@scheme)
when :response
@challenge.delete(domain_uri)
return authenticator.complete_authentication(authphrase)
end
nil
end
# Challenge handler: remember URL and challenge token for response.
def challenge(uri, param_str)
return false unless SSPIEnabled
if param_str.nil? or @challenge[uri].nil?
c = @challenge[uri] = {}
c[:state] = :init
c[:authenticator] = nil
c[:authphrase] = ""
else
c = @challenge[uri]
c[:state] = :response
c[:authphrase] = param_str
end
true
end
end
end

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,84 @@
# HTTPClient - HTTP client library.
# Copyright (C) 2000-2009 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
#
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
# redistribute it and/or modify it under the same terms of Ruby's license;
# either the dual license version in 2003, or any later version.
class HTTPClient
# Represents a HTTP response to an asynchronous request. Async methods of
# HTTPClient such as get_async, post_async, etc. returns an instance of
# Connection.
#
# == How to use
#
# 1. Invoke HTTP method asynchronously and check if it's been finished
# periodically.
#
# connection = clnt.post_async(url, body)
# print 'posting.'
# while true
# break if connection.finished?
# print '.'
# sleep 1
# end
# puts '.'
# res = connection.pop
# p res.status
#
# 2. Read the response as an IO.
#
# connection = clnt.get_async('http://dev.ctor.org/')
# io = connection.pop.content
# while str = io.read(40)
# p str
# end
class Connection
attr_accessor :async_thread
def initialize(header_queue = [], body_queue = []) # :nodoc:
@headers = header_queue
@body = body_queue
@async_thread = nil
@queue = Queue.new
end
# Checks if the asynchronous invocation has been finished or not.
def finished?
if !@async_thread
# Not in async mode.
true
elsif @async_thread.alive?
# Working...
false
else
# Async thread have been finished.
join
true
end
end
# Retrieves a HTTP::Message instance of HTTP response. Do not invoke this
# method twice for now. The second invocation will be blocked.
def pop
@queue.pop
end
def push(result) # :nodoc:
@queue.push(result)
end
# Waits the completion of the asynchronous invocation.
def join
if @async_thread
@async_thread.join
end
nil
end
end
end

View file

@ -0,0 +1,562 @@
# cookie.rb is redistributed file which is originally included in Webagent
# version 0.6.2 by TAKAHASHI `Maki' Masayoshi. And it contains some bug fixes.
# You can download the entire package of Webagent from
# http://www.rubycolor.org/arc/.
# Cookie class
#
# I refered to w3m's source to make these classes. Some comments
# are quoted from it. I'm thanksful for author(s) of it.
#
# w3m homepage: http://ei5nazha.yz.yamagata-u.ac.jp/~aito/w3m/eng/
require 'uri'
require 'time'
require 'monitor'
class WebAgent
module CookieUtils
def head_match?(str1, str2)
str1 == str2[0, str1.length]
end
def tail_match?(str1, str2)
if str1.length > 0
str1 == str2[-str1.length..-1].to_s
else
true
end
end
def domain_match(host, domain)
domainname = domain.sub(/\.\z/, '').downcase
hostname = host.sub(/\.\z/, '').downcase
case domain
when /\d+\.\d+\.\d+\.\d+/
return (hostname == domainname)
when '.'
return true
when /^\./
# allows; host == rubyforge.org, domain == .rubyforge.org
return tail_match?(domainname, '.' + hostname)
else
return (hostname == domainname)
end
end
def total_dot_num(string)
string.scan(/\./).length()
end
end
class Cookie
include CookieUtils
attr_accessor :name, :value
attr_accessor :domain, :path
attr_accessor :expires ## for Netscape Cookie
attr_accessor :url
attr_writer :use, :secure, :discard, :domain_orig, :path_orig, :override
USE = 1
SECURE = 2
DOMAIN = 4
PATH = 8
DISCARD = 16
OVERRIDE = 32
OVERRIDE_OK = 32
def initialize()
@name = @value = @domain = @path = nil
@expires = nil
@url = nil
@use = @secure = @discard = @domain_orig = @path_orig = @override = nil
end
def discard?
@discard
end
def use?
@use
end
def secure?
@secure
end
def domain_orig?
@domain_orig
end
def path_orig?
@path_orig
end
def override?
@override
end
def flag
flg = 0
flg += USE if @use
flg += SECURE if @secure
flg += DOMAIN if @domain_orig
flg += PATH if @path_orig
flg += DISCARD if @discard
flg += OVERRIDE if @override
flg
end
def set_flag(flag)
flag = flag.to_i
@use = true if flag & USE > 0
@secure = true if flag & SECURE > 0
@domain_orig = true if flag & DOMAIN > 0
@path_orig = true if flag & PATH > 0
@discard = true if flag & DISCARD > 0
@override = true if flag & OVERRIDE > 0
end
def match?(url)
domainname = url.host
if (!domainname ||
!domain_match(domainname, @domain) ||
(@path && !head_match?(@path, url.path)) ||
(@secure && (url.scheme != 'https')) )
return false
else
return true
end
end
def join_quotedstr(array, sep)
ret = Array.new()
old_elem = nil
array.each{|elem|
if (elem.scan(/"/).length % 2) == 0
if old_elem
old_elem << sep << elem
else
ret << elem
old_elem = nil
end
else
if old_elem
old_elem << sep << elem
ret << old_elem
old_elem = nil
else
old_elem = elem.dup
end
end
}
ret
end
def parse(str, url)
@url = url
# TODO: should not depend on join_quotedstr. scan with escape like CSV.
cookie_elem = str.split(/;/)
cookie_elem = join_quotedstr(cookie_elem, ';')
cookie_elem -= [""] # del empty elements, a cookie might included ";;"
first_elem = cookie_elem.shift
if first_elem !~ /([^=]*)(\=(.*))?/
return
## raise ArgumentError 'invalid cookie value'
end
@name = $1.strip
@value = normalize_cookie_value($3)
cookie_elem.each{|pair|
key, value = pair.split(/=/, 2) ## value may nil
key.strip!
value = normalize_cookie_value(value)
case key.downcase
when 'domain'
@domain = value
when 'expires'
@expires = nil
begin
@expires = Time.parse(value).gmtime() if value
rescue ArgumentError
end
when 'path'
@path = value
when 'secure'
@secure = true ## value may nil, but must 'true'.
else
## ignore
end
}
end
def normalize_cookie_value(value)
if value
value = value.strip.sub(/\A"(.*)"\z/) { $1 }
value = nil if value.empty?
end
value
end
private :normalize_cookie_value
end
class CookieManager
include CookieUtils
### errors
class Error < StandardError; end
class ErrorOverrideOK < Error; end
class SpecialError < Error; end
attr_reader :cookies
attr_accessor :cookies_file
attr_accessor :accept_domains, :reject_domains
# for conformance to http://wp.netscape.com/newsref/std/cookie_spec.html
attr_accessor :netscape_rule
SPECIAL_DOMAIN = [".com",".edu",".gov",".mil",".net",".org",".int"]
def initialize(file=nil)
@cookies = Array.new()
@cookies.extend(MonitorMixin)
@cookies_file = file
@is_saved = true
@reject_domains = Array.new()
@accept_domains = Array.new()
@netscape_rule = false
end
def cookies=(cookies)
@cookies = cookies
@cookies.extend(MonitorMixin)
end
def save_all_cookies(force = nil, save_unused = true, save_discarded = true)
@cookies.synchronize do
check_expired_cookies()
if @is_saved and !force
return
end
File.open(@cookies_file, 'w') do |f|
@cookies.each do |cookie|
if (cookie.use? or save_unused) and
(!cookie.discard? or save_discarded)
f.print(cookie.url.to_s,"\t",
cookie.name,"\t",
cookie.value,"\t",
cookie.expires.to_i,"\t",
cookie.domain,"\t",
cookie.path,"\t",
cookie.flag,"\n")
end
end
end
end
@is_saved = true
end
def save_cookies(force = nil)
save_all_cookies(force, false, false)
end
def check_expired_cookies()
@cookies.reject!{|cookie|
is_expired = (cookie.expires && (cookie.expires < Time.now.gmtime))
if is_expired && !cookie.discard?
@is_saved = false
end
is_expired
}
end
def parse(str, url)
cookie = WebAgent::Cookie.new()
cookie.parse(str, url)
add(cookie)
end
def make_cookie_str(cookie_list)
if cookie_list.empty?
return nil
end
ret = ''
c = cookie_list.shift
ret += "#{c.name}=#{c.value}"
cookie_list.each{|cookie|
ret += "; #{cookie.name}=#{cookie.value}"
}
return ret
end
private :make_cookie_str
def find(url)
return nil if @cookies.empty?
cookie_list = Array.new()
@cookies.each{|cookie|
is_expired = (cookie.expires && (cookie.expires < Time.now.gmtime))
if cookie.use? && !is_expired && cookie.match?(url)
if cookie_list.select{|c1| c1.name == cookie.name}.empty?
cookie_list << cookie
end
end
}
return make_cookie_str(cookie_list)
end
def find_cookie_info(domain, path, name)
@cookies.find{|c|
c.domain == domain && c.path == path && c.name == name
}
end
private :find_cookie_info
# not tested well; used only netscape_rule = true.
def cookie_error(err, override)
if !err.kind_of?(ErrorOverrideOK) || !override
raise err
end
end
private :cookie_error
def add(cookie)
url = cookie.url
name, value = cookie.name, cookie.value
expires, domain, path =
cookie.expires, cookie.domain, cookie.path
secure, domain_orig, path_orig =
cookie.secure?, cookie.domain_orig?, cookie.path_orig?
discard, override =
cookie.discard?, cookie.override?
domainname = url.host
domain_orig, path_orig = domain, path
use_security = override
if domain
# [DRAFT 12] s. 4.2.2 (does not apply in the case that
# host name is the same as domain attribute for version 0
# cookie)
# I think that this rule has almost the same effect as the
# tail match of [NETSCAPE].
if domain !~ /^\./ && domainname != domain
domain = '.'+domain
end
# [NETSCAPE] rule
if @netscape_rule
n = total_dot_num(domain)
if n < 2
cookie_error(SpecialError.new(), override)
elsif n == 2
## [NETSCAPE] rule
ok = SPECIAL_DOMAIN.select{|sdomain|
sdomain == domain[-(sdomain.length)..-1]
}
if ok.empty?
cookie_error(SpecialError.new(), override)
end
end
end
# this implementation does not check RFC2109 4.3.2 case 2;
# the portion of host not in domain does not contain a dot.
# according to nsCookieService.cpp in Firefox 3.0.4, Firefox 3.0.4
# and IE does not check, too.
end
path ||= url.path.sub(%r|/[^/]*|, '')
domain ||= domainname
@cookies.synchronize do
cookie = find_cookie_info(domain, path, name)
if !cookie
cookie = WebAgent::Cookie.new()
cookie.use = true
@cookies << cookie
end
check_expired_cookies()
end
cookie.url = url
cookie.name = name
cookie.value = value
cookie.expires = expires
cookie.domain = domain
cookie.path = path
## for flag
cookie.secure = secure
cookie.domain_orig = domain_orig
cookie.path_orig = path_orig
if discard || cookie.expires == nil
cookie.discard = true
else
cookie.discard = false
@is_saved = false
end
end
def load_cookies()
return if !File.readable?(@cookies_file)
@cookies.synchronize do
@cookies.clear
File.open(@cookies_file,'r'){|f|
while line = f.gets
cookie = WebAgent::Cookie.new()
@cookies << cookie
col = line.chomp.split(/\t/)
cookie.url = URI.parse(col[0])
cookie.name = col[1]
cookie.value = col[2]
if col[3].empty? or col[3] == '0'
cookie.expires = nil
else
cookie.expires = Time.at(col[3].to_i).gmtime
end
cookie.domain = col[4]
cookie.path = col[5]
cookie.set_flag(col[6])
end
}
end
end
def check_cookie_accept_domain(domain)
unless domain
return false
end
@accept_domains.each{|dom|
if domain_match(domain, dom)
return true
end
}
@reject_domains.each{|dom|
if domain_match(domain, dom)
return false
end
}
return true
end
end
end
__END__
=begin
== WebAgent::CookieManager Class
Load, save, parse and send cookies.
=== Usage
## initialize
cm = WebAgent::CookieManager.new("/home/foo/bar/cookie")
## load cookie data
cm.load_cookies()
## parse cookie from string (maybe "Set-Cookie:" header)
cm.parse(str)
## send cookie data to url
f.write(cm.find(url))
## save cookie to cookiefile
cm.save_cookies()
=== Class Methods
-- CookieManager::new(file=nil)
create new CookieManager. If a file is provided,
use it as cookies' file.
=== Methods
-- CookieManager#save_cookies(force = nil)
save cookies' data into file. if argument is true,
save data although data is not modified.
-- CookieManager#parse(str, url)
parse string and store cookie (to parse HTTP response header).
-- CookieManager#find(url)
get cookies and make into string (to send as HTTP request header).
-- CookieManager#add(cookie)
add new cookie.
-- CookieManager#load_cookies()
load cookies' data from file.
== WebAgent::CookieUtils Module
-- CookieUtils::head_match?(str1, str2)
-- CookieUtils::tail_match?(str1, str2)
-- CookieUtils::domain_match(host, domain)
-- CookieUtils::total_dot_num(str)
== WebAgent::Cookie Class
=== Class Methods
-- Cookie::new()
create new cookie.
=== Methods
-- Cookie#match?(url)
match cookie by url. if match, return true. otherwise,
return false.
-- Cookie#name
-- Cookie#name=(name)
-- Cookie#value
-- Cookie#value=(value)
-- Cookie#domain
-- Cookie#domain=(domain)
-- Cookie#path
-- Cookie#path=(path)
-- Cookie#expires
-- Cookie#expires=(expires)
-- Cookie#url
-- Cookie#url=(url)
accessor methods for cookie's items.
-- Cookie#discard?
-- Cookie#discard=(discard)
-- Cookie#use?
-- Cookie#use=(use)
-- Cookie#secure?
-- Cookie#secure=(secure)
-- Cookie#domain_orig?
-- Cookie#domain_orig=(domain_orig)
-- Cookie#path_orig?
-- Cookie#path_orig=(path_orig)
-- Cookie#override?
-- Cookie#override=(override)
-- Cookie#flag
-- Cookie#set_flag(flag_num)
accessor methods for flags.
=end

View file

@ -0,0 +1,867 @@
# HTTPClient - HTTP client library.
# Copyright (C) 2000-2009 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
#
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
# redistribute it and/or modify it under the same terms of Ruby's license;
# either the dual license version in 2003, or any later version.
require 'time'
# A namespace module for HTTP Message definitions used by HTTPClient.
module HTTP
# Represents HTTP response status code. Defines constants for HTTP response
# and some conditional methods.
module Status
OK = 200
CREATED = 201
ACCEPTED = 202
NON_AUTHORITATIVE_INFORMATION = 203
NO_CONTENT = 204
RESET_CONTENT = 205
PARTIAL_CONTENT = 206
MOVED_PERMANENTLY = 301
FOUND = 302
SEE_OTHER = 303
TEMPORARY_REDIRECT = MOVED_TEMPORARILY = 307
BAD_REQUEST = 400
UNAUTHORIZED = 401
PROXY_AUTHENTICATE_REQUIRED = 407
INTERNAL = 500
# Status codes for successful HTTP response.
SUCCESSFUL_STATUS = [
OK, CREATED, ACCEPTED,
NON_AUTHORITATIVE_INFORMATION, NO_CONTENT,
RESET_CONTENT, PARTIAL_CONTENT
]
# Status codes which is a redirect.
REDIRECT_STATUS = [
MOVED_PERMANENTLY, FOUND, SEE_OTHER,
TEMPORARY_REDIRECT, MOVED_TEMPORARILY
]
# Returns true if the given status represents successful HTTP response.
# See also SUCCESSFUL_STATUS.
def self.successful?(status)
SUCCESSFUL_STATUS.include?(status)
end
# Returns true if the given status is thought to be redirect.
# See also REDIRECT_STATUS.
def self.redirect?(status)
REDIRECT_STATUS.include?(status)
end
end
# Represents a HTTP message. A message is for a request or a response.
#
# Request message is generated from given parameters internally so users
# don't need to care about it. Response message is the instance that
# methods of HTTPClient returns so users need to know how to extract
# HTTP response data from Message.
#
# Some attributes are only for a request or a response, not both.
#
# == How to use HTTP response message
#
# 1. Gets response message body.
#
# res = clnt.get(url)
# p res.content #=> String
#
# 2. Gets response status code.
#
# res = clnt.get(url)
# p res.status #=> 200, 501, etc. (Integer)
#
# 3. Gets response header.
#
# res = clnt.get(url)
# res.header['set-cookie'].each do |value|
# p value
# end
# assert_equal(1, res.header['last-modified'].size)
# p res.header['last-modified'].first
#
class Message
CRLF = "\r\n"
# Represents HTTP message header.
class Headers
# HTTP version in a HTTP header. Float.
attr_accessor :http_version
# Size of body. nil when size is unknown (e.g. chunked response).
attr_reader :body_size
# Request/Response is chunked or not.
attr_accessor :chunked
# Request only. Requested method.
attr_reader :request_method
# Request only. Requested URI.
attr_accessor :request_uri
# Request only. Requested query.
attr_accessor :request_query
# Request only. Requested via proxy or not.
attr_accessor :request_via_proxy
# Response only. HTTP status
attr_reader :status_code
# Response only. HTTP status reason phrase.
attr_accessor :reason_phrase
# Used for dumping response.
attr_accessor :body_type # :nodoc:
# Used for dumping response.
attr_accessor :body_charset # :nodoc:
# Used for dumping response.
attr_accessor :body_date # :nodoc:
# HTTP response status code to reason phrase mapping definition.
STATUS_CODE_MAP = {
Status::OK => 'OK',
Status::CREATED => "Created",
Status::NON_AUTHORITATIVE_INFORMATION => "Non-Authoritative Information",
Status::NO_CONTENT => "No Content",
Status::RESET_CONTENT => "Reset Content",
Status::PARTIAL_CONTENT => "Partial Content",
Status::MOVED_PERMANENTLY => 'Moved Permanently',
Status::FOUND => 'Found',
Status::SEE_OTHER => 'See Other',
Status::TEMPORARY_REDIRECT => 'Temporary Redirect',
Status::MOVED_TEMPORARILY => 'Temporary Redirect',
Status::BAD_REQUEST => 'Bad Request',
Status::INTERNAL => 'Internal Server Error',
}
# $KCODE to charset mapping definition.
CHARSET_MAP = {
'NONE' => 'us-ascii',
'EUC' => 'euc-jp',
'SJIS' => 'shift_jis',
'UTF8' => 'utf-8',
}
# Creates a Message::Headers. Use init_request, init_response, or
# init_connect_request for acutual initialize.
def initialize
@http_version = 1.1
@body_size = nil
@chunked = false
@request_method = nil
@request_uri = nil
@request_query = nil
@request_via_proxy = nil
@status_code = nil
@reason_phrase = nil
@body_type = nil
@body_charset = nil
@body_date = nil
@is_request = nil
@header_item = []
@dumped = false
end
# Initialize this instance as a CONNECT request.
def init_connect_request(uri)
@is_request = true
@request_method = 'CONNECT'
@request_uri = uri
@request_query = nil
@http_version = 1.0
end
# Placeholder URI object for nil uri.
NIL_URI = URI.parse('http://nil-uri-given/')
# Initialize this instance as a general request.
def init_request(method, uri, query = nil)
@is_request = true
@request_method = method
@request_uri = uri || NIL_URI
@request_query = query
@request_via_proxy = false
end
# Initialize this instance as a response.
def init_response(status_code)
@is_request = false
self.status_code = status_code
end
# Sets status code and reason phrase.
def status_code=(status_code)
@status_code = status_code
@reason_phrase = STATUS_CODE_MAP[@status_code]
end
# Returns 'Content-Type' header value.
def contenttype
self['Content-Type'][0]
end
# Sets 'Content-Type' header value. Overrides if already exists.
def contenttype=(contenttype)
delete('Content-Type')
self['Content-Type'] = contenttype
end
# Sets byte size of message body.
# body_size == nil means that the body is_a? IO
def body_size=(body_size)
@body_size = body_size
end
# Dumps message header part and returns a dumped String.
def dump
set_header
str = nil
if @is_request
str = request_line
else
str = response_status_line
end
str + @header_item.collect { |key, value|
"#{ key }: #{ value }#{ CRLF }"
}.join
end
# Adds a header. Addition order is preserved.
def add(key, value)
if value.is_a?(Array)
value.each do |v|
@header_item.push([key, v])
end
else
@header_item.push([key, value])
end
end
# Sets a header.
def set(key, value)
delete(key)
add(key, value)
end
# Returns an Array of headers for the given key. Each element is a pair
# of key and value. It returns an single element Array even if the only
# one header exists. If nil key given, it returns all headers.
def get(key = nil)
if key.nil?
all
else
key = key.upcase
@header_item.find_all { |k, v| k.upcase == key }
end
end
# Returns an Array of all headers.
def all
@header_item
end
# Deletes headers of the given key.
def delete(key)
key = key.upcase
@header_item.delete_if { |k, v| k.upcase == key }
end
# Adds a header. See set.
def []=(key, value)
set(key, value)
end
# Returns an Array of header values for the given key.
def [](key)
get(key).collect { |item| item[1] }
end
private
def request_line
path = create_query_uri(@request_uri, @request_query)
if @request_via_proxy
path = "#{ @request_uri.scheme }://#{ @request_uri.host }:#{ @request_uri.port }#{ path }"
end
"#{ @request_method } #{ path } HTTP/#{ @http_version }#{ CRLF }"
end
def response_status_line
if defined?(Apache)
"HTTP/#{ @http_version } #{ @status_code } #{ @reason_phrase }#{ CRLF }"
else
"Status: #{ @status_code } #{ @reason_phrase }#{ CRLF }"
end
end
def set_header
if @is_request
set_request_header
else
set_response_header
end
end
def set_request_header
return if @dumped
@dumped = true
keep_alive = Message.keep_alive_enabled?(@http_version)
if !keep_alive and @request_method != 'CONNECT'
set('Connection', 'close')
end
if @chunked
set('Transfer-Encoding', 'chunked')
elsif @body_size and (keep_alive or @body_size != 0)
set('Content-Length', @body_size.to_s)
end
if @http_version >= 1.1
if @request_uri.port == @request_uri.default_port
# GFE/1.3 dislikes default port number (returns 404)
set('Host', "#{@request_uri.host}")
else
set('Host', "#{@request_uri.host}:#{@request_uri.port}")
end
end
end
def set_response_header
return if @dumped
@dumped = true
if defined?(Apache) && self['Date'].empty?
set('Date', Time.now.httpdate)
end
keep_alive = Message.keep_alive_enabled?(@http_version)
if @chunked
set('Transfer-Encoding', 'chunked')
else
if keep_alive or @body_size != 0
set('Content-Length', @body_size.to_s)
end
end
if @body_date
set('Last-Modified', @body_date.httpdate)
end
if self['Content-Type'].empty?
set('Content-Type', "#{ @body_type || 'text/html' }; charset=#{ charset_label(@body_charset || $KCODE) }")
end
end
def charset_label(charset)
CHARSET_MAP[charset] || 'us-ascii'
end
def create_query_uri(uri, query)
if @request_method == 'CONNECT'
return "#{uri.host}:#{uri.port}"
end
path = uri.path
path = '/' if path.nil? or path.empty?
query_str = nil
if uri.query
query_str = uri.query
end
if query
if query_str
query_str += "&#{Message.create_query_part_str(query)}"
else
query_str = Message.create_query_part_str(query)
end
end
if query_str
path += "?#{query_str}"
end
path
end
end
# Represents HTTP message body.
class Body
# Size of body. nil when size is unknown (e.g. chunked response).
attr_reader :size
# maxbytes of IO#read for streaming request. See DEFAULT_CHUNK_SIZE.
attr_accessor :chunk_size
# Default value for chunk_size
DEFAULT_CHUNK_SIZE = 1024 * 16
# Creates a Message::Body. Use init_request or init_response
# for acutual initialize.
def initialize
@body = nil
@size = nil
@positions = nil
@chunk_size = nil
end
# Initialize this instance as a request.
def init_request(body = nil, boundary = nil)
@boundary = boundary
@positions = {}
set_content(body, boundary)
@chunk_size = DEFAULT_CHUNK_SIZE
end
# Initialize this instance as a response.
def init_response(body = nil)
@body = body
if @body.respond_to?(:size)
@size = @body.size
else
@size = nil
end
end
# Dumps message body to given dev.
# dev needs to respond to <<.
#
# Message header must be given as the first argument for performance
# reason. (header is dumped to dev, too)
# If no dev (the second argument) given, this method returns a dumped
# String.
def dump(header = '', dev = '')
if @body.is_a?(Parts)
dev << header
buf = ''
@body.parts.each do |part|
if Message.file?(part)
reset_pos(part)
while !part.read(@chunk_size, buf).nil?
dev << buf
end
else
dev << part
end
end
elsif @body
dev << header + @body
else
dev << header
end
dev
end
# Dumps message body with chunked encoding to given dev.
# dev needs to respond to <<.
#
# Message header must be given as the first argument for performance
# reason. (header is dumped to dev, too)
# If no dev (the second argument) given, this method returns a dumped
# String.
def dump_chunked(header = '', dev = '')
dev << header
if @body.is_a?(Parts)
@body.parts.each do |part|
if Message.file?(part)
reset_pos(part)
dump_chunks(part, dev)
else
dev << dump_chunk(part)
end
end
dev << (dump_last_chunk + CRLF)
elsif @body
reset_pos(@body)
dump_chunks(@body, dev)
dev << (dump_last_chunk + CRLF)
end
dev
end
# Returns a message body itself.
def content
@body
end
private
def set_content(body, boundary = nil)
if body.respond_to?(:read)
# uses Transfer-Encoding: chunked. bear in mind that server may not
# support it. at least ruby's CGI doesn't.
@body = body
remember_pos(@body)
@size = nil
elsif boundary and Message.multiparam_query?(body)
@body = build_query_multipart_str(body, boundary)
@size = @body.size
else
@body = Message.create_query_part_str(body)
@size = @body.size
end
end
def remember_pos(io)
# IO may not support it (ex. IO.pipe)
@positions[io] = io.pos rescue nil
end
def reset_pos(io)
io.pos = @positions[io] if @positions.key?(io)
end
def dump_chunks(io, dev)
buf = ''
while !io.read(@chunk_size, buf).nil?
dev << dump_chunk(buf)
end
end
def dump_chunk(str)
dump_chunk_size(str.size) + (str + CRLF)
end
def dump_last_chunk
dump_chunk_size(0)
end
def dump_chunk_size(size)
sprintf("%x", size) + CRLF
end
class Parts
attr_reader :size
def initialize
@body = []
@size = 0
@as_stream = false
end
def add(part)
if Message.file?(part)
@as_stream = true
@body << part
if part.respond_to?(:size)
if sz = part.size
@size += sz
else
@size = nil
end
elsif part.respond_to?(:lstat)
@size += part.lstat.size
else
# use chunked upload
@size = nil
end
elsif @body[-1].is_a?(String)
@body[-1] += part.to_s
@size += part.to_s.size if @size
else
@body << part.to_s
@size += part.to_s.size if @size
end
end
def parts
if @as_stream
@body
else
[@body.join]
end
end
end
def build_query_multipart_str(query, boundary)
parts = Parts.new
query.each do |attr, value|
value ||= ''
headers = ["--#{boundary}"]
if Message.file?(value)
remember_pos(value)
param_str = params_from_file(value).collect { |k, v|
"#{k}=\"#{v}\""
}.join("; ")
if value.respond_to?(:mime_type)
content_type = value.mime_type
else
content_type = Message.mime_type(value.path)
end
headers << %{Content-Disposition: form-data; name="#{attr}"; #{param_str}}
headers << %{Content-Type: #{content_type}}
else
headers << %{Content-Disposition: form-data; name="#{attr}"}
end
parts.add(headers.join(CRLF) + CRLF + CRLF)
parts.add(value)
parts.add(CRLF)
end
parts.add("--#{boundary}--" + CRLF + CRLF) # empty epilogue
parts
end
def params_from_file(value)
params = {}
params['filename'] = File.basename(value.path || '')
# Creation time is not available from File::Stat
if value.respond_to?(:mtime)
params['modification-date'] = value.mtime.rfc822
end
if value.respond_to?(:atime)
params['read-date'] = value.atime.rfc822
end
params
end
end
class << self
private :new
# Creates a Message instance of 'CONNECT' request.
# 'CONNECT' request does not have Body.
# uri:: an URI that need to connect. Only uri.host and uri.port are used.
def new_connect_request(uri)
m = new
m.header.init_connect_request(uri)
m.header.body_size = nil
m
end
# Creates a Message instance of general request.
# method:: HTTP method String.
# uri:: an URI object which represents an URL of web resource.
# query:: a Hash or an Array of query part of URL.
# e.g. { "a" => "b" } => 'http://host/part?a=b'
# Give an array to pass multiple value like
# [["a", "b"], ["a", "c"]] => 'http://host/part?a=b&a=c'
# body:: a Hash or an Array of body part.
# e.g. { "a" => "b" } => 'a=b'.
# Give an array to pass multiple value like
# [["a", "b"], ["a", "c"]] => 'a=b&a=c'.
# boundary:: When the boundary given, it is sent as
# a multipart/form-data using this boundary String.
def new_request(method, uri, query = nil, body = nil, boundary = nil)
m = new
m.header.init_request(method, uri, query)
m.body = Body.new
m.body.init_request(body || '', boundary)
if body
m.header.body_size = m.body.size
m.header.chunked = true if m.body.size.nil?
else
m.header.body_size = nil
end
m
end
# Creates a Message instance of response.
# body:: a String or an IO of response message body.
def new_response(body)
m = new
m.header.init_response(Status::OK)
m.body = Body.new
m.body.init_response(body)
m.header.body_size = m.body.size || 0
m
end
@@mime_type_handler = nil
# Sets MIME type handler.
#
# handler must respond to :call with a single argument :path and returns
# a MIME type String e.g. 'text/html'.
# When the handler returns nil or an empty String,
# 'application/octet-stream' is used.
#
# When you set nil to the handler, internal_mime_type is used instead.
# The handler is nil by default.
def mime_type_handler=(handler)
@@mime_type_handler = handler
end
# Returns MIME type handler.
def mime_type_handler
@@mime_type_handler
end
# For backward compatibility.
alias set_mime_type_func mime_type_handler=
alias get_mime_type_func mime_type_handler
def mime_type(path) # :nodoc:
if @@mime_type_handler
res = @@mime_type_handler.call(path)
if !res || res.to_s == ''
return 'application/octet-stream'
else
return res
end
else
internal_mime_type(path)
end
end
# Default MIME type handler.
# See mime_type_handler=.
def internal_mime_type(path)
case path
when /\.txt$/i
'text/plain'
when /\.(htm|html)$/i
'text/html'
when /\.doc$/i
'application/msword'
when /\.png$/i
'image/png'
when /\.gif$/i
'image/gif'
when /\.(jpg|jpeg)$/i
'image/jpeg'
else
'application/octet-stream'
end
end
# Returns true if the given HTTP version allows keep alive connection.
# version:: Float
def keep_alive_enabled?(version)
version >= 1.1
end
# Returns true if the given query (or body) has a multiple parameter.
def multiparam_query?(query)
query.is_a?(Array) or query.is_a?(Hash)
end
# Returns true if the given object is a File. In HTTPClient, a file is;
# * must respond to :read for retrieving String chunks.
# * must respond to :path and returns a path for Content-Disposition.
# * must respond to :pos and :pos= to rewind for reading.
# Rewinding is only needed for following HTTP redirect. Some IO impl
# defines :pos= but raises an Exception for pos= such as StringIO
# but there's no problem as far as using it for non-following methods
# (get/post/etc.)
def file?(obj)
obj.respond_to?(:read) and obj.respond_to?(:path) and
obj.respond_to?(:pos) and obj.respond_to?(:pos=)
end
def create_query_part_str(query) # :nodoc:
if multiparam_query?(query)
escape_query(query)
elsif query.respond_to?(:read)
query = query.read
else
query.to_s
end
end
def escape_query(query) # :nodoc:
query.collect { |attr, value|
if value.respond_to?(:read)
value = value.read
end
escape(attr.to_s) << '=' << escape(value.to_s)
}.join('&')
end
# from CGI.escape
def escape(str) # :nodoc:
str.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
'%' + $1.unpack('H2' * $1.size).join('%').upcase
}.tr(' ', '+')
end
end
# HTTP::Message::Headers:: message header.
attr_accessor :header
# HTTP::Message::Body:: message body.
attr_reader :body
# OpenSSL::X509::Certificate:: response only. server certificate which is
# used for retrieving the response.
attr_accessor :peer_cert
# Creates a Message. This method should be used internally.
# Use Message.new_connect_request, Message.new_request or
# Message.new_response instead.
def initialize # :nodoc:
@header = Headers.new
@body = @peer_cert = nil
end
# Dumps message (header and body) to given dev.
# dev needs to respond to <<.
def dump(dev = '')
str = header.dump + CRLF
if header.chunked
dev = body.dump_chunked(str, dev)
elsif body
dev = body.dump(str, dev)
else
dev << str
end
dev
end
# Sets a new body. header.body_size is updated with new body.size.
def body=(body)
@body = body
@header.body_size = @body.size if @header
end
# Returns HTTP version in a HTTP header. Float.
def version
@header.http_version
end
# Sets HTTP version in a HTTP header. Float.
def version=(version)
@header.http_version = version
end
# Returns HTTP status code in response. Integer.
def status
@header.status_code
end
alias code status
alias status_code status
# Sets HTTP status code of response. Integer.
# Reason phrase is updated, too.
def status=(status)
@header.status_code = status
end
# Returns HTTP status reason phrase in response. String.
def reason
@header.reason_phrase
end
# Sets HTTP status reason phrase of response. String.
def reason=(reason)
@header.reason_phrase = reason
end
# Sets 'Content-Type' header value. Overrides if already exists.
def contenttype
@header.contenttype
end
# Returns 'Content-Type' header value.
def contenttype=(contenttype)
@header.contenttype = contenttype
end
# Returns a content of message body. A String or an IO.
def content
@body.content
end
end
end

View file

@ -0,0 +1,863 @@
# HTTPClient - HTTP client library.
# Copyright (C) 2000-2009 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
#
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
# redistribute it and/or modify it under the same terms of Ruby's license;
# either the dual license version in 2003, or any later version.
# httpclient/session.rb is based on http-access.rb in http-access/0.0.4.
# Some part of code in http-access.rb was recycled in httpclient.rb.
# Those part is copyrighted by Maehashi-san.
require 'socket'
require 'thread'
require 'stringio'
require 'httpclient/timeout'
require 'httpclient/ssl_config'
require 'httpclient/http'
class HTTPClient
# Represents a Site: protocol scheme, host String and port Number.
class Site
# Protocol scheme.
attr_accessor :scheme
# Host String.
attr_reader :host
# Port number.
attr_reader :port
# Creates a new Site based on the given URI.
def initialize(uri = nil)
if uri
@scheme = uri.scheme
@host = uri.host
@port = uri.port.to_i
else
@scheme = 'tcp'
@host = '0.0.0.0'
@port = 0
end
end
# Returns address String.
def addr
"#{@scheme}://#{@host}:#{@port.to_s}"
end
# Returns true is scheme, host and port are '=='
def ==(rhs)
(@scheme == rhs.scheme) and (@host == rhs.host) and (@port == rhs.port)
end
# Same as ==.
def eql?(rhs)
self == rhs
end
def hash # :nodoc:
[@scheme, @host, @port].hash
end
def to_s # :nodoc:
addr
end
# Returns true if scheme, host and port of the given URI matches with this.
def match(uri)
(@scheme == uri.scheme) and (@host == uri.host) and (@port == uri.port.to_i)
end
def inspect # :nodoc:
sprintf("#<%s:0x%x %s>", self.class.name, __id__, addr)
end
end
# Manages sessions for a HTTPClient instance.
class SessionManager
# Name of this client. Used for 'User-Agent' header in HTTP request.
attr_accessor :agent_name
# Owner of this client. Used for 'From' header in HTTP request.
attr_accessor :from
# Requested protocol version
attr_accessor :protocol_version
# Chunk size for chunked request
attr_accessor :chunk_size
# Device for dumping log for debugging
attr_accessor :debug_dev
# Boolean value for Socket#sync
attr_accessor :socket_sync
attr_accessor :connect_timeout
# Maximum retry count. 0 for infinite.
attr_accessor :connect_retry
attr_accessor :send_timeout
attr_accessor :receive_timeout
attr_accessor :read_block_size
attr_accessor :protocol_retry_count
attr_accessor :ssl_config
attr_reader :test_loopback_http_response
def initialize(client)
@client = client
@proxy = client.proxy
@agent_name = nil
@from = nil
@protocol_version = nil
@debug_dev = client.debug_dev
@socket_sync = true
@chunk_size = 4096
@connect_timeout = 60
@connect_retry = 1
@send_timeout = 120
@receive_timeout = 60 # For each read_block_size bytes
@read_block_size = 1024 * 16 # follows net/http change in 1.8.7
@protocol_retry_count = 5
@ssl_config = nil
@test_loopback_http_response = []
@sess_pool = []
@sess_pool_mutex = Mutex.new
end
def proxy=(proxy)
if proxy.nil?
@proxy = nil
else
@proxy = Site.new(proxy)
end
end
def query(req, via_proxy)
req.body.chunk_size = @chunk_size
sess = open(req.header.request_uri, via_proxy)
begin
sess.query(req)
rescue
sess.close
raise
end
sess
end
def reset(uri)
site = Site.new(uri)
close(site)
end
def reset_all
close_all
end
def keep(sess)
add_cached_session(sess)
end
private
def open(uri, via_proxy = false)
sess = nil
if cached = get_cached_session(uri)
sess = cached
else
sess = Session.new(@client, Site.new(uri), @agent_name, @from)
sess.proxy = via_proxy ? @proxy : nil
sess.socket_sync = @socket_sync
sess.requested_version = @protocol_version if @protocol_version
sess.connect_timeout = @connect_timeout
sess.connect_retry = @connect_retry
sess.send_timeout = @send_timeout
sess.receive_timeout = @receive_timeout
sess.read_block_size = @read_block_size
sess.protocol_retry_count = @protocol_retry_count
sess.ssl_config = @ssl_config
sess.debug_dev = @debug_dev
sess.test_loopback_http_response = @test_loopback_http_response
end
sess
end
def close_all
@sess_pool_mutex.synchronize do
@sess_pool.each do |sess|
sess.close
end
end
@sess_pool.clear
end
def close(dest)
if cached = get_cached_session(dest)
cached.close
true
else
false
end
end
def get_cached_session(uri)
cached = nil
@sess_pool_mutex.synchronize do
new_pool = []
@sess_pool.each do |s|
if s.dest.match(uri)
cached = s
else
new_pool << s
end
end
@sess_pool = new_pool
end
cached
end
def add_cached_session(sess)
@sess_pool_mutex.synchronize do
@sess_pool << sess
end
end
end
# Wraps up OpenSSL::SSL::SSLSocket and offers debugging features.
class SSLSocketWrap
def initialize(socket, context, debug_dev = nil)
unless SSLEnabled
raise ConfigurationError.new('Ruby/OpenSSL module is required')
end
@context = context
@socket = socket
@ssl_socket = create_openssl_socket(@socket)
@debug_dev = debug_dev
end
def ssl_connect
@ssl_socket.connect
end
def post_connection_check(host)
verify_mode = @context.verify_mode || OpenSSL::SSL::VERIFY_NONE
if verify_mode == OpenSSL::SSL::VERIFY_NONE
return
elsif @ssl_socket.peer_cert.nil? and
check_mask(verify_mode, OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT)
raise OpenSSL::SSL::SSLError.new('no peer cert')
end
hostname = host.host
if @ssl_socket.respond_to?(:post_connection_check) and RUBY_VERSION > "1.8.4"
@ssl_socket.post_connection_check(hostname)
else
@context.post_connection_check(@ssl_socket.peer_cert, hostname)
end
end
def peer_cert
@ssl_socket.peer_cert
end
def close
@ssl_socket.close
@socket.close
end
def closed?
@socket.closed?
end
def eof?
@ssl_socket.eof?
end
def gets(*args)
str = @ssl_socket.gets(*args)
debug(str)
str
end
def read(*args)
str = @ssl_socket.read(*args)
debug(str)
str
end
def readpartial(*args)
str = @ssl_socket.readpartial(*args)
debug(str)
str
end
def <<(str)
rv = @ssl_socket.write(str)
debug(str)
rv
end
def flush
@ssl_socket.flush
end
def sync
@ssl_socket.sync
end
def sync=(sync)
@ssl_socket.sync = sync
end
private
def check_mask(value, mask)
value & mask == mask
end
def create_openssl_socket(socket)
ssl_socket = nil
if OpenSSL::SSL.const_defined?("SSLContext")
ctx = OpenSSL::SSL::SSLContext.new
@context.set_context(ctx)
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ctx)
else
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket)
@context.set_context(ssl_socket)
end
ssl_socket
end
def debug(str)
@debug_dev << str if @debug_dev && str
end
end
# Wraps up a Socket for method interception.
module SocketWrap
def initialize(socket, *args)
super(*args)
@socket = socket
end
def close
@socket.close
end
def closed?
@socket.closed?
end
def eof?
@socket.eof?
end
def gets(*args)
@socket.gets(*args)
end
def read(*args)
@socket.read(*args)
end
def readpartial(*args)
# StringIO doesn't support :readpartial
if @socket.respond_to?(:readpartial)
@socket.readpartial(*args)
else
@socket.read(*args)
end
end
def <<(str)
@socket << str
end
def flush
@socket.flush
end
def sync
@socket.sync
end
def sync=(sync)
@socket.sync = sync
end
end
# Module for intercepting Socket methods and dumps in/out to given debugging
# device. debug_dev must respond to <<.
module DebugSocket
extend SocketWrap
def debug_dev=(debug_dev)
@debug_dev = debug_dev
end
def close
super
debug("! CONNECTION CLOSED\n")
end
def gets(*args)
str = super
debug(str)
str
end
def read(*args)
str = super
debug(str)
str
end
def readpartial(*args)
str = super
debug(str)
str
end
def <<(str)
super
debug(str)
end
private
def debug(str)
@debug_dev << str if str && @debug_dev
end
end
# Dummy Socket for emulating loopback test.
class LoopBackSocket
include SocketWrap
def initialize(host, port, response)
super(response.is_a?(StringIO) ? response : StringIO.new(response))
@host = host
@port = port
end
def <<(str)
# ignored
end
end
# Manages a HTTP session with a Site.
class Session
include HTTPClient::Timeout
# Destination site
attr_reader :dest
# Proxy site
attr_accessor :proxy
# Boolean value for Socket#sync
attr_accessor :socket_sync
# Requested protocol version
attr_accessor :requested_version
# Device for dumping log for debugging
attr_accessor :debug_dev
attr_accessor :connect_timeout
attr_accessor :connect_retry
attr_accessor :send_timeout
attr_accessor :receive_timeout
attr_accessor :read_block_size
attr_accessor :protocol_retry_count
attr_accessor :ssl_config
attr_reader :ssl_peer_cert
attr_accessor :test_loopback_http_response
def initialize(client, dest, agent_name, from)
@client = client
@dest = dest
@proxy = nil
@socket_sync = true
@requested_version = nil
@debug_dev = nil
@connect_timeout = nil
@connect_retry = 1
@send_timeout = nil
@receive_timeout = nil
@read_block_size = nil
@protocol_retry_count = 5
@ssl_config = nil
@ssl_peer_cert = nil
@test_loopback_http_response = nil
@agent_name = agent_name
@from = from
@state = :INIT
@requests = []
@status = nil
@reason = nil
@headers = []
@socket = nil
@readbuf = nil
end
# Send a request to the server
def query(req)
connect if @state == :INIT
req.header.request_via_proxy = !@proxy.nil?
begin
timeout(@send_timeout, SendTimeoutError) do
set_header(req)
req.dump(@socket)
# flush the IO stream as IO::sync mode is false
@socket.flush unless @socket_sync
end
rescue Errno::ECONNABORTED, Errno::ECONNRESET, Errno::EPIPE
close
raise KeepAliveDisconnected.new
rescue HTTPClient::TimeoutError
close
raise
rescue
if SSLEnabled and $!.is_a?(OpenSSL::SSL::SSLError)
raise KeepAliveDisconnected.new
else
raise
end
end
@state = :META if @state == :WAIT
@next_connection = nil
@requests.push(req)
end
def close
if !@socket.nil? and !@socket.closed?
# @socket.flush may block when it the socket is already closed by
# foreign host and the client runs under MT-condition.
@socket.close
end
@state = :INIT
end
def closed?
@state == :INIT
end
def get_header
begin
if @state != :META
raise RuntimeError.new("get_status must be called at the beginning of a session")
end
read_header
rescue
close
raise
end
[@version, @status, @reason, @headers]
end
def eof?
if !@content_length.nil?
@content_length == 0
else
@socket.closed? or @socket.eof?
end
end
def get_body(&block)
begin
read_header if @state == :META
return nil if @state != :DATA
if @chunked
read_body_chunked(&block)
elsif @content_length
read_body_length(&block)
else
read_body_rest(&block)
end
rescue
close
raise
end
if eof?
if @next_connection
@state = :WAIT
else
close
end
end
nil
end
private
def set_header(req)
if @requested_version
if /^(?:HTTP\/|)(\d+.\d+)$/ =~ @requested_version
req.version = $1.to_f
end
end
if @agent_name
req.header.set('User-Agent', "#{@agent_name} #{LIB_NAME}")
end
if @from
req.header.set('From', @from)
end
req.header.set('Date', Time.now.httpdate)
end
# Connect to the server
def connect
site = @proxy || @dest
retry_number = 0
begin
timeout(@connect_timeout, ConnectTimeoutError) do
@socket = create_socket(site)
if @dest.scheme == 'https'
if @socket.is_a?(LoopBackSocket)
connect_ssl_proxy(@socket, URI.parse(@dest.to_s)) if @proxy
else
@socket = create_ssl_socket(@socket)
connect_ssl_proxy(@socket, URI.parse(@dest.to_s)) if @proxy
@socket.ssl_connect
@socket.post_connection_check(@dest)
@ssl_peer_cert = @socket.peer_cert
end
end
# Use Ruby internal buffering instead of passing data immediately
# to the underlying layer
# => we need to to call explicitly flush on the socket
@socket.sync = @socket_sync
end
rescue RetryableResponse
retry_number += 1
if retry_number < @protocol_retry_count
retry
end
raise BadResponseError.new("connect to the server failed with status #{@status} #{@reason}")
rescue TimeoutError
if @connect_retry == 0
retry
else
retry_number += 1
retry if retry_number < @connect_retry
end
close
raise
end
@state = :WAIT
end
def create_socket(site)
socket = nil
begin
@debug_dev << "! CONNECT TO #{site.host}:#{site.port}\n" if @debug_dev
if str = @test_loopback_http_response.shift
socket = LoopBackSocket.new(site.host, site.port, str)
else
socket = TCPSocket.new(site.host, site.port)
end
if @debug_dev
@debug_dev << "! CONNECTION ESTABLISHED\n"
socket.extend(DebugSocket)
socket.debug_dev = @debug_dev
end
rescue SystemCallError => e
e.message << " (#{site})"
raise
rescue SocketError => e
e.message << " (#{site})"
raise
end
socket
end
# wrap socket with OpenSSL.
def create_ssl_socket(raw_socket)
SSLSocketWrap.new(raw_socket, @ssl_config, @debug_dev)
end
def connect_ssl_proxy(socket, uri)
req = HTTP::Message.new_connect_request(uri)
@client.request_filter.each do |filter|
filter.filter_request(req)
end
set_header(req)
req.dump(@socket)
@socket.flush unless @socket_sync
res = HTTP::Message.new_response('')
parse_header
res.version, res.status, res.reason = @version, @status, @reason
@headers.each do |key, value|
res.header.set(key, value)
end
commands = @client.request_filter.collect { |filter|
filter.filter_response(req, res)
}
if commands.find { |command| command == :retry }
raise RetryableResponse.new
end
unless @status == 200
raise BadResponseError.new("connect to ssl proxy failed with status #{@status} #{@reason}", res)
end
end
# Read status block.
def read_header
@content_length = nil
@chunked = false
@chunk_length = 0
parse_header
# Head of the request has been parsed.
@state = :DATA
req = @requests.shift
if req.header.request_method == 'HEAD'
@content_length = 0
if @next_connection
@state = :WAIT
else
close
end
end
@next_connection = false unless @content_length
end
StatusParseRegexp = %r(\AHTTP/(\d+\.\d+)\s+(\d\d\d)\s*([^\r\n]+)?\r?\n\z)
def parse_header
timeout(@receive_timeout, ReceiveTimeoutError) do
begin
initial_line = @socket.gets("\n")
if initial_line.nil?
raise KeepAliveDisconnected.new
end
if StatusParseRegexp !~ initial_line
@version = '0.9'
@status = nil
@reason = nil
@next_connection = false
@content_length = nil
@readbuf = initial_line
break
end
@version, @status, @reason = $1, $2.to_i, $3
@next_connection = HTTP::Message.keep_alive_enabled?(@version.to_f)
@headers = []
while true
line = @socket.gets("\n")
unless line
raise BadResponseError.new('unexpected EOF')
end
line.chomp!
break if line.empty?
key, value = line.split(/\s*:\s*/, 2)
parse_keepalive_header(key, value)
@headers << [key, value]
end
end while (@version == '1.1' && @status == 100)
end
end
def parse_keepalive_header(key, value)
key = key.downcase
if key == 'content-length'
@content_length = value.to_i
elsif key == 'transfer-encoding' and value.downcase == 'chunked'
@chunked = true
@chunk_length = 0
@content_length = nil
elsif key == 'connection' or key == 'proxy-connection'
if value.downcase == 'keep-alive'
@next_connection = true
else
@next_connection = false
end
end
end
def read_body_length(&block)
return nil if @content_length == 0
buf = ''
while true
maxbytes = @read_block_size
maxbytes = @content_length if maxbytes > @content_length
timeout(@receive_timeout, ReceiveTimeoutError) do
begin
@socket.readpartial(maxbytes, buf)
rescue EOFError
buf = nil
end
end
if buf && buf.length > 0
@content_length -= buf.length
yield buf
else
@content_length = 0
end
return if @content_length == 0
end
end
RS = "\r\n"
def read_body_chunked(&block)
buf = ''
while true
len = @socket.gets(RS)
@chunk_length = len.hex
if @chunk_length == 0
@content_length = 0
@socket.gets(RS)
return
end
timeout(@receive_timeout, ReceiveTimeoutError) do
@socket.read(@chunk_length + 2, buf)
end
unless buf.empty?
yield buf.slice(0, @chunk_length)
end
end
end
def read_body_rest
if @readbuf and @readbuf.length > 0
yield @readbuf
@readbuf = nil
end
buf = ''
while true
timeout(@receive_timeout, ReceiveTimeoutError) do
begin
@socket.readpartial(@read_block_size, buf)
rescue EOFError
buf = nil
end
end
if buf && buf.length > 0
yield buf
else
return
end
end
end
end
end

View file

@ -0,0 +1,417 @@
# HTTPClient - HTTP client library.
# Copyright (C) 2000-2009 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
#
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
# redistribute it and/or modify it under the same terms of Ruby's license;
# either the dual license version in 2003, or any later version.
class HTTPClient
begin
require 'openssl'
SSLEnabled = true
rescue LoadError
SSLEnabled = false
end
# Represents SSL configuration for HTTPClient instance.
# The implementation depends on OpenSSL.
#
# == Trust Anchor Control
#
# SSLConfig loads 'httpclient/cacert.p7s' as a trust anchor
# (trusted certificate(s)) with set_trust_ca in initialization time.
# This means that HTTPClient instance trusts some CA certificates by default,
# like Web browsers. 'httpclient/cacert.p7s' is created by the author and
# included in released package.
#
# 'cacert.p7s' is automatically generated from JDK 1.6.
#
# You may want to change trust anchor by yourself. Call clear_cert_store
# then set_trust_ca for that purpose.
class SSLConfig
include OpenSSL if SSLEnabled
# OpenSSL::X509::Certificate:: certificate for SSL client authenticateion.
# nil by default. (no client authenticateion)
attr_reader :client_cert
# OpenSSL::PKey::PKey:: private key for SSL client authentication.
# nil by default. (no client authenticateion)
attr_reader :client_key
# A number which represents OpenSSL's verify mode. Default value is
# OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT.
attr_reader :verify_mode
# A number of verify depth. Certification path which length is longer than
# this depth is not allowed.
attr_reader :verify_depth
# A callback handler for custom certificate verification. nil by default.
# If the handler is set, handler.call is invoked just after general
# OpenSSL's verification. handler.call is invoked with 2 arguments,
# ok and ctx; ok is a result of general OpenSSL's verification. ctx is a
# OpenSSL::X509::StoreContext.
attr_reader :verify_callback
# SSL timeout in sec. nil by default.
attr_reader :timeout
# A number of OpenSSL's SSL options. Default value is
# OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv2
attr_reader :options
# A String of OpenSSL's cipher configuration. Default value is
# ALL:!ADH:!LOW:!EXP:!MD5:+SSLv2:@STRENGTH
# See ciphers(1) man in OpenSSL for more detail.
attr_reader :ciphers
# OpenSSL::X509::X509::Store used for verification. You can reset the
# store with clear_cert_store and set the new store with cert_store=.
attr_reader :cert_store # don't use if you don't know what it is.
# For server side configuration. Ignore this.
attr_reader :client_ca # :nodoc:
# Creates a SSLConfig.
def initialize(client)
return unless SSLEnabled
@client = client
@cert_store = X509::Store.new
@client_cert = @client_key = @client_ca = nil
@verify_mode = SSL::VERIFY_PEER | SSL::VERIFY_FAIL_IF_NO_PEER_CERT
@verify_depth = nil
@verify_callback = nil
@dest = nil
@timeout = nil
@options = defined?(SSL::OP_ALL) ? SSL::OP_ALL | SSL::OP_NO_SSLv2 : nil
@ciphers = "ALL:!ADH:!LOW:!EXP:!MD5:+SSLv2:@STRENGTH"
load_cacerts
end
# Sets certificate (OpenSSL::X509::Certificate) for SSL client
# authentication.
# client_key and client_cert must be a pair.
#
# Calling this method resets all existing sessions.
def client_cert=(client_cert)
@client_cert = client_cert
change_notify
end
# Sets private key (OpenSSL::PKey::PKey) for SSL client authentication.
# client_key and client_cert must be a pair.
#
# Calling this method resets all existing sessions.
def client_key=(client_key)
@client_key = client_key
change_notify
end
# Sets certificate and private key for SSL client authentication.
# cert_file:: must be a filename of PEM/DER formatted file.
# key_file:: must be a filename of PEM/DER formatted file. Key must be an
# RSA key. If you want to use other PKey algorithm,
# use client_key=.
#
# Calling this method resets all existing sessions.
def set_client_cert_file(cert_file, key_file)
@client_cert = X509::Certificate.new(File.open(cert_file).read)
@client_key = PKey::RSA.new(File.open(key_file).read)
change_notify
end
# Drops current certificate store (OpenSSL::X509::Store) for SSL and create
# new one for the next session.
#
# Calling this method resets all existing sessions.
def clear_cert_store
@cert_store = X509::Store.new
change_notify
end
# Sets new certificate store (OpenSSL::X509::Store).
# don't use if you don't know what it is.
#
# Calling this method resets all existing sessions.
def cert_store=(cert_store)
@cert_store = cert_store
change_notify
end
# Sets trust anchor certificate(s) for verification.
# trust_ca_file_or_hashed_dir:: a filename of a PEM/DER formatted
# OpenSSL::X509::Certificate or
# a 'c-rehash'eddirectory name which stores
# trusted certificate files.
#
# Calling this method resets all existing sessions.
def set_trust_ca(trust_ca_file_or_hashed_dir)
if FileTest.directory?(trust_ca_file_or_hashed_dir)
@cert_store.add_path(trust_ca_file_or_hashed_dir)
else
@cert_store.add_file(trust_ca_file_or_hashed_dir)
end
change_notify
end
# Adds CRL for verification.
# crl:: a OpenSSL::X509::CRL or a filename of a PEM/DER formatted
# OpenSSL::X509::CRL.
#
# Calling this method resets all existing sessions.
def set_crl(crl)
unless crl.is_a?(X509::CRL)
crl = X509::CRL.new(File.open(crl).read)
end
@cert_store.add_crl(crl)
@cert_store.flags = X509::V_FLAG_CRL_CHECK | X509::V_FLAG_CRL_CHECK_ALL
change_notify
end
# Sets verify mode of OpenSSL. New value must be a combination of
# constants OpenSSL::SSL::VERIFY_*
#
# Calling this method resets all existing sessions.
def verify_mode=(verify_mode)
@verify_mode = verify_mode
change_notify
end
# Sets verify depth. New value must be a number.
#
# Calling this method resets all existing sessions.
def verify_depth=(verify_depth)
@verify_depth = verify_depth
change_notify
end
# Sets callback handler for custom certificate verification.
# See verify_callback.
#
# Calling this method resets all existing sessions.
def verify_callback=(verify_callback)
@verify_callback = verify_callback
change_notify
end
# Sets SSL timeout in sec.
#
# Calling this method resets all existing sessions.
def timeout=(timeout)
@timeout = timeout
change_notify
end
# Sets SSL options. New value must be a combination of # constants
# OpenSSL::SSL::OP_*
#
# Calling this method resets all existing sessions.
def options=(options)
@options = options
change_notify
end
# Sets cipher configuration. New value must be a String.
#
# Calling this method resets all existing sessions.
def ciphers=(ciphers)
@ciphers = ciphers
change_notify
end
def client_ca=(client_ca) # :nodoc:
@client_ca = client_ca
change_notify
end
# interfaces for SSLSocketWrap.
def set_context(ctx) # :nodoc:
# Verification: Use Store#verify_callback instead of SSLContext#verify*?
ctx.cert_store = @cert_store
ctx.verify_mode = @verify_mode
ctx.verify_depth = @verify_depth if @verify_depth
ctx.verify_callback = @verify_callback || method(:default_verify_callback)
# SSL config
ctx.cert = @client_cert
ctx.key = @client_key
ctx.client_ca = @client_ca
ctx.timeout = @timeout
ctx.options = @options
ctx.ciphers = @ciphers
end
# post connection check proc for ruby < 1.8.5.
# this definition must match with the one in ext/openssl/lib/openssl/ssl.rb
def post_connection_check(peer_cert, hostname) # :nodoc:
check_common_name = true
cert = peer_cert
cert.extensions.each{|ext|
next if ext.oid != "subjectAltName"
ext.value.split(/,\s+/).each{|general_name|
if /\ADNS:(.*)/ =~ general_name
check_common_name = false
reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+")
return true if /\A#{reg}\z/i =~ hostname
elsif /\AIP Address:(.*)/ =~ general_name
check_common_name = false
return true if $1 == hostname
end
}
}
if check_common_name
cert.subject.to_a.each{|oid, value|
if oid == "CN"
reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+")
return true if /\A#{reg}\z/i =~ hostname
end
}
end
raise SSL::SSLError, "hostname was not match with the server certificate"
end
# Default callback for verification: only dumps error.
def default_verify_callback(is_ok, ctx)
if $DEBUG
puts "#{ is_ok ? 'ok' : 'ng' }: #{ctx.current_cert.subject}"
end
if !is_ok
depth = ctx.error_depth
code = ctx.error
msg = ctx.error_string
STDERR.puts "at depth #{depth} - #{code}: #{msg}"
end
is_ok
end
# Sample callback method: CAUTION: does not check CRL/ARL.
def sample_verify_callback(is_ok, ctx)
unless is_ok
depth = ctx.error_depth
code = ctx.error
msg = ctx.error_string
STDERR.puts "at depth #{depth} - #{code}: #{msg}" if $DEBUG
return false
end
cert = ctx.current_cert
self_signed = false
ca = false
pathlen = nil
server_auth = true
self_signed = (cert.subject.cmp(cert.issuer) == 0)
# Check extensions whatever its criticality is. (sample)
cert.extensions.each do |ex|
case ex.oid
when 'basicConstraints'
/CA:(TRUE|FALSE), pathlen:(\d+)/ =~ ex.value
ca = ($1 == 'TRUE')
pathlen = $2.to_i
when 'keyUsage'
usage = ex.value.split(/\s*,\s*/)
ca = usage.include?('Certificate Sign')
server_auth = usage.include?('Key Encipherment')
when 'extendedKeyUsage'
usage = ex.value.split(/\s*,\s*/)
server_auth = usage.include?('Netscape Server Gated Crypto')
when 'nsCertType'
usage = ex.value.split(/\s*,\s*/)
ca = usage.include?('SSL CA')
server_auth = usage.include?('SSL Server')
end
end
if self_signed
STDERR.puts 'self signing CA' if $DEBUG
return true
elsif ca
STDERR.puts 'middle level CA' if $DEBUG
return true
elsif server_auth
STDERR.puts 'for server authentication' if $DEBUG
return true
end
return false
end
private
def change_notify
@client.reset_all
end
def load_cacerts
[
[DIST_CERT, 'cacert.p7s'],
[DIST_CERT_SHA1, 'cacert_sha1.p7s']
].each do |cert_str, ca_file|
file = File.join(File.dirname(__FILE__), ca_file)
if File.exist?(file)
p7 = PKCS7.read_smime(File.open(file) { |f| f.read })
selfcert = X509::Certificate.new(cert_str)
store = X509::Store.new
store.add_cert(selfcert)
if (p7.verify(nil, store, p7.data, 0))
set_trust_ca(file)
return
end
end
end
STDERR.puts("cacerts loading failed")
end
DIST_CERT =<<__DIST_CERT__
-----BEGIN CERTIFICATE-----
MIID/TCCAuWgAwIBAgIBATANBgkqhkiG9w0BAQ0FADBLMQswCQYDVQQGEwJKUDER
MA8GA1UECgwIY3Rvci5vcmcxFDASBgNVBAsMC0RldmVsb3BtZW50MRMwEQYDVQQD
DApodHRwY2xpZW50MB4XDTA5MDUyMTEyMzkwNVoXDTM3MTIzMTIzNTk1OVowSzEL
MAkGA1UEBhMCSlAxETAPBgNVBAoMCGN0b3Iub3JnMRQwEgYDVQQLDAtEZXZlbG9w
bWVudDETMBEGA1UEAwwKaHR0cGNsaWVudDCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAM2PlkdTH97zvIHoPIMj87wnNvpqIQUD7L/hlysO0XBsmR/XZUeU
ZKB10JQqMXviWpTnU9KU6xGTx3EI4wfd2dpLwH/d4d7K4LngW1kY7kJlZeJhakno
GzQ40RSI9WkQ0R9KOE888f7OkTBafcL8UyWFVIMhQBw2d9iNl4Jc69QojayCDoSX
XbbEP0n8yi7HwIU3RFuX6DtMpOx4/1K7Z002ccOGJ3J9kHgeDQSQtF42cQYC7qj2
67I/OQgnB7ycxTCP0E7bdXQg+zqsngrhaoNn/+I+CoO7nD4t4uQ+B4agALh4PPxs
bQD9MCL+VurNGLYv0HVd+ZlLblpddC9PLTsCAwEAAaOB6zCB6DAPBgNVHRMBAf8E
BTADAQH/MDEGCWCGSAGG+EIBDQQkFiJSdWJ5L09wZW5TU0wgR2VuZXJhdGVkIENl
cnRpZmljYXRlMB0GA1UdDgQWBBRAnB6XlMoOcm7HVAw+JWxY205PHTAOBgNVHQ8B
Af8EBAMCAQYwcwYDVR0jBGwwaoAUQJwel5TKDnJux1QMPiVsWNtOTx2hT6RNMEsx
CzAJBgNVBAYTAkpQMREwDwYDVQQKDAhjdG9yLm9yZzEUMBIGA1UECwwLRGV2ZWxv
cG1lbnQxEzARBgNVBAMMCmh0dHBjbGllbnSCAQEwDQYJKoZIhvcNAQENBQADggEB
ABVFepybD5XqsBnOn/oDHvK0xAPMF4Ap4Ht1yMQLObg8paVhANSdqIevPlCr/mPL
DRjcy+J1fCnE6lCfsfLdTgAjirqt8pm92NccxmJ8hTmMd3LWC1n+eYWaolqTCVRM
Bpe8UY9enyXrFoudHlr9epr18E6As6VrCSfpXFZkD9WHVSWpzkB3qATu5qcDCzCH
bI0755Mdm/1hKJCD4l69h3J3OhRIEUPJfHnPvM5wtiyC2dcE9itwE/wdVzBJeIBX
JQm+Qj+K8qXcRTzZZGIBjw2n46xJgW6YncNCHU/WWfNCYwdkngHS/aN8IbEjhCwf
viXFisVrDN/+pZZGMf67ZaY=
-----END CERTIFICATE-----
__DIST_CERT__
DIST_CERT_SHA1 =<<__DIST_CERT__
-----BEGIN CERTIFICATE-----
MIID/TCCAuWgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJKUDER
MA8GA1UECgwIY3Rvci5vcmcxFDASBgNVBAsMC0RldmVsb3BtZW50MRMwEQYDVQQD
DApodHRwY2xpZW50MB4XDTA5MDYyNTE0MjUzN1oXDTEwMTIzMTIzNTk1OVowSzEL
MAkGA1UEBhMCSlAxETAPBgNVBAoMCGN0b3Iub3JnMRQwEgYDVQQLDAtEZXZlbG9w
bWVudDETMBEGA1UEAwwKaHR0cGNsaWVudDCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAM2PlkdTH97zvIHoPIMj87wnNvpqIQUD7L/hlysO0XBsmR/XZUeU
ZKB10JQqMXviWpTnU9KU6xGTx3EI4wfd2dpLwH/d4d7K4LngW1kY7kJlZeJhakno
GzQ40RSI9WkQ0R9KOE888f7OkTBafcL8UyWFVIMhQBw2d9iNl4Jc69QojayCDoSX
XbbEP0n8yi7HwIU3RFuX6DtMpOx4/1K7Z002ccOGJ3J9kHgeDQSQtF42cQYC7qj2
67I/OQgnB7ycxTCP0E7bdXQg+zqsngrhaoNn/+I+CoO7nD4t4uQ+B4agALh4PPxs
bQD9MCL+VurNGLYv0HVd+ZlLblpddC9PLTsCAwEAAaOB6zCB6DAPBgNVHRMBAf8E
BTADAQH/MDEGCWCGSAGG+EIBDQQkFiJSdWJ5L09wZW5TU0wgR2VuZXJhdGVkIENl
cnRpZmljYXRlMB0GA1UdDgQWBBRAnB6XlMoOcm7HVAw+JWxY205PHTAOBgNVHQ8B
Af8EBAMCAQYwcwYDVR0jBGwwaoAUQJwel5TKDnJux1QMPiVsWNtOTx2hT6RNMEsx
CzAJBgNVBAYTAkpQMREwDwYDVQQKDAhjdG9yLm9yZzEUMBIGA1UECwwLRGV2ZWxv
cG1lbnQxEzARBgNVBAMMCmh0dHBjbGllbnSCAQIwDQYJKoZIhvcNAQEFBQADggEB
AGKhgByl/ur6SBFFKJcISJONFRaxf2ji0l6ut9XO1H2BSOSRjUbsFDWdWZG+D24Q
JKKseSWPWAC5uHq00sBWkvmtip+duESPeDEdumdBhdiUUgGamW2Ew2y4yAdAVDeG
t1p2fs8SylQN6AMTG/+R+MGHxhvg+UELYLcvAjjcDW2VhDQaJ1eFEfcMW1zRtvvh
LJmVErouwFKyAjwhbF6sNxmToSnbO1ciWwIILMsOBNHMETCp+SzkRDIRWIkm6m+q
RwRyYoHysODGvnu8VXS1hGRr2GIxeBga7dAGa2VLE/iUQ0d4lEskYU+6C4ZLyAWF
O89dvLNRzpL10MaWCYVREks=
-----END CERTIFICATE-----
__DIST_CERT__
end
end

View file

@ -0,0 +1,136 @@
# HTTPClient - HTTP client library.
# Copyright (C) 2000-2009 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
#
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
# redistribute it and/or modify it under the same terms of Ruby's license;
# either the dual license version in 2003, or any later version.
require 'timeout'
require 'thread'
class HTTPClient
# Replaces timeout.rb to avoid Thread creation and scheduling overhead.
#
# You should check another timeout replace in WEBrick.
# See lib/webrick/utils.rb in ruby/1.9.
#
# About this implementation:
# * Do not create Thread for each timeout() call. Just create 1 Thread for
# timeout scheduler.
# * Do not wakeup the scheduler thread so often. Let scheduler thread sleep
# until the nearest period.
class TimeoutScheduler
# Represents timeout period.
class Period
attr_reader :thread, :time
# Creates new Period.
def initialize(thread, time, ex)
@thread, @time, @ex = thread, time, ex
@lock = Mutex.new
end
# Raises if thread exists and alive.
def raise(message)
@lock.synchronize do
if @thread and @thread.alive?
@thread.raise(@ex, message)
end
end
end
# Cancel this Period. Mutex is needed to avoid too-late exception.
def cancel
@lock.synchronize do
@thread = nil
end
end
end
# Creates new TimeoutScheduler.
def initialize
@pool = {}
@next = nil
@thread = start_timer_thread
end
# Registers new timeout period.
def register(thread, sec, ex)
period = Period.new(thread, Time.now + sec, ex || ::Timeout::Error)
@pool[period] = true
if @next.nil? or period.time < @next
begin
@thread.wakeup
rescue ThreadError
# Thread may be dead by fork.
@thread = start_timer_thread
end
end
period
end
# Cancels the given period.
def cancel(period)
@pool.delete(period)
period.cancel
end
private
def start_timer_thread
thread = Thread.new {
while true
if @pool.empty?
@next = nil
sleep
else
min, = @pool.min { |a, b| a[0].time <=> b[0].time }
@next = min.time
sec = @next - Time.now
if sec > 0
sleep(sec)
end
end
now = Time.now
@pool.keys.each do |period|
if period.time < now
period.raise('execution expired')
cancel(period)
end
end
end
}
Thread.pass while thread.status != 'sleep'
thread
end
end
class << self
# CAUTION: caller must aware of race condition.
def timeout_scheduler
@timeout_scheduler ||= TimeoutScheduler.new
end
end
timeout_scheduler # initialize at first time.
module Timeout
def timeout(sec, ex = nil, &block)
return yield if sec == nil or sec.zero?
scheduler = nil
begin
scheduler = HTTPClient.timeout_scheduler
period = scheduler.register(Thread.current, sec, ex)
yield(sec)
ensure
scheduler.cancel(period) if scheduler and period
end
end
end
end

View file

@ -0,0 +1,86 @@
# HTTPClient - HTTP client library.
# Copyright (C) 2000-2009 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
#
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
# redistribute it and/or modify it under the same terms of Ruby's license;
# either the dual license version in 2003, or any later version.
require 'uri'
class HTTPClient
# A module for common function.
module Util
# Keyword argument helper.
# args:: given arguments.
# *field:: a list of arguments to be extracted.
#
# You can extract 3 arguments (a, b, c) with:
#
# include Util
# def my_method(*args)
# a, b, c = keyword_argument(args, :a, :b, :c)
# ...
# end
# my_method(1, 2, 3)
# my_method(:b => 2, :a = 1)
#
# instead of;
#
# def my_method(a, b, c)
# ...
# end
#
def keyword_argument(args, *field)
if args.size == 1 and args[0].is_a?(Hash)
args[0].values_at(*field)
else
args
end
end
# Gets an URI instance.
def urify(uri)
if uri.nil?
nil
elsif uri.is_a?(URI)
uri
else
URI.parse(uri.to_s)
end
end
# Returns true if the given 2 URIs have a part_of relationship.
# * the same scheme
# * the same host String (no host resolution or IP-addr conversion)
# * the same port number
# * target URI's path starts with base URI's path.
def uri_part_of(uri, part)
((uri.scheme == part.scheme) and
(uri.host == part.host) and
(uri.port == part.port) and
uri.path.upcase.index(part.path.upcase) == 0)
end
module_function :uri_part_of
# Returns parent directory URI of the given URI.
def uri_dirname(uri)
uri = uri.clone
uri.path = uri.path.sub(/\/[^\/]*\z/, '/')
uri
end
module_function :uri_dirname
# Finds a value of a Hash.
def hash_find_value(hash, &block)
v = hash.find(&block)
v ? v[1] : nil
end
module_function :hash_find_value
end
end

View file

@ -0,0 +1,908 @@
::HTTP httpclient/http.rb /^module HTTP/
::HTTP::Message httpclient/http.rb /^ class Message/
::HTTP::Message#HTTP::Message.new httpclient/http.rb /^ def initialize/
::HTTP::Message#body httpclient/http.rb /^ attr_reader :body/
::HTTP::Message#body= httpclient/http.rb /^ def body=/
::HTTP::Message#code httpclient/http.rb /^ alias code/
::HTTP::Message#content httpclient/http.rb /^ def content/
::HTTP::Message#contenttype httpclient/http.rb /^ def contenttype/
::HTTP::Message#contenttype= httpclient/http.rb /^ def contenttype=/
::HTTP::Message#dump httpclient/http.rb /^ def dump/
::HTTP::Message#header httpclient/http.rb /^ attr_accessor :header/
::HTTP::Message#peer_cert httpclient/http.rb /^ attr_accessor :peer_cert/
::HTTP::Message#reason httpclient/http.rb /^ def reason/
::HTTP::Message#reason= httpclient/http.rb /^ def reason=/
::HTTP::Message#status httpclient/http.rb /^ def status/
::HTTP::Message#status= httpclient/http.rb /^ def status=/
::HTTP::Message#status_code httpclient/http.rb /^ alias status_code/
::HTTP::Message#version httpclient/http.rb /^ def version/
::HTTP::Message#version= httpclient/http.rb /^ def version=/
::HTTP::Message.create_query_part_str httpclient/http.rb /^ def create_query_part_str/
::HTTP::Message.escape httpclient/http.rb /^ def escape/
::HTTP::Message.escape_query httpclient/http.rb /^ def escape_query/
::HTTP::Message.file? httpclient/http.rb /^ def file?/
::HTTP::Message.get_mime_type_func httpclient/http.rb /^ alias get_mime_type_func/
::HTTP::Message.internal_mime_type httpclient/http.rb /^ def internal_mime_type/
::HTTP::Message.keep_alive_enabled? httpclient/http.rb /^ def keep_alive_enabled?/
::HTTP::Message.mime_type httpclient/http.rb /^ def mime_type/
::HTTP::Message.mime_type_handler httpclient/http.rb /^ def mime_type_handler/
::HTTP::Message.mime_type_handler= httpclient/http.rb /^ def mime_type_handler=/
::HTTP::Message.multiparam_query? httpclient/http.rb /^ def multiparam_query?/
::HTTP::Message.new_connect_request httpclient/http.rb /^ def new_connect_request/
::HTTP::Message.new_request httpclient/http.rb /^ def new_request/
::HTTP::Message.new_response httpclient/http.rb /^ def new_response/
::HTTP::Message.set_mime_type_func httpclient/http.rb /^ alias set_mime_type_func/
::HTTP::Message::Body httpclient/http.rb /^ class Body/
::HTTP::Message::Body#HTTP::Message::Body.new httpclient/http.rb /^ def initialize/
::HTTP::Message::Body#build_query_multipart_str httpclient/http.rb /^ def build_query_multipart_str/
::HTTP::Message::Body#chunk_size httpclient/http.rb /^ attr_accessor :chunk_size/
::HTTP::Message::Body#content httpclient/http.rb /^ def content/
::HTTP::Message::Body#dump httpclient/http.rb /^ def dump/
::HTTP::Message::Body#dump_chunk httpclient/http.rb /^ def dump_chunk/
::HTTP::Message::Body#dump_chunk_size httpclient/http.rb /^ def dump_chunk_size/
::HTTP::Message::Body#dump_chunked httpclient/http.rb /^ def dump_chunked/
::HTTP::Message::Body#dump_chunks httpclient/http.rb /^ def dump_chunks/
::HTTP::Message::Body#dump_last_chunk httpclient/http.rb /^ def dump_last_chunk/
::HTTP::Message::Body#init_request httpclient/http.rb /^ def init_request/
::HTTP::Message::Body#init_response httpclient/http.rb /^ def init_response/
::HTTP::Message::Body#params_from_file httpclient/http.rb /^ def params_from_file/
::HTTP::Message::Body#remember_pos httpclient/http.rb /^ def remember_pos/
::HTTP::Message::Body#reset_pos httpclient/http.rb /^ def reset_pos/
::HTTP::Message::Body#set_content httpclient/http.rb /^ def set_content/
::HTTP::Message::Body#size httpclient/http.rb /^ attr_reader :size/
::HTTP::Message::Body::Parts httpclient/http.rb /^ class Parts/
::HTTP::Message::Body::Parts#HTTP::Message::Body::Parts.new httpclient/http.rb /^ def initialize/
::HTTP::Message::Body::Parts#add httpclient/http.rb /^ def add/
::HTTP::Message::Body::Parts#parts httpclient/http.rb /^ def parts/
::HTTP::Message::Body::Parts#size httpclient/http.rb /^ attr_reader :size/
::HTTP::Message::Headers httpclient/http.rb /^ class Headers/
::HTTP::Message::Headers#HTTP::Message::Headers.new httpclient/http.rb /^ def initialize/
::HTTP::Message::Headers#[] httpclient/http.rb /^ def []/
::HTTP::Message::Headers#[]= httpclient/http.rb /^ def []=/
::HTTP::Message::Headers#add httpclient/http.rb /^ def add/
::HTTP::Message::Headers#all httpclient/http.rb /^ def all/
::HTTP::Message::Headers#body_charset httpclient/http.rb /^ attr_accessor :body_charset # :nodoc:/
::HTTP::Message::Headers#body_date httpclient/http.rb /^ attr_accessor :body_date # :nodoc:/
::HTTP::Message::Headers#body_size httpclient/http.rb /^ attr_reader :body_size/
::HTTP::Message::Headers#body_size= httpclient/http.rb /^ def body_size=/
::HTTP::Message::Headers#body_type httpclient/http.rb /^ attr_accessor :body_type # :nodoc:/
::HTTP::Message::Headers#charset_label httpclient/http.rb /^ def charset_label/
::HTTP::Message::Headers#chunked httpclient/http.rb /^ attr_accessor :chunked/
::HTTP::Message::Headers#contenttype httpclient/http.rb /^ def contenttype/
::HTTP::Message::Headers#contenttype= httpclient/http.rb /^ def contenttype=/
::HTTP::Message::Headers#create_query_uri httpclient/http.rb /^ def create_query_uri/
::HTTP::Message::Headers#delete httpclient/http.rb /^ def delete/
::HTTP::Message::Headers#dump httpclient/http.rb /^ def dump/
::HTTP::Message::Headers#get httpclient/http.rb /^ def get/
::HTTP::Message::Headers#http_version httpclient/http.rb /^ attr_accessor :http_version/
::HTTP::Message::Headers#init_connect_request httpclient/http.rb /^ def init_connect_request/
::HTTP::Message::Headers#init_request httpclient/http.rb /^ def init_request/
::HTTP::Message::Headers#init_response httpclient/http.rb /^ def init_response/
::HTTP::Message::Headers#reason_phrase httpclient/http.rb /^ attr_accessor :reason_phrase/
::HTTP::Message::Headers#request_line httpclient/http.rb /^ def request_line/
::HTTP::Message::Headers#request_method httpclient/http.rb /^ attr_reader :request_method/
::HTTP::Message::Headers#request_query httpclient/http.rb /^ attr_accessor :request_query/
::HTTP::Message::Headers#request_uri httpclient/http.rb /^ attr_accessor :request_uri/
::HTTP::Message::Headers#request_via_proxy httpclient/http.rb /^ attr_accessor :request_via_proxy/
::HTTP::Message::Headers#response_status_line httpclient/http.rb /^ def response_status_line/
::HTTP::Message::Headers#set httpclient/http.rb /^ def set/
::HTTP::Message::Headers#set_header httpclient/http.rb /^ def set_header/
::HTTP::Message::Headers#set_request_header httpclient/http.rb /^ def set_request_header/
::HTTP::Message::Headers#set_response_header httpclient/http.rb /^ def set_response_header/
::HTTP::Message::Headers#status_code httpclient/http.rb /^ attr_reader :status_code/
::HTTP::Message::Headers#status_code= httpclient/http.rb /^ def status_code=/
::HTTP::Status httpclient/http.rb /^ module Status/
::HTTP::Status.redirect? httpclient/http.rb /^ def self.redirect?/
::HTTP::Status.successful? httpclient/http.rb /^ def self.successful?/
::HTTPClient httpclient.rb /^class HTTPClient/
::HTTPClient httpclient/auth.rb /^class HTTPClient/
::HTTPClient httpclient/connection.rb /^class HTTPClient/
::HTTPClient httpclient/session.rb /^class HTTPClient/
::HTTPClient httpclient/ssl_config.rb /^class HTTPClient/
::HTTPClient httpclient/timeout.rb /^class HTTPClient/
::HTTPClient httpclient/util.rb /^class HTTPClient/
::HTTPClient#HTTPClient.new httpclient.rb /^ def initialize/
::HTTPClient#cookie_manager httpclient.rb /^ attr_accessor :cookie_manager/
::HTTPClient#create_boundary httpclient.rb /^ def create_boundary/
::HTTPClient#create_request httpclient.rb /^ def create_request/
::HTTPClient#debug_dev httpclient.rb /^ def debug_dev/
::HTTPClient#debug_dev= httpclient.rb /^ def debug_dev=/
::HTTPClient#default_redirect_uri_callback httpclient.rb /^ def default_redirect_uri_callback/
::HTTPClient#delete httpclient.rb /^ def delete/
::HTTPClient#delete_async httpclient.rb /^ def delete_async/
::HTTPClient#do_get_block httpclient.rb /^ def do_get_block/
::HTTPClient#do_get_header httpclient.rb /^ def do_get_header/
::HTTPClient#do_get_stream httpclient.rb /^ def do_get_stream/
::HTTPClient#do_request httpclient.rb /^ def do_request/
::HTTPClient#do_request_async httpclient.rb /^ def do_request_async/
::HTTPClient#dump_dummy_request_response httpclient.rb /^ def dump_dummy_request_response/
::HTTPClient#file_in_form_data? httpclient.rb /^ def file_in_form_data?/
::HTTPClient#follow_redirect httpclient.rb /^ def follow_redirect/
::HTTPClient#follow_redirect_count httpclient.rb /^ attr_accessor :follow_redirect_count/
::HTTPClient#get httpclient.rb /^ def get/
::HTTPClient#get_async httpclient.rb /^ def get_async/
::HTTPClient#get_content httpclient.rb /^ def get_content/
::HTTPClient#getenv httpclient.rb /^ def getenv/
::HTTPClient#head httpclient.rb /^ def head/
::HTTPClient#head_async httpclient.rb /^ def head_async/
::HTTPClient#https? httpclient.rb /^ def https?/
::HTTPClient#load_environment httpclient.rb /^ def load_environment/
::HTTPClient#no_proxy httpclient.rb /^ def no_proxy/
::HTTPClient#no_proxy= httpclient.rb /^ def no_proxy=/
::HTTPClient#no_proxy? httpclient.rb /^ def no_proxy?/
::HTTPClient#options httpclient.rb /^ def options/
::HTTPClient#options_async httpclient.rb /^ def options_async/
::HTTPClient#override_header httpclient.rb /^ def override_header/
::HTTPClient#post httpclient.rb /^ def post/
::HTTPClient#post_async httpclient.rb /^ def post_async/
::HTTPClient#post_content httpclient.rb /^ def post_content/
::HTTPClient#propfind httpclient.rb /^ def propfind/
::HTTPClient#propfind_async httpclient.rb /^ def propfind_async/
::HTTPClient#proppatch httpclient.rb /^ def proppatch/
::HTTPClient#proppatch_async httpclient.rb /^ def proppatch_async/
::HTTPClient#protect_keep_alive_disconnected httpclient.rb /^ def protect_keep_alive_disconnected/
::HTTPClient#proxy httpclient.rb /^ def proxy/
::HTTPClient#proxy= httpclient.rb /^ def proxy=/
::HTTPClient#proxy_auth httpclient.rb /^ attr_reader :proxy_auth/
::HTTPClient#put httpclient.rb /^ def put/
::HTTPClient#put_async httpclient.rb /^ def put_async/
::HTTPClient#redirect_uri_callback= httpclient.rb /^ def redirect_uri_callback=/
::HTTPClient#request httpclient.rb /^ def request/
::HTTPClient#request_async httpclient.rb /^ def request_async/
::HTTPClient#request_filter httpclient.rb /^ attr_reader :request_filter/
::HTTPClient#reset httpclient.rb /^ def reset/
::HTTPClient#reset_all httpclient.rb /^ def reset_all/
::HTTPClient#save_cookie_store httpclient.rb /^ def save_cookie_store/
::HTTPClient#set_auth httpclient.rb /^ def set_auth/
::HTTPClient#set_basic_auth httpclient.rb /^ def set_basic_auth/
::HTTPClient#set_cookie_store httpclient.rb /^ def set_cookie_store/
::HTTPClient#set_proxy_auth httpclient.rb /^ def set_proxy_auth/
::HTTPClient#ssl_config httpclient.rb /^ attr_reader :ssl_config/
::HTTPClient#strict_redirect_uri_callback httpclient.rb /^ def strict_redirect_uri_callback/
::HTTPClient#test_loopback_response httpclient.rb /^ attr_reader :test_loopback_response/
::HTTPClient#trace httpclient.rb /^ def trace/
::HTTPClient#trace_async httpclient.rb /^ def trace_async/
::HTTPClient#www_auth httpclient.rb /^ attr_reader :www_auth/
::HTTPClient.attr_proxy httpclient.rb /^ def attr_proxy/
::HTTPClient.timeout_scheduler httpclient/timeout.rb /^ def timeout_scheduler/
::HTTPClient::AuthFilterBase httpclient/auth.rb /^ class AuthFilterBase/
::HTTPClient::AuthFilterBase#parse_authentication_header httpclient/auth.rb /^ def parse_authentication_header/
::HTTPClient::AuthFilterBase#parse_challenge_header httpclient/auth.rb /^ def parse_challenge_header/
::HTTPClient::BadResponseError httpclient.rb /^ class BadResponseError/
::HTTPClient::BadResponseError#HTTPClient::BadResponseError.new httpclient.rb /^ def initialize/
::HTTPClient::BadResponseError#res httpclient.rb /^ attr_reader :res/
::HTTPClient::BasicAuth httpclient/auth.rb /^ class BasicAuth/
::HTTPClient::BasicAuth#HTTPClient::BasicAuth.new httpclient/auth.rb /^ def initialize/
::HTTPClient::BasicAuth#challenge httpclient/auth.rb /^ def challenge/
::HTTPClient::BasicAuth#get httpclient/auth.rb /^ def get/
::HTTPClient::BasicAuth#reset_challenge httpclient/auth.rb /^ def reset_challenge/
::HTTPClient::BasicAuth#scheme httpclient/auth.rb /^ attr_reader :scheme/
::HTTPClient::BasicAuth#set httpclient/auth.rb /^ def set/
::HTTPClient::ConfigurationError httpclient.rb /^ class ConfigurationError/
::HTTPClient::ConnectTimeoutError httpclient.rb /^ class ConnectTimeoutError/
::HTTPClient::Connection httpclient/connection.rb /^ class Connection/
::HTTPClient::Connection#HTTPClient::Connection.new httpclient/connection.rb /^ def initialize/
::HTTPClient::Connection#async_thread httpclient/connection.rb /^ attr_accessor :async_thread/
::HTTPClient::Connection#finished? httpclient/connection.rb /^ def finished?/
::HTTPClient::Connection#join httpclient/connection.rb /^ def join/
::HTTPClient::Connection#pop httpclient/connection.rb /^ def pop/
::HTTPClient::Connection#push httpclient/connection.rb /^ def push/
::HTTPClient::DebugSocket httpclient/session.rb /^ module DebugSocket/
::HTTPClient::DebugSocket#<< httpclient/session.rb /^ def <</
::HTTPClient::DebugSocket#close httpclient/session.rb /^ def close/
::HTTPClient::DebugSocket#debug httpclient/session.rb /^ def debug/
::HTTPClient::DebugSocket#debug_dev= httpclient/session.rb /^ def debug_dev=/
::HTTPClient::DebugSocket#gets httpclient/session.rb /^ def gets/
::HTTPClient::DebugSocket#read httpclient/session.rb /^ def read/
::HTTPClient::DebugSocket#readpartial httpclient/session.rb /^ def readpartial/
::HTTPClient::DigestAuth httpclient/auth.rb /^ class DigestAuth/
::HTTPClient::DigestAuth#HTTPClient::DigestAuth.new httpclient/auth.rb /^ def initialize/
::HTTPClient::DigestAuth#calc_cred httpclient/auth.rb /^ def calc_cred/
::HTTPClient::DigestAuth#challenge httpclient/auth.rb /^ def challenge/
::HTTPClient::DigestAuth#get httpclient/auth.rb /^ def get/
::HTTPClient::DigestAuth#parse_challenge_param httpclient/auth.rb /^ def parse_challenge_param/
::HTTPClient::DigestAuth#reset_challenge httpclient/auth.rb /^ def reset_challenge/
::HTTPClient::DigestAuth#scheme httpclient/auth.rb /^ attr_reader :scheme/
::HTTPClient::DigestAuth#set httpclient/auth.rb /^ def set/
::HTTPClient::KeepAliveDisconnected httpclient.rb /^ class KeepAliveDisconnected/
::HTTPClient::LoopBackSocket httpclient/session.rb /^ class LoopBackSocket/
::HTTPClient::LoopBackSocket#<< httpclient/session.rb /^ def <</
::HTTPClient::LoopBackSocket#HTTPClient::LoopBackSocket.new httpclient/session.rb /^ def initialize/
::HTTPClient::NegotiateAuth httpclient/auth.rb /^ class NegotiateAuth/
::HTTPClient::NegotiateAuth#HTTPClient::NegotiateAuth.new httpclient/auth.rb /^ def initialize/
::HTTPClient::NegotiateAuth#challenge httpclient/auth.rb /^ def challenge/
::HTTPClient::NegotiateAuth#get httpclient/auth.rb /^ def get/
::HTTPClient::NegotiateAuth#ntlm_opt httpclient/auth.rb /^ attr_reader :ntlm_opt/
::HTTPClient::NegotiateAuth#reset_challenge httpclient/auth.rb /^ def reset_challenge/
::HTTPClient::NegotiateAuth#scheme httpclient/auth.rb /^ attr_reader :scheme/
::HTTPClient::NegotiateAuth#set httpclient/auth.rb /^ def set/
::HTTPClient::ProxyAuth httpclient/auth.rb /^ class ProxyAuth/
::HTTPClient::ProxyAuth#HTTPClient::ProxyAuth.new httpclient/auth.rb /^ def initialize/
::HTTPClient::ProxyAuth#basic_auth httpclient/auth.rb /^ attr_reader :basic_auth/
::HTTPClient::ProxyAuth#filter_request httpclient/auth.rb /^ def filter_request/
::HTTPClient::ProxyAuth#filter_response httpclient/auth.rb /^ def filter_response/
::HTTPClient::ProxyAuth#negotiate_auth httpclient/auth.rb /^ attr_reader :negotiate_auth/
::HTTPClient::ProxyAuth#reset_challenge httpclient/auth.rb /^ def reset_challenge/
::HTTPClient::ProxyAuth#set_auth httpclient/auth.rb /^ def set_auth/
::HTTPClient::ProxyAuth#sspi_negotiate_auth httpclient/auth.rb /^ attr_reader :sspi_negotiate_auth/
::HTTPClient::ReceiveTimeoutError httpclient.rb /^ class ReceiveTimeoutError/
::HTTPClient::RetryableResponse httpclient.rb /^ class RetryableResponse/
::HTTPClient::SSLConfig httpclient/ssl_config.rb /^ class SSLConfig/
::HTTPClient::SSLConfig#HTTPClient::SSLConfig.new httpclient/ssl_config.rb /^ def initialize/
::HTTPClient::SSLConfig#cert_store httpclient/ssl_config.rb /^ attr_reader :cert_store # don't use if you don't know what it is./
::HTTPClient::SSLConfig#cert_store= httpclient/ssl_config.rb /^ def cert_store=/
::HTTPClient::SSLConfig#change_notify httpclient/ssl_config.rb /^ def change_notify/
::HTTPClient::SSLConfig#ciphers httpclient/ssl_config.rb /^ attr_reader :ciphers/
::HTTPClient::SSLConfig#ciphers= httpclient/ssl_config.rb /^ def ciphers=/
::HTTPClient::SSLConfig#clear_cert_store httpclient/ssl_config.rb /^ def clear_cert_store/
::HTTPClient::SSLConfig#client_ca httpclient/ssl_config.rb /^ attr_reader :client_ca # :nodoc:/
::HTTPClient::SSLConfig#client_ca= httpclient/ssl_config.rb /^ def client_ca=/
::HTTPClient::SSLConfig#client_cert httpclient/ssl_config.rb /^ attr_reader :client_cert/
::HTTPClient::SSLConfig#client_cert= httpclient/ssl_config.rb /^ def client_cert=/
::HTTPClient::SSLConfig#client_key httpclient/ssl_config.rb /^ attr_reader :client_key/
::HTTPClient::SSLConfig#client_key= httpclient/ssl_config.rb /^ def client_key=/
::HTTPClient::SSLConfig#default_verify_callback httpclient/ssl_config.rb /^ def default_verify_callback/
::HTTPClient::SSLConfig#load_cacerts httpclient/ssl_config.rb /^ def load_cacerts/
::HTTPClient::SSLConfig#options httpclient/ssl_config.rb /^ attr_reader :options/
::HTTPClient::SSLConfig#options= httpclient/ssl_config.rb /^ def options=/
::HTTPClient::SSLConfig#post_connection_check httpclient/ssl_config.rb /^ def post_connection_check/
::HTTPClient::SSLConfig#sample_verify_callback httpclient/ssl_config.rb /^ def sample_verify_callback/
::HTTPClient::SSLConfig#set_client_cert_file httpclient/ssl_config.rb /^ def set_client_cert_file/
::HTTPClient::SSLConfig#set_context httpclient/ssl_config.rb /^ def set_context/
::HTTPClient::SSLConfig#set_crl httpclient/ssl_config.rb /^ def set_crl/
::HTTPClient::SSLConfig#set_trust_ca httpclient/ssl_config.rb /^ def set_trust_ca/
::HTTPClient::SSLConfig#timeout httpclient/ssl_config.rb /^ attr_reader :timeout/
::HTTPClient::SSLConfig#timeout= httpclient/ssl_config.rb /^ def timeout=/
::HTTPClient::SSLConfig#verify_callback httpclient/ssl_config.rb /^ attr_reader :verify_callback/
::HTTPClient::SSLConfig#verify_callback= httpclient/ssl_config.rb /^ def verify_callback=/
::HTTPClient::SSLConfig#verify_depth httpclient/ssl_config.rb /^ attr_reader :verify_depth/
::HTTPClient::SSLConfig#verify_depth= httpclient/ssl_config.rb /^ def verify_depth=/
::HTTPClient::SSLConfig#verify_mode httpclient/ssl_config.rb /^ attr_reader :verify_mode/
::HTTPClient::SSLConfig#verify_mode= httpclient/ssl_config.rb /^ def verify_mode=/
::HTTPClient::SSLSocketWrap httpclient/session.rb /^ class SSLSocketWrap/
::HTTPClient::SSLSocketWrap#<< httpclient/session.rb /^ def <</
::HTTPClient::SSLSocketWrap#HTTPClient::SSLSocketWrap.new httpclient/session.rb /^ def initialize/
::HTTPClient::SSLSocketWrap#check_mask httpclient/session.rb /^ def check_mask/
::HTTPClient::SSLSocketWrap#close httpclient/session.rb /^ def close/
::HTTPClient::SSLSocketWrap#closed? httpclient/session.rb /^ def closed?/
::HTTPClient::SSLSocketWrap#create_openssl_socket httpclient/session.rb /^ def create_openssl_socket/
::HTTPClient::SSLSocketWrap#debug httpclient/session.rb /^ def debug/
::HTTPClient::SSLSocketWrap#eof? httpclient/session.rb /^ def eof?/
::HTTPClient::SSLSocketWrap#flush httpclient/session.rb /^ def flush/
::HTTPClient::SSLSocketWrap#gets httpclient/session.rb /^ def gets/
::HTTPClient::SSLSocketWrap#peer_cert httpclient/session.rb /^ def peer_cert/
::HTTPClient::SSLSocketWrap#post_connection_check httpclient/session.rb /^ def post_connection_check/
::HTTPClient::SSLSocketWrap#read httpclient/session.rb /^ def read/
::HTTPClient::SSLSocketWrap#readpartial httpclient/session.rb /^ def readpartial/
::HTTPClient::SSLSocketWrap#ssl_connect httpclient/session.rb /^ def ssl_connect/
::HTTPClient::SSLSocketWrap#sync httpclient/session.rb /^ def sync/
::HTTPClient::SSLSocketWrap#sync= httpclient/session.rb /^ def sync=/
::HTTPClient::SSPINegotiateAuth httpclient/auth.rb /^ class SSPINegotiateAuth/
::HTTPClient::SSPINegotiateAuth#HTTPClient::SSPINegotiateAuth.new httpclient/auth.rb /^ def initialize/
::HTTPClient::SSPINegotiateAuth#challenge httpclient/auth.rb /^ def challenge/
::HTTPClient::SSPINegotiateAuth#get httpclient/auth.rb /^ def get/
::HTTPClient::SSPINegotiateAuth#reset_challenge httpclient/auth.rb /^ def reset_challenge/
::HTTPClient::SSPINegotiateAuth#scheme httpclient/auth.rb /^ attr_reader :scheme/
::HTTPClient::SSPINegotiateAuth#set httpclient/auth.rb /^ def set/
::HTTPClient::SendTimeoutError httpclient.rb /^ class SendTimeoutError/
::HTTPClient::Session httpclient.rb /^ class Session/
::HTTPClient::Session httpclient/session.rb /^ class Session/
::HTTPClient::Session#HTTPClient::Session.new httpclient/session.rb /^ def initialize/
::HTTPClient::Session#close httpclient/session.rb /^ def close/
::HTTPClient::Session#closed? httpclient/session.rb /^ def closed?/
::HTTPClient::Session#connect httpclient/session.rb /^ def connect/
::HTTPClient::Session#connect_retry httpclient/session.rb /^ attr_accessor :connect_retry/
::HTTPClient::Session#connect_ssl_proxy httpclient/session.rb /^ def connect_ssl_proxy/
::HTTPClient::Session#connect_timeout httpclient/session.rb /^ attr_accessor :connect_timeout/
::HTTPClient::Session#create_socket httpclient/session.rb /^ def create_socket/
::HTTPClient::Session#create_ssl_socket httpclient/session.rb /^ def create_ssl_socket/
::HTTPClient::Session#debug_dev httpclient/session.rb /^ attr_accessor :debug_dev/
::HTTPClient::Session#dest httpclient/session.rb /^ attr_reader :dest/
::HTTPClient::Session#eof? httpclient/session.rb /^ def eof?/
::HTTPClient::Session#get_body httpclient/session.rb /^ def get_body/
::HTTPClient::Session#get_header httpclient/session.rb /^ def get_header/
::HTTPClient::Session#parse_header httpclient/session.rb /^ def parse_header/
::HTTPClient::Session#parse_keepalive_header httpclient/session.rb /^ def parse_keepalive_header/
::HTTPClient::Session#protocol_retry_count httpclient/session.rb /^ attr_accessor :protocol_retry_count/
::HTTPClient::Session#proxy httpclient/session.rb /^ attr_accessor :proxy/
::HTTPClient::Session#query httpclient/session.rb /^ def query/
::HTTPClient::Session#read_block_size httpclient/session.rb /^ attr_accessor :read_block_size/
::HTTPClient::Session#read_body_chunked httpclient/session.rb /^ def read_body_chunked/
::HTTPClient::Session#read_body_length httpclient/session.rb /^ def read_body_length/
::HTTPClient::Session#read_body_rest httpclient/session.rb /^ def read_body_rest/
::HTTPClient::Session#read_header httpclient/session.rb /^ def read_header/
::HTTPClient::Session#receive_timeout httpclient/session.rb /^ attr_accessor :receive_timeout/
::HTTPClient::Session#requested_version httpclient/session.rb /^ attr_accessor :requested_version/
::HTTPClient::Session#send_timeout httpclient/session.rb /^ attr_accessor :send_timeout/
::HTTPClient::Session#set_header httpclient/session.rb /^ def set_header/
::HTTPClient::Session#socket_sync httpclient/session.rb /^ attr_accessor :socket_sync/
::HTTPClient::Session#ssl_config httpclient/session.rb /^ attr_accessor :ssl_config/
::HTTPClient::Session#ssl_peer_cert httpclient/session.rb /^ attr_reader :ssl_peer_cert/
::HTTPClient::Session#test_loopback_http_response httpclient/session.rb /^ attr_accessor :test_loopback_http_response/
::HTTPClient::SessionManager httpclient/session.rb /^ class SessionManager/
::HTTPClient::SessionManager#HTTPClient::SessionManager.new httpclient/session.rb /^ def initialize/
::HTTPClient::SessionManager#add_cached_session httpclient/session.rb /^ def add_cached_session/
::HTTPClient::SessionManager#agent_name httpclient/session.rb /^ attr_accessor :agent_name/
::HTTPClient::SessionManager#chunk_size httpclient/session.rb /^ attr_accessor :chunk_size/
::HTTPClient::SessionManager#close httpclient/session.rb /^ def close/
::HTTPClient::SessionManager#close_all httpclient/session.rb /^ def close_all/
::HTTPClient::SessionManager#connect_retry httpclient/session.rb /^ attr_accessor :connect_retry/
::HTTPClient::SessionManager#connect_timeout httpclient/session.rb /^ attr_accessor :connect_timeout/
::HTTPClient::SessionManager#debug_dev httpclient/session.rb /^ attr_accessor :debug_dev/
::HTTPClient::SessionManager#from httpclient/session.rb /^ attr_accessor :from/
::HTTPClient::SessionManager#get_cached_session httpclient/session.rb /^ def get_cached_session/
::HTTPClient::SessionManager#keep httpclient/session.rb /^ def keep/
::HTTPClient::SessionManager#open httpclient/session.rb /^ def open/
::HTTPClient::SessionManager#protocol_retry_count httpclient/session.rb /^ attr_accessor :protocol_retry_count/
::HTTPClient::SessionManager#protocol_version httpclient/session.rb /^ attr_accessor :protocol_version/
::HTTPClient::SessionManager#proxy= httpclient/session.rb /^ def proxy=/
::HTTPClient::SessionManager#query httpclient/session.rb /^ def query/
::HTTPClient::SessionManager#read_block_size httpclient/session.rb /^ attr_accessor :read_block_size/
::HTTPClient::SessionManager#receive_timeout httpclient/session.rb /^ attr_accessor :receive_timeout/
::HTTPClient::SessionManager#reset httpclient/session.rb /^ def reset/
::HTTPClient::SessionManager#reset_all httpclient/session.rb /^ def reset_all/
::HTTPClient::SessionManager#send_timeout httpclient/session.rb /^ attr_accessor :send_timeout/
::HTTPClient::SessionManager#socket_sync httpclient/session.rb /^ attr_accessor :socket_sync/
::HTTPClient::SessionManager#ssl_config httpclient/session.rb /^ attr_accessor :ssl_config/
::HTTPClient::SessionManager#test_loopback_http_response httpclient/session.rb /^ attr_reader :test_loopback_http_response/
::HTTPClient::Site httpclient/session.rb /^ class Site/
::HTTPClient::Site#== httpclient/session.rb /^ def ==/
::HTTPClient::Site#HTTPClient::Site.new httpclient/session.rb /^ def initialize/
::HTTPClient::Site#addr httpclient/session.rb /^ def addr/
::HTTPClient::Site#eql? httpclient/session.rb /^ def eql?/
::HTTPClient::Site#hash httpclient/session.rb /^ def hash/
::HTTPClient::Site#host httpclient/session.rb /^ attr_reader :host/
::HTTPClient::Site#inspect httpclient/session.rb /^ def inspect/
::HTTPClient::Site#match httpclient/session.rb /^ def match/
::HTTPClient::Site#port httpclient/session.rb /^ attr_reader :port/
::HTTPClient::Site#scheme httpclient/session.rb /^ attr_accessor :scheme/
::HTTPClient::Site#to_s httpclient/session.rb /^ def to_s/
::HTTPClient::SocketWrap httpclient/session.rb /^ module SocketWrap/
::HTTPClient::SocketWrap#<< httpclient/session.rb /^ def <</
::HTTPClient::SocketWrap#HTTPClient::SocketWrap.new httpclient/session.rb /^ def initialize/
::HTTPClient::SocketWrap#close httpclient/session.rb /^ def close/
::HTTPClient::SocketWrap#closed? httpclient/session.rb /^ def closed?/
::HTTPClient::SocketWrap#eof? httpclient/session.rb /^ def eof?/
::HTTPClient::SocketWrap#flush httpclient/session.rb /^ def flush/
::HTTPClient::SocketWrap#gets httpclient/session.rb /^ def gets/
::HTTPClient::SocketWrap#read httpclient/session.rb /^ def read/
::HTTPClient::SocketWrap#readpartial httpclient/session.rb /^ def readpartial/
::HTTPClient::SocketWrap#sync httpclient/session.rb /^ def sync/
::HTTPClient::SocketWrap#sync= httpclient/session.rb /^ def sync=/
::HTTPClient::Timeout httpclient/timeout.rb /^ module Timeout/
::HTTPClient::Timeout#timeout httpclient/timeout.rb /^ def timeout/
::HTTPClient::TimeoutError httpclient.rb /^ class TimeoutError/
::HTTPClient::TimeoutScheduler httpclient/timeout.rb /^ class TimeoutScheduler/
::HTTPClient::TimeoutScheduler#HTTPClient::TimeoutScheduler.new httpclient/timeout.rb /^ def initialize/
::HTTPClient::TimeoutScheduler#cancel httpclient/timeout.rb /^ def cancel/
::HTTPClient::TimeoutScheduler#register httpclient/timeout.rb /^ def register/
::HTTPClient::TimeoutScheduler#start_timer_thread httpclient/timeout.rb /^ def start_timer_thread/
::HTTPClient::TimeoutScheduler::Period httpclient/timeout.rb /^ class Period/
::HTTPClient::TimeoutScheduler::Period#HTTPClient::TimeoutScheduler::Period.new httpclient/timeout.rb /^ def initialize/
::HTTPClient::TimeoutScheduler::Period#cancel httpclient/timeout.rb /^ def cancel/
::HTTPClient::TimeoutScheduler::Period#raise httpclient/timeout.rb /^ def raise/
::HTTPClient::TimeoutScheduler::Period#thread httpclient/timeout.rb /^ attr_reader :thread, :time/
::HTTPClient::TimeoutScheduler::Period#time httpclient/timeout.rb /^ attr_reader :thread, :time/
::HTTPClient::Util httpclient/util.rb /^ module Util/
::HTTPClient::Util#hash_find_value httpclient/util.rb /^ def hash_find_value/
::HTTPClient::Util#keyword_argument httpclient/util.rb /^ def keyword_argument/
::HTTPClient::Util#uri_dirname httpclient/util.rb /^ def uri_dirname/
::HTTPClient::Util#uri_part_of httpclient/util.rb /^ def uri_part_of/
::HTTPClient::Util#urify httpclient/util.rb /^ def urify/
::HTTPClient::WWWAuth httpclient/auth.rb /^ class WWWAuth/
::HTTPClient::WWWAuth#HTTPClient::WWWAuth.new httpclient/auth.rb /^ def initialize/
::HTTPClient::WWWAuth#basic_auth httpclient/auth.rb /^ attr_reader :basic_auth/
::HTTPClient::WWWAuth#digest_auth httpclient/auth.rb /^ attr_reader :digest_auth/
::HTTPClient::WWWAuth#filter_request httpclient/auth.rb /^ def filter_request/
::HTTPClient::WWWAuth#filter_response httpclient/auth.rb /^ def filter_response/
::HTTPClient::WWWAuth#negotiate_auth httpclient/auth.rb /^ attr_reader :negotiate_auth/
::HTTPClient::WWWAuth#reset_challenge httpclient/auth.rb /^ def reset_challenge/
::HTTPClient::WWWAuth#set_auth httpclient/auth.rb /^ def set_auth/
::WebAgent httpclient/cookie.rb /^class WebAgent/
::WebAgent::Cookie httpclient/cookie.rb /^ class Cookie/
::WebAgent::Cookie#WebAgent::Cookie.new httpclient/cookie.rb /^ def initialize/
::WebAgent::Cookie#discard httpclient/cookie.rb /^ attr_writer :use, :secure, :discard, :domain_orig, :path_orig, :override/
::WebAgent::Cookie#discard? httpclient/cookie.rb /^ def discard?/
::WebAgent::Cookie#domain httpclient/cookie.rb /^ attr_accessor :domain, :path/
::WebAgent::Cookie#domain_orig httpclient/cookie.rb /^ attr_writer :use, :secure, :discard, :domain_orig, :path_orig, :override/
::WebAgent::Cookie#domain_orig? httpclient/cookie.rb /^ def domain_orig?/
::WebAgent::Cookie#expires httpclient/cookie.rb /^ attr_accessor :expires ## for Netscape Cookie/
::WebAgent::Cookie#flag httpclient/cookie.rb /^ def flag/
::WebAgent::Cookie#join_quotedstr httpclient/cookie.rb /^ def join_quotedstr/
::WebAgent::Cookie#match? httpclient/cookie.rb /^ def match?/
::WebAgent::Cookie#name httpclient/cookie.rb /^ attr_accessor :name, :value/
::WebAgent::Cookie#normalize_cookie_value httpclient/cookie.rb /^ def normalize_cookie_value/
::WebAgent::Cookie#override httpclient/cookie.rb /^ attr_writer :use, :secure, :discard, :domain_orig, :path_orig, :override/
::WebAgent::Cookie#override? httpclient/cookie.rb /^ def override?/
::WebAgent::Cookie#parse httpclient/cookie.rb /^ def parse/
::WebAgent::Cookie#path httpclient/cookie.rb /^ attr_accessor :domain, :path/
::WebAgent::Cookie#path_orig httpclient/cookie.rb /^ attr_writer :use, :secure, :discard, :domain_orig, :path_orig, :override/
::WebAgent::Cookie#path_orig? httpclient/cookie.rb /^ def path_orig?/
::WebAgent::Cookie#secure httpclient/cookie.rb /^ attr_writer :use, :secure, :discard, :domain_orig, :path_orig, :override/
::WebAgent::Cookie#secure? httpclient/cookie.rb /^ def secure?/
::WebAgent::Cookie#set_flag httpclient/cookie.rb /^ def set_flag/
::WebAgent::Cookie#url httpclient/cookie.rb /^ attr_accessor :url/
::WebAgent::Cookie#use httpclient/cookie.rb /^ attr_writer :use, :secure, :discard, :domain_orig, :path_orig, :override/
::WebAgent::Cookie#use? httpclient/cookie.rb /^ def use?/
::WebAgent::Cookie#value httpclient/cookie.rb /^ attr_accessor :name, :value/
::WebAgent::CookieManager httpclient/cookie.rb /^ class CookieManager/
::WebAgent::CookieManager#WebAgent::CookieManager.new httpclient/cookie.rb /^ def initialize/
::WebAgent::CookieManager#accept_domains httpclient/cookie.rb /^ attr_accessor :accept_domains, :reject_domains/
::WebAgent::CookieManager#add httpclient/cookie.rb /^ def add/
::WebAgent::CookieManager#check_cookie_accept_domain httpclient/cookie.rb /^ def check_cookie_accept_domain/
::WebAgent::CookieManager#check_expired_cookies httpclient/cookie.rb /^ def check_expired_cookies/
::WebAgent::CookieManager#cookie_error httpclient/cookie.rb /^ def cookie_error/
::WebAgent::CookieManager#cookies httpclient/cookie.rb /^ attr_reader :cookies/
::WebAgent::CookieManager#cookies= httpclient/cookie.rb /^ def cookies=/
::WebAgent::CookieManager#cookies_file httpclient/cookie.rb /^ attr_accessor :cookies_file/
::WebAgent::CookieManager#find httpclient/cookie.rb /^ def find/
::WebAgent::CookieManager#find_cookie_info httpclient/cookie.rb /^ def find_cookie_info/
::WebAgent::CookieManager#load_cookies httpclient/cookie.rb /^ def load_cookies/
::WebAgent::CookieManager#make_cookie_str httpclient/cookie.rb /^ def make_cookie_str/
::WebAgent::CookieManager#netscape_rule httpclient/cookie.rb /^ attr_accessor :netscape_rule/
::WebAgent::CookieManager#parse httpclient/cookie.rb /^ def parse/
::WebAgent::CookieManager#reject_domains httpclient/cookie.rb /^ attr_accessor :accept_domains, :reject_domains/
::WebAgent::CookieManager#save_all_cookies httpclient/cookie.rb /^ def save_all_cookies/
::WebAgent::CookieManager#save_cookies httpclient/cookie.rb /^ def save_cookies/
::WebAgent::CookieManager::Error httpclient/cookie.rb /^ class Error/
::WebAgent::CookieManager::ErrorOverrideOK httpclient/cookie.rb /^ class ErrorOverrideOK/
::WebAgent::CookieManager::SpecialError httpclient/cookie.rb /^ class SpecialError/
::WebAgent::CookieUtils httpclient/cookie.rb /^ module CookieUtils/
::WebAgent::CookieUtils#domain_match httpclient/cookie.rb /^ def domain_match/
::WebAgent::CookieUtils#head_match? httpclient/cookie.rb /^ def head_match?/
::WebAgent::CookieUtils#tail_match? httpclient/cookie.rb /^ def tail_match?/
::WebAgent::CookieUtils#total_dot_num httpclient/cookie.rb /^ def total_dot_num/
<< httpclient/session.rb /^ def <</
<< httpclient/session.rb /^ def <</
<< httpclient/session.rb /^ def <</
<< httpclient/session.rb /^ def <</
== httpclient/session.rb /^ def ==/
AuthFilterBase httpclient/auth.rb /^ class AuthFilterBase/
BadResponseError httpclient.rb /^ class BadResponseError/
BasicAuth httpclient/auth.rb /^ class BasicAuth/
Body httpclient/http.rb /^ class Body/
ConfigurationError httpclient.rb /^ class ConfigurationError/
ConnectTimeoutError httpclient.rb /^ class ConnectTimeoutError/
Connection httpclient/connection.rb /^ class Connection/
Cookie httpclient/cookie.rb /^ class Cookie/
CookieManager httpclient/cookie.rb /^ class CookieManager/
CookieUtils httpclient/cookie.rb /^ module CookieUtils/
DebugSocket httpclient/session.rb /^ module DebugSocket/
DigestAuth httpclient/auth.rb /^ class DigestAuth/
Error httpclient/cookie.rb /^ class Error/
ErrorOverrideOK httpclient/cookie.rb /^ class ErrorOverrideOK/
HTTP httpclient/http.rb /^module HTTP/
HTTP::Message.new httpclient/http.rb /^ def initialize/
HTTP::Message::Body.new httpclient/http.rb /^ def initialize/
HTTP::Message::Body::Parts.new httpclient/http.rb /^ def initialize/
HTTP::Message::Headers.new httpclient/http.rb /^ def initialize/
HTTPClient httpclient.rb /^class HTTPClient/
HTTPClient httpclient/auth.rb /^class HTTPClient/
HTTPClient httpclient/connection.rb /^class HTTPClient/
HTTPClient httpclient/session.rb /^class HTTPClient/
HTTPClient httpclient/ssl_config.rb /^class HTTPClient/
HTTPClient httpclient/timeout.rb /^class HTTPClient/
HTTPClient httpclient/util.rb /^class HTTPClient/
HTTPClient.new httpclient.rb /^ def initialize/
HTTPClient::BadResponseError.new httpclient.rb /^ def initialize/
HTTPClient::BasicAuth.new httpclient/auth.rb /^ def initialize/
HTTPClient::Connection.new httpclient/connection.rb /^ def initialize/
HTTPClient::DigestAuth.new httpclient/auth.rb /^ def initialize/
HTTPClient::LoopBackSocket.new httpclient/session.rb /^ def initialize/
HTTPClient::NegotiateAuth.new httpclient/auth.rb /^ def initialize/
HTTPClient::ProxyAuth.new httpclient/auth.rb /^ def initialize/
HTTPClient::SSLConfig.new httpclient/ssl_config.rb /^ def initialize/
HTTPClient::SSLSocketWrap.new httpclient/session.rb /^ def initialize/
HTTPClient::SSPINegotiateAuth.new httpclient/auth.rb /^ def initialize/
HTTPClient::Session.new httpclient/session.rb /^ def initialize/
HTTPClient::SessionManager.new httpclient/session.rb /^ def initialize/
HTTPClient::Site.new httpclient/session.rb /^ def initialize/
HTTPClient::SocketWrap.new httpclient/session.rb /^ def initialize/
HTTPClient::TimeoutScheduler.new httpclient/timeout.rb /^ def initialize/
HTTPClient::TimeoutScheduler::Period.new httpclient/timeout.rb /^ def initialize/
HTTPClient::WWWAuth.new httpclient/auth.rb /^ def initialize/
Headers httpclient/http.rb /^ class Headers/
KeepAliveDisconnected httpclient.rb /^ class KeepAliveDisconnected/
LoopBackSocket httpclient/session.rb /^ class LoopBackSocket/
Message httpclient/http.rb /^ class Message/
NegotiateAuth httpclient/auth.rb /^ class NegotiateAuth/
Parts httpclient/http.rb /^ class Parts/
Period httpclient/timeout.rb /^ class Period/
ProxyAuth httpclient/auth.rb /^ class ProxyAuth/
ReceiveTimeoutError httpclient.rb /^ class ReceiveTimeoutError/
RetryableResponse httpclient.rb /^ class RetryableResponse/
SSLConfig httpclient/ssl_config.rb /^ class SSLConfig/
SSLSocketWrap httpclient/session.rb /^ class SSLSocketWrap/
SSPINegotiateAuth httpclient/auth.rb /^ class SSPINegotiateAuth/
SendTimeoutError httpclient.rb /^ class SendTimeoutError/
Session httpclient.rb /^ class Session/
Session httpclient/session.rb /^ class Session/
SessionManager httpclient/session.rb /^ class SessionManager/
Site httpclient/session.rb /^ class Site/
SocketWrap httpclient/session.rb /^ module SocketWrap/
SpecialError httpclient/cookie.rb /^ class SpecialError/
Status httpclient/http.rb /^ module Status/
Timeout httpclient/timeout.rb /^ module Timeout/
TimeoutError httpclient.rb /^ class TimeoutError/
TimeoutScheduler httpclient/timeout.rb /^ class TimeoutScheduler/
Util httpclient/util.rb /^ module Util/
WWWAuth httpclient/auth.rb /^ class WWWAuth/
WebAgent httpclient/cookie.rb /^class WebAgent/
WebAgent::Cookie.new httpclient/cookie.rb /^ def initialize/
WebAgent::CookieManager.new httpclient/cookie.rb /^ def initialize/
[] httpclient/http.rb /^ def []/
[]= httpclient/http.rb /^ def []=/
accept_domains httpclient/cookie.rb /^ attr_accessor :accept_domains, :reject_domains/
add httpclient/cookie.rb /^ def add/
add httpclient/http.rb /^ def add/
add httpclient/http.rb /^ def add/
add_cached_session httpclient/session.rb /^ def add_cached_session/
addr httpclient/session.rb /^ def addr/
agent_name httpclient/session.rb /^ attr_accessor :agent_name/
all httpclient/http.rb /^ def all/
async_thread httpclient/connection.rb /^ attr_accessor :async_thread/
attr_proxy httpclient.rb /^ def attr_proxy/
basic_auth httpclient/auth.rb /^ attr_reader :basic_auth/
basic_auth httpclient/auth.rb /^ attr_reader :basic_auth/
body httpclient/http.rb /^ attr_reader :body/
body= httpclient/http.rb /^ def body=/
body_charset httpclient/http.rb /^ attr_accessor :body_charset # :nodoc:/
body_date httpclient/http.rb /^ attr_accessor :body_date # :nodoc:/
body_size httpclient/http.rb /^ attr_reader :body_size/
body_size= httpclient/http.rb /^ def body_size=/
body_type httpclient/http.rb /^ attr_accessor :body_type # :nodoc:/
build_query_multipart_str httpclient/http.rb /^ def build_query_multipart_str/
calc_cred httpclient/auth.rb /^ def calc_cred/
cancel httpclient/timeout.rb /^ def cancel/
cancel httpclient/timeout.rb /^ def cancel/
cert_store httpclient/ssl_config.rb /^ attr_reader :cert_store # don't use if you don't know what it is./
cert_store= httpclient/ssl_config.rb /^ def cert_store=/
challenge httpclient/auth.rb /^ def challenge/
challenge httpclient/auth.rb /^ def challenge/
challenge httpclient/auth.rb /^ def challenge/
challenge httpclient/auth.rb /^ def challenge/
change_notify httpclient/ssl_config.rb /^ def change_notify/
charset_label httpclient/http.rb /^ def charset_label/
check_cookie_accept_domain httpclient/cookie.rb /^ def check_cookie_accept_domain/
check_expired_cookies httpclient/cookie.rb /^ def check_expired_cookies/
check_mask httpclient/session.rb /^ def check_mask/
chunk_size httpclient/http.rb /^ attr_accessor :chunk_size/
chunk_size httpclient/session.rb /^ attr_accessor :chunk_size/
chunked httpclient/http.rb /^ attr_accessor :chunked/
ciphers httpclient/ssl_config.rb /^ attr_reader :ciphers/
ciphers= httpclient/ssl_config.rb /^ def ciphers=/
clear_cert_store httpclient/ssl_config.rb /^ def clear_cert_store/
client_ca httpclient/ssl_config.rb /^ attr_reader :client_ca # :nodoc:/
client_ca= httpclient/ssl_config.rb /^ def client_ca=/
client_cert httpclient/ssl_config.rb /^ attr_reader :client_cert/
client_cert= httpclient/ssl_config.rb /^ def client_cert=/
client_key httpclient/ssl_config.rb /^ attr_reader :client_key/
client_key= httpclient/ssl_config.rb /^ def client_key=/
close httpclient/session.rb /^ def close/
close httpclient/session.rb /^ def close/
close httpclient/session.rb /^ def close/
close httpclient/session.rb /^ def close/
close httpclient/session.rb /^ def close/
close_all httpclient/session.rb /^ def close_all/
closed? httpclient/session.rb /^ def closed?/
closed? httpclient/session.rb /^ def closed?/
closed? httpclient/session.rb /^ def closed?/
code httpclient/http.rb /^ alias code/
connect httpclient/session.rb /^ def connect/
connect_retry httpclient/session.rb /^ attr_accessor :connect_retry/
connect_retry httpclient/session.rb /^ attr_accessor :connect_retry/
connect_ssl_proxy httpclient/session.rb /^ def connect_ssl_proxy/
connect_timeout httpclient/session.rb /^ attr_accessor :connect_timeout/
connect_timeout httpclient/session.rb /^ attr_accessor :connect_timeout/
content httpclient/http.rb /^ def content/
content httpclient/http.rb /^ def content/
contenttype httpclient/http.rb /^ def contenttype/
contenttype httpclient/http.rb /^ def contenttype/
contenttype= httpclient/http.rb /^ def contenttype=/
contenttype= httpclient/http.rb /^ def contenttype=/
cookie_error httpclient/cookie.rb /^ def cookie_error/
cookie_manager httpclient.rb /^ attr_accessor :cookie_manager/
cookies httpclient/cookie.rb /^ attr_reader :cookies/
cookies= httpclient/cookie.rb /^ def cookies=/
cookies_file httpclient/cookie.rb /^ attr_accessor :cookies_file/
create_boundary httpclient.rb /^ def create_boundary/
create_openssl_socket httpclient/session.rb /^ def create_openssl_socket/
create_query_part_str httpclient/http.rb /^ def create_query_part_str/
create_query_uri httpclient/http.rb /^ def create_query_uri/
create_request httpclient.rb /^ def create_request/
create_socket httpclient/session.rb /^ def create_socket/
create_ssl_socket httpclient/session.rb /^ def create_ssl_socket/
debug httpclient/session.rb /^ def debug/
debug httpclient/session.rb /^ def debug/
debug_dev httpclient.rb /^ def debug_dev/
debug_dev httpclient/session.rb /^ attr_accessor :debug_dev/
debug_dev httpclient/session.rb /^ attr_accessor :debug_dev/
debug_dev= httpclient.rb /^ def debug_dev=/
debug_dev= httpclient/session.rb /^ def debug_dev=/
default_redirect_uri_callback httpclient.rb /^ def default_redirect_uri_callback/
default_verify_callback httpclient/ssl_config.rb /^ def default_verify_callback/
delete httpclient.rb /^ def delete/
delete httpclient/http.rb /^ def delete/
delete_async httpclient.rb /^ def delete_async/
dest httpclient/session.rb /^ attr_reader :dest/
digest_auth httpclient/auth.rb /^ attr_reader :digest_auth/
discard httpclient/cookie.rb /^ attr_writer :use, :secure, :discard, :domain_orig, :path_orig, :override/
discard? httpclient/cookie.rb /^ def discard?/
do_get_block httpclient.rb /^ def do_get_block/
do_get_header httpclient.rb /^ def do_get_header/
do_get_stream httpclient.rb /^ def do_get_stream/
do_request httpclient.rb /^ def do_request/
do_request_async httpclient.rb /^ def do_request_async/
domain httpclient/cookie.rb /^ attr_accessor :domain, :path/
domain_match httpclient/cookie.rb /^ def domain_match/
domain_orig httpclient/cookie.rb /^ attr_writer :use, :secure, :discard, :domain_orig, :path_orig, :override/
domain_orig? httpclient/cookie.rb /^ def domain_orig?/
dump httpclient/http.rb /^ def dump/
dump httpclient/http.rb /^ def dump/
dump httpclient/http.rb /^ def dump/
dump_chunk httpclient/http.rb /^ def dump_chunk/
dump_chunk_size httpclient/http.rb /^ def dump_chunk_size/
dump_chunked httpclient/http.rb /^ def dump_chunked/
dump_chunks httpclient/http.rb /^ def dump_chunks/
dump_dummy_request_response httpclient.rb /^ def dump_dummy_request_response/
dump_last_chunk httpclient/http.rb /^ def dump_last_chunk/
eof? httpclient/session.rb /^ def eof?/
eof? httpclient/session.rb /^ def eof?/
eof? httpclient/session.rb /^ def eof?/
eql? httpclient/session.rb /^ def eql?/
escape httpclient/http.rb /^ def escape/
escape_query httpclient/http.rb /^ def escape_query/
expires httpclient/cookie.rb /^ attr_accessor :expires ## for Netscape Cookie/
file? httpclient/http.rb /^ def file?/
file_in_form_data? httpclient.rb /^ def file_in_form_data?/
filter_request httpclient/auth.rb /^ def filter_request/
filter_request httpclient/auth.rb /^ def filter_request/
filter_response httpclient/auth.rb /^ def filter_response/
filter_response httpclient/auth.rb /^ def filter_response/
find httpclient/cookie.rb /^ def find/
find_cookie_info httpclient/cookie.rb /^ def find_cookie_info/
finished? httpclient/connection.rb /^ def finished?/
flag httpclient/cookie.rb /^ def flag/
flush httpclient/session.rb /^ def flush/
flush httpclient/session.rb /^ def flush/
follow_redirect httpclient.rb /^ def follow_redirect/
follow_redirect_count httpclient.rb /^ attr_accessor :follow_redirect_count/
from httpclient/session.rb /^ attr_accessor :from/
get httpclient.rb /^ def get/
get httpclient/auth.rb /^ def get/
get httpclient/auth.rb /^ def get/
get httpclient/auth.rb /^ def get/
get httpclient/auth.rb /^ def get/
get httpclient/http.rb /^ def get/
get_async httpclient.rb /^ def get_async/
get_body httpclient/session.rb /^ def get_body/
get_cached_session httpclient/session.rb /^ def get_cached_session/
get_content httpclient.rb /^ def get_content/
get_header httpclient/session.rb /^ def get_header/
get_mime_type_func httpclient/http.rb /^ alias get_mime_type_func/
getenv httpclient.rb /^ def getenv/
gets httpclient/session.rb /^ def gets/
gets httpclient/session.rb /^ def gets/
gets httpclient/session.rb /^ def gets/
hash httpclient/session.rb /^ def hash/
hash_find_value httpclient/util.rb /^ def hash_find_value/
head httpclient.rb /^ def head/
head_async httpclient.rb /^ def head_async/
head_match? httpclient/cookie.rb /^ def head_match?/
header httpclient/http.rb /^ attr_accessor :header/
host httpclient/session.rb /^ attr_reader :host/
http_version httpclient/http.rb /^ attr_accessor :http_version/
https? httpclient.rb /^ def https?/
init_connect_request httpclient/http.rb /^ def init_connect_request/
init_request httpclient/http.rb /^ def init_request/
init_request httpclient/http.rb /^ def init_request/
init_response httpclient/http.rb /^ def init_response/
init_response httpclient/http.rb /^ def init_response/
inspect httpclient/session.rb /^ def inspect/
internal_mime_type httpclient/http.rb /^ def internal_mime_type/
join httpclient/connection.rb /^ def join/
join_quotedstr httpclient/cookie.rb /^ def join_quotedstr/
keep httpclient/session.rb /^ def keep/
keep_alive_enabled? httpclient/http.rb /^ def keep_alive_enabled?/
keyword_argument httpclient/util.rb /^ def keyword_argument/
load_cacerts httpclient/ssl_config.rb /^ def load_cacerts/
load_cookies httpclient/cookie.rb /^ def load_cookies/
load_environment httpclient.rb /^ def load_environment/
make_cookie_str httpclient/cookie.rb /^ def make_cookie_str/
match httpclient/session.rb /^ def match/
match? httpclient/cookie.rb /^ def match?/
mime_type httpclient/http.rb /^ def mime_type/
mime_type_handler httpclient/http.rb /^ def mime_type_handler/
mime_type_handler= httpclient/http.rb /^ def mime_type_handler=/
multiparam_query? httpclient/http.rb /^ def multiparam_query?/
name httpclient/cookie.rb /^ attr_accessor :name, :value/
negotiate_auth httpclient/auth.rb /^ attr_reader :negotiate_auth/
negotiate_auth httpclient/auth.rb /^ attr_reader :negotiate_auth/
netscape_rule httpclient/cookie.rb /^ attr_accessor :netscape_rule/
new_connect_request httpclient/http.rb /^ def new_connect_request/
new_request httpclient/http.rb /^ def new_request/
new_response httpclient/http.rb /^ def new_response/
no_proxy httpclient.rb /^ def no_proxy/
no_proxy= httpclient.rb /^ def no_proxy=/
no_proxy? httpclient.rb /^ def no_proxy?/
normalize_cookie_value httpclient/cookie.rb /^ def normalize_cookie_value/
ntlm_opt httpclient/auth.rb /^ attr_reader :ntlm_opt/
open httpclient/session.rb /^ def open/
options httpclient.rb /^ def options/
options httpclient/ssl_config.rb /^ attr_reader :options/
options= httpclient/ssl_config.rb /^ def options=/
options_async httpclient.rb /^ def options_async/
override httpclient/cookie.rb /^ attr_writer :use, :secure, :discard, :domain_orig, :path_orig, :override/
override? httpclient/cookie.rb /^ def override?/
override_header httpclient.rb /^ def override_header/
params_from_file httpclient/http.rb /^ def params_from_file/
parse httpclient/cookie.rb /^ def parse/
parse httpclient/cookie.rb /^ def parse/
parse_authentication_header httpclient/auth.rb /^ def parse_authentication_header/
parse_challenge_header httpclient/auth.rb /^ def parse_challenge_header/
parse_challenge_param httpclient/auth.rb /^ def parse_challenge_param/
parse_header httpclient/session.rb /^ def parse_header/
parse_keepalive_header httpclient/session.rb /^ def parse_keepalive_header/
parts httpclient/http.rb /^ def parts/
path httpclient/cookie.rb /^ attr_accessor :domain, :path/
path_orig httpclient/cookie.rb /^ attr_writer :use, :secure, :discard, :domain_orig, :path_orig, :override/
path_orig? httpclient/cookie.rb /^ def path_orig?/
peer_cert httpclient/http.rb /^ attr_accessor :peer_cert/
peer_cert httpclient/session.rb /^ def peer_cert/
pop httpclient/connection.rb /^ def pop/
port httpclient/session.rb /^ attr_reader :port/
post httpclient.rb /^ def post/
post_async httpclient.rb /^ def post_async/
post_connection_check httpclient/session.rb /^ def post_connection_check/
post_connection_check httpclient/ssl_config.rb /^ def post_connection_check/
post_content httpclient.rb /^ def post_content/
propfind httpclient.rb /^ def propfind/
propfind_async httpclient.rb /^ def propfind_async/
proppatch httpclient.rb /^ def proppatch/
proppatch_async httpclient.rb /^ def proppatch_async/
protect_keep_alive_disconnected httpclient.rb /^ def protect_keep_alive_disconnected/
protocol_retry_count httpclient/session.rb /^ attr_accessor :protocol_retry_count/
protocol_retry_count httpclient/session.rb /^ attr_accessor :protocol_retry_count/
protocol_version httpclient/session.rb /^ attr_accessor :protocol_version/
proxy httpclient.rb /^ def proxy/
proxy httpclient/session.rb /^ attr_accessor :proxy/
proxy= httpclient.rb /^ def proxy=/
proxy= httpclient/session.rb /^ def proxy=/
proxy_auth httpclient.rb /^ attr_reader :proxy_auth/
push httpclient/connection.rb /^ def push/
put httpclient.rb /^ def put/
put_async httpclient.rb /^ def put_async/
query httpclient/session.rb /^ def query/
query httpclient/session.rb /^ def query/
raise httpclient/timeout.rb /^ def raise/
read httpclient/session.rb /^ def read/
read httpclient/session.rb /^ def read/
read httpclient/session.rb /^ def read/
read_block_size httpclient/session.rb /^ attr_accessor :read_block_size/
read_block_size httpclient/session.rb /^ attr_accessor :read_block_size/
read_body_chunked httpclient/session.rb /^ def read_body_chunked/
read_body_length httpclient/session.rb /^ def read_body_length/
read_body_rest httpclient/session.rb /^ def read_body_rest/
read_header httpclient/session.rb /^ def read_header/
readpartial httpclient/session.rb /^ def readpartial/
readpartial httpclient/session.rb /^ def readpartial/
readpartial httpclient/session.rb /^ def readpartial/
reason httpclient/http.rb /^ def reason/
reason= httpclient/http.rb /^ def reason=/
reason_phrase httpclient/http.rb /^ attr_accessor :reason_phrase/
receive_timeout httpclient/session.rb /^ attr_accessor :receive_timeout/
receive_timeout httpclient/session.rb /^ attr_accessor :receive_timeout/
redirect? httpclient/http.rb /^ def self.redirect?/
redirect_uri_callback= httpclient.rb /^ def redirect_uri_callback=/
register httpclient/timeout.rb /^ def register/
reject_domains httpclient/cookie.rb /^ attr_accessor :accept_domains, :reject_domains/
remember_pos httpclient/http.rb /^ def remember_pos/
request httpclient.rb /^ def request/
request_async httpclient.rb /^ def request_async/
request_filter httpclient.rb /^ attr_reader :request_filter/
request_line httpclient/http.rb /^ def request_line/
request_method httpclient/http.rb /^ attr_reader :request_method/
request_query httpclient/http.rb /^ attr_accessor :request_query/
request_uri httpclient/http.rb /^ attr_accessor :request_uri/
request_via_proxy httpclient/http.rb /^ attr_accessor :request_via_proxy/
requested_version httpclient/session.rb /^ attr_accessor :requested_version/
res httpclient.rb /^ attr_reader :res/
reset httpclient.rb /^ def reset/
reset httpclient/session.rb /^ def reset/
reset_all httpclient.rb /^ def reset_all/
reset_all httpclient/session.rb /^ def reset_all/
reset_challenge httpclient/auth.rb /^ def reset_challenge/
reset_challenge httpclient/auth.rb /^ def reset_challenge/
reset_challenge httpclient/auth.rb /^ def reset_challenge/
reset_challenge httpclient/auth.rb /^ def reset_challenge/
reset_challenge httpclient/auth.rb /^ def reset_challenge/
reset_challenge httpclient/auth.rb /^ def reset_challenge/
reset_pos httpclient/http.rb /^ def reset_pos/
response_status_line httpclient/http.rb /^ def response_status_line/
sample_verify_callback httpclient/ssl_config.rb /^ def sample_verify_callback/
save_all_cookies httpclient/cookie.rb /^ def save_all_cookies/
save_cookie_store httpclient.rb /^ def save_cookie_store/
save_cookies httpclient/cookie.rb /^ def save_cookies/
scheme httpclient/auth.rb /^ attr_reader :scheme/
scheme httpclient/auth.rb /^ attr_reader :scheme/
scheme httpclient/auth.rb /^ attr_reader :scheme/
scheme httpclient/auth.rb /^ attr_reader :scheme/
scheme httpclient/session.rb /^ attr_accessor :scheme/
secure httpclient/cookie.rb /^ attr_writer :use, :secure, :discard, :domain_orig, :path_orig, :override/
secure? httpclient/cookie.rb /^ def secure?/
send_timeout httpclient/session.rb /^ attr_accessor :send_timeout/
send_timeout httpclient/session.rb /^ attr_accessor :send_timeout/
set httpclient/auth.rb /^ def set/
set httpclient/auth.rb /^ def set/
set httpclient/auth.rb /^ def set/
set httpclient/auth.rb /^ def set/
set httpclient/http.rb /^ def set/
set_auth httpclient.rb /^ def set_auth/
set_auth httpclient/auth.rb /^ def set_auth/
set_auth httpclient/auth.rb /^ def set_auth/
set_basic_auth httpclient.rb /^ def set_basic_auth/
set_client_cert_file httpclient/ssl_config.rb /^ def set_client_cert_file/
set_content httpclient/http.rb /^ def set_content/
set_context httpclient/ssl_config.rb /^ def set_context/
set_cookie_store httpclient.rb /^ def set_cookie_store/
set_crl httpclient/ssl_config.rb /^ def set_crl/
set_flag httpclient/cookie.rb /^ def set_flag/
set_header httpclient/http.rb /^ def set_header/
set_header httpclient/session.rb /^ def set_header/
set_mime_type_func httpclient/http.rb /^ alias set_mime_type_func/
set_proxy_auth httpclient.rb /^ def set_proxy_auth/
set_request_header httpclient/http.rb /^ def set_request_header/
set_response_header httpclient/http.rb /^ def set_response_header/
set_trust_ca httpclient/ssl_config.rb /^ def set_trust_ca/
size httpclient/http.rb /^ attr_reader :size/
size httpclient/http.rb /^ attr_reader :size/
socket_sync httpclient/session.rb /^ attr_accessor :socket_sync/
socket_sync httpclient/session.rb /^ attr_accessor :socket_sync/
ssl_config httpclient.rb /^ attr_reader :ssl_config/
ssl_config httpclient/session.rb /^ attr_accessor :ssl_config/
ssl_config httpclient/session.rb /^ attr_accessor :ssl_config/
ssl_connect httpclient/session.rb /^ def ssl_connect/
ssl_peer_cert httpclient/session.rb /^ attr_reader :ssl_peer_cert/
sspi_negotiate_auth httpclient/auth.rb /^ attr_reader :sspi_negotiate_auth/
start_timer_thread httpclient/timeout.rb /^ def start_timer_thread/
status httpclient/http.rb /^ def status/
status= httpclient/http.rb /^ def status=/
status_code httpclient/http.rb /^ attr_reader :status_code/
status_code httpclient/http.rb /^ alias status_code/
status_code= httpclient/http.rb /^ def status_code=/
strict_redirect_uri_callback httpclient.rb /^ def strict_redirect_uri_callback/
successful? httpclient/http.rb /^ def self.successful?/
sync httpclient/session.rb /^ def sync/
sync httpclient/session.rb /^ def sync/
sync= httpclient/session.rb /^ def sync=/
sync= httpclient/session.rb /^ def sync=/
tail_match? httpclient/cookie.rb /^ def tail_match?/
test_loopback_http_response httpclient/session.rb /^ attr_accessor :test_loopback_http_response/
test_loopback_http_response httpclient/session.rb /^ attr_reader :test_loopback_http_response/
test_loopback_response httpclient.rb /^ attr_reader :test_loopback_response/
thread httpclient/timeout.rb /^ attr_reader :thread, :time/
time httpclient/timeout.rb /^ attr_reader :thread, :time/
timeout httpclient/ssl_config.rb /^ attr_reader :timeout/
timeout httpclient/timeout.rb /^ def timeout/
timeout= httpclient/ssl_config.rb /^ def timeout=/
timeout_scheduler httpclient/timeout.rb /^ def timeout_scheduler/
to_s httpclient/session.rb /^ def to_s/
total_dot_num httpclient/cookie.rb /^ def total_dot_num/
trace httpclient.rb /^ def trace/
trace_async httpclient.rb /^ def trace_async/
uri_dirname httpclient/util.rb /^ def uri_dirname/
uri_part_of httpclient/util.rb /^ def uri_part_of/
urify httpclient/util.rb /^ def urify/
url httpclient/cookie.rb /^ attr_accessor :url/
use httpclient/cookie.rb /^ attr_writer :use, :secure, :discard, :domain_orig, :path_orig, :override/
use? httpclient/cookie.rb /^ def use?/
value httpclient/cookie.rb /^ attr_accessor :name, :value/
verify_callback httpclient/ssl_config.rb /^ attr_reader :verify_callback/
verify_callback= httpclient/ssl_config.rb /^ def verify_callback=/
verify_depth httpclient/ssl_config.rb /^ attr_reader :verify_depth/
verify_depth= httpclient/ssl_config.rb /^ def verify_depth=/
verify_mode httpclient/ssl_config.rb /^ attr_reader :verify_mode/
verify_mode= httpclient/ssl_config.rb /^ def verify_mode=/
version httpclient/http.rb /^ def version/
version= httpclient/http.rb /^ def version=/
www_auth httpclient.rb /^ attr_reader :www_auth/

View file

@ -0,0 +1,2 @@
Manifest
pkg

View file

@ -0,0 +1,73 @@
Problem
=======
- Images are too large because they are not optimized
- Users & your bandwidth is wasted for useless metadata
- local image optimization requires tons of programs / libaries / knowledge
Solution
========
- *LOSSLESS* size reduction (10-97% size reduction) in the cloud
- optmizes all images(jpg+png+[gif]) from a given folder
Install
=======
install ruby + rubygems
sudo gem install smusher
Usage
=====
Optimize a single image or a whole folder in the cloud.
converting gif-s to png-s:
- called with a folder gif-s will not be converted
- called on a single .gif or wildcard, image(s) will be converted if optimizeable
Usage:
smusher /apps/x/public/images [options]
smusher /apps/x/public/images/x.png [options]
smusher /apps/x/public/images/*.png [options]
Options are:
-q, --quiet no output
-c, --convert-gifs convert all .gif`s in the given folder
--service PunyPng use PunyPng for image optimizing, instead of SmushIt
-v, --version display current version
Protection
==========
Any image that returns a failure code, is larger than before,
or is empty will not be saved.
Example
======
smusher /apps/ts/public/images
smushing /apps/rs/public/images/social/facebook_icon.png
2887 -> 132 = 4%
smushing /apps/rs/public/images/social/myspace_icon.png
3136 -> 282 = 8%
smushing /apps/rs/public/images/dvd/dvd_1.png
5045 -> 4 = 0%
reverted!
...
TODO
====
- only optimize 'new' images -> save time when doing on each deploy
- convert gifs to png, even if the new size is the same, for consistency (atm only those which get smaller are converted)
ALTERNATIVES
============
If you want to lossless reduce images and minify css + js, try [reduce](http://github.com/grosser/reduce).
Authors
======
###Contributors
- [retr0h](http://geminstallthat.wordpress.com/)
[Michael Grosser](http://pragmatig.wordpress.com)
grosser.michael@gmail.com
Hereby placed under public domain, do what you want, just do not hold me accountable...

31
vendor/gems/gems/smusher-0.4.2/Rakefile vendored Normal file
View file

@ -0,0 +1,31 @@
desc "Run all specs in spec directory"
task :default do |t|
require 'spec'
options = "--colour --format progress --loadby --reverse"
files = FileList['spec/**/*_spec.rb']
system("spec #{options} #{files}")
end
begin
require 'jeweler'
project_name = 'smusher'
Jeweler::Tasks.new do |gem|
gem.name = project_name
gem.summary = "Automatic Lossless Reduction Of All Your Images"
gem.email = "grosser.michael@gmail.com"
gem.homepage = "http://github.com/grosser/#{project_name}"
gem.authors = ["Michael Grosser"]
%w[rake json httpclient].each{|d| gem.add_dependency d}
gem.rubyforge_project = 'smusher'
end
# fake task so that rubyforge:release works
task :rdoc do
`mkdir rdoc`
`echo documentation is at http://github.com/grosser/#{project_name} > rdoc/README.rdoc`
end
Jeweler::RubyforgeTasks.new
rescue LoadError
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
end

View file

@ -0,0 +1 @@
0.4.2

39
vendor/gems/gems/smusher-0.4.2/bin/smusher vendored Executable file
View file

@ -0,0 +1,39 @@
#!/usr/bin/env ruby
require 'rubygems'
require 'optparse'
require 'smusher'
options = {}
OptionParser.new do |opts|
opts.banner = <<BANNER
Optimize a single image or a whole folder in the cloud.
gif`s:
- called with a folder gif`s will not be optimized
- called on a singe .gif, it will be optimized if it is optimizeable
Usage:
smusher /apps/x/public/images [options]
smusher /apps/x/public/images/x.png [options]
smusher /apps/x/public/images/*.png [options]
Options are:
BANNER
opts.on("-q", "--quiet","no output") { options[:quiet]=true }
opts.on("--service S", String, "use service: PunyPng or default SmushIt") {|x| options[:service]=x }
opts.on("-c", "--convert-gifs","convert all .gif`s in the given folder") { options[:convert_gifs]=true }
opts.on("-h", "--help","Show this.") { puts opts; exit }
opts.on('-v', '--version','Show Version'){ puts Smusher::VERSION; exit}
end.parse!
path = ARGV.first
if path.to_s.empty? or not File.exist?(path)
puts "Usage instructions: autotest --help"
exit
end
if File.directory?(path)
Smusher.optimize_images_in_folder(path,options)
else
Smusher.optimize_image(ARGV,options)
end

View file

@ -0,0 +1,97 @@
require 'rubygems'
require 'rake'
require 'json'
require 'open-uri'
require 'httpclient'
require 'smusher/smush_it'
require 'smusher/puny_png'
module Smusher
extend self
MINIMUM_IMAGE_SIZE = 20#byte
VERSION = File.read( File.join(File.dirname(__FILE__),'..','VERSION') ).strip
# optimize the given image
# converts gif to png, if size is lower
# can be called with a file-path or an array of files-paths
def optimize_image(files,options={})
service = options[:service] || 'SmushIt'
service = eval(service)
files.each do |file|
check_options(options)
puts "THIS FILE IS EMPTY!!! #{file}" and return if size(file).zero?
success = false
with_logging(file,options[:quiet]) do
write_optimized_data(file, service)
success = true
end
if success and service.converts_gif_to_png?
gif = /\.gif$/
`mv #{file} #{file.sub(gif,'.png')}` if file =~ gif
end
end
end
# fetch all jpg/png images from given folder and optimize them
def optimize_images_in_folder(folder, options={})
check_options(options)
images_in_folder(folder, options[:convert_gifs]).each do |file|
optimize_image(file, options)
end
end
private
def check_options(options)
known_options = [:convert_gifs, :quiet, :service]
if options.detect{|k,v| not known_options.include?(k)}
raise "Known options: #{known_options*' '}"
end
end
def write_optimized_data(file, service)
optimized = service.optimized_image_data_for(file)
raise "Error: got larger" if size(file) < optimized.size
raise "Error: empty file downloaded" if optimized.size < MINIMUM_IMAGE_SIZE
raise "cannot be optimized further" if size(file) == optimized.size
File.open(file,'w') {|f| f.write optimized}
end
def sanitize_folder(folder)
folder.sub(%r[/$],'')#remove tailing slash
end
def images_in_folder(folder,with_gifs=false)
folder = sanitize_folder(folder)
images = %w[png jpg jpeg JPG]
images << 'gif' if with_gifs
images.map! {|ext| "#{folder}/**/*.#{ext}"}
FileList[*images]
end
def size(file)
File.exist?(file) ? File.size(file) : 0
end
def with_logging(file,quiet)
puts "smushing #{file}" unless quiet
before = size(file)
begin; yield; rescue; puts $! unless quiet; end
after = size(file)
unless quiet
result = "#{(100*after)/before}%"
puts "#{before} -> #{after}".ljust(40) + " = #{result}"
puts ''
end
end
end

View file

@ -0,0 +1,17 @@
module Smusher
class PunyPng
def self.converts_gif_to_png?
false
end
def self.optimized_image_data_for(file)
url = 'http://www.gracepointafterfive.com/punypng_staging/api/optimize'
response = HTTPClient.post url, { 'img' => File.new(file), 'key' => 'd1b72ab4813da6b69e1d6018303ac690c014599d'}
response = JSON.parse(response.body.content)
raise "puny_png: #{response['error']}" if response['error']
image_url = response['optimized_url']
raise "no optimized_url found" unless image_url
open(image_url) { |source| source.read() }
end
end
end

View file

@ -0,0 +1,22 @@
module Smusher
class SmushIt
def self.converts_gif_to_png?
true
end
def self.optimized_image_data_for(file)
#I leave these urls here, just in case it stops working again...
# url = "http://smush.it/ws.php" # original, redirects to somewhere else..
# url = "http://developer.yahoo.com/yslow/smushit/ws.php" # official but does not work
# url = "http://smushit.com/ysmush.it/ws.php" # used at the new page but does not hande uploads
# url = "http://smushit.eperf.vip.ac4.yahoo.com/ysmush.it/ws.php" # used at the new page but does not hande uploads
url = 'http://ws1.adq.ac4.yahoo.com/ysmush.it/ws.php'
response = HTTPClient.post url, { 'files[]' => File.new(file)}
response = JSON.parse(response.body.content)
raise "smush.it: #{response['error']}" if response['error']
image_url = response['dest']
raise "no dest path found" unless image_url
open(image_url) { |source| source.read() }
end
end
end

View file

@ -0,0 +1,79 @@
# Generated by jeweler
# DO NOT EDIT THIS FILE
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
# -*- encoding: utf-8 -*-
Gem::Specification.new do |s|
s.name = %q{smusher}
s.version = "0.4.2"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Michael Grosser"]
s.date = %q{2009-10-09}
s.default_executable = %q{smusher}
s.email = %q{grosser.michael@gmail.com}
s.executables = ["smusher"]
s.extra_rdoc_files = [
"README.markdown"
]
s.files = [
".gitignore",
"README.markdown",
"Rakefile",
"VERSION",
"bin/smusher",
"lib/smusher.rb",
"lib/smusher/puny_png.rb",
"lib/smusher/smush_it.rb",
"rdoc/README.rdoc",
"smusher.gemspec",
"spec/empty/.gitignore",
"spec/images/ad.gif",
"spec/images/add.png",
"spec/images/drink_empty.png",
"spec/images/logo.gif",
"spec/images/people.jpg",
"spec/images/water.JPG",
"spec/images/woman.jpeg",
"spec/out/ad.gif",
"spec/out/people.jpg",
"spec/reduced/add.png",
"spec/reduced/add_puny.png",
"spec/reduced/fam.png",
"spec/smusher/puny_png_spec.rb",
"spec/smusher/smush_it_spec.rb",
"spec/smusher_spec.rb",
"spec/spec_helper.rb"
]
s.homepage = %q{http://github.com/grosser/smusher}
s.rdoc_options = ["--charset=UTF-8"]
s.require_paths = ["lib"]
s.rubyforge_project = %q{smusher}
s.rubygems_version = %q{1.3.5}
s.summary = %q{Automatic Lossless Reduction Of All Your Images}
s.test_files = [
"spec/smusher/smush_it_spec.rb",
"spec/smusher/puny_png_spec.rb",
"spec/spec_helper.rb",
"spec/smusher_spec.rb"
]
if s.respond_to? :specification_version then
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = 3
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<rake>, [">= 0"])
s.add_runtime_dependency(%q<json>, [">= 0"])
s.add_runtime_dependency(%q<httpclient>, [">= 0"])
else
s.add_dependency(%q<rake>, [">= 0"])
s.add_dependency(%q<json>, [">= 0"])
s.add_dependency(%q<httpclient>, [">= 0"])
end
else
s.add_dependency(%q<rake>, [">= 0"])
s.add_dependency(%q<json>, [">= 0"])
s.add_dependency(%q<httpclient>, [">= 0"])
end
end

View file

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 945 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

View file

@ -0,0 +1,12 @@
require 'spec/spec_helper'
describe Smusher::PunyPng do
describe :optimized_image_data_for do
it "loads the reduced image" do
original = File.join(ROOT,'images','add.png')
reduced = File.read(File.join(ROOT, 'reduced', 'add_puny.png'))
received = Smusher::PunyPng.optimized_image_data_for(original)
received.should == reduced
end
end
end

View file

@ -0,0 +1,12 @@
require 'spec/spec_helper'
describe Smusher::SmushIt do
describe :optimized_image_data_for do
it "loads the reduced image" do
original = File.join(ROOT,'images','add.png')
reduced = File.open(File.join(ROOT,'reduced','add.png')).read
received = Smusher::SmushIt.optimized_image_data_for(original)
received.should == reduced
end
end
end

View file

@ -0,0 +1,181 @@
require 'spec/spec_helper'
describe :smusher do
def copy(image_name)
FileUtils.cp(File.join(ROOT,'images',image_name), @out)
end
def size
File.size(@file)
end
before do
#prepare output folder
@out = File.join(ROOT,'out')
FileUtils.rm_r @out, :force=>true
FileUtils.mkdir @out
copy 'people.jpg'
copy 'ad.gif'
@file = File.join(@out,'people.jpg')
end
describe :optimize_image do
it "stores the image in an reduced size" do
original_size = size
Smusher.optimize_image(@file)
size.should < original_size
end
it "does not append newline" do
copy 'add.png'
file = File.join(@out, 'add.png')
Smusher.optimize_image file
# pure File.read() will omit trailing \n
File.readlines(file).last.split('').last.should_not == "\n"
end
it "can be called with an array of files" do
original_size = size
Smusher.optimize_image([@file])
size.should < original_size
end
it "it does nothing if size stayed the same" do
original_size = size
Smusher::SmushIt.should_receive(:optimized_image_data_for).and_return File.read(@file)
Smusher.optimize_image(@file)
size.should == original_size
end
it "does not save images whoes size got larger" do
original_size = size
Smusher::SmushIt.should_receive(:optimized_image_data_for).and_return File.read(@file)*2
Smusher.optimize_image(@file)
size.should == original_size
end
it "does not save images if their size is error-sugesting-small" do
original_size = size
Smusher::SmushIt.should_receive(:optimized_image_data_for).and_return 'oops...'
Smusher.optimize_image(@file)
size.should == original_size
end
describe "gif handling" do
before do
copy 'logo.gif'
@file = File.join(@out,'logo.gif')
@file_png = File.join(@out,'logo.png')
end
it "converts gifs to png even if they have the same size" do
pending
copy 'ad.gif'
file = File.join(@out,'ad.gif')
original_size = size
Smusher.optimize_image(file)
File.size(File.join(@out,'ad.png')).should == original_size
end
it "stores converted .gifs in .png files" do
Smusher.optimize_image(@file)
File.exist?(@file).should == false
File.exist?(@file_png).should == true
end
it "does not rename gifs, if optimizing failed" do
Smusher::SmushIt.should_receive(:optimized_image_data_for).and_return File.read(@file)
Smusher.optimize_image(@file)
File.exist?(@file).should == true
File.exist?(@file_png).should == false
end
end
describe 'options' do
it "does not produce output when :quiet is given" do
$stdout.should_receive(:write).never
Smusher.optimize_image(@file,:quiet=>true)
end
it "raises when an unknown option was given" do
lambda{Smusher.optimize_image(@file,:q=>true)}.should raise_error
end
end
end
describe :optimize_images_in_folder do
before do
FileUtils.rm @file
@files = []
%w[add.png drink_empty.png].each do |image_name|
copy image_name
@files << File.join(@out,image_name)
end
@before = @files.map {|f|File.size(f)}
end
it "optimizes all images" do
Smusher.optimize_images_in_folder(@out)
new_sizes = @files.map {|f|File.size(f)}
new_sizes.size.times {|i| new_sizes[i].should < @before[i]}
end
it "does not convert gifs" do
copy 'logo.gif'
Smusher.optimize_images_in_folder(@out)
File.exist?(File.join(@out,'logo.png')).should == false
end
it "converts gifs to png when option was given" do
copy 'logo.gif'
Smusher.optimize_images_in_folder(@out,:convert_gifs=>true)
File.exist?(File.join(@out,'logo.png')).should == true
end
end
describe :sanitize_folder do
it "cleans a folders trailing slash" do
Smusher.send(:sanitize_folder,"xx/").should == 'xx'
end
it "does not clean if there is no trailing slash" do
Smusher.send(:sanitize_folder,"/x/ccx").should == '/x/ccx'
end
end
describe :images_in_folder do
it "finds all non-gif images" do
folder = File.join(ROOT,'images')
all = %w[add.png drink_empty.png people.jpg water.JPG woman.jpeg].map{|name|"#{folder}/#{name}"}
result = Smusher.send(:images_in_folder,folder)
(all+result).uniq.size.should == all.size
end
it "finds nothing if folder is empty" do
Smusher.send(:images_in_folder,File.join(ROOT,'empty')).should == []
end
end
describe :size do
it "find the size of a file" do
Smusher.send(:size,@file).should == File.size(@file)
end
it "and_return 0 for missing file" do
Smusher.send(:size,File.join(ROOT,'xxxx','dssdfsddfs')).should == 0
end
end
describe :logging do
it "yields" do
val = 0
Smusher.send(:with_logging,@file,false) {val = 1}
val.should == 1
end
end
it "has a VERSION" do
Smusher::VERSION.should =~ /^\d+\.\d+\.\d+$/
end
end

View file

@ -0,0 +1,8 @@
# ---- requirements
require 'rubygems'
require 'spec'
$LOAD_PATH << 'lib'
require 'smusher'
ROOT = File.expand_path(File.dirname(__FILE__))

View file

@ -0,0 +1,26 @@
# -*- encoding: utf-8 -*-
Gem::Specification.new do |s|
s.name = %q{httpclient}
s.version = "2.1.5.2"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["NAKAMURA, Hiroshi"]
s.date = %q{2009-06-24}
s.email = %q{nahi@ruby-lang.org}
s.files = ["lib/tags", "lib/http-access2", "lib/http-access2/http.rb", "lib/http-access2/cookie.rb", "lib/httpclient", "lib/httpclient/connection.rb", "lib/httpclient/cacert_sha1.p7s", "lib/httpclient/http.rb", "lib/httpclient/auth.rb", "lib/httpclient/util.rb", "lib/httpclient/session.rb", "lib/httpclient/ssl_config.rb", "lib/httpclient/timeout.rb", "lib/httpclient/cookie.rb", "lib/httpclient/cacert.p7s", "lib/httpclient.rb", "lib/http-access2.rb"]
s.homepage = %q{http://dev.ctor.org/httpclient}
s.require_paths = ["lib"]
s.rubygems_version = %q{1.3.5}
s.summary = %q{gives something like the functionality of libwww-perl (LWP) in Ruby}
if s.respond_to? :specification_version then
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = 2
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
else
end
else
end
end

View file

@ -0,0 +1,41 @@
# -*- encoding: utf-8 -*-
Gem::Specification.new do |s|
s.name = %q{smusher}
s.version = "0.4.2"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Michael Grosser"]
s.date = %q{2009-10-08}
s.default_executable = %q{smusher}
s.email = %q{grosser.michael@gmail.com}
s.executables = ["smusher"]
s.extra_rdoc_files = ["README.markdown"]
s.files = [".gitignore", "README.markdown", "Rakefile", "VERSION", "bin/smusher", "lib/smusher.rb", "lib/smusher/puny_png.rb", "lib/smusher/smush_it.rb", "rdoc/README.rdoc", "smusher.gemspec", "spec/empty/.gitignore", "spec/images/ad.gif", "spec/images/add.png", "spec/images/drink_empty.png", "spec/images/logo.gif", "spec/images/people.jpg", "spec/images/water.JPG", "spec/images/woman.jpeg", "spec/out/ad.gif", "spec/out/people.jpg", "spec/reduced/add.png", "spec/reduced/add_puny.png", "spec/reduced/fam.png", "spec/smusher/puny_png_spec.rb", "spec/smusher/smush_it_spec.rb", "spec/smusher_spec.rb", "spec/spec_helper.rb"]
s.homepage = %q{http://github.com/grosser/smusher}
s.rdoc_options = ["--charset=UTF-8"]
s.require_paths = ["lib"]
s.rubyforge_project = %q{smusher}
s.rubygems_version = %q{1.3.5}
s.summary = %q{Automatic Lossless Reduction Of All Your Images}
s.test_files = ["spec/smusher/smush_it_spec.rb", "spec/smusher/puny_png_spec.rb", "spec/spec_helper.rb", "spec/smusher_spec.rb"]
if s.respond_to? :specification_version then
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = 3
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<rake>, [">= 0"])
s.add_runtime_dependency(%q<json>, [">= 0"])
s.add_runtime_dependency(%q<httpclient>, [">= 0"])
else
s.add_dependency(%q<rake>, [">= 0"])
s.add_dependency(%q<json>, [">= 0"])
s.add_dependency(%q<httpclient>, [">= 0"])
end
else
s.add_dependency(%q<rake>, [">= 0"])
s.add_dependency(%q<json>, [">= 0"])
s.add_dependency(%q<httpclient>, [">= 0"])
end
end