diff options
Diffstat (limited to 'Demo/sockets/gopher.py')
-rwxr-xr-x | Demo/sockets/gopher.py | 352 |
1 files changed, 0 insertions, 352 deletions
diff --git a/Demo/sockets/gopher.py b/Demo/sockets/gopher.py deleted file mode 100755 index bd29ec0..0000000 --- a/Demo/sockets/gopher.py +++ /dev/null @@ -1,352 +0,0 @@ -#! /usr/bin/env python3 - -# A simple gopher client. -# -# Usage: gopher [ [selector] host [port] ] - -import sys -import os -import socket - -# Default selector, host and port -DEF_SELECTOR = '' -DEF_HOST = 'gopher.micro.umn.edu' -DEF_PORT = 70 - -# Recognized file types -T_TEXTFILE = '0' -T_MENU = '1' -T_CSO = '2' -T_ERROR = '3' -T_BINHEX = '4' -T_DOS = '5' -T_UUENCODE = '6' -T_SEARCH = '7' -T_TELNET = '8' -T_BINARY = '9' -T_REDUNDANT = '+' -T_SOUND = 's' - -# Dictionary mapping types to strings -typename = {'0': '<TEXT>', '1': '<DIR>', '2': '<CSO>', '3': '<ERROR>', \ - '4': '<BINHEX>', '5': '<DOS>', '6': '<UUENCODE>', '7': '<SEARCH>', \ - '8': '<TELNET>', '9': '<BINARY>', '+': '<REDUNDANT>', 's': '<SOUND>'} - -# Oft-used characters and strings -CRLF = '\r\n' -TAB = '\t' - -# Open a TCP connection to a given host and port -def open_socket(host, port): - if not port: - port = DEF_PORT - elif type(port) == type(''): - port = int(port) - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect((host, port)) - return s - -# Send a selector to a given host and port, return a file with the reply -def send_request(selector, host, port): - s = open_socket(host, port) - s.send(selector + CRLF) - s.shutdown(1) - return s.makefile('r') - -# Get a menu in the form of a list of entries -def get_menu(selector, host, port): - f = send_request(selector, host, port) - list = [] - while 1: - line = f.readline() - if not line: - print('(Unexpected EOF from server)') - break - if line[-2:] == CRLF: - line = line[:-2] - elif line[-1:] in CRLF: - line = line[:-1] - if line == '.': - break - if not line: - print('(Empty line from server)') - continue - typechar = line[0] - parts = line[1:].split(TAB) - if len(parts) < 4: - print('(Bad line from server: %r)' % (line,)) - continue - if len(parts) > 4: - print('(Extra info from server: %r)' % (parts[4:],)) - parts.insert(0, typechar) - list.append(parts) - f.close() - return list - -# Get a text file as a list of lines, with trailing CRLF stripped -def get_textfile(selector, host, port): - list = [] - get_alt_textfile(selector, host, port, list.append) - return list - -# Get a text file and pass each line to a function, with trailing CRLF stripped -def get_alt_textfile(selector, host, port, func): - f = send_request(selector, host, port) - while 1: - line = f.readline() - if not line: - print('(Unexpected EOF from server)') - break - if line[-2:] == CRLF: - line = line[:-2] - elif line[-1:] in CRLF: - line = line[:-1] - if line == '.': - break - if line[:2] == '..': - line = line[1:] - func(line) - f.close() - -# Get a binary file as one solid data block -def get_binary(selector, host, port): - f = send_request(selector, host, port) - data = f.read() - f.close() - return data - -# Get a binary file and pass each block to a function -def get_alt_binary(selector, host, port, func, blocksize): - f = send_request(selector, host, port) - while 1: - data = f.read(blocksize) - if not data: - break - func(data) - -# A *very* simple interactive browser - -# Browser main command, has default arguments -def browser(*args): - selector = DEF_SELECTOR - host = DEF_HOST - port = DEF_PORT - n = len(args) - if n > 0 and args[0]: - selector = args[0] - if n > 1 and args[1]: - host = args[1] - if n > 2 and args[2]: - port = args[2] - if n > 3: - raise RuntimeError('too many args') - try: - browse_menu(selector, host, port) - except socket.error as msg: - print('Socket error:', msg) - sys.exit(1) - except KeyboardInterrupt: - print('\n[Goodbye]') - -# Browse a menu -def browse_menu(selector, host, port): - list = get_menu(selector, host, port) - while 1: - print('----- MENU -----') - print('Selector:', repr(selector)) - print('Host:', host, ' Port:', port) - print() - for i in range(len(list)): - item = list[i] - typechar, description = item[0], item[1] - print(repr(i+1).rjust(3) + ':', description, end=' ') - if typechar in typename: - print(typename[typechar]) - else: - print('<TYPE=' + repr(typechar) + '>') - print() - while 1: - try: - str = input('Choice [CR == up a level]: ') - except EOFError: - print() - return - if not str: - return - try: - choice = int(str) - except ValueError: - print('Choice must be a number; try again:') - continue - if not 0 < choice <= len(list): - print('Choice out of range; try again:') - continue - break - item = list[choice-1] - typechar = item[0] - [i_selector, i_host, i_port] = item[2:5] - if typechar in typebrowser: - browserfunc = typebrowser[typechar] - try: - browserfunc(i_selector, i_host, i_port) - except (IOError, socket.error): - t, v, tb = sys.exc_info() - print('***', t, ':', v) - else: - print('Unsupported object type') - -# Browse a text file -def browse_textfile(selector, host, port): - x = None - try: - p = os.popen('${PAGER-more}', 'w') - x = SaveLines(p) - get_alt_textfile(selector, host, port, x.writeln) - except IOError as msg: - print('IOError:', msg) - if x: - x.close() - f = open_savefile() - if not f: - return - x = SaveLines(f) - try: - get_alt_textfile(selector, host, port, x.writeln) - print('Done.') - except IOError as msg: - print('IOError:', msg) - x.close() - -def raw_input(prompt): - sys.stdout.write(prompt) - sys.stdout.flush() - return sys.stdin.readline() - -# Browse a search index -def browse_search(selector, host, port): - while 1: - print('----- SEARCH -----') - print('Selector:', repr(selector)) - print('Host:', host, ' Port:', port) - print() - try: - query = input('Query [CR == up a level]: ') - except EOFError: - print() - break - query = query.strip() - if not query: - break - if '\t' in query: - print('Sorry, queries cannot contain tabs') - continue - browse_menu(selector + TAB + query, host, port) - -# "Browse" telnet-based information, i.e. open a telnet session -def browse_telnet(selector, host, port): - if selector: - print('Log in as', repr(selector)) - if type(port) != type(''): - port = repr(port) - sts = os.system('set -x; exec telnet ' + host + ' ' + port) - if sts: - print('Exit status:', sts) - -# "Browse" a binary file, i.e. save it to a file -def browse_binary(selector, host, port): - f = open_savefile() - if not f: - return - x = SaveWithProgress(f) - get_alt_binary(selector, host, port, x.write, 8*1024) - x.close() - -# "Browse" a sound file, i.e. play it or save it -def browse_sound(selector, host, port): - browse_binary(selector, host, port) - -# Dictionary mapping types to browser functions -typebrowser = {'0': browse_textfile, '1': browse_menu, \ - '4': browse_binary, '5': browse_binary, '6': browse_textfile, \ - '7': browse_search, \ - '8': browse_telnet, '9': browse_binary, 's': browse_sound} - -# Class used to save lines, appending a newline to each line -class SaveLines: - def __init__(self, f): - self.f = f - def writeln(self, line): - self.f.write(line + '\n') - def close(self): - sts = self.f.close() - if sts: - print('Exit status:', sts) - -# Class used to save data while showing progress -class SaveWithProgress: - def __init__(self, f): - self.f = f - def write(self, data): - sys.stdout.write('#') - sys.stdout.flush() - self.f.write(data) - def close(self): - print() - sts = self.f.close() - if sts: - print('Exit status:', sts) - -# Ask for and open a save file, or return None if not to save -def open_savefile(): - try: - savefile = input( \ - 'Save as file [CR == don\'t save; |pipeline or ~user/... OK]: ') - except EOFError: - print() - return None - savefile = savefile.strip() - if not savefile: - return None - if savefile[0] == '|': - cmd = savefile[1:].strip() - try: - p = os.popen(cmd, 'w') - except IOError as msg: - print(repr(cmd), ':', msg) - return None - print('Piping through', repr(cmd), '...') - return p - if savefile[0] == '~': - savefile = os.path.expanduser(savefile) - try: - f = open(savefile, 'w') - except IOError as msg: - print(repr(savefile), ':', msg) - return None - print('Saving to', repr(savefile), '...') - return f - -# Test program -def test(): - if sys.argv[4:]: - print('usage: gopher [ [selector] host [port] ]') - sys.exit(2) - elif sys.argv[3:]: - browser(sys.argv[1], sys.argv[2], sys.argv[3]) - elif sys.argv[2:]: - try: - port = int(sys.argv[2]) - selector = '' - host = sys.argv[1] - except ValueError: - selector = sys.argv[1] - host = sys.argv[2] - port = '' - browser(selector, host, port) - elif sys.argv[1:]: - browser('', sys.argv[1]) - else: - browser() - -# Call the test program as a main program -test() |