📄 sbineturl.cpp
字号:
} else { absoluteUrl = baseUrl; const VXIchar* absoluteUrlStr = absoluteUrl.c_str(); const VXIchar* pathPtr = wcsstr(absoluteUrlStr, L"://"); if (pathPtr) pathPtr += 3; else pathPtr = absoluteUrlStr; if (relativeUrl[0] == L'/' && relativeUrl[1] != L'/') { // The relative URL is an absolute path. // Find the pointer to the beginning of the path in the absoluteUrl. pathPtr = wcschr(pathPtr, L'/'); if (pathPtr) absoluteUrl.resize(pathPtr - absoluteUrlStr); } else { // The relative URL is a relative path. // Find the pointer to the end of the path. pathPtr = wcsrchr(pathPtr, L'/'); if (pathPtr) { // Clear anything after the last slash in the path part of the // absolute URL. ++pathPtr; absoluteUrl.resize(pathPtr - absoluteUrlStr); } else { // Add a slash at the end of the absolute URL if it didn't have one. absoluteUrl += L"/"; } } // Remove the ../ and move up // the abs. url accordingly // Remove .. from relative url and go up one level in absolute url // Remove the last '/' from the abs. url vxistring absUrl = absoluteUrl.c_str(); if( absUrl[absUrl.length() - 1] == L'/' ) absUrl.erase(absUrl.length() - 1 ); // find the first "../" string from rel. url vxistring relUrl = relativeUrl; vxistring::size_type pos = 0; vxistring::size_type idx, i; idx = relUrl.find(L"../", pos); while( idx != vxistring::npos ) { // first remove the ../ from rel. url relUrl.erase(idx, idx+3); // go up one level from the abs. url i = absUrl.rfind(L"/"); if( i != vxistring::npos ) absUrl.erase(i); idx = relUrl.find(L"../", idx - 2); } // take care of '//' if( relUrl.substr(0,2) == L"//" ) { idx = absUrl.find(L"://"); if ( idx != vxistring::npos ) absUrl.erase(idx+1); } // insert the last '/' to abs. url if( relUrl[0] != L'/' ) absUrl.push_back(L'/'); absUrl += relUrl.c_str(); absoluteUrl = absUrl.c_str(); } return VXIinet_RESULT_SUCCESS; } VXIinetResult SBinetURL::parse(const VXIchar* pszUrl, const VXIchar* pszUrlBase) { // TBD: Must apply SPR 7530 fix here too, for now only in WinInetResolveUrl, // support for relative URL starting with / as specified by the RFC that // defines file:// access VXIinetResult eResult( VXIinet_RESULT_SUCCESS ); if( !pszUrl || !pszUrl[0]) { //Error(200, L"%s%s", L"Operation", L"parse URL"); return VXIinet_RESULT_INVALID_ARGUMENT; } if (pszUrlBase != NULL) _baseURL = pszUrlBase; else _baseURL = L""; // Combine the base and relative URLs to get an absolute URL. eResult = combineURL(pszUrlBase, pszUrl, _absoluteURL); if (eResult == VXIinet_RESULT_SUCCESS) { // Parse the absolute URL into its components. URLInfo urlInfo; eResult = parseURL(_absoluteURL.c_str(), urlInfo); if (eResult == VXIinet_RESULT_SUCCESS) { if (!wcscmp(urlInfo.protocol.c_str(), L"file")) { _protocol = FILE_PROTOCOL; } else if (!wcscmp(urlInfo.protocol.c_str(), L"http")) { _protocol = HTTP_PROTOCOL; _host = urlInfo.host; _port = urlInfo.port == -1 ? 80 : urlInfo.port; } else if (!wcscmp(urlInfo.protocol.c_str(), L"https")) { _protocol = HTTPS_PROTOCOL; _host = urlInfo.host; _port = urlInfo.port == -1 ? 443 : urlInfo.port; } else { eResult = VXIinet_RESULT_NON_FATAL_ERROR; } } if (eResult == VXIinet_RESULT_SUCCESS) { _strPath = urlInfo.path; // Remove trailing / in absolute URL to ensure that www.speechworks.com // and www.speechworks.com/ are seen as the same URL. int idx = _absoluteURL.length() - 1; if (_absoluteURL[idx] == L'/') _absoluteURL.resize(idx); } } N_absoluteURL = _absoluteURL; N_baseURL = _baseURL; N_host = _host; N_strPath = _strPath; return eResult; } #endif /* WIN32 */ SBinetNString SBinetURL::valueToNString(const VXIValue* value) { // Convert numeric types using a narrow character buffer in order to // avoid the need for swprintf( ) which doesn't exist in the GNU // GCC C library for GCC 2.x and earlier. char tempBuf[32]; *tempBuf = '\0'; switch (VXIValueGetType(value)) { case VALUE_BOOLEAN: { VXIbool valBool = VXIBooleanValue( (const VXIBoolean *)value ); sprintf (tempBuf, "%s", valBool ? "true" : "false"); } break; case VALUE_INTEGER: { VXIint32 valInt = VXIIntegerValue( (const VXIInteger *)value ); sprintf (tempBuf, "%d", valInt); } break; case VALUE_FLOAT: { VXIflt32 valFloat = VXIFloatValue( (const VXIFloat *)value ); sprintf (tempBuf, "%f", valFloat); } break; case VALUE_STRING: return VXIStringCStr( (const VXIString *)value ); case VALUE_PTR: { void *valPtr = VXIPtrValue( (const VXIPtr *)value ); sprintf (tempBuf, "%p", valPtr); } break; case VALUE_MAP: case VALUE_VECTOR: case VALUE_CONTENT: default: // These types are supposed to be handled before entering this function. break; } return tempBuf; } bool SBinetURL::requiresMultipart(const VXIValue *value) { switch (VXIValueGetType(value)) { case VALUE_CONTENT: return true; case VALUE_MAP: return requiresMultipart((const VXIMap*) value); case VALUE_VECTOR: return requiresMultipart((const VXIVector*) value); default: return false; } } bool SBinetURL::requiresMultipart(const VXIMap* vximap) { if (vximap == NULL) return false; const VXIchar *key = NULL; const VXIValue *value = NULL; bool result = false; VXIMapIterator *mapIterator = VXIMapGetFirstProperty( vximap, &key, &value ); do { if (key != NULL && value != NULL && requiresMultipart(value)) { result = true; break; } } while (VXIMapGetNextProperty(mapIterator, &key, &value) == VXIvalue_RESULT_SUCCESS); VXIMapIteratorDestroy(&mapIterator); return result; } bool SBinetURL::requiresMultipart(const VXIVector* vxivector) { for (VXIunsigned i = VXIVectorLength(vxivector); i > 0; i--) { const VXIValue* value = VXIVectorGetElement(vxivector, i); if (value != NULL && requiresMultipart(value)) { return true; } } return false; } void SBinetURL::appendQueryArgsToURL(const VXIMap* queryArgs) { SBinetNString queryArgsNStr = queryArgsToNString(queryArgs); if (queryArgsNStr.length() > 0) { const wchar_t delim = wcschr(_strPath.c_str(), L'?') == NULL ? L'?' : L'&'; _strPath += delim; _strPath += queryArgsNStr; _absoluteURL += delim; _absoluteURL += queryArgsNStr; // maintain narrow and wide representations synchronized. N_strPath += delim; N_strPath += queryArgsNStr; N_absoluteURL += delim; N_absoluteURL += queryArgsNStr; } } SBinetNString SBinetURL::queryArgsToNString(const VXIMap* queryArgs) const { SBinetNString result; if (queryArgs) { VXIString *strResult = VXIValueToString((const VXIValue *) queryArgs, L"", VALUE_FORMAT_URL_QUERY_ARGS); if (strResult) { // URL query args encoding ensures we only have ASCII here result += VXIStringCStr(strResult); VXIStringDestroy(&strResult); } } return result; } /* * Utilities */ void SBinetURL::appendKeyToMultipart(SBinetNString& result, const char *key ) { // Print the boundary start if (result.length() != 0) result += CRLF; result += "--" SB_BOUNDARY CRLF; result += "Content-Disposition: form-data; name=\""; result += key; result += "\"" CRLF; } void SBinetURL::appendValueToMultipart(SBinetNString& result, const SBinetNString& value) { // char tempbuf[20]; // if (value.length() > 0) // { // result += "Content-Type: text/plain" CRLF; // result += "Content-Length: "; // sprintf(tempbuf, "%d", value.length()); // result += tempbuf; // result += CRLF; // // blank line. // result += CRLF; // result += value; // } result += CRLF; result += value; } void SBinetURL::appendQueryArgsVectorToMultipart(SBinetNString& result, const VXIVector *vxivector, SBinetNString& fieldName) { const VXIValue *value = NULL; VXIunsigned vectorLen = VXIVectorLength(vxivector); int prevLen = fieldName.length(); for(VXIunsigned i = 0 ; i < vectorLen ; i++) { value = VXIVectorGetElement(vxivector, i); if (value != NULL) { appendArrayIndexToName(fieldName, i); appendQueryArgsToMultipart(result, value, fieldName); fieldName.resize(prevLen); } } } void SBinetURL::appendQueryArgsMapToMultipart(SBinetNString& result, const VXIMap *vximap, SBinetNString& fieldName) { const VXIchar *key = NULL; const VXIValue *value = NULL; int prevLen = fieldName.length(); VXIMapIterator *mapIterator = VXIMapGetFirstProperty(vximap, &key, &value ); do { if (key != NULL && value != NULL) { fieldName += '.'; fieldName += key; appendQueryArgsToMultipart(result, value, fieldName); fieldName.resize(prevLen); } } while (VXIMapGetNextProperty(mapIterator, &key, &value) == VXIvalue_RESULT_SUCCESS); VXIMapIteratorDestroy(&mapIterator); } SBinetNString SBinetURL::queryArgsToMultipart(const VXIMap* queryArgs) { SBinetNString result; if(!queryArgs) return(result); const VXIchar *key = NULL; const VXIValue *value = NULL; VXIMapIterator* mapIterator = VXIMapGetFirstProperty( queryArgs, &key, &value ); do { if (key != NULL && value != NULL) { SBinetNString fieldName = key; appendQueryArgsToMultipart(result, value, fieldName); } } while ( VXIMapGetNextProperty( mapIterator, &key, &value ) == VXIvalue_RESULT_SUCCESS ); // Print the boundary terminator result += CRLF "--" SB_BOUNDARY "--" CRLF; VXIMapIteratorDestroy(&mapIterator); return result; } void SBinetURL::appendQueryArgsToMultipart(SBinetNString& result, const VXIValue *value, SBinetNString& fieldName) { switch (VXIValueGetType(value)) { case VALUE_CONTENT: { // audio const VXIchar* type; const VXIbyte* data; VXIulong size; char sizeInt[10]; appendKeyToMultipart(result, fieldName.c_str()); VXIContentValue((const VXIContent *) value, &type, &data, &size); result += "Content-Type: "; result += type; result += CRLF; sprintf(sizeInt,"%lu",size); result += "Content-Length: "; result += sizeInt; result += CRLF; // One blank line before actual data. result += CRLF; result.append((const char*) data, size); } break; case VALUE_MAP: appendQueryArgsMapToMultipart(result, (const VXIMap *) value, fieldName); break; case VALUE_VECTOR: appendQueryArgsVectorToMultipart(result, (const VXIVector *)value, fieldName); break; default: appendKeyToMultipart(result, fieldName.c_str()); appendValueToMultipart(result, valueToNString(value)); break; } } // // Infer a MIME content type from a URL (by the extension) // VXIString *SBinetURL::getContentTypeFromUrl() const { // // Determine the extension. This has to work for local files and also HTTP // const VXIchar *url = _strPath.c_str(); if (url == NULL || !*url) { return NULL; } const VXIchar *urlEnd = url; // Search for the end of the URL. while (*urlEnd != L'?' && *urlEnd != L'#' && *urlEnd) urlEnd++; // Now look for the last '.' VXIchar ext[1024]; const VXIchar *urlDot = urlEnd - 1; while (urlDot >= url && *urlDot != L'.') urlDot--; if (urlDot >= url) { ::wcsncpy(ext, urlDot, urlEnd - urlDot); ext[urlEnd - urlDot] = L'\0'; if (*ext) { const VXIchar* typeFromMap = SBinetChannel::mapExtension(ext); if (typeFromMap != NULL) { if (*typeFromMap) return VXIStringCreate(typeFromMap); else return NULL; } // GN: Skip this step. The default type will be returned instead. // This is what happens on other OSes. The problem is that if // the file extension is .xml, FindMimeFromData() will return // a MIME type of text/xml and this is not one of the supported // types in SRGS. Allow the user of INET to determine the type // instead by returning the default type. #if 0 /* * Could not find in map, use Win32 if available */ #ifdef _WIN32 // Try Windows, this supports a number of hardcoded MIME content // types as well as extension mapping rules. To define a new // extension mapping rule, create a new Win32 registry key called // HKEY_CLASSES_ROOT\.<ext> where <ext> is the extension name. Then // create a value under that called "Content Type" where the data is // the content type string, such as "audio/aiff". Browse that // location in the registry for numerous examples (not all have a // content type mapping though). // // TBD sniff the actual data buffer too as this permits, pass the // proposed MIME type too (as returned by the web server, if any). VXIchar *mimeBuf; if (FindMimeFromData (NULL, url, NULL, 0, NULL, 0, &mimeBuf, 0) != NOERROR) mimeBuf = NULL; /* FindMimeFromData( ) leaks, we add unknown extensions here to make it so we only leak once per extension instead of repeatedly */ if (mimeBuf && *mimeBuf) { SBinetChannel::addExtensionRule(ext, mimeBuf); return VXIStringCreate(mimeBuf); } else { SBinetChannel::addExtensionRule(ext, L""); } #endif #endif } } /* * Couldn't figure out MIME type: return default type. */ return NULL; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -