
WebSite API 1.1 SDK
Server Function Descriptions
15-September-97
Index
Syntax
void send_http_header(TCTX *tp, BOOL do_xhdr)
- 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):
- 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.
- 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.
- 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));
//
// 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
}
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.
Example
See the example in send_http_header()
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(buf); // 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.
Example
TrueRandAddNoise(0); // Add entropy to the RNG
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();
TrueRandAddNoise((DWORD)ch);
}
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();
Syntax
void TrueRandGetBytes(BYTE *buf,
DWORD len)
- buf
- buffer to receive random bytes
- 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);
Syntax
void unescape_url(char *url)
- 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(buf);
Returns with /Name with Spaces/$$name.html
in buf.
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.
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.
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");
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!
}
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!
}
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>