Change the way the namespaces are handled in the XmlNode class

This commit is contained in:
Florent Le Coz
2014-05-28 17:40:45 +02:00
parent a350caf6e0
commit 1c93afc9a7
5 changed files with 57 additions and 44 deletions
+6 -5
View File
@@ -154,14 +154,15 @@ int main()
xml.add_stanza_callback([](const Stanza& stanza) xml.add_stanza_callback([](const Stanza& stanza)
{ {
std::cout << stanza.to_string() << std::endl; std::cout << stanza.to_string() << std::endl;
assert(stanza.get_name() == "stream_ns:stanza"); assert(stanza.get_name() == "stanza");
assert(stanza.get_tag("xmlns") == "stream_ns");
assert(stanza.get_tag("b") == "c"); assert(stanza.get_tag("b") == "c");
assert(stanza.get_inner() == "inner"); assert(stanza.get_inner() == "inner");
assert(stanza.get_tail() == ""); assert(stanza.get_tail() == "");
assert(stanza.get_child("stream_ns:child1") != nullptr); assert(stanza.get_child("child1", "stream_ns") != nullptr);
assert(stanza.get_child("stream_ns:child2") == nullptr); assert(stanza.get_child("child2", "stream_ns") == nullptr);
assert(stanza.get_child("child2_ns:child2") != nullptr); assert(stanza.get_child("child2", "child2_ns") != nullptr);
assert(stanza.get_child("child2_ns:child2")->get_tail() == "tail"); assert(stanza.get_child("child2", "child2_ns")->get_tail() == "tail");
}); });
xml.feed(doc.data(), doc.size(), true); xml.feed(doc.data(), doc.size(), true);
+16 -28
View File
@@ -17,19 +17,6 @@
# include <systemd/sd-daemon.h> # include <systemd/sd-daemon.h>
#endif #endif
#define STREAM_NS "http://etherx.jabber.org/streams"
#define COMPONENT_NS "jabber:component:accept"
#define MUC_NS "http://jabber.org/protocol/muc"
#define MUC_USER_NS MUC_NS"#user"
#define MUC_ADMIN_NS MUC_NS"#admin"
#define DISCO_NS "http://jabber.org/protocol/disco"
#define DISCO_ITEMS_NS DISCO_NS"#items"
#define DISCO_INFO_NS DISCO_NS"#info"
#define XHTMLIM_NS "http://jabber.org/protocol/xhtml-im"
#define STANZA_NS "urn:ietf:params:xml:ns:xmpp-stanzas"
#define STREAMS_NS "urn:ietf:params:xml:ns:xmpp-streams"
#define VERSION_NS "jabber:iq:version"
using namespace std::string_literals; using namespace std::string_literals;
unsigned long XmppComponent::current_id = 0; unsigned long XmppComponent::current_id = 0;
@@ -106,7 +93,8 @@ void XmppComponent::on_connection_failed(const std::string& reason)
void XmppComponent::on_connected() void XmppComponent::on_connected()
{ {
log_info("connected to XMPP server"); log_info("connected to XMPP server");
XmlNode node("stream:stream", nullptr); XmlNode node("", nullptr);
node.set_name("stream:stream");
node["xmlns"] = COMPONENT_NS; node["xmlns"] = COMPONENT_NS;
node["xmlns:stream"] = STREAM_NS; node["xmlns:stream"] = STREAM_NS;
node["to"] = this->served_hostname; node["to"] = this->served_hostname;
@@ -183,7 +171,7 @@ void XmppComponent::on_remote_stream_open(const XmlNode& node)
sprintf(digest + (i*2), "%02x", result[i]); sprintf(digest + (i*2), "%02x", result[i]);
digest[HASH_LENGTH * 2] = '\0'; digest[HASH_LENGTH * 2] = '\0';
Stanza handshake("handshake"); Stanza handshake(COMPONENT_NS":handshake");
handshake.set_inner(digest); handshake.set_inner(digest);
handshake.close(); handshake.close();
this->send_stanza(handshake); this->send_stanza(handshake);
@@ -329,7 +317,7 @@ void XmppComponent::handle_presence(const Stanza& stanza)
} }
else if (type == "unavailable") else if (type == "unavailable")
{ {
XmlNode* status = stanza.get_child(COMPONENT_NS":status"); XmlNode* status = stanza.get_child("status", COMPONENT_NS);
bridge->leave_irc_channel(std::move(iid), status ? std::move(status->get_inner()) : ""); bridge->leave_irc_channel(std::move(iid), status ? std::move(status->get_inner()) : "");
} }
} }
@@ -363,19 +351,19 @@ void XmppComponent::handle_message(const Stanza& stanza)
this->send_stanza_error("message", from, to_str, id, this->send_stanza_error("message", from, to_str, id,
error_type, error_name, ""); error_type, error_name, "");
}); });
XmlNode* body = stanza.get_child(COMPONENT_NS":body"); XmlNode* body = stanza.get_child("body", COMPONENT_NS);
if (type == "groupchat") if (type == "groupchat")
{ {
if (to.resource.empty()) if (to.resource.empty())
if (body && !body->get_inner().empty()) if (body && !body->get_inner().empty())
bridge->send_channel_message(iid, body->get_inner()); bridge->send_channel_message(iid, body->get_inner());
XmlNode* subject = stanza.get_child(COMPONENT_NS":subject"); XmlNode* subject = stanza.get_child("subject", COMPONENT_NS);
if (subject) if (subject)
bridge->set_channel_topic(iid, subject->get_inner()); bridge->set_channel_topic(iid, subject->get_inner());
} }
else if (type == "error") else if (type == "error")
{ {
const XmlNode* error = stanza.get_child(COMPONENT_NS":error"); const XmlNode* error = stanza.get_child("error", COMPONENT_NS);
// Only a set of errors are considered “fatal”. If we encounter one of // Only a set of errors are considered “fatal”. If we encounter one of
// them, we purge (we disconnect the user from all the IRC servers). // them, we purge (we disconnect the user from all the IRC servers).
// We consider this to be true, unless the error condition is // We consider this to be true, unless the error condition is
@@ -440,9 +428,9 @@ void XmppComponent::handle_iq(const Stanza& stanza)
if (type == "set") if (type == "set")
{ {
XmlNode* query; XmlNode* query;
if ((query = stanza.get_child(MUC_ADMIN_NS":query"))) if ((query = stanza.get_child("query", MUC_ADMIN_NS)))
{ {
const XmlNode* child = query->get_child(MUC_ADMIN_NS":item"); const XmlNode* child = query->get_child("item", MUC_ADMIN_NS);
if (child) if (child)
{ {
std::string nick = child->get_tag("nick"); std::string nick = child->get_tag("nick");
@@ -450,7 +438,7 @@ void XmppComponent::handle_iq(const Stanza& stanza)
if (!nick.empty() && role == "none") if (!nick.empty() && role == "none")
{ // This is a kick { // This is a kick
std::string reason; std::string reason;
XmlNode* reason_el = child->get_child(MUC_ADMIN_NS":reason"); XmlNode* reason_el = child->get_child("reason", MUC_ADMIN_NS);
if (reason_el) if (reason_el)
reason = reason_el->get_inner(); reason = reason_el->get_inner();
Iid iid(to.local); Iid iid(to.local);
@@ -463,7 +451,7 @@ void XmppComponent::handle_iq(const Stanza& stanza)
else if (type == "get") else if (type == "get")
{ {
XmlNode* query; XmlNode* query;
if ((query = stanza.get_child(DISCO_INFO_NS":query"))) if ((query = stanza.get_child("query", DISCO_INFO_NS)))
{ // Disco info { // Disco info
if (to_str == this->served_hostname) if (to_str == this->served_hostname)
{ // On the gateway itself { // On the gateway itself
@@ -476,11 +464,11 @@ void XmppComponent::handle_iq(const Stanza& stanza)
{ {
stanza_error.disable(); stanza_error.disable();
XmlNode* query; XmlNode* query;
if ((query = stanza.get_child(VERSION_NS":query"))) if ((query = stanza.get_child("query", VERSION_NS)))
{ {
XmlNode* name_node = query->get_child(VERSION_NS":name"); XmlNode* name_node = query->get_child("name", VERSION_NS);
XmlNode* version_node = query->get_child(VERSION_NS":version"); XmlNode* version_node = query->get_child("version", VERSION_NS);
XmlNode* os_node = query->get_child(VERSION_NS":os"); XmlNode* os_node = query->get_child("os", VERSION_NS);
std::string name; std::string name;
std::string version; std::string version;
std::string os; std::string os;
@@ -500,7 +488,7 @@ void XmppComponent::handle_iq(const Stanza& stanza)
void XmppComponent::handle_error(const Stanza& stanza) void XmppComponent::handle_error(const Stanza& stanza)
{ {
XmlNode* text = stanza.get_child(STREAMS_NS":text"); XmlNode* text = stanza.get_child("text", STREAMS_NS);
std::string error_message("Unspecified error"); std::string error_message("Unspecified error");
if (text) if (text)
error_message = text->get_inner(); error_message = text->get_inner();
+14
View File
@@ -9,6 +9,20 @@
#include <memory> #include <memory>
#include <string> #include <string>
#define STREAM_NS "http://etherx.jabber.org/streams"
#define COMPONENT_NS "jabber:component:accept"
#define MUC_NS "http://jabber.org/protocol/muc"
#define MUC_USER_NS MUC_NS"#user"
#define MUC_ADMIN_NS MUC_NS"#admin"
#define DISCO_NS "http://jabber.org/protocol/disco"
#define DISCO_ITEMS_NS DISCO_NS"#items"
#define DISCO_INFO_NS DISCO_NS"#info"
#define XHTMLIM_NS "http://jabber.org/protocol/xhtml-im"
#define STANZA_NS "urn:ietf:params:xml:ns:xmpp-stanzas"
#define STREAMS_NS "urn:ietf:params:xml:ns:xmpp-streams"
#define VERSION_NS "jabber:iq:version"
#define ADHOC_NS "http://jabber.org/protocol/commands"
/** /**
* An XMPP component, communicating with an XMPP server using the protocole * An XMPP component, communicating with an XMPP server using the protocole
* described in XEP-0114: Jabber Component Protocol * described in XEP-0114: Jabber Component Protocol
+18 -9
View File
@@ -84,10 +84,18 @@ std::string xml_unescape(const std::string& data)
} }
XmlNode::XmlNode(const std::string& name, XmlNode* parent): XmlNode::XmlNode(const std::string& name, XmlNode* parent):
name(name),
parent(parent), parent(parent),
closed(false) 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::XmlNode(const std::string& name):
@@ -144,11 +152,11 @@ std::string XmlNode::get_tail() const
return xml_unescape(this->tail); return xml_unescape(this->tail);
} }
XmlNode* XmlNode::get_child(const std::string& name) const XmlNode* XmlNode::get_child(const std::string& name, const std::string& xmlns) const
{ {
for (auto& child: this->children) for (auto& child: this->children)
{ {
if (child->name == name) if (child->name == name && child->get_tag("xmlns") == xmlns)
return child; return child;
} }
return nullptr; return nullptr;
@@ -184,13 +192,14 @@ XmlNode* XmlNode::get_parent() const
return this->parent; return this->parent;
} }
void XmlNode::set_name(const std::string& name)
{
this->name = name;
}
const std::string XmlNode::get_name() const const std::string XmlNode::get_name() const
{ {
const std::vector<std::string> splited = utils::split(this->name, ':', false); return this->name;
if (splited.empty())
return "";
const std::string res = splited.back();
return res;
} }
std::string XmlNode::to_string() const std::string XmlNode::to_string() const
@@ -209,7 +218,7 @@ std::string XmlNode::to_string() const
res += child->to_string(); res += child->to_string();
if (this->closed) if (this->closed)
{ {
res += "</" + this->name + ">"; res += "</" + this->get_name() + ">";
} }
} }
res += utils::remove_invalid_xml_chars(this->tail); res += utils::remove_invalid_xml_chars(this->tail);
+2 -1
View File
@@ -69,7 +69,7 @@ public:
/** /**
* Get a pointer to the first child element with that name * Get a pointer to the first child element with that name
*/ */
XmlNode* get_child(const std::string& name) const; XmlNode* get_child(const std::string& name, const std::string& xmlns) const;
/** /**
* Add a node child to this node. Assign this node to the child’s parent. * Add a node child to this node. Assign this node to the child’s parent.
* Returns a pointer to the newly added child. * Returns a pointer to the newly added child.
@@ -87,6 +87,7 @@ public:
*/ */
void close(); void close();
XmlNode* get_parent() const; XmlNode* get_parent() const;
void set_name(const std::string& name);
const std::string get_name() const; const std::string get_name() const;
/** /**
* Serialize the stanza into a string * Serialize the stanza into a string