#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ----------------------------------------------------------------------------------
# Copyleft (K) by Jose Rodriguez. This source is free (GPL)
# Partially based on John Nielsen ASPN recipe (http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/301740)
# Partially based on Alessandro Budai recipe (http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/456195)
# ----------------------------------------------------------------------------------
# ClientCookie to connection through a proxy using the CONNECT method, (useful for SSL)
# tested with python 2.4
import mechanize as ClientCookie
import urllib
import httplib
import socket
import base64
def split_proxy_URL(proxy):
if proxy is None:
return None, None, None
try:
if proxy[:7] != 'http://': # Ensures proxy string begins with 'http://'
proxy = 'http://' + proxy
except:
pass
proxy_username = proxy_password = None
urltype, r_type = urllib.splittype(proxy)
proxy, XXX = urllib.splithost(r_type)
if '@' in proxy:
proxy_username, proxy = proxy.split('@', 1)
if ':' in proxy_username:
proxy_username, proxy_password = proxy_username.split(':', 1)
return proxy, proxy_username, proxy_password
class ProxyHTTPConnection(httplib.HTTPConnection):
_ports = {'http' : 80, 'https' : 443}
def request(self, method, url, body=None, headers={}):
#request is called before connect, so can interpret url and get
#real host/port to be used to make CONNECT request to proxy
proto, rest = urllib.splittype(url)
if proto is None:
raise ValueError, "unknown URL type: %s" % url
host, rest = urllib.splithost(rest) # get host
host, port = urllib.splitport(host) #try to get port
#if port is not defined try to get from proto
if port is None:
try:
port = self._ports[proto]
except KeyError:
raise ValueError, "unknown protocol for: %s" % url
self._real_host = host
self._real_port = port
httplib.HTTPConnection.request(self, method, url, body, headers)
def connect(self):
httplib.HTTPConnection.connect(self)
self.send("CONNECT %s:%d HTTP/1.0\r\n" % (self._real_host, self._real_port))
if self.proxy_user is not None and self.proxy_passwd is not None:
cred = base64.encodestring("%s:%s" % (urllib.unquote(self.proxy_user), urllib.unquote(self.proxy_passwd))).strip()
self.send("Proxy-authorization: Basic %s\r\n" % cred)
self.send("User-Agent: Mozilla/5.0 (Compatible; libgmail-python)\r\n\r\n")
response = self.response_class(self.sock, strict=self.strict, method=self._method)
(version, code, message) = response._read_status()
#probably here we can handle auth requests...
if code != 200:
#proxy returned and error, abort connection, and raise exception
self.close()
raise socket.error, "Proxy connection failed: %d %s" % (code, message.strip())
#eat up header block from proxy....
while True:
line = response.fp.readline() #should not use directly fp probablu
if line == '\r\n': break
@classmethod
def new_auth(cls, proxy_host, proxy_user = None, proxy_passwd = None):
cls.proxy_host = proxy_host
cls.proxy_user = proxy_user
cls.proxy_passwd = proxy_passwd
return cls
class ProxyHTTPSConnection(ProxyHTTPConnection):
default_port = 443
def __init__(self, host, port = None, key_file = None, cert_file = None, strict = None):
ProxyHTTPConnection.__init__(self, host, port)
self.key_file = key_file
self.cert_file = cert_file
def connect(self):
ProxyHTTPConnection.connect(self)
#make the sock ssl-aware
ssl = socket.ssl(self.sock, self.key_file, self.cert_file)
self.sock = httplib.FakeSocket(self.sock, ssl)
class ConnectHTTPHandler(ClientCookie.HTTPHandler):
def __init__(self, proxy=None, debuglevel=0):
self.proxy, self.proxy_user, self.proxy_passwd = split_proxy_URL(proxy)
ClientCookie.HTTPHandler.__init__(self, debuglevel)
def do_open(self, http_class, req):
if self.proxy is not None:
req.set_proxy(self.proxy, 'http')
return ClientCookie.HTTPHandler.do_open(self, ProxyHTTPConnection.new_auth(self.proxy, self.proxy_user, self.proxy_passwd), req)
class ConnectHTTPSHandler(ClientCookie.HTTPSHandler):
def __init__(self, proxy=None, debuglevel=0):
self.proxy, self.proxy_user, self.proxy_passwd = split_proxy_URL(proxy)
ClientCookie.HTTPSHandler.__init__(self, debuglevel)
def do_open(self, http_class, req):
if self.proxy is not None:
req.set_proxy(self.proxy, 'https')
return ClientCookie.HTTPSHandler.do_open(self, ProxyHTTPSConnection.new_auth(self.proxy, self.proxy_user, self.proxy_passwd), req)
|