HTMLEx

ISAPI Filter/Extension for
Microsoft Internet Information Server
and Microsoft Personal Web Server
Version 2.17 (beta)

HTMLEx

(c)Zoltan Pekic, 1996.
zoltanp@rijeka.riteh.hr
Last updated: 07.12.1996.

Contents:
  1. What is HTMLEx?
  2. How does it work?
  3. Hardware/software requirements
  4. Installation
  5. Deinstallation
  6. Files used by/changed by HTMLEx
    6.1. HTM Files
    6.1.1. Server variable tags
    6.1.2. Current access tags
    6.1.3. Last access tags
    6.1.4. Other tags
    6.1.5. User-defined random generation tags (in INI file)
    6.1.6. User-defined random generation tags (in Registry)
    6.1.7. User-defined constant tags (in INI file)
    6.1.8. User-defined constant tags (in Registry)
    6.1.9. Additional notes about HTMLEx tags
    6.2. INI Files
    6.3. LOG Files
    6.4. ERR Files
    6.5. Application event log
  7. Controlling HTMLEx behaviour
    7.1. Via Registry
    7.2. Via <!HTMLEx> tag
  8. HTMLEx scripts
    8.1. Understanding HTMLEx scripts
    8.2. Commands
    8.3. Expressions
    8.3.1. Notes about expressions and datatypes
    8.3.2. Variables
    8.3.3. Constants
    8.3.4. Operators
    8.3.5. Functions
    8.4. Defining external variables
    8.4.1. Via registry
    8.4.2. Via INI file
    8.5. Additional notes about HTMLEx scripts
  9. Using HTMLEx as an ISAPI extension
    9.1. Configuring IIS for HTMLEx script execution
    9.2. Notes about using HTMLEx as CGI scripting tool
  10. File list
  11. Revision history
  12. Notes, comments, warnings, bugs etc.

1. What is HTMLEx?

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.

Back to contents


2. How does it work?

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:

Starting with version 2.10, HTMLEx can be used as an interpreter for CGI scripts, capable of processing data returned by clients using the standard GET and/or POST methods. This was made possible by inclusion of 2 additional exported functions, which turn HTMLEx into an ISAPI extension as well:

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.

Back to contents


3. Hardware/software requirements

Back to contents


4. Installation

Back to contents


5. Deinstallation

Back to contents


6. Files used by/changed by HTMLEx

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).

W A R N I N G
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!
Back to contents

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.

Back to contents

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)

Back to contents

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> 

Back to contents

6.1.4. Other tags

%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...)

Back to contents

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:

Back to contents

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:

Back to contents

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>

Back to contents

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> 

Back to contents

6.1.9. Additional notes about HTMLEx tags
When using predefined and/or defining new tags for HTMLEx expansion, please consider the following facts:

Back to contents

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.
=======================================================================

Back to contents

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).

Back to contents

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

Back to contents

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:

Events not related to any .HTM file (e.g. HTMLEx startup, missing keys etc.) are always logged into application event log.
Event logging is not supported under Windows 95, making it advisable to enable .ERR file generation when using HTMLEx with PWS.

Back to contents


7. Controlling HTMLEx behaviour

7.1. Via Registry
Upon starting, HTMLEx will read its global configuration values which are stored in the registry, under the following keys:

Back to contents

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 registry
Please note that everything is case censitive in this control tag!

Back to contents


8. HTMLEx scripts

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.

W A R N I N G
THE USE OF CURLY BRACKETS ({}) FOR HTMLEx SCRIPTING LANGUAGE
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)

Back to contents

8.2. Commands

[IF-ELSE-ENDIF | REPEAT-UNTIL | WHILE-ENDWHILE | WRITE | FILE | LOG | ADDHEADER | SETHEADER ]
[EVENT | EXIT | RETURN | CALL | SUBROUTINE | ASSIGNMENT OPERATION]

Back to contents

8.3. Expressions

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
---------------------------------------------------------------------- 

Back to contents

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.

Back to contents

8.3.3. Constants

----------------------------------------------------------------------------
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!
----------------------------------------------------------------------------

Back to contents

8.3.4. Operators

----------------------------------------------------------------------------
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
----------------------------------------------------------------------------    

Back to contents

8.3.5. Functions

----------------------------------------------------------------------
                    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)
----------------------------------------------------------------------

Back to contents

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)
----------------------------------------------------------------------

Back to contents

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 

Back to contents

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:

Back to contents


9. Using HTMLEx as an ISAPI extension

W A R N I N G
THIS IS THE FIRST RELEASE OF HTMLEx WITH CGI SCRIPTING FUNCTIONALITY
AND SOME THE FEATURES MENTIONED BELOW REQUIRE MORE THOROUGH TESTING
- USE THEM WITH CAUTION!

9.1. Configuring IIS for HTMLEx script execution

Back to contents

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:


10. File list

   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    

Back to contents


11. Revision history
   ===================================================================
   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 
   ===================================================================

Back to contents


12. Notes, comments, warnings, bugs etc.
HTMLEx is not so modest anymore, and it is likely to have many bugs, especially when the script execution is enabled. Use this feature only when necessary, and check out your scripts carefuly! The biggest problem with IIS filters is that any GPF in them INVARIABLY STOPS THE WWW SERVICE! All client transactions just hang until they time out, the only method to recover is to stop and restart the WWW service using the Internet Service Manager, hardly an option if you're away on your long overdue Tahiti vacation. I have tested HTMLEx using Microsoft's Internet Explorer V3.0, Netscape 3.0, Lynx (!) running on Ultrix 4.1, Netscan Tools 2.30, on my Pentium-133 with 48MB RAM and Service Pack 3 ,and it worked more or less OK. Same testing was done after upgrading to NT Server 4.0 and IIS2.0. If you find any bugs, inconsistencies, or have some ideas about making HTMLEx more useful, please e-mail me to:

zoltanp@rijeka.riteh.hr

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:

http://161.53.40.11/HTMLEx/default.htm

Known bug #1:
Sometimes some HTMLEx tags get scrambled - they cannot be resolved and are
simply being passed through. Seems to have dissapeared in V1.04 (?)
Changing the default %/% tag end/start character is recommended
in order to avoid confusion with HTM tags containing the '%' character.
Known bug #2:
On very long HTML pages, first tag is skipped, the second one and the others
expand nicely. Seems to have dissapeared in V1.04 (?)
Known bug #3:
The subroutine calling code is rather complex, highly recursive and therefore
subject to bugs. There were reports of scrambled output when using subroutines.
It seems that putting a few empty lines before/after the subroutine body
helps.
Known bug #4+:
Script interpreter is probably loaded with bugs,
they just haven't been discovered yet...
Special caution required with cookie functions
which have not been tested properly!

THIS SOFTWARE IS FREEWARE - IT MAY BE FREELY COPIED, DISTRIBUTED
AND ENHANCED IN FUNCTIONALITY AS LONG AS THE ORIGINAL AUTHOR'S
NAME IS PRESERVED

THE AUTHOR WISHES TO EXPRESS HIS GRATITUDE TO ALL WEBMASTERS WHO TOOK THE RISK, TRIED HTMLEx, AND HELPED WITH THEIR POSITIVE FEEDBACK TO DEBUG THIS PROGRAM AND MAKE IT MORE USEFUL. SPECIAL THANKS TO Domagoj Pensa FOR HIS USEFUL ADVICES AND HIS KID BROTHER Luka, A TRUE GRAPHICS WIZARD. I'M ALSO VERY GRATEFUL (AND YOU SHOULD BE TOO!) TO Mikael Persson WHO CONVERTED THE ORIGINAL TEXT-ONLY DOCUMENTATION INTO HTM FORM
IF YOU DECIDE TO USE HTMLEx ON YOUR WWW SERVER,
PLEASE SEND A NOTE WITH ITS URL TO THE AUTHOR.
YOUR SITE WILL BE ADDED TO THE 'HTMLEx enhanced Website' LIST

Back to contents


Appendix A. Date/time values formatting codes (strftime function)

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

Back to contents


Appendix B. File Attribute Flags

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

Back to contents


* EOF *