📄 hxurl.cpp
字号:
/* ***** 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 = '\0'; } // 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 = '\0'; 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 = '\0'; 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) == '\0') { 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) == '\0') { 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 = '\0'; 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) == '\0') { m_LastError = HXR_INVALID_URL_HOST; goto cleanup; } // Zero terminate password and move the cursor to the hostname *pszOption = '\0'; if (m_pszUsername) { ::SaveStringToHeader(m_pProperties, PROPERTY_USERNAME, m_pszUsername); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -