=> going-flying.com gemini git repository
=> summary
=> tree
=> log
=> refs
=> view raw
#!/usr/bin/env python3 # -*- coding: UTF-8 -*- '''converter (c) 2021 Matthew J ErnisseAll Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ''' import base64 import datetime import secrets import sys import qrcode from urllib.parse import parse_qs, quote, unquote, urlparse import gmicgi BACK_LINK = '/cgi-bin/converter/' MAIN_SCREEN = ''' # Matt's Gemini CGI Toolbox. I wanted to see what kind of things I could do with a CGI script. Think a collection of little oneliners. This is that. As I think of little toys I'll probably add to this. It happens to be written in Python. ## Number base converters Display a number in binary, decimal and hexadecimal. If your input cannot be recognized, the script will return a permanent failure. => bin Binary Input => dec Decimal Input => hex Hexadecimal Input ## Encode / Decode => base64/encode Base64 Encode => base64/decode Base64 Decode => url/encode URL Quote => url/decode URL Unquote ## Random Stuff While I have taken care to be fairly reasonable with these things, please note that Molly Brown does produce logs that get saved which means that while they may be cryptographically secure, they also may end up in a log file somewhere. As such these should be used for demonstration purposes only. => random/base32 Random number, Base32 encoded => random/totp Random number, encoded as a TOTP secret ## Other Stuff => unixdate Unix timestamp to UTC date ## Suggestions? Want to see something here? Feel free to drop me a line. => mailto:matt@going-flying.com => / ↩ Home ''' def encode_response(cgi, input, result): global BACK_LINK cgi.Response.Ok('text/gemini') if type(result) == bytes: result = result.decode('utf-8') output = f'# Input\n{input}\n\n' output += f'# Output\n{result}\n\n' output += f'=> {BACK_LINK} Back\n' output += f'=> / Home' print(output) def ender(i): s = { 42: 'Life, The Universe, and Everything', 69: 'Nice', 242: 'I have 17 remixes of Headhunter here somewhere', 420: 'Nice', 1701: 'The Final Frontier', 2257: 'The dawn of the third age of mankind', 3303: 'Remember...', 31337: 'Greetz to Zero Cool and Joey' } return f' ({s[i]})\n\n' if i in s.keys() else '\n\n' def pretty_binary(i): ''' Pad a binary number out into space-separated octets.''' j = bin(i)[2:] out = [] while len(j) > 8: out.insert(0, j[len(j) - 8:]) j = j[:len(j) - 8] return '0' * (8 - len(j)) + j + ' ' + ' '.join(out) def result_table(cgi, input, b, d, h): ''' Print out the result page. ''' global BACK_LINK cgi.Response.Ok('text/gemini') output = f'# Input\n{input}{ender(d)}' output += f'## Binary Representation\n{b}\n\n' output += f'## Decimal Representation\n{d}\n\n' output += f'## Hexadecimal Representation\n0x{h}\n\n' output += f'=> {BACK_LINK} Back\n' output += f'=> / Home' print(output) def secret_response(cgi, val, qr=False): global BACK_LINK cgi.Response.Ok('text/gemini') if type(val) == bytes: val = val.decode('utf-8') output = f'# Your secret\n' output += f'{val}\n' if qr: e_val = base64.b64encode(val.encode('utf-8')).decode('utf-8') output += f'=> {BACK_LINK}random/qr/{e_val} QR Code\n\n' output += f'=> {BACK_LINK} Back\n' output += f'=> / Home' print(output) if __name__ == '__main__': cgi = gmicgi.GeminiCGI() if not cgi.query_string: if not cgi.path_info: cgi.Response.Ok('text/gemini') print(MAIN_SCREEN) # Number base conversion elif cgi.path_info == 'bin': cgi.Response.Input('Binary Number?') elif cgi.path_info == 'dec': cgi.Response.Input('Number?') elif cgi.path_info == 'hex': cgi.Response.Input('Hex Number?') # base64 encode/decode elif cgi.path_info == 'base64/encode': cgi.Response.Input('String to encode?') elif cgi.path_info == 'base64/decode': cgi.Response.Input('String to decode?') # urlencode/decode elif cgi.path_info == 'url/encode': cgi.Response.Input('String to encode?') elif cgi.path_info == 'url/decode': cgi.Response.Input('String to decode?') # Random Stuff elif cgi.path_info == 'random/base32': val = base64.b32encode(secrets.token_bytes(30)) secret_response(cgi, val) elif cgi.path_info == 'random/totp': cgi.Response.Input('Account Label?') elif cgi.path_info.startswith('random/qr'): val = cgi.path_info.split('/')[-1] val = base64.b64decode(val).decode('utf-8') png = qrcode.make(val) cgi.Response.Ok('image/png') sys.stdout.flush() png.save(sys.stdout.buffer) sys.stdout.flush() # Unixdate elif cgi.path_info == 'unixdate': cgi.Response.Input('UNIX Timestamp?') else: cgi.Response.Redirect(BACK_LINK) else: if not cgi.path_info: cgi.Response.Redirect(BACK_LINK) # Number base conversion elif cgi.path_info == 'bin': s = cgi.query_string try: d = int(s, 2) b = pretty_binary(d) h = f'{d:02X}' except Exception: cgi.Response.Fail() sys.exit() result_table(cgi, s, b, d, h) elif cgi.path_info == 'dec': s = cgi.query_string try: d = int(s) b = pretty_binary(d) h = f'{d:02X}' except Exception: cgi.Response.Fail() sys.exit() result_table(cgi, s, b, d, h) elif cgi.path_info == 'hex': s = cgi.query_string try: d = int(s, 16) b = pretty_binary(d) h = f'{d:02X}' except Exception: cgi.Response.Fail() sys.exit() result_table(cgi, s, b, d, h) # base64 encode/decode elif cgi.path_info == 'base64/encode': s = cgi.query_dequoted try: res = base64.b64encode(s.encode('utf-8')) except Exception as e: sys.stderr.write(f'{e!s}\n') sys.stderr.flush() cgi.Response.Fail() sys.exit() encode_response(cgi, s, res) elif cgi.path_info == 'base64/decode': s = cgi.query_dequoted try: res = base64.b64decode(s, validate=True) except Exception: cgi.Response.Fail() sys.exit() encode_response(cgi, s, res) # urlencode/decode elif cgi.path_info == 'url/encode': s = cgi.query_dequoted try: res = quote(s, errors='strict') except Exception: cgi.Response.Fail() sys.exit() encode_response(cgi, s, res) elif cgi.path_info == 'url/decode': s = cgi.query_dequoted try: res = unquote(s, errors='strict') except Exception: cgi.Response.Fail() sys.exit() encode_response(cgi, s, res) # Random Stuff elif cgi.path_info == 'random/totp': # Leave pre-urlencoded! label = cgi.query_string val = base64.b32encode(secrets.token_bytes(30)) val = val.decode('utf-8') secret_response( cgi, f'otpauth://totp/{label}?secret={val}', True ) # Unixdate elif cgi.path_info == 'unixdate': ts = cgi.query_dequoted try: dt = datetime.datetime.fromtimestamp(float(ts)) t = dt.strftime('%A %d %B %Y %H:%M:%S UTC') except Exception: cgi.Response.Fail() sys.exit() cgi.Response.Ok('text/gemini') output = f'# UNIX Timestamp {ts}\n' output += f'{t}\n\n' output += f'=> {BACK_LINK} Back\n' output += f'=> / Home' print(output) else: cgi.Response.NotFound()
text/gemini
This content has been proxied by September (ba2dc).