Building a Web Server Application |
![]() ![]() ![]() |
There are advanced web based packages available for QM but for many applications a simple CGI program gives an easy way to achieve web connectivity with no additional software.
The program below requires the qmclilib library to be included when it is compiled and linked. The executable program file should be placed in the cgi-bin subdirectory of the relevant web account.
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <\qmsys\syscom\qmclilib.h> [ Windows ] #include </usr/qmsys/SYSCOM/qmclilib.h> [ Linux / FreeBSD ]
// Set the following six lines as appropriate for your system #define SERVER_ADDRESS "localhost" /* Server network address or name... */ #define SERVER_PORT 4243 /* ...and port on which to connect */ #define SERVER_USER "xxx" /* Server user name... */ #define SERVER_PASSWORD "xxxxx" /* ...and password */ #define SERVER_ACCOUNT "xxxxx" /* Web server QM account name */ #define SERVER_PROGRAM "xxxxx" /* Catalogued program to run on server */
char NullString[] = "";
char InputData[32767] = ""; /* Incoming data stream */ char Response[99999] = ""; /* Response to send */ char * ClientIP; /* Client IP address */ char * ClientUser; /* User name if web authentication used */
/* ====================================================================== */
int main() { char * RequestMethod; char * p;
RequestMethod = getenv("REQUEST_METHOD"); if (RequestMethod == NULL) { printf("Program must be executed by a Web browser\n"); return 1; }
ClientIP = ((p = getenv("REMOTE_ADDR")) != NULL)?p:NullString; ClientUser = ((p = getenv("REMOTE_USER")) != NULL)?p:NullString;
if (!strcmp(RequestMethod,"GET")) { if ((p = getenv("QUERY_STRING")) != NULL) strcpy(InputData, p); } else if (!strcmp(RequestMethod,"POST")) { if ((p = getenv("CONTENT_LENGTH")) != NULL) { fread(InputData, atoi(p), 1, stdin); } }
/* Check for locally processed screens */
ParseInputData();
if (!QMConnect(SERVER_ADDRESS, SERVER_PORT, SERVER_USER, SERVER_PASSWORD, SERVER_ACCOUNT)) { strcpy(Response, "Failed to connect. The server may be offline."); } else { QMCall(SERVER_PROGRAM, 4, InputData, ClientIP, ClientUser, Response); QMDisconnect(); }
printf("Content-type: text/html\n\n"); printf("<meta http-equiv=\"Pragma\" content=\"no-cache\">\n"); printf("%s\n", Response);
return 0; }
Web requests received by this program will be passed to the catalogued QMBasic subroutine identified by SERVER_PROGRAM. The declaration of this is SUBROUTINE SERVER(INPUT.DATA, CLIENT.IP, CLIENT.USER, RESPONSE)
When used with HTML forms with the method attribute set to "post" or "get", any data sent with the form will be passed to the QM server program via the first argument (INPUT.DATA). Typically, the form would include an item in this data that can be used to determine the screen being processed.
The CLIENT.IP is the network address of the client user and can be used for simple security checking.
If the user has been authenticated using the conventional web user authentication process, the user name appears in CLIENT.USER. If authentication has not been performed, this will be a null string.
The server subroutine must return valid HTML data to be returned to the web client via the RESPONSE argument. For applications that return very large HTML strings it may be better for the QMBasic component to write the data to a temporary file and pass this name back to the C program. This avoids the need for the Response variable in the above example to be sized to fit the largest string that could ever be returned. |