Merge pull request 'Implement Titan support' (#1) from titan-implemenatation into main
Some checks failed
Test web app / Check syntax (push) Successful in 12s
Test web app / Test server with Flask Dev Mode (push) Successful in 14s
Test web app / Test server with Gunicorn (WSGI) (push) Successful in 13s
Test web app / Test server with Hypercorn (ASGI) (push) Has been cancelled
Some checks failed
Test web app / Check syntax (push) Successful in 12s
Test web app / Test server with Flask Dev Mode (push) Successful in 14s
Test web app / Test server with Gunicorn (WSGI) (push) Successful in 13s
Test web app / Test server with Hypercorn (ASGI) (push) Has been cancelled
Reviewed-on: #1
This commit is contained in:
commit
682f30a330
2 changed files with 121 additions and 1 deletions
122
server.py
122
server.py
|
@ -25,6 +25,9 @@ def external():
|
|||
@app.route("/cross-server.png")
|
||||
def crosserver():
|
||||
return send_file("cross-server.png")
|
||||
@app.route("/write.png")
|
||||
def write():
|
||||
return send_file("write.png")
|
||||
@app.route("/loadcert")
|
||||
def loadcert():
|
||||
return send_file("loadcert.html")
|
||||
|
@ -100,9 +103,118 @@ def favicon():
|
|||
@app.route("/logo.png")
|
||||
def logo():
|
||||
return send_file("gem2browser.png")
|
||||
@app.route("/titan", methods=['GET', 'POST'])
|
||||
def titanedit():
|
||||
url = request.args.get('url')
|
||||
queries = request.args.get('query')
|
||||
certfile = request.cookies.get('certname')
|
||||
code = "<h1>Something went wrong...</h1>\n"
|
||||
title = "Something went wrong..."
|
||||
try:
|
||||
if request.method == "POST":
|
||||
mimetype = request.form.get("mimetype")
|
||||
token = request.form.get("token")
|
||||
value = request.form.get("value")
|
||||
gsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
fulladdr = "titan://" + url
|
||||
contx = ssl.create_default_context()
|
||||
contx.check_hostname = False
|
||||
contx.verify_mode = ssl.CERT_NONE
|
||||
if certfile:
|
||||
contx.load_cert_chain(certfile=homefolder + "/certs/" + certfile + "-chain.pem", keyfile=homefolder + "/certs/" + certfile + "-privkey.pem");
|
||||
gemsocket = contx.wrap_socket(gsocket, server_hostname=urlparse(fulladdr).hostname)
|
||||
gemsocket.connect((urlparse(fulladdr).hostname, 1965))
|
||||
gemsocket.send(bytes(fulladdr + (";mime=" + mimetype if mimetype else "") + (";token=" + token if token else "") + f";size={len(value)}" + "\r\n" + value, "UTF-8"))
|
||||
gemraw = bytearray()
|
||||
allraw = []
|
||||
num = 0
|
||||
ok = False
|
||||
binary = False
|
||||
while True:
|
||||
gemresponse = gemsocket.recv(2048)
|
||||
allraw.append(gemresponse)
|
||||
if len(gemresponse) != 0:
|
||||
for i in gemresponse:
|
||||
gemraw.append(i)
|
||||
else:
|
||||
break
|
||||
found = False
|
||||
mtype = bytearray()
|
||||
for i in bytes(gemraw):
|
||||
try:
|
||||
if not found:
|
||||
mtype.append(i)
|
||||
if "\n" in bytes(mtype).decode() and not found:
|
||||
found = True
|
||||
ok = bytes(mtype).decode().split(" ")[0][0] == "3"
|
||||
code = bytes(mtype).decode()
|
||||
break
|
||||
except:
|
||||
pass
|
||||
if not ok:
|
||||
resp = make_response(f'<!DOCTYPE html>\n<html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" href="/style.css"><title>Something went wrong...</title></head><body><h1>Something went wrong...</h1><p>I submitted the Titan request, I expected a redirect, but got: <pre>{code}</pre></p></body></html>', 500)
|
||||
return resp
|
||||
else:
|
||||
ref = bytes(mtype).decode().split(" ")[1]
|
||||
return redirect("/gem?gemini=" + quote((ref[9:] if "gemini://" in ref else ref).replace("\r", "").replace("\n", ""), safe=''))
|
||||
else:
|
||||
mimetype_edit = ""
|
||||
if ";edit" in url:
|
||||
gsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
fulladdr = "titan://" + url
|
||||
contx = ssl.create_default_context()
|
||||
contx.check_hostname = False
|
||||
contx.verify_mode = ssl.CERT_NONE
|
||||
if certfile:
|
||||
contx.load_cert_chain(certfile=homefolder + "/certs/" + certfile + "-chain.pem", keyfile=homefolder + "/certs/" + certfile + "-privkey.pem");
|
||||
gemsocket = contx.wrap_socket(gsocket, server_hostname=urlparse(fulladdr).hostname)
|
||||
gemsocket.connect((urlparse(fulladdr).hostname, 1965))
|
||||
gemsocket.send(bytes(fulladdr + "\r\n", "UTF-8"))
|
||||
mimetype = ""
|
||||
gemraw = bytearray()
|
||||
num = 0
|
||||
ok = False
|
||||
binary = False
|
||||
while True:
|
||||
gemresponse = gemsocket.recv(2048)
|
||||
if len(gemresponse) != 0:
|
||||
for i in gemresponse:
|
||||
gemraw.append(i)
|
||||
else:
|
||||
break
|
||||
found = False
|
||||
gemcontent_binary = bytearray()
|
||||
mtype = bytearray()
|
||||
for i in bytes(gemraw):
|
||||
try:
|
||||
if not found:
|
||||
mtype.append(i)
|
||||
else:
|
||||
gemcontent_binary.append(i)
|
||||
if "\n" in bytes(mtype).decode() and not found:
|
||||
found = True
|
||||
ok = bytes(mtype).decode().split(" ")[0][0] == "2"
|
||||
code = bytes(mtype).decode()
|
||||
mimetype_edit = bytes(mtype).decode().replace("\r", "").split("\n")[0].split(" ")[1].split(";")[0]
|
||||
except:
|
||||
pass
|
||||
if not ok:
|
||||
resp = make_response(f'<!DOCTYPE html>\n<html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" href="/style.css"><title>Something went wrong...</title></head><body><h1>Something went wrong...</h1><p>Gemini server wanted to use Titan editor, but it returned <code>{code}</code></p></body></html>', 500)
|
||||
return resp
|
||||
val = gemcontent_binary.decode()
|
||||
else:
|
||||
val = ""
|
||||
if ";mimetype" in url:
|
||||
mimetype_edit = url.split(";mimetype=")[1].split(";")[0]
|
||||
ifquery = "&query=" + queries if queries != None else ""
|
||||
url = url.replace(";edit", "")
|
||||
return f'<!DOCTYPE html>\n<html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" href="/style.css"><title>Advanced Editor (Titan)</title></head><body><h1>Advanced Editor (Titan)</h1><p>The gemini server wants more data, but using the Titan protocol, you may edit here.</p><br><form action="/titan?url={url}{ifquery}" method=post enctype=multipart/form-data><p>Mimetype: <input type="text" name="mimetype" class="input" value="{mimetype_edit}"></p><p>Token (Not required for edits): <input type="text" name="token" class="input"></p><br><textarea width="90vw" height="75vh" class="input" name="value" style="font-style: monospace;">{val}</textarea><br><br><input type="submit" class="go" value="Done"></body></html>'
|
||||
except:
|
||||
code += "<pre>" + traceback.format_exc() + "</pre>"
|
||||
resp = make_response(f'<!DOCTYPE html>\n<html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" href="/style.css"><title>{title}</title></head><body>{code}</body></html>', 500)
|
||||
return resp
|
||||
@app.route("/gem")
|
||||
def relay():
|
||||
print(request.headers.get('User-Agent'))
|
||||
url = request.args.get('gemini')
|
||||
queries = request.args.get('query')
|
||||
certfile = request.cookies.get('certname')
|
||||
|
@ -237,6 +349,14 @@ def relay():
|
|||
tempurl = "/".join(url.split("/")[:-1]) + "/" + goto
|
||||
tempurl = quote(tempurl, safe='')
|
||||
goto = f"/gem?gemini={tempurl}"
|
||||
elif prse.scheme == "titan":
|
||||
extra = "<img height=\"19\" src=\"/write.png\">"
|
||||
extracomment = "This is a titan link, you may edit text using this link."
|
||||
q = ""
|
||||
if "?" in goto:
|
||||
q = goto.split("?")[1]
|
||||
goto = goto.replace(f"?{q}", "")
|
||||
goto = f"/titan?url=" + goto[8:] + ("&query=" + q if q else "")
|
||||
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})"
|
||||
|
|
BIN
write.png
Normal file
BIN
write.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 859 B |
Loading…
Add table
Add a link
Reference in a new issue