libupnp/ixml/src/document.c

593 lines
13 KiB
C

/*******************************************************************************
*
* Copyright (c) 2000-2003 Intel Corporation
* All rights reserved.
* Copyright (c) 2012 France Telecom All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************/
/*!
* \file
*/
#include "ixmldebug.h"
#include "ixmlparser.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void ixmlDocument_init(IXML_Document *doc)
{
memset(doc, 0, sizeof(IXML_Document));
}
void ixmlDocument_free(IXML_Document *doc)
{
if (doc != NULL) {
ixmlNode_free((IXML_Node *)doc);
}
}
/*!
* When this function is called first time, nodeptr is the root of the subtree,
* so it is not necessay to do two steps recursion.
*
* Internal function called by ixmlDocument_importNode
*/
static void ixmlDocument_setOwnerDocument(
/*! [in] The document node. */
IXML_Document *doc,
/*! [in] \todo documentation. */
IXML_Node *nodeptr)
{
if (nodeptr != NULL) {
nodeptr->ownerDocument = doc;
ixmlDocument_setOwnerDocument(
doc, ixmlNode_getFirstChild(nodeptr));
ixmlDocument_setOwnerDocument(
doc, ixmlNode_getNextSibling(nodeptr));
}
}
int ixmlDocument_importNode(
IXML_Document *doc,
IXML_Node *importNode,
BOOL deep,
IXML_Node **rtNode)
{
unsigned short nodeType;
IXML_Node *newNode;
*rtNode = NULL;
if (doc == NULL || importNode == NULL) {
return IXML_INVALID_PARAMETER;
}
nodeType = ixmlNode_getNodeType(importNode);
if (nodeType == eDOCUMENT_NODE) {
return IXML_NOT_SUPPORTED_ERR;
}
newNode = ixmlNode_cloneNode(importNode, deep);
if (newNode == NULL) {
return IXML_FAILED;
}
ixmlDocument_setOwnerDocument(doc, newNode);
*rtNode = newNode;
return IXML_SUCCESS;
}
int ixmlDocument_createElementEx(
IXML_Document *doc,
const DOMString tagName,
IXML_Element **rtElement)
{
int errCode = IXML_SUCCESS;
IXML_Element *newElement = NULL;
if (doc == NULL || tagName == NULL) {
errCode = IXML_INVALID_PARAMETER;
goto ErrorHandler;
}
newElement = (IXML_Element *) malloc(sizeof(IXML_Element));
if (newElement == NULL) {
errCode = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler;
}
ixmlElement_init(newElement);
newElement->tagName = strdup(tagName);
if (newElement->tagName == NULL) {
ixmlElement_free(newElement);
newElement = NULL;
errCode = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler;
}
/* set the node fields */
newElement->n.nodeType = eELEMENT_NODE;
newElement->n.nodeName = strdup(tagName);
if (newElement->n.nodeName == NULL) {
free(newElement->tagName);
ixmlElement_free(newElement);
newElement = NULL;
errCode = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler;
}
newElement->n.ownerDocument = doc;
ErrorHandler:
*rtElement = newElement;
return errCode;
}
IXML_Element *ixmlDocument_createElement(
IXML_Document *doc,
const DOMString tagName)
{
IXML_Element *newElement = NULL;
int ret = IXML_SUCCESS;
ret = ixmlDocument_createElementEx(doc, tagName, &newElement);
if (ret != IXML_SUCCESS) {
IxmlPrintf(__FILE__, __LINE__, "ixmlDocument_createElement",
"Error %d\n", ret);
return NULL;
}
return newElement;
}
int ixmlDocument_createDocumentEx(IXML_Document **rtDoc)
{
IXML_Document *doc;
int errCode = IXML_SUCCESS;
doc = NULL;
doc = (IXML_Document *)malloc(sizeof (IXML_Document));
if (doc == NULL) {
errCode = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler;
}
ixmlDocument_init(doc);
doc->n.nodeName = strdup((const char*)DOCUMENTNODENAME);
if (doc->n.nodeName == NULL) {
ixmlDocument_free(doc);
doc = NULL;
errCode = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler;
}
doc->n.nodeType = eDOCUMENT_NODE;
doc->n.ownerDocument = doc;
ErrorHandler:
*rtDoc = doc;
return errCode;
}
IXML_Document *ixmlDocument_createDocument()
{
IXML_Document *doc = NULL;
ixmlDocument_createDocumentEx(&doc);
return doc;
}
int ixmlDocument_createTextNodeEx(
IXML_Document *doc,
const DOMString data,
IXML_Node **textNode)
{
IXML_Node *returnNode;
int rc = IXML_SUCCESS;
returnNode = NULL;
if (doc == NULL || data == NULL) {
rc = IXML_INVALID_PARAMETER;
goto ErrorHandler;
}
returnNode = (IXML_Node *)malloc(sizeof (IXML_Node));
if (returnNode == NULL) {
rc = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler;
}
/* initialize the node */
ixmlNode_init(returnNode);
returnNode->nodeName = strdup((const char*)TEXTNODENAME);
if (returnNode->nodeName == NULL) {
ixmlNode_free(returnNode);
returnNode = NULL;
rc = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler;
}
/* add in node value */
if (data != NULL) {
returnNode->nodeValue = strdup(data);
if (returnNode->nodeValue == NULL) {
ixmlNode_free(returnNode);
returnNode = NULL;
rc = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler;
}
}
returnNode->nodeType = eTEXT_NODE;
returnNode->ownerDocument = doc;
ErrorHandler:
*textNode = returnNode;
return rc;
}
IXML_Node *ixmlDocument_createTextNode(
IXML_Document *doc,
const DOMString data)
{
IXML_Node *returnNode = NULL;
ixmlDocument_createTextNodeEx(doc, data, &returnNode);
return returnNode;
}
int ixmlDocument_createAttributeEx(
IXML_Document *doc,
const DOMString name,
IXML_Attr **rtAttr)
{
IXML_Attr *attrNode = NULL;
int errCode = IXML_SUCCESS;
attrNode = (IXML_Attr *)malloc(sizeof (IXML_Attr));
if (attrNode == NULL) {
errCode = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler;
}
if (doc == NULL || name == NULL) {
ixmlAttr_free(attrNode);
attrNode = NULL;
errCode = IXML_INVALID_PARAMETER;
goto ErrorHandler;
}
ixmlAttr_init(attrNode);
attrNode->n.nodeType = eATTRIBUTE_NODE;
/* set the node fields */
attrNode->n.nodeName = strdup(name);
if (attrNode->n.nodeName == NULL) {
ixmlAttr_free(attrNode);
attrNode = NULL;
errCode = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler;
}
attrNode->n.ownerDocument = doc;
ErrorHandler:
*rtAttr = attrNode;
return errCode;
}
IXML_Attr *ixmlDocument_createAttribute(
IXML_Document *doc,
const DOMString name)
{
IXML_Attr *attrNode = NULL;
if(ixmlDocument_createAttributeEx(doc, name, &attrNode) != IXML_SUCCESS)
return NULL;
return attrNode;
}
int ixmlDocument_createAttributeNSEx(
IXML_Document *doc,
const DOMString namespaceURI,
const DOMString qualifiedName,
IXML_Attr **rtAttr )
{
IXML_Attr *attrNode = NULL;
int errCode = IXML_SUCCESS;
if (doc == NULL || namespaceURI == NULL || qualifiedName == NULL) {
errCode = IXML_INVALID_PARAMETER;
goto ErrorHandler;
}
errCode =
ixmlDocument_createAttributeEx(doc, qualifiedName, &attrNode);
if (errCode != IXML_SUCCESS) {
goto ErrorHandler;
}
/* set the namespaceURI field */
attrNode->n.namespaceURI = strdup(namespaceURI);
if (attrNode->n.namespaceURI == NULL) {
ixmlAttr_free(attrNode);
attrNode = NULL;
errCode = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler;
}
/* set the localName and prefix */
errCode =
ixmlNode_setNodeName((IXML_Node *)attrNode, qualifiedName);
if (errCode != IXML_SUCCESS) {
ixmlAttr_free(attrNode);
attrNode = NULL;
goto ErrorHandler;
}
ErrorHandler:
*rtAttr = attrNode;
return errCode;
}
IXML_Attr *ixmlDocument_createAttributeNS(
IXML_Document *doc,
const DOMString namespaceURI,
const DOMString qualifiedName)
{
IXML_Attr *attrNode = NULL;
ixmlDocument_createAttributeNSEx(
doc, namespaceURI, qualifiedName, &attrNode);
return attrNode;
}
int ixmlDocument_createCDATASectionEx(
IXML_Document *doc,
const DOMString data,
IXML_CDATASection **rtCD)
{
int errCode = IXML_SUCCESS;
IXML_CDATASection *cDSectionNode = NULL;
if(doc == NULL || data == NULL) {
errCode = IXML_INVALID_PARAMETER;
goto ErrorHandler;
}
cDSectionNode = (IXML_CDATASection *)malloc(sizeof (IXML_CDATASection));
if (cDSectionNode == NULL) {
errCode = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler;
}
ixmlCDATASection_init(cDSectionNode);
cDSectionNode->n.nodeType = eCDATA_SECTION_NODE;
cDSectionNode->n.nodeName = strdup((const char*)CDATANODENAME);
if (cDSectionNode->n.nodeName == NULL) {
ixmlCDATASection_free(cDSectionNode);
cDSectionNode = NULL;
errCode = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler;
}
cDSectionNode->n.nodeValue = strdup(data);
if (cDSectionNode->n.nodeValue == NULL) {
ixmlCDATASection_free( cDSectionNode );
cDSectionNode = NULL;
errCode = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler;
}
cDSectionNode->n.ownerDocument = doc;
ErrorHandler:
*rtCD = cDSectionNode;
return errCode;
}
IXML_CDATASection *ixmlDocument_createCDATASection(
IXML_Document *doc,
const DOMString data)
{
IXML_CDATASection *cDSectionNode = NULL;
ixmlDocument_createCDATASectionEx(doc, data, &cDSectionNode);
return cDSectionNode;
}
int ixmlDocument_createElementNSEx(
IXML_Document *doc,
const DOMString namespaceURI,
const DOMString qualifiedName,
IXML_Element **rtElement)
{
IXML_Element *newElement = NULL;
int ret = IXML_SUCCESS;
int line = 0;
if (doc == NULL || namespaceURI == NULL || qualifiedName == NULL) {
line = __LINE__;
ret = IXML_INVALID_PARAMETER;
goto ErrorHandler;
}
ret = ixmlDocument_createElementEx(doc, qualifiedName, &newElement);
if (ret != IXML_SUCCESS) {
line = __LINE__;
goto ErrorHandler;
}
/* set the namespaceURI field */
newElement->n.namespaceURI = strdup(namespaceURI);
if (newElement->n.namespaceURI == NULL) {
line = __LINE__;
ixmlElement_free(newElement);
newElement = NULL;
ret = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler;
}
/* set the localName and prefix */
ret = ixmlNode_setNodeName((IXML_Node *)newElement, qualifiedName);
if (ret != IXML_SUCCESS) {
line = __LINE__;
ixmlElement_free(newElement);
newElement = NULL;
ret = IXML_INSUFFICIENT_MEMORY;
goto ErrorHandler;
}
newElement->n.nodeValue = NULL;
ErrorHandler:
*rtElement = newElement;
if (ret != IXML_SUCCESS) {
IxmlPrintf(__FILE__, line, "ixmlDocument_createElementNSEx", "Error %d\n", ret);
}
return ret;
}
IXML_Element *ixmlDocument_createElementNS(
IXML_Document *doc,
const DOMString namespaceURI,
const DOMString qualifiedName)
{
IXML_Element *newElement = NULL;
ixmlDocument_createElementNSEx(doc, namespaceURI, qualifiedName, &newElement);
return newElement;
}
IXML_NodeList *ixmlDocument_getElementsByTagName(
IXML_Document *doc,
const DOMString tagName)
{
IXML_NodeList *returnNodeList = NULL;
if (doc == NULL || tagName == NULL) {
return NULL;
}
ixmlNode_getElementsByTagName((IXML_Node *)doc, tagName, &returnNodeList);
return returnNodeList;
}
IXML_NodeList *ixmlDocument_getElementsByTagNameNS(
IXML_Document *doc,
const DOMString namespaceURI,
const DOMString localName)
{
IXML_NodeList *returnNodeList = NULL;
if (doc == NULL || namespaceURI == NULL || localName == NULL) {
return NULL;
}
ixmlNode_getElementsByTagNameNS(
(IXML_Node *)doc, namespaceURI, localName, &returnNodeList);
return returnNodeList;
}
IXML_Element *ixmlDocument_getElementById(
IXML_Document *doc,
const DOMString tagName)
{
IXML_Element *rtElement = NULL;
IXML_Node *nodeptr = (IXML_Node *)doc;
const char *name;
if (nodeptr == NULL || tagName == NULL) {
return rtElement;
}
if (ixmlNode_getNodeType(nodeptr) == eELEMENT_NODE) {
name = ixmlNode_getNodeName(nodeptr);
if (name == NULL) {
return rtElement;
}
if (strcmp(tagName, name) == 0) {
rtElement = (IXML_Element *)nodeptr;
return rtElement;
} else {
rtElement = ixmlDocument_getElementById(
(IXML_Document *)ixmlNode_getFirstChild(nodeptr),
tagName );
if (rtElement == NULL) {
rtElement = ixmlDocument_getElementById(
(IXML_Document *)ixmlNode_getNextSibling(nodeptr),
tagName);
}
}
} else {
rtElement = ixmlDocument_getElementById(
(IXML_Document *)ixmlNode_getFirstChild(nodeptr),
tagName);
if (rtElement == NULL) {
rtElement = ixmlDocument_getElementById(
(IXML_Document *)ixmlNode_getNextSibling(nodeptr),
tagName);
}
}
return rtElement;
}