hxurl.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:36k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: hxurl.cpp,v 1.25.2.4 2004/07/09 01:48:15 hubbe Exp $
- *
- * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file,
- * are subject to the current version of the RealNetworks Public
- * Source License (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (the "RCSL") available at
- * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
- * will apply. You may also obtain the license terms directly from
- * RealNetworks. You may not use this file except in compliance with
- * the RPSL or, if you have a valid RCSL with RealNetworks applicable
- * to this file, the RCSL. Please see the applicable RPSL or RCSL for
- * the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the
- * portions it created.
- *
- * This file, and the files included with this file, is distributed
- * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
- * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
- * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
- * ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- #include "hlxclib/string.h"
- #include "hlxclib/stdlib.h"
- //#include "hlxclib/stdio.h"
- #include <ctype.h>
- #include "hxcom.h"
- #include "hxtypes.h"
- #include "hxresult.h"
- #include "hxcomm.h"
- #include "tparse.h"
- #include "dbcs.h"
- #include "protdefs.h"
- #include "hxstrutl.h"
- #include "hxslist.h"
- #include "hxurl.h"
- #include "ihxpckts.h"
- #include "chxminiccf.h"
- #include "hxheap.h"
- #ifdef _DEBUG
- #undef HX_THIS_FILE
- static const char HX_THIS_FILE[] = __FILE__;
- #endif
- /* We should really define it in a common header file */
- #if defined (_WINDOWS ) || defined (WIN32) || defined(_SYMBIAN)
- #define OS_SEPARATOR_CHAR '\'
- #define OS_SEPARATOR_STRING "\"
- #elif defined (_UNIX) || defined(_OPENWAVE)
- #define OS_SEPARATOR_CHAR '/'
- #define OS_SEPARATOR_STRING "/"
- #elif defined (_MACINTOSH)
- #define OS_SEPARATOR_CHAR ':'
- #define OS_SEPARATOR_STRING ":"
- #else
- #error "undefined platform hxurl.cpp"
- #endif // defined (_WINDOWS ) || defined (WIN32)
- CHXURL::CHXURL (const char* pszURL)
- :m_LastError (HXR_OK)
- ,m_pActualURL(NULL)
- ,m_pszURL(NULL)
- ,m_pszEscapedURL(NULL)
- ,m_pszOptions (NULL)
- ,m_pszHost (NULL)
- ,m_pszPort (NULL)
- ,m_pszUsername(NULL)
- ,m_pszPassword(NULL)
- ,m_unProtocol(fileProtocol)
- ,m_unDefaultPort(0)
- ,m_bNetworkProtocol (FALSE)
- ,m_pszResource (NULL)
- ,m_pProperties (NULL)
- ,m_pOptions (NULL)
- ,m_pCCF(CreateCCF())
- {
- if (m_pCCF)
- {
- m_pCCF->AddRef();
- }
-
- ConstructURL(pszURL);
- }
- CHXURL::CHXURL (const char* pszURL, IUnknown* pContext)
- :m_LastError (HXR_OK)
- ,m_pActualURL(NULL)
- ,m_pszURL(NULL)
- ,m_pszEscapedURL(NULL)
- ,m_pszOptions (NULL)
- ,m_pszHost (NULL)
- ,m_pszPort (NULL)
- ,m_pszUsername(NULL)
- ,m_pszPassword(NULL)
- ,m_unProtocol(fileProtocol)
- ,m_unDefaultPort(0)
- ,m_bNetworkProtocol (FALSE)
- ,m_pszResource (NULL)
- ,m_pProperties (NULL)
- ,m_pOptions (NULL)
- ,m_pCCF(0)
- {
- if (pContext)
- {
- pContext->QueryInterface(IID_IHXCommonClassFactory, (void**)&m_pCCF);
- }
-
- ConstructURL(pszURL);
- }
- void CHXURL::ConstructURL(const char* pszURL)
- {
- char* pszInputURL = NULL;
- char* pszTemp = NULL;
- char* pFragment = NULL;
- char* pNewURL = NULL;
- char* pResource = NULL;
- char* pszDollarSign = NULL;
- HX_ASSERT(pszURL != NULL);
- if (!pszURL)
- {
- m_LastError = HXR_INVALID_PATH;
- return;
- }
-
- if (!m_pCCF)
- {
- m_LastError = HXR_UNEXPECTED;
- return;
- }
- pszInputURL = new char[strlen(pszURL) + 1];
- if(!pszInputURL)
- {
- m_LastError = HXR_OUTOFMEMORY;
- return;
- }
- strcpy(pszInputURL, pszURL); /* Flawfinder: ignore */
- // Keep permanent copy of input url
- m_pszEscapedURL = new char[strlen(pszInputURL)+1];
- strcpy(m_pszEscapedURL, pszInputURL); /* Flawfinder: ignore */
- // IHXValues
- if (m_pCCF)
- {
- m_pCCF->CreateInstance(CLSID_IHXValues, (void**)&m_pProperties);
- m_pCCF->CreateInstance(CLSID_IHXValues, (void**)&m_pOptions);
- }
- // protocol: determine whether it's network or local
- if (0 == StringNCompare(pszInputURL, "http:", 5))
- {
- m_unProtocol = httpProtocol;
- m_unDefaultPort = DEFAULT_HTTP_PORT;
- }
- else if (0 == StringNCompare(pszInputURL, "chttp:", 6))
- {
- m_unProtocol = httpProtocol;
- m_unDefaultPort = DEFAULT_HTTP_PORT;
- }
- else if (0 == StringNCompare(pszInputURL, "pnm:", 4))
- {
- m_unProtocol = pnmProtocol;
- m_bNetworkProtocol = TRUE;
- m_unDefaultPort = DEFAULT_PNA_PORT;
- }
- else if (0 == StringNCompare(pszInputURL, "rtsp:", 5))
- {
- m_unProtocol = rtspProtocol;
- m_bNetworkProtocol = TRUE;
- m_unDefaultPort = DEFAULT_RTSP_PORT;
- }
- else if (0 == StringNCompare(pszInputURL, "helix-sdp:", 10))
- {
- m_unProtocol = helixSDPProtocol;
- m_bNetworkProtocol = TRUE;
- m_unDefaultPort = DEFAULT_RTSP_PORT;
- }
- else if (0 == StringNCompare(pszInputURL, "https:", 6))
- {
- m_unProtocol = httpsProtocol;
- m_unDefaultPort = DEFAULT_HTTPS_PORT;
- }
- if (m_pProperties)
- {
- m_pProperties->SetPropertyULONG32(PROPERTY_PROTOCOL, (ULONG32)m_unProtocol);
- }
- else
- {
- m_LastError = HXR_UNEXPECTED;
- goto cleanup;
- }
- // no need to further parse helix-sdp protocol
- if (helixSDPProtocol != m_unProtocol)
- {
- // separate fragment from the URL
- if (0!=(pszTemp = (char*) ::HXFindChar(pszInputURL, '#')))
- {
- // save fragment
- pFragment = pszTemp + 1;
- ::SaveStringToHeader(m_pProperties, PROPERTY_FRAGMENT, pFragment);
- *pszTemp = ' ';
- }
- // HP - allow '$' in directory/file name
- //
- // still need to take care of that obsolete $ sign option:
- // rtsp://moe.cr.prognet.com/ambush.rm$1:00
- // time after the $ is assumed to be the start time.
- //
- // the solution is to compare the string following the $ to
- // a properly formed time. If the string is a time and only
- // a time, then we know its the old-style start-time option
- // otherwise, '$' is part of the directory/file name and we
- // will keep it.
- pszDollarSign = (char*) ::HXFindChar(pszInputURL, '$');
- while (pszDollarSign)
- {
- pszTemp = pszDollarSign + 1;
- if (::TimeParse(pszTemp))
- {
- *pszDollarSign = ' ';
- INT32 lLen = (2 * strlen(pszURL)) + 8;
- pNewURL = new char[lLen];
- memset(pNewURL, 0, lLen);
-
- // upgrade to a new URL
- SafeSprintf(pNewURL, lLen, "%s?start=%s", pszInputURL, pszTemp);
- HX_VECTOR_DELETE(pszInputURL);
- pszInputURL = pNewURL;
- break;
- }
- pszDollarSign = (char*) ::HXFindChar(pszTemp, '$');
- }
- }
- #if !defined(_MACINTOSH) && !defined(_MAC_UNIX)
- // on Mac, unescaping can put /'s and ?'s back into file and folder names, which is deadly inside URLs
- //if (0 == StringNCompare(pszInputURL, "file:", 5))
- {
- // we only unescape the URL on local source since we are
- // *responding* instead of *requesting* for the given source
- Unescape(pszInputURL);
- }
- #endif
- if (!CompressURL(pszInputURL, m_pszURL))
- {
- // make a copy of the URL
- m_pszURL = new char[strlen(pszInputURL)+1];
- strcpy(m_pszURL, pszInputURL); /* Flawfinder: ignore */
- }
- m_pActualURL = new char[strlen(m_pszURL)+1];
- strcpy(m_pActualURL, m_pszURL); /* Flawfinder: ignore */
- ::SaveStringToHeader(m_pProperties, PROPERTY_URL, m_pszURL);
- // no need to further parse helix-sdp protocol
- if (helixSDPProtocol != m_unProtocol)
- {
- // separate options from the URL
- if (0 != (pszTemp = (char*) ::HXFindChar(m_pszURL, '?')))
- {
- // options
- m_pszOptions = pszTemp + 1;
- }
-
- // collect protocol, host, port and resource info
- ParseURL (m_pszURL);
-
- // collect other options info if it has
- if (m_pszOptions)
- {
- if (HXR_INCOMPLETE == CollectOptions(m_pszOptions) && m_pszResource)
- {
- // bad options and remove it from the URL
- pszTemp = (char*) ::HXFindChar(m_pszResource, '?');
- if (pszTemp)
- {
- *pszTemp = ' ';
- ParseResource();
- }
- }
- }
- }
- cleanup:
- HX_VECTOR_DELETE(pszInputURL);
- }
- CHXURL::~CHXURL ()
- {
- HX_VECTOR_DELETE(m_pActualURL);
- HX_VECTOR_DELETE(m_pszURL);
- HX_VECTOR_DELETE(m_pszEscapedURL);
- HX_RELEASE(m_pProperties);
- HX_RELEASE(m_pOptions);
- HX_RELEASE(m_pCCF);
- }
- CHXURL::CHXURL(const CHXURL& rhs)
- :m_LastError (HXR_OK)
- ,m_pActualURL(NULL)
- ,m_pszURL(NULL)
- ,m_pszOptions (NULL)
- ,m_pszHost (NULL)
- ,m_pszPort (NULL)
- ,m_pszUsername(NULL)
- ,m_pszPassword(NULL)
- ,m_unProtocol (fileProtocol)
- ,m_bNetworkProtocol (FALSE)
- ,m_pszResource (NULL)
- ,m_pProperties (NULL)
- ,m_pOptions (NULL)
- ,m_pCCF(rhs.m_pCCF)
- {
- if (m_pCCF)
- {
- m_pCCF->AddRef();
- }
- ConstructURL(rhs.GetEscapedURL());
- }
- CHXURL& CHXURL::operator=(const CHXURL& rhs)
- {
- if (&rhs != this)
- {
- // Clean out old data
- HX_VECTOR_DELETE(m_pActualURL);
- HX_VECTOR_DELETE(m_pszURL);
- HX_VECTOR_DELETE(m_pszEscapedURL);
- HX_RELEASE(m_pProperties);
- HX_RELEASE(m_pOptions);
- HX_RELEASE(m_pCCF);
- m_LastError = HXR_OK;
- m_pszOptions = NULL;
- m_pszHost = NULL;
- m_pszPort = NULL;
- m_pszUsername = NULL;
- m_pszPassword = NULL;
- m_unProtocol = fileProtocol;
- m_bNetworkProtocol = FALSE;
- m_pszResource = NULL;
- ConstructURL(rhs.GetEscapedURL());
- m_pCCF = rhs.m_pCCF;
- if (m_pCCF)
- {
- m_pCCF->AddRef();
- }
- }
- return *this;
- }
- HX_RESULT CHXURL::ParseURL (char* pszURL)
- {
- char* pszOption = NULL;
- char* pszTemp = NULL;
- char* pszSlash = NULL;
- char* pszCursor = NULL;
- if (HXR_OK != m_LastError)
- {
- goto cleanup;
- }
- pszCursor = pszURL;
-
- //
- // let's start
- //
- // find the scheme - note that ParseURL only succeeds
- // for absolute URLs
- m_LastError = HXR_INVALID_PROTOCOL; // assume the worst
- pszTemp = (char *) FindURLSchemeEnd(pszURL);
- if (pszTemp)
- {
- char* pScheme = new_string(pszURL, pszTemp - pszURL);
- m_LastError = HXR_OK;
- ::SaveStringToHeader(m_pProperties, PROPERTY_SCHEME, pScheme);
- delete[] pScheme;
- }
- if(HXR_OK != m_LastError)
- {
- goto cleanup;
- }
- pszCursor = pszTemp + 1;
-
- if(strncmp(pszCursor, "//", 2) == 0)
- {
- pszCursor += 2; // skip '//'
- }
- else if(strncmp(pszCursor, "/", 1) == 0)
- {
- pszCursor += 1; // skip '/' (ill-formed url?)
- }
- if (fileProtocol == m_unProtocol)
- {
- // resource
- if (*(m_pszResource = pszCursor) == ' ')
- {
- m_LastError = HXR_INVALID_URL_PATH;
- goto cleanup;
- }
- }
- // network URL + http
- else
- {
- // First check for optional username and password parameters.
- // The colon is also optional if either username or password
- // is not given Form in context:
- // protocol://username:password@host:port/resource (From RFC
- // 1738)
- pszTemp = (char*) ::HXFindChar(pszCursor, ':');
- pszSlash = (char*) ::HXFindChar(pszCursor, '/');
- pszOption = (char*) ::HXFindChar(pszCursor, '@');
- // There is a username or password if we see a '@' character
- // according to RFC 1738 this is a reserved character
- if (pszOption && pszOption < pszSlash)
- {
- // Username
- if (*(m_pszUsername = pszCursor) == ' ')
- {
- m_LastError = HXR_INVALID_URL_HOST;
- goto cleanup;
- }
- // If the is a ':' and it is before the '@' then we have a
- // password, so zero terminate the username and move the
- // cursor to the password
- if (pszTemp && (pszTemp < pszOption))
- {
- *pszTemp = ' ';
- pszCursor = pszTemp+1;
- }
- // There is no ':' so move the cursor to the '@' character
- // so it will be a zero terminated empty string
- else
- pszCursor = pszOption;
- // Password
- if (*(m_pszPassword = pszCursor) == ' ')
- {
- m_LastError = HXR_INVALID_URL_HOST;
- goto cleanup;
- }
- // Zero terminate password and move the cursor to the hostname
- *pszOption = ' ';
- if (m_pszUsername)
- {
- ::SaveStringToHeader(m_pProperties, PROPERTY_USERNAME, m_pszUsername);
- }
- if (m_pszPassword)
- {
- ::SaveStringToHeader(m_pProperties, PROPERTY_PASSWORD, m_pszPassword);
- }
- pszCursor = pszOption+1;
- }
- // host
- if (*(m_pszHost = pszCursor) == ' ')
- {
- m_LastError = HXR_INVALID_URL_HOST;
- goto cleanup;
- }
- // port
- pszTemp = (char*) ::HXFindChar(pszCursor, '/');
- if (pszTemp)
- {
- *pszTemp = ' ';
- pszCursor = pszTemp+1;
- }
- else
- {
- // it's legal to have RTSP or HTTP URLs with no resource.
- // The correct behavior for RTSP would be not to flag this as
- // an error but the client core treats the lack of a resource
- // as a failure. The correct change would be to have the client
- // core check explicitly for a resource but legacy code rears its
- // ugly head... so we flag the error (client core is happy) but
- // go ahead and parse the rest of the headers (so you can still
- // get the host:port if you need to). */
- if (m_unProtocol != httpProtocol && m_unProtocol != rtspProtocol)
- {
- m_LastError = HXR_INVALID_URL_PATH;
- }
- pszCursor = NULL;
- }
- // port
- pszTemp = (char*) ::HXFindChar(m_pszHost, ':');
- if (pszTemp)
- {
- *pszTemp = ' ';
-
- if (*(m_pszPort = pszTemp+1) == ' ')
- {
- m_LastError = HXR_INVALID_URL_HOST;
- goto cleanup;
- }
- }
- if (m_pszHost)
- {
- ::SaveStringToHeader(m_pProperties, PROPERTY_HOST, m_pszHost);
- }
- if (m_pszPort)
- {
- m_pProperties->SetPropertyULONG32(PROPERTY_PORT, (ULONG32)atol(m_pszPort));
- }
- else if (m_unDefaultPort > 0)
- {
- m_pProperties->SetPropertyULONG32(PROPERTY_PORT, (ULONG32)m_unDefaultPort);
- }
- if (pszCursor && (*(m_pszResource = pszCursor) == ' ' && m_unProtocol != httpProtocol && m_unProtocol != rtspProtocol))
- {
- m_LastError = HXR_INVALID_URL_PATH;
- goto cleanup;
- }
- }
- //
- // other options?
- //
- /*
- // 1.0 player
- if (pszTemp = (char*) ::HXFindChar(pszCursor, '$'))
- {
- *pszTemp = ' ';
- pszCursor = pszTemp+1;
- if (*(m_pszStartTime = pszCursor) == ' ')
- {
- m_LastError = HXR_FAILED;
- goto cleanup;
- }
- }
- */
- cleanup:
- ParseResource();
- return m_LastError;
- }
- void
- CHXURL::TrimOffSpaces(char*& pszString)
- {
- if( NULL == pszString )
- return;
-
- char* pszValue = pszString;
- char* pszCursor = pszString;
-
- // trim off the leading spaces
- while (*pszCursor == ' ')
- {
- pszCursor++;
- }
- pszValue = pszCursor;
- // trim off the tailing spaces
- if( strlen(pszCursor) != 0 )
- {
- pszCursor = pszCursor + strlen(pszCursor) - 1;
-
- while (*pszCursor == ' ' )
- {
- pszCursor--;
- }
- ++pszCursor;
- if( *pszCursor != ' ' )
- *pszCursor = ' ';
- }
-
- pszString = pszValue;
- }
-
- HX_RESULT
- CHXURL::CollectOptions (char* pszOptions)
- {
- HX_RESULT hr = HXR_OK;
- char* pszCursor = NULL;
- char* pszKey = NULL;
- char* pszValue = NULL;
- char* pszTemp = NULL;
- BOOL bValueQuoted = FALSE;
-
- if (HXR_OK != m_LastError)
- {
- return m_LastError;
- }
- pszCursor = pszOptions;
- char* pszEndOptions = pszOptions + strlen(pszOptions);
- // let's start parsing
- while (pszCursor < pszEndOptions)
- {
- //
- // collect one value pair at a time
- //
- // <key>="<value>" or <key>=<value>
- pszKey = pszCursor;
- if (!(pszTemp = (char*) ::HXFindChar(pszCursor, '=')))
- {
- hr = HXR_FAILED;
- goto cleanup;
- }
- *pszTemp = ' ';
- pszCursor = pszTemp + 1;
- // remove all the spaces between '=' and actual value
- while (*pszCursor == ' ')
- {
- pszCursor++;
- }
- // "<value>"
- if (*pszCursor == '"')
- {
- bValueQuoted = TRUE;
- pszCursor += 1;
- }
- pszValue = pszCursor;
- if (bValueQuoted)
- {
- if (!(pszTemp = (char*) ::HXFindChar(pszCursor, '"')))
- {
- hr = HXR_INCOMPLETE;
- goto cleanup;
- }
- *pszTemp = ' ';
- pszCursor = pszTemp + 1;
- }
- if ((pszTemp = (char*) ::HXFindChar(pszCursor, '&')) != 0)
- {
- *pszTemp = ' ';
-
- // move cursor to the next pair
- pszCursor = pszTemp + 1;
- }
- else
- {
- // move cursor to the end of this URL
- pszCursor += strlen(pszValue);
- }
- // trim off leading/tailing spaces
- TrimOffSpaces(pszKey);
- TrimOffSpaces(pszValue);
- // decode each value (option) since it may be URL-encoded.
- CHXString strUnescapedOptionValue;
- CHXURL::decodeURL(pszValue, strUnescapedOptionValue);
- pszValue = (char *)(const char *)strUnescapedOptionValue;
- // save to the header
- if (!strcasecmp("Start", pszKey)
- || !strcasecmp("End", pszKey)
- || !strcasecmp("Delay", pszKey)
- || !strcasecmp("Duration", pszKey))
- {
- m_pOptions->SetPropertyULONG32(pszKey, (ULONG32) ::TimeParse(pszValue) * 100);
- }
- else if (bValueQuoted || !IsNumber(pszValue))
- {
- IHXBuffer* pBuffer = NULL;
- if (m_pCCF)
- {
- m_pCCF->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer);
- }
- if (!pBuffer)
- {
- hr = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- pBuffer->Set((UCHAR*)pszValue, strlen(pszValue)+1);
- m_pOptions->SetPropertyBuffer(pszKey, (IHXBuffer*) pBuffer);
- pBuffer->Release();
- }
- else
- {
- m_pOptions->SetPropertyULONG32(pszKey, (ULONG32) atol(pszValue));
- }
-
- bValueQuoted = FALSE;
- pszKey = NULL;
- pszValue = NULL;
- }
-
- cleanup:
- return hr;
- }
- BOOL
- CHXURL::IsTimeValue (char* pszValue)
- {
- int i = 0;
- char* pszData = NULL;
- char* pszTemp = NULL;
- // time value format: hh:mm:ss
- if (isdigit(*pszValue) &&
- isdigit(*(pszValue+1)) &&
- *(pszValue+2) == ':' &&
- isdigit(*(pszValue+3)) &&
- isdigit(*(pszValue+4)) &&
- *(pszValue+5) == ':' &&
- isdigit(*(pszValue+6)) &&
- isdigit(*(pszValue+7)))
- {
- for (i = 0; i < 3; i++)
- {
- pszData = pszValue;
- if (i < 2)
- {
- pszTemp = (char*) ::HXFindChar(pszValue, ':');
- pszTemp = ' ';
- }
- switch (i)
- {
- case 0: // hh
- if (atoi(pszData) >= 24)
- {
- return FALSE;
- }
- break;
- case 1: // mm
- if (atoi(pszData) >= 60)
- {
- return FALSE;
- }
- break;
- case 2: // ss
- if (atoi(pszData) >= 60)
- {
- return FALSE;
- }
- break;
- default:
- break;
- }
- pszValue = pszTemp + 1;
- }
- return TRUE;
- }
- return FALSE;
- }
- BOOL
- CHXURL::IsNumber(char* pszValue)
- {
- char* pszCursor = pszValue;
- while (*pszCursor != ' ')
- {
- if (!isdigit(*pszCursor))
- {
- return FALSE;
- }
- pszCursor++;
- }
- return TRUE;
- }
- // case insensitive compare
- int
- CHXURL::StringNCompare (const char* pszStr1, const char* pszStr2, size_t nChars)
- {
- #ifdef _WINDOWS
- return strnicmp (pszStr1, pszStr2, nChars);
- #elif defined(_MACINTOSH)
- return strnicmp (pszStr1, pszStr2, nChars);
- #elif defined(_UNIX) || defined(_OPENWAVE)
- return strncasecmp (pszStr1, pszStr2, nChars);
- #elif defined(_SYMBIAN)
- return strnicmp(pszStr1, pszStr2, nChars);
- #elif
- # error "undefined platform....."
- #else
- return -1;
- #endif
- }
- void
- CHXURL::AddOption(char* pKey, char* pValue)
- {
- // trim off leading/tailing spaces
- TrimOffSpaces(pKey);
- TrimOffSpaces(pValue);
-
- // save to the header
- if (IsNumber(pValue))
- {
- m_pOptions->SetPropertyULONG32(pKey, (ULONG32) atol(pValue));
- }
- else
- {
- IHXBuffer* pBuffer = NULL;
- if (m_pCCF)
- {
- m_pCCF->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer);
- }
- if (pBuffer)
- {
- pBuffer->Set((UCHAR*)pValue, strlen(pValue)+1);
- m_pOptions->SetPropertyBuffer(pKey, (IHXBuffer*) pBuffer);
- pBuffer->Release();
- }
- }
- }
- void
- CHXURL::AddOption(char* pKey, UINT32 ulValue)
- {
- TrimOffSpaces(pKey);
- m_pOptions->SetPropertyULONG32(pKey, ulValue);
- }
- IHXValues*
- CHXURL::GetProperties(void)
- {
- if (m_pProperties)
- {
- m_pProperties->AddRef();
- }
- return m_pProperties;
- }
- IHXValues*
- CHXURL::GetOptions(void)
- {
- if (m_pOptions)
- {
- m_pOptions->AddRef();
- }
- return m_pOptions;
- }
- char*
- CHXURL::GetAltURL(BOOL& bDefault)
- {
- IHXBuffer* pValue = NULL;
- char* pAltURL = NULL;
- char* pURL = NULL;
- char* pCursor1 = NULL;
- char* pCursor2 = NULL;
- bDefault = FALSE;
- if (HXR_OK != m_LastError)
- {
- goto cleanup;
- }
- // retrieve Alt-URL if it exists in the option list
- if (HXR_OK == m_pOptions->GetPropertyBuffer("altURL", pValue) && pValue)
- {
- // allocate mem. for m_pszAltURL
- pAltURL = new char[pValue->GetSize()];
- SafeStrCpy(pAltURL, (const char*)pValue->GetBuffer(), pValue->GetSize());
- }
- else if (HXR_OK == m_pProperties->GetPropertyBuffer("url", pValue) && pValue)
- {
- if (m_unProtocol == pnmProtocol ||
- m_unProtocol == rtspProtocol)
- {
- bDefault = TRUE;
-
- // The +1 is NOT for the NULL terminator since the size already has space for it. The +1 is actually because
- // if the URL contains a pnm:// the code below will potentially add a http:// which is one more character than
- // a pnm URL. A rtsp:// URL will work correctly
- INT32 lSize = pValue->GetSize() + 1;
- pAltURL = new char[lSize];
- memset(pAltURL, 0, lSize);
- pURL = (char*)pValue->GetBuffer();
-
- switch (m_unProtocol)
- {
- case pnmProtocol:
- SafeSprintf(pAltURL, lSize, "http:%s", pURL + 4);
- break;
- case rtspProtocol:
- SafeSprintf(pAltURL, lSize, "http:%s", pURL + 5);
- break;
- default:
- break;
- }
- // exclude the port from the URL
- if (m_pszPort)
- {
- pCursor1 = strstr(pAltURL, m_pszPort);
- pCursor2 = pCursor1 + strlen(m_pszPort);
- pCursor1--; // back up over the ':'
-
- while(*pCursor2)
- {
- *pCursor1++ = *pCursor2++;
- }
- *pCursor1 = ' ';
- }
- }
- }
- cleanup:
- HX_RELEASE(pValue);
- return pAltURL;
- }
- void
- CHXURL::ParseResource(void)
- {
- char* pszTemp = NULL;
- char* pResource = NULL;
- char* pPath = NULL;
- char* pFullPath = NULL;
- if (m_pszResource && (*m_pszResource != ' '))
- {
- ::SaveStringToHeader(m_pProperties, PROPERTY_RESOURCE, m_pszResource);
- ::StrAllocCopy(pResource, m_pszResource);
-
- pszTemp = ::HXFindChar(pResource, '?');
- if (pszTemp)
- {
- *pszTemp = ' ';
- }
- pFullPath = new char[strlen(pResource) + 2];
- SafeSprintf(pFullPath, strlen(pResource)+2, "/%s", pResource);
- ::SaveStringToHeader(m_pProperties, PROPERTY_FULLPATH, pFullPath);
- pszTemp = ::HXReverseFindChar(pResource, '/');
- if (pszTemp)
- {
- *pszTemp = ' ';
-
- pPath = new char[strlen(pResource)+2];
- SafeSprintf(pPath, strlen(pResource)+2, "/%s", pResource);
- ::SaveStringToHeader(m_pProperties, PROPERTY_PATH, pPath);
- }
- else
- {
- ::SaveStringToHeader(m_pProperties, PROPERTY_PATH, "/");
- }
- HX_VECTOR_DELETE(pFullPath);
- HX_VECTOR_DELETE(pPath);
- HX_VECTOR_DELETE(pResource);
- }
- else if (m_unProtocol == rtspProtocol)
- {
- ::SaveStringToHeader(m_pProperties, PROPERTY_RESOURCE, "