ARCHIVED: Web forms with Transform 3.0 users' guide
Due to the evolving coronavirus situation, the retirement of Webserve was delayed until April 16 to allow classes that reference sites on Webserve to continue with minimal disruption.
All remaining Webserve sites were disabled beginning April 16, along with login access to webserve.iu.edu. If you have websites that still need to be moved to IU Sitehosting, you should migrate immediately.
On this page:
- About Transform
- General overview of Transform
- Name your form and template files
- Install Transform in your account
- Set the form action to point to Transform
- Details of creating a template file
- Divide your template into sections
- Set required variables
- Template section details
- *success-response* section
- *error-response* section
- *email-response* section
- *append-response* section
- Specify the filename where the data is appended (!append-file-name)
- Protect append files
- Control where your data is appended in a file (!append-after and !append-before)
- Include record delimiters in your files (!record-delimiter)
- Append to or overwrite files (!append-mode = overwrite)
- Edit, copy, or move your append files (tf_lock and tf_unlock)
- *define-variables* section
- Handle illegal/reserved template characters ([, ], and |)
- Environment variables (!DATE, !HTTP_USER_AGENT, etc.)
- Debug your templates (!debug)
- Advanced use
- Use multiple sections
- Conditional branching (!use-if)
- Force use of the *error-response* (!force-error-if)
- Select which lines in any one section are printed (!print-if and !end-print-if)
- Use external files as part of your template
- Carry information forward to subsequent HTML forms (!carry-forward)
- Use Perl regular expressions in conditional tests
- Authentication: Control access to your forms and documents
- Examples
About Transform
Transform is a generic utility for processing HTML forms. Using Transform, you can have the values submitted via a form emailed to you or appended to a data file. Transform gives you control over the format of the information returned to you as well as the response you return to users.
General overview of Transform
To use Transform, you create an HTML form and a corresponding
Transform template file. The template file allows you to control the
results of a submitted form. Each field in an HTML form has a name
(for example, NAME = "question"
). In the corresponding plain
text Transform template file, you control where the value of a form
variable (for example, a value entered by the user) is displayed by
including the variable name in square brackets (for example,
[question]
). See the example below.
A simple example
In the following HTML code for a form, three fields are defined:
"name", "email", and "question" (that is, NAME="name"
,
NAME="email"
, and NAME="question"
); view what this form would look like to a user.
<html> <head> <title>A Sample Question Form</title> </head> <body> <h2>A Sample Question Form</h2> <hr> <form method = "POST" action = "transform_action_statement"> <p> Enter your name:<br> <input NAME="name" size = 40> <br> Enter your email address:<br> <input NAME="email" size=40> <br> Enter your question:<br> <textarea NAME="question" rows=10 cols=40></textarea> <p> <input type="submit" value="Submit your question"> </form> </body> </html>
To email the results of this form to a user whose email address
is smith@indiana.edu
and provide a "thank you" response
to the user, you could create a corresponding template file like the
following:
# begin template file # Lines beginning with a # sign are considered comments. # The *email-response* line below specifies that this is the email-response # section of the template file. Other sections will be described later. # The other lines are just plain text with html form variable names # enclosed in [ ] where you want the values entered by the user # printed in the email message *email-response* To:smith@indiana.edu From:[email] Subject: Question from [name] Question from [name] Supplied email address is [email] See the question below: [question] # Now begin the *success-response* section that will be displayed to # the user. Because this is being sent back to the user's browser # it must be in the form of an html document *success-response* <html> <head> <title>Thank You</title> </head> <body> <h1>Thank You</h1> Your name is: [name] <br> You supplied the following email address: [email] <br> Your question was: <br> [question] </body> </html> # end template file
To see the results of this template file, fill out this form and submit it. This form will not actually send mail; it will just echo back what the response would look like.
Note that when the *success-response* section of the template
file is echoed back to you, each form variable name in square
brackets is replaced with the corresponding values supplied in the
form (that is, name
, email
, and
question
). If this template were operational, the
*email-response* section would ensure that submitting the form would
also send an email message.
Name your form and template files
In general, you will have a single HTML form and a corresponding
template file. Your HTML form files must have a .html
extension, and the corresponding Transform template files must have
a .tpl
extension.
The HTML form and the template files should be in the same
directory and have the same name except for the extension. For
example, if your form were named send_comments.html
,
the corresponding template file would be
send_comments.tpl
. To avoid confusion, you may want to
create one or more specific forms directories in your
www
directory, and place all forms and templates
there.
Legal/illegal characters: When naming your forms and template files (and any directories that lead to them), you may use only the following characters: A-Z, a-z, 0-9, hyphen (-), underscore (_), and period (.). In addition, you may use tilde (~) and slash (/) when supplying paths to these files.
When a person fills out a web form processed by Transform, if HTML code is included, the code will display as HTML character code for security reasons.
Install Transform in your account
To have Transform process your HTML forms, you must install Transform in your own Webserve account. To install Transform, log into your account using a SSH secure shell client, such as PuTTY. For more about installing or obtaining PuTTY, see ARCHIVED: Use PuTTY to connect to Webserve.
Due to the evolving coronavirus situation, the retirement of Webserve was delayed until April 16 to allow classes that reference sites on Webserve to continue with minimal disruption.
All remaining Webserve sites were disabled beginning April 16, along with login access to webserve.iu.edu. If you have websites that still need to be moved to IU Sitehosting, you should migrate immediately.
Once logged into your account, type cd www
to change
to your www
web document directory. Then, type
tf_install
.
You should install Transform 3.0 into any subdirectory where you
have forms by typing tf_install
from within that directory.
The tf_install
command does the following:
- It creates a
tf_support
directory in your login directory, unless it already exists. Transform will use this directory as needed to store files when processing your forms. - It copies a file called
transform.cgi
into the current directory (that is, the same directory you are in when you typetf_install
). You will point to this file in the form action statement in your form.
- Transform will append to the files in your account immediately when using an *append-response* section in your template.
- You may install multiple copies of
transform.cgi
in different directories if you need to use special access control mechanisms; see Authentication: Controlling Access to Your Forms and Documents. transform.cgi
is not actually the Transform program; it's just a stub that points to it. Thus, you will automatically use new versions of Transform as they're installed.
Set the form action to point to Transform
When a user submits data through an HTML form, the data goes to
an application on the web server. This application reads the form
data and does something with it. Transform is one such
application. To use Transform, you must indicate in your form that
you want Transform to receive and process your form data. In some
cases, you must also specify the location of your template file;
this is the purpose of the action =
string in the HTML
<form> statement that begins a form.
Point to Transform installed in your account
Simple method
In the simplest case where your form and template files have the same name (except for the extension) and are in the same directory, the HTML statement that begins the form and specifies what application should process the form can be:
On www.indiana.edu:
<form method = "POST" action = "http://www.indiana.edu/~username/transform.cgi">
On www.iupui.edu (~username accounts only):
<form method = "POST" action = "http://www.iupui.edu/~username/transform.cgi">
When someone submits your HTML form, Transform will know the location of your form, and can thus derive the location of your template file if it has the same name and is in the same directory. The statement breaks down as follows:
<form
begins the form.- Using
method = "POST"
will post data. Always usemethod = "POST"
when using Transform in HTML forms. For more, see URIs, Addressability, and the use of HTTP GET and POST from the W3C. action =
specifies where to send form data. In this case,http://www.indiana.edu/~username/transform.cgi
orhttp://www.iupui.edu/~username/transform.cgi
.This statement essentially provides a URL to
transform.cgi
in your account. You build this URL just as you would build a URL to a document in your web directory using a tilde (~) before your account name. (Thus, if you issued thetf_install
command in some subdirectory of your web directory, you would have to include additional directory path information in the URL.)If you have installed Transform in every directory where you have a form, you can use a relative link to
transform.cgi
rather than the entire path. Your form action statement for either campus would then read,<form method = "POST" action = "transform.cgi">
.For more, see Authentication: Controlling access to your forms and documents. Although this describes controlling access to documents in your web directory, the information also applies to
transform.cgi
in your account, because it is installed in your web directory.
Complete method
In cases where you have multiple forms per HTML file, or a form in a *success-response* or *error-response* section, you must specify the exact location of the template file. Otherwise, Transform won't find your template file and will report an error. This method is similar to the one described above, except that you must supply a path to the template file:
<form method = "POST" action = "http://www.indiana.edu/~username/transform.cgi?template_path">
or
<form method = "POST" action = "http://www.iupui.edu/~username/transform.cgi?template_path">
The template_path
specifies the location of your
template. As an example, assume that your account name on the web
server is www-user
, and the template is stored in your
www
directory along with the rest of your HTML
files. If your template were called comment.tpl
, the
path you would specify is www-user/www/comment
.
This is a combination of your web server account name, the path
to your template directory (in this case, www
), and the
name of the template with no extension. Note the
question mark (?
) separating the location of Transform
and your template path. The question mark is
required.
In this example, the complete action=
specification
would be one of the following:
http://www.indiana.edu/~username/transform.cgi?www-user/www/comment
http://www.iupui.edu/~username/transform.cgi?www-user/www/comment
Note that
http://www.indiana.edu/~username/transform.cgi
or
http://www.iupui.edu/~username/transform.cgi
is a complete URL to the copy of Transform. You may also provide a
shortened URL that is like a normal relative URL:
/~username/transform.cgi
. Be sure to include the
leading slash (/
).
The specification for action =
must be on a single line
(that is, with no returns). If you include a return in the action
=
string, some versions of Netscape may display a "Broken
Pipe" message or some other odd message; alternatively, Transform
may display the following error with no path given:
Account does not exist Error in path specified:
Virtual host users
To use Transform with a virtual host, you must install Transform in
your account as described above. When pointing to Transform
in the action =
statement, supply the following:
http://my_virtual_host.indiana.edu/transform.cgi
This assumes you have transform.cgi
installed in your standard
document directory. If you have it installed in a subdirectory, you
must supply additional path information.
Details of creating a template file
Divide your template into sections
In the examples above, the *email-response* template section header declared that the template information that followed would be sent as an email message. The *success-response* section header declared the section of the template to be displayed to a user who successfully submits the form. There are actually five possible template sections (and section headers) that control how you want to dispense submitted form information. When you create a template file, you simply include the sections you need for your specific application.
When using section headers, you must include one or more
asterisks on both sides of the name (for example,
*email-response*
, ***email-response***
,
etc.), and you must always begin them in the first column of your
template file.
The five types of sections and their section headers in a template are:
- *success-response*: Describes the message that is returned to users when they successfully submit a form. Always use this section to inform users that a form was successfully submitted. Because this section is returned to a user's web browser, it must be in the form of an HTML document.
- *error-response*: Describes the message that is
returned to users if they did not fill out the form correctly. As
you'll see below, you may specify that certain form variables are
required; that is, if the user does not fill them in, the
*error-response* section of the template (and only this section)
will display.
By using the
!force-error-if
command, you can force only the *error-response* to display based on testing the values of the form variables entered by the user. Always use this section if you define required fields or force an error so that you can inform users where they made an error in the form. Because this section is returned to the user's web browser, it must be in the form of an HTML document. - *email-response*: Describes the format of an email message to be sent to you. Only use this section if you wish to receive the results of a submitted form as an email message.
- *append-response*: Describes how you would like form information appended to a data file in your account. Only use this section if you need to have form information appended to a file.
- *define-variables*: Defines whether a variable is required, error messages for required variables, and the values of some special variables. Like the other sections, this is not required unless you need its special features.
Which sections are used and when
When Transform reads the values submitted via a form, it sets a flag indicating success or error. Transform sets an error flag if a user doesn't complete a required form variable, or if you force an error based on the values the user supplied. If the error flag is set, only the *error-response* section of the template is processed, and no other sections are examined. If there is no error condition, any *error-response* section is ignored; the *success-response*, *email-response*, and *append-response* sections are processed instead.
Set required variables
If you don't wish to receive the results of a form unless the user fills in a particular field, you can designate that field as required.
In the Transform template file, specify a required field (that is,
variable) by appending req-
to the variable name. For
example, if you had a text input area named "email" in your form
(name = "email"
), then in your template, you would
normally enclose the email
variable in square brackets
([email]
). In the template, you can make
[email]
a required variable by prefixing
req-
to the variable name
([req-email]
).
req-
doesn't
change the name of the variable; the req-
is stripped
from the variable name as the form is processed.
An example with required variables (using error and response sections)
In the following example, the "email" and "question" fields are required; however, the "name" field is not:
# begin template file # Lines beginning with a # sign are considered comments. # Use the *define-variables* section to specify which variables # are required. Supply a specific error message for the [email] variable *define-variables* [req-name] [req-email] = "<b> Please enter an email address </b>" [req-question] # The *email-response* line below specifies that this is the email-response # section of the template file. Other sections will be described later. # The other lines are just plain text with html form variable names # enclosed in [ ] where you want the values entered by the user # printed in the email message *email-response* To:smith@indiana.edu From:[email] Subject: Question from [name] Question from [name] Supplied email address is [email] See the question below: [question] # Now begin the *success-response* section that will be displayed to # the user. Because this is being sent back to the user's browser # it must be in the form of a html document *success-response* <html> <head> <title>Thank You</title> </head> <body> <h1>Thank You</h1> Your name is: [name] <br> You supplied the following email address: [email] <br> Your question was: <br> [question] </body> </html> # Now let's add a error-response section # Again, this must be in the form of a html document because it is being # returned to the user's browser. # Remember, this section is displayed to the user when required # fields, flagged with req-, are not completed by the user. *error-response* <html> <head> <title>Sorry, you made an error</title> </head> <body> <h2>Sorry, you made an error</h2> <p> You must complete the following fields: <p> Your name: [name] <p> Your email address: [email]<p> Your question: <br> [question]<p> Use the <b>back</b> selection on your browser to go back and complete all required fields.<p> </body> </html> # end template file
Try submitting the form with all fields completed, and then submit the form again without completing all fields. Note that when required fields ("question" or "email") aren't filled in, the *error-response* section of the template is returned to you. When all fields are completed, the *success-response* section is returned.
In the above template example, req-
prefixed a
variable ([email]
) only once. If a variable is prefixed
with req-
anywhere in a template, it affects the
variable everywhere else it appears in the template.
Template section details
*success-response* section
The *success-response* section allows you to create a message that is returned to users who successfully submit a form. Always use this section to inform users that their information was successfully submitted. If no *success-response* section is present, the *email-response* or *append-response* section will display to the user instead.
Because the *success-response* is returned to the user's web browser, it must be in the form of an HTML document. For example:
# This section must be a correct html document *success-response* <html> <head> <title>Your title</title> </head> <body> Your html success response with variables included in [ ]s anywhere you like. Note that because this is an html document, you can include href links to other documents or images if you like. </body> </html>
Since the *success-response* section is an HTML document, you may include HTML forms that call other Transform templates. Using this technique, you can effectively chain multiple forms together.
*error-response* section
The *error-response* section allows you to display an error
message to users if there were errors in the submitted form. The
only time the *error-response* section displays is if a user didn't
fill in a field you specified as required, or if you used the
!force-error-if
command (see below) to define an error
condition based on the user-supplied values. If you have required
fields in your template, you should always add an *error-response*
section.
The format of the *error-response* section, like the *success-response* section, must be in the form of an HTML document because it is returned to the user's web browser. Error messages for form variables that the user doesn't complete will not automatically appear in the *error-response* section when it is returned to the user. To display an error message, you must supply the variable name in brackets ([]). For example:
# This section must be a correct html document *error-response* <html> <head> <title>Your title</title> </head> <body> # Include in your error response variables # in [ ]s anywhere you like. Typically you may want # to include something like the following to be sure that # the user sees the error message for each variable: The following variables must be completed in this form:<p> Description of your first variable:[var1]<br> Description of your second variable:[var2]<br> Description of your third variable:[var3]<br> # Here, [var1] would be replaced with the error message # for var1 if it wasn't filled in by the user. The same # for [var2] and [var3]. # Also include instructions for getting back to the # partially completed form such as: Use the <b>back</b> selection on your browser to go back and complete all required fields.<p> </body> </html>
You can use !print-if
to print only the information
about the required variables that were missing. For more, see Selecting which lines in any one section are
printed.
*email-response* section
The *email-response* section defines the format of an email message that will be sent to you. The first four lines of the *email-response* section must be:
*email-response* To:username_to_receive_message@indiana.edu From:some_user@somewhere Subject: a subject for the message
General rules for the *email-response* section:
- There must be no blank lines separating the
first four lines shown above. If the three lines following the
*email-response* section marker do not contain
To:
,From:
, andSubject:
(in exactly that order), Transform won't send the email message. - The "To:" field must not be blank.
- What you have in the body of the message after the first four lines is up to you. You should include one blank line after the "To:", "From:", and "Subject:" header information. Since this will be sent as a normal ASCII mail message, any blank lines or spaces you include in the body of the *email-response* section will appear in the email message.
- If you do not define a *success-response* or *error-response* section in your template file, the *email-response* section will be used in their place to send a response back to the user after the form is submitted. This is bad practice; you should always supply the other sections.
- A note on building a "From:" address: For publicly available
forms, you should request the user's email address and have the
variable inserted into the "From:" field (for example,
From:[email]
). Remember, however, that this cannot be trusted. The user could enter anyone's email address. - When using the
iu_auth
oriupui_auth
form of Transform, you can build the "From:" email address with an environment variable. The!NETWORK_ID
variable is set to the user's network username. By adding@indiana.edu
or@iupui.edu
to the!NETWORK_ID
, you can build a trustworthy "From:" address (for example,From:[!NETWORK_ID]@indiana.edu
orFrom:[!NETWORK_ID]@iupui.edu
). For more aboutiu_auth
oriupui_auth
and other ways of restricting access, see Authentication: Control access to your forms and documents.
*append-response* section
The *append-response* section defines how form information will be appended to a data file. The format of the *append-response* section is up to you; like the other template sections, you include a form variable name in square brackets to have its value included in the file.
Use the *append-response* section any time you want the submitted form information appended to a file. Examples might include collecting data to be added to a database or having form information appended to an HTML file to be displayed to users (for example, for a guestbook).
You can modify how or when information is appended to a file with
a variety of commands (described below). All the commands begin with
an exclamation point (for example, !command
), and must
immediately follow the *append-response* section header, one command
per line. They must also begin in column 1. The first line following
the *append-response* header that does not begin
with one of the following commands is treated as the beginning of the
information you want appended to a file.
The Transform commands specific to the *append-response* section include:
!append-file-name
= your_file_name!append-after
= "string"!append-before
= "string"!record_delimiter
!append-mode
= overwrite
These will be discussed after a short example.
Example
Assume you have a form which collects information for three form
variables, [name]
, [email-address]
, and
[comment]
, and you want the results of a form
submission appended to a file. You could use the following
*append-response* section:
*append-response* !append-file-name = my_file_name Name: [name] Email address: [email-address] Comment : [comment]
In the above example, the information would append to a file just as you see it, except the values entered by the user submitting the form would replace the variable names in square brackets.
Specify where the data is appended (!append-file-name)
The default: If you don't specify an
!append-file-name
command, Transform will attempt to
build a default file name. This isn't a good idea, but it is
allowed. By default, the results of the form are appended to a file
called service.dat
(where service
is the
name of your form/template without the extension) in a directory
called form_data
in your login directory. To use this
default behavior, you must first create a directory called
form_data
in your login directory. If the
service.dat
file does not exist, it will be created
(and then appended to next time).
Using the !append-file-name command
You must place the !append-file-name
command
immediately following the *append-response* section header along
with other !commands. The general form of the
!append-file-name
command is:
!append-file-name = "file_to_append_to"
Replace file_to_append_to
with the path to a
file.
There are three possible ways to specify the "file_to_append_to":
- A complete path. If you type
pwd
(meaning "print working directory") in any directory, you will see a complete path to that directory. To create an acceptable "file_to_append_to", add the specific append file name to the result of thepwd
command. For example:/ip/account/my_append_directory/my_append_file_name.dat
. - A path relative to your login directory. If the
"file_to_append_to" begins with a tilde (~), it is assumed that the path is
relative to your login directory. For example:
~account/my_append_directory/my_append_file_name.dat
. - A simple file name. If "file_to_append_to" is just a file name
with no slashes (/) indicating the path, Transform will append to
the "file_to_append_to" in your default append directory,
form_data
. For example, the command!append-file-name = "mydata.dat"
would append the form data to themydata.dat
file in theform_data
directory, which is in your login directory. (As described above, you must create theform_data
directory before appending to files there.)
General rules for !append-file-name
- If the "file_to_append_to" specified does not exist, Transform will create it.
- You must create the directories first. If you specify a complete path to a file and the directories in the path do not exist, Transform will report an error and won't create the directories.
- You may only append to files in your own account.
Illegal characters: When naming an append file (and any directories that lead to them), you may only use the following characters: A-Z, a-z, 0-9, hyphen (-), underscore (_), and period (.). In addition, tilde (~) and slash (/) may be used when supplying paths to these files.
Be aware that in the !append-file-name =
"file_to_append_to"
command, the "file_to_append_to" may include one
or more form variable names in brackets. Before appending to the
file, the "file_to_append_to" string will have any variable name in
brackets replaced by their value. This allows you to change the name
of the append file based on user form input. For example, if you had
a form variable named class
that had possible values of
freshman
, sophomore
, junior
, or
senior
, you could write data to freshman.dat
or
sophomore.dat
, etc. using the following:
!append-file-name = "~account/my_dir/[class].dat"
[class]
would be replaced with the value for the
class variable in the append file name. Note, however, the warning
about illegal characters above. If you attempt to create a file name
based on variables supplied in a text input area by the user, an
error may result if the user enters illegal characters. (For more,
see the !trim section.)
Protecting append files
When creating or modifying an append file, Transform makes the following assumptions about how the file should be protected (for example, readable by others or not):
- If the append file is being created in your web directory where
normal HTML files go (that is,
www
orwwws
), Transform assumes that you want the append file delivered over the web (for example, a guestbook) and creates the file with world-read privileges. - If the file is being created anywhere outside the web directory, Transform assumes that the file should remain private and creates it such that only the owner has privileges.
- If Transform is appending to a file that already exists (that you or Transform created), it will not change the privileges. If you change the privileges of a file, Transform will honor these changes.
Controlling where your data is appended in a file (!append-after and !append-before)
Two commands, !append-after
and
!append-before
, give you some control over where new
information is placed in an append file. The general form of these
commands is:
!append-after = "string" !append-before = "string"
In the above example, string
is some string in your
append file. If you supply one of these commands, Transform will
search your append file for the first occurrence of
string
, and then place the new form data on the line
immediately before (if you used !append-before
) or
after (if you used !append-after
) this
string
.
You may only use one of these commands in any given *append-response* section.
As an example, let's assume you have an HTML guestbook file with
a standard header and footer, and you want Transform to place any
new information submitted in a form between the header and
footer. You could do this by placing an HTML comment such as
<!-- include after here -->
between the header
and the footer at the beginning of an *append-response* section. For
example:
*append-response* !append-after = "<!-- include after here-->" ... the rest of your append response goes here ...
This would cause all new submissions to append immediately after
the <!-- include after here -->
HTML
comment. Note that this would also prepend the newest submissions to
the top of the file (right after the comment but before previous
submissions). If you used !append-before
instead, the
newest submissions would be at the bottom of the file, before the
comment, but after previous submissions.
If Transform doesn't find the string
for an
!append-before
or !append-after
command,
Transform will append the new information to the end of the file
(and no warning message will display).
!append-before
or !append-after
commands. To insert information at the appropriate place in the
file, Transform must read through the entire file and then re-write
it. Appending in this fashion can become very slow
if the file grows large. Avoid using these commands if you are
simply collecting data and the files may become large.
As described for the file name in the !append-file-name
command, the string
following !append-before
or
!append-after
may contain form variable names in brackets. This
allows you to have multiple comment tags in an HTML document, with
information being placed before or after a particular tag based on
the value of a form variable supplied by the user.
Including record delimiters in your files (!record-delimiter)
When using append files to collect information, it is often useful to have begin and end record markers included in the file so you know where one submission ends and the next one begins. You can do this by including tags in your *append-response* section which mark the beginning and end of the record, or you can allow Transform to do it for you.
If you include !record-delimiter
at the beginning of
the *append-response* section (along with any other !commands),
Transform will automatically include the following HTML comments at
the end of each submitted record:
<!-- Begin Record "seconds" "date" --> at the beginning of each submitted record and <!-- End Record -->
Here, "seconds"
is the number of seconds since January
1, 1970 (useful for easily determining the age of a record), and
"date" is the current date (for example, Mon Jul 6 13:43:16 EDT 2015).
Transform writes the begin record comment this way because another application, which is not yet complete, will allow you to scan your append file containing this standard begin record tag and eliminate records older than some number of hours or days. For example, cleaning up older records might be important for a ride board, calendar, or other application where old records should be removed or archived.
You may also have additional information in the begin record
comment tag by including a string after the
!record-delimiter
command, where string
is
any string (and may include form variables in brackets):
!record-delimiter = "string"
This writes string
in the begin record tag after the
date and before the close of the HTML comment.
Appending to or overwriting files (!append-mode = overwrite)
Normally, Transform just appends (or adds) data to a file (although
you can control where it includes new information with
!append-after
and
!append-before
). However, there are occasions where
you'd want Transform to completely overwrite a file with the new
form information. You can enable this with the !append-mode =
overwrite
command.
If you place !append-mode = overwrite
at the
beginning of your *append-response*, new information will overwrite
rather than append to the file specified with the
!append-file-name
command. Be aware that this destroys
any old information in the append file.
As an example of when you might wish to do this, assume that you
want to create an HTML file that contains the date when your form
was last used. The following *append-response* section would create
a new (overwritten) file that includes the current date every time
your form is submitted to Transform (this uses the
[!DATE]
environment variable to stamp the date in the
file).
*append-response* !append-file-name = ~account/www/last_date.html !append-mode = overwrite # Remember lines beginning with # are comments # The first line following the *append-response* header # that doesn't begin with ! is the beginning of the data for the file <html> <body> This form was last accessed on [!DATE] <p> </body> </html>
Editing, copying, or moving your append files (tf_lock and tf_unlock)
If you attempt to edit an append file while Transform is trying
to append new user-supplied information to it, you may get
unexpected results. Before Transform adds information to your append
file, it first creates a lock file. If you need to edit an append
file, you must let Transform know you are in the process of
modifying the file. You do this with two utilities,
tf_lock
and tf_unlock
:
- Log into your account and
cd
to the directory containing the append file you wish to edit. - To create a lock file, type
tf_lock file_name
, wherefile_name
is the name of the append file you wish to modify. - Edit your file. Since it is locked, Transform will postpone any modification to the file until it is unlocked.
- Type
tf_unlock file_name
to unlock the file (don't forget, or no new information will be appended).
In general, use tf_lock
and tf_unlock
any time you need to work with append files and don't want Transform
simultaneously trying an append operation.
Transform appends to files immediately when the form is
submitted. The only exception is when you lock the file with
tf_lock
. If a user attempts to append to one of your
files while you have it locked, Transform will temporarily store the
user append information in your account. Once you unlock the file,
the next form submission to your account will cause any pending user
information to be appended in the order in which the information was
received.
*define variables* section
The *define-variables* section, unlike the other template sections, is never output. It sets the properties of various global variables, sets global error conditions, and defines properties for required variables. A discussion of each feature follows.
Setting required variables
As shown in the examples above, a variable name that begins with
req-
anywhere in the template file is considered a
required variable or field. Often, especially in forms with lots of
variables, it isn't convenient to have your req-
declarations sprinkled all over the template file. To avoid this,
use the *define-variables* section to define all your required
variables in a single compact section, typically at the top of your
template file.
Each variable name listed in square brackets in the *define-variables* section must be on a line by itself. For example:
# Begin the define-variables section # Remember lines beginning with # are comments # This sample section simply declares that the # following three variables are required *define-variables* [req-name] [req-email] [req-question] #end define-variables section # other sections follow ... include other sections here ... #end template
Specifying error messages for required variables
By default, when a user fails to fill out a required variable, Transform will replace the empty value of the variable with the following:
**** Error - value required *****
When the *error-response* section of your template displays to the user, this error message will be printed where the variable name in square brackets appears (just as an actual user-supplied value would). Think of this error message as the default value for all required variables; if the user doesn't supply a value, the error message will display.
In the *define-variables* section, you can override this default and specify an error message for each required variable by using the following format:
[req-yourvariable] = "Your error message for this variable"
Since this error message is returned to the user via the
*error-response* section, it is effectively part of an HTML
document. Thus, you may include HTML markup tags in your error
message. This includes not only simple markup like bolding your error
message (for example, <b>Error Message</b>
), but
also links (that is, <a href= ...
) to other documents
that might describe how to complete the form field.
Because your error message may be long (especially if you
include links to other documents), it may continue on multiple
lines. Remember to start each new required variable name (in square
brackets) on a new line. Also, you may include variable names in
square brackets (for example, [req-email] = "Sorry [name], email
address required"
) in the body of the error message. For
example:
# begin define-variables section # quotation marks around the error message are optional *define-variables* [req-name] = <b>You must complete the name field</b> [req-email] = "The email field is required, see <a href="http://www.indiana.edu/~www-user/email_instruct.html"> Email Instructions</a> for information on completing the email address field" # Since no error message is supplied for [req-question] # below, the default error message will be used [req-question] # end define-variables section
Special command variables in the *define-variables* section
You can also change some of Transform's default behavior by including special command variables and their new values in the *define variables* section. These are of the general form:
!special_variable_name = new value
Each special variable name begins with an exclamation point
(!). Each !special_variable = new value
must begin on a
new line, and most may continue on multiple lines if necessary. You
may use the following special command variables in your
*define-variables* section:
- !general-error-message = "your
default error message"
The
!general-error-message
command allows you to change the default error message. By default, when the user doesn't complete a required field, Transform inserts**** Error - value required ****
.While you can provide an individual error message for each required variable (see above), you may also change this default error message by including
general-error-message = "your default error message"
.Note that HTML codes may be included in the !general-error-message, including links to other documents if appropriate.
- !append-file-name = file_to_append_to
The
!append-file-name
command allows you to set the name of the file you want the form information appended to. You should place this command at the top of your *append-response* section. For more, see Specifying the filename where data is appended. - !show-sig = no
By default, the Transform signature, "<hr/> Form processed by Transform version #.#", will appear at the end of the page returned to users. To remove this signature from your response, include the line
!show-sig = no
in the *define-variables* section of your template file. - !checkbox-html-delimiter = "delimiter" and
!checkbox-text-delimiter = "delimiter"
These two command variables are similar and will be discussed together. If you don't use HTML checkbox-type input fields, skip this section.
The HTML forms language allows you to create multiple checkboxes which have the same
NAME = variable_name
(if you don't use the sameNAME=
for multiple checkboxes, skip this section), resulting in multiple values for the same variable name. The problem, then, is how to display multiple values for the same variable name. Transform does this by inserting a delimiter between each value for the variable when they display as the result of a[checkbox-variable]
in your template. By default, Transform puts a comma followed by a space (, ) between the values.The two command variables,
!checkbox-html-delimiter
and!checkbox-text-delimiter
, allow you to change this default delimiter.The
!checkbox-html-delimiter
command variable changes the delimiter when a checkbox value is displayed in the *error-response* and *success-response* sections of your template (remember, these sections are HTML documents). For example,!checkbox-html-delimiter = "<br>"
would result in a line break between each checkbox value when the *error-response* or *success-response* is returned.The
!checkbox-text-delimiter
command variable changes the delimiter used in the *email-response* and *append-response* sections of your template (remember, these are plain text documents). For example,!checkbox-text-delimiter = " - "
would result in a space, a dash, and a space between each checkbox value in the *email-response* and *append-response* sections. - !trim = [var1] [var2] [var...]
Use the
!trim
command if you want to ensure variables supplied by the user have no leading or trailing spaces. Any variable names in square brackets after the!trim =
command will have any leading or trailing spaces removed. The!trim
command may not be continued on multiple lines, but you may repeat it as many times as you like. This command can be handy if, for example, you want to build a file name with a word supplied by the user in a text input area and want to ensure it has no leading or trailing spaces. - !force-error-if expression
The
!force-error-if
command lets you force the use of the *error-response* section (and as a result, no other sections) based on the values of the variables supplied by the user. For more, see Forcing use of the *error-response*. - !use-linebreak mode = [var1] [var2] [var...] and
!linebreak-delimiter = "delimiter"
There may be a problem when you use <textarea> input areas in your forms. Users may type or paste multiple paragraphs into these textarea boxes. If this text (via a Transform variable) then displays as an HTML document (for example, *success-response*, *error-response*, or an append file that is an HTML document), any white space separating paragraphs will be represented as a single space in the HTML document, and thus paragraphs will run together. This is typical for HTML documents; <br> and <p> tags are generally used to achieve line breaks and paragraphs.
The Transform
!use-linebreak-mode
command can help alleviate (but not eliminate) this problem. The!use-linebreak-mode
command tells Transform which of your form variables are textareas. When outputting these variables to HTML documents, Transform will add an HTML line break (<br>) before each hard return. The assumption is that word processors place a hard return at the end of paragraphs, and if a user is typing into a textarea box, they will use theEnter
key to indicate paragraph or line breaks. Thus, if a user pastes text into a textarea from a word processor document or simply types into the textarea, the <br> added before the hard return will simulate, via HTML markup, the line breaks intended by the user.You can include the
!use-linebreak-mode
command either in the *define-variables* section or at the beginning of any other section (along with any other !commands). It has the general form:!use-linebreak-mode = [var1] [var2] [var...]
In the above example,
[var1]
,[var2]
, and[var...]
are the textarea variables in your form you'd like treated this way.Unlike many other *define-variables* commands, the
!use-linebreak-mode
command cannot be continued on multiple lines. If you have more [variables] than will fit on a single line, repeat the!use-linebreak-mode
command as many times as necessary to list all your variables. Note that the addition of the HTML line break, <br>, is typically useful only if the template section will result in HTML output (for example, you wouldn't want many <br> tags in your email messages). Transform makes the following assumptions about which sections are to be treated as HTML documents and therefore when it will include <br> tags before hard returns:Transform will always honor
!use-linebreak-mode
commands at the beginning of a *success-response*, *error-response*, *append-response*, or *email-response* section. Transform will ignore any!use-linebreak-mode
commands in *define-variables* while that section is being processed (that is,!use-linebreak-mode
commands for individual sections override settings in the *define-variables* section).Given the above, if you include
!use-linebreak-mode
commands in the *define-variables* section, the following rules apply:Since Transform always returns *success-response* and *error-response* sections to the user's browser as HTML documents, Transform always performs this conversion on specified variables in these sections.
Transform will perform this conversion on *append-response* sections if the append file name ends in
.html
; it assumes that you want an.html
append file viewed via the web. If the append file name ends in anything other than.html
(that is, you're using the *append-response* section to collect data), Transform won't perform this conversion.Transform never performs this conversion on *email-response* sections, since these are mailed as plain text documents.
As described above,
!use-linebreak-mode
places a <br> before any hard return. If you enclose a textarea variable that is being processed by the!use-linebreak-mode
command in <pre> and </pre> tags, the resulting lines will be double spaced. This is because both the <br> and the hard return cause a line break. To avoid double spacing, change the line break character to <br> by including the following line in your *define-variables* section:!linebreak-delimiter = "<br>"
You may get unexpected results if you set the line break delimiter to anything else.
Handle illegal/reserved template characters ([, ], and |)
Three characters cause problems if you try to use them as normal printing characters in your templates: [, ], and |. You can only use square brackets ([ and ] ) in your templates on either side of a variable name. Vertical bars (|) cannot be used as printable characters, because Transform uses them internally.
To print these characters, use character codes in their
place. Character codes will convert to the appropriate
characters. The character codes are as follows: %5b
([), %5d
(]), %7c
(|).
Environment variables (!DATE, !HTTP_USER_AGENT, etc.)
In addition to the variables you have defined in your form, you may print some standard environment variables.
Environment variables must begin with an exclamation point (!), and should be uppercase to distinguish them from your own variables. Like other variables, they must be enclosed in square brackets in your template. Environment variables currently allowed include:
- [!NETWORK_ID] - The user's Network ID when using
iu_auth
oriupui_auth
forms of Transform. This variable is not set unless usingiu_auth
oriupui_auth
, or if you have developed an.htaccess
file that requires users to enter a username and password. - [!DATE] - Prints the date and time
- [!HTTP_USER_AGENT] - The type of web browser being used
- [!REMOTE_HOST] - The name of the machine making the form request
- [!REMOTE_ADDR] - The IP number of the machine making the form request
- [!TIME] - The number of seconds since January 1, 1970. This is
useful for creating unique filenames. For example,
!append-file-name = "[!TIME].html"
would create unique file name each time someone uses the form and template.
While the [!DATE] variable above allows you to stamp the current date, it prints a complete date string. If you wish to customize the date format, use the following additional environment variables:
- [!SDOW] - The day of the week abbreviated to three characters
- [!DOW] - The day of the week (complete spelling)
- [!SMOY] - The month of the year abbreviated to three characters
- [!MOY] - The complete month of the year
- [!D] - The day of the month (1 or 2 digits as required)
- [!DD] - The day of the month (always 2 digits; for example, 01, 02)
- [!M] - The numeric month of the year (1 or 2 digits as required)
- [!MM] - The month of the year (always 2 digits)
- [!YY] - The year (2 digits)
- [!YYYY] - The year (4 digits)
- [!HOUR] - The hour of the day (always 2 digits)
- [!MIN] - The minute of the hour (2 digits)
- [!SEC] - The seconds (2 digits)
Debug your templates (!debug)
By default, Transform tries to inform you of errors in your templates. There are cases, however, when Transform can't be sure whether a line contains an error or something you intended, and as a result reports nothing. This can lead to unexpected results when running Transform.
To assist with this problem, you can tell Transform to use debug mode while scanning your templates. In debug mode, Transform will more carefully examine each line and report potential errors.
To invoke debug mode, include !debug
as the
first line in your template. If you add a
2
to this line (that is, !debug 2
), in addition to
potential errors, Transform will report information about the
variables and sections it finds in your form and template. This can
be useful for detecting misspellings of variable names and section
headers.
Be sure to remove (or comment out with a #
) the
!debug
command before putting your form/template in
production; this mode always results in the printing of beginning
and ending debug headers.
Advanced use
Transform has additional features that allow chaining forms together and conditional display of information based on user input. The following assumes that you understand the general form/template features described above.
Use multiple sections
Transform allows you to have only one *define-variables* section, but you may have as many different *success-response*, *error-response*, *email-response*, or *append-response* sections as you like in any template.
For example, your template might contain two *email-response* sections if you wanted to send two differently formatted email messages (for example, a user confirmation message and an internally formatted message with different information). As another example, you might want to use two *append-response* sections to append different information to two different files.
Transform examines and processes multiple sections of the same type (for example, multiple *success-response* sections) in the order they appear in your template. When using multiple sections, keep the following in mind:
- If you have multiple *success-response* sections that qualify to
be output (see Conditional branching), they will
be output in the order they appear in the template (that is,
concatenated together). The same is true for *error-response*
sections; however, they display only when a required variable is
missing or a
!force-error-if
error condition is set. - If you have multiple *append-response* or *email-response* sections, Transform processes them in the order they appear in the template, but each section is processed independently (that is, there is no concatenation of multiple sections of the same type).
- Internally, Transform processes and outputs your sections in the following order: any *error-response* sections (if required, and then stops), any *email-response* sections, any *append-response* sections, and finally, any *success-response* sections. In addition, Transform performs some error checking just before each section is output. As a result, if when first developing a Transform template you make errors, Transform may process and output the sections without errors if they appear first in the template. Transform will then stop when it reaches the error.
Conditional branching (!use-if)
Transform supports a form of conditional branching. This feature
allows you to control which sections in your template are processed
based on the form values supplied by the user. The general idea is
that you may begin a template section with a !use-if
command which defines a logical test against the value of one or
more form variables. The entire section will only be processed if
the expression is true. The general form of the !use-if
command is:
!use-if expression
In the above example, expression
is a logical
expression. The expression may be as simple as testing the value of
a single variable (for example, !use-if [food] eq "apple"
) or,
as in the following example, a more complex test of multiple
variables.
Assume you have an HTML checkbox on your form that allows users to indicate that they would like to receive a confirmation email message after submitting a form. The HTML code for this checkbox might look like:
Check this box to have a confirmation email message sent <input type = checkbox name = confirm value = yes>
The name of this checkbox is confirm
; if checked by
the user, it would send a value of yes
to be
processed.
You could then create an *email-response* section in the corresponding template file that would only be sent if this checkbox were checked by including a conditional test:
*email-response* !use-if [confirm] eq "yes" To:whoever@indiana.edu From:[username]@indiana.edu Subject: Confirmation message ...the rest of your message template...
In the conditional test above, !use-if [confirm] eq
"yes"
says process this section (in this case, send an email
message) if the HTML form variable confirm
has a value
of yes
.
Note that the conditional test immediately follows the *email-response* section header. Transform ignores conditional test statements if they do not immediately follow the section header.
General rules for !use-if
- The
!use-if
command is allowed in the *success-response*, *error-response*, *email-response*, or *append-response* sections and must immediately follow the section header, before any other !commands you may need for that section. They are not allowed in the *define-variables* section, which is never output to users. - Each section may only contain one
!use-if
command. - The
!use-if
command must start in column 1. Expressions may span multiple lines, but each continuation line must begin with!!
starting in column 1.
General rules for building expressions
Following are general rules for building logical
expressions. While these are shown with the !use-if
command, the expressions can also be used to control which lines of
a section are printed (!print-if
) or to set an error
condition (!force-error-if
).
Allowed comparison operators
Following is a complete list of available c operators:
Comparison operator | Meaning |
---|---|
eq | equal string comparison q |
ne | not equal string comparison |
== | equal numeric comparison |
!= | not equal numeric comparison |
> | numeric greater than |
< | numeric less than |
<= | numeric less than or equal |
>= | numeric greater than or equal |
=~ | Perl regular expression matches
|
!~ | Perl regular expression doesn't match
|
In addition, you can use the following shortened test (that is,
without an operator or value) to see if the variable has any value
(that is, if anything was entered by the user). Simply enter the
variable name without an operator. For example, !use-if
[var]
would be true if [var]
has any value other
than null ("") or zero (0).
Note the difference between string and numeric comparisons. For
example, a string comparison of 1.0 e 1
would be false
because strings are being compared, but 1.0 == 1
would
be true because numerically, 1.0 equals 1. Be sure to use the
correct comparison type. In addition, note that string comparisons
are case insensitive, for example, YES eq yes
would be true.
For more about the =~ and !~ Perl regular expression operators, see Using Perl regular expressions in conditional tests.
Allowed Boolean operators
In addition to the comparison operators above, you may use the following Boolean operators when building tests for multiple variables:
Boolean operator | Meaning |
---|---|
not | logical not |
and | logical and |
or | logical or |
You can use these operators to test the values of multiple
variables in a single test. Boolean operators are evaluated in a
specific order: "not" is evaluated first, followed by "and", and
finally "or". If needed, you can also use parentheses to group tests
together and ensure the evaluations are in the order you intend. If
the test you wish to use won't fit on one line, you may use multiple
lines. Any additional continuation lines must, however, begin with
!!
in column 1. For example:
!use-if [class] eq "freshman" or [class] eq "sophomore"
!use-if [class] eq "freshman" or [class] eq "sophomore" !! or [class] eq "junior"
!use-if ( [class] eq "freshman" or [class] eq "sophomore" ) !! and [school] eq "business"
Multiple comparisons (!use-if examples)
Often you may want to test the values of two or more variables to determine whether a given section should be used; for example:
- The following two lines would cause a section to be processed if
the form variable
computer
had a value of"ibm"
and the form variableproblem
had a value of"printing"
:!use-if [computer] eq "ibm" and !! [problem] eq "printing"
- The following two lines would cause a section to be processed if
the form variable
location
had a value of"IU"
or the form variablehost
had a value of"IU"
:!use-if [location] eq "IU" or !! [host] eq "IU"
- Things become more complicated when you need to use multiple
logical operators together. For example, assume that you want to
process a template section only if
favorite-color
is"red"
andclass
is either"grad"
or"senior"
(that is, process the template section for either graduate students or seniors whose favorite color is red). Consider the wrong and right ways to do this:Wrong:
!use-if [favorite-color] eq "red" and !! [class] eq "grad" or [class] eq "senior"
Remember, "and" statements are evaluated before "or" statements. This
!use-if
command says process this section only if users' favorite color is red and they are "grad" students; then, add (or) all seniors, so the combined set ends up being true for grads whose favorite color is red plus seniors.Right:
!use-if [favorite-color] eq "red" and !! ( [class] eq "grad" or [class] eq "senior" )
By putting parentheses around the "or" tests for
[class]
, you ensure that these tests are evaluated first (so[class]
must be"grad"
or"senior"
). They are then evaluated in an "and" statement with[favorite-color]
. Thus, given all grads and seniors, pick those whose favorite color is red.
Force use of the *error-response* (!force-error-if)
!force-error-if expression
Normally, the *error-response* section of your template displays
to the user only if the user didn't complete a required variable; if
the *error-response* displays, other sections are not processed (no
*email-response*, *append-response*, etc.). However, you may want to
test the values of variables (for example, eq, ne, etc.), and then create
an error condition if the user entered an incorrect value. That is,
an inappropriate value for a variable is an error in the same way
that a missing required variable is an error. The
!force-error-if
command allows you to do this.
The general form of this command is !force-error-if
expression
, where expression
is any legal conditional expression. For example:
!force-error-if [answer] > 10
The above would cause an *error-response* (and no other sections)
to display if the value of the variable [answer]
were
greater than 10
.
For more about building conditional tests, see General rules for building expressions. (The syntax
for !force-error-if
is exactly like that described for
!use-if
.)
Use !force-error-if
!force-error-if
commands must appear in the *define-variables* section of your template; a!force-error-if
declaration is a global condition that is not specific to any particular section.- You may include as many
!force-error-if
commands as you like. If any one of them is true, Transform sets an error condition and an *error-response* displays. - As described for
!use-if
above, expressions may continue on multiple lines. Continuation lines must start in column 1 and begin with!!
. For example:!force-error-if [please_register] eq "yes" !! and [class_time] eq ""
If a
!force-error-if
condition is true, Transform sets an error condition and some *error-response* displays. You may have multiple *error-response* sections with!use-if
commands at the top that resolve which *error-response* should display. The!force-error-if
command only sets the error condition; it doesn't specify which *error-response* should display. Consider the following template:# begin template *define-variables* !force-error-if [user-type] eq "student" !! and [class-level] eq "" !force-error-if [please_register] eq "yes" !! and [class_time] eq "" *success-response* ... whatever ... *error-response* !use-if [user-type] eq "student" !! and [class-level] eq "" ... Hey, you say you're a student. Please go back and specify freshman, sophomore, junior or senior. ... *error-response* !use-if [please_register] eq "yes" !! and [class_time] eq "" ... If you'd like to register, please go back a select a time for the class. ... # end template
In this example, a different *error-response* will display depending on which
!force-error-if
condition is true. If both error conditions are true, Transform would display both *error-response* sections because both are valid based on the conditions tested. For another way to conditionally control what information displays, see!print-if
below.
Select which lines in any one section are printed (!print-if and !end-print-if)
!print-if
The !use-if
conditional branching section above
describes how you can control which sections in your template file
are processed. However, there are occasions when you'd like to
control which lines in any one section are printed. This is what the
!print-if
command allows you to do. Using this command
(along with the closing !end-print-if
command), you can
have just a subset of the lines in a section printed based on the
value of one or more form variables. This command has the general
form:
!print-if expression ... the lines to print ... !end-print-if
Use !print-if
!print-if
commands are allowed anywhere in the *success-response*, *error-response*, *email-response*, or *append-response* sections, except they must follow any other !commands that appear after the section header (for example,!append-file-name
,!use-if
, etc). That is, they appear in the body of the section to control which lines are output.- Think of
!print-if
as a way of defining a block of lines to be printed given the value of a form variable. You must indicate the end of each block to Transform. You can end a block with either another!print-if
command, or with the terminating!end-print-if
command. You must terminate the last!print-if
(block) in any one section with a!end-print-if
command. A typical application of!print-if
might look like:# begin section *section-header* ... beginning lines for this section ... !print-if [some_var] eq some_value ... a block of lines ... !print-if [some_other_var] eq some_value ... a block of lines ... !end-print-if ... ending lines for this section ... # end of section
- Like
!use-if
and!force-error-if
, the expressions following!print-if
may continue on multiple lines. Any continuation lines must begin in column 1 with!!
. For example:!print-if ( [color] eq "red" or [color] eq "blue" ) !! and [answer] eq "yes" ... print lines ... !end-print-if
- Remember that the value of a variable that was not entered by a
user will always be equal to "". This is true for conditional test
expressions in general, but is particularly handy for
!print-if
commands.Thus,
!print-if [var] eq ""
will always be true if a variable was not entered;!print-if [var] ne ""
will always be true if a variable was entered and has any value; and the shortened test,!print-if [var]
, will always be true if a variable having any value other than 0 (zero) was entered.
Example
There may be times when you have a lot of form fields that the
user is not required to complete, and you'd like to have any blank
fields eliminated before receiving that data. The
!print-if
command allows you to do this. Assume you
have a form that collects name ([name]
), address
([address]
), email address ([email]
),
class registration information ([registration]
), and a
comment ([comment]
). Further, assume you'd like the
results of the form emailed to you, but you also want the comment
field eliminated if no comment was entered. You could accomplish
this with an *email-response* section like the following:
*email-response* To: user@indiana.edu From:[email] Subject: Registration Information # Print out the variables we always want printed # (although they may be blank depending on whether they # were made required fields) Name:[name] Address:[address] Email address:[email] Registration information:[registration] # Now print out the comment, but only if it was entered by the user. # Use the shortened version of !print-if with no test for a value. # This says print the comment if it had any value <b>!print-if [comment]</b> Comment:[comment] # add the required ending statement <b>!end-print-if</b> # end of *email-response* section
An *error-response* example
Assume you have an *error-response* like the following:
# There were three form variables: "name", "email" and "question" # Recall that "name" and "question" were required variables *error-response* <html> <head> <title>Sorry [name], you made an error</title> </head> <body> <h2>Sorry [name], you made an error</h2> <p> You must complete the following fields: <p> Your email address: [email]<p> Your question: <br> [question]<p> </body> </html>
With this type of *error-response*, all required variables must be printed so the error messages for the missing required variables appear. In the following example, the *error-response* is modified to print only missing required variables:
*error-response* <html> <head> <title>Sorry [name], you made an error</title> </head> <body> <h2>Sorry [name], you made an error</h2> <p> You didn't complete the following required fields: <p> # Remember that variables that weren't entered by the user # will always be equal to "" # If [email] has no value print the error message for [email] !print-if [email] eq "" Your email address: [email]<p> # If [question] has no value print the error message for [question] !print-if [question] eq "" Your question: [question]<p> # end the block of !print-if commands !end-print-if </body> </html>
Use !print-if, !force-error-if, and required variables together
Following is a brief example of how you might use
!force-error-if
, !print-if
, and required
variables together to create an effective *error-response* for a
form. This example is not complete; it only shows the relevant
portions of the template.
Assume you are creating a form that allows users to register for
some class section. In this form, the [name]
variable
is always required. Also assume there is one section on Thursday,
but two on Friday. Thus, if a user selects Thursday, no further
information is needed. A user who chooses Friday, however, must also
indicate the class time; the day of the week is stored in the
variable [class_day]
, and the time of day in
[class_time]
.
This example demonstrates a situation where a variable is conditionally required (that is, required only if another variable has some specific value):
*define-variables* # Make "name" a plain 'ol required variable [req-name] # force an error if they selected Friday but didn't enter # a class time. !force-error-if [class_day] eq "Friday" and [class_time] eq "" *success-response* ... some success-response ... # Develop an error-response that tests for each possible # error condition *error-response* ... some html header information ... # Test to see if if there was an error because [name] wasn't entered !print-if [name] eq "" Please go back and enter your name. It is required! <p> !end-print-if # Now check to see if there was an error because they selected Friday, # but didn't give a time. This is exactly the same test as used in the # force-error-if command above in the *define-variables* section. !print-if [class_day] eq "Friday" and [class_time] eq "" Hey, if you want to go on Friday, you must also specify a time. Please go back an select a time. <p> !end-print-if ... end the error-response html ...
Using external files as part of your template
If you create many forms/templates, you may find that there are portions of a template file that you constantly repeat from template to template. Building a template would be easier if you could place these various portions in separate files. You may also find that you would simply like to include other files (or portions of files) as part of your response to users when building your template. Transform has two commands that allow you to include information from external files:
!include = your_file_name !print-file = your_file_name
To understand the difference between these commands, it is useful
to know how Transform processes your form/template. Transform begins
by assembling your entire template (which may be made of component
files brought in via !include
). Once Transform has your
whole template, it examines the submitted form variables, determines
which section types you have included in your template, and begins
processing the sections of your template. During this process, it
evaluates any conditional elements (for example, !use-if
,
!force-error-if
, !print-if
), and finally
outputs the appropriate sections (or lines) of your template and
processes any !print-file
commands.
While !include
and !print-file
both
allow you to read in files external to your template, they operate
at different points in the process and offer different features:
!include
commands are processed at the initial stage when Transform reads your template. As a result, new sections (via*section-headers*
) can be defined in files read in via!include
.!print-file
commands are processed at the final step when appropriate sections or lines are output.
Building a template from separate files (!include)
!include
allows you to include standard template
sections that are stored in a separate file. For example, assume
that you wanted to include the same HTML
*success-response*
for multiple forms. If you put the
entire *success-response*
in a file called
success.html
, you could include it in any number of
templates like so:
# begin template *email-response* ... your email response template information... *error-response* ...any error message... # Now simply !include the standard *success-response* !include = "success.html" # end template
This would insert your success.html
file into your
template while the template file is being read.
The general form of the !include
command is:
!include = "file_name"
There are three possible ways to specify the "file_name":
- A complete path. If you type
pwd
(meaning "print working directory") in any directory, you will see a complete path to that directory. To create an acceptable "file_name" for!include
, you would add the specific include file name to the result of thepwd
command. For example:/ip/account/some_directory/my_include_file_name.dat
- A path relative to your login directory. If the "file_name"
begins with a tilde (~), it is assumed that the path is relative to
your login directory. For example:
~account/some_directory/my_include_file_name.dat
- A simple file name. If "file_name" contains no slashes (that is, no path information), it is assumed to be in the same directory as the template file.
General rules for !include
:
- Each
!include
command must be on a line by itself. - The name of the file to include after the
!include =
command may not contain variable names in square brackets (that is, you cannot build a file name with variables).!print-file
does allow this. This is because Transform doesn't know the value of your variables when reading include files. !include
files may contain complete or parts of various template sections which include form variables in square brackets. In fact, you can use!include
to read in whole sections of the template file if you like. For example:#begin template !include = standard_error_response.html !include = standard_success_response.html !include = email_section_for_this_service.txt #end template
The above would be a perfectly valid template file, assuming the
!include
files existed.- Files included with
!include
may also contain!include
commands. Any file you include with the!include
command may also contain!include
commands for other files. - In general, use
!include
instead of!print-file
(described below) if you have complete sections, including section headers, stored in separate files.
Printing files to output (!print-file)
!print-file
allows you to have information stored in
a file printed out when the sections of a template file are
processed. Because !print-file
commands are evaluated
at the final step in the process, they can take advantage of the
values of your form variables (whereas !include
commands cannot). The general form of the !print-file
command is:
!print-file = "file_name"
Like !include
, there are three possible ways to
specify the "file_name":
- A complete path. If you type
pwd
(meaning "print in working directory") in any directory, you will see a complete path to that directory. To create an acceptable "file_name" for!print-file
, you would add the specific include file name to the result of thepwd
command. For example:/ip/account/some_directory/my_include_file_name.dat
- A path relative to your login directory. If the "file_name"
begins with a tilde (~), it is assumed that the path is relative to
your login directory. For example:
~account/some_directory/my_include_file_name.dat
- A simple file name. If "file_name" contains no slashes (that is, no path information), it is assumed to be in the same directory as the template file.
Following are things you can and can't do with
!print-file
:
- In general, think of the information stored in a
!print-file
as being output at the last minute. !print-file
commands must begin in the first column and be on a single line by themselves.!print-file
commands are allowed in all sections except the*define-variables*
section, because the*define-variables*
section is only used for setting variables and is never output.- Information stored in a
!print-file
may contain variable names in square brackets. Transform will replace the variable names with their values before they are output. - The "file_name" specified in a
!print-file
command may contain variable names in square brackets. For example:!print-file = [user].html
If the current value for [user] were "moe", Transform would output a file named
moe.html
at this point in your template file (assuming the file exists in the same directory as your template). - Information stored in a
!print-file
file may not contain section headers (for example, *success-response*), or the !commands that must immediately follow section headers (for example,!use-if
,!append-file-name
)!print-files
are output at the last minute; section headers and these !commands must be "known" to Transform prior to the output step. You can, however, use!print-files
for everything except the section headers and initial!commands
. For example:*email-response* !use-if [confirm] eq "yes" !print-file = "confirm_email_message.txt"
!print-file
can be more efficient than!include
, especially if the amount of information stored in external files is large. Consider the following example:Assume that you wanted to include the same HTML signature file at the bottom of every
*error-response*
and*success-response*
for some set of forms/templates. Assume the following signature information was stored in a file calledsig.html
in the same directory as your forms/templates:<hr>Send comments or questions to blah@indiana.edu<hr>
To include this signature information in any template file, you could do the following:
# begin template *email-response* ... your email response template information... *success-response* ...any success message... !print-file = sig.html *error-response* ...any error message... !print-file = s.html # end template
This would result in the
sig.html
file being printed at the end of the*success-response*
or the*error-response*
when it was displayed to the user.In the example above, you could use
!include
instead of!print-file
and get the same results. The problem with using!include
, however, is that your signature file,sig.html
, would be read in twice (for the success and error responses) when the template is initially being built. Using!print-file
, thesig.html
file is only read once, when either the success or error response section is being output.!print-file
commands may be included in files that are read in by!print-file
(that is, a!print-file
may contain!print-file
, which may also contain!print-file
, etc.). Collectively, a maximum of 50!print-file
commands are allowed per form submission.- Files read in via
!print-file
may contain!print-if
commands. - If a
!print-file
you specify is not found, the command is simply ignored and no error message is given. This allows you to set up conditions where files are only printed if they exist. If debug mode is turned on (that is, with!debug
), an error message will be printed if the!print-file
does not exist. You may want to use!debug
mode when initially testing your template. !print-file
commands may be embedded inside!print-if
blocks. This allows you to select which!print-file
to output based on user input. For example:*success-response* eiou ... whatever ... !print-if [color] e red !print-file = "my_red_file.html" !print-if [color] eq blue !print-file = "my_blue_file.html" !end-print-if
Controlling the lines printed from a !print-file (!begin-print-file, !end-print-file, !print-file-mode)
Using !begin-print-file
,
!end-print-file
, and !print-file-mode
, you
have some control over which lines in a !print-file
are
actually printed. These commands are used as follows:
!begin-print-file-with = any_begin_string !begin-print-file-after = any_begin_string
These two commands control where to begin
printing the contents of the file. The !print-file
is
scanned until the first line containing
"any_begin_string" is found. Printing then begins either "with" that
line (using !begin-print-file-with
) or with the next
line (using !begin-print-file-after
).
!end-print-file-with = any_end_string !end-print-file-before = any_end_string
These two commands control where to stop
printing the contents of the file. While printing the file, it is
scanned for "any_end_string". When this string is found on a line,
printing either stops immediately (using
!end-print-file-before
), or the line with the
"any_end_string" is printed and then printing stops (using
!end-print-file-with
).
!print-file-mode = multi
By default, if !begin-print-file
and
!end-print-file
are set, only the first set of lines in
the file which match the begin and end criteria are printed. If
!print-file-mode = multi
is specified, the entire
!print-file
will be scanned for multiple occurrences of
the begin/end criteria. Each set of lines which match the criteria
will be printed in the order they're found.
General rules for using !begin-print-file
,
!end-print-file
, and !print-file-mode
:
- These commands must precede the
!print-file
command they are to be applied to in your template file. - These commands only operate once. You must enter them separately
before each
!print-file
command. If these commands not do not immediately precede the!print-file
command, the default!print-file
behavior will be used (that is, print the whole file). For example:!begin-print-file-with = "the first line I want" !end-print-file-with = "the last line I want" !print-file = "my_red_file.html" !print-file = "my_blue_file.html"
The above example would result in the
!begin-print-file-with
and!end-print-file-with
being applied tomy_red_file.html
, but notmy_blue_file.html
. All ofmy_blue_file.html
would be printed. - The string you specify to mark the place to start or end
printing of a file may contain variable names in square brackets
(which will be replaced with their values before testing). For
example, if the variable [username] had a value of "moe",
!begin-print-file-with = [username]-line
would cause printing to occur at the first line which contained "moe-line".
Carry information forward to subsequent HTML forms (!carry-forward)
In advanced use, there are times when you'd like to use the
*success-response* or *error-response* sections of your template to
deliver an HTML form, and would like to have the variables entered
in a form carried forward into the subsequent *success-response* or
*error-response* form. You would use the !carry-forward
command for this purpose.
Imagine a scenario where you display an initial form to the user, collect some basic registration information (for example, "name", "address", "phone", and "course"), and then in the *success-response* for the "course" type selected by the user (see Conditional branching), you deliver another form which collects specific registration information about this particular course (for example, "time", "date", etc). The problem is that when the user submits the course-specific form, you also need to include the "name", "address", and "phone" information from the previous form.
One way to accomplish this would be to write hidden form variable statements in the *success-response* section containing the subsequent form, setting each statement to the variables in the first form.
In general, hidden variables (variables that won't be shown to the user) can be included in any HTML form with statements like:
<input type = hidden name = "some_name" value = "some_value">
If you wanted the form in the *success-response* section to
include values of the name
, address
, and
phone
variables from the original submitted form, you could
include the following lines:
*success-response* ... any header text ... #begin form <form method = "post" action = "transform_action_statement"> ... include any input boxes for course specific date, time, etc .. # now the hidden variables <input type = hidden name = "name" value = "[name]"> <input type = hidden name = "address" value = "[address]"> <input type = hidden name = "phone" value = "[phone]"> #end form </form>
Note that the hidden form variable statements above have their
"value =
" parts set to a form variable in
brackets. Like other places in a Transform template, these form
variable names in brackets are replaced by the actual values
supplied by the user submitting the form.
There can be a problem with this approach, however. If the user
input included quotes ("), this would cause the value to be
truncated in the value =
part of the hidden variable
when it reached the user-supplied quote. The Transform command
!carry-forward
allows you to avoid this problem
and provides a shortcut for creating hidden variables.
!carry-forward
The purpose of the !carry-forward
command is to automatically
create hidden value form commands, but only for those variables that
have user-submitted values. The general format of the
!carry-forward
command is:
!carry-forward = [var1] [var2] [var3] etc
Using the !carry-forward
command, the example above
would look like so:
*success-response* ... any header text ... #begin form <form method = "post" action = "transform_action_statement"> ... include any input boxes for course specific date, time, etc .. # now the hidden variables !carry-forward = [name] [address] [phone] #end form </form>
The !carry-forward
command above would cause hidden form
variables statements to be included for each of the variables
listed, but only if the variable had a value.
Some things to remember about using !carry-forward
:
- You can use
!carry-forward
in *success-response* or *error-response* sections, which are returned to the user as HTML. You may also use!carry-forward
in *append-response* sections, but this would be useful only if your append file were an HTML form. - Hidden variable commands will only be created for those variables which have values.
- Although no checking is done, you should only use
!carry-forward
within a form (that is, between<form>
and</form>
). It wouldn't make sense anywhere else since hidden form variable commands are being generated. !carry-forward
commands cannot continue on multiple lines. You may, however, add as many!carry-forward
commands as you like to include as many form variables as you need. Just be sure the line begins with!carry-forward
, and each command is on a line by itself.- Remember that the
!carry-forward
command only creates hidden form variables for those form variables that have values. If you would like to have any environment variables carried forward with hidden form variables, you must create these hidden form variable statements yourself. In addition, you must give these environment variables different names. Otherwise, they will collide with the new environment variables of the same name created when the form is submitted. For example, if you wanted to carry forward an initial value of the[!TIME]
variable from one form to the next, you would have to create your own variable name:<input type = hidden name = "initial_time" value = "[!TIME]">
- While the hidden form variable statements created are not seen by the user, they are not secret. The user can view the source of the file to see the hidden form value statements. Do not try to hide any sensitive information this way.
Using !carry-forward for all variables
Using a special form of the !carry-forward
command,
you can have all (or all but just a few) variables carried
forward. If you include the keyword all
after the
!carry-forward
command, hidden form variables will be
created for all form variables that have values. If the keyword
all
is followed by one or more variable names in square
brackets with a hyphen/minus in front of it (for example,
-[variable]
), these variables will be removed from the
"all" list. For example:
!carry-forward all
will create hidden form variables for all form variables that have values, and
!carry-forward all -[school] -[books]
will create hidden form variables for all form variables that have
values except [school]
and [books]
.
!carry-forward
once
in any given template section. When Transform sees the
!carry-forward
command, it creates the hidden form
variables immediately. Repeating this command would result in
multiple hidden form variables for a given variable. If you need to
use the -[variable]
feature, all variables you want to
remove from the list must be in a single !carry-forward
command
line.
Use Perl regular expressions in conditional tests
When building conditional tests, two comparison operators ( =~ and !~ ) give you access to Perl's regular expressions. Regular expressions offer a flexible and powerful way of testing the values of submitted form variables.
Following is a brief and incomplete introduction to using Perl regular expressions with Transform. Using regular expressions can be very complicated; this functionality is provided in Transform for advanced users who have knowledge of regular expressions.
In the conditional tests described earlier, you may include regular expression tests in the following format:
[var] =~ regex [var] !~ regex
where regex
is a valid Perl regular expression.
Loosely, the =~ operator means "does contain". Thus, [var]
=~ regex
is true if the variable [var]
"does contain" (or "does match" ) the pattern defined in
regex
. The !~ operator is just the inverse that is, "does not contain" or "does not match").
Build a Perl regular expression
Building a regular expression involves defining a pattern, and
then testing to see if the pattern matches (using =~
)
or doesn't match (using !~
) the characters in the
string on the left side of the expression (here,
[var]
). The pattern must begin and end with a slash
(/
). (Note that patterns may begin with m
to redefine the delimiter.) For example:
[var] =~ /Moe/
would be true if the string "Moe" was found
anywhere in the variable [var]
.
In regular expressions, most characters simply match themselves. There are, however, some characters that have special meaning in regular expressions and do not simply match themselves. These characters include:
\ | [ ] ( ) { } . + * ? ^ $
When using these characters in regular expressions to match themselves, they must be preceded by a backslash (\). For example, to test for the string "Moe?", put a backslash in front of the question mark:
[var] =~ /Moe\?/
Character classes
In regular expressions, you can use some special backslashed
characters to automatically match a whole set of characters. For
example, \d
will match any digit (that is, 0-9). Some of
these special backslashed characters include:
\d - A digit (0-9) \D - A non-digit (not 0-9) \w - A word character (a-z A-Z 0-9 and _) \W - A non-word character (not in the list above)
Thus, [var] =~ /\d/
would be true if there was a
digit anywhere in the variable, [var]
.
In addition to these character classes, a period (.) has special
meaning. A period matches any character (except a newline). Thus,
[var] =~ /./
would match any single character.
Specify the number of matches
In the example above, \d
matches a single digit
character. Special quantifiers in regular expressions allow you to
specify how many times the preceding character (for ex, a digit with
\d
) should match. These quantifiers include:
{n,m} - At least n times, but no more than m times {n,} - Must match at least n times {n} - Must match exactly n times * - 0 or more times + - 1 or more times ? - 0 or 1 time
For example:
/\d+/ - matches 1 or more digits /\d?/ - matches 0 or 1 digits /\d*/ - matches 0 or more digits (by itself this will always match) /\d{1,3} - matches from 1 to 3 contiguous digits
Match the beginning, the end, or the entire string
If [var]
was set to the string
"help102", the following regular expression would test
true:
[var] =~ /\d+/
because zero or more digits were found in the string.
You can also test whether the string ended in digits, began with digits, or contained only digits. If the first character in a regular express is a caret (^), then the regular expression is only true if it matches from the beginning of the string. If the regular expression ends in a dollar sign ($), then the regular expression is only true if it matches from the end of the string.
For example (assume that [var]
was set to
"help102"):
[var] =~ /^\d+/
would test false, because [var]
does not begin with one or more digits. Conversely,
<dd>[var] =~ /\d+$/ </dd>
would test true, because [var]
does end with one or more digits.
You can combine ^ and $ in one expression to force matching against the entire string. For example:
[var] =~ /^\d+$/
would test false, because from the beginning of
the string to the end of the string, there are not just one or more
digits (that is, it begins with "help"). If [var]
had been set to
"1234567", the test would be true. This expression is useful for
testing whether a field contains all digits. With a small change,
you could test for a specific number of digits (for example, /^\d{3}$/
must contain exactly three digits).
Match this or that or that or that
Sometimes you may want to match any one of some finite set of words (or other more complex expressions). You can do this using the vertical bar (|). For example:
[color] =~ /red|yellow|green/
would match if [color]
contained "red" or "yellow" or
"green". You can also put parentheses around these groups to isolate
the alternation to just that set of words. For example:
[color] =~ /(red|yellow|green) car/
would match "red car", "yellow car", or "green car".
Match some set of characters
The last example showed how to pick between different possible words (which could have each been more complex expressions). You may also define a list of characters to match by putting them in square brackets ([ ]). For example:
[word] =~ /[a]/
would match if [word]
contains any lowercase vowels,
in any order;
[word] =~ /[A-Za-z]/
would match any upper or lowercase letter. The hyphen allows you to automatically provide a range;
[word] =~ /[A-Z a-z]/
spaces are significant. This would match a space or any upper or lowercase letter;
[word] =~ /[^aeiou]/
is different. If a caret (^) is the first character in the square brackets, it is treated as the inverse. In this case, rather than matching a vowel, it means match anything but a lowercase vowel.
Case insensitive matching
Use when matching any upper- or lower-case vowel; case is
disregarded. Include an i
after the regular expression:
[word] =~ /[aeiou]/i
Put it all together
The examples above mostly describe individual features of Perl regular expressions. The real power of regular expressions is that you can use all of these features in a single regular expression. Here are some more examples:
- Match a value that looks like a course number (for example, A100 through
Z999), with a leading capital letter followed by three numbers:
[course] =~ /^[A-Z]\d{3}$/
Here,
[A-Z]
matches a single uppercase character. The\d{3}
matches exactly three digits. - Match a value that looks like a seven-character phone number,
with or without the hyphen (for example, 8551111 or 855-1111):
[phone] =~ /^\d{3}(-|)\d{4}$/
Here, the first three digits are matched with
\d{3}
. Then,(-|)
says match either hyphen or null (note there is nothing between the vertical bar and the closing parenthesis). Then, match four more digits. - Match a value that looks like a seven-character phone number,
with or without the hyphen, that could also include an optional initial
area code (for example, 812-855-1111, 812-8551111, 8551111, or
855-1111):
[phone] =~ /^(\d{3})?(-|)?\d{3}(-|)\d{4}$/
Here, you would use the "?", 0, or 1 operator to match the area code 0 or 1 times with
(\d{3})?
. Then, you would match a hyphen (or no hyphen) after the area code 0 or 1 times with(-|)?
. The rest of the expression is the same as the above phone number example.Note that this expression isn't quite right, because it would match -855-1111. In some cases, you may find it easiest to create two (or more) regular expressions that match the possible range of legal values and join them with "or" (for example,
[var] =~ expression or [var] =~ expression2
). - Match a string that begins and ends with a digit (for example,
2abcde4); what's in between doesn't matter.
[var] =~ /^\d.*\d$/
Here, you match on a beginning digit (
^\d
), followed by 0 or more of any character (.*
), and finally a digit at the end of the string (\d$
).
General rules for using regular expressions in Transform
- An ill-defined regular expression will result in an error message. The error message comes from the Perl interpreter, and will attempt to clarify the problem with the expression.
- Transform variable names in square brackets
cannot appear in the expression portion of the
statement. For example:
[var] =~ /^[var2]$/
The above example is silently illegal. Although it won't generate an error, it also won't replace
[var2]
with the value of this variable. This prevents user-supplied input from being part of the expression (a potential security problem). - Perl users should be aware that regular expressions in Transform are used only to build tests against the values of form variables. The normal replacement and variable assignment functions associated with regular expressions are meaningless in this context.
- You must use Perl's rules for regular expressions. Some of the rules may differ from those used by other applications.
For more about Perl regular expressions, refer to a comprehensive Perl resource (for example, Programming Perl by Tom Christiansen et al.; published by O'Reilly & Associates).
Authentication: Control access to your forms and documents
By default, all forms or documents in your www
directory and subdirectories may be viewed by anyone on the
internet. However, on the central servers, you may have some control
over who can access your files. You may limit access to only users
with an IU Network ID or create your own custom access
control. For more, see Control web page access for Pages.
This form of authentication works by placing a
.htaccess
file in the directory containing the files
you want to control access to. Note that this works on a
directory-by-directory basis; the .htaccess
file only
restricts access to the files and subdirectories in the directory
where it resides. When a user attempts to access a file (via an
HTML link) in a directory containing a .htaccess
file, the www
server checks to see whether the user
may access that directory.
Since control is on a directory-by-directory basis, you must
create a special directory (or directories) for documents or forms
that you want to restrict access to. You must also install
Transform in this directory and point to this copy in your form
action statement. For example, in your www
directory,
you could create a directory called net_id
and place
all forms and documents that you want to make available only to
users with IU Network IDs in this directory.
Examples
For working examples that demonstrate some of Transform's features, see Transform Examples.
This is document bfsd in the Knowledge Base.
Last modified on 2021-09-08 10:20:44.