759 lines
23 KiB
C
759 lines
23 KiB
C
#include "type.h"
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Searches the list of parameters passed to a CGI handler and returns the
|
|
// index of a given parameter within that list.
|
|
//
|
|
// \param pcToFind is a pointer to a string containing the name of the
|
|
// parameter that is to be found.
|
|
// \param pcParam is an array of character pointers, each containing the name
|
|
// of a single parameter as encoded in the URI requesting the CGI.
|
|
// \param iNumParams is the number of elements in the pcParam array.
|
|
//
|
|
// This function searches an array of parameters to find the string passed in
|
|
// \e pcToFind. If the string is found, the index of that string within the
|
|
// \e pcParam array is returned, otherwise -1 is returned.
|
|
//
|
|
// \return Returns the index of string \e pcToFind within array \e pcParam
|
|
// or -1 if the string does not exist in the array.
|
|
//
|
|
//*****************************************************************************
|
|
int FindCGIParameter(const char *pcToFind, char *pcParam[], int iNumParams)
|
|
{
|
|
int iLoop;
|
|
|
|
//
|
|
// Scan through all the parameters in the array.
|
|
//
|
|
for(iLoop = 0; iLoop < iNumParams; iLoop++)
|
|
{
|
|
//
|
|
// Does the parameter name match the provided string?
|
|
//
|
|
if(strcmp(pcToFind, pcParam[iLoop]) == 0)
|
|
{
|
|
//
|
|
// We found a match - return the index.
|
|
//
|
|
return(iLoop);
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we drop out, the parameter was not found.
|
|
//
|
|
return(-1);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Determines whether a given character is a valid hexadecimal digit.
|
|
//
|
|
// \param cDigit is the ASCII character code to be checked for validity.
|
|
//
|
|
// This function checks the passed character to determime whether or not it is
|
|
// a valid hexadecimal digit.
|
|
//
|
|
// \return Returns \e true if the passed character is a valid hex digit or \e
|
|
// false otherwise
|
|
//
|
|
//*****************************************************************************
|
|
tBoolean IsValidHexDigit(const char cDigit)
|
|
{
|
|
if(((cDigit >= '0') && (cDigit <= '9')) ||
|
|
((cDigit >= 'a') && (cDigit <= 'f')) ||
|
|
((cDigit >= 'A') && (cDigit <= 'F')))
|
|
{
|
|
return(true);
|
|
}
|
|
else
|
|
{
|
|
return(false);
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Converts an ASCII character to a hex digit value.
|
|
//
|
|
// \param cDigit is the ASCII character code to convert to a number.
|
|
//
|
|
// This function converts a passed ASCII character to a number assuming that
|
|
// the character is a valid hexadecimal digit. If the character is not a valid
|
|
// hex digit, the value 0xFF is returned.
|
|
//
|
|
// \return Returns the number represented by hex digit \e cDigit or 0xFF if
|
|
// the character passed is not valid hex.
|
|
//
|
|
//*****************************************************************************
|
|
unsigned char HexDigit(const char cDigit)
|
|
{
|
|
if((cDigit >= '0') && (cDigit <= '9'))
|
|
{
|
|
return(cDigit - '0');
|
|
}
|
|
else
|
|
{
|
|
if((cDigit >= 'a') && (cDigit <= 'f'))
|
|
{
|
|
return((cDigit - 'a') + 10);
|
|
}
|
|
else
|
|
{
|
|
if((cDigit >= 'A') && (cDigit <= 'F'))
|
|
{
|
|
return((cDigit - 'A') + 10);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we get here, we were passed an invalid hex digit so return 0xFF.
|
|
//
|
|
return(0xFF);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Decodes a single %xx escape sequence as an ASCII character.
|
|
//
|
|
// \param pcEncoded points to the ``%'' character at the start of a three
|
|
// character escape sequence which represents a single ASCII character.
|
|
// \param pcDecoded points to a byte which will be written with the decoded
|
|
// character assuming the escape sequence is valid.
|
|
//
|
|
// This function decodes a single escape sequence of the form ``%xy'' where
|
|
// x and y represent hexadecimal digits. If each digit is a valid hex digit,
|
|
// the function writes the decoded character to the pcDecoded buffer and
|
|
// returns true, else it returns false.
|
|
//
|
|
// \return Returns \b true on success or \b false if pcEncoded does not point
|
|
// to a valid escape sequence.
|
|
//
|
|
//*****************************************************************************
|
|
tBoolean DecodeHexEscape(const char *pcEncoded, char *pcDecoded)
|
|
{
|
|
if((pcEncoded[0] != '%') || !IsValidHexDigit(pcEncoded[1]) ||
|
|
!IsValidHexDigit(pcEncoded[2]))
|
|
{
|
|
return(false);
|
|
}
|
|
else
|
|
{
|
|
*pcDecoded = ((HexDigit(pcEncoded[1]) * 16) +
|
|
HexDigit(pcEncoded[2]));
|
|
return(true);
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Encodes a string for use within an HTML tag, escaping non alphanumeric
|
|
// characters.
|
|
//
|
|
// \param pcDecoded is a pointer to a null terminated ASCII string.
|
|
// \param pcEncoded is a pointer to a storage for the encoded string.
|
|
// \param ulLen is the number of bytes of storage pointed to by pcEncoded.
|
|
//
|
|
// This function encodes a string, adding escapes in place of any special,
|
|
// non-alphanumeric characters. If the encoded string is too long for the
|
|
// provided output buffer, the output will be truncated.
|
|
//
|
|
// \return Returns the number of characters written to the output buffer
|
|
// not including the terminating NULL.
|
|
//
|
|
//*****************************************************************************
|
|
unsigned long
|
|
EncodeFormString(const char *pcDecoded, char *pcEncoded,
|
|
unsigned long ulLen)
|
|
{
|
|
unsigned long ulLoop;
|
|
unsigned long ulCount;
|
|
|
|
//
|
|
// Make sure we were not passed a tiny buffer.
|
|
//
|
|
if(ulLen <= 1)
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
//
|
|
// Initialize our output character counter.
|
|
//
|
|
ulCount = 0;
|
|
|
|
//
|
|
// Step through each character of the input until we run out of data or
|
|
// space to put our output in.
|
|
//
|
|
for(ulLoop = 0; pcDecoded[ulLoop] && (ulCount < (ulLen - 1)); ulLoop++)
|
|
{
|
|
switch(pcDecoded[ulLoop])
|
|
{
|
|
//
|
|
// Pass most characters without modification.
|
|
//
|
|
default:
|
|
{
|
|
pcEncoded[ulCount++] = pcDecoded[ulLoop];
|
|
break;
|
|
}
|
|
|
|
case '\'':
|
|
{
|
|
ulCount += snprintf(&pcEncoded[ulCount], (ulLen - ulCount),
|
|
"'");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return(ulCount);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Decodes a string encoded as part of an HTTP URI.
|
|
//
|
|
// \param pcEncoded is a pointer to a null terminated string encoded as per
|
|
// RFC1738, section 2.2.
|
|
// \param pcDecoded is a pointer to storage for the decoded, null terminated
|
|
// string.
|
|
// \param ulLen is the number of bytes of storage pointed to by pcDecoded.
|
|
//
|
|
// This function decodes a string which has been encoded using the method
|
|
// described in RFC1738, section 2.2 for URLs. If the decoded string is too
|
|
// long for the provided output buffer, the output will be truncated.
|
|
//
|
|
// \return Returns the number of character written to the output buffer, not
|
|
// including the terminating NULL.
|
|
//
|
|
//*****************************************************************************
|
|
unsigned long
|
|
DecodeFormString(const char *pcEncoded, char *pcDecoded,
|
|
unsigned long ulLen,int ign_quotation)
|
|
{
|
|
unsigned long ulLoop;
|
|
unsigned long ulCount;
|
|
tBoolean bValid;
|
|
|
|
ulCount = 0;
|
|
ulLoop = 0;
|
|
|
|
//
|
|
// Keep going until we run out of input or fill the output buffer.
|
|
//
|
|
while(pcEncoded[ulLoop] && (ulCount < (ulLen - 1)))
|
|
{
|
|
switch(pcEncoded[ulLoop])
|
|
{
|
|
//
|
|
// '+' in the encoded data is decoded as a space.
|
|
//
|
|
case '+':
|
|
{
|
|
pcDecoded[ulCount++] = ' ';
|
|
ulLoop++;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// '%' in the encoded data indicates that the following 2
|
|
// characters indicate the hex ASCII code of the decoded character.
|
|
//
|
|
case '%':
|
|
{
|
|
if(pcEncoded[ulLoop + 1] && pcEncoded[ulLoop + 2])
|
|
{
|
|
//
|
|
// Decode the escape sequence.
|
|
//
|
|
bValid = DecodeHexEscape(&pcEncoded[ulLoop],
|
|
&pcDecoded[ulCount]);
|
|
|
|
//
|
|
// If the escape sequence was valid, move to the next
|
|
// output character.
|
|
//
|
|
if(ign_quotation)//用户提交 " 字符,忽略,不做处理
|
|
{
|
|
if(pcDecoded[ulCount]=='"')
|
|
{
|
|
pcDecoded[ulCount]=' ';
|
|
}
|
|
}
|
|
if(bValid)
|
|
{
|
|
ulCount++;
|
|
}
|
|
|
|
//
|
|
// Skip past the escape sequence in the encoded string.
|
|
//
|
|
ulLoop += 3;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We reached the end of the string partway through an
|
|
// escape sequence so just ignore it and return the number
|
|
// of decoded characters found so far.
|
|
//
|
|
pcDecoded[ulCount] = '\0';
|
|
return(ulCount);
|
|
}
|
|
break;
|
|
}
|
|
case '"': //用户提交"" 字符,忽略,不做处理
|
|
if(ign_quotation)
|
|
{
|
|
pcDecoded[ulCount++] = ' ';
|
|
ulLoop++;
|
|
}
|
|
else
|
|
{
|
|
pcDecoded[ulCount++] = pcEncoded[ulLoop++];
|
|
}
|
|
break;
|
|
//
|
|
// For all other characters, just copy the input to the output.
|
|
//
|
|
default:
|
|
{
|
|
pcDecoded[ulCount++] = pcEncoded[ulLoop++];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Terminate the string and return the number of characters we decoded.
|
|
//
|
|
pcDecoded[ulCount] = '\0';
|
|
return(ulCount);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Ensures that a string passed represents a valid decimal number and,
|
|
// if so, converts that number to a long.
|
|
//
|
|
// \param pcValue points to a null terminated string which should contain an
|
|
// ASCII representation of a decimal number.
|
|
// \param plValue points to storage which will receive the number represented
|
|
// by pcValue assuming the string is a valid decimal number.
|
|
//
|
|
// This function determines whether or not a given string represents a valid
|
|
// decimal number and, if it does, converts the string into a decimal number
|
|
// which is returned to the caller.
|
|
//
|
|
// \return Returns \b true if the string is a valid representation of a
|
|
// decimal number or \b false if not.
|
|
|
|
//*****************************************************************************
|
|
tBoolean
|
|
CheckDecimalParam(const char *pcValue, long *plValue)
|
|
{
|
|
unsigned long ulLoop;
|
|
tBoolean bStarted;
|
|
tBoolean bFinished;
|
|
tBoolean bNeg;
|
|
long lAccum;
|
|
|
|
//
|
|
// Check that the string is a valid decimal number.
|
|
//
|
|
bStarted = false;
|
|
bFinished = false;
|
|
bNeg = false;
|
|
ulLoop = 0;
|
|
lAccum = 0;
|
|
|
|
while(pcValue[ulLoop])
|
|
{
|
|
//
|
|
// Ignore whitespace before the string.
|
|
//
|
|
if(!bStarted)
|
|
{
|
|
if((pcValue[ulLoop] == ' ') || (pcValue[ulLoop] == '\t'))
|
|
{
|
|
ulLoop ++;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Ignore a + or - character as long as we have not started.
|
|
//
|
|
if((pcValue[ulLoop] == '+') || (pcValue[ulLoop] == '-'))
|
|
{
|
|
//
|
|
// If the string starts with a '-', remember to negate the
|
|
// result.
|
|
//
|
|
bNeg = (pcValue[ulLoop] == '-') ? true : false;
|
|
bStarted = true;
|
|
ulLoop++;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We found something other than whitespace or a sign character
|
|
// so we start looking for numerals now.
|
|
//
|
|
bStarted = true;
|
|
}
|
|
}
|
|
|
|
if(bStarted)
|
|
{
|
|
if(!bFinished)
|
|
{
|
|
//
|
|
// We expect to see nothing other than valid digit characters
|
|
// here.
|
|
//
|
|
if((pcValue[ulLoop] >= '0') && (pcValue[ulLoop] <= '9'))
|
|
{
|
|
lAccum = (lAccum * 10) + (pcValue[ulLoop] - '0');
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Have we hit whitespace? If so, check for no more
|
|
// characters until the end of the string.
|
|
//
|
|
if((pcValue[ulLoop] == ' ') || (pcValue[ulLoop] == '\t'))
|
|
{
|
|
bFinished = true;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We got something other than a digit or whitespace so
|
|
// this makes the string invalid as a decimal number.
|
|
//
|
|
return(false);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We are scanning for whitespace until the end of the string.
|
|
//
|
|
if((pcValue[ulLoop] != ' ') && (pcValue[ulLoop] != '\t'))
|
|
{
|
|
//
|
|
// We found something other than whitespace so the string
|
|
// is not valid.
|
|
//
|
|
return(false);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Move on to the next character in the string.
|
|
//
|
|
ulLoop++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we drop out of the loop, the string must be valid. All we need to do
|
|
// now is negate the accumulated value if the string started with a '-'.
|
|
//
|
|
*plValue = bNeg ? -lAccum : lAccum;
|
|
return(true);
|
|
}
|
|
|
|
void CheckStringParam(const char *pcValue, char *pbuf)
|
|
{
|
|
unsigned long ulLoop;
|
|
tBoolean bStarted;
|
|
|
|
// Check that the string is a valid string.
|
|
bStarted = false;
|
|
ulLoop = 0;
|
|
|
|
while(pcValue[ulLoop])
|
|
{
|
|
// Ignore whitespace before the string.
|
|
if(!bStarted)
|
|
{
|
|
if((pcValue[ulLoop] == ' ') || (pcValue[ulLoop] == '\t')|| (pcValue[ulLoop] == '\"'))
|
|
{
|
|
ulLoop ++;
|
|
continue;
|
|
}
|
|
bStarted = true;
|
|
}
|
|
|
|
if(bStarted)
|
|
{
|
|
if((pcValue[ulLoop] == '\t')|| (pcValue[ulLoop] == '\"')||(pcValue[ulLoop] == '\0'))
|
|
{
|
|
*pbuf = 0;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
*pbuf++ = pcValue[ulLoop];
|
|
}
|
|
|
|
ulLoop++;
|
|
}
|
|
}
|
|
*pbuf = 0;
|
|
return;
|
|
}
|
|
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Searches the list of parameters passed to a CGI handler for a parameter
|
|
// with the given name and, if found, reads the parameter value as a decimal
|
|
// number.
|
|
//
|
|
// \param pcName is a pointer to a string containing the name of the
|
|
// parameter that is to be found.
|
|
// \param pcParam is an array of character pointers, each containing the name
|
|
// of a single parameter as encoded in the URI requesting the CGI.
|
|
// \param iNumParams is the number of elements in the pcParam array.
|
|
// \param pcValues is an array of values associated with each parameter from
|
|
// the pcParam array.
|
|
// \param pbError is a pointer that will be written to \b true if there is any
|
|
// error during the parameter parsing process (parameter not found, value is
|
|
// not a valid decimal number).
|
|
//
|
|
// This function searches an array of parameters to find the string passed in
|
|
// \e pcName. If the string is found, the corresponding parameter value is
|
|
// read from array pcValues and checked to make sure that it is a valid
|
|
// decimal number. If so, the number is returned. If any error is detected,
|
|
// parameter \e pbError is written to \b true. Note that \e pbError is NOT
|
|
// written if the parameter is successfully found and validated. This is to
|
|
// allow multiple parameters to be parsed without the caller needing to check
|
|
// return codes after each individual call.
|
|
//
|
|
// \return Returns the value of the parameter or 0 if an error is detected (in
|
|
// which case \e *pbError will be \b true).
|
|
//
|
|
//*****************************************************************************
|
|
long
|
|
GetCGIParam(const char *pcName, char *pcParams[], char *pcValue[],
|
|
int iNumParams, tBoolean *pbError)
|
|
{
|
|
int iParam;
|
|
long lValue;
|
|
tBoolean bRetcode;
|
|
|
|
//
|
|
// Is the parameter we are looking for in the list?
|
|
//
|
|
*pbError = false;
|
|
iParam = FindCGIParameter(pcName, pcParams, iNumParams);
|
|
if(iParam != -1)
|
|
{
|
|
//
|
|
// We found the parameter so now get its value.
|
|
//
|
|
bRetcode = CheckDecimalParam(pcValue[iParam], &lValue);
|
|
if(bRetcode)
|
|
{
|
|
//
|
|
// All is well - return the parameter value.
|
|
//
|
|
return(lValue);
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we reach here, there was a problem so return 0 and set the error
|
|
// flag.
|
|
//
|
|
*pbError = true;
|
|
return(0);
|
|
}
|
|
|
|
long GetCGIStringParam(const char *pcName, char *pcParams[], char *pcValue[],
|
|
int iNumParams,char *pbuf,int buflen,int ign_quotation)
|
|
{
|
|
int iParam;
|
|
|
|
// Is the parameter we are looking for in the list?
|
|
iParam = FindCGIParameter(pcName, pcParams, iNumParams);
|
|
if(iParam != -1)
|
|
{
|
|
// We found the parameter so now get its value.
|
|
//CheckStringParam(pcValue[iParam], pbuf);
|
|
return DecodeFormString(pcValue[iParam], pbuf,buflen,ign_quotation);
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
tBoolean
|
|
CheckHexParam(const char *pcValue, long *plValue)
|
|
{
|
|
unsigned long ulLoop;
|
|
tBoolean bStarted;
|
|
tBoolean bFinished;
|
|
tBoolean bNeg;
|
|
long lAccum;
|
|
|
|
//
|
|
// Check that the string is a valid HEX number.
|
|
//
|
|
bStarted = false;
|
|
bFinished = false;
|
|
bNeg = false;
|
|
ulLoop = 0;
|
|
lAccum = 0;
|
|
|
|
while(pcValue[ulLoop])
|
|
{
|
|
//
|
|
// Ignore whitespace before the string.
|
|
//
|
|
if(!bStarted)
|
|
{
|
|
if((pcValue[ulLoop] == ' ') || (pcValue[ulLoop] == '\t')|| (pcValue[ulLoop] == '\"'))
|
|
{
|
|
ulLoop ++;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Ignore a + or - character as long as we have not started.
|
|
//
|
|
if((pcValue[ulLoop] == '+') || (pcValue[ulLoop] == '-'))
|
|
{
|
|
//
|
|
// If the string starts with a '-', remember to negate the
|
|
// result.
|
|
//
|
|
bNeg = (pcValue[ulLoop] == '-') ? true : false;
|
|
bStarted = true;
|
|
ulLoop++;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We found something other than whitespace or a sign character
|
|
// so we start looking for numerals now.
|
|
//
|
|
bStarted = true;
|
|
}
|
|
}
|
|
|
|
if(bStarted)
|
|
{
|
|
if(!bFinished)
|
|
{
|
|
//
|
|
// We expect to see nothing other than valid digit characters
|
|
// here.
|
|
//
|
|
if((pcValue[ulLoop] >= '0') && (pcValue[ulLoop] <= '9'))
|
|
{
|
|
lAccum = (lAccum * 16) + (pcValue[ulLoop] - '0');
|
|
}
|
|
else if((pcValue[ulLoop] >= 'A') && (pcValue[ulLoop] <= 'F'))
|
|
{
|
|
lAccum = (lAccum * 16) + (pcValue[ulLoop]+ 10 - 'A');
|
|
}
|
|
else if((pcValue[ulLoop] >= 'a') && (pcValue[ulLoop] <= 'f'))
|
|
{
|
|
lAccum = (lAccum * 16) + (pcValue[ulLoop]+ 10 - 'a');
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Have we hit whitespace? If so, check for no more
|
|
// characters until the end of the string.
|
|
//
|
|
if((pcValue[ulLoop] == ' ') || (pcValue[ulLoop] == '\t')|| (pcValue[ulLoop] == '\"'))
|
|
{
|
|
bFinished = true;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We got something other than a digit or whitespace so
|
|
// this makes the string invalid as a decimal number.
|
|
//
|
|
return(false);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We are scanning for whitespace until the end of the string.
|
|
//
|
|
if((pcValue[ulLoop] != ' ') && (pcValue[ulLoop] != '\t')|| (pcValue[ulLoop] == '\"'))
|
|
{
|
|
//
|
|
// We found something other than whitespace so the string
|
|
// is not valid.
|
|
//
|
|
return(false);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Move on to the next character in the string.
|
|
//
|
|
ulLoop++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we drop out of the loop, the string must be valid. All we need to do
|
|
// now is negate the accumulated value if the string started with a '-'.
|
|
//
|
|
*plValue = bNeg ? -lAccum : lAccum;
|
|
return(true);
|
|
}
|
|
long
|
|
GetCGIHexParam(const char *pcName, char *pcParams[], char *pcValue[],
|
|
int iNumParams, tBoolean *pbError)
|
|
{
|
|
int iParam;
|
|
long lValue;
|
|
tBoolean bRetcode;
|
|
|
|
*pbError = false;
|
|
//
|
|
// Is the parameter we are looking for in the list?
|
|
//
|
|
iParam = FindCGIParameter(pcName, pcParams, iNumParams);
|
|
if(iParam != -1)
|
|
{
|
|
//
|
|
// We found the parameter so now get its value.
|
|
//
|
|
bRetcode = CheckHexParam(pcValue[iParam], &lValue);
|
|
if(bRetcode)
|
|
{
|
|
//
|
|
// All is well - return the parameter value.
|
|
//
|
|
return(lValue);
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we reach here, there was a problem so return 0 and set the error
|
|
// flag.
|
|
//
|
|
*pbError = true;
|
|
return(0);
|
|
}
|
|
|