HTMLEx |
Microsoft Internet Information Server and Microsoft Personal Web Server Version 2.17 (beta) HTMLExzoltanp@rijeka.riteh.hr Last updated: 07.12.1996. |
HTMLEx is an ISAPI Filter (DLL) for Microsoft's Internet Information Server running under Windows NT 3.51 or later (IIS in the following text), and Microsoft Personal Web Server running under Windows 95 (PWS in the following text). The use of this filter enhances the HTM pages with features such as: customizeable text and graphic counters, greeting messages with client's browser and host name, automatic generation of last update date/time values, inclusion of unlimited number of randomly generated URLs and/or images (eg. for ads) on the page, etc.: all of this on a per-page basis without writing a single line of CGI code! These features are configured by various sections of an INI file which has the same name and location as its corresponding HTM file, or using the HTMLEx key in registry. For each HTM file HTMLEx will also generate its own log file (also in Windows INI file compatible layout). If script language execution is enabled, the expanded form of HTM file is taken to be a special script file, which is interpreted by HTMLEx and the result of execution is than finally sent to client.
ISAPI (Internet Server API) filters are replaceable DLLs called by the Microsoft's WWW server (inetinfo.exe) on every HTTP request. During the DLLs registration process, the filter must tell the server in which type of notification is it interested, and subsequently the server will call the appropriate notification routine in the DLL, with all the date needed to process the request. The filter can add, delete, change or simply monitor the flow of this data. More than one filter can be chained in the processing of a HTTP request.
ISAPI filters have two entry points (exported functions):
GetFilterVersion
Exchanges version information with the server, and
requests notifications about events filter wants to process. The HTMLEx
filter is interested in following notifications:
These two notifications will be called regardless whether is it an unsecure or secure (SSL) HTTP transaction, and with default notification order (ie. following the order in which they appear in the \HKEY_LOCAL_MACHINE\...\W3SVC\Parameters\Filter DLLs key.). During this phase, global configuration parameters are read from the HTMLEx key (if present). Hard-coded defaults are used if the required value is not present there.
HttpFilterProc
Called two times during the HTTP request process:
If script execution is enabled, this expanded form is the program text for internal HTMLEx interpreter. The script is executed and output text is concatenated forming thus the final output buffer presented to client.
GetExtensionVersion
Identifies a DLL as an ISAPI extension, informs
the IIS about the implemented specification version and a short description.
HttpExtensionProc
The DLL entry point called by IIS when a .ztm file
is found in URL (see 9. and 4.). IIS prepares a data block called the
'Extension control block' which contains data about physical location
of the script about to be executed, as well as data gathered from
clients using the GET or POST methods. Using this information, a filter
context is generated (as well as necessary .INI, .LOG and .ERR file
names), and the HTMLExpand function is called. Data returned by the
script are transmitted to client using the WriteClient ISAPI function.
6.1. HTM Files
If the ExpandByDefault registry value is set to 1 (default), HTMLEx will
try to parse every HTM file before being sent to the client. In order to
disable this behavior (eg. for improved performance), insert the following
tag somewhere at the top of HTM file:
<!HTMLEx noexpand> (or <!---HTMLEx noexpand>)
According to HTML syntax, clients will interpret this as a comment, but HTMLEx will abort all processing (including the generation of INI and LOG files) as soon as this string (case sensitive!) is encountered.
As an alternative, if the ExpandByDefault registry value contains 0, no parsing/expanding will occur, unless the following tag is found near the top of file:
<!HTMLEx expand>
All HTMLEx tags are case sensitive strings with rather descriptive names, marked with a leading and trailing percent signs (%), eg.: %CurrentClientIPAddress%, %SERVER_SOFTWARE%, %LastFileUpdateDate% etc.
To have a single percent sign displayed in the client's browser, use the "null tag", which is %%.
If HTMLEx is used as a CGI script interpreter (in .ZTM files), the 'expand', 'noexpand', 'execute' and 'noexecute' have no effect, i.e. .ZTM files ARE ALWAYS EXPANDED AND EXECUTED! The 'nolog' option has also no effect in case of any HTMLEx script execution (.ZTM or .HTM).
Some HTML tag use a single % sign (e.g. <hr width=65%>). This can confuse HTMLEx - write <hr width=65%%> instead. This problem has been (I hope!) corrected in V1.04 |
In V1.06 and above, it is possible to change the tag start/end strings from % / % to something else, e.g. <!# / #!>. Use this feature to avoid confusion with server includes, if enabled! |
6.1.1. Server variable tags
Mostly for request debugging purposes, HTMLEx will recognize and expand
the following CGI variable tags into its values:
%SERVER_SOFTWARE% ... Microsoft-Internet-Information-Server/1.0 or Microsoft-Internet-Information-Server/2.0 or Microsoft-PWS-95/2.0 %CONTENT_LENGTH% ... 0 In .ZTM scripts: number of characters retrie- ved from the client if POST method was used, 0 if GET was used. %CONTENT_TYPE% ... null, or in .ZTM scripts: 'application/x-www-form-urlencoded' %GATEWAY_INTERFACE% ... CGI/1.1 %PATH_INFO% ... null In .ZTM scripts: name of the script as it appears in the URL, i.e. relative to the WWW server root %PATH_TRANSLATED% ... HTM file location on the server (drive:\path) %QUERY_STRING% ... null In .ZTM scripts: data sent by the client if the GET method was used, null if POST was used. %REMOTE_ADDR% ... clients IP address (numeric) %REMOTE_HOST% ... same as above %REMOTE_USER% ... null (valid only after authentication) %REQUEST_METHOD% ... GET (meaningless if not used in CGI scripts) In .ZTM scripts: GET or POST, depending on the method used to retrieve data from the client %SCRIPT_NAME% ... HTM file path as it appears in its URL %SERVER_NAME% ... servers IP address %SERVER_PORT% ... as configured, 80 by default %SERVER_PROTOCOL% ... HTTP/1.0 %HTTP_USER_AGENT% ... Mozilla/x.xx most of the time :) %HTTP_ACCEPT% ... MIME types client browser is able to handle %HTTP_REFERER% ... URL of the document from which the link led to this one, or <Unknown referer> if unknown %HTTP_COOKIE% ... Contains the cookie string sent in by the client If not empty, will be recorded in .LOG file This server variable contains all cookies received from the client in raw form. To extract a single cookie the GetCookie function should be used %HTTP_xxx% ... All other HTTP headers received from the client xxx stands for the header's name, where all - characters in have been changed to _
The value of these variables is captured during the transaction's HTTP_FILTER_URL_MAP phase, or in case of a .ZTM script they are retrieved using the GetServerVariable Extension control block member function.
6.1.2. Current access tags
Tags that apply to current connection between the client and server:
%CurrentCnt% ... Number of hits this page had received since its INI file was created (in plain text form) %CurrentGraphCnt% ... Same as above, but in graphical form. This tag creates a number (2-9, as given by the iDigitCount entry in INI file [Log] section) of <img src="X" alt="x"> URLs, where X is the appropriate string from the c0 to c9 entries in INI file [Digits] section. Defaults are /0.gif to /9.gif (unless changed by Digits section in registry) - meaning they have to be in server's home directory. %CurrentClientIPAddress% ... Same as %REMOTE_ADDR% %CurrentClientHost% ... If this tag is present, HTMLEx will try to do a reverse DNS lookup (get host name by its numeric address). This can be a time consuming process, which will stall the data transfer until done or the attempt times out. %CurrentClientBrowser% ... Same as %HTTP_USER_AGENT% %CurrentAccessDate% ... Current system date. All date values are formatted according to cDateFormat entry in LOG file [Log] section. Default is "%A, %B %d, %Y." (unless changed by DateFormat value in registry) %CurrentAccessTime% ... Current system time. All time values are formatted according to cTimeFormat entry in LOG file [Log] section. Default is "%H:%M:%S" (unless changed by TimeFormat value in registry)
6.1.3. Last access tags
These tags have the same meaning like the %CurrentX% ones, but
the values are for the connection immediately preceding the current.
The values are read in from the INI file [LastAccess] section, which
is updated after each connection. If all or some of the entries there
are missing, the following values will be returned:
%LastCnt% ... 0 %LastGraphCnt% ... According to %LastCnt% %LastClientIPAddress% ... <Unknown IP address> %LastClientHost% ... <Unknown host> %LastClientBrowser% ... <Unknown browser> %LastAccessDate% ... <Unknown date> %LastAccessTime% ... <Unknown time>
%HOSTNAME% ... Value returned by the gethostname() WinSock function, contains only the server's name without domain, ie. before the first dot, or localhost in a very unlikely case of an error. %LogStartDate% ... Value from the cStartDate entry in LOG file [Log] section. If there is no INI file or this entry/section is missing, the current system date value is put there, effectively marking the start of logging/access counting %LastFileUpdateDate% ... Date when the HTM file was last changed. Direct- ly read from file system %LastFileUpdateTime% ... Time when the HTM file was last changed (written to). Directly read from the file system %HTMLExVer% ... Link to HTMLEx home page %HTMLExLogo% ... Same as above, but with a nice little anima- ted gif! (HTMLExR.gif should be located in server's home directory). %HTMLExAuthor% ... Link to my e-mail address %AdminName% ... Contents of the ...\W3SVC\Parameters\AdminName registry value (REG_SZ), or Administrator if not found. %AdminEmail% ... Contents of the ...\W3SVC\Parameters\AdminEmail registry value (REG_SZ), or Admin@corp.com if not found. %% ... Will result in a single %. NEVER PUT AN ODD NUMBER OF %'s TOGETHER (That would be odd any- way...)
6.1.5. User-defined random generation tags (in INI file)
HTMLEx is able to generate any number of random HTM page elements, just
follow this procedure:
... <body %PageColorScheme%> ...
... [%PageColorScheme%] ; Black/White/Red/Orange cA=bgcolor="#000000" text="#FFFFFF" link="#FF0000" vlink="#FF7F00" ; White/Black/Cyan/Blue cB=bgcolor="#FFFFFF" text="#000000" link="#00FFFF" vlink="#0000FF"
6.1.6. User-defined random generation tags (in Registry)
These tags apply to all pages being processed by HTMLEx. Each must have
its own key under the ...\W3SVC\HTMLEx key. The following example a puts an
random ad to any number of your servers' pages:
A ... REG_SZ ... <img src="/ads/sponsor1/logo.gif"> B ... REG_SZ ... <img src="/ads/sponsor2/logo.gif"> etc...
... <body> <center>%BigHeaderAd%</center> ... </body> </html>These tags can be added, removed and values changed on the fly, without stopping and restarting the server.
6.1.7. User-defined constant tags (in INI file)
Each user-defined constant tag is a single entry under the [Tags]
section in INI file. Entry names must be enclosed in percent signs.
Example:
... [Tags] %MailHyperlink%=<a href="mailto:name@machine.domain.com">name</a>
6.1.8. User-defined constant tags (in Registry)
Each user-defined constant tag in registry is a value in "Tags" key
under the ...\W3SVC\HTMLEx key. Using these tags it is possible to update
many HTM pages simultaneously, without restarting the IIS.
Example:
%StandardFooter% ... REG_MULTI_SZ ... <hr> <h5>[ <a href="...">Home page</a> | <a href="...">Guestbook</a> | <a href="...">Feedback</a> ]</h5> <hr>
6.1.9. Additional notes about HTMLEx tags
When using predefined and/or defining new tags for HTMLEx expansion,
please consider the following facts:
6.2. INI Files
Each HTM file processed by HTMLEx gets its own INI file created in
the same directory. Why obsolete INIs, and not the registry? The idea
was to let each user freely customize each of his/her HTM files. Users
normally can change the contents of their directories, but they should
be kept hands off the registry! Changing HTM files' names and directories
would also litter registry (HKEY_LOCAL_MACHINE) with many new keys and
values. It's better to litter some directory or mess up a few INI files
than the registry! Values defined in INI override those defined in
registry. Also note that INI entries are always preceded by type character
('i' or 'c'), which is NOT present in the corresponding registry value
name.
======================================================================= Section Entry Default Note ======================================================================= [Config] cTagStart from Registry Characters that mark (TagStart) the beggining of a tag Eg. <!# instead of % cTagEnd from Registry Characters that mark (TagEnd) the end of a tag Eg. #!> instead of % ----------------------------------------------------------------------- [Log] cStartDate Current date In cDateFormat format cDateFormat from Registry This format is used (DateFormat) for all %XDate% tags. See Appendix A for more details cTimeFormat from Registry Used for all %XTime% tags. (TimeFormat) See Appendix A for more details cIgnoreAddress from Registry Comma delimited list of (IgnoreAddress) numeric IP addresses. No counting/logging will occur for these client hosts. It can contain asterisks as wildcards, eg. 161.53.*.* or *.*.*.* which will exclude all hits from being counted/ logged iDigitCnt from Registry Valid range: 2-9, if set (DigitCnt) to 0, will change as requ- ired iMaxLogFileSize from Registry If the LOG file reaches (DigitCnt) this size (in kb) it will be deleted, and a new one created (if 0, LOG file will grow ad infinitum!) ----------------------------------------------------------------------- [LastAccess] cTime See 6.1.3 The %CurrentAccessX% tag cIP -"- values are dumped cHost -"- here after each cBrowser -"- transaction, and will iCnt -"- become %LastAccessX% at cDate -"- the next one ----------------------------------------------------------------------- [Digits] c0 from Registry Any valid image URL ... (HTMLEx\Digits c9 key) ----------------------------------------------------------------------- [%WhatEverYouLike%] cA none User-defined "random" ... tags. cZ Any number of these can be present in the INI file, each with up to 26 entries always named cA to cZ. Note the % signs in the entry name. (Also see 6.1.5) ----------------------------------------------------------------------- [Tags] %Anything% none User-defined constant tags. Apply only to the corresponding HTM file. Tag name must be enclosed by two percent signs. ------------------------------------------------------------------------ [Exec] cCmdStart from registry This combination of (CmdStart) characters marks the beggining of HTMLEx command. MUST BE DIFF- ERENT FROM cTagStart !! cCmdEnd from registry This combination of (CmdEnd) characters marks the end of HTMLEx command. MUST BE DIFFERENT FROM cTagStart !! iMaxLoop from registry All WHILE and REPEAT (MaxLoop) loops will be aborted after iMaxLoop iterati- ons, unless they termina- te earlier due to their logical conditions. =======================================================================
6.3. LOG Files
A LOG file with the same name as the HTM is generated in the HTM file
directory (if enabled, see 7.), and will grow up to the size defined by
MaxLogFileSize value in registry or iMaxLogFileSize value in corresponding
INI file. LOG file generation can be disabled by setting the GenerateLogs
registry value to 0. Please note that LOG files are always generated when
HTMLEx scripts are executed, regardless of registry or INI setting. For the
n-th access the following section will be appended to the LOG file:
[n] cDate= ... Current system date cTime= ... Current system time cIP= ... Value of %REMOTE_ADDR% tag cHost= ... Value of %REMOTE_HOST% tag (or %CurrentClientHost% if present in the HTM file) cBrowser= ... Value of %HTTP_USER_AGENT% tag cReferer= ... Value of %HTTP_REFERER% tag cCookie= ... Value of %HTTP_COOKIE% tag (If not empty, it will contain all cookies sent by client in the following form: NAME1=VALUE1[;NAME2=VALUE2[;...]])HTMLEx scripts may also create custom text values in LOG file using the LOG command (see 8.2).
6.4. ERR Files
In order to prevent the excessive filling of the application event log,
HTMLEx will by default (see 7.1 and 6.2) for each .HTM file generate a
corresponding .ERR file in the same directory. Each section in this file
(generated by the n-th access) will have the following form:
[n]
Ixxx=<Information event explanation> - or -
Wxxx=<Warning event explanation> - or -
Exxx=<Error event explanation>
Where xxx is a unique numeric identifier for each event
6.5. Application event log
If script execution is enabled, and either GenerateErrFiles registry value
or iGenerateErrFiles entry in .INI are set to 0, then all anomalies
encountered during the tag expansion and/or script interpretation (syntax
errors, bad arguments, divisions by zero, stack overflows, etc.) are
recorded in application event log, in one of the following three categories:
7.1. Via Registry
Upon starting, HTMLEx will read its global configuration values which
are stored in the registry, under the following keys:
======================================================================== Value Type Default Meaning ======================================================================== TempDir REG_SZ System tempo- COOKIE PROCESSING WILL NOT rary direc- WORK WITHOUT THIS SETTING! tory??? It must contain full path (without trailing backslash) to a directory over which IUSR_computername has R/W access. If not present, HTMLEx will try to use the system temporary directory, but with little success... ------------------------------------------------------------------------ ExpandableExtensions REG_SZ .htm,.html, All files with these exten- .stm, sions (note the dot!) will .shtm,.shtml be candidates for HTMLEx ------------------------------------------------------------------------ UnexpandableExtensions .exe,.dll, All URLs containing these .asp extensions will be skipped REG_SZ by HTMLEx ------------------------------------------------------------------------ SkipDirectories REG_SZ none Upto 16 comma delimited full paths can be defined. URLs located in these di- rectories will be excluded from HTMLEx processing. ------------------------------------------------------------------------ DateFormat REG_SZ %A, %B %d, %Y. Default format for %XDate% tags. ------------------------------------------------------------------------ TimeFormat REG_SZ %H:%M:%S Default format for %XTime% tags. ------------------------------------------------------------------------ IgnoreAddress REG_SZ 0.0.0.0 Comma delimited list of numeric IP addresses: No counting/logging will occur for these client hosts. The '*' character can be used as IP wildcard (mask) symbol ------------------------------------------------------------------------ MaxLogFileSize REG_DWORD 64 If not otherwise defined in INI, LOG files will grow only upto this size (in kb). Set to 0 for no limit. ------------------------------------------------------------------------ DigitCnt REG_DWORD 5 Default number of digits in graphical counters. If set to 0, it will change accor- ding to counter's value ------------------------------------------------------------------------ ExpandByDefault REG_DWORD 1 If set to 0, each file must have the <!HTMLEx expand> tag in order to be processed If set to 1 (default), each file must have the <!HTMLEx noexpand> tag to bypass pro- cessing ------------------------------------------------------------------------ ExecuteByDefault REG_DWORD 0 If set to 0 (default), each script must have the <!HTMLEx execute> tag in order to be inter- preted. If set to 0, each file must have the <!HTMLEx noexecute> tag to bypass interpretation ------------------------------------------------------------------------ ExpandDefaultPages REG_DWORD 1 If the current page's name matches the default page, it will be expanded. ------------------------------------------------------------------------ ExpandOtherPages REG_DWORD 1 Enables expansion of pages with name other than "Default Load File" ------------------------------------------------------------------------ GenerateLogs REG_DWORD 1 Enables logging for all pages that pass through HTMLEx. ------------------------------------------------------------------------ TagStart REG_SZ % Sets the combination of characters (max. 16) which precede a tag ------------------------------------------------------------------------ TagEnd REG_SZ % Sets the combination of characters (max. 16) which must follow a tag ------------------------------------------------------------------------ CmdStart REG_SZ { Sets the combination of characters (max. 16) which precede a command ------------------------------------------------------------------------ CmdEnd REG_SZ } Sets the combination of characters (max. 16) which must follow a command ------------------------------------------------------------------------ MaxLoop REG_DWORD 64 WHILE and UNTIL loops will be terminated after MaxLoop iterations unless they are terminated before by their logical conditions ------------------------------------------------------------------------ GenerateErrFiles REG_DWORD 1 Put all warning, error and information event explana- tions generated during the HTM file expansion/execution into a separate .ERR file and not into the application event log ------------------------------------------------------------------------ D404Reply REG_SZ none If the client requests a non existing htm file, the '404 Not Found' error is returned. Each directory can contain a special htm file which will be transferred instead. Should contain only name.ext of that file, no path info. Takes precedence over the file defined in S404Reply ------------------------------------------------------------------------ S404Reply REG_SZ none Contains the fully qualified drive:\path\name.ext of the htm file which will be trans- ferred to client in a case of '404 Not Found Error' ------------------------------------------------------------------------ Log404Errors REG_DWORD 0 Enables logging of '404 Not Found' messages in app event log, which occur when clients request a file not present on the WWW server ========================================================================In order to change the default images for displaying graphical counters, the subkey called "Digits" can be created in the ..\W3SVC\HTMLEx key:
======================================================================== Value Type Default Meaning ======================================================================== 0 REG_SZ /0.gif Image for digit "0" ... ... ... ... 9 REG_SZ /9.gif Image for digit "9" ========================================================================To change HTMLEx configuration via registry, IIS must be stopped and restarted.
7.2. Via <!HTMLEx> tag
In addition to registry, HTMLEx behaviour can be changed for each file
by inserting the special "meta" tag somewhere near the beggining of HTM
file (harmless, interpreted as "comment" by WWW browsers):
<!HTMLEx [noexpand | expand] [execute | noexecute] [nolog] [noini] [justcount] [noctags] [nortags]>
noexpand ... all processing skipped. No INI/LOG generation/updating. (if ExpandByDefault is set to 1). Ignored in .ZTM CGI scripts (always expanded) expand ... proceed with HTMLEx processing (if ExpandByDefault is set to 0). Ignored in .ZTM CGI scripts (always expanded) execute ... treat the expanded form as a script and execute it (must be present if ExecuteByDefault is set to 0, which is default!) Ignored in .ZTM CGI scripts (always executed) noexecute ... output expanded form, do not execute it (must be present if ExecuteByDefault is set to 1) Ignored in .ZTM CGI scripts (always executed) nolog ... no LOG file is generated/appended to noini ... no INI file will be generated. This setting is only effective when used in .ZTM CGI scripts. However, if the .INI file exists, it's settings will still be used! justcount ... performance enhancement. Only the following tags will be expanded (in addition to "Random" tags): %CurrentCnt%, %CurrentGraphCnt%, %LastCnt%, %LastGraphCnt%, %%, %REMOTE_HOST%, %CurrentClientHost% (and some others :)) noctags ... disables the expansion of user-defined constant tags, from both the INI file and the registry nortags ... disables the expansion of user-defined random tags, from both the INI file and the registryPlease note that everything is case censitive in this control tag!
8.1. Understanding HTMLEx scripts
HTMLEx scripts are another possibility of making your WWW pages more
interesting and more 'intelligent'. They are by no means a replacement to
usual CGI scripts, but rather an addition. Consider a quite common example:
if using frames and other browser-specific features, a more straightfoward
version of same pages must be mantained. The general approach was to put up
'start' page with links to various versions and let the user decide which
one to take. By using HTMLEx scripts, the HTM file itself can detect the
client's browser version and output only the data it can handle. You can
also change the look of the pages depending on the time of day (make them
"lighter" in graphics during rush hours) and day of week (special weekend
messages etc.). HTM pages can also detect the country and/or the domain
of the client (e.g. automatically generate English, French or Italian
home page, without waiting for the user to make the selection). If the
user is not from some priviledged domain or computer, you can simply omit
some info or links on the page, which can be a nice security feature. (Best
way to keep a secret is not to let anyone know you have one!). By using
the HTTP_REFERER server variable in HTMLEx scripts, it is easy to
enforce that some server areas can only be viewed only by following the
link from a special page (disclaimers, warnings etc.).
If HTMLEx script execution is enabled (see 7.2), HTMLEx will after tag expansion (they are now simply text in HTM page!) treat the same HTM file as a simple program. It will look for commands placed between curly brackets ({}, this can be changed, see 6.2 and 7.1) and execute them. All text outside the brackets (the actual HTML language elements) is passed to the client. The client only gets the result of script execution, which is void from all HTMLEx script commands, and has no notion that any script execution occured at all.
HTMLEx command lines which start with ! or // are treated as comments.
COMMANDS CAN ITERFERE WITH JAVA SCRIPS IN HTM FILES. IN THAT CASE, CHANGE THE DELIMITING CHARACTERS VIA cCmdStart/cCmdEnd INI FILE ENTRIES (SEE 6.2), OR CmdStart/CmdEnd REGISTRY VALUES (SEE 7.1) |
Syntax: {IF lExpression} ... block1 ... [{ELSE} ... block2 ...] {ENDIF} Note: If the logical expression lExpression evaluates to TRUE, all text in block1 is interpreted, otherwise the block2 is inter- preted (if there is an {ELSE}), or skipped past the {ENDIF}. Example: {IF strpos('%CurrentClientBrowser%',"Mozilla",0)} {IF strpos('%CurrentClientBrowser%',"Compatible",0)} <h3>A Netscape compatible will do the trick, too!</h3> {ELSE} <h3>You've got the real McCoy!</h3> {ENDIF} {ELSE} <h3>How about finally getting a real browser!</h3> {ENDIF}
Syntax: {REPEAT} ... block ... {UNTIL lExpression} Note: The block is executed over and over until lExpression is FALSE. As soon as it becomes TRUE (have you learned Pascal in high school?), or loop count reaches iMaxLoop, it is terminated. Block between REPEAT and UTIL is executed at least once. Example: {i=0} {REPEAT} {j=0} {REPEAT} {write str("%4i",j)} {j=j+1} {UNTIL j>9}{i=i+1} {UNTIL i>9}
Syntax: {WHILE lExpression} ... block ... {ENDWHILE} Note: Logical expression following the WHILE statement is evaluated. If it is TRUE, block is executed, and another iteration is started. If it is FALSE or iMaxLoop number of iteration is reached, execution continues just after ENDWHILE. Example: {hSearch=FindFirst("c:\pub\win32\*.zip",&cZipName)} {bFound=IIf(hSearch,TRUE,FALSE)} {WHILE bFound} {WRITE str('<a href="%s">',cZipName),cZipName,'</a>'} {bFound=FindNext(hSearch,&cZipName)} {ENDWHILE} {bFound=FindClose(hSearch)}
Syntax: {WRITE isfExpr1[,isfExpr2[,[isfExpr3 ... ]]]} Note: One or more Expressions (which can be of integer, string or floating point type) are evaluated and their result is appended to the output data stream. Example: {WRITE _Hour,":",_Minute,":",_Second," is the time over here."}
Syntax: {FILE cFullFileName} Note: This command puts the contents of file whose fully qualified name (i.e. drive:\path\name.ext) is given in cFullFileName into the output stream. Example: <h2>Here on the server, this file looks quite different:</h2> <pre> {FILE "f:\services\www\htmlex\script.htm"} </pre>
Syntax: {LOG cLogEntryName [,] cLogEntryValue} Note: HTMLEx will append an entry to the LOG file associated with HTM being interpreted, just after the normal logging entries (see 6.3). Both cLogEntryName and cLogEntryValue must be valid string expressions. Has no effect if logging is disabled (see 7.2.). Example: {LOG "cRandomKey" str("%08X",dwRandomKey)}
Syntax: {ADDHEADER cHeaderName [,] cHeaderValue} Note: When returning the requested document to the client, HTMLEx will add a custom HTTP header to the response, along with the others generated by server (Content-Length, Content-Type, Last-Modified etc.). It is mostly used for setting cookies, in which case cHeaderName must contain "Set-Cookie:", and the cHeaderValue should include the complete cookie text, as returned by the CreateCookie() function. More than one header can be added, but the standard HTTP headers CANNOT be changed/replaced with this command (use SETHEADER for that purpose). After being generated, and before they are sent to client, additional tags are stored in temporary files, in directory specified by TempDir registry value (see 7.1), which are (hopefuly!) deleted after the connection terminates. However, if HTMLEx is invoked from HTMLEx debugger (HTMLXD.EXE) and not from the IIS, these files ARE NOT DELETED, in order to view the generated headers. Example: <html> ... {LVisit=GetCookie("LASTVISIT","%HTTP_COOKIE%")} {IF STRLEN(LVisit)} {STRSPLIT(LVisit,"=",&N,&V)} {WRITE "<h6>Your last visit:",V,"</h6>"} {ELSE} <h6>This is your first visit (at least in a month)!</h6> {ENDIF} {ADDHEADER "Set-Cookie", CreateCookie("LASTVISIT","%CurrentAccessDate%","","/",30*24*3600)} ... </html>
Syntax: {SETHEADER cHeaderName [,] cHeaderValue} Note: This command is similar to ADDHEADER, but it will replace any header with the name cHeaderName, regardless whether it was generated by the HTTP server or previously executed ADDHEADER / SETHEADER command. This command has no effect when used in ISAPI (.ZTM) scripts, which allow only headers to be added to the usual header: Content-type: text/html Content-Length: ... Example: <html> {// This will ignore cache and force reload on IE3.0,} {// but unfortunately has no effect on NN3.0...} {SETHEADER "cache-control:","private"} ... </html>
Syntax: {EVENT iType [,] iID [,] cDescription} Note: An event is written into the Application Log, with the following parameters: - iType, integer expression determines the event type: 0 ... INFORMATION (blue) 1 ... WARNING (yellow) 2 ... ERROR (red) - iID, integer expression, event identifier - cDescription, string expression, will be displayed in 'Event Detail' event viewer window. This command has no effect when HTMLEx is running under PWS on Windows95. Example: {EVENT INFORMATION 900 str("%08X",dwRandomKey)}
Syntax: {EXIT [cErrNote]} Note: This command will, when executed, immediately terminate the script interpreter and output data generated so far. The optional parameter cErrNote will be written into correspon- ding .ERR file (or Application Event Log as a Warning Event) if specified. If used within a subroutine, it will pass the execution to the calling script. Example: {IF bFatalError} <h3>Fatal error: script terminated!</h3> <body> </html> {EXIT "Exit due to a fatal error"} {ENDIF}
Syntax: {SUBROUTINE SubroutineName([VarName][,VarName...])} Note: Defines a subroutine within the HTMLEx script file. Unlike subroutines defined via registry it can only be called from within the script which contains it. There can be more than one subroutine within the script, each terminated by RETURN command. Subroutines should follow after the "main" script, ie. after the closing </HTML> tag. Example: <HTML> <!HTMLEx expand execute> ... {GETFILENAMES(&cHTMName,&Dummy,&Dummy,&Dummy)} {CALL CrackPath(cHTMName,&cDrive,&cDir,&cFN)} ... </HTML> {SUBROUTINE CrackPath(cPath,cDrive,cDir,cFileName)} {STRSPLIT(cPath,':',&cDrive,&cRest)} {cDrive=cDrive+':'} {cDir=""} {REPEAT} {STRSPLIT(cRest,'\',&cBef,&cRest)} {cDir=cDir+cBef+'\'} {UNTIL STRPOS(cRest,'\',0)<0} {cFileName=cRest} {RETURN}
Syntax: {RETURN [cErrNote]} Note: This must be the last statement in script-defined subroutines. If used outside subroutines, it has the same effect as the exit command. Example: See the subroutine command.
Syntax: {CALL SubroutineName([Param][,Param[,...]])} Note: It is possible to define external subroutines using the HTMLEx scripting syntax. Subroutine definitions can reside in the reg- istry and/or external files and are visible for all executing scripts. Only variables defined in subroutine variable list and those defined externaly (see 8.4) are visible in subroutines. Subroutines can return values into calling script via parameters passed by name (ie. variable names preceded by &). Recursive calls are allowed, (theoretically!), but avoiding this practice is strongly recommended. To define and use a subroutine, follow these steps: - Create the key 'Subroutines' under the HKEY_LOCAL_MACHINE\ \SYSTEM\CurrentControlSet\Services\W3SVC\HTMLEx key - For each subroutine defined, create a single value, with the name in the form: SubroutineName([VarName][,VarName...]) - Two registry types are allowed for each value (subroutine definition): - REG_SZ ... value data is the fully qualified name of the file containing the subroutine code - REG_MULTI_SZ ... subroutine code is in the value data, ie. it is located in the registry! - Starting with V2.15, it is possible to define a subroutine within the script itself. For more info, see the SUBROUTINE command. Subroutines defined in script file cannot be called recursively. Example: - Create the key 'Subroutines' under ...\W3SVC\HTMLEx key - Add value named 'NTTime(cRet)' under Subroutines key, with the type REG_EXPAND_SZ - Enter the following code in the Multi string editor data field: {iS=_TickCount/1000} {iH=iS/(60*60)}{iS=iS-iH*60*60} {iM=iS/60}{iS=iS-iM*60} {cRet="NT started " <... all into single line! ...> +str("%2i hours, ",iH) +str("%2i minutes and ",iM) +str("%2i seconds ago",iS)} - In the .HTM where you want this subroutine used, include: <!HTMLEx expand execute> ... {CALL NTTime(&ItHasBeenOnForSuchALongTime)} {WRITE ItHasBeenOnForSuchALongTime} ... </HTML>
Syntax: {VarName1[,VarName2[, ...]] [=] Expression} Note: Expression is evaluated and its result is stored into one or more variables. If no variable with such name(s) exist, they are created and assigned the value and type of expression. Values cannot be assigned in function/command parameters. The maximum number of variables in HTMLEx scripts is limited. Example: {iRandom rnd(1,100)} {i,j,k=i+1} {bComingFromUniversity strpos("%CurrentClientHost%",".edu",0)}
8.3.1. Notes about expressions and datatypes
Expressions can contain any combination of variable names, constants,
operators and functions following the usual syntax of languages like
C, Pascal, Basic or Fortran. When in doubt about the priority of operations, use parentheses! Also note the behaviour of arithmetic operators
(+,-,/,*): they will always evaluate to floating point (real) value,
UNLESS BOTH OPERANDS ARE INTEGERS: i.e. 5/2 will return 2, while 5/2.
or 5./2 evaluate to 2.5! The "+" operator is also used for string concatenation. Function and variable names are case insensitive.
Data types recognized by HTMLEx:
---------------------------------------------------------------------- Type Symbol Note ---------------------------------------------------------------------- Integer/Double word/logical i 4 byte value (DWORD) Real/Floating point f 8 byte double-precision floating point number String/Character s C-style zero terminated string, max. 1024 chars! Pointer to variable p Address of a variable (stored in same field as integer value) Unknown/Undefined u Used only internaly Numeric n i or f Numeric or string x i, f, or s ----------------------------------------------------------------------
8.3.2. Variables
Variable names must start with a letter and continue with any of the
following characters (max. 64): A...Z, 0...9, #, $, _. When HTMLEx starts
executing the script, following variables are already defined:
----------------------------------------------------------------------- Name Type Value ----------------------------------------------------------------------- FALSE i 0 TRUE i 1 INFORMATION i 0 To be used in LOG command WARNING i 1 ditto ERROR i 2 ditto _Year i 1996 and beyond... (from GetSystemTime API function) _Month i 0..12 _DayOfWeek i 0 (Sunday) ... 6 (Saturday) _Day i 1 ... 31 _Hour i 0 ... 23 _Minute i 0 ... 59 _Second i 0 ... 59 _Milliseconds i 0 ... 999 _TickCount i Number of milliseconds elapsed since the NT session start (GetTickCount API function) _MemoryLoad i 0 ... 100 Percent of system memory used (from GlobalMemoryStatus API function) HOSTNAME s Name of the computer running HTMLEx, as returned by the gethostname() WinSock func- tion (ie. without domain name!) ------------------------------------------------------------------------Note: variables preceded by '_' always reflect the current state, of course!
In case of .ZTM CGI scripts, two additional variables can be used (they are undefined otherwise, ie. VALTYPE(GET) or VALTYPE(POST) return 0):
----------------------------------------------------------------------- Name Type Value ----------------------------------------------------------------------- GET s Data sent by client if the GET method was used, empty if data was sent by client using POST. Same as %QUERY_STRING% tag expanded. POST s Data sent by client if the POST method was used, empty if GET was used. -----------------------------------------------------------------------Note: When using GET and/or POST variables, be aware of the way client data is encoded in them ('application/x-www-form-urlencoded'):
The DecodeFormFieldData function can be used to convert the urlencoded strings into clear-text form.
---------------------------------------------------------------------------- Type Examples Notes ---------------------------------------------------------------------------- i 77 Decimal (77) 077 Octal (63 decimal!) 0x77 Hex (119 decimal!) 0X0000FFFF Will give a 255.255.0.0 net mask when used in Addr2S, S2Addr functions! ---------------------------------------------------------------------------- f 3.141592 you know this one... .254e-1 exactly one inch! ---------------------------------------------------------------------------- s "" null string, contains a single null-char, length is 0 '' same as above "%CurrentClientHost%" HTMLEx will expand the tags first, so when it comes to script execution, it will see this like "slip2256.rmii.com" '%CurrentClientBrowser%' If double quotes are expected in string constant, put it into single ones and vice-versa! ----------------------------------------------------------------------------
---------------------------------------------------------------------------- Symbol Priority Operand(s) Result Note ---------------------------------------------------------------------------- + 4 i + i i Addition f + n f s + s s String concatenation + 7 + i i Plus sign (ignored) + f f - 4 i - i i Substraction f - n f - 7 - i i Sign change - f f * 5 i * i i Multiplication f * n f / 5 i / i i Mod f / n f Division (division by zero will return zero, and generate a warning event in application log!) << 6 i1 << i2 i Shift left i1 (multiply by power of 2) i2 places >> 6 i2 >> i2 i Shift right i1 (divide by power of 2) i2 places == 2 n == n i Equal s1 == s2 i strcmp(s1,s2)==0 (ALL STRING COMPARISONS ARE CASE SENSITIVE!) != 2 n != n i Not equal s1 != s2 i strcmp(s1,s2)!=0 <= 2 n <= n i Less than or equal s1 <= s2 i strcmp(s1,s2)<=0 < 2 n < n i Less than s1 < s2 i strcmp(s1,s2)<0 >= 2 n >= n i Greater than or equal s1 >= s2 i strcmp(s1,s2)>=0 > 2 n > n i Greater than s1 > s2 i strcmp(s1,s2)>0 & 5 i & i i Bitwise AND & 7 & n p Address-of operator | 4 i | i i Bitwise OR && 3 x && x i Logical AND. Strings are always TRUE unless empty ("" or ''), while any non-zero numeric value is regarded as TRUE || 1 x || x i Logical OR ! 7 x i Logical negation ----------------------------------------------------------------------------
---------------------------------------------------------------------- HTMLEx Functions Overview ---------------------------------------------------------------------- Category Return value Name and parameters ---------------------------------------------------------------------- Arithmetic n SQRT(n) ---------------------------------------------------------------------- String i STRLEN(s) s SUBSTR(s,i,i) s STRUPR(s) s LTRIM(s) s RTRIM(s) i STRPOS(s,s,i) s STRCPY(s,s,i) i STRSPLIT(s,s,p,p) ---------------------------------------------------------------------- Data conversion i INT(x) f REAL(x) s STR(s,x) i VALTYPE(xu) ---------------------------------------------------------------------- File manipulation i GETFILEINFO(s,s,p,p,p,p) i GETFILENAMES(p,p,p,p) i FINDFIRST(s,p) i FINDNEXT(i,p) i FINDCLOSE(i) i READINIORREG(is,s,s,x,p) i WRITEINIORREG(is,s,s,x) ---------------------------------------------------------------------- CGI support s GETFORMFIELD(is,s) s DECODEFORMFIELDDATA(s) s ENCODEFORMFIELDDATA(s) ---------------------------------------------------------------------- Cookie processing s CREATECOOKIE(s,s,s,s,i) s GETCOOKIE(is,s) ---------------------------------------------------------------------- Misc i RND(i,i) s ADDR2S(i,is) i S2ADDR(s,is) x IIF(i,x,x) s CREATEANCHORS(s) s GRAPHCNT(i,i) s DECODEDATE(i,s) s DECODETIME(i,s) ----------------------------------------------------------------------
Syntax : ADDR2S(iAddr,isAndMask) Argument(s) : iAddr ... IP address in numeric form isAndMask ... IP address mask in numeric or decimal-dot string form Return value: iAddr & isAdnMask in decimal-dot (string) form Example : ADDR2S(0x0100007f,"255.255.255.255") ... "127.0.0.1"
Syntax : CREATEANCHORS(sText) Argument : sText ... ordinary text in which the following references are searched: http://, https://, ftp://, mailto:, news:, gopher://, telnet:, file://. They are converted into <a href="URL">URL</a> HTML tags. Return value: sText with URLs in HTML form, or sText unchanged if none was found. Example : CREATEANCHORS('http://erc.riteh.hr/') ... would return: http://erc.riteh.hr/
Syntax : CREATECOOKIE(sName,sValue,sDomain,sPath,iExpTimeOffset) Arguments : sName ... any string which will identify the cookie sValue ... any string (data) associated with the cookie name sDomain ... specifies the hostname (ie. www server's name) or the domain (tail match) for which the client will return this cookie. If empty, the ;domain=xxx.yyy.zzz part of the cookie will be left out sPath ... specifies the path for which the client will return this cookie in case of the head match with the current URL. If empty, the ;path=ppp part of the cookie will be left out iExpTimeOffset ... Number of seconds from this moment on which specifies the moment when this cookie will expire, ie. will be removed from client's list and not returned any more. If zero the ;expires=datetime part of the cookie will be left out, and the cookie will expire as soon as the session between browser and WWW server ends. The datetime value is generated with the string "%a, %d-%b-%y %H:%M:%S GMT" (See Appendix A.) Return value: Complete cookie text which should be sent to client by the HEADER command (with HTTP header name set to "Set-Cookie:", or an empty string if either cName or cValue are empty Examples : CreateCookie("C1","500","","",24*60*60) ... "C1=500; expires=Sat, 14-Sep-96 14:49:13 GMT" (if created on Friday, 13-Sep-96 14:49:13) CreateCookie("C2","Cake","www.riteh.hr","/en",0) ... "C2=Cake; domain=www.riteh.hr; path=/en" CreateCookie("C3","","fooonline.com","",0) ... "" (invalid, no cookie value specified) Note : The sName and sValue parameters must not be empty strings, and no parameter should contain the '=' or ';' characters.
Syntax : DECODEDATE(iDate,sDateFormat) Argument(s) : iDate ... value returned by the GetFileInfo() function, in the pDateTime parameter (time is encoded in old DOS form in low order word) sDateFormat ... String defining the format which will be used for decoding (See Appendix A) If empty (""), the default date format is used, as defined by registry or overriden by corresponding .INI file Return value: String containing plain-text representation of the time value in iDate Example : See the GetFileInfo() function
Syntax : DECODEFORMFIELDDATA(sSrc) Argument : sSrc ... Text in the 'application/x-www-form-urlencoded' form (see 8.3.2) Return value: String converted into plain text form Example : see STRSPLIT() function
Syntax : DECODETIME(iTime,sTimeFormat) Argument(s) : iTime ... value returned by the GetFileInfo() function, in the pDateTime parameter (time is encoded in old DOS form in high order word) sTimeFormat ... String defining the format which will be used for decoding (See Appendix A) If empty (""), the defauld time format is used, as defined by registry or overriden by corresponding .INI file Return value: String containing plain-text representation of the time value in iTime Example : See the GetFileInfo() function
Syntax : ENCODEFORMFIELDDATA(sSrc) Argument : cSrc ... Any text Return value: String encoded in a same way as it would be if it had been sent by a HTTP client Example : EncodeFormFieldData("What's up?") ... would return: What%27s+up%3F
Syntax : FILESIZE(cFileName) Argument(s) : sFileName ... Name of the file (including full drive:\path!) whose length is queried Return value: 0 ... File not found, invalid name, or really 0 bytes long! -1 ... sFileName is a directory (folder) n>0 ... Length of cFileName, in bytes Example : {iFS=FILESIZE(cDir+cFN)} {WRITE cDir,cFN,STR(IIF(iFS==-1," Directory"," %8i),iFS)} Note : Obsolete. Use GetFileInfo() instead.
Syntax : FINDCLOSE(iSHandle) Argument(s) : iSHandle ... Search handle returned by FINDFIRST() and used in subsequent calls to FINDNEXT() Return value: TRUE if search handle was valid and it was closed properly, false otherwise Example : {WRITE IIF(FINDCLOSE(hJPGSearch),"OK","Something's wrong")}
Syntax : FINDFIRST(sSPattern,pNameOfFirst) Argument(s) : sSPattern ... File search pattern, including the complete drive:\path. pFirstName ... Pointer to the string variable which will receive the name (without drive:\path\ !) of the first matching file Return value: Search handle (integer), to be used in subsequent FINDNEXT() function calls and finaly released by FINDCLOSE(). If there was no match, will return 0. Example : {hJPGSearch=FINDFIRST("c:\pub\pics\*.jpg",&cJPGName)}
Syntax : FINDNEXT(iSHandle,pNameOfNext) Argument(s) : iSHandle ... search handle returned by FINDFIRST() pNameOfNext ... Pointer to the string variable which will receive the name (without drive:\path\ !) of the next matching file Return value: TRUE, if a file was found, FALSE otherwise Example : {WHILE FINDNEXT(hJPGSearch,&cJPGName)} {WRITE STR('<a href="%s">',cJPGName),cJPGName,"</a>"} {ENDWHILE}
Syntax : GETFILEINFO(sFilePath,sFileName,pRes,pAttr,pSize,pDateTime) Arguments : sFilePath ... Path to the file about to be queried sFileName ... Name.ext of the file about to be queried. The sFilePath and sFileName are concatenated, with a backslash inserted between if required. pRes ... Reserved. Will generate an emtpy string varia- ble pAttr ... Pointer to integer variable which will receive the file attribute flags (see Appendix B) pSize ... Pointer to integer variable receiving the file size in bytes (0 if file is a folder) pDateTime ... Pointer to integer variable receiving the enco- ded last file update date/time value. Use the DECODEDATE() and DECODETIME() functions to convert it into human-readable form Return value: TRUE if the file name specified by sFilePath+cFileName is valid and actualy exists, FALSE otherwise Example : {GetFileNames(&HTMName,&Dummy,&Dummy,&Dummy)} {GetFileInfo(HTMName,"",&Dummy,&Dummy,&Size,&DT)} {WRITE "Document size: ",Size," bytes.<br>"} {WRITE "Last updated:",DECODEDATE(DT,"")," ",DECODETIME(DT,"")}
Syntax : GETFILENAMES(pHTMName,pININame,pLOGName,pERRName) Arguments : pHTMName ... points to variable which will receive the fully qualified filename of the executing script pININame ... points to variable which will receive the fully qualified filename of the initializa- tion file associated with the script pLOGName ... points to variable which will receive the fully qualified filename of the log file associated with the script pERRName ... points to variable which will receive the fully qualified filename of the error/warning log file associated with the script Return value: Always TRUE Example : See WRITEINIORREG() function Note : pLOGName and pERRName will contain valid file names even if logging and error file generation is disabled for this script
Syntax : GetFormField(isIndex,sClientCookie) Argument(s) : isIndex ... Integer (iIndex>=1) selecting the name=value pair from the cookie string sent by the client. If isIndex is a string, it should be the name of the specific cookie. This name is looked up (case sensitive!) in sClientCookie argument, and if found, the complete Name=Value pair is returned sClientCookie ... String containing the full "Cookie:" header received from client, typically the the value of %HTTP_COOKIE% tag/server variable is used for this parameter Name=value pairs (ie. cookies) are delimited using the ';' character Return value: Complete Name=value pair on the position given by isIndex, or as found in sClientCookie after searching for isIndex string. Empty string if isIndex<0 or isIndex exceedes the number of available pairs, or isIndex contains a string which cannot be found in sFormData. Example : See the HEADER command Note : Clients may return multiple cookies in HTTP_COOKIE server variable in any order (unless they are related with the ;path=... value, in which case the most specific cookie is returned first)
Syntax : GetFormField(isIndex,sFormData) Argument(s) : isIndex ... Integer (iIndex>=1) selecting the name=value pair from the GET or POST string sent by the client. If isIndex is a string, it should be the name followed by a '=' character of a HTML form field. This name is looked up (case sensitive!) in sFormData argument, and if found, the complete Name=Value pair is returned sFormData ... String containing the full (encoded) form data retrieved from the client, typically GET or POST variable, depending on the method used. Name=value pairs are delimited using the '&' character Return value: Complete Name=value pair on the position given by isIndex, or as found in sFormData after searching for isIndex string. Empty string if isIndex<0 or isIndex exceedes the number of available pairs, or isIndex contains a string which cannot be found in sFormData. Example : {Dummy=STRSPLIT(GETFORMFIELD("emailaddr=",POST),"=",&EMA)} {EMA=LTRIM(RTRIM(EMA))} {IF STRLEN(EMA)==0} <h2>Please retry, and enter your e-mail address!</h2> {ENDIF}
Syntax : GRAPHCNT(iCnt,iDigitCnt) Argument(s) : iCnt ....... integer (counter value) which is to be represented in graphical form iDigitCnt ... number of digits (images) in graphical URL string. If iDigitCnt==0, the default number valid for this page is used. Return value: String containing the URLs of digit images which when displayed represent the integer iCnt. The URLs of single digits are the same ones which would be used for %CurrentGraphCnt% tag. (see 6.1.2) Example : GRAPHCNT(32,3) ... would return the following string: <img src="/0.gif" alt="0"> <img src="/3.gif" alt="3"> <img src="/2.gif" alt="2">
Syntax : IIF(iExpr,xTrue,xFalse) Argument(s) : iExpr ... logical expression, will evaluate to TRUE or FALSE xTrue ... result of IIF, if iExpr==TRUE xFalse ... result of IIF, if iExpr==FALSE Return value: value of xTrue or xFalse. Please note 2 important things: a) BOTH xTrue AND xFalse ARE EVALUATED BEFORE IIF RETURNS! (This will be changed in future versions of HTMLEx) b) Data type returned by IIF also depends on iExpr!, i.e. both xTrue and xFalse can evaluate to different types Example : {i=IIF(i<10,i+1,10)}<!Let i go only to 10!>
Syntax : INT(fsExpr) Argument(s) : fsExpr ... floating point or string expression Return value: Integer part of floating point number or conversion of a decimal, octal or hex string Example : INT('010') ... 8
Syntax : LTRIM(sExpr) Argument : sExpr ... any valid string expression Return value: Returns sExpr, but the first character is set to first character with ASCII code > 32 Example : See RTRIM() function
Syntax : READINIORREG(isSrc,sKeySection,sEVName,xDefault,pDst) Argument(s) : isSrc ......... Selects the data source. If it is integer, data is being read from the registry: 0 ... HKEY_CLASSES_ROOT 1 ... HKEY_CURRENT_USER 2 ... HKEY_LOCAL_MACHINE 3 ... HKEY_USERS If string, it is assumed to be the fully qualified name of the initialization file sKeySection ... Name of the subkey within the of the registry root keys, or name of the section within the INI file given in isSrc. sEVName ....... Name of the value in the isSrc\sKeySection registry key, or name of the entry in the sKeySection part of the isSrc file xDefault ...... Default value returned in pDst variable if no registry value/INI entry cannot be found. Should be string in case of reading from INI file pDst .......... pointer to a variable which will receive the value from registry/INI file, or xDefault Return value: Registry ...... TRUE if sEVName was found and its value was transferred into pDst, FALSE otherwise. INI file ...... Number of characters actually read from INI file. Example : {WWWKey="SYSTEM\CurrentControlSet\Services\W3SVC"} {Dummy=ReadINIorReg(2,WWWKey+"\Parameters\Virtual Roots","/," ,"god knows where",&WWWRoot)} {WRITE "WWW root directory is ",WWWRoot}
Syntax : REAL(isExpr) Argument(s) : isExpr ... integer or string expression Return value: Integer converted to floating point or conversion from string to floating point Example : REAL(1+REAL('1')) ... 0.2e+01
Syntax : RND(iRndMin,iRndMax) Argument(s) : iRndMin ... lowest random integer allowed iRndMax ... highest random integer allowed Return value: Random integer somewhere between iRndMin and iRndMax Example : {IF RND(1,100)<33} {WRITE "Every third visitor gets very lucky!"} {ENDIF} Note : To initialize the random number generator (randomize), call this function with any parameters and discard its result!
Syntax : RTRIM(sExpr) Argument : sExpr ... any valid string expression Return value: sExpr, but with all characters after the last character with ASCII code > 32 removed Example : STRUPR(LTRIM(RTRIM(" yes! "))) ... YES!
Syntax : S2ADDR(sDotAddr,isAndMask) Argument(s) : sDotAddr ... IP address in decimal-dot notation, eg. "161.53.40.11" isAndMask ... IP address mask in string or integer form, will be bit-anded with sDotAddr integer representation Return value: sDotAddr & isAndMask in 4-byte numeric form Example : {WRITE IIF(S2ADDR('%CurrentClientIPAddress%','255.255.0.0') ==0x000035a1),"Dobrodosli!","Welcome!")}
Syntax : SQRT(nExpr) Argument(s) : nExpr ... numeric value Return value: Square root of the nExpr value. If nExpr<=0, 0 will be returned and a warning event will be added to the application event log or .ERR file Example : {Area=SQRT(s*(s-a)*(s-b)*(s-c))}
Syntax : STR(sFormat,xExpr) Argument(s) : sFormat ... string used to format xExpr data value. Beside actual format specifiers (like in C sprintf() function!) it can contain any other string. xExpr ... single i, f, or s data value. NOTE THAT UNLIKE sprintf() THIS FUNCTION CAN CONVERT JUST ONE PARAMETER AT A TIME! Return value: xExpr in string form Note : If the percent character (%tag%, default) is used to enclose the HTMLEx tags, USE DOUBLE PERCENT CHARACTERS (%%) IN sFormat TO AVOID ERRONEOUS TAG EXPANSION! (See example below) Example : STR("Here it is in hex form: %%08x",100) ... 0x00000064
Syntax : STRCPY(sDest,sSrc,iPos) Argument(s) : sDest ... String which will be copied to sSrc ... String which will be copied iPos ... Character position in sDest (starting at 0!) where sSrc will be copied Return value: sDest modified starting at iDestPos position Example : {iSlash=STRPOS(cPath,'/',0} {WHILE iSlash>-1} {cPath=STRCPY(cPath,'\',iSlash)} {iSlash=STRPOS(cPath,'/',iSlash+1)} {ENDWHILE}
Syntax : STRLEN(sExpr) Argument(s) : sExpr ... string expression Return value: number of characters in sExpr Example : STRLEN('%SERVER_SOFTWARE%') ... 40
Syntax : STRPOS(sStr,sSubStr,iStartPos) Argument(s) : sStr ... String presumed to contain sSubStr sSubStr ... String being looked for iPos ... Search starts at this position in sStr Return value: Position of first occurence of sSubStr within sStr, or -1 if not found. Example : {IF STRPOS('%CurrentClientBrowser%',"NT",0)>-1} {WRITE "Congratulations for using my favourite OS!"} {ENDIF}
Syntax : STRSPLIT(sSrc,sSplitter,pBefore,pAfter) Argument(s) : sSrc ... String which will be split into two parts sSplitter ... String searched in sSrc, which stands between the two parts pBefore ... Points to string variable which will receive the part before sSplitter. If sSplitter is not found within sStr, it will contain the whole sStr pAfter ... Points to string variable which will receive the part od sStr after sSplitter, or empty string if sSplitter is not found Return value: TRUE if sSplitter was found in sSrc, FALSE otherwise Example : {IF StrSplit(GetFormField(1,POST),"=",&FName,&FData)} {FData=DecodeFormFieldData(FData)} {ELSE} {FData="Default"} {ENDIF}
Syntax : STRUPR(sExpr) Argument(s) : sExpr ... mixed upper/lowercase string Return value: same as sExpr, but a-z turned to A-Z Example : {IF Name==STRUPR(Name)} {WRITE "Invalid name, contains no letters!"} {ENDIF}
Syntax : SUBSTR(sExpr,iStartPos,iLength) Argument(s) : sExpr ... source string iStartPos ... first char in sExpr (1st char is at pos. 0!) iLength ... number of chars in resulting substring Return value: Part of sExpr. Null string if iStartPos<0 or iLength<1. Example : SUBSTR('%SERVER_SOFTWARE%',10,8) ... 'Internet'
Syntax : VALTYPE(xuExpr) Argument(s) : xuExpr ... any expression Return value: 0 ... undefined, unknown or error 1 ... integer 2 ... real 3 ... string 4 ... variable pointer Example : {IF VALTYPE(Ex)==0} {EVENT WARNING,199,"Something's wrong with Ex!"} {ENDIF}
Syntax : WRITEINIORREG(isDst,sKeySection,sEVName,nsValue) Argument(s) : isDst ......... Selects the data destination. If it is an integer, data is being written into registry: 0 ... HKEY_CLASSES_ROOT 1 ... HKEY_CURRENT_USER 2 ... HKEY_LOCAL_MACHINE 3 ... HKEY_USERS If string, it is assumed to be the fully qualified name of the initialization file sKeySection ... Name of the subkey within the of the registry root keys, or name of the section within the INI file given in isSrc. sEVName ....... Name of the value in the isSrc\sKeySection registry key, or name of the entry in the sKeySection part of the isSrc file nsValue ....... Value written into INI file or registry. Integers will create a REG_DWORD value in registry, strings and floating point values (after conversion!) will be stored in REG_SZ. In INI files, all values are first converted into strings Return value: TRUE if nsValue was successfuly written into registry or INI file, FALSE otherwise. Example : {IF "%REMOTE_ADDR%"==SpecialIPAddress} {Dummy=GetFileNames(&HTMFN,&INIFN,&LOGFN,&ERRFN)} {Dummy=ReadIniOrReg(INIFN,SpecialIPAddress,"Cnt","0",&Cnt)} {Cnt=str("%i",int(Cnt)+1)} {Dummy=WriteIniOrReg(INIFN,SpecialIPAddress,"Cnt",Cnt)} {ENDIF}
8.4. Defining external variables
In addition to read-only variables predefined by HTMLEx (see 8.3.2) and
the ones created during the script execution (see 8.2), variables and their
values can also be externaly defined.
8.4.1. Via registry
Using the registry editor create the "Variables" subkey under the
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W3SVC\HTMLEx key.
Each value in this key will create a variable for all scripts that will
begin execution from that moment on. Please note that no floating point
variables can be created via registry, only integer and string:
---------------------------------------------------------------------- Registry data type Variable data type ---------------------------------------------------------------------- REG_DWORD i REG_SZ s REG_MULTI_SZ s (Lines will be separated by a \n character) REG_EXPAND_SZ s (References to system environment variables will be expanded) ----------------------------------------------------------------------
8.4.2. Via INI file
Each script can have its own private variables created by adding the
[Variables] section in the corresponding .INI file. The type of variable
is inferred by the first character of value name, eg.:
[Variables] cThisDirectory=c:\services\www\htmlex\ ... string variable fE=2.718282 ... floating point variable iForbiddenFromHr=9 iForbiddenToHr=0x11 ... integers WideBar="<hr size=8>" ... string
8.5. Additional notes about HTMLEx scripts
The HTMLEx script language has all the elements necessary to write rather
complex programs, but before you do, consider the following (severe!?) limitations:
AND SOME THE FEATURES MENTIONED BELOW REQUIRE MORE THOROUGH TESTING - USE THEM WITH CAUTION! |
9.1. Configuring IIS for HTMLEx script execution
Name : .ztm (or your own) Type : REG_SZ String: drive:\full_path\HTMLEx.dll, the same as present in 'Filter DLLs' value under '...\W3SVC\Parameters' key
<HTML> ... <FORM METHOD="POST" ACTION="/scripts/scriptname.ztm"> ... <INPUT TYPE=SUBMIT> </FORM> ... </HTML>The scriptname.ztm CGI script will be started when the 'Submit Query' button is pressed. Data entered into form will be available in the script in POST variable. (Or GET, had METHOD="GET" been specified instead)
<HTML> ... <A HREF="/scripts/example.ztm>Click here to start a script!</A> ... </HTML>Parameters can be passed to .ztm scripts invoked this way via a query string, which is appended after the URL, delimited with a single ? character:
<A HREF="/scripts/foo.ztm?Param1+Param2">Pass some params!</a>In this case, the query string Param1+Param2 will appear in foo.ztm in the GET variable (or expanded value of %QUERY_STRING% tag)
9.2. Notes about using HTMLEx as CGI scripting tool
Using HTMLEx language for writing CGI scripts (programs) is hardly an
alternative for commonly used script languages like PERL, and even less
for customized, heavy-duty ISAPI applications written in C/C++, but it can
come in handy as a quick, stop-gap CGI tool. All that is needed are IIS,
HTMLEx.dll (version 2.10 or higher!) and any plain-text editor. HTMLEx
scripting language contains a number of functions which make easier the
common tasks in all CGI programs like parsing the data returned from client,
splitting it into name/value pairs, decoding it into clear text, writing it
into files on the server and returning replies to client. Additionaly, all
HTMLEx tags found in the script are expanded before the execution starts,
giving extra flexibility: HTMLEx global configuration in registy is also
valid for HTMLEx CGI scripts, each can be customized with the corresponding
.INI file, and will generate .ERR and .LOG files, too.
When using HTMLEx CGI scripts, please keep the following in mind:
HTMLEx.TXT ... A very short note about HTMLEx Manual.htm ... Manual you're reading right now. In previous versions it was a plain-text file, but Mikael Persson converted it into HTM for greater convenience. HttpFilt.h ... ISAPI filters (from SDK, needed for compilation) HttpExt.h ... ISAPI extensions (from SDK, needed for compilation) resource.h ... Resource header, required by HTMLEx.rc HTMLEx.rc ... Resource text, contains only a VS_VERSION_INFO resource HTMLEx.mdp ... Microsoft Visual C++ 4.0 project workspace file HTMLEx.mak ... Microsoft Visual C++ 4.0 generated make file HTMLEx.def ... Definition of the exported functions HTMLEx.cpp ... Source code HTMLEx.dll ... Intel binary Test.htm ... HTM File for testing - contains all HTMLEx tags Script.htm ... Sample HTMLEx (filter) script file FrmTst.ztm ... Sample HTMLEx CGI script. Put it into /scripts directory, and test data returned by HTML forms. (<FORM METHOD="POST" ACTION="/scripts/FrmTst.ztm">) 0.gif ... Small images containing digits 0...9 ... These files are used by default for 9.gif displaying graphical counters. (Put them into server's home directory.) Designed by Marco Bosco (MarkB, http://www.riteh.hr/users/markb/) HTMLExR.gif .. "Official" HTMLEx logo, an animated gif, created by Luka Pensa (http://www.riteh.hr/nsquad/). Put it into your server's home directory, and use the %HTMLExLogo% tag on your home page! GBook.htm .... Sample guestbook entry form. Place it anywhere under WWW server's root. Calls /scripts/GBook.ztm when the Submit button is pressed GBook.ztm .... Data processing CGI script for HTMLEx sample guestbook. Put it into /scripts or equivalent WWW server directory Last10.ztm ... CGI script to display the last 10 guestbook entries. Called by HTM page which is dynamically generated by GBook.ztm. Must be located under /scripts directory DumpLog.ztm .. CGI script which displays the HTMLEx log file in fancy table form. Put it into /scripts or equivalent folder and execute it with the full path to HTM file as parame- ter
=================================================================== Ver Rev Date Note =================================================================== 1 00 14.04.1996. >First release version. Intel only :( 1 01 19.04.1996. >Fatal memory bug squashed (?) - seems it won't bring IIS down any longer ???? >Default digit images are /0.gif ... /9.gif >Bug regarding "Random" HTMLEx tag as the first one in HTM file also resolved >.shtm(l) files will also pass through HTMLEx - but who knows what will happen to them... 1 02 20.04.1996. >HTMLEx can be controlled via: - Registry (W3SVC\HTMLEx key) - tag in file 1 03 23.04.1996. >It seems that HTMLEx now works fine with files larger than 8k (THIS MUST BE TESTED MORE THOROUGHLY!!) >Following configuration values added to HTMLEx key in Registry: - DateFormat (REG_SZ) - TimeFormat (REG_SZ) - DigitCnt (REG_DWORD) 1 04 27.04.1996. >Resolved bug: percent signs in ordinary HTML tags are ignored (e.g. <HR SIZE=55%>) >Default digits for graphical counters can be set using the ..\HTMLEx\Digits key. >In addition to User-defined random generation tags in INI files, they can also be defined via registry. >User-defined tags can be added via INI file [Tags] section (on a per-page basis), or globally via \HTMLEx\Tags key in registry. 1 05 04.05.1996. >Log file size can be limited: globaly (in re- gistry) or for each htm file (in INI file) >Counting/INI file updating/logging can be disabled for hits from hosts with specific IP addresses (e.g. server's own address) >Locations for default digit images changed from \x.gif to /x.gif 1 06 07.05.1996. >Tag start and end strings can be changed from % (default) via registry and/or INI file >Reverse DNS lookup bug resolved? >Counter image URLs now include the alt="x" tag (will display something when referenced images cannot be located) 1 07 13.05.1996. >HTMLEx default behaviour can be changed by setting the ExpandByDefault registry value to 0 - only files with will be processed. >HTMLEx processing is bypassed for all URLs containing the extensions listed in UnexpandableExtensions registry key. >No file is processed if located inside one of the directories specified in SkipDirectories registry key. 2 00 02.06.1996. >It's a whole new story now... scripting language has been introduced, justifying the higher major version number! 2 01 23.06.1996. >IF statement bug corrected. (Parser strayed when a variable name started with 'IF') >String indexes allowed in pseudo-arrays >Some new functions added: FileSize, StrCpy, WriteINIorReg, ReadINIorReg, GetFileNames >WRITE command optimized memory-wise >Will immediately abort parsing when Memory block is filled up, without waiting for a protection fault :) >ERR files are generated by default, instead of filling up the Application Event Log (can be disabled via Registry/INI files) >CALL command added with subroutine calling mechanism 2 10 08.07.1996. >Added ISAPI extension functionality:HTMLEx can be used as a CGI scripting language, if .ZTM files are associated in IIS Script map with HTMLEx.dll >Two new predefined variables (GET and POST) and 6 new functions (GetFormField, Decode- FormFieldData, CreateAnchors, StrSplit, LTrim and RTrim were introduced to make CGI scripting, especially form processing easier. >%HTMLExLogo% tag added, so use it! (If Netscape has one, Internet Explorer has one, why shouldn't HTMLEx have one too!) 2 11 22.07.1996. >CreateAnchors debugged (will return the the same string if there are no URLs in it) >IF-ELSE-ENDIF should work properly regard- less of nesting depth >Commands can be commented out by preceding them with either ! or // >HTTP_REFERER tag added, included also in all .INI and .LOG files ><!HTMLEx ...> meta-tag now seems to work properly? >EXIT command added >GRAPHCNT function added 2 15 07.08.1996. >Functions can be used as commands (return va- lue ignored) >CREATEANCHORS function returns anchor hot- spots without protocol name ><!HTMLEx nolog> really disables logging, even for scripts >New functions added: GetFileInfo (obsoletes FileSize), DecodeDate, DecodeTime >Time related functions/tags always return local time, not UTC >Subroutines can be defined in the same file as main script, by using the new SUBROUTINE/ RETURN command pair >HOSTNAME predefined script variable added 2 16 16.09.1996. >HTTP_xxx server variables added (for detecting the xxx HTTP headers received from clients) >If present, HTTP_COOKIE server variable recorded in .LOG files >Some small speed enhancements have been made >Additional headers (typically: Set-Cookie) can be added to server's response with HEADER command >Functions added to facilitate cookie creation and retrieval: CreateCookie() and GetCookie() >TempDir registry entry needed for normal cookie processing (they are temporarily stored in .TMP files in this directory) >The '404 Not Found' reply can be replaced with a custom error page for the whole server, or each directory separately >Logging of '404 Not Found' errors in applica- tion event log is disabled by default (can be reenabled via registry) 2 17 07.12.1996. ><!---HTMLEx ...> also accepted as control tag. This is more conforming to HTML standard and is likely to cause less problems with HTM editors (which should skip it as an ordinary comment) >The few remaining 16-bit API calls removed at last >IgnoreAddress registry setting can be used to disable hit counts for whole domains by using the '*' symbol in IP addressed (eg. 161.*.*.*) >Following constant tags added: %HOSTNAME%, %AdminName%, %AdminEmail%. >HEADER command changed into ADDHEADER (HEADER keyword still works!) >SETHEADER command added, HTTP header generation code completely revamped >'Subroutine Not Found' (in the same HTM file) bug resolved >noini option will disable INI file generation for ISAPI extensions (.ZTMs) >file:// added to CreateAnchors() function ===================================================================
I am especially interested in porting the HTMLEx to other NT platforms (Alpha, MIPS, PPC). If you think you could do it, please contact me by all means - we will put your port of HTMLEx onto its home page, which is:
AND ENHANCED IN FUNCTIONALITY AS LONG AS THE ORIGINAL AUTHOR'S NAME IS PRESERVED PLEASE SEND A NOTE WITH ITS URL TO THE AUTHOR. YOUR SITE WILL BE ADDED TO THE 'HTMLEx enhanced Website' LIST |
The formatting codes for strftime are listed below:
%a Abbreviated weekday name %A Full weekday name %b Abbreviated month name %B Full month name %c Date and time representation appropriate for locale %d Day of month as decimal number (01 - 31) %H Hour in 24-hour format (00 - 23) %I Hour in 12-hour format (01 - 12) %j Day of year as decimal number (001 - 366) %m Month as decimal number (01 - 12) %M Minute as decimal number (00 - 59) %p Current locale's A.M./P.M. indicator for 12-hour clock %S Second as decimal number (00 - 59) %U Week of year as decimal number, with Sunday as first day of week (00 - 51) %w Weekday as decimal number (0 - 6; Sunday is 0) %W Week of year as decimal number, with Monday as first day of week (00 - 51) %x Date representation for current locale %X Time representation for current locale %y Year without century, as decimal number (00 - 99) %Y Year with century, as decimal number %z Time-zone name or abbreviation; no characters if time zone is unknown (also %Z) %% Percent sign
The following section from WINNT.H lists file attribute flags as returned by the GetFileInfo function:
... #define FILE_ATTRIBUTE_READONLY 0x00000001 #define FILE_ATTRIBUTE_HIDDEN 0x00000002 #define FILE_ATTRIBUTE_SYSTEM 0x00000004 #define FILE_ATTRIBUTE_DIRECTORY 0x00000010 #define FILE_ATTRIBUTE_ARCHIVE 0x00000020 #define FILE_ATTRIBUTE_NORMAL 0x00000080 #define FILE_ATTRIBUTE_TEMPORARY 0x00000100 #define FILE_ATTRIBUTE_COMPRESSED 0x00000800 ...