## PowerWeb Server++ API

### Bypass CGI Performance and Capability Limitations!

PowerWeb Server++ APIs let you create custom applications and services with languages such as Rexx and C, independently of CompuSource. The APIs let you modify all aspects of the server's operation at several different levels. The APIs are not limited to script execution. With PowerWeb APIs, you extend the server at no cost in performance, and you only override those facilities that you need to. The PowerWeb APIs and PowerWeb Macros share a common access method for manipulating the PowerWeb Server++ status variables.

## Table of Contents

> Introduction

> Why not CGI?

> PowerWeb API Syntax

> Compiling Your API Hook

> Where to Store Your API Hook Module

> Using an API Hook within HTML

> Associating an API Hook with a Resource

> Sample Code

> PowerWeb Global API Reference

> > Encryption
> > Implement a new encryption algorithm.

> > Encoding
> > Implement a new encoding algorithm for packing data.

> > TraceLog
> > Store trace information where and how you want to.

> PowerWeb Server API Reference

> > ServerInitialisation
> > Perform initialisation tasks when the server starts up.

> > ServerTermination
> > Perform termination tasks when the server shuts down.

> > ResourceNameTranslation
> > Translates a virtual URL into a physical filename.

> > ErrorLog
> > Store error log information where and how you want to.

> > AuditLog
> > Store audit trail information where and how you want to.

> PowerWeb Resource API Reference

> > UserAuthentication
> > Authenticates the user.

> > AccessControl
> > Determines whether the client has access permission.

> > ResourceType
> > Determines the MIME type and MIME encoding of the resource.

> > CommandProcessing
> > Executes the extended equivalent of a CGI script.

> > ServerInclusions
> > Processes unrecognised Web Macros and server-side includes.

> PowerWeb API Functions

> PowerWeb C Library

> PowerWeb Rexx Library

## Introduction

PowerWeb Server++ APIs are calls to libraries written by the WebMaster or an associated programming team. They extend the functionality of PowerWeb Server++ by allowing selected portions of the operation of the server to be overridden. If necessary, every aspect of the server's handling of a request can be modified, to totally customise the server, while taking advantage of PowerWeb Server++'s fast, secure, and reliable kernel.

A simple example is that of writing an equivalent of a CGI program, except that the API extension is far more efficient because it removes the overhead of the CGI interface which is typically many times greater than the overall time taken by PowerWeb Server++ to service a normal request. For example, PowerWeb Server++ might service an entire request within 30 milliseconds, whereas a CGI script could take 3 seconds just to load!

If your server is linked to a database to perform queries, an even better speedup can be achieved by using the API extensions. CGI scripts are forced to log on to the database server every time a request arrives. With an API extension, you can log on once when the PowerWeb Server++ starts up and then keep the connection open to service queries until such time as the PowerWeb Server++ shuts down, in which case you can log off from the database server. This results in far less network traffic as well as requiring less powerful hardware to sustain a given throughput.

The APIs are broken up into three groups: Global, Server and Resource, according to the object to which they attach. Global APIs apply across all servers and requests, while Server APIs apply to a specific server and its operation. Resource APIs modify the behaviour of the PowerWeb Server++ when accessing or manipulating a particular resource, such as a document.

This fine level of granularity gives powerful control and flexibility so that the WebMaster can change the method of operation for a single document, while leaving all others unchanged, or the WebMaster could define an API extension that applies to all resources across the entire server.

The management of all these API extensions is performed through the Administration and Configuration Pages with a web browser. There is no need to manually modify operating system configuration files with arcane details.

API extensions can be written in Rexx or in any compiled language compatible with the C language calling convention (such as COBOL or FORTRAN). The ability to write extensions in Rexx provides quick prototyping and in most cases will give satisfactory speed (achieved through caching the Rexx script in tokenised form to reduce overhead).

## Why not CGI?

The CGI interface is a simple-to-use method of executing programs to deliver custom responses within a Web server. PowerWeb Server++ provides the full functionality of CGI, while also offering PowerWeb Server++ APIs as a better alternative for many purposes.

The CGI interface requires the server to load a new process for every request. If the server doesn't have to run such CGI programs all that often, there is typically no performance problem, but if CGI is being used often, the overhead of simply creating the new process to run the CGI program is normally far higher than servicing the request itself (usually 10 to 100 times longer).

CGI is also limited to the extent with which it can interact with the server. A CGI program is passed a fixed set of a few server status variables and has no way of obtaining more information, or of returning information, other than documents, to the server. This severely limits the types of applications that can be created with CGI.

CGI is targeted at one specific purpose: the task of returning a document to the server to be relayed to the client's browser. There is no facility to modify aspects of the server's operation, such as customising the authentication procedure or altering the format or destination of the audit log (to store it in a relational database for example).

All these limitations and efficiency issues are overcome through the PowerWeb Server++ APIs. The lowest possible overheads, full access to the entire Server status and data structures, and the ability to customise any aspect of the server's operation are key benefits of the API.

## PowerWeb API Syntax

PowerWeb Server++ API extensions are written in Rexx or any compiled language that has a compatible calling convention with the C programming language. The API calls have been carefully designed to avoid cross-platform, cross-language and cross-compiler incompatibilities such as data type conversions and structure alignment.

All C-compatible functions called by PowerWeb Server++ have the following definition:

> `typedef long (*pfnAPI)(void* parcel);`

These functions should return one of the following values:

> HOOK_OK | 0
> HOOK_NO_ACTION | 1
> HOOK_CALL_AGAIN | 2
> HOOK_ERROR | 3
> HOOK_ABORT_CONNECTION | 4
> HOOK_ABORT_SERVER | 5

If an API extension encounters an error, it should log it in the error log (by writing to the variable "Server:/ErrorOutput"), set a protocol-dependent status code (by writing to the variable "Request:/StatusCode") and return HOOK_ERROR or HOOK_ABORT_xx. Custom error message text to be sent to the client browser can be stored in "Request:/StatusText".

PowerWeb Server++ function calls and variables are multi-thread safe, so there will be no problems with partially interleaved text being sent to the error log, for example.

When an API extension needs to call PowerWeb back, it uses one of a family of library functions. All these functions have standardised return values:

> ERR_INTERNAL | -3
> ERR_MEMORY | -2
> ERR_BAD_ARGUMENTS | -1
> ERR_NONE | 0
> ERR_NOT_FOUND | 1
> ERR_NO_LONGER_EXISTS | 2
> ERR_ACCESS_DENIED | 3
> ERR_BUSY | 4
> ERR_INVALID_TYPE | 5
> ERR_NOT_A_LIST | 6
> ERR_VALUE_TRUNCATED | 7
> ERR_INCOMPATIBLE_VERSION | 8
> ERR_BAD_NAME | 9

Under Rexx, if there is an error, then Rexx error 40 is always raised, because there is no facility within Rexx for specific return values.

## Compiling Your API Hook

If you are using IBM's CSet++ compiler, you can compile with dynamic linking to the runtime library (as shown in our "\powerweb\tour\source\*" sample source code directory), otherwise you should compile with static linking to your C runtime library to prevent conflicts. You should compile with multi-threading enabled and specify that a DLL should be generated, and not a standalone executable.

For example, IBM's CSet++ compiler uses the compiler switches:
`/Gd+ /Ge- /Gm+`

You should also ensure that "\powerweb\include" is on your INCLUDE path and that "\powerweb\lib" is on your LIB path. Refer to the file "\powerweb\tour\source\tour.nmk" for a sample NMAKE script.

Rexx modules do not need compiling prior to use. PowerWeb Server++ takes advantage of caching of the tokenised image of the Rexx module to improve the speed of execution.

## Where to Store Your API Hook Module

API Hook Modules can be stored in any directory, but the guidelines below will help you manage all your modules. The PowerWeb Server++ is initially configured during installation to support API Hooks in the following suggested directories.

> Suggested Location for Rexx Modules:
> Put your module in the directory "\powerweb\rexx-bin", so that you can load it with the URL "/rexx-bin/module.cmd" where "module.cmd" is the name of your Rexx module.

> Example URL: "/rexx-bin/svrpush.cmd"

> Suggested Location for C Modules:
> Put your library DLL in the directory "\powerweb\bin", so that you can load it with the URL "/bin/module!function" where "module" is the name of your DLL (without the file extension) and "function" is the name of the function within your DLL to call.

> Example URL: "/bin/property!ShowMenu"

## Using an API Hook within HTML

Once you have written a CommandProcessing API hook, you can call it directly from within HTML by one of two methods, without any further configuration of the server:

URL

API Hook Modules can be called directly by using a URL, and do not need to be associated with a specific Resource.

> Rexx Examples:
> /rexx-bin/svrpush.cmd

> C Examples:
> /bin/tour!TourDirect
> /bin/property!ShowMenu

PowerWeb Macro

API Hook Modules can be called directly from within PowerWeb Macros. The Macro is named exec and is used as follows:

> Rexx Examples:
> <!--#exec rexx="/rexx-bin/svrpush.cmd" -->

> C Examples:
> <!--#exec api="/bin/tour!TourDirect" -->
> <!--#exec api="/bin/property!ShowMenu" -->

## Associating an API Hook with a Resource

If you want to write an API Hook for purposes other than CommandProcessing, or if you want to associate that Hook with specified Resources, then you will need to configure the PowerWeb Server++ to tell it under what circumstances to call your new hook.

> Global API Hooks
> Define these by selecting "Global" from the "/admin" page and then selecting "Hook".

> Server API Hooks
> Define these by selecting "Servers" from the "/admin" page, selecting the "Advanced Settings" for the relevant Server, and then selecting "Hook".

> Resource API Hooks
> Define these by selecting "Resources" from the "/admin" page and then selecting the "API Hook" for the relevant Resource.

In each case, you will be able to specify the implementation language and the location of your module, as well as the name of the function to call. The default is to cache calls to API hooks, so you may wish to switch caching off during debugging, so that you don't have to restart PowerWeb Server++ to test each new version of your module.

## PowerWeb Global API Reference

Global API hooks apply across all services and resources.

> ### Encryption

> PowerWeb Server++ is not limited to its built-in encryption algorithms. With the Encryption hook, you can define new methods, making PowerWeb an excellent platform for testing and evaluating new security models.

> Arguments In: To Be Documented with PowerWeb Secure Server++.

> Arguments Out: To Be Documented with PowerWeb Secure Server++.

> ### Encoding

> Data transmission can be encoded as well as encrypted. Encoding is defined as a mechanism for compressing or translating data, such as used by popular ZIP programs. The ability to define a hook to handle custom encoding methods means you can write specialised client-server software without losing the advantages of the HTTP framework and server.

> Arguments In: To Be Documented with PowerWeb Secure Server++.

> Arguments Out: To Be Documented with PowerWeb Secure Server++.

> ### TraceLog

> Informational and debugging messages are sent to the Trace Log. This hook allows such messages to be redirected, ignored, or formatted differently.

> Arguments In:

> > Argument:/Message
> > The text that is to be output to the trace log.

> Arguments Out: None.

## PowerWeb Server API Reference

Server API hooks apply to a specific service, such as HTTP or NNTP. Multiple services can share the same API hook by pointing to the same library module.

> ### ServerInitialisation

> This hook is called when the service is started and allows for the extension library to initialise itself. A typical initialisation might be the establishment of a link to a database server, to avoid the overhead of logging in and out for every service request.

> Arguments In: None.

> Arguments Out: None.

> ### ServerTermination

> This hook is called when the service shuts down. It is not guaranteed to be called if the PowerWeb Server++ is aborted abnormally. The main purpose of this hook is to allow cleanup and relinquishing of resources obtained during the "ServerInitialisation" hook.

> Arguments In: None.

> Arguments Out: None.

> ### ResourceNameTranslation

> Resource Name Translation converts a logical (or virtual) name into a physical resource name. PowerWeb Server++ has a built-in function which does this according to the Aliases defined in its server configuration. With this hook, you can override or modify this behaviour. If you need to access the Alias information, it is stored in the variable directory "Config:/Security/Alias".

> Arguments In:

> > Argument:/VirtualName
> > The name of the resource, as specified by the remote client.

> Arguments Out:

> > Argument:/PhysicalName
> > The translated physical name of the resource, typically a filename accessible via the server's file system.

> > Argument:/Type
> > The object type of the resource. Refer to the list of object types.

> ### ErrorLog

> Information sent to the "Server:/ErrorOutput" variable is written to disk by the default version of this hook. By defining your own hook, you can output different information (such as status from your own library module) or redirect the log to a different location or storage mechanism (such as a database).

> Arguments In:

> > Argument:/Message
> > The text that is to be output to the Error Log.

> Arguments Out: None.

> ### AuditLog

> Information sent to the "Server:/Audit/AuditOutput" variable is written to disk by the default version of this hook. By defining your own hook, you can output different information (such as status from your own library module) or redirect the log to a different location or storage mechanism (such as a database).

> Arguments In:

> > Server:/Audit/AuditFile
> > The destination of the audit log information. The API hook writer may choose to override this parameter.

> Arguments Out: None.

## PowerWeb Resource API Reference

Resource API hooks apply to a specific resource and are invoked when processing needs to occur for that resource. A resource is typically a document or data file, but can also be items such as built-in commands or API extensions based on URL.

> ### UserAuthentication

> Authentication and Access Control are two separate phases in PowerWeb Server++. Authentication refers to the checking of the validity of the user's identity, whereas Access Control defines whether the specified user is allowed access to a given resource from a given machine.

> The Authentication hook splits apart the authorization string provided by the client browser and stores the authenticated results back in other server status variables.

> Arguments In:

> > Request:/Header/In/Authorization
> > The authorization string provided by the browser (if any).

> Arguments Out:

> > Request:/AuthenticateType
> > The type of authentication that was performed.

> > Request:/AuthenticateUser
> > The authenticated user name.

> > Request:/AuthenticatePassword
> > The password that was supplied (optional).

> ### AccessControl

> Access Control defines whether the specified user is allowed access to a given resource from a given machine. By defining your own hook, you can implement other access control policies such as allowing access only during specified time periods during the day.

> Arguments In:

> > Request:/Resource
> > The physical resource being accessed.

> > Request:/Protocol
> > The name of the protocol being used to access this resource.

> > Request:/Method
> > The protocol-specific method, such as GET or POST.

> > Request:/SubMethod
> > The protocol and method-specific sub-method, such as INCLUDE or EXEC.

> > Request:/AuthenticateUser
> > The authenticated user name.

> > Connect:/RemoteAddress
> > The remote client's IP address.

> > Connect:/RemoteHost
> > The remote client's machine host name, as determined by reverse domain name server lookup.

> Arguments Out:

> > Request:/StatusCode
> > The protocol-specific status code to return to the client if access is denied.

> ### ResourceType

> The ResourceType hook tells PowerWeb Server++ the MIME type and encoding of the resource. The default handler bases its decisions on the filename extension of the resource.

> Arguments In:

> > Argument:/Resource
> > The physical name of the resource to be accessed after resource name translation.

> Arguments Out:

> > Argument:/ContentType
> > The MIME type of the resource.

> > Argument:/ContentEncoding
> > The MIME encoding of the resource.

> ### CommandProcessing

> The CommandProcessing hook is the closest equivalent to CGI. It provides a superset of CGI functionality because all server variables can be both queried and set (subject to access control permissions).

> Custom applications can use this hook to perform tasks other than serving of documents or data files. Database searches, gateways to other systems and services, administration tasks, etc can all be performed by this hook.

> Arguments In: None.

> Arguments Out: None.

> ### ServerInclusions

> The ServerInclusions hook allows the developer to define customised PowerWeb Macros, extending the existing set provided with PowerWeb Server++. Any unrecognised macro is passed to this hook for execution.

> > Argument:/WebMacro
> > The name of the PowerWeb Macro to be interpreted.

> > Argument:/Attributes
> > The full text of the PowerWeb Macro to be interpreted, excluding the name. Attributes are typically space-delimited and are composed of "name=value" pairs where values can be contained in quotes.

> Arguments Out:

> > Request:/Result
> > The processed output of the PowerWeb Macro should be appended to this variable. It will be automatically sent to the client's browser.

## PowerWeb API Functions

The PowerWeb Server++ Interface Functions, Organised by Family, are:

> Navigation Within the Variable Directories:

> > ServerGetConfig
> > Get a handle to the "Config:/" variable sub-directory.

> > C Example:
> > `rc = ServerGetConfig(parcel, &handleConfig);`

> > Rexx Example:
> > `handleConfig = ServerGetConfig(parcel)`

> > ServerGetServer
> > Get a handle to the "Server:/" variable sub-directory.

> > C Example:
> > `rc = ServerGetServer(parcel, &handleServer);`

> > Rexx Example:
> > `handleServer = ServerGetServer(parcel)`

> > ServerGetConnect
> > Get a handle to the "Connect:/" variable sub-directory.

> > C Example:
> > `rc = ServerGetConnect(parcel, &handleConnect);`

> > Rexx Example:
> > `handleConnect = ServerGetConnect(parcel)`

> > ServerGetRequest
> > Get a handle to the "Request:/" variable sub-directory.

> > C Example:
> > `rc = ServerGetRequest(parcel, &handleRequest);`

> > Rexx Example:
> > `handleRequest = ServerGetRequest(parcel)`

> > ServerGetParameters
> > Get a handle to the "Parameter:/" variable sub-directory.

> > C Example:
> > `rc = ServerGetParameters(parcel, &handleParam);`

> > Rexx Example:
> > `handleParameters = ServerGetParameters(parcel)`

> > ServerGetArguments
> > Get a handle to the "Argument:/" variable sub-directory.

> > C Example:
> > `rc = ServerGetArguments(parcel, &handleArgument);`

> > Rexx Example:
> > `handleArguments = ServerGetArguments(parcel)`

> > ServerFind
> > Get a handle to the variable with a specified name. The name can be absolute or relative to the handle passed over as a first parameter.

> > C Example 1:
> > `rc = ServerGetRequest(parcel, &handleRequest);
> > rc = ServerFind(handleRequest, "Resource", &handleVariable);`

> > C Example 2:
> > `rc = ServerGetConfig(parcel, &handleConfig);
> > rc = ServerFind(handleConfig, "/Servers/HTTP", &handleHTTP);
> > rc = ServerFind(handleHTTP, "ErrorFile", &handleFile);`

> > Rexx Example 1:
> > `handleRequest = ServerGetRequest(parcel)
> > handleVariable = ServerFind(handleRequest, "Resource")`

> > Rexx Example 2:
> > `handleConfig = ServerGetConfig(parcel)
> > handleHTTP = ServerFind(handleConfig, "/Servers/HTTP")
> > handleFile = ServerFind(handleHTTP, "ErrorFile")`

> Querying a Variable's Attributes:

> > ServerKind
> > Returns the data type of the indicated variable:
> > 1. 32-bit signed integer
> > 2. Double-precision floating point
> > 3. Variable-length text
> > 4. Variable-length binary buffer
> > 5. List that contains other Variables
> > 6. Pointer to another Variable

> > C Example:
> > `rc = ServerFind(parcel, "Config:/Servers", &handleServers);
> > rc = ServerKind(handleServers, &iKind);
> > `

> > ServerSize
> > Returns the size in bytes of the indicated variable, unless it is a List variable, in which case it returns the number of variables contained in that list.

> > C Example:
> > `rc = ServerFind(parcel, "Config:/Servers", &handleServers);
> > rc = ServerSize(handleServers, &cServers);
> > `

> > ServerName
> > Returns the name of the indicated variable. Often used in conjunction with the hierarchy browsing functions described below.

> > C Example:
> > `rc = ServerGetConfig(parcel, &handleConfig);
> > rc = ServerChild(handleConfig, &handleFirst);
> > rc = ServerName(handleFirst, buffer, sizeof(buffer));
> > `

> Reading the Contents of a Variable:

> > ServerReadInteger
> > Reads the indicated variable and converts it (if necessary) into a 32 bit signed integer.

> > C Example:
> > `rc = ServerReadInteger(parcel, "Server:/Stats/Clients", &iClients);`

> > ServerReadFloat
> > Reads the indicated variable and converts it (if necessary) into a double precision floating point number.

> > C Example:
> > `rc = ServerReadFloat(parcel, "Config:/VersionConfig", &dVersion);`

> > ServerReadText
> > Reads the indicated variable and converts it (if necessary) into a text buffer.

> > C Example:
> > `rc = ServerReadText(parcel, "Config:/ConfigFile", buffer, sizeof(buffer));`

> > ServerReadBinary
> > Reads the indicated variable and converts it (if necessary) into an unformatted binary buffer.

> > C Example:
> > `rc = ServerReadBinary(parcel, "Request:/ArgumentText", buffer, sizeof(buffer));`

> Overwriting the Contents of a Variable:

> > ServerWriteInteger
> > Writes the integer value to the indicated variable, performing datatype conversions if necessary.

> > C Example:
> > `rc = ServerWriteInteger(parcel, "Request:/StatusCode", 401);`

> > ServerWriteFloat
> > Writes the double precision floating point value to the indicated variable, performing datatype conversions if necessary.

> > ServerWriteText
> > Writes the text buffer to the indicated variable, performing datatype conversions if necessary.

> > C Example:
> > `rc = ServerWriteText(parcel, "Request:/StatusText", "Authorisation is Required");`

> > ServerWriteBinary
> > Writes the binary buffer to the indicated variable, performing datatype conversions if necessary.

> > C Example:
> > `rc = ServerWriteBinary(parcel, "Request:/Result", buffer, cbResult);`

> Appending to the Existing Contents of a Variable:

> > ServerAppendText
> > Appends a text buffer to the existing content of the indicated variable, performing datatype conversions if necessary.

> > C Example:
> > `rc = ServerAppendText(parcel, "Request:/Result", "All Rights Reserved");`

> > ServerAppendBinary
> > Appends a binary buffer to the existing content of the indicated variable, performing datatype conversions if necessary.

> > C Example:
> > `rc = ServerAppendText(parcel, "Request:/Result", buffer, cbExtra);`

> Creating New Variables:

> > ServerNewInteger
> > Creates a new integer variable, initialised to a given value, and given a specified name within the indicated variable directory.

> > C Example:
> > `rc = ServerFind(parcel, "Request:/Argument", &handleArgument);
> > rc = ServerNewInteger(handleArgument, "MyNewFormVariable", 100);`

> > ServerNewFloat
> > Creates a new floating point variable, initialised to a given value, and given a specified name within the indicated variable directory.

> > C Example:
> > `rc = ServerFind(parcel, "Request:/Argument", &handleArgument);
> > rc = ServerNewFloat(handleArgument, "MyNewFormVariable", 3.1415);`

> > ServerNewText
> > Creates a new text variable, initialised to a given value, and given a specified name within the indicated variable directory.

> > C Example:
> > `rc = ServerFind(parcel, "Request:/Argument", &handleArgument);
> > rc = ServerNewText(handleArgument, "MyNewFormVariable", "MyForm");`

> > ServerNewBinary
> > Creates a new binary variable, initialised to a given value, and given a specified name within the indicated variable directory.

> > C Example:
> > `rc = ServerFind(parcel, "Request:/Argument", &handleArgument);
> > rc = ServerNewBinary(handleArgument, "MyNewFormVariable", buffer, cbData);`

> > ServerNewList
> > Creates a new list variable, given a specified name within the indicated variable directory. A list variable is the same as a "variable directory" - it is simply a variable that can contain other variables (of any type, including nested lists).

> > C Example:
> > `rc = ServerGetConfig(parcel, &handleConfig);
> > rc = ServerNewList(handleConfig, "ClientList");`

> Browsing Through the Variable Directory Hierarchy:

> > ServerParent
> > Returns the handle of the parent of the indicated variable.

> > C Example:
> > `rc = ServerParent(handleVariable, &handleParent);`

> > ServerChild
> > Returns the handle of the first child of the indicated variable.

> > C Example:
> > `rc = ServerChild(handleVariable, &handleChild);`

> > ServerSibling
> > Returns the handle of the next sibling of the indicated variable. Commonly used in conjunction with ServerChild in order to walk through the entire tree of variables.

> > C Example:
> > `rc = ServerChild(handleVariable, &handleChild);
> > rc = ServerSibling(handleChild, &handleNext);`

Please read the PowerWeb Macro Reference Manual for details on the directory structure of PowerWeb's variables. You can also browse the server configuration and status variables to gain familiarity with the "Config:/" set of variables.

Another source of information is the help contained in the /admin/help/ URL which contains a list of HTML pages, starting with the letters "var", which describe the variables and their usages.

## PowerWeb C Library

When compiling your API extensions, you will need to link with the "PowerWeb.Lib" library module. This module consists of all the interface functions to PowerWeb Server++.

You will need to read the function descriptions, before writing code to call these functions.

The PowerWeb Server++ C/C++ Interface Function Definitions Are:

> Returns | Function | Parameters
> --- | --- | ---
> long | ServerGetConfig | (void* parcel, void** handle);
> long | ServerGetServer | (void* parcel, void** handle);
> long | ServerGetConnect | (void* parcel, void** handle);
> long | ServerGetRequest | (void* parcel, void** handle);
> long | ServerGetParameters | (void* parcel, void** handle);
> long | ServerGetArguments | (void* parcel, void** handle);
> long | ServerFind | (void* parent, const char* pszName, void** item);
> long | ServerKind | (void* parent, unsigned long* type);
> long | ServerSize | (void* parent, unsigned long* size);
> long | ServerName | (void* parent, char* value, unsigned long size);
> long | ServerReadInteger | (void* parent, const char* pszName, long* value);
> long | ServerReadFloat | (void* parent, const char* pszName, double* value);
> long | ServerReadText | (void* parent, const char* pszName, char* value, unsigned long size);
> long | ServerReadBinary | (void* parent, const char* pszName, unsigned char* value, unsigned long size);
> long | ServerWriteInteger | (void* parent, const char* pszName, long value);
> long | ServerWriteFloat | (void* parent, const char* pszName, double value);
> long | ServerWriteText | (void* parent, const char* pszName, const char* value);
> long | ServerWriteBinary | (void* parent, const char* pszName, const unsigned char* value, unsigned long size);
> long | ServerAppendText | (void* parent, const char* pszName, const char* value);
> long | ServerAppendBinary | (void* parent, const char* pszName, const unsigned char* value, unsigned long size);
> long | ServerNewInteger | (void* parent, const char* pszName, long value);
> long | ServerNewFloat | (void* parent, const char* pszName, double value);
> long | ServerNewText | (void* parent, const char* pszName, const char* value);
> long | ServerNewBinary | (void* parent, const char* pszName, const unsigned char* value, unsigned long size);
> long | ServerNewList | (void* parent, const char* pszName);
> long | ServerParent | (void* here, void** handle);
> long | ServerChild | (void* here, void** handle);
> long | ServerSibling | (void* here, void** handle);

Parameters:

> void* parcel
> The parcel pointer is the same one that was passed to the API hook from PowerWeb Server++. It should be treated as a "magic cookie" which identifies the current context. The parcel is unique within the system, and allows for easy and safe multi-threading.

> void** handle
> The handle pointer is another "magic cookie", this time one that refers to a specific PowerWeb variable directory or individual variable. It is used to query a specific variable or to navigate through the hierarchy. It is a pointer to a pointer to allow PowerWeb to write the value of the handle pointer into it.

> void* parent
> The parent pointer is either the "parcel" pointer or a "handle" pointer. When the pszName contains a fully qualified global name (ie. has a prefix of "Request:/", "Server:/", etc) then the "parent" pointer is the "parcel" pointer, otherwise the pszName is a relative reference to a "handle" pointer.

Examples:

> Perform Access Control via the Remote User's IP Address:
> This particular example limits access to a single IP address. It is obviously easier to set up a security rule in the configuration to provide this type of protection, but the example shows the basic components of writing an API Extension.

> >     long AccessControlHook(void *parcel)
> >     {
> >       char   ip[32];

> >       ServerReadText(parcel, "Connect:/RemoteAddress", ip, sizeof(ip));

> >       if (strcmp(ip, "12.34.56.78") != 0) {
> >         ServerWriteInteger(parcel, "Request:/StatusCode", 403);
> >         return HOOK_ERROR;
> >       }

> >       return HOOK_OK;
> >     }

> Guided Tour Sample Code:
> The Guided Tour has a complete example of API hooks for forms processing, dynamic document translation, simple direct-call hooks, and a tree view of your server settings.

## PowerWeb Rexx Library

The Rexx Library is equivalent in functionality to the C-compatible API library. The function names have been kept consistent for ease of working in both environments. It is a straightforward procedure to port a Rexx prototype to C for speed because of this consistency.

You will need to read the function descriptions, before writing code to call these functions.

The PowerWeb Server++ Rexx Interface Function Definitions Are:

> Returns | Function | Parameters
> --- | --- | ---
> handle | ServerGetConfig | parcel
> handle | ServerGetServer | parcel
> handle | ServerGetConnect | parcel
> handle | ServerGetRequest | parcel
> handle | ServerGetParameters | parcel
> handle | ServerGetArguments | parcel
> handle | ServerFind | parent, name
> type | ServerKind | handle
> size | ServerSize | handle
> name | ServerName | handle
> value | ServerReadText | parent, name
> value | ServerReadBinary | parent, name
> - | ServerWriteText | parent, name, value
> - | ServerWriteBinary | parent, name, value
> - | ServerAppendText | parent, name, value
> - | ServerAppendBinary | parent, name, value
> - | ServerNewInteger | parent, name, value
> - | ServerNewFloat | parent, name, value
> - | ServerNewText | parent, name, value
> - | ServerNewBinary | parent, name, value
> - | ServerNewList | parent, name, value
> handle | ServerParent | handle
> handle | ServerChild | handle
> handle | ServerSibling | handle

Examples:

> Guided Tour Sample Code:
> The Guided Tour has a complete Rexx example of an API hook for dynamic translation of a database into an HTML document. It has equivalent functionality to the C example, so you can compare the two language implementations.

> There is also has an example of server push in the file "\powerweb\rexx-bin\svrpush.cmd" for those browsers capable of handling this feature which allows for periodic updating of the client's page or image.