home *** CD-ROM | disk | FTP | other *** search
/ Netrunner 2004 October / NETRUNNER0410.ISO / regular / iria107a.lzh / script / urlparse.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2000-11-17  |  8.6 KB  |  311 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.0)
  3.  
  4. '''Parse (absolute and relative) URLs.
  5.  
  6. See RFC 1808: "Relative Uniform Resource Locators", by R. Fielding,
  7. UC Irvine, June 1995.
  8. '''
  9. import string
  10. from string import join, split, rfind
  11. uses_relative = [
  12.     'ftp',
  13.     'http',
  14.     'gopher',
  15.     'nntp',
  16.     'wais',
  17.     'file',
  18.     'https',
  19.     'shttp',
  20.     'prospero',
  21.     'rtsp',
  22.     'rtspu',
  23.     '']
  24. uses_netloc = [
  25.     'ftp',
  26.     'http',
  27.     'gopher',
  28.     'nntp',
  29.     'telnet',
  30.     'wais',
  31.     'file',
  32.     'https',
  33.     'shttp',
  34.     'snews',
  35.     'prospero',
  36.     'rtsp',
  37.     'rtspu',
  38.     '']
  39. non_hierarchical = [
  40.     'gopher',
  41.     'hdl',
  42.     'mailto',
  43.     'news',
  44.     'telnet',
  45.     'wais',
  46.     'snews',
  47.     'sip']
  48. uses_params = [
  49.     'ftp',
  50.     'hdl',
  51.     'prospero',
  52.     'http',
  53.     'https',
  54.     'shttp',
  55.     'rtsp',
  56.     'rtspu',
  57.     'sip',
  58.     '']
  59. uses_query = [
  60.     'http',
  61.     'wais',
  62.     'https',
  63.     'shttp',
  64.     'gopher',
  65.     'rtsp',
  66.     'rtspu',
  67.     'sip',
  68.     '']
  69. uses_fragment = [
  70.     'ftp',
  71.     'hdl',
  72.     'http',
  73.     'gopher',
  74.     'news',
  75.     'nntp',
  76.     'wais',
  77.     'https',
  78.     'shttp',
  79.     'snews',
  80.     'file',
  81.     'prospero',
  82.     '']
  83. scheme_chars = string.letters + string.digits + '+-.'
  84. MAX_CACHE_SIZE = 20
  85. _parse_cache = { }
  86.  
  87. def clear_cache():
  88.     '''Clear the parse cache.'''
  89.     global _parse_cache
  90.     _parse_cache = { }
  91.  
  92.  
  93. def urlparse(url, scheme = '', allow_fragments = 1):
  94.     """Parse a URL into 6 components:
  95. \t<scheme>://<netloc>/<path>;<params>?<query>#<fragment>
  96. \tReturn a 6-tuple: (scheme, netloc, path, params, query, fragment).
  97. \tNote that we don't break the components up in smaller bits
  98. \t(e.g. netloc is a single string) and we don't expand % escapes."""
  99.     key = (url, scheme, allow_fragments)
  100.     cached = _parse_cache.get(key, None)
  101.     if cached:
  102.         return cached
  103.     
  104.     if len(_parse_cache) >= MAX_CACHE_SIZE:
  105.         clear_cache()
  106.     
  107.     find = string.find
  108.     netloc = path = params = query = fragment = ''
  109.     i = find(url, ':')
  110.     if i > 0:
  111.         if url[:i] == 'http':
  112.             scheme = string.lower(url[:i])
  113.             url = url[i + 1:]
  114.             if url[:2] == '//':
  115.                 i = find(url, '/', 2)
  116.                 if i < 0:
  117.                     i = len(url)
  118.                 
  119.                 netloc = url[2:i]
  120.                 url = url[i:]
  121.             
  122.             if allow_fragments:
  123.                 i = string.rfind(url, '#')
  124.                 if i >= 0:
  125.                     fragment = url[i + 1:]
  126.                     url = url[:i]
  127.                 
  128.             
  129.             i = find(url, '?')
  130.             if i >= 0:
  131.                 query = url[i + 1:]
  132.                 url = url[:i]
  133.             
  134.             i = find(url, ';')
  135.             if i >= 0:
  136.                 params = url[i + 1:]
  137.                 url = url[:i]
  138.             
  139.             tuple = (scheme, netloc, url, params, query, fragment)
  140.             _parse_cache[key] = tuple
  141.             return tuple
  142.         
  143.         for c in url[:i]:
  144.             pass
  145.         else:
  146.             (scheme, url) = (string.lower(url[:i]), url[i + 1:])
  147.     
  148.     if scheme in uses_netloc:
  149.         if url[:2] == '//':
  150.             i = find(url, '/', 2)
  151.             if i < 0:
  152.                 i = len(url)
  153.             
  154.             (netloc, url) = (url[2:i], url[i:])
  155.         
  156.     
  157.     if allow_fragments and scheme in uses_fragment:
  158.         i = string.rfind(url, '#')
  159.         if i >= 0:
  160.             (url, fragment) = (url[:i], url[i + 1:])
  161.         
  162.     
  163.     if scheme in uses_query:
  164.         i = find(url, '?')
  165.         if i >= 0:
  166.             (url, query) = (url[:i], url[i + 1:])
  167.         
  168.     
  169.     if scheme in uses_params:
  170.         i = find(url, ';')
  171.         if i >= 0:
  172.             (url, params) = (url[:i], url[i + 1:])
  173.         
  174.     
  175.     tuple = (scheme, netloc, url, params, query, fragment)
  176.     _parse_cache[key] = tuple
  177.     return tuple
  178.  
  179.  
  180. def urlunparse(.0):
  181.     '''Put a parsed URL back together again.  This may result in a
  182. \tslightly different, but equivalent URL, if the URL that was parsed
  183. \toriginally had redundant delimiters, e.g. a ? with an empty query
  184. \t(the draft states that these are equivalent).'''
  185.     (scheme, netloc, url, params, query, fragment) = .0
  186.     if netloc and scheme in uses_netloc and url[:2] == '//':
  187.         if url[:1] != '/':
  188.             url = '/' + url
  189.         
  190.         if not netloc:
  191.             pass
  192.         url = '//' + '' + url
  193.     
  194.     if scheme:
  195.         url = scheme + ':' + url
  196.     
  197.     if params:
  198.         url = url + ';' + params
  199.     
  200.     if query:
  201.         url = url + '?' + query
  202.     
  203.     if fragment:
  204.         url = url + '#' + fragment
  205.     
  206.     return url
  207.  
  208.  
  209. def urljoin(base, url, allow_fragments = 1):
  210.     '''Join a base URL and a possibly relative URL to form an absolute
  211. \tinterpretation of the latter.'''
  212.     if not base:
  213.         return url
  214.     
  215.     (bscheme, bnetloc, bpath, bparams, bquery, bfragment) = urlparse(base, '', allow_fragments)
  216.     (scheme, netloc, path, params, query, fragment) = urlparse(url, bscheme, allow_fragments)
  217.     if scheme != bscheme or scheme not in uses_relative:
  218.         return urlunparse((scheme, netloc, path, params, query, fragment))
  219.     
  220.     if scheme in uses_netloc:
  221.         if netloc:
  222.             return urlunparse((scheme, netloc, path, params, query, fragment))
  223.         
  224.         netloc = bnetloc
  225.     
  226.     if path[:1] == '/':
  227.         return urlunparse((scheme, netloc, path, params, query, fragment))
  228.     
  229.     if not path:
  230.         if not query:
  231.             pass
  232.         return urlunparse((scheme, netloc, bpath, params, bquery, fragment))
  233.     
  234.     segments = split(bpath, '/')[:-1] + split(path, '/')
  235.     if segments[-1] == '.':
  236.         segments[-1] = ''
  237.     
  238.     while '.' in segments:
  239.         segments.remove('.')
  240.     while 1:
  241.         i = 1
  242.         n = len(segments) - 1
  243.         while i < n:
  244.             if segments[i] == '..' and segments[i - 1]:
  245.                 del segments[i - 1:i + 1]
  246.                 break
  247.             
  248.             i = i + 1
  249.         break
  250.     if len(segments) == 2 and segments[1] == '..' and segments[0] == '':
  251.         segments[-1] = ''
  252.     elif len(segments) >= 2 and segments[-1] == '..':
  253.         segments[-2:] = [
  254.             '']
  255.     
  256.     return urlunparse((scheme, netloc, join(segments, '/'), params, query, fragment))
  257.  
  258.  
  259. def urldefrag(url):
  260.     '''Removes any existing fragment from URL.
  261.  
  262. \tReturns a tuple of the defragmented URL and the fragment.  If
  263. \tthe URL contained no fragments, the second element is the
  264. \tempty string.
  265. \t'''
  266.     (s, n, p, a, q, frag) = urlparse(url)
  267.     defrag = urlunparse((s, n, p, a, q, ''))
  268.     return (defrag, frag)
  269.  
  270. test_input = '\n      http://a/b/c/d\n\n      g:h        = <URL:g:h>\n      http:g     = <URL:http://a/b/c/g>\n      http:      = <URL:http://a/b/c/d>\n      g          = <URL:http://a/b/c/g>\n      ./g        = <URL:http://a/b/c/g>\n      g/         = <URL:http://a/b/c/g/>\n      /g         = <URL:http://a/g>\n      //g        = <URL:http://g>\n      ?y         = <URL:http://a/b/c/d?y>\n      g?y        = <URL:http://a/b/c/g?y>\n      g?y/./x    = <URL:http://a/b/c/g?y/./x>\n      .          = <URL:http://a/b/c/>\n      ./         = <URL:http://a/b/c/>\n      ..         = <URL:http://a/b/>\n      ../        = <URL:http://a/b/>\n      ../g       = <URL:http://a/b/g>\n      ../..      = <URL:http://a/>\n      ../../g    = <URL:http://a/g>\n      ../../../g = <URL:http://a/../g>\n      ./../g     = <URL:http://a/b/g>\n      ./g/.      = <URL:http://a/b/c/g/>\n      /./g       = <URL:http://a/./g>\n      g/./h      = <URL:http://a/b/c/g/h>\n      g/../h     = <URL:http://a/b/c/h>\n      http:g     = <URL:http://a/b/c/g>\n      http:      = <URL:http://a/b/c/d>\n      http:?y         = <URL:http://a/b/c/d?y>\n      http:g?y        = <URL:http://a/b/c/g?y>\n      http:g?y/./x    = <URL:http://a/b/c/g?y/./x>\n'
  271.  
  272. def test():
  273.     import sys
  274.     base = ''
  275.     if sys.argv[1:]:
  276.         fn = sys.argv[1]
  277.         if fn == '-':
  278.             fp = sys.stdin
  279.         else:
  280.             fp = open(fn)
  281.     else:
  282.         import StringIO
  283.         fp = StringIO.StringIO(test_input)
  284.     while 1:
  285.         line = fp.readline()
  286.         if not line:
  287.             break
  288.         
  289.         words = string.split(line)
  290.         if not words:
  291.             continue
  292.         
  293.         url = words[0]
  294.         parts = urlparse(url)
  295.         print '%-10s : %s' % (url, parts)
  296.         abs = urljoin(base, url)
  297.         if not base:
  298.             base = abs
  299.         
  300.         wrapped = '<URL:%s>' % abs
  301.         print '%-10s = %s' % (url, wrapped)
  302.         if len(words) == 3 and words[1] == '=':
  303.             if wrapped != words[2]:
  304.                 print 'EXPECTED', words[2], '!!!!!!!!!!'
  305.             
  306.         
  307.  
  308. if __name__ == '__main__':
  309.     test()
  310.  
  311.