summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt3
-rw-r--r--src/xmpp/jid.cpp94
-rw-r--r--src/xmpp/jid.hpp36
-rw-r--r--src/xmpp/xmpp_parser.cpp169
-rw-r--r--src/xmpp/xmpp_parser.hpp126
-rw-r--r--src/xmpp/xmpp_stanza.cpp274
-rw-r--r--src/xmpp/xmpp_stanza.hpp160
7 files changed, 0 insertions, 862 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 29d3c74..617c113 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -76,9 +76,6 @@ include_directories(${ICONV_INCLUDE_DIRS})
include_directories(${LIBUUID_INCLUDE_DIRS})
# If they are found in louloulibs CMakeLists.txt, we inherite these values
-if(LIBIDN_FOUND)
- include_directories(${LIBIDN_INCLUDE_DIRS})
-endif()
if(SYSTEMD_FOUND)
include_directories(${SYSTEMD_INCLUDE_DIRS})
endif()
diff --git a/src/xmpp/jid.cpp b/src/xmpp/jid.cpp
deleted file mode 100644
index 6149ceb..0000000
--- a/src/xmpp/jid.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-#include <xmpp/jid.hpp>
-#include <cstring>
-#include <map>
-
-#include <louloulibs.h>
-#ifdef LIBIDN_FOUND
- #include <stringprep.h>
-#endif
-
-#include <logger/logger.hpp>
-
-Jid::Jid(const std::string& jid)
-{
- std::string::size_type slash = jid.find('/');
- if (slash != std::string::npos)
- {
- this->resource = jid.substr(slash + 1);
- }
-
- std::string::size_type at = jid.find('@');
- if (at != std::string::npos && at < slash)
- {
- this->local = jid.substr(0, at);
- at++;
- }
- else
- at = 0;
-
- this->domain = jid.substr(at, slash - at);
-}
-
-#include <iostream>
-
-static constexpr size_t max_jid_part_len = 1023;
-
-std::string jidprep(const std::string& original)
-{
-#ifdef LIBIDN_FOUND
- using CacheType = std::map<std::string, std::string>;
- static CacheType cache;
- std::pair<CacheType::iterator, bool> cached = cache.insert({original, {}});
- if (std::get<1>(cached) == false)
- { // Insertion failed: the result is already in the cache, return it
- return std::get<0>(cached)->second;
- }
-
- const std::string error_msg("Failed to convert " + original + " into a valid JID:");
- Jid jid(original);
-
- char local[max_jid_part_len] = {};
- memcpy(local, jid.local.data(), jid.local.size());
- Stringprep_rc rc = static_cast<Stringprep_rc>(::stringprep(local, max_jid_part_len,
- static_cast<Stringprep_profile_flags>(0), stringprep_xmpp_nodeprep));
- if (rc != STRINGPREP_OK)
- {
- log_error(error_msg + stringprep_strerror(rc));
- return "";
- }
-
- char domain[max_jid_part_len] = {};
- memcpy(domain, jid.domain.data(), jid.domain.size());
- rc = static_cast<Stringprep_rc>(::stringprep(domain, max_jid_part_len,
- static_cast<Stringprep_profile_flags>(0), stringprep_nameprep));
- if (rc != STRINGPREP_OK)
- {
- log_error(error_msg + stringprep_strerror(rc));
- return "";
- }
-
- // If there is no resource, stop here
- if (jid.resource.empty())
- {
- std::get<0>(cached)->second = std::string(local) + "@" + domain;
- return std::get<0>(cached)->second;
- }
-
- // Otherwise, also process the resource part
- char resource[max_jid_part_len] = {};
- memcpy(resource, jid.resource.data(), jid.resource.size());
- rc = static_cast<Stringprep_rc>(::stringprep(resource, max_jid_part_len,
- static_cast<Stringprep_profile_flags>(0), stringprep_xmpp_resourceprep));
- if (rc != STRINGPREP_OK)
- {
- log_error(error_msg + stringprep_strerror(rc));
- return "";
- }
- std::get<0>(cached)->second = std::string(local) + "@" + domain + "/" + resource;
- return std::get<0>(cached)->second;
-
-#else
- (void)original;
- return "";
-#endif
-}
diff --git a/src/xmpp/jid.hpp b/src/xmpp/jid.hpp
deleted file mode 100644
index b6975a2..0000000
--- a/src/xmpp/jid.hpp
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef JID_INCLUDED
-# define JID_INCLUDED
-
-#include <string>
-
-/**
- * Parse a JID into its different subart
- */
-class Jid
-{
-public:
- explicit Jid(const std::string& jid);
-
- std::string domain;
- std::string local;
- std::string resource;
-
-private:
- Jid(const Jid&) = delete;
- Jid(Jid&&) = delete;
- Jid& operator=(const Jid&) = delete;
- Jid& operator=(Jid&&) = delete;
-};
-
-/**
- * Prepare the given UTF-8 string according to the XMPP node stringprep
- * identifier profile. This is used to send properly-formed JID to the XMPP
- * server.
- *
- * If the stringprep library is not found, we return an empty string. When
- * this function is used, the result must always be checked for an empty
- * value, and if this is the case it must not be used as a JID.
- */
-std::string jidprep(const std::string& original);
-
-#endif // JID_INCLUDED
diff --git a/src/xmpp/xmpp_parser.cpp b/src/xmpp/xmpp_parser.cpp
deleted file mode 100644
index 6bb0d28..0000000
--- a/src/xmpp/xmpp_parser.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-#include <xmpp/xmpp_parser.hpp>
-#include <xmpp/xmpp_stanza.hpp>
-
-#include <logger/logger.hpp>
-
-/**
- * Expat handlers. Called by the Expat library, never by ourself.
- * They just forward the call to the XmppParser corresponding methods.
- */
-
-static void start_element_handler(void* user_data, const XML_Char* name, const XML_Char** atts)
-{
- static_cast<XmppParser*>(user_data)->start_element(name, atts);
-}
-
-static void end_element_handler(void* user_data, const XML_Char* name)
-{
- static_cast<XmppParser*>(user_data)->end_element(name);
-}
-
-static void character_data_handler(void *user_data, const XML_Char *s, int len)
-{
- static_cast<XmppParser*>(user_data)->char_data(s, len);
-}
-
-/**
- * XmppParser class
- */
-
-XmppParser::XmppParser():
- level(0),
- current_node(nullptr)
-{
- this->init_xml_parser();
-}
-
-void XmppParser::init_xml_parser()
-{
- // Create the expat parser
- this->parser = XML_ParserCreateNS("UTF-8", ':');
- XML_SetUserData(this->parser, static_cast<void*>(this));
-
- // Install Expat handlers
- XML_SetElementHandler(this->parser, &start_element_handler, &end_element_handler);
- XML_SetCharacterDataHandler(this->parser, &character_data_handler);
-}
-
-XmppParser::~XmppParser()
-{
- if (this->current_node)
- delete this->current_node;
- XML_ParserFree(this->parser);
-}
-
-int XmppParser::feed(const char* data, const int len, const bool is_final)
-{
- int res = XML_Parse(this->parser, data, len, is_final);
- if (res == XML_STATUS_ERROR &&
- (XML_GetErrorCode(this->parser) != XML_ERROR_FINISHED))
- log_error("Xml_Parse encountered an error: " <<
- XML_ErrorString(XML_GetErrorCode(this->parser)))
- return res;
-}
-
-int XmppParser::parse(const int len, const bool is_final)
-{
- int res = XML_ParseBuffer(this->parser, len, is_final);
- if (res == XML_STATUS_ERROR)
- log_error("Xml_Parsebuffer encountered an error: " <<
- XML_ErrorString(XML_GetErrorCode(this->parser)));
- return res;
-}
-
-void XmppParser::reset()
-{
- XML_ParserFree(this->parser);
- this->init_xml_parser();
- if (this->current_node)
- delete this->current_node;
- this->current_node = nullptr;
- this->level = 0;
-}
-
-void* XmppParser::get_buffer(const size_t size) const
-{
- return XML_GetBuffer(this->parser, static_cast<int>(size));
-}
-
-void XmppParser::start_element(const XML_Char* name, const XML_Char** attribute)
-{
- level++;
-
- XmlNode* new_node = new XmlNode(name, this->current_node);
- if (this->current_node)
- this->current_node->add_child(new_node);
- this->current_node = new_node;
- for (size_t i = 0; attribute[i]; i += 2)
- this->current_node->set_attribute(attribute[i], attribute[i+1]);
- if (this->level == 1)
- this->stream_open_event(*this->current_node);
-}
-
-void XmppParser::end_element(const XML_Char* name)
-{
- (void)name;
- level--;
- this->current_node->close();
- if (level == 1)
- {
- this->stanza_event(*this->current_node);
- }
- if (level == 0)
- {
- this->stream_close_event(*this->current_node);
- delete this->current_node;
- this->current_node = nullptr;
- }
- else
- this->current_node = this->current_node->get_parent();
- if (level == 1)
- this->current_node->delete_all_children();
-}
-
-void XmppParser::char_data(const XML_Char* data, int len)
-{
- if (this->current_node->has_children())
- this->current_node->get_last_child()->add_to_tail(std::string(data, len));
- else
- this->current_node->add_to_inner(std::string(data, len));
-}
-
-void XmppParser::stanza_event(const Stanza& stanza) const
-{
- for (const auto& callback: this->stanza_callbacks)
- {
- try {
- callback(stanza);
- } catch (const std::exception& e) {
- log_debug("Unhandled exception: " << e.what());
- }
- }
-}
-
-void XmppParser::stream_open_event(const XmlNode& node) const
-{
- for (const auto& callback: this->stream_open_callbacks)
- callback(node);
-}
-
-void XmppParser::stream_close_event(const XmlNode& node) const
-{
- for (const auto& callback: this->stream_close_callbacks)
- callback(node);
-}
-
-void XmppParser::add_stanza_callback(std::function<void(const Stanza&)>&& callback)
-{
- this->stanza_callbacks.emplace_back(std::move(callback));
-}
-
-void XmppParser::add_stream_open_callback(std::function<void(const XmlNode&)>&& callback)
-{
- this->stream_open_callbacks.emplace_back(std::move(callback));
-}
-
-void XmppParser::add_stream_close_callback(std::function<void(const XmlNode&)>&& callback)
-{
- this->stream_close_callbacks.emplace_back(std::move(callback));
-}
diff --git a/src/xmpp/xmpp_parser.hpp b/src/xmpp/xmpp_parser.hpp
deleted file mode 100644
index 79c9f8f..0000000
--- a/src/xmpp/xmpp_parser.hpp
+++ /dev/null
@@ -1,126 +0,0 @@
-#ifndef XMPP_PARSER_INCLUDED
-# define XMPP_PARSER_INCLUDED
-
-#include <xmpp/xmpp_stanza.hpp>
-
-#include <functional>
-
-#include <expat.h>
-
-/**
- * A SAX XML parser that builds XML nodes and spawns events when a complete
- * stanza is received (an element of level 2), or when the document is
- * opened/closed (an element of level 1)
- *
- * After a stanza_event has been spawned, we delete the whole stanza. This
- * means that even with a very long document (in XMPP the document is
- * potentially infinite), the memory is never exhausted as long as each
- * stanza is reasonnably short.
- *
- * The element names generated by expat contain the namespace of the
- * element, a colon (':') and then the actual name of the element. To get
- * an element "x" with a namespace of "http://jabber.org/protocol/muc", you
- * just look for an XmlNode named "http://jabber.org/protocol/muc:x"
- *
- * TODO: enforce the size-limit for the stanza (limit the number of childs
- * it can contain). For example forbid the parser going further than level
- * 20 (arbitrary number here), and each XML node to have more than 15 childs
- * (arbitrary number again).
- */
-class XmppParser
-{
-public:
- explicit XmppParser();
- ~XmppParser();
-
-public:
- /**
- * Init the XML parser and install the callbacks
- */
- void init_xml_parser();
- /**
- * Feed the parser with some XML data
- */
- int feed(const char* data, const int len, const bool is_final);
- /**
- * Parse the data placed in the parser buffer
- */
- int parse(const int size, const bool is_final);
- /**
- * Reset the parser, so it can be used from scratch afterward
- */
- void reset();
- /**
- * Get a buffer provided by the xml parser.
- */
- void* get_buffer(const size_t size) const;
- /**
- * Add one callback for the various events that this parser can spawn.
- */
- void add_stanza_callback(std::function<void(const Stanza&)>&& callback);
- void add_stream_open_callback(std::function<void(const XmlNode&)>&& callback);
- void add_stream_close_callback(std::function<void(const XmlNode&)>&& callback);
-
- /**
- * Called when a new XML element has been opened. We instanciate a new
- * XmlNode and set it as our current node. The parent of this new node is
- * the previous "current" node. We have all the element's attributes in
- * this event.
- *
- * We spawn a stream_event with this node if this is a level-1 element.
- */
- void start_element(const XML_Char* name, const XML_Char** attribute);
- /**
- * Called when an XML element has been closed. We close the current_node,
- * set our current_node as the parent of the current_node, and if that was
- * a level-2 element we spawn a stanza_event with this node.
- *
- * And we then delete the stanza (and everything under it, its children,
- * attribute, etc).
- */
- void end_element(const XML_Char* name);
- /**
- * Some inner or tail data has been parsed
- */
- void char_data(const XML_Char* data, int len);
- /**
- * Calls all the stanza_callbacks one by one.
- */
- void stanza_event(const Stanza& stanza) const;
- /**
- * Calls all the stream_open_callbacks one by one. Note: the passed node is not
- * closed yet.
- */
- void stream_open_event(const XmlNode& node) const;
- /**
- * Calls all the stream_close_callbacks one by one.
- */
- void stream_close_event(const XmlNode& node) const;
-
-private:
- /**
- * Expat structure.
- */
- XML_Parser parser;
- /**
- * The current depth in the XML document
- */
- size_t level;
- /**
- * The deepest XML node opened but not yet closed (to which we are adding
- * new children, inner or tail)
- */
- XmlNode* current_node;
- /**
- * A list of callbacks to be called on an *_event, receiving the
- * concerned Stanza/XmlNode.
- */
- std::vector<std::function<void(const Stanza&)>> stanza_callbacks;
- std::vector<std::function<void(const XmlNode&)>> stream_open_callbacks;
- std::vector<std::function<void(const XmlNode&)>> stream_close_callbacks;
-
- XmppParser(const XmppParser&) = delete;
- XmppParser& operator=(const XmppParser&) = delete;
-};
-
-#endif // XMPP_PARSER_INCLUDED
diff --git a/src/xmpp/xmpp_stanza.cpp b/src/xmpp/xmpp_stanza.cpp
deleted file mode 100644
index df19105..0000000
--- a/src/xmpp/xmpp_stanza.cpp
+++ /dev/null
@@ -1,274 +0,0 @@
-#include <xmpp/xmpp_stanza.hpp>
-
-#include <utils/encoding.hpp>
-#include <utils/split.hpp>
-
-#include <stdexcept>
-#include <iostream>
-
-#include <string.h>
-
-std::string xml_escape(const std::string& data)
-{
- std::string res;
- res.reserve(data.size());
- for (size_t pos = 0; pos != data.size(); ++pos)
- {
- switch(data[pos])
- {
- case '&':
- res += "&amp;";
- break;
- case '<':
- res += "&lt;";
- break;
- case '>':
- res += "&gt;";
- break;
- case '\"':
- res += "&quot;";
- break;
- case '\'':
- res += "&apos;";
- break;
- default:
- res += data[pos];
- break;
- }
- }
- return res;
-}
-
-std::string xml_unescape(const std::string& data)
-{
- std::string res;
- res.reserve(data.size());
- const char* str = data.c_str();
- while (str && *str && static_cast<size_t>(str - data.c_str()) < data.size())
- {
- if (*str == '&')
- {
- if (strncmp(str+1, "amp;", 4) == 0)
- {
- res += "&";
- str += 4;
- }
- else if (strncmp(str+1, "lt;", 3) == 0)
- {
- res += "<";
- str += 3;
- }
- else if (strncmp(str+1, "gt;", 3) == 0)
- {
- res += ">";
- str += 3;
- }
- else if (strncmp(str+1, "quot;", 5) == 0)
- {
- res += "\"";
- str += 5;
- }
- else if (strncmp(str+1, "apos;", 5) == 0)
- {
- res += "'";
- str += 5;
- }
- else
- res += "&";
- }
- else
- res += *str;
- str++;
- }
- return res;
-}
-
-XmlNode::XmlNode(const std::string& name, XmlNode* parent):
- parent(parent),
- closed(false)
-{
- // split the namespace and the name
- auto n = name.rfind(":");
- if (n == std::string::npos)
- this->name = name;
- else
- {
- this->name = name.substr(n+1);
- this->attributes["xmlns"] = name.substr(0, n);
- }
-}
-
-XmlNode::XmlNode(const std::string& name):
- XmlNode(name, nullptr)
-{
-}
-
-XmlNode::~XmlNode()
-{
- this->delete_all_children();
-}
-
-void XmlNode::delete_all_children()
-{
- for (auto& child: this->children)
- {
- delete child;
- }
- this->children.clear();
-}
-
-void XmlNode::set_attribute(const std::string& name, const std::string& value)
-{
- this->attributes[name] = value;
-}
-
-void XmlNode::set_tail(const std::string& data)
-{
- this->tail = xml_escape(data);
-}
-
-void XmlNode::add_to_tail(const std::string& data)
-{
- this->tail += xml_escape(data);
-}
-
-void XmlNode::set_inner(const std::string& data)
-{
- this->inner = xml_escape(data);
-}
-
-void XmlNode::add_to_inner(const std::string& data)
-{
- this->inner += xml_escape(data);
-}
-
-std::string XmlNode::get_inner() const
-{
- return xml_unescape(this->inner);
-}
-
-std::string XmlNode::get_tail() const
-{
- return xml_unescape(this->tail);
-}
-
-XmlNode* XmlNode::get_child(const std::string& name, const std::string& xmlns) const
-{
- for (auto& child: this->children)
- {
- if (child->name == name && child->get_tag("xmlns") == xmlns)
- return child;
- }
- return nullptr;
-}
-
-std::vector<XmlNode*> XmlNode::get_children(const std::string& name, const std::string& xmlns) const
-{
- std::vector<XmlNode*> res;
- for (auto& child: this->children)
- {
- if (child->name == name && child->get_tag("xmlns") == xmlns)
- res.push_back(child);
- }
- return res;
-}
-
-XmlNode* XmlNode::add_child(XmlNode* child)
-{
- child->parent = this;
- this->children.push_back(child);
- return child;
-}
-
-XmlNode* XmlNode::add_child(XmlNode&& child)
-{
- XmlNode* new_node = new XmlNode(std::move(child));
- return this->add_child(new_node);
-}
-
-XmlNode* XmlNode::get_last_child() const
-{
- return this->children.back();
-}
-
-void XmlNode::close()
-{
- if (this->closed)
- throw std::runtime_error("Closing an already closed XmlNode");
- this->closed = true;
-}
-
-XmlNode* XmlNode::get_parent() const
-{
- return this->parent;
-}
-
-void XmlNode::set_name(const std::string& name)
-{
- this->name = name;
-}
-
-const std::string XmlNode::get_name() const
-{
- return this->name;
-}
-
-std::string XmlNode::to_string() const
-{
- std::string res("<");
- res += this->name;
- for (const auto& it: this->attributes)
- res += " " + it.first + "='" + sanitize(it.second) + "'";
- if (this->closed && !this->has_children() && this->inner.empty())
- res += "/>";
- else
- {
- res += ">" + sanitize(this->inner);
- for (const auto& child: this->children)
- res += child->to_string();
- if (this->closed)
- {
- res += "</" + this->get_name() + ">";
- }
- }
- res += sanitize(this->tail);
- return res;
-}
-
-bool XmlNode::has_children() const
-{
- return !this->children.empty();
-}
-
-const std::string XmlNode::get_tag(const std::string& name) const
-{
- try
- {
- const auto& value = this->attributes.at(name);
- return value;
- }
- catch (const std::out_of_range& e)
- {
- return "";
- }
-}
-
-bool XmlNode::del_tag(const std::string& name)
-{
- if (this->attributes.erase(name) != 0)
- return true;
- return false;
-}
-
-std::string& XmlNode::operator[](const std::string& name)
-{
- return this->attributes[name];
-}
-
-std::string sanitize(const std::string& data)
-{
- if (utils::is_valid_utf8(data.data()))
- return xml_escape(utils::remove_invalid_xml_chars(data));
- else
- return xml_escape(utils::remove_invalid_xml_chars(utils::convert_to_utf8(data, "ISO-8859-1")));
-}
diff --git a/src/xmpp/xmpp_stanza.hpp b/src/xmpp/xmpp_stanza.hpp
deleted file mode 100644
index f1a6a0f..0000000
--- a/src/xmpp/xmpp_stanza.hpp
+++ /dev/null
@@ -1,160 +0,0 @@
-#ifndef XMPP_STANZA_INCLUDED
-# define XMPP_STANZA_INCLUDED
-
-#include <unordered_map>
-#include <string>
-#include <vector>
-
-std::string xml_escape(const std::string& data);
-std::string xml_unescape(const std::string& data);
-std::string sanitize(const std::string& data);
-
-/**
- * Represent an XML node. It has
- * - A parent XML node (in the case of the first-level nodes, the parent is
- nullptr)
- * - zero, one or more children XML nodes
- * - A name
- * - A map of attributes
- * - inner data (text inside the node)
- * - tail data (text just after the node)
- */
-class XmlNode
-{
-public:
- explicit XmlNode(const std::string& name, XmlNode* parent);
- explicit XmlNode(const std::string& name);
- XmlNode(XmlNode&& node):
- name(std::move(node.name)),
- parent(node.parent),
- closed(node.closed),
- attributes(std::move(node.attributes)),
- children(std::move(node.children)),
- inner(std::move(node.inner)),
- tail(std::move(node.tail))
- {
- node.parent = nullptr;
- }
- /**
- * The copy constructor do not copy the parent attribute. The children
- * nodes are all copied recursively.
- */
- XmlNode(const XmlNode& node):
- name(node.name),
- parent(nullptr),
- closed(node.closed),
- attributes(node.attributes),
- children{},
- inner(node.inner),
- tail(node.tail)
- {
- for (XmlNode* child: node.children)
- {
- XmlNode* child_copy = new XmlNode(*child);
- this->add_child(child_copy);
- }
- }
-
- ~XmlNode();
-
- void delete_all_children();
- void set_attribute(const std::string& name, const std::string& value);
- /**
- * Set the content of the tail, that is the text just after this node
- */
- void set_tail(const std::string& data);
- /**
- * Append the given data to the content of the tail. This exists because
- * the expat library may provide the complete text of an element in more
- * than one call
- */
- void add_to_tail(const std::string& data);
- /**
- * Set the content of the inner, that is the text inside this node.
- */
- void set_inner(const std::string& data);
- /**
- * Append the given data to the content of the inner. For the reason
- * described in add_to_tail comment.
- */
- void add_to_inner(const std::string& data);
- /**
- * Get the content of inner
- */
- std::string get_inner() const;
- /**
- * Get the content of the tail
- */
- std::string get_tail() const;
- /**
- * Get a pointer to the first child element with that name and that xml namespace
- */
- XmlNode* get_child(const std::string& name, const std::string& xmlns) const;
- /**
- * Get a vector of all the children that have that name and that xml namespace.
- */
- std::vector<XmlNode*> get_children(const std::string& name, const std::string& xmlns) const;
- /**
- * Add a node child to this node. Assign this node to the child’s parent.
- * Returns a pointer to the newly added child.
- */
- XmlNode* add_child(XmlNode* child);
- XmlNode* add_child(XmlNode&& child);
- /**
- * Returns the last of the children. If the node doesn't have any child,
- * the behaviour is undefined. The user should make sure this is the case
- * by calling has_children() for example.
- */
- XmlNode* get_last_child() const;
- /**
- * Mark this node as closed, nothing else
- */
- void close();
- XmlNode* get_parent() const;
- void set_name(const std::string& name);
- const std::string get_name() const;
- /**
- * Serialize the stanza into a string
- */
- std::string to_string() const;
- /**
- * Whether or not this node has at least one child (if not, this is a leaf
- * node)
- */
- bool has_children() const;
- /**
- * Gets the value for the given attribute, returns an empty string if the
- * node as no such attribute.
- */
- const std::string get_tag(const std::string& name) const;
- /**
- * Remove the attribute of the node. Does nothing if that attribute is not
- * present. Returns true if the tag was removed, false if it was absent.
- */
- bool del_tag(const std::string& name);
- /**
- * Use this to set an attribute's value, like node["id"] = "12";
- */
- std::string& operator[](const std::string& name);
-
-private:
- std::string name;
- XmlNode* parent;
- bool closed;
- std::unordered_map<std::string, std::string> attributes;
- std::vector<XmlNode*> children;
- std::string inner;
- std::string tail;
-
- XmlNode& operator=(const XmlNode&) = delete;
- XmlNode& operator=(XmlNode&&) = delete;
-};
-
-/**
- * An XMPP stanza is just an XML node of level 2 in the XMPP document (the
- * level 1 ones are the <stream::stream/>, and the ones above 2 are just the
- * content of the stanzas)
- */
-typedef XmlNode Stanza;
-
-#endif // XMPP_STANZA_INCLUDED