home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2012 January / maximum-cd-2012-01.iso / DiscContents / digsby_setup.exe / lib / urllib2.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2011-10-05  |  34.3 KB  |  1,140 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.6)
  3.  
  4. import base64
  5. import hashlib
  6. import httplib
  7. import mimetools
  8. import os
  9. import posixpath
  10. import random
  11. import re
  12. import socket
  13. import sys
  14. import time
  15. import urlparse
  16. import bisect
  17.  
  18. try:
  19.     from cStringIO import StringIO
  20. except ImportError:
  21.     from StringIO import StringIO
  22.  
  23. from urllib import unwrap, unquote, splittype, splithost, quote, addinfourl, splitport, splitattr, ftpwrapper, splituser, splitpasswd, splitvalue
  24. from urllib import localhost, url2pathname, getproxies
  25. __version__ = sys.version[:3]
  26. _opener = None
  27.  
  28. def urlopen(url, data = None, timeout = socket._GLOBAL_DEFAULT_TIMEOUT):
  29.     global _opener
  30.     if _opener is None:
  31.         _opener = build_opener()
  32.     
  33.     return _opener.open(url, data, timeout)
  34.  
  35.  
  36. def install_opener(opener):
  37.     global _opener
  38.     _opener = opener
  39.  
  40.  
  41. class URLError(IOError):
  42.     
  43.     def __init__(self, reason):
  44.         self.args = (reason,)
  45.         self.reason = reason
  46.  
  47.     
  48.     def __str__(self):
  49.         return '<urlopen error %s>' % self.reason
  50.  
  51.  
  52.  
  53. class HTTPError(URLError, addinfourl):
  54.     __super_init = addinfourl.__init__
  55.     
  56.     def __init__(self, url, code, msg, hdrs, fp):
  57.         self.code = code
  58.         self.msg = msg
  59.         self.hdrs = hdrs
  60.         self.fp = fp
  61.         self.filename = url
  62.         if fp is not None:
  63.             self._HTTPError__super_init(fp, hdrs, url, code)
  64.         
  65.  
  66.     
  67.     def __str__(self):
  68.         return 'HTTP Error %s: %s' % (self.code, self.msg)
  69.  
  70.  
  71. _cut_port_re = re.compile(':\\d+$')
  72.  
  73. def request_host(request):
  74.     url = request.get_full_url()
  75.     host = urlparse.urlparse(url)[1]
  76.     if host == '':
  77.         host = request.get_header('Host', '')
  78.     
  79.     host = _cut_port_re.sub('', host, 1)
  80.     return host.lower()
  81.  
  82.  
  83. class Request:
  84.     
  85.     def __init__(self, url, data = None, headers = { }, origin_req_host = None, unverifiable = False):
  86.         self._Request__original = unwrap(url)
  87.         self.type = None
  88.         self.host = None
  89.         self.port = None
  90.         self.data = data
  91.         self.headers = { }
  92.         for key, value in headers.items():
  93.             self.add_header(key, value)
  94.         
  95.         self.unredirected_hdrs = { }
  96.         if origin_req_host is None:
  97.             origin_req_host = request_host(self)
  98.         
  99.         self.origin_req_host = origin_req_host
  100.         self.unverifiable = unverifiable
  101.  
  102.     
  103.     def __getattr__(self, attr):
  104.         if attr[:12] == '_Request__r_':
  105.             name = attr[12:]
  106.             if hasattr(Request, 'get_' + name):
  107.                 getattr(self, 'get_' + name)()
  108.                 return getattr(self, attr)
  109.         
  110.         raise AttributeError, attr
  111.  
  112.     
  113.     def get_method(self):
  114.         if self.has_data():
  115.             return 'POST'
  116.         return 'GET'
  117.  
  118.     
  119.     def add_data(self, data):
  120.         self.data = data
  121.  
  122.     
  123.     def has_data(self):
  124.         return self.data is not None
  125.  
  126.     
  127.     def get_data(self):
  128.         return self.data
  129.  
  130.     
  131.     def get_full_url(self):
  132.         return self._Request__original
  133.  
  134.     
  135.     def get_type(self):
  136.         if self.type is None:
  137.             (self.type, self._Request__r_type) = splittype(self._Request__original)
  138.             if self.type is None:
  139.                 raise ValueError, 'unknown url type: %s' % self._Request__original
  140.             self.type is None
  141.         
  142.         return self.type
  143.  
  144.     
  145.     def get_host(self):
  146.         if self.host is None:
  147.             (self.host, self._Request__r_host) = splithost(self._Request__r_type)
  148.             if self.host:
  149.                 self.host = unquote(self.host)
  150.             
  151.         
  152.         return self.host
  153.  
  154.     
  155.     def get_selector(self):
  156.         return self._Request__r_host
  157.  
  158.     
  159.     def set_proxy(self, host, type):
  160.         self.host = host
  161.         self.type = type
  162.         self._Request__r_host = self._Request__original
  163.  
  164.     
  165.     def has_proxy(self):
  166.         return self._Request__r_host == self._Request__original
  167.  
  168.     
  169.     def get_origin_req_host(self):
  170.         return self.origin_req_host
  171.  
  172.     
  173.     def is_unverifiable(self):
  174.         return self.unverifiable
  175.  
  176.     
  177.     def add_header(self, key, val):
  178.         self.headers[key.capitalize()] = val
  179.  
  180.     
  181.     def add_unredirected_header(self, key, val):
  182.         self.unredirected_hdrs[key.capitalize()] = val
  183.  
  184.     
  185.     def has_header(self, header_name):
  186.         if not header_name in self.headers:
  187.             pass
  188.         return header_name in self.unredirected_hdrs
  189.  
  190.     
  191.     def get_header(self, header_name, default = None):
  192.         return self.headers.get(header_name, self.unredirected_hdrs.get(header_name, default))
  193.  
  194.     
  195.     def header_items(self):
  196.         hdrs = self.unredirected_hdrs.copy()
  197.         hdrs.update(self.headers)
  198.         return hdrs.items()
  199.  
  200.  
  201.  
  202. class OpenerDirector:
  203.     
  204.     def __init__(self):
  205.         client_version = 'Python-urllib/%s' % __version__
  206.         self.addheaders = [
  207.             ('User-agent', client_version)]
  208.         self.handlers = []
  209.         self.handle_open = { }
  210.         self.handle_error = { }
  211.         self.process_response = { }
  212.         self.process_request = { }
  213.  
  214.     
  215.     def add_handler(self, handler):
  216.         if not hasattr(handler, 'add_parent'):
  217.             raise TypeError('expected BaseHandler instance, got %r' % type(handler))
  218.         hasattr(handler, 'add_parent')
  219.         added = False
  220.         for meth in dir(handler):
  221.             if meth in ('redirect_request', 'do_open', 'proxy_open'):
  222.                 continue
  223.             
  224.             i = meth.find('_')
  225.             protocol = meth[:i]
  226.             condition = meth[i + 1:]
  227.             if condition.startswith('error'):
  228.                 j = condition.find('_') + i + 1
  229.                 kind = meth[j + 1:]
  230.                 
  231.                 try:
  232.                     kind = int(kind)
  233.                 except ValueError:
  234.                     pass
  235.  
  236.                 lookup = self.handle_error.get(protocol, { })
  237.                 self.handle_error[protocol] = lookup
  238.             elif condition == 'open':
  239.                 kind = protocol
  240.                 lookup = self.handle_open
  241.             elif condition == 'response':
  242.                 kind = protocol
  243.                 lookup = self.process_response
  244.             elif condition == 'request':
  245.                 kind = protocol
  246.                 lookup = self.process_request
  247.             
  248.             handlers = lookup.setdefault(kind, [])
  249.             if handlers:
  250.                 bisect.insort(handlers, handler)
  251.             else:
  252.                 handlers.append(handler)
  253.             added = True
  254.         
  255.         if added:
  256.             bisect.insort(self.handlers, handler)
  257.             handler.add_parent(self)
  258.         
  259.  
  260.     
  261.     def close(self):
  262.         pass
  263.  
  264.     
  265.     def _call_chain(self, chain, kind, meth_name, *args):
  266.         handlers = chain.get(kind, ())
  267.         for handler in handlers:
  268.             func = getattr(handler, meth_name)
  269.             result = func(*args)
  270.             if result is not None:
  271.                 return result
  272.         
  273.  
  274.     
  275.     def open(self, fullurl, data = None, timeout = socket._GLOBAL_DEFAULT_TIMEOUT):
  276.         if isinstance(fullurl, basestring):
  277.             req = Request(fullurl, data)
  278.         else:
  279.             req = fullurl
  280.             if data is not None:
  281.                 req.add_data(data)
  282.             
  283.         req.timeout = timeout
  284.         protocol = req.get_type()
  285.         meth_name = protocol + '_request'
  286.         for processor in self.process_request.get(protocol, []):
  287.             meth = getattr(processor, meth_name)
  288.             req = meth(req)
  289.         
  290.         response = self._open(req, data)
  291.         meth_name = protocol + '_response'
  292.         for processor in self.process_response.get(protocol, []):
  293.             meth = getattr(processor, meth_name)
  294.             response = meth(req, response)
  295.         
  296.         return response
  297.  
  298.     
  299.     def _open(self, req, data = None):
  300.         result = self._call_chain(self.handle_open, 'default', 'default_open', req)
  301.         if result:
  302.             return result
  303.         protocol = req.get_type()
  304.         result = self._call_chain(self.handle_open, protocol, protocol + '_open', req)
  305.         if result:
  306.             return result
  307.         return self._call_chain(self.handle_open, 'unknown', 'unknown_open', req)
  308.  
  309.     
  310.     def error(self, proto, *args):
  311.         if proto in ('http', 'https'):
  312.             dict = self.handle_error['http']
  313.             proto = args[2]
  314.             meth_name = 'http_error_%s' % proto
  315.             http_err = 1
  316.             orig_args = args
  317.         else:
  318.             dict = self.handle_error
  319.             meth_name = proto + '_error'
  320.             http_err = 0
  321.         args = (dict, proto, meth_name) + args
  322.         result = self._call_chain(*args)
  323.         if result:
  324.             return result
  325.         if http_err:
  326.             args = (dict, 'default', 'http_error_default') + orig_args
  327.             return self._call_chain(*args)
  328.  
  329.  
  330.  
  331. def build_opener(*handlers):
  332.     import types
  333.     
  334.     def isclass(obj):
  335.         if not isinstance(obj, types.ClassType):
  336.             pass
  337.         return hasattr(obj, '__bases__')
  338.  
  339.     opener = OpenerDirector()
  340.     default_classes = [
  341.         ProxyHandler,
  342.         UnknownHandler,
  343.         HTTPHandler,
  344.         HTTPDefaultErrorHandler,
  345.         HTTPRedirectHandler,
  346.         FTPHandler,
  347.         FileHandler,
  348.         HTTPErrorProcessor]
  349.     if hasattr(httplib, 'HTTPS'):
  350.         default_classes.append(HTTPSHandler)
  351.     
  352.     skip = set()
  353.     for klass in default_classes:
  354.         for check in handlers:
  355.             if isclass(check):
  356.                 if issubclass(check, klass):
  357.                     skip.add(klass)
  358.                 
  359.             issubclass(check, klass)
  360.             if isinstance(check, klass):
  361.                 skip.add(klass)
  362.                 continue
  363.         
  364.     
  365.     for klass in skip:
  366.         default_classes.remove(klass)
  367.     
  368.     for klass in default_classes:
  369.         opener.add_handler(klass())
  370.     
  371.     for h in handlers:
  372.         if isclass(h):
  373.             h = h()
  374.         
  375.         opener.add_handler(h)
  376.     
  377.     return opener
  378.  
  379.  
  380. class BaseHandler:
  381.     handler_order = 500
  382.     
  383.     def add_parent(self, parent):
  384.         self.parent = parent
  385.  
  386.     
  387.     def close(self):
  388.         pass
  389.  
  390.     
  391.     def __lt__(self, other):
  392.         if not hasattr(other, 'handler_order'):
  393.             return True
  394.         return self.handler_order < other.handler_order
  395.  
  396.  
  397.  
  398. class HTTPErrorProcessor(BaseHandler):
  399.     handler_order = 1000
  400.     
  401.     def http_response(self, request, response):
  402.         code = response.code
  403.         msg = response.msg
  404.         hdrs = response.info()
  405.         if code <= code:
  406.             pass
  407.         elif not code < 300:
  408.             response = self.parent.error('http', request, response, code, msg, hdrs)
  409.         
  410.         return response
  411.  
  412.     https_response = http_response
  413.  
  414.  
  415. class HTTPDefaultErrorHandler(BaseHandler):
  416.     
  417.     def http_error_default(self, req, fp, code, msg, hdrs):
  418.         raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
  419.  
  420.  
  421.  
  422. class HTTPRedirectHandler(BaseHandler):
  423.     max_repeats = 4
  424.     max_redirections = 10
  425.     
  426.     def redirect_request(self, req, fp, code, msg, headers, newurl):
  427.         m = req.get_method()
  428.         if (code in (301, 302, 303, 307) or m in ('GET', 'HEAD') or code in (301, 302, 303)) and m == 'POST':
  429.             newurl = newurl.replace(' ', '%20')
  430.             newheaders = dict((lambda .0: for k, v in .0:
  431. if k.lower() not in ('content-length', 'content-type'):
  432. (k, v)continue)(req.headers.items()))
  433.             return Request(newurl, headers = newheaders, origin_req_host = req.get_origin_req_host(), unverifiable = True)
  434.         raise HTTPError(req.get_full_url(), code, msg, headers, fp)
  435.  
  436.     
  437.     def http_error_302(self, req, fp, code, msg, headers):
  438.         if 'location' in headers:
  439.             newurl = headers.getheaders('location')[0]
  440.         elif 'uri' in headers:
  441.             newurl = headers.getheaders('uri')[0]
  442.         else:
  443.             return None
  444.         urlparts = ('location' in headers).urlparse(newurl)
  445.         if not urlparts.path:
  446.             urlparts = list(urlparts)
  447.             urlparts[2] = '/'
  448.         
  449.         newurl = urlparse.urlunparse(urlparts)
  450.         newurl = urlparse.urljoin(req.get_full_url(), newurl)
  451.         new = self.redirect_request(req, fp, code, msg, headers, newurl)
  452.         if new is None:
  453.             return None
  454.         visited[newurl] = visited.get(newurl, 0) + 1
  455.         fp.read()
  456.         fp.close()
  457.         return self.parent.open(new)
  458.  
  459.     http_error_301 = http_error_303 = http_error_307 = http_error_302
  460.     inf_msg = 'The HTTP server returned a redirect error that would lead to an infinite loop.\nThe last 30x error message was:\n'
  461.  
  462.  
  463. def _parse_proxy(proxy):
  464.     (scheme, r_scheme) = splittype(proxy)
  465.     if not r_scheme.startswith('/'):
  466.         scheme = None
  467.         authority = proxy
  468.     elif not r_scheme.startswith('//'):
  469.         raise ValueError('proxy URL with no authority: %r' % proxy)
  470.     
  471.     end = r_scheme.find('/', 2)
  472.     if end == -1:
  473.         end = None
  474.     
  475.     authority = r_scheme[2:end]
  476.     (userinfo, hostport) = splituser(authority)
  477.     if userinfo is not None:
  478.         (user, password) = splitpasswd(userinfo)
  479.     else:
  480.         user = None
  481.         password = None
  482.     return (scheme, user, password, hostport)
  483.  
  484.  
  485. class ProxyHandler(BaseHandler):
  486.     handler_order = 100
  487.     
  488.     def __init__(self, proxies = None):
  489.         if proxies is None:
  490.             proxies = getproxies()
  491.         
  492.         self.proxies = proxies
  493.         for type, url in proxies.items():
  494.             setattr(self, '%s_open' % type, (lambda r, proxy = url, type = type, meth = self.proxy_open: meth(r, proxy, type)))
  495.         
  496.  
  497.     
  498.     def proxy_open(self, req, proxy, type):
  499.         orig_type = req.get_type()
  500.         (proxy_type, user, password, hostport) = _parse_proxy(proxy)
  501.         if proxy_type is None:
  502.             proxy_type = orig_type
  503.         
  504.         if user and password:
  505.             user_pass = '%s:%s' % (unquote(user), unquote(password))
  506.             creds = base64.b64encode(user_pass).strip()
  507.             req.add_header('Proxy-authorization', 'Basic ' + creds)
  508.         
  509.         hostport = unquote(hostport)
  510.         req.set_proxy(hostport, proxy_type)
  511.         if orig_type == proxy_type:
  512.             return None
  513.         return self.parent.open(req)
  514.  
  515.  
  516.  
  517. class HTTPPasswordMgr:
  518.     
  519.     def __init__(self):
  520.         self.passwd = { }
  521.  
  522.     
  523.     def add_password(self, realm, uri, user, passwd):
  524.         if isinstance(uri, basestring):
  525.             uri = [
  526.                 uri]
  527.         
  528.         if realm not in self.passwd:
  529.             self.passwd[realm] = { }
  530.         
  531.         for default_port in (True, False):
  532.             reduced_uri = []([ self.reduce_uri(u, default_port) for u in uri ])
  533.             self.passwd[realm][reduced_uri] = (user, passwd)
  534.         
  535.  
  536.     
  537.     def find_user_password(self, realm, authuri):
  538.         domains = self.passwd.get(realm, { })
  539.         for default_port in (True, False):
  540.             reduced_authuri = self.reduce_uri(authuri, default_port)
  541.             for uris, authinfo in domains.iteritems():
  542.                 for uri in uris:
  543.                     if self.is_suburi(uri, reduced_authuri):
  544.                         return authinfo
  545.                 
  546.             
  547.         
  548.         return (None, None)
  549.  
  550.     
  551.     def reduce_uri(self, uri, default_port = True):
  552.         parts = urlparse.urlsplit(uri)
  553.         if parts[1]:
  554.             scheme = parts[0]
  555.             authority = parts[1]
  556.             if not parts[2]:
  557.                 pass
  558.             path = '/'
  559.         else:
  560.             scheme = None
  561.             authority = uri
  562.             path = '/'
  563.         (host, port) = splitport(authority)
  564.         if default_port and port is None and scheme is not None:
  565.             dport = {
  566.                 'http': 80,
  567.                 'https': 443 }.get(scheme)
  568.             if dport is not None:
  569.                 authority = '%s:%d' % (host, dport)
  570.             
  571.         
  572.         return (authority, path)
  573.  
  574.     
  575.     def is_suburi(self, base, test):
  576.         if base == test:
  577.             return True
  578.         if base[0] != test[0]:
  579.             return False
  580.         common = posixpath.commonprefix((base[1], test[1]))
  581.         if len(common) == len(base[1]):
  582.             return True
  583.         return False
  584.  
  585.  
  586.  
  587. class HTTPPasswordMgrWithDefaultRealm(HTTPPasswordMgr):
  588.     
  589.     def find_user_password(self, realm, authuri):
  590.         (user, password) = HTTPPasswordMgr.find_user_password(self, realm, authuri)
  591.         if user is not None:
  592.             return (user, password)
  593.         return HTTPPasswordMgr.find_user_password(self, None, authuri)
  594.  
  595.  
  596.  
  597. class AbstractBasicAuthHandler:
  598.     rx = re.compile('(?:.*,)*[ \t]*([^ \t]+)[ \t]+realm=(["\'])(.*?)\\2', re.I)
  599.     
  600.     def __init__(self, password_mgr = None):
  601.         if password_mgr is None:
  602.             password_mgr = HTTPPasswordMgr()
  603.         
  604.         self.passwd = password_mgr
  605.         self.add_password = self.passwd.add_password
  606.  
  607.     
  608.     def http_error_auth_reqed(self, authreq, host, req, headers):
  609.         authreq = headers.get(authreq, None)
  610.         if authreq:
  611.             mo = AbstractBasicAuthHandler.rx.search(authreq)
  612.             if mo:
  613.                 (scheme, quote, realm) = mo.groups()
  614.                 if scheme.lower() == 'basic':
  615.                     return self.retry_http_basic_auth(host, req, realm)
  616.             
  617.         
  618.  
  619.     
  620.     def retry_http_basic_auth(self, host, req, realm):
  621.         (user, pw) = self.passwd.find_user_password(realm, host)
  622.         if pw is not None:
  623.             raw = '%s:%s' % (user, pw)
  624.             auth = 'Basic %s' % base64.b64encode(raw).strip()
  625.             if req.headers.get(self.auth_header, None) == auth:
  626.                 return None
  627.             req.add_header(self.auth_header, auth)
  628.             return self.parent.open(req)
  629.         return None
  630.  
  631.  
  632.  
  633. class HTTPBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
  634.     auth_header = 'Authorization'
  635.     
  636.     def http_error_401(self, req, fp, code, msg, headers):
  637.         url = req.get_full_url()
  638.         return self.http_error_auth_reqed('www-authenticate', url, req, headers)
  639.  
  640.  
  641.  
  642. class ProxyBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
  643.     auth_header = 'Proxy-authorization'
  644.     
  645.     def http_error_407(self, req, fp, code, msg, headers):
  646.         authority = req.get_host()
  647.         return self.http_error_auth_reqed('proxy-authenticate', authority, req, headers)
  648.  
  649.  
  650.  
  651. def randombytes(n):
  652.     if os.path.exists('/dev/urandom'):
  653.         f = open('/dev/urandom')
  654.         s = f.read(n)
  655.         f.close()
  656.         return s
  657.     L = [ chr(random.randrange(0, 256)) for i in range(n) ]
  658.     return ''.join(L)
  659.  
  660.  
  661. class AbstractDigestAuthHandler:
  662.     
  663.     def __init__(self, passwd = None):
  664.         if passwd is None:
  665.             passwd = HTTPPasswordMgr()
  666.         
  667.         self.passwd = passwd
  668.         self.add_password = self.passwd.add_password
  669.         self.retried = 0
  670.         self.nonce_count = 0
  671.  
  672.     
  673.     def reset_retry_count(self):
  674.         self.retried = 0
  675.  
  676.     
  677.     def http_error_auth_reqed(self, auth_header, host, req, headers):
  678.         authreq = headers.get(auth_header, None)
  679.         if self.retried > 5:
  680.             raise HTTPError(req.get_full_url(), 401, 'digest auth failed', headers, None)
  681.         self.retried > 5
  682.         self.retried += 1
  683.  
  684.     
  685.     def retry_http_digest_auth(self, req, auth):
  686.         (token, challenge) = auth.split(' ', 1)
  687.         chal = parse_keqv_list(parse_http_list(challenge))
  688.         auth = self.get_authorization(req, chal)
  689.         if auth:
  690.             auth_val = 'Digest %s' % auth
  691.             if req.headers.get(self.auth_header, None) == auth_val:
  692.                 return None
  693.             req.add_unredirected_header(self.auth_header, auth_val)
  694.             resp = self.parent.open(req)
  695.             return resp
  696.  
  697.     
  698.     def get_cnonce(self, nonce):
  699.         dig = hashlib.sha1('%s:%s:%s:%s' % (self.nonce_count, nonce, time.ctime(), randombytes(8))).hexdigest()
  700.         return dig[:16]
  701.  
  702.     
  703.     def get_authorization(self, req, chal):
  704.         
  705.         try:
  706.             realm = chal['realm']
  707.             nonce = chal['nonce']
  708.             qop = chal.get('qop')
  709.             algorithm = chal.get('algorithm', 'MD5')
  710.             opaque = chal.get('opaque', None)
  711.         except KeyError:
  712.             return None
  713.  
  714.         (H, KD) = self.get_algorithm_impls(algorithm)
  715.         if H is None:
  716.             return None
  717.         (user, pw) = self.passwd.find_user_password(realm, req.get_full_url())
  718.         if user is None:
  719.             return None
  720.         A1 = '%s:%s:%s' % (user, realm, pw)
  721.         A2 = '%s:%s' % (req.get_method(), req.get_selector())
  722.         if qop == 'auth':
  723.             self.nonce_count += 1
  724.             ncvalue = '%08x' % self.nonce_count
  725.             cnonce = self.get_cnonce(nonce)
  726.             noncebit = '%s:%s:%s:%s:%s' % (nonce, ncvalue, cnonce, qop, H(A2))
  727.             respdig = KD(H(A1), noncebit)
  728.         elif qop is None:
  729.             respdig = KD(H(A1), '%s:%s' % (nonce, H(A2)))
  730.         else:
  731.             raise URLError("qop '%s' is not supported." % qop)
  732.         base = None if req.has_data() else H is None % (user, realm, nonce, req.get_selector(), respdig)
  733.         if opaque:
  734.             base += ', opaque="%s"' % opaque
  735.         
  736.         if entdig:
  737.             base += ', digest="%s"' % entdig
  738.         
  739.         base += ', algorithm="%s"' % algorithm
  740.         if qop:
  741.             base += ', qop=auth, nc=%s, cnonce="%s"' % (ncvalue, cnonce)
  742.         
  743.         return base
  744.  
  745.     
  746.     def get_algorithm_impls(self, algorithm):
  747.         algorithm = algorithm.upper()
  748.         if algorithm == 'MD5':
  749.             
  750.             H = lambda x: hashlib.md5(x).hexdigest()
  751.         elif algorithm == 'SHA':
  752.             
  753.             H = lambda x: hashlib.sha1(x).hexdigest()
  754.         
  755.         
  756.         KD = lambda s, d: H('%s:%s' % (s, d))
  757.         return (H, KD)
  758.  
  759.     
  760.     def get_entity_digest(self, data, chal):
  761.         pass
  762.  
  763.  
  764.  
  765. class HTTPDigestAuthHandler(BaseHandler, AbstractDigestAuthHandler):
  766.     auth_header = 'Authorization'
  767.     handler_order = 490
  768.     
  769.     def http_error_401(self, req, fp, code, msg, headers):
  770.         host = urlparse.urlparse(req.get_full_url())[1]
  771.         retry = self.http_error_auth_reqed('www-authenticate', host, req, headers)
  772.         self.reset_retry_count()
  773.         return retry
  774.  
  775.  
  776.  
  777. class ProxyDigestAuthHandler(BaseHandler, AbstractDigestAuthHandler):
  778.     auth_header = 'Proxy-Authorization'
  779.     handler_order = 490
  780.     
  781.     def http_error_407(self, req, fp, code, msg, headers):
  782.         host = req.get_host()
  783.         retry = self.http_error_auth_reqed('proxy-authenticate', host, req, headers)
  784.         self.reset_retry_count()
  785.         return retry
  786.  
  787.  
  788.  
  789. class AbstractHTTPHandler(BaseHandler):
  790.     
  791.     def __init__(self, debuglevel = 0):
  792.         self._debuglevel = debuglevel
  793.  
  794.     
  795.     def set_http_debuglevel(self, level):
  796.         self._debuglevel = level
  797.  
  798.     
  799.     def do_request_(self, request):
  800.         host = request.get_host()
  801.         if not host:
  802.             raise URLError('no host given')
  803.         host
  804.         if request.has_data():
  805.             data = request.get_data()
  806.             if not request.has_header('Content-type'):
  807.                 request.add_unredirected_header('Content-type', 'application/x-www-form-urlencoded')
  808.             
  809.             if not request.has_header('Content-length'):
  810.                 request.add_unredirected_header('Content-length', '%d' % len(data))
  811.             
  812.         
  813.         sel_host = host
  814.         if request.has_proxy():
  815.             (scheme, sel) = splittype(request.get_selector())
  816.             (sel_host, sel_path) = splithost(sel)
  817.         
  818.         if not request.has_header('Host'):
  819.             request.add_unredirected_header('Host', sel_host)
  820.         
  821.         for name, value in self.parent.addheaders:
  822.             name = name.capitalize()
  823.             if not request.has_header(name):
  824.                 request.add_unredirected_header(name, value)
  825.                 continue
  826.         
  827.         return request
  828.  
  829.     
  830.     def do_open(self, http_class, req):
  831.         host = req.get_host()
  832.         if not host:
  833.             raise URLError('no host given')
  834.         host
  835.         h = http_class(host, timeout = req.timeout)
  836.         h.set_debuglevel(self._debuglevel)
  837.         headers = dict(req.headers)
  838.         headers.update(req.unredirected_hdrs)
  839.         headers['Connection'] = 'close'
  840.         headers = dict((lambda .0: for name, val in .0:
  841. (name.title(), val))(headers.items()))
  842.         
  843.         try:
  844.             h.request(req.get_method(), req.get_selector(), req.data, headers)
  845.             r = h.getresponse()
  846.         except socket.error:
  847.             err = None
  848.             raise URLError(err)
  849.  
  850.         r.recv = r.read
  851.         fp = socket._fileobject(r, close = True)
  852.         resp = addinfourl(fp, r.msg, req.get_full_url())
  853.         resp.code = r.status
  854.         resp.msg = r.reason
  855.         return resp
  856.  
  857.  
  858.  
  859. class HTTPHandler(AbstractHTTPHandler):
  860.     
  861.     def http_open(self, req):
  862.         return self.do_open(httplib.HTTPConnection, req)
  863.  
  864.     http_request = AbstractHTTPHandler.do_request_
  865.  
  866. if hasattr(httplib, 'HTTPS'):
  867.     
  868.     class HTTPSHandler(AbstractHTTPHandler):
  869.         
  870.         def https_open(self, req):
  871.             return self.do_open(httplib.HTTPSConnection, req)
  872.  
  873.         https_request = AbstractHTTPHandler.do_request_
  874.  
  875.  
  876.  
  877. class HTTPCookieProcessor(BaseHandler):
  878.     
  879.     def __init__(self, cookiejar = None):
  880.         import cookielib
  881.         if cookiejar is None:
  882.             cookiejar = cookielib.CookieJar()
  883.         
  884.         self.cookiejar = cookiejar
  885.  
  886.     
  887.     def http_request(self, request):
  888.         self.cookiejar.add_cookie_header(request)
  889.         return request
  890.  
  891.     
  892.     def http_response(self, request, response):
  893.         self.cookiejar.extract_cookies(response, request)
  894.         return response
  895.  
  896.     https_request = http_request
  897.     https_response = http_response
  898.  
  899.  
  900. class UnknownHandler(BaseHandler):
  901.     
  902.     def unknown_open(self, req):
  903.         type = req.get_type()
  904.         raise URLError('unknown url type: %s' % type)
  905.  
  906.  
  907.  
  908. def parse_keqv_list(l):
  909.     parsed = { }
  910.     for elt in l:
  911.         (k, v) = elt.split('=', 1)
  912.         if v[0] == '"' and v[-1] == '"':
  913.             v = v[1:-1]
  914.         
  915.         parsed[k] = v
  916.     
  917.     return parsed
  918.  
  919.  
  920. def parse_http_list(s):
  921.     res = []
  922.     part = ''
  923.     escape = quote = False
  924.     for cur in s:
  925.         if escape:
  926.             part += cur
  927.             escape = False
  928.             continue
  929.         
  930.         if quote:
  931.             if cur == '\\':
  932.                 escape = True
  933.                 continue
  934.             elif cur == '"':
  935.                 quote = False
  936.             
  937.             part += cur
  938.             continue
  939.         
  940.         if cur == ',':
  941.             res.append(part)
  942.             part = ''
  943.             continue
  944.         
  945.         if cur == '"':
  946.             quote = True
  947.         
  948.         part += cur
  949.     
  950.     if part:
  951.         res.append(part)
  952.     
  953.     return [ part.strip() for part in res ]
  954.  
  955.  
  956. class FileHandler(BaseHandler):
  957.     
  958.     def file_open(self, req):
  959.         url = req.get_selector()
  960.         if url[:2] == '//' and url[2:3] != '/':
  961.             req.type = 'ftp'
  962.             return self.parent.open(req)
  963.         return self.open_local_file(req)
  964.  
  965.     names = None
  966.     
  967.     def get_names(self):
  968.         if FileHandler.names is None:
  969.             
  970.             try:
  971.                 FileHandler.names = (socket.gethostbyname('localhost'), socket.gethostbyname(socket.gethostname()))
  972.             except socket.gaierror:
  973.                 FileHandler.names = (socket.gethostbyname('localhost'),)
  974.             except:
  975.                 None<EXCEPTION MATCH>socket.gaierror
  976.             
  977.  
  978.         None<EXCEPTION MATCH>socket.gaierror
  979.         return FileHandler.names
  980.  
  981.     
  982.     def open_local_file(self, req):
  983.         import email.utils as email
  984.         import mimetypes
  985.         host = req.get_host()
  986.         file = req.get_selector()
  987.         localfile = url2pathname(file)
  988.         
  989.         try:
  990.             stats = os.stat(localfile)
  991.             size = stats.st_size
  992.             modified = email.utils.formatdate(stats.st_mtime, usegmt = True)
  993.             mtype = mimetypes.guess_type(file)[0]
  994.             if not mtype:
  995.                 pass
  996.             headers = mimetools.Message(StringIO('Content-type: %s\nContent-length: %d\nLast-modified: %s\n' % ('text/plain', size, modified)))
  997.             if host:
  998.                 (host, port) = splitport(host)
  999.             
  1000.             if (not host or not port) and socket.gethostbyname(host) in self.get_names():
  1001.                 return addinfourl(open(localfile, 'rb'), headers, 'file:' + file)
  1002.         except OSError:
  1003.             msg = None
  1004.             raise URLError(msg)
  1005.  
  1006.         raise URLError('file not on local host')
  1007.  
  1008.  
  1009.  
  1010. class FTPHandler(BaseHandler):
  1011.     
  1012.     def ftp_open(self, req):
  1013.         import ftplib
  1014.         import mimetypes
  1015.         host = req.get_host()
  1016.         if not host:
  1017.             raise URLError('ftp error: no host given')
  1018.         host
  1019.         (host, port) = splitport(host)
  1020.         if port is None:
  1021.             port = ftplib.FTP_PORT
  1022.         else:
  1023.             port = int(port)
  1024.         (user, host) = splituser(host)
  1025.         if user:
  1026.             (user, passwd) = splitpasswd(user)
  1027.         else:
  1028.             passwd = None
  1029.         host = unquote(host)
  1030.         if not user:
  1031.             pass
  1032.         user = unquote('')
  1033.         if not passwd:
  1034.             pass
  1035.         passwd = unquote('')
  1036.         
  1037.         try:
  1038.             host = socket.gethostbyname(host)
  1039.         except socket.error:
  1040.             msg = None
  1041.             raise URLError(msg)
  1042.  
  1043.         (path, attrs) = splitattr(req.get_selector())
  1044.         dirs = path.split('/')
  1045.         dirs = map(unquote, dirs)
  1046.         dirs = dirs[:-1]
  1047.         file = dirs[-1]
  1048.         if dirs and not dirs[0]:
  1049.             dirs = dirs[1:]
  1050.         
  1051.         
  1052.         try:
  1053.             fw = self.connect_ftp(user, passwd, host, port, dirs, req.timeout)
  1054.             if not file or 'I':
  1055.                 pass
  1056.             type = 'D'
  1057.             for attr in attrs:
  1058.                 (attr, value) = splitvalue(attr)
  1059.                 if attr.lower() == 'type' and value in ('a', 'A', 'i', 'I', 'd', 'D'):
  1060.                     type = value.upper()
  1061.                     continue
  1062.             
  1063.             (fp, retrlen) = fw.retrfile(file, type)
  1064.             headers = ''
  1065.             mtype = mimetypes.guess_type(req.get_full_url())[0]
  1066.             if mtype:
  1067.                 headers += 'Content-type: %s\n' % mtype
  1068.             
  1069.             if retrlen is not None and retrlen >= 0:
  1070.                 headers += 'Content-length: %d\n' % retrlen
  1071.             
  1072.             sf = StringIO(headers)
  1073.             headers = mimetools.Message(sf)
  1074.             return addinfourl(fp, headers, req.get_full_url())
  1075.         except ftplib.all_errors:
  1076.             msg = None
  1077.             raise URLError, 'ftp error: %s' % msg, sys.exc_info()[2]
  1078.  
  1079.  
  1080.     
  1081.     def connect_ftp(self, user, passwd, host, port, dirs, timeout):
  1082.         fw = ftpwrapper(user, passwd, host, port, dirs, timeout)
  1083.         return fw
  1084.  
  1085.  
  1086.  
  1087. class CacheFTPHandler(FTPHandler):
  1088.     
  1089.     def __init__(self):
  1090.         self.cache = { }
  1091.         self.timeout = { }
  1092.         self.soonest = 0
  1093.         self.delay = 60
  1094.         self.max_conns = 16
  1095.  
  1096.     
  1097.     def setTimeout(self, t):
  1098.         self.delay = t
  1099.  
  1100.     
  1101.     def setMaxConns(self, m):
  1102.         self.max_conns = m
  1103.  
  1104.     
  1105.     def connect_ftp(self, user, passwd, host, port, dirs, timeout):
  1106.         key = (user, host, port, '/'.join(dirs), timeout)
  1107.         if key in self.cache:
  1108.             self.timeout[key] = time.time() + self.delay
  1109.         else:
  1110.             self.cache[key] = ftpwrapper(user, passwd, host, port, dirs, timeout)
  1111.             self.timeout[key] = time.time() + self.delay
  1112.         self.check_cache()
  1113.         return self.cache[key]
  1114.  
  1115.     
  1116.     def check_cache(self):
  1117.         t = time.time()
  1118.         if self.soonest <= t:
  1119.             for k, v in self.timeout.items():
  1120.                 if v < t:
  1121.                     self.cache[k].close()
  1122.                     del self.cache[k]
  1123.                     del self.timeout[k]
  1124.                     continue
  1125.             
  1126.         
  1127.         self.soonest = min(self.timeout.values())
  1128.         if len(self.cache) == self.max_conns:
  1129.             for k, v in self.timeout.items():
  1130.                 if v == self.soonest:
  1131.                     del self.cache[k]
  1132.                     del self.timeout[k]
  1133.                     break
  1134.                     continue
  1135.             
  1136.             self.soonest = min(self.timeout.values())
  1137.         
  1138.  
  1139.  
  1140.