From 5cbf942f99ed0e81c08e22b3937dc202921c72c5 Mon Sep 17 00:00:00 2001 From: Ferry Boender Date: Wed, 1 Apr 2015 20:44:40 +0200 Subject: [PATCH] Deprecated the 'script_raw' option in favour of an output type specifier. 'escaped' will wrap output in PRE tags and esape the HTML entities in the output. 'html' will not and allows the script to include HTML markup. 'raw' is the former 'script_raw' option and directly streams output to the browser. --- doc/MANUAL.md | 48 +++++++++++------- examples/{raw => output_types}/README.md | 0 .../{raw => output_types}/job_large_bin.sh | 0 examples/output_types/job_show_html.sh | 7 +++ .../{raw => output_types}/job_show_image.sh | 0 examples/output_types/output.json | 38 ++++++++++++++ examples/{raw => output_types}/test.jpg | Bin examples/raw/raw.json | 21 -------- src/scriptform.py | 22 ++++---- 9 files changed, 88 insertions(+), 48 deletions(-) rename examples/{raw => output_types}/README.md (100%) rename examples/{raw => output_types}/job_large_bin.sh (100%) create mode 100755 examples/output_types/job_show_html.sh rename examples/{raw => output_types}/job_show_image.sh (100%) create mode 100644 examples/output_types/output.json rename examples/{raw => output_types}/test.jpg (100%) delete mode 100644 examples/raw/raw.json diff --git a/doc/MANUAL.md b/doc/MANUAL.md index 7394a5f..bbb6424 100644 --- a/doc/MANUAL.md +++ b/doc/MANUAL.md @@ -14,11 +14,11 @@ - [Text](#form_def) - [Password](#form_def) - [File](#form_def) +1. [Output](#output) 1. [Callbacks](#form_def) - [Script callbacks]() - [Validation]() - [Field Values]() - - [Output]() - [Python callbacks]() 1. [Users](#users) @@ -60,9 +60,8 @@ Structurally, they are made up of the following elements: script isn't found, if the script isn't executable or (if the `script` tag is omitted) if no Python callback is registered to handle this form. **String**. - - **`script_raw`**: If present and `true`, the output of the script is sent - to the browser as-is. The script must include the proper headers and body - itself. This allows you to output images, stream files, etc. + - **`output`**: Determines how the output of the callback is handled. See + the *Output types* seciton. - **`fields`**: List of fields in the form. Each field is a dictionary. **Required**, **List of dictionaries**. - **`name`**: The name of the field. This is what is passed as an @@ -215,6 +214,33 @@ The original file name of the uploaded file is stored in a new variable No additional validation is done on the file contents, or the file name. + +## Output + +FIXME + + If + its value is `escaped`, the output of the callback will have its HTML + entities escaped and will be wrapped in PRE elements. This is the + **default** option. If the value is `html`, the output will not be + escaped or wrapped in PRE tags, and can thus include HTML markup. If the + output is `raw`, the output of the script is streamed directly to the + client's browser. This allows you to output images, binary files, etc to + the client. The script must include the proper headers and body itself. + +If the script's exit code is 0, the output of the script (stdout) is captured +and shown to the user in the browser. + +If a script's exit code is not 0, it is assumed an error occured. Scriptform +will show the script's stderr output (in red) to the user instead of stdin. + +If the form definition has a `script_raw` field, and its value is `true`, +Scriptform will pass the output of the script to the browser as-is. This allows +scripts to show images, stream a file download to the browser or even show +completely custom HTML output. The script's output must be a valid HTTP +response, including headers and a body. Examples of raw script output can be +found in the `examples/raw` directory. + ## Callbacks Callbacks are called after the form has been submitted and its values have been @@ -281,20 +307,6 @@ ends. Examples of file uploads can be found in the `examples/simple` and `examples/megacorp` directories. -#### Output - -If the script's exit code is 0, the output of the script (stdout) is captured -and shown to the user in the browser. - -If a script's exit code is not 0, it is assumed an error occured. Scriptform -will show the script's stderr output (in red) to the user instead of stdin. - -If the form definition has a `script_raw` field, and its value is `true`, -Scriptform will pass the output of the script to the browser as-is. This allows -scripts to show images, stream a file download to the browser or even show -completely custom HTML output. The script's output must be a valid HTTP -response, including headers and a body. Examples of raw script output can be -found in the `examples/raw` directory. ### Python callbacks diff --git a/examples/raw/README.md b/examples/output_types/README.md similarity index 100% rename from examples/raw/README.md rename to examples/output_types/README.md diff --git a/examples/raw/job_large_bin.sh b/examples/output_types/job_large_bin.sh similarity index 100% rename from examples/raw/job_large_bin.sh rename to examples/output_types/job_large_bin.sh diff --git a/examples/output_types/job_show_html.sh b/examples/output_types/job_show_html.sh new file mode 100755 index 0000000..974e1a0 --- /dev/null +++ b/examples/output_types/job_show_html.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +echo "Here's some bold text. The output of ls:
"
+
+ls
+
+echo '

A link:

Google.com' diff --git a/examples/raw/job_show_image.sh b/examples/output_types/job_show_image.sh similarity index 100% rename from examples/raw/job_show_image.sh rename to examples/output_types/job_show_image.sh diff --git a/examples/output_types/output.json b/examples/output_types/output.json new file mode 100644 index 0000000..2d8bec7 --- /dev/null +++ b/examples/output_types/output.json @@ -0,0 +1,38 @@ +{ + "title": "Output type callback examples", + "forms": { + "show_image": { + "title": "Show an image", + "description": "Shows you an image. This is a 'raw' output type where the script writes a complete HTTP response to stdout, which is directly streamed to the browser by scriptform.", + "submit_title": "Show", + "script": "job_show_image.sh", + "output": "raw", + "fields": {} + }, + "large_bin": { + "title": "Download large binary file", + "description": "Download a large (100mb) binary file. This demonstrated streaming directly to the client of large files.", + "submit_title": "Download", + "script": "job_large_bin.sh", + "output": "raw", + "fields": {} + }, + "some_html": { + "title": "Show some HTML", + "description": "This is the 'html' output type, which allows HTML in the output of scripts. This can be useful to refer to another form after this form is completed, for instance.", + "submit_title": "Show HTML", + "script": "job_show_html.sh", + "output": "html", + "fields": {} + }, + "escaped": { + "title": "Escaped contents (default)", + "description": "This is the 'escaped' output type. It is the default. The HTML entities in the output are escaped properly, and is wrapped in PRE elements.", + "submit_title": "Show HTML", + "script": "job_show_html.sh", + "output": "escaped", + "fields": {} + } + + } +} diff --git a/examples/raw/test.jpg b/examples/output_types/test.jpg similarity index 100% rename from examples/raw/test.jpg rename to examples/output_types/test.jpg diff --git a/examples/raw/raw.json b/examples/raw/raw.json deleted file mode 100644 index fe87282..0000000 --- a/examples/raw/raw.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "title": "Raw callback examples", - "forms": { - "show_image": { - "title": "Show an image", - "description": "Shows you an image", - "submit_title": "Show", - "script": "job_show_image.sh", - "script_raw": true, - "fields": {} - }, - "large_bin": { - "title": "Download large binary file", - "description": "Download a large (100mb) binary file", - "submit_title": "Download", - "script": "job_large_bin.sh", - "script_raw": true, - "fields": {} - } - } -} diff --git a/src/scriptform.py b/src/scriptform.py index 60a3dd9..5fbdcc3 100755 --- a/src/scriptform.py +++ b/src/scriptform.py @@ -142,14 +142,14 @@ class FormDefinition: for validation of the form values. """ def __init__(self, name, title, description, fields, script=None, - script_raw=False, submit_title="Submit", + output='escaped', submit_title="Submit", allowed_users=None): self.name = name self.title = title self.description = description self.fields = fields self.script = script - self.script_raw = script_raw + self.output = output self.submit_title = submit_title self.allowed_users = allowed_users @@ -581,16 +581,20 @@ class ScriptFormWebApp(WebAppHandler): # Repopulate form values with uploaded tmp filenames form_values.update(file_fields) - # Call user's callback. If a result is returned, we assume the callback - # was not a raw script, so we wrap its output in some nice HTML. - # Otherwise the callback should have written its own response to the + # Call user's callback. If a result is returned, we wrap its output + # in some nice HTML. If no result is returned, the output was raw + # and the callback should have written its own response to the # self.wfile filehandle. result = self.scriptform.callback(form_name, form_values, self.wfile) if result: if result['exitcode'] != 0: - msg = '{0}'.format(result['stderr']) + msg = '{0}'.format(cgi.escape(result['stderr'])) else: - msg = '
{0}
'.format(result['stdout']) + if form_def.output == 'escaped': + msg = '
{0}
'.format(cgi.escape(result['stdout'])) + else: + msg = result['stdout'] + output = html_submit_response.format( header=html_header.format(title=self.scriptform.title), footer=html_footer, @@ -653,7 +657,7 @@ class ScriptForm: form['description'], form['fields'], script, - script_raw=form.get('script_raw', False), + output=form.get('output', 'escaped'), submit_title=form.get('submit_title', None), allowed_users=form.get('allowed_users', None)) @@ -673,7 +677,7 @@ class ScriptForm: for k, v in form_values.items(): env[k] = str(v) - if form.script_raw: + if form.output == 'raw': p = subprocess.Popen(form.script, shell=True, stdout=output_fh, stderr=output_fh, env=env) stdout, stderr = p.communicate(input)