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
void PingStep1(XmppComponent&, AdhocSession&, XmlNode& command_node)
{
XmlNode note("note");
XmlSubNode note(command_node, "note");
note["type"] = "info";
note.set_inner("Pong");
command_node.add_child(std::move(note));
}
void HelloStep1(XmppComponent&, AdhocSession&, XmlNode& command_node)
{
XmlNode x("jabber:x:data:x");
XmlSubNode x(command_node, "jabber:x:data:x");
x["type"] = "form";
XmlNode title("title");
XmlSubNode title(x, "title");
title.set_inner("Configure your name.");
x.add_child(std::move(title));
XmlNode instructions("instructions");
XmlSubNode instructions(x, "instructions");
instructions.set_inner("Please provide your name.");
x.add_child(std::move(instructions));
XmlNode name_field("field");
XmlSubNode name_field(x, "field");
name_field["var"] = "name";
name_field["type"] = "text-single";
name_field["label"] = "Your name";
XmlNode required("required");
name_field.add_child(std::move(required));
x.add_child(std::move(name_field));
command_node.add_child(std::move(x));
XmlSubNode required(name_field, "required");
}
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"))
{
XmlNode note("note");
command_node.delete_all_children();
XmlSubNode note(command_node, "note");
note["type"] = "info";
note.set_inner("Hello "s + value->get_inner() + "!"s);
command_node.delete_all_children();
command_node.add_child(std::move(note));
return;
}
}
}
command_node.delete_all_children();
XmlNode error(ADHOC_NS":error");
XmlSubNode error(command_node, ADHOC_NS":error");
error["type"] = "modify";
XmlNode condition(STANZA_NS":bad-request");
error.add_child(std::move(condition));
command_node.add_child(std::move(error));
XmlSubNode condition(error, STANZA_NS":bad-request");
session.terminate();
}
......@@ -82,8 +73,7 @@ void Reload(XmppComponent&, AdhocSession&, XmlNode& command_node)
{
::reload_process();
command_node.delete_all_children();
XmlNode note("note");
XmlSubNode note(command_node, "note");
note["type"] = "info";
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
auto command_it = this->commands.find(node);
if (command_it == this->commands.end())
{
XmlNode error(ADHOC_NS":error");
XmlSubNode error(command_node, ADHOC_NS":error");
error["type"] = "cancel";
XmlNode condition(STANZA_NS":item-not-found");
error.add_child(std::move(condition));
command_node.add_child(std::move(error));
XmlSubNode condition(error, STANZA_NS":item-not-found");
}
else if (command_it->second.is_admin_only() &&
Config::get("admin", "") != jid.local + "@" + jid.domain)
{
XmlNode error(ADHOC_NS":error");
XmlSubNode error(command_node, ADHOC_NS":error");
error["type"] = "cancel";
XmlNode condition(STANZA_NS":forbidden");
error.add_child(std::move(condition));
command_node.add_child(std::move(error));
XmlSubNode condition(error, STANZA_NS":forbidden");
}
else
{
......@@ -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));
if (session_it == this->sessions.end())
{
XmlNode error(ADHOC_NS":error");
XmlSubNode error(command_node, ADHOC_NS":error");
error["type"] = "modify";
XmlNode condition(STANZA_NS":bad-request");
error.add_child(std::move(condition));
command_node.add_child(std::move(error));
XmlSubNode condition(error, STANZA_NS":bad-request");
}
else if (action == "execute" || action == "next" || action == "complete")
{
......@@ -90,10 +84,8 @@ XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, co
else
{
command_node["status"] = "executing";
XmlNode actions("actions");
XmlNode next("next");
actions.add_child(std::move(next));
command_node.add_child(std::move(actions));
XmlSubNode actions(command_node, "actions");
XmlSubNode next(actions, "next");
}
}
else if (action == "cancel")
......@@ -104,11 +96,9 @@ XmlNode AdhocCommandsHandler::handle_request(const std::string& executor_jid, co
}
else // unsupported action
{
XmlNode error(ADHOC_NS":error");
XmlSubNode error(command_node, ADHOC_NS":error");
error["type"] = "modify";
XmlNode condition(STANZA_NS":bad-request");
error.add_child(std::move(condition));
command_node.add_child(std::move(error));
XmlSubNode condition(error, STANZA_NS":bad-request");
}
}
return command_node;
......
......@@ -172,12 +172,13 @@ void XmppComponent::on_stanza(const Stanza& stanza)
void XmppComponent::send_stream_error(const std::string& name, const std::string& explanation)
{
XmlNode node("stream:error");
XmlNode error(name);
Stanza node("stream:error");
{
XmlSubNode error(node, name);
error["xmlns"] = STREAM_NS;
if (!explanation.empty())
error.set_inner(explanation);
node.add_child(std::move(error));
}
this->send_stanza(node);
}
......@@ -187,6 +188,7 @@ void XmppComponent::send_stanza_error(const std::string& kind, const std::string
const bool fulljid)
{
Stanza node(kind);
{
if (!to.empty())
node["to"] = to;
if (!from.empty())
......@@ -199,19 +201,21 @@ void XmppComponent::send_stanza_error(const std::string& kind, const std::string
if (!id.empty())
node["id"] = id;
node["type"] = "error";
XmlNode error("error");
{
XmlSubNode error(node, "error");
error["type"] = error_type;
XmlNode inner_error(defined_condition);
{
XmlSubNode inner_error(error, defined_condition);
inner_error["xmlns"] = STANZA_NS;
error.add_child(std::move(inner_error));
}
if (!text.empty())
{
XmlNode text_node("text");
XmlSubNode text_node(error, "text");
text_node["xmlns"] = STANZA_NS;
text_node.set_inner(text);
error.add_child(std::move(text_node));
}
node.add_child(std::move(error));
}
}
this->send_stanza(node);
}
......@@ -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,
const std::string& type, const bool fulljid, const bool nocopy)
{
XmlNode node("message");
node["to"] = to;
Stanza message("message");
{
message["to"] = to;
if (fulljid)
node["from"] = from;
message["from"] = from;
else
node["from"] = from + "@" + this->served_hostname;
message["from"] = from + "@" + this->served_hostname;
if (!type.empty())
node["type"] = type;
XmlNode body_node("body");
message["type"] = type;
XmlSubNode body_node(message, "body");
body_node.set_inner(std::get<0>(body));
node.add_child(std::move(body_node));
if (std::get<1>(body))
{
XmlNode html("html");
XmlSubNode html(message, "html");
html["xmlns"] = XHTMLIM_NS;
// Pass the ownership of the pointer to this xmlnode
html.add_child(std::move(std::get<1>(body)));
node.add_child(std::move(html));
}
if (nocopy)
{
XmlNode private_node("private");
XmlSubNode private_node(message, "private");
private_node["xmlns"] = "urn:xmpp:carbons:2";
node.add_child(std::move(private_node));
XmlNode nocopy("no-copy");
XmlSubNode nocopy(message, "no-copy");
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,
......@@ -306,14 +305,15 @@ void XmppComponent::send_user_join(const std::string& from,
const std::string& to,
const bool self)
{
XmlNode node("presence");
node["to"] = to;
node["from"] = from + "@" + this->served_hostname + "/" + nick;
Stanza presence("presence");
{
presence["to"] = to;
presence["from"] = from + "@" + this->served_hostname + "/" + nick;
XmlNode x("x");
XmlSubNode x(presence, "x");
x["xmlns"] = MUC_USER_NS;
XmlNode item("item");
XmlSubNode item(x, "item");
if (!affiliation.empty())
item["affiliation"] = affiliation;
if (!role.empty())
......@@ -324,16 +324,14 @@ void XmppComponent::send_user_join(const std::string& from,
if (!preped_jid.empty())
item["jid"] = preped_jid;
}
x.add_child(std::move(item));
if (self)
{
XmlNode status("status");
XmlSubNode status(x, "status");
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,
......@@ -341,44 +339,43 @@ void XmppComponent::send_invalid_room_error(const std::string& muc_name,
const std::string& to)
{
Stanza presence("presence");
if (!muc_name.empty())
{
if (!muc_name.empty ())
presence["from"] = muc_name + "@" + this->served_hostname + "/" + nick;
else
presence["from"] = this->served_hostname;
presence["to"] = to;
presence["type"] = "error";
XmlNode x("x");
XmlSubNode x(presence, "x");
x["xmlns"] = MUC_NS;
presence.add_child(std::move(x));
XmlNode error("error");
XmlSubNode error(presence, "error");
error["by"] = muc_name + "@" + this->served_hostname;
error["type"] = "cancel";
XmlNode item_not_found("item-not-found");
XmlSubNode item_not_found(error, "item-not-found");
item_not_found["xmlns"] = STANZA_NS;
error.add_child(std::move(item_not_found));
XmlNode text("text");
XmlSubNode text(error, "text");
text["xmlns"] = STANZA_NS;
text["xml:lang"] = "en";
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);
error.add_child(std::move(text));
presence.add_child(std::move(error));
}
this->send_stanza(presence);
}
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;
if (who.empty())
message["from"] = from + "@" + this->served_hostname;
else
message["from"] = from + "@" + this->served_hostname + "/" + who;
message["type"] = "groupchat";
XmlNode subject("subject");
XmlSubNode subject(message, "subject");
subject.set_inner(std::get<0>(topic));
message.add_child(std::move(subject));
}
this->send_stanza(message);
}
......@@ -391,16 +388,18 @@ void XmppComponent::send_muc_message(const std::string& muc_name, const std::str
else // Message from the room itself
message["from"] = muc_name + "@" + this->served_hostname;
message["type"] = "groupchat";
XmlNode body("body");
{
XmlSubNode body(message, "body");
body.set_inner(std::get<0>(xmpp_body));
message.add_child(std::move(body));
}
if (std::get<1>(xmpp_body))
{
XmlNode html("html");
XmlSubNode html(message, "html");
html["xmlns"] = XHTMLIM_NS;
// Pass the ownership of the pointer to this xmlnode
html.add_child(std::move(std::get<1>(xmpp_body)));
message.add_child(std::move(html));
}
this->send_stanza(message);
}
......@@ -415,40 +414,40 @@ void XmppComponent::send_history_message(const std::string& muc_name, const std:
message["from"] = muc_name + "@" + this->served_hostname;
message["type"] = "groupchat";
XmlNode body("body");
{
XmlSubNode body(message, "body");
body.set_inner(body_txt);
message.add_child(std::move(body));
XmlNode delay("delay");
}
{
XmlSubNode delay(message, "delay");
delay["xmlns"] = DELAY_NS;
delay["from"] = muc_name + "@" + this->served_hostname;
delay["stamp"] = utils::to_string(timestamp);
}
message.add_child(std::move(delay));
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)
{
Stanza presence("presence");
{
presence["to"] = jid_to;
presence["from"] = muc_name + "@" + this->served_hostname + "/" + nick;
presence["type"] = "unavailable";
const std::string message_str = std::get<0>(message);
XmlNode x("x");
XmlSubNode x(presence, "x");
x["xmlns"] = MUC_USER_NS;
if (self)
{
XmlNode status("status");
XmlSubNode status(x, "status");
status["code"] = "110";
x.add_child(std::move(status));
}
presence.add_child(std::move(x));
if (!message_str.empty())
{
XmlNode status("status");
XmlSubNode status(presence, "status");
status.set_inner(message_str);
presence.add_child(std::move(status));
}
}
this->send_stanza(presence);
}
......@@ -462,24 +461,22 @@ void XmppComponent::send_nick_change(const std::string& muc_name,
const bool self)
{
Stanza presence("presence");
{
presence["to"] = jid_to;
presence["from"] = muc_name + "@" + this->served_hostname + "/" + old_nick;
presence["type"] = "unavailable";
XmlNode x("x");
XmlSubNode x(presence, "x");
x["xmlns"] = MUC_USER_NS;
XmlNode item("item");
XmlSubNode item(x, "item");
item["nick"] = new_nick;
x.add_child(std::move(item));
XmlNode status("status");
XmlSubNode status(x, "status");
status["code"] = "303";
x.add_child(std::move(status));
if (self)
{
XmlNode status2("status");
status2["code"] = "110";
x.add_child(std::move(status2));
XmlSubNode status(x, "status");
status["code"] = "110";
}
}
presence.add_child(std::move(x));
this->send_stanza(presence);
this->send_user_join(muc_name, new_nick, "", affiliation, role, jid_to, self);
......@@ -489,32 +486,28 @@ void XmppComponent::kick_user(const std::string& muc_name, const std::string& ta
const std::string& author, const std::string& jid_to, const bool self)
{
Stanza presence("presence");
{
presence["from"] = muc_name + "@" + this->served_hostname + "/" + target;
presence["to"] = jid_to;
presence["type"] = "unavailable";
XmlNode x("x");
XmlSubNode x(presence, "x");
x["xmlns"] = MUC_USER_NS;
XmlNode item("item");
XmlSubNode item(x, "item");
item["affiliation"] = "none";
item["role"] = "none";
XmlNode actor("actor");
XmlSubNode actor(item, "actor");
actor["nick"] = author;
actor["jid"] = author; // backward compatibility with old clients
item.add_child(std::move(actor));
XmlNode reason("reason");
XmlSubNode reason(item, "reason");
reason.set_inner(txt);
item.add_child(std::move(reason));
x.add_child(std::move(item));
XmlNode status("status");
XmlSubNode status(x, "status");
status["code"] = "307";
x.add_child(std::move(status));
if (self)
{
XmlNode status("status");
XmlSubNode status(x, "status");
status["code"] = "110";
x.add_child(std::move(status));
}
presence.add_child(std::move(x));
}
this->send_stanza(presence);
}
......@@ -527,28 +520,26 @@ void XmppComponent::send_presence_error(const std::string& muc_name,
const std::string& text)
{
Stanza presence("presence");
{
presence["from"] = muc_name + "@" + this->served_hostname + "/" + nickname;
presence["to"] = jid_to;
presence["type"] = "error";
XmlNode x("x");
XmlSubNode x(presence, "x");
x["xmlns"] = MUC_NS;
presence.add_child(std::move(x));
XmlNode error("error");
XmlSubNode error(presence, "error");
error["by"] = muc_name + "@" + this->served_hostname;
error["type"] = type;
if (!text.empty())
{
XmlNode text_node("text");
XmlSubNode text_node(error, "text");
text_node["xmlns"] = STANZA_NS;
text_node.set_inner(text);
error.add_child(std::move(text_node));
}
if (!error_code.empty())
error["code"] = error_code;
XmlNode subnode(condition);
XmlSubNode subnode(error, condition);
subnode["xmlns"] = STANZA_NS;
error.add_child(std::move(subnode));
presence.add_child(std::move(error));
}
this->send_stanza(presence);
}
......@@ -559,15 +550,15 @@ void XmppComponent::send_affiliation_role_change(const std::string& muc_name,
const std::string& jid_to)
{
Stanza presence("presence");
{
presence["from"] = muc_name + "@" + this->served_hostname + "/" + target;
presence["to"] = jid_to;
XmlNode x("x");
XmlSubNode x(presence, "x");
x["xmlns"] = MUC_USER_NS;
XmlNode item("item");
XmlSubNode item(x, "item");
item["affiliation"] = affiliation;
item["role"] = role;
x.add_child(std::move(item));
presence.add_child(std::move(x));
}
this->send_stanza(presence);
}
......@@ -579,27 +570,30 @@ void XmppComponent::send_version(const std::string& id, const std::string& jid_t
iq["id"] = id;
iq["to"] = jid_to;
iq["from"] = jid_from;
XmlNode query("query");
{
XmlSubNode query(iq, "query");
query["xmlns"] = VERSION_NS;
if (version.empty())
{
XmlNode name("name");
{
XmlSubNode name(query, "name");
name.set_inner("biboumi");
query.add_child(std::move(name));
XmlNode version("version");
}
{
XmlSubNode version(query, "version");
version.set_inner(SOFTWARE_VERSION);
query.add_child(std::move(version));
XmlNode os("os");
}
{
XmlSubNode os(query, "os");
os.set_inner(SYSTEM_NAME);
query.add_child(std::move(os));
}
}
else
{
XmlNode name("name");
XmlSubNode name(query, "name");
name.set_inner(version);
query.add_child(std::move(name));
}
iq.add_child(std::move(query));
}
this->send_stanza(iq);
}
......@@ -608,24 +602,24 @@ void XmppComponent::send_adhoc_commands_list(const std::string& id, const std::s
const bool with_admin_only, const AdhocCommandsHandler& adhoc_handler)
{
Stanza iq("iq");
{
iq["type"] = "result";
iq["id"] = id;
iq["to"] = requester_jid;
iq["from"] = from_jid;
XmlNode query("query");
XmlSubNode query(iq, "query");
query["xmlns"] = DISCO_ITEMS_NS;
query["node"] = ADHOC_NS;
for (const auto& kv: adhoc_handler.get_commands())
for (const auto &kv: adhoc_handler.get_commands())
{
if (kv.second.is_admin_only() && !with_admin_only)
continue;
XmlNode item("item");
XmlSubNode item(query, "item");
item["jid"] = from_jid;
item["node"] = kv.first;
item["name"] = kv.second.name;
query.add_child(std::move(item));
}
iq.add_child(std::move(query));
}
this->send_stanza(iq);
}
......@@ -633,13 +627,14 @@ void XmppComponent::send_iq_version_request(const std::string& from,
const std::string& jid_to)
{
Stanza iq("iq");
{
iq["type"] = "get";
iq["id"] = "version_"s + XmppComponent::next_id();
iq["from"] = from + "@" + this->served_hostname;
iq["to"] = jid_to;
XmlNode query("query");