Commit 5a5bb7f6 authored by louiz’'s avatar louiz’

Introduce a XmlSubNode class that automatically adds itself into its parent

parent f512c9c6
...@@ -18,30 +18,24 @@ bool AdhocCommand::is_admin_only() const ...@@ -18,30 +18,24 @@ bool AdhocCommand::is_admin_only() const
void PingStep1(XmppComponent&, AdhocSession&, XmlNode& command_node) void PingStep1(XmppComponent&, AdhocSession&, XmlNode& command_node)
{ {
XmlNode note("note"); XmlSubNode note(command_node, "note");
note["type"] = "info"; note["type"] = "info";
note.set_inner("Pong"); note.set_inner("Pong");
command_node.add_child(std::move(note));
} }
void HelloStep1(XmppComponent&, AdhocSession&, XmlNode& command_node) void HelloStep1(XmppComponent&, AdhocSession&, XmlNode& command_node)
{ {
XmlNode x("jabber:x:data:x"); XmlSubNode x(command_node, "jabber:x:data:x");
x["type"] = "form"; x["type"] = "form";
XmlNode title("title"); XmlSubNode title(x, "title");
title.set_inner("Configure your name."); title.set_inner("Configure your name.");
x.add_child(std::move(title)); XmlSubNode instructions(x, "instructions");
XmlNode instructions("instructions");
instructions.set_inner("Please provide your name."); instructions.set_inner("Please provide your name.");
x.add_child(std::move(instructions)); XmlSubNode name_field(x, "field");
XmlNode name_field("field");
name_field["var"] = "name"; name_field["var"] = "name";
name_field["type"] = "text-single"; name_field["type"] = "text-single";
name_field["label"] = "Your name"; name_field["label"] = "Your name";
XmlNode required("required"); XmlSubNode required(name_field, "required");
name_field.add_child(std::move(required));
x.add_child(std::move(name_field));
command_node.add_child(std::move(x));
} }
void HelloStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node) void HelloStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node)
...@@ -60,21 +54,18 @@ void HelloStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node) ...@@ -60,21 +54,18 @@ void HelloStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node)
{ {
if (const XmlNode* value = name_field->get_child("value", "jabber:x:data")) if (const XmlNode* value = name_field->get_child("value", "jabber:x:data"))
{ {
XmlNode note("note"); command_node.delete_all_children();
XmlSubNode note(command_node, "note");
note["type"] = "info"; note["type"] = "info";
note.set_inner("Hello "s + value->get_inner() + "!"s); note.set_inner("Hello "s + value->get_inner() + "!"s);
command_node.delete_all_children();
command_node.add_child(std::move(note));
return; return;
} }
} }
} }
command_node.delete_all_children(); command_node.delete_all_children();
XmlNode error(ADHOC_NS":error"); XmlSubNode error(command_node, ADHOC_NS":error");
error["type"] = "modify"; error["type"] = "modify";
XmlNode condition(STANZA_NS":bad-request"); XmlSubNode condition(error, STANZA_NS":bad-request");
error.add_child(std::move(condition));
command_node.add_child(std::move(error));
session.terminate(); session.terminate();
} }
...@@ -82,8 +73,7 @@ void Reload(XmppComponent&, AdhocSession&, XmlNode& command_node) ...@@ -82,8 +73,7 @@ void Reload(XmppComponent&, AdhocSession&, XmlNode& command_node)
{ {
::reload_process(); ::reload_process();
command_node.delete_all_children(); command_node.delete_all_children();
XmlNode note("note"); XmlSubNode note(command_node, "note");
note["type"] = "info"; note["type"] = "info";
note.set_inner("Configuration reloaded."); note.set_inner("Configuration reloaded.");
command_node.add_child(std::move(note));
} }
...@@ -36,20 +36,16 @@ XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, co ...@@ -36,20 +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())
{ {
XmlNode error(ADHOC_NS":error"); XmlSubNode error(command_node, ADHOC_NS":error");
error["type"] = "cancel"; error["type"] = "cancel";
XmlNode condition(STANZA_NS":item-not-found"); XmlSubNode condition(error, STANZA_NS":item-not-found");
error.add_child(std::move(condition));
command_node.add_child(std::move(error));
} }
else if (command_it->second.is_admin_only() && else if (command_it->second.is_admin_only() &&
Config::get("admin", "") != jid.local + "@" + jid.domain) Config::get("admin", "") != jid.local + "@" + jid.domain)
{ {
XmlNode error(ADHOC_NS":error"); XmlSubNode error(command_node, ADHOC_NS":error");
error["type"] = "cancel"; error["type"] = "cancel";
XmlNode condition(STANZA_NS":forbidden"); XmlSubNode condition(error, STANZA_NS":forbidden");
error.add_child(std::move(condition));
command_node.add_child(std::move(error));
} }
else else
{ {
...@@ -68,11 +64,9 @@ XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, co ...@@ -68,11 +64,9 @@ XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, co
auto session_it = this->sessions.find(std::make_pair(sessionid, executor_jid)); auto session_it = this->sessions.find(std::make_pair(sessionid, executor_jid));
if (session_it == this->sessions.end()) if (session_it == this->sessions.end())
{ {
XmlNode error(ADHOC_NS":error"); XmlSubNode error(command_node, ADHOC_NS":error");
error["type"] = "modify"; error["type"] = "modify";
XmlNode condition(STANZA_NS":bad-request"); XmlSubNode condition(error, STANZA_NS":bad-request");
error.add_child(std::move(condition));
command_node.add_child(std::move(error));
} }
else if (action == "execute" || action == "next" || action == "complete") else if (action == "execute" || action == "next" || action == "complete")
{ {
...@@ -90,10 +84,8 @@ XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, co ...@@ -90,10 +84,8 @@ XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, co
else else
{ {
command_node["status"] = "executing"; command_node["status"] = "executing";
XmlNode actions("actions"); XmlSubNode actions(command_node, "actions");
XmlNode next("next"); XmlSubNode next(actions, "next");
actions.add_child(std::move(next));
command_node.add_child(std::move(actions));
} }
} }
else if (action == "cancel") else if (action == "cancel")
...@@ -104,11 +96,9 @@ XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, co ...@@ -104,11 +96,9 @@ XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, co
} }
else // unsupported action else // unsupported action
{ {
XmlNode error(ADHOC_NS":error"); XmlSubNode error(command_node, ADHOC_NS":error");
error["type"] = "modify"; error["type"] = "modify";
XmlNode condition(STANZA_NS":bad-request"); XmlSubNode condition(error, STANZA_NS":bad-request");
error.add_child(std::move(condition));
command_node.add_child(std::move(error));
} }
} }
return command_node; return command_node;
......
...@@ -172,12 +172,13 @@ void XmppComponent::on_stanza(const Stanza& stanza) ...@@ -172,12 +172,13 @@ 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)
{ {
XmlNode node("stream:error"); Stanza node("stream:error");
XmlNode error(name); {
XmlSubNode error(node, name);
error["xmlns"] = STREAM_NS; error["xmlns"] = STREAM_NS;
if (!explanation.empty()) if (!explanation.empty())
error.set_inner(explanation); error.set_inner(explanation);
node.add_child(std::move(error)); }
this->send_stanza(node); this->send_stanza(node);
} }
...@@ -187,6 +188,7 @@ void XmppComponent::send_stanza_error(const std::string& kind, const std::string ...@@ -187,6 +188,7 @@ void XmppComponent::send_stanza_error(const std::string& kind, const std::string
const bool fulljid) const bool fulljid)
{ {
Stanza node(kind); Stanza node(kind);
{
if (!to.empty()) if (!to.empty())
node["to"] = to; node["to"] = to;
if (!from.empty()) if (!from.empty())
...@@ -199,19 +201,21 @@ void XmppComponent::send_stanza_error(const std::string& kind, const std::string ...@@ -199,19 +201,21 @@ void XmppComponent::send_stanza_error(const std::string& kind, const std::string
if (!id.empty()) if (!id.empty())
node["id"] = id; node["id"] = id;
node["type"] = "error"; node["type"] = "error";
XmlNode error("error"); {
XmlSubNode error(node, "error");
error["type"] = error_type; error["type"] = error_type;
XmlNode inner_error(defined_condition); {
XmlSubNode inner_error(error, defined_condition);
inner_error["xmlns"] = STANZA_NS; inner_error["xmlns"] = STANZA_NS;
error.add_child(std::move(inner_error)); }
if (!text.empty()) if (!text.empty())
{ {
XmlNode text_node("text"); XmlSubNode text_node(error, "text");
text_node["xmlns"] = STANZA_NS; text_node["xmlns"] = STANZA_NS;
text_node.set_inner(text); text_node.set_inner(text);
error.add_child(std::move(text_node));
} }
node.add_child(std::move(error)); }
}
this->send_stanza(node); this->send_stanza(node);
} }
...@@ -264,38 +268,33 @@ void* XmppComponent::get_receive_buffer(const size_t size) const ...@@ -264,38 +268,33 @@ void* XmppComponent::get_receive_buffer(const size_t size) const
void XmppComponent::send_message(const std::string& from, Xmpp::body&& body, const std::string& to, void XmppComponent::send_message(const std::string& from, Xmpp::body&& body, const std::string& to,
const std::string& type, const bool fulljid, const bool nocopy) const std::string& type, const bool fulljid, const bool nocopy)
{ {
XmlNode node("message"); Stanza message("message");
node["to"] = to; {
message["to"] = to;
if (fulljid) if (fulljid)
node["from"] = from; message["from"] = from;
else else
node["from"] = from + "@" + this->served_hostname; message["from"] = from + "@" + this->served_hostname;
if (!type.empty()) if (!type.empty())
node["type"] = type; message["type"] = type;
XmlNode body_node("body"); XmlSubNode body_node(message, "body");
body_node.set_inner(std::get<0>(body)); body_node.set_inner(std::get<0>(body));
node.add_child(std::move(body_node));
if (std::get<1>(body)) if (std::get<1>(body))
{ {
XmlNode html("html"); XmlSubNode html(message, "html");
html["xmlns"] = XHTMLIM_NS; html["xmlns"] = XHTMLIM_NS;
// Pass the ownership of the pointer to this xmlnode // Pass the ownership of the pointer to this xmlnode
html.add_child(std::move(std::get<1>(body))); html.add_child(std::move(std::get<1>(body)));
node.add_child(std::move(html));
} }
if (nocopy) if (nocopy)
{ {
XmlNode private_node("private"); XmlSubNode private_node(message, "private");
private_node["xmlns"] = "urn:xmpp:carbons:2"; private_node["xmlns"] = "urn:xmpp:carbons:2";
node.add_child(std::move(private_node)); XmlSubNode nocopy(message, "no-copy");
XmlNode nocopy("no-copy");
nocopy["xmlns"] = "urn:xmpp:hints"; nocopy["xmlns"] = "urn:xmpp:hints";
node.add_child(std::move(nocopy));
} }
}
this->send_stanza(node); this->send_stanza(message);
} }
void XmppComponent::send_user_join(const std::string& from, void XmppComponent::send_user_join(const std::string& from,
...@@ -306,14 +305,15 @@ void XmppComponent::send_user_join(const std::string& from, ...@@ -306,14 +305,15 @@ void XmppComponent::send_user_join(const std::string& from,
const std::string& to, const std::string& to,
const bool self) const bool self)
{ {
XmlNode node("presence"); Stanza presence("presence");
node["to"] = to; {
node["from"] = from + "@" + this->served_hostname + "/" + nick; presence["to"] = to;
presence["from"] = from + "@" + this->served_hostname + "/" + nick;
XmlNode x("x"); XmlSubNode x(presence, "x");
x["xmlns"] = MUC_USER_NS; x["xmlns"] = MUC_USER_NS;
XmlNode item("item"); XmlSubNode item(x, "item");
if (!affiliation.empty()) if (!affiliation.empty())
item["affiliation"] = affiliation; item["affiliation"] = affiliation;
if (!role.empty()) if (!role.empty())
...@@ -324,16 +324,14 @@ void XmppComponent::send_user_join(const std::string& from, ...@@ -324,16 +324,14 @@ void XmppComponent::send_user_join(const std::string& from,
if (!preped_jid.empty()) if (!preped_jid.empty())
item["jid"] = preped_jid; item["jid"] = preped_jid;
} }
x.add_child(std::move(item));
if (self) if (self)
{ {
XmlNode status("status"); XmlSubNode status(x, "status");
status["code"] = "110"; status["code"] = "110";
x.add_child(std::move(status));
} }
node.add_child(std::move(x)); }
this->send_stanza(node); this->send_stanza(presence);
} }
void XmppComponent::send_invalid_room_error(const std::string& muc_name, void XmppComponent::send_invalid_room_error(const std::string& muc_name,
...@@ -341,44 +339,43 @@ void XmppComponent::send_invalid_room_error(const std::string& muc_name, ...@@ -341,44 +339,43 @@ void XmppComponent::send_invalid_room_error(const std::string& muc_name,
const std::string& to) const std::string& to)
{ {
Stanza presence("presence"); Stanza presence("presence");
if (!muc_name.empty()) {
if (!muc_name.empty ())
presence["from"] = muc_name + "@" + this->served_hostname + "/" + nick; presence["from"] = muc_name + "@" + this->served_hostname + "/" + nick;
else else
presence["from"] = this->served_hostname; presence["from"] = this->served_hostname;
presence["to"] = to; presence["to"] = to;
presence["type"] = "error"; presence["type"] = "error";
XmlNode x("x"); XmlSubNode x(presence, "x");
x["xmlns"] = MUC_NS; x["xmlns"] = MUC_NS;
presence.add_child(std::move(x)); XmlSubNode error(presence, "error");
XmlNode error("error");
error["by"] = muc_name + "@" + this->served_hostname; error["by"] = muc_name + "@" + this->served_hostname;
error["type"] = "cancel"; error["type"] = "cancel";
XmlNode item_not_found("item-not-found"); XmlSubNode item_not_found(error, "item-not-found");
item_not_found["xmlns"] = STANZA_NS; item_not_found["xmlns"] = STANZA_NS;
error.add_child(std::move(item_not_found)); XmlSubNode text(error, "text");
XmlNode text("text");
text["xmlns"] = STANZA_NS; text["xmlns"] = STANZA_NS;
text["xml:lang"] = "en"; text["xml:lang"] = "en";
text.set_inner(muc_name + text.set_inner(muc_name +
" is not a valid IRC channel name. A correct room jid is of the form: #<chan>%<server>@" + " is not a valid IRC channel name. A correct room jid is of the form: #<chan>%<server>@" +
this->served_hostname); this->served_hostname);
error.add_child(std::move(text)); }
presence.add_child(std::move(error));
this->send_stanza(presence); this->send_stanza(presence);
} }
void XmppComponent::send_topic(const std::string& from, Xmpp::body&& topic, const std::string& to, const std::string& who) void XmppComponent::send_topic(const std::string& from, Xmpp::body&& topic, const std::string& to, const std::string& who)
{ {
XmlNode message("message"); Stanza message("message");
{
message["to"] = to; message["to"] = to;
if (who.empty()) if (who.empty())
message["from"] = from + "@" + this->served_hostname; message["from"] = from + "@" + this->served_hostname;
else else
message["from"] = from + "@" + this->served_hostname + "/" + who; message["from"] = from + "@" + this->served_hostname + "/" + who;
message["type"] = "groupchat"; message["type"] = "groupchat";
XmlNode subject("subject"); XmlSubNode subject(message, "subject");
subject.set_inner(std::get<0>(topic)); subject.set_inner(std::get<0>(topic));
message.add_child(std::move(subject)); }
this->send_stanza(message); this->send_stanza(message);
} }
...@@ -391,16 +388,18 @@ void XmppComponent::send_muc_message(const std::string& muc_name, const std::str ...@@ -391,16 +388,18 @@ void XmppComponent::send_muc_message(const std::string& muc_name, const std::str
else // Message from the room itself else // Message from the room itself
message["from"] = muc_name + "@" + this->served_hostname; message["from"] = muc_name + "@" + this->served_hostname;
message["type"] = "groupchat"; message["type"] = "groupchat";
XmlNode body("body");
{
XmlSubNode body(message, "body");
body.set_inner(std::get<0>(xmpp_body)); body.set_inner(std::get<0>(xmpp_body));
message.add_child(std::move(body)); }
if (std::get<1>(xmpp_body)) if (std::get<1>(xmpp_body))
{ {
XmlNode html("html"); XmlSubNode html(message, "html");
html["xmlns"] = XHTMLIM_NS; html["xmlns"] = XHTMLIM_NS;
// Pass the ownership of the pointer to this xmlnode // Pass the ownership of the pointer to this xmlnode
html.add_child(std::move(std::get<1>(xmpp_body))); html.add_child(std::move(std::get<1>(xmpp_body)));
message.add_child(std::move(html));
} }
this->send_stanza(message); this->send_stanza(message);
} }
...@@ -415,40 +414,40 @@ void XmppComponent::send_history_message(const std::string& muc_name, const std: ...@@ -415,40 +414,40 @@ void XmppComponent::send_history_message(const std::string& muc_name, const std:
message["from"] = muc_name + "@" + this->served_hostname; message["from"] = muc_name + "@" + this->served_hostname;
message["type"] = "groupchat"; message["type"] = "groupchat";
XmlNode body("body"); {
XmlSubNode body(message, "body");
body.set_inner(body_txt); body.set_inner(body_txt);
message.add_child(std::move(body)); }
{
XmlNode delay("delay"); XmlSubNode delay(message, "delay");
delay["xmlns"] = DELAY_NS; delay["xmlns"] = DELAY_NS;
delay["from"] = muc_name + "@" + this->served_hostname; delay["from"] = muc_name + "@" + this->served_hostname;
delay["stamp"] = utils::to_string(timestamp); delay["stamp"] = utils::to_string(timestamp);
}
message.add_child(std::move(delay));
this->send_stanza(message); this->send_stanza(message);
} }
void XmppComponent::send_muc_leave(const std::string& muc_name, std::string&& nick, Xmpp::body&& message, const std::string& jid_to, const bool self) void XmppComponent::send_muc_leave(const std::string& muc_name, std::string&& nick, Xmpp::body&& message, const std::string& jid_to, const bool self)
{ {
Stanza presence("presence"); Stanza presence("presence");
{
presence["to"] = jid_to; presence["to"] = jid_to;
presence["from"] = muc_name + "@" + this->served_hostname + "/" + nick; presence["from"] = muc_name + "@" + this->served_hostname + "/" + nick;
presence["type"] = "unavailable"; presence["type"] = "unavailable";
const std::string message_str = std::get<0>(message); const std::string message_str = std::get<0>(message);
XmlNode x("x"); XmlSubNode x(presence, "x");
x["xmlns"] = MUC_USER_NS; x["xmlns"] = MUC_USER_NS;
if (self) if (self)
{ {
XmlNode status("status"); XmlSubNode status(x, "status");
status["code"] = "110"; status["code"] = "110";
x.add_child(std::move(status));
} }
presence.add_child(std::move(x));
if (!message_str.empty()) if (!message_str.empty())
{ {
XmlNode status("status"); XmlSubNode status(presence, "status");
status.set_inner(message_str); status.set_inner(message_str);
presence.add_child(std::move(status)); }
} }
this->send_stanza(presence); this->send_stanza(presence);
} }
...@@ -462,24 +461,22 @@ void XmppComponent::send_nick_change(const std::string& muc_name, ...@@ -462,24 +461,22 @@ void XmppComponent::send_nick_change(const std::string& muc_name,
const bool self) const bool self)
{ {
Stanza presence("presence"); Stanza presence("presence");
{
presence["to"] = jid_to; presence["to"] = jid_to;
presence["from"] = muc_name + "@" + this->served_hostname + "/" + old_nick; presence["from"] = muc_name + "@" + this->served_hostname + "/" + old_nick;
presence["type"] = "unavailable"; presence["type"] = "unavailable";
XmlNode x("x"); XmlSubNode x(presence, "x");
x["xmlns"] = MUC_USER_NS; x["xmlns"] = MUC_USER_NS;
XmlNode item("item"); XmlSubNode item(x, "item");
item["nick"] = new_nick; item["nick"] = new_nick;
x.add_child(std::move(item)); XmlSubNode status(x, "status");
XmlNode status("status");
status["code"] = "303"; status["code"] = "303";
x.add_child(std::move(status));
if (self) if (self)
{ {
XmlNode status2("status"); XmlSubNode status(x, "status");
status2["code"] = "110"; status["code"] = "110";
x.add_child(std::move(status2)); }
} }
presence.add_child(std::move(x));
this->send_stanza(presence); this->send_stanza(presence);
this->send_user_join(muc_name, new_nick, "", affiliation, role, jid_to