📄 sbineturl.cpp
字号:
/****************License************************************************
*
* Copyright 2000-2003. ScanSoft, Inc.
*
* Use of this software is subject to notices and obligations set forth
* in the SpeechWorks Public License - Software Version 1.2 which is
* included with this software.
*
* ScanSoft is a registered trademark of ScanSoft, Inc., and OpenSpeech,
* SpeechWorks and the SpeechWorks logo are registered trademarks or
* trademarks of SpeechWorks International, Inc. in the United States
* and other countries.
*
***********************************************************************/
#include <vxibuildopts.h>
#if P_VXI
#ifndef _SB_USE_STD_NAMESPACE
#define _SB_USE_STD_NAMESPACE
#endif
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#ifdef _WIN32
#undef HTTP_VERSION
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <wininet.h>
#include <urlmon.h>
#else
#include <unistd.h> // for getcwd()
#endif /* WIN32 */
#include <stdio.h>
#include <string.h>
#include "vxi/VXIvalue.h"
#include "vxi/VXIinet.h"
#include "vxi/VXItrd.h"
#include "SBinetURL.h"
#include "SBinetChannel.h"
#include "HttpUtils.hpp"
#include "SBinetString.hpp"
#define INET_MAX_PATH 1024
// #if defined(_decunix_) || defined(_solaris_)
// static int my_wcscasecmp(const wchar_t *s1, const wchar_t *s2)
// {
// register unsigned int u1, u2;
// for (;;) {
// u1 = (unsigned int) *s1++;
// u2 = (unsigned int) *s2++;
// if (HttpUtils::toUpper(u1) != HttpUtils::toUpper(u2)) {
// return HttpUtils::toUpper(u1) - HttpUtils::toUpper(u2);
// }
// if (u1 == '\0') {
// return 0;
// }
// }
// }
// #else
// #define my_wcscasecmp ::wcscasecmp
// #endif
#if defined(_MSC_VER)
#pragma warning(disable:4061)
#endif
static void
appendArrayIndexToName(SBinetNString& fieldName,
VXIunsigned index)
{
char tempBuf[8];
sprintf(tempBuf, ".%d", index);
fieldName += tempBuf;
}
VXIinetResult SBinetURL::create(const VXIchar *pszName,
const VXIchar *pszUrlBase,
SBinetURL *& url)
{
url = new SBinetURL();
if (url == NULL)
{
return VXIinet_RESULT_OUT_OF_MEMORY;
}
VXIinetResult rc = url->parse(pszName, pszUrlBase);
if (rc != VXIinet_RESULT_SUCCESS)
{
delete url;
url = NULL;
}
return rc;
}
SBinetURL& SBinetURL::operator=(const SBinetURL& rhs)
{
if (this != &rhs)
{
_absoluteURL = rhs._absoluteURL;
_baseURL = rhs._baseURL;
_host = rhs._host;
_strPath = rhs._strPath;
_protocol = rhs._protocol;
_port = rhs._port;
N_absoluteURL = rhs.N_absoluteURL;
N_baseURL = rhs.N_baseURL;
N_host = rhs.N_host;
N_strPath = rhs.N_strPath;
}
return *this;
}
bool SBinetURL::operator==(const SBinetURL& rhs)
{
if (this == &rhs)
return true;
if (_protocol != rhs._protocol)
return false;
if (::wcscmp(_strPath.c_str(), rhs._strPath.c_str()) != 0)
return false;
if (_protocol >= HTTP_PROTOCOL)
{
if ( _port != rhs._port)
return false;
if (SBinetHttpUtils::casecmp(_host.c_str(), rhs._host.c_str()) != 0)
return false;
}
return true;
}
#ifdef _WIN32
VXIinetResult SBinetURL::parse(const VXIchar* pszUrl, const VXIchar* pszUrlBase)
{
VXIinetResult eResult( VXIinet_RESULT_SUCCESS );
if( !pszUrl || !*pszUrl)
{
//Error(200, L"%s%s", L"Operation", L"parse URL");
return VXIinet_RESULT_INVALID_ARGUMENT;
}
if (pszUrlBase != NULL)
_baseURL = pszUrlBase;
else
_baseURL = L"";
// If the caller is using "file:", just strip it because apparently
// Internet*() doesn't do the right thing with file URI's
bool relativeFileUri = false;
if (!wcsncmp(L"file:", pszUrl, 5)) { // file:...
pszUrl += 5;
if (!wcsncmp(L"//", pszUrl, 2)) // file://...
pszUrl += 2;
relativeFileUri = true;
}
wchar_t *tmpUrl = NULL;
const wchar_t *absoluteUrl = pszUrl;
// The parsing of URL is complicated by the fact that we want unsafe
// characters to be encoded using %-notation for HTTP URLs, but we want
// %-notatation to be converted into unsaface characters for file URLs. So,
// on entry we convert the URL into unsafe notation, then for HTTP URLs, we
// re-encode it back using %-notation.
// Combine the base and (possibly relative) URL. Since we stripped the
// transport type above, don't combine them if the transport type of the
// base URI differs.
if( pszUrlBase && pszUrlBase[0] && !(relativeFileUri && (0 == wcsncmp(L"http:", pszUrlBase, 5))))
{
VXIulong len = (::wcslen(pszUrlBase) + ::wcslen(pszUrl)) * 3;
tmpUrl = new VXIchar [len];
if( !tmpUrl )
{
//Error(103, NULL);
return VXIinet_RESULT_OUT_OF_MEMORY;
}
if (InternetCombineUrl(pszUrlBase, pszUrl, tmpUrl, &len, ICU_BROWSER_MODE | ICU_DECODE| ICU_NO_ENCODE) == TRUE)
{
absoluteUrl = tmpUrl;
}
else
{
delete [] tmpUrl;
return VXIinet_RESULT_NON_FATAL_ERROR;
}
}
else
{
VXIulong len = ::wcslen (pszUrl) * 3;
tmpUrl = new VXIchar [len];
if( !tmpUrl )
{
//Error(103, NULL);
return VXIinet_RESULT_OUT_OF_MEMORY;
}
if (InternetCanonicalizeUrl(pszUrl, tmpUrl, &len, ICU_BROWSER_MODE | ICU_DECODE | ICU_NO_ENCODE) == TRUE)
{
absoluteUrl = tmpUrl;
}
else
{
delete [] tmpUrl;
return VXIinet_RESULT_NON_FATAL_ERROR;
}
}
// Now parse the absolute URL to decide if it is file or network access
int pathLen = 0;
int queryLen = 0;
const wchar_t* queryPtr = ::wcschr(absoluteUrl, L'?');
if (queryPtr)
{
pathLen = queryPtr - absoluteUrl + 1;
queryLen = ::wcslen(queryPtr) + 1;
}
else
{
pathLen = ::wcslen(absoluteUrl) + 1;
queryLen = 0;
}
if (pathLen < INET_MAX_PATH)
pathLen = INET_MAX_PATH;
wchar_t protocol[INET_MAX_PATH];
wchar_t* host = new wchar_t [pathLen];
wchar_t* urlPath = new wchar_t [pathLen];
wchar_t* query = NULL;
if (queryLen > 0)
query = new wchar_t [queryLen];
URL_COMPONENTS components;
memset (&components, 0, sizeof (URL_COMPONENTS));
components.dwStructSize = sizeof (URL_COMPONENTS);
components.lpszScheme = protocol;
components.dwSchemeLength = INET_MAX_PATH;
components.lpszHostName = host;
components.dwHostNameLength = pathLen;
components.lpszUrlPath = urlPath;
components.dwUrlPathLength = pathLen;
components.lpszExtraInfo = query;
components.dwExtraInfoLength = queryLen;
if(InternetCrackUrl(absoluteUrl, ::wcslen (absoluteUrl), 0, &components) == TRUE)
{
switch (components.nScheme)
{
case INTERNET_SCHEME_FILE:
// File access, return the local file path
_protocol = FILE_PROTOCOL;
_strPath = urlPath;
_absoluteURL = absoluteUrl;
break;
case INTERNET_SCHEME_HTTPS:
case INTERNET_SCHEME_HTTP:
{
// HTTP access, return the absolute URL
_protocol = (components.nScheme == INTERNET_SCHEME_HTTP ?
HTTP_PROTOCOL : HTTPS_PROTOCOL);
_absoluteURL = absoluteUrl;
// remove trailing / in absolute URL to ensure that www.spechworks.com
// and www.speechwork.com/ are seen as the same URL.
int idx = _absoluteURL.length() - 1;
if (_absoluteURL[idx] == L'/')
{
_absoluteURL.resize(idx);
}
_host = host;
// Retrieve the host name, the port number and the local file.
_port = components.nPort;
if (components.dwUrlPathLength == 0)
{
_strPath = L"/";
}
else
{
_strPath = urlPath;
SBinetNString utf8path, escapedPath;
SBinetHttpUtils::utf8encode(urlPath, utf8path);
SBinetHttpUtils::escapeString(utf8path.c_str(),
SBinetHttpUtils::URL_PATH,
escapedPath);
_strPath = escapedPath;
}
if (components.dwExtraInfoLength > 0)
_strPath += query;
break;
}
default:
delete [] tmpUrl;
delete [] host;
delete [] urlPath;
delete [] query;
return VXIinet_RESULT_INVALID_ARGUMENT;
}
}
else
{
// Couldn't be parsed.
// If the absoluteUrl contains a colon, it is because the parsing of the
// URL failed. If the URL contained a colon and were valid, it would have
// been parsed sucessfully by InternetCrackURL. If it doesn't contain a
// colon, we assume it is a path relative to the current directory.
//
if (::wcschr(absoluteUrl, L':') != NULL)
{
delete [] tmpUrl;
delete [] host;
delete [] urlPath;
delete [] query;
return VXIinet_RESULT_INVALID_ARGUMENT;
}
wchar_t *ignored;
*urlPath = L'\0';
_protocol = FILE_PROTOCOL;
if ((GetFullPathName(absoluteUrl, pathLen, urlPath, &ignored) > 0) &&
*urlPath)
{
_strPath = urlPath;
_absoluteURL = absoluteUrl;
}
else
{
//Error(225, L"%s%s", L"URL", pszUrl);
eResult = VXIinet_RESULT_INVALID_ARGUMENT;
}
}
N_absoluteURL = _absoluteURL;
N_baseURL = _baseURL;
N_host = _host;
N_strPath = _strPath;
delete [] tmpUrl;
delete [] host;
delete [] urlPath;
delete [] query;
return eResult;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -