ODBscript
Open DataBase
Scripting Language

Version 3

User's Guide - Part 3


String Functions

The following string functions can be used anywhere that you can use a variable: in the output text; in HTML tags; and in ODBscript commands and expressions.

All string function names begin with a $ sign. Like variables, the names are not case-sensitive. Each function has one or more "arguments" enclosed within a set of parentheses. You can put spaces between the function name and the left "(" of the arguments if you like.

Each of the arguments to these functions are evaluated like SET expressions, so you can use any arithmetic or logic expressions as arguments. For each of these string functions, the result of evaluating the first argument will be treated as a character string, even if it is an arithmetic expression. Like SET and IF expressions, character strings do not need to be enclosed in quotes unless you need to prevent inadvertent interpretation (e.g, if the string contains math operation symbols or commas), but you may use quotes if you like. (Note, however, that variable references within quotes will not have their values substituted.) Character strings may consist of several "concatenated" quoted or unquoted strings or variables in a row, such as ("Variable one is" $var1$ "and variable two is" $var2$), which will be treated as a single string argument.

(Note that the section after this defines numeric functions that always return numeric results, and which are ordinarily used only in the context of arithmetic or logical expressions. However, each of those functions can also be used as string functions by placing a "$" prefix in front of the numeric function name, so any those functions can also be used anywhere you can use a string function.)

Important Note: When string functions are used directly in the output text (as opposed to being used in ODBscript commands), the entire list of arguments must appear on a single line. Otherwise, you will get an error message, "function missing right paren ')'...". (ODBscript commands, however, do not have this limitation: function arguments in commands, such as SET, can span multiple lines.)

$asc (number)

The $asc( ) function produces a single character, which is the ASCII character for the given number (or expression). This function may be used to insert special characters into the output.

$cardType (string)

This function returns the credit card type (i.e., the card issuer) for the given string, which is presumed to be a credit card number. The supported card types (and the returned values) are: "VISA", "MASTERCARD", "AMEX" (American Express), "DISCOVER", and "DINERS CLUB/CARTE BLANCHE". If the card type is not recognized, the value "UNKNOWN" is returned. The card type is determined by the first few digits of the number, and the remainder of the string is not checked. See the isCreditCard( ) numeric function for fully validating the number.

$dateAdd (date, number_to_add, result_date_format [,units])

The dateAdd function adds the specified number of days, months, or years to the input date, then formats the result using the given date format mask. The optional units parameter can be "D" to specify days (which is the default if this parameter is omitted), "M" to specify months, or "Y" to specify years. (The quotes are not required.) See the FORMAT command for details of date format masks. The number to add can be either positive or negative. The input date field must be recognizable as a date using these rules:

$dateDiff (date_1, date_2)

The dateDiff function subtracts the given date_2 from date_1, returning the number of days between the two dates. Note that "date_1 minus date_2" will be a negative number if date_1 is before date_2. This allows the result to be used as a date comparison: a negative result means that date_1 is before date_2, a positive non-zero result means that date_2 is before date_1, and a zero result means the two dates are equal. If you always want the positive number of days, then put the later date first, or if you don't know the order of the dates, use abs($dateDiff(date_1,date_2)) (or the string function version $abs($dateDiff(date_1,date_2)) to insert the result in ordinary output.) The input dates must be valid under the rules detailed for the input to the $dateAdd( ) function, above.

$decrypt (string, key)

Decrypts the given string using the specified key. (Presumably, the string was encrypted using the same key by the $encrypt( ) function or the JavaScript equivalent.)

$encrypt (string, key)

Encrypts the given string using the specified key. (The result string may be decrypted using the same key by the $decrypt( ) function or the JavaScript equivalent.) The encryption uses a strong, "private key" method.

$env (environment_variable)

This function returns the string value of an "environment" variable. For CGI programs, environment variables are defined by the Web server. ODBscript automatically sets up variables for many commonly used CGI environment variables (see predefined variables set by ODBscript); this function is provided to get the value of any others that you may need. For example, if you are using "authentication" for access (password-protected pages), then you can use $env(REMOTE_USER) to get the user's login name.

$eval (expression)

The $eval( ) function produces the result of evaluating the given string as an arithmetic or logic or expression. The primary use for this function is to insert a calculated result into the output without having to SET a variable to that result. For example, when outputting the results of a query as a table, you might use "$eval($Quantity$ * $Price$)" as a table column entry to compute a result using the values in other columns in the same row. Note that if the $eval( ) function is unable to evaluate the given string as a valid arithmetic/logic expression, then no error is produced but the result will just be the original string. Also note that it is never necessary to use $eval( ) in a SET or IF expression, since those expressions are always evaluated unless the expression is inside double-quote marks. (However, you might SET a variable to be a quoted $eval( ) expression, in which case the $eval( ) is not evaluated at that point; it is evaluated when the SET variable is actually referenced in the document, which causes the variable act as a "macro" for a formula.)

$format (mask, expression)

This function will format the given expression or character string using the specified "mask". See the FORMAT command for details on using masks. The distinction between the FORMAT command and the $format( ) string function is that the FORMAT command is used before referencing a variable to define a mask that will be applied each time the variable is referenced. The $format( ) string function, on the other hand, formats and outputs the result directly at the point where the function is used. Also, the "expression" to be formatted may be a computed result, so this function may be used to insert a formatted calculation into the output, such as $format("$#,###,##0,00", $Quantity$ * $Price$).

$hex (string)

The $hex( ) string function converts the given string to hexadecimal characters, two per input character.

$httpGet (URL, var [,var,...])

Execute an HTTP "get" request to the specified URL, optionally passing the given list of variables in the URL. Variable names must not be enclosed in "$" characters: specify only plain variable names in this list. The response to the request should be ASCII text or HTML only -- not binary data -- and the result will be truncated if necessary to the maximum size of a variable value (which is 8 KB in the standard version or 32 KB in the "large variable" version). The HTTPGET command should be used instead of this function whenever the response is simply to be output to the user's browser; this function should only be used when some processing of the response is required. The specified variable list will be added to the URL is standard HTTP form, i.e. following a question mark, in the from or "variable=value", with multiple variables separated by "&" characters, and all values "URL encoded" to prevent special characters and spaces from being misinterpreted. Alternatively, the URL that you specify can already have variables encoded in it, or it may have some variables and more variables can be added via the list. (Any existing "?" will be detected, and if so, the additional variables will be added after a "&" character.) See the HTTPGET command for details about response status and HTTP headers. If the response is assigned to a variable and it is necessary to break the response into individual lines for processing, a $split( ) may be used in a WHILE loop, such as:
    response = $httpGet(www.domain.com/script,var);  note: "?var=$url($var$) added to URL;
    WHILE $response$;
        line = $split(response, $asc(10));  note: split response at first CR character;
        note: process a single line of the response in the variable $line$;
    ENDWHILE;   note: loop will end when no more lines left in $response$
Note that the response headers are set in a single variable named $http_headers$, also separated by CR (carriage return) characters, so a similar $split( ) loop can be used to process the individual headers.

$httpPost (URL, var [,var,...])

Execute an HTTP "post" request to the specified URL, optionally passing the given list of variables as "post" data. Variable names must not be enclosed in "$" characters: specify only plain variable names in this list. This command is similar to the $httpGet( ) function above, except that the "post" method allows more data to be passed (because it is passed in the "body" of the request, not in the URL itself). Like the $httpGet( ) function above, this function is restricted to ASCII text or HTML responses, and only up to the maximum variable size (8 KB or 32 KB).

$icase (string)

The $icase( ) function "shifts" the first character of the given string to uppercase and all remaining characters to lowercase. ("Initial capital.") It has no effect on non-alphabetic characters. (Note that only the first character of the string is capitalized. To capitalize the first character of each word in the string, use the $wcase( ) function.)

$if (test, iftrue [, iffalse])

The $if( ) function is an "immediate IF" statement. It is a convenient way to avoid using an <% IF ... %> ... <% ELSE %> ... <% ENDIF %> sequence when you just need a short section of output or a conditional string assignment in a SET command. If the specified "test" is true, this string function returns the "iftrue" argument (which is evaluated as an expression). If the "test" is false, the evaluated "iffalse" expression is returned. The "iffalse" expression is not required: If it is omitted and the test is false, then an empty (null) string is returned. The "test" can be any conditional expression allowed in the IF command.

Example:

    <% SET avg = $if($number$ > 0, $sum$/$number$, 0) %>

In the above statement "avg" is set to "$sum$/$number$" only if "$number$ > 0". Otherwise, "avg" is set to "0". Like all string functions, $if can be used directly in the output. For example, the following will produce lines such as "No records selected", "1 record selected", or "10 records selected" depending on the value of $row$:

    $if($row$, $row$, "No") record$if($row$<>1, "s") selected.

$lcase (string)

The $lcase( ) function "shifts" the given string to lowercase characters. It has no effect on non-alphabetic characters.

$left (string, count)

This function produces the leftmost "count" characters of the given string. For example, $left(ABCDEFG, 4) produces "ABCD" in the output. If "count" is less than or equal to zero, the result will be a null string. If "count" is greater than the length of the string, the result will be the full input string.

$ljust (string, length)

This function produces a fixed-width output that is "length" characters long, with the given string starting at the first character position (i.e., "left justified"). The output string is padded with spaces on the end if necessary to produce the given "length". The string is truncated on the right side if it is longer than "length" (i.e., the end of the string will be lost). $Ljust( ) and $rjust( ) are primarily intended for creating tables with fixed-width columns in "pre-formatted" HTML text (i.e., inside the <PRE> and </PRE> tags) and in output text files. (In normal HTML, extra spaces are ignored.)

$match (string, pattern)

The $match( ) function scans the specified string for any match with the given "regular expression" pattern. If any match is found, the value returned is the matching substring. The $match( ) string function can be used in an IF to test the value of the extracted substring, or it can be used in a SET command to assign the matched substring to another variable. Like all string functions, you can also use $match( ) directly in your output without assigning the result to another variable; that is, the matching substring will be output. The $match( ) function is also useful as an argument for other functions. For example, $repl($string$,$match($string$,pattern)=newvalue) could be used to replace the matched substring. Remember that, like all functions, the subject character string and the pattern are both evaluated as "arithmetic/logic expressions", so it is usually necessary to put quotes (" ") around the pattern.

Please see the match( ) "numeric" function for a complete list of regular expression "meta-characters" and some examples.

$memo (string)

The $memo( ) function is useful for improving the readability of long memo-type database columns. One typical problem with displaying memo fields in an HTML document is that the default for HTML text is to "line fill" to the current width of the window, ignoring any "new line" characters (the ENTER key) in the source. This destroys any line spacing and paragraphing that the user intended in a memo field. You might enclose a memo field inside <PRE> and </PRE> HTML tags (which indicates "pre-formatted text" and turns off line fill). But if there are any long lines in the memo without any "new line" characters, then those lines extend off the right side of the page, and you have to use the browser's bottom scroll bar to read them. (The problem is that most input methods, such as browser forms and database GUI interfaces, automatically "wrap" words as they are typed but without actually inserting "new line" characters in the text, so users might or might not hit the ENTER key at the end of each intended line.) To improve the readability of these fields without destroying the users intended line spacing, the $memo( ) function replaces each single "new line" character with an HTML <BR> tag ("line break"), and each occurrence of two consecutive "new line" characters with a <P> tag ("paragraph"). Thus, long lines will "wrap" at the right side of the browser window but the user's "new lines" and intended paragraphs are preserved.

$mid (string, start [,count])

The $mid( ) string function extracts a substring from anywhere within the given string. "Start" is the first character position to begin the extraction (counting the first character as 1). If only the "start" argument is given, then all character following the "start" position are included in the result. For example, $mid(ABCDEFG, 3) produces "CDEFG" in the output. If the "count" argument is given, then it specifies the number of characters to extract. For example, $mid(ABCDEFG, 3, 4) produces "CDEF" in the output. If "start" is less than or equal to zero or is greater than the length of the string, or if "count" is less than or equal to zero, the result will be a null string. If "start" plus "count" is greater than the length of the string, the result will be the full input string following the "start" position.

$nbsp (variable)

The $nbsp( ) string function can be used to output the value of the given variable, if it has a value, or to output the HTML character entity reference "&nbsp;" (a "non-breaking space") if the variable has no value. If the variable has a FORMAT mask defined, the value will be formatted with that mask, and if it has a DEFAULT value, that default will be used. Having an "&nbsp;" output instead of an actual blank or empty string is most useful in a <TABLE> cell because browsers combine any adjacent table cells that have no values, but "&nbsp;" in a cell counts as a value, so the cell remains distinct but empty.

$newFileName (path [,prefix])

This function will return a unique file name that you can use for an output file. (It does not actually create the file; it simply gives you a file name that is guaranteed to be currently unused.) The "path" parameter specifies the intended file system directory for the file. The optional "prefix" argument specifies a file name prefix (the first few characters of the name). The unique file name returned will include a number added to this prefix, or just a number if no prefix is specified. The returned file name will include the directory path, so you can use this name in an OUTPUT command. Typically, you will want to save the returned name in a variable, so that it can be used later:
    <% SET tempfile = $newFileName("/temp", "out") %>
    <% OUTPUT $tempfile$ %>

$pathInfo (file)

The $pathInfo( ) function and the following $pathTranslated( ) function are provided to make is easier to reference files relative to the current ODBscript script file, and thus avoid having to "hard code" directory information in your scripts. This makes it easier to rearrange the structure of your Website without having to change the directory paths specified in scripts.

Given a file name argument (which may include a subdirectory), the $pathInfo( ) function returns a URL-type file path specification relative to the path of the current script. (By "URL-type file path", we mean relative to your Web server's root and virtual directory mappings, as used in URLs.) This function uses the server variable named "path_info," which is normally the "extra path" directory information after the "odb.exe" in the URL that invoked ODBscript. For example, if the URL was "http://www.yourdomain.com/scripts/odb.exe/your_site/your_dir/script1.odb" then the server variable "path_info" contains "/your_site/your_dir/script1.odb". ODBscript always sets up a predefined variable named $path_info_dir$ with just the directory part of the path_info, which would be "/your_site/your_dir" in the given example, but the $pathInfo( ) function provides a more convenient way to use that value: It combines the $path_info_dir$ value with the given "file" argument, according to conventional "relative path" notation. If the "file" argument is just a file name, then $pathInfo( ) simply returns the $path_info_dir$ followed by a "/" followed by the given file name. That is, it returns a URL file path for a file on the same directory as the current script file. For the given example, $pathInfo("script2.odb") would return "/your_site/your_dir/script2.odb". But the "file" argument can also be preceded by "../" to move up one level in the directory structure (i.e., ".." represents the "parent" directory of the current path_info, without knowing its name). For the given example, $pathInfo("../another_dir/script3.odb") would return "/your_site/another_dir/script3.odb". You can use any number of levels, such as "../../" to move up two levels.

$pathTranslated (file)

Like the $pathInfo( ) function above, the $pathTranslated( ) function is provided to make is easier to reference files relative to the current ODBscript script file, and thus avoid having to "hard code" directory information in your scripts. But $pathTranslated( ) operates on the actual file system path of the current script file, rather than on the Web server's root and virtual directory mappings. This is actually the more important function, since commands such as INCLUDE, OUTPUT, and IMPORT require an actual file system path instead of a Web server mapped path.

This function uses the value of the server variable named "path_translated", which is the "path_info" of the current script file but with the Web server directory mappings translated to actual file system directories. (Note that the file system directory of the current script is also in the predefined variable named $path_translated_dir$, but the $pathTranslated( ) function makes it easier to use.) Similar to the $pathInfo( ) function described above, this function takes the given "file" argument and returns an actual file system path relative to the current script file, using conventional "relative path" notation. The "file" argument can include a subdirectory before the file name (e.g. $pathTranslated("include/file.txt"), and note that in this case, no preceding "/" should be used). The "file" argument can also use "../" to represent the "parent" directory of the current script file, to any number of levels. This is the major advantage of using this function: you can reference files "up" and "over" in the current script directory structure, without knowing or "hard coding" the names of those directories.

$pwd (string)

The $pwd( ) function creates a "one-way encrypted" version of the given string. It can be used to encrypt passwords stored in a file so that the passwords cannot be used by anyone who happens to gain access to the file. The encryption is "one way" because the passwords cannot be "decrypted". Rather, when a user enters a password to access a function, the entered password should be passed through this same function and the result should be compared to the stored password. That is, since this function always produces the same result for a given input string, the two encrypted values can be compared without knowing the original password -- they will match only when the same password is used both times.

For example, something like this can be used to insert a user and password into a file:

    <% INSERT INTO Users (user, password) VALUES ('$user$','$pwd($password$)') %>
Now, when a user accesses a form and enters a user ID and password (lets call the form input variables "userid" and "passwd" so they don't conflict with the database columns), you can do this:
    <% SQL SELECT password FROM Users WHERE user='$userid$' ;
       IF $row$ = 0 %>
          No such user. Please go back and reenter your user ID.
          <% EXIT %>
       <% ENDIF;
       IF $pwd($passwd$) <> $password$ %>
          Incorrect password. Please go back and reenter your password.
          <% EXIT %>
       <% ENDIF;
       NOTE: encrypted password matches, allow operation %>
This function always produces exactly 16 output characters, regardless of the length of the password. Note that since passwords cannot be decrypted, if someone forgets his password, you cannot extract the current password from the data. You will have to assign a new password. Also note that $pwd( ) is not compatible with any other password encryption schemes; you must use ODBscript to create the encrypted passwords and to check them.

$rand (mod)

$rand( ) returns a pseudo-random number as a character string. Random numbers are in the range of 0 to 65535. The "mod" parameter is optional; if given, the random number will be divided by this number and the remainder will be returned. Therefore, to get a random number in the range of 0 to 9999, use $rand(10000). To get a random number in the range of 1 to 10000, use $rand(10000)+1. Larger random numbers can be generated by using the $rand( ) function multiple times, such as $rand()$rand()$rand(). (Also see the rand( ) numeric function, which can only be used in an arithmetic expression).

$read (fileID)

$read( ) reads a single line of text from a file opened with the OPEN command. The file ID is simply a label -- any name or number that you wish to use -- which must match the fileID used in the OPEN command. Important note: The text string read from the file will not have a new line character at the end; as a convenience, these are automatically removed. (If you need a line break when you use the variable -- for example, if you write it out again -- you can use $asc(10) to insert a "linefeed", which is the new line character.)

$repl (string, find1=replace1 [, find2=replace2, ...])

The $repl( ) string function replaces one or more substrings within the given string with new substring values. Each occurrence of a "find" substring (which may be one or more characters) within the given string is replaced with the specified "replace" substring. The replacements are defined with an "=" between the "find" substring and the "replace" substring. Multiple replacement pairs may be given, separated by commas. You can use quotes around the "find" and "replace" string values, but quotes are required only if a substring contains a comma or an "=" sign, or if the substring is a single space character, " ". If a substring contains any double-quote characters ("), you can use single-quotes (') around the string, such as '"'.

$reverseDNS (IP_address [,not_found_result])

The $reverseDNS( ) function performs a "reverse DNS lookup" on the input (dot-delimited) IP address, returning the domain name if it is found. (The DNS server currently configured as the default for the local system will be queried.) If no domain name is found for the IP address, this function returns the "not_found_result" string or expression, if given, or no result (a zero-length string) if that optional argument is omitted. For example, this line shows the remote host name associated with the user's IP address, or shows a message if no DNS entry is found.
        Your host system is: $reverseDNS($remote_addr$, "(Unknown)")

$right (string, count)

This function produces the rightmost "count" characters of the given string. For example, $right(ABCDEFG, 4) produces "DEFG" in the output. If "count" is less than or equal to zero, the result will be a null string. If "count" is greater than the length of the string, the result will be the full input string.

$rjust (string, length)

This function produces a fixed-width output that is "length" characters long, with the given string ending exactly at the rightmost position (i.e., "right justified"). The output field is filled with leading spaces on the lefthand side if necessary to produce the given "length". The string is truncated on the left side if it is longer than "length" (i.e., the beginning of the string will be lost). $Rjust( ) and $ljust( ) are primarily intended for creating tables with fixed-width columns in "pre-formatted" HTML text (i.e., inside the <PRE> and </PRE> tags) and in output text files. (In normal HTML, extra spaces are ignored.)

$split (variable, delimiters)

The $split( ) function splits the given "variable" into two pieces: It returns a substring from the front of the given "variable" (similar to the $left( ) function), up to the first instance of any one of the given "delimiters" characters, and it resets the given "variable" to be all of the remaining characters following the found delimiter character. Only a defined variable name can be given as the "variable" parameter, and this variable name must be given without any enclosing "$" characters. The "delimiters" parameter should be a literal character string (or possibly a variable reference) containing one or more characters, and the returned string will be all of the characters up to the first occurrence of any one of these characters.

For example, assume that a variable named "input" contains the character string value "x=10". After this SET command,

    <% SET var = $split(input, "=") %>
then variable $var$ would have the value "x" and the original variable $input$ would have the value "10".

The $split( ) function is also useful in a WHILE loop to handle an indefinite list of delimited values in a variable. For example, suppose that variable "input" is a list of names separated by commas. The following loop will allow processing each of these names individually until the "input" variable is empty:

    <% WHILE $input$ %>
      <% SET name = $split(input, ",") %>
      $name$
      ...
    <% ENDWHILE %>

$sysDecrypt (string)

Decrypts the given string using a special internal key, which is unique for the Web server and which is kept secret. (This function is only useful if the string was encrypted using the $sysEncrypt( ) function on the same server.)

$sysEncrypt (string)

Encrypts the given string using a special internal key, which is unique for the Web server and which is kept secret. (This function is only useful if the string will be decrypted using the $sysDecrypt( ) function on the same server.) This encryption is required for the values of "in_database" and "in_sql" when using no script mode. Note that when these encrypted strings are passed as the VALUE="..." parts of <INPUT> tags in a form, you must use double-quoted values, not single-quoted (apostrophe) values. This is because apostrophes are possible characters in the encrypted string, which will cause browsers to cut the value short if VALUE='...' is used, but the double-quote character is not a possible encryption character so VALUE="..." will always work.

$trim (string)

The $trim( ) function removes any leading and trailing spaces, tab characters, and "new line" characters from the given string.

$ucase (string)

The $ucase( ) function "shifts" the given string to uppercase characters. It has no effect on non-alphabetic characters.

$url (string)

The $url( ) function encodes the given string in "URL format". This format codes spaces as "+" signs and special characters as "%xx" where "xx" is the hexadecimal number of the ASCII character. This function allows passing variables to a CGI program as the "query string" in a URL link. The "query string" is anything following a "?" (question mark) in the URL. CGI variables may be included in the query string by "name=value" pairs, with multiple variables separated by the "&" (ampersand) character. For example:
<A HREF="/scripts/odb.exe/script.odb?category=$url($category$)&uid=$url($uid$)">
The CGI program will get these named variables just like <INPUT> variables in a <FORM>.

$var (variable_name)

This function simply returns the value of the given variable_name. It is not particularly useful when used with a literal variable name (i.e., just a variable name without the enclosing "$" characters) because $variable_name$ will do the same thing. (That is, $variable_name$ and $var(variable_name) will produce exactly the same output: the current value of the variable.) It is useful, however, when the name of the variable that you actually want to reference is contained in the value of another variable. Then, it becomes a kind of "indirect" reference to a value. Suppose for example that a variable named "abc" contains the value "This is ABC". If another variable named "xyz" contains the value "abc", then referencing $xyz$ will of course produce "abc". However, the string function $var($xyz$) becomes $var(abc) after variable replacement, which will produce "This is ABC". (Note that if variable "xyz" had the value "$abc$" instead of "abc", then you wouldn't need or want to use $var( ), because variables can reference other variables with "$" characters around their names and they will automatically be resolved. Therefore, the $var( ) function is really only useful in those special cases when a variable contains the name of another variable, but without "$" characters around the name.) This function returns an empty string if the variable_name is undefined.

The $var( ) function can also be used on the lefthand side of the SET command, as the target variable of the SET assignment. This is the only case where a variable reference or string function can be used as the target of the SET command. (The SET command will allow you to use the syntax "SET $variable_name$ = ..." instead of "SET variable_name = ...", but the "$" characters are actually ignored in the first case, and both statements have the same result: setting a variable named "variable_name".) When used in this manner, the $var( ) function is again a type of "indirection", because the value of the function argument is evaluated, and that becomes the name of the variable that is actually SET. In this case, it is very important to be careful whether or not you use $var(variable_name) or $var($variable_name$), or some combination of variable references and literal values, depending on exactly what you want to do. The rule is that the argument will be completely resolved, just as with any other string function argument, and the resulting value becomes the name of variable that is actually set. Therefore, "SET $var(variable_name) = ..." is not really useful, since that will be the same as using "SET variable_name = ...". However, "SET $var($variable_name$) = ..." can be used when the value of variable_name is actually the name of the variable that you want to set. This is also a useful function when you want to construct a variable name dynamically, using some combination of variables and literal values. For example, if a variable named "number" contains the value "3", then using "SET $var(row$number$) = ..." will actually set a variable named "row3".

$varstr (variable_name)

This function returns the value of the given variable_name without resolving any embedded variables or string functions that may be contained in that value. That is, ordinarily when you reference $variable_name$ and the value of $variable_name$ contains additional variable references or string functions, then those references will also be resolved "recursively", up to 16 levels deep. For cases when that is not desirable, i.e., you want to leave the variable references in the value and not replace them with their current value, the $varstr( ) function will disable the embedded variable replacement. Ordinarily, this function should be used with a literal variable_name (rather than $variable_name$) as the argument, because the argument should be the variable name itself, not its value. (The only case where you would use $varstr($variable_name$) or some other expression rather than $var(variable_name) is when the value of the variable contains the name of another variable, and this other variable is actually the one that you want to use. That is, the argument is always completely resolved, just as any string function argument would be, and the resulting value will be the name of the variable that is returned.) This function returns an empty string if the variable_name is undefined.

$wcase (string)

The $wcase( ) function "shifts" the first character of each word in the given string to uppercase and all remaining characters in each word to lowercase. It has no effect on non-alphabetic characters. (Note: To capitalize only the first character of the string and lowercase the rest of the string, use the $icase( ) function.)


Numeric Functions

Following are the mathematical and numeric-valued functions that you may use in
SET or IF statement arithmetic expressions, or as string function arguments. Each of these functions returns a single numeric value, and they can only be used in the context of an arithmetic or logical expression. However, note that there are also string-function equivalents for each of these numeric functions, which are identical in form except that the function names begin with the "$" prefix character (for example, $abs(number)). When used as string functions, these may be used in any context where a variable may be used, such as directly in the output.

abs (number)

Abs( ) returns the absolute value (a positive number) of the given number. That is, it will remove the "-" sign of a negative number, but it does not affect a positive number.

and (number1, number2)

And( ) returns the value of the "Boolean AND" (sometimes called "logical AND") bitwise function performed on the two given numbers. The Boolean AND operation tests the corresponding bits ("binary digits") of the two numbers and produces a result bit of 1 only if the two corresponding bits are both 1; otherwise the result bit is 0. Boolean AND has two primary uses: testing whether one or more specific bits are currently set in a number (for example, if each bit represents a yes/no "flag"); and "masking out" some of the bits in a number. For example, and($n$,2) can be used to test if the second bit of the $n$ number is a 1 (because 2 has a binary value of 00000010 for the low 8 bits), regardless of the other bits in $n$. Used as a "mask", and($n$,15) returns the lowest four bits of $n$ (because 15 is 00001111 in binary), discarding all higher bits. Note that this function only works on integer numbers, and ODBscript uses 32-bit integers. To use this function on characters, see the ord( ) function; or to convert the result to a character, see the $asc( ) function.

char (string, characters)

Char( ) returns the character position in "string" (counting the first character as 1) of the first occurrence of any one of the characters in the "characters" argument. Returns 0 if there are no such characters in the string.

clock ( )

Clock( ) returns the number of CPU seconds used by the ODBscript program up to that point in the script. You can use this function to see how much CPU time is being used by a script, and it's particularly useful when you are trying to improve the efficiency of a script. (Note that if your database uses an external server, such as SQL Server or MySQL, you will only be timing ODBscript itself and the ODBC DLL routines that it uses, not the CPU time used by the server.)

cos (angle)

Cos( ) returns the trigonometric cosine of the given angle (measured in radians; radians = (degrees/180) * 3.1416).

createDir (directory)

This function will create a new directory, or a subdirectory if the first part of the "directory" is an existing directory path. This function returns a 1 ("true") if the directory was successfully created or a 0 ("false") if the directory could not be created. This function could be used in an IF statement, but if you do not need to test the result, you can use it in a SET statement and ignore the returned result. You might also use it with the $if( ) function. If the creation fails, the file system error message will be set in variable $file_error$.

createFile (filename)

This function will create a new file. This function returns a 1 ("true") if the file was successfully created or a 0 ("false") if the file could not be created. (Note that you do not need to use this function to create an ODBscript output file; the OUTPUT command automatically creates files if they do not already exist.) This function could be used in an IF statement, but if you do not need to test the result, you can use it in a SET statement and ignore the returned result. You might also use it with the $if( ) function. If the creation fails, the file system error message will be set in variable $file_error$.

Examples:

1.  <% IF createFile($filename$) %>
        File $filename$ created.
    <% ELSE %>
        ERROR creating $filename$. The error was: $file_error$
    <% ENDIF %>

2.  <% SET stat=createFile($filename$) %>

3.  File $filename$ $if(createFile($filename$), "created", "not created")

decr (variable), decrAfter(variable)

Decr( ) and decrAfter( ) decrement (subtract 1 from) the current value of the specified variable, similar to <% SET variable = $variable$ - 1 %> and referencing the variable either before or after the subtraction. (See incr( ) below for incrementing functions.) The specified variable must be an existing variable, and only the name of the variable should be given, not enclosed in "$" characters. The decr( ) function decrements the variable's value before returning it (i.e., it returns the current value minus 1), while decrAfter( ) returns the current value and then decrements the variable. Both functions reset the variable to the new decremented value. These functions are simply conveniences, useful for "counter" variables to automatically decrement them when they are used, without needing a SET statement.

Example: The following loop is executed 10 times, automatically decrementing "n" each time it is referenced in the WHILE test condition. (Note that "n" is initialized to 10, so the first use of decr( ) will return 9. Within the loop, $n$ will be 9 on the first loop and 0 on the last loop.)

    <% SET n = 10 %>
    <% WHILE decr(n) >= 0 %>
        N is now $n$ ...
    <% ENDWHILE %>

deleteFile (filename)

This function will delete (remove from the system) the specified file, if it exists. This function returns a 1 ("true") if the file was deleted or a 0 ("false") if the file did not exist or could not be deleted (e.g. if it is open to another program). This function could be used in an IF statement, but if you do not need to test the result, you can use it in a SET statement and ignore the returned result. You might also use it with the $if( ) function. If the delete fails, the file system error message will be set in variable $file_error$.

Examples:

1.  <% IF deleteFile($filename$) %>
        File $filename$ deleted.
    <% ELSE %>
        ERROR deleting $filename$. The error was: $file_error$
    <% ENDIF %>

2.  <% SET stat=deleteFile($filename$) %>

3.  File $filename$ $if(deleteFile($filename$), "deleted", "not deleted")

exp (number)

Exp( ) returns the exponential value of the given number (i.e., e raised to the power of the input number).

fileExists(filename)

This function (which would typically be used in an IF statement) returns a 1 ("true") if the specified file already exists on the system, or a 0 ("false") if the file does not exist.

Example:

    <% IF fileExists($filename$) %>
        File $filename$ already exists.
    <% ELSE %>
        File $filename$ does not exist.
    <% ENDIF %>

incr (variable), incrAfter(variable)

Incr( ) and incrAfter( ) increment (add 1 to) the current value of the specified variable, similar to <% SET variable = $variable$ + 1 %> and referencing the variable either before or after the subtraction. (See decr( ) above for decrementing functions.) The specified variable must be an existing variable, and only the name of the variable should be given, not enclosed in "$" characters. The incr( ) function increments the variable's value before returning it (i.e., it returns the current value plus 1), while incrAfter( ) returns the current value and then increments the variable. Both functions reset the variable to the new incremented value. These functions are simply conveniences, useful for "counter" variables to automatically increment them when they are used, without needing a SET statement.

Example: The following loop is executed 10 times, automatically incrementing "n" each time it is referenced in the WHILE test condition:

    <% SET n = 0 %>
    <% WHILE incr(n) <= 10 %>
        Line $n$ ...
    <% ENDWHILE %>

int (number)

Int( ) forces the given numeric argument to be an integer (a whole number). Any fractional part of the number is discarded. (Use the round(number, 1) function to round a number to the nearest integer.)

isAlpha (string)

IsAplha( ) returns 1 (or "true") if all of the characters in the given string are either alphabetic characters or spaces. Returns 0 (or "false") if there are any non-alphabetic characters in the string. (Function names are not case sensitive, but the capitalization shown is easier to read.)

isAlphaNum (string)

IsAlphaNum( ) returns 1 (or "true") if all of the characters in the given string are either alphabetic characters or digits. Returns 0 (or "false") if there are any non-alphanumeric characters in the string. (Function names are not case sensitive, but the capitalization shown is easier to read.)

isCreditCard (string)

This function returns a 1 (or "true") if the given string contains a valid Visa, Master Card, American Express, Discover, or Diner's Club/Carte Blanche credit card number. The number may include spaces and "-" characters, but they are not required. This function verifies the number format by checking the prefix digits (which denote the card type), the total number of digits (which depends on the type), and the "Luhn mod(10) check-digit". NOTE: Only the validity of the card number format is checked, not the status of the credit card account. This function returns a 0 (or "false") if the card type is not recognized, if it contains an improper number of digits, if it contains non-digit characters other than spaces or "-", or if the check-digit is incorrect. To determine the card type, you can use the $cardType( ) string function.

isNumber (string)

IsNumber( ) returns "1" (or "true") if all of the characters in the given string are either digit characters 0 through 9 or a decimal point ".", or (for the first character only) a plus or minus sign. Returns 0 (or "false") if there are any non-numeric characters in the string. (Function names are not case sensitive, but the capitalization shown is easier to read.)

len (string)

Len( ) returns the number of characters in the given string value.

log (number)

Log( ) returns the "natural" (base-e) logarithm of the given number.

log10 (number)

Log10( ) returns the base-10 logarithm of the given number.

match (string, pattern)

The match( ) function scans the specified string for any match with the given "regular expression" pattern. If any match is found, the value returned from match( ) is the character position, counting from 1, of the matching substring. The match( ) function can be used by itself in an IF statement (e.g., <% IF match(...) %> or <% IF NOT match(...) %>) as a test for pattern matching, or it can be used in a SET statement to assign the matched substring's position to another variable. The match( ) function is also useful as an argument for other functions. For example, the expression $left($string$, match($string$,pattern)-1) would return the substring in front of the matched substring. Remember that, like all functions, the subject character string and the pattern are both evaluated as "arithmetic/logic expressions", so it's usually necessary to put quotes (" ") around the pattern.

The regular expression "meta-characters" that are supported are:

^ Beginning of string (i.e. the following pattern must match the string starting at character number 1).
$ End of string (i.e. the preceding match must be at the end of string's value).
. Match any single character.
* Match zero or more occurrences of the preceding character or [...] character class.
? Match zero or one occurrence of the preceding character or [...] character class.
+ Match one or more occurrence of the preceding character or [...] character class.
[...] Match a single character to any one of the characters in the specified list (a "character class"), such as [ABC].
[a-z] Match a single character to any one of the characters between the two characters separated by "-", e.g. [0-9] would be any digit, or [A-Z] would be any uppercase alphabetic. You can include several pairs in the same list, such as [a-zA-Z0-9] to match any alpha-numeric character. You can mix character ranges with lists, such as [ABC0-9] to match "A", "B", "C", or any digit.
[^...] Match any character that is not specified in the list for the character class, such as [^a-zA-Z0-9] to match any non-alpha-numeric character.
{n} Match the preceding character or character class exactly "n" times, e.g. [0-9]{8} would match exactly eight digits.
{n,} Match the preceding character or character class "n" times or more, such as [0-9]{8,} to match eight or more digits.
{n,m} Match the preceding character or character class at least "n" times but no more than "m" times, such as [0-9]{8,10} to match eight, nine, or ten digits.
| Pattern "or" separator. Match either the preceding pattern completely or the following pattern completely. May be used multiple times.
\t The ASCII tab character.
\r The ASCII carriage-return character.
\n The ASCII linefeed ("new line") character.
\ "Escape", take the next character "literally" as part of the pattern, not as a special character. For example, \* means the asterisk is in the pattern to be matched, instead of the meaning shown above. Use \\ to specify the backslash itself.

Pattern Examples:

A standard US phone number has a three-digit area code, a three-digit exchange code, then four digits. But several different conventions are used for the format of a phone number, such as optional parentheses around the area code and hyphens or spaces between the groups. The following pattern will match any of the typical formats, while failing to match an invalid phone number:

    match($phone$, "^(?[0-9]{3})?[- ]?[0-9]{3}[- ]?[0-9]{4}$")
The pattern is given as a quoted string. The "^" as the first character means that the remainder of the pattern must match starting with the first character of the subject string. (Otherwise, a pattern can be matched anywhere within the string.) The next character, "(" is immediately followed by a "?" which specifies zero or one occurrence of the character (i.e., an optional character). Next, "[0-9]{3}" means that exactly three digits should be present. Then there is another optional ")". Following that, the specification "[- ]?" means that a single hyphen or space may or may not be present. Similarly, the rest of the pattern specifies a three-digit group followed by a four-digit group, perhaps with a hyphen or space between them. The last character of the pattern, "$", means that the end of the subject string is expected after the four-digit group, so this pattern will not match if extra characters or digits are entered. (Typically, your patterns used with the VALIDATE command will begin with "^" and end with "$", to exclude extraneous characters. If neither of these characters is given, then a matching substring may be found anywhere within the subject string, but you might use only one or the other to match only the beginning or the end of the string.) The pattern above will match any of the following phone number formats: (719) 555-1212, (719)555-1212, (719) 555 1212, 719-555-1212, 719 555-1212, 719 555 1212, 719 5551212, or 7195551212.

The following pattern could be used to validate that an e-mail address is of the general form "something@something.something". It checks that the initial character in each section is alpha-numeric, and that there is at least one more character (any character) in each section.

    match($email$, "[a-zA-Z0-9].+@[a-zA-Z0-9].+\.[a-zA-Z0-9].+")

max (number1, number2)

Returns the larger value of number1 or number2.

min (number1, number2)

Returns the smaller value of number1 or number2.

mod (number, mod)

Mod( ) returns the modulus of the given number (remainder after division by the given "mod" value).

or (number1, number2)

Or( ) returns the value of the "Boolean OR" (sometimes called "logical OR") bitwise function performed on the two given numbers. The Boolean OR operation tests the corresponding bits ("binary digits") of the two numbers and produces a result bit of 1 if either of the two corresponding bits are 1; otherwise the result bit is 0 only if the two corresponding bits are both 0. Boolean OR has one primary use: to set one or more specific bits to be 1 in a number, regardless of the current value. For example, if each bit represents a yes/no "flag", or( ) can be used to set bits to "yes". Or($n$,2) will set the second bit of the $n$ number to be a 1 (because 2 has a binary value of 00000010 for the low 8 bits), regardless of the current value of that bit. Note that this function only works on integer numbers, and ODBscript uses 32-bit integers. To use this function on characters, see the ord( ) function; or to convert the result to a character, see the $asc( ) function.

ord (string [,position])

Ord( ) returns the numeric character code for the character at the specified position in the given character string. The position argument can be omitted and it defaults to 1 (the first character in the string).

pos (string1, string2)

Pos( ) returns the character position in string1 (counting the first character as 1) of the first occurrence of string2. Returns 0 if string2 is not contained anywhere within string1.

rand (mod)

Rand( ) returns a pseudo-random number. Random numbers are in the range of 0 to 65535. The "mod" parameter is optional; if given, the random number will be divided by this number and the remainder will be returned. Therefore, to get a random number in the range of 0 to 9999, use rand(10000). (To get a random number in the range of 1 to 10000, use rand(10000)+1). (Also see the $rand( ) string function, which returns a random number as a character string; in an arithmetic expression, you can actually use either).

renameFile (filename, newfilename)

This function will rename the file "filename" to be "newfilename". The function returns 1 ("true") if the renaming was successful or 0 ("false") if the file could not be renamed (for example, if the filename does not exist or if renaming access is not allowed). The newfilename can include optional directory information, and the file will be moved to that directory. Otherwise, if just a filename is given, the file will be renamed on its current directory. If the renaming fails, the file system error message will be set in variable $file_error$.

Examples:

1.  <% IF renameFile($upload_filename$, $filename$) %>
        Upload file $upload_filename$ was renamed to $filename$.
    <% ELSE %>
        ERROR renaming $upload_filename$ to $filename$. $file_error$
    <% ENDIF %>

2.  <% SET stat=renameFile($upload_filename$, $filename$) %>

3.  File $upload_filename$
    $if(renameFile($upload_filename$, $filename$), "renamed", "NOT renamed")
    to $filename$.

round (number, factor)

This function rounds the given numeric argument to the nearest whole multiple of the given "factor". For example, round($var$, 0.01) would round to the nearest hundredths, and round($var$, 1) would round to the nearest whole number. (Note that this is different from some common rounding functions in that the "factor" is not the number of fractional digits to round to; it is the unit to round to. This allows more flexibility, such as rounding to the nearest quarter by using "0.25" as the factor, rounding to the nearest hundred by using "100", or to the nearest "K" with a factor of "1024".)

sin (angle)

Sin( :) returns the trigonometric sine of the given angle (measured in radians; radians = (degrees/180) * 3.1416).

tan (angle)

Tan ( ) returns the trigonometric tangent of the given angle (measured in radians; radians = (degrees/180) * 3.1416).

xor (number1, number2)

Xor( ) returns the value of the "Boolean exclusive-or" (sometimes called "logical exclusive-or") bitwise function performed on the two given numbers. The Boolean XOR operation tests the corresponding bits ("binary digits") of the two numbers and produces a result bit of 1 if either one, but only 1, of the two corresponding bits is a 1; otherwise the result bit is 0 if the two corresponding bits are both 0 or both 1. When used with "bit flags" stored in a single number, the xor( ) function can be used to reverse the current value of specific bits, without changing other bits. For example, xor($n$,2) reverses the second lowest bit while leaving all other bits as they were. (See the and( ) and or( ) functions for examples of setting and testing bit flags.) Boolean XOR has many other interesting and useful properties, such as: if c=xor(a,b), then a=xor(c,b) and b=xor(c,a). (This property is sometimes used for encryption, since "a" can be extracted from "c" if and only if "b" is known. The principle works for any number of numbers; say, if you XOR three numbers together, you can extract any one of them if you know the other two. This principle is used in RAID disk drive technology to allow a single disk to back up several others: If any disk fails, its data can be recovered by XORing all the remaining drives with the backup drive.) Note that this function only works on integer numbers, and ODBscript uses 32-bit integers. To use this function on characters, see the ord( ) function; or to convert the result to a character, see the $asc( ) function.


 

Predefined Variables

Following is a list of predefined variables in ODBscript. The first table lists variables that are set by ODBscript and may be used like any other variable. The second table lists variables that can be input to ODBscript to cause special processing. The third table lists variables that you can set in a script to control subsequent formatting. (For example, see the
TABLE and FORM commands.)

Variables Set by ODBscript

date_shortCurrent date in the format MM-DD-YYYY, where "MM" is the number of the current month, "DD" is the number of the day, and "YYYY" is the four-digit year
date_ymdCurrent date in the format YYYYMMDD, where "YYYY" is the four-digit year, "MM" is the number of the current month, and "DD" is the number of the day
date_y_m_dCurrent date in the format YYYY-MM-DD, where "YYYY" is the four-digit year, "MM" is the number of the current month, and "DD" is the number of the day
dayDay number in current month, one or two digits (Use $format("0#", $day$) to force two digits)
file_is_dirInside an EACHFILE loop, a value of 1 indicates that the current file is a subdirectory, and 0 indicates that it is an ordinary file.
file_dateInside an EACHFILE loop, the date that the current file was last written to.
file_nameInside an EACHFILE loop, the current file name (without directory information).
file_sizeInside an EACHFILE loop, the size of the current file in bytes.
http_cookieHTTP cookie string input by browser. All cookies sent are in this string in the form of "name=value" with multiple cookies separated by semi-colons. (Each cookie is also set up as a named variable, so this string is not required to use cookies.)
http_refererThe URL of the document that was used to invoke ODBscript. This variable is typically not set by the browser for a bookmark link or a locally loaded page.
http_responseThe status response (the first response header) of an HTTPGET or HTTPPOST request.
http_headersAll response headers, after the first one (which is in http_response) from an HTTPGET or HTTPPOST request. The multiple headers in this variable are separated by their original "newline" ($asc(10)) characters.
importrowCurrent input line number in an IMPORT loop
input_variableCurrent input CGI variable name in an EACHINPUT loop
input_valueValue of CGI variable ($input_variable$ above) in an EACHINPUT loop
monthCurrent month, one or two digits. (Use $format("0#", $month$) to force two digits)
monthnameFull name of current month (e.g., "September")
multirowCurrent variable number in an EACHMULTI loop
odbic_errorThe text of the last ODBscript error message that was generated. May be tested (e.g., <% IF $odbic_error$ %>) to check for errors following commands such as SENDMAIL.
path_infoAny "extra path" directory information after the "odb.exe" in the URL that invoked ODBscript. When ODBscript is run as a CGI, this should be the script file. (Example: if the URL was "http://www.yourdomain.com/scripts/odb.exe/your_dir/script1.odb" then "path_info" contains "/your_dir/script1.odb" and the input script file is expected to be "script1.odb" on subdirectory "your_dir".) If the invoking URL does not specify this "path_info", then a variable named "script" must be passed in to ODBscript to name the script file
path_info_dirThe directory specified in path_info (i.e., path_info with the script file name removed). (See also the $pathInfo( ) function, which produces file paths relative to this directory.)
path_translatedIf any directory information is provided after the odb.exe URL (i.e., any "path_info"), then this is the full file system directory path after it has been "mapped" by the Web server
path_translated_dirThe directory specified in path_translated (i.e., path_translated with the script file name removed). (See also the $pathTranslated( ) function, which produces file paths relative to this directory.)
query_stringAny data following a "?" in the URL that was used to invoke ODBscript. (Any "variable=value" pairs in this string will already be set up, but you can use $query_string$ directly if you do not use that format; for example, you might use "/cgi-bin/odb.exe/script.odb?command" to pass a single command word in the query string. Everything following the "?" will be in $query_string$)
remote_addrInternet numeric address (nnn.nnn.nnn.nnn) that the user is running on
remote_hostHost that the user is running on (may be node name, but commonly is numeric Internet address)
rowCurrent result row number after a SELECT statement
rows_affectedNumber of rows affected by an INSERT, UPDATE or DELETE SQL statement
script_nameThe path to the odb.exe CGI program (e.g., "/scripts/odb.exe") from the invoking URL. (Useful for creating forms in the script file that will invoke ODBscript, rather than "hard-coding" the URL.)
server_nameInternet node name of the host system (i.e., the system that ODBscript is running on)
sql_errorError message returned by ODBC driver after SQL execution (or may say "No rows selected" after a valid SELECT, or "### rows affected" after a valid INSERT, UPDATE or DELETE)
sql_statementThe last executed SQL statement, with all variables expanded
sql_statusThe status of the SQL operation (interpretation depends on operation): -2 = no rows selected/affected; -1 = SQL execution error; 0 = SELECT or DDL succeeded; 1 = one or more rows affected by INSERT, UPDATE, or DELETE.
timeCurrent 12-hour clock time in the format HH:MMam or HH:MMpm, where "HH" is the hour and "MM" is the minute
time_hmsCurrent 12-hour clock time in the format HH:MM:SSam or HH:MM:SSpm, where "HH" is the hour, "MM" is the minute, and "SS" is the seconds
time24Current 24-hour clock time in the format HH:MM, where "HH" is the hour and "MM" is the minute
time24_hmsCurrent 24-hour clock time in the format HH:MM:SS, where "HH" is the hour, "MM" is the minute, and "SS" is the seconds
todayCurrent date in the format "Month DD, YYYY", where "Month" is the full name of the current month, "DD" is the one- or two-digit day of the month, and "YYYY" is the four-digit year
upload_name(where name is the name of the variable, not the name of a file, in an <INPUT TYPE="file" NAME="..."> tag) Unique name assigned to an uploaded file (usually a temporary name)
upload_name_size(where name is the name of the variable, not the name of a file, in an <INPUT TYPE="file" NAME="..."> tag) Size in bytes of an uploaded file
weekdayFull name of current day of week (e.g., "Monday")
yearCurrent year, four digits

Optional Variables Input to ODBscript

in_databaseODBC connection string (may be used instead of DATABASE command; required for "no script mode"). NOTE: This input string must be encrypted with the $sysEncrypt( ) function on the same system to which it is sent.
defaultSpecifies variable default values (like the DEFAULT command) in the format "variable=value [, variable=value, ...]"
eachrowFormatting to use for each result row (optional when no script file)
formatSpecifies variable formatting masks (like the FORMAT command) in the format "variable=mask [, variable=mask, ...]"
scriptscript file to process
max_uploadSpecifies the maximum file size, in bytes, for an uploaded file.
outputOutput file to write (i.e., output is sent to this file instead of back to the user's browser)
path_infoAny "extra path" data following "odb.exe" in the URL used to invoke ODBscript (normally set by CGI interface but provided as an input in case your server does not set properly). This should be the script file
path_translatedFull file system directory path after "path_info" has been "mapped" by your Web server (normally set by CGI interface but provided as an input in case your server does not set properly)
script_nameCGI path program name, (e.g., "/scripts/odb.exe") (normally set by CGI interface but provided as an input in case your server does not set properly)
in_sqlSQL statement to execute (required for "no script mode"). NOTE: This input string must be encrypted with the $sysEncrypt( ) function on the same system to which it is sent.
sql_footerText to output following the "in_sql" statement execution and "eachrow" result formatting (optional for "no script mode")
sql_headerText to be output before executing the "sql" statement (optional for "no script mode")
sql_titleText to use in the HTML TITLE command (optional for "no script mode")
traceTurns on TRACE mode when the passed value is set to "on".
translateSpecifies a translation table for a variable (like the TRANSLATE command) in the format "variable_name value=newvalue [, value=newvalue, ...]"
upload_dirSpecifies the directory on the host system to receive an uploaded file.
upload_prefixSpecifies the file name prefix to use for an uploaded file. (The actual file name will have a unique number added.)

Format Control Variables

table_fontAny HTML parameters for a <FONT> tag (e.g., FACE, COLOR, SIZE) to be added to data cells output by the TABLE command. (No default.)
table_th_fontAny HTML parameters for a <FONT> tag (e.g., FACE, COLOR, SIZE) to be added to the table headers output by the TABLE command. (Defaults to table_font, if that is defined.)
table_tdAny HTML parameters for the <TD> tags (e.g., BGCOLOR, ALIGN) for the table column data output by the TABLE command. (No default.)
table_thAny HTML parameters for the <TH> tags (e.g., BGCOLOR, ALIGN) for the table column headers output by the TABLE command. (No default.)
table_trAny HTML parameters for the <TR> tags (e.g., BGCOLOR, ALIGN) for the table rows output by the TABLE command. (No default.)
form_fontAny HTML parameters for a <FONT> tag (e.g., FACE, COLOR, SIZE) to be added to all prompt labels output by the FORM, UPDATEFORM, and INSERTFORM commands. (No default.)
form_prompt_tdAny HTML parameters for the <TD> tags (e.g., BGCOLOR, ALIGN) for the prompt labels output by the FORM, UPDATEFORM, and INSERTFORM commands. (Default: "align=right".)
form_value_tdAny HTML parameters for the <TD> tags (e.g., BGCOLOR, ALIGN) for the input fields output by the FORM, UPDATEFORM, and INSERTFORM commands. (No default.)
form_tableAny HTML parameters for the <TABLE> tag (e.g., WIDTH, BGCOLOR) output by the FORM, UPDATEFORM, and INSERTFORM commands. (No default.)
form_trAny HTML parameters for the <TR> tags (e.g., BGCOLOR, ALIGN) for the table rows output by the FORM, UPDATEFORM, and INSERTFORM commands. (No default.)


File Uploading

Uploading files from a Web browser is accomplished with a special type of HTML input form, so it does not require any special commands in ODBscript. However, handling the uploaded file (e.g., giving the file the desired name on the host system) will usually require some processing in a script. Like ordinary input forms, these upload forms can have an ACTION="..." specification to execute ODBscript , including a script file name, and this script can deal with the uploaded file as appropriate for your application.

Some file upload parameters can be passed directly in this HTML form (e.g. , as hidden input fields in the form), but to address certain security issues, you can define uploading options, limits, and restrictions in a special file named "odb_upload.ini", which is normally placed on the CGI directory (see below).

Browser uploading is implemented through the use of the HTML form type < FORM ENCTYPE="multipart/form-data">. This form should have at least one input field with a type of <INPUT TYPE="file" ...>. Multiple files may be uploaded in the same form by having multiple TYPE="file" input fields. There is an example of a file-uploading form, named uploadf.htm, in the EXAMPLE.ZIP file.

The file data is actually saved to disk before executing the script. Files can be uploaded to any directory for which your CGI programs have "read" and "write" access privileges, but the specific directory must be specified. The upload directory (i.e., the receiving directory on your host system) can be set in a variable named "upload_dir" that is passed in the form itself, or it can be set in the "odb_upload.ini" file. For example, you might code this variable in the form as an <INPUT TYPE="hidden" NAME="upload_dir" VALUE="..."> field, or perhaps you might give the user a "pull-down" selection list, as in the example form. You could also allow the user to enter the directory in a normal INPUT field named "upload_dir", but that could create some obvious security problems. In the "odb_upload.ini" file, you can simply have a line that says something like "upload_dir=..." (where the value after the "=" is your upload directory). If an "upload_dir" is specified in the "odb_upload.ini" file, then that variable will be ignored in the form input.

As noted, files can be uploaded to any directory for which your CGI programs have "read" and "write" access privileges, so you don't necessarily need to upload to a Web server document directory (unless, of course, you want to make the files available for later downloading through the Web). Typically, you should use a special directory, used only for uploading, to make the uploaded files more manageable.

If you need to upload to several directories, but don't want the process to be allowed to upload to all accessible directories, you can use the "odb_upload.ini" file to specify which directories are allowed for uploading. This is done by specifying one or more "allowed_dir=..." lines in the file, where each line specifies a directory where uploads are allowed. You can then have different upload directories specified in the upload forms, without worrying that a form might be modified to upload to specify a directory that you don't want to allow: If an "upload_dir" is specified in the form that isn't also specified as an "allowed_dir" in the INI file, then the upload will not be processed.

An uploaded file does not initially have the same name as the original file on the user's system. (Doing so would potentially create a conflict with an existing file of the same name on the host.) Instead, ODBscript always creates a file with an arbitrary, unique name to receive the uploaded file data. Optionally, the input form data can specify a variable named "upload_prefix" and the uploaded file names will have this prefix plus a unique number. The "upload_prefix" defaults to "upload", so file names would be "upload1", "upload2", etc. In the script, there will be a variable set to be the unique name that was actually given to the uploaded file and also a variable set to the original file name on the user's system, and the script can use these names as appropriate for your application.

For example, if you use this functionality to allow users to upload HTML files to their own Web directories, you will probably want to rename the upload files to be the same as the original files on the user's system. ODBscript sets the user's original file name in the variable named by the file upload tag itself. For example, if the tag is <INPUT TYPE="file" NAME="filename"> then the variable $filename$ will contain the original file name. The unique file name created on the host (with the upload directory path) is then set in a variable with the prefix "upload_" plus this same tag name (e.g., in this case, $upload_filename$). ODBscript has a function that will allow you do the needed renaming: renameFile($upload_filename$, $filename$). There is also a function called fileExists($filename$) that will allow you to test for the existence of a given file, which you should use before attempting the renaming. (If such a file already exists, the renaming attempt will fail.) Optionally, you might want to delete any previous file with the same name, so there is also a deleteFile($filename$) function.

On the other hand, if you allowed users to upload graphic files that you want to be associated with database entries that are made in the same form, and all these files are stored on the same directory, you might run into name conflicts if you try to use the original names. In this case, you may not want to rename the uploaded file, but instead keep the unique name assigned by the upload. That is, you could just insert the created file name into the database with the other data, and then use that name in any links to the image file when you later display the data in an HTML page.

Another possibility is that the script could use the uploaded data immediately in some manner and then delete the upload file. For example, if the uploaded file is attached to an e-mail, then you will probably want to delete it after sending the e-mail. Or, the file could contain some data that the script is to operate on (e.g., with an IMPORT command), and then the file could be deleted.

The odb_upload.ini File

You can install a file named odb_upload.ini on your system to control certain file uploading parameters such as the maximum file size, the allowable upload directories, and the allowable upload file types. This is a security feature, so unless you really need unrestricted uploading access, using odb_upload.ini is strongly recommended.

When uploading a file, ODBscript will look for this control file on the "current working directory" (i.e., it will attempt to open the file without specifying any directory). This working directory is set up by the Web server when executing CGI programs, and it will usually be either the URL "root" directory of your Web site, or possibly the CGI directory itself. However, your Web server may set some other directory (such as the server's own base directory), so this may require some experimentation to get correct. One quick way to determine the CGI working directory it to execute a test script containing the command <% EXEC DIR %>, which will produce a listing of the working directory (because no other directory is specified), with the name of that directory at the top of the listing. To test that you have correctly identified the working directory, you can put a test file on that directory to output a message (e.g., "<HTML> Hello" is enough), and then try a URL that executes odb.exe passing that file name as an input named "script" (e.g., your domain and CGI path followed by "odb.exe?script=testfile"). If the "script" input does not provide a file path, ODBscript will try to open it on the current working, so if your test file works, you can put odb_upload.ini on that same directory.

The lines in this odb_upload.ine file are in the form of "variable = value" (with spaces and tabs ignored). Do not put any quotes around the values, and put each variable=value pair on a separate line. Any line that begins with an exclamation (!) is ignored as a comment line. The variables that you may use in this file are:

Because the "odb_upload.ini" can control access to your directories, it is the one file that ODBscript will never upload. That is, if you attempt to upload "odb_upload.ini", you will get an "Illegal file" error.

The Example Files

As mentioned, there is an HTML file included in EXAMPLE.ZIP, uploadf.htm, that shows an example of a file uploading form. The ACTION URL for the form links to odb.exe and specifies the script file uploadf.odb, which is also included in EXAMPLE.ZIP. This form and script implement a general purpose file uploading utility which you may find useful "as is", or you can customize them for your particular application.

Note in particular that the <FORM> declaration has a specification of ENCTYPE="multipart/form-data", which is required for any file uploading form. Also required is at least one <INPUT TYPE="file" ...> in the form body. This will create a standard INPUT text box in which the user can directly type a file path, but the browser will also add a "Browse" button so the user can find the file using a Windows directory browsing function (similar to that used by Notepad, for example) to locate the directory and highlight the desired file.

The file-type INPUT must specify a NAME="...", which can be anything. When the ACTION script is executed, a variable with this name will contain the original file name (without any directory information). For example, uploadf.htm has <INPUT TYPE="file" NAME="filename">, so in the script uploadf.odb, variable $filename$ will contain the original file name. You can have multiple TYPE="file" input fields in your form; in this case, you can use a different NAME for each, or you could use the same NAME for all of them and then process these with an EACHMULTI loop.

As noted above, when a file is first uploaded, it does not have the original file name. Instead, uploaded files are given a unique, arbitrary file name. The default for this name is "upload" plus a unique number (i.e., a number that is currently unused by any file on the upload directory). In your input form, you can provide a hidden input NAME="upload_prefix" with a VALUE that specifies a different name prefix. In the ACTION script, the actual uploaded file name (with directory path) will be preset in a variable named "upload_" plus the variable NAME used in the TYPE="file" input. For example, in the case of the uploadf.htm form which has an <INPUT TYPE="file" NAME="filename">, when the script uploadf.odb is executed, the variable $upload_filename$ will contain the actual name of the uploaded file and $filename$ will contain the original file name. (As another example, if you were to use <INPUT TYPE="file" NAME="imagefile">, then $imagefile$ and $upload_imagefile$ would contain the original file name and the uploaded file name, respectively.) There is another variable set using this input variable name, upload_name_size (e.g., for the two previous examples, upload_filename_size or upload_imagefile_size), which will be set to the uploaded file size, in bytes.

The uploading process needs to know where to put the file on the server system, so you must provide an input variable named "upload_dir" to specify this directory. In uploadf.htm, "upload_dir" is implemented as a SELECT choice list, which you can edit to be a list of the upload directories you want to use on your system. If you want to always upload to a fixed directory, you can omit the SELECT list and define "upload_dir" as a TYPE="hidden" input. (You could also use a standard TYPE="text" input if you want to allow the user to specify any directory, but that's obviously risky.) Or, you can specify "upload_dir = ..." in the "odb_upload.ini" file, and all uploads will go to that directory. If "upload_dir" is not defined by one of these methods, the upload will fail.

Note that in the script, you can move a file to a different directory with the renameFile( ) function. Therefore, the "upload_dir" directory is not necessarily the final destination for the file. So, you may prefer to always upload to a fixed directory, then deal with the final destination by the renaming that you do in the script.

The maximum size of an uploaded file can be controlled with an optional input variable named "max_upload", which can be set in the upload form or in the "odb_upload.ini" file. (If "max_upload" is set in the INI file, then it will be ignored if passed in the form.) In the script uploadf.htm, a hidden input is used to specify a value of 1,000,000. You can edit (or omit) this value to suit your application. As noted above, there is a variable set to be the actual size of the uploaded file: upload_name_size (where name is the NAME parameter of the <INPUT> tag). Note that this file size might be 0, which might be because the original file is actually empty, but it also might be because the specified file did not exist on the user's system (which can happen if the user types in a file name rather than browsing to find the file). Browsers do not indicate this error condition in the upload process -- they simply send an empty file -- so you may want to warn the user of this possible error, as is done in the sample script.

The input form in uploadf.htm has some other variables that are used in script uploadf.odb to implement a general-purpose upload utility. Note that these variables are used ONLY by the script, and not by ODBscript itself, so you may want to modify these for your implementation. One of these is <INPUT NAME="host_filename"> which the script uses (if the form user enters a value) to rename the uploaded file. This allows giving the uploaded file a name that is different from the original file on the user's system. Otherwise, if this variable is not entered in the form, the script will rename the uploaded file to the original file name.

The form in uploadf.htm also has "radio" input variable named "exists_opt" which the script uploadf.odb uses to handle any previously existing file with the same name. The default is "new file", which means that the upload will NOT replace any existing file, and the upload will fail if the file already exists. But if the "overwrite" option is checked, the script will replace any existing file with the uploaded file. If the "save existing file.BAK" option is checked, the script will first rename any existing file, adding a ".bak" extension to its name, before renaming the uploaded file. This allows you to "recover" the original file using the form at the bottom of uploadf.htm. The "restore" function consists of deleting the current version of the file name, then renaming the ".bak" file to the original name.


 

Running ODBscript as a CGI Program

To run ODBscript as a CGI program, the executable file (odb.exe) must be installed on a "CGI directory". CGI directories are defined in your Web server's configuration file. CGI directories are generally created as subdirectories of the primary HTML directory (that is, the same root directory as your Web pages), and they are commonly named something like "scripts", "cgi", or perhaps "cgi-bin". If you already have such a directory defined, then simply copy odb.exe there. If you do not already have such a directory, you will need to check your Web server's documentation for configuration details.

With a properly defined CGI directory, your Web server will automatically recognize CGI programs when this directory is specified in a URL. Like the URL for a Web page, a CGI URL should omit the primary HTML directory. For example, if you have a Web page named "pagex.html" and your primary HTML directory is defined in your server's configuration file to be "httpfile", then the directory path to the file would be "\httpfile\pages.html". However, the URL would be something like "http://www.yourdomain.com/pagex.html" because your server expects that all HTML files will be on the "httpfile" directory. Similarly, if your CGI directory is "\httpfile\scripts" and ODBscript has been installed there, then the URL would be "http://www.yourdomain.com/scripts/odb.exe".

There are two ways that CGI programs may be referenced from an HTML document. Perhaps the most common is as the ACTION function of a FORM declaration, such as:

    <FORM METHOD="post" ACTION="http://www.yourdomain.com/scripts/odb.exe">
(Note that ODBscript will also work with METHOD="get", but the "get" method has limitations on the number of bytes of data that may be passed to the program.)

All of the INPUT fields in the FORM declaration will be passed in to ODBscript as named variables; see the ODBscript Variables section.

The second method of invoking a CGI program from an HTML document is as an ordinary URL in an "anchor" link (that is, the HTML "A" command). In this case, HTML allows variables to be included in the link by placing a question mark (?) immediately at the end of the URL and adding a "variable=value" specification. Additional "variable=value" pairs may be added to this by separating them with an ampersand (&) character. (Note, however, that certain "special" characters are not allowed in URLs and must be represented by codes. Spaces are not allowed, and the convention is to use the plus sign (+) as the code for a space. Other special characters are encoding by using a percent sign (%) followed by the two-digit ASCII hex code for the character.) In ODBscript, variables that are passed in with the URL are decoded for special characters, but after that they are treated the same as FORM INPUT variables.

If you are creating an anchor link in ODBscript script file, then you can use the $url( ) string function to encode a variable so that it may be passed in a URL.


 

Running ODBscript from the Command Prompt

You can run ODBscript from the DOS command line prompt and write the output to an HTML file on disk. If you do not need "real time" access to your database (for example, if the data does not change often), then using this method will avoid CGI and database overhead for every page access. Or, if your Web pages are on your Internet Service Provider's host machine and you cannot install CGI programs and databases on that host, then you can generate your pages from a database on your PC and upload the generated HTML. Also, you can use the Windows Schedule server (which you will find in the Services window) to run ODBscript on at regular timed intervals.

It's important to note that ODBscript only runs as a "console" type program -- not as a pure Windows program. The main significance of this is that if you simply double-click the program file name in a folder listing, the program will be executed in a Command Prompt window, but since no input file can be specified this way, odb.exe will immediately display an error and quit, closing the window. (This usually happens too fast to even read the error message.) So, you need to either open a Command Prompt window first (which is usually found in the Start > Programs > Accessories menu), so you can specify the input script in the run command, or you can use the Windows "Run..." function from the Start menu (which also allows typing in the necessary input script specification).

Also note that on Windows XP systems, offline usage requires using the Program Compatibility Wizard to set the program to run in Windows 95 mode with "visual themes" disabled.

To use this mode, the odb.exe program file can be on any directory. Run ODBscript as you would any DOS program -- from the MS-DOS prompt or from the Windows "Run..." box. Following the program name (ODBscript) in the run command, you must specify an input file (the script) with a "-i" prefix and an output file (the generated HTML) with a "-o" prefix. (The file name may be placed immediately after the "-i" or "-o", with no spaces, or you may place a space between "-i" or "-o" and the filename.) Unless these files are on the current working directory, you will also need to specify directory paths for ODBscript and the files, such as:

    \httpfile\scripts\ODBscript -i \httpfile\script.odb -o \httpfile\pagex.odb
You can also pass variables into ODBscript on the command line. Following the input and output file specifications, you can specify any necessary "variable=value" pairs. For example, if the SQL statement in the script file is something like, "SELECT * FROM items WHERE category = $cat$", then you can say "cat=widgets" in the ODBscript run command to give the $cat$ variable a value. Important Note: If there are any spaces in either the variable name or the value, then you must enclose the entire "variable=value" specification inside of double-quote marks, such as "name=Joe Smith". (Otherwise, DOS will not interpret the variable declaration as a single argument.) If neither the variable nor its value contain any spaces, you can omit the double-quotes. If you need to specify several "variable=value" pairs, separate them from each other in the run command by spaces.

If an output file is specified, then the file will be created if it does not already exist; otherwise, the existing file will be over-written. If your input script contains an OUTPUT command, then that command will override any output file specified with the -o option. If no output file is specified when ODBscript is run from the command prompt (either with the "-o" option or an OUTPUT command in your script), then the output will be written to your screen.


 

Using ODBscript Without a Script File

You can get ODBscript to execute an SQL statement and do some simple formatting without a script file. To do this, you will need to specify some required input variables, and you may optionally use some others. (Refer to the section Predefined Variables, in the "Optional Variables Input" table.)

If ODBscript in not given a script file to process, it will first look for a file named "default.odb" on the "current working directory" (see below). An example of such a file in included in the distribution ZIP file, and you may customize this script for your application. If ODBscript finds this default.odb file, it will be used as the script; otherwise ODBscript will use an internally defined default script which is similar to the example.

In the <FORM> that you use to execute the "no script mode", you can define certain hidden input variables (e.g., <INPUT TYPE="hidden" NAME="var" VALUE="value"<) to control the processing. For the supplied default.odb script and the internally defined script, the minimum required input variables are "in_database", which defines the ODBC connection, and "in_sql", which defines an SQL statement to execute.

Important Note: For security, the input variables "in_database" and "in_sql" must be encrypted using the $sysEncrypt( ) function on the same server that they will be executed. For example, when you output a form to the user's browser containing these hidden inputs, you should use VALUE="$sysEncrypt('...')" instead of directly passing the database connection string and the SQL statement. Since encryption is required for these two special input variables, they will always be decrypted, automatically, before processing the script, so you should not use $sysDecrypt$( ) when you reference $in_database$ and $in_sql$ in your default.odb script.

You could use, for example, something like this in a form:

  <INPUT NAME="in_sql" TYPE="hidden"  VALUE="$sysEncrypt("INSERT INTO ...")">
However, since the SQL statements can be rather long, there is a problem with putting the $sysEncrypt("...") directly in the output form like that: Remember that for all function references used directly in the output text, the entire list of function arguments must be on a single line, or you will get a "missing right parenthesis" error. The SET command, however, does not have that limitation -- the function argument list and quoted strings used as function arguments can be continued on one or more lines -- so the easiest way to avoid that problem is to first set a variable to be the encrypted SQL statement and then use VALUE="$variable$" as the value of the form's <INPUT> tag.

Here, then, in an example of a "no template mode" form that insert a user's name and e-mail address into a table named Email. Note that the $sysEncrypt( ) arguments are given as quoted strings, so the variable references $UserName$ and $UserEmail$ will not be "de-reference" in those strings. (They will de-reference to be the user's input when the form is submitted.) Important: Also note that the VALUE="..." parts of the <INPUT> tags use double-quoted values, not single-quoted (apostrophe) values. This is because the apostrophe is a possible character in the encrypted string, which will cause browsers to cut the value short if VALUE='...' is used, but the double-quote character is not a possible encryption character.

  <%
  SET in_database=$sysEncrypt("DSN=MyData;UID=Admin");
  SET in_sql=$sysEncrypt("INSERT INTO Email (UserName, UserEmail) 
                          VALUES('$UserName$','$UserEmail$')");
  %>
  <FORM ACTION="/cgi-bin/odb.exe" METHOD="post">
  Your Name: <INPUT NAME="UserName" TYPE="text" SIZE="40"><BR>
  Your E-mail: <INPUT NAME="UserEmail" TYPE="text" SIZE="40"><BR>
  <INPUT TYPE="submit" VALUE="Add your e-mail"><BR>
  <INPUT NAME="in_database" TYPE="hidden" VALUE="$in_database$">
  <INPUT NAME="in_sql" TYPE="hidden" VALUE="$in_sql$">
  </FORM>

If you use only these variables, then ODBscript will execute the SQL and format the results using some defaults. The default page formatting will include a page title of "SQL Result". If the SQL statement is a SELECT, then all the results will be displayed using a TABLE command. For INSERT, UPDATE, and DELETE statements, the number of rows affected will be displayed. If an SQL execution error is detected, then the ODBC error message will be displayed.

You may optionally define the variable "sql_title" and it will be used as the Web page title (that is, in an HTML TITLE command, to be shown at the top of the browser window).

You may optionally define the variable "sql_header" and it will be inserted into the output before executing the SQL command. (Like all variables, $sql_header$ may include other variable references, such as $sql_statement$, $sql_title$, or other input variables from the form.)

You may optionally define the variable "eachrow" which will be used like the text in an EACHROW command to format each of the result rows from a SELECT statement.

You may optionally define the variable "sql_footer" which will be inserted into the output following the SQL execution and the result formatting.

You may also define any of the other variables shown in the "Optional Variables Input" table.

If you wish to use the default.odb (or your own customized version), you must install it on the "current working directory" that ODBscript will see when it runs. Unfortunately, this varies between different Web server products. Some will use the URL "root" directory of your Web site, whereas others will set the working directory for CGIs to be the CGI directory itself, and still other servers may use their own working directory. This may require some experimentation to get correct. One quick way to determine the CGI working directory it to execute a test script containing the command <% EXEC DIR %>, which will produce a listing of the working directory (because no other directory is specified), with the name of that directory at the top of the listing.

You can customize default.odb anyway you like. For example, you can use your standard site HTML page layout and formatting. You might also add SQL error logging to a disk file (using OUTPUT ... APPEND, or OPEN ... APPEND and WRITE) or you might e-mail the errors to a support person (using SENDMAIL). You could add your own standard input variables, such as a URL to REDIRECT to after the SQL execution. (If you use REDIRECT, make sure that your script doesn't produce any output, since REDIRECT won't work if you've already sent any HTML to the browser.)

Important Note: The example default.odb script has one feature that you may or may not wish to use: It will check to see if the form submitting the SQL statement was loaded from the same host system. This is done by checking the standard CGI request header HTTP_REFERER, which is the URL of the page submitting the form. If it does not match the current host name when ODBscript runs, the user will see an error message, "Input from foreign host is not allowed." This is a security feature, in addition to the encryption, to prevent "foreign" forms (e.g., edited forms on the user's PC) from executing SQL statements in your database. Unfortunately, some PC "firewall" products can suppress any outgoing HTTP_REFERER headers, so users running firewalls with that suppression enabled will not be able to execute "no script mode" unless you define a default.odb script that does not contain that checking, or you inform your users that they must disable that suppression in their firewalls. (Note that the internally defined default script does not have this checking.)


Copyright ©1997-2004, Roger Harris. All rights reserved.