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

later_than

Syntax

BOOL later_than(char *t1, char *t2)
t1
HTTP-compliant date/time to test
t2
HTTP-compliant date/time to test against
Returns TRUE only if t1 is later than t2

Description

Compare times in HTTP-compliant string format. This function is exposed so that you can do your own "If Modified Since" support. You can use http_timestr() or http_nt_timestr() to get properly formatted string(s).

Example

struct stat fi;
char *cp;
FILE *myfp;
...
fstat(fileno(myfp), &fi);
strcpy(tp->last_modified, http_timestr(fi.st_mtime));
if(tp->if_modified_since[0] != '\0' &&
!later_than(cp, tp->if_modified_since))
die(USE_LOCAL_COPY, NULL, tp);

MD5Init

Syntax

void MD5Init(MD5Context *ctx);
ctx
Address of an MD5 context block

Description

Call this function to set up an MD5 digest. The structure definition and typedef for MD5Context is in wsapi.h. See also MD5Update() and MD5Final(). See RFC 1321: The MD5 Message-Digest Algorithm for more information on MD5 itself.

Example

See the example in MD5Update().

MD5Update

Syntax

void MD5Update(MD5Context *ctx, BYTE *buf, DWORD len);
ctx
Address of an (at least) initialized MD5 context block
buf
Buffer containing data to be added to the digest
len
Length in bytes of the data in the buffer to be added to the digest

Description

Use this function to add data to the digest. You may call this fucntion as many times as you want, with buffers of any size. The MD5Context structure must be initialized using MD5Init() before calling this function for the first time.

See Also MD5Init() and MD5Final(). See RFC 1321: The MD5 Message-Digest Algorithm for more information on MD5 itself.

Example

//
// Determine the MD5 digest of a string. Returns 16 bytes
// (digest is a 128 bit number). No regard for byte-ordering
// here, as Intel is a little-endian machine. You may need
// the bytes ordered differently!
//
void MDString(char *str, BYTE digest[16]) {
    MD5Context ctx;

    MD5Init(&ctx;);
    MD5Update(&ctx;, str, strlen(str));
	MD5Final(digest, &ctx;);
}

MD5Final

Syntax

void MD5Final(BYTE digest[16}, MD5Context *ctx);
digest
A 16-byte array into which the digest is put
ctx
Address of the MD5 context block used to accumulate the digest

Description

Once you have accumulated all the data you want into the digest, call this function to complete the digest and fill it into the specified 16-byte buffer. Once the digest has been copied, this function zeroes the context block to remove any traces of the operation.

See Also MD5Init() and MD5Update(). See RFC 1321: The MD5 Message-Digest Algorithm for more information on MD5 itself.

Example

See the example in MD5Update().

nflush

Syntax

void nflush(TCTX *tp)
tp
transaction context pointer

Description

Flush the network output buffer. Call this when you want to force all remaining data out to the network (and to the client). Useful mostly in server-push applications. The function will fail via an exception (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. 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

nflush(tp); // Force remaining data to browser

ngets

Syntax

void ngets(char *buf, int max, TCTX *tp)
buf
Address of buffer to receive next line of data from client
max
Maximum length of line (safety stop)
tp
transaction context pointer

Description

Get the next "line" of data from the browser. A line is a string ending in a linefeed character (0x0A). If the line length exceeds max, the function generates an exception via the ABORT macro and does not return. It also generates exceptions 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. 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. If you call this when there is no complete line available for input, the call will hang for the Read Timeout (as set in the server's property sheet) then fail via an exception.

Example

char buf[MED_STRING_LEN];
...
ngets(buf, MED_STRING_LEN, tp);

normalize_url

Syntax

BOOL normalize_url(/wsdocs/wsapi/char_path/index.html)
path
URL path (only, no scheme/host/port)
Return TRUE if any modifications were made to the URL

Description

Remove redundant or unsafe syntax from a URL. Remove multiple /s, change ./ to /, remove things like foo/../ and trailing /. This function is useful when comparing a URL to a reference. If the URL has spurious syntax, the match will fail, however the URL may still translate into a usable file path.

The return value, if TRUE, can be used to generate a redirect response to the cliet with the cleaned-up path. The server does this automatically on simple GET URLs.

Example

char buf[MAX_STRING_LEN];
BOOL bMod;
...
strcpy(buf, "/foo/../bar/././//./xyz.html");
bMod = normalize_url(/wsdocs/wsapi/buf/index.html); // Results in /bar/xyz.html, returns TRUE

nputs

Syntax

void nputs(char *str, TCTX *tp)
str
Address of string to send to the client
tp
transaction context pointer

Description

Buffered write of a string to the client. The string may be any length. Line terminators are not significant. The data will be actually sent to the client only when the internal WebSite net buffer is full, or when you call nflush(). The function will fail via an exception (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. 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

nputs("X-Special-Header: Fun-n-games\015\012", tp);1 // HTTP headers CRLF terminated

nread

Syntax

void nread(char *buf, long nreq, TCTX *tp)
buf
address of buffer to receive data
nreq
number of bytes to read
tp
transaction context pointer

Description

Read specified number of bytes from the client. The function generates exceptions 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. 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. If you call this when there fewer than nreq bytes available for input, the call will hang for the Read Timeout (as set in the server's property sheet) then fail via an exception.

Example

char buf[MAX_STRING_LEN];
...
if(tp->content_length > (MAX_STRING_LEN - 1))
die(SERVER_ERROR, "Content exceeded internal buffer size.", tp);
nread(buf, tp->content_length, tp);

nreadf

Syntax

void nreadf(HANDLE hFile, long nreq, TCTX *tp)
hFile
Win32 open file handle
nreq
number of bytes to read
tp
transaction context pointer

Description

Efficient read of specified number of bytes from the client directly into an open file. The file must be open for write. The function generates exceptions on file and 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 handle(s) 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. If you call this when there fewer than nreq bytes available for input, the call will hang for the Read Timeout (as set in the server's property sheet) then fail via an exception.

Example

HANDLE hFile;
...
hFile = CreateFile(...
...
__try
{
nreadf(hFile, tp->content_length, tp);
}
__finally
{
CloseHandle(hFile); // Avoid file handle leaks
}

nwrite

Syntax

void nwrite(char *buf, int nreq, TCB *tp)
buf
Buffer containing bytes to write to client
nreq
Number of bytes to write from buffer
tp
transaction context pointer

Description

Buffered write to the client. The buffer may be any length. The data will be actually sent to the client only when the internal WebSite net buffer is full, or when you call nflush(). The function will fail via an exception (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. 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

nwrite(buf, 1200, tp);1

nwritef

Syntax

void nwritef(HANDLE hFile, DWORD dwStartPos, DWORD dwCount, TCB *tp)
hFile
Win32 open file handle
dwStartPos
Starting byte position in file (0-based)
dwCount
Number of bytes to send
tp
transaction context pointer

Description

Efficient direct (unbuffered) write from open file (from given offset to end-of-file) to client. This function first calls nflush() to empty the WebSite internal network output buffer, then transmits the file using memory-mapped I/O. The function will fail via an exception (using the ABORT macro) on a variety of network I/O problems. In general, you need to be concerned about these in order to close the file handle and/or if you have allocated memory that needs to be freed. 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

char *fn = "c:\\foo\\bar.html";
HANDLE hFile;
BY_HANDLE_FILE_INFORMATION finfo;
SYSTEMTIME stLastModGMT;
...
hFile = CreateFile(fn, ...);
set_content_type(fn, tp);
GetFileInformationByHandle(hFile, &finfo);     // Get file info
tp->content_length = finfo.nFileSizeLow;       // File must be < 2GB!
//
// Set up HTTP Last-Modified. The SYSTEMTIME is assumed to be in GMT!
//
FileTimeToSystemTime(&(finfo.ftLastWriteTime), &stLastModGMT);
http_nt_timestr(&stLastModGMT, tp->last_modified, sizeof(tp->last_modified));
//
// Add an "extra header" field to the HTTP header
// 
if(tp->num_rsp_xhdr < MAX_EXT_HEADERS)
{
    tp->rsp_xhdr[tp->num_rsp_xhdr].key = wsapi_strdup("X-Special", tp);
    tp->rsp_xhdr[tp->num_rsp_xhdr++].value = wsapi_strdup("Some info", tp);
//           NOTE! --------------^^
}

//
// Send the HTTP header, then the file itself.
//
send_http_header(tp, TRUE);
__try
{
    nwritef(hFile, tp);        // This may generate an exception...
}
__finally
{
    CloseHandle(hFile);        // This prevents file handle leaks
}

open_form_decoder

Syntax

FORM_CTX open_form_decoder(BYTE *data, DWORD len, TCTX *tp)
data
Pointer to the form data in memory, plus a terminating null character.
len
The length in bytes of the form data in memory.
tp
transaction context pointer

Returns an opaque context handle (FORM_CTX as defined in wsapi.h), which is used in subsequent calls to decode_next_field(), and eventually, close_form_decoder().

Description

Initializes the WSAPI form decoder for subsequent enumeration of the fields in the form via calls to decode_next_field(). The decoder engine is optimized to do in-memory scanning and conversion, rather than relying on slower streaming techniques. This means that the whole of the posted form data must reside in a read/write memory block. This may conveniently be created by allocating tp->content-length + 1 bytes using wsapi_malloc(), then reading tp->content-length bytes into the block with a single call to nread().

The WSAPI form decoder transparently handles both form data encoding types (application/x-www-form-urlencoded and multipart/form-data). This means that WSAPI generators that use the decoder with forms need not be concerned with the encoding used in a form. It also means that the new forms-based file uploading feature of some browsers is supported by the decoder.

Example:

FRM_CTX ctx;
FIELD *fp;
BYTE *pdata;
DWORD dlen;
...
dlen = tp->content_length;
pdata=wsapi_malloc((dlen+ 1), tp); // Allocate space for form data & null
pdata[dlen] = '\0';                // Terminating null, required!
//
// Guard the rest against network errors, etc.
//
__try
{
    nread(pdata, dlen, tp);        // Read all form data
    ctx = open_form_decoder(pdata, dlen, tp);  // Initialize the decoder
    while((fp = decode_next_field(ctx, tp)) != NULL)
    {
        ... do what you like with the field data
        ... accessible via fp->
    }
}
__finally                         // Assure proper memory cleanup!
{
    close_form_decoder(ctx, tp);
    wsapi_free(pdata);
}

OpenRegKey

Syntax

HKEY OpenRegKey(char *key)
key
String containing the key name, relative to HKEY_LOCAL_MACHINE

Description

Open a registry key. If the key does not exist, this function generates an exception via the ABORT macro. You can trap these with a try/except block for cleanup purposes.

Example

HKEY hKey;
...
hKey = OpenRegKey("SOFTWARE\\Denny\\WebServer\\CurrentVersion");

plus_to_space

Syntax

void plus_to_space(char *str)
str
String containing plus-separated components

Description

Convert plus characters in a string to space characters. The inverse of space_to_plus(). Generally used together with unescape_url(). The conversion is done in place, therefore the buffer containing the string must be writeable.

Example

char buf[SML_STRING_LEN];
...
strcpy(buf, "This+is+a+test");
plus_to_space(/wsdocs/wsapi/buf/index.html); // Results in "This is a test"

process_get

Syntax

void process_get(char *meth, char *url, char *args, TCTX *tp)
meth
method, GET or HEAD (only!)
url
URL path only (absolute, must start with /)
args
URL arguments (query string), must not be NULL
tp
transaction context pointer

Description

High-level interface to the server's GET handler. Use this to cause the server to act as though the client issued a GET for the specified URL and arguments. When the function returns, the target document will have been sent to the client.

The function will fail via an exception (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

process_get("GET", "/", "", tp);1 // Return home page
O'Reilly Tech Support <support@ora.com>