xmlconfig.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:60k
- /* ***** 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 -->nn",
- 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;
- }
- return CfgVarString;
- }
- void
- XMLConfig::StuffRegistry(XMLConfigList* list)
- {
- CHXSimpleList::Iterator i;
- char* regname = list->m_parentnode->get_registry_name();
- if(m_pRegistry->GetTypeByName(regname) == PT_UNKNOWN)
- {
- m_pRegistry->AddComp(regname);
- }
- delete [] regname;
- for(i = list->Begin(); i != list->End(); ++i)
- {
- XMLConfigListNode* node = (XMLConfigListNode*)(*i);
- switch(node->m_type)
- {
- case CfgVar:
- regname = node->get_registry_name();
- switch(GetVarType(node))
- {
- case CfgVarInt:
- // printf("%s = %ldn", regname, node->m_int);
- if(m_pRegistry->GetTypeByName(regname) == PT_UNKNOWN)
- {
- m_pRegistry->AddInt(regname, node->m_int);
- }
- else
- {
- m_pRegistry->SetIntByName(regname, node->m_int);
- }
- break;
- case CfgVarString:
- {
- CHXBuffer* pBuffer = new CHXBuffer;
- pBuffer->AddRef();
- pBuffer->Set((UINT8*)node->m_value,
- strlen(node->m_value) + 1);
- // printf("%s = %sn", regname, (const char *)pBuffer->GetBuffer());
- if(m_pRegistry->GetTypeByName(regname) == PT_UNKNOWN)
- {
- m_pRegistry->AddStr(regname, pBuffer);
- }
- else
- {
- m_pRegistry->SetStrByName(regname, pBuffer);
- }
- pBuffer->Release();
- break;
- }
- case CfgVarBool:
- // printf("%s = %ldn", regname, node->m_bool);
- if(m_pRegistry->GetTypeByName(regname) == PT_UNKNOWN)
- {
- m_pRegistry->AddInt(regname, node->m_bool);
- }
- else
- {
- m_pRegistry->SetIntByName(regname, node->m_bool);
- }
- break;
- }
- delete [] regname;
- break;
- case CfgList:
- StuffRegistry(node->m_pList);
- break;
- }
- }
- }
- //
- // Method: Read
- //
- // Parameters:
- //
- // filename: The file to be read.
- // pWinRegKey: The Windows registry key to be filled in (can be
- // NULL if no registry writing is needed).
- // pServRegKey: The Server registry key to be filled in.
- //
- // Notes: the bIncludedFile is for internal recursive use only. Do not
- // set it when calling from outside this object.
- HX_RESULT
- XMLConfig::Read(char* filename,
- char* pServRegKey,
- BOOL bIncludedFile)
- {
- HX_RESULT hResult = HXR_OK;
- FILE* fp=0;
- XMLParser parser;
- XMLTag* tag = 0;
- CBigByteQueue queue(MAX_TAG_SIZE);
- int l=0;
- BOOL filedone = FALSE;
- UINT32 indent = 0;
- HX_ASSERT(filename && strlen(filename));
- HX_VECTOR_DELETE(m_filename);
- m_filename = new_string(filename);
- fp = fopen(filename, "r");
- if (!fp)
- {
- ERRMSG(m_pMessages, "%s: file not found", filename);
- return HXR_FILE_NOT_FOUND;
- }
- if(!m_pList)
- {
- m_pList = new XMLConfigList;
- m_pList->m_parentnode = new XMLConfigListNode;
- m_pList->m_parentnode->m_name = new_string(pServRegKey);
- m_pList->m_parentnode->m_parent = NULL;
- }
- // read the config file into the byte queue
- INT32 nBufSize = 16384;
- BYTE* pBuf = new BYTE[nBufSize];
- while (!filedone && hResult == HXR_OK)
- {
- l = fread(pBuf, 1, nBufSize, fp);
- if (l > 0)
- {
- if (!queue.EnQueue(pBuf, l))
- {
- if (!queue.Grow(l))
- {
- ERRMSG(m_pMessages,
- "error expanding data structure while parsing %s",
- filename);
- hResult = HXR_FAIL;
- }
- if (!queue.EnQueue(pBuf, l))
- {
- ERRMSG(m_pMessages,
- "unknown error while parsing %s",
- filename);
- hResult = HXR_FAIL;
- }
- }
- }
- else
- {
- filedone = TRUE;
- }
- }
- UINT32 bytesUsed=0;
- UINT32 bytesAvail=0;
- BYTE* p=0;
- while (hResult == HXR_OK && (bytesAvail = queue.GetQueuedItemCount()) > 0)
- {
- if (bytesAvail > nBufSize)
- {
- HX_VECTOR_DELETE(pBuf);
- pBuf = new BYTE[bytesAvail];
- nBufSize = bytesAvail;
- }
- p = pBuf;
- queue.DeQueue(pBuf, bytesAvail);
- bytesUsed = bytesAvail;
- HX_DELETE(tag);
- XMLParseResult res = parser.Parse((const char*&)p, bytesAvail, tag);
- queue.EnQueue(p, bytesAvail - (p - pBuf));
- switch(res)
- {
- case XMLPNoClose:
- // A tag opener was found, but no closer yet.
- if (filedone)
- {
- pBuf[bytesAvail - 1] = ' ';
- if (bytesAvail > MAX_ERROR_CHARS)
- {
- pBuf[MAX_ERROR_CHARS - 1] = ' ';
- }
- ERRMSG(m_pMessages,
- "%s: Missing close for tag '%s'...", m_filename, pBuf);
- hResult = HXR_FAIL;
- }
- break;
- case XMLPNoTagType:
- *p = 0;
- ERRMSG(m_pMessages,
- "%s: Badly formed tag '%s'", m_filename, pBuf);
- break;
- case XMLPBadAttribute:
- *p = 0;
- ERRMSG(m_pMessages,
- "%s: Badly formed attribute in '%s'", m_filename,
- pBuf);
- break;
- case XMLPPlainText:
- //Some text. What do we care?
- break;
- case XMLPBadEndTag:
- *p = 0;
- ERRMSG(m_pMessages,
- "%s: Unexpected end tag '</%s>'", m_filename, tag->m_name);
- hResult = HXR_FAIL;
- break;
- case XMLPComment:
- // A comment, fine.
- if(tag != NULL)
- {
- //Some kind of comment directive
- XMLAttribute* pAttr = tag->attribute(0);
- if(pAttr &&
- pAttr->name)
- {
- if(strcasecmp(pAttr->name, "include") == 0)
- {
- char* path;
- char* newfile = new char[1024];
- if(!strchr(tag->attribute(0)->value,
- OS_SEPARATOR_CHAR) &&
- ((path = strrchr(m_filename, OS_SEPARATOR_CHAR))
- != NULL))
- {
- path++;
- if (path - m_filename < 1024)
- {
- strncpy(newfile, m_filename, path - m_filename);
- newfile[path - m_filename] = ' ';
- }
- SafeStrCat(newfile, tag->attribute(0)->value, 1024);
- }
- else
- {
- SafeStrCpy(newfile, tag->attribute(0)->value, 1024);
- }
- char* filename = m_filename;
- m_filename = NULL;
- Read(newfile, pServRegKey, TRUE);
- delete[] m_filename;
- m_filename = filename;
- delete[] newfile;
- }
- }
- }
- break;
- case XMLPDirective:
- // A directive. We don't handle any yet.
- break;
- case XMLPProcInst:
- // A processing Instruction, whee!
- break;
- case XMLPTag:
- {
- if(Expand(tag, &queue))
- break;
- XMLConfigListNode* node = new XMLConfigListNode;
- node->m_parent = m_pList->m_parentnode;
- node->m_vserver = m_vserver;
- if(tag->m_need_close)
- {
- if(strcasecmp(tag->m_name, "list") == 0)
- {
- const char* name = tag->get_attribute("name");
- if(!name)
- {
- ERRMSG(m_pMessages,
- "%s: List tag requires a name attribute",
- m_filename);
- // Process anyway, give it a dummy name
- name = "XXXBADLIST";
- }
- node->m_type = CfgList;
- node->m_name = new_string(name);
- node->m_num = tag->elem;
- m_pList->AddTail(node);
- m_pListStack.Push(m_pList);
- node->m_pList = new XMLConfigList;
- m_pList = node->m_pList;
- m_pList->m_parentnode = node;
- }
- else if(strcasecmp(tag->m_name, "server") == 0)
- {
- const char* server = tag->get_attribute("number");
- if(!server)
- {
- ERRMSG(m_pMessages,
- "%s: Server tag requires a number, defaulting to 0",
- m_filename);
- m_vserver = 0;
- }
- else
- {
- char vserver_str[64]; /* Flawfinder: ignore */
- m_vserver = atol(server);
- sprintf(vserver_str, "server%ld", m_vserver); /* Flawfinder: ignore */
- if(m_pRegistry->GetTypeByName(vserver_str) == PT_UNKNOWN)
- {
- m_pRegistry->AddComp(vserver_str);
- sprintf(vserver_str, "server%ld.config", /* Flawfinder: ignore */
- m_vserver);
- m_pRegistry->AddComp(vserver_str);
- }
- }
- }
- }
- else if(tag->m_type != XMLEndTag)
- {
- const char* name = tag->get_attribute("name");
- const char* value = tag->get_attribute("value");
- if(name && value)
- {
- node->m_type = CfgVar;
- node->m_name = new_string(name);
- node->m_value = new_string(value);
- node->m_num = tag->elem;
- m_pList->AddTail(node);
- }
- }
- else
- {
- // An End Tag
- if(strcasecmp(tag->m_name, "list") == 0)
- {
- m_pList = (XMLConfigList*)m_pListStack.Pop();
- }
- else if(strcasecmp(tag->m_name, "server") == 0)
- {
- if(m_vserver < 0)
- {
- ERRMSG(m_pMessages,
- "%s: </Server> Tag with no matching <Server>",
- m_filename);
- }
- else
- {
- m_vserver = -1;
- }
- }
- }
- break;
- }
- }
- }
- if(hResult == HXR_OK && !bIncludedFile)
- {
- StuffRegistry(m_pList);
- delete m_pList->m_parentnode;
- }
- if (hResult == HXR_OK && !m_pListStack.IsEmpty())
- {
- ERRMSG(m_pMessages,
- "%s: <List> tag with no matching </List>",
- m_filename);
- hResult = HXR_FAIL;
- }
- // cleanup
- if (fp) fclose(fp);
- HX_VECTOR_DELETE(pBuf);
- HX_DELETE(tag);
- return hResult;
- }
- char*
- XMLConfig::XMLConfigListNode::get_registry_name(INT32 vserver)
- {
- char* name;
- if(m_parent)
- {
- char* parentname = m_parent->get_registry_name(
- vserver < 0 ? m_vserver : vserver);
- name = new char[strlen(parentname) + strlen(m_name) + 2];
- sprintf(name, "%s.%s", parentname, m_name); /* Flawfinder: ignore */
- delete [] parentname;
- return name;
- }
- else
- {
- if(vserver >= 0)
- {
- name = new char[26 + strlen(m_name) + 2];
- sprintf(name, "server%ld.%s", vserver, m_name); /* Flawfinder: ignore */
- }
- else
- {
- name = new_string(m_name);
- }
- return name;
- }
- }
- ///XXXPM This func does not correctly handle the original file not
- ///being there.
- HX_RESULT
- XMLConfig::WriteToFile(const char* pKeyName, const char* pFileName)
- {
- UINT32 ulListsToIgnore = 0;
- /*
- * Make sure we have a valid file name to use.
- */
- if (!pFileName)
- {
- return HXR_FAIL;
- }
- /*
- * Copy filename to filename.bak.
- */
- char *pNewFileName = new char[strlen(pFileName) + strlen(".bak") + 1];
- sprintf(pNewFileName, "%s.bak", pFileName); /* Flawfinder: ignore */
- FILE* fpOld = fopen(pFileName, "r");
- FILE* fpNew = fopen(pNewFileName, "w");
- if (!fpNew || !fpOld)
- {
- HX_VECTOR_DELETE(pNewFileName);
- if (fpNew) fclose(fpNew);
- if (fpOld) fclose(fpOld);
- return HXR_FAIL;
- }
- INT32 nBufSize=16384;
- BYTE* pBuf = new BYTE[nBufSize];
- int iGot = 0;
- while (!feof(fpOld))
- {
- iGot = fread(pBuf, sizeof(char), nBufSize, fpOld);
- if (iGot)
- {
- fwrite(pBuf, sizeof(char), iGot, fpNew);
- }
- }
- fclose(fpNew);
- fclose(fpOld);
- #ifdef _UNIX
- chmod(pNewFileName, 0700);
- #endif //UNIX
- fpNew = fopen(pFileName, "w");
- fpOld = fopen(pNewFileName, "r");
- HX_VECTOR_DELETE(pNewFileName);
- if (!fpNew || !fpOld)
- {
- if (fpNew) fclose(fpNew);
- if (fpOld) fclose(fpOld);
- return HXR_FAIL;
- }
- int l;
- BOOL filedone = 0;
- XMLTag* tag = 0;
- XMLTag* wspacetag = 0;
- CBigByteQueue queue(MAX_TAG_SIZE);
- XMLParser parser;
- HX_RESULT hResult = HXR_OK;
- /*
- * Files are all aready. Now we need to build our config levels list.
- */
- CHXSimpleList levlist;
- /*
- * Add for level 0.
- */
- CHXSimpleList* pNewList = new CHXSimpleList;
- IHXValues* pValues = 0;
- _AddPropsToList(pNewList, pKeyName, m_pRegistry);
- XMLConfigString curr_level;
- curr_level.AddLevel(pKeyName);
- while (!filedone && hResult == HXR_OK)
- {
- l = fread(pBuf, 1, nBufSize, fpOld);
- if (l > 0)
- {
- if (!queue.EnQueue(pBuf, l))
- {
- if (!queue.Grow(l))
- {
- ERRMSG(m_pMessages,
- "error expanding data structure while parsing");
- hResult = HXR_FAIL;
- }
- if (!queue.EnQueue(pBuf, l))
- {
- ERRMSG(m_pMessages,
- "unknown error while parsing");
- hResult = HXR_FAIL;
- }
- }
- }
- else
- {
- filedone = TRUE;
- }
- }
- UINT32 bytesUsed=0;
- UINT32 bytesAvail=0;
- BYTE* p=0;
- while (hResult == HXR_OK && (bytesAvail = queue.GetQueuedItemCount()) > 0)
- {
- if (bytesAvail > nBufSize)
- {
- HX_VECTOR_DELETE(pBuf);
- pBuf = new BYTE[bytesAvail];
- nBufSize = bytesAvail;
- }
- p = pBuf;
- queue.DeQueue(pBuf, bytesAvail);
- bytesUsed = bytesAvail;
- HX_DELETE(tag);
- XMLParseResult res = parser.Parse((const char*&)p, bytesAvail, tag);
- queue.EnQueue(p, bytesAvail - (p - pBuf));
- switch(res)
- {
- case XMLPNoClose:
- // A tag opener was found, but no closer yet.
- if (filedone)
- {
- pBuf[bytesAvail - 1] = ' ';
- if (bytesAvail > MAX_ERROR_CHARS)
- {
- pBuf[MAX_ERROR_CHARS - 1] = ' ';
- }
- ERRMSG(m_pMessages,
- "%s: Missing close for tag %s...", m_filename, pBuf);
- hResult = HXR_FAIL;
- }
- break;
- case XMLPNoTagType:
- *p = 0;
- ERRMSG(m_pMessages,
- "%s: Badly formed tag %s", m_filename, pBuf);
- break;
- case XMLPBadAttribute:
- *p = 0;
- ERRMSG(m_pMessages,
- "%s: Badly formed attribute in %s", m_filename,
- pBuf);
- break;
- case XMLPPlainText:
- /*
- * Just plaintext. Dump this out directly.
- */
- if (wspacetag)
- {
- delete wspacetag;
- }
- wspacetag = tag;
- tag = 0;
- /*
- fwrite(tag->m_cur_attribute->value, sizeof(char),
- strlen(tag->m_cur_attribute->value), fpNew);
- */
- break;
- case XMLPBadEndTag:
- *p = 0;
- ERRMSG(m_pMessages,
- "%s: Unexpected tag %s", m_filename, pBuf);
- break;
- case XMLPComment:
- /*
- * Just a comment. Dump it out. Comment lives from
- * p to pBuf.
- */
- if (wspacetag)
- {
- fwrite(wspacetag->m_cur_attribute->value, sizeof(char),
- strlen(wspacetag->m_cur_attribute->value), fpNew);
- delete wspacetag;
- wspacetag = 0;
- }
- fwrite(pBuf, sizeof(char), p - pBuf, fpNew);
- break;
- case XMLPDirective:
- // A directive. We don't handle any yet.
- break;
- case XMLPProcInst:
- /*
- * Just dump processing instructions as we read them.
- */
- if (wspacetag)
- {
- fwrite(wspacetag->m_cur_attribute->value, sizeof(char),
- strlen(wspacetag->m_cur_attribute->value), fpNew);
- delete wspacetag;
- wspacetag = 0;
- }
- fwrite(pBuf, sizeof(char), p - pBuf, fpNew);
- break;
- case XMLPTag:
- {
- if(Expand(tag, &queue))
- break;
- if(tag->m_need_close)
- {
- if(strcasecmp(tag->m_name, "list") == 0)
- {
- if (ulListsToIgnore)
- {
- ulListsToIgnore++;
- }
- else
- {
- const char* name = tag->get_attribute("name");
- if(!name)
- {
- ERRMSG(m_pMessages,
- "%s: List tag requires a name attribute",
- m_filename);
- // Process anyway, give it a dummy name
- name = "XXXBADLIST";
- }
- /*
- * Remove current tag from list, push current list,
- * create new list, add next level's props.
- */
- _RemovePropFromList(pNewList, name);
- curr_level.AddLevel(name);
- if (!_PropExists(&curr_level, m_pRegistry))
- {
- curr_level.RemoveLevel();
- ulListsToIgnore++;
- }
- else
- {
- levlist.AddHead((void*)pNewList);
- if (wspacetag)
- {
- fwrite(wspacetag->m_cur_attribute->value, sizeof(char),
- strlen(wspacetag->m_cur_attribute->value), fpNew);
- delete wspacetag;
- wspacetag = 0;
- }
- fprintf(fpNew, "<List Name="%s">", name);
- pNewList = new CHXSimpleList;
- _AddPropsToList(pNewList, curr_level.CharStar(), m_pRegistry);
- }
- }
-
- }
- }
- else if(tag->m_type != XMLEndTag)
- {
- if (!ulListsToIgnore)
- {
- const char* name = tag->get_attribute("name");
- const char* value = tag->get_attribute("value");
- if (name)
- {
- curr_level.AddLevel(name);
- _RemovePropFromList(pNewList, name);
- /*
- * Make sure this prop is still set.
- */
- if (_PropExists(&curr_level, m_pRegistry))
- {
- if (wspacetag)
- {
- fwrite(wspacetag->m_cur_attribute->value, sizeof(char),
- strlen(wspacetag->m_cur_attribute->value), fpNew);
- delete wspacetag;
- wspacetag = 0;
- }
- char* p = _GetPropValueString(curr_level.CharStar(), m_pRegistry);
- if (p)
- {
- fprintf(fpNew, "<Var %s="%s"/>",
- name,
- p);
- delete[] p;
- }
- }
- curr_level.RemoveLevel();
- }
- }
- }
- else
- {
- // An End Tag
- if(strcasecmp(tag->m_name, "list") == 0)
- {
- if (ulListsToIgnore)
- {
- ulListsToIgnore --;
- }
- else
- {
- /*
- * Need to add the stuff at this level that was
- * was not in the config file.
- */
- if (pNewList->GetCount() == 0)
- {
- if (wspacetag)
- {
- fwrite(wspacetag->m_cur_attribute->value, sizeof(char),
- strlen(wspacetag->m_cur_attribute->value), fpNew);
- }
- }
- else
- {
- fprintf(fpNew, "n");
- AppendPropsToFile(fpNew, curr_level, pNewList,
- 4, m_pRegistry, pKeyName);
- _IndentFile(fpNew, 4, curr_level, pKeyName);
- }
- delete wspacetag;
- wspacetag = 0;
- fprintf(fpNew, "</List>");
- curr_level.RemoveLevel();
- delete pNewList;
- pNewList = (CHXSimpleList*)levlist.RemoveHead();
- }
- }
- }
- break;
- }
- }
- // Give up if we've lost all hope
- if (HXR_OK != hResult)
- {
- break;
- }
- }
- if (hResult == HXR_OK && wspacetag)
- {
- fwrite(wspacetag->m_cur_attribute->value, sizeof(char),
- strlen(wspacetag->m_cur_attribute->value), fpNew);
- delete wspacetag;
- wspacetag = 0;
- }
- /*
- * Ok, done with the whole file. Make sure that all of the base level stuff
- * gets added.
- */
- //XXXPM Calculate this later.
- if (hResult == HXR_OK)
- {
- int indent = 4;
- AppendPropsToFile(fpNew, curr_level, pNewList, indent, m_pRegistry, pKeyName);
- }
- // cleanup
- if (fpNew) fclose(fpNew);
- if (fpOld) fclose(fpOld);
- HX_DELETE(pNewList);
- HX_VECTOR_DELETE(pBuf);
- HX_DELETE(tag);
- return hResult;
- }
- void
- XMLConfig::_AddPropsToList(CHXSimpleList* pList, const char* pName,
- IHXRegistry2* preg)
- {
- IHXValues* pValues = 0;
- UINT32 ul;
- const char* pPropName;
- preg->GetPropListByName(pName, pValues);
- if (pValues)
- {
- if (HXR_OK == pValues->GetFirstPropertyULONG32(pPropName, ul))
- {
- XMLPropInfo* pInfo = new XMLPropInfo;
- pInfo->m_pName = new char[strlen(pPropName) + 1 - strlen(pName)];
- strcpy(pInfo->m_pName, &(pPropName[strlen(pName) + 1])); /* Flawfinder: ignore */
- pInfo->m_Type = preg->GetTypeByName(pPropName);
- pList->AddHead((void*)pInfo);
- while (HXR_OK == pValues->GetNextPropertyULONG32(pPropName, ul))
- {
- XMLPropInfo* pInfo = new XMLPropInfo;
- pInfo->m_pName = new char[strlen(pPropName) + 1 - strlen(pName)];
- strcpy(pInfo->m_pName, &(pPropName[strlen(pName) + 1]));
- pInfo->m_Type = preg->GetTypeByName(pPropName);
- pList->AddHead((void*)pInfo);
- }
- }
- pValues->Release();
- }
- }
- void
- XMLConfig::_RemovePropFromList(CHXSimpleList* pList, const char* pName)
- {
- LISTPOSITION pos;
- pos = pList->GetHeadPosition();
- XMLPropInfo* pProp;
-
- while (pos)
- {
- pProp = (XMLPropInfo*)pList->GetAt(pos);
- if (!pProp)
- {
- return;
- }
- if (!strcasecmp(pProp->m_pName, pName))
- {
- pList->RemoveAt(pos);
- delete pProp;
- return;
- }
- pList->GetNext(pos);
- }
- }
- char*
- XMLConfig::_GetPropValueString(const char* pName, IHXRegistry2* pReg)
- {
- int vartype;
- IHXBuffer* pBuffer;
- INT32 l;
- char* ret;
- vartype = pReg->GetTypeByName(pName);
- if(vartype == PT_INTEGER)
- {
- if(HXR_OK == pReg->GetIntByName(pName, l))
- {
- char num[32]; /* Flawfinder: ignore */
- sprintf(num, "%d", l); /* Flawfinder: ignore */
- ret = new char[strlen(num) + 1];
- strcpy(ret, num); /* Flawfinder: ignore */
- return ret;
- }
- else
- {
- return 0;
- }
- }
- else if(vartype == PT_STRING)
- {
- if(HXR_OK == pReg->GetStrByName(pName,
- pBuffer) && pBuffer)
- {
- ret = new char[pBuffer->GetSize()+1];
- strcpy(ret, (const char*)pBuffer->GetBuffer()); /* Flawfinder: ignore */
- pBuffer->Release();
- return ret;
- }
- else
- {
- return 0;
- }
- }
- return 0;
- }
- void
- XMLConfig::_CleanList(CHXSimpleList* pList)
- {
- XMLPropInfo* pInfo;
- while (!pList->IsEmpty())
- {
- pInfo = (XMLPropInfo*)pList->RemoveHead();
- delete pInfo;
- }
- }
- void
- XMLConfig::AppendPropsToFile(FILE* fp, XMLConfigString level,
- CHXSimpleList* pList, int indent_per_level,
- IHXRegistry2* hxreg, const char* pBase)
- {
- XMLPropInfo* pInfo = 0;
- while (!pList->IsEmpty())
- {
- pInfo = (XMLPropInfo*)pList->RemoveHead();
- level.AddLevel(pInfo->m_pName);
- _AppendPropToFile(fp, level, indent_per_level, hxreg, pBase);
- level.RemoveLevel();
- delete pInfo;
- }
- }
- void
- XMLConfig::_IndentFile(FILE* fp, int indent_per_level,
- XMLConfigString level,
- const char* pBase)
- {
- int dots_to_ignore = 1;
- INT32 i;
- const char* pc;
- pc = pBase;
- while (*pc)
- {
- if (*pc == '.')
- {
- dots_to_ignore ++;
- }
- pc++;
- }
- pc = level.CharStar();
- while (*pc)
- {
- if (*pc == '.')
- {
- if (dots_to_ignore)
- {
- dots_to_ignore--;
- }
- else
- {
- for (i = 0; i < indent_per_level; i++)
- {
- fprintf(fp, " ");
- }
- }
- }
- pc ++;
- }
- }
- void
- XMLConfig::_AppendPropToFile(FILE* fp, XMLConfigString level,
- int indent_per_level,
- IHXRegistry2* hxreg,
- const char* pBase)
- {
- /*
- * Indent a proper amount.
- */
- INT32 i;
- IHXBuffer* pBuf = 0;
- _IndentFile(fp, indent_per_level, level, pBase);
- HXPropType type = hxreg->GetTypeByName(level.CharStar());
- switch (type)
- {
- case PT_COMPOSITE:
- fprintf(fp, "<List Name="%s">n", level.Top());
- IHXValues* pValues;
- if (HXR_OK == hxreg->GetPropListByName(level.CharStar(),
- pValues) && pValues)
- {
- HX_RESULT res;
- UINT32 ul;
- const char* pName;
- res = pValues->GetFirstPropertyULONG32(pName, ul);
- while (res == HXR_OK)
- {
- const char* pc = pName + strlen(pName);
- while (pc > pName)
- {
- pc--;
- if (*pc == '.')
- {
- pc++;
- level.AddLevel(pc);
- _AppendPropToFile(fp, level, indent_per_level, hxreg, pBase);
- level.RemoveLevel();
- res = pValues->GetNextPropertyULONG32(pName, ul);
- break;
- }
- }
- }
- pValues->Release();
- }
- _IndentFile(fp, indent_per_level, level, pBase);
- fprintf(fp, "</List>n");
- break;
- case PT_INTEGER:
- if (HXR_OK == hxreg->GetIntByName(level.CharStar(), i))
- {
- fprintf(fp, "<Var %s="%ld"/>n", level.Top(),
- i);
- }
- break;
- case PT_STRING:
- if (HXR_OK == hxreg->GetStrByName(level.CharStar(), pBuf)
- && pBuf)
- {
- fprintf(fp, "<Var %s="%s"/>n", level.Top(),
- (const char*)pBuf->GetBuffer());
- pBuf->Release();
- pBuf = 0;
- }
- break;
- }
- }
- int
- XMLConfig::_PropExists(XMLConfigString* p, IHXRegistry2* preg)
- {
- return (preg->GetPropStatusByName(p->CharStar()) == HXR_OK) ? TRUE : FALSE;
- }
- /*
- * IHXRegConfig::WriteKey
- */
- STDMETHODIMP
- XMLConfig::WriteKey(const char* pKeyName)
- {
- /*
- * If there is a filename then we got it from a file.
- */
- if (m_filename)
- {
- WriteToFile(pKeyName, m_filename);
- return HXR_OK;
- }
- HX_ASSERT(0);
- return HXR_FAIL;
- }
- HX_RESULT
- XMLConfig::Reconfigure(IHXReconfigServerResponse* pResp)
- {
- if (m_pReconfigureResponse)
- {
- return HXR_UNEXPECTED;
- }
- m_pReconfigureResponse = pResp;
- m_pReconfigureResponse->AddRef();
- /*
- * If they started from a config file, then reload
- * from the config file.
- */
- if (m_filename)
- {
- return Reconfigure(m_filename);
- }
- /*
- * If we got here there was a booboo
- */
- m_pReconfigureResponse->ReconfigServerDone(HXR_OK, 0, 0);
- m_pReconfigureResponse->Release();
- m_pReconfigureResponse = 0;
- return HXR_OK;
- }
- HX_RESULT
- XMLConfig::Reconfigure(const char* pFileName)
- {
- if (!pFileName)
- {
- return HXR_FAIL;
- }
- FILE* fp = fopen(pFileName, "r");
- if (!fp)
- {
- return HXR_FAIL;
- }
- /*
- * Pretend that there is one outstanding just to keep
- * the done methods from getting called, seeing a 0,
- * and sending the response until the end of this
- * func.
- */
- m_ActiveSetsOutstanding++;
- const char* pKeyName = "config";
- int l = 0;
- BOOL filedone = 0;
- XMLTag* tag = 0;
- CBigByteQueue queue(MAX_TAG_SIZE);
- XMLParser parser;
- HX_RESULT hResult = HXR_OK;
- /*
- * Files are all aready. Now we need to build our config levels list.
- */
- CHXSimpleList levlist;
- /*
- * Add for level 0.
- */
- CHXSimpleList* pNewList = new CHXSimpleList;
- IHXValues* pValues = 0;
- _AddPropsToList(pNewList, pKeyName, m_pRegistry);
- XMLConfigString curr_level;
- curr_level.AddLevel(pKeyName);
- // read the config file into the byte queue
- INT32 nBufSize = 16384;
- BYTE* pBuf = new BYTE[nBufSize];
- while (!filedone && hResult == HXR_OK)
- {
- l = fread(pBuf, 1, nBufSize, fp);
- if (l > 0)
- {
- if (!queue.EnQueue(pBuf, l))
- {
- if (!queue.Grow(l))
- {
- ERRMSG(m_pMessages,
- "error expanding data structure while parsing %s",
- pFileName);
- hResult = HXR_FAIL;
- }
- if (!queue.EnQueue(pBuf, l))
- {
- ERRMSG(m_pMessages,
- "unknown error while parsing %s",
- pFileName);
- hResult = HXR_FAIL;
- }
- }
- }
- else
- {
- filedone = TRUE;
- }
- }
- UINT32 bytesUsed=0;
- UINT32 bytesAvail=0;
- BYTE* p=0;
- while (hResult == HXR_OK && (bytesAvail = queue.GetQueuedItemCount()) > 0)
- {
- if (bytesAvail > nBufSize)
- {
- HX_VECTOR_DELETE(pBuf);
- pBuf = new BYTE[bytesAvail];
- nBufSize = bytesAvail;
- }
- p = pBuf;
- queue.DeQueue(pBuf, bytesAvail);
- bytesUsed = bytesAvail;
- HX_DELETE(tag);
- XMLParseResult res = parser.Parse((const char*&)p, bytesAvail, tag);
- queue.EnQueue(p, bytesAvail - (p - pBuf));
- switch(res)
- {
- case XMLPNoClose:
- // A tag opener was found, but no closer yet.
- if (filedone)
- {
- pBuf[bytesAvail - 1] = ' ';
- if (bytesAvail > MAX_ERROR_CHARS)
- {
- pBuf[MAX_ERROR_CHARS - 1] = ' ';
- }
- ERRMSG(m_pMessages,
- "%s: Missing close for tag %s...", m_filename, pBuf);
- hResult = HXR_FAIL;
- }
- break;
- case XMLPNoTagType:
- *p = 0;
- ERRMSG(m_pMessages,
- "%s: Badly formed tag %s", m_filename, pBuf);
- break;
- case XMLPBadAttribute:
- *p = 0;
- ERRMSG(m_pMessages,
- "%s: Badly formed attribute in %s", m_filename,
- pBuf);
- break;
- case XMLPPlainText:
- break;
- case XMLPBadEndTag:
- *p = 0;
- ERRMSG(m_pMessages,
- "%s: Unexpected tag %s", m_filename, pBuf);
- break;
- case XMLPComment:
- break;
- case XMLPDirective:
- // A directive. We don't handle any yet.
- break;
- case XMLPProcInst:
- // A processing Instruction, whee!
- break;
- case XMLPTag:
- {
- if(Expand(tag, &queue))
- break;
- if(tag->m_need_close)
- {
- if(strcasecmp(tag->m_name, "list") == 0)
- {
- const char* name = tag->get_attribute("name");
- if(!name)
- {
- ERRMSG(m_pMessages,
- "%s: List tag requires a name attribute",
- m_filename);
- // Process anyway, give it a dummy name
- name = "XXXBADLIST";
- }
- /*
- * Remove current tag from list, push current list,
- * create new list, add next level's props.
- */
- _RemovePropFromList(pNewList, name);
- curr_level.AddLevel(name);
- levlist.AddHead((void*)pNewList);
- pNewList = new CHXSimpleList;
- _AddPropsToList(pNewList, curr_level.CharStar(), m_pRegistry);
-
- }
- }
- else if(tag->m_type != XMLEndTag)
- {
- const char* name = tag->get_attribute("name");
- const char* value = tag->get_attribute("value");
- if (name)
- {
- curr_level.AddLevel(name);
- _RemovePropFromList(pNewList, name);
- /*
- * Here we need to try to set that value.
- */
- _ResetProp(&curr_level, value, m_pRegistry);
- curr_level.RemoveLevel();
- }
- }
- else
- {
- // An End Tag
- /*
- * Here we need to try to delete everything that
- * was not in the file.
- */
- if(strcasecmp(tag->m_name, "list") == 0)
- {
- _HandlePropsRemovedFromFile(
- &curr_level, pNewList,
- m_pRegistry);
- curr_level.RemoveLevel();
- delete pNewList;
- pNewList = (CHXSimpleList*)levlist.RemoveHead();
- }
- }
- break;
- }
- }
- }
-
- _HandlePropsRemovedFromFile(&curr_level, pNewList, m_pRegistry);
- // cleanup
- if (fp) fclose(fp);
- HX_DELETE(tag);
- HX_DELETE(pNewList);
- HX_VECTOR_DELETE(pBuf);
- // send reconfig response
- m_ActiveSetsOutstanding--;
- MaybeSendReconfigResponse();
- return hResult;
- }
- #ifdef _WIN32
- HX_RESULT
- XMLConfig::ReconfigureFromReg(const char* pKeyname)
- {
- HX_ASSERT(pKeyname && strlen(pKeyname));
- /*
- * This should be a duplication of the above loop just using
- * the registry instead of a file.
- */
- /*
- * Pretend that there is one outstanding just to keep
- * the done methods from getting called, seeing a 0,
- * and sending the response until the end of this
- * func.
- */
- m_ActiveSetsOutstanding++;
- CHXSimpleList levlist;
- CHXSimpleList indexlist;
- int curr_index = 0;
- UINT32 ulBufLen = 512;
- UINT32 ulRealBufLen = 512;
- char* pRegBuf = new char[512];
- UINT32 ulBufLen2 = 256;
- UINT32 ulRealBufLen2 = 256;
- char* pRegBuf2 = new char[256];
- UINT32 ulBufLen3 = 256;
- UINT32 ulRealBufLen3 = 256;
- char* pRegBuf3 = new char[256];
- FILETIME msbs;
- /*
- * Add for level 0.
- */
- CHXSimpleList* pNewList = new CHXSimpleList;
- IHXValues* pValues = 0;
- _AddPropsToList(pNewList, "Config", m_pRegistry);
- XMLConfigString curr_level;
- curr_level.AddLevel("Config");
- char* pRegBase = new char[512];
- memset(pRegBase, 0, 512);
- SafeSprintf(pRegBase, 512, "Software\RealNetworks\%s\%d.%d\",
- m_szServerversion, m_ulMajor, m_ulMinor);
- UINT32 ulRegBase = strlen(pRegBase) + 1;
- HKEY hKey=0;
- LONG ret=0;
- BOOL bDone = 0;
- char* pc=0;
- /*
- * While we are not done...
- */
- while (!bDone)
- {
- pc = pRegBase + ulRegBase;
- SafeStrCpy(pc, curr_level.CharStar(), 512-ulRegBase);
- while (pc < pRegBase + 512 && *pc)
- {
- if (*pc == '.')
- {
- *pc = '\';
- }
- pc++;
- }
- ret = RegOpenKeyEx(HKEY_CLASSES_ROOT, pRegBase, 0, KEY_READ, &hKey);
- if (ret != ERROR_SUCCESS)
- {
- //XXXPM fix this
- HX_ASSERT(0);
- }
- ulBufLen = ulRealBufLen;
- //XXXPM handle buffer too small
- ret = RegEnumKeyEx(hKey, curr_index,
- pRegBuf, &ulBufLen, 0, NULL, NULL, &msbs);
- curr_index++;
- /*
- * If it is a composite...
- */
- if (ret == ERROR_SUCCESS)
- {
- const char* name = pRegBuf;
- _RemovePropFromList(pNewList, name);
- curr_level.AddLevel(name);
- levlist.AddHead((void*)pNewList);
- indexlist.AddHead((void*)curr_index);
- curr_index = 0;
- pNewList = new CHXSimpleList;
- _AddPropsToList(pNewList, curr_level.CharStar(), m_pRegistry);
- }
- /*
- * It is a non composite value, so we need to get that value.
- */
- else
- {
- const char* name = pRegBuf;
- const char* value = 0;
- ulBufLen2 = ulRealBufLen2;
- ulBufLen3 = ulRealBufLen3;
- DWORD dwType;
- //XXXPM handle buffer too small
- ret = RegEnumValue(hKey, 0, pRegBuf2, &ulBufLen2, 0, &dwType,
- (unsigned char*)pRegBuf3, &ulBufLen3);
- if (ret == ERROR_SUCCESS)
- {
- value = pRegBuf3;
- _ResetProp(&curr_level, value, m_pRegistry);
- curr_level.RemoveLevel();
- delete pNewList;
- pNewList = (CHXSimpleList*)levlist.RemoveHead();
- curr_index = (int)indexlist.RemoveHead();
- }
- else
- {
- /*
- * Closing a composite.
- */
- _HandlePropsRemovedFromFile(&curr_level, pNewList, m_pRegistry);
- curr_level.RemoveLevel();
- delete pNewList;
- if (!levlist.IsEmpty())
- {
- pNewList = (CHXSimpleList*)levlist.RemoveHead();
- curr_index = (int)indexlist.RemoveHead();
- }
- else
- {
- pNewList = 0;
- bDone = 1;
- }
- }
- }
- RegCloseKey(hKey);
- }
- delete[] pRegBase;
- delete[] pRegBuf;
- delete[] pRegBuf2;
- delete[] pRegBuf3;
- m_ActiveSetsOutstanding--;
- MaybeSendReconfigResponse();
- return HXR_OK;
- }
- #endif
- HX_RESULT
- XMLConfig::_ResetProp(XMLConfigString* plevel, const char* value, IHXRegistry2* preg)
- {
- HX_RESULT res = HXR_FAIL;
- IHXActiveRegistry* pActiveReg = 0;
- LONG32 ulCurrent;
- LONG32 ulNew;
- preg->QueryInterface(IID_IHXActiveRegistry,
- (void**)&pActiveReg);
- if (pActiveReg == 0)
- {
- return HXR_FAIL;
- }
- /*
- * If the prop exists, then figure out the type.
- */
- if (_PropExists(plevel, preg))
- {
- HXPropType type;
- type = preg->GetTypeByName(plevel->CharStar());
- switch (type)
- {
- case PT_INTEGER:
- ulCurrent = 0;
- ulNew = atoi(value);
- /*
- * If it is an int and we are not changing its value, then say ok and
- * exit.
- */
- preg->GetIntByName(plevel->CharStar(),
- ulCurrent);
- if (ulCurrent == ulNew)
- {
- res = HXR_OK;
- goto done;
- }
- /*
- * Try to set it by hand first.
- */
- res = preg->SetIntByName(plevel->CharStar(),
- atoi(value));
- /*
- * If it failed because it was active, then use the active reg
- * to set it and add it to our outstanding actives count.
- */
- if (res == HXR_PROP_ACTIVE)
- {
- m_ActiveSetsOutstanding ++;
- res = pActiveReg->SetActiveInt(plevel->CharStar(),
- ulNew, this);
- if (res != HXR_OK)
- {
- m_ActiveSetsOutstanding --;
- }
- }
- /*
- * res should be set for good by now.
- */
- goto done;
-
- case PT_STRING:
- IHXBuffer* pCurrent = 0;
- /*
- * See if we are changing this string value at all.
- */
- preg->GetStrByName(plevel->CharStar(),
- pCurrent);
- if (pCurrent)
- {
- /*
- * If we are not changing it at all then say ok and exit.
- */
- if (!strcmp((const char*)pCurrent->GetBuffer(),
- value))
- {
- pCurrent->Release();
- res = HXR_OK;
- goto done;
- }
- pCurrent->Release();
- }
- /*
- * We are changing it so get a new buffer and set it.
- */
- IHXBuffer* pBuffer = new CHXBuffer();
- pBuffer->AddRef();
- pBuffer->Set((const unsigned char*)value, strlen(value) + 1);
- res = preg->SetStrByName(plevel->CharStar(),
- pBuffer);
- /*
- * If we failed to set it because it is active, then use the
- * active registry and add to our outstanding actives count.
- */
- if (res == HXR_PROP_ACTIVE)
- {
- m_ActiveSetsOutstanding++;
- res = pActiveReg->SetActiveStr(plevel->CharStar(),
- pBuffer, this);
- if (res != HXR_OK)
- {
- m_ActiveSetsOutstanding --;
- }
- }
- pBuffer->Release();
- goto done;
- }
-
- }
- else
- {
- /*
- * This is the case where this prop was not already there,
- * so figure out the type from the data.
- */
- BOOL bIsNum = TRUE;
- const char* pc = value;
- while(*pc)
- {
- if (*pc < '0' || *pc > '9')
- {
- bIsNum = FALSE;
- break;
- }
- pc++;
- }
- if (pc == value)
- {
- bIsNum = FALSE;
- }
- if (bIsNum)
- {
- /*
- * It should be an Integer type so attempt to Set it through the
- * active reg. (This acts like an add through the active reg. Could
- * have tried to add it by hand first, but didn't.
- */
- m_ActiveSetsOutstanding++;
- res = pActiveReg->SetActiveInt(plevel->CharStar(),
- atoi(value), this);
- if (res != HXR_OK)
- {
- m_ActiveSetsOutstanding--;
- }
- }
- else
- {
- /*
- * It should be a string type. We will just try to do it through active.
- * (see last comment).
- */
- IHXBuffer* pBuffer = new CHXBuffer();
- pBuffer->AddRef();
- pBuffer->Set((const unsigned char*)value,
- strlen(value) + 1);
- m_ActiveSetsOutstanding++;
- res = pActiveReg->SetActiveStr(plevel->CharStar(),
- pBuffer, this);
- if (res != HXR_OK)
- {
- m_ActiveSetsOutstanding--;
- }
- pBuffer->Release();
- }
- }
- done:;
- pActiveReg->Release();
- return res;
- }
- /************************************************************************
- * IHXActivePropUserResponse stuff.
- *
- * Called with status result on completion of set request.
- */
- STDMETHODIMP
- XMLConfig::SetActiveIntDone(HX_RESULT res,
- const char* pName,
- UINT32 ul,
- IHXBuffer* pInfo[],
- UINT32 ulNumInfo)
- {
- m_ActiveSetsOutstanding--;
- MaybeSendReconfigResponse();
- return HXR_OK;
- }
- STDMETHODIMP
- XMLConfig::SetActiveStrDone(HX_RESULT res,
- const char* pName,
- IHXBuffer* pBuffer,
- IHXBuffer* pInfo[],
- UINT32 ulNumInfo)
- {
- m_ActiveSetsOutstanding--;
- MaybeSendReconfigResponse();
- return HXR_OK;
- }
- STDMETHODIMP
- XMLConfig::SetActiveBufDone(HX_RESULT res,
- const char* pName,
- IHXBuffer* pBuffer,
- IHXBuffer* pInfo[],
- UINT32 ulNumInfo)
- {
- m_ActiveSetsOutstanding--;
- MaybeSendReconfigResponse();
- return HXR_OK;
- }
- STDMETHODIMP
- XMLConfig::DeleteActivePropDone(HX_RESULT res,
- const char* pName,
- IHXBuffer* pInfo[],
- UINT32 ulNumInfo)
- {
- m_ActiveSetsOutstanding--;
- MaybeSendReconfigResponse();
- return HXR_OK;
- }
- void
- XMLConfig::MaybeSendReconfigResponse()
- {
- /*
- * If everything has not happened yet,
- * then bail.
- */
- if (m_ActiveSetsOutstanding)
- {
- return;
- }
- m_pReconfigureResponse->ReconfigServerDone(HXR_OK,
- 0, 0);
- m_pReconfigureResponse->Release();
- m_pReconfigureResponse = 0;
- }
- void
- XMLConfig::_HandlePropsRemovedFromFile(XMLConfigString* plevel,
- CHXSimpleList* pList,
- IHXRegistry2* preg)
- {
- XMLPropInfo* pInfo;
- while (!pList->IsEmpty())
- {
- pInfo = (XMLPropInfo*)pList->RemoveHead();
- plevel->AddLevel(pInfo->m_pName);
- switch (pInfo->m_Type)
- {
- case PT_STRING:
- {
- IHXBuffer* pval;
- pval = _GetDefaultValString(
- plevel->CharStar(), preg);
- if (!pval)
- {
- if (!preg->DeleteByName(
- plevel->CharStar()))
- {
- IHXActiveRegistry* pActiveReg = 0;
- preg->QueryInterface(IID_IHXActiveRegistry,
- (void**)&pActiveReg);
- if (pActiveReg)
- {
- m_ActiveSetsOutstanding++;
- if (HXR_OK != pActiveReg->DeleteActiveProp(
- plevel->CharStar(),
- this))
- {
- m_ActiveSetsOutstanding--;
- }
- pActiveReg->Release();
- }
- }
- }
- else
- {
- if (HXR_PROP_ACTIVE == preg->SetStrByName(plevel->CharStar(),
- pval))
- {
- IHXActiveRegistry* pActiveReg = 0;
- preg->QueryInterface(IID_IHXActiveRegistry,
- (void**)&pActiveReg);
- if (pActiveReg)
- {
- m_ActiveSetsOutstanding++;
- if (HXR_OK != pActiveReg->SetActiveStr(
- plevel->CharStar(), pval,
- this))
- {
- m_ActiveSetsOutstanding--;
- }
- pActiveReg->Release();
- }
- }
- pval->Release();
- }
- }
- break;
- case PT_INTEGER:
- {
- INT32 i;
- if (!_GetDefaultValInt(
- plevel->CharStar(),
- &i, preg))
- {
- if (!preg->DeleteByName(
- plevel->CharStar()))
- {
- IHXActiveRegistry* pActiveReg = 0;
- preg->QueryInterface(IID_IHXActiveRegistry,
- (void**)&pActiveReg);
- if (pActiveReg)
- {
- m_ActiveSetsOutstanding++;
- if (HXR_OK != pActiveReg->DeleteActiveProp(
- plevel->CharStar(),
- this))
- {
- m_ActiveSetsOutstanding--;
- }
- pActiveReg->Release();
- }
- }
- }
- else
- {
- if (HXR_PROP_ACTIVE == preg->SetIntByName(plevel->CharStar(),
- i))
- {
- IHXActiveRegistry* pActiveReg = 0;
- preg->QueryInterface(IID_IHXActiveRegistry,
- (void**)&pActiveReg);
- if (pActiveReg)
- {
- m_ActiveSetsOutstanding++;
- if (HXR_OK != pActiveReg->SetActiveInt(
- plevel->CharStar(),
- i, this))
- {
- m_ActiveSetsOutstanding--;
- }
- pActiveReg->Release();
- }
- }
- }
- }
- break;
- case PT_COMPOSITE:
- ///XXXPM there will be a bug here if we have default vars in sub lists and
- //we try and delete the list. The default vals will not be found here.
- IHXActiveRegistry* pActiveReg = 0;
- preg->QueryInterface(IID_IHXActiveRegistry,
- (void**)&pActiveReg);
- if (pActiveReg)
- {
- m_ActiveSetsOutstanding++;
- HX_RESULT res;
- res = pActiveReg->DeleteActiveProp(plevel->CharStar(),
- this);
- if (res != HXR_OK)
- {
- m_ActiveSetsOutstanding--;
- }
- pActiveReg->Release();
- }
- break;
- }
- plevel->RemoveLevel();
- delete pInfo;
- }
-
- }
- IHXBuffer*
- XMLConfig::_GetDefaultValString(const char* pProp,
- IHXRegistry2* preg)
- {
- IHXBuffer* pBuffer = 0;
- char configdefaults[256]; /* Flawfinder: ignore */
- HX_ASSERT(strlen(pProp) < 220);
- SafeSprintf(configdefaults, 256, "configdefaults%s", strchr(pProp, '.'));
- preg->GetStrByName(configdefaults, pBuffer);
- return pBuffer;
- }
- int
- XMLConfig::_GetDefaultValInt(const char* pProp, INT32* pOut,
- IHXRegistry2* preg)
- {
- char configdefaults[256]; /* Flawfinder: ignore */
- HX_ASSERT(strlen(pProp) < 220);
- SafeSprintf(configdefaults, 256, "configdefaults%s", strchr(pProp, '.'));
- if (HXR_OK != preg->GetIntByName(configdefaults, *pOut))
- {
- return 0;
- }
- return 1;
- }