⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hxurl.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* ***** BEGIN LICENSE BLOCK ***** 
 * Version: RCSL 1.0/RPSL 1.0 
 *  
 * Portions Copyright (c) 1995-2002 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 
 * Version 1.0 (the "RPSL") available at 
 * http://www.helixcommunity.org/content/rpsl unless you have licensed 
 * the file under the RealNetworks Community Source License Version 1.0 
 * (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.  
 *  
 * 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);
	    }

	    if (m_pszPassword)
	    {
		::SaveStringToHeader(m_pProperties, PROPERTY_PASSWORD, m_pszPassword);
	    }

	    pszCursor = pszOption+1;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -