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.

pull/7/head
Ferry Boender 10 years ago
parent dfe9cc2393
commit 5cbf942f99
  1. 48
      doc/MANUAL.md
  2. 0
      examples/output_types/README.md
  3. 0
      examples/output_types/job_large_bin.sh
  4. 7
      examples/output_types/job_show_html.sh
  5. 0
      examples/output_types/job_show_image.sh
  6. 38
      examples/output_types/output.json
  7. 0
      examples/output_types/test.jpg
  8. 21
      examples/raw/raw.json
  9. 22
      src/scriptform.py

@ -14,11 +14,11 @@
- [Text](#form_def) - [Text](#form_def)
- [Password](#form_def) - [Password](#form_def)
- [File](#form_def) - [File](#form_def)
1. [Output](#output)
1. [Callbacks](#form_def) 1. [Callbacks](#form_def)
- [Script callbacks]() - [Script callbacks]()
- [Validation]() - [Validation]()
- [Field Values]() - [Field Values]()
- [Output]()
- [Python callbacks]() - [Python callbacks]()
1. [Users](#users) 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` 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. tag is omitted) if no Python callback is registered to handle this form.
**String**. **String**.
- **`script_raw`**: If present and `true`, the output of the script is sent - **`output`**: Determines how the output of the callback is handled. See
to the browser as-is. The script must include the proper headers and body the *Output types* seciton.
itself. This allows you to output images, stream files, etc.
- **`fields`**: List of fields in the form. Each field is a dictionary. - **`fields`**: List of fields in the form. Each field is a dictionary.
**Required**, **List of dictionaries**. **Required**, **List of dictionaries**.
- **`name`**: The name of the field. This is what is passed as an - **`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. No additional validation is done on the file contents, or the file name.
## <a name="output">Output</a>
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
Callbacks are called after the form has been submitted and its values have been 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 of file uploads can be found in the `examples/simple` and
`examples/megacorp` directories. `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 ### Python callbacks

@ -0,0 +1,7 @@
#!/bin/sh
echo "Here's some <b>bold</b> text. The output of ls:<pre style='background-color: #F2F2F8'>"
ls
echo '</pre><br>A link:<br><br><a href="http://www.google.com">Google.com</a>'

@ -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": {}
}
}
}

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

@ -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": {}
}
}
}

@ -142,14 +142,14 @@ class FormDefinition:
for validation of the form values. for validation of the form values.
""" """
def __init__(self, name, title, description, fields, script=None, def __init__(self, name, title, description, fields, script=None,
script_raw=False, submit_title="Submit", output='escaped', submit_title="Submit",
allowed_users=None): allowed_users=None):
self.name = name self.name = name
self.title = title self.title = title
self.description = description self.description = description
self.fields = fields self.fields = fields
self.script = script self.script = script
self.script_raw = script_raw self.output = output
self.submit_title = submit_title self.submit_title = submit_title
self.allowed_users = allowed_users self.allowed_users = allowed_users
@ -581,16 +581,20 @@ class ScriptFormWebApp(WebAppHandler):
# Repopulate form values with uploaded tmp filenames # Repopulate form values with uploaded tmp filenames
form_values.update(file_fields) form_values.update(file_fields)
# Call user's callback. If a result is returned, we assume the callback # Call user's callback. If a result is returned, we wrap its output
# was not a raw script, so we wrap its output in some nice HTML. # in some nice HTML. If no result is returned, the output was raw
# Otherwise the callback should have written its own response to the # and the callback should have written its own response to the
# self.wfile filehandle. # self.wfile filehandle.
result = self.scriptform.callback(form_name, form_values, self.wfile) result = self.scriptform.callback(form_name, form_values, self.wfile)
if result: if result:
if result['exitcode'] != 0: if result['exitcode'] != 0:
msg = '<span class="error">{0}</span>'.format(result['stderr']) msg = '<span class="error">{0}</span>'.format(cgi.escape(result['stderr']))
else: else:
msg = '<pre>{0}</pre>'.format(result['stdout']) if form_def.output == 'escaped':
msg = '<pre>{0}</pre>'.format(cgi.escape(result['stdout']))
else:
msg = result['stdout']
output = html_submit_response.format( output = html_submit_response.format(
header=html_header.format(title=self.scriptform.title), header=html_header.format(title=self.scriptform.title),
footer=html_footer, footer=html_footer,
@ -653,7 +657,7 @@ class ScriptForm:
form['description'], form['description'],
form['fields'], form['fields'],
script, script,
script_raw=form.get('script_raw', False), output=form.get('output', 'escaped'),
submit_title=form.get('submit_title', None), submit_title=form.get('submit_title', None),
allowed_users=form.get('allowed_users', None)) allowed_users=form.get('allowed_users', None))
@ -673,7 +677,7 @@ class ScriptForm:
for k, v in form_values.items(): for k, v in form_values.items():
env[k] = str(v) env[k] = str(v)
if form.script_raw: if form.output == 'raw':
p = subprocess.Popen(form.script, shell=True, stdout=output_fh, p = subprocess.Popen(form.script, shell=True, stdout=output_fh,
stderr=output_fh, env=env) stderr=output_fh, env=env)
stdout, stderr = p.communicate(input) stdout, stderr = p.communicate(input)

Loading…
Cancel
Save