symbian-qemu-0.9.1-12/python-2.6.1/Demo/sockets/gopher.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 #! /usr/bin/env python
       
     2 
       
     3 # A simple gopher client.
       
     4 #
       
     5 # Usage: gopher [ [selector] host [port] ]
       
     6 
       
     7 import string
       
     8 import sys
       
     9 import os
       
    10 import socket
       
    11 
       
    12 # Default selector, host and port
       
    13 DEF_SELECTOR = ''
       
    14 DEF_HOST     = 'gopher.micro.umn.edu'
       
    15 DEF_PORT     = 70
       
    16 
       
    17 # Recognized file types
       
    18 T_TEXTFILE  = '0'
       
    19 T_MENU      = '1'
       
    20 T_CSO       = '2'
       
    21 T_ERROR     = '3'
       
    22 T_BINHEX    = '4'
       
    23 T_DOS       = '5'
       
    24 T_UUENCODE  = '6'
       
    25 T_SEARCH    = '7'
       
    26 T_TELNET    = '8'
       
    27 T_BINARY    = '9'
       
    28 T_REDUNDANT = '+'
       
    29 T_SOUND     = 's'
       
    30 
       
    31 # Dictionary mapping types to strings
       
    32 typename = {'0': '<TEXT>', '1': '<DIR>', '2': '<CSO>', '3': '<ERROR>', \
       
    33         '4': '<BINHEX>', '5': '<DOS>', '6': '<UUENCODE>', '7': '<SEARCH>', \
       
    34         '8': '<TELNET>', '9': '<BINARY>', '+': '<REDUNDANT>', 's': '<SOUND>'}
       
    35 
       
    36 # Oft-used characters and strings
       
    37 CRLF = '\r\n'
       
    38 TAB = '\t'
       
    39 
       
    40 # Open a TCP connection to a given host and port
       
    41 def open_socket(host, port):
       
    42     if not port:
       
    43         port = DEF_PORT
       
    44     elif type(port) == type(''):
       
    45         port = string.atoi(port)
       
    46     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
       
    47     s.connect((host, port))
       
    48     return s
       
    49 
       
    50 # Send a selector to a given host and port, return a file with the reply
       
    51 def send_request(selector, host, port):
       
    52     s = open_socket(host, port)
       
    53     s.send(selector + CRLF)
       
    54     s.shutdown(1)
       
    55     return s.makefile('r')
       
    56 
       
    57 # Get a menu in the form of a list of entries
       
    58 def get_menu(selector, host, port):
       
    59     f = send_request(selector, host, port)
       
    60     list = []
       
    61     while 1:
       
    62         line = f.readline()
       
    63         if not line:
       
    64             print '(Unexpected EOF from server)'
       
    65             break
       
    66         if line[-2:] == CRLF:
       
    67             line = line[:-2]
       
    68         elif line[-1:] in CRLF:
       
    69             line = line[:-1]
       
    70         if line == '.':
       
    71             break
       
    72         if not line:
       
    73             print '(Empty line from server)'
       
    74             continue
       
    75         typechar = line[0]
       
    76         parts = string.splitfields(line[1:], TAB)
       
    77         if len(parts) < 4:
       
    78             print '(Bad line from server: %r)' % (line,)
       
    79             continue
       
    80         if len(parts) > 4:
       
    81             print '(Extra info from server: %r)' % (parts[4:],)
       
    82         parts.insert(0, typechar)
       
    83         list.append(parts)
       
    84     f.close()
       
    85     return list
       
    86 
       
    87 # Get a text file as a list of lines, with trailing CRLF stripped
       
    88 def get_textfile(selector, host, port):
       
    89     list = []
       
    90     get_alt_textfile(selector, host, port, list.append)
       
    91     return list
       
    92 
       
    93 # Get a text file and pass each line to a function, with trailing CRLF stripped
       
    94 def get_alt_textfile(selector, host, port, func):
       
    95     f = send_request(selector, host, port)
       
    96     while 1:
       
    97         line = f.readline()
       
    98         if not line:
       
    99             print '(Unexpected EOF from server)'
       
   100             break
       
   101         if line[-2:] == CRLF:
       
   102             line = line[:-2]
       
   103         elif line[-1:] in CRLF:
       
   104             line = line[:-1]
       
   105         if line == '.':
       
   106             break
       
   107         if line[:2] == '..':
       
   108             line = line[1:]
       
   109         func(line)
       
   110     f.close()
       
   111 
       
   112 # Get a binary file as one solid data block
       
   113 def get_binary(selector, host, port):
       
   114     f = send_request(selector, host, port)
       
   115     data = f.read()
       
   116     f.close()
       
   117     return data
       
   118 
       
   119 # Get a binary file and pass each block to a function
       
   120 def get_alt_binary(selector, host, port, func, blocksize):
       
   121     f = send_request(selector, host, port)
       
   122     while 1:
       
   123         data = f.read(blocksize)
       
   124         if not data:
       
   125             break
       
   126         func(data)
       
   127 
       
   128 # A *very* simple interactive browser
       
   129 
       
   130 # Browser main command, has default arguments
       
   131 def browser(*args):
       
   132     selector = DEF_SELECTOR
       
   133     host = DEF_HOST
       
   134     port = DEF_PORT
       
   135     n = len(args)
       
   136     if n > 0 and args[0]:
       
   137         selector = args[0]
       
   138     if n > 1 and args[1]:
       
   139         host = args[1]
       
   140     if n > 2 and args[2]:
       
   141         port = args[2]
       
   142     if n > 3:
       
   143         raise RuntimeError, 'too many args'
       
   144     try:
       
   145         browse_menu(selector, host, port)
       
   146     except socket.error, msg:
       
   147         print 'Socket error:', msg
       
   148         sys.exit(1)
       
   149     except KeyboardInterrupt:
       
   150         print '\n[Goodbye]'
       
   151 
       
   152 # Browse a menu
       
   153 def browse_menu(selector, host, port):
       
   154     list = get_menu(selector, host, port)
       
   155     while 1:
       
   156         print '----- MENU -----'
       
   157         print 'Selector:', repr(selector)
       
   158         print 'Host:', host, ' Port:', port
       
   159         print
       
   160         for i in range(len(list)):
       
   161             item = list[i]
       
   162             typechar, description = item[0], item[1]
       
   163             print string.rjust(repr(i+1), 3) + ':', description,
       
   164             if typename.has_key(typechar):
       
   165                 print typename[typechar]
       
   166             else:
       
   167                 print '<TYPE=' + repr(typechar) + '>'
       
   168         print
       
   169         while 1:
       
   170             try:
       
   171                 str = raw_input('Choice [CR == up a level]: ')
       
   172             except EOFError:
       
   173                 print
       
   174                 return
       
   175             if not str:
       
   176                 return
       
   177             try:
       
   178                 choice = string.atoi(str)
       
   179             except string.atoi_error:
       
   180                 print 'Choice must be a number; try again:'
       
   181                 continue
       
   182             if not 0 < choice <= len(list):
       
   183                 print 'Choice out of range; try again:'
       
   184                 continue
       
   185             break
       
   186         item = list[choice-1]
       
   187         typechar = item[0]
       
   188         [i_selector, i_host, i_port] = item[2:5]
       
   189         if typebrowser.has_key(typechar):
       
   190             browserfunc = typebrowser[typechar]
       
   191             try:
       
   192                 browserfunc(i_selector, i_host, i_port)
       
   193             except (IOError, socket.error):
       
   194                 print '***', sys.exc_type, ':', sys.exc_value
       
   195         else:
       
   196             print 'Unsupported object type'
       
   197 
       
   198 # Browse a text file
       
   199 def browse_textfile(selector, host, port):
       
   200     x = None
       
   201     try:
       
   202         p = os.popen('${PAGER-more}', 'w')
       
   203         x = SaveLines(p)
       
   204         get_alt_textfile(selector, host, port, x.writeln)
       
   205     except IOError, msg:
       
   206         print 'IOError:', msg
       
   207     if x:
       
   208         x.close()
       
   209     f = open_savefile()
       
   210     if not f:
       
   211         return
       
   212     x = SaveLines(f)
       
   213     try:
       
   214         get_alt_textfile(selector, host, port, x.writeln)
       
   215         print 'Done.'
       
   216     except IOError, msg:
       
   217         print 'IOError:', msg
       
   218     x.close()
       
   219 
       
   220 # Browse a search index
       
   221 def browse_search(selector, host, port):
       
   222     while 1:
       
   223         print '----- SEARCH -----'
       
   224         print 'Selector:', repr(selector)
       
   225         print 'Host:', host, ' Port:', port
       
   226         print
       
   227         try:
       
   228             query = raw_input('Query [CR == up a level]: ')
       
   229         except EOFError:
       
   230             print
       
   231             break
       
   232         query = string.strip(query)
       
   233         if not query:
       
   234             break
       
   235         if '\t' in query:
       
   236             print 'Sorry, queries cannot contain tabs'
       
   237             continue
       
   238         browse_menu(selector + TAB + query, host, port)
       
   239 
       
   240 # "Browse" telnet-based information, i.e. open a telnet session
       
   241 def browse_telnet(selector, host, port):
       
   242     if selector:
       
   243         print 'Log in as', repr(selector)
       
   244     if type(port) <> type(''):
       
   245         port = repr(port)
       
   246     sts = os.system('set -x; exec telnet ' + host + ' ' + port)
       
   247     if sts:
       
   248         print 'Exit status:', sts
       
   249 
       
   250 # "Browse" a binary file, i.e. save it to a file
       
   251 def browse_binary(selector, host, port):
       
   252     f = open_savefile()
       
   253     if not f:
       
   254         return
       
   255     x = SaveWithProgress(f)
       
   256     get_alt_binary(selector, host, port, x.write, 8*1024)
       
   257     x.close()
       
   258 
       
   259 # "Browse" a sound file, i.e. play it or save it
       
   260 def browse_sound(selector, host, port):
       
   261     browse_binary(selector, host, port)
       
   262 
       
   263 # Dictionary mapping types to browser functions
       
   264 typebrowser = {'0': browse_textfile, '1': browse_menu, \
       
   265         '4': browse_binary, '5': browse_binary, '6': browse_textfile, \
       
   266         '7': browse_search, \
       
   267         '8': browse_telnet, '9': browse_binary, 's': browse_sound}
       
   268 
       
   269 # Class used to save lines, appending a newline to each line
       
   270 class SaveLines:
       
   271     def __init__(self, f):
       
   272         self.f = f
       
   273     def writeln(self, line):
       
   274         self.f.write(line + '\n')
       
   275     def close(self):
       
   276         sts = self.f.close()
       
   277         if sts:
       
   278             print 'Exit status:', sts
       
   279 
       
   280 # Class used to save data while showing progress
       
   281 class SaveWithProgress:
       
   282     def __init__(self, f):
       
   283         self.f = f
       
   284     def write(self, data):
       
   285         sys.stdout.write('#')
       
   286         sys.stdout.flush()
       
   287         self.f.write(data)
       
   288     def close(self):
       
   289         print
       
   290         sts = self.f.close()
       
   291         if sts:
       
   292             print 'Exit status:', sts
       
   293 
       
   294 # Ask for and open a save file, or return None if not to save
       
   295 def open_savefile():
       
   296     try:
       
   297         savefile = raw_input( \
       
   298     'Save as file [CR == don\'t save; |pipeline or ~user/... OK]: ')
       
   299     except EOFError:
       
   300         print
       
   301         return None
       
   302     savefile = string.strip(savefile)
       
   303     if not savefile:
       
   304         return None
       
   305     if savefile[0] == '|':
       
   306         cmd = string.strip(savefile[1:])
       
   307         try:
       
   308             p = os.popen(cmd, 'w')
       
   309         except IOError, msg:
       
   310             print repr(cmd), ':', msg
       
   311             return None
       
   312         print 'Piping through', repr(cmd), '...'
       
   313         return p
       
   314     if savefile[0] == '~':
       
   315         savefile = os.path.expanduser(savefile)
       
   316     try:
       
   317         f = open(savefile, 'w')
       
   318     except IOError, msg:
       
   319         print repr(savefile), ':', msg
       
   320         return None
       
   321     print 'Saving to', repr(savefile), '...'
       
   322     return f
       
   323 
       
   324 # Test program
       
   325 def test():
       
   326     if sys.argv[4:]:
       
   327         print 'usage: gopher [ [selector] host [port] ]'
       
   328         sys.exit(2)
       
   329     elif sys.argv[3:]:
       
   330         browser(sys.argv[1], sys.argv[2], sys.argv[3])
       
   331     elif sys.argv[2:]:
       
   332         try:
       
   333             port = string.atoi(sys.argv[2])
       
   334             selector = ''
       
   335             host = sys.argv[1]
       
   336         except string.atoi_error:
       
   337             selector = sys.argv[1]
       
   338             host = sys.argv[2]
       
   339             port = ''
       
   340         browser(selector, host, port)
       
   341     elif sys.argv[1:]:
       
   342         browser('', sys.argv[1])
       
   343     else:
       
   344         browser()
       
   345 
       
   346 # Call the test program as a main program
       
   347 test()