WebSite Professional Server Self Test

WebSite API 1.1 SDK
Server Function Descriptions

Return to Overview

15-September-97

Index

bind_wsapi
close_form_decoder
construct_url
decode_next_field
DbgDump
die
do_imagemap
escape_url
evaluate_access
exec_cgi
exec_cgi_to_file
file_to_url
get_content_type
get_server_variable
GetRegBin
GetRegString
get_temp_name
http_timestr
http_nt_timestr
later_than
MD5Init
MD5Update
MD5Final
nflush
ngets
normalize_url
nputs
nread
nreadf
nwrite
nwritef
OpenRegKey
open_form_decoder
plus_to_space
process_get
send_http_header
set_content_type
space_to_plus
TrueRandAddNoise
TrueRandEntropy
TrueRandGetByte
TrueRandGetBytes
unescape_url
url_to_file
wsapi_free
wsapi_log_event
wsapi_malloc
wsapi_realloc
wsapi_strdup

bind_wsapi

Syntax

BOOL bind_wsapi(WORD major, WORD minor, BOOL strict);
major
The major version of your DLL, based on the header file which was used to compile it.
minor
The minor version of your DLL, based on the header file which was used to compile it.
strict
Version matching criteria. See the description section.
Returns TRUE or FALSE to indicate that the versions are compatible.

Description

This routine performs run-time version locking between the extension and the server. The header file used to compile extension contains a #define that carries the major and minor version numbers of the interface for which the header file was written. The extension must call this function at process-attach time, with its major and minor versions as arguments, as shown above. If this function returns TRUE, the interface is usable, else it returns FALSE. If the DLL gets a FALSE back from this function, it must return FALSE from its DLLMain function, refusing the load. The logic in the server will report the load refusal to the logs and via a one-time MessageBox. The ground rules are:
strict = TRUE
Major and minor versions must match
strict = FALSE
Fail if either the major versions do not match, or the minor version of the extension is greater than that of the server.
Major version changes occur when the interface is changed so as to be incompatible with previous versions (e.g., the TCTX structure changes). Minor version changes occur when bugs are fixed and/or new functionality is added in a way that is backward compatible. The DLL cannot load if its minor version is greater than that of the server because it may depend on such bug fixes or additional functionality in the server for its proper operation.

Example

#include "wsapi.h"
...

BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
{
    switch(fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            return(bind_wsapi(MAJOR_VERSION, MINOR_VERSION, FALSE));

        case DLL_PROCESS_DETACH:            // No process-wise cleanup
        case DLL_THREAD_ATTACH:             // No thread-wise initialization
        case DLL_THREAD_DETACH:             // No thread-wise cleanup
            return(TRUE);
    }
}

close_form_decoder

Syntax

void close_form_decoder(FORM_CTX ctx, TCTX *tp);
ctx
The opaque decoding context handle returned by a previous call to open_form_decoder().
tp
Transaction context pointer

Description

This function closes down the forms decoder instance created by a previous call to open_form_decoder(). Failing to call this for each successfull call to open_forms_decoder() will result in a memory leak. Therefore, place the call to close_form_decoder() in the __finally block of a try/finally statement, with the call to open_form_decoder() in the __try portion.

Example

See the example in the description of open_form_decoder() and the code in the formdump sample provided with WebSite.

construct_url

Syntax

void construct_url(char *dest, char *src, TCTX *tp)
dest
buffer to receive the constructed "full" URL
src
buffer containing the URL path
tp
Transaction context pointer

Description

This function constructs a complete URL (including the scheme, hostname, and port), given a URL path. The resultant URL has a scheme of http:// or https:// (if the connection is using SSL). The hostname and port number depend on the identity and port via which the current request arrived. If the port number is 80 (or 443 for an SSL connection), the port component of the URL is omitted.

Example

char dest[MED_STRING_LEN];
char *src = "/foo/bar.html";
...
construct_url(dest, src, tp);
The resulting complete URL might look like http://www.me.com/foo/bar.html

decode_next_field

Syntax

PFIELD decode_next_field(FORM_CTX ctx, TCTX *tp);
ctx
The opaque decoding context handle returned by a previous call to open_form_decoder().
tp
Transaction context pointer

Returns a thread-safe pointer to a FIELD structure:

typedef struct {                            // Field descriptor
	char name[MED_STRING_LEN];          // Field name
	BYTE *data;                         // -> field data
	DWORD len;                          // Field data length
	char ctype[MED_STRING_LEN];         // File content-type
	char xftype[MED_STRING_LEN];        // File content-transfer-encoding
	char fname[MED_STRING_LEN];         // Client's file name (file fields)
}FIELD, *PFIELD;
or NULL if there are no (more) fields to enumerate.

Description

Following a successful call to open_form_decoder(), each call to this function retrieves the name, contents and optional attributes of the "next" form field. This information is put into a FIELD structure as shown above, and the function returns a pointer to the structure. The structure is thread-safe; it remains valid until the next call to decode_next_field() with the given context handle.

Example

See the example in the description of open_form_decoder() and the code in the formdump sample provided with WebSite.

DbgDump

Syntax

void DbgDump (BYTE *buf, WORD len, char *label)
buf
Buffer containing bytes to dump
len
Number of bytes to dump
label
Label for the dump listing

Description

Mainframe style buffer dump. Writes a hex/ascii dump of the buffer to the server's log server.log.

Example

char buf[1024];
...
DbgDump(buf, 64, "Test dump
Dumps the first 64 bytes of buf. The output to server.log looks something like this:
10:10:46 Test dump [127.0.0.1] (64, 0x40)
-----|-------------------------------------|----------------
0000  48545450 2F312E30 20323030 204F4B0D   HTTP/1.0 200 OK.
0010  0A446174 653A2054 75657364 61792C20   .Date: Tuesday, 
0020  30352D53 65702D39 35203137 3A31303A   05-Sep-95 17:10:
0030  34362047 4D540D0A 53657276 65723A20   46 GMT..Server: 
0040  57656253 69746553 65637572 652F312E   WebSiteSecure/1.

die

Syntax

void die(int type, char *string, TCTX *tp)
type
HTTP status code (see Description for legal values)
string
status-specific string (see Description for usage)
tp
transaction context pointer

Description

This function provides your extension with a "clean exit", returning a properly formatted and worded HTTP status message to the client. The function never returns; the thread is terminated and cleaned up after returning the HTTP message. Use this only in a generator, pre-processor or post-processor. Do not use it in any other type of extension.

Die() can generate HTTP responses for the most common HTTP/1.0 status codes, providing the correctly worded reason phrases, and additional information provided in the string parameter. The status codes have corresponding symbolic definitions in wsapi.h. You should use the symbolic code. The following describes each of these status codes, and the usage of the string parameter. The symbolic status value is passed in the type parameter. For details on the meaning of each of these responses, see the HTTP/1.0 Specification. If you need to return a response not supported by die() you'll need to construct it yourself. Use send_http_header() to start the response.

204 (No Response)
The body of the response will contain "<string>, and there is nothing to return."
302 (Moved Temporarily)
string is the target URL. The HTTP header will contain both the (older) Location: and the (preferred) URI: forms of the redirection lines, each specifying the target URL. The body of the message will contain "This document has moved here", and the word here will be a hyperlink to the target URL. Normally, the browser will automatically fetch the target document, so the message body will not be seen by the browser user. It is included for broken browsers.
304 (Not Modified)
string is not used.
400 (Bad Request)
The body of the message will contain "The server could not handle your request. Reason: <string>".
401 (Unauthorized)
This generates an HTTP/1.0 WWW-Authenticate: header line, with string as the data for that line. Normally string should be something like Basic Realm="<whatever>". This causes the browser to display the username/password dialog with the realm as part of the prompt string.
403 (Forbidden)
The body of the message will contain <string>
404 (Not Found)
The body of the message will contain The requested URL was not found on this server: <string>
500 (Server Error)
The body of the message will contain The server encountered an internal error or misconfiguration and was unable to complete your request. Message: <string>... (additional text follows this).
501 (Not Implemented)
The body of the message will contain We are sorry to be unable to perform the method <string> with this URL... (additional text follows this).

Example

#include "wsapi.h"
die(REDIRECT, "http://other.web.site/foo.html", tp);

do_imagemap

Syntax

void do_imagemap(int method, char *map_name, char *coords, TCTX *tp)
method
The HTTP method to use (integer code, see wsapi.h)
map_name
The name of the imagemap (see description)
coords
coordinate string (see description)
tp
transaction context pointer

Description

Handle the current request as an imagemap. Handles traditional imagemaps using GET and an ISMAP image, as well as alternative use of a form with <INPUT TYPE=IMAGE>. Note: This supports only "nameless" fields here. If there's a name on the IMAGE field, it means in all likelihood it's part of a "real" form that would have to be handled by an extension or CGI form handler. Therefore, the form designer must not name imagemap fields. With this in mind, the coordinates can be in two forms, depending on the method in use:

GET (ISMAP): x,y (on URL)

GET/POST (FORM): x=x&y=y (on URL(GET), read from client(POST))

If the call specifies GET, the coordinate string is assumed to be in the transaction context block's args field. If the call specifies post, the function will read the coordinate string from the network as "content".

The function will return only if the resulting target URL is local (part of the local server's URL-space). If not, the function will generate a redirect and complete the transaction without returning. If the function does return, the server will have completed sending the local document, so in general you can simply call the ABORT macro to complete the transaction. This will log the request (including calling the logger extension if any).

map_name can be either a registry-resident imagemap or a file-based imagemap. The server tells the difference by looking at map_name and if there is no colon character present, it assumes that the imagemap is registry-resident. Otherwise, it assumes that map_name is a complete disk/directory/file pathname for the imagemap, which must be an NCSA-format map file.

The easiest way to use do_imagemap is shown in the example below.

Example

do_imagemap(M_GET, "d:\web-aux\maps\us.map", "125,90", tp);
ABORT;

escape_url

Syntax

void escape_url(/wsdocs/wsapi/char_buf/index.html)
buf
string that needs escaping according to the HTTP/1.0 rules.

Description

Escapes a string according to the conventions used in HTTP. The escape operation is performed in place, therefore the result may be longer than the original string. The buffer must be writeable.

Example

char buf[MED_STRING_LEN];

...

strcpy(buf, "/Name With Spaces/$$name.html");
escape_url(/wsdocs/wsapi/buf/index.html);

Returns with /Name%20with%20Spaces/%14%14name.html in buf.


evaluate_access

Syntax

void evaluate_access(char *url, TCTX *tp)
url
string containing URL path of object
tp
Transaction context pointer
May not return (see description)

Description

Evaluate access control for the given URL. If access is allowed, the tp->allow field is set TRUE and the tp->allow_options field is set with the access options bitmask. The bits in the bitmask are defined in wsapi.h and are:
OPTION SYMBOL           DESCRIPTION
----------------------- ---------------------------------------------
SECOPT_SSL_ONLY         Access permitted via SSL only
SECOPTS_OR_CLASS_USERS  Access granted to user OR host address
SECOPTS_NO_BROWSE       Disallow directory browsing
Normally, you won't be concerned about the options. They are used by evaluate_access itself, and internally by the server. They are provided for your information, however.

If access fails for lack of user authentication this function does not return. The server sends a 401 Not Authorized message to the browser, causing the username/password dialog to appear. If the user enters a username and password, the browser will reissue the same request again with the new username and password.

If access fails because the client IP address or hostname is disallowed, or access requires SSL and the connection is not SSL, or if the URL specifies a directory and browsing is locked out, the function returns with tp->allow set to FALSE. In this case, you are free to handle the issue any way you wish.

The function will fail via an exception if access control fails. In general, you need to be concerned about this only if you have allocated memory that needs to be freed or handles that need to be closed. In this case, you should guard the call with a try/finally or a try/except block as appropriate to your application. Do not dismiss these exceptions under any circumstances. They are used for proper completion of the transaction.

Example

evaluate_access("/docs/private/sales_3Q.html", tp);

exec_cgi

Syntax

void exec_cgi(char *meth, char *file, char *args, int intfc, TCTX *tp)
meth
Method (e.g., POST, PUT)
file
Full physical pathname of the executable or "associated" document
args
URL arguments ("query string"), must not be NULL
intfc
CGI interface to use (e.g., SCRIPT_WIN, see wsapi.h).
tp
transaction context pointer
May not return (see description)

Description

High level interface to the server's CGI handler. This function will execute a CGI script or program using the selected method and CGI interface, and send the results to the browser. The function may not return, e.g., if the CGI program returns a Location: or URI: header, or if it fails access control. Errors will use the ABORT macro and will not return either. If the function does return, the response from the CGI program has been sent to the browser and the transaction is finished.

WebSite has three CGI interfaces: Windows, DOS and Standard. This function can be used to execute a CGI program using any one of these interfaces. See wsapi.h for the symbolic codes used to select the interface. The function url_to_file() returns the document type, which for a CGI type document, can be used to select the CGI interface.

The function will fail via an exception if access control fails, if the CGI returns Location: or URI:, or (using the ABORT macro) on a variety of network I/O problems. In general, you need to be concerned about these only if you have allocated memory that needs to be freed or handles that need to be closed. In this case, you should guard the call with a try/finally or a try/except block as appropriate to your application. Do not dismiss these exceptions under any circumstances. They are used for proper completion of the transaction.

Example

exec_cgi ("GET",
"C:\\website\\cgi-win\\foo.exe",
"search=abcd&type=starts",
SCRIPT_WIN, tp);

exec_cgi_to_file

Syntax

void exec_cgi_to_file(char *meth, char *file, char *args, int intfc, TCTX *tp)
meth
Method (e.g., POST, PUT)
file
Full physical pathname of the executable or "associated" document
args
URL arguments ("query string"), must not be NULL
intfc
CGI interface to use (e.g., SCRIPT_WIN, see wsapi.h).
tp
transaction context pointer
May not return (see description)

Description

Identical to the exec_cgi() function, except that the output of the CGI program is not sent to the client. Rather, the function returns with the spooled output of the CGI program open on a temporary file. The handle of the open file is in tp->hOutFile. It will include any HTTP headers generated by the CGI program as well as any content. You must close this file when you are finished with it, before you let the transaction complete.

Example

exec_cgi_to_file ("GET", // Exec to a temp file
"C:\\website\\cgi-win\\foo.exe",
"search=abcd&type=starts",
SCRIPT_WIN, tp);
ReadFile(tp->hOutFile, ...); // Read CGI output

file_to_url

Syntax

void file_to_url(char *path, TCTX *tp)
path
full file pathname (including drive spec)
tp
transaction context pointer

Description

File path to URL ("reverse") mapping. The opposite of url_to_file(). Translates a physical file pathname to a URL for the file. The conversion is done in place, therefore the buffer containing the URL pathname must be writeable. This translation depends on a unique relationship between the physical pathname and the URL. Redundant mappings can result in unpredictable results.

Example

char buf[MAX_STRING_LEN];
...
strcpy(buf, "c:\\website\\cgi-win\\test.exe");
file_to_url(/wsdocs/wsapi/buf/index.html);

The result will be something like /cgi-win/test.exe.


get_content_type

Syntax

char *get_content_type(char *file, TCTX *tp)
file
filename of the file for which the content type is desired
tp
transaction context pointer
Returns HTTP/MIME content type in allocated string.

Description

Get the HTTP/MIME content type of the given file. This information is taken from WebSte's registry-based content type mapping table, which uses the file's "extension" as the key. If the filename does not contain a period, the "default" content type (usually application/octet-stream) is returned. The function returns a pointer to the content type string in allocated memory. Depending on how this is used, you may need to free this space to avoid memory leaks.

Example

char *cp;
...
cp = get_content_type("abc.gif", tp);

Completes with allocated string containing (most likely) image/gif.


get_server_variable

Syntax

BOOL get_server_variable(char *name, char *buf, DWORD size, TCB *tp)
name
the CGI-style name of the variable to get
buf
the buffer into which the value of the variable is placed
size
The length in bytes of buf. Overflow truncates the value string.
tp
transaction context pointer
Returns TRUE if the named variable exists (it still may be empty) and FALSE if there is no such named variable.

Description

This function is provided for users who are upgrading from Microsoft ISAPI or Standard CGI to WSAPI. It simply provides a way to access data that is contained in the transaction context block (TCTX) using CGI-style "environment variable" names. This is a superset of the variables supported by ISAPI and most CGI interfaces. Compatibility names have been provided as well.

get_server_variable() is less efficient than reading data directly from the TCTX, so you should do the latter if at all practical. Also note that the names used here are the "NCSA" style names, for maximum compatility with ported applications. Name matching is caseless.

The following ISAPI/CGI-style named variables are supported by get_server_variable():

Supported CGI-Style Variables
Variable Name Description
Server Information
DEBUG_MODE If WebSite's API/CGI tracing switch is on, this is "YES", otherwise it is "NO"
DOCUMENT_ROOT The physical directory path corresponding to the URL "/index.html" for the current request. May vary if multi-homing is in use.
GATEWAY_INTERFACE The name and version of the gateway interface (e.g. "WSAPI/1.1")
GMT_OFFSET Offset of local time from GMT, seconds, negative west of GMT (PST is -28800, 8 hours west)
SERVER_ADMIN The email address of the server's administrator
SERVER_NAME The server's current hostname (will vary if multi-homing is used)
SERVER_PORT The TCP port on which the server received the current request (different ports are used for SSL and "normal").
SERVER_PROTOCOL The name and version of the server's protocol ("HTTP/1.0")
SERVER_SOFTWARE The name and version of the server software (e.g. "WebSitePro/1.2")
Client Info
HTTP_ACCEPT List of media content types (and possibly Q-values) that the client will accept
HTTP_ACCEPT_LANGUAGE List of languages that the client will accept
HTTP_FROM Email address of the client user (not currently supported by browsers)
HTTP_KEEP_ALIVE If the client supports keep-alive, this will be YES, otherwise it will be NO
HTTP_USER_AGENT The name and version of the client (browser) software
REMOTE_ADDR The IP address of the remote (client) host or proxy gateway.
REMOTE_HOST The DNS hostname of the remote (client) host (only if DNS reverse lookup is enabled, else this is identical to REMOTE_ADDR)
REMOTE_USER Identical to AUTH_USER. Provided for compatibility.
Client Authentication (present only if client sends authentication data)
AUTH_NAME The realm from which user and group names are taken. WebSite supports multiple realms.
AUTH_PASSWORD The password furnished with the authentication data
AUTH_TYPE The authentication type. Currently always "BASIC"
AUTH_USER The username furnished with the authentication data
Request Info
CONTENT_LENGTH Length in bytes of data sent with the request (e.g., form data)
CONTENT_TYPE Media content type of data sent with the request (e.g. multipart/form-data) Includes parameters such as boundary strings.
HTTP_REQUEST_RANGE Range spec(s) sent with request. See current HTTP byte-range spec for details.
PATH_INFO "Extra" path information from the URL, also known as the "logical path"
PATH_TRANSLATED The translation of PATH_INFO to a physical path, using the current mapping. May vary if multi-homing is in use.
QUERY_STRING Data from the URL that follows the "?" in its raw original form
QUERY_STRING_UNESCAPED Translation of QUERY_STRING from raw to final form (plus to space and URL unescaping)
REQUEST_METHOD The HTTP method specified with the request (e.g., "GET", "POST")
SCRIPT_NAME The URL path of the WSAPI extension, suitable for making self-referencing URLs
HTTP Extra Headers Any header not assigned to one of the above variables may be accessed by it's header label, or as part of the ALL_HTTP list (provided for ISAPI compatibility)
<extra-header-name> Returns the value of that header. For example "HTTP-Cookie" will get the cookie string sent with the request. Useful with SHTTP.
ALL_HTTP All HTTP headers that are not assigned to one of the above variables. These variables are of the form HTTP_ for compatibility with ISAPI. The headers consist of a linefeed-separated list of <name>=<value> pairs.

Example

char buf[MAX_STRING_LEN];
BOOL bExists;
...
bExists = get_server_variable("SERVER_SOFTWARE", buf, sizeof(/wsdocs/wsapi/buf/index.html)-1, tp);

get_temp_name

Syntax

void get_temp_name(/wsdocs/wsapi/char_buf/index.html)
buf
buffer to receive the tempfile name (see below)

Description

Generate a unique name for temporary files. The form of the returned string is xxxxxxws where the xxxxxx is a hexadecimal number, up to six digits, without leading zeroes. This name is guaranteed to be unique among other such names generated by WebSite, but not system-wide. Therefore, it is strongly suggested that you create all temporary files in WebSite's CGI temporary directory. The path to this directory is contained in tp->temp_name.

Example

char buf[16];
...
get_temp_name(/wsdocs/wsapi/buf/index.html);

GetRegBin

Syntax

DWORD GetRegBin(char *name, HKEY hKey)
name
name of 4-byte REG_BIN or REG_DWORD value to get
hKey
handle of key under which the value is located

Description

Get a 4-byte binary value from the registry. Works with either 4-byte REG_BIN or REG_DWORD values. If the named value does not exist, or if it is not one of these types, this function generates an exception via the ABORT macro. You can trap these with a try/except block.

Example

DWORD foo;
HKEY hKey;
...
hKey = OpenRegKey("SOFTWARE\\Denny\\WebServer\\CurrentVersion");
foo = GetRegBin("LowTime", hKey); RegCloseKey(hKey);

GetRegString

Syntax

Char *GetRegString(char *name, HKEY hKey)
name
name of 4-byte REG_BIN or REG_DWORD value to get
hKey
handle of key under which the value is located
Returns a pointer to an allocated string

Description

Get a string value from the registry. If the named value does not exist, or if it is not one of these types, this function generates an exception via the ABORT macro. You can trap these with a try/except block. The string is created in allocated space. Depending on how the string is going to be used, you may have to free this to avoid memory leaks.

Example

char *foo;
HKEY hKey;
...
hKey = OpenRegKey("SOFTWARE\\Denny\\WebServer\\CurrentVersion");
foo = GetRegString("FilePath", hKey);
RegCloseKey(hKey);
...
free(foo); // Be careful!

http_nt_timestr

Syntax

char *http_nt_timestr(LPSYSTEMTIME pst, char *buf, int len)
pst
Address of a SYSTEMTIME structure (GMT)
buf
Buffer into which the HTTP/1.0 date-time string is put
len
Length in bytes of buf
Returns buf

Description

Creates a date/time string, in the format required for HTTP headers, from a Win32 SYSTEMTIME structure. Do not use local time. This function assumes that (as usual) the SYSTEMTIME is in GMT. If the buffer is too small, the string is truncated.

Example

char buf[SML_STRING_LEN];
SYSTEMTIME st;
...
GetSystemTime(&st); // Not GetLocalTime()!!!
http_nt_timestr(&st, buf, sizeof(/wsdocs/wsapi/buf/index.html)); // Get HTTP-compliant "now"

http_timestr

Syntax

#include <time.h>
...
char *http_timestr(time_t sec, char *buf, int len)
sec
C Runtime time value (e.g. from the time() function)
buf
Buffer into which the HTTP/1.0 date-time string is put
len
Length in bytes of buf
Returns buf

Description

Creates a date/time string, in the format required for HTTP headers, from Unix/C runtime time. If the buffer is too small, the string is truncated.

Example

#include <time.h>
char buf[SML_STRING_LEN];
...
http_timestr(time(NULL), buf, sizeof(/wsdocs/wsapi/buf/index.html)); // Get HTTP-compliant "now"

O'Reilly Tech Support <support@ora.com>