home *** CD-ROM | disk | FTP | other *** search
/ com!online 2005 April / com_0405_1.iso / opensource / BTpp-0.5.4-bin.exe / $INSTDIR / BT++.exe / urllib.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2003-04-19  |  44.7 KB  |  1,514 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.2)
  3.  
  4. import string
  5. import socket
  6. import os
  7. import stat
  8. import time
  9. import sys
  10. import types
  11. __all__ = [
  12.     'urlopen',
  13.     'URLopener',
  14.     'FancyURLopener',
  15.     'urlretrieve',
  16.     'urlcleanup',
  17.     'quote',
  18.     'quote_plus',
  19.     'unquote',
  20.     'unquote_plus',
  21.     'urlencode',
  22.     'url2pathname',
  23.     'pathname2url',
  24.     'splittag',
  25.     'localhost',
  26.     'thishost',
  27.     'ftperrors',
  28.     'basejoin',
  29.     'unwrap',
  30.     'splittype',
  31.     'splithost',
  32.     'splituser',
  33.     'splitpasswd',
  34.     'splitport',
  35.     'splitnport',
  36.     'splitquery',
  37.     'splitattr',
  38.     'splitvalue',
  39.     'splitgophertype',
  40.     'getproxies']
  41. __version__ = '1.15'
  42. MAXFTPCACHE = 10
  43. if os.name == 'mac':
  44.     from macurl2path import url2pathname, pathname2url
  45. elif os.name == 'nt':
  46.     from nturl2path import url2pathname, pathname2url
  47. elif os.name == 'riscos':
  48.     from rourl2path import url2pathname, pathname2url
  49. else:
  50.     
  51.     def url2pathname(pathname):
  52.         return unquote(pathname)
  53.  
  54.     
  55.     def pathname2url(pathname):
  56.         return quote(pathname)
  57.  
  58. _urlopener = None
  59.  
  60. def urlopen(url, data = None):
  61.     global _urlopener
  62.     if not _urlopener:
  63.         _urlopener = FancyURLopener()
  64.     
  65.     if data is None:
  66.         return _urlopener.open(url)
  67.     else:
  68.         return _urlopener.open(url, data)
  69.  
  70.  
  71. def urlretrieve(url, filename = None, reporthook = None, data = None):
  72.     global _urlopener
  73.     if not _urlopener:
  74.         _urlopener = FancyURLopener()
  75.     
  76.     return _urlopener.retrieve(url, filename, reporthook, data)
  77.  
  78.  
  79. def urlcleanup():
  80.     if _urlopener:
  81.         _urlopener.cleanup()
  82.     
  83.  
  84. ftpcache = { }
  85.  
  86. class URLopener:
  87.     __tempfiles = None
  88.     version = 'Python-urllib/%s' % __version__
  89.     
  90.     def __init__(self, proxies = None, **x509):
  91.         if proxies is None:
  92.             proxies = getproxies()
  93.         
  94.         self.proxies = proxies
  95.         self.key_file = x509.get('key_file')
  96.         self.cert_file = x509.get('cert_file')
  97.         self.addheaders = [
  98.             ('User-agent', self.version)]
  99.         self._URLopener__tempfiles = []
  100.         self._URLopener__unlink = os.unlink
  101.         self.tempcache = None
  102.         self.ftpcache = ftpcache
  103.  
  104.     
  105.     def __del__(self):
  106.         self.close()
  107.  
  108.     
  109.     def close(self):
  110.         self.cleanup()
  111.  
  112.     
  113.     def cleanup(self):
  114.         if self._URLopener__tempfiles:
  115.             for file in self._URLopener__tempfiles:
  116.                 
  117.                 try:
  118.                     self._URLopener__unlink(file)
  119.                 except OSError:
  120.                     pass
  121.  
  122.             
  123.             del self._URLopener__tempfiles[:]
  124.         
  125.         if self.tempcache:
  126.             self.tempcache.clear()
  127.         
  128.  
  129.     
  130.     def addheader(self, *args):
  131.         self.addheaders.append(args)
  132.  
  133.     
  134.     def open(self, fullurl, data = None):
  135.         fullurl = unwrap(toBytes(fullurl))
  136.         if self.tempcache and self.tempcache.has_key(fullurl):
  137.             (filename, headers) = self.tempcache[fullurl]
  138.             fp = open(filename, 'rb')
  139.             return addinfourl(fp, headers, fullurl)
  140.         
  141.         (urltype, url) = splittype(fullurl)
  142.         if not urltype:
  143.             urltype = 'file'
  144.         
  145.         if self.proxies.has_key(urltype):
  146.             proxy = self.proxies[urltype]
  147.             (urltype, proxyhost) = splittype(proxy)
  148.             (host, selector) = splithost(proxyhost)
  149.             url = (host, fullurl)
  150.         else:
  151.             proxy = None
  152.         name = 'open_' + urltype
  153.         self.type = urltype
  154.         if '-' in name:
  155.             name = '_'.join(name.split('-'))
  156.         
  157.         if not hasattr(self, name):
  158.             if proxy:
  159.                 return self.open_unknown_proxy(proxy, fullurl, data)
  160.             else:
  161.                 return self.open_unknown(fullurl, data)
  162.         
  163.         
  164.         try:
  165.             if data is None:
  166.                 return getattr(self, name)(url)
  167.             else:
  168.                 return getattr(self, name)(url, data)
  169.         except socket.error:
  170.             msg = None
  171.             raise IOError, ('socket error', msg), sys.exc_info()[2]
  172.  
  173.  
  174.     
  175.     def open_unknown(self, fullurl, data = None):
  176.         (type, url) = splittype(fullurl)
  177.         raise IOError, ('url error', 'unknown url type', type)
  178.  
  179.     
  180.     def open_unknown_proxy(self, proxy, fullurl, data = None):
  181.         (type, url) = splittype(fullurl)
  182.         raise IOError, ('url error', 'invalid proxy for %s' % type, proxy)
  183.  
  184.     
  185.     def retrieve(self, url, filename = None, reporthook = None, data = None):
  186.         url = unwrap(toBytes(url))
  187.         if self.tempcache and self.tempcache.has_key(url):
  188.             return self.tempcache[url]
  189.         
  190.         (type, url1) = splittype(url)
  191.         if not filename and not type or type == 'file':
  192.             
  193.             try:
  194.                 fp = self.open_local_file(url1)
  195.                 hdrs = fp.info()
  196.                 del fp
  197.                 return (url2pathname(splithost(url1)[1]), hdrs)
  198.             except IOError:
  199.                 msg = None
  200.  
  201.         
  202.         fp = self.open(url, data)
  203.         headers = fp.info()
  204.         if not filename:
  205.             import tempfile
  206.             (garbage, path) = splittype(url)
  207.             if not path:
  208.                 pass
  209.             (garbage, path) = splithost('')
  210.             if not path:
  211.                 pass
  212.             (path, garbage) = splitquery('')
  213.             if not path:
  214.                 pass
  215.             (path, garbage) = splitattr('')
  216.             suffix = os.path.splitext(path)[1]
  217.             filename = tempfile.mktemp(suffix)
  218.             self._URLopener__tempfiles.append(filename)
  219.         
  220.         result = (filename, headers)
  221.         if self.tempcache is not None:
  222.             self.tempcache[url] = result
  223.         
  224.         tfp = open(filename, 'wb')
  225.         bs = 1024 * 8
  226.         size = -1
  227.         blocknum = 1
  228.         if reporthook:
  229.             if headers.has_key('content-length'):
  230.                 size = int(headers['Content-Length'])
  231.             
  232.             reporthook(0, bs, size)
  233.         
  234.         block = fp.read(bs)
  235.         if reporthook:
  236.             reporthook(1, bs, size)
  237.         
  238.         while block:
  239.             tfp.write(block)
  240.             block = fp.read(bs)
  241.             blocknum = blocknum + 1
  242.             if reporthook:
  243.                 reporthook(blocknum, bs, size)
  244.             
  245.         fp.close()
  246.         tfp.close()
  247.         del fp
  248.         del tfp
  249.         return result
  250.  
  251.     
  252.     def open_http(self, url, data = None):
  253.         import httplib
  254.         user_passwd = None
  255.         if type(url) is types.StringType:
  256.             (host, selector) = splithost(url)
  257.             if host:
  258.                 (user_passwd, host) = splituser(host)
  259.                 host = unquote(host)
  260.             
  261.             realhost = host
  262.         else:
  263.             (host, selector) = url
  264.             (urltype, rest) = splittype(selector)
  265.             url = rest
  266.             user_passwd = None
  267.             if urltype.lower() != 'http':
  268.                 realhost = None
  269.             else:
  270.                 (realhost, rest) = splithost(rest)
  271.                 if realhost:
  272.                     (user_passwd, realhost) = splituser(realhost)
  273.                 
  274.                 if user_passwd:
  275.                     selector = '%s://%s%s' % (urltype, realhost, rest)
  276.                 
  277.                 if proxy_bypass(realhost):
  278.                     host = realhost
  279.                 
  280.         if not host:
  281.             raise IOError, ('http error', 'no host given')
  282.         
  283.         if user_passwd:
  284.             import base64
  285.             auth = base64.encodestring(user_passwd).strip()
  286.         else:
  287.             auth = None
  288.         h = httplib.HTTP(host)
  289.         if data is not None:
  290.             h.putrequest('POST', selector)
  291.             h.putheader('Content-type', 'application/x-www-form-urlencoded')
  292.             h.putheader('Content-length', '%d' % len(data))
  293.         else:
  294.             h.putrequest('GET', selector)
  295.         if auth:
  296.             h.putheader('Authorization', 'Basic %s' % auth)
  297.         
  298.         if realhost:
  299.             h.putheader('Host', realhost)
  300.         
  301.         for args in self.addheaders:
  302.             apply(h.putheader, args)
  303.         
  304.         h.endheaders()
  305.         if data is not None:
  306.             h.send(data)
  307.         
  308.         (errcode, errmsg, headers) = h.getreply()
  309.         fp = h.getfile()
  310.         if errcode == 200:
  311.             return addinfourl(fp, headers, 'http:' + url)
  312.         elif data is None:
  313.             return self.http_error(url, fp, errcode, errmsg, headers)
  314.         else:
  315.             return self.http_error(url, fp, errcode, errmsg, headers, data)
  316.  
  317.     
  318.     def http_error(self, url, fp, errcode, errmsg, headers, data = None):
  319.         name = 'http_error_%d' % errcode
  320.         if hasattr(self, name):
  321.             method = getattr(self, name)
  322.             if data is None:
  323.                 result = method(url, fp, errcode, errmsg, headers)
  324.             else:
  325.                 result = method(url, fp, errcode, errmsg, headers, data)
  326.             if result:
  327.                 return result
  328.             
  329.         
  330.         return self.http_error_default(url, fp, errcode, errmsg, headers)
  331.  
  332.     
  333.     def http_error_default(self, url, fp, errcode, errmsg, headers):
  334.         void = fp.read()
  335.         fp.close()
  336.         raise IOError, ('http error', errcode, errmsg, headers)
  337.  
  338.     if hasattr(socket, 'ssl'):
  339.         
  340.         def open_https(self, url, data = None):
  341.             import httplib
  342.             user_passwd = None
  343.             if type(url) is types.StringType:
  344.                 (host, selector) = splithost(url)
  345.                 if host:
  346.                     (user_passwd, host) = splituser(host)
  347.                     host = unquote(host)
  348.                 
  349.                 realhost = host
  350.             else:
  351.                 (host, selector) = url
  352.                 (urltype, rest) = splittype(selector)
  353.                 url = rest
  354.                 user_passwd = None
  355.                 if urltype.lower() != 'https':
  356.                     realhost = None
  357.                 else:
  358.                     (realhost, rest) = splithost(rest)
  359.                     if realhost:
  360.                         (user_passwd, realhost) = splituser(realhost)
  361.                     
  362.                     if user_passwd:
  363.                         selector = '%s://%s%s' % (urltype, realhost, rest)
  364.                     
  365.             if not host:
  366.                 raise IOError, ('https error', 'no host given')
  367.             
  368.             if user_passwd:
  369.                 import base64
  370.                 auth = base64.encodestring(user_passwd).strip()
  371.             else:
  372.                 auth = None
  373.             h = httplib.HTTPS(host, 0, key_file = self.key_file, cert_file = self.cert_file)
  374.             if data is not None:
  375.                 h.putrequest('POST', selector)
  376.                 h.putheader('Content-type', 'application/x-www-form-urlencoded')
  377.                 h.putheader('Content-length', '%d' % len(data))
  378.             else:
  379.                 h.putrequest('GET', selector)
  380.             if auth:
  381.                 h.putheader('Authorization: Basic %s' % auth)
  382.             
  383.             if realhost:
  384.                 h.putheader('Host', realhost)
  385.             
  386.             for args in self.addheaders:
  387.                 apply(h.putheader, args)
  388.             
  389.             h.endheaders()
  390.             if data is not None:
  391.                 h.send(data)
  392.             
  393.             (errcode, errmsg, headers) = h.getreply()
  394.             fp = h.getfile()
  395.             if errcode == 200:
  396.                 return addinfourl(fp, headers, 'https:' + url)
  397.             elif data is None:
  398.                 return self.http_error(url, fp, errcode, errmsg, headers)
  399.             else:
  400.                 return self.http_error(url, fp, errcode, errmsg, headers, data)
  401.  
  402.     
  403.     
  404.     def open_gopher(self, url):
  405.         import gopherlib
  406.         (host, selector) = splithost(url)
  407.         if not host:
  408.             raise IOError, ('gopher error', 'no host given')
  409.         
  410.         host = unquote(host)
  411.         (type, selector) = splitgophertype(selector)
  412.         (selector, query) = splitquery(selector)
  413.         selector = unquote(selector)
  414.         if query:
  415.             query = unquote(query)
  416.             fp = gopherlib.send_query(selector, query, host)
  417.         else:
  418.             fp = gopherlib.send_selector(selector, host)
  419.         return addinfourl(fp, noheaders(), 'gopher:' + url)
  420.  
  421.     
  422.     def open_file(self, url):
  423.         if url[:2] == '//' and url[2:3] != '/' and url[2:12].lower() != 'localhost/':
  424.             return self.open_ftp(url)
  425.         else:
  426.             return self.open_local_file(url)
  427.  
  428.     
  429.     def open_local_file(self, url):
  430.         import mimetypes
  431.         import mimetools
  432.         import rfc822
  433.         import StringIO
  434.         (host, file) = splithost(url)
  435.         localname = url2pathname(file)
  436.         
  437.         try:
  438.             stats = os.stat(localname)
  439.         except OSError:
  440.             e = None
  441.             raise IOError(e.errno, e.strerror, e.filename)
  442.  
  443.         size = stats[stat.ST_SIZE]
  444.         modified = rfc822.formatdate(stats[stat.ST_MTIME])
  445.         mtype = mimetypes.guess_type(url)[0]
  446.         if not mtype:
  447.             pass
  448.         headers = mimetools.Message(StringIO.StringIO('Content-Type: %s\nContent-Length: %d\nLast-modified: %s\n' % ('text/plain', size, modified)))
  449.         if not host:
  450.             urlfile = file
  451.             if file[:1] == '/':
  452.                 urlfile = 'file://' + file
  453.             
  454.             return addinfourl(open(localname, 'rb'), headers, urlfile)
  455.         
  456.         (host, port) = splitport(host)
  457.         if not port and socket.gethostbyname(host) in (localhost(), thishost()):
  458.             urlfile = file
  459.             if file[:1] == '/':
  460.                 urlfile = 'file://' + file
  461.             
  462.             return addinfourl(open(localname, 'rb'), headers, urlfile)
  463.         
  464.         raise IOError, ('local file error', 'not on local host')
  465.  
  466.     
  467.     def open_ftp(self, url):
  468.         import mimetypes
  469.         import mimetools
  470.         import StringIO
  471.         (host, path) = splithost(url)
  472.         if not host:
  473.             raise IOError, ('ftp error', 'no host given')
  474.         
  475.         (host, port) = splitport(host)
  476.         (user, host) = splituser(host)
  477.         if user:
  478.             (user, passwd) = splitpasswd(user)
  479.         else:
  480.             passwd = None
  481.         host = unquote(host)
  482.         if not user:
  483.             pass
  484.         user = unquote('')
  485.         if not passwd:
  486.             pass
  487.         passwd = unquote('')
  488.         host = socket.gethostbyname(host)
  489.         if not port:
  490.             import ftplib
  491.             port = ftplib.FTP_PORT
  492.         else:
  493.             port = int(port)
  494.         (path, attrs) = splitattr(path)
  495.         path = unquote(path)
  496.         dirs = path.split('/')
  497.         (dirs, file) = (dirs[:-1], dirs[-1])
  498.         if dirs and not dirs[0]:
  499.             dirs = dirs[1:]
  500.         
  501.         if dirs and not dirs[0]:
  502.             dirs[0] = '/'
  503.         
  504.         key = (user, host, port, '/'.join(dirs))
  505.         if len(self.ftpcache) > MAXFTPCACHE:
  506.             for k in self.ftpcache.keys():
  507.                 if k != key:
  508.                     v = self.ftpcache[k]
  509.                     del self.ftpcache[k]
  510.                     v.close()
  511.                 
  512.             
  513.         
  514.         
  515.         try:
  516.             if not self.ftpcache.has_key(key):
  517.                 self.ftpcache[key] = ftpwrapper(user, passwd, host, port, dirs)
  518.             
  519.             if not file:
  520.                 type = 'D'
  521.             else:
  522.                 type = 'I'
  523.             for attr in attrs:
  524.                 (attr, value) = splitvalue(attr)
  525.                 if attr.lower() == 'type' and value in ('a', 'A', 'i', 'I', 'd', 'D'):
  526.                     type = value.upper()
  527.                 
  528.             
  529.             (fp, retrlen) = self.ftpcache[key].retrfile(file, type)
  530.             mtype = mimetypes.guess_type('ftp:' + url)[0]
  531.             headers = ''
  532.             if mtype:
  533.                 headers += 'Content-Type: %s\n' % mtype
  534.             
  535.             if retrlen is not None and retrlen >= 0:
  536.                 headers += 'Content-Length: %d\n' % retrlen
  537.             
  538.             headers = mimetools.Message(StringIO.StringIO(headers))
  539.             return addinfourl(fp, headers, 'ftp:' + url)
  540.         except ftperrors():
  541.             msg = None
  542.             raise IOError, ('ftp error', msg), sys.exc_info()[2]
  543.  
  544.  
  545.     
  546.     def open_data(self, url, data = None):
  547.         import StringIO
  548.         import mimetools
  549.         import time
  550.         
  551.         try:
  552.             (type, data) = url.split(',', 1)
  553.         except ValueError:
  554.             raise IOError, ('data error', 'bad data URL')
  555.  
  556.         if not type:
  557.             type = 'text/plain;charset=US-ASCII'
  558.         
  559.         semi = type.rfind(';')
  560.         if semi >= 0 and '=' not in type[semi:]:
  561.             encoding = type[semi + 1:]
  562.             type = type[:semi]
  563.         else:
  564.             encoding = ''
  565.         msg = []
  566.         msg.append('Date: %s' % time.strftime('%a, %d %b %Y %T GMT', time.gmtime(time.time())))
  567.         msg.append('Content-type: %s' % type)
  568.         if encoding == 'base64':
  569.             import base64
  570.             data = base64.decodestring(data)
  571.         else:
  572.             data = unquote(data)
  573.         msg.append('Content-length: %d' % len(data))
  574.         msg.append('')
  575.         msg.append(data)
  576.         msg = '\n'.join(msg)
  577.         f = StringIO.StringIO(msg)
  578.         headers = mimetools.Message(f, 0)
  579.         f.fileno = None
  580.         return addinfourl(f, headers, url)
  581.  
  582.  
  583.  
  584. class FancyURLopener(URLopener):
  585.     
  586.     def __init__(self, *args):
  587.         apply(URLopener.__init__, (self,) + args)
  588.         self.auth_cache = { }
  589.         self.tries = 0
  590.         self.maxtries = 10
  591.  
  592.     
  593.     def http_error_default(self, url, fp, errcode, errmsg, headers):
  594.         return addinfourl(fp, headers, 'http:' + url)
  595.  
  596.     
  597.     def http_error_302(self, url, fp, errcode, errmsg, headers, data = None):
  598.         self.tries += 1
  599.         result = self.redirect_internal(url, fp, errcode, errmsg, headers, data)
  600.         self.tries = 0
  601.         return result
  602.  
  603.     
  604.     def redirect_internal(self, url, fp, errcode, errmsg, headers, data):
  605.         if headers.has_key('location'):
  606.             newurl = headers['location']
  607.         elif headers.has_key('uri'):
  608.             newurl = headers['uri']
  609.         else:
  610.             return None
  611.         void = fp.read()
  612.         fp.close()
  613.         newurl = basejoin(self.type + ':' + url, newurl)
  614.         if data is None:
  615.             return self.open(newurl)
  616.         else:
  617.             return self.open(newurl, data)
  618.  
  619.     
  620.     def http_error_301(self, url, fp, errcode, errmsg, headers, data = None):
  621.         return self.http_error_302(url, fp, errcode, errmsg, headers, data)
  622.  
  623.     
  624.     def http_error_401(self, url, fp, errcode, errmsg, headers, data = None):
  625.         if not headers.has_key('www-authenticate'):
  626.             URLopener.http_error_default(self, url, fp, errcode, errmsg, headers)
  627.         
  628.         stuff = headers['www-authenticate']
  629.         import re
  630.         match = re.match('[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', stuff)
  631.         if not match:
  632.             URLopener.http_error_default(self, url, fp, errcode, errmsg, headers)
  633.         
  634.         (scheme, realm) = match.groups()
  635.         if scheme.lower() != 'basic':
  636.             URLopener.http_error_default(self, url, fp, errcode, errmsg, headers)
  637.         
  638.         name = 'retry_' + self.type + '_basic_auth'
  639.         if data is None:
  640.             return getattr(self, name)(url, realm)
  641.         else:
  642.             return getattr(self, name)(url, realm, data)
  643.  
  644.     
  645.     def retry_http_basic_auth(self, url, realm, data = None):
  646.         (host, selector) = splithost(url)
  647.         i = host.find('@') + 1
  648.         host = host[i:]
  649.         (user, passwd) = self.get_user_passwd(host, realm, i)
  650.         if not user:
  651.             pass
  652.         if not passwd:
  653.             return None
  654.         
  655.         host = quote(user, safe = '') + ':' + quote(passwd, safe = '') + '@' + host
  656.         newurl = 'http://' + host + selector
  657.         if data is None:
  658.             return self.open(newurl)
  659.         else:
  660.             return self.open(newurl, data)
  661.  
  662.     
  663.     def retry_https_basic_auth(self, url, realm, data = None):
  664.         (host, selector) = splithost(url)
  665.         i = host.find('@') + 1
  666.         host = host[i:]
  667.         (user, passwd) = self.get_user_passwd(host, realm, i)
  668.         if not user:
  669.             pass
  670.         if not passwd:
  671.             return None
  672.         
  673.         host = quote(user, safe = '') + ':' + quote(passwd, safe = '') + '@' + host
  674.         newurl = '//' + host + selector
  675.         return self.open_https(newurl, data)
  676.  
  677.     
  678.     def get_user_passwd(self, host, realm, clear_cache = 0):
  679.         key = realm + '@' + host.lower()
  680.         if self.auth_cache.has_key(key):
  681.             if clear_cache:
  682.                 del self.auth_cache[key]
  683.             else:
  684.                 return self.auth_cache[key]
  685.         
  686.         (user, passwd) = self.prompt_user_passwd(host, realm)
  687.         if user or passwd:
  688.             self.auth_cache[key] = (user, passwd)
  689.         
  690.         return (user, passwd)
  691.  
  692.     
  693.     def prompt_user_passwd(self, host, realm):
  694.         import getpass
  695.         
  696.         try:
  697.             user = raw_input('Enter username for %s at %s: ' % (realm, host))
  698.             passwd = getpass.getpass('Enter password for %s in %s at %s: ' % (user, realm, host))
  699.             return (user, passwd)
  700.         except KeyboardInterrupt:
  701.             print 
  702.             return (None, None)
  703.  
  704.  
  705.  
  706. _localhost = None
  707.  
  708. def localhost():
  709.     global _localhost
  710.     if not _localhost:
  711.         _localhost = socket.gethostbyname('localhost')
  712.     
  713.     return _localhost
  714.  
  715. _thishost = None
  716.  
  717. def thishost():
  718.     global _thishost
  719.     if not _thishost:
  720.         _thishost = socket.gethostbyname(socket.gethostname())
  721.     
  722.     return _thishost
  723.  
  724. _ftperrors = None
  725.  
  726. def ftperrors():
  727.     global _ftperrors
  728.     if not _ftperrors:
  729.         import ftplib
  730.         _ftperrors = ftplib.all_errors
  731.     
  732.     return _ftperrors
  733.  
  734. _noheaders = None
  735.  
  736. def noheaders():
  737.     global _noheaders
  738.     if not _noheaders:
  739.         import mimetools
  740.         import StringIO
  741.         _noheaders = mimetools.Message(StringIO.StringIO(), 0)
  742.         _noheaders.fp.close()
  743.     
  744.     return _noheaders
  745.  
  746.  
  747. class ftpwrapper:
  748.     
  749.     def __init__(self, user, passwd, host, port, dirs):
  750.         self.user = user
  751.         self.passwd = passwd
  752.         self.host = host
  753.         self.port = port
  754.         self.dirs = dirs
  755.         self.init()
  756.  
  757.     
  758.     def init(self):
  759.         import ftplib
  760.         self.busy = 0
  761.         self.ftp = ftplib.FTP()
  762.         self.ftp.connect(self.host, self.port)
  763.         self.ftp.login(self.user, self.passwd)
  764.         for dir in self.dirs:
  765.             self.ftp.cwd(dir)
  766.         
  767.  
  768.     
  769.     def retrfile(self, file, type):
  770.         import ftplib
  771.         self.endtransfer()
  772.         if type in ('d', 'D'):
  773.             cmd = 'TYPE A'
  774.             isdir = 1
  775.         else:
  776.             cmd = 'TYPE ' + type
  777.             isdir = 0
  778.         
  779.         try:
  780.             self.ftp.voidcmd(cmd)
  781.         except ftplib.all_errors:
  782.             self.init()
  783.             self.ftp.voidcmd(cmd)
  784.  
  785.         conn = None
  786.         if file and not isdir:
  787.             
  788.             try:
  789.                 self.ftp.nlst(file)
  790.             except ftplib.error_perm:
  791.                 reason = None
  792.                 raise IOError, ('ftp error', reason), sys.exc_info()[2]
  793.  
  794.             self.ftp.voidcmd(cmd)
  795.             
  796.             try:
  797.                 cmd = 'RETR ' + file
  798.                 conn = self.ftp.ntransfercmd(cmd)
  799.             except ftplib.error_perm:
  800.                 reason = None
  801.                 if str(reason)[:3] != '550':
  802.                     raise IOError, ('ftp error', reason), sys.exc_info()[2]
  803.                 
  804.             except:
  805.                 str(reason)[:3] != '550'
  806.  
  807.         
  808.         if not conn:
  809.             self.ftp.voidcmd('TYPE A')
  810.             if file:
  811.                 cmd = 'LIST ' + file
  812.             else:
  813.                 cmd = 'LIST'
  814.             conn = self.ftp.ntransfercmd(cmd)
  815.         
  816.         self.busy = 1
  817.         return (addclosehook(conn[0].makefile('rb'), self.endtransfer), conn[1])
  818.  
  819.     
  820.     def endtransfer(self):
  821.         if not (self.busy):
  822.             return None
  823.         
  824.         self.busy = 0
  825.         
  826.         try:
  827.             self.ftp.voidresp()
  828.         except ftperrors():
  829.             pass
  830.  
  831.  
  832.     
  833.     def close(self):
  834.         self.endtransfer()
  835.         
  836.         try:
  837.             self.ftp.close()
  838.         except ftperrors():
  839.             pass
  840.  
  841.  
  842.  
  843.  
  844. class addbase:
  845.     
  846.     def __init__(self, fp):
  847.         self.fp = fp
  848.         self.read = self.fp.read
  849.         self.readline = self.fp.readline
  850.         if hasattr(self.fp, 'readlines'):
  851.             self.readlines = self.fp.readlines
  852.         
  853.         if hasattr(self.fp, 'fileno'):
  854.             self.fileno = self.fp.fileno
  855.         
  856.  
  857.     
  858.     def __repr__(self):
  859.         return '<%s at %s whose fp = %s>' % (self.__class__.__name__, `id(self)`, `self.fp`)
  860.  
  861.     
  862.     def close(self):
  863.         self.read = None
  864.         self.readline = None
  865.         self.readlines = None
  866.         self.fileno = None
  867.         if self.fp:
  868.             self.fp.close()
  869.         
  870.         self.fp = None
  871.  
  872.  
  873.  
  874. class addclosehook(addbase):
  875.     
  876.     def __init__(self, fp, closehook, *hookargs):
  877.         addbase.__init__(self, fp)
  878.         self.closehook = closehook
  879.         self.hookargs = hookargs
  880.  
  881.     
  882.     def close(self):
  883.         addbase.close(self)
  884.         if self.closehook:
  885.             apply(self.closehook, self.hookargs)
  886.             self.closehook = None
  887.             self.hookargs = None
  888.         
  889.  
  890.  
  891.  
  892. class addinfo(addbase):
  893.     
  894.     def __init__(self, fp, headers):
  895.         addbase.__init__(self, fp)
  896.         self.headers = headers
  897.  
  898.     
  899.     def info(self):
  900.         return self.headers
  901.  
  902.  
  903.  
  904. class addinfourl(addbase):
  905.     
  906.     def __init__(self, fp, headers, url):
  907.         addbase.__init__(self, fp)
  908.         self.headers = headers
  909.         self.url = url
  910.  
  911.     
  912.     def info(self):
  913.         return self.headers
  914.  
  915.     
  916.     def geturl(self):
  917.         return self.url
  918.  
  919.  
  920.  
  921. def basejoin(base, url):
  922.     (type, path) = splittype(url)
  923.     if type:
  924.         return url
  925.     
  926.     (host, path) = splithost(path)
  927.     (type, basepath) = splittype(base)
  928.     if host:
  929.         if type:
  930.             return type + '://' + host + path
  931.         else:
  932.             return url
  933.     
  934.     (host, basepath) = splithost(basepath)
  935.     (basepath, basetag) = splittag(basepath)
  936.     (basepath, basequery) = splitquery(basepath)
  937.     if path[:1] != '/':
  938.         if path[:1] in ('#', '?'):
  939.             i = len(basepath)
  940.         else:
  941.             i = basepath.rfind('/')
  942.         if i < 0:
  943.             if host:
  944.                 basepath = '/'
  945.             else:
  946.                 basepath = ''
  947.         else:
  948.             basepath = basepath[:i + 1]
  949.         while basepath and path[:3] == '../':
  950.             path = path[3:]
  951.             i = basepath[:-1].rfind('/')
  952.             if i > 0:
  953.                 basepath = basepath[:i + 1]
  954.             elif i == 0:
  955.                 basepath = '/'
  956.                 break
  957.             else:
  958.                 basepath = ''
  959.         path = basepath + path
  960.     
  961.     if host and path and path[0] != '/':
  962.         path = '/' + path
  963.     
  964.     if type and host:
  965.         return type + '://' + host + path
  966.     elif type:
  967.         return type + ':' + path
  968.     elif host:
  969.         return '//' + host + path
  970.     else:
  971.         return path
  972.  
  973.  
  974. def toBytes(url):
  975.     if type(url) is types.UnicodeType:
  976.         
  977.         try:
  978.             url = url.encode('ASCII')
  979.         except UnicodeError:
  980.             raise UnicodeError('URL ' + repr(url) + ' contains non-ASCII characters')
  981.  
  982.     
  983.     return url
  984.  
  985.  
  986. def unwrap(url):
  987.     url = url.strip()
  988.     if url[:1] == '<' and url[-1:] == '>':
  989.         url = url[1:-1].strip()
  990.     
  991.     if url[:4] == 'URL:':
  992.         url = url[4:].strip()
  993.     
  994.     return url
  995.  
  996. _typeprog = None
  997.  
  998. def splittype(url):
  999.     global _typeprog
  1000.     if _typeprog is None:
  1001.         import re
  1002.         _typeprog = re.compile('^([^/:]+):')
  1003.     
  1004.     match = _typeprog.match(url)
  1005.     if match:
  1006.         scheme = match.group(1)
  1007.         return (scheme.lower(), url[len(scheme) + 1:])
  1008.     
  1009.     return (None, url)
  1010.  
  1011. _hostprog = None
  1012.  
  1013. def splithost(url):
  1014.     global _hostprog
  1015.     if _hostprog is None:
  1016.         import re
  1017.         _hostprog = re.compile('^//([^/]*)(.*)$')
  1018.     
  1019.     match = _hostprog.match(url)
  1020.     if match:
  1021.         return match.group(1, 2)
  1022.     
  1023.     return (None, url)
  1024.  
  1025. _userprog = None
  1026.  
  1027. def splituser(host):
  1028.     global _userprog
  1029.     if _userprog is None:
  1030.         import re
  1031.         _userprog = re.compile('^(.*)@(.*)$')
  1032.     
  1033.     match = _userprog.match(host)
  1034.     if match:
  1035.         return map(unquote, match.group(1, 2))
  1036.     
  1037.     return (None, host)
  1038.  
  1039. _passwdprog = None
  1040.  
  1041. def splitpasswd(user):
  1042.     global _passwdprog
  1043.     if _passwdprog is None:
  1044.         import re
  1045.         _passwdprog = re.compile('^([^:]*):(.*)$')
  1046.     
  1047.     match = _passwdprog.match(user)
  1048.     if match:
  1049.         return match.group(1, 2)
  1050.     
  1051.     return (user, None)
  1052.  
  1053. _portprog = None
  1054.  
  1055. def splitport(host):
  1056.     global _portprog
  1057.     if _portprog is None:
  1058.         import re
  1059.         _portprog = re.compile('^(.*):([0-9]+)$')
  1060.     
  1061.     match = _portprog.match(host)
  1062.     if match:
  1063.         return match.group(1, 2)
  1064.     
  1065.     return (host, None)
  1066.  
  1067. _nportprog = None
  1068.  
  1069. def splitnport(host, defport = -1):
  1070.     global _nportprog
  1071.     if _nportprog is None:
  1072.         import re
  1073.         _nportprog = re.compile('^(.*):(.*)$')
  1074.     
  1075.     match = _nportprog.match(host)
  1076.     if match:
  1077.         (host, port) = match.group(1, 2)
  1078.         
  1079.         try:
  1080.             if not port:
  1081.                 raise ValueError, 'no digits'
  1082.             
  1083.             nport = int(port)
  1084.         except ValueError:
  1085.             nport = None
  1086.  
  1087.         return (host, nport)
  1088.     
  1089.     return (host, defport)
  1090.  
  1091. _queryprog = None
  1092.  
  1093. def splitquery(url):
  1094.     global _queryprog
  1095.     if _queryprog is None:
  1096.         import re
  1097.         _queryprog = re.compile('^(.*)\\?([^?]*)$')
  1098.     
  1099.     match = _queryprog.match(url)
  1100.     if match:
  1101.         return match.group(1, 2)
  1102.     
  1103.     return (url, None)
  1104.  
  1105. _tagprog = None
  1106.  
  1107. def splittag(url):
  1108.     global _tagprog
  1109.     if _tagprog is None:
  1110.         import re
  1111.         _tagprog = re.compile('^(.*)#([^#]*)$')
  1112.     
  1113.     match = _tagprog.match(url)
  1114.     if match:
  1115.         return match.group(1, 2)
  1116.     
  1117.     return (url, None)
  1118.  
  1119.  
  1120. def splitattr(url):
  1121.     words = url.split(';')
  1122.     return (words[0], words[1:])
  1123.  
  1124. _valueprog = None
  1125.  
  1126. def splitvalue(attr):
  1127.     global _valueprog
  1128.     if _valueprog is None:
  1129.         import re
  1130.         _valueprog = re.compile('^([^=]*)=(.*)$')
  1131.     
  1132.     match = _valueprog.match(attr)
  1133.     if match:
  1134.         return match.group(1, 2)
  1135.     
  1136.     return (attr, None)
  1137.  
  1138.  
  1139. def splitgophertype(selector):
  1140.     if selector[:1] == '/' and selector[1:2]:
  1141.         return (selector[1], selector[2:])
  1142.     
  1143.     return (None, selector)
  1144.  
  1145.  
  1146. def unquote(s):
  1147.     mychr = chr
  1148.     myatoi = int
  1149.     list = s.split('%')
  1150.     res = [
  1151.         list[0]]
  1152.     myappend = res.append
  1153.     del list[0]
  1154.     for item in list:
  1155.         if item[1:2]:
  1156.             
  1157.             try:
  1158.                 myappend(mychr(myatoi(item[:2], 16)) + item[2:])
  1159.             except ValueError:
  1160.                 myappend('%' + item)
  1161.  
  1162.         else:
  1163.             myappend('%' + item)
  1164.     
  1165.     return ''.join(res)
  1166.  
  1167.  
  1168. def unquote_plus(s):
  1169.     if '+' in s:
  1170.         s = ' '.join(s.split('+'))
  1171.     
  1172.     return unquote(s)
  1173.  
  1174. always_safe = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.-'
  1175. _fast_safe_test = always_safe + '/'
  1176. _fast_safe = None
  1177.  
  1178. def _fast_quote(s):
  1179.     global _fast_safe
  1180.     if _fast_safe is None:
  1181.         _fast_safe = { }
  1182.         for c in _fast_safe_test:
  1183.             _fast_safe[c] = c
  1184.         
  1185.     
  1186.     res = list(s)
  1187.     for i in range(len(res)):
  1188.         c = res[i]
  1189.         if not _fast_safe.has_key(c):
  1190.             res[i] = '%%%02X' % ord(c)
  1191.         
  1192.     
  1193.     return ''.join(res)
  1194.  
  1195.  
  1196. def quote(s, safe = '/'):
  1197.     safe = always_safe + safe
  1198.     if _fast_safe_test == safe:
  1199.         return _fast_quote(s)
  1200.     
  1201.     res = list(s)
  1202.     for i in range(len(res)):
  1203.         c = res[i]
  1204.         if c not in safe:
  1205.             res[i] = '%%%02X' % ord(c)
  1206.         
  1207.     
  1208.     return ''.join(res)
  1209.  
  1210.  
  1211. def quote_plus(s, safe = ''):
  1212.     if ' ' in s:
  1213.         l = s.split(' ')
  1214.         for i in range(len(l)):
  1215.             l[i] = quote(l[i], safe)
  1216.         
  1217.         return '+'.join(l)
  1218.     else:
  1219.         return quote(s, safe)
  1220.  
  1221.  
  1222. def urlencode(query, doseq = 0):
  1223.     if hasattr(query, 'items'):
  1224.         query = query.items()
  1225.     else:
  1226.         
  1227.         try:
  1228.             x = len(query)
  1229.             if len(query) and type(query[0]) != types.TupleType:
  1230.                 raise TypeError
  1231.         except TypeError:
  1232.             (ty, va, tb) = sys.exc_info()
  1233.             raise TypeError, 'not a valid non-string sequence or mapping object', tb
  1234.  
  1235.     l = []
  1236.     if not doseq:
  1237.         for k, v in query:
  1238.             k = quote_plus(str(k))
  1239.             v = quote_plus(str(v))
  1240.             l.append(k + '=' + v)
  1241.         
  1242.     else:
  1243.         for k, v in query:
  1244.             k = quote_plus(str(k))
  1245.             if type(v) == types.StringType:
  1246.                 v = quote_plus(v)
  1247.                 l.append(k + '=' + v)
  1248.             elif type(v) == types.UnicodeType:
  1249.                 v = quote_plus(v.encode('ASCII', 'replace'))
  1250.                 l.append(k + '=' + v)
  1251.             else:
  1252.                 
  1253.                 try:
  1254.                     x = len(v)
  1255.                 except TypeError:
  1256.                     v = quote_plus(str(v))
  1257.                     l.append(k + '=' + v)
  1258.  
  1259.                 for elt in v:
  1260.                     l.append(k + '=' + quote_plus(str(elt)))
  1261.                 
  1262.         
  1263.     return '&'.join(l)
  1264.  
  1265.  
  1266. def getproxies_environment():
  1267.     proxies = { }
  1268.     for name, value in os.environ.items():
  1269.         name = name.lower()
  1270.         if value and name[-6:] == '_proxy':
  1271.             proxies[name[:-6]] = value
  1272.         
  1273.     
  1274.     return proxies
  1275.  
  1276. if os.name == 'mac':
  1277.     
  1278.     def getproxies():
  1279.         
  1280.         try:
  1281.             import ic
  1282.         except ImportError:
  1283.             return { }
  1284.  
  1285.         
  1286.         try:
  1287.             config = ic.IC()
  1288.         except ic.error:
  1289.             return { }
  1290.  
  1291.         proxies = { }
  1292.         if config.has_key('UseHTTPProxy') and config['UseHTTPProxy']:
  1293.             
  1294.             try:
  1295.                 value = config['HTTPProxyHost']
  1296.             except ic.error:
  1297.                 pass
  1298.  
  1299.             proxies['http'] = 'http://%s' % value
  1300.         
  1301.         return proxies
  1302.  
  1303.     
  1304.     def proxy_bypass(x):
  1305.         return 0
  1306.  
  1307. elif os.name == 'nt':
  1308.     
  1309.     def getproxies_registry():
  1310.         proxies = { }
  1311.         
  1312.         try:
  1313.             import _winreg
  1314.         except ImportError:
  1315.             return proxies
  1316.  
  1317.         
  1318.         try:
  1319.             internetSettings = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, 'Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings')
  1320.             proxyEnable = _winreg.QueryValueEx(internetSettings, 'ProxyEnable')[0]
  1321.             if proxyEnable:
  1322.                 proxyServer = str(_winreg.QueryValueEx(internetSettings, 'ProxyServer')[0])
  1323.                 if '=' in proxyServer:
  1324.                     for p in proxyServer.split(';'):
  1325.                         (protocol, address) = p.split('=', 1)
  1326.                         import re
  1327.                         if not re.match('^([^/:]+)://', address):
  1328.                             address = '%s://%s' % (protocol, address)
  1329.                         
  1330.                         proxies[protocol] = address
  1331.                     
  1332.                 elif proxyServer[:5] == 'http:':
  1333.                     proxies['http'] = proxyServer
  1334.                 else:
  1335.                     proxies['http'] = 'http://%s' % proxyServer
  1336.                     proxies['ftp'] = 'ftp://%s' % proxyServer
  1337.             
  1338.             internetSettings.Close()
  1339.         except (WindowsError, ValueError, TypeError):
  1340.             pass
  1341.  
  1342.         return proxies
  1343.  
  1344.     
  1345.     def getproxies():
  1346.         if not getproxies_environment():
  1347.             pass
  1348.         return getproxies_registry()
  1349.  
  1350.     
  1351.     def proxy_bypass(host):
  1352.         
  1353.         try:
  1354.             import _winreg
  1355.             import re
  1356.             import socket
  1357.         except ImportError:
  1358.             return 0
  1359.  
  1360.         
  1361.         try:
  1362.             internetSettings = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, 'Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings')
  1363.             proxyEnable = _winreg.QueryValueEx(internetSettings, 'ProxyEnable')[0]
  1364.             proxyOverride = str(_winreg.QueryValueEx(internetSettings, 'ProxyOverride')[0])
  1365.         except WindowsError:
  1366.             return 0
  1367.  
  1368.         if not proxyEnable or not proxyOverride:
  1369.             return 0
  1370.         
  1371.         host = [
  1372.             host]
  1373.         
  1374.         try:
  1375.             addr = socket.gethostbyname(host[0])
  1376.             if addr != host:
  1377.                 host.append(addr)
  1378.         except socket.error:
  1379.             pass
  1380.  
  1381.         proxyOverride = proxyOverride.split(';')
  1382.         i = 0
  1383.         while i < len(proxyOverride):
  1384.             if proxyOverride[i] == '<local>':
  1385.                 proxyOverride[i:i + 1] = [
  1386.                     'localhost',
  1387.                     '127.0.0.1',
  1388.                     socket.gethostname(),
  1389.                     socket.gethostbyname(socket.gethostname())]
  1390.             
  1391.             i += 1
  1392.         for test in proxyOverride:
  1393.             test = test.replace('.', '\\.')
  1394.             test = test.replace('*', '.*')
  1395.             test = test.replace('?', '.')
  1396.             for val in host:
  1397.                 if re.match(test, val, re.I):
  1398.                     return 1
  1399.                 
  1400.             
  1401.         
  1402.         return 0
  1403.  
  1404. else:
  1405.     getproxies = getproxies_environment
  1406.     
  1407.     def proxy_bypass(host):
  1408.         return 0
  1409.  
  1410.  
  1411. def test1():
  1412.     import time
  1413.     s = ''
  1414.     for i in range(256):
  1415.         s = s + chr(i)
  1416.     
  1417.     s = s * 4
  1418.     t0 = time.time()
  1419.     qs = quote(s)
  1420.     uqs = unquote(qs)
  1421.     t1 = time.time()
  1422.     if uqs != s:
  1423.         print 'Wrong!'
  1424.     
  1425.     print `s`
  1426.     print `qs`
  1427.     print `uqs`
  1428.     print round(t1 - t0, 3), 'sec'
  1429.  
  1430.  
  1431. def reporthook(blocknum, blocksize, totalsize):
  1432.     print 'Block number: %d, Block size: %d, Total size: %d' % (blocknum, blocksize, totalsize)
  1433.  
  1434.  
  1435. def test(args = []):
  1436.     if not args:
  1437.         args = [
  1438.             '/etc/passwd',
  1439.             'file:/etc/passwd',
  1440.             'file://localhost/etc/passwd',
  1441.             'ftp://ftp.python.org/pub/python/README',
  1442.             'http://www.python.org/index.html']
  1443.         if hasattr(URLopener, 'open_https'):
  1444.             args.append('https://synergy.as.cmu.edu/~geek/')
  1445.         
  1446.     
  1447.     
  1448.     try:
  1449.         for url in args:
  1450.             print '-' * 10, url, '-' * 10
  1451.             (fn, h) = urlretrieve(url, None, reporthook)
  1452.             print fn
  1453.             if h:
  1454.                 print '======'
  1455.                 for k in h.keys():
  1456.                     print k + ':', h[k]
  1457.                 
  1458.                 print '======'
  1459.             
  1460.             fp = open(fn, 'rb')
  1461.             data = fp.read()
  1462.             del fp
  1463.             if '\r' in data:
  1464.                 table = string.maketrans('', '')
  1465.                 data = data.translate(table, '\r')
  1466.             
  1467.             print data
  1468.             (fn, h) = (None, None)
  1469.         
  1470.         print '-' * 40
  1471.     finally:
  1472.         urlcleanup()
  1473.  
  1474.  
  1475.  
  1476. def main():
  1477.     import getopt
  1478.     import sys
  1479.     
  1480.     try:
  1481.         (opts, args) = getopt.getopt(sys.argv[1:], 'th')
  1482.     except getopt.error:
  1483.         msg = None
  1484.         print msg
  1485.         print 'Use -h for help'
  1486.         return None
  1487.  
  1488.     t = 0
  1489.     for o, a in opts:
  1490.         if o == '-t':
  1491.             t = t + 1
  1492.         
  1493.         if o == '-h':
  1494.             print 'Usage: python urllib.py [-t] [url ...]'
  1495.             print '-t runs self-test;', 'otherwise, contents of urls are printed'
  1496.             return None
  1497.         
  1498.     
  1499.     if t:
  1500.         if t > 1:
  1501.             test1()
  1502.         
  1503.         test(args)
  1504.     elif not args:
  1505.         print 'Use -h for help'
  1506.     
  1507.     for url in args:
  1508.         print urlopen(url).read(),
  1509.     
  1510.  
  1511. if __name__ == '__main__':
  1512.     main()
  1513.  
  1514.