1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
|
From 0061298dd0945f7f67e7fa340c6649b179c804d5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?louiz=E2=80=99?= <louiz@louiz.org>
Date: Thu, 10 Mar 2022 23:23:47 +0100
Subject: [PATCH] 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.
---
src/xmpp/adhoc_command.cpp | 6 +++---
src/xmpp/adhoc_commands_handler.cpp | 12 ++++++------
src/xmpp/biboumi_adhoc_commands.cpp | 28 ++++++++++++++--------------
src/xmpp/xmpp_component.cpp | 2 +-
src/xmpp/xmpp_parser.cpp | 2 +-
src/xmpp/xmpp_parser.hpp | 4 ++--
src/xmpp/xmpp_stanza.cpp | 14 +++++++++++++-
src/xmpp/xmpp_stanza.hpp | 6 ++++++
tests/xmpp.cpp | 2 ++
9 files changed, 48 insertions(+), 28 deletions(-)
diff --git a/src/xmpp/adhoc_command.cpp b/src/xmpp/adhoc_command.cpp
index fbf4ce200b82..f8c8e4f146d6 100644
--- a/src/xmpp/adhoc_command.cpp
+++ b/src/xmpp/adhoc_command.cpp
@@ -26,7 +26,7 @@ void PingStep1(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";
XmlSubNode title(x, "title");
title.set_inner("Configure your name.");
@@ -65,9 +65,9 @@ void HelloStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node)
}
}
command_node.delete_all_children();
- XmlSubNode error(command_node, ADHOC_NS":error");
+ XmlSubNode error(command_node, ADHOC_NS, "error");
error["type"] = "modify";
- XmlSubNode condition(error, STANZA_NS":bad-request");
+ XmlSubNode condition(error, STANZA_NS, "bad-request");
session.terminate();
}
diff --git a/src/xmpp/adhoc_commands_handler.cpp b/src/xmpp/adhoc_commands_handler.cpp
index ff4c1e5506fb..7a84b2e11a45 100644
--- a/src/xmpp/adhoc_commands_handler.cpp
+++ b/src/xmpp/adhoc_commands_handler.cpp
@@ -36,16 +36,16 @@ XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, co
auto command_it = this->commands.find(node);
if (command_it == this->commands.end())
{
- XmlSubNode error(command_node, ADHOC_NS":error");
+ XmlSubNode error(command_node, ADHOC_NS, "error");
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() &&
!Config::is_in_list("admin", jid.bare()))
{
- XmlSubNode error(command_node, ADHOC_NS":error");
+ XmlSubNode error(command_node, ADHOC_NS, "error");
error["type"] = "cancel";
- XmlSubNode condition(error, STANZA_NS":forbidden");
+ XmlSubNode condition(error, STANZA_NS, "forbidden");
}
else
{
@@ -94,9 +94,9 @@ XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, co
}
else // unsupported action
{
- XmlSubNode error(command_node, ADHOC_NS":error");
+ XmlSubNode error(command_node, ADHOC_NS, "error");
error["type"] = "modify";
- XmlSubNode condition(error, STANZA_NS":bad-request");
+ XmlSubNode condition(error, STANZA_NS, "bad-request");
}
}
return command_node;
diff --git a/src/xmpp/biboumi_adhoc_commands.cpp b/src/xmpp/biboumi_adhoc_commands.cpp
index 792955c37ec7..aea316d64042 100644
--- a/src/xmpp/biboumi_adhoc_commands.cpp
+++ b/src/xmpp/biboumi_adhoc_commands.cpp
@@ -34,7 +34,7 @@ void DisconnectUserStep1(XmppComponent& xmpp_component, AdhocSession&, XmlNode&
{
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";
XmlSubNode title(x, "title");
title.set_inner("Disconnect a user from the gateway");
@@ -108,9 +108,9 @@ void DisconnectUserStep2(XmppComponent& xmpp_component, AdhocSession& session, X
return;
}
}
- XmlSubNode error(command_node, ADHOC_NS":error");
+ XmlSubNode error(command_node, ADHOC_NS, "error");
error["type"] = "modify";
- XmlSubNode condition(error, STANZA_NS":bad-request");
+ XmlSubNode condition(error, STANZA_NS, "bad-request");
session.terminate();
}
@@ -124,7 +124,7 @@ void ConfigureGlobalStep1(XmppComponent&, AdhocSession& session, XmlNode& comman
auto options = Database::get_global_options(owner.bare());
command_node.delete_all_children();
- XmlSubNode x(command_node, "jabber:x:data:x");
+ XmlSubNode x(command_node, "jabber:x:data", "x");
x["type"] = "form";
XmlSubNode title(x, "title");
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.");
return;
}
- XmlSubNode error(command_node, ADHOC_NS":error");
+ XmlSubNode error(command_node, ADHOC_NS, "error");
error["type"] = "modify";
- XmlSubNode condition(error, STANZA_NS":bad-request");
+ XmlSubNode condition(error, STANZA_NS, "bad-request");
session.terminate();
}
@@ -238,7 +238,7 @@ void ConfigureIrcServerStep1(XmppComponent&, AdhocSession& session, XmlNode& com
auto commands = Database::get_after_connection_commands(options);
command_node.delete_all_children();
- XmlSubNode x(command_node, "jabber:x:data:x");
+ XmlSubNode x(command_node, "jabber:x:data", "x");
x["type"] = "form";
XmlSubNode title(x, "title");
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.");
return;
}
- XmlSubNode error(command_node, ADHOC_NS":error");
+ XmlSubNode error(command_node, ADHOC_NS, "error");
error["type"] = "modify";
- XmlSubNode condition(error, STANZA_NS":bad-request");
+ XmlSubNode condition(error, STANZA_NS, "bad-request");
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,
iid.get_server(), iid.get_local());
node.delete_all_children();
- XmlSubNode x(node, "jabber:x:data:x");
+ XmlSubNode x(node, "jabber:x:data", "x");
x["type"] = "form";
XmlSubNode title(x, "title");
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
{
- XmlSubNode error(command_node, ADHOC_NS":error");
+ XmlSubNode error(command_node, ADHOC_NS, "error");
error["type"] = "modify";
- XmlSubNode condition(error, STANZA_NS":bad-request");
+ XmlSubNode condition(error, STANZA_NS, "bad-request");
session.terminate();
}
}
@@ -749,7 +749,7 @@ void DisconnectUserFromServerStep1(XmppComponent& xmpp_component, AdhocSession&
{ // Send a form to select the user to disconnect
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";
XmlSubNode title(x, "title");
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();
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";
XmlSubNode title(x, "title");
title.set_inner("Disconnect a user from selected IRC servers");
diff --git a/src/xmpp/xmpp_component.cpp b/src/xmpp/xmpp_component.cpp
index de9a7a631be6..62a98ce3bb2c 100644
--- a/src/xmpp/xmpp_component.cpp
+++ b/src/xmpp/xmpp_component.cpp
@@ -175,7 +175,7 @@ void XmppComponent::on_stanza(const Stanza& stanza)
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);
error["xmlns"] = STREAM_NS;
diff --git a/src/xmpp/xmpp_parser.cpp b/src/xmpp/xmpp_parser.cpp
index 781fe4cd94b0..1f25fa6f982b 100644
--- a/src/xmpp/xmpp_parser.cpp
+++ b/src/xmpp/xmpp_parser.cpp
@@ -38,7 +38,7 @@ XmppParser::XmppParser():
void XmppParser::init_xml_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));
// Install Expat handlers
diff --git a/src/xmpp/xmpp_parser.hpp b/src/xmpp/xmpp_parser.hpp
index ec42f9a326e1..1e5e4e55a875 100644
--- a/src/xmpp/xmpp_parser.hpp
+++ b/src/xmpp/xmpp_parser.hpp
@@ -18,9 +18,9 @@
* 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
+ * 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
- * 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
* it can contain). For example forbid the parser going further than level
diff --git a/src/xmpp/xmpp_stanza.cpp b/src/xmpp/xmpp_stanza.cpp
index 435f33313b09..0103dd71a357 100644
--- a/src/xmpp/xmpp_stanza.cpp
+++ b/src/xmpp/xmpp_stanza.cpp
@@ -52,7 +52,7 @@ XmlNode::XmlNode(const std::string& name, XmlNode* parent):
parent(parent)
{
// split the namespace and the name
- auto n = name.rfind(':');
+ auto n = name.rfind('\1');
if (n == std::string::npos)
this->name = name;
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()
{
this->children.clear();
diff --git a/src/xmpp/xmpp_stanza.hpp b/src/xmpp/xmpp_stanza.hpp
index f4b394814e5b..a706337baca0 100644
--- a/src/xmpp/xmpp_stanza.hpp
+++ b/src/xmpp/xmpp_stanza.hpp
@@ -25,6 +25,8 @@ class XmlNode
public:
explicit XmlNode(const std::string& name, XmlNode* parent);
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
* nodes are all copied recursively.
@@ -150,6 +152,10 @@ public:
XmlNode(name),
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()
{
diff --git a/tests/xmpp.cpp b/tests/xmpp.cpp
index 14c51daa460f..c49c2fda94ea 100644
--- a/tests/xmpp.cpp
+++ b/tests/xmpp.cpp
@@ -67,6 +67,8 @@ TEST_CASE("substanzas")
CHECK(!d.has_children());
}
CHECK(b.has_children());
+ XmlSubNode e(a, "namespace", "name");
+ CHECK(e.get_tag("xmlns") == "namespace");
}
CHECK(a.has_children());
}
--
2.34.1
|