The Professional Way to Move Files!
TOC PREV NEXT INDEX

Appendix A: FireScript Editor

This appendix describes the purpose and syntax of the FireScript language and how it used to make an FTP connection through a firewall.

What is a FireScript?


A FireScript allows you to customize the sequence of commands and responses used to log in to an FTP server. This customization may be necessary if your FTP server requires any non-standard commands to be issued before or after logging in, or if certain types of firewalls are between the client and the server.

FireScripts are written in a custom FireScript language, developed specifically for use by WS_FTP Pro. FireScripts can perform the same functions that WS_FTP Pro uses internally to connect to a host or firewall type. FireScripts, however, let you determine if and when these functions are used. In particular, the FireScript determines when to autodetect the host type, and when to go secure with an SSL connection. The script can choose whether or not to try the XAUTH command, and also whether it is necessary to log in to a user account after sending the user ID and password.

FireScript Components


A FireScript is broken into three sections: fwsc, comment and script. As in a Windows ini file, the name of the section appears alone on a line, in square brackets, followed by the rest of the section.

The fwsc section is internally structured with name=value pairs in the same manner as a Windows ini section. It contains identifying information about the script, and indicates what variables will be required by the script.

The comment section is free-form text intended for human readers. It is ignored by the script executable.

The script section contains the scripts executable portion and conforms to the FireScript syntax.

Below is an example FireScript demonstrating this layout.

[fwsc]

author=Ipswitch

connectto=firewall
 

... other values not shown would typically include 'required=' and 'version='

[comment]

This is an example script that connects to an FTP proxy. It is incomplete because many of the commands required to connect have been deleted for clarity. The main purpose is to demonstrate the organization of the FireScript into three sections.

[script]
send ("OPEN %HostAddress") {}
tryssl;
send ("USER %HostUserId")
{
case (300..399) :

	continue ;
 
	case any : 
 
	return (false) ;

}
 

... most of script not shown due to the size.

label success;	

gossl;

return (true);
 

The fwsc Section

The fwsc section lets you specify information about the script in a manner similar to a Windows ini file. Most of the parameters are present for informational purposes. This includes the author and version fields. A few of the parameters are used by the script executive in determining whether or not to show the login dialog, and which IP address to use.

The parser recognizes and stores values for the following parameters:

fwsc Parameters

Parameter

Meaning and Values

author

Informational only. Author of the FireScript.

version

Informational only. Version number of the script file.

verdate

Informational only. Date on which this version was updated.

required

A comma delimited list of fields that must be present for the FireScript to execute. The login dialog is displayed if all required fields are not present, and the Connect button is disabled until all required fields have been filled in.

preask

A comma delimited list of fields that are not required but which, if not present, will cause the login dialog to be displayed.

connectto

`firewall' or `host'. This parameter tells WS_FTP Pro which IP address to use when establishing the connection.

Unrecognized parameters are ignored.

The Comment Section

Use the comment section to describe the actions of the FireScript. The FireScript code should be well described, so it will be easier to understand and update later. The FireScript executive ignores the comment section.

You can also insert comments in the script section by using the `//' comment delimiter as in C++ and Java. Any text on a line following the `//' sequence is ignored by the parser.

The Script Section

The script section consists of a sequence of statements that send commands to the firewall or to the FTP server. Some of these statements have results, or trigger responses from the firewall or FTP server. There is a simple control structure that allows the script to take different paths of execution, based on these results or responses.

The Connection Sequence


A request for connection to an FTP site comes from user actions in either the Classic or Explorer interface, or by one of the WS_FTP Pro utilities such as Find or Synchronize. Sometimes, additional connections are requested by the Transfer Manager to resume or to speed up transfers. All connections are created by the CreateConnection function in the WS_FTP Pro API.

The connection sequence consists of two stages.

The first stage works the same whether WS_FTP Pro is using a FireScript or using one of its internal firewall types. Before executing the script, WS_FTP Pro checks the fwsc section for the list of fields marked as required and preask. If any are missing, it displays the login dialog. If the user fills in all required information and presses Connect, WS_FTP Pro then checks the connectto field. Depending on this field, it will either establish a connection to the firewall's IP address and port, or to the FTP server's IP address and port. If this field is not present, WS_FTP Pro defaults to the IP address of the firewall, if present.

After the connection is established successfully, and a valid socket is opened, WS_FTP Pro calls the FireScript executive to execute the FireScript. If the FireScript logs in correctly and returns success, the CreateConnection function returns the authorized connection to the caller.

The FireScript Language


The FireScript language contains a limited version of elements you may be familiar with if you have written scripts or programs in other languages. It uses variables, declarations, and statements to perform actions and direct program flow. Each of these elements is described in the following sections.

Syntactically, FireScript statements are terminated by semicolons. They may therefore extend across multiple lines, and you can have multiple statements on a line. A string however, may not span lines. The final closing quote must appear on the same line of source code as the opening quote. For example, the code below is valid:

contains

(
 
lastreply,

"Welcome to my cool FTP site"

)

;
 

but the following is not:

contains ( lastreply, "Welcome to 

my cool FTP site" );
 

FireScript Variables


Firecripts work with the login information provided by WS_FTP Pro. This includes at least the user IDs and passwords, the IP address and port of the FTP server, and sometimes the IP address and port of the firewall. These fields are often read from a site profile, an FTP URL, or from the command line. As described before, if some of the required information is missing, the connect sequence presents the login dialog so that the user can enter it interactively. The script executive stores this information in a set of intrinsic variables before beginning execution. In addition there are intrinsic variables that contain the results of the last command issued. These are set by the script executive after such statements are executed.

The syntax for using a variable depends on the statement or expression in which it is used. Below is a list of all the intrinsic variables:

FireScript Intrinsic Variables

Variable

Meaning and Usage

FwUserId

The user's user ID on the firewall. Some firewalls require users to log in to the firewall before allowing other connections to be made through the firewall.

FwPassword

The user's password on the firewall. Required if the user must log in to the firewall.

FwAccount

Account on the firewall. Required if the user must specify an account on the firewall. Practically unheard of but included in case required.

FwAddress

The IP address of the firewall. Required if the user must connect to the firewall, and have the firewall in turn connect to the FTP server and act as proxy.

HostUserId

The user's ID on the FTP server. Almost always required. Specify `anonymous' if the user does not have a user ID on the server.

HostPassword

The user's password on the FTP server. Almost always required in conjunction with a user ID. Use your email address as the password when using `anonymous' for the user ID.

HostAccount

The user's account on the FTP server. To access certain information in some operating systems, FTP servers on those systems require an account to be sent after successful login with user ID and password.

HostAddress

The IP address of the host. The script executive may connect directly to this address, or will send the address to a firewall that will act as a proxy.

LastFtpCode

The 3-digit, numeric code of the last response received from the FTP server or firewall. For example, after a successful login, the LastFtpCode would be 230.

LastReply

The text of the last response from the server. e.g. "230 user logged in"

FireScripts neither need nor use user-defined variables, so there are no variable declarations. Also, since the FireScript cannot directly set the value of one of the intrinsic variables, there is no need for any assignment statements.

String Expansion


Some of the commands and functions in the FireScript language take strings as arguments. To these you may either pass a string variable or a string literal surrounded by double quotes, e.g. "This is a string." To put a double quote inside a string, preface it with the percent sign `%'. The percent sign `%' is used as an escape character to embed variables and quote characters in strings.

The sequence %% is replaced by a single %.
The sequence %" is replaced by ".
% followed by the name of a variable is replaced by the value of the variable.

For example, the script statement below:

send ("OPEN %HostAddress")
 

If HostAddress is equal to "ftp.ipswitch.com" when this script is invoked, the command will be expanded to:

send ("OPEN ftp.ipswitch.com")
 

the expression,

contains (lastreply, "%% full")
 

will be expanded at runtime to:

contains(lastreply "% full")
 

and the statement

send ("SITE SETLOG %"f:\log files\access.log%" 
-clear")
 

the expanded string sent will be:

SITE SETLOG "f:\log files\access.log" -clear
 

Passing a string variable is equivalent to, but faster than passing a string literal that expands the variable.

Example:

isempty(FwPassword)
 

is equivalent to but faster than

isempty("%FwPassword")
 

Function Expressions


Currently the FireScript language does not allow full-blown expressions. It does include two function expressions with some boolean operators for evaluating the state of variables. They are contains and isempty. The boolean operators supported are not and and.

The contains function takes two strings and returns true if the second string is found in the first. The search is case sensitive. Both strings are expanded first.

The isempty function takes a string and returns true if there are any characters in the string. You can use it to test if a value was specified for one of the intrinsic variables.

The not boolean operator reverses the value returned by the function expression.

Example:

If the HostAccount variable contains the value `usr987i'
isempty (HostAccount) will return false but
not isempty(HostAccount) will evaluate to true.

The and boolean operator requires all specified conditions to be true.

Example, If the HostAccount variable contains a value such as `usr987I'
The last reply from the server is "230 User logged in, please send account"

then the following expression will evaluate to true:

case (200..299) and not isempty(HostAccount) 
and contains(lastreply, "ACCOUNT") :
 

FireScript Statements


The FireScript language includes several types of statements. Statements cause actions to be taken, or direct the flow of execution of the script. The following sections describe the types of statements.

Switch Statements


The send statement and the xauth statement are called switching statements, because they imply an immediate switch statement based on the server response. The switch statement contains case statements very similar to Java and C++ case statements, except the conditions are not constants checked against a single expression.

A switching statement such as send and xauth is always immediately followed by a set of case statements between curly braces { <case statements> }. The set of case statements may be empty, in which case there is nothing between the curly braces, but the braces must be present.

Example of Switch Statement:

send ("USER %FwUserId") {}
 

The send statement takes a single argument, the string to be sent to the server. The string is expanded before it is sent. The maximum legal length for the expanded string is about 512 bytes, the maximum length of an FTP line. The send command then waits on a response from the server and evaluates the response against the conditions in each of the enclosed case statements.

The xauth statement takes no arguments. It examines the welcome banner for an xauth invitation supplied by WS_FTP server. If it is not connected to WS_FTP server or cannot find the invitation, xauth does nothing, and the case statements are not evaluated. If it does find the invitation, it encodes the user ID and password and sends the xauth command to the server. It then waits on the response and evaluates it against the case statements just as the send command does.

Case Statements


Case statements are enclosed in switching statements. A case statement lists a set of conditions that the server response must satisfy for the case to be activated.

The list of conditions is followed by a colon `:'.

Case stataments are processed in the order in which they are listed until the first match is found.

Once a match is found for the conditions in a case statement, then the nested statements are executed.

A case condition may be a list of FTP codes and code ranges, a function expression, or one of the special cases, any and timeout.

If a case includes a list of ftp codes/ranges, the list must appear first, followed by any function expressions. The list is comma separated and enclosed in parentheses. Each item in the list must either be a single 3-digit code, or a range specified by two 3-digit codes separated by a double period `..'. The range is inclusive and it is recommended that the lower bound be specified first.

The special cases any and timeout must appear by themselves.

Examples of Case Statements

The following case condition will match if the returned ftp code is either 226 or 231.

case (226, 231)  :  
 

The following case conditions will match if the returned ftp code is either 226 or 231, or between 250 and 299 inclusive. So 250 itself will match, as well as 251, 252 etc. up to 299

case (226, 231, 250..299) :
 

The following case conditions will match if the returned ftp code is in the 300s and the returned string contains the text "email address".

case (300..399) and contains(lastreply, "email 
address") :
 

The following case conditions will match if the returned ftp code is 500 or greater and the returned string contains the specified error message

case (500..999) and contains(lastreply, "user 
%HostUserId cannot login.") :
 

If a case contains more than one condition they must be separated by and. The and operator specifies that all the listed conditions must be satisifed. So in the previous example, the ftpcode must be between 500 and 599 AND the last reply must also contain the specified string. Both must be true. If either is false, the case will not match.

The not operator reverses the result of a function. We may for example want to make sure that the last response does not contain a certain string. For example:

case (500..599) and not contains(lastreply, 
"server is busy") :
 

There is no or operator. The same logic may be applied by using multiple case statements.

The following case condition will match if the send command timed out.

case timeout :
 

Case any is the catch all case, and if present should be the last case in the enclosing list. If it is followed by other case statements they will never be evaluated.

For example, the following case condition will always match.

case any:
 

If case statements overlap and two case statements would match the response, then the first one encountered will be executed.

Example:

case (200..299) and contains(lastreply, "please 
send user account") :
 
...

case (200..299) :

...
 

If the case with the contains function appeared after the one without it, it would never get evaluated.

Continue


Unlike C and C++, execution inside a case statement does not fall through to the next case statement. Only the statements listed under the activated case are executed. Then execution continues at the next statement after the enclosing switching statement. The continue statement jumps to the statement following the enclosing switching statement. It does the same thing as a break, inside of a C/C++ switch statement, except it is not absolutely necessary.

Switching statements may not be nested. That is, neither a send statement nor an xauth statement may appear inside a case statement.

Jumps and Labels


A jump statement transfers execution to another part of the script. The jump destination must be defined by a label that also appears in the script. The Ipswitch example FireScripts use jumps to different code sequences from inside case statements, so the code that gets executed depends on which case was activated.

A label declaration consists of the word label, followed by the name of the label and a semicolon.

A jump statement consists of the word jump, followed by the name of the jump destination, and a semicolon.

A label may not appear inside a case statement. You can't jump into a case statement.

Return


The return statement acts like a function in that it takes a single parameter, either true or false to indicate success or failure. It terminates script execution and returns to the caller. If it returns true, the connection is assumed to be logged in and authorized. If it returns false, the caller may either try again or abandon the connection.

Autodetect


The autodetect statement examines the last reply from the server to help determine the host type of the FTP server to which it is connected. Autodetect expects to examine the welcome banner so the statement should be placed immediately after the welcome banner is returned. Here are two example banners returned from two popular FTP servers. Autodetect would detect the first as being a Microsoft NT server, and the second as being an Ipswitch WS_FTP server.

220 tstsrvnt Microsoft FTP Service (Version 3.0).
 
220 tstsrvws X2 WS_FTP Server 1.0.5 (1737223651)
 

If connection was made directly to the host FTP server and the welcome banner was already returned before the script begins execution, then autodetect should be the first statement in the script. If the connection was made to the firewall and the welcome banner from the host ftp server becomes available later in the script, the autodetect statement should be placed at that point. If the firewall swallows or replaces the welcome banner from the ftp host, or for some other reason, the ftp client never sees the welcome banner, then leave out the autodetect statement. WS_FTP Pro will try to determine the host type after the script executes.

Autodetect does nothing if the host type in the site profile is set to anything other than `Auto Detect.' The autodetect statement has no return value and does not change the flow of the script.

SSL Statements


The tryssl and gossl commands attempt to open a secure channel with the server via SSL. The difference between them is that if gossl fails, the script will terminate and return false, while if tryssl fails, the script will continue. The commands can appear more than once in the program. If a secure connection was not requested, or has already been established, the commands will do nothing. If the commands fail to go secure, they will display a message box to the user, asking the user if she wishes to continue in the clear, try again for SSL later in the sequence, or abandon the connection. If the user chooses to continue in the clear, future calls to tryssl or gossl will do nothing.

When the script completes, the script executive checks the SSL status of the connection to make sure that a request for a secure connection was honored. In the site profile, if the user selected Use SSL, then the script executive will issue a warning to the user if the connection is not secure. At this point, the user may abandon the connection. This warning is issued if a secure connection was attempted and the user chose to continue in the clear.

The placement of the attempts to open an SSL channel can be very important, depending on the type of firewall through which the script is connecting.

FireScript Key Words


Below is a complete list of all the keywords used and understood by the language. You may not use these words as label names.

gossl

tryssl

autodetect

send

xauth

case

continue

and

not

any

timeout

return

jump

label

true

false

FireScript reserved words

The following words are reserved for future versions of the language and the parser. You should not use these words to name your labels.

switch

if

for

next

while

loop

break

function

int

bool

string

var

password

or

FireScript statements

gossl

tryssl

autodetect

send

xauth

jump

return

continue

FireScript intrinsic functions

contains

isempty

FireScript intrinsic variables

FwUserId

FwPassword

FwAccount

FwAddress

HostUserId

HostPassword

HostAccount

HostAddress

LastFtpCode

LastReply



Ipswitch, Inc.
http://www.ipswitch.com
TOC PREV NEXT INDEX
©Ipswitch 2003