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); {
error["xmlns"] = STREAM_NS; XmlSubNode error(node, name);
if (!explanation.empty()) error["xmlns"] = STREAM_NS;
error.set_inner(explanation); if (!explanation.empty())
node.add_child(std::move(error)); error.set_inner(explanation);
}
this->send_stanza(node); this->send_stanza(node);
} }
...@@ -187,31 +188,34 @@ void XmppComponent::send_stanza_error(const std::string& kind, const std::string ...@@ -187,31 +188,34 @@ 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()) {
node["to"] = to; if (!to.empty())
if (!from.empty()) node["to"] = to;
if (!from.empty())
{
if (fulljid)
node["from"] = from;
else
node["from"] = from + "@" + this->served_hostname;
}
if (!id.empty())
node["id"] = id;
node["type"] = "error";
{ {
if (fulljid) XmlSubNode error(node, "error");
node["from"] = from; error["type"] = error_type;
else {
node["from"] = from + "@" + this->served_hostname; XmlSubNode inner_error(error, defined_condition);
inner_error["xmlns"] = STANZA_NS;
}
if (!text.empty())
{
XmlSubNode text_node(error, "text");
text_node["xmlns"] = STANZA_NS;
text_node.set_inner(text);
}
} }
if (!id.empty()) }
node["id"] = id;
node["type"] = "error";
XmlNode error("error");
error["type"] = error_type;
XmlNode inner_error(defined_condition);
inner_error["xmlns"] = STANZA_NS;
error.add_child(std::move(inner_error));
if (!text.empty())
{
XmlNode text_node("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); 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; {
if (fulljid) message["to"] = to;
node["from"] = from; if (fulljid)
else message["from"] = from;
node["from"] = from + "@" + this->served_hostname; else
if (!type.empty()) message["from"] = from + "@" + this->served_hostname;
node["type"] = type; if (!type.empty())
XmlNode body_node("body"); message["type"] = type;
body_node.set_inner(std::get<0>(body)); XmlSubNode body_node(message, "body");
node.add_child(std::move(body_node)); body_node.set_inner(std::get<0>(body));
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) XmlSubNode private_node(message, "private");
{ private_node["xmlns"] = "urn:xmpp:carbons:2";
XmlNode private_node("private"); XmlSubNode nocopy(message, "no-copy");
private_node["xmlns"] = "urn:xmpp:carbons:2"; nocopy["xmlns"] = "urn:xmpp:hints";
node.add_child(std::move(private_node)); }
}
XmlNode nocopy("no-copy"); this->send_stanza(message);
nocopy["xmlns"] = "urn:xmpp:hints";
node.add_child(std::move(nocopy));
}
this->send_stanza(node);
} }
void XmppComponent::send_user_join(const std::string& from, void XmppComponent::send_user_join(const std::string& from,
...@@ -306,34 +305,33 @@ void XmppComponent::send_user_join(const std::string& from, ...@@ -306,34 +305,33 @@ 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");
x["xmlns"] = MUC_USER_NS; XmlSubNode x(presence, "x");
x["xmlns"] = MUC_USER_NS;
XmlNode item("item");
if (!affiliation.empty()) XmlSubNode item(x, "item");
item["affiliation"] = affiliation; if (!affiliation.empty())
if (!role.empty()) item["affiliation"] = affiliation;
item["role"] = role; if (!role.empty())
if (!realjid.empty()) item["role"] = role;
{ if (!realjid.empty())
const std::string preped_jid = jidprep(realjid); {
if (!preped_jid.empty()) const std::string preped_jid = jidprep(realjid);
item["jid"] = preped_jid; if (!preped_jid.empty())
} 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(presence);
this->send_stanza(node);
} }
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()) {
presence["from"] = muc_name + "@" + this->served_hostname + "/" + nick; if (!muc_name.empty ())
else presence["from"] = muc_name + "@" + this->served_hostname + "/" + nick;
presence["from"] = this->served_hostname; else
presence["to"] = to; presence["from"] = this->served_hostname;
presence["type"] = "error"; presence["to"] = to;
XmlNode x("x"); presence["type"] = "error";
x["xmlns"] = MUC_NS; XmlSubNode x(presence, "x");
presence.add_child(std::move(x)); x["xmlns"] = MUC_NS;
XmlNode error("error"); XmlSubNode error(presence, "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; {
if (who.empty()) message["to"] = to;
message["from"] = from + "@" + this->served_hostname; if (who.empty())
else message["from"] = from + "@" + this->served_hostname;
message["from"] = from + "@" + this->served_hostname + "/" + who; else
message["type"] = "groupchat"; message["from"] = from + "@" + this->served_hostname + "/" + who;
XmlNode subject("subject"); message["type"] = "groupchat";
subject.set_inner(std::get<0>(topic)); XmlSubNode subject(message, "subject");
message.add_child(std::move(subject)); subject.set_inner(std::get<0>(topic));
}
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");
body.set_inner(std::get<0>(xmpp_body)); {
message.add_child(std::move(body)); XmlSubNode body(message, "body");
body.set_inner(std::get<0>(xmpp_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,41 +414,41 @@ void XmppComponent::send_history_message(const std::string& muc_name, const std: ...@@ -415,41 +414,41 @@ 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"); {
body.set_inner(body_txt); XmlSubNode body(message, "body");
message.add_child(std::move(body)); body.set_inner(body_txt);
}
XmlNode delay("delay"); {
delay["xmlns"] = DELAY_NS; XmlSubNode delay(message, "delay");
delay["from"] = muc_name + "@" + this->served_hostname; delay["xmlns"] = DELAY_NS;
delay["stamp"] = utils::to_string(timestamp); delay["from"] = muc_name + "@" + this->served_hostname;
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["from"] = muc_name + "@" + this->served_hostname + "/" + nick; presence["to"] = jid_to;
presence["type"] = "unavailable"; presence["from"] = muc_name + "@" + this->served_hostname + "/" + nick;
const std::string message_str = std::get<0>(message); presence["type"] = "unavailable";
XmlNode x("x"); const std::string message_str = std::get<0>(message);
x["xmlns"] = MUC_USER_NS; XmlSubNode x(presence, "x");
if (self) x["xmlns"] = MUC_USER_NS;
{ if (self)
XmlNode status("status"); {
status["code"] = "110"; XmlSubNode status(x, "status");
x.add_child(std::move(status)); status["code"] = "110";
} }
presence.add_child(std::move(x)); if (!message_str.empty())
if (!message_str.empty()) {
{ XmlSubNode status(presence, "status");
XmlNode status("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["from"] = muc_name + "@" + this->served_hostname + "/" + old_nick; presence["to"] = jid_to;
presence["type"] = "unavailable"; presence["from"] = muc_name + "@" + this->served_hostname + "/" + old_nick;
XmlNode x("x"); presence["type"] = "unavailable";
x["xmlns"] = MUC_USER_NS; XmlSubNode x(presence, "x");
XmlNode item("item"); x["xmlns"] = MUC_USER_NS;
item["nick"] = new_nick; XmlSubNode item(x, "item");
x.add_child(std::move(item)); item["nick"] = new_nick;
XmlNode status("status"); XmlSubNode status(x, "status");
status["code"] = "303"; status["code"] = "303";
x.add_child(std::move(status));