/* Copyright (C) 2005-2009 Michel de Boer This program 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. This program 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, see . */ #include "pidf_body.h" #include #include #include "log.h" #include "util.h" #include "audits/memman.h" #define PIDF_XML_VERSION "1.0" #define PIDF_NAMESPACE "urn:ietf:params:xml:ns:pidf" #define IS_PIDF_TAG(node, tag) IS_XML_TAG(node, tag, PIDF_NAMESPACE) #define IS_PIDF_ATTR(attr, attr_name) IS_XML_ATTR(attr, attr_name, PIDF_NAMESPACE) bool t_pidf_xml_body::extract_status(void) { assert(xml_doc); xmlNode *root_element = NULL; // Get root root_element = xmlDocGetRootElement(xml_doc); if (!root_element) { log_file->write_report("PIDF document has no root element.", "t_pidf_xml_body::extract_status", LOG_NORMAL, LOG_WARNING); return false; } // Check if root is if (!IS_PIDF_TAG(root_element, "presence")) { log_file->write_report("PIDF document has invalid root element.", "t_pidf_xml_body::extract_status", LOG_NORMAL, LOG_WARNING); return false; } pres_entity.clear(); tuple_id.clear(); basic_status.clear(); // Get presence entity xmlChar *prop_entity = xmlGetProp(root_element, BAD_CAST "entity"); if (prop_entity) { pres_entity = (char *)prop_entity; } else { log_file->write_report("Presence entity is missing.", "t_pidf_xml_body::extract_status", LOG_NORMAL, LOG_WARNING); } xmlNode *child = root_element->children; // Process children of root. for (xmlNode *cur_node = child; cur_node; cur_node = cur_node->next) { // Process tuple if (IS_PIDF_TAG(cur_node, "tuple")) { process_pidf_tuple(cur_node); // Process the first tuple and then stop. // Currently there is no support for multiple tuples // or additional elements. break; } } return true; } void t_pidf_xml_body::process_pidf_tuple(xmlNode *tuple) { assert(tuple); // Get tuple id. xmlChar *id = xmlGetProp(tuple, BAD_CAST "id"); if (id) { tuple_id = (char *)id; } else { log_file->write_report("Tuple id is missing.", "t_pidf_xml_body::process_pidf_tuple", LOG_NORMAL, LOG_WARNING); } // Find status element xmlNode *child = tuple->children; for (xmlNode *cur_node = child; cur_node; cur_node = cur_node->next) { // Process status if (IS_PIDF_TAG(cur_node, "status")) { process_pidf_status(cur_node); break; } } } void t_pidf_xml_body::process_pidf_status(xmlNode *status) { assert(status); xmlNode *child = status->children; for (xmlNode *cur_node = child; cur_node; cur_node = cur_node->next) { // Process status if (IS_PIDF_TAG(cur_node, "basic")) { process_pidf_basic(cur_node); break; } } } void t_pidf_xml_body::process_pidf_basic(xmlNode *basic) { assert(basic); xmlNode *child = basic->children; if (child && child->type == XML_TEXT_NODE) { basic_status = tolower((char*)child->content); } else { log_file->write_report(" element has no content.", "t_pidf_xml_body::process_pidf_basic", LOG_NORMAL, LOG_WARNING); } } void t_pidf_xml_body::create_xml_doc(const string &xml_version, const string &charset) { t_sip_body_xml::create_xml_doc(xml_version, charset); // presence xmlNode *node_presence = xmlNewNode(NULL, BAD_CAST "presence"); xmlNs *ns_pidf = xmlNewNs(node_presence, BAD_CAST PIDF_NAMESPACE, NULL); xmlNewProp(node_presence, BAD_CAST "entity", BAD_CAST pres_entity.c_str()); xmlDocSetRootElement(xml_doc, node_presence); // tuple xmlNode *node_tuple = xmlNewChild(node_presence, ns_pidf, BAD_CAST "tuple", NULL); xmlNewProp(node_tuple, BAD_CAST "id", BAD_CAST tuple_id.c_str()); // status xmlNode *node_status = xmlNewChild(node_tuple, ns_pidf, BAD_CAST "status", NULL); // basic xmlNewChild(node_status, ns_pidf, BAD_CAST "basic", BAD_CAST basic_status.c_str()); } t_pidf_xml_body::t_pidf_xml_body() : t_sip_body_xml () {} t_sip_body *t_pidf_xml_body::copy(void) const { t_pidf_xml_body *body = new t_pidf_xml_body(*this); MEMMAN_NEW(body); // Clear the xml_doc pointer in the new body, as a copy of the // XML document must be copied to the body. body->xml_doc = NULL; copy_xml_doc(body); return body; } t_body_type t_pidf_xml_body::get_type(void) const { return BODY_PIDF_XML; } t_media t_pidf_xml_body::get_media(void) const { return t_media("application", "pidf+xml"); } string t_pidf_xml_body::get_pres_entity(void) const { return pres_entity; } string t_pidf_xml_body::get_tuple_id(void) const { return tuple_id; } string t_pidf_xml_body::get_basic_status(void) const { return basic_status; } void t_pidf_xml_body::set_pres_entity(const string &_pres_entity) { clear_xml_doc(); pres_entity = _pres_entity; } void t_pidf_xml_body::set_tuple_id(const string &_tuple_id) { clear_xml_doc(); tuple_id = _tuple_id; } void t_pidf_xml_body::set_basic_status(const string &_basic_status) { clear_xml_doc(); basic_status = _basic_status; } bool t_pidf_xml_body::parse(const string &s) { if (t_sip_body_xml::parse(s)) { if (!extract_status()) { MEMMAN_DELETE(xml_doc); xmlFreeDoc(xml_doc); xml_doc = NULL; } } return (xml_doc != NULL); }