From d600a2843f1dbe3b1ba2dead9a020cc73d7d10ae Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 27 Feb 2015 12:16:09 +0100 Subject: Remove all the libs that are now in louloulibs --- src/xmpp/biboumi_component.cpp | 568 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 568 insertions(+) create mode 100644 src/xmpp/biboumi_component.cpp (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp new file mode 100644 index 0000000..2ecf247 --- /dev/null +++ b/src/xmpp/biboumi_component.cpp @@ -0,0 +1,568 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include + +#ifdef SYSTEMD_FOUND +# include +#endif + +using namespace std::string_literals; + +static std::set kickable_errors{ + "gone", + "internal-server-error", + "item-not-found", + "jid-malformed", + "recipient-unavailable", + "redirect", + "remote-server-not-found", + "remote-server-timeout", + "service-unavailable", + "malformed-error" + }; + + +BiboumiComponent::BiboumiComponent(std::shared_ptr poller, const std::string& hostname, const std::string& secret): + XmppComponent(poller, hostname, secret) +{ + this->stanza_handlers.emplace("presence", + std::bind(&BiboumiComponent::handle_presence, this,std::placeholders::_1)); + this->stanza_handlers.emplace("message", + std::bind(&BiboumiComponent::handle_message, this,std::placeholders::_1)); + this->stanza_handlers.emplace("iq", + std::bind(&BiboumiComponent::handle_iq, this,std::placeholders::_1)); + + this->adhoc_commands_handler.get_commands()= { + {"ping", AdhocCommand({&PingStep1}, "Do a ping", false)}, + {"hello", AdhocCommand({&HelloStep1, &HelloStep2}, "Receive a custom greeting", false)}, + {"disconnect-user", AdhocCommand({&DisconnectUserStep1, &DisconnectUserStep2}, "Disconnect a user from the gateway", true)}, + {"reload", AdhocCommand({&Reload}, "Reload biboumi’s configuration", true)} + }; +} + +void BiboumiComponent::shutdown() +{ + for (auto it = this->bridges.begin(); it != this->bridges.end(); ++it) + { + it->second->shutdown("Gateway shutdown"); + } +} + +void BiboumiComponent::clean() +{ + auto it = this->bridges.begin(); + while (it != this->bridges.end()) + { + it->second->clean(); + if (it->second->active_clients() == 0) + it = this->bridges.erase(it); + else + ++it; + } +} + +void BiboumiComponent::handle_presence(const Stanza& stanza) +{ + std::string from = stanza.get_tag("from"); + std::string id = stanza.get_tag("id"); + std::string to_str = stanza.get_tag("to"); + std::string type = stanza.get_tag("type"); + + // Check for mandatory tags + if (from.empty()) + { + log_warning("Received an invalid presence stanza: tag 'from' is missing."); + return; + } + if (to_str.empty()) + { + this->send_stanza_error("presence", from, this->served_hostname, id, + "modify", "bad-request", "Missing 'to' tag"); + return; + } + + Bridge* bridge = this->get_user_bridge(from); + Jid to(to_str); + Iid iid(to.local); + + // An error stanza is sent whenever we exit this function without + // disabling this scopeguard. If error_type and error_name are not + // changed, the error signaled is internal-server-error. Change their + // value to signal an other kind of error. For example + // feature-not-implemented, etc. Any non-error process should reach the + // stanza_error.disable() call at the end of the function. + std::string error_type("cancel"); + std::string error_name("internal-server-error"); + utils::ScopeGuard stanza_error([&](){ + this->send_stanza_error("presence", from, to_str, id, + error_type, error_name, ""); + }); + + if (iid.is_channel && !iid.get_server().empty()) + { // presence toward a MUC that corresponds to an irc channel, or a + // dummy channel if iid.chan is empty + if (type.empty()) + { + const std::string own_nick = bridge->get_own_nick(iid); + if (!own_nick.empty() && own_nick != to.resource) + bridge->send_irc_nick_change(iid, to.resource); + XmlNode* x = stanza.get_child("x", MUC_NS); + XmlNode* password = x ? x->get_child("password", MUC_NS): nullptr; + bridge->join_irc_channel(iid, to.resource, + password ? password->get_inner() : ""); + } + else if (type == "unavailable") + { + XmlNode* status = stanza.get_child("status", COMPONENT_NS); + bridge->leave_irc_channel(std::move(iid), status ? std::move(status->get_inner()) : ""); + } + } + else + { + // An user wants to join an invalid IRC channel, return a presence error to him + if (type.empty()) + this->send_invalid_room_error(to.local, to.resource, from); + } + stanza_error.disable(); +} + +void BiboumiComponent::handle_message(const Stanza& stanza) +{ + std::string from = stanza.get_tag("from"); + std::string id = stanza.get_tag("id"); + std::string to_str = stanza.get_tag("to"); + std::string type = stanza.get_tag("type"); + + if (from.empty()) + return; + if (type.empty()) + type = "normal"; + Bridge* bridge = this->get_user_bridge(from); + Jid to(to_str); + Iid iid(to.local); + + std::string error_type("cancel"); + std::string error_name("internal-server-error"); + utils::ScopeGuard stanza_error([&](){ + this->send_stanza_error("message", from, to_str, id, + error_type, error_name, ""); + }); + XmlNode* body = stanza.get_child("body", COMPONENT_NS); + if (type == "groupchat" && iid.is_channel) + { + if (body && !body->get_inner().empty()) + { + bridge->send_channel_message(iid, body->get_inner()); + } + XmlNode* subject = stanza.get_child("subject", COMPONENT_NS); + if (subject) + bridge->set_channel_topic(iid, subject->get_inner()); + } + else if (type == "error") + { + const XmlNode* error = stanza.get_child("error", COMPONENT_NS); + // Only a set of errors are considered “fatal”. If we encounter one of + // them, we purge (we disconnect the user from all the IRC servers). + // We consider this to be true, unless the error condition is + // specified and is not in the kickable_errors set + bool kickable_error = true; + if (error && error->has_children()) + { + const XmlNode* condition = error->get_last_child(); + if (kickable_errors.find(condition->get_name()) == kickable_errors.end()) + kickable_error = false; + } + if (kickable_error) + bridge->shutdown("Error from remote client"); + } + else if (type == "chat") + { + if (body && !body->get_inner().empty()) + { + // a message for nick!server + if (iid.is_user && !iid.get_local().empty()) + { + bridge->send_private_message(iid, body->get_inner()); + bridge->remove_preferred_from_jid(iid.get_local()); + } + else if (!iid.is_user && !to.resource.empty()) + { // a message for chan%server@biboumi/Nick or + // server@biboumi/Nick + // Convert that into a message to nick!server + Iid user_iid(utils::tolower(to.resource) + "!" + iid.get_server()); + bridge->send_private_message(user_iid, body->get_inner()); + bridge->set_preferred_from_jid(user_iid.get_local(), to_str); + } + } + } + else if (iid.is_user) + this->send_invalid_user_error(to.local, from); + stanza_error.disable(); +} + +// We MUST return an iq, whatever happens, except if the type is +// "result". +// To do this, we use a scopeguard. If an exception is raised somewhere, an +// iq of type error "internal-server-error" is sent. If we handle the +// request properly (by calling a function that registers an iq to be sent +// later, or that directly sends an iq), we disable the ScopeGuard. If we +// reach the end of the function without having disabled the scopeguard, we +// send a "feature-not-implemented" iq as a result. If an other kind of +// error is found (for example the feature is implemented in biboumi, but +// the request is missing some attribute) we can just change the values of +// error_type and error_name and return from the function (without disabling +// the scopeguard); an iq error will be sent +void BiboumiComponent::handle_iq(const Stanza& stanza) +{ + std::string id = stanza.get_tag("id"); + std::string from = stanza.get_tag("from"); + std::string to_str = stanza.get_tag("to"); + std::string type = stanza.get_tag("type"); + + if (from.empty()) + return; + if (id.empty() || to_str.empty() || type.empty()) + { + this->send_stanza_error("iq", from, this->served_hostname, id, + "modify", "bad-request", ""); + return; + } + + Bridge* bridge = this->get_user_bridge(from); + Jid to(to_str); + + // These two values will be used in the error iq sent if we don't disable + // the scopeguard. + std::string error_type("cancel"); + std::string error_name("internal-server-error"); + utils::ScopeGuard stanza_error([&](){ + this->send_stanza_error("iq", from, to_str, id, + error_type, error_name, ""); + }); + if (type == "set") + { + XmlNode* query; + if ((query = stanza.get_child("query", MUC_ADMIN_NS))) + { + const XmlNode* child = query->get_child("item", MUC_ADMIN_NS); + if (child) + { + std::string nick = child->get_tag("nick"); + std::string role = child->get_tag("role"); + std::string affiliation = child->get_tag("affiliation"); + if (!nick.empty()) + { + Iid iid(to.local); + if (role == "none") + { // This is a kick + std::string reason; + XmlNode* reason_el = child->get_child("reason", MUC_ADMIN_NS); + if (reason_el) + reason = reason_el->get_inner(); + bridge->send_irc_kick(iid, nick, reason, id, from); + } + else + bridge->forward_affiliation_role_change(iid, nick, affiliation, role); + stanza_error.disable(); + } + } + } + else if ((query = stanza.get_child("command", ADHOC_NS))) + { + Stanza response("iq"); + response["to"] = from; + response["from"] = this->served_hostname; + response["id"] = id; + XmlNode inner_node = this->adhoc_commands_handler.handle_request(from, *query); + if (inner_node.get_child("error", ADHOC_NS)) + response["type"] = "error"; + else + response["type"] = "result"; + response.add_child(std::move(inner_node)); + response.close(); + this->send_stanza(response); + stanza_error.disable(); + } + } + else if (type == "get") + { + XmlNode* query; + if ((query = stanza.get_child("query", DISCO_INFO_NS))) + { // Disco info + if (to_str == this->served_hostname) + { + const std::string node = query->get_tag("node"); + if (node.empty()) + { + // On the gateway itself + this->send_self_disco_info(id, from); + stanza_error.disable(); + } + } + } + else if ((query = stanza.get_child("query", VERSION_NS))) + { + Iid iid(to.local); + if (iid.is_user || + (iid.is_channel && !to.resource.empty())) + { + // Get the IRC user version + std::string target; + if (iid.is_user) + target = iid.get_local(); + else + target = to.resource; + bridge->send_irc_version_request(iid.get_server(), target, id, + from, to_str); + } + else + { + // On the gateway itself or on a channel + this->send_version(id, from, to_str); + } + stanza_error.disable(); + } + else if ((query = stanza.get_child("query", DISCO_ITEMS_NS))) + { + Iid iid(to.local); + const std::string node = query->get_tag("node"); + if (node == ADHOC_NS) + { + this->send_adhoc_commands_list(id, from); + stanza_error.disable(); + } + else if (node.empty() && !iid.is_user && !iid.is_channel) + { // Disco on an IRC server: get the list of channels + bridge->send_irc_channel_list_request(iid, id, from); + stanza_error.disable(); + } + } + else if ((query = stanza.get_child("ping", PING_NS))) + { + Iid iid(to.local); + if (iid.is_user) + { // Ping any user (no check on the nick done ourself) + bridge->send_irc_user_ping_request(iid.get_server(), + iid.get_local(), id, from, to_str); + } + else if (iid.is_channel && !to.resource.empty()) + { // Ping a room participant (we check if the nick is in the room) + bridge->send_irc_participant_ping_request(iid, + to.resource, id, from, to_str); + } + else + { // Ping a channel, a server or the gateway itself + bridge->on_gateway_ping(iid.get_server(), + id, from, to_str); + } + stanza_error.disable(); + } + } + else if (type == "result") + { + stanza_error.disable(); + XmlNode* query; + if ((query = stanza.get_child("query", VERSION_NS))) + { + XmlNode* name_node = query->get_child("name", VERSION_NS); + XmlNode* version_node = query->get_child("version", VERSION_NS); + XmlNode* os_node = query->get_child("os", VERSION_NS); + std::string name; + std::string version; + std::string os; + if (name_node) + name = name_node->get_inner() + " (through the biboumi gateway)"; + if (version_node) + version = version_node->get_inner(); + if (os_node) + os = os_node->get_inner(); + const Iid iid(to.local); + bridge->send_xmpp_version_to_irc(iid, name, version, os); + } + else + { + const auto it = this->waiting_iq.find(id); + if (it != this->waiting_iq.end()) + { + it->second(bridge, stanza); + this->waiting_iq.erase(it); + } + } + } + error_type = "cancel"; + error_name = "feature-not-implemented"; +} + +Bridge* BiboumiComponent::get_user_bridge(const std::string& user_jid) +{ + try + { + return this->bridges.at(user_jid).get(); + } + catch (const std::out_of_range& exception) + { + this->bridges.emplace(user_jid, std::make_unique(user_jid, this, this->poller)); + return this->bridges.at(user_jid).get(); + } +} + +Bridge* BiboumiComponent::find_user_bridge(const std::string& user_jid) +{ + try + { + return this->bridges.at(user_jid).get(); + } + catch (const std::out_of_range& exception) + { + return nullptr; + } +} + +std::list BiboumiComponent::get_bridges() const +{ + std::list res; + for (auto it = this->bridges.begin(); it != this->bridges.end(); ++it) + res.push_back(it->second.get()); + return res; +} + +void BiboumiComponent::send_self_disco_info(const std::string& id, const std::string& jid_to) +{ + Stanza iq("iq"); + iq["type"] = "result"; + iq["id"] = id; + iq["to"] = jid_to; + iq["from"] = this->served_hostname; + XmlNode query("query"); + query["xmlns"] = DISCO_INFO_NS; + XmlNode identity("identity"); + 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); +} + +void BiboumiComponent::send_adhoc_commands_list(const std::string& id, const std::string& requester_jid) +{ + Stanza iq("iq"); + iq["type"] = "result"; + iq["id"] = id; + iq["to"] = requester_jid; + iq["from"] = this->served_hostname; + XmlNode query("query"); + query["xmlns"] = DISCO_ITEMS_NS; + query["node"] = ADHOC_NS; + for (const auto& kv: this->adhoc_commands_handler.get_commands()) + { + XmlNode item("item"); + 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); +} + +void BiboumiComponent::send_iq_version_request(const std::string& from, + const std::string& jid_to) +{ + Stanza iq("iq"); + iq["type"] = "get"; + iq["id"] = "version_"s + this->next_id(); + iq["from"] = from + "@" + this->served_hostname; + 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); +} + +void BiboumiComponent::send_ping_request(const std::string& from, + const std::string& jid_to, + const std::string& id) +{ + Stanza iq("iq"); + iq["type"] = "get"; + iq["id"] = id; + iq["from"] = from + "@" + this->served_hostname; + iq["to"] = jid_to; + XmlNode ping("ping"); + ping["xmlns"] = PING_NS; + ping.close(); + iq.add_child(std::move(ping)); + iq.close(); + this->send_stanza(iq); + + auto result_cb = [from, id](Bridge* bridge, const Stanza& stanza) + { + Jid to(stanza.get_tag("to")); + if (to.local != from) + { + log_error("Received a corresponding ping result, but the 'to' from " + "the response mismatches the 'from' of the request"); + } + else + bridge->send_irc_ping_result(from, id); + }; + this->waiting_iq[id] = result_cb; +} + +void BiboumiComponent::send_iq_room_list_result(const std::string& id, + const std::string to_jid, + const std::string& from, + const std::vector& rooms_list) +{ + Stanza iq("iq"); + iq["from"] = from + "@" + this->served_hostname; + iq["to"] = to_jid; + iq["id"] = id; + iq["type"] = "result"; + XmlNode query("query"); + query["xmlns"] = DISCO_ITEMS_NS; + for (const auto& room: rooms_list) + { + XmlNode item("item"); + item["jid"] = room.channel + "%" + from + "@" + this->served_hostname; + item.close(); + query.add_child(std::move(item)); + } + query.close(); + iq.add_child(std::move(query)); + iq.close(); + this->send_stanza(iq); +} -- cgit v1.2.3 From d31619714b0a55ea9330d34f35480d4ae7f8f055 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 2 Mar 2015 11:04:55 +0100 Subject: Move non-specific adhoc commands into louloulibs Only keep some biboumi-specific commands into biboumi_adhoc_commands.hpp/cpp --- src/xmpp/biboumi_component.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 2ecf247..ba8cb49 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 0a6b673b14efc4f623ea445045e6fc60e9842a25 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 7 May 2015 17:01:17 +0200 Subject: Support raw IRC messages Messages received on an IRC server JID are forwarded as raw IRC messages. fix #2486 --- src/xmpp/biboumi_component.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index ba8cb49..37383a8 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -211,6 +211,11 @@ void BiboumiComponent::handle_message(const Stanza& stanza) bridge->send_private_message(user_iid, body->get_inner()); bridge->set_preferred_from_jid(user_iid.get_local(), to_str); } + else if (!iid.is_user && !iid.is_channel) + { // Message sent to the server JID + // Convert the message body into a raw IRC message + bridge->send_raw_message(iid.get_server(), body->get_inner()); + } } } else if (iid.is_user) -- cgit v1.2.3 From 5475d16b574e1daf9c1e5f94b5b821bfb1b9c8f8 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 11 May 2015 04:47:31 +0200 Subject: Return a stanza error whenever the IRCClient for a given server does not exist Instead of ignoring the stanza, we send back an error of type remote-server-not-found each time it's possible. Also avoid having to do if (!irc) return; everytime. fix #3045 --- src/xmpp/biboumi_component.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 37383a8..4996438 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -166,6 +166,8 @@ void BiboumiComponent::handle_message(const Stanza& stanza) error_type, error_name, ""); }); XmlNode* body = stanza.get_child("body", COMPONENT_NS); + + try { // catch IRCNotConnected exceptions if (type == "groupchat" && iid.is_channel) { if (body && !body->get_inner().empty()) @@ -220,6 +222,13 @@ void BiboumiComponent::handle_message(const Stanza& stanza) } else if (iid.is_user) this->send_invalid_user_error(to.local, from); + } catch (const IRCNotConnected& ex) + { + this->send_stanza_error("message", from, to_str, id, + "cancel", "remote-server-not-found", + "Not connected to IRC server "s + ex.hostname, + true); + } stanza_error.disable(); } @@ -262,6 +271,7 @@ void BiboumiComponent::handle_iq(const Stanza& stanza) this->send_stanza_error("iq", from, to_str, id, error_type, error_name, ""); }); + try { if (type == "set") { XmlNode* query; @@ -412,6 +422,16 @@ void BiboumiComponent::handle_iq(const Stanza& stanza) } } } + } + catch (const IRCNotConnected& ex) + { + this->send_stanza_error("iq", from, to_str, id, + "cancel", "remote-server-not-found", + "Not connected to IRC server "s + ex.hostname, + true); + stanza_error.disable(); + return; + } error_type = "cancel"; error_name = "feature-not-implemented"; } -- cgit v1.2.3 From ad5bd99618fd4f1ee92d48d90912d627187aaa11 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 11 May 2015 05:03:09 +0200 Subject: Properly send error response on presence stanzas --- src/xmpp/biboumi_component.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 4996438..5d571ec 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -116,6 +116,7 @@ void BiboumiComponent::handle_presence(const Stanza& stanza) error_type, error_name, ""); }); + try { if (iid.is_channel && !iid.get_server().empty()) { // presence toward a MUC that corresponds to an irc channel, or a // dummy channel if iid.chan is empty @@ -141,6 +142,14 @@ void BiboumiComponent::handle_presence(const Stanza& stanza) if (type.empty()) this->send_invalid_room_error(to.local, to.resource, from); } + } + catch (const IRCNotConnected& ex) + { + this->send_stanza_error("presence", from, to_str, id, + "cancel", "remote-server-not-found", + "Not connected to IRC server "s + ex.hostname, + true); + } stanza_error.disable(); } -- cgit v1.2.3 From 8da03f98307e03a767cb68659c8473c896cbd325 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 9 Jun 2015 14:51:55 +0200 Subject: Remove a useless duplicate method --- src/xmpp/biboumi_component.cpp | 25 ------------------------- 1 file changed, 25 deletions(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 5d571ec..b7613d3 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -506,31 +506,6 @@ void BiboumiComponent::send_self_disco_info(const std::string& id, const std::st this->send_stanza(iq); } -void BiboumiComponent::send_adhoc_commands_list(const std::string& id, const std::string& requester_jid) -{ - Stanza iq("iq"); - iq["type"] = "result"; - iq["id"] = id; - iq["to"] = requester_jid; - iq["from"] = this->served_hostname; - XmlNode query("query"); - query["xmlns"] = DISCO_ITEMS_NS; - query["node"] = ADHOC_NS; - for (const auto& kv: this->adhoc_commands_handler.get_commands()) - { - XmlNode item("item"); - 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); -} - void BiboumiComponent::send_iq_version_request(const std::string& from, const std::string& jid_to) { -- cgit v1.2.3 From 7f7c429ae4c49e856a43816138991135ffb7f840 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 9 Jun 2015 14:52:46 +0200 Subject: Do not send the admin-only adhoc commands to non-admin users They were not able to execute them anyway, so this was just a little usability issue. --- src/xmpp/biboumi_component.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index b7613d3..c1fa339 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -50,7 +50,7 @@ BiboumiComponent::BiboumiComponent(std::shared_ptr poller, const std::st this->stanza_handlers.emplace("iq", std::bind(&BiboumiComponent::handle_iq, this,std::placeholders::_1)); - this->adhoc_commands_handler.get_commands()= { + this->adhoc_commands_handler.get_commands() = { {"ping", AdhocCommand({&PingStep1}, "Do a ping", false)}, {"hello", AdhocCommand({&HelloStep1, &HelloStep2}, "Receive a custom greeting", false)}, {"disconnect-user", AdhocCommand({&DisconnectUserStep1, &DisconnectUserStep2}, "Disconnect a user from the gateway", true)}, @@ -370,7 +370,10 @@ void BiboumiComponent::handle_iq(const Stanza& stanza) const std::string node = query->get_tag("node"); if (node == ADHOC_NS) { - this->send_adhoc_commands_list(id, from); + Jid from_jid(from); + this->send_adhoc_commands_list(id, from, + (Config::get("admin", "") == + from_jid.local + "@" + from_jid.domain)); stanza_error.disable(); } else if (node.empty() && !iid.is_user && !iid.is_channel) -- cgit v1.2.3 From e8f22efe34415db0e1e5cb94635b089b18efe055 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 1 Sep 2015 04:42:12 +0200 Subject: 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) --- src/xmpp/biboumi_component.cpp | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index c1fa339..f578c30 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -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); } @@ -536,9 +529,7 @@ void BiboumiComponent::send_ping_request(const std::string& from, iq["to"] = jid_to; XmlNode ping("ping"); ping["xmlns"] = PING_NS; - ping.close(); iq.add_child(std::move(ping)); - iq.close(); this->send_stanza(iq); auto result_cb = [from, id](Bridge* bridge, const Stanza& stanza) @@ -571,11 +562,8 @@ void BiboumiComponent::send_iq_room_list_result(const std::string& id, { XmlNode item("item"); item["jid"] = room.channel + "%" + from + "@" + this->served_hostname; - item.close(); query.add_child(std::move(item)); } - query.close(); iq.add_child(std::move(query)); - iq.close(); this->send_stanza(iq); } -- cgit v1.2.3 From f3b3d937ae274d0eec4a737d11ba19a7f4ceef03 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 1 Sep 2015 14:47:57 +0200 Subject: =?UTF-8?q?Use=20unique=5Fptr=20to=20store=20the=20XmlNode?= =?UTF-8?q?=E2=80=99s=20children?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also fix some constness things --- src/xmpp/biboumi_component.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index f578c30..51775ab 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -125,14 +125,14 @@ void BiboumiComponent::handle_presence(const Stanza& stanza) const std::string own_nick = bridge->get_own_nick(iid); if (!own_nick.empty() && own_nick != to.resource) bridge->send_irc_nick_change(iid, to.resource); - XmlNode* x = stanza.get_child("x", MUC_NS); - XmlNode* password = x ? x->get_child("password", MUC_NS): nullptr; + const XmlNode* x = stanza.get_child("x", MUC_NS); + const XmlNode* password = x ? x->get_child("password", MUC_NS): nullptr; bridge->join_irc_channel(iid, to.resource, password ? password->get_inner() : ""); } else if (type == "unavailable") { - XmlNode* status = stanza.get_child("status", COMPONENT_NS); + const XmlNode* status = stanza.get_child("status", COMPONENT_NS); bridge->leave_irc_channel(std::move(iid), status ? std::move(status->get_inner()) : ""); } } @@ -174,7 +174,7 @@ void BiboumiComponent::handle_message(const Stanza& stanza) this->send_stanza_error("message", from, to_str, id, error_type, error_name, ""); }); - XmlNode* body = stanza.get_child("body", COMPONENT_NS); + const XmlNode* body = stanza.get_child("body", COMPONENT_NS); try { // catch IRCNotConnected exceptions if (type == "groupchat" && iid.is_channel) @@ -183,7 +183,7 @@ void BiboumiComponent::handle_message(const Stanza& stanza) { bridge->send_channel_message(iid, body->get_inner()); } - XmlNode* subject = stanza.get_child("subject", COMPONENT_NS); + const XmlNode* subject = stanza.get_child("subject", COMPONENT_NS); if (subject) bridge->set_channel_topic(iid, subject->get_inner()); } @@ -283,7 +283,7 @@ void BiboumiComponent::handle_iq(const Stanza& stanza) try { if (type == "set") { - XmlNode* query; + const XmlNode* query; if ((query = stanza.get_child("query", MUC_ADMIN_NS))) { const XmlNode* child = query->get_child("item", MUC_ADMIN_NS); @@ -298,7 +298,7 @@ void BiboumiComponent::handle_iq(const Stanza& stanza) if (role == "none") { // This is a kick std::string reason; - XmlNode* reason_el = child->get_child("reason", MUC_ADMIN_NS); + const XmlNode* reason_el = child->get_child("reason", MUC_ADMIN_NS); if (reason_el) reason = reason_el->get_inner(); bridge->send_irc_kick(iid, nick, reason, id, from); @@ -327,7 +327,7 @@ void BiboumiComponent::handle_iq(const Stanza& stanza) } else if (type == "get") { - XmlNode* query; + const XmlNode* query; if ((query = stanza.get_child("query", DISCO_INFO_NS))) { // Disco info if (to_str == this->served_hostname) @@ -405,12 +405,12 @@ void BiboumiComponent::handle_iq(const Stanza& stanza) else if (type == "result") { stanza_error.disable(); - XmlNode* query; + const XmlNode* query; if ((query = stanza.get_child("query", VERSION_NS))) { - XmlNode* name_node = query->get_child("name", VERSION_NS); - XmlNode* version_node = query->get_child("version", VERSION_NS); - XmlNode* os_node = query->get_child("os", VERSION_NS); + const XmlNode* name_node = query->get_child("name", VERSION_NS); + const XmlNode* version_node = query->get_child("version", VERSION_NS); + const XmlNode* os_node = query->get_child("os", VERSION_NS); std::string name; std::string version; std::string os; -- cgit v1.2.3 From 45e8fe56a688ec03201cdfc3dfea6ae186af682d Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 18 Sep 2015 21:55:21 +0200 Subject: Add an AdhocCommandsHandler to store commands specific to IRC servers --- src/xmpp/biboumi_component.cpp | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 51775ab..974676b 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -41,7 +41,8 @@ static std::set kickable_errors{ BiboumiComponent::BiboumiComponent(std::shared_ptr poller, const std::string& hostname, const std::string& secret): - XmppComponent(poller, hostname, secret) + XmppComponent(poller, hostname, secret), + irc_server_adhoc_commands_handler(this) { this->stanza_handlers.emplace("presence", std::bind(&BiboumiComponent::handle_presence, this,std::placeholders::_1)); @@ -313,9 +314,21 @@ void BiboumiComponent::handle_iq(const Stanza& stanza) { Stanza response("iq"); response["to"] = from; - response["from"] = this->served_hostname; + response["from"] = to_str; response["id"] = id; - XmlNode inner_node = this->adhoc_commands_handler.handle_request(from, *query); + + // Depending on the 'to' jid in the request, we use one adhoc + // command handler or an other + Iid iid(to.local); + AdhocCommandsHandler* adhoc_handler; + if (!to.local.empty() && !iid.is_user && !iid.is_channel) + adhoc_handler = &this->irc_server_adhoc_commands_handler; + else + adhoc_handler = &this->adhoc_commands_handler; + + // Execute the command, if any, and get a result XmlNode that we + // insert in our response + XmlNode inner_node = adhoc_handler->handle_request(from, to_str, *query); if (inner_node.get_child("error", ADHOC_NS)) response["type"] = "error"; else @@ -370,10 +383,22 @@ void BiboumiComponent::handle_iq(const Stanza& stanza) if (node == ADHOC_NS) { Jid from_jid(from); - this->send_adhoc_commands_list(id, from, - (Config::get("admin", "") == - from_jid.local + "@" + from_jid.domain)); - stanza_error.disable(); + if (to.local.empty()) + { // Get biboumi's adhoc commands + this->send_adhoc_commands_list(id, from, this->served_hostname, + (Config::get("admin", "") == + from_jid.local + "@" + from_jid.domain), + this->adhoc_commands_handler); + stanza_error.disable(); + } + else if (!iid.is_user && !iid.is_channel) + { // Get the server's adhoc commands + this->send_adhoc_commands_list(id, from, to_str, + (Config::get("admin", "") == + from_jid.local + "@" + from_jid.domain), + this->irc_server_adhoc_commands_handler); + stanza_error.disable(); + } } else if (node.empty() && !iid.is_user && !iid.is_channel) { // Disco on an IRC server: get the list of channels -- cgit v1.2.3 From 1691cf8f64d6175c61ddf9a4f4a95b44c32d698e Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 18 Sep 2015 22:01:02 +0200 Subject: Introduce the configure ad-hoc command on irc servers Provides two options for now, and they have no effect yet --- src/xmpp/biboumi_component.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 974676b..920a2a3 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -17,6 +17,7 @@ #include #include +#include #include @@ -57,6 +58,12 @@ BiboumiComponent::BiboumiComponent(std::shared_ptr poller, const std::st {"disconnect-user", AdhocCommand({&DisconnectUserStep1, &DisconnectUserStep2}, "Disconnect a user from the gateway", true)}, {"reload", AdhocCommand({&Reload}, "Reload biboumi’s configuration", true)} }; + + this->irc_server_adhoc_commands_handler.get_commands() = { +#ifdef USE_DATABASE + {"configure", AdhocCommand({&ConfigureIrcServerStep1, &ConfigureIrcServerStep2}, "Configure a few settings for that IRC server", false)}, +#endif + }; } void BiboumiComponent::shutdown() -- cgit v1.2.3 From 142516a69bb000ce80cbb6509d1f407438a94663 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 26 Oct 2015 20:09:39 +0100 Subject: Fix some trivial issues reported by cppcheck --- src/xmpp/biboumi_component.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 920a2a3..10dce57 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -579,7 +579,7 @@ void BiboumiComponent::send_ping_request(const std::string& from, } void BiboumiComponent::send_iq_room_list_result(const std::string& id, - const std::string to_jid, + const std::string& to_jid, const std::string& from, const std::vector& rooms_list) { -- cgit v1.2.3 From de6335b9944190ec5454ff4052710d05d8b02b43 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 5 Nov 2015 02:37:46 +0100 Subject: Fix a clang warning --- src/xmpp/biboumi_component.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 10dce57..f4de302 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -141,7 +141,7 @@ void BiboumiComponent::handle_presence(const Stanza& stanza) else if (type == "unavailable") { const XmlNode* status = stanza.get_child("status", COMPONENT_NS); - bridge->leave_irc_channel(std::move(iid), status ? std::move(status->get_inner()) : ""); + bridge->leave_irc_channel(std::move(iid), status ? status->get_inner() : ""); } } else -- cgit v1.2.3 From 700a6c7bc39aa48af5037ecbb9778b20fb6f87df Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 3 Dec 2015 21:09:26 +0100 Subject: JID class provides bare() and full() methods --- src/xmpp/biboumi_component.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index f4de302..6f1e585 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -394,7 +394,7 @@ void BiboumiComponent::handle_iq(const Stanza& stanza) { // Get biboumi's adhoc commands this->send_adhoc_commands_list(id, from, this->served_hostname, (Config::get("admin", "") == - from_jid.local + "@" + from_jid.domain), + from_jid.bare()), this->adhoc_commands_handler); stanza_error.disable(); } @@ -402,7 +402,7 @@ void BiboumiComponent::handle_iq(const Stanza& stanza) { // Get the server's adhoc commands this->send_adhoc_commands_list(id, from, to_str, (Config::get("admin", "") == - from_jid.local + "@" + from_jid.domain), + from_jid.bare()), this->irc_server_adhoc_commands_handler); stanza_error.disable(); } -- cgit v1.2.3 From 1f6eea62f46789c0d3ebe7da133ccad2e59c89c8 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 3 Dec 2015 21:14:24 +0100 Subject: Add an ad-hoc command to disconnect a user from one or more IRC server fix #3077 --- src/xmpp/biboumi_component.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 6f1e585..72b767f 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -55,7 +55,8 @@ BiboumiComponent::BiboumiComponent(std::shared_ptr poller, const std::st this->adhoc_commands_handler.get_commands() = { {"ping", AdhocCommand({&PingStep1}, "Do a ping", false)}, {"hello", AdhocCommand({&HelloStep1, &HelloStep2}, "Receive a custom greeting", false)}, - {"disconnect-user", AdhocCommand({&DisconnectUserStep1, &DisconnectUserStep2}, "Disconnect a user from the gateway", true)}, + {"disconnect-user", AdhocCommand({&DisconnectUserStep1, &DisconnectUserStep2}, "Disconnect selected users from the gateway", true)}, + {"disconnect-from-irc-servers", AdhocCommand({&DisconnectUserFromServerStep1, &DisconnectUserFromServerStep2, &DisconnectUserFromServerStep3}, "Disconnect from the selected IRC servers", false)}, {"reload", AdhocCommand({&Reload}, "Reload biboumi’s configuration", true)} }; -- cgit v1.2.3 From 7e2427148e9023483f266cd3ac4e167d50320796 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 21 Dec 2015 20:45:40 +0100 Subject: =?UTF-8?q?Use=20references=20instead=20of=20raw=20pointer,=20to?= =?UTF-8?q?=20store=20the=20=E2=80=9Cparent=E2=80=9D=20object?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In Bridge and IrcClient --- src/xmpp/biboumi_component.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 72b767f..9682dcb 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -488,7 +488,7 @@ Bridge* BiboumiComponent::get_user_bridge(const std::string& user_jid) } catch (const std::out_of_range& exception) { - this->bridges.emplace(user_jid, std::make_unique(user_jid, this, this->poller)); + this->bridges.emplace(user_jid, std::make_unique(user_jid, *this, this->poller)); return this->bridges.at(user_jid).get(); } } -- cgit v1.2.3 From 9714d02018904b0c207a3f4d7de0be1a6a22774b Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 21 Dec 2015 21:15:03 +0100 Subject: Also store a reference instead of a pointer, in AdhocCommandsHandler --- src/xmpp/biboumi_component.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 9682dcb..e697fcd 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -43,7 +43,7 @@ static std::set kickable_errors{ BiboumiComponent::BiboumiComponent(std::shared_ptr poller, const std::string& hostname, const std::string& secret): XmppComponent(poller, hostname, secret), - irc_server_adhoc_commands_handler(this) + irc_server_adhoc_commands_handler(*this) { this->stanza_handlers.emplace("presence", std::bind(&BiboumiComponent::handle_presence, this,std::placeholders::_1)); -- cgit v1.2.3 From 1fc3fa1bd8d98d45d18e8af76202cbf6b757b369 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 24 Dec 2015 15:50:29 +0100 Subject: Add an ad-hoc configure command on IRC channels Include encodingIn and encodingOut options, unused at the moment --- src/xmpp/biboumi_component.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index e697fcd..e30bdd3 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -43,7 +43,8 @@ static std::set kickable_errors{ BiboumiComponent::BiboumiComponent(std::shared_ptr poller, const std::string& hostname, const std::string& secret): XmppComponent(poller, hostname, secret), - irc_server_adhoc_commands_handler(*this) + irc_server_adhoc_commands_handler(*this), + irc_channel_adhoc_commands_handler(*this) { this->stanza_handlers.emplace("presence", std::bind(&BiboumiComponent::handle_presence, this,std::placeholders::_1)); @@ -65,6 +66,9 @@ BiboumiComponent::BiboumiComponent(std::shared_ptr poller, const std::st {"configure", AdhocCommand({&ConfigureIrcServerStep1, &ConfigureIrcServerStep2}, "Configure a few settings for that IRC server", false)}, #endif }; + this->irc_channel_adhoc_commands_handler.get_commands() = { + {"configure", AdhocCommand({&ConfigureIrcChannelStep1, &ConfigureIrcChannelStep2}, "Configure a few settings for that IRC channel", false)}, + }; } void BiboumiComponent::shutdown() @@ -331,6 +335,8 @@ void BiboumiComponent::handle_iq(const Stanza& stanza) AdhocCommandsHandler* adhoc_handler; if (!to.local.empty() && !iid.is_user && !iid.is_channel) adhoc_handler = &this->irc_server_adhoc_commands_handler; + else if (!to.local.empty() && iid.is_channel) + adhoc_handler = &this->irc_channel_adhoc_commands_handler; else adhoc_handler = &this->adhoc_commands_handler; @@ -407,6 +413,14 @@ void BiboumiComponent::handle_iq(const Stanza& stanza) this->irc_server_adhoc_commands_handler); stanza_error.disable(); } + else if (!iid.is_user && iid.is_channel) + { // Get the channel's adhoc commands + this->send_adhoc_commands_list(id, from, to_str, + (Config::get("admin", "") == + from_jid.bare()), + this->irc_channel_adhoc_commands_handler); + stanza_error.disable(); + } } else if (node.empty() && !iid.is_user && !iid.is_channel) { // Disco on an IRC server: get the list of channels -- cgit v1.2.3 From 4233e1f6538351e3bf3c15c88454455998b718e5 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 9 Jan 2016 17:00:52 +0100 Subject: Do not fail to build when litesql is not used fix #3151 --- src/xmpp/biboumi_component.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index e30bdd3..564c79a 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -67,7 +67,9 @@ BiboumiComponent::BiboumiComponent(std::shared_ptr poller, const std::st #endif }; this->irc_channel_adhoc_commands_handler.get_commands() = { +#ifdef USE_DATABASE {"configure", AdhocCommand({&ConfigureIrcChannelStep1, &ConfigureIrcChannelStep2}, "Configure a few settings for that IRC channel", false)}, +#endif }; } -- cgit v1.2.3 From 6770629bd7db1bf9f371a1d8a2376fad71cbd0f7 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 21 Jan 2016 16:52:44 +0100 Subject: Fix a clang-check warning I think it was a UB --- src/xmpp/biboumi_component.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 564c79a..65fbfc5 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -543,7 +543,7 @@ void BiboumiComponent::send_self_disco_info(const std::string& id, const std::st identity["type"] = "irc"; identity["name"] = "Biboumi XMPP-IRC gateway"; query.add_child(std::move(identity)); - for (const std::string& ns: {DISCO_INFO_NS, MUC_NS, ADHOC_NS}) + for (const char* ns: {DISCO_INFO_NS, MUC_NS, ADHOC_NS}) { XmlNode feature("feature"); feature["var"] = ns; -- cgit v1.2.3 From 1e56c59e8241dbfc6a2526c371cc2e894f9d0f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 25 Apr 2016 11:29:52 +0200 Subject: Include the Configure ad-hoc command on biboumi's JID for fixed_irc_server MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Because a jid like “freenode.example.org” is both the JID for the configured IRC server, and biboumi’s JID. fix #3175 --- src/xmpp/biboumi_component.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 65fbfc5..5b1d0e0 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -61,9 +61,18 @@ BiboumiComponent::BiboumiComponent(std::shared_ptr poller, const std::st {"reload", AdhocCommand({&Reload}, "Reload biboumi’s configuration", true)} }; +#ifdef USE_DATABASE + AdhocCommand configure_server_command({&ConfigureIrcServerStep1, &ConfigureIrcServerStep2}, "Configure a few settings for that IRC server", false); + if (!Config::get("fixed_irc_server", "").empty()) + { + this->adhoc_commands_handler.get_commands().emplace(std::make_pair("configure", + configure_server_command)); + } +#endif + this->irc_server_adhoc_commands_handler.get_commands() = { #ifdef USE_DATABASE - {"configure", AdhocCommand({&ConfigureIrcServerStep1, &ConfigureIrcServerStep2}, "Configure a few settings for that IRC server", false)}, + {"configure", configure_server_command}, #endif }; this->irc_channel_adhoc_commands_handler.get_commands() = { -- cgit v1.2.3 From 367de4826c3c7298a88e80c92e325081a3c3d794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 18 May 2016 22:53:17 +0200 Subject: Associate a bridge with a bare JID instead of a full JID ref #2556 --- src/xmpp/biboumi_component.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 5b1d0e0..94d85c6 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -507,22 +507,24 @@ void BiboumiComponent::handle_iq(const Stanza& stanza) Bridge* BiboumiComponent::get_user_bridge(const std::string& user_jid) { + auto bare_jid = Jid{user_jid}.bare(); try { - return this->bridges.at(user_jid).get(); + return this->bridges.at(bare_jid).get(); } catch (const std::out_of_range& exception) { - this->bridges.emplace(user_jid, std::make_unique(user_jid, *this, this->poller)); - return this->bridges.at(user_jid).get(); + this->bridges.emplace(bare_jid, std::make_unique(bare_jid, *this, this->poller)); + return this->bridges.at(bare_jid).get(); } } Bridge* BiboumiComponent::find_user_bridge(const std::string& user_jid) { + auto bare_jid = Jid{user_jid}.bare(); try { - return this->bridges.at(user_jid).get(); + return this->bridges.at(bare_jid).get(); } catch (const std::out_of_range& exception) { -- cgit v1.2.3 From 711861d40e365564e3828a251066c16e924d30f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Sun, 22 May 2016 12:54:18 +0200 Subject: Add methods to know which resource is on which server or channel --- src/xmpp/biboumi_component.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 94d85c6..6dae92c 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -519,9 +519,9 @@ Bridge* BiboumiComponent::get_user_bridge(const std::string& user_jid) } } -Bridge* BiboumiComponent::find_user_bridge(const std::string& user_jid) +Bridge* BiboumiComponent::find_user_bridge(const std::string& full_jid) { - auto bare_jid = Jid{user_jid}.bare(); + auto bare_jid = Jid{full_jid}.bare(); try { return this->bridges.at(bare_jid).get(); -- cgit v1.2.3 From 66609cfba2b581be52de6096193751d1bb4ec3c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Sun, 22 May 2016 12:52:05 +0200 Subject: Remove all usage of std::list --- src/xmpp/biboumi_component.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 6dae92c..e5aee9a 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -532,9 +532,9 @@ Bridge* BiboumiComponent::find_user_bridge(const std::string& full_jid) } } -std::list BiboumiComponent::get_bridges() const +std::vector BiboumiComponent::get_bridges() const { - std::list res; + std::vector res; for (auto it = this->bridges.begin(); it != this->bridges.end(); ++it) res.push_back(it->second.get()); return res; -- cgit v1.2.3 From 507d0c2cbe3c41e3d8e6d38862fe418cb551adf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Thu, 2 Jun 2016 01:35:15 +0200 Subject: Forward everything to all concerned XMPP resources --- src/xmpp/biboumi_component.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index e5aee9a..6a9bc87 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -105,26 +105,27 @@ void BiboumiComponent::clean() void BiboumiComponent::handle_presence(const Stanza& stanza) { - std::string from = stanza.get_tag("from"); + std::string from_str = stanza.get_tag("from"); std::string id = stanza.get_tag("id"); std::string to_str = stanza.get_tag("to"); std::string type = stanza.get_tag("type"); // Check for mandatory tags - if (from.empty()) + if (from_str.empty()) { log_warning("Received an invalid presence stanza: tag 'from' is missing."); return; } if (to_str.empty()) { - this->send_stanza_error("presence", from, this->served_hostname, id, + this->send_stanza_error("presence", from_str, this->served_hostname, id, "modify", "bad-request", "Missing 'to' tag"); return; } - Bridge* bridge = this->get_user_bridge(from); + Bridge* bridge = this->get_user_bridge(from_str); Jid to(to_str); + Jid from(from_str); Iid iid(to.local); // An error stanza is sent whenever we exit this function without @@ -136,7 +137,7 @@ void BiboumiComponent::handle_presence(const Stanza& stanza) std::string error_type("cancel"); std::string error_name("internal-server-error"); utils::ScopeGuard stanza_error([&](){ - this->send_stanza_error("presence", from, to_str, id, + this->send_stanza_error("presence", from_str, to_str, id, error_type, error_name, ""); }); @@ -151,8 +152,8 @@ void BiboumiComponent::handle_presence(const Stanza& stanza) bridge->send_irc_nick_change(iid, to.resource); const XmlNode* x = stanza.get_child("x", MUC_NS); const XmlNode* password = x ? x->get_child("password", MUC_NS): nullptr; - bridge->join_irc_channel(iid, to.resource, - password ? password->get_inner() : ""); + bridge->join_irc_channel(iid, to.resource, password ? password->get_inner(): "", + from.resource); } else if (type == "unavailable") { @@ -164,12 +165,12 @@ void BiboumiComponent::handle_presence(const Stanza& stanza) { // An user wants to join an invalid IRC channel, return a presence error to him if (type.empty()) - this->send_invalid_room_error(to.local, to.resource, from); + this->send_invalid_room_error(to.local, to.resource, from_str); } } catch (const IRCNotConnected& ex) { - this->send_stanza_error("presence", from, to_str, id, + this->send_stanza_error("presence", from_str, to_str, id, "cancel", "remote-server-not-found", "Not connected to IRC server "s + ex.hostname, true); -- cgit v1.2.3 From 2d11a5f49454717c404b25825f18e696281207d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 8 Jun 2016 01:32:39 +0200 Subject: Support multiple nick session, except for IQs ref #2556 --- src/xmpp/biboumi_component.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 6a9bc87..62e17d0 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -158,7 +158,7 @@ void BiboumiComponent::handle_presence(const Stanza& stanza) else if (type == "unavailable") { const XmlNode* status = stanza.get_child("status", COMPONENT_NS); - bridge->leave_irc_channel(std::move(iid), status ? status->get_inner() : ""); + bridge->leave_irc_channel(std::move(iid), status ? status->get_inner() : "", from.resource); } } else -- cgit v1.2.3 From b2e7edeea8bf08b6b7e75d60af3af0c30fdaa4f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Fri, 24 Jun 2016 11:23:01 +0200 Subject: =?UTF-8?q?Properly=20set=20the=20=E2=80=9Cfrom=E2=80=9D=20of=20th?= =?UTF-8?q?e=20ping=20results=20to=20the=20correct=20full=20JID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/xmpp/biboumi_component.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 62e17d0..e4d4899 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -580,8 +580,8 @@ void BiboumiComponent::send_iq_version_request(const std::string& from, } void BiboumiComponent::send_ping_request(const std::string& from, - const std::string& jid_to, - const std::string& id) + const std::string& jid_to, + const std::string& id) { Stanza iq("iq"); iq["type"] = "get"; -- cgit v1.2.3 From fcb2681b7b3f221160fac027731fc3688d73d59d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Fri, 24 Jun 2016 11:24:40 +0200 Subject: Log a warning when we receive an iq without a from --- src/xmpp/biboumi_component.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/xmpp/biboumi_component.cpp') diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index e4d4899..a6aac21 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -285,8 +285,10 @@ void BiboumiComponent::handle_iq(const Stanza& stanza) std::string to_str = stanza.get_tag("to"); std::string type = stanza.get_tag("type"); - if (from.empty()) + if (from.empty()) { + log_warning("Received an iq without a 'from'. Ignoring."); return; + } if (id.empty() || to_str.empty() || type.empty()) { this->send_stanza_error("iq", from, this->served_hostname, id, -- cgit v1.2.3