/*++ Copyright (c) 1994 Microsoft Corporation Module Name: request.cxx Abstract: Contains HTTP utility functions Contents: pHttpGetUrlLen pHttpGetUrlString pHttpBuildUrl Author: Keith Moore (keithmo) 16-Nov-1994 Revision History: --*/ #include #include "httpp.h" // // functions // DWORD pHttpGetUrlLen( IN INTERNET_SCHEME SchemeType, IN LPSTR lpszTargetName, IN LPSTR lpszObjectName, IN DWORD dwPort, OUT LPDWORD lpdwUrlLen ) /*++ Routine Description: This routine finds the length of an HTTP URL from targethostname port and the object and returns the length Arguments: SchemeType - type of scheme for URL lpszTargetName - host name lpszObjectName - URL-path dwPort - port (if not default) lpdwUrlLen - returned URL length Return Value: DWORD --*/ { LPSTR schemeName; DWORD schemeLength; schemeName = MapUrlScheme(SchemeType, &schemeLength); if (schemeName == NULL) { return ERROR_WINHTTP_UNRECOGNIZED_SCHEME; } int portLen; *lpdwUrlLen = 0; if (dwPort) { CHAR TcpipPortString[32]; //itoa(dwPort, TcpipPortString, 10); wsprintf(TcpipPortString, "%d", dwPort); portLen = lstrlen(TcpipPortString); } else { portLen = 0; } *lpdwUrlLen = schemeLength + sizeof("://") + portLen + lstrlen(lpszTargetName) + lstrlen(lpszObjectName) ; return ERROR_SUCCESS; } DWORD pHttpGetUrlString( IN INTERNET_SCHEME SchemeType, IN LPSTR lpszTargetName, IN LPSTR lpszCWD, IN LPSTR lpszObjectName, IN LPSTR lpszExtension, IN DWORD dwPort, OUT LPSTR * lplpUrlName, OUT LPDWORD lpdwUrlLen ) /*++ Routine Description: This routine returns a LocaAlloc'ed buffer containing an HTTP URL constructed from the TargetHost, the ObjectName and the port. The caller is responsible for freeing the memory. Arguments: SchemeType - lpszTargetName - lpszCWD - lpszObjectName - lpszExtension - dwPort - lplpUrlName - lpdwUrlLen - Return Value: DWORD --*/ { DWORD dwError= ERROR_SUCCESS, dwSav, i; URL_COMPONENTSA sUrlComp; char *pBuff = (char *) ALLOCATE_FIXED_MEMORY(INTERNET_MAX_URL_LENGTH); UNREFERENCED_PARAMETER(lpszExtension); UNREFERENCED_PARAMETER(lpszCWD); if (pBuff == NULL) { dwError = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } INET_ASSERT(lpszCWD == NULL); *lplpUrlName = NULL; memset(&sUrlComp, 0, sizeof(sUrlComp)); sUrlComp.dwStructSize = sizeof(sUrlComp); sUrlComp.nScheme = SchemeType; sUrlComp.lpszHostName = lpszTargetName; sUrlComp.lpszUrlPath = lpszObjectName; sUrlComp.nPort = (INTERNET_PORT)dwPort; dwSav = INTERNET_MAX_URL_LENGTH; for (i=0; i<2; i++) { if(!WinHttpCreateUrlA(&sUrlComp, 0, pBuff, &dwSav)) { dwError = GetLastError(); if ((dwError == ERROR_INSUFFICIENT_BUFFER) && (i==0)) { //do not use reallocate here not to initiate unnecessary memory copy FREE_MEMORY(pBuff); pBuff = (char*)ALLOCATE_FIXED_MEMORY(dwSav); if (pBuff) { continue; } else { dwError = ERROR_NOT_ENOUGH_MEMORY; } } goto Cleanup; } else { dwError = ERROR_SUCCESS; break; } } // BUGBUG, this is because WinHttpCreateUrl is not returning // the correct size dwSav = strlen(pBuff)+5; for(i=0;i<2;++i) { *lplpUrlName = (LPSTR)ALLOCATE_ZERO_MEMORY(dwSav); if (*lplpUrlName) { if(!InternetCanonicalizeUrl(pBuff, *lplpUrlName, &dwSav, ICU_ENCODE_SPACES_ONLY)){ FREE_MEMORY(*lplpUrlName); // general paranoia *lplpUrlName = NULL; dwError = GetLastError(); if ((i == 1) || (dwError != ERROR_INSUFFICIENT_BUFFER)) { goto Cleanup; } } else { dwError = ERROR_SUCCESS; *lpdwUrlLen = dwSav; break; } } else { SetLastError(dwError = ERROR_NOT_ENOUGH_MEMORY); goto Cleanup; } } Cleanup: if (pBuff) FREE_MEMORY(pBuff); if (dwError != ERROR_SUCCESS) { INET_ASSERT(!*lplpUrlName); *lpdwUrlLen = 0; } return (dwError); } DWORD pHttpBuildUrl( IN INTERNET_SCHEME SchemeType, IN LPSTR lpszTargetName, IN LPSTR lpszObjectName, IN DWORD dwPort, IN LPSTR lpszUrl, IN OUT LPDWORD lpdwBuffSize ) /*++ Routine Description: This routine builds an HTTP URL in the buffer passed. If the size is not enough it returns ERROR_INSUFFICIENT_BUFFER. Arguments: SchemeType - type of scheme - http, gopher, etc. lpszTargetName - host name lpszObjectName - URL-path dwPort - port number (if not default) lpszUrl - place to write URL lpdwBuffSize - IN: size of lpszUrl buffer OUT: size of URL written to lpszUrl Return Value: DWORD --*/ { DWORD dwBuffLen; DWORD error; error = pHttpGetUrlLen(SchemeType, lpszTargetName, lpszObjectName, dwPort, &dwBuffLen ); if (error != ERROR_SUCCESS) { return error; } if (dwBuffLen > *lpdwBuffSize) { return (ERROR_INSUFFICIENT_BUFFER); } LPSTR schemeName; DWORD schemeLength; schemeName = MapUrlScheme(SchemeType, &schemeLength); if (schemeName == NULL) { // // should never happen // INET_ASSERT(FALSE); return ERROR_WINHTTP_UNRECOGNIZED_SCHEME; } LPSTR p = lpszUrl; int len; int urlLength; memcpy((LPVOID)p, (LPVOID)schemeName, schemeLength); p += schemeLength; urlLength = schemeLength; memcpy((LPVOID)p, (LPVOID)"://", sizeof("://") - 1); p += sizeof("://") - 1; urlLength += sizeof("://") - 1; len = lstrlen(lpszTargetName); memcpy((LPVOID)p, (LPVOID)lpszTargetName, len); p += len; urlLength += len; if (dwPort && (dwPort != INTERNET_DEFAULT_HTTP_PORT)) { CHAR TcpipPortString[32]; //itoa(dwPort, TcpipPortString, 10); wsprintf(TcpipPortString, "%d", dwPort); INET_ASSERT(TcpipPortString[0] != '\0'); *p++ = ':'; len = lstrlen(TcpipPortString); memcpy((LPVOID)p, (LPVOID)TcpipPortString, len); p += len; urlLength += len + 1; } len = lstrlen(lpszObjectName); memcpy((LPVOID)p, (LPVOID)lpszObjectName, len); urlLength += len; *lpdwBuffSize = urlLength; return ERROR_SUCCESS; }