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 + -
显示快捷键?