# WebSite API 1.1 SDK Server Function Descriptions

15-September-97

## Index

### Syntax

tp
transaction context pointer
do_xhdr
if true, send extra headers if any (see description)

### Description

Send the HTTP header. This function handles all of the work in sending a properly formatted HTTP/1.0 header to the client, including the blank "separator" line. Normally (see below for exceptions), the HTTP status code is 200 and the reason phrase is OK. At a minimum, the following is sent:
HTTP/1.0 200 OK
Date: Thursday, 07-Sep-1995 23:21:37 GMT
Server: WebSite/1.1
Allow-Ranges: bytes
You can control the status code and reason phrase as follows (in order of priority):
1. If you fill a string (e.g. "404 Not Found")into the ret_status string in the TCTX, that status code and reason phrase will be sent.
2. If you put a URL into the location field of the TCTX (and the ret_status field is empty), A 302 Moved Temporarily response (redirect) will result.
3. If neither (1) or (2) are true, this function sends 200 OK.
WARNING: Explicitly set tp->location[0] = '\0'; before calling this function (just to be safe) unless you want to redirect. Option 2 is mainly for the server's internal logic.

NOTE: It's easier to send a redirect using the die() function. In addition, some browsers will choke on a "full" 302 response if keep-alive is in effect. die() automatically chooses a "brief" or "full" response format for redirects depending on whether keep-alive is in effect.

In addition, depending on the contents of some fields in the transaction context block (TCTX), additional HTTP headers may be included. If the fields are not empty strings (or not -1 in the case of content length), the corresponding header lines are included:

TCTX Field Header Sent Not Sent if
tp->content_type Content-Type: empty string
tp->last_modified Last-Modified: empty string
tp->content_length Content-Length: -1 (minus one)
tp->content_encoding Content-Encoding: empty string
tp->keep_alive Connection: Keep-Alive
not TRUE (client's state controls this)

Finally, any HTTP extra headers that may have been added to the TCTX will be sent if the do_xhdr parameter is TRUE.

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

//
//
{
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.
//
__try
{
nwritef(hFile, tp);        // This may generate an exception...
}
__finally
{
CloseHandle(hFile);        // This prevents file handle leaks
}

## set_content_type

### Syntax

void set_content_type(char *file, TCTX *tp)
file
full physical pathname of the file
tp
transaction context pointer

### Description

Fill in the tp->content_type field with the HTTP/MIME content type, given the full file pathname.

## space_to_plus

### Syntax

void space_to_plus(char *str)
str
String to convert from spaces to pluses, according to HTTP encoding rules

### Description

Transliterate a string, converting spaces to pluses. The inverse of plus_to_space(). Generally used in combination with escape_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.");
space_to_plus(/wsdocs/wsapi/buf/index.html); // Produces "This+is+a+test"

### Syntax

void TrueRandGetNoise(DWORD data)
data
A 32-bit noise-enhancer (see Description)

### Description

Add entropy to the server's cryptographically secure random number generator. The significant aspect of making this call is its timing, not the data parameter. Call this function only if you know the event that triggers the call is truly random in its timing. User's keystroke timing is a good example. The 32-bit data value can be anything that adds to the variation in the event. It doesn't add much to the randomness, so if you are in doubt, just pass zero for data.

The server adds entropy each time it receives a request from the net, using the time differences between received requests. This is a high quality source of random events.

## TrueRandEntropy

### Syntax

DWORD TrueRandEntropy(void)

### Description

Get the current estimated entropy in the server's cryptographically secure random number generator (RNG). The returned value is an estimate of the number of bits of entropy available from the RNG.

### Example:

DWORD ent, ent_req;
...
ent_req = 1024;                     // Generating 1024 bit RSA keypair
while(TrueRandEntropy() < ent_req)  // Gather entropy as needed
{
char ch;

ch = wait_for_keystroke();
}

## TrueRandGetByte

### Syntax

BYTE TrueRandGetByte(void)

### Description

Get a single random byte from the server's cryptographically secure random number generator (RNG).. Reduces the entropy in the random number pool by 8 bits.

### Example

BYTE b;
...
b = TrueRandGetByte();

## TrueRandGetBytes

### Syntax

void TrueRandGetBytes(BYTE *buf, DWORD len)
buf
len
number of random bytes to get

### Description

Retrieve multiple bytes from the server's cryptographically secure random number generator (RNG). The bytes are copied into the caller's buffer. Reduces the entropy by 8*len bits.

### Example

BYTE key[KEYSIZE];
...
TrueRandGetBytes(key, KEYSIZE);

## unescape_url

### Syntax

void unescape_url(/wsdocs/wsapi/char_url/index.html)
url
string containing data that is escaped according to HTTP/1.0 rules

### Description

Remove HTTP/1.0 escaping from string. The string is converted into a form with the real characters instead of the HTTP/1.0 escape sequences. The conversion is done in place, therefore the buffer containing the URL pathname must be writeable.

### Example

char buf[MED_STRING_LEN];
...
strcpy(buf, "/Name%20with%20Spaces/%14%14name.html
");
unescape_url(/wsdocs/wsapi/buf/index.html);

Returns with /Name with Spaces/name.html in buf.

## url_to_file

### Syntax

int url_to_file(char *pathname, BOOL do_index, TCTX *tp)
path
pathname in URL-space
do_index
TRUE to add "index" document if directory URL, else FALSE
tp
transaction context pointer
Returns the object type for the mapping that was used (e.g., STD_DOCUMENT). See wsapi.h.

### Description

URL to file path mapping. The opposite of file_to_url(). Translates a URL-space pathname to a physical file pathname or redirection URL. 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 URL and the physical pathname. Redundant mappings can result in unpredictable results.

If do_index is TRUE, the returned string will include the "index" (or default) document if the original URL is a directory URL and an index file is present in the directory. Note that the default document specification usually used with WebSite is index.*, so this document is not necessarily index.html. Check the MIME content type of the returned document before making any decisions.

The return value indicates the object type of the URL target. If the URL resolved via the document map, the return value will be STD_DOCUMENT and the result will be a physical file pathname. If the URL resolved via one of the CGI maps, the return value will be one of the CGI object types (e.g., SCRIPT_WIN) and the result will be a physical file pathname. If the URL resolved via the redirection map, the return value will be REDIRECT_URL and the result will be the new (redirected) URL.

### Example

char buf[MAX_STRING_LEN];
int type;
...
strcpy(buf, "/cgi-win/test.exe");
type = url_to_file(buf, tp);

The result in buf will be something like c:\website\cgi-win\test.exe and the return value will be SCRIPT_WIN.

## wsapi_free

### Syntax

void *wsapi_free(void *ptr)
ptr
Pointer to memory allocated by wsapi_malloc, wsapi_realloc, or wsapi_strdup.

### Description

Must be used to free memory allocated by wsapi_malloc, wsapi_realloc, or wsapi_strdup.

## wsapi_log_event

### Syntax

void wsapi_log_event(HANDLE hDll, char *msg)
hDll
Handle of your extension DLL, passed as the first parameter to the DLLMain function.
msg
The message you wish to log

### Description

Log a message to the server's log (server.log_, and if on Windows NT, to the NT Event Log as well. Call this to log a message for the administrator. The message parameter is used to format a message that looks like this: "The <type> DLL <path> logged <msg>", where <type> is the extension type (e.g., pre-processor, generator), <path> is the DLL's pathname as it appears in the registry, and <message> is your message parameter. For example:
The post-processor DLL C:\website\wsapi\pagecnt.dll logged: I am happy!

### Example

static HINSTANCE _hDll;
...
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
{
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
_hDll = hInstDLL;
return(bind_wsapi(MAJOR_VERSION, MINOR_VERSION, FALSE));
...
void some_other_function(...
{
...
wsapi_log_event(_hDll, "Hello from my WSAPI extension");

## wsapi_malloc

### Syntax

void *wsapi_malloc(long size, TCTX *tp)
size
number of bytes to allocate
tp
transaction context pointer
Returns a typeless pointer to the allocated memory which must be freed using wsapi_free.

### Description

Allocate memory in the server's heap zone via the C runtime library malloc() service, with error control. The function will fail via an exception (using the ABORT macro) on allocation failure. In general, you need to be concerned about these only if you have allocated other 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

struct foo *p1;
struct bar *p2;
...
__try
{
p1 = p2 = NULL;                       // Sentinels
p1 = wsapi_malloc(sizeof(*p1), tp);
p2 = wsapi_malloc(sizeof(*p2), tp);
}
__except(EXCEPTION_EXCUTE_HANDLER)
{
if(p1) wsapi_free(p1);                // Safely free any allocations
if(p2) wsapi_free(p2);
ABORT;              // DO NOT DISMISS THE EXCEPTION!
}

## wsapi_realloc

### Syntax

void *wsapi_realloc(void *ptr, long size, TCB *tp)
ptr
Address of a previously allocated memory block
size
new size for allocation
tp
transaction context pointer
Returns a (possibly changed) typeless pointer to the re-sized block of memory which must be freed using wsapi_free.

### Description

Re-size a memory block via the C runtime library realloc() service, with error control. The function will fail via an exception (using the ABORT macro) on allocation failure. In general, you need to be concerned about these only if you have allocated other 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

struct foo *p1;
struct bar *p2;
...
__try
{
p1 = p2 = NULL;                       // Sentinels
p1 = wsapi_malloc(sizeof(*p1), tp);
p2 = wsapi_malloc(sizeof(*p2), tp);
...
p2 = wsapi_realloc(p2, (sizeof(*p2) + 1024), tp);
}
__except(EXCEPTION_EXCUTE_HANDLER)
{
if(p1) wsapi_free(p1);                // Safely free any allocations
if(p2) wsapi_free(p2);
ABORT;              // DO NOT DISMISS THE EXCEPTION!
}

## wsapi_strdup

### Syntax

char *wsapi_strdup(char *str, TCTX *tp)

str address of string to duplicate

tp transaction context pointer

Returns a pointer to a copy of the string in allocated memory, which must be freed using wsapi_free.

### Description

Duplicate a string into allocated memory. The function will fail via an exception (using the ABORT macro) on allocation failure. In general, you need to be concerned about these only if you have allocated other 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. You must wsapi_free this space unless it is attached to a transaction context field that you know will be freed by the server during transaction cleanup. See the documentation on the TCTX fields for more information.

### Example

char *name = NULL;                // Sentinel
...
__try
{
name = wsapi_strdup("This is a test", tp);
...
}
__finally
{
if(name) wsapi_free(name);    // Safe free
...
}

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