📄 sbineturl.cpp
字号:
#else /* not WIN32 */
struct URLInfo
{
SBinetString protocol;
SBinetString fragment;
SBinetString query;
SBinetString path;
SBinetString host;
int port;
};
static VXIinetResult parseURL(const VXIchar* const url, URLInfo& urlInfo)
{
// Initialize the URLInfo structure.
urlInfo.port = -1;
// Check to see if the URL is invalid.
if (!url || (url[0] == 0))
return VXIinet_RESULT_NON_FATAL_ERROR;
VXIchar* tmpUrl = new VXIchar [wcslen(url) + 1];
wcscpy(tmpUrl, url);
const VXIchar* tmpUrlOriginal = tmpUrl;
// Check for the protocol part.
bool needToCanonicalize = false;
VXIchar* protocolEndPtr = wcschr(tmpUrl, L':');
if (protocolEndPtr && (!wcsncmp(tmpUrl, L"file", 4) || !wcsncmp(tmpUrl, L"http", 4)))
{
// Found the protocol. Copy it to the URLInfo structure.
int protLen = protocolEndPtr - tmpUrl;
urlInfo.protocol.append(tmpUrl, protLen);
// Advance past the protocol part of the URL.
if (0 == wcsncmp(protocolEndPtr + 1, L"//", 2))
{
tmpUrl = protocolEndPtr + 3;
}
else
{
tmpUrl = protocolEndPtr + 1;
needToCanonicalize = 1;
}
}
else
{
// The default protocol is the file protocol.
urlInfo.protocol = L"file";
}
if (!wcscmp(urlInfo.protocol.c_str(), L"file"))
{
// If the URL uses the file protocol, the rest of the URL is the path.
// The path needs to be canonicalized. It could still be an absolute
// path if it starts with a '/'. If it does not, create the absolute
// path by prepending the current path with the current directory.
if (needToCanonicalize && tmpUrl[0] != '/')
{
char buf[1024];
urlInfo.path = getcwd(buf, 1024);
urlInfo.path += '/';
}
VXIchar* endPtr = wcschr(tmpUrl, L'?');
VXIchar* fragmentPtr = wcschr(tmpUrl, L'#');
if (endPtr)
{
if (fragmentPtr && (fragmentPtr < endPtr))
endPtr = fragmentPtr;
}
else if (fragmentPtr)
{
endPtr = fragmentPtr;
}
// Strip the query and/or fragment part of the file URI if
// there is any.
if (endPtr)
*endPtr = L'\0';
urlInfo.path += tmpUrl;
}
else
{
// Check for the fragment part.
VXIchar* fragmentPtr = wcsrchr(tmpUrl, L'#');
if (fragmentPtr)
{
// Found the fragment. Copy it to the URLInfo structure.
*fragmentPtr = L'\0';
urlInfo.fragment = ++fragmentPtr;
}
// Check for the query part.
VXIchar* queryPtr = wcsrchr(tmpUrl, L'?');
if (queryPtr)
{
// Found the query. Copy it to the URLInfo structure.
*queryPtr = L'\0';
urlInfo.query = ++queryPtr;
}
// Check for the path part.
VXIchar* pathPtr = wcschr(tmpUrl, L'/');
if (pathPtr)
{
// Found the path. Copy it to the URLInfo structure.
// First, we need to UTF-8 encode it and then escape it.
SBinetNString utfPath, escapedPath;
SBinetHttpUtils::utf8encode(pathPtr, utfPath);
SBinetHttpUtils::escapeString(utfPath.c_str(),
SBinetHttpUtils::URL_PATH,
escapedPath);
urlInfo.path = escapedPath;
// Append the query to the path.
if (queryPtr)
{
// Add the query to the path.
urlInfo.path += L'?';
urlInfo.path += urlInfo.query;
}
*pathPtr = L'\0';
}
else
{
// No path was specified so set the path to root ("/").
urlInfo.path = "/";
}
// Check for the username:password part.
VXIchar* userpassEndPtr = wcschr(tmpUrl, L'@');
if (userpassEndPtr)
{
// For now, just ignore username and password.
tmpUrl = userpassEndPtr + 1;
}
// Check for the port part.
VXIchar* portPtr = wcsrchr(tmpUrl, L':');
if (portPtr)
{
*portPtr = L'\0';
++portPtr;
// Check if the port is valid (all digits).
VXIchar* end = NULL;
long port = wcstol(portPtr, &end, 10);
if ((end) && (*end == L'\0'))
urlInfo.port = (int) port;
}
// The rest is the host part.
urlInfo.host = tmpUrl;
if (urlInfo.host[0] == 0)
{
delete [] tmpUrlOriginal;
return VXIinet_RESULT_NON_FATAL_ERROR;
}
}
delete [] tmpUrlOriginal;
return VXIinet_RESULT_SUCCESS;
}
typedef std::basic_string<VXIchar> vxistring;
static VXIinetResult combineURL(const VXIchar* const baseUrl,
const VXIchar* const relativeUrl,
SBinetString& absoluteUrl)
{
// Check to see if the relative URL is referencing another host
// (i.e. the protocol is specified).
const VXIchar* protocolEndPtr = wcschr(relativeUrl, L':');
if (!baseUrl || (protocolEndPtr && (!wcsncmp(relativeUrl, L"file", 4) || !wcsncmp(relativeUrl, L"http", 4))))
{
// HACK to allow OSR to load absolute local URLs
if (wcsstr(relativeUrl, L"/file://"))
absoluteUrl = relativeUrl + 1;
else
absoluteUrl = relativeUrl;
}
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -