Commit e8f22efe authored by louiz’'s avatar louiz’

XmlNodes are now always closed

Remove the close() method and closed attribute. Remove all the calls to
close().  (Save one bool per XmlNode, yay, and save a few ifs and some
useless function calls. At best it should be unnoticeably faster and lighter
and save a few keystrokes in the future)
parent df006a19
......@@ -25,7 +25,6 @@ void PingStep1(XmppComponent*, AdhocSession&, XmlNode& command_node)
XmlNode note("note");
note["type"] = "info";
note.set_inner("Pong");
note.close();
command_node.add_child(std::move(note));
}
......@@ -35,22 +34,17 @@ void HelloStep1(XmppComponent*, AdhocSession&, XmlNode& command_node)
x["type"] = "form";
XmlNode title("title");
title.set_inner("Configure your name.");
title.close();
x.add_child(std::move(title));
XmlNode instructions("instructions");
instructions.set_inner("Please provide your name.");
instructions.close();
x.add_child(std::move(instructions));
XmlNode name_field("field");
name_field["var"] = "name";
name_field["type"] = "text-single";
name_field["label"] = "Your name";
XmlNode required("required");
required.close();
name_field.add_child(std::move(required));
name_field.close();
x.add_child(std::move(name_field));
x.close();
command_node.add_child(std::move(x));
}
......@@ -75,7 +69,6 @@ void HelloStep2(XmppComponent*, AdhocSession& session, XmlNode& command_node)
XmlNode note("note");
note["type"] = "info";
note.set_inner("Hello "s + value->get_inner() + "!"s);
note.close();
command_node.delete_all_children();
command_node.add_child(std::move(note));
return;
......@@ -86,9 +79,7 @@ void HelloStep2(XmppComponent*, AdhocSession& session, XmlNode& command_node)
XmlNode error(ADHOC_NS":error");
error["type"] = "modify";
XmlNode condition(STANZA_NS":bad-request");
condition.close();
error.add_child(std::move(condition));
error.close();
command_node.add_child(std::move(error));
session.terminate();
}
......@@ -100,6 +91,5 @@ void Reload(XmppComponent*, AdhocSession&, XmlNode& command_node)
XmlNode note("note");
note["type"] = "info";
note.set_inner("Configuration reloaded.");
note.close();
command_node.add_child(std::move(note));
}
......@@ -36,9 +36,7 @@ XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, Xm
XmlNode error(ADHOC_NS":error");
error["type"] = "cancel";
XmlNode condition(STANZA_NS":item-not-found");
condition.close();
error.add_child(std::move(condition));
error.close();
command_node.add_child(std::move(error));
}
else if (command_it->second.is_admin_only() &&
......@@ -47,9 +45,7 @@ XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, Xm
XmlNode error(ADHOC_NS":error");
error["type"] = "cancel";
XmlNode condition(STANZA_NS":forbidden");
condition.close();
error.add_child(std::move(condition));
error.close();
command_node.add_child(std::move(error));
}
else
......@@ -72,9 +68,7 @@ XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, Xm
XmlNode error(ADHOC_NS":error");
error["type"] = "modify";
XmlNode condition(STANZA_NS":bad-request");
condition.close();
error.add_child(std::move(condition));
error.close();
command_node.add_child(std::move(error));
}
else if (action == "execute" || action == "next" || action == "complete")
......@@ -95,9 +89,7 @@ XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, Xm
command_node["status"] = "executing";
XmlNode actions("actions");
XmlNode next("next");
next.close();
actions.add_child(std::move(next));
actions.close();
command_node.add_child(std::move(actions));
}
}
......@@ -112,9 +104,7 @@ XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, Xm
XmlNode error(ADHOC_NS":error");
error["type"] = "modify";
XmlNode condition(STANZA_NS":bad-request");
condition.close();
error.add_child(std::move(condition));
error.close();
command_node.add_child(std::move(error));
}
}
......
......@@ -89,12 +89,9 @@ void XmppComponent::on_connected()
{
log_info("connected to XMPP server");
this->first_connection_try = true;
XmlNode node("", nullptr);
node.set_name("stream:stream");
node["xmlns"] = COMPONENT_NS;
node["xmlns:stream"] = STREAM_NS;
node["to"] = this->served_hostname;
this->send_stanza(node);
this->send_data("<stream:stream to='");
this->send_data(std::string{this->served_hostname});
this->send_data("' xmlns:stream='http://etherx.jabber.org/streams' xmlns='" COMPONENT_NS "'>");
this->doc_open = true;
// We may have some pending data to send: this happens when we try to send
// some data before we are actually connected. We send that data right now, if any
......@@ -152,10 +149,9 @@ void XmppComponent::on_remote_stream_open(const XmlNode& node)
sprintf(digest + (i*2), "%02x", result[i]);
digest[HASH_LENGTH * 2] = '\0';
Stanza handshake(COMPONENT_NS":handshake");
handshake.set_inner(digest);
handshake.close();
this->send_stanza(handshake);
this->send_data("<handshake xmlns='" COMPONENT_NS "'>");
this->send_data(digest);
this->send_data("</handshake>");
}
void XmppComponent::on_remote_stream_close(const XmlNode& node)
......@@ -192,9 +188,7 @@ void XmppComponent::send_stream_error(const std::string& name, const std::string
error["xmlns"] = STREAM_NS;
if (!explanation.empty())
error.set_inner(explanation);
error.close();
node.add_child(std::move(error));
node.close();
this->send_stanza(node);
}
......@@ -220,19 +214,15 @@ void XmppComponent::send_stanza_error(const std::string& kind, const std::string
error["type"] = error_type;
XmlNode inner_error(defined_condition);
inner_error["xmlns"] = STANZA_NS;
inner_error.close();
error.add_child(std::move(inner_error));
if (!text.empty())
{
XmlNode text_node("text");
text_node["xmlns"] = STANZA_NS;
text_node.set_inner(text);
text_node.close();
error.add_child(std::move(text_node));
}
error.close();
node.add_child(std::move(error));
node.close();
this->send_stanza(node);
}
......@@ -295,7 +285,6 @@ void XmppComponent::send_message(const std::string& from, Xmpp::body&& body, con
node["type"] = type;
XmlNode body_node("body");
body_node.set_inner(std::get<0>(body));
body_node.close();
node.add_child(std::move(body_node));
if (std::get<1>(body))
{
......@@ -303,10 +292,8 @@ void XmppComponent::send_message(const std::string& from, Xmpp::body&& body, con
html["xmlns"] = XHTMLIM_NS;
// Pass the ownership of the pointer to this xmlnode
html.add_child(std::get<1>(body).release());
html.close();
node.add_child(std::move(html));
}
node.close();
this->send_stanza(node);
}
......@@ -336,19 +323,15 @@ void XmppComponent::send_user_join(const std::string& from,
if (!preped_jid.empty())
item["jid"] = preped_jid;
}
item.close();
x.add_child(std::move(item));
if (self)
{
XmlNode status("status");
status["code"] = "110";
status.close();
x.add_child(std::move(status));
}
x.close();
node.add_child(std::move(x));
node.close();
this->send_stanza(node);
}
......@@ -365,14 +348,12 @@ void XmppComponent::send_invalid_room_error(const std::string& muc_name,
presence["type"] = "error";
XmlNode x("x");
x["xmlns"] = MUC_NS;
x.close();
presence.add_child(std::move(x));
XmlNode error("error");
error["by"] = muc_name + "@" + this->served_hostname;
error["type"] = "cancel";
XmlNode item_not_found("item-not-found");
item_not_found["xmlns"] = STANZA_NS;
item_not_found.close();
error.add_child(std::move(item_not_found));
XmlNode text("text");
text["xmlns"] = STANZA_NS;
......@@ -380,11 +361,8 @@ void XmppComponent::send_invalid_room_error(const std::string& muc_name,
text.set_inner(muc_name +
" is not a valid IRC channel name. A correct room jid is of the form: #<chan>%<server>@" +
this->served_hostname);
text.close();
error.add_child(std::move(text));
error.close();
presence.add_child(std::move(error));
presence.close();
this->send_stanza(presence);
}
......@@ -396,13 +374,11 @@ void XmppComponent::send_invalid_user_error(const std::string& user_name, const
message["type"] = "error";
XmlNode x("x");
x["xmlns"] = MUC_NS;
x.close();
message.add_child(std::move(x));
XmlNode error("error");
error["type"] = "cancel";
XmlNode item_not_found("item-not-found");
item_not_found["xmlns"] = STANZA_NS;
item_not_found.close();
error.add_child(std::move(item_not_found));
XmlNode text("text");
text["xmlns"] = STANZA_NS;
......@@ -410,11 +386,8 @@ void XmppComponent::send_invalid_user_error(const std::string& user_name, const
text.set_inner(user_name +
" is not a valid IRC user name. A correct user jid is of the form: <nick>!<server>@" +
this->served_hostname);
text.close();
error.add_child(std::move(text));
error.close();
message.add_child(std::move(error));
message.close();
this->send_stanza(message);
}
......@@ -426,9 +399,7 @@ void XmppComponent::send_topic(const std::string& from, Xmpp::body&& topic, cons
message["type"] = "groupchat";
XmlNode subject("subject");
subject.set_inner(std::get<0>(topic));
subject.close();
message.add_child(std::move(subject));
message.close();
this->send_stanza(message);
}
......@@ -443,7 +414,6 @@ void XmppComponent::send_muc_message(const std::string& muc_name, const std::str
message["type"] = "groupchat";
XmlNode body("body");
body.set_inner(std::get<0>(xmpp_body));
body.close();
message.add_child(std::move(body));
if (std::get<1>(xmpp_body))
{
......@@ -451,10 +421,8 @@ void XmppComponent::send_muc_message(const std::string& muc_name, const std::str
html["xmlns"] = XHTMLIM_NS;
// Pass the ownership of the pointer to this xmlnode
html.add_child(std::get<1>(xmpp_body).release());
html.close();
message.add_child(std::move(html));
}
message.close();
this->send_stanza(message);
}
......@@ -471,19 +439,15 @@ void XmppComponent::send_muc_leave(const std::string& muc_name, std::string&& ni
{
XmlNode status("status");
status["code"] = "110";
status.close();
x.add_child(std::move(status));
}
x.close();
presence.add_child(std::move(x));
if (!message_str.empty())
{
XmlNode status("status");
status.set_inner(message_str);
status.close();
presence.add_child(std::move(status));
}
presence.close();
this->send_stanza(presence);
}
......@@ -503,22 +467,17 @@ void XmppComponent::send_nick_change(const std::string& muc_name,
x["xmlns"] = MUC_USER_NS;
XmlNode item("item");
item["nick"] = new_nick;
item.close();
x.add_child(std::move(item));
XmlNode status("status");
status["code"] = "303";
status.close();
x.add_child(std::move(status));
if (self)
{
XmlNode status2("status");
status2["code"] = "110";
status2.close();
x.add_child(std::move(status2));
}
x.close();
presence.add_child(std::move(x));
presence.close();
this->send_stanza(presence);
this->send_user_join(muc_name, new_nick, "", affiliation, role, jid_to, self);
......@@ -542,21 +501,15 @@ void XmppComponent::kick_user(const std::string& muc_name,
XmlNode actor("actor");
actor["nick"] = author;
actor["jid"] = author; // backward compatibility with old clients
actor.close();
item.add_child(std::move(actor));
XmlNode reason("reason");
reason.set_inner(txt);
reason.close();
item.add_child(std::move(reason));
item.close();
x.add_child(std::move(item));
XmlNode status("status");
status["code"] = "307";
status.close();
x.add_child(std::move(status));
x.close();
presence.add_child(std::move(x));
presence.close();
this->send_stanza(presence);
}
......@@ -574,7 +527,6 @@ void XmppComponent::send_presence_error(const std::string& muc_name,
presence["type"] = "error";
XmlNode x("x");
x["xmlns"] = MUC_NS;
x.close();
presence.add_child(std::move(x));
XmlNode error("error");
error["by"] = muc_name + "@" + this->served_hostname;
......@@ -583,11 +535,8 @@ void XmppComponent::send_presence_error(const std::string& muc_name,
error["code"] = error_code;
XmlNode subnode(condition);
subnode["xmlns"] = STANZA_NS;
subnode.close();
error.add_child(std::move(subnode));
error.close();
presence.add_child(std::move(error));
presence.close();
this->send_stanza(presence);
}
......@@ -605,11 +554,8 @@ void XmppComponent::send_affiliation_role_change(const std::string& muc_name,
XmlNode item("item");
item["affiliation"] = affiliation;
item["role"] = role;
item.close();
x.add_child(std::move(item));
x.close();
presence.add_child(std::move(x));
presence.close();
this->send_stanza(presence);
}
......@@ -627,27 +573,21 @@ void XmppComponent::send_version(const std::string& id, const std::string& jid_t
{
XmlNode name("name");
name.set_inner("biboumi");
name.close();
query.add_child(std::move(name));
XmlNode version("version");
version.set_inner(SOFTWARE_VERSION);
version.close();
query.add_child(std::move(version));
XmlNode os("os");
os.set_inner(SYSTEM_NAME);
os.close();
query.add_child(std::move(os));
}
else
{
XmlNode name("name");
name.set_inner(version);
name.close();
query.add_child(std::move(name));
}
query.close();
iq.add_child(std::move(query));
iq.close();
this->send_stanza(iq);
}
......@@ -669,12 +609,9 @@ void XmppComponent::send_adhoc_commands_list(const std::string& id, const std::s
item["jid"] = this->served_hostname;
item["node"] = kv.first;
item["name"] = kv.second.name;
item.close();
query.add_child(std::move(item));
}
query.close();
iq.add_child(std::move(query));
iq.close();
this->send_stanza(iq);
}
......@@ -688,9 +625,7 @@ void XmppComponent::send_iq_version_request(const std::string& from,
iq["to"] = jid_to;
XmlNode query("query");
query["xmlns"] = VERSION_NS;
query.close();
iq.add_child(std::move(query));
iq.close();
this->send_stanza(iq);
}
......@@ -704,7 +639,6 @@ void XmppComponent::send_iq_result(const std::string& id, const std::string& to_
iq["to"] = to_jid;
iq["id"] = id;
iq["type"] = "result";
iq.close();
this->send_stanza(iq);
}
......
......@@ -104,7 +104,6 @@ void XmppParser::end_element(const XML_Char* name)
{
(void)name;
level--;
this->current_node->close();
if (level == 1)
{
this->stanza_event(*this->current_node);
......
......@@ -84,8 +84,7 @@ std::string xml_unescape(const std::string& data)
}
XmlNode::XmlNode(const std::string& name, XmlNode* parent):
parent(parent),
closed(false)
parent(parent)
{
// split the namespace and the name
auto n = name.rfind(":");
......@@ -191,13 +190,6 @@ 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;
......@@ -219,17 +211,14 @@ std::string XmlNode::to_string() const
res += this->name;
for (const auto& it: this->attributes)
res += " " + it.first + "='" + sanitize(it.second) + "'";
if (this->closed && !this->has_children() && this->inner.empty())
if (!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 += "</" + this->get_name() + ">";
}
res += sanitize(this->tail);
return res;
......
......@@ -27,7 +27,6 @@ public:
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)),
......@@ -42,7 +41,6 @@ public:
XmlNode(const XmlNode& node):
name(node.name),
parent(nullptr),
closed(node.closed),
attributes(node.attributes),
children{},
inner(node.inner),
......@@ -106,10 +104,6 @@ public:
* 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;
......@@ -140,7 +134,6 @@ public:
private:
std::string name;
XmlNode* parent;
bool closed;
std::unordered_map<std::string, std::string> attributes;
std::vector<XmlNode*> children;
std::string inner;
......
......@@ -80,7 +80,6 @@ Xmpp::body irc_format_to_xhtmlim(const std::string& s)
else if (s[pos_end] == IRC_FORMAT_NEWLINE_CHAR)
{
XmlNode* br_node = new XmlNode("br");
br_node->close();
current_node->add_child(br_node);
cleaned += '\n';
}
......@@ -126,7 +125,6 @@ Xmpp::body irc_format_to_xhtmlim(const std::string& s)
// close opened span, if any
if (current_node != result.get())
{
current_node->close();
result->add_child(current_node);
current_node = result.get();
}
......@@ -163,12 +161,8 @@ Xmpp::body irc_format_to_xhtmlim(const std::string& s)
current_node->add_to_inner(txt);
if (current_node != result.get())
{
current_node->close();
result->add_child(current_node);
}
result->add_child(current_node);
result->close();
Xmpp::body body_res = std::make_tuple(cleaned, std::move(result));
return body_res;
}
......@@ -10,18 +10,15 @@ void DisconnectUserStep1(XmppComponent* xmpp_component, AdhocSession&, XmlNode&
x["type"] = "form";
XmlNode title("title");
title.set_inner("Disconnect a user from the gateway");
title.close();
x.add_child(std::move(title));
XmlNode instructions("instructions");
instructions.set_inner("Choose a user JID and a quit message");
instructions.close();
x.add_child(std::move(instructions));
XmlNode jids_field("field");
jids_field["var"] = "jids";
jids_field["type"] = "list-multi";
jids_field["label"] = "The JIDs to disconnect";
XmlNode required("required");
required.close();
jids_field.add_child(std::move(required));
for (Bridge* bridge: biboumi_component->get_bridges())
{
......@@ -29,12 +26,9 @@ void DisconnectUserStep1(XmppComponent* xmpp_component, AdhocSession&, XmlNode&
option["label"] = bridge->get_jid();
XmlNode value("value");
value.set_inner(bridge->get_jid());
value.close();
option.add_child(std::move(value));
option.close();
jids_field.add_child(std::move(option));
}
jids_field.close();
x.add_child(std::move(jids_field));
XmlNode message_field("field");
......@@ -43,11 +37,8 @@ void DisconnectUserStep1(XmppComponent* xmpp_component, AdhocSession&, XmlNode&
message_field["label"] = "Quit message";
XmlNode message_value("value");
message_value.set_inner("Disconnected by admin");
message_value.close();
message_field.add_child(std::move(message_value));
message_field.close();
x.add_child(std::move(message_field));
x.close();
command_node.add_child(std::move(x));
}
......@@ -95,7 +86,6 @@ void DisconnectUserStep2(XmppComponent* xmpp_component, AdhocSession& session, X
note.set_inner("1 user has been disconnected.");
else
note.set_inner(std::to_string(num) + " users have been disconnected.");
note.close();
command_node.add_child(std::move(note));
return;
}
......@@ -103,9 +93,7 @@ void DisconnectUserStep2(XmppComponent* xmpp_component, AdhocSession& session, X
XmlNode error(ADHOC_NS":error");
error["type"] = "modify";
XmlNode condition(STANZA_NS":bad-request");
condition.close();
error.add_child(std::move(condition));
error.close();
command_node.add_child(std::move(error));
session.terminate();
}
......@@ -321,7 +321,6 @@ void BiboumiComponent::handle_iq(const Stanza& stanza)
else
response["type"] = "result";
response.add_child(std::move(inner_node));
response.close();
this->send_stanza(response);
stanza_error.disable();
}
......@@ -494,18 +493,14 @@ void BiboumiComponent::send_self_disco_info(const std::string& id, const std::st
identity["category"] = "conference";
identity["type"] = "irc";
identity["name"] = "Biboumi XMPP-IRC gateway";
identity.close();
query.add_child(std::move(identity));
for (const std::string& ns: {DISCO_INFO_NS, MUC_NS, ADHOC_NS})
{
XmlNode feature("feature");
feature["var"] = ns;
feature.close();
query.add_child(std::move(feature));
}
query.close();
iq.add_child(std::move(query));
iq.close();
this->send_stanza(iq);
}
......@@ -519,9 +514,7 @@ void BiboumiComponent::send_iq_version_request(const std::string& from,
iq["to"] = jid_to;
XmlNode query("query");
query["xmlns"] = VERSION_NS;
query.close();
iq.add_child(std::move(query));
iq.close();
this->send_stanza(iq);