#!/usr/bin/python3 import sys, socket, subprocess, re, traceback history = [] host = 'ake.crabdance.com' port = 70 path = '' mode = 'cat' GOPHER_SCHEMA = re.compile(r'^(?:gopher:\/\/)([^:\/]+)(?::(\d+))*\/([01])(.*)$') def download_file(link): print('Download file from {}:{} to current directory\nleave blank to abort'.format(link['host'], link['path'])) filename = input('filename: ') if filename == '': return with open(filename, 'wb') as f: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((link['host'], link['port'])) s.sendall('{}\r\n'.format(link['path']).encode('utf-8')) resp = b'' while True: packet = s.recv(1024) if not packet: break resp += packet s.close() f.write(resp) print('Saved to {}'.format(filename)) while True: try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) s.sendall('{}\r\n'.format(path).encode('utf-8')) resp = b'' while True: packet = s.recv(1024) if not packet: break resp += packet except: traceback.print_exc() resp = '3An error occured during page loading\t\tnone\t0\r\n1Back to previous page\t{3}\t{1}\t{2}\r\n'.format(*history[-1]).encode('utf-8') finally: s.close() sys.stdout.write('\033[2J') if mode == 'doc': sys.stdout.write(resp.decode('utf-8')) else: entries = [entry.rstrip().split('\t') for entry in resp.decode('utf-8').split('\n')] links = [] for line in entries: if len(line[0]) == 0: continue if line[0][0] == 'i': print('\t' + line[0][1:]) elif line[0][0] == '0': links.append(dict( type='doc', host=line[2], port=int(line[3]), path=line[1] )) print('[{}]\t\033[4;33m{}\033[0m'.format(len(links), line[0][1:])) elif line[0][0] == '1': links.append(dict( type='cat', host=line[2], port=int(line[3]), path=line[1] )) print('[{}] +\t\033[1;34m{}{}\033[0m'.format(len(links), line[0][1:], ' \033[1;32m(external link)' if line[2] != host else '')) elif line[0][0] == '7': links.append(dict( type='find', host=line[2], port=int(line[3]), path=line[1] )) print('[{}] ?\t\033[7;32m{}\033[0m'.format(len(links), line[0][1:])) elif line[0][0] == '9': links.append(dict( type='bin', host=line[2], port=int(line[3]), path=line[1] )) print('[{}] *\t\033[1;35m{}\033[0m'.format(len(links), line[0][1:])) elif line[0][0] == 'h': links.append(dict( type='link', host=line[2], port=int(line[3]), path=line[1] )) print('[{}] >\t\033[4;36m{}\033[0m'.format(len(links), line[0][1:])) elif line[0][0] == 'I': print('\t[picture: {}]'.format(line[0][1:])) elif line[0][0] == '3': print('\t\033[7;1;31m{}\033[0m'.format(line[0][1:])) elif line[0][0] == '.': print('[done]') else: print('\tNot supported: {}'.format(line[0])) action = input('\033[1;31m{}:{}\033[0m> '.format(host, path)).rstrip() if action == 'exit': break elif action == 'back': mode, host, port, path = history.pop() elif action == 'up': history.append((mode, host, port, path)) path = path[:path.rfind('/')] mode = 'cat' elif action == 'home': history.append((mode, host, port, path)) path = '' mode = 'cat' elif action[0] == '@': history.append((mode, host, port, path)) host = action[1:] path = '' mode = 'cat' elif action.isdigit(): link_index = int(action) - 1 if len(links) <= link_index: print('No such link') elif links[link_index]['type'] == 'bin': download_file(links[link_index]) elif links[link_index]['type'] == 'link': print(repr(links[link_index])) subprocess.call(['xdg-open', links[link_index]['path'][4:]]) else: history.append((mode, host, port, path)) mode = links[link_index]['type'] host = links[link_index]['host'] port = links[link_index]['port'] path = links[link_index]['path'] if mode == 'find': query = input('Search query: ') path += '\t' + query elif action.startswith('gopher:'): result = GOPHER_SCHEMA.match(action) if result is not None: history.append((mode, host, port, path)) host = result.group(1) port = int(result.group(2)) if result.group(2) else 70 mode = 'cat' if result.group(3) == '1' else 'doc' path = result.group(4) else: history.append((mode, host, port, path)) path = action