/** * httpresp
* A CGI program to simulate various HTTP responses.
* Features:
* *
* Compilation:
* Compiles on both UNIX and Windows. Remember to set "-DUNIX" option on UNIX. *
* You are free to use this code and to make modifications provided * this notice is retained. *

* If you found this useful, please add a note of acknowledgement to my * guestbook. * If you would like to report a bug or suggest some improvements, * you are most welcome. I will be happy to help you use this piece of code. *

* * @author Tanmay K. Mohapatra * @version 1.00, 18th Dec, 1999 * * Modification log: * 1.00 Tanmay 18th Dec 1999 Original Version */ #ifdef UNIX #include #else #include #endif #include #include #include #include "CGIEnv.h" CCGIEnv *pCGIEnv; #define ACTION_SEND_STATUS "status" #define ACTION_SEND_FILE "file" #define ACTION_SEND_STRING "string" #define ACTION_DELAY_HEADER "delayheader" #define ACTION_DELAY_CONTENT "delaycontent" #define ACTION_SEND_HEADER "header" #define HTTPRESP_USAGE_MSG \ "httpresp usage\ httpresp acts on name=value pairs passed to it through either the query string or post data.
\ Example: http://myserver.on.nt/httpresp.exe?status=404 Not Found&string=File Not Found


\ \ \ \ \ \ \ \
status:HTTP status code to send (e.g. "200 Ok" for success)
file:The file will be read and its contents sent in the response. It should NOT have HTTP headers
string:The will be sent in the response. It should NOT have HTTP headers
delayheader:Do not send headers till so many secs. Can be used to test timeout.
delaycontent:Do not send content till so many secs. Can be used to test timeout.
header[0-20]:Header strings - header1 to header20. Each string is one line of the header. (e.g. "Content-length: 1000")
\ " typedef struct { char *pStatus; char *pFileToSend; char *pStringToSend; char *pHeaders[20]; // 20 headers should be sufficient int iDelayHeader; int iDelayContent; } tstHttpResp; static int checkForSendStatus (tstHttpResp *pstHttpResp, CCGIEnv *pCGIEnv); static int checkForFileToSend (tstHttpResp *pstHttpResp, CCGIEnv *pCGIEnv); static int checkForStringToSend (tstHttpResp *pstHttpResp, CCGIEnv *pCGIEnv); static int checkForHeaders (tstHttpResp *pstHttpResp, CCGIEnv *pCGIEnv); static int checkWhetherToDelayHeader (tstHttpResp *pstHttpResp, CCGIEnv *pCGIEnv); static int checkWhetherToDelayContent (tstHttpResp *pstHttpResp, CCGIEnv *pCGIEnv); static char * getValueAnyWay (const char *sName, CCGIEnv *pCGIEnv); static int checkEmptyCallAndSetHelp (tstHttpResp *pstHttpResp); static int doHeaderSendDelay (tstHttpResp *pstHttpResp); static int doContentSendDelay (tstHttpResp *pstHttpResp); static int setContent (tstHttpResp *pstHttpResp, CCGIEnv *pCGIEnv); static int setHeaders (tstHttpResp *pstHttpResp, CCGIEnv *pCGIEnv); int main(int argc, char **argv) { tstHttpResp stHttpResp; pCGIEnv = new CCGIEnv(); pCGIEnv->readQueryData(); pCGIEnv->readCGIEnv(); pCGIEnv->readPostData(); memset(&stHttpResp, 0, sizeof(stHttpResp)); checkForSendStatus (&stHttpResp, pCGIEnv); checkForFileToSend (&stHttpResp, pCGIEnv); checkForStringToSend (&stHttpResp, pCGIEnv); checkForHeaders (&stHttpResp, pCGIEnv); checkWhetherToDelayHeader (&stHttpResp, pCGIEnv); checkWhetherToDelayContent (&stHttpResp, pCGIEnv); checkEmptyCallAndSetHelp(&stHttpResp); setHeaders(&stHttpResp, pCGIEnv); setContent(&stHttpResp, pCGIEnv); doHeaderSendDelay(&stHttpResp); pCGIEnv->sendHeaders(); doContentSendDelay(&stHttpResp); pCGIEnv->sendResponse(); return 0; } static int checkEmptyCallAndSetHelp(tstHttpResp *pstHttpResp) { if(!pstHttpResp->pStatus) { pstHttpResp->pStatus = "200 Ok"; } if( (!pstHttpResp->pFileToSend) && (!pstHttpResp->pStringToSend) ) { int iNumHeaders; for (iNumHeaders=0; (iNumHeaders < (sizeof(pstHttpResp->pHeaders)-1)) && pstHttpResp->pHeaders[iNumHeaders]; iNumHeaders++); if(!iNumHeaders) { // no headers and no data, set our own help pstHttpResp->pStringToSend = HTTPRESP_USAGE_MSG; } } return 0; } static int doHeaderSendDelay(tstHttpResp *pstHttpResp) { if(pstHttpResp->iDelayHeader > 0) { #ifdef UNIX sleep(pstHttpResp->iDelayHeader); #else /* WIN32 */ Sleep(1000*pstHttpResp->iDelayHeader); #endif } return 0; } static int doContentSendDelay(tstHttpResp *pstHttpResp) { if(pstHttpResp->iDelayContent > 0) { #ifdef UNIX sleep(pstHttpResp->iDelayContent); #else /* WIN32 */ Sleep(1000*pstHttpResp->iDelayContent); #endif } return 0; } static int setContent(tstHttpResp *pstHttpResp, CCGIEnv *pCGIEnv) { if(pstHttpResp->pStringToSend) { pCGIEnv->accumulateResponse(pstHttpResp->pStringToSend); } if(pstHttpResp->pFileToSend) { // read the file and append to output char sBuff[2048]; FILE *fp; int iRead; if(fp = fopen(pstHttpResp->pFileToSend, "r")) { while(!feof(fp)) { if((iRead = fread(sBuff, 1, sizeof(sBuff), fp)) > 0) { pCGIEnv->accumulateResponse(sBuff, iRead); } } fclose(fp); } } return 0; } static int setHeaders(tstHttpResp *pstHttpResp, CCGIEnv *pCGIEnv) { int iIndex; char *sHeader; if(pstHttpResp->pStatus) { char *pEndCode; if(sHeader = strdup(pstHttpResp->pStatus)) { if(pEndCode = strchr(sHeader, ' ')) { int iCode; *pEndCode = 0; iCode = atoi(sHeader); pCGIEnv->setHTTPResponseCode(iCode, pEndCode+1); } free(sHeader); } } for (iIndex=0; (iIndex < (sizeof(pstHttpResp->pHeaders)-1)) && pstHttpResp->pHeaders[iIndex]; iIndex++) { if(sHeader = strdup(pstHttpResp->pHeaders[iIndex])) { char *pNameValSep; if(pNameValSep = strchr(sHeader, '=')) { *pNameValSep = 0; pCGIEnv->setResponseHeader(sHeader, pNameValSep+1); } free(sHeader); } } return 0; } static char * getValueAnyWay(const char *sName, CCGIEnv *pCGIEnv) { char *pValue; if(!(pValue = pCGIEnv->pQueryData->getValueFor(sName))) { pValue = pCGIEnv->pPostData->getValueFor(sName); } return pValue; } static int checkForSendStatus(tstHttpResp *pstHttpResp, CCGIEnv *pCGIEnv) { pstHttpResp->pStatus = getValueAnyWay(ACTION_SEND_STATUS, pCGIEnv); return 0; } static int checkForFileToSend(tstHttpResp *pstHttpResp, CCGIEnv *pCGIEnv) { pstHttpResp->pFileToSend = getValueAnyWay(ACTION_SEND_FILE, pCGIEnv); return 0; } static int checkForStringToSend(tstHttpResp *pstHttpResp, CCGIEnv *pCGIEnv) { pstHttpResp->pStringToSend = getValueAnyWay(ACTION_SEND_STRING, pCGIEnv); return 0; } static int checkForHeaders(tstHttpResp *pstHttpResp, CCGIEnv *pCGIEnv) { int iIndex; char sName[32]; char *sValue; for (iIndex=0; iIndex < (sizeof(pstHttpResp->pHeaders)-1); iIndex++) { sprintf(sName, "%s%d", ACTION_SEND_HEADER, iIndex); sValue = getValueAnyWay(sName, pCGIEnv); if(!sValue) break; pstHttpResp->pHeaders[iIndex] = strdup(sValue); } return 0; } static int checkWhetherToDelayHeader(tstHttpResp *pstHttpResp, CCGIEnv *pCGIEnv) { char *sDelayHeader = getValueAnyWay(ACTION_DELAY_HEADER, pCGIEnv); if(sDelayHeader) { pstHttpResp->iDelayHeader = atoi(sDelayHeader); } return 0; } static int checkWhetherToDelayContent(tstHttpResp *pstHttpResp, CCGIEnv *pCGIEnv) { char *sDelayContent = getValueAnyWay(ACTION_DELAY_CONTENT, pCGIEnv); if(sDelayContent) { pstHttpResp->iDelayContent = atoi(sDelayContent); } return 0; }