home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyos2bin.zip / Lib / gopherlib.py < prev    next >
Text File  |  1996-02-14  |  4KB  |  192 lines

  1. # Gopher protocol client interface
  2.  
  3. import string
  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. # Function mapping all file types to strings; unknown types become TYPE='x'
  40. _names = dir()
  41. _type_to_name_map = None
  42. def type_to_name(gtype):
  43.     global _type_to_name_map
  44.     if not _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 _type_to_name_map.has_key(gtype):
  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. # Send a selector to a given host and port, return a file with the reply
  57. def send_selector(selector, host, port = 0):
  58.     import socket
  59.     import string
  60.     if not port:
  61.         i = string.find(host, ':')
  62.         if i >= 0:
  63.             host, port = host[:i], string.atoi(host[i+1:])
  64.     if not port:
  65.         port = DEF_PORT
  66.     elif type(port) == type(''):
  67.         port = string.atoi(port)
  68.     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  69.     s.connect(host, port)
  70.     s.send(selector + CRLF)
  71.     s.shutdown(1)
  72.     return s.makefile('rb')
  73.  
  74. # Send a selector and a query string
  75. def send_query(selector, query, host, port = 0):
  76.     return send_selector(selector + '\t' + query, host, port)
  77.  
  78. # The following functions interpret the data returned by the gopher
  79. # server according to the expected type, e.g. textfile or directory
  80.  
  81. # Get a directory in the form of a list of entries
  82. def get_directory(f):
  83.     import string
  84.     list = []
  85.     while 1:
  86.         line = f.readline()
  87.         if not line:
  88.             print '(Unexpected EOF from server)'
  89.             break
  90.         if line[-2:] == CRLF:
  91.             line = line[:-2]
  92.         elif line[-1:] in CRLF:
  93.             line = line[:-1]
  94.         if line == '.':
  95.             break
  96.         if not line:
  97.             print '(Empty line from server)'
  98.             continue
  99.         gtype = line[0]
  100.         parts = string.splitfields(line[1:], TAB)
  101.         if len(parts) < 4:
  102.             print '(Bad line from server:', `line`, ')'
  103.             continue
  104.         if len(parts) > 4:
  105.             if parts[4:] != ['+']:
  106.                 print '(Extra info from server:', parts[4:], ')'
  107.         else:
  108.             parts.append('')
  109.         parts.insert(0, gtype)
  110.         list.append(parts)
  111.     return list
  112.  
  113. # Get a text file as a list of lines, with trailing CRLF stripped
  114. def get_textfile(f):
  115.     list = []
  116.     get_alt_textfile(f, list.append)
  117.     return list
  118.  
  119. # Get a text file and pass each line to a function, with trailing CRLF stripped
  120. def get_alt_textfile(f, func):
  121.     while 1:
  122.         line = f.readline()
  123.         if not line:
  124.             print '(Unexpected EOF from server)'
  125.             break
  126.         if line[-2:] == CRLF:
  127.             line = line[:-2]
  128.         elif line[-1:] in CRLF:
  129.             line = line[:-1]
  130.         if line == '.':
  131.             break
  132.         if line[:2] == '..':
  133.             line = line[1:]
  134.         func(line)
  135.  
  136. # Get a binary file as one solid data block
  137. def get_binary(f):
  138.     data = f.read()
  139.     return data
  140.  
  141. # Get a binary file and pass each block to a function
  142. def get_alt_binary(f, func, blocksize):
  143.     while 1:
  144.         data = f.read(blocksize)
  145.         if not data:
  146.             break
  147.         func(data)
  148.  
  149. # Trivial test program
  150. def test():
  151.     import sys
  152.     import getopt
  153.     opts, args = getopt.getopt(sys.argv[1:], '')
  154.     selector = DEF_SELECTOR
  155.     type = selector[0]
  156.     host = DEF_HOST
  157.     port = DEF_PORT
  158.     if args:
  159.         host = args[0]
  160.         args = args[1:]
  161.     if args:
  162.         type = args[0]
  163.         args = args[1:]
  164.         if len(type) > 1:
  165.             type, selector = type[0], type
  166.         else:
  167.             selector = ''
  168.             if args:
  169.                 selector = args[0]
  170.                 args = args[1:]
  171.         query = ''
  172.         if args:
  173.             query = args[0]
  174.             args = args[1:]
  175.     if type == A_INDEX:
  176.         f = send_query(selector, query, host)
  177.     else:
  178.         f = send_selector(selector, host)
  179.     if type == A_TEXT:
  180.         list = get_textfile(f)
  181.         for item in list: print item
  182.     elif type in (A_MENU, A_INDEX):
  183.         list = get_directory(f)
  184.         for item in list: print item
  185.     else:
  186.         data = get_binary(f)
  187.         print 'binary data:', len(data), 'bytes:', `data[:100]`[:40]
  188.  
  189. # Run the test when run as script
  190. if __name__ == '__main__':
  191.     test()
  192.