xmlconfig.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 2,482 行 · 第 1/4 页

CPP
2,482
字号
/* ***** BEGIN LICENSE BLOCK *****
 * Source last modified: $Id: xmlconfig.cpp,v 1.9.22.1 2004/07/19 21:04:07 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 ***** */


//  $Id: xmlconfig.cpp,v 1.9.22.1 2004/07/19 21:04:07 hubbe Exp $

#ifdef _UNIX 
#include <sys/stat.h> 
#endif 

#include "hxtypes.h"
#include "hxcom.h"
#include "looseprs.h"
#include "cbbqueue.h"
#include "hxstrutl.h"
#include "ihxpckts.h"
#include "chxpckts.h"
#include "hxmon.h"	// for registry property type enums
#include "hxerror.h"
#include "xmlconfig.h"
#include "errmsg_macros.h"

#define MAX_TAG_SIZE	32768
#define MAX_ERROR_CHARS 20	// Number of chars to print if an error occurs

static const XMLConfigAlias aliases[] = {
    //Note: Attribute specs here should not have quotes in them!
    //      %0 is replaced with the name of the alias (leftmost column)
    //      %n with the value of the nth attribute
    //      %  args can only appear in the values of attributes
    
    //Alias This Tag    To This         With these 3 args      and these flags
    {"FSMount",		"List",	"Name=FSMount", NULL, NULL,         0},
    {"Plugin",          "List", "Name=%1",      NULL, NULL,         0},
    {"MimeTypes",       "List", "Name=MimeTypes", NULL, NULL,       0},
    {"Type",            "List", "Name=%1",      NULL, NULL,         0},
    {"Ext",             "Var",  NULL,           NULL, NULL,         0},
    {"IPBindings",      "List", "Name=IPBindings", NULL, NULL,      0},
    {"HTTPDeliverable", "List", "Name=HTTPDeliverable", NULL, NULL,      0},
    {"Path",     	"Var",	NULL, NULL, NULL,     0},
    {"ConnectControl",  "List", "Name=ConnectControl", NULL, NULL,  0},
    {"Multicast",	"List", "Name=Multicast", NULL, NULL,0},
    {"Address",         "Var",  NULL,           NULL, NULL,         0},
    {"NetMask",         "Var",  NULL,           NULL, NULL,         0},
    {"AccessLogging",   "List", "Name=AccessLogging", NULL, NULL,   0},
    {"LiveArchive",     "List", "Name=LiveArchive", NULL, NULL,     0},
    {"FarmSplit",       "List", "Name=FarmSplit", NULL, NULL,     0},
    {"Directory",       "List", "Name=%1",      NULL, NULL,         0},
    {"AccessControl",  	"List", "Name=AccessControl", NULL, NULL,     0},
    {"Rule",     	"List", "Name=%1", NULL, NULL,     0},
    {"Access",     	"Var",	NULL, NULL, NULL,     0},
    {"Transmission",    "Var", 	NULL, NULL, NULL,     0},
    {"To",     		"Var",	NULL, NULL, NULL,     0},
    {"From",     	"Var",	NULL, NULL, NULL,     0},
    {"Ports",     	"List", "Name=Ports", NULL, NULL,     0},
    {"Num",     	"Var", NULL, NULL, NULL,     0},
    {"Proxy",     	"List", "Name=Proxy", NULL, NULL,     0},
    {NULL, NULL, NULL, NULL, NULL, 0}
};

#if defined (_WINDOWS ) || defined (_WIN32) || defined(_SYMBIAN)
#define OS_SEPARATOR_CHAR	'\\'
#define OS_SEPARATOR_STRING	"\\"
#elif defined (_UNIX)
#define OS_SEPARATOR_CHAR	'/'
#define OS_SEPARATOR_STRING	"/"
#elif defined (_MACINTOSH) 
#ifdef _MAC_MACHO
#define OS_SEPARATOR_CHAR       '/' 
#define OS_SEPARATOR_STRING     "/" 
#else
#define OS_SEPARATOR_CHAR       ':' 
#define OS_SEPARATOR_STRING     ":" 
#endif
#endif // defined (_WINDOWS ) || defined (_WIN32)

XMLConfig::XMLConfigListNode::~XMLConfigListNode()
{
    if(m_pList)
    {
	delete m_pList;
    }
    if(m_name)
	delete [] m_name;
    if(m_value)
	delete [] m_value;
}

XMLConfig::XMLConfigList::~XMLConfigList()
{
    CHXSimpleList::Iterator i;

    for(i = Begin(); i != End(); ++i)
    {
	XMLConfigListNode* node = (XMLConfigListNode*)(*i);
	delete node;
    }
}

XMLConfig::XMLConfig():m_filename(NULL), m_lRefCount(0), m_pList(NULL),
                       m_ulMajor(0), m_ulMinor(0), m_ActiveSetsOutstanding(0),
                       m_pRegistry(NULL), m_pMessages(NULL), m_szServerversion(NULL),
                       m_pReconfigureResponse(NULL)
{
}

XMLConfig::XMLConfig(IHXRegistry2* pRegistry, IHXErrorMessages* pMessages, const char* szserverversion,
                     UINT32 dwMajor, UINT32 dwMinor)
     : m_filename(0), m_lRefCount(0), m_pList(NULL), m_ulMajor(dwMajor), m_ulMinor(dwMinor)
       , m_ActiveSetsOutstanding(0), m_pReconfigureResponse(NULL)
{
    if (pRegistry)
    {
        m_pRegistry = pRegistry;
        m_pRegistry->AddRef();
    }

    if (pMessages)
    {
        m_pMessages = pMessages;
        m_pMessages->AddRef(); 
    }

    m_szServerversion = new_string(szserverversion);
    
    XMLConfigAlias* alias = (XMLConfigAlias*) &aliases[0];
    char lwr[256]; /* Flawfinder: ignore */
    m_vserver = -1;

    while(alias->from)
    {
	SafeStrCpy(lwr, alias->from, 256);
	strlwr(lwr);
	m_alias_dict.enter(lwr, alias);
	alias++;
    }
}
XMLConfig::~XMLConfig()
{
    delete[] m_szServerversion; 
    HX_RELEASE(m_pReconfigureResponse);
    HX_RELEASE(m_pRegistry);
    HX_RELEASE(m_pMessages); 
}

HX_RESULT
XMLConfig::init(IHXRegistry2* pRegistry, IHXErrorMessages* pMessages, const char* szserverversion,
                     UINT32 dwMajor, UINT32 dwMinor)
{
    m_ulMajor = dwMajor;
    m_ulMinor = dwMinor;
    if (pRegistry)
    {
        m_pRegistry = pRegistry;
        m_pRegistry->AddRef();
    }

    if (pMessages)
    {
        m_pMessages = pMessages;
        m_pMessages->AddRef(); 
    }

    m_szServerversion = new_string(szserverversion);
    
    XMLConfigAlias* alias = (XMLConfigAlias*) &aliases[0];
    char lwr[256]; /* Flawfinder: ignore */
    m_vserver = -1;

    while(alias->from)
    {
	SafeStrCpy(lwr, alias->from, 256);
	strlwr(lwr);
	m_alias_dict.enter(lwr, alias);
	alias++;
    }
    return HXR_OK;
}

STDMETHODIMP
XMLConfig::QueryInterface(REFIID riid, void** ppvObj)
{
    if(IsEqualIID(riid, IID_IUnknown))
    {
        AddRef();
        *ppvObj = (IUnknown*)(IHXRegConfig*)this;
        return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IHXRegConfig))
    {
	AddRef();
	*ppvObj = (IHXRegConfig*)this;
	return HXR_OK;
    }

    *ppvObj = NULL;
    return HXR_NOINTERFACE;
}

STDMETHODIMP_(UINT32)
XMLConfig::AddRef()
{
    return InterlockedIncrement(&m_lRefCount);    
}

STDMETHODIMP_(UINT32)
XMLConfig::Release()
{
    if (InterlockedDecrement(&m_lRefCount) > 0)
    {
        return m_lRefCount;
    }

    delete this;
    return 0;
}

HX_RESULT
XMLConfig::Write(const char* name, const char* filename)
{
    FILE* outfile = fopen(filename, "w");
    if(!outfile)
    {
	return HXR_INVALID_FILE;
    }

    fprintf(outfile, "<?XML Version=\"1.0\" ?>\n");
    fprintf(outfile, "<!-- Auto generated by %s %d.%d -->\n\n",
            m_szServerversion, m_ulMajor, m_ulMinor);

#ifdef _UNIX
    chmod(filename, 0700);
#endif //UNIX

    return DumpConfig(name, 0, outfile, m_pRegistry);
}

HX_RESULT
XMLConfig::DumpConfig(const char* name, int indent, FILE* outfile,
		      IHXRegistry2* pRegistry)
{
    IHXValues* pValues;
    const char* propName;
    HX_RESULT res;
    UINT32 prop_id;

    if(HXR_OK != pRegistry->GetPropListByName(name,
					  pValues))
	return HXR_FAIL;

    char* point = (char*)strrchr(name, '.');
    if(point)
    {
	if(strcasecmp(point + 1, "XXXBADLIST") == 0)
	    return HXR_FAIL;

	for(int j = 0; j < indent - 1; j++)
	    fprintf(outfile, "  ");
	fprintf(outfile, "<List %s>\n", point + 1);
    }
    
    res = pValues->GetFirstPropertyULONG32(propName, prop_id);
    while(res == HXR_OK)
    {
	HXPropType type = pRegistry->GetTypeById(prop_id);
	switch(type)
	{
	    case PT_COMPOSITE:
		DumpConfig(propName, indent+1, outfile, pRegistry);
		break;
	    case PT_INTEGER:
	    {
		INT32 val;
		if(HXR_OK == pRegistry->GetIntById(prop_id, val))
		{
		    
		    fprintf(outfile, "%*.*s<Var %s=\"%ld\"/>\n",
			    indent * 2, indent * 2, "  ",
			    strrchr(propName, '.') + 1,
			    val);
		}
		break;
	    }
	    case PT_INTREF:
		break;
	    case PT_STRING:
	    {
		IHXBuffer* pBuffer;
		if(HXR_OK == pRegistry->GetStrById(prop_id, pBuffer) && pBuffer)
		{
		    fprintf(outfile, "%*.*s<Var %s=\"%s\"/>\n",
			    indent * 2, indent * 2, "  ",
			    strrchr(propName, '.') + 1,
			    pBuffer->GetBuffer());
		    pBuffer->Release();
		}
		break;
	    }
	    case PT_BUFFER:
	    {
		IHXBuffer* pBuffer;
		pRegistry->GetBufById(prop_id, pBuffer);
		if(pBuffer)
		{
		    fprintf(outfile, "%*.*s<Var %s=\"%s\"/>\n",
			    indent * 2, indent * 2, "  ",
			    strrchr(propName, '.') + 1,
			    pBuffer->GetBuffer());
		    pBuffer->Release();
		}
		break;
	    }
	    case PT_UNKNOWN:
	    default:
		break;
	}

	res = pValues->GetNextPropertyULONG32(propName, prop_id);
    }
    if(point)
	fprintf(outfile, "%*.*s</List>\n", (indent - 1) * 2, (indent-1)*2, "  ");
    fflush(outfile);
    pValues->Release();
    return HXR_OK;
}

void
XMLConfig::ExpandAttribute(XMLTag* tag, const char* attribute)
{
    const char* equals;
    char subst[2048]; /* Flawfinder: ignore */
    const char* a;
    UINT32 arg;
    UINT32 i;

    equals = strchr(attribute, '=');
    // Aliases are hardcoded.  Don't enter wrong ones, dumbass.
    HX_ASSERT(equals);

    tag->new_attribute()->name = new char[equals - attribute + 1];
    strncpy(tag->m_cur_attribute->name, attribute, /* Flawfinder: ignore */
	    equals - attribute);
    tag->m_cur_attribute->name[equals - attribute] = 0;

    // Attributes already present in the tag with the same name
    // as an aliased attribute override the alias.
    for(i = 0; i < tag->m_numAttributes - 1; i++)
    {
	if(tag->attribute(i)->name && 
	   (strcasecmp(tag->attribute(i)->name, 
		       tag->m_cur_attribute->name) == 0))
	{
	    break;
	}
    }
    if(i < tag->m_numAttributes - 1)
    {
	// Found a duplicate attribute with this name, throw out the
	// alias version.
	delete tag->m_cur_attribute;
	tag->m_numAttributes--;
    }
    else if(!strchr(equals, '%'))
    {
	tag->m_cur_attribute->value = new_string(equals+1);
    }
    else
    {
	for(a = equals, i = 0; *a; a++, i++)
	{
	    switch(*a)
	    {
		case '%':
		    arg = *(a+1) - '0';
		    if(arg > 0)
		    {
			if(arg - 1 < tag->m_numAttributes)
			{
			    SafeStrCpy(&subst[i], tag->attribute(arg - 1)->value, 2048-i);
			    i+= strlen(tag->attribute(arg - 1)->value);
			}
			else
			{
			    ERRMSG(m_pMessages,
				   "%s: Alias %s requires at least %d arguments",
				   m_filename,
				   tag->m_name, arg);
			    return;
			}
		    }
		    else
		    {
			SafeStrCpy(&subst[i], tag->m_name, 2048-i);
			i += strlen(tag->m_name);
		    }
		    break;
		default:
		    subst[i] = *a;
	    }
	}
	subst[i] = 0;
	tag->m_cur_attribute->value = new_string(subst);
    }
}

// XMLConfig::Expand
//
// Do alias and loose syntax expansion
BOOL
XMLConfig::Expand(XMLTag* tag, CBigByteQueue* queue)
{
    UINT32 i;

    Dict_entry* ent;
    XMLConfigAlias* alias;
    char* lwr = new char[strlen(tag->m_name) + 1];
    BOOL ignore = FALSE;

    strcpy(lwr, tag->m_name); /* Flawfinder: ignore */
    strlwr(lwr);
    if((ent = m_alias_dict.find(lwr)) != NULL)
    {
	alias = (XMLConfigAlias*)ent->obj;
	delete [] tag->m_name;
	tag->m_name = new_string(alias->to);
	if(tag->m_type == XMLPlainTag)
	{
	    if(alias->attr1)
	    {
		ExpandAttribute(tag, alias->attr1);
	    }
	    if(alias->attr2)
	    {
		ExpandAttribute(tag, alias->attr2);
	    }
	    if(alias->attr3)
	    {
		ExpandAttribute(tag, alias->attr3);
	    }
	}
	if((alias->flags & AL_TAGIFY) && (tag->m_type != XMLEndTag))
	{
	    UINT32 bytesAvail = queue->GetQueuedItemCount();
	    BYTE* buf = new BYTE[bytesAvail];
	    queue->DeQueue(buf, bytesAvail);
	    BOOL isList = FALSE;
	    char ibuf[1024]; /* Flawfinder: ignore */

	    if(!tag->m_need_close && strcasecmp(alias->to, "list") == 0)
	    {
		isList = TRUE;
		ignore = TRUE;
		if(tag->get_attribute("name"))
		    SafeSprintf(ibuf, 1024, "<List Name=\"%s\">",
			    tag->get_attribute("name"));
		else
		    SafeSprintf(ibuf, 1024, "<List Name=\"%s\">",
			    alias->from);
		queue->EnQueue(ibuf, strlen(ibuf));
	    }
	    UINT32 i;
	    for(i = 0; i < tag->m_numAttributes; i++)
	    {
		if (tag->attribute(i)->name)
		{
		    SafeSprintf(ibuf, 1024, "<Var Name=\"%s\" Value=\"%s\"/>",
			   (tag->attribute(i)->name ? tag->attribute(i)->name : ""),
			    tag->attribute(i)->value);
		    queue->EnQueue(ibuf, strlen(ibuf));
		}
	    }
	    if(isList)
	    {
		sprintf(ibuf, "</List>"); /* Flawfinder: ignore */
		queue->EnQueue(ibuf, strlen(ibuf));
	    }
	    queue->EnQueue(buf, bytesAvail);
	}
    }
    delete [] lwr;

    if(tag->m_type != XMLPlainTag || ignore)
	return ignore;

    if(strcasecmp(tag->m_name, "list") == 0)
    {
	if(tag->m_numAttributes < 1)
	{
	    return ignore;
	}
	
	for(i = 0; i < tag->m_numAttributes; i++)
	{
	    if(!tag->attribute(i)->name)
	    {
		tag->attribute(i)->name = new_string("name");
	    }
	    else if(strcasecmp(tag->attribute(i)->name, "name") != 0)
	    {
		ERRMSG(m_pMessages,
		       "%s: Unknown List Attribute %s",
		       m_filename,
		       tag->attribute(i)->name);
		return ignore;
	    }
	}
    }
    else if(strcasecmp(tag->m_name, "var") == 0)
    {
	if(tag->m_numAttributes < 1)
	{
	    ERRMSG(m_pMessages,
		   "%s: Var tag requires at least one attribute",
		   m_filename);
	    return ignore;
	}

	if(tag->m_numAttributes == 1)
	{
	    // Special case, <Var x=y> converts to <Var name=x value=y>
	    tag->new_attribute()->name = new_string("value");
	    tag->attribute(1)->value = tag->attribute(0)->value;
	    tag->attribute(0)->value = tag->attribute(0)->name;
	    if(!tag->attribute(0)->value)
	    {
		char* val = new char[20];
		sprintf(val, "elem%ld", tag->elem); /* Flawfinder: ignore */
		tag->attribute(0)->value = val;
	    }
	    tag->attribute(0)->name = new_string("name");
	}
    }
    else if(strcasecmp(tag->m_name, "server") == 0)
    {
	if(tag->m_numAttributes < 1)
	{
	    ERRMSG(m_pMessages,
		   "%s: Server tag requires at least one attribute",
		   m_filename);
	    return ignore;
	}
	if(!tag->get_attribute("number"))
	{
	    tag->attribute(0)->name = new_string("number");
	}
    }
    return ignore;
}

XMLConfigVarType
XMLConfig::GetVarType(XMLConfigListNode* node)
{
    char* pos = node->m_value;

    if (0 == *pos)
    {
         return CfgVarString;
    }
    for(; *pos && isdigit(*pos); pos++)
	;
    if(*pos == 0 && *(node->m_value) != 0)
    {
	node->m_int = atol(node->m_value);
	return CfgVarInt;
    }
    
    if(strcasecmp(node->m_value, "true") == 0)
    {
	node->m_bool = TRUE;
	return CfgVarBool;
    }
    else if(strcasecmp(node->m_value, "false") == 0)
    {
	node->m_bool = FALSE;
	return CfgVarBool;

⌨️ 快捷键说明

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