Skip to content

Instantly share code, notes, and snippets.

@SteveBarnes-BH
Last active November 1, 2021 12:20
Show Gist options
  • Save SteveBarnes-BH/a4ae0a17fab15a9076a6844adf10220c to your computer and use it in GitHub Desktop.
Save SteveBarnes-BH/a4ae0a17fab15a9076a6844adf10220c to your computer and use it in GitHub Desktop.
CGI Debugging - sometimes you have a web page that uses CGI and you need to see what data is being POSTed.
#!/usr/bin/env python
"""
This script is based on https://cgi.tutorial.codepoint.net/file-upload but with changes as needed.
To use:
- Download the web page to be debugged.
- Edit it to replace `action="/cgi-bin/cgi-post"` with `action="/cgi-bin/cgi-post.py"` (on Windows on Linux you can simply rename this file to not have .py at the end.
- place in a cgi-bin subdirectory of the one where you saved the web page
- start a simple web server with ` python -m http.server 8001 --bind localhost --cgi`
- browse to http://localhost:8001/factory_page.html or whatever the file is called.
- Fill in and submit the form.
"""
import cgi
import os
# Enable browser based CGI debugging
import cgitb
cgitb.enable()
try: # Windows needs stdio set for binary mode.
import msvcrt
msvcrt.setmode(0, os.O_BINARY) # stdin = 0
msvcrt.setmode(1, os.O_BINARY) # stdout = 1
except ImportError:
pass
form = cgi.FieldStorage()
message = "<H1>Form Submitted!</H1>"
message += "<P>Form Fields: " + ", ".join(form.keys()) + "</P><UL>"
for k in form.keys():
message += f"<LI>{k}:{form[k]}</LI>"
message += "</UL>"
# A nested FieldStorage instance holds the file - the name will depend on the form
known_used = ["CONTENT_TYPE", "CONTENT_LENGTH"]
if 'updatefilename' in form:
fileitem = form['updatefilename']
# Test if the file was uploaded
if fileitem.filename:
# strip leading path from file name
# to avoid directory traversal attacks
fn = os.path.basename(fileitem.filename)
# Ucomment the following line if you would like to actually save the uploaded file
#open('files/' + fn, 'wb').write(fileitem.file.read())
filelen = len(fileitem.file.read())
reported_len = os.getenv("CONTENT_LENGTH", "ERR!")
message += f'<P>The file "{fn}" was uploaded successfully with {filelen} bytes.</P>'
message += "<p>Env Values (can act as parameters to CGI scripts)</p><UL>"
env = os.environ
for k, v in env.items():
if k in known_used:
message += f'<LI><B>{k} = {v}</B></LI>'
else:
message += f'<LI>{k} = {v}</LI>'
message += "</OL>"
else:
message = '<P>No file was uploaded</P>'
print("""\
Content-Type: text/html\n
<html><body>
%s
</body></html>
""" % (message,))
# Sending from Python
import requests
url = "http://localhost:8001/cgi-bin/cgi-post.py"
values = {'DB': 'photcat', 'OUT': 'csv', 'SHORT': 'short'}
files = {'updatefilename':("Fred.txt", open("some_local_file.ext", "rb"))}
resp = requests.post(url, files=files, data=values)
# Then play with resp.text, etc.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment