xmlconfig.cpp

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

CPP
2,482
字号
    }
    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 = %ld\n", 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 = %s\n", 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 = %ld\n", 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] = '\0';
		    if (bytesAvail > MAX_ERROR_CHARS)
		    {
			pBuf[MAX_ERROR_CHARS - 1] = '\0';
		    }
		    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] = '\0';
                                }
				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] = '\0';
		    if (bytesAvail > MAX_ERROR_CHARS)
		    {
			pBuf[MAX_ERROR_CHARS - 1] = '\0';
		    }
		    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

⌨️ 快捷键说明

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