refactored browser cgi to be recursive and support auto-redirects

This commit is contained in:
James Tomasino 2023-02-24 20:26:26 +00:00
parent 4e9276b4ea
commit 899857f4f5
1 changed files with 22 additions and 15 deletions

View File

@ -10,18 +10,31 @@ from os import getenv
urllib.parse.uses_relative.append("gemini")
urllib.parse.uses_netloc.append("gemini")
redirect_count = 0
def clean(text):
return text.replace('&', '&amp;').replace('<','&lt;').replace('>','&gt;').replace('"', '&quot;').replace('\'', '&#x27;')
print("Content-type: text/html\r\n\r\n")
def query(url = None):
global redirect_count
if url:
queryurl = url
elif getenv('QUERY_STRING'):
queryurl = getenv('QUERY_STRING')
else:
print("<h1>What?</h1><p>I'm sorry, but I don't know what you want me to do without a URL.</p>")
sys.exit()
if getenv('QUERY_STRING'):
try:
baseurl = getenv('QUERY_STRING').split('?')[0]
baseurl = queryurl.split('?')[0]
response = gemcall.request(baseurl)
if response.responsecode in [30, 31]:
newtarget = urllib.parse.urljoin(baseurl, response.meta)
print(f"<h1>RESPONSE: \"{str(response.responsecode)} {response.meta}\"</h1><p>This address redirects to <a href='{newtarget}'>{newtarget}</a>.</p>")
if redirect_count < 5:
redirect_count += 1
query(newtarget)
else:
print(f"<h1>RESPONSE: \"{str(response.responsecode)} {response.meta}\"</h1><p>This address redirects to <a href='{newtarget}'>{newtarget}</a>.</p>")
elif response.responsecode == 20 and "text/" in response.meta:
responsetext = response.read(100*1024) # We don't support more than 100kb
if "text/gemini" in response.meta:
@ -39,7 +52,6 @@ if getenv('QUERY_STRING'):
if not line.linetype == gemtextparser.LineType.PREFORM and preform:
print("</code></pre>")
preform = False
if line.linetype == gemtextparser.LineType.LISTITEM:
if not listmode:
print("<ul>")
@ -49,7 +61,6 @@ if getenv('QUERY_STRING'):
if not line.linetype == gemtextparser.LineType.LISTITEM and listmode:
print("</ul>")
listmode = False
if line.linetype == gemtextparser.LineType.BLOCKQUOTE:
if not blockquote:
print("<blockquote>")
@ -59,7 +70,6 @@ if getenv('QUERY_STRING'):
if not line.linetype == gemtextparser.LineType.BLOCKQUOTE and blockquote:
print("</blockquote>")
blockquote = False
if line.linetype == gemtextparser.LineType.H1 and line.text():
print(f"<h1>{clean(line.text())}</h1>")
continue
@ -69,7 +79,6 @@ if getenv('QUERY_STRING'):
if line.linetype == gemtextparser.LineType.H3 and line.text():
print(f"<h3>{clean(line.text())}</h3>")
continue
if line.linetype == gemtextparser.LineType.LINK:
linkURL = urllib.parse.urljoin(baseurl, clean(line.linkURL().replace("'","")))
target = "" if linkURL.startswith("gemini://") else " target='_blank'"
@ -78,7 +87,6 @@ if getenv('QUERY_STRING'):
else:
print(f"<a href='{linkURL}'{target}>{linkURL}</a><br/>")
continue
if line.linetype == gemtextparser.LineType.PLAIN:
print(f"{clean(line.text())}<br/>")
if listmode:
@ -87,12 +95,10 @@ if getenv('QUERY_STRING'):
print("</blockquote>")
if preform:
print("</code></pre>")
else:
print("<pre><code>")
print(clean(responsetext.decode('utf8', errors='ignore')))
print("</code></pre>")
elif response.responsecode == 20:
print(f"<h1>RESPONSE: \"20 Success\", but...</h1><p>The Wobbly browser only supports text responses, and this response is '{clean(response.meta)}'.</p>")
elif response.responsecode in [40, 41, 42, 43, 44, 50, 51, 52, 53, 59]:
@ -101,10 +107,11 @@ if getenv('QUERY_STRING'):
print(f"<h1>RESPONSE: \"{str(response.responsecode)} {clean(response.meta)}\"</h1><p>The Wobbly browser does not support client certificates. Please install a more full-featured browser to visit this page.</p>")
elif response.responsecode in [10,11]:
print(f"<h1>RESPONSE: \"{str(response.responsecode)} {clean(response.meta)}\"</h1><p>The status codes 10 and 11 are requests for user input.</p><p>The only means of submitting user input to a server in gemini is via the so-called QUERY_STRING; the part of a URL that follows after a '?'. The Wobbly browser does not support this for privacy/security reasons. Please install a more full-featured browser to be able to submit data.</p>")
response.discard()
except Exception as e:
print(f"<h1>Unknown Error</h1><p>Something went wrong when trying to fetch '{getenv('QUERY_STRING')}'. Could not recover.</p>")
print(f"<h1>Unknown Error</h1><p>Something went wrong when trying to fetch '{queryurl}'. Could not recover.</p>")
print(f"<p>Exception Message:</p><p>{print(repr(e))}</p>")
else:
print("<h1>What?</h1><p>I'm sorry, but I don't know what you want me to do without a URL.</p>")
print("Content-type: text/html\r\n\r\n")
query()