#!/usr/bin/python3
import asyncio, traceback, socket, ssl
from urllib.parse import urlparse
from flask import Flask, request, redirect, send_file, Response
from hypercorn.config import Config
from hypercorn.asyncio import serve
app = Flask(__name__)
@app.route("/")
def root():
return """
Gem2Browser
Gem2Browser
"""
@app.route("/external.png")
def external():
return send_file("external.png")
@app.route("/cross-server.png")
def crosserver():
return send_file("cross-server.png")
@app.route("/style.css")
def style():
return send_file("style.css")
@app.route("/gem")
def relay():
url = request.args.get('gemini')
if url == None:
return redirect("/")
code = "Something went wrong...
\n"
title = "Something went wrong..."
try:
gsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
fulladdr = "gemini://" + url
gemsocket = ssl._create_unverified_context().wrap_socket(gsocket, server_hostname=urlparse(fulladdr).hostname)
gemsocket.connect((urlparse(fulladdr).hostname, 1965))
gemsocket.send(bytes("gemini://" + url + "\r\n", "UTF-8"))
received = ""
while True:
gemresponse = gemsocket.recv(2048)
try:
if gemresponse.decode() != "":
received += gemresponse.decode()
else:
break
except:
return f'\nSomething went wrong...Something went wrong...
The file that the Gemini server sent couldn\'t be decoded by Gem2Browser.
'
received = received.replace("\r", "")
firstline = True
redirected = False
gemtext = True
code = ""
for i in received.split("\n"):
i = i.replace("<", "<").replace("<", ">")
if firstline:
if i.split(" ")[0][0] == "3":
return redirect("/gem?gemini=" + i.split(" ")[1][9:])
elif i.split(" ")[0][0] != "2":
return f'\nSomething went wrong...Something went wrong...
The specified Gemini server returned a status of: {i}
'
else:
firstline = False
if i.split(" ")[1].split(";")[0] != "text/gemini":
print("Unrecognised type: " + i.split(" ")[1])
return Response(" ".join(received.split("\n")[1:]), mimetype=i.split(" ")[1])
else:
if i[0:2] == "# ":
if title == "Something went wrong...":
title = i[2:]
temp = i[2:]
code += f"{temp}
\n"
elif i[0:3] == "## ":
temp = i[3:]
code += f"{temp}
\n"
elif i[0:4] == "### ":
temp = i[4:]
code += f"{temp}
\n"
elif i[0:2] == "* ":
temp = i[2:]
code += f"\n"
elif i[0:2] == "=>":
temp = " ".join(i[2:].strip().replace(" ", " ").split(" "))
goto = temp.split(" ")[0]
prse = urlparse(goto)
extra = ""
extracomment = goto
if prse.netloc == "" and prse.scheme == "":
isdir = url[len(url) - 1] == "/"
isabs = goto[0] == "/" or goto[0:2] == "//"
dubleslash = goto[0:2] == "//"
if isabs:
tempurl = urlparse(fulladdr).hostname + "/" + (goto[1:] if dubleslash else goto)
elif isdir:
tempurl = url + goto
else:
tempurl = "/".join(url.split("/")[:-1]) + "/" + goto
goto = f"/gem?gemini={tempurl}"
elif prse.scheme != "gemini":
extra = ""
extracomment = f"This link points to an address that isn't gemini ({prse.scheme})"
else:
if prse.hostname != urlparse(fulladdr).hostname:
extra = ""
extracomment = f"This link points to an address that isn't from the server you're currently connecting to ({prse.hostname})"
goto = goto.replace("gemini://", "")
goto = f"/gem?gemini={goto}"
if temp.split(" ") == 1:
comment = goto
else:
comment = " ".join(temp.split(" ")[1:])
code += f"{comment} {extra}
\n"
elif i[0:2] == ">":
code += f"{i}
\n"
else:
code += f"{i}
\n"
if title == "Something went wrong...":
title = "gemini://" + url
except:
code += "" + traceback.format_exc() + "
"
return f'\n{title}{code}'
# Run the Hypercorn ASGI server
conf = Config()
conf.bind = "0.0.0.0:2009"
asyncio.run(serve(app, conf))