#!/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