#!/usr/bin/env python
"""
data.cgi - Data URI Resolver
Author: Sean B. Palmer, inamidst.com
@@ Autodetect whether to use GET or POST
"""
import sys, os, cgi, urllib
allowed = frozenset(['text/plain', 'text/html', 'image/svg+xml',
'application/xhtml+xml'])
PATH_INFO = os.environ.get('PATH_INFO', '')
QUERY_STRING = os.environ.get('QUERY_STRING', '')
SCRIPT_NAME = os.environ.get('SCRIPT_NAME', '')
REQUEST_URI = os.environ.get('REQUEST_URI', '')
REQUEST_METHOD = os.environ.get('REQUEST_METHOD', '')
script = REQUEST_URI.split('?')[0]
def serve(status, headers, body):
sys.stdout.write("Status: %s\r\n" % status)
for header in headers.iteritems():
sys.stdout.write("%s: %s\r\n" % header)
sys.stdout.write("\r\n")
sys.stdout.write(str(body))
sys.exit()
def ok(mime, body):
serve(200, {'Content-Type': mime}, body)
def redirect(uri, temp=False):
if not uri.startswith('http:'):
from urlparse import urljoin
domain = os.environ.get('SERVER_NAME', 'localhost')
uri = urljoin('http://' + domain + REQUEST_URI, uri)
status = (301, 307)[temp]
headers = {'Location': uri, 'Content-Type': 'text/html'}
body = 'Go!' % uri
serve(status, headers, body)
def error(msg):
body = '
%s
' % cgi.escape(msg)
serve(501, {'Content-Type': 'text/html'}, body)
def query():
form = cgi.FieldStorage()
form.__call__ = lambda s: form[s].value
if not form.has_key('data'):
error('Form must have key "data".')
uridata = urllib.quote(form('data'))
# Commas, as metachars, need encoding: ,
uridata = uridata.replace(',', '%2C')
# @@ It should be done with slashes too, but that breaks Apache...
# uridata = uridata.replace('/', '%2F')
if form.has_key('mime'):
mime = form('mime')
if mime != 'text/html':
uridata = mime + ',' + uridata
redirect(script + uridata)
def homepage():
import textwrap
ok('text/html', textwrap.dedent("""\
Data URI Resolver - Paste 'n' Go
The form above uses GET by default but only allows up to 2,048 bytes.
By switching to POST you won't get a bookmarkable URI, but you will be
able to send up to 51,200 bytes.
Data URI Resolver
By Sean B. Palmer.
See the script for details.
"""))
def post():
form = cgi.FieldStorage()
form.__call__ = lambda s: form[s].value
if not form.has_key('data'):
error('Form must have key "data".')
uridata = urllib.quote(form('data'))
data('/' + uridata)
def data(path):
# path = REQUEST_URI[5:] # len(SCRIPT_NAME.rsplit('/', 1)[0]):]
if path.startswith('/'):
path = path[1:]
if ',' in path:
mime, uridata = path.split(',', 1)
else: mime, uridata = 'text/html', path
if mime.endswith(';base64'):
import base64
mime = mime[:-7]
uridata = base64.b64decode(uridata)
if mime not in allowed:
uridata = mime + ',' + uridata
mime = 'text/html'
# error('MIME type "%s" is not allowed.' % mime)
import urllib
# @@ Should probably do this above
uridata = urllib.unquote(uridata)
if (REQUEST_METHOD == 'GET') and (len(uridata) >= 2048):
error('Data length must be less than 2048 bytes.')
elif (REQUEST_METHOD == 'POST') and (len(uridata) >= 51200):
error('Data length must be less than 51,200 bytes.')
ok(mime, uridata)
def main():
import cgitb
cgitb.enable()
if REQUEST_METHOD == 'GET':
if QUERY_STRING: query()
elif PATH_INFO == '/': homepage()
elif not PATH_INFO:
redirect(REQUEST_URI + '/')
else: data(PATH_INFO)
else: post()
if __name__=="__main__":
main()