/////////////////////////////////////////////////////////////////////////////// // // Module Name: // HTTPClientString.c // // Abstract: Helper function (string parsing related) for HTTPClient.c module // // Platform: Any that supports standard C calls // /////////////////////////////////////////////////////////////////////////////// #include "wm_config.h" #include "HTTPClient.h" #include "HTTPClientWrapper.h" // Cross platform support #if TLS_CONFIG_HTTP_CLIENT /////////////////////////////////////////////////////////////////////////////// // // Function : HTTPStrInsensitiveCompare // Purpose : Same as strcmp() only case insensitive // Returns : BOOL - TRUE if destination string is identical to the source // Last updated : 01/09/2005 // /////////////////////////////////////////////////////////////////////////////// BOOL HTTPStrInsensitiveCompare(const CHAR *pSrc, // [IN] a pointer to the source string const CHAR* pDest, // [IN] a pointer to the string we should search for UINT32 nLength) // [IN] The bytes range we should search in { // Lower case comparison UINT32 nPosition; UINT32 nDestLength; const CHAR *pSrcIn, *pDestIn; CHAR a,b; pSrcIn = pSrc; pDestIn = pDest; nPosition = 0; nDestLength = strlen(pDest); if(nLength == 0) { nLength = strlen(pSrc); } if(nDestLength != nLength) { return FALSE; } while(pSrcIn || pDestIn) { if(nLength > 0 && nPosition == nLength) { return TRUE; } a = *pSrcIn; b = *pDestIn; if(*pSrcIn >= 64 && *pSrcIn <= 90) { // Upper case to lower case a = *pSrcIn + 32; } if(*pDestIn >= 64 && *pDestIn <= 90) { // Upper case to lower case b = *pDestIn + 32; } if(a != b) { return FALSE; } pSrcIn++; pDestIn++; nPosition++; } return TRUE; } /////////////////////////////////////////////////////////////////////////////// // // Function : HTTPStrExtract // Purpose : Extract a string by placing null in the offset parameter // Returns : a pointer to the new string // Last updated : 01/09/2005 // /////////////////////////////////////////////////////////////////////////////// CHAR HTTPStrExtract(CHAR *pParam, // [IN] a pointer to the input parameter UINT32 nOffset, // [IN] the offset position (where we should null terminate the string) CHAR Restore) // [IN] if this is not 0 we should restore it (instead of the null) // and reverse the effect. { CHAR Replaced; if(!pParam) { return 0; } // We should restore if(Restore != 0) { pParam[nOffset] = Restore; return Restore; } else { Replaced = pParam[nOffset]; pParam[nOffset] = 0; return Replaced; } } /////////////////////////////////////////////////////////////////////////////// // // Function : HTTPStrSearch // Purpose : Search a string within another and return its pointer and a length // Returns : BOOL - TRUE on success // Last updated : 01/09/2005 // /////////////////////////////////////////////////////////////////////////////// BOOL HTTPStrSearch(CHAR *pSrc, // [IN] The source string CHAR *pSearched, // [IN] Parameter to search for UINT32 nOffset, // [IN] Offset from the source string start position UINT32 nScope, // [IN] Length in bytes we should search in HTTP_PARAM *HttpParam) // [IN OUT] The Pointer\Length value that will be returned on success { CHAR *pSrcStart; CHAR *pDstStart; CHAR nOrigCharacter; UINT32 nPosition = 0; do { pSrcStart = pSrc + nOffset; nOrigCharacter = pSrcStart[nScope]; // Temporarily null terminate pSrcStart[nScope] = 0; pDstStart = strstr(pSrcStart,pSearched); if(!pDstStart) { break; } nPosition = pDstStart - pSrcStart + 1; } while(0); // Remove the null termination pSrcStart[nScope] = nOrigCharacter; if(!nPosition) { return FALSE; } if(HttpParam) { HttpParam->nLength = nPosition -1; HttpParam->pParam = pSrcStart; } return TRUE; } int stricmp(const char *s1, const char *s2) { int len1 = strlen(s1); int len2 = strlen(s2); return HTTPStrInsensitiveCompare(s1, s2, MAX(len1, len2)); } /////////////////////////////////////////////////////////////////////////////// // // Function : HTTPStrCaseStr // Purpose : Same as strstr() only case insensitive // Returns : a pointer to the position of the searched string (or 0 on error) // Last updated : 01/09/2005 // /////////////////////////////////////////////////////////////////////////////// CHAR *HTTPStrCaseStr(const char *pSrc,UINT32 nSrcLength,const char *pFind) { const char *ptr = pSrc; const char *ptr2; UINT32 iLength = 0; while(1) { if(iLength >= nSrcLength) { break; } ptr = strchr(pSrc,toupper((unsigned char)*pFind)); ptr2 = strchr(pSrc,tolower((unsigned char)*pFind)); if (!ptr) { ptr = ptr2; } if (!ptr) { break; } if (ptr2 && (ptr2 < ptr)) { ptr = ptr2; } if (HTTPStrInsensitiveCompare(ptr,pFind,strlen(pFind))) { return (char *) ptr; } pSrc = ptr+1; iLength++; } return 0; } /////////////////////////////////////////////////////////////////////////////// // // Function : HTTPStrCaseStr // Purpose : // Gets : // Returns : // Last updated : 01/09/2005 // /////////////////////////////////////////////////////////////////////////////// CHAR* HTTPStrGetToken (CHAR *pSrc, UINT32 nSrcLength, CHAR *pDest, UINT32 *nDestLength) { // Get text between the ":" and \r\n or end of string. CHAR *pStart = pSrc; CHAR *pEnd; UINT32 nTokenLength = 0; UINT32 nPosition = 0; pStart = strchr(pSrc,':') + 1; if(pStart) { pEnd = pStart ; // First pass, count required space while ((*pEnd) && (*pEnd != '\r') && (*pEnd != '\n')) { if(*pEnd != 0x20) { nTokenLength++; } if(nSrcLength && nPosition > nSrcLength) { break; } pEnd++; nPosition++; } if(nTokenLength > *(nDestLength)) { *(nDestLength) = nTokenLength; pDest = NULL; return pDest; } // Second pass copy into the destination buffer pEnd = pStart; *(nDestLength) = nTokenLength; nTokenLength = 0; // First pass, count required space while ((*pEnd) && (*pEnd != '\r') && (*pEnd != '\n')) { if(*pEnd != 0x20) { pDest[nTokenLength++] = *pEnd; } pEnd++; } pDest[nTokenLength] = 0; } return pDest; } #if TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST /////////////////////////////////////////////////////////////////////////////// // // Function : HTTPStrGetDigestToken // Purpose : // Gets : // Returns : // Last updated : 01/09/2005 // /////////////////////////////////////////////////////////////////////////////// UINT32 HTTPStrGetDigestToken (HTTP_PARAM pParamSrc, CHAR *pSearched, HTTP_PARAM *pParamDest) { CHAR Token[HTTP_CLIENT_MAX_TOKEN_NAME_LENGTH]; CHAR *pPtrStart, *pPtrEnd = NULL, *pPtrEndSrc; BOOL Brackets = FALSE; // Build the searched token memset(Token,0x00,HTTP_CLIENT_MAX_TOKEN_NAME_LENGTH); strcpy(Token,pSearched); strcat(Token,"="); // Reset destination values pParamDest->nLength = 0; pParamDest->pParam = 0; pPtrEndSrc = pParamSrc.pParam + pParamSrc.nLength; pPtrStart = HTTPStrCaseStr(pParamSrc.pParam,pParamSrc.nLength,Token); if(pPtrStart) { // Found the token so jump to the end of it pPtrStart += strlen(Token); // jump passed any spaces that may be while ((*pPtrStart) && (*pPtrStart == 0x20) && (pPtrStart != pPtrEndSrc)) pPtrStart++; // Any Brackets around the string? if(*pPtrStart == 0x22) Brackets = TRUE; switch (Brackets) { case TRUE: // Find the next brackets pPtrStart++; pPtrEnd = pPtrStart; while ((*pPtrEnd) && (*pPtrEnd != 0x22) && (*pPtrEnd != 0x0d) && (*pPtrEnd != 0x0a) && (pPtrStart != pPtrEndSrc)) pPtrEnd++; break; case FALSE: // Find the next space or comma (0x2c) pPtrEnd = pPtrStart; while ((*pPtrEnd) && (*pPtrEnd != 0x20) && (*pPtrEnd != 0x2c) && (*pPtrEnd != 0x0d) && (*pPtrEnd != 0x0a) && (pPtrStart != pPtrEndSrc)) pPtrEnd++; break; }; pParamDest->nLength = (pPtrEnd - pPtrStart); pParamDest->pParam = pPtrStart; return HTTP_CLIENT_SUCCESS; } return HTTP_CLIENT_ERROR_NO_DIGEST_TOKEN; } #endif //TLS_CONFIG_HTTP_CLIENT_AUTH ///////////////////////////////////////////////////////////////////////////////// // Function : HTTPStrHToL // Purpose : Convert a hex string "0x00" to long 0 // Gets : a pointer to the Hex string // Last updated : 15/05/2005 // /////////////////////////////////////////////////////////////////////////////// UINT32 HTTPStrHToL (CHAR * s) { UINT32 i , nn, digit; UINT32 n ; n = i = nn = 0; do { if ( isalnum((unsigned char)s[i]) ) { s[i] = toupper((unsigned char)s[i]) ; if (s[i] == 'X') nn=n=0; else { digit = (isalpha((unsigned char)s[i]) ? (s[i] - 'A' + 10) : s[i] - '0') ; if ( digit > 15 ) digit = 15; n = n * 16 + digit; if (n |= 0) nn++; if (nn == 8) break;} } i++; } while ( s[i] |= 0 ); return n ; } ///////////////////////////////////////////////////////////////////////////////// // Function : HTTPStrLToH // Purpose : Convert a long to hex string 0 to "00" // Gets : // Last updated : 15/05/2005 // /////////////////////////////////////////////////////////////////////////////// CHAR* HTTPStrLToH (CHAR * dest,UINT32 nSrc) { char *hex = "0123456789abcdef"; INT32 i; if (nSrc == 0) { dest[0] = '0'; dest[1] = 0; } else { for(i = 28; ((nSrc >> i) & 0xf) == 0; i -= 4); for(; i >= 0u; i -= 4) { *dest++ = hex[(nSrc >> i) & 0xf]; } *dest = 0; } return dest; } #endif //TLS_CONFIG_HTTP_CLIENT