home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_2832 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  34.4 KB  |  1,147 lines

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