#!/usr/bin/python3 import asyncio, traceback, socket, ssl, zipfile, random, string, io from OpenSSL import crypto from urllib.parse import urlparse, quote from flask import Flask, request, redirect, send_file, Response, make_response from hypercorn.config import Config from hypercorn.asyncio import serve from pathlib import Path homefolder = str(Path.home()) app = Flask(__name__) @app.route("/robots.txt") def robots(): return Response("User-agent: *\nDisallow: /", mimetype="text/plain") @app.route("/") def root(): return send_file("home.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("/loadcert") def loadcert(): return send_file("loadcert.html") def allowed_file(filename): return '.' in filename and filename.rsplit('.', 1)[1].lower() == "pem" @app.route("/certload", methods=['GET', 'POST']) def loadcert(): if request.method == 'POST': if 'cert' not in request.files: return "Invalid request. (cert is missing!)" if 'privkey' not in request.files: return "Invalid request. (privkey is missing!)" cert = request.files['cert'] privkey = request.files['privkey'] if cert.filename == '' or privkey.filename == '': return "Please upload a certificate and private key." if allowed_file(cert.filename) and allowed_file(privkey.filename): random_name = ''.join(random.choice(string.ascii_lowercase+string.digits+string.ascii_uppercase) for i in range(8)) cert.save(homefolder + "/certs/" + randomname + "-chain.pem") privkey.save(homefolder + "/certs/" + randomname + "-privkey.pem") return redirect("/") else: return "Both files must be a .pem file, you might want to generate a certificate via the home page." else: return "Cannot go to /certload with GET, perhaps you're looking for /loadcert" @app.route("/gencert.zip") def gencert(): random_name = ''.join(random.choice(string.ascii_lowercase+string.digits+string.ascii_uppercase) for i in range(8)) k = crypto.PKey() k.generate_key(crypto.TYPE_RSA, 1024) cert = crypto.X509() cert.get_subject().C = "US" cert.get_subject().ST = "Earth" cert.get_subject().L = "Earth" cert.get_subject().O = random_name cert.get_subject().OU = random_name cert.get_subject().CN = "g2b.swee.codes" cert.set_serial_number(1000) cert.gmtime_adj_notBefore(0) cert.gmtime_adj_notAfter(10*365*24*60*60) cert.set_issuer(cert.get_subject()) cert.set_pubkey(k) cert.sign(k, 'sha1') #open(homefolder + "/" + random_name + "-privkey.pem", "wb").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k)) #open(homefolder + "/" + random_name + "-cert.pem", "wb").write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) zip_buffer = io.BytesIO() with zipfile.ZipFile(zip_buffer, "a", zipfile.ZIP_DEFLATED, False) as zip_file: for file_name, data in [('cert.pem', io.BytesIO(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))), ('privkey.pem', io.BytesIO(crypto.dump_privatekey(crypto.FILETYPE_PEM, k)))]: zip_file.writestr(file_name, data.getvalue()) open(homefolder + "/certs/" + random_name + "-chain.pem", "wb").write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) open(homefolder + "/certs/" + random_name + "-privkey.pem", "wb").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k)) resp = make_response(zip_buffer.getvalue()) resp.set_cookie('certname',random_name) resp.mimetype = "application/zip" return resp @app.route("/style.css") def style(): return send_file("style.css") @app.route("/logo.png") def logo(): return send_file("gem2browser.png") @app.route("/gem") def relay(): print(request.headers.get('User-Agent')) url = request.args.get('gemini') queries = request.args.get('query') if url == None: return redirect("/") code = "
The specified Gemini server wants more data:
{i}' elif i.split(" ")[0][0] == "6": return f'\n
The specified Gemini server wants a client certificate, or the certificate is invalid.
{i}
You can load a certificate in home page.
' elif i.split(" ")[0][0] != "2": return f'\nThe 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 escaped: if i[0:3] == "```": code += "\n" escaped = False else: code += i + "\n" else: if i[0:2] == "# ": if title == "Something went wrong...": title = i[2:] temp = i[2:] code += f"\n" escaped = True elif i[0:4] == "### ": temp = i[4:] code += f"{temp}
\n" elif i[0:2] == "* ": temp = i[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