/* * Copyright (C) 2005 iptelorg GmbH * * This file is part of ser, a free SIP server. * * ser 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 2 of the License, or * (at your option) any later version * * For a license to use the ser software under conditions * other than those described here, or to purchase support for this * software, please contact iptel.org by e-mail at the following addresses: * info@iptel.org * * ser 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include static char rl_namespace[] = "urn:ietf:params:xml:ns:resource-lists"; static int read_entry_ref(xmlNode *entry_node, entry_ref_t **dst) { xmlAttr *a; const char *a_val; /* allocate memory and prepare empty node */ if (!dst) return -1; *dst = (entry_ref_t*)cds_malloc(sizeof(entry_ref_t)); if (!(*dst)) return -2; memset(*dst, 0, sizeof(entry_ref_t)); /* get attributes */ a = find_attr(entry_node->properties, "ref"); if (a) { a_val = get_attr_value(a); if (a_val) (*dst)->ref = zt_strdup(a_val); } return 0; } static int read_name(xmlNode *name_node, display_name_t **dst) { xmlAttr *a; const char *a_val; /* allocate memory and prepare empty node */ if (!dst) return -1; *dst = (display_name_t*)cds_malloc(sizeof(display_name_t)); if (!(*dst)) return -2; memset(*dst, 0, sizeof(display_name_t)); /* get attributes */ a = find_attr(name_node->properties, "lang"); if (a) { a_val = get_attr_value(a); if (a_val) (*dst)->lang = zt_strdup(a_val); } a_val = get_node_value(name_node); if (a_val) (*dst)->name = zt_strdup(a_val); return 0; } static int read_names(xmlNode *entry_node, display_name_t **dst) { xmlNode *n; display_name_t *name, *last; int res = 0; last = NULL; *dst = NULL; n = entry_node->children; while (n) { if (n->type == XML_ELEMENT_NODE) { if (cmp_node(n, "display-name", rl_namespace) >= 0) { res = read_name(n, &name); if (res == 0) { if (name) { SEQUENCE_ADD((*dst), last, name); name = NULL; } } else break; } } n = n->next; } return res; } static int read_entry(xmlNode *entry_node, entry_t **dst) { xmlAttr *a; const char *a_val; /* allocate memory and prepare empty node */ if (!dst) return -1; *dst = (entry_t*)cds_malloc(sizeof(entry_t)); if (!(*dst)) return -2; memset(*dst, 0, sizeof(entry_t)); /* get attributes */ a = find_attr(entry_node->properties, "uri"); if (a) { a_val = get_attr_value(a); if (a_val) (*dst)->uri = zt_strdup(a_val); } return read_names(entry_node, &((*dst)->display_names)); } static int read_external(xmlNode *entry_node, external_t **dst) { xmlAttr *a; const char *a_val; /* allocate memory and prepare empty node */ if (!dst) return -1; *dst = (external_t*)cds_malloc(sizeof(external_t)); if (!(*dst)) return -2; memset(*dst, 0, sizeof(external_t)); /* get attributes */ a = find_attr(entry_node->properties, "anchor"); if (a) { a_val = get_attr_value(a); if (a_val) (*dst)->anchor = zt_strdup(a_val); } return 0; } int read_list(xmlNode *list_node, list_t **dst, int read_content_only) { int res = 0; xmlAttr *a; const char *a_val; xmlNode *n; list_content_t *l, *last_l; /* allocate memory and prepare empty node */ if (!dst) return -1; *dst = (list_t*)cds_malloc(sizeof(list_t)); if (!(*dst)) return -2; memset(*dst, 0, sizeof(list_t)); /* get attributes */ if (!read_content_only) { a = find_attr(list_node->properties, "name"); if (a) { a_val = get_attr_value(a); if (a_val) (*dst)->name = zt_strdup(a_val); } } /* read entries */ last_l = NULL; n = list_node->children; while (n) { if (n->type == XML_ELEMENT_NODE) { l = (list_content_t*) cds_malloc(sizeof(list_content_t)); if (!l) return -1; memset(l, 0, sizeof(*l)); if (cmp_node(n, "list", rl_namespace) >= 0) { res = read_list(n, &l->u.list, 0); if (res == 0) { if (l->u.list) { l->type = lct_list; SEQUENCE_ADD((*dst)->content, last_l, l); l = NULL; } } else break; } if (cmp_node(n, "entry", rl_namespace) >= 0) { res = read_entry(n, &l->u.entry); if (res == 0) { if (l->u.entry) { l->type = lct_entry; SEQUENCE_ADD((*dst)->content, last_l, l); l = NULL; } } else break; } if (cmp_node(n, "entry-ref", rl_namespace) >= 0) { res = read_entry_ref(n, &l->u.entry_ref); if (res == 0) { if (l->u.entry_ref) { l->type = lct_entry_ref; SEQUENCE_ADD((*dst)->content, last_l, l); l = NULL; } } else break; } if (cmp_node(n, "external", rl_namespace) >= 0) { res = read_external(n, &l->u.external); if (res == 0) { if (l->u.external) { l->type = lct_external; SEQUENCE_ADD((*dst)->content, last_l, l); l = NULL; } } else break; } if (l) { cds_free(l); l = NULL; } } n = n->next; } return 0; } static int read_resource_lists(xmlNode *root, resource_lists_t **dst) { resource_lists_t *rl; /* xmlAttr *a; */ xmlNode *n; list_t *l, *last_l; int res = 0; if (!dst) return -1; else *dst = NULL; if (!root) return -1; if (cmp_node(root, "resource-lists", rl_namespace) < 0) { ERROR_LOG("document is not a resource-lists\n"); return -1; } rl = (resource_lists_t*)cds_malloc(sizeof(resource_lists_t)); if (!rl) return -2; *dst = rl; rl->lists = NULL; last_l = NULL; n = root->children; while (n) { if (n->type == XML_ELEMENT_NODE) { if (cmp_node(n, "list", rl_namespace) >= 0) { res = read_list(n, &l, 0); if (res == 0) { if (l) SEQUENCE_ADD(rl->lists, last_l, l); } else break; } } n = n->next; } return res; } int parse_resource_lists_xml(const char *data, int data_len, resource_lists_t **dst) { int res = 0; xmlDocPtr doc; /* the resulting document tree */ if (dst) *dst = NULL; doc = xmlReadMemory(data, data_len, NULL, NULL, xml_parser_flags); if (doc == NULL) { ERROR_LOG("can't parse document\n"); return -1; } res = read_resource_lists(xmlDocGetRootElement(doc), dst); xmlFreeDoc(doc); return res; } int parse_list_xml(const char *data, int data_len, list_t **dst) { int res = 0; xmlDocPtr doc; /* the resulting document tree */ if (dst) *dst = NULL; doc = xmlReadMemory(data, data_len, NULL, NULL, xml_parser_flags); if (doc == NULL) { ERROR_LOG("can't parse document\n"); return -1; } res = read_list(xmlDocGetRootElement(doc), dst, 0); xmlFreeDoc(doc); return res; } int parse_as_list_content_xml(const char *data, int data_len, list_t **dst) { int res = 0; xmlDocPtr doc; /* the resulting document tree */ if (dst) *dst = NULL; doc = xmlReadMemory(data, data_len, NULL, NULL, xml_parser_flags); if (doc == NULL) { ERROR_LOG("can't parse document\n"); return -1; } res = read_list(xmlDocGetRootElement(doc), dst, 1); xmlFreeDoc(doc); return res; } int parse_entry_xml(const char *data, int data_len, entry_t **dst) { int res = 0; xmlDocPtr doc; /* the resulting document tree */ if (dst) *dst = NULL; doc = xmlReadMemory(data, data_len, NULL, NULL, xml_parser_flags); if (doc == NULL) { ERROR_LOG("can't parse document\n"); return -1; } res = read_entry(xmlDocGetRootElement(doc), dst); xmlFreeDoc(doc); return res; } void free_display_name(display_name_t *n) { if (!n) return; if (n->name) cds_free(n->name); if (n->lang) cds_free(n->lang); cds_free(n); } void free_display_names(display_name_t *sequence_first) { display_name_t *d, *n; if (!sequence_first) return; d = SEQUENCE_FIRST(sequence_first); while (d) { n = SEQUENCE_NEXT(d); free_display_name(d); d = n; } } void free_entry(entry_t *e) { if (!e) return; if (e->uri) cds_free(e->uri); free_display_names(e->display_names); cds_free(e); } void free_entry_ref(entry_ref_t *e) { if (!e) return; if (e->ref) cds_free(e->ref); cds_free(e); } void free_external(external_t *e) { if (!e) return; if (e->anchor) cds_free(e->anchor); cds_free(e); } void free_list(list_t *l) { list_content_t *e, *f; if (!l) return; if (l->name) cds_free(l->name); e = SEQUENCE_FIRST(l->content); while (e) { switch (e->type) { case lct_list: free_list(e->u.list); break; case lct_entry: free_entry(e->u.entry); break; case lct_entry_ref: free_entry_ref(e->u.entry_ref); break; case lct_external: free_external(e->u.external); break; } f = e; e = SEQUENCE_NEXT(e); /* TRACE_LOG("freeing %p\n", f); */ cds_free(f); } cds_free(l); } void free_resource_lists(resource_lists_t *rl) { list_t *e, *f; if (!rl) return; e = SEQUENCE_FIRST(rl->lists); while (e) { f = SEQUENCE_NEXT(e); free_list(e); e = f; } cds_free(rl); }