Пример #1
0
/*
*****************************************************************************
** FUNCTION NAME: createElementTextNode
**
** FUNCTION INPUTS:
**  @IXML_Element *parentElement: parent element
**  @char *name: tag name
**  @char *value: tag value
**
** FUNCTION DESCRIPTION
**   This function will create element with name and value, and add to parent
** element.
**
** FUNCTION OUTPUTS:
**   Returns IXML_Element pointer when success,on NULL on failed.
**
** HISTORY:
** 2008-7-2	Steven Leong	Created
*****************************************************************************
*/
IXML_Element* createElementTextNode(IXML_Element *parentElement, char *name, char *value)
{
	IXML_Element *element = NULL;
	IXML_Node *node = NULL;

	element = ixmlDocument_createElement(parentElement->n.ownerDocument, name);
	if(element == NULL){
		return NULL;
	}
	if(value != NULL){
		node = ixmlDocument_createTextNode(parentElement->n.ownerDocument, value);
		if(node == NULL){
			ixmlElement_free(element);
			return NULL;
		}
		if(ixmlNode_appendChild((IXML_Node *)element, node) != IXML_SUCCESS){
			ixmlElement_free(element);
			ixmlNode_free(node);
			return NULL;
		}
	}
	if(ixmlNode_appendChild((IXML_Node *)parentElement,(IXML_Node *)element)!=IXML_SUCCESS){
		ixmlElement_free(element);
		return NULL;
	}
	return element;
}
Пример #2
0
/************************************************************************
* Function : addToAction
*
* Parameters:
*	IN int response: flag to tell if the ActionDoc is for response
*		or request
*	INOUT IXML_Document **ActionDoc: request or response document
*	IN char *ActionName: Name of the action request or response
*	IN char *ServType: Service type
*	IN char * ArgName: Name of the argument
*	IN char * ArgValue: Value of the argument
*
* Description:
*	This function adds the argument in the action request or response.
* This function creates the action request or response if it is a first
* argument else it will add the argument in the document
*
* Returns: int
*	returns UPNP_E_SUCCESS if successful else returns appropriate error
***************************************************************************/
static int
addToAction( IN int response,
             INOUT IXML_Document ** ActionDoc,
             IN const char *ActionName,
             IN const char *ServType,
             IN const char *ArgName,
             IN const char *ArgValue )
{
    char *ActBuff = NULL;
    IXML_Node *node = NULL;
    IXML_Element *Ele = NULL;
    IXML_Node *Txt = NULL;
    int rc = 0;

    if( ActionName == NULL || ServType == NULL ) {
        return UPNP_E_INVALID_PARAM;
    }

    if( *ActionDoc == NULL ) {
        ActBuff = ( char * )malloc( HEADER_LENGTH );
        if( ActBuff == NULL ) {
            return UPNP_E_OUTOF_MEMORY;
        }

        if( response ) {
            sprintf( ActBuff,
                "<u:%sResponse xmlns:u=\"%s\">\r\n</u:%sResponse>",
                ActionName, ServType, ActionName );
        } else {
            sprintf( ActBuff,
                "<u:%s xmlns:u=\"%s\">\r\n</u:%s>",
                ActionName, ServType, ActionName );
        }

        rc = ixmlParseBufferEx( ActBuff, ActionDoc );
        free( ActBuff );
        if( rc != IXML_SUCCESS ) {
            if( rc == IXML_INSUFFICIENT_MEMORY ) {
                return UPNP_E_OUTOF_MEMORY;
            } else {
                return UPNP_E_INVALID_DESC;
            }
        }
    }

    if( ArgName != NULL /*&& ArgValue != NULL */  ) {
        node = ixmlNode_getFirstChild( ( IXML_Node * ) * ActionDoc );
        Ele = ixmlDocument_createElement( *ActionDoc, ArgName );
        if( ArgValue ) {
            Txt = ixmlDocument_createTextNode( *ActionDoc, ArgValue );
            ixmlNode_appendChild( ( IXML_Node * ) Ele, Txt );
        }

        ixmlNode_appendChild( node, ( IXML_Node * ) Ele );
    }

    return UPNP_E_SUCCESS;
}
Пример #3
0
struct xmlelement *xmldoc_new_topelement(struct xmldoc *doc,
                                         const char *elementName,
                                         const char *xmlns)
{
	struct xmlelement *result = NULL;
	assert(doc != NULL);
	assert(elementName != NULL);
	result = malloc(sizeof(*result));
#ifdef HAVE_LIBUPNP
	IXML_Element *element;
	if (xmlns) {
		element = ixmlDocument_createElementNS(doc->doc, xmlns,
                                                       elementName);
                ixmlElement_setAttribute(element, "xmlns",
                                         xmlns);
	} else {
		element = ixmlDocument_createElement(doc->doc, elementName);
	}
	ixmlNode_appendChild((IXML_Node *)(doc->doc),(IXML_Node *)element);
	result->element = element;
#else
#ifdef HAVE_LIBXML
	xmlNodePtr root_node;
	root_node = xmlNewNode(NULL, BAD_CAST "root");
	xmlDocSetRootElement(doc->doc, root_node);
#endif
#endif
	return result;
}
Пример #4
0
/*
*****************************************************************************
** FUNCTION NAME: ResponseCMD
**
** FUNCTION INPUTS:
**  @char *objID: object ID
**
** FUNCTION DESCRIPTION
**   This function will create response xml string without error
**
** FUNCTION OUTPUTS:
**   Returns ZAPP_SUCCESS on success, or ZAPP_FAILED on failed.
**
** HISTORY:
** 2008-7-2	Steven Leong	Created
*****************************************************************************
*/
int ResponseCMD(char *objID)
{
	IXML_Document *dom = NULL;
	IXML_Element *element = NULL;
	char *ptrXml = NULL;
	
	/* Package response xml */
	if((dom = ixmlDocument_createDocument()) == NULL)
		return ZAPP_FAILED;
	//ret node
	if((element = ixmlDocument_createElement(dom,"ret")) == NULL)
		goto errOut;
	ixmlNode_appendChild(&dom->n, (IXML_Node *)element);
	//err node
	if(createElementTextNode(element,"err","0") == NULL)
		goto errOut;
	//msg node
	if(createElementTextNode(element,"msg","") == NULL)
		goto errOut;
	//category node
	if(createElementTextNode(element,"objID", objID) == NULL)
		goto errOut;
	
	ptrXml = ixmlPrintDocument(dom);

	ZRipResponse(ptrXml);

	ZFREE(ptrXml);
	ixmlDocument_free(dom);
	return ZAPP_SUCCESS;

errOut:
	ixmlDocument_free(dom);
	return ZAPP_FAILED;
}
Пример #5
0
/**
 * Adds provided data to the storage.
 * @param checkPrefix If @a TRUE than all nodes with absolute URIs will be
 *                    checked to have /obix prefix.
 * @return @a 0 on success; error code otherwise.
 */
static int xmldb_putDOMHelper(IXML_Element* data, BOOL checkPrefix)
{
    IXML_Node* node = ixmlElement_getNode(data);
    IXML_Node* newNode = NULL;

    // shortcut for cleaning all resources if error occurs.
    void onError()
    {
        if (newNode != NULL)
        {
            ixmlNode_free(newNode);
        }
    }

    const char* href = checkNode(node, checkPrefix);
    if (href == NULL)
    {
        // error is already logged.
        onError();
        return -1;
    }

    // append node to the storage
    int error = ixmlDocument_importNode(_storage, node, TRUE, &newNode);
    if (error != IXML_SUCCESS)
    {
        log_warning("Unable to write to the storage (error %d).", error);
        onError();
        return error;
    }

    // look for available node with the same href
    IXML_Node* nodeInStorage = getNodeByHref(_storage, href, NULL);
    if (nodeInStorage != NULL)
    {
        log_warning("Unable to write to the storage: The object with the same "
                    "URI (%s) already exists.", href);
        onError();
        return -2;
        // overwrite existing node
        //ixmlNode_replaceChild(ixmlNode_getParentNode(nodeInStorage),
        //                      newNode,
        //                      nodeInStorage,
        //                      &nodeInStorage);
        //ixmlNode_free(nodeInStorage);
    }

    // append as a new node
    error = ixmlNode_appendChild(ixmlDocument_getNode(_storage), newNode);
    if (error != IXML_SUCCESS)
    {
        log_warning("Unable to write to the storage (error %d).", error);
        onError();
        return error;
    }

    return 0;
}
Пример #6
0
void xmlelement_add_element(struct xmldoc *doc,
			    struct xmlelement *parent,
			    struct xmlelement *child)
{
	assert(doc != NULL);
	assert(parent != NULL);
	assert(child != NULL);
	ixmlNode_appendChild((IXML_Node *) to_ielem(parent),
                             (IXML_Node *) to_ielem(child));
}
/*================================================================
*   ixmlNode_insertBefore
*       Inserts the node newChild before the existing child node refChild.
*       If refChild is null, insert newChild at the end of the list of
*       children. If the newChild is already in the tree, it is first
*       removed.   
*       External function.
*   Parameters:
*       newChild: the node to insert.
*   Returns:
*
*=================================================================*/
int
ixmlNode_insertBefore( IN IXML_Node * nodeptr,
                       IN IXML_Node * newChild,
                       IN IXML_Node * refChild )
{

    int ret = IXML_SUCCESS;

    if( ( nodeptr == NULL ) || ( newChild == NULL ) ) {
        return IXML_INVALID_PARAMETER;
    }
    // whether nodeptr allow children of the type of newChild 
    if( ixmlNode_allowChildren( nodeptr, newChild ) == FALSE ) {
        return IXML_HIERARCHY_REQUEST_ERR;
    }
    // or if newChild is one of nodeptr's ancestors
    if( ixmlNode_isAncestor( newChild, nodeptr ) == TRUE ) {
        return IXML_HIERARCHY_REQUEST_ERR;
    }
    // if newChild was created from a different document 
    if( nodeptr->ownerDocument != newChild->ownerDocument ) {
        return IXML_WRONG_DOCUMENT_ERR;
    }
    // if refChild is not a child of nodeptr
    if( ixmlNode_isParent( nodeptr, refChild ) == FALSE ) {
        return IXML_NOT_FOUND_ERR;
    }

    if( refChild != NULL ) {
        if( ixmlNode_isParent( nodeptr, newChild ) == TRUE ) {
            ixmlNode_removeChild( nodeptr, newChild, NULL );
            newChild->nextSibling = NULL;
            newChild->prevSibling = NULL;
        }

        newChild->nextSibling = refChild;
        if( refChild->prevSibling != NULL ) {
            ( refChild->prevSibling )->nextSibling = newChild;
            newChild->prevSibling = refChild->prevSibling;
        }

        refChild->prevSibling = newChild;

        if( newChild->prevSibling == NULL ) {
            nodeptr->firstChild = newChild;
        }

        newChild->parentNode = nodeptr;

    } else {
        ret = ixmlNode_appendChild( nodeptr, newChild );
    }

    return ret;
}
Пример #8
0
void xmlelement_add_text(struct xmldoc *doc,
			 struct xmlelement *parent,
			 const char *text)
{
	assert(doc != NULL);
	assert(parent != NULL);
	assert(text != NULL);
	IXML_Node *textNode;
	textNode = ixmlDocument_createTextNode(to_idoc(doc), text);
	ixmlNode_appendChild((IXML_Node *) to_ielem(parent), textNode);
}
Пример #9
0
int xmlelement_add_element(struct xmldoc *doc,
                           struct xmlelement *parent,
                           struct xmlelement *child)
{
	int result = -1;
	assert(doc != NULL);
	assert(parent != NULL);
	assert(child != NULL);
#ifdef HAVE_LIBUPNP
	ixmlNode_appendChild((IXML_Node *)(parent->element),
                             (IXML_Node *)(child->element));
	result = 0;
#endif
	return result;
}
Пример #10
0
struct xmlelement *xmldoc_new_topelement(struct xmldoc *doc,
                                         const char *elementName,
                                         const char *xmlns)
{
	assert(doc != NULL);
	assert(elementName != NULL);
	IXML_Element *element;
	if (xmlns) {
		element = ixmlDocument_createElementNS(to_idoc(doc), xmlns,
                                                       elementName);
                ixmlElement_setAttribute(element, "xmlns", xmlns);
	} else {
		element = ixmlDocument_createElement(to_idoc(doc), elementName);
	}
	ixmlNode_appendChild((IXML_Node *)(to_idoc(doc)),(IXML_Node *)element);
	return (struct xmlelement *) element;
}
Пример #11
0
int xmlelement_add_text(struct xmldoc *doc,
                        struct xmlelement *parent,
                        const char *text)
{
	int result = -1;
	assert(doc != NULL);
	assert(parent != NULL);
	assert(text != NULL);
#ifdef HAVE_LIBUPNP
	IXML_Node *textNode;
	textNode = ixmlDocument_createTextNode(doc->doc, text);
	ixmlNode_appendChild((IXML_Node *)(parent->element),
                             textNode);
	result = 0;
#endif
	return result;
}
Пример #12
0
int rtpxmlNode_appendChild(RTPXML_Node *nodeptr,RTPXML_Node* newChild)
{
	return ixmlNode_appendChild((IXML_Node *)nodeptr,newChild);
}
Пример #13
0
/************************************************************************
* Function : makeAction											
*																	
* Parameters:														
*	IN int response: flag to tell if the ActionDoc is for response 
*					or request
*	IN char * ActionName: Name of the action request or response
*	IN char * ServType: Service type
*	IN int NumArg :Number of arguments in the action request or response
*	IN char * Arg : pointer to the first argument
*	IN va_list ArgList: Argument list
*
* Description:		
*	This function creates the action request or response from the argument
* list.
* Returns: IXML_Document *
*	returns action request or response document if successful 
*	else returns NULL
***************************************************************************/
static IXML_Document *
makeAction( IN int response,
            IN const char *ActionName,
            IN const char *ServType,
            IN int NumArg,
            IN const char *Arg,
            IN va_list ArgList )
{
    const char *ArgName,
     *ArgValue;
    char *ActBuff;
    int Idx = 0;
    IXML_Document *ActionDoc;
    IXML_Node *node;
    IXML_Element *Ele;
    IXML_Node *Txt = NULL;

    if( ActionName == NULL || ServType == NULL ) {
        return NULL;
    }

    ActBuff = ( char * )malloc( HEADER_LENGTH );
    if( ActBuff == NULL ) {
        return NULL;
    }

    if( response ) {
        sprintf( ActBuff, "<u:%sResponse xmlns:u=\"%s\"></u:%sResponse>",
                 ActionName, ServType, ActionName );
    } else {
        sprintf( ActBuff, "<u:%s xmlns:u=\"%s\"></u:%s>",
                 ActionName, ServType, ActionName );
    }

    if( ixmlParseBufferEx( ActBuff, &ActionDoc ) != IXML_SUCCESS ) {
        free( ActBuff );
        return NULL;
    }

    free( ActBuff );

    if( ActionDoc == NULL ) {
        return NULL;
    }

    if( NumArg > 0 ) {
        //va_start(ArgList, Arg);
        ArgName = Arg;
        while( Idx++ != NumArg ) {
            ArgValue = va_arg( ArgList, const char * );

            if( ArgName != NULL ) {
                node = ixmlNode_getFirstChild( ( IXML_Node * ) ActionDoc );
                Ele = ixmlDocument_createElement( ActionDoc, ArgName );
                if( ArgValue ) {
                    Txt =
                        ixmlDocument_createTextNode( ActionDoc, ArgValue );
                    ixmlNode_appendChild( ( IXML_Node * ) Ele, Txt );
                }

                ixmlNode_appendChild( node, ( IXML_Node * ) Ele );
            }

            ArgName = va_arg( ArgList, const char * );
        }
        //va_end(ArgList);
    }
Пример #14
0
int WriteID3Tag(char *ptrPath,ZDB_METATRACK *trackMeta)
{
    IXML_Document *dom = NULL;
    IXML_Element *elementCmd = NULL;
    IXML_Element *element = NULL;
    IXML_Node *node = NULL;
    char *ptrXml = NULL;
    char *result = NULL;

    if((dom = ixmlDocument_createDocument()) == NULL)
        return ZAPP_FAILED;

    /*cmd node*/
    if((elementCmd = ixmlDocument_createElement(dom, "cmd")) == NULL)
        goto errOut;

    /*op = WriteMetadata*/
    ixmlElement_setAttribute(elementCmd,"op","WriteMetadata");
    ixmlNode_appendChild(&dom->n, (IXML_Node *)elementCmd);

    //FileName node
    if((element = ixmlDocument_createElement(dom, "FileName")) == NULL)
        goto errOut;
    if((node = ixmlDocument_createTextNode(dom, ptrPath)) == NULL)
    {
        ixmlElement_free(element);
        goto errOut;
    }
    ixmlNode_appendChild((IXML_Node *)element, node);
    ixmlNode_appendChild((IXML_Node *)elementCmd, (IXML_Node *)element);

    //artFile node
    if((element = ixmlDocument_createElement(dom, "artFile")) == NULL)
         goto errOut;
    if((node = ixmlDocument_createTextNode(dom, trackMeta->albumArtURI)) == NULL)
    {
       ixmlElement_free(element);
       goto errOut;
    }
    ixmlNode_appendChild((IXML_Node *)element, node);
    ixmlNode_appendChild((IXML_Node *)elementCmd, (IXML_Node *)element);

    //title node
    if((element = ixmlDocument_createElement(dom, "title")) == NULL)
       goto errOut;
    if((node = ixmlDocument_createTextNode(dom, trackMeta->trackTitle)) == NULL)
    {
       ixmlElement_free(element);
       goto errOut;
    }
    ixmlNode_appendChild((IXML_Node *)element, node);
    ixmlNode_appendChild((IXML_Node *)elementCmd, (IXML_Node *)element);

    //album node
    if((element = ixmlDocument_createElement(dom, "album")) == NULL)
        goto errOut;
    if((node = ixmlDocument_createTextNode(dom, trackMeta->albumname)) == NULL)
    {
        ixmlElement_free(element);
        goto errOut;
    }
    ixmlNode_appendChild((IXML_Node *)element, node);
    ixmlNode_appendChild((IXML_Node *)elementCmd, (IXML_Node *)element);

    //artistname node
    if((element = ixmlDocument_createElement(dom, "artist")) == NULL)
        goto errOut;
    if((node = ixmlDocument_createTextNode(dom, trackMeta->artistname)) == NULL)
    {
       ixmlElement_free(element);
       goto errOut;
    }
    ixmlNode_appendChild((IXML_Node *)element, node);
    ixmlNode_appendChild((IXML_Node *)elementCmd, (IXML_Node *)element);

    //genre node
    if((element = ixmlDocument_createElement(dom, "genre")) == NULL)
        goto errOut;
    if((node = ixmlDocument_createTextNode(dom, trackMeta->genrename)) == NULL)
    {
        ixmlElement_free(element);
        goto errOut;
    }
    ixmlNode_appendChild((IXML_Node *)element, node);
    ixmlNode_appendChild((IXML_Node *)elementCmd, (IXML_Node *)element);

    //year node
    if((element = ixmlDocument_createElement(dom, "year")) == NULL)
        goto errOut;
    if((node = ixmlDocument_createTextNode(dom, trackMeta->releaseDate)) == NULL)
    {
       ixmlElement_free(element);
       goto errOut;
    }
    ixmlNode_appendChild((IXML_Node *)element, node);
    ixmlNode_appendChild((IXML_Node *)elementCmd, (IXML_Node *)element);

    //trackNum node
    if((element = ixmlDocument_createElement(dom, "trackNum")) == NULL)
       goto errOut;
    if((node = ixmlDocument_createTextNode(dom, trackMeta->trackNo)) == NULL)
    {
       ixmlElement_free(element);
       goto errOut;
    }
    ixmlNode_appendChild((IXML_Node *)element, node);
    ixmlNode_appendChild((IXML_Node *)elementCmd, (IXML_Node *)element);
    ptrXml = ixmlPrintDocument(dom);
    result = Call3rdPartyCommand("zxtract", ptrXml, strlen(ptrXml),32);

errOut:
    if(result)
    {
       free(result);
    }

    ixmlDocument_free(dom);
    if(ptrXml != NULL)
    {
        free(ptrXml);
    }
    return ZAPP_SUCCESS;
}
Пример #15
0
/************************************************************************
*	Function :	config_description_doc
*
*	Parameters :
*		INOUT IXML_Document *doc ;IMXL description document to be 
*					configured	
*		IN const char* ip_str ;	string containing the IP port number
*		OUT char** root_path_str ;	buffer to hold the root path
*					of the configured description document
*		INOUT IXML_Document *doc :	Description document
*		IN const char* ip_str :	ipaddress string
*		OUT char** root_path_str :	root path string
*
*	Description : Configure the description document. Add the standard 
*		format and then add information from the root device and any
*		child nodes.
*
*	Return : int ;
*		UPNP_E_SUCCESS - On Success
*		UPNP_E_OUTOF_MEMORY - Default Error
*		UPNP_E_INVALID_DESC - Invalid child node		
*		UPNP_E_INVALID_URL - Invalid node information
*
*	Note :
************************************************************************/
static int
config_description_doc( INOUT IXML_Document * doc,
                        IN const char *ip_str,
                        OUT char **root_path_str )
{
    xboolean addNew = FALSE;
    IXML_NodeList *baseList;
    IXML_Element *element = NULL;
    IXML_Element *newElement = NULL;
    IXML_Node *textNode = NULL;
    IXML_Node *rootNode = NULL;
    IXML_Node *urlbase_node = NULL;
    char *urlBaseStr = "URLBase";
    const DOMString domStr = NULL;
    uri_type uri;
    int err_code;
    int len;
    membuffer url_str;
    membuffer root_path;

    membuffer_init( &url_str );
    membuffer_init( &root_path );

    err_code = UPNP_E_OUTOF_MEMORY; // default error

    baseList = ixmlDocument_getElementsByTagName( doc, urlBaseStr );
    if( baseList == NULL ) {
        // urlbase not found -- create new one
        addNew = TRUE;
        element = ixmlDocument_createElement( doc, urlBaseStr );
        if( element == NULL ) {
            goto error_handler;
        }

        if( membuffer_append_str( &url_str, "http://" ) != 0 ||
            membuffer_append_str( &url_str, ip_str ) != 0 ||
            membuffer_append_str( &url_str, "/" ) != 0 ||
            membuffer_append_str( &root_path, "/" ) != 0 ) {
            goto error_handler;
        }

        rootNode = ixmlNode_getFirstChild( ( IXML_Node * ) doc );
        if( rootNode == NULL ) {
            err_code = UPNP_E_INVALID_DESC;
            goto error_handler;
        }

        err_code =
            ixmlNode_appendChild( rootNode, ( IXML_Node * ) element );
        if( err_code != IXML_SUCCESS ) {
            goto error_handler;
        }

        textNode =
            ixmlDocument_createTextNode( doc, ( char * )url_str.buf );
        if( textNode == NULL ) {
            goto error_handler;
        }

        err_code =
            ixmlNode_appendChild( ( IXML_Node * ) element, textNode );
        if( err_code != IXML_SUCCESS ) {
            goto error_handler;
        }

    } else {
        // urlbase found
        urlbase_node = ixmlNodeList_item( baseList, 0 );
        assert( urlbase_node != NULL );

        textNode = ixmlNode_getFirstChild( urlbase_node );
        if( textNode == NULL ) {
            err_code = UPNP_E_INVALID_DESC;
            goto error_handler;
        }

        domStr = ixmlNode_getNodeValue( textNode );
        if( domStr == NULL ) {
            err_code = UPNP_E_INVALID_URL;
            goto error_handler;
        }

        len = parse_uri( domStr, strlen( domStr ), &uri );
        if( len < 0 || uri.type != ABSOLUTE ) {
            err_code = UPNP_E_INVALID_URL;
            goto error_handler;
        }

        if( membuffer_assign( &url_str, uri.scheme.buff,
                              uri.scheme.size ) != 0 ||
            membuffer_append_str( &url_str, "://" ) != 0 ||
            membuffer_append_str( &url_str, ip_str ) != 0 ) {
            goto error_handler;
        }
        // add leading '/' if missing from relative path
        if( ( uri.pathquery.size > 0 && uri.pathquery.buff[0] != '/' ) ||
            ( uri.pathquery.size == 0 )
             ) {
            if( membuffer_append_str( &url_str, "/" ) != 0 ||
                membuffer_append_str( &root_path, "/" ) != 0 ) {
                goto error_handler;
            }
        }

        if( membuffer_append( &url_str, uri.pathquery.buff,
                              uri.pathquery.size ) != 0 ||
            membuffer_append( &root_path, uri.pathquery.buff,
                              uri.pathquery.size ) != 0 ) {
            goto error_handler;
        }
        // add trailing '/' if missing
        if( url_str.buf[url_str.length - 1] != '/' ) {
            if( membuffer_append( &url_str, "/", 1 ) != 0 ) {
                goto error_handler;
            }
        }

        err_code = ixmlNode_setNodeValue( textNode, url_str.buf );
        if( err_code != IXML_SUCCESS ) {
            goto error_handler;
        }
    }

    *root_path_str = membuffer_detach( &root_path );    // return path
    err_code = UPNP_E_SUCCESS;

  error_handler:
    if( err_code != UPNP_E_SUCCESS ) {
        ixmlElement_free( newElement );
    }

    ixmlNodeList_free( baseList );

    membuffer_destroy( &root_path );
    membuffer_destroy( &url_str );

    return err_code;
}