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