From 545ab11ff3a334b242ba2d7fc87e2b6ba0185cb5 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 18 Jun 2014 11:46:28 +0200 Subject: Support version request to IRC users --- src/bridge/bridge.cpp | 36 ++++++++++++++++++++++++++++++ src/bridge/bridge.hpp | 6 ++++- src/xmpp/xmpp_component.cpp | 53 ++++++++++++++++++++++++++++++++------------- src/xmpp/xmpp_component.hpp | 6 +++-- 4 files changed, 83 insertions(+), 18 deletions(-) diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 384131f..9501d47 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -275,6 +275,42 @@ void Bridge::send_xmpp_version_to_irc(const Iid& iid, const std::string& name, c this->send_private_message(iid, "\01VERSION "s + result + "\01", "NOTICE"); } +void Bridge::send_irc_version_request(const std::string& irc_hostname, const std::string& target, + const std::string& iq_id, const std::string& to_jid, + const std::string& from_jid) +{ + Iid iid(target + "!" + irc_hostname); + this->send_private_message(iid, "\01VERSION\01"); + + // TODO, add a timer to remove that waiting iq if the server does not + // respond with a matching command before n seconds + this->add_waiting_iq([this, target, iq_id, to_jid, irc_hostname, from_jid](const std::string& hostname, const IrcMessage& message){ + if (irc_hostname != hostname) + return false; + IrcUser user(message.prefix); + if (message.command == "NOTICE" && user.nick == target && + message.arguments.size() >= 2 && message.arguments[1].substr(0, 9) == "\01VERSION ") + { + // remove the "\01VERSION " and the "\01" parts from the string + const std::string version = message.arguments[1].substr(9, message.arguments[1].size() - 10); + this->xmpp->send_version(iq_id, to_jid, from_jid, version); + return true; + } + if (message.command == "401" && message.arguments.size() >= 2 + && message.arguments[1] == target) + { + std::string error_message = "No such nick"; + if (message.arguments.size() >= 3) + error_message = message.arguments[2]; + this->xmpp->send_stanza_error("iq", to_jid, from_jid, iq_id, "cancel", "item-not-found", + error_message, true); + return true; + } + return false; + }); +} + + void Bridge::send_message(const Iid& iid, const std::string& nick, const std::string& body, const bool muc) { if (muc) diff --git a/src/bridge/bridge.hpp b/src/bridge/bridge.hpp index 9eb239d..a75b319 100644 --- a/src/bridge/bridge.hpp +++ b/src/bridge/bridge.hpp @@ -66,7 +66,11 @@ public: void send_irc_kick(const Iid& iid, const std::string& target, const std::string& reason, const std::string& iq_id, const std::string& to_jid); void set_channel_topic(const Iid& iid, const std::string& subject); - void send_xmpp_version_to_irc(const Iid& iid, const std::string& name, const std::string& version, const std::string& os); + void send_xmpp_version_to_irc(const Iid& iid, const std::string& name, const std::string& version, + const std::string& os); + void send_irc_version_request(const std::string& irc_hostname, const std::string& target, + const std::string& iq_id, const std::string& to_jid, + const std::string& from_jid); /*** ** diff --git a/src/xmpp/xmpp_component.cpp b/src/xmpp/xmpp_component.cpp index c06b46b..b855d67 100644 --- a/src/xmpp/xmpp_component.cpp +++ b/src/xmpp/xmpp_component.cpp @@ -509,10 +509,22 @@ void XmppComponent::handle_iq(const Stanza& stanza) else if ((query = stanza.get_child("query", VERSION_NS))) { Iid iid(to.local); - if (!iid.is_user) + 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_self_version(id, from, to_str); + this->send_version(id, from, to_str); } stanza_error.disable(); } @@ -983,7 +995,8 @@ void XmppComponent::send_self_disco_info(const std::string& id, const std::strin this->send_stanza(iq); } -void XmppComponent::send_self_version(const std::string& id, const std::string& jid_to, const std::string& jid_from) +void XmppComponent::send_version(const std::string& id, const std::string& jid_to, const std::string& jid_from, + const std::string& version) { Stanza iq("iq"); iq["type"] = "result"; @@ -992,18 +1005,28 @@ void XmppComponent::send_self_version(const std::string& id, const std::string& iq["from"] = jid_from; XmlNode query("query"); query["xmlns"] = VERSION_NS; - XmlNode name("name"); - name.set_inner("biboumi"); - name.close(); - query.add_child(std::move(name)); - XmlNode version("version"); - version.set_inner(BIBOUMI_VERSION); - version.close(); - query.add_child(std::move(version)); - XmlNode os("os"); - os.set_inner(SYSTEM_NAME); - os.close(); - query.add_child(std::move(os)); + if (version.empty()) + { + XmlNode name("name"); + name.set_inner("biboumi"); + name.close(); + query.add_child(std::move(name)); + XmlNode version("version"); + version.set_inner(BIBOUMI_VERSION); + version.close(); + query.add_child(std::move(version)); + XmlNode os("os"); + os.set_inner(SYSTEM_NAME); + os.close(); + query.add_child(std::move(os)); + } + else + { + XmlNode name("name"); + name.set_inner(version); + name.close(); + query.add_child(std::move(name)); + } query.close(); iq.add_child(std::move(query)); iq.close(); diff --git a/src/xmpp/xmpp_component.hpp b/src/xmpp/xmpp_component.hpp index ab1d584..ce594ec 100644 --- a/src/xmpp/xmpp_component.hpp +++ b/src/xmpp/xmpp_component.hpp @@ -200,9 +200,11 @@ public: */ void send_self_disco_info(const std::string& id, const std::string& jid_to); /** - * Send a result IQ with the gateway version. + * Send a result IQ with the given version, or the gateway version if the + * passed string is empty. */ - void send_self_version(const std::string& id, const std::string& jid_to, const std::string& jid_from); + void send_version(const std::string& id, const std::string& jid_to, const std::string& jid_from, + const std::string& version=""); /** * Send the list of all available ad-hoc commands to that JID. The list is * different depending on what JID made the request. -- cgit v1.2.3