home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 June / PCWorld_2005-06_cd.bin / software / vyzkuste / firewally / firewally.exe / framework-2.3.exe / gopherlib.py < prev    next >
Text File  |  2003-12-30  |  6KB  |  206 lines

  1. """Gopher protocol client interface."""
  2.  
  3. __all__ = ["send_selector","send_query"]
  4.  
  5. # Default selector, host and port
  6. DEF_SELECTOR = '1/'
  7. DEF_HOST     = 'gopher.micro.umn.edu'
  8. DEF_PORT     = 70
  9.  
  10. # Recognized file types
  11. A_TEXT       = '0'
  12. A_MENU       = '1'
  13. A_CSO        = '2'
  14. A_ERROR      = '3'
  15. A_MACBINHEX  = '4'
  16. A_PCBINHEX   = '5'
  17. A_UUENCODED  = '6'
  18. A_INDEX      = '7'
  19. A_TELNET     = '8'
  20. A_BINARY     = '9'
  21. A_DUPLICATE  = '+'
  22. A_SOUND      = 's'
  23. A_EVENT      = 'e'
  24. A_CALENDAR   = 'c'
  25. A_HTML       = 'h'
  26. A_TN3270     = 'T'
  27. A_MIME       = 'M'
  28. A_IMAGE      = 'I'
  29. A_WHOIS      = 'w'
  30. A_QUERY      = 'q'
  31. A_GIF        = 'g'
  32. A_HTML       = 'h'          # HTML file
  33. A_WWW        = 'w'          # WWW address
  34. A_PLUS_IMAGE = ':'
  35. A_PLUS_MOVIE = ';'
  36. A_PLUS_SOUND = '<'
  37.  
  38.  
  39. _names = dir()
  40. _type_to_name_map = {}
  41. def type_to_name(gtype):
  42.     """Map all file types to strings; unknown types become TYPE='x'."""
  43.     global _type_to_name_map
  44.     if _type_to_name_map=={}:
  45.         for name in _names:
  46.             if name[:2] == 'A_':
  47.                 _type_to_name_map[eval(name)] = name[2:]
  48.     if gtype in _type_to_name_map:
  49.         return _type_to_name_map[gtype]
  50.     return 'TYPE=' + `gtype`
  51.  
  52. # Names for characters and strings
  53. CRLF = '\r\n'
  54. TAB = '\t'
  55.  
  56. def send_selector(selector, host, port = 0):
  57.     """Send a selector to a given host and port, return a file with the reply."""
  58.     import socket
  59.     if not port:
  60.         i = host.find(':')
  61.         if i >= 0:
  62.             host, port = host[:i], int(host[i+1:])
  63.     if not port:
  64.         port = DEF_PORT
  65.     elif type(port) == type(''):
  66.         port = int(port)
  67.     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  68.     s.connect((host, port))
  69.     s.sendall(selector + CRLF)
  70.     s.shutdown(1)
  71.     return s.makefile('rb')
  72.  
  73. def send_query(selector, query, host, port = 0):
  74.     """Send a selector and a query string."""
  75.     return send_selector(selector + '\t' + query, host, port)
  76.  
  77. def path_to_selector(path):
  78.     """Takes a path as returned by urlparse and returns the appropriate selector."""
  79.     if path=="/":
  80.         return "/"
  81.     else:
  82.         return path[2:] # Cuts initial slash and data type identifier
  83.  
  84. def path_to_datatype_name(path):
  85.     """Takes a path as returned by urlparse and maps it to a string.
  86.     See section 3.4 of RFC 1738 for details."""
  87.     if path=="/":
  88.         # No way to tell, although "INDEX" is likely
  89.         return "TYPE='unknown'"
  90.     else:
  91.         return type_to_name(path[1])
  92.  
  93. # The following functions interpret the data returned by the gopher
  94. # server according to the expected type, e.g. textfile or directory
  95.  
  96. def get_directory(f):
  97.     """Get a directory in the form of a list of entries."""
  98.     entries = []
  99.     while 1:
  100.         line = f.readline()
  101.         if not line:
  102.             print '(Unexpected EOF from server)'
  103.             break
  104.         if line[-2:] == CRLF:
  105.             line = line[:-2]
  106.         elif line[-1:] in CRLF:
  107.             line = line[:-1]
  108.         if line == '.':
  109.             break
  110.         if not line:
  111.             print '(Empty line from server)'
  112.             continue
  113.         gtype = line[0]
  114.         parts = line[1:].split(TAB)
  115.         if len(parts) < 4:
  116.             print '(Bad line from server:', `line`, ')'
  117.             continue
  118.         if len(parts) > 4:
  119.             if parts[4:] != ['+']:
  120.                 print '(Extra info from server:',
  121.                 print parts[4:], ')'
  122.         else:
  123.             parts.append('')
  124.         parts.insert(0, gtype)
  125.         entries.append(parts)
  126.     return entries
  127.  
  128. def get_textfile(f):
  129.     """Get a text file as a list of lines, with trailing CRLF stripped."""
  130.     lines = []
  131.     get_alt_textfile(f, lines.append)
  132.     return lines
  133.  
  134. def get_alt_textfile(f, func):
  135.     """Get a text file and pass each line to a function, with trailing CRLF stripped."""
  136.     while 1:
  137.         line = f.readline()
  138.         if not line:
  139.             print '(Unexpected EOF from server)'
  140.             break
  141.         if line[-2:] == CRLF:
  142.             line = line[:-2]
  143.         elif line[-1:] in CRLF:
  144.             line = line[:-1]
  145.         if line == '.':
  146.             break
  147.         if line[:2] == '..':
  148.             line = line[1:]
  149.         func(line)
  150.  
  151. def get_binary(f):
  152.     """Get a binary file as one solid data block."""
  153.     data = f.read()
  154.     return data
  155.  
  156. def get_alt_binary(f, func, blocksize):
  157.     """Get a binary file and pass each block to a function."""
  158.     while 1:
  159.         data = f.read(blocksize)
  160.         if not data:
  161.             break
  162.         func(data)
  163.  
  164. def test():
  165.     """Trivial test program."""
  166.     import sys
  167.     import getopt
  168.     opts, args = getopt.getopt(sys.argv[1:], '')
  169.     selector = DEF_SELECTOR
  170.     type = selector[0]
  171.     host = DEF_HOST
  172.     if args:
  173.         host = args[0]
  174.         args = args[1:]
  175.     if args:
  176.         type = args[0]
  177.         args = args[1:]
  178.         if len(type) > 1:
  179.             type, selector = type[0], type
  180.         else:
  181.             selector = ''
  182.             if args:
  183.                 selector = args[0]
  184.                 args = args[1:]
  185.         query = ''
  186.         if args:
  187.             query = args[0]
  188.             args = args[1:]
  189.     if type == A_INDEX:
  190.         f = send_query(selector, query, host)
  191.     else:
  192.         f = send_selector(selector, host)
  193.     if type == A_TEXT:
  194.         lines = get_textfile(f)
  195.         for item in lines: print item
  196.     elif type in (A_MENU, A_INDEX):
  197.         entries = get_directory(f)
  198.         for item in entries: print item
  199.     else:
  200.         data = get_binary(f)
  201.         print 'binary data:', len(data), 'bytes:', `data[:100]`[:40]
  202.  
  203. # Run the test when run as script
  204. if __name__ == '__main__':
  205.     test()
  206.