Web Forms with Transform 3.0: the Users' Guide

Table of Contents

What is 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.

Note: This document assumes you know how to create html forms. Transform does not create forms for you, it only gives you a convenient way of dispensing submitted form information. Using your search engine of choice you can find many HTML forms tutorials online.


General overview of Transform
To use Transform, you create an html form and a corresponding Transform template file. It is the template file that allows you to control what will happen to the results of a submitted form. Each field in an html form has a name (i.e. NAME = "question" ). In the corresponding plain text Transform template file, you control where the value of a form variable is displayed (i.e. the value entered by the user) by simply including the variable name in square brackets (e.g. [question]). This is best explained by example.

A Simple Example
Examine the following simple html code for a form. Note that there are three fields defined, "name", "email", and "question" (i.e. NAME="name", NAME="email", and NAME="question"). You can also 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 the response would look like.

Note that the *success-response* section of the template file is just echoed back to you verbatim, except that every occurrence of each form variable name in square brackets was replaced with the values supplied in the form for the variables (i.e. "name", "email", and "question"). If this template were actually operational, submitting the form would also result in an email message being sent, because of the *email-response* section.


Naming Your Form and Template Files
Your html form files must have a .html extension and the corresponding Transform template files must have a .tpl extension.

In general, you will have a single html form and a corresponding template file. The html form and the template file should be in the same directory and have the same name except for the extension (i.e. a .html extension for the form and a .tpl extension for the template). For example, if your form were named "send_comments.html", the corresponding template file would be named "send_comments.tpl" and they would be in the same directory. 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 only use them 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.

When a person fills out a web form processed by Transform, if HTML code is included, the code will be displayed as HTML character code instead. (See: HTML Coded Character Set .) This is done for security reasons.

A note for advanced use: In more advanced applications of Transform you may have an html file which contains multiple forms or a *success-response* or *error-response* section which contains an html form. In these cases, the name of the template file will not necessarily match any html file and you will have to be careful that you point to the right template file in the form action statement (see below).


Installing Transform in your account
To have Transform process your html forms, you must install Transform in your own Web account.

To install Transform, you must log into your account using SSH Secure Shell Client, such as PuTTY. For instructions on how to use PuTTY, please see How to use PuTTY on Webserve. This document also tells you how to obtain PuTTY if you do not already have it.

Once logged in, type cd www to change directory to your web document directory, www. Then simply type:

tf_install

We encourage you to 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 (i.e. the same directory you are in when you type tf_install). It is this "transform.cgi" that you will point to in the action = statement in your form (See below).
Some notes about using Transform from your account:
Transform will append to the files in your account immediately when using an *append-response* in your template (See below).
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 for information about controlling access.)
transform.cgi is not actually the Transform program, it's just a stub that points to it. Thus, as new versions of Transform are installed, you will use new version automatically.

Setting the Form "action = " to Point to Transform
When an html form is submitted by a user, the data filled in by the user is sent to an application on the Web server. This application reads the form data and does something with it. Transform is one such application. In order to use Transform, you must indicate in your form that you want Transform to receive and process your form data. In addition, in some cases you must specify the location of your template file. This is the purpose of the "action =" string in the html <form> statement that you use to begin a form.
Pointing to Transform installed in your account
The simple method
In the simplest case where your form and template files have the same name (except for the extension), and they are in the same directory, the html statement that begins the form and specifies the action (i.e. what application should process the form) can be just:
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">
This method works because when your html form is submitted, Transform "knows" 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.
This line breaks down as follows:
  • The initial <form says, begin a form.
  • The method = "POST" says you want to post data. Always use method = "POST" when using Transform in html forms. For more information on the use of HTTP GET and POST, please see this W3C article, URIs, Addressability, and the use of HTTP GET and POST .
  • The action = section specifies where to send the form data. In this case,

    http://www.indiana.edu/~username/transform.cgi
    or
    http://www.iupui.edu/~username/transform.cgi.

    This statement essentially provides a url to transform.cgi in your account. You build this url just like you would build a url to a document in your web directory using a tilde (e.g.~) before your account name. (Thus, if you issued the tf_install command in some subdirectory of your web directory, additional directory path information would have to be included in the url.)

    If you have installed Transform into every directory where you have a form, you can use a relative link to transform.cgi rather than including the entire path. Your form action statement (at either campus) would then read

    <form method = "POST" action = "transform.cgi">

    You may want to look at Controlling Access to your Forms and Documents. While this describes controlling access to documents in your web directory, the information provided also applies to transform.cgi installed in your own account. Since transform.cgi is installed in your web directory, the same rules apply.

The Complete Method
In those cases where you have multiple forms per html file or you have a form in a *success-response* or *error-response*, you must specify the exact location of the template file to use. Otherwise, Transform will not find your template file and 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 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:

    "http://www.indiana.edu/~username/transform.cgi?www-user/www/comment"
    or
    "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. Instead, you may provide a shortened URL that is like a normal relative URL:

    /~username/transform.cgi

    Note the leading slash!


Note:The specification you supply for the action= must be on a single line (i.e. with no Returns). With some versions of Netscape, you may get a "Broken Pipe" message or some other odd message if you include a Return in the action = string. Or you may get an error message back from Transform saying:
Account does not exist
Error in path specified:

 

with no path given; this is probably because your action = specification contains a Return.
A note for Virtual Host users
If you want to use Transform with a virtual host, you must install Transform in your account as described above. Then, when pointing to Transform in the "action = " statement, you simply supply:
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.

Creating a Template File - the Details
Dividing Your Template into Sections
In the examples above, the *email-response* template section header was used to declare that the template information that followed was to be sent as an email message. The *success-response* section header declared the section of the template to be displayed to the user upon successful submission of the form. There are actually five possible template sections (and section headers) that control the various ways you want to dispense submitted form information. When you create a template file, you simply include those sections that are needed for your specific application.

When using these section header names you must include one or more asterisks on both sides of the name (e.g. *email-response*, ***email-response***, etc), and you must always begin them in the first column in your template file. Important: Be very careful that you spell the section headers exactly as shown below. If you mis-spell a section header, Transform may not recognize it as a header and an entire section may be included as part of the previous section. The five types of sections and their section headers are:

*success-response*
The *success-response* section of a template is used to describe the message that is returned to the user when a form is successfully submitted. Always use this section to communicate to users that a form has been successful submitted. Because this section is returned to the user's web browser, it must be in the form of an html document.
*error-response*
The *error-response* section of a template is used to describe the message that is returned to the user when the form was not filled out correctly. As you'll see below, you may specify that certain form variables are "required" - that is, if they are not filled in by the user then the *error-response* section of the template (and only this section) is displayed. In addition, using the !force-error-if command, you can force only the *error-response* to be displayed 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 you can indicate to 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*
The *email-response* section of a template is used to describe the format of an email message to be sent to you. Only use this section if you wish to have the results of a submitted form sent to you as an email message.
*append-response*
The *append-response* section of a template is used to describe 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*
The *define-variables* section is used to define whether a variable is required, error messages for required variables and to define the values of some special variables. Like the other sections, this section is not required unless you need to use its special features.
Which sections are used and when...
When Transform reads the values submitted via a form, it sets a flag of whether there is success or error. An error flag is set if a required form variable isn't completed by the user 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 - 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.

Setting required variables
In many cases, certain fields in your forms may be required - that is, you don't wish to receive the results of the form unless the field has been filled in by the user. In a Transform template file you can specify which fields (i.e. variables) are required by simply including a req- in front of any variable name that is required. For example, if you had a text input area in your form named "email" (e.g. name = "email" in the form), you would normally refer to this variable in your template with "email" inside square brackets (e.g. [email]). By placing the string req- in front of the variable name anywhere in your template the variable becomes a required variable (e.g. [req-email]. Note that flagging a variable as required with req- doesn't change the name of the variable; it is simply a flag that sets the variable as required - the "req-" is stripped off the front of the variable name.
An example with required variables - using error and success response sections
To show how these template sections can be used, let's look at how we could change the previous example. If you wanted to require that the email address and question fields be filled in, but not the name field, the template file might look like:
# 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
 
Now try this form. Try submitting it both with all fields completed and without completing all fields. Note that when required fields aren't filled in (i.e. question or email) you get the *error-response* section of the template returned to you. When all fields are completed, the *success-response* section is returned.
Note that in the template above, req- was only placed in front of one of the [email] variables (i.e. once in the entire template). If a variable name is prefixed with req- anywhere in the template, it affects the variable everywhere else in the template as well.
 
The Details of Each Template Section
The *success-response* section
 
The *success-response* section allows you to create a message that is returned to the user upon successful submission of a form. Always use this section as a means of informing users that their information has been successfully submitted. If no *success-response* section is present, the *email-response* or *append-response* section will be displayed to the user instead.
Since the *success-response* is being 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>
 
Advanced use tip: Since the *success-response* section is an html document you may have it include html forms which call other Transform templates. Using this technique, you can effectively chain multiple forms together.
 
The *error-response* section
 
The *error-response* section allows you to provide the user with an error message if there were errors in their submitted form. The only time the *error-response* section is displayed is if the 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 values supplied by the user. If you have required fields in your template, you should always supply an *error-response* section.
One important note about errors: if the user doesn't complete a required field, the only way they can get back to their partially completed form is to use the Back button on their browser. You may want to indicate this in your *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 being returned to the user's Web browser. Note that error messages for form variables that are not completed by the user will not automatically appear in the *error-response* section when it is returned to the user. To have an error message for a variable displayed, 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>

Advanced use tip: You may also want to look at Selecting which lines in any one section are printed below for information about using !print-if to have information about only those required variables that were missing printed.
 
The *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*
 
  • 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:, and Subject: (in exactly that order), Transform will complain and refuse to send the email message (but see an exception in Advanced Use).
  • The To: field must not be blank. To state the obvious, Transform cannot send the message if the To: field is blank and it will complain.
  • 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:, Subject: header information. Note that 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 be included in the mail 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 they submit a form. This is bad practice - you should always supply these other sections.
  • A note on building a From: address. For publicly available forms, you should request an email address from the user and simply have the variable inserted into the From field (e.g. From:[email] ). Remember, however, that this cannot be trusted. The user could have entered anyone's email address.
  • When using the iu_auth or iupui_auth form of Transform, an environment variable is available to you for building the From: email address. When using iu_auth or iupui_auth a variable named !NETWORK_ID is set to the user's network username. By adding @indiana.edu or @iupui.edu to the !NETWORK_ID, you can build a From: address that can be trusted (e.g. From:[!NETWORK_ID]@indiana.edu or From:[!NETWORK_ID]@iupui.edu ). For information about iu_auth or iupui_auth and other ways of restricting access, see Authentication: Controlling Access to Your Forms and Documents.
Special Note: Since this email response section allows you to send email To:  anyone, From:  anyone, there is the potential for abuse. In order to address this problem, data is collected for each form processed by Transform that results in email being sent. We record the name of the form, the To: email address, and the name of the account where the form resides. This is sufficient information for us to track any reported problems. No other form information is recorded.
 
The *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.
Important Note: You should not use the following characters in your append file as field delimiters: Semi-colon (;) or ampersand (&).
The *append-response* section can be used 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 that will be displayed to users (e.g. for a guestbook).
 
Note: there are a variety of commands described below that allow you to modify how or where information is appended to a file. All these commands begin with an exclamation point (e.g. !command). The general rule for using these commands is that all the !commands 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 assumed to be the beginning of the information you want appended to a file.
The Transform !commands that are 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.
 
A Simple Example
 
Assume you had a simple html form which collected information for three form variables, "name", "email-address", and "comment", and you wanted to have the result of a form submission appended to a file. The following simple *append-response* section would accomplish that task:
 
*append-response*
!append-file-name = my_file_name
Name:          [name]
Email address: [email-address]
Comment :      [comment]
 
In this example, the information would be appended to a file just as you see it above except that the variable names in square brackets would be replaced with the values enter by the user submitting the form.
Specifying the file where the data is appended
 
!append-file-name = file_to_append_to
The default
 
If you don't specify a !append-file-name command, Transform will attempt to build a "default" file name. This really isn't a very 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. In order 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 the next time).
 
Using the !append-file-name command
 
The !append-file-name command allows you to specify the file where the form information will be appended. The !append-file-name command must be placed immediately following the *append-response* section header along with other !commands. (While you can include the !append-file-name command in the *define-variables* section of your template, this older method of specifying an !append-file-name should no longer be be used.)
The general form of the !append-file-name command is:
!append-file-name = "file_to_append_to"
 
where "file_to_append_to" is the path to a file.
 
There are three possible ways to specify the "file_to_append_to":
 
1. A complete path : if you type pwd (meaning "print working directory") in any directory you will be given a complete path to that directory. To create an acceptable "file_to_append_to" you would add the specific append file name to the result of the pwd command. For example:
/ip/account/my_append_directory/my_append_file_name.dat
 
2. A path relative to your login directory: if the "file_to_append_to" begins with a ~, it is assumed that the path is relative to your login directory. For example:
~account/my_append_directory/my_append_file_name.dat
 
3. A simple file name - if "file_to_append_to" is just a file name with no slashes (i.e. / ) 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 cause the form data to be appended to a file name "mydata.dat" in the "form_data" directory in your login directory. Note: As described above, you must create the "form_data" directory before appending to files there.
 
General rules for !append-file-name
 
  • If the "file_to_append_to" specified does not exist, it will be created.
  • If you specify a complete path to a file and the directories in the path do not exist, Transform will report an error, not create the directories. You must create the directories first.
  • 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 them 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.
 
Advanced use tip: In the command !append-file-name = "file_to_append_to", 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", I could cause data to be written to "freshman.dat" or "sophomore.dat", etc. using the following:
 
!append-file-name = "~account/my_dir/[class].dat"
 
because "[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 users enters illegal characters. (See !trim for some help with this problem.)
 
File protection - protect those append files
When creating or modifying an append file, Transform makes the following assumptions about how the file should be protected (e.g. readable by others or not).
 
If the append file is being created in your web directory where normal html files go (i.e. www or wwws), it is assumed that you intend to allow the append file to be delivered over the web (e.g. a guestbook) and the file is created with world read privileges to accommodate this.
 
If the file is being created anywhere outside the web directory, it is assumed that the file should remain private and it is created such that only the owner has privileges.
 
If Transform is appending to a file that already exists (that you created or it created), it will not change the privileges. Thus if you change the privileges of a file, Transform will honor these changes.
 
Controlling where your data is appended in a file
!append-after
!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"
Where "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 had an html guestbook file with a standard header and footer and you wanted Transform to place any new information submitted in a form between the header and footer. You could accomplish this by putting an html comment such a
 
<!-- include after here -->
 
between the header and the footer and then create an *append-response* section that might begin like:
*append-response*
!append-after = "<!-- include after here -->"
... the rest of your append response goes here ...
This would cause all new submissions to be appended immediately after the <!-- include after here --> html comment. Note that this would also cause the newest submissions to be written at the top of the file (right after the comment but before previous submissions). If !append-before had been used instead, the newest submissions would be at the bottom of the file, before the comment, but after previous submissions.
 
If the "string" for an !append-before or !append-after command is not found in your file, the new information will be appended to the end of the file (and no warning message will be given).
 
Warning: You must be very careful about the size of your files if you use !append-before or !append-after commands. In order 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, very slow if the file grows large. You should avoid using these commands if you are simply collecting data and the files may become large.
 
Advanced Use Tip: Note, 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
Important Note: You should not use the following characters in your append file as field delimiters: Semi-colon (;) or ampersand (&).
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. One way to do this is by simply including tags in your *append-response* section which mark the beginning and end of the record. Another is to 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 html comments:
 
<!-- Begin Record "seconds" "date" -->
at the beginning of each submitted record and
<!-- End Record -->
at the end of each submitted record 
Here "seconds" is the number of seconds since Jan 1, 1970 (useful for easily determining the age of a record) and "date" is the current date (e.g. Mon Mar 4 13:43:16 EST 1999).
 
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. This cleaning up of older records might be important, for example, for a ride board, a calendar, or other applications where old records should be removed or archived. (More information will be available about this application when it is available.)
 
You may also have additional information included in the begin record comment tag by including a string after the !record-delimiter command:
!record-delimiter = "string"
where "string" is any string (and may include form variables in brackets). This results in "string" being written 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 where it includes new information can be controlled with !append-after and !append-before). There are occasions, however, where you'd like Transform to completely overwrite a file with the new form information. This is what the !append-mode = overwrite command enables. If you place
 
!append-mode = overwrite

at the beginning of your *append-response*, the append file specified with the !append-file-name command will be overwritten with the new information rather than appended to. Warning: Any old information in the file will be destroyed.
 
Why would you want to do this? Here's a silly example. Assume that you want to create an html file that contains the date your form was last used. The following *append-response* section would create a new (overwritten) file that included the current date every time your form was submitted to Transform. (This uses an Environment Variable named [!DATE] 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
 
Problem: 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. When Transform has to append information to your append file, it signals that it is working on your file by creating a lock file before working on your file. If you need to edit (or otherwise modify) 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. These utilities are used as follows:
 
Log into your account and cd to the directory containing the append file you wish to edit/modify.
 
Type tf_lock file_name where "file_name" is the name of the append file you wish to modify. This will cause a lock file to be created.
 
Edit or modify 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 do any work with append files and you don't want Transform simultaneously trying an append operation.
When your data is appended
 
Files are appended to immediately when the form is submitted. The only exception is if you have used tf_lock to lock the file to work on it. If a user attempts to append to one of your files while you have it locked, the user append information will temporarily be stored in your account. Once you unlock the file, the next form submission to your account will cause and pending user information to be appended in the order in which the information was received.
 
The *define-variables* section
 
The *define-variables* section, unlike the other template sections, is never output. Its purpose is to set the properties of various global variables, set global error conditions and to define properties for required variables. A discussion of each feature follows.
 
Setting required variables
 
As shown in the examples above, a variable name which 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. This is one purpose of the *define-variables* section. It allows you to define all your required variables in a single compact section, typically at the top of your template file. Note: 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
**** Error - value required *****
When the *error-response* section of your template is displayed to the user, this error message will be printed when the variable name appears in square brackets (just as an actual user supplied value would). You can think of this error message as simply the default value for all required variables. Thus any variable that was required will have the error message displayed any time the variable name appears in square brackets if no value was supplied by the user.
In the *define-variables* section you can override this default, and provide a specific error message for each required variable. You specify the error message in the *define-variables* section as follows:
[req-yourvariable] = "Your error message for this variable"
Note that since this error message is being returned to the user via the *error-response* section, it is effectively part of an html document, so you may include html markup codes in your error message. This includes not only simple markup like bolding your error message (e.g. <b> Error Message </b>), but also including links (i.e <a href= ...) to other documents which might describe how to complete the form field.
 
Because your error message may be long (especially if you include links to other documents), they may continue on multiple lines. Just remember to start each new required variable name (in square brackets) on a new line. Also note that you may include variable names in square brackets in the body of the error message itself (e.g
[req-email] = "Sorry [name], email address required" is OK!
 
The example of the *define-variables* section shown above might look like the following if we included error messages:
 
# 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/%7ewww-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
 
The *define-variables* section of your template can also be used to change some of the default behavior of Transform. This is accomplished by including special command variables and their new values. These are of the general form:
!special_variable_name = new value
Each special variable name begins with a exclamation point (e.g ! ). Each !special_variable = new value must begin on a new line and most may continue on multiple lines if necessary. You may currently 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 just 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 many include this command in the *define-variables* section, or within the *append-file* section itself. For a complete discussion of this command see Specify the filename where data is appended above. It is now recommended that you place this command at the top of your *append-response* section(s).
  • !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. You may remove this signature from your response by including 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 same NAME= for multiple checkboxes, skip this section.) This results 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 are displayed as the result of a [checkbox-variable] in your template. By default, Transform puts a comma followed by a space (e.g. , ) 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 changes the delimiter when a checkbox value is displayed in *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 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 space dash space between each checkbox value in the *email-response* and *append-response* sections.
  • !trim = [var1] [var2] [var...]
    The !trim command is used if you want to be sure variables supplied by the user have no leading or trailing spaces. Any the 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 allows you to 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. See Forcing use of the *error-response* in the Advanced Use section for a complete description of this command.
  • !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 cut/paste multiple paragraphs into these textarea boxes. If this text (via a Transform variable) is then displayed as an html document (e.g. *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> codes are typically used to achieve linebreaks and paragraphs. The Transform !use-linebreak-mode command can be used to to help alleviate (but not eliminate) this problem.
    You can use the !use-linebreak-mode command to tell Transform which of your form variables are TEXTAREAs. Then when outputting these variables to html documents, Transform will add an html linebreak (e.g. <br> ) before each "hard return". The assumption is that word processers place a "hard return" at the end of paragraphs and that if a user is typing into a TEXTAREA box they will use the enter/return key (i.e. a "hard return") to indicate paragraph or line breaks. Thus if a user cuts/pastes 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 linebreaks 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...]
    where [var1] [var2] and [var...] are simply 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, just repeat the !use-linebreak-mode command as many times as is 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 (i.e. you wouldn't want a bunch of <br> codes in your e-mail messages). Transform makes the following assumptions about which sections are to be treated as html documents and therefore when it will include <br>s before "hard returns".
     
    !use-linebreak-mode commands at the beginning of *success-response*, *error-response*, *append-response* or *email-response* sections will always be honored for that section and any !use-linebreak-mode commands in the *define-variables* section will be ignored while that section is being processed (i.e. !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 *success-response* and *error-response* sections are always returned to the user's browser as html documents, this conversion is always performed on specified variables in these sections.
     
    This conversion will be performed on *append-response* sections if the append file name ends in .html. The assumption here is that if the append file name ends in .html, you intend to have this append file viewed via the web. If the append file name ends in anything other than .html (e.g. you're using the *append-response* section to collect data), this conversion will not be performed.
     
    This conversion is never performed on *email-response* sections since these are mailed as plain text documents.
     
    As described, !use-linebreak-mode causes a <br> to be placed before any "hard return". If you include <pre> and </pre> around a textarea variable being processed by the !use-linebreak-mode command you'll find the resulting lines are double spaced. This is because both the <br> and the "hard return" cause a line break. To avoid this double spacing you can change the linebreak character to just <br> by including the following line in your *define-variables* section:
     
    !linebreak-delimiter = "<br>"

    You may get unexpected results if you set the linebreak delimiter to anything else.
Illegal/reserved template characters - what to do
There are three characters that cause problems if you try to use them as normal printing characters in your templates. They are [, ] and |. Square brackets (i.e. [ and ] ) may only be used in your templates on either side of a variable name. Vertical bars (i.e. | ) are used internally by Transform and cannot be used as a printable character in your templates.
If you need to have these characters printed, you may include a special code in their place. This special code will be converted back to the appropriate character during printing. Below are the codes to include in your template files to have these characters printed: <pre> Character Code [ %5b ] %5d | %7c Sorry these codes are so ugly.

Environment Variables
In addition to the variables you have defined in your form, there are some standard environment variables defined which you may have printed.

Environment variables must begin with an exclamation point (e.g. !) 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 or iupui_auth forms of Transform. This variable is not set unless using iu_auth or iupui_auth, or if you have developed an .htaccess file which requires users to enter a username and password.
  • [!DATE] - used to print 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 Jan 1, 1970. This is useful for creating unique filenames. For example, !append-file-name = "[!TIME].html" would create unique file name each time the form and template were used.

While the [!DATE] variable above allows you to stamp the current date, it prints a complete date string. For those of you that would like to "roll-your-own" dates, the following additional date related environment variables are available:

  • [!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 (e.g. 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 - debugging your templates
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 result in unexpected results when running Transform.

To assist with this problem, you can tell Transform to use a "debug" mode while scanning your templates. While in this mode, Transform will more carefully examine each line and report potential errors. To invoke debug mode, simply include:

!debug
as the first line in your template. If you add a 2 to this line (e.g. !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
This section describes some additional features of Transform that allow chaining of forms together and conditional display of information based on user input. In the discussion which follows it is assumed that you understand the general form/template features described above.

Multiple Sections
Transform allows you to have multiple definitions for each type of section except the *define-variables* section (only one is allowed). For example, your template might contain two *email-response* sections if you wanted to send two email messages that were formatted differently (e.g. 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.

Stated explicitly, you may 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.

Note: multiple sections of the same type (e.g. multiple *success-response* sections) are examined and processed in the order they appear in your template. There are some important points here:

1. If you have multiple *success-response* sections that qualify to be output (see Conditional Branching below), they will be output in the order they appear in the template (i.e. effectively just concatenated together). The same is true for *error-response* sections (however, they are only displayed when a required variable is missing or a !force-error-if error condition is set).
2. If you have multiple *append-response* or *email-response* sections, they are processed in the order they appear in the template, but each section is processed independently (i.e. there is no concatenation of multiple sections of the same type).
3. Internally, Transform processes and outputs your sections in the following order: any *error-response* section(s) (if required, and then stops), any *email-response* section(s), any *append-response* section(s) and finally, any *success-response* section(s). In addition, some error checking is performed just before each section is output. As a result, if when first developing a Transform template you make errors, sections without errors may be processed and output if they appear first in the template. Transform will then stop when in reaches the error.

So why would I want multiple *success-response* or *error-response* sections? Because you can control which one is delivered to the user based on the input supplied in the form (see Conditional Branching, next).

Conditional Branching
A form of conditional branching is supported by Transform. 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

where expression is a logical expression. The expression may be as simple as testing the value of a single variable (e.g. !use-if [food] eq "apple") or, as you'll see below, a more complex test of multiple variables.

A simple example
As an example, let's assume you had an html checkbox on your form that would allow the user to indicate they would like to have a confirmation email message sent to them as a result of 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>
Note the name of this check box is confirm and if checked by the user, a value of yes would be sent to be processed. In the form, this check box would appear like so:
Check this box to have a confirmation email message sent
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 like so:
*email-response*
!use-if [confirm] eq "yes"
To:whoever@indiana.edu
From:[username]@indiana.edu
Subject: Confirmation message
...the rest of your message template...
The conditional test above, !use-if [confirm] eq "yes" simply says, process this section (i.e. 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. Conditional test statements will be ignored 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
What follows are the general rules for building logical expressions. While these are shown with the !use-if command, you'll see later these same expressions can 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
 
In the example above, eq was used to test whether the string returned for [confirm] was equal to the string "yes". Other comparison operators are available. A complete list is given below:
 
eq - equal string comparison
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, the following shortened test (i.e. without an operator or value) can be used to see if the variable has any value (that is, 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 (i.e. "" ) or zero (i.e. 0 ).
    
Note the difference between string and numeric comparisons. For example, a string comparison of 1.0 eq 1 would be false because strings are being compared, but 1.0 == 1 would be true because numerically, 1.0 equals 1. Be sure you use the correct comparison type. In addition, note that string comparisons are case insensitive, that is, YES eq yes would be true.
 
For a discussion of using the =~ and !~ Perl regular expression operators, see Using Perl regular expressions.
 
Allowed boolean operators
 
In addition to the comparison operators above you may use the following boolean operators when building tests for multiple variables:
not - logical not
and - logical and
or - logical or
Using these operators you can test the values of multiple variables in a single test. Note that these 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. It is wise to include parentheses to insure 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. Some examples:
 
!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. Below are some examples with descriptions which demonstrate this type of test.
 
Examples
 
1. The following two lines would cause a section to be processed if the form variable "computer" had a value of "ibm" and the form variable "problem" had a value of "printing"
!use-if  [computer] eq "ibm" and
!!       [problem]  eq "printing"
2. The following two lines would cause a section to be processed if the form variable "location" had a value of "IU" or the form variable "host" had a value of "IU"
!use-if [location] eq "IU" or
!!      [host]  eq "IU"
3. Things get a little more complicated when you need to use multiple logical operators together. Consider the following example:
Assume that you wanted to process a template section only if "favorite-color" was "red" and "class" was either "grad" or "senior" (e.g. process the template section for either graduate students or seniors whose favorite color is red). Consider the wrong and right way to do this:
 
Wrong
!use-if [favorite-color] eq "red" and
!!      [class] eq "grad"   or   [class] eq "senior"
Remember ANDs are evaluated before ORs. This !use-if command says process this section if their 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. Next examine the correct way to do this:
 
Right
!use-if [favorite-color] eq "red" and
!!      ( [class] eq "grad"   or   [class] eq "senior" )
Here by simply putting parentheses around the OR'ed tests for [class] we insure that this gets evaluated first (so [class] must be "grad" or "senior"). This is then AND'ed with [favorite-color]. Thus, given all grads and seniors, pick those whose favorite color is red.
 

Forcing use of the *error-response*
!force-error-if expression
Normally, the *error-response* section of your template is only displayed to the user if a required variable is not completed by the user. (And remember, if the *error-response* is displayed, other sections are not processed - no *email-response*, *append-response*, etc.) The problem is that you may want to test the values of variables (e.g. eq, ne, etc), and create an error condition if the value entered by the user is incorrect. That is, an inappropriate value for a variable is an error in the same way that a missing required variable is an error. This is what the !force-error-if command allows you to do.
The general form of this command is:
 
!force-error-if expression
 
where expression is any legal conditional expression. For a complete discussion of how to build conditional tests, see the section starting at General rules for building expressions where !use-if is described. The syntax for !force-error-if is exactly like that described for!use-if. For example:
 
!force-error-if [answer] > 10

would cause an *error-response* to be displayed (and no other sections) if the value of the variable [answer] were greater than 10.
 
Using !force-error-if
 
  • !force-error-if commands must be placed in the *define-variables* section of your template. A !force-error-if declaration is not specific to any particular section, but a global condition and thus must be placed in the *define-variables* section.
  • You may include as many !force-error-if commands as you like. If any one of them is true, an error condition is set and an *error-response* is displayed.
  • 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 ""
    
    would force an error if the user asked to register ( [please_register] ) but didn't include their choice for a time ( [class_time] eq "" ).
  • If a !force-error-if condition is true, an error condition is set and some *error-response* is displayed. You may have multiple *error-response* sections with !use-if commands at the top which resolve which *error-response* should be displayed. The !force-error-if command only sets the error condition, it doesn't specify which *error-response* should be displayed. 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 be displayed depending on which !force-error-if condition is true. What happens if both error conditions are true? Transform would display BOTH *error-response* sections because they both are valid based on the conditions tested. See !print-if below for another way to conditionally control what information is displayed.

Selecting which lines in any one section are printed
!print-if
The !use-if, conditional branching section above describes how you can control which sections in your template file are processed. There are occasions, however, 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
where expression is any legal conditional test expression. For a complete discussion of how to build a conditional test see the section starting at General rules for building expressions where !use-if is described.
 
Using !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 are used after the section header (e.g. !append-file-name, !use-if, etc). That is, they are used 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 to Transform the end of each block. There are two ways to end a block, either with another !print-if command or with the terminating !end-print-if command. The last !print-if (block) in any one section must be terminated 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 and begin 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 was entered and has any value other than 0 (zero).
A real 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 that data is sent to you. 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 e-mailed to you, but you'd like 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
 
Let's assume we have an *error-response* like the following shown in an example above:
# 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. Let's see how we could modify this *error-response* so that only missing required variables are printed:
*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>
 
Using !print-if, !force-error-if and required variables together
 
What follows 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 - only the relevant portions of the template are provided.
 
Assume you are creating a form which allows users to register for some class section. In this form "name" (e.g. [name]) is always required. Also assume that there is one section on Thursday, but two on Friday. Thus if they select Thursday, no further information is needed, but if they choose Friday they must also indicated the time for the class. The day of the week is stored in the variable [class_day], time of day in [class_time].
 
This example demonstrates one of those situations where a variable is conditionally "required" - a variable is required only if another variable has some specific value. Clearly these requirements are beyond the capibilities of simple required variables. Here's how it might be done:
*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 these various portions could be placed 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 which allow you to include information from external files:
 
!include = your_file_name
!print-file = your_file_name

In order to understand the difference between these commands, a short discussion about how Transform processes your form/template is in order. Transform begins by assembling your entire template (which may be made of component files that are brought in via !include). Once it 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 (e.g.!use-if, !force-error-if, !print-if), and finally outputs the appropriate sections (or lines) of your template (and processes !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 as described above. !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. On the other hand !print-file commands are processed at the final step when appropriate sections or lines are being output. Keep this in mind when reading the specific descriptions of these commands below. Because these are commands are processed at different points in the process, different features are available.
 
!include - building a template from separate files
The !include allows you to include standard template sections that have been stored in a separate file. For example, assume that you wanted to include the same html *success-response* for a number of 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 result in your "success.html" file being inserted into your template as 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":
 
1. A complete path - if you type pwd (meaning "print working directory") in any directory, you will be given 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 the pwd command. For example:
/ip/account/some_directory/my_include_file_name.dat
 
2. A path relative to your login directory - if the "file_name" begins with a ~, it is assumed that the path is relative to your login directory. For example:
~account/some_directory/my_include_file_name.dat
 
3. A simple file name - If "file_name" contains no slashes (i.e. no path information), it is assumed to be in the same directory as the template file.
 
General rules for !include:
  • !include commands must be on a line by themselves.
  • The name of the file to include provided after !include = command may not contain variable names in square brackets (i.e. 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
    
    would be a perfectly valid template file assuming the !include files existed.
  • Files included with !include may also contain !include commands. Any file you are including 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.

 
!print-file - printing files to output
!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":
1. A complete path - if you type pwd (meaning "print working directory") in any directory, you will be given 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 the pwd command. For example:
/ip/account/some_directory/my_include_file_name.dat
 
2. A path relative to your login directory - if the "file_name" begins with a ~, it is assumed that the path is relative to your login directory. For example:
~account/some_directory/my_include_file_name.dat
 
3. A simple file name - If "file_name" contains no slashes (i.e. no path information), it is assumed to be in the same directory as the template file.
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 must 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. These variable names will be replaced with their values before being 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 it exists in the same directory as your template).
     
  • Information stored in a !print-file file may not contain section headers (e.g. *success-response*) or the !commands that must immediately follow section headers (e.g. !use-if, !append-file-name, etc). !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 called "sig.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 = sig.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, !include could have been used instead of !print-file with 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, "sig.html" 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. (A !print-file may contain !print-file which may contain !print-file...). 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 is a feature.) This allows you to set up conditions where files are only printed if they exist. If debug mode is turned on (i.e. 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*
    ... whatever ...
    !print-if [color] eq 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 (i.e. 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"
    
    Would result in the !begin-print-file-with and !end-print-file-with being applied to "my_red_file.html", but not "my_blue_file.html". All of "my_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"

Carrying Information Forward
In advanced use, there are times when you'd like to use the *success-response* or *error-response* html sections of your template to deliver a subsequent html form and you would like to have the variables entered in a form carried forward into the subsequent *success-response* or *error-response* form. This is what the !carry-forward command does.
 
Imagine a scenario where you display an initial form to the user, collect some basic registration information (e.g. "name", "address", "phone", and "course") and then in the *success-response* for the "course" type selected by the user (see Conditional Branching above) you deliver another form which collects specific registration information about this particular course (e.g. 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. Confused? An example:
 
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 I wanted the form in my *success-response* section to include values of the variables "name", "address" and "phone" from the original submitted form, I could include the following lines in my success response:
*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 will be replaced by the actual values supplied by the user submitting the form.
 
There can be a problem with this approach, however. If the user included quotes in their input (i.e. " ), 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 get around this problem and gives you a short cut for creating these 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 actually have values submitted by the user. The general form 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, those which are returned to the user as html. You may also use !carry-forward in *append-response* sections, but this would only be useful 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 (i.e. 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, include 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 to do this:
    <input type = hidden name = "initial_time" value = "[!TIME]">
    
    • While the hidden form variable statements created are not seen by the user, they are not a secret. The user can simply 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 hypen/minus in front of it (e.g. -[variable]), these variables will be removed from the "all" list. For example:
!carry-forward all
Create hidden form variables for all form variables that have values.
!carry-forward all -[school] -[books]
Create hidden form variables for all form variables that have values except [school] and [books].
One special note about using this "all" form of !carry-forward. You may only use this command 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.

Using Perl regular expressions in conditional tests
When building conditional tests, there are two comparison operators ( =~ and !~ ) that give you access to Perl's regular expressions. Using regular expressions, you have a flexible and powerful way of testing the values of submitted form variables. What follows 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. Beyond this brief introduction, a Perl book describing the full functionality is recommended.

In the conditional tests described earlier, you may include regular expression tests as follows:

[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, it can loosely be described as "does not contain" or "does not match".

Building a Perl regular expression
The idea behind building a regular expression is 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 (e.g. / ). (Note for Perl users: 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. These 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, if we wanted to test for the string "Moe?" we would have to put a backslash in front of the question mark:
[var] =~ /Moe\?/
Character classes
There are some special backslashed characters that can be used in regular expressions which will automatically match a whole set of characters. For example \d will match any digit (i.e. 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 charcter (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 (e.g. .) has special meaning. A period matchs any character (except a newline). Thus,
[var] =~ /./
would match any single character.

How many?

In the example above, \d matches a single digit character. There are special quantifiers in regular expressions that allow you to specify how many times the preceding character (e.g. 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

Matching 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 0 or more digits were found in the string. What if instead we wanted to test whether the string ended in digits, began with digits, or the entire string contained only digits? If the first character in a regular express is a caret (e.g.^), 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 (e.g. $) then the regular expression is only true if it matches from the end of the string. Again, assume that [var] was set to "help102". The expression:
[var] =~ /^\d+/
would test false because [var] does not begin with 1 or more digits.
<dd>[var] =~ /\d+$/
</dd>
would test true because [var] does end with 1 or more digits.

The ^ and $ can be combined in one expression to force matching against the entire string:

[var] =~ /^\d+$/
would test false because from the begining of the string to the end of the string, there are not just 1 or more digits (i.e. it begins with "help"). If [var] had been set to "1234567" this 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 (e.g. /^\d{3}$/ - must contain exactly 3 digits).
Match this or that or that or that

Sometimes you like to match any one of some finite set of words (or other more complex expression). This is accomplished using the vertical bar (e.g. |). 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 (e.g. [ ] ). For example,

[word] =~ /[aeiou]/
would match if [word] contains any lowercase vowels, in any order.
[word] =~ /[A-Za-z]/
would match any upper or lowercase letter. The hypen 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]/
This is different. If a caret (e.g. ^) is the first character in the square brackets, its treated as the inverse. In this case, rather than matching a vowel, this means match anything but lowercase vowel.

Case insensitive matching

Don't care about the case. Just include an "i" after the regular expression.

[word] =~ /[aeiou]/i
Match any vowel, upper or lower case.

Putting it all together

The examples above have mostly described 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 (e.g. A100 through Z999), with a leading capital letter followed by 3 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 hypen (e.g. 8551111 or 855-1111).
    [phone] =~ /^\d{3}(-|)\d{4}$/
    
    Here we first match the first thre digits 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.
  • What if we have the same example as above, but we wanted to match if they also supply an optional initial area code (e.g. 812-855-1111, 812-8551111, 8551111 or 855-1111). This is like the last example except the first part must be optional.
    [phone] =~ /^(\d{3})?(-|)?\d{3}(-|)\d{4}$/
    
    Here we make use of the "?", 0 or 1 operator. We match the area code 0 or 1 times with (\d{3})? and then match a hyphen (or no hyphen) after the area code 0 or 1 times with (-|)?. The rest of the expression is the same as above.
    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 then simply "or" them together (e.g. [var] =~ expression or [var] =~ expression2).
  • Match a string that begins and ends with a digit (what's in between doesn't matter)(e.g. 2abcde4).
    [var] =~ /^\d.*\d$/
    
    Here we 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

  • Ill-defined regular expressions 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]$/
    
    is silently illegal. While no error will be produced, this will not result in replacing [var2] with the value of this variable. This prevents user supplied input from being part of the expression - a potential security problem.
  • For Perl users. Regular expressions in Transform are only used 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.

This should be just about enough for you to get yourself in trouble. For more information about Perl regular expressions, look at a good Perl book like "Programming Perl" by Larry Wall, Tom Christiansen and Randal L. Schwartz, published by O'Reilly & Associates.


Controlling Who Can Submit Your Form
Authentication:
Controlling Access to Your Forms and Documents
Introduction
 
By default, all forms or documents in your www directory (and in subdirectories within the www directory) may be viewed by anyone on the internet. On the central servers you may, however, have some control over who can access your files. You may limit access to only users with an IU network ID and passphrase or create your own custom access control. See Controlling Web Page Access for more information.

How it works
 
This form of authentication works by placing a file (called .htaccess) in the directory where the files you want to control access to reside. Note that this is on a directory by directory basis. The .htaccess file only restricts access to the files in the directory where it resides and subdirectories under the directory where it resides.
When a user attempts to access a file (via an html link) in a directory with a .htaccess file, the www server checks to see whether the user can have access to that directory.

How do I do this?
 
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 to 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 an IU Network IDs in this directory.