129 lines
No EOL
5.6 KiB
Python
129 lines
No EOL
5.6 KiB
Python
#!/usr/bin/python3
|
|
import asyncio, traceback, socket, ssl
|
|
from urllib.parse import urlparse
|
|
from flask import Flask, request, redirect, send_file
|
|
from hypercorn.config import Config
|
|
from hypercorn.asyncio import serve
|
|
app = Flask(__name__)
|
|
@app.route("/")
|
|
def root():
|
|
return """
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<link rel="stylesheet" href="/style.css">
|
|
<title>Gem2Browser</title>
|
|
</head>
|
|
<body>
|
|
<center>
|
|
<h1>Gem2Browser</h1>
|
|
<form action="/gem">
|
|
<p>gemini://<input class="input" value="geminiprotocol.net" type="text" name="gemini"></p><br>
|
|
<input type="submit" class="go" value="Go!">
|
|
</form>
|
|
</center>
|
|
</body>
|
|
</html>
|
|
"""
|
|
@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 = "<h1>Something went wrong...</h1>\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)
|
|
if gemresponse.decode() != "":
|
|
received += gemresponse.decode()
|
|
else:
|
|
break
|
|
received = received.replace("\r", "")
|
|
firstline = True
|
|
redirected = False
|
|
gemtext = True
|
|
code = ""
|
|
for i in received.split("\n"):
|
|
if firstline:
|
|
if i.split(" ")[0][0] == "3":
|
|
return redirect("/gem?gemini=" + i.split(" ")[1][9:])
|
|
elif i.split(" ")[0][0] != "2":
|
|
return f'<!DOCTYPE html>\n<html><head><meta charset="UTF-8"><link rel="stylesheet" href="/style.css"><title>Something went wrong...</title></head><body><h1>Something went wrong...</h1><p>The specified Gemini server returned a status of: {i}</p></body></html>'
|
|
else:
|
|
firstline = False
|
|
if i.split(" ")[1] != "text/gemini":
|
|
return f'<!DOCTYPE html>\n<html><head><meta charset="UTF-8"><link rel="stylesheet" href="/style.css"><title>Something went wrong...</title></head><body><h1>Something went wrong...</h1><p>This path returned a file that isn\'t Gemtext, which Gem2Browser doesn\'t support downloading files.</p></body></html>'
|
|
else:
|
|
if i[0:2] == "# ":
|
|
if title == "Something went wrong...":
|
|
title = i[2:]
|
|
temp = i[2:]
|
|
code += f"<h1>{temp}</h1>\n"
|
|
elif i[0:3] == "## ":
|
|
temp = i[3:]
|
|
code += f"<h2>{temp}</h2>\n"
|
|
elif i[0:4] == "### ":
|
|
temp = i[4:]
|
|
code += f"<h3>{temp}</h3>\n"
|
|
elif i[0:2] == "* ":
|
|
temp = i[2:]
|
|
code += f"<ul><li>{temp}</li></ul>\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] == "/"
|
|
if isdir:
|
|
print(url + goto)
|
|
tempurl = url + goto
|
|
else:
|
|
tempurl = "/".join(url.split("/")[:-1]) + "/" + goto
|
|
goto = f"/gem?gemini={tempurl}"
|
|
elif prse.scheme != "gemini":
|
|
extra = "<img height=\"19\" src=\"/external.png\">"
|
|
extracomment = f"This link points to an address that isn't gemini ({prse.scheme})"
|
|
else:
|
|
if prse.hostname != urlparse(fulladdr).hostname:
|
|
extra = "<img height=\"19\" src=\"/cross-server.png\">"
|
|
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"<p title=\"{extracomment}\"><a href=\"{goto}\">{comment} {extra}</a></p>\n"
|
|
elif i[0:2] == ">":
|
|
code += f"<p class='greentext'>{i}</p>\n"
|
|
else:
|
|
code += f"<p>{i}</p>\n"
|
|
if title == "Something went wrong...":
|
|
title = "gemini://" + url
|
|
except:
|
|
code += traceback.format_exc()
|
|
return f'<!DOCTYPE html>\n<html><head><meta charset="UTF-8"><link rel="stylesheet" href="/style.css"><title>{title}</title></head><body>{code}</body></html>'
|
|
|
|
# Run the Hypercorn ASGI server
|
|
conf = Config()
|
|
conf.bind = "0.0.0.0:2009"
|
|
asyncio.run(serve(app, conf)) |