Do not use ':' as a namespace separator with expat

Instead use \1, and build our own nodes by explicitely separating the
namespace and the node name.
This commit is contained in:
louiz’
2022-03-10 23:23:47 +01:00
parent 18b6006e30
commit 0061298dd0
9 changed files with 48 additions and 28 deletions
+3 -3
View File
@@ -26,7 +26,7 @@ void PingStep1(XmppComponent&, AdhocSession&, XmlNode& command_node)
void HelloStep1(XmppComponent&, AdhocSession&, XmlNode& command_node) void HelloStep1(XmppComponent&, AdhocSession&, XmlNode& command_node)
{ {
XmlSubNode x(command_node, "jabber:x:data:x"); XmlSubNode x(command_node, "jabber:x:data", "x");
x["type"] = "form"; x["type"] = "form";
XmlSubNode title(x, "title"); XmlSubNode title(x, "title");
title.set_inner("Configure your name."); title.set_inner("Configure your name.");
@@ -65,9 +65,9 @@ void HelloStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node)
} }
} }
command_node.delete_all_children(); command_node.delete_all_children();
XmlSubNode error(command_node, ADHOC_NS":error"); XmlSubNode error(command_node, ADHOC_NS, "error");
error["type"] = "modify"; error["type"] = "modify";
XmlSubNode condition(error, STANZA_NS":bad-request"); XmlSubNode condition(error, STANZA_NS, "bad-request");
session.terminate(); session.terminate();
} }
+6 -6
View File
@@ -36,16 +36,16 @@ XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, co
auto command_it = this->commands.find(node); auto command_it = this->commands.find(node);
if (command_it == this->commands.end()) if (command_it == this->commands.end())
{ {
XmlSubNode error(command_node, ADHOC_NS":error"); XmlSubNode error(command_node, ADHOC_NS, "error");
error["type"] = "cancel"; error["type"] = "cancel";
XmlSubNode condition(error, STANZA_NS":item-not-found"); XmlSubNode condition(error, STANZA_NS, "item-not-found");
} }
else if (command_it->second.is_admin_only() && else if (command_it->second.is_admin_only() &&
!Config::is_in_list("admin", jid.bare())) !Config::is_in_list("admin", jid.bare()))
{ {
XmlSubNode error(command_node, ADHOC_NS":error"); XmlSubNode error(command_node, ADHOC_NS, "error");
error["type"] = "cancel"; error["type"] = "cancel";
XmlSubNode condition(error, STANZA_NS":forbidden"); XmlSubNode condition(error, STANZA_NS, "forbidden");
} }
else else
{ {
@@ -94,9 +94,9 @@ XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, co
} }
else // unsupported action else // unsupported action
{ {
XmlSubNode error(command_node, ADHOC_NS":error"); XmlSubNode error(command_node, ADHOC_NS, "error");
error["type"] = "modify"; error["type"] = "modify";
XmlSubNode condition(error, STANZA_NS":bad-request"); XmlSubNode condition(error, STANZA_NS, "bad-request");
} }
} }
return command_node; return command_node;
+14 -14
View File
@@ -34,7 +34,7 @@ void DisconnectUserStep1(XmppComponent& xmpp_component, AdhocSession&, XmlNode&
{ {
auto& biboumi_component = dynamic_cast<BiboumiComponent&>(xmpp_component); auto& biboumi_component = dynamic_cast<BiboumiComponent&>(xmpp_component);
XmlSubNode x(command_node, "jabber:x:data:x"); XmlSubNode x(command_node, "jabber:x:data", "x");
x["type"] = "form"; x["type"] = "form";
XmlSubNode title(x, "title"); XmlSubNode title(x, "title");
title.set_inner("Disconnect a user from the gateway"); title.set_inner("Disconnect a user from the gateway");
@@ -108,9 +108,9 @@ void DisconnectUserStep2(XmppComponent& xmpp_component, AdhocSession& session, X
return; return;
} }
} }
XmlSubNode error(command_node, ADHOC_NS":error"); XmlSubNode error(command_node, ADHOC_NS, "error");
error["type"] = "modify"; error["type"] = "modify";
XmlSubNode condition(error, STANZA_NS":bad-request"); XmlSubNode condition(error, STANZA_NS, "bad-request");
session.terminate(); session.terminate();
} }
@@ -124,7 +124,7 @@ void ConfigureGlobalStep1(XmppComponent&, AdhocSession& session, XmlNode& comman
auto options = Database::get_global_options(owner.bare()); auto options = Database::get_global_options(owner.bare());
command_node.delete_all_children(); command_node.delete_all_children();
XmlSubNode x(command_node, "jabber:x:data:x"); XmlSubNode x(command_node, "jabber:x:data", "x");
x["type"] = "form"; x["type"] = "form";
XmlSubNode title(x, "title"); XmlSubNode title(x, "title");
title.set_inner("Configure some global default settings."); title.set_inner("Configure some global default settings.");
@@ -220,9 +220,9 @@ void ConfigureGlobalStep2(XmppComponent& xmpp_component, AdhocSession& session,
note.set_inner("Configuration successfully applied."); note.set_inner("Configuration successfully applied.");
return; return;
} }
XmlSubNode error(command_node, ADHOC_NS":error"); XmlSubNode error(command_node, ADHOC_NS, "error");
error["type"] = "modify"; error["type"] = "modify";
XmlSubNode condition(error, STANZA_NS":bad-request"); XmlSubNode condition(error, STANZA_NS, "bad-request");
session.terminate(); session.terminate();
} }
@@ -238,7 +238,7 @@ void ConfigureIrcServerStep1(XmppComponent&, AdhocSession& session, XmlNode& com
auto commands = Database::get_after_connection_commands(options); auto commands = Database::get_after_connection_commands(options);
command_node.delete_all_children(); command_node.delete_all_children();
XmlSubNode x(command_node, "jabber:x:data:x"); XmlSubNode x(command_node, "jabber:x:data", "x");
x["type"] = "form"; x["type"] = "form";
XmlSubNode title(x, "title"); XmlSubNode title(x, "title");
title.set_inner("Configure the IRC server " + server_domain); title.set_inner("Configure the IRC server " + server_domain);
@@ -565,9 +565,9 @@ void ConfigureIrcServerStep2(XmppComponent& xmpp_component, AdhocSession& sessio
note.set_inner("Configuration successfully applied."); note.set_inner("Configuration successfully applied.");
return; return;
} }
XmlSubNode error(command_node, ADHOC_NS":error"); XmlSubNode error(command_node, ADHOC_NS, "error");
error["type"] = "modify"; error["type"] = "modify";
XmlSubNode condition(error, STANZA_NS":bad-request"); XmlSubNode condition(error, STANZA_NS, "bad-request");
session.terminate(); session.terminate();
} }
@@ -586,7 +586,7 @@ void insert_irc_channel_configuration_form(XmlNode& node, const Jid& requester,
auto options = Database::get_irc_channel_options_with_server_default(requester.local + "@" + requester.domain, auto options = Database::get_irc_channel_options_with_server_default(requester.local + "@" + requester.domain,
iid.get_server(), iid.get_local()); iid.get_server(), iid.get_local());
node.delete_all_children(); node.delete_all_children();
XmlSubNode x(node, "jabber:x:data:x"); XmlSubNode x(node, "jabber:x:data", "x");
x["type"] = "form"; x["type"] = "form";
XmlSubNode title(x, "title"); XmlSubNode title(x, "title");
title.set_inner("Configure the IRC channel " + iid.get_local() + " on server " + iid.get_server()); title.set_inner("Configure the IRC channel " + iid.get_local() + " on server " + iid.get_server());
@@ -671,9 +671,9 @@ void ConfigureIrcChannelStep2(XmppComponent& xmpp_component, AdhocSession& sessi
} }
else else
{ {
XmlSubNode error(command_node, ADHOC_NS":error"); XmlSubNode error(command_node, ADHOC_NS, "error");
error["type"] = "modify"; error["type"] = "modify";
XmlSubNode condition(error, STANZA_NS":bad-request"); XmlSubNode condition(error, STANZA_NS, "bad-request");
session.terminate(); session.terminate();
} }
} }
@@ -749,7 +749,7 @@ void DisconnectUserFromServerStep1(XmppComponent& xmpp_component, AdhocSession&
{ // Send a form to select the user to disconnect { // Send a form to select the user to disconnect
auto& biboumi_component = dynamic_cast<BiboumiComponent&>(xmpp_component); auto& biboumi_component = dynamic_cast<BiboumiComponent&>(xmpp_component);
XmlSubNode x(command_node, "jabber:x:data:x"); XmlSubNode x(command_node, "jabber:x:data", "x");
x["type"] = "form"; x["type"] = "form";
XmlSubNode title(x, "title"); XmlSubNode title(x, "title");
title.set_inner("Disconnect a user from selected IRC servers"); title.set_inner("Disconnect a user from selected IRC servers");
@@ -794,7 +794,7 @@ void DisconnectUserFromServerStep2(XmppComponent& xmpp_component, AdhocSession&
command_node.delete_all_children(); command_node.delete_all_children();
auto& biboumi_component = dynamic_cast<BiboumiComponent&>(xmpp_component); auto& biboumi_component = dynamic_cast<BiboumiComponent&>(xmpp_component);
XmlSubNode x(command_node, "jabber:x:data:x"); XmlSubNode x(command_node, "jabber:x:data", "x");
x["type"] = "form"; x["type"] = "form";
XmlSubNode title(x, "title"); XmlSubNode title(x, "title");
title.set_inner("Disconnect a user from selected IRC servers"); title.set_inner("Disconnect a user from selected IRC servers");
+1 -1
View File
@@ -175,7 +175,7 @@ void XmppComponent::on_stanza(const Stanza& stanza)
void XmppComponent::send_stream_error(const std::string& name, const std::string& explanation) void XmppComponent::send_stream_error(const std::string& name, const std::string& explanation)
{ {
Stanza node("stream:error"); Stanza node("stream", "error");
{ {
XmlSubNode error(node, name); XmlSubNode error(node, name);
error["xmlns"] = STREAM_NS; error["xmlns"] = STREAM_NS;
+1 -1
View File
@@ -38,7 +38,7 @@ XmppParser::XmppParser():
void XmppParser::init_xml_parser() void XmppParser::init_xml_parser()
{ {
// Create the expat parser // Create the expat parser
this->parser = XML_ParserCreateNS("UTF-8", ':'); this->parser = XML_ParserCreateNS("UTF-8", '\1');
XML_SetUserData(this->parser, static_cast<void*>(this)); XML_SetUserData(this->parser, static_cast<void*>(this));
// Install Expat handlers // Install Expat handlers
+2 -2
View File
@@ -18,9 +18,9 @@
* stanza is reasonnably short. * stanza is reasonnably short.
* *
* The element names generated by expat contain the namespace of the * The element names generated by expat contain the namespace of the
* element, a colon (':') and then the actual name of the element. To get * element, a \1 separator and then the actual name of the element. To get
* an element "x" with a namespace of "http://jabber.org/protocol/muc", you * 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" * just look for an XmlNode named "http://jabber.org/protocol/muc\1x"
* *
* TODO: enforce the size-limit for the stanza (limit the number of childs * 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 * it can contain). For example forbid the parser going further than level
+13 -1
View File
@@ -52,7 +52,7 @@ XmlNode::XmlNode(const std::string& name, XmlNode* parent):
parent(parent) parent(parent)
{ {
// split the namespace and the name // split the namespace and the name
auto n = name.rfind(':'); auto n = name.rfind('\1');
if (n == std::string::npos) if (n == std::string::npos)
this->name = name; this->name = name;
else else
@@ -67,6 +67,18 @@ XmlNode::XmlNode(const std::string& name):
{ {
} }
XmlNode::XmlNode(const std::string& xmlns, const std::string& name, XmlNode* parent):
name(name),
parent(parent)
{
this->attributes["xmlns"] = xmlns;
}
XmlNode::XmlNode(const std::string& xmlns, const std::string& name):
XmlNode(xmlns, name, nullptr)
{
}
void XmlNode::delete_all_children() void XmlNode::delete_all_children()
{ {
this->children.clear(); this->children.clear();
+6
View File
@@ -25,6 +25,8 @@ class XmlNode
public: public:
explicit XmlNode(const std::string& name, XmlNode* parent); explicit XmlNode(const std::string& name, XmlNode* parent);
explicit XmlNode(const std::string& name); explicit XmlNode(const std::string& name);
explicit XmlNode(const std::string& xmlns, const std::string& name, XmlNode* parent);
explicit XmlNode(const std::string& xmlns, const std::string& name);
/** /**
* The copy constructor does not copy the parent attribute. The children * The copy constructor does not copy the parent attribute. The children
* nodes are all copied recursively. * nodes are all copied recursively.
@@ -150,6 +152,10 @@ public:
XmlNode(name), XmlNode(name),
parent_to_add(parent_ref) parent_to_add(parent_ref)
{} {}
XmlSubNode(XmlNode& parent_ref, const std::string& xmlns, const std::string& name):
XmlNode(xmlns, name),
parent_to_add(parent_ref)
{}
~XmlSubNode() ~XmlSubNode()
{ {
+2
View File
@@ -67,6 +67,8 @@ TEST_CASE("substanzas")
CHECK(!d.has_children()); CHECK(!d.has_children());
} }
CHECK(b.has_children()); CHECK(b.has_children());
XmlSubNode e(a, "namespace", "name");
CHECK(e.get_tag("xmlns") == "namespace");
} }
CHECK(a.has_children()); CHECK(a.has_children());
} }