doubango/trunk/tinyXCAP/tinyXCAP/src/xdm_rlist.c

617 lines
18 KiB
C

/****************************************************************************
_ _
| | | |
_ | | ___ _ _| | _ ____ ____ ____ ___
/ || |/ _ \| | | | || \ / _ | _ \ / _ |/ _ \
( (_| | |_| | |_| | |_) | ( | | | | ( ( | | |_| |
\____|\___/ \____|____/ \_||_|_| |_|\_|| |\___/
(_____|
Copyright (C) 2009 xxxyyyzzz <imsframework(at)gmail.com>
This file is part of Open Source Doubango IMS Client Framework project.
DOUBANGO is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DOUBANGO is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU General Public License
along with DOUBANGO.
****************************************************************************/
/*
RFC 4826 - Extensible Markup Language (XML) Formats for Representing Resource Lists
resource-lists
->list-1(name)
->entry-1(uri, display-name)
->entry-2(uri, display-name)
->list-2(name)
->list-3(name)
*/
#include "xdm_rlist.h"
#include "xdm_utils.h"
#define RLIST_SELECT_LIST_BY_NAME(lname)\
xdm_xml_select_node(rlist->docPtr->children, \
XDM_XML_NODE_SELECT_BY_NAME("resource-lists"), \
XDM_XML_NODE_SELECT_BY_ATT("list", "name", lname), \
XDM_XML_NODE_SELECT_CONTENT(), \
XDM_XML_NODE_SELECT_END())
#define RLIST_XML_HEADER "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" \
"<resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\" " \
"xmlns:xd=\"urn:oma:xml:xdm:xcap-directory\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
#define RLIST_XML_FOOTER "</resource-lists>"
#define RLIST_RETURN_IF_INVALID(rlist) if(!rlist || !(rlist->docPtr)) return 0;
//static const char* xdm_rlist_ns = "urn:ietf:params:xml:ns:resource-lists";
/* init entry*/
void xdm_rlist_entry_init(xdm_rlist_entry_t *entry)
{
memset(entry, 0, sizeof(xdm_rlist_entry_t));
}
/* set entry's uri and display-name */
void xdm_rlist_entry_set(xdm_rlist_entry_t *entry, const char* uri, const char* display_name)
{
if(entry)
{
xdm_strupdate(&(entry->uri), uri);
xdm_strupdate(&(entry->display_name), display_name);
}
}
/* free entry */
void xdm_rlist_entry_free(void **_entry)
{
xdm_rlist_entry_t **entry = ((xdm_rlist_entry_t**)_entry);
XDM_SAFE_FREE((*entry)->uri);
XDM_SAFE_FREE((*entry)->display_name);
XDM_SAFE_FREE((*entry)->list);
XDM_SAFE_FREE((*entry)->last_modified);
XDM_SAFE_FREE((*entry)->etag);
free(*_entry);
(*_entry) = 0;
}
/* init list */
void xdm_rlist_list_init(xdm_rlist_list_t *list)
{
memset(list, 0, sizeof(xdm_rlist_list_t));
}
/* set list's name and display-name */
void xdm_rlist_list_set(xdm_rlist_list_t *list, const char* name, const char* display_name)
{
if(list)
{
xdm_strupdate(&(list->name), name);
xdm_strupdate(&(list->display_name), display_name);
}
}
/* free list */
void xdm_rlist_list_free(void **_list)
{
xdm_rlist_list_t **list = ((xdm_rlist_list_t**)_list);
XDM_SAFE_FREE((*list)->display_name);
XDM_SAFE_FREE((*list)->name);
free(*_list);
(*_list) = 0;
}
/* init list2 */
void xdm_rlist_list2_init(xdm_rlist_list2_t *list2)
{
memset(list2, 0, sizeof(xdm_rlist_list2_t));
}
/* set list2's name and display-name */
void xdm_rlist_list2_set(xdm_rlist_list2_t *list2, const char* name, const char* display_name)
{
if(list2)
{
xdm_strupdate(&(list2->name), name);
xdm_strupdate(&(list2->display_name),display_name);
}
}
/* add external eement to the list2 */
void xdm_rlist_list2_add_external(xdm_rlist_list2_t *list2, const char* anchor)
{
if(list2)
{
xdm_rlist_external_t *external = 0;
if(!(list2->externals))
{
XDM_LIST_CREATE(list2->externals);
}
XDM_RLIST_EXTERNAL_CREATE(external);
xdm_rlist_external_set(external, anchor);
xdm_list_add_data(list2->externals, ((void**)&external), xdm_rlist_external_free);
}
}
/* and an entry to the list */
void xdm_rlist_list2_add_entry(xdm_rlist_list2_t *list2, const char* uri, const char* display_name)
{
if(list2)
{
xdm_rlist_entry_t *entry = 0;
XDM_RLIST_ENTRY_CREATE(entry);
xdm_rlist_entry_set(entry, uri, display_name);
if(!(list2->entries))
{
XDM_LIST_CREATE(list2->entries);
}
xdm_list_add_data(list2->entries, ((void**)&entry), xdm_rlist_entry_free);
}
}
/* free list2 */
void xdm_rlist_list2_free(void **_list2)
{
xdm_rlist_list2_t **list2 = ((xdm_rlist_list2_t**)_list2);
XDM_SAFE_FREE((*list2)->display_name);
XDM_SAFE_FREE((*list2)->name);
XDM_LIST_SAFE_FREE((*list2)->externals);
XDM_LIST_SAFE_FREE((*list2)->entries);
free(*_list2);
(*_list2) = 0;
}
/* init external */
void xdm_rlist_external_init(xdm_rlist_external_t *external)
{
memset(external, 0, sizeof(xdm_rlist_external_t));
}
/* set external's anchor */
void xdm_rlist_external_set(xdm_rlist_external_t *external, const char* anchor)
{
if(external)
{
xdm_strupdate(&(external->anchor), anchor);
}
}
/* free external */
void xdm_rlist_external_free(void **_external)
{
xdm_rlist_external_t **external = ((xdm_rlist_external_t**)_external);
XDM_SAFE_FREE((*external)->anchor);
XDM_SAFE_FREE((*external)->list);
free(*_external);
(*_external) = 0;
}
/* xml<->entry binding*/
/* ATTENTION: use 'XDM_RLIST_ENTRY_SAFE_FREE' function to free the returned object */
xdm_rlist_entry_t* xdm_rlist_entry_from_xml(const xmlNodePtr node, const char* lname)
{
xmlNodePtr node2 = 0;
xdm_rlist_entry_t *rlist_entry = 0;
if(xdm_xml_find_node(node, "entry", nft_none))
{
XDM_RLIST_ENTRY_CREATE(rlist_entry);
rlist_entry->list = xdm_strdup(lname);
/* display-name */
node2 = xdm_xml_select_node(node, XDM_XML_NODE_SELECT_BY_NAME("entry"),
XDM_XML_NODE_SELECT_BY_NAME("display-name"), XDM_XML_NODE_SELECT_END());
rlist_entry->display_name = xdm_strdup(XDM_XML_NODE_SAFE_GET_TEXTVALUE(node2));
/* uri */
node2 = xdm_xml_select_node(node,
XDM_XML_NODE_SELECT_ATT_VALUE("entry", "uri"), XDM_XML_NODE_SELECT_END());
rlist_entry->uri = xdm_strdup(XDM_XML_NODE_SAFE_GET_TEXTVALUE(node2));
/* last-modified */
node2 = xdm_xml_select_node(node,
XDM_XML_NODE_SELECT_ATT_VALUE("entry", "last-modified"), XDM_XML_NODE_SELECT_END());
rlist_entry->last_modified = xdm_strdup(XDM_XML_NODE_SAFE_GET_TEXTVALUE(node2));
/* etag */
node2 = xdm_xml_select_node(node,
XDM_XML_NODE_SELECT_ATT_VALUE("entry", "etag"), XDM_XML_NODE_SELECT_END());
rlist_entry->etag = xdm_strdup(XDM_XML_NODE_SAFE_GET_TEXTVALUE(node2));
}
else return 0;
return rlist_entry;
}
/* xml<->entry binding*/
/* ATTENTION: use 'XDM_RLIST_EXTERNAL_SAFE_FREE' function to free the returned object */
xdm_rlist_external_t* xdm_rlist_external_from_xml(const xmlNodePtr node, const char* lname)
{
xmlNodePtr node2 = 0;
xdm_rlist_external_t *rlist_external = 0;
if(xdm_xml_find_node(node, "external", nft_none))
{
XDM_RLIST_EXTERNAL_CREATE(rlist_external);
rlist_external->list = xdm_strdup(lname);
/* anchor */
node2 = xdm_xml_select_node(node,
XDM_XML_NODE_SELECT_ATT_VALUE("external", "anchor"),
XDM_XML_NODE_SELECT_END());
rlist_external->anchor = xdm_strdup(XDM_XML_NODE_SAFE_GET_TEXTVALUE(node2));
}else return 0;
return rlist_external;
}
/* xml<->list binding*/
/* ATTENTION: use 'XDM_RLIST_LIST_SAFE_FREE' function to free the returned object */
xdm_rlist_list_t* xdm_rlist_list_from_xml(const xmlNodePtr node)
{
xmlNodePtr node2 = 0;
xdm_rlist_list_t *rlist_list = 0;
if(xdm_xml_find_node(node, "list", nft_none))
{
XDM_RLIST_LIST_CREATE(rlist_list);
/* name */
node2 = xdm_xml_select_node(node,
XDM_XML_NODE_SELECT_ATT_VALUE("list", "name"),
XDM_XML_NODE_SELECT_END());
rlist_list->name = xdm_strdup(XDM_XML_NODE_SAFE_GET_TEXTVALUE(node2));
/* display-name */
node2 = xdm_xml_select_node(node, XDM_XML_NODE_SELECT_BY_NAME("list"),
XDM_XML_NODE_SELECT_BY_NAME("display-name"),
XDM_XML_NODE_SELECT_END());
rlist_list->display_name = xdm_strdup(XDM_XML_NODE_SAFE_GET_TEXTVALUE(node2));
}else return 0;
return rlist_list;
}
/* xml<->list binding*/
/* ATTENTION: use 'XDM_RLIST_LIST2_SAFE_FREE' function to free the returned object */
xdm_rlist_list2_t* xdm_rlist_list2_from_xml(const xmlNodePtr node)
{
xmlNodePtr node2 = 0;
xdm_rlist_list2_t *rlist_list2 = 0;
if(xdm_xml_find_node(node, "list", nft_none))
{
XDM_RLIST_LIST_CREATE(rlist_list2);
/** name **/
node2 = xdm_xml_select_node(node,
XDM_XML_NODE_SELECT_ATT_VALUE("list", "name"),
XDM_XML_NODE_SELECT_END());
rlist_list2->name = xdm_strdup(XDM_XML_NODE_SAFE_GET_TEXTVALUE(node2));
/** display-name **/
node2 = xdm_xml_select_node(node, XDM_XML_NODE_SELECT_BY_NAME("list"),
XDM_XML_NODE_SELECT_BY_NAME("display-name"),
XDM_XML_NODE_SELECT_END());
rlist_list2->display_name = xdm_strdup(XDM_XML_NODE_SAFE_GET_TEXTVALUE(node2));
/** externals **/
/* select first external */
if(! (node2 = xdm_xml_find_node(node->children, "external", nft_none)) ) node2 = xdm_xml_find_node(node->children, "external", nft_next);
if(node2)
{
xdm_rlist_external_t *rlist_external = 0;
XDM_LIST_CREATE(rlist_list2->externals);
do
{
rlist_external = xdm_rlist_external_from_xml(node2, rlist_list2->name);
xdm_list_add_data(rlist_list2->externals, ((void**) &rlist_external), xdm_rlist_external_free);
}
while(node2 = xdm_xml_find_node(node2, "external", nft_next));
}
/** entries **/
/* select first entry */
if(!(node2 = xdm_xml_find_node(node->children, "entry", nft_none))) node2 = xdm_xml_find_node(node->children, "entry", nft_next);
if(node2)
{
xdm_rlist_entry_t *rlist_entry = 0;
XDM_LIST_CREATE(rlist_list2->entries);
do
{
rlist_entry = xdm_rlist_entry_from_xml(node2, rlist_list2->name);
xdm_list_add_data(rlist_list2->entries, ((void**) &rlist_entry), xdm_rlist_entry_free);
}
while(node2 = xdm_xml_find_node(node2, "entry", nft_next));
}
}else return 0;
return rlist_list2;
}
/* create resource-lists document */
xdm_rlist_t* xdm_rlist_create(const char* buffer, size_t size)
{
if(buffer && size)
{
xdm_rlist_t* rlist = (xdm_rlist_t*)malloc(sizeof(xdm_rlist_t));
memset(rlist, 0, sizeof(xdm_rlist_t));
rlist->docPtr = xmlParseMemory(buffer, (int)size);
return rlist;
}
return 0;
}
/* get all lists(xdm_rlist_list_t or xdm_rlist_list2_t) */
/* ATTENTION: use 'XDM_LIST_SAFE_FREE' function to free the returned object */
xdm_rlist_listx_L_t* xdm_rlist_get_all_lists(const xdm_rlist_t* rlist, int type2)
{
xdm_rlist_listx_L_t* list = 0;
xmlNodePtr node = 0;
RLIST_RETURN_IF_INVALID(rlist);
/* root */
node = xdm_xml_select_node(rlist->docPtr->children,
XDM_XML_NODE_SELECT_BY_NAME("resource-lists"),
XDM_XML_NODE_SELECT_END());
/* select first list */
if(!xdm_xml_find_node(node, "list", nft_none)) node = xdm_xml_find_node(node, "list", nft_next);
if(node)
{
XDM_LIST_CREATE(list);
do
{
if(type2)
{
xdm_rlist_list2_t* rlist_list2 = xdm_rlist_list2_from_xml(node);
xdm_list_add_data(list, ((void**) &rlist_list2), xdm_rlist_list2_free);
}
else
{
xdm_rlist_list_t* rlist_list = xdm_rlist_list_from_xml(node);
xdm_list_add_data(list, ((void**) &rlist_list), xdm_rlist_list_free);
}
}
while(node = xdm_xml_find_node(node, "list", nft_next));
}
return list;
}
/* returns all entries into the list named @lname */
/* ATTENTION: use 'XDM_LIST_SAFE_FREE' function to free the returned object */
xdm_rlist_entry_L_t* xdm_rlist_get_entries_by_list(const xdm_rlist_t* rlist, const char* lname)
{
xdm_rlist_entry_t *rlist_entry = 0;
xdm_rlist_entry_L_t* list = 0;
xmlNodePtr node = 0;
RLIST_RETURN_IF_INVALID(rlist);
node = RLIST_SELECT_LIST_BY_NAME(lname);
if(!node) return 0;
XDM_LIST_CREATE(list);
/* select first entry */
if(!xdm_xml_find_node(node, "entry", nft_none)) node = xdm_xml_find_node(node, "entry", nft_next);
if(node)
{
do
{
rlist_entry = xdm_rlist_entry_from_xml(node, lname);
xdm_list_add_data(list, ((void**) &rlist_entry), xdm_rlist_entry_free);
}
while(node = xdm_xml_find_node(node, "entry", nft_next));
}
return list;
}
/* returns a list of externals by list name (xdm_rlist_external_t) */
/* ATTENTION: use 'XDM_LIST_SAFE_FREE' function to free the returned object */
xdm_rlist_external_L_t* xdm_rlist_get_externals_by_list(const xdm_rlist_t* rlist, const char* lname)
{
xdm_rlist_external_t *rlist_external = 0;
xdm_rlist_external_L_t* list = 0;
xmlNodePtr node = 0;
RLIST_RETURN_IF_INVALID(rlist);
node = RLIST_SELECT_LIST_BY_NAME(lname);
if(!node) return 0;
/* select first external */
if(!xdm_xml_find_node(node, "external", nft_none)) node = xdm_xml_find_node(node, "external", nft_next);
if(node)
{
XDM_LIST_CREATE(list);
do
{
rlist_external = xdm_rlist_external_from_xml(node, lname);
xdm_list_add_data(list, ((void**) &rlist_external), xdm_rlist_external_free);
}
while(node = xdm_xml_find_node(node, "external", nft_next));
}
return list;
}
/* serialize an external */
/* ATTENTION: use 'XDM_SAFE_FREE' macro to free the returned string */
char* xdm_rlist_external_serialize(const xdm_rlist_external_t *external)
{
char* external_str = 0;
if(!external) return 0;
xdm_sprintf(&external_str, "<external anchor=\"%s\" />", external->anchor);
return external_str;
}
/* serialize an entry */
/* ATTENTION: use 'XDM_SAFE_FREE' macro to free the returned string */
char* xdm_rlist_entry_serialize(const xdm_rlist_entry_t *entry)
{
return entry ? xdm_rlist_entry_serialize2(entry->uri, entry->display_name) : 0;
}
/* serialize an entry */
/* ATTENTION: use 'XDM_SAFE_FREE' macro to free the returned string */
char* xdm_rlist_entry_serialize2(const char* uri, const char* displayname)
{
char* entry_str = 0;
if(!uri || !displayname) return 0;
xdm_sprintf(&entry_str,
"<entry uri=\"%s\" xmlns=\"urn:ietf:params:xml:ns:resource-lists\">"
"<display-name>%s</display-name>"
"</entry>",
uri, displayname);
return entry_str;
}
/* serialize list */
/* ATTENTION: use 'XDM_SAFE_FREE' macro to free the returned string */
char* xdm_rlist_list_serialize(const xdm_rlist_list_t *list)
{
return list ? xdm_rlist_list_serialize2(list->name, list->display_name) : 0;
}
/* serialize list */
/* ATTENTION: use 'XDM_SAFE_FREE' macro to free the returned string */
char* xdm_rlist_list_serialize2(const char* name, const char* displayname)
{
char* list_str = 0;
if(!name || !displayname) return 0;
/* serialize */
xdm_sprintf(&list_str,
"<list name=\"%s\" xmlns=\"urn:ietf:params:xml:ns:resource-lists\">"
"<display-name>%s</display-name>"
"</list>",
name, displayname);
return list_str;
}
/* serialize list2 */
/* ATTENTION: use 'XDM_SAFE_FREE' macro to free the returned string */
char* xdm_rlist_list2_serialize(const xdm_rlist_list2_t *list2)
{
char* list2_str = 0;
xdm_list_item_t *item = 0;
/* check validity */
if(!list2) return 0;
/* name and display-name */
xdm_sprintf(&list2_str,
"<list name=\"%s\" xmlns=\"urn:ietf:params:xml:ns:resource-lists\">"
"<display-name>%s</display-name>",
list2->name, list2->display_name);
/* entries */
xdm_list_foreach(item, list2->entries)
{
xdm_rlist_entry_t *entry = ((xdm_rlist_entry_t*)item->data);
char* entry_str = xdm_rlist_entry_serialize(entry);
xdm_strcat(&list2_str, (const char*)entry_str);
XDM_FREE(entry_str);
}
/*externals*/
xdm_list_foreach(item, list2->externals)
{
xdm_rlist_external_t *external = ((xdm_rlist_external_t*)item->data);
char* external_str = xdm_rlist_external_serialize(external);
xdm_strcat(&list2_str, (const char*)external_str);
XDM_FREE(external_str);
}
/* close list */
xdm_strcat(&list2_str, "</list>");
return list2_str;
}
/* will serialize a complete resource-lists whith xml header*/
/* ATTENTION: use 'XDM_SAFE_FREE' macro to free the returned string */
char* xdm_rlist_rlist2_serialize(const xdm_list_t *rlist2)
{
xdm_list_item_t* item = 0;
char* rlist2_str = 0;
if(!rlist2) return 0;
/* xml header */
xdm_strcat(&rlist2_str, RLIST_XML_HEADER);
xdm_list_foreach(item, rlist2)
{
/* get list2 */
xdm_rlist_list2_t *list2 = ((xdm_rlist_list2_t*)item->data);
char* list2_str = xdm_rlist_list2_serialize(list2);
xdm_strcat(&rlist2_str, list2_str);
XDM_FREE(list2_str);
}
/* xml footer */
xdm_strcat(&rlist2_str, RLIST_XML_FOOTER);
return rlist2_str;
}
/* add xml header to the content */
/* ATTENTION: use 'XDM_SAFE_FREE' macro to free the returned string */
char* xdm_rlist_add_xml_header(const char* xml_content)
{
char* xml = 0;
/* append xml header */
xdm_sprintf(&xml,
"%s%s%s",
RLIST_XML_HEADER, xml_content, RLIST_XML_FOOTER);
return xml;
}
/* free resource-lists document */
void xdm_rlist_free(xdm_rlist_t **rlist )
{
if(*rlist)
{
xmlFreeDoc((*rlist)->docPtr);
free(*rlist);
(*rlist)=0;
}
}
#undef RLIST_SELECT_LIST_BY_NAME
#undef RLIST_RETURN_IF_INVALID
#undef RLIST_XML_HEADER
#undef RLIST_XML_FOOTER