Source code for gopher.golfer

import socket
from os import listdir
from os.path import isfile, join
import os

TCP_IP = '0.0.0.0'
HOST = 'Golfer'
TCP_PORT = 3333
FILE_DIR = '/olala/gopher/files'

DEFAULT_NOTIFIER = "localhost"
if "DEFAULT_NOTIFIER" in os.environ:
    DEFAULT_NOTIFIER = os.environ["DEFAULT_NOTIFIER"]

POD_IP = "0.0.0.0"
if "POD_IP" in os.environ:
    POD_IP = os.environ["POD_IP"]


[docs]def get_entries(): """returns `[(DirEntry)]` as defined by the gopher protocol """ commands = ['newfile', 'notify', 'delete'] for com in commands: yield ("!Command\t" + "!/" + com + "\t" + HOST + "\t" + str(TCP_PORT) + "\n") for entry in (("0" + f + "\t" + "0/" + f + "\t" + HOST + "\t" + str(TCP_PORT) + "\n") for f in listdir(FILE_DIR) if isfile(join(FILE_DIR, f))): yield entry
[docs]def get_selectors(): """returns a list of selectors for the known files """ return ((f, "0/" + f) for f in listdir(FILE_DIR) if isfile(join(FILE_DIR, f)))
[docs]def main(): """Starts the gopher server """ listener = socket.socket() listener.bind((TCP_IP, TCP_PORT)) listener.listen() print("Golfer started on port", TCP_PORT) notifications = [DEFAULT_NOTIFIER.split(':')] notifications[0][1] = int(notifications[0][1]) print("Notifications:", notifications) while True: conn, addr = listener.accept() data = "" while True: new_data = conn.recv(1) if not new_data or new_data == b'\n': break data += new_data.decode() print(data, "from", addr) if data == '': for entry in get_entries(): conn.send(entry.encode()) else: data = data.split() if data[0] == "!/newfile": if len(data) == 2: for addr in notifications: try: print('sending a notification to', addr) notifier = socket.create_connection(addr) notifier.send(b"pssssst want some ?" + POD_IP.encode() + b":" + str(TCP_PORT).encode() + b"|0/" + data[1].encode() + b"#") notifier.close() except ConnectionRefusedError: print("Can't connect to notifier") except socket.gaierror: print("Invalid notifier address") print("Notified") elif data[0] == "!/notify": print("Added hook: ", data) if len(data) == 2 and \ len(data[1].split(':')) == 2: addr, port = data[1].split(':') notifications.append((addr, port)) elif data[0] == "!/delete": if len(data) == 2: selector_requested = data[1] for file_name in map(lambda x: x[0], filter(lambda x: x[1] == selector_requested, get_selectors())): os.remove(FILE_DIR+'/'+file_name) for file_name, selector in get_selectors(): if selector == data[0]: selected_file = open(FILE_DIR+'/'+file_name, "r") conn.send(selected_file.read().encode()) selected_file.close() conn.close()
if __name__ == "__main__": main()