home *** CD-ROM | disk | FTP | other *** search
- #include "cgiportal.h"
-
- /*************************************************************************
-
- CGIPortal is copyright 1999 Lextek International
- All Rights Reserved.
-
- Lextek International specializes in high performance full text indexing
- and retrieval software ("search engines"). These search engines are
- programmed in C/C++ and are not simply another Perl application but
- are highly optomized utilizing the latest research and technology
- in information retrieval. Please e-mail pollarda@lextek.com
- if you have need of a full text indexing and retrieval engine to add
- search engine functionality to your web application.
-
- This application was written for Lextek International by Art Pollard
-
- Permission is granted to you to use this code module in your web
- application(s) free of charge. No warrenty is made as to the suitability
- of CGIPortal to your application or even that CGIPortal is bug or error free.
-
- BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
- WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
- EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
- OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
- KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
- LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
- THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- *************************************************************************/
-
-
-
- /*****************************************************************
- ByteToHex() converts the character Ch to a hexidecimal value. The
- buffer where the hex value is placed is specified by Hex. It is
- important to note that the buffer specified by Hex must be at
- least 2 bytes in length as that is how large the hex value which
- will be placed in Hex is going to be.
- *****************************************************************/
-
-
- void ByteToHex(char *Hex, char Ch) {
- char HexCodes[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
-
- Hex[0] = HexCodes[(Ch >> 4) & 0x0F];
- Hex[1] = HexCodes[Ch & 0x0F];
- }
-
-
- /*****************************************************************
- HexToByte converts the two character hex code specified by Hex into
- a character and places it at the position specified by Byte.
- *****************************************************************/
-
- void HexToByte(char *Byte, char *Hex) {
- size_t Counter;
- for(Counter = 0; Counter < 2; Counter ++) {
- *Byte <<= 4;
-
- if(Hex[Counter] >= '0' && Hex[Counter] <= '9')
- *Byte |= (0x0F & (Hex[Counter] - '0'));
- else
- if(Hex[Counter] >= 'a' && Hex[Counter] <= 'f')
- *Byte |= (0x0F & ((Hex[Counter] - 'a') + 0x0A));
- else
- if(Hex[Counter] >= 'A' && Hex[Counter] <= 'F')
- *Byte |= (0x0F & ((Hex[Counter] - 'A') + 0x0A));
- }
- }
-
- /*****************************************************************
- UnescapeURLData is a utility function (not used by CGIPortal) which
- is provided mainly for your benifit. This function converts any
- hex codes to their appropriate characters, and any other URL
- specific characters to their appropriate characters (e.g. '+' -> ' ').
- Since an unescaped string is shorter than the escaped string, this is
- all done in place.
- *****************************************************************/
-
- void UnescapeURLData(char *String) {
- size_t Counter;
- size_t OutputPos;
-
- for(Counter = 0, OutputPos = 0; String[Counter] != 0;) {
- if(String[Counter] == '+') {
- String[OutputPos] = ' ';
- OutputPos ++;
- Counter += 3;
- continue;
- }
- if(String[Counter] == '%') {
- HexToByte(&String[OutputPos],&String[Counter + 1]);
- OutputPos ++;
- Counter += 3;
- continue;
- }
- String[OutputPos] = String[Counter];
- Counter ++; OutputPos ++;
- }
- String[OutputPos] = 0x00;
- }
-
- /*****************************************************************
- AddPointerToPointerList() is a CGIPortal utility function which
- is used interally to add a pointer to the pointer list expanding
- the list buffer if need be. This function returns 0 if not enough
- memory is available or 1 on success.
- *****************************************************************/
-
-
- int AddPointerToPointerList(CGIVarListT *CGIVars, char *Pointer) {
- char **PointerList,**Tmp;
- size_t NumAllocatedPointers;
-
- if(CGIVars->NumValuePointers == CGIVars->ValuePointerListSize) {
-
- if(CGIVars->NumValuePointers < 32)
- NumAllocatedPointers = 32;
- else
- NumAllocatedPointers <<= 1;
-
- PointerList = (char **) malloc(NumAllocatedPointers * sizeof(char *));
-
- if(PointerList == NULL)
- return 0;
-
- memcpy(PointerList,&CGIVars->NumValuePointers,CGIVars->NumValuePointers * sizeof(char *));
- Tmp = CGIVars->ValuePointers;
- CGIVars->ValuePointers = PointerList;
-
- CGIVars->ValuePointerListSize = NumAllocatedPointers;
- free(Tmp);
- }
- CGIVars->ValuePointers[CGIVars->NumValuePointers] = Pointer;
- CGIVars->NumValuePointers ++;
- return 1;
- }
-
- /*****************************************************************
- UnescapeURLDataAndDoPointers() is an internal function for CGI portal
- which unescapes the data passed into the CGI application and parses
- out all of the variables and their associated values. This is done
- in one pass for speed reasons. This function returns 0 on failure
- (you are out of memory and are probably running a Windows machine)
- or 1 on success.
- *****************************************************************/
-
-
- int UnescapeURLDataAndDoPointers(CGIVarListT *CGIVars) {
- size_t Counter;
- size_t OutputPos;
- size_t PointerCounter;
- int SetPointerFlag = 1;
-
- for(Counter = 0, OutputPos = 0; CGIVars->ValueList[Counter] != 0;) {
- if(CGIVars->ValueList[Counter] == '&') {
- CGIVars->ValueList[OutputPos] = 0x00;
- SetPointerFlag = 1;
- OutputPos ++;
- Counter ++;
- continue;
- }
-
- if(SetPointerFlag == 1) {
- if(AddPointerToPointerList(CGIVars,&CGIVars->ValueList[OutputPos]) == 0)
- return 0;
- SetPointerFlag = 0;
- }
-
- if(CGIVars->ValueList[Counter] == '+') {
- CGIVars->ValueList[OutputPos] = ' ';
- OutputPos ++;
- Counter += 3;
- }
- else
- if(CGIVars->ValueList[Counter] == '%') {
- HexToByte(&CGIVars->ValueList[OutputPos],&CGIVars->ValueList[Counter + 1]);
- OutputPos ++;
- Counter += 3;
- }
- else {
- CGIVars->ValueList[OutputPos] = CGIVars->ValueList[Counter];
- Counter ++; OutputPos ++;
- }
- }
- CGIVars->ValueList[OutputPos] = 0x00;
- return 1;
- }
-
- /**************************************************************************
- ExpandVarListSize() is an internal function which is called if the
- variable list size is not large enough to hold all the variables available.
- This functions allocates a new buffer and all the variables are copied over
- and the old buffer replaced and freed. This function returns 0 on failure
- and 1 on success.
- **************************************************************************/
-
- int ExpandVarListSize(CGIVarListT *CGIVars, size_t Size) {
- char *Temp;
-
- Temp = (char *) malloc(Size);
- if(Temp == NULL)
- return 0;
- if(CGIVars->ValueList != NULL) {
- memcpy(Temp,CGIVars->ValueList,CGIVars->AmountInList);
- free(CGIVars->ValueList);
- }
- CGIVars->ValueList = Temp;
- CGIVars->ValueListSize = Size;
- return 1;
- }
- /**************************************************************************
- ReadStandardVariablesFromStdin() is an internal function used to
- read the CGI variables from standard in. This function returns 0 on
- failure and 1 on success. If a failure occurs, it means that you are
- out of memory. (And thus must be running on a Windows machine.)
- **************************************************************************/
-
- int ReadStandardVariablesFromStdin(CGIVarListT *CGIVars) {
- char *CurrentPos = CGIVars->ValueList + CGIVars->AmountInList, *Temp;
- size_t AmountRead, TotalRead = 0;
-
-
- for(;;) {
- AmountRead = fread(CurrentPos,1,CGIVars->ValueListSize - TotalRead,stdin);
- if(AmountRead + TotalRead < CGIVars->ValueListSize) {
- CGIVars->AmountInList += AmountRead;
- CGIVars->ValueList[CGIVars->AmountInList] = 0x00;
- break;
- }
- TotalRead += AmountRead;
-
- if(ExpandVarListSize(CGIVars, CGIVars->ValueListSize * 2) == 0)
- return 0;
- }
- return 1;
- }
- /**************************************************************************
- ReadStandardVariablesFromEnvironment() is used internally to read the CGI
- data from the various environment variables. The variables are passed
- in as the string EnvironmentVars. This function returns 0 on
- failure and 1 on success. If a failure occurs, it means that you are
- out of memory. (And thus must be running on a Windows machine.)
- **************************************************************************/
- int ReadStandardVariablesFromEnvironment(CGIVarListT *CGIVars, char *EnvironmentVars) {
- size_t Length;
-
- Length = strlen(EnvironmentVars);
-
- if(Length + 5 + CGIVars->AmountInList > CGIVars->ValueListSize) {
- if(ExpandVarListSize(CGIVars,(CGIVars->ValueListSize + Length) * 2) == 0)
- return 0;
- }
- strcpy(CGIVars->ValueList + CGIVars->AmountInList,"&");
- CGIVars->AmountInList += 1;
- strcpy(CGIVars->ValueList + CGIVars->AmountInList,EnvironmentVars);
- CGIVars->AmountInList += Length;
- return 1;
-
- }
-
- /**************************************************************************
- InitializeCGIVars() is used to initialize a CGIVarListT struct which has
- not been previously initilized. (Or one that has been previously initilized
- but its memory has been freed by a call to ClearCGIVars().) Be sure to
- call this function at the beginning of your CGI application to allocate
- the memory which is going to be used to read the CGI variables.
- The ListSize variable is the number of bytes which will be used initially
- to store the CGI variables. (A good starting off point is 1024) The number
- of pointers is the size of the pointer list which will be used to point
- to each of the CGI variables. The number of pointers should be as large if
- not larger than the maximum number of pointers used by your application.
-
- Note: Both the variable buffer and the pointer buffer will grow as need
- be as the CGI variables are read. This means that ListSize and NumPointers
- does not need to be exact but absolutely must be bigger than 0.
-
- This function returns 0 on failure (out of memory) and 1 on success.
-
- **************************************************************************/
-
- int InititalizeCGIVars(CGIVarListT *CGIVars, size_t ListSize, size_t NumPointers) {
- CGIVars->ValueList = (char *) malloc(ListSize);
- if(CGIVars->ValueList == NULL)
- return 0;
- CGIVars->ValueListSize = ListSize;
- CGIVars->AmountInList = 0;
-
- CGIVars->ValuePointers = (char **) malloc(sizeof(char *) * NumPointers);
- if(CGIVars->ValuePointers == NULL) {
- free(CGIVars->ValueList);
- return 0;
- }
- CGIVars->ValuePointerListSize = NumPointers;
- CGIVars->NumValuePointers = 0;
- //CGIVars->CookieList = NULL;
- }
-
- /**************************************************************************
- ResetCGIVars() resets te CGIVarListT structure. This does not initilize
- it but serves as a way for you to reuse the CGIVarList struct without having
- to free and reallocate memory every time you want to use the structure.
- This function is aimed at long running CGI applications where more than
- one read of CGI variables (from stdin or the environment) is called for.
- **************************************************************************/
-
- void ResetCGIVars(CGIVarListT *CGIVars) {
- CGIVars->AmountInList = 0;
- CGIVars->NumValuePointers = 0;
- }
-
- /**************************************************************************
- ClearCGIVars() frees any memory allocated during InitializeCGIVars() or
- during the process of reading the CGI data. Call this function at the
- end of your CGI program.
- **************************************************************************/
- void ClearCGIVars(CGIVarListT *CGIVars) {
- if(CGIVars->ValueList != NULL)
- free(CGIVars->ValueList);
- if(CGIVars->ValuePointers != NULL)
- free(CGIVars->ValuePointers);
- }
-
- /**************************************************************************
- ReadCGIData() reads all of the variables available when the CGI application
- is called. It also unescapes any data stored in the variable names/data
- and stores it all in a list of 0x00 delimited strings. (This of course
- means that you can't have 0x00 (%00) in your data.) Call this function
- when you want to begin reading the variable names from the environment
- or standard input. This function returns 0 on
- failure and 1 on success. If a failure occurs, it means that you are
- out of memory. (And thus must be running on a Windows machine.)
- **************************************************************************/
-
- int ReadCGIData(CGIVarListT *CGIVars) {
- char *Temp;
-
- CGIVars->AmountInList = 0;
-
- // If there is a POST method, go ahead and get it.
- CGIVars->RequestMethod = getenv("REQUEST_METHOD");
- if(CGIVars->RequestMethod != NULL && stricmp(CGIVars->RequestMethod,"POST")) {
- if(ReadStandardVariablesFromStdin(CGIVars) == 0)
- return 0;
- }
-
- // If there is any GET method data then we get it too.
- CGIVars->QueryString = getenv("QUERY_STRING");
- if(CGIVars->QueryString != NULL) {
- if(ReadStandardVariablesFromEnvironment(CGIVars,CGIVars->QueryString) == 0)
- return 0;
- }
-
- // If there is any Cookie info, we get that.
- CGIVars->CookieString = getenv("HTTP_COOKIE");
- if(CGIVars->CookieString != NULL) {
- if(ReadStandardVariablesFromEnvironment(CGIVars,CGIVars->CookieString) == 0)
- return 0;
- }
-
- // Now we unescape the strings and set the pointers to the
- // different values
- UnescapeURLDataAndDoPointers(CGIVars);
- return 1;
- }
- /***********************************************************************
- FindCGIValue() is used to find the value assocaiated with a given variable
- name. FindCGIValue takes a pointer to a CGIVarListT struct (properly
- initialized of course) and a pointer to a 0x00 terminated string
- which specifies the variable name. Note: Name matching is done
- CASE INSENSITIVE!!! This function returns a pointer to the value
- if the variable name is found or NULL on failure.
- ***********************************************************************/
-
- char *FindCGIValue(CGIVarListT *CGIVars, char *VariableName) {
- char ScratchBuff[80];
- size_t VariableNameLength;
-
- strcpy(ScratchBuff,VariableName);
- strcat(ScratchBuff,"=");
- VariableNameLength = strlen(ScratchBuff);
- for(CGIVars->CurrentPos = 0; CGIVars->CurrentPos < CGIVars->NumValuePointers ; CGIVars->CurrentPos ++) {
- if(strnicmp(CGIVars->ValuePointers[CGIVars->CurrentPos],ScratchBuff,VariableNameLength) == 0) {
- return CGIVars->ValuePointers[CGIVars->CurrentPos] + VariableNameLength;
- }
- }
- return NULL;
- }
-
- /*********************************************************************
- FindNextCGIValue() starts examining variables beginning at the first
- variable after the last one examined by either FindCGIValue() or
- FindNextCGIValue(). It takes as a paramerer the CGIVarList structure
- (properly initilized me of course) and a pointer to the 0x00 terminated
- variable name. This returns either a pointer to the appropriate value
- if the value being looked for is found or NULL on failure. Note: Name
- matching is done CASE INSENSITIVE!!!
- *********************************************************************/
-
- char *FindNextCGIValue(CGIVarListT *CGIVars, char *VariableName) {
- char ScratchBuff[80];
- size_t VariableNameLength;
-
- strcpy(ScratchBuff,VariableName);
- strcat(ScratchBuff,"=");
- VariableNameLength = strlen(ScratchBuff);
-
- // Advance away from the last variable examined.
- if(CGIVars->CurrentPos + 1 < CGIVars->NumValuePointers)
- CGIVars->CurrentPos ++;
-
- for(; CGIVars->CurrentPos < CGIVars->NumValuePointers ; CGIVars->CurrentPos ++) {
- if(strnicmp(CGIVars->ValuePointers[CGIVars->CurrentPos],ScratchBuff,VariableNameLength) == 0) {
- return CGIVars->ValuePointers[CGIVars->CurrentPos] + VariableNameLength;
- }
- }
- return NULL;
- }
-
-
- /*
-
- Here is some pseudocode has to how the various
- functions may be called.
-
-
- // Standard CGI application
- int main() {
- CGIVarListT Vars;
- char *VariableValue;
-
- if(InititalizeCGIVars(&Vars,1024,12) == 0) {
- // Out of memory
- }
- if(ReadCGIData(&Vars) == 0) {
- // Out of memory
- }
- for (EachVariableYouWantToUse) {
- VariableValue = FindCGIValue(&Vars,"MyVariable");
- if(VariableValue == NULL) {
- // Variable Not Found.
- }
- }
- // Do your CGI stuff here.
-
-
- ClearCGIVars(&Vars);
- return 1;
- }
-
-
- Long Running CGI application
-
-
- int main() {
- CGIVarListT Vars;
- char *VariableValue;
-
- if(InititalizeCGIVars(&Vars,1024,12) == 0) {
- // Out of memory
- }
-
- for(EachProcess) {
- if(ReadCGIData(&Vars) == 0) {
- // Out of memory
- }
- for (EachVariableYouWantToUse) {
- VariableValue = FindCGIValue(&Vars,"MyVariable");
- if(VariableValue == NULL) {
- // Variable Not Found.
- }
- }
-
- // Do your CGI stuff here.
-
- ResetCGIVars(&Vars);
- }
-
- ClearCGIVars(&Vars);
- return 1;
- }
-
-
- */
-
-
-
-
- /*
- Simple test program which grabs the CGI data from the environment
- variables QUERY_STRING and HTTP_COOKIE.
-
- int main() {
- char Choice[80], *VariableValue;
- int Result;
- CGIVarListT Vars;
-
- putenv("QUERY_STRING=Jane=Doe%20a%20Deer&Dinkum=Software&Hewlett=Packard");
- putenv("HTTP_COOKIE=John=1&Mary=2&Henry=3&Joe=4");
-
- for(;;) {
- printf("\n\n1) Parse Header");
- printf("\n2) Get Value");
- printf("\n0) Quit\n:");
- gets(Choice);
- Result = atoi(Choice);
- switch(Result) {
- case 1: InititalizeCGIVars(&Vars,1024,12);
- ReadCGIData(&Vars);
- break;
- case 2: printf("\nVariable Name :");
- gets(Choice);
- VariableValue = FindCGIValue(&Vars,Choice);
- if(VariableValue != NULL)
- printf("Value = %s",VariableValue);
- else
- printf("Value = NULL");
- break;
- case 0: exit(1);
- };
- }
- }
-
-
- */
-
-
-
-