From bf7b05ef72bbdac97704d262ddfe418908267535 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 6 Nov 2013 20:51:05 +0100 Subject: Implement the Bridge class to translate between the two protocols MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add all useful classes as well: Jid, Iid, IrcChannel, IrcUser etc to properly keep the informations about what we receive from the IRC server. Only handle the MUC join stanza, and send the list of users in the IRC channel to the XMPP user, and the IRC channel’s topic, for now. --- src/bridge/bridge.cpp | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/bridge/bridge.cpp (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp new file mode 100644 index 0000000..638777d --- /dev/null +++ b/src/bridge/bridge.cpp @@ -0,0 +1,57 @@ +#include +#include +#include + +Bridge::Bridge(const std::string& user_jid, XmppComponent* xmpp, Poller* poller): + user_jid(user_jid), + xmpp(xmpp), + poller(poller) +{ +} + +Bridge::~Bridge() +{ +} + +IrcClient* Bridge::get_irc_client(const std::string& hostname, const std::string& username) +{ + try + { + return this->irc_clients.at(hostname).get(); + } + catch (const std::out_of_range& exception) + { + this->irc_clients.emplace(hostname, std::make_shared(hostname, username, this)); + std::shared_ptr irc = this->irc_clients.at(hostname); + this->poller->add_socket_handler(irc); + irc->start(); + return irc.get(); + } +} + +void Bridge::join_irc_channel(const Iid& iid, const std::string& username) +{ + IrcClient* irc = this->get_irc_client(iid.server, username); + irc->send_join_command(iid.chan); +} + +void Bridge::send_xmpp_message(const std::string& from, const std::string& author, const std::string& msg) +{ + const std::string body = std::string("[") + author + std::string("] ") + msg; + this->xmpp->send_message(from, body, this->user_jid); +} + +void Bridge::send_user_join(const std::string& hostname, const std::string& chan_name, const std::string nick) +{ + this->xmpp->send_user_join(chan_name + "%" + hostname, nick, this->user_jid); +} + +void Bridge::send_self_join(const std::string& hostname, const std::string& chan_name, const std::string nick) +{ + this->xmpp->send_self_join(chan_name + "%" + hostname, nick, this->user_jid); +} + +void Bridge::send_topic(const std::string& hostname, const std::string& chan_name, const std::string topic) +{ + this->xmpp->send_topic(chan_name + "%" + hostname, topic, this->user_jid); +} -- cgit v1.2.3 From a418b6ed5d70f0e61e71bb1adce2a693ade89e30 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 7 Nov 2013 01:53:09 +0100 Subject: Send and receive messages Also correctly respond to PING with the id, escape some XML content, but not always --- src/bridge/bridge.cpp | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 638777d..5047a78 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -2,6 +2,8 @@ #include #include +#include + Bridge::Bridge(const std::string& user_jid, XmppComponent* xmpp, Poller* poller): user_jid(user_jid), xmpp(xmpp), @@ -29,15 +31,54 @@ IrcClient* Bridge::get_irc_client(const std::string& hostname, const std::string } } +IrcClient* Bridge::get_irc_client(const std::string& hostname) +{ + try + { + return this->irc_clients.at(hostname).get(); + } + catch (const std::out_of_range& exception) + { + return nullptr; + } +} + + void Bridge::join_irc_channel(const Iid& iid, const std::string& username) { IrcClient* irc = this->get_irc_client(iid.server, username); irc->send_join_command(iid.chan); } +void Bridge::send_channel_message(const Iid& iid, const std::string& body) +{ + if (iid.chan.empty() || iid.server.empty()) + { + std::cout << "Cannot send message to channel: [" << iid.chan << "] on server [" << iid.server << "]" << std::endl; + return; + } + IrcClient* irc = this->get_irc_client(iid.server); + if (!irc) + { + std::cout << "Cannot send message: no client exist for server " << iid.server << std::endl; + return; + } + irc->send_channel_message(iid.chan, body); + this->xmpp->send_muc_message(iid.chan + "%" + iid.server, irc->get_own_nick(), body, this->user_jid); +} + +void Bridge::send_muc_message(const Iid& iid, const std::string& nick, const std::string& body) +{ + this->xmpp->send_muc_message(iid.chan + "%" + iid.server, nick, body, this->user_jid); +} + void Bridge::send_xmpp_message(const std::string& from, const std::string& author, const std::string& msg) { - const std::string body = std::string("[") + author + std::string("] ") + msg; + std::string body; + if (!author.empty()) + body = std::string("[") + author + std::string("] ") + msg; + else + body = msg; this->xmpp->send_message(from, body, this->user_jid); } -- cgit v1.2.3 From f38b31a63ee203e53d1135a87f1b4e9faaf7dd3f Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 9 Nov 2013 21:40:29 +0100 Subject: Remove IRC colors from the body when forwarding it to XMPP --- src/bridge/bridge.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 5047a78..f028f5b 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -1,6 +1,9 @@ #include +#include #include #include +#include + #include @@ -15,6 +18,17 @@ Bridge::~Bridge() { } +std::string Bridge::sanitize_for_xmpp(const std::string& str) +{ + std::string res; + if (utils::is_valid_utf8(str.c_str())) + res = str; + else + res = utils::convert_to_utf8(str, "ISO-8859-1"); + remove_irc_colors(res); + return res; +} + IrcClient* Bridge::get_irc_client(const std::string& hostname, const std::string& username) { try @@ -43,7 +57,6 @@ IrcClient* Bridge::get_irc_client(const std::string& hostname) } } - void Bridge::join_irc_channel(const Iid& iid, const std::string& username) { IrcClient* irc = this->get_irc_client(iid.server, username); @@ -64,12 +77,14 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) return; } irc->send_channel_message(iid.chan, body); + // We do not need to convert body to utf-8: it comes from our XMPP server, + // so it's ok to send it back this->xmpp->send_muc_message(iid.chan + "%" + iid.server, irc->get_own_nick(), body, this->user_jid); } void Bridge::send_muc_message(const Iid& iid, const std::string& nick, const std::string& body) { - this->xmpp->send_muc_message(iid.chan + "%" + iid.server, nick, body, this->user_jid); + this->xmpp->send_muc_message(iid.chan + "%" + iid.server, nick, this->sanitize_for_xmpp(body), this->user_jid); } void Bridge::send_xmpp_message(const std::string& from, const std::string& author, const std::string& msg) @@ -79,7 +94,7 @@ void Bridge::send_xmpp_message(const std::string& from, const std::string& autho body = std::string("[") + author + std::string("] ") + msg; else body = msg; - this->xmpp->send_message(from, body, this->user_jid); + this->xmpp->send_message(from, this->sanitize_for_xmpp(body), this->user_jid); } void Bridge::send_user_join(const std::string& hostname, const std::string& chan_name, const std::string nick) @@ -94,5 +109,5 @@ void Bridge::send_self_join(const std::string& hostname, const std::string& chan void Bridge::send_topic(const std::string& hostname, const std::string& chan_name, const std::string topic) { - this->xmpp->send_topic(chan_name + "%" + hostname, topic, this->user_jid); + this->xmpp->send_topic(chan_name + "%" + hostname, this->sanitize_for_xmpp(topic), this->user_jid); } -- cgit v1.2.3 From 7c671499350e22f8bfba2f72b9827aa5b200f7b0 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 9 Nov 2013 23:17:48 +0100 Subject: Implement part and join, both ways --- src/bridge/bridge.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index f028f5b..9dbea2f 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -82,11 +82,23 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) this->xmpp->send_muc_message(iid.chan + "%" + iid.server, irc->get_own_nick(), body, this->user_jid); } +void Bridge::leave_irc_channel(Iid&& iid, std::string&& status_message) +{ + IrcClient* irc = this->get_irc_client(iid.server); + if (irc) + irc->send_part_command(iid.chan, status_message); +} + void Bridge::send_muc_message(const Iid& iid, const std::string& nick, const std::string& body) { this->xmpp->send_muc_message(iid.chan + "%" + iid.server, nick, this->sanitize_for_xmpp(body), this->user_jid); } +void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, std::string&& message, const bool self) +{ + this->xmpp->send_muc_leave(std::move(iid.chan) + "%" + std::move(iid.server), std::move(nick), this->sanitize_for_xmpp(message), this->user_jid, self); +} + void Bridge::send_xmpp_message(const std::string& from, const std::string& author, const std::string& msg) { std::string body; -- cgit v1.2.3 From 7ba2d0fb45e7466e6fb38002bf1866d1f5e39c28 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sun, 10 Nov 2013 05:41:22 +0100 Subject: Handle the ACTION (/me) IRC command, both ways --- src/bridge/bridge.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 9dbea2f..89a6231 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -4,9 +4,11 @@ #include #include - #include +static const char* action_prefix = "\01ACTION "; +static const size_t action_prefix_len = 8; + Bridge::Bridge(const std::string& user_jid, XmppComponent* xmpp, Poller* poller): user_jid(user_jid), xmpp(xmpp), @@ -76,7 +78,10 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) std::cout << "Cannot send message: no client exist for server " << iid.server << std::endl; return; } - irc->send_channel_message(iid.chan, body); + if (body.substr(0, 4) == "/me ") + irc->send_channel_message(iid.chan, action_prefix + body.substr(4) + "\01"); + else + irc->send_channel_message(iid.chan, body); // We do not need to convert body to utf-8: it comes from our XMPP server, // so it's ok to send it back this->xmpp->send_muc_message(iid.chan + "%" + iid.server, irc->get_own_nick(), body, this->user_jid); @@ -91,7 +96,16 @@ void Bridge::leave_irc_channel(Iid&& iid, std::string&& status_message) void Bridge::send_muc_message(const Iid& iid, const std::string& nick, const std::string& body) { - this->xmpp->send_muc_message(iid.chan + "%" + iid.server, nick, this->sanitize_for_xmpp(body), this->user_jid); + const std::string& utf8_body = this->sanitize_for_xmpp(body); + if (utf8_body.substr(0, action_prefix_len) == action_prefix) + { // Special case for ACTION (/me) messages: + // "\01ACTION goes out\01" == "/me goes out" + this->xmpp->send_muc_message(iid.chan + "%" + iid.server, nick, + std::string("/me ") + utf8_body.substr(action_prefix_len, utf8_body.size() - action_prefix_len - 1), + this->user_jid); + } + else + this->xmpp->send_muc_message(iid.chan + "%" + iid.server, nick, utf8_body, this->user_jid); } void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, std::string&& message, const bool self) -- cgit v1.2.3 From 10d528717723a72dd3240c634980a461cf9fa2df Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sun, 10 Nov 2013 06:33:04 +0100 Subject: Handle private messages, both ways --- src/bridge/bridge.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 89a6231..1f394bf 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -87,6 +87,15 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) this->xmpp->send_muc_message(iid.chan + "%" + iid.server, irc->get_own_nick(), body, this->user_jid); } +void Bridge::send_private_message(const Iid& iid, const std::string& body) +{ + if (iid.chan.empty() || iid.server.empty()) + return ; + IrcClient* irc = this->get_irc_client(iid.server); + if (irc) + irc->send_private_message(iid.chan, body); +} + void Bridge::leave_irc_channel(Iid&& iid, std::string&& status_message) { IrcClient* irc = this->get_irc_client(iid.server); @@ -94,18 +103,19 @@ void Bridge::leave_irc_channel(Iid&& iid, std::string&& status_message) irc->send_part_command(iid.chan, status_message); } -void Bridge::send_muc_message(const Iid& iid, const std::string& nick, const std::string& body) +void Bridge::send_message(const Iid& iid, const std::string& nick, const std::string& body, const bool muc) { - const std::string& utf8_body = this->sanitize_for_xmpp(body); + std::string utf8_body = this->sanitize_for_xmpp(body); if (utf8_body.substr(0, action_prefix_len) == action_prefix) { // Special case for ACTION (/me) messages: // "\01ACTION goes out\01" == "/me goes out" - this->xmpp->send_muc_message(iid.chan + "%" + iid.server, nick, - std::string("/me ") + utf8_body.substr(action_prefix_len, utf8_body.size() - action_prefix_len - 1), - this->user_jid); + utf8_body = std::string("/me ") + + utf8_body.substr(action_prefix_len, utf8_body.size() - action_prefix_len - 1); } - else + if (muc) this->xmpp->send_muc_message(iid.chan + "%" + iid.server, nick, utf8_body, this->user_jid); + else + this->xmpp->send_message(iid.chan + "%" + iid.server, utf8_body, this->user_jid); } void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, std::string&& message, const bool self) -- cgit v1.2.3 From 096a4e3bafe6e2d238e4592f57f22f19f363fcbd Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 11 Nov 2013 00:24:34 +0100 Subject: Handle nick changes, both ways --- src/bridge/bridge.cpp | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 1f394bf..d292af3 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -59,10 +59,15 @@ IrcClient* Bridge::get_irc_client(const std::string& hostname) } } -void Bridge::join_irc_channel(const Iid& iid, const std::string& username) +bool Bridge::join_irc_channel(const Iid& iid, const std::string& username) { IrcClient* irc = this->get_irc_client(iid.server, username); - irc->send_join_command(iid.chan); + if (irc->is_channel_joined(iid.chan) == false) + { + irc->send_join_command(iid.chan); + return true; + } + return false; } void Bridge::send_channel_message(const Iid& iid, const std::string& body) @@ -103,6 +108,13 @@ void Bridge::leave_irc_channel(Iid&& iid, std::string&& status_message) irc->send_part_command(iid.chan, status_message); } +void Bridge::send_irc_nick_change(const Iid& iid, const std::string& new_nick) +{ + IrcClient* irc = this->get_irc_client(iid.server); + if (irc) + irc->send_nick_command(new_nick); +} + void Bridge::send_message(const Iid& iid, const std::string& nick, const std::string& body, const bool muc) { std::string utf8_body = this->sanitize_for_xmpp(body); @@ -118,11 +130,17 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st this->xmpp->send_message(iid.chan + "%" + iid.server, utf8_body, this->user_jid); } -void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, std::string&& message, const bool self) +void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self) { this->xmpp->send_muc_leave(std::move(iid.chan) + "%" + std::move(iid.server), std::move(nick), this->sanitize_for_xmpp(message), this->user_jid, self); } +void Bridge::send_nick_change(Iid&& iid, const std::string& old_nick, const std::string& new_nick, const bool self) +{ + this->xmpp->send_nick_change(std::move(iid.chan) + "%" + std::move(iid.server), + old_nick, new_nick, this->user_jid, self); +} + void Bridge::send_xmpp_message(const std::string& from, const std::string& author, const std::string& msg) { std::string body; @@ -147,3 +165,11 @@ void Bridge::send_topic(const std::string& hostname, const std::string& chan_nam { this->xmpp->send_topic(chan_name + "%" + hostname, this->sanitize_for_xmpp(topic), this->user_jid); } + +std::string Bridge::get_own_nick(const Iid& iid) +{ + IrcClient* irc = this->get_irc_client(iid.server); + if (irc) + return irc->get_own_nick(); + return ""; +} -- cgit v1.2.3 From 5817a95b5ee89480788832be35679dfcd2ed833b Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 12 Nov 2013 23:43:43 +0100 Subject: Basic handling of modes, both ways --- src/bridge/bridge.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index d292af3..0b26a7f 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -4,6 +4,7 @@ #include #include +#include #include static const char* action_prefix = "\01ACTION "; @@ -83,6 +84,12 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) std::cout << "Cannot send message: no client exist for server " << iid.server << std::endl; return; } + if (body.substr(0, 6) == "/mode ") + { + std::vector args = utils::split(body.substr(6), ' ', false); + irc->send_mode_command(iid.chan, args); + return; + } if (body.substr(0, 4) == "/me ") irc->send_channel_message(iid.chan, action_prefix + body.substr(4) + "\01"); else -- cgit v1.2.3 From 0859801230f999889d0f7356864888e8c5936cda Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 13 Nov 2013 01:24:36 +0100 Subject: Handle KICK in irc channel, both ways --- src/bridge/bridge.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 0b26a7f..e39cdd3 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -122,6 +122,13 @@ void Bridge::send_irc_nick_change(const Iid& iid, const std::string& new_nick) irc->send_nick_command(new_nick); } +void Bridge::send_irc_kick(const Iid& iid, const std::string& target, const std::string& reason) +{ + IrcClient* irc = this->get_irc_client(iid.server); + if (irc) + irc->send_kick_command(iid.chan, target, reason); +} + void Bridge::send_message(const Iid& iid, const std::string& nick, const std::string& body, const bool muc) { std::string utf8_body = this->sanitize_for_xmpp(body); @@ -180,3 +187,8 @@ std::string Bridge::get_own_nick(const Iid& iid) return irc->get_own_nick(); return ""; } + +void Bridge::kick_muc_user(Iid&& iid, const std::string& target, const std::string& reason, const std::string& author) +{ + this->xmpp->kick_user(iid.chan + "%" + iid.server, target, reason, author, this->user_jid); +} -- cgit v1.2.3 From bfcc9cdc7462c515c308592735bc661103fb92b5 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 21 Nov 2013 00:58:14 +0100 Subject: Send XMPP multi-line messages as multiple IRC messages --- src/bridge/bridge.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index e39cdd3..e24ab88 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -73,6 +73,10 @@ bool Bridge::join_irc_channel(const Iid& iid, const std::string& username) void Bridge::send_channel_message(const Iid& iid, const std::string& body) { + std::vector lines = utils::split(body, '\n', true); + if (lines.empty()) + return ; + const std::string first_line = lines[0]; if (iid.chan.empty() || iid.server.empty()) { std::cout << "Cannot send message to channel: [" << iid.chan << "] on server [" << iid.server << "]" << std::endl; @@ -84,16 +88,19 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) std::cout << "Cannot send message: no client exist for server " << iid.server << std::endl; return; } - if (body.substr(0, 6) == "/mode ") + if (first_line.substr(0, 6) == "/mode ") { - std::vector args = utils::split(body.substr(6), ' ', false); + std::vector args = utils::split(first_line.substr(6), ' ', false); irc->send_mode_command(iid.chan, args); return; } - if (body.substr(0, 4) == "/me ") - irc->send_channel_message(iid.chan, action_prefix + body.substr(4) + "\01"); + if (first_line.substr(0, 4) == "/me ") + irc->send_channel_message(iid.chan, action_prefix + first_line.substr(4) + "\01"); else - irc->send_channel_message(iid.chan, body); + irc->send_channel_message(iid.chan, first_line); + // Send each of the other lines of the message as a separate IRC message + for (std::vector::const_iterator it = lines.begin() + 1; it != lines.end(); ++it) + irc->send_channel_message(iid.chan, *it); // We do not need to convert body to utf-8: it comes from our XMPP server, // so it's ok to send it back this->xmpp->send_muc_message(iid.chan + "%" + iid.server, irc->get_own_nick(), body, this->user_jid); -- cgit v1.2.3 From fba01f46468050d4f3b8eb35373ed49a3584868e Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 22 Nov 2013 21:00:07 +0100 Subject: Remove incomplete implementation of remove_irc_colors --- src/bridge/bridge.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index e24ab88..e08e2a4 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -28,7 +28,6 @@ std::string Bridge::sanitize_for_xmpp(const std::string& str) res = str; else res = utils::convert_to_utf8(str, "ISO-8859-1"); - remove_irc_colors(res); return res; } -- cgit v1.2.3 From e6f20d3c0fd4ba8696a4410a366741c9b9f3562d Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 22 Nov 2013 21:00:32 +0100 Subject: Implement IRC format to xhtml-im conversion The generated XML is very verbose because each IRC formatting tag makes us close a element and reopen it with the new style applied. However, this works quite well and is easy to implement. --- src/bridge/bridge.cpp | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index e08e2a4..7e6f801 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -21,14 +21,14 @@ Bridge::~Bridge() { } -std::string Bridge::sanitize_for_xmpp(const std::string& str) +Xmpp::body Bridge::make_xmpp_body(const std::string& str) { std::string res; if (utils::is_valid_utf8(str.c_str())) res = str; else res = utils::convert_to_utf8(str, "ISO-8859-1"); - return res; + return irc_format_to_xhtmlim(res); } IrcClient* Bridge::get_irc_client(const std::string& hostname, const std::string& username) @@ -102,7 +102,8 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) irc->send_channel_message(iid.chan, *it); // We do not need to convert body to utf-8: it comes from our XMPP server, // so it's ok to send it back - this->xmpp->send_muc_message(iid.chan + "%" + iid.server, irc->get_own_nick(), body, this->user_jid); + this->xmpp->send_muc_message(iid.chan + "%" + iid.server, irc->get_own_nick(), + this->make_xmpp_body(body), this->user_jid); } void Bridge::send_private_message(const Iid& iid, const std::string& body) @@ -137,22 +138,17 @@ void Bridge::send_irc_kick(const Iid& iid, const std::string& target, const std: void Bridge::send_message(const Iid& iid, const std::string& nick, const std::string& body, const bool muc) { - std::string utf8_body = this->sanitize_for_xmpp(body); - if (utf8_body.substr(0, action_prefix_len) == action_prefix) - { // Special case for ACTION (/me) messages: - // "\01ACTION goes out\01" == "/me goes out" - utf8_body = std::string("/me ") + - utf8_body.substr(action_prefix_len, utf8_body.size() - action_prefix_len - 1); - } if (muc) - this->xmpp->send_muc_message(iid.chan + "%" + iid.server, nick, utf8_body, this->user_jid); + this->xmpp->send_muc_message(iid.chan + "%" + iid.server, nick, + this->make_xmpp_body(body), this->user_jid); else - this->xmpp->send_message(iid.chan + "%" + iid.server, utf8_body, this->user_jid); + this->xmpp->send_message(iid.chan + "%" + iid.server, + this->make_xmpp_body(body), this->user_jid); } void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self) { - this->xmpp->send_muc_leave(std::move(iid.chan) + "%" + std::move(iid.server), std::move(nick), this->sanitize_for_xmpp(message), this->user_jid, self); + this->xmpp->send_muc_leave(std::move(iid.chan) + "%" + std::move(iid.server), std::move(nick), this->make_xmpp_body(message), this->user_jid, self); } void Bridge::send_nick_change(Iid&& iid, const std::string& old_nick, const std::string& new_nick, const bool self) @@ -168,7 +164,7 @@ void Bridge::send_xmpp_message(const std::string& from, const std::string& autho body = std::string("[") + author + std::string("] ") + msg; else body = msg; - this->xmpp->send_message(from, this->sanitize_for_xmpp(body), this->user_jid); + this->xmpp->send_message(from, this->make_xmpp_body(body), this->user_jid); } void Bridge::send_user_join(const std::string& hostname, const std::string& chan_name, const std::string nick) @@ -183,7 +179,7 @@ void Bridge::send_self_join(const std::string& hostname, const std::string& chan void Bridge::send_topic(const std::string& hostname, const std::string& chan_name, const std::string topic) { - this->xmpp->send_topic(chan_name + "%" + hostname, this->sanitize_for_xmpp(topic), this->user_jid); + this->xmpp->send_topic(chan_name + "%" + hostname, this->make_xmpp_body(topic), this->user_jid); } std::string Bridge::get_own_nick(const Iid& iid) -- cgit v1.2.3 From a4c845ab6c54172ea305f33734c83238c75d421a Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 3 Dec 2013 19:10:44 +0100 Subject: Use the logger everywhere --- src/bridge/bridge.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 7e6f801..2ad6af8 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -3,7 +3,7 @@ #include #include #include - +#include #include #include @@ -78,13 +78,13 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) const std::string first_line = lines[0]; if (iid.chan.empty() || iid.server.empty()) { - std::cout << "Cannot send message to channel: [" << iid.chan << "] on server [" << iid.server << "]" << std::endl; + log_warning("Cannot send message to channel: [" << iid.chan << "] on server [" << iid.server << "]"); return; } IrcClient* irc = this->get_irc_client(iid.server); if (!irc) { - std::cout << "Cannot send message: no client exist for server " << iid.server << std::endl; + log_warning("Cannot send message: no client exist for server " << iid.server); return; } if (first_line.substr(0, 6) == "/mode ") -- cgit v1.2.3 From b11126a19dbaadf4c32fb8dbec22754ad0712c26 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sun, 8 Dec 2013 20:14:12 +0100 Subject: Provide a JID for IRC users, and add a stringprep dependency for this --- src/bridge/bridge.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 2ad6af8..973e095 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -167,9 +167,11 @@ void Bridge::send_xmpp_message(const std::string& from, const std::string& autho this->xmpp->send_message(from, this->make_xmpp_body(body), this->user_jid); } -void Bridge::send_user_join(const std::string& hostname, const std::string& chan_name, const std::string nick) +void Bridge::send_user_join(const std::string& hostname, + const std::string& chan_name, + const IrcUser* user) { - this->xmpp->send_user_join(chan_name + "%" + hostname, nick, this->user_jid); + this->xmpp->send_user_join(chan_name + "%" + hostname, user->nick, user->host, this->user_jid); } void Bridge::send_self_join(const std::string& hostname, const std::string& chan_name, const std::string nick) -- cgit v1.2.3 From 3afb63a650b8b925ce1ba722dd42b7418f623713 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 21 Dec 2013 21:04:41 +0100 Subject: Shutdown cleanly on SIGINT --- src/bridge/bridge.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 973e095..606cb02 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -21,6 +21,14 @@ Bridge::~Bridge() { } +void Bridge::shutdown() +{ + for (auto it = this->irc_clients.begin(); it != this->irc_clients.end(); ++it) + { + it->second->send_quit_command(); + } +} + Xmpp::body Bridge::make_xmpp_body(const std::string& str) { std::string res; -- cgit v1.2.3 From aa53276859a5fc80071d24111a311297e058e603 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 27 Dec 2013 11:53:29 +0100 Subject: Keep a "connected" state in the SocketHandler class --- src/bridge/bridge.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 606cb02..3a755a3 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -50,7 +50,6 @@ IrcClient* Bridge::get_irc_client(const std::string& hostname, const std::string this->irc_clients.emplace(hostname, std::make_shared(hostname, username, this)); std::shared_ptr irc = this->irc_clients.at(hostname); this->poller->add_socket_handler(irc); - irc->start(); return irc.get(); } } -- cgit v1.2.3 From e8e592d1ace5413a1e7d8b59b9467c78d8d68ea9 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 27 Dec 2013 12:01:26 +0100 Subject: Remove disconnected IrcClients --- src/bridge/bridge.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 3a755a3..c93d710 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -29,6 +29,19 @@ void Bridge::shutdown() } } +void Bridge::clean() +{ + auto it = this->irc_clients.begin(); + while (it != this->irc_clients.end()) + { + IrcClient* client = it->second.get(); + if (!client->is_connected()) + it = this->irc_clients.erase(it); + else + ++it; + } +} + Xmpp::body Bridge::make_xmpp_body(const std::string& str) { std::string res; -- cgit v1.2.3 From 43cc60e4a9e2859fdf67c89e58ee18cf7571f186 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 27 Dec 2013 15:34:58 +0100 Subject: Handle nickname conflicts by sending the correct XMPP error presence --- src/bridge/bridge.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index c93d710..7f245db 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -216,3 +216,8 @@ void Bridge::kick_muc_user(Iid&& iid, const std::string& target, const std::stri { this->xmpp->kick_user(iid.chan + "%" + iid.server, target, reason, author, this->user_jid); } + +void Bridge::send_nickname_conflict_error(const Iid& iid, const std::string& nickname) +{ + this->xmpp->send_nickname_conflict_error(iid.chan + "%" + iid.server, nickname, this->user_jid); +} -- cgit v1.2.3 From acf769d83a40e971ccc1346225688841465b36ee Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sun, 29 Dec 2013 19:57:43 +0100 Subject: Use isupport informations to know the user modes when joining Also remove the duplicate send_self_join methods, user only send_user_join --- src/bridge/bridge.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 7f245db..fb3afc7 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -189,14 +189,18 @@ void Bridge::send_xmpp_message(const std::string& from, const std::string& autho void Bridge::send_user_join(const std::string& hostname, const std::string& chan_name, - const IrcUser* user) + const IrcUser* user, + const bool self) { - this->xmpp->send_user_join(chan_name + "%" + hostname, user->nick, user->host, this->user_jid); -} - -void Bridge::send_self_join(const std::string& hostname, const std::string& chan_name, const std::string nick) -{ - this->xmpp->send_self_join(chan_name + "%" + hostname, nick, this->user_jid); + std::string affiliation = "participant"; + std::string role = "none"; + if (user->modes.find('o') != user->modes.end()) + { + affiliation = "admin"; + role = "moderator"; + } + this->xmpp->send_user_join(chan_name + "%" + hostname, user->nick, user->host, + affiliation, role, this->user_jid, self); } void Bridge::send_topic(const std::string& hostname, const std::string& chan_name, const std::string topic) -- cgit v1.2.3 From e840704b58a984351971e8034e74f5e9fdfaf114 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 4 Jan 2014 01:30:03 +0100 Subject: Convert received modes into roles and affiliations --- src/bridge/bridge.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index fb3afc7..d034bcd 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -225,3 +225,35 @@ void Bridge::send_nickname_conflict_error(const Iid& iid, const std::string& nic { this->xmpp->send_nickname_conflict_error(iid.chan + "%" + iid.server, nickname, this->user_jid); } + +void Bridge::send_affiliation_role_change(const Iid& iid, const std::string& target, const char mode) +{ + std::string role; + std::string affiliation; + if (mode == 0) + { + role = "participant"; + affiliation = "none"; + } + else if (mode == 'a') + { + role = "moderator"; + affiliation = "owner"; + } + else if (mode == 'o') + { + role = "moderator"; + affiliation = "admin"; + } + else if (mode == 'h') + { + role = "moderator"; + affiliation = "member"; + } + else if (mode == 'v') + { + role = "participant"; + affiliation = "member"; + } + this->xmpp->send_affiliation_role_change(iid.chan + "%" + iid.server, target, affiliation, role, this->user_jid); +} -- cgit v1.2.3 From fbec16f1a208881ea49923287aae27978d79681e Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 4 Jan 2014 01:53:50 +0100 Subject: Possibility to change a channel's topic --- src/bridge/bridge.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index d034bcd..dae5a72 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -156,6 +156,13 @@ void Bridge::send_irc_kick(const Iid& iid, const std::string& target, const std: irc->send_kick_command(iid.chan, target, reason); } +void Bridge::set_channel_topic(const Iid& iid, const std::string& subject) +{ + IrcClient* irc = this->get_irc_client(iid.server); + if (irc) + irc->send_topic_command(iid.chan, subject); +} + void Bridge::send_message(const Iid& iid, const std::string& nick, const std::string& body, const bool muc) { if (muc) -- cgit v1.2.3 From fef9c8193ddf8cdf81978874be788af9441e2286 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 6 Jan 2014 01:22:43 +0100 Subject: Also set the role and affiliation of users already in the chan --- src/bridge/bridge.cpp | 56 ++++++++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 32 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index dae5a72..be0d270 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -6,6 +6,7 @@ #include #include #include +#include static const char* action_prefix = "\01ACTION "; static const size_t action_prefix_len = 8; @@ -21,6 +22,22 @@ Bridge::~Bridge() { } +/** + * Return the role and affiliation, corresponding to the given irc mode */ +static std::tuple get_role_affiliation_from_irc_mode(const char mode) +{ + if (mode == 'a' || mode == 'q') + return std::make_tuple("moderator", "owner"); + else if (mode == 'o') + return std::make_tuple("moderator", "admin"); + else if (mode == 'h') + return std::make_tuple("moderator", "member"); + else if (mode == 'v') + return std::make_tuple("participant", "member"); + else + return std::make_tuple("participant", "none"); +} + void Bridge::shutdown() { for (auto it = this->irc_clients.begin(); it != this->irc_clients.end(); ++it) @@ -197,15 +214,13 @@ void Bridge::send_xmpp_message(const std::string& from, const std::string& autho void Bridge::send_user_join(const std::string& hostname, const std::string& chan_name, const IrcUser* user, + const char user_mode, const bool self) { - std::string affiliation = "participant"; - std::string role = "none"; - if (user->modes.find('o') != user->modes.end()) - { - affiliation = "admin"; - role = "moderator"; - } + std::string affiliation; + std::string role; + std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(user_mode); + this->xmpp->send_user_join(chan_name + "%" + hostname, user->nick, user->host, affiliation, role, this->user_jid, self); } @@ -237,30 +252,7 @@ void Bridge::send_affiliation_role_change(const Iid& iid, const std::string& tar { std::string role; std::string affiliation; - if (mode == 0) - { - role = "participant"; - affiliation = "none"; - } - else if (mode == 'a') - { - role = "moderator"; - affiliation = "owner"; - } - else if (mode == 'o') - { - role = "moderator"; - affiliation = "admin"; - } - else if (mode == 'h') - { - role = "moderator"; - affiliation = "member"; - } - else if (mode == 'v') - { - role = "participant"; - affiliation = "member"; - } + + std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(mode); this->xmpp->send_affiliation_role_change(iid.chan + "%" + iid.server, target, affiliation, role, this->user_jid); } -- cgit v1.2.3 From cf9f3a1f2855b358aa9bbc31f234801e9e1efc28 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 17 Feb 2014 01:43:58 +0100 Subject: Include role and affiliation in the join presence of the nick change process --- src/bridge/bridge.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index be0d270..6460e6b 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -195,10 +195,18 @@ void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& me this->xmpp->send_muc_leave(std::move(iid.chan) + "%" + std::move(iid.server), std::move(nick), this->make_xmpp_body(message), this->user_jid, self); } -void Bridge::send_nick_change(Iid&& iid, const std::string& old_nick, const std::string& new_nick, const bool self) +void Bridge::send_nick_change(Iid&& iid, + const std::string& old_nick, + const std::string& new_nick, + const char user_mode, + const bool self) { + std::string affiliation; + std::string role; + std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(user_mode); + this->xmpp->send_nick_change(std::move(iid.chan) + "%" + std::move(iid.server), - old_nick, new_nick, this->user_jid, self); + old_nick, new_nick, affiliation, role, this->user_jid, self); } void Bridge::send_xmpp_message(const std::string& from, const std::string& author, const std::string& msg) -- cgit v1.2.3 From 190c4ff1762e5e762e913f98033369ed75ed5291 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 20 Feb 2014 02:19:50 +0100 Subject: QUIT the irc server when the last channel is left --- src/bridge/bridge.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 6460e6b..5122a69 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -42,7 +42,7 @@ void Bridge::shutdown() { for (auto it = this->irc_clients.begin(); it != this->irc_clients.end(); ++it) { - it->second->send_quit_command(); + it->second->send_quit_command("Gateway shutdown"); } } @@ -193,6 +193,9 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self) { this->xmpp->send_muc_leave(std::move(iid.chan) + "%" + std::move(iid.server), std::move(nick), this->make_xmpp_body(message), this->user_jid, self); + IrcClient* irc = this->get_irc_client(iid.server); + if (irc && irc->number_of_joined_channels() == 0) + irc->send_quit_command(""); } void Bridge::send_nick_change(Iid&& iid, -- cgit v1.2.3 From 61ca40fa0e6c819aa72f3f2364667c7b990855d4 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 20 Feb 2014 02:31:16 +0100 Subject: Delete empty bridges objects --- src/bridge/bridge.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 5122a69..bb3bfb0 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -249,6 +249,11 @@ std::string Bridge::get_own_nick(const Iid& iid) return ""; } +size_t Bridge::connected_clients() const +{ + return this->irc_clients.size(); +} + void Bridge::kick_muc_user(Iid&& iid, const std::string& target, const std::string& reason, const std::string& author) { this->xmpp->kick_user(iid.chan + "%" + iid.server, target, reason, author, this->user_jid); -- cgit v1.2.3 From 99aba5667d0d7ba6657f9c175a9342126bc4b0f2 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 22 Feb 2014 21:42:24 +0100 Subject: Connection to servers does not block the process anymore --- src/bridge/bridge.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index bb3bfb0..ed685f9 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -52,7 +52,7 @@ void Bridge::clean() while (it != this->irc_clients.end()) { IrcClient* client = it->second.get(); - if (!client->is_connected()) + if (!client->is_connected() && !client->is_connecting()) it = this->irc_clients.erase(it); else ++it; @@ -249,7 +249,7 @@ std::string Bridge::get_own_nick(const Iid& iid) return ""; } -size_t Bridge::connected_clients() const +size_t Bridge::active_clients() const { return this->irc_clients.size(); } -- cgit v1.2.3 From f6029d5bcf9f529d72e0846661f555e189669b26 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 24 Feb 2014 21:03:51 +0100 Subject: Add missing stdexcept includes --- src/bridge/bridge.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index ed685f9..9b7908a 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From a20c60a0d84f2f22777e3831cac1315302b7a095 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 10 Apr 2014 20:11:17 +0200 Subject: Messages coming from the IRC server are of type "chat" --- src/bridge/bridge.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 9b7908a..277f696 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -188,7 +188,7 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st this->make_xmpp_body(body), this->user_jid); else this->xmpp->send_message(iid.chan + "%" + iid.server, - this->make_xmpp_body(body), this->user_jid); + this->make_xmpp_body(body), this->user_jid, "chat"); } void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self) @@ -220,7 +220,7 @@ void Bridge::send_xmpp_message(const std::string& from, const std::string& autho body = std::string("[") + author + std::string("] ") + msg; else body = msg; - this->xmpp->send_message(from, this->make_xmpp_body(body), this->user_jid); + this->xmpp->send_message(from, this->make_xmpp_body(body), this->user_jid, "chat"); } void Bridge::send_user_join(const std::string& hostname, -- cgit v1.2.3 From 020325dbb071f1735bceb80de9f982aefcd2de47 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sun, 13 Apr 2014 15:37:56 +0200 Subject: [WIP] DummyIrcChannel --- src/bridge/bridge.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 9b7908a..f4d4814 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -100,6 +101,25 @@ IrcClient* Bridge::get_irc_client(const std::string& hostname) bool Bridge::join_irc_channel(const Iid& iid, const std::string& username) { IrcClient* irc = this->get_irc_client(iid.server, username); + if (iid.chan.empty()) + { // Join the dummy channel + if (irc->is_welcomed()) + { + if (irc->get_dummy_channel().joined) + return false; + // Immediately simulate a message coming from the IRC server saying that we + // joined the channel + const IrcMessage join_message(irc->get_nick(), "JOIN", {""}); + irc->on_channel_join(join_message); + const IrcMessage end_join_message(std::string(iid.server), "366", + {irc->get_nick(), + "", "End of NAMES list"}); + irc->on_channel_completely_joined(end_join_message); + } + else + irc->get_dummy_channel().joining = true; + return true; + } if (irc->is_channel_joined(iid.chan) == false) { irc->send_join_command(iid.chan); -- cgit v1.2.3 From 5739d418e2b35dfc038fe1a12f8b5c7eeeed6868 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 15 Apr 2014 04:56:50 +0200 Subject: Better way to leave the dummy room --- src/bridge/bridge.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index da10e28..e874ccb 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -44,7 +44,9 @@ void Bridge::shutdown() { for (auto it = this->irc_clients.begin(); it != this->irc_clients.end(); ++it) { - it->second->send_quit_command("Gateway shutdown"); + const std::string exit_message("Gateway shutdown"); + it->second->send_quit_command(exit_message); + it->second->leave_dummy_channel(exit_message); } } -- cgit v1.2.3 From 14b6793d7fe78cfbab4f2686eb58e59d4f40338c Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 15 Apr 2014 05:11:36 +0200 Subject: Joining the dummy channel connects to the irc server --- src/bridge/bridge.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index e874ccb..eceb22e 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -119,7 +119,10 @@ bool Bridge::join_irc_channel(const Iid& iid, const std::string& username) irc->on_channel_completely_joined(end_join_message); } else + { irc->get_dummy_channel().joining = true; + irc->start(); + } return true; } if (irc->is_channel_joined(iid.chan) == false) -- cgit v1.2.3 From 848b50185f25927cffc250b1885e6d47a42b4326 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 21 Apr 2014 22:46:45 +0200 Subject: Remove unused action_prefix_len variable --- src/bridge/bridge.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index eceb22e..a2f481c 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -11,7 +11,6 @@ #include static const char* action_prefix = "\01ACTION "; -static const size_t action_prefix_len = 8; Bridge::Bridge(const std::string& user_jid, XmppComponent* xmpp, Poller* poller): user_jid(user_jid), -- cgit v1.2.3 From 4e61b0d57e4e0a127b8b8db2dab6452695ff425c Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 25 Apr 2014 00:53:08 +0200 Subject: The author name from messages from the server are now nicely formated --- src/bridge/bridge.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index a2f481c..12a56d7 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -241,7 +241,12 @@ void Bridge::send_xmpp_message(const std::string& from, const std::string& autho { std::string body; if (!author.empty()) - body = std::string("[") + author + std::string("] ") + msg; + { + IrcUser user(author); + body = std::string("\u000303") + user.nick + (user.host.empty()? + std::string("\u0003: "): + (" (\u000310" + user.host + std::string("\u000303)\u0003: "))) + msg; + } else body = msg; this->xmpp->send_message(from, this->make_xmpp_body(body), this->user_jid, "chat"); -- cgit v1.2.3 From f6e6b8905be010d7329316cea4546900ad8a2d19 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 29 Apr 2014 21:50:13 +0200 Subject: Use C++14 string_literals --- src/bridge/bridge.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 12a56d7..4b2d895 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -10,6 +10,8 @@ #include #include +using namespace std::string_literals; + static const char* action_prefix = "\01ACTION "; Bridge::Bridge(const std::string& user_jid, XmppComponent* xmpp, Poller* poller): @@ -243,9 +245,9 @@ void Bridge::send_xmpp_message(const std::string& from, const std::string& autho if (!author.empty()) { IrcUser user(author); - body = std::string("\u000303") + user.nick + (user.host.empty()? - std::string("\u0003: "): - (" (\u000310" + user.host + std::string("\u000303)\u0003: "))) + msg; + body = "\u000303"s + user.nick + (user.host.empty()? + "\u0003: ": + (" (\u000310" + user.host + "\u000303)\u0003: ")) + msg; } else body = msg; -- cgit v1.2.3 From 65f219594d16bac119e50ac882139f5b1461b1e3 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 29 Apr 2014 21:56:05 +0200 Subject: Fix a little indentation --- src/bridge/bridge.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 4b2d895..aa88262 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -246,8 +246,8 @@ void Bridge::send_xmpp_message(const std::string& from, const std::string& autho { IrcUser user(author); body = "\u000303"s + user.nick + (user.host.empty()? - "\u0003: ": - (" (\u000310" + user.host + "\u000303)\u0003: ")) + msg; + "\u0003: ": + (" (\u000310" + user.host + "\u000303)\u0003: ")) + msg; } else body = msg; -- cgit v1.2.3 From 5ec05cb0edda6b01ff5c21a42edf9142b90399e5 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 6 May 2014 22:50:37 +0200 Subject: Forward CTCP version request to XMPP --- src/bridge/bridge.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index aa88262..6c85722 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -304,3 +304,8 @@ void Bridge::send_affiliation_role_change(const Iid& iid, const std::string& tar std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(mode); this->xmpp->send_affiliation_role_change(iid.chan + "%" + iid.server, target, affiliation, role, this->user_jid); } + +void Bridge::send_iq_version_request(const std::string& nick, const std::string& hostname) +{ + this->xmpp->send_iq_version_request(nick + "%" + hostname, this->user_jid); +} -- cgit v1.2.3 From 579ca4bdb6b8806d821daa2ee47d60260b64f0f8 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 7 May 2014 02:02:47 +0200 Subject: Forward iq version results to IRC --- src/bridge/bridge.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 6c85722..f9dc9a6 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -170,13 +170,13 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) this->make_xmpp_body(body), this->user_jid); } -void Bridge::send_private_message(const Iid& iid, const std::string& body) +void Bridge::send_private_message(const Iid& iid, const std::string& body, const std::string& type) { if (iid.chan.empty() || iid.server.empty()) return ; IrcClient* irc = this->get_irc_client(iid.server); if (irc) - irc->send_private_message(iid.chan, body); + irc->send_private_message(iid.chan, body, type); } void Bridge::leave_irc_channel(Iid&& iid, std::string&& status_message) @@ -207,6 +207,13 @@ void Bridge::set_channel_topic(const Iid& iid, const std::string& subject) irc->send_topic_command(iid.chan, subject); } +void Bridge::send_xmpp_version_to_irc(const Iid& iid, const std::string& name, const std::string& version, const std::string& os) +{ + std::string result(name + " " + version + " " + os); + + this->send_private_message(iid, "\01VERSION "s + result + "\01", "NOTICE"); +} + void Bridge::send_message(const Iid& iid, const std::string& nick, const std::string& body, const bool muc) { if (muc) -- cgit v1.2.3 From 12c8b1ae0b6f4c2b80d7c787b892ebcaafae6b03 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 15 May 2014 00:21:08 +0200 Subject: Disconnect the user from all its IRC servers whenever he returns an error fix #2524 --- src/bridge/bridge.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index f9dc9a6..b2563f0 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -41,11 +41,10 @@ static std::tuple get_role_affiliation_from_irc_mode(c return std::make_tuple("participant", "none"); } -void Bridge::shutdown() +void Bridge::shutdown(const std::string& exit_message) { for (auto it = this->irc_clients.begin(); it != this->irc_clients.end(); ++it) { - const std::string exit_message("Gateway shutdown"); it->second->send_quit_command(exit_message); it->second->leave_dummy_channel(exit_message); } -- cgit v1.2.3 From 01cd6eb5166c99a83facda804bfa3150e24e8b1e Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sun, 18 May 2014 20:23:08 +0200 Subject: Split the messages on \n when sending them back to the XMPP user --- src/bridge/bridge.cpp | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index b2563f0..7a60267 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -135,10 +135,6 @@ bool Bridge::join_irc_channel(const Iid& iid, const std::string& username) void Bridge::send_channel_message(const Iid& iid, const std::string& body) { - std::vector lines = utils::split(body, '\n', true); - if (lines.empty()) - return ; - const std::string first_line = lines[0]; if (iid.chan.empty() || iid.server.empty()) { log_warning("Cannot send message to channel: [" << iid.chan << "] on server [" << iid.server << "]"); @@ -150,23 +146,33 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) log_warning("Cannot send message: no client exist for server " << iid.server); return; } - if (first_line.substr(0, 6) == "/mode ") + // Because an IRC message cannot contain \n, we need to convert each line + // of text into a separate IRC message. For conveniance, we also cut the + // message into submessages on the XMPP side, this way the user of the + // gateway sees what was actually sent over IRC. For example if an user + // sends “hello\n/me waves”, two messages will be generated: “hello” and + // “/me waves”. Note that the “command” handling (messages starting with + // /me, /mode, etc) is done for each message generated this way. In the + // above example, the /me will be interpreted. + std::vector lines = utils::split(body, '\n', true); + if (lines.empty()) + return ; + for (const std::string& line: lines) { - std::vector args = utils::split(first_line.substr(6), ' ', false); - irc->send_mode_command(iid.chan, args); - return; + if (line.substr(0, 6) == "/mode ") + { + std::vector args = utils::split(line.substr(6), ' ', false); + irc->send_mode_command(iid.chan, args); + continue; // We do not want to send that back to the + // XMPP user, that’s not a textual message. + } + else if (line.substr(0, 4) == "/me ") + irc->send_channel_message(iid.chan, action_prefix + line.substr(4) + "\01"); + else + irc->send_channel_message(iid.chan, line); + this->xmpp->send_muc_message(iid.chan + "%" + iid.server, irc->get_own_nick(), + this->make_xmpp_body(line), this->user_jid); } - if (first_line.substr(0, 4) == "/me ") - irc->send_channel_message(iid.chan, action_prefix + first_line.substr(4) + "\01"); - else - irc->send_channel_message(iid.chan, first_line); - // Send each of the other lines of the message as a separate IRC message - for (std::vector::const_iterator it = lines.begin() + 1; it != lines.end(); ++it) - irc->send_channel_message(iid.chan, *it); - // We do not need to convert body to utf-8: it comes from our XMPP server, - // so it's ok to send it back - this->xmpp->send_muc_message(iid.chan + "%" + iid.server, irc->get_own_nick(), - this->make_xmpp_body(body), this->user_jid); } void Bridge::send_private_message(const Iid& iid, const std::string& body, const std::string& type) -- cgit v1.2.3 From 7fb0b671bbe6150d60b9f1efd4d8abc885c23844 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sun, 18 May 2014 20:48:42 +0200 Subject: Also do that cut of message on \n for private messages, and handle /me --- src/bridge/bridge.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 7a60267..d803e5e 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -180,8 +180,21 @@ void Bridge::send_private_message(const Iid& iid, const std::string& body, const if (iid.chan.empty() || iid.server.empty()) return ; IrcClient* irc = this->get_irc_client(iid.server); - if (irc) - irc->send_private_message(iid.chan, body, type); + if (!irc) + { + log_warning("Cannot send message: no client exist for server " << iid.server); + return; + } + std::vector lines = utils::split(body, '\n', true); + if (lines.empty()) + return ; + for (const std::string& line: lines) + { + if (line.substr(0, 4) == "/me ") + irc->send_private_message(iid.chan, action_prefix + line.substr(4) + "\01", type); + else + irc->send_private_message(iid.chan, line, type); + } } void Bridge::leave_irc_channel(Iid&& iid, std::string&& status_message) -- cgit v1.2.3 From 5507adbe9473f4b41e52d16498f14850773e5e45 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 27 May 2014 01:01:44 +0200 Subject: SocketHandlers own the poller and add themself into it only when the socket is created MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to call socket() with the parameters provided by getaddrinfo, so we can’t addd the fd into the poller immediately. We need to wait the connection attempt, and then the SocketHandler can call add_socket_handler itself, if the connection succeeds, or is in progress. --- src/bridge/bridge.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index d803e5e..78cd2d2 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -14,7 +14,7 @@ using namespace std::string_literals; static const char* action_prefix = "\01ACTION "; -Bridge::Bridge(const std::string& user_jid, XmppComponent* xmpp, Poller* poller): +Bridge::Bridge(const std::string& user_jid, XmppComponent* xmpp, std::shared_ptr poller): user_jid(user_jid), xmpp(xmpp), poller(poller) @@ -81,9 +81,8 @@ IrcClient* Bridge::get_irc_client(const std::string& hostname, const std::string } catch (const std::out_of_range& exception) { - this->irc_clients.emplace(hostname, std::make_shared(hostname, username, this)); + this->irc_clients.emplace(hostname, std::make_shared(this->poller, hostname, username, this)); std::shared_ptr irc = this->irc_clients.at(hostname); - this->poller->add_socket_handler(irc); return irc.get(); } } -- cgit v1.2.3 From 6c2d03da4ea0443624b6bf434b6a654c12e48438 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 28 May 2014 01:27:41 +0200 Subject: Send an error presence when the connection to the IRC server fails --- src/bridge/bridge.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 78cd2d2..70650a5 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -241,6 +241,11 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st this->make_xmpp_body(body), this->user_jid, "chat"); } +void Bridge::send_join_failed(const Iid& iid, const std::string& nick, const std::string& type, const std::string& condition, const std::string& text) +{ + this->xmpp->send_presence_error(iid.chan + "%" + iid.server, nick, this->user_jid, type, condition, text); +} + void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self) { this->xmpp->send_muc_leave(std::move(iid.chan) + "%" + std::move(iid.server), std::move(nick), this->make_xmpp_body(message), this->user_jid, self); -- cgit v1.2.3 From c2311b2893f3db755b67c43e5ad60cef66b10ab2 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 30 May 2014 16:08:23 +0200 Subject: Send (every 240s) a PING command to all connected irc servers fix #2452 --- src/bridge/bridge.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 70650a5..3377135 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -63,6 +63,11 @@ void Bridge::clean() } } +const std::string& Bridge::get_jid() const +{ + return this->user_jid; +} + Xmpp::body Bridge::make_xmpp_body(const std::string& str) { std::string res; -- cgit v1.2.3 From 7c1a38999c2eebfbd0939c9f8f8f864f10d9bc9a Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 11 Jun 2014 02:37:11 +0200 Subject: Rewrite the whole IID usage IRC users and channels are now distinguished by the separator used in the IID (% or !). ref #2468 --- src/bridge/bridge.cpp | 72 +++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 3377135..6d864c0 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -106,8 +106,8 @@ IrcClient* Bridge::get_irc_client(const std::string& hostname) bool Bridge::join_irc_channel(const Iid& iid, const std::string& username) { - IrcClient* irc = this->get_irc_client(iid.server, username); - if (iid.chan.empty()) + IrcClient* irc = this->get_irc_client(iid.get_server(), username); + if (iid.get_local().empty()) { // Join the dummy channel if (irc->is_welcomed()) { @@ -117,7 +117,7 @@ bool Bridge::join_irc_channel(const Iid& iid, const std::string& username) // joined the channel const IrcMessage join_message(irc->get_nick(), "JOIN", {""}); irc->on_channel_join(join_message); - const IrcMessage end_join_message(std::string(iid.server), "366", + const IrcMessage end_join_message(std::string(iid.get_server()), "366", {irc->get_nick(), "", "End of NAMES list"}); irc->on_channel_completely_joined(end_join_message); @@ -129,9 +129,9 @@ bool Bridge::join_irc_channel(const Iid& iid, const std::string& username) } return true; } - if (irc->is_channel_joined(iid.chan) == false) + if (irc->is_channel_joined(iid.get_local()) == false) { - irc->send_join_command(iid.chan); + irc->send_join_command(iid.get_local()); return true; } return false; @@ -139,15 +139,15 @@ bool Bridge::join_irc_channel(const Iid& iid, const std::string& username) void Bridge::send_channel_message(const Iid& iid, const std::string& body) { - if (iid.chan.empty() || iid.server.empty()) + if (iid.get_local().empty() || iid.get_server().empty()) { - log_warning("Cannot send message to channel: [" << iid.chan << "] on server [" << iid.server << "]"); + log_warning("Cannot send message to channel: [" << iid.get_local() << "] on server [" << iid.get_server() << "]"); return; } - IrcClient* irc = this->get_irc_client(iid.server); + IrcClient* irc = this->get_irc_client(iid.get_server()); if (!irc) { - log_warning("Cannot send message: no client exist for server " << iid.server); + log_warning("Cannot send message: no client exist for server " << iid.get_server()); return; } // Because an IRC message cannot contain \n, we need to convert each line @@ -166,27 +166,27 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) if (line.substr(0, 6) == "/mode ") { std::vector args = utils::split(line.substr(6), ' ', false); - irc->send_mode_command(iid.chan, args); + irc->send_mode_command(iid.get_local(), args); continue; // We do not want to send that back to the // XMPP user, that’s not a textual message. } else if (line.substr(0, 4) == "/me ") - irc->send_channel_message(iid.chan, action_prefix + line.substr(4) + "\01"); + irc->send_channel_message(iid.get_local(), action_prefix + line.substr(4) + "\01"); else - irc->send_channel_message(iid.chan, line); - this->xmpp->send_muc_message(iid.chan + "%" + iid.server, irc->get_own_nick(), + irc->send_channel_message(iid.get_local(), line); + this->xmpp->send_muc_message(std::to_string(iid), irc->get_own_nick(), this->make_xmpp_body(line), this->user_jid); } } void Bridge::send_private_message(const Iid& iid, const std::string& body, const std::string& type) { - if (iid.chan.empty() || iid.server.empty()) + if (iid.get_local().empty() || iid.get_server().empty()) return ; - IrcClient* irc = this->get_irc_client(iid.server); + IrcClient* irc = this->get_irc_client(iid.get_server()); if (!irc) { - log_warning("Cannot send message: no client exist for server " << iid.server); + log_warning("Cannot send message: no client exist for server " << iid.get_server()); return; } std::vector lines = utils::split(body, '\n', true); @@ -195,38 +195,38 @@ void Bridge::send_private_message(const Iid& iid, const std::string& body, const for (const std::string& line: lines) { if (line.substr(0, 4) == "/me ") - irc->send_private_message(iid.chan, action_prefix + line.substr(4) + "\01", type); + irc->send_private_message(iid.get_local(), action_prefix + line.substr(4) + "\01", type); else - irc->send_private_message(iid.chan, line, type); + irc->send_private_message(iid.get_local(), line, type); } } void Bridge::leave_irc_channel(Iid&& iid, std::string&& status_message) { - IrcClient* irc = this->get_irc_client(iid.server); + IrcClient* irc = this->get_irc_client(iid.get_server()); if (irc) - irc->send_part_command(iid.chan, status_message); + irc->send_part_command(iid.get_local(), status_message); } void Bridge::send_irc_nick_change(const Iid& iid, const std::string& new_nick) { - IrcClient* irc = this->get_irc_client(iid.server); + IrcClient* irc = this->get_irc_client(iid.get_server()); if (irc) irc->send_nick_command(new_nick); } void Bridge::send_irc_kick(const Iid& iid, const std::string& target, const std::string& reason) { - IrcClient* irc = this->get_irc_client(iid.server); + IrcClient* irc = this->get_irc_client(iid.get_server()); if (irc) - irc->send_kick_command(iid.chan, target, reason); + irc->send_kick_command(iid.get_local(), target, reason); } void Bridge::set_channel_topic(const Iid& iid, const std::string& subject) { - IrcClient* irc = this->get_irc_client(iid.server); + IrcClient* irc = this->get_irc_client(iid.get_server()); if (irc) - irc->send_topic_command(iid.chan, subject); + irc->send_topic_command(iid.get_local(), subject); } void Bridge::send_xmpp_version_to_irc(const Iid& iid, const std::string& name, const std::string& version, const std::string& os) @@ -239,22 +239,22 @@ void Bridge::send_xmpp_version_to_irc(const Iid& iid, const std::string& name, c void Bridge::send_message(const Iid& iid, const std::string& nick, const std::string& body, const bool muc) { if (muc) - this->xmpp->send_muc_message(iid.chan + "%" + iid.server, nick, + this->xmpp->send_muc_message(std::to_string(iid), nick, this->make_xmpp_body(body), this->user_jid); else - this->xmpp->send_message(iid.chan + "%" + iid.server, + this->xmpp->send_message(std::to_string(iid), this->make_xmpp_body(body), this->user_jid, "chat"); } void Bridge::send_join_failed(const Iid& iid, const std::string& nick, const std::string& type, const std::string& condition, const std::string& text) { - this->xmpp->send_presence_error(iid.chan + "%" + iid.server, nick, this->user_jid, type, condition, text); + this->xmpp->send_presence_error(std::to_string(iid), nick, this->user_jid, type, condition, text); } void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self) { - this->xmpp->send_muc_leave(std::move(iid.chan) + "%" + std::move(iid.server), std::move(nick), this->make_xmpp_body(message), this->user_jid, self); - IrcClient* irc = this->get_irc_client(iid.server); + this->xmpp->send_muc_leave(std::to_string(iid), std::move(nick), this->make_xmpp_body(message), this->user_jid, self); + IrcClient* irc = this->get_irc_client(iid.get_server()); if (irc && irc->number_of_joined_channels() == 0) irc->send_quit_command(""); } @@ -269,7 +269,7 @@ void Bridge::send_nick_change(Iid&& iid, std::string role; std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(user_mode); - this->xmpp->send_nick_change(std::move(iid.chan) + "%" + std::move(iid.server), + this->xmpp->send_nick_change(std::to_string(iid), old_nick, new_nick, affiliation, role, this->user_jid, self); } @@ -309,7 +309,7 @@ void Bridge::send_topic(const std::string& hostname, const std::string& chan_nam std::string Bridge::get_own_nick(const Iid& iid) { - IrcClient* irc = this->get_irc_client(iid.server); + IrcClient* irc = this->get_irc_client(iid.get_server()); if (irc) return irc->get_own_nick(); return ""; @@ -322,12 +322,12 @@ size_t Bridge::active_clients() const void Bridge::kick_muc_user(Iid&& iid, const std::string& target, const std::string& reason, const std::string& author) { - this->xmpp->kick_user(iid.chan + "%" + iid.server, target, reason, author, this->user_jid); + this->xmpp->kick_user(std::to_string(iid), target, reason, author, this->user_jid); } void Bridge::send_nickname_conflict_error(const Iid& iid, const std::string& nickname) { - this->xmpp->send_nickname_conflict_error(iid.chan + "%" + iid.server, nickname, this->user_jid); + this->xmpp->send_nickname_conflict_error(std::to_string(iid), nickname, this->user_jid); } void Bridge::send_affiliation_role_change(const Iid& iid, const std::string& target, const char mode) @@ -336,10 +336,10 @@ void Bridge::send_affiliation_role_change(const Iid& iid, const std::string& tar std::string affiliation; std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(mode); - this->xmpp->send_affiliation_role_change(iid.chan + "%" + iid.server, target, affiliation, role, this->user_jid); + this->xmpp->send_affiliation_role_change(std::to_string(iid), target, affiliation, role, this->user_jid); } void Bridge::send_iq_version_request(const std::string& nick, const std::string& hostname) { - this->xmpp->send_iq_version_request(nick + "%" + hostname, this->user_jid); + this->xmpp->send_iq_version_request(nick + "!" + hostname, this->user_jid); } -- cgit v1.2.3 From 04de62a4e0af4843e84c933e16f249ba1df6874f Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 18 Jun 2014 22:42:58 +0200 Subject: Messages to room participants are forwarded to the IRC user For example, both JID #chan%server@biboumi/Toto and toto!server@biboumi are equivalent, except that if you send a message to the first one, subsequent messages coming from the user toto will come from that same JID. This is done to be consistent for the XMPP user, and respond from the same JID than the 'to' of the first message. fix #2468 --- src/bridge/bridge.cpp | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 6d864c0..a0964df 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -242,8 +242,18 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st this->xmpp->send_muc_message(std::to_string(iid), nick, this->make_xmpp_body(body), this->user_jid); else - this->xmpp->send_message(std::to_string(iid), - this->make_xmpp_body(body), this->user_jid, "chat"); + { + std::string target = std::to_string(iid); + bool fulljid = false; + auto it = this->preferred_user_from.find(iid.get_local()); + if (it != this->preferred_user_from.end()) + { + target = it->second; + fulljid = true; + } + this->xmpp->send_message(target, this->make_xmpp_body(body), + this->user_jid, "chat", fulljid); + } } void Bridge::send_join_failed(const Iid& iid, const std::string& nick, const std::string& type, const std::string& condition, const std::string& text) @@ -343,3 +353,19 @@ void Bridge::send_iq_version_request(const std::string& nick, const std::string& { this->xmpp->send_iq_version_request(nick + "!" + hostname, this->user_jid); } + +void Bridge::set_preferred_from_jid(const std::string& nick, const std::string& full_jid) +{ + auto it = this->preferred_user_from.find(nick); + if (it == this->preferred_user_from.end()) + this->preferred_user_from.emplace(nick, full_jid); + else + this->preferred_user_from[nick] = full_jid; +} + +void Bridge::remove_preferred_from_jid(const std::string& nick) +{ + auto it = this->preferred_user_from.find(nick); + if (it != this->preferred_user_from.end()) + this->preferred_user_from.erase(it); +} -- cgit v1.2.3 From 26ffc8fe121e03e1b663aa0015a71b0fc914f95e Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 19 Jun 2014 22:21:49 +0200 Subject: Implement a way to add callbacks, waiting for an IRC event to return an iq --- src/bridge/bridge.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index a0964df..c2ac11f 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -369,3 +370,20 @@ void Bridge::remove_preferred_from_jid(const std::string& nick) if (it != this->preferred_user_from.end()) this->preferred_user_from.erase(it); } + +void Bridge::add_waiting_iq(iq_responder_callback_t&& callback) +{ + this->waiting_iq.emplace_back(std::move(callback)); +} + +void Bridge::trigger_response_iq(const std::string& irc_hostname, const IrcMessage& message) +{ + auto it = this->waiting_iq.begin(); + while (it != this->waiting_iq.end()) + { + if ((*it)(irc_hostname, message) == true) + it = this->waiting_iq.erase(it); + else + ++it; + } +} -- cgit v1.2.3 From 2117838cf9fb083f6f74386abbb56e3b28d4db46 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 19 Jun 2014 22:22:29 +0200 Subject: =?UTF-8?q?Return=20a=20proper=20iq=20when=20the=20IRC=E2=80=AFser?= =?UTF-8?q?ver=20responds=20to=20our=20kick?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A result or an error, depending on the type of message --- src/bridge/bridge.cpp | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index c2ac11f..384131f 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -216,11 +216,49 @@ void Bridge::send_irc_nick_change(const Iid& iid, const std::string& new_nick) irc->send_nick_command(new_nick); } -void Bridge::send_irc_kick(const Iid& iid, const std::string& target, const std::string& reason) +void Bridge::send_irc_kick(const Iid& iid, const std::string& target, const std::string& reason, + const std::string& iq_id, const std::string& to_jid) { IrcClient* irc = this->get_irc_client(iid.get_server()); if (irc) - irc->send_kick_command(iid.get_local(), target, reason); + { + irc->send_kick_command(iid.get_local(), target, reason); + this->add_waiting_iq([this, target, iq_id, to_jid, iid](const std::string& irc_hostname, const IrcMessage& message){ + if (irc_hostname != iid.get_server()) + return false; + if (message.command == "KICK" && message.arguments.size() >= 2) + { + const std::string target_later = message.arguments[1]; + const std::string chan_name_later = utils::tolower(message.arguments[0]); + if (target_later != target || chan_name_later != iid.get_local()) + return false; + this->xmpp->send_iq_result(iq_id, to_jid, std::to_string(iid)); + } + else if (message.command == "401" && message.arguments.size() >= 2) + { + const std::string target_later = message.arguments[1]; + if (target_later != target) + return false; + 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, std::to_string(iid), iq_id, "cancel", "item-not-found", + error_message, false); + } + else if (message.command == "482" && message.arguments.size() >= 2) + { + const std::string chan_name_later = utils::tolower(message.arguments[1]); + if (chan_name_later != iid.get_local()) + return false; + std::string error_message = "You're not channel operator"; + if (message.arguments.size() >= 3) + error_message = message.arguments[2]; + this->xmpp->send_stanza_error("iq", to_jid, std::to_string(iid), iq_id, "cancel", "not-allowed", + error_message, false); + } + return true; + }); + } } void Bridge::set_channel_topic(const Iid& iid, const std::string& subject) -- cgit v1.2.3 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 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'src/bridge/bridge.cpp') 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) -- cgit v1.2.3 From e3ea0d62c79cf74e154f24d7f5a0fa8c7d26d73b Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 8 Aug 2014 00:46:27 +0200 Subject: Use generic send_presence_error() instead of almost identical specializations --- src/bridge/bridge.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 9501d47..ba4911a 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -331,9 +331,11 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st } } -void Bridge::send_join_failed(const Iid& iid, const std::string& nick, const std::string& type, const std::string& condition, const std::string& text) +void Bridge::send_presence_error(const Iid& iid, const std::string& nick, + const std::string& type, const std::string& condition, + const std::string& error_code, const std::string& text) { - this->xmpp->send_presence_error(std::to_string(iid), nick, this->user_jid, type, condition, text); + this->xmpp->send_presence_error(std::to_string(iid), nick, this->user_jid, type, condition, error_code, text); } void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self) @@ -412,7 +414,7 @@ void Bridge::kick_muc_user(Iid&& iid, const std::string& target, const std::stri void Bridge::send_nickname_conflict_error(const Iid& iid, const std::string& nickname) { - this->xmpp->send_nickname_conflict_error(std::to_string(iid), nickname, this->user_jid); + this->xmpp->send_presence_error(std::to_string(iid), nickname, this->user_jid, "cancel", "conflict", "409", ""); } void Bridge::send_affiliation_role_change(const Iid& iid, const std::string& target, const char mode) -- cgit v1.2.3 From e1d69806ed7c92bdfe1bf632064bf68b3d1d266b Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 12 Nov 2014 04:05:56 +0100 Subject: =?UTF-8?q?Rename=20iq=5Fresponder=5Fcallback=5Ft=20to=20irc=5F?= =?UTF-8?q?=E2=80=A6=20and=20add=20the=20equivalent=20to=20wait=20for=20iq?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bridge/bridge.cpp | 98 +++++++++++++++++++++++++++------------------------ 1 file changed, 52 insertions(+), 46 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index ba4911a..bc89073 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -220,45 +221,49 @@ void Bridge::send_irc_kick(const Iid& iid, const std::string& target, const std: const std::string& iq_id, const std::string& to_jid) { IrcClient* irc = this->get_irc_client(iid.get_server()); - if (irc) + + if (!irc) + return; + + irc->send_kick_command(iid.get_local(), target, reason); + irc_responder_callback_t cb = [this, target, iq_id, to_jid, iid](const std::string& irc_hostname, + const IrcMessage& message) -> bool { - irc->send_kick_command(iid.get_local(), target, reason); - this->add_waiting_iq([this, target, iq_id, to_jid, iid](const std::string& irc_hostname, const IrcMessage& message){ - if (irc_hostname != iid.get_server()) + if (irc_hostname != iid.get_server()) + return false; + if (message.command == "KICK" && message.arguments.size() >= 2) + { + const std::string target_later = message.arguments[1]; + const std::string chan_name_later = utils::tolower(message.arguments[0]); + if (target_later != target || chan_name_later != iid.get_local()) return false; - if (message.command == "KICK" && message.arguments.size() >= 2) - { - const std::string target_later = message.arguments[1]; - const std::string chan_name_later = utils::tolower(message.arguments[0]); - if (target_later != target || chan_name_later != iid.get_local()) - return false; - this->xmpp->send_iq_result(iq_id, to_jid, std::to_string(iid)); - } - else if (message.command == "401" && message.arguments.size() >= 2) - { - const std::string target_later = message.arguments[1]; - if (target_later != target) - return false; - 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, std::to_string(iid), iq_id, "cancel", "item-not-found", - error_message, false); - } - else if (message.command == "482" && message.arguments.size() >= 2) - { - const std::string chan_name_later = utils::tolower(message.arguments[1]); - if (chan_name_later != iid.get_local()) - return false; - std::string error_message = "You're not channel operator"; - if (message.arguments.size() >= 3) - error_message = message.arguments[2]; - this->xmpp->send_stanza_error("iq", to_jid, std::to_string(iid), iq_id, "cancel", "not-allowed", - error_message, false); - } - return true; - }); - } + this->xmpp->send_iq_result(iq_id, to_jid, std::to_string(iid)); + } + else if (message.command == "401" && message.arguments.size() >= 2) + { + const std::string target_later = message.arguments[1]; + if (target_later != target) + return false; + 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, std::to_string(iid), iq_id, "cancel", "item-not-found", + error_message, false); + } + else if (message.command == "482" && message.arguments.size() >= 2) + { + const std::string chan_name_later = utils::tolower(message.arguments[1]); + if (chan_name_later != iid.get_local()) + return false; + std::string error_message = "You're not channel operator"; + if (message.arguments.size() >= 3) + error_message = message.arguments[2]; + this->xmpp->send_stanza_error("iq", to_jid, std::to_string(iid), iq_id, "cancel", "not-allowed", + error_message, false); + } + return true; + }; + this->add_waiting_irc(std::move(cb)); } void Bridge::set_channel_topic(const Iid& iid, const std::string& subject) @@ -284,7 +289,8 @@ void Bridge::send_irc_version_request(const std::string& irc_hostname, const std // 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){ + irc_responder_callback_t cb = [this, target, iq_id, to_jid, irc_hostname, from_jid](const std::string& hostname, const IrcMessage& message) -> bool + { if (irc_hostname != hostname) return false; IrcUser user(message.prefix); @@ -307,10 +313,10 @@ void Bridge::send_irc_version_request(const std::string& irc_hostname, const std return true; } return false; - }); + }; + this->add_waiting_irc(std::move(cb)); } - void Bridge::send_message(const Iid& iid, const std::string& nick, const std::string& body, const bool muc) { if (muc) @@ -447,18 +453,18 @@ void Bridge::remove_preferred_from_jid(const std::string& nick) this->preferred_user_from.erase(it); } -void Bridge::add_waiting_iq(iq_responder_callback_t&& callback) +void Bridge::add_waiting_irc(irc_responder_callback_t&& callback) { - this->waiting_iq.emplace_back(std::move(callback)); + this->waiting_irc.emplace_back(std::move(callback)); } -void Bridge::trigger_response_iq(const std::string& irc_hostname, const IrcMessage& message) +void Bridge::trigger_on_irc_message(const std::string& irc_hostname, const IrcMessage& message) { - auto it = this->waiting_iq.begin(); - while (it != this->waiting_iq.end()) + auto it = this->waiting_irc.begin(); + while (it != this->waiting_irc.end()) { if ((*it)(irc_hostname, message) == true) - it = this->waiting_iq.erase(it); + it = this->waiting_irc.erase(it); else ++it; } -- cgit v1.2.3 From d8da7984b23bf8f30b5f8f53895cbae5be50347a Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 12 Nov 2014 06:16:10 +0100 Subject: Implement PING, user to user only (XMPP and IRC side, using CTCP PING) ref #2757 --- src/bridge/bridge.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index bc89073..08fd569 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -7,7 +7,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -280,6 +282,50 @@ 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_ping_result(const Iid& iid, const std::string& id) +{ + this->send_private_message(iid, "\01PING "s + utils::revstr(id), "NOTICE"); +} + +void Bridge::send_irc_user_ping_request(const std::string& irc_hostname, const std::string& nick, + const std::string& iq_id, const std::string& to_jid, + const std::string& from_jid) +{ + Iid iid(nick + "!" + irc_hostname); + this->send_private_message(iid, "\01PING " + iq_id + "\01"); + + irc_responder_callback_t cb = [this, nick, iq_id, to_jid, irc_hostname, from_jid](const std::string& hostname, const IrcMessage& message) -> bool + { + if (irc_hostname != hostname) + return false; + IrcUser user(message.prefix); + const std::string body = message.arguments[1]; + if (message.command == "NOTICE" && user.nick == nick && + message.arguments.size() >= 2 && body.substr(0, 6) == "\01PING ") + { + const std::string id = body.substr(6, body.size() - 6); + if (id != iq_id) + return false; + Jid jid(from_jid); + this->xmpp->send_iq_result(iq_id, to_jid, jid.local); + return true; + } + if (message.command == "401" && message.arguments.size() >= 2 + && message.arguments[1] == nick) + { + 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", "service-unavailable", + error_message, true); + return true; + } + + return false; + }; + this->add_waiting_irc(std::move(cb)); +} + 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) @@ -437,6 +483,15 @@ void Bridge::send_iq_version_request(const std::string& nick, const std::string& this->xmpp->send_iq_version_request(nick + "!" + hostname, this->user_jid); } +void Bridge::send_xmpp_ping_request(const std::string& nick, const std::string& hostname, + const std::string& id) +{ + // Use revstr because the forwarded ping to target XMPP user must not be + // the same that the request iq, but we also need to get it back easily + // (revstr again) + this->xmpp->send_ping_request(nick + "!" + hostname, this->user_jid, utils::revstr(id)); +} + void Bridge::set_preferred_from_jid(const std::string& nick, const std::string& full_jid) { auto it = this->preferred_user_from.find(nick); -- cgit v1.2.3 From 4a8bcd3cbde0a41902999db7acc346de020cf564 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 12 Nov 2014 07:51:10 +0100 Subject: Implement PING to in-room participant ref #2575 --- src/bridge/bridge.cpp | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 08fd569..ed61c6b 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -326,13 +326,41 @@ void Bridge::send_irc_user_ping_request(const std::string& irc_hostname, const s this->add_waiting_irc(std::move(cb)); } +void Bridge::send_irc_participant_ping_request(const Iid& iid, const std::string& nick, + const std::string& iq_id, const std::string& to_jid, + const std::string& from_jid) +{ + IrcClient* irc = this->get_irc_client(iid.get_server()); + if (!irc) + { + this->xmpp->send_stanza_error("iq", to_jid, from_jid, iq_id, "cancel", "item-not-found", + "Not connected to IRC server"s + iid.get_server(), true); + return; + } + IrcChannel* chan = irc->get_channel(iid.get_local()); + if (!chan->joined) + { + this->xmpp->send_stanza_error("iq", to_jid, from_jid, iq_id, "cancel", "not-allowed", + "", true); + return; + } + if (chan->get_self()->nick != nick && !chan->find_user(nick)) + { + this->xmpp->send_stanza_error("iq", to_jid, from_jid, iq_id, "cancel", "item-not-found", + "Recipient not in room", true); + return; + } + + // The user is in the room, send it a direct PING + this->send_irc_user_ping_request(iid.get_server(), nick, iq_id, to_jid, from_jid); +} + 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 irc_responder_callback_t cb = [this, target, iq_id, to_jid, irc_hostname, from_jid](const std::string& hostname, const IrcMessage& message) -> bool -- cgit v1.2.3 From 12eeb4d11eee5b8e6514f0ce8bf7508cc2d6d7a1 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 12 Nov 2014 08:10:46 +0100 Subject: Implement the PING on a server or the gateway itself fix #2575 --- src/bridge/bridge.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index ed61c6b..a7d8fe6 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -355,6 +355,17 @@ void Bridge::send_irc_participant_ping_request(const Iid& iid, const std::string this->send_irc_user_ping_request(iid.get_server(), nick, iq_id, to_jid, from_jid); } +void Bridge::on_gateway_ping(const std::string& irc_hostname, const std::string& iq_id, const std::string& to_jid, + const std::string& from_jid) +{ + Jid jid(from_jid); + if (irc_hostname.empty() || this->get_irc_client(irc_hostname)) + this->xmpp->send_iq_result(iq_id, to_jid, jid.local); + else + this->xmpp->send_stanza_error("iq", to_jid, from_jid, iq_id, "cancel", "service-unavailable", + "", true); +} + 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) -- cgit v1.2.3 From 720e31a5113c25e48d7754bb812ab84c6c31d1d9 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 17 Dec 2014 13:37:57 +0100 Subject: Fix a few issues reported by static analyzers --- src/bridge/bridge.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index a7d8fe6..c925f9e 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -480,7 +480,7 @@ void Bridge::send_user_join(const std::string& hostname, affiliation, role, this->user_jid, self); } -void Bridge::send_topic(const std::string& hostname, const std::string& chan_name, const std::string topic) +void Bridge::send_topic(const std::string& hostname, const std::string& chan_name, const std::string& topic) { this->xmpp->send_topic(chan_name + "%" + hostname, this->make_xmpp_body(topic), this->user_jid); } -- cgit v1.2.3 From e4fcbd3030f033c24102db9f6b6abfb540332c9d Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Wed, 14 Jan 2015 12:38:46 +0100 Subject: Add support for password-protected IRC rooms. --- src/bridge/bridge.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index c925f9e..5fa96c8 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -108,7 +108,7 @@ IrcClient* Bridge::get_irc_client(const std::string& hostname) } } -bool Bridge::join_irc_channel(const Iid& iid, const std::string& username) +bool Bridge::join_irc_channel(const Iid& iid, const std::string& username, const std::string& password) { IrcClient* irc = this->get_irc_client(iid.get_server(), username); if (iid.get_local().empty()) @@ -135,7 +135,7 @@ bool Bridge::join_irc_channel(const Iid& iid, const std::string& username) } if (irc->is_channel_joined(iid.get_local()) == false) { - irc->send_join_command(iid.get_local()); + irc->send_join_command(iid.get_local(), password); return true; } return false; -- cgit v1.2.3 From 2c5d3d89b0eb1e6b8d888b4d37ceca6f23c2e314 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 24 Jan 2015 16:19:13 +0100 Subject: Change IRC modes when receiving an affiliation/role change request fix #2946 --- src/bridge/bridge.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 5fa96c8..fc00c8c 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -183,6 +183,72 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) } } +void Bridge::forward_affiliation_role_change(const Iid& iid, const std::string& nick, + const std::string& affiliation, + const std::string& role) +{ + IrcClient* irc = this->get_irc_client(iid.get_server()); + if (!irc) + return; + IrcChannel* chan = irc->get_channel(iid.get_local()); + if (!chan || !chan->joined) + return; + IrcUser* user = chan->find_user(nick); + if (!user) + return; + // For each affiliation or role, we have a “maximal” mode that we want to + // set. We must remove any superior mode at the same time. For example if + // the user already has +o mode, and we set its affiliation to member, we + // remove the +o mode, and add +v. For each “superior” mode (for example, + // for +v, the superior modes are 'h', 'a', 'o' and 'q') we check if that + // user has it, and if yes we remove that mode + + std::size_t nb = 1; // the number of times the nick must be + // repeated in the argument list + std::string modes; // The string of modes to + // add/remove. For example "+v-aoh" + std::vector modes_to_remove; // List of modes to check for removal + if (affiliation == "none") + { + modes = ""; + nb = 0; + modes_to_remove = {'v', 'h', 'o', 'a', 'q'}; + } + else if (affiliation == "member") + { + modes = "+v"; + modes_to_remove = {'h', 'o', 'a', 'q'}; + } + else if (role == "moderator") + { + modes = "+h"; + modes_to_remove = {'o', 'a', 'q'}; + } + else if (affiliation == "admin") + { + modes = "+o"; + modes_to_remove = {'a', 'q'}; + } + else if (affiliation == "owner") + { + modes = "+a"; + modes_to_remove = {'q'}; + } + else + return; + for (const char mode: modes_to_remove) + if (user->modes.find(mode) != user->modes.end()) + { + modes += "-"s + mode; + nb++; + } + if (modes.empty()) + return; + std::vector args(nb, nick); + args.insert(args.begin(), modes); + irc->send_mode_command(iid.get_local(), args); +} + void Bridge::send_private_message(const Iid& iid, const std::string& body, const std::string& type) { if (iid.get_local().empty() || iid.get_server().empty()) -- cgit v1.2.3 From 2df0ebf2dfed1dcbf80c92bff8361e2a04581bec Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 25 Feb 2015 18:35:30 +0100 Subject: Add support for a fixed_irc_server configuration This option lets the administrator choose a specific IRC server, and only that server can be used with this biboumi instance. In this mode, JIDs to use are changed like this: - #chan%irc.example.com@biboumi.example.com -> #chan@biboumi.example.com - user!irc.example.com@biboumi.example.com -> user!@biboumi.example.com - #chan%irc.example.com@biboumi.example.com/Nick -> #chan@biboumi.example.com/Nick - %irc.example.com@biboumi.example.com -> no equivalent - irc.example.com@biboumi.example.com -> no equivalent --- src/bridge/bridge.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index fc00c8c..e312345 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -542,13 +543,13 @@ void Bridge::send_user_join(const std::string& hostname, std::string role; std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(user_mode); - this->xmpp->send_user_join(chan_name + "%" + hostname, user->nick, user->host, + this->xmpp->send_user_join(chan_name + utils::empty_if_fixed_server("%" + hostname), user->nick, user->host, affiliation, role, this->user_jid, self); } void Bridge::send_topic(const std::string& hostname, const std::string& chan_name, const std::string& topic) { - this->xmpp->send_topic(chan_name + "%" + hostname, this->make_xmpp_body(topic), this->user_jid); + this->xmpp->send_topic(chan_name + utils::empty_if_fixed_server("%" + hostname), this->make_xmpp_body(topic), this->user_jid); } std::string Bridge::get_own_nick(const Iid& iid) @@ -585,7 +586,7 @@ void Bridge::send_affiliation_role_change(const Iid& iid, const std::string& tar void Bridge::send_iq_version_request(const std::string& nick, const std::string& hostname) { - this->xmpp->send_iq_version_request(nick + "!" + hostname, this->user_jid); + this->xmpp->send_iq_version_request(nick + "!" + utils::empty_if_fixed_server(hostname), this->user_jid); } void Bridge::send_xmpp_ping_request(const std::string& nick, const std::string& hostname, @@ -594,7 +595,7 @@ void Bridge::send_xmpp_ping_request(const std::string& nick, const std::string& // Use revstr because the forwarded ping to target XMPP user must not be // the same that the request iq, but we also need to get it back easily // (revstr again) - this->xmpp->send_ping_request(nick + "!" + hostname, this->user_jid, utils::revstr(id)); + this->xmpp->send_ping_request(nick + "!" + utils::empty_if_fixed_server(hostname), this->user_jid, utils::revstr(id)); } void Bridge::set_preferred_from_jid(const std::string& nick, const std::string& full_jid) -- cgit v1.2.3 From c01befb054075ab414fd602859e5999a138aa5bf Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 26 Feb 2015 05:02:08 +0100 Subject: Implement room discovery using the LIST irc command ref #2472 --- src/bridge/bridge.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index fc00c8c..2e3520d 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -285,6 +286,43 @@ void Bridge::send_irc_nick_change(const Iid& iid, const std::string& new_nick) irc->send_nick_command(new_nick); } +void Bridge::send_irc_channel_list_request(const Iid& iid, const std::string& iq_id, + const std::string& to_jid) +{ + IrcClient* irc = this->get_irc_client(iid.get_server()); + + if (!irc) + return; + + irc->send_list_command(); + irc_responder_callback_t cb = [this, iid, iq_id, to_jid](const std::string& irc_hostname, + const IrcMessage& message) -> bool + { + static std::vector list; + + if (irc_hostname != iid.get_server()) + return false; + if (message.command == "263" || message.command == "RPL_TRYAGAIN") + { // TODO send an error iq + return true; + } + else if (message.command == "322" || message.command == "RPL_LIST") + { // Add element to list + if (message.arguments.size() == 4) + list.emplace_back(message.arguments[1], message.arguments[2], + message.arguments[3]); + return false; + } + else if (message.command == "323" || message.command == "RPL_LISTEND") + { // Send the iq response with the content of the list + this->xmpp->send_iq_room_list_result(iq_id, to_jid, std::to_string(iid), list); + return true; + } + return false; + }; + this->add_waiting_irc(std::move(cb)); +} + void Bridge::send_irc_kick(const Iid& iid, const std::string& target, const std::string& reason, const std::string& iq_id, const std::string& to_jid) { -- cgit v1.2.3 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/bridge/bridge.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 1a205bd..85049b9 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include #include @@ -20,7 +20,7 @@ using namespace std::string_literals; static const char* action_prefix = "\01ACTION "; -Bridge::Bridge(const std::string& user_jid, XmppComponent* xmpp, std::shared_ptr poller): +Bridge::Bridge(const std::string& user_jid, BiboumiComponent* xmpp, std::shared_ptr poller): user_jid(user_jid), xmpp(xmpp), poller(poller) -- 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/bridge/bridge.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 85049b9..45cdc01 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -273,6 +273,17 @@ void Bridge::send_private_message(const Iid& iid, const std::string& body, const } } +void Bridge::send_raw_message(const std::string& hostname, const std::string& body) +{ + IrcClient* irc = this->get_irc_client(hostname); + if (!irc) + { + log_warning("Cannot send message: no client exist for server " << hostname); + return ; + } + irc->send_raw(body); +} + void Bridge::leave_irc_channel(Iid&& iid, std::string&& status_message) { IrcClient* irc = this->get_irc_client(iid.get_server()); -- 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/bridge/bridge.cpp | 71 +++++++++++++++++++++++---------------------------- 1 file changed, 32 insertions(+), 39 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 45cdc01..16264d4 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -99,6 +99,18 @@ IrcClient* Bridge::get_irc_client(const std::string& hostname, const std::string } IrcClient* Bridge::get_irc_client(const std::string& hostname) +{ + try + { + return this->irc_clients.at(hostname).get(); + } + catch (const std::out_of_range& exception) + { + throw IRCNotConnected(hostname); + } +} + +IrcClient* Bridge::find_irc_client(const std::string& hostname) { try { @@ -145,17 +157,17 @@ bool Bridge::join_irc_channel(const Iid& iid, const std::string& username, const void Bridge::send_channel_message(const Iid& iid, const std::string& body) { - if (iid.get_local().empty() || iid.get_server().empty()) + if (iid.get_server().empty()) { - log_warning("Cannot send message to channel: [" << iid.get_local() << "] on server [" << iid.get_server() << "]"); + this->xmpp->send_stanza_error("message", this->user_jid, std::to_string(iid), "", + "cancel", "remote-server-not-found", + std::to_string(iid) + " is not a valid channel name. " + "A correct room jid is of the form: #%", + false); return; } IrcClient* irc = this->get_irc_client(iid.get_server()); - if (!irc) - { - log_warning("Cannot send message: no client exist for server " << iid.get_server()); - return; - } + // Because an IRC message cannot contain \n, we need to convert each line // of text into a separate IRC message. For conveniance, we also cut the // message into submessages on the XMPP side, this way the user of the @@ -190,8 +202,6 @@ void Bridge::forward_affiliation_role_change(const Iid& iid, const std::string& const std::string& role) { IrcClient* irc = this->get_irc_client(iid.get_server()); - if (!irc) - return; IrcChannel* chan = irc->get_channel(iid.get_local()); if (!chan || !chan->joined) return; @@ -254,13 +264,15 @@ void Bridge::forward_affiliation_role_change(const Iid& iid, const std::string& void Bridge::send_private_message(const Iid& iid, const std::string& body, const std::string& type) { if (iid.get_local().empty() || iid.get_server().empty()) - return ; - IrcClient* irc = this->get_irc_client(iid.get_server()); - if (!irc) { - log_warning("Cannot send message: no client exist for server " << iid.get_server()); + this->xmpp->send_stanza_error("message", this->user_jid, std::to_string(iid), "", + "cancel", "remote-server-not-found", + std::to_string(iid) + " is not a valid channel name. " + "A correct room jid is of the form: #%", + false); return; } + IrcClient* irc = this->get_irc_client(iid.get_server()); std::vector lines = utils::split(body, '\n', true); if (lines.empty()) return ; @@ -276,26 +288,19 @@ void Bridge::send_private_message(const Iid& iid, const std::string& body, const void Bridge::send_raw_message(const std::string& hostname, const std::string& body) { IrcClient* irc = this->get_irc_client(hostname); - if (!irc) - { - log_warning("Cannot send message: no client exist for server " << hostname); - return ; - } irc->send_raw(body); } void Bridge::leave_irc_channel(Iid&& iid, std::string&& status_message) { IrcClient* irc = this->get_irc_client(iid.get_server()); - if (irc) - irc->send_part_command(iid.get_local(), status_message); + irc->send_part_command(iid.get_local(), status_message); } void Bridge::send_irc_nick_change(const Iid& iid, const std::string& new_nick) { IrcClient* irc = this->get_irc_client(iid.get_server()); - if (irc) - irc->send_nick_command(new_nick); + irc->send_nick_command(new_nick); } void Bridge::send_irc_channel_list_request(const Iid& iid, const std::string& iq_id, @@ -303,10 +308,8 @@ void Bridge::send_irc_channel_list_request(const Iid& iid, const std::string& iq { IrcClient* irc = this->get_irc_client(iid.get_server()); - if (!irc) - return; - irc->send_list_command(); + irc_responder_callback_t cb = [this, iid, iq_id, to_jid](const std::string& irc_hostname, const IrcMessage& message) -> bool { @@ -340,9 +343,6 @@ void Bridge::send_irc_kick(const Iid& iid, const std::string& target, const std: { IrcClient* irc = this->get_irc_client(iid.get_server()); - if (!irc) - return; - irc->send_kick_command(iid.get_local(), target, reason); irc_responder_callback_t cb = [this, target, iq_id, to_jid, iid](const std::string& irc_hostname, const IrcMessage& message) -> bool @@ -387,8 +387,7 @@ void Bridge::send_irc_kick(const Iid& iid, const std::string& target, const std: void Bridge::set_channel_topic(const Iid& iid, const std::string& subject) { IrcClient* irc = this->get_irc_client(iid.get_server()); - if (irc) - irc->send_topic_command(iid.get_local(), subject); + irc->send_topic_command(iid.get_local(), subject); } void Bridge::send_xmpp_version_to_irc(const Iid& iid, const std::string& name, const std::string& version, const std::string& os) @@ -447,12 +446,6 @@ void Bridge::send_irc_participant_ping_request(const Iid& iid, const std::string const std::string& from_jid) { IrcClient* irc = this->get_irc_client(iid.get_server()); - if (!irc) - { - this->xmpp->send_stanza_error("iq", to_jid, from_jid, iq_id, "cancel", "item-not-found", - "Not connected to IRC server"s + iid.get_server(), true); - return; - } IrcChannel* chan = irc->get_channel(iid.get_local()); if (!chan->joined) { @@ -475,7 +468,7 @@ void Bridge::on_gateway_ping(const std::string& irc_hostname, const std::string& const std::string& from_jid) { Jid jid(from_jid); - if (irc_hostname.empty() || this->get_irc_client(irc_hostname)) + if (irc_hostname.empty() || this->find_irc_client(irc_hostname)) this->xmpp->send_iq_result(iq_id, to_jid, jid.local); else this->xmpp->send_stanza_error("iq", to_jid, from_jid, iq_id, "cancel", "service-unavailable", @@ -548,7 +541,7 @@ void Bridge::send_presence_error(const Iid& iid, const std::string& nick, void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self) { this->xmpp->send_muc_leave(std::to_string(iid), std::move(nick), this->make_xmpp_body(message), this->user_jid, self); - IrcClient* irc = this->get_irc_client(iid.get_server()); + IrcClient* irc = this->find_irc_client(iid.get_server()); if (irc && irc->number_of_joined_channels() == 0) irc->send_quit_command(""); } @@ -603,7 +596,7 @@ void Bridge::send_topic(const std::string& hostname, const std::string& chan_nam std::string Bridge::get_own_nick(const Iid& iid) { - IrcClient* irc = this->get_irc_client(iid.get_server()); + IrcClient* irc = this->find_irc_client(iid.get_server()); if (irc) return irc->get_own_nick(); return ""; -- cgit v1.2.3 From 7fe0dc2667229287ab9f1825e84403a25bc863fe Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 11 May 2015 05:31:11 +0200 Subject: Fix the case of the nick for ping requests fix #3041 --- src/bridge/bridge.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 16264d4..4bfd1b2 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -409,13 +409,13 @@ void Bridge::send_irc_user_ping_request(const std::string& irc_hostname, const s Iid iid(nick + "!" + irc_hostname); this->send_private_message(iid, "\01PING " + iq_id + "\01"); - irc_responder_callback_t cb = [this, nick, iq_id, to_jid, irc_hostname, from_jid](const std::string& hostname, const IrcMessage& message) -> bool + irc_responder_callback_t cb = [this, nick=utils::tolower(nick), iq_id, to_jid, irc_hostname, from_jid](const std::string& hostname, const IrcMessage& message) -> bool { if (irc_hostname != hostname) return false; IrcUser user(message.prefix); const std::string body = message.arguments[1]; - if (message.command == "NOTICE" && user.nick == nick && + if (message.command == "NOTICE" && utils::tolower(user.nick) == nick && message.arguments.size() >= 2 && body.substr(0, 6) == "\01PING ") { const std::string id = body.substr(6, body.size() - 6); -- cgit v1.2.3 From cc1255d216bf7ac6029a5dd3bc8aadae06df446b Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 11 May 2015 05:31:47 +0200 Subject: Fix the way we check for the PING id --- src/bridge/bridge.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 4bfd1b2..8c364ee 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -418,7 +418,7 @@ void Bridge::send_irc_user_ping_request(const std::string& irc_hostname, const s if (message.command == "NOTICE" && utils::tolower(user.nick) == nick && message.arguments.size() >= 2 && body.substr(0, 6) == "\01PING ") { - const std::string id = body.substr(6, body.size() - 6); + const std::string id = body.substr(6, body.size() - 7); if (id != iq_id) return false; Jid jid(from_jid); -- cgit v1.2.3 From 763be827c9349d39adbdd8cf731565bef316a01a Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 11 May 2015 05:43:32 +0200 Subject: Fix a message.arguments size check --- src/bridge/bridge.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 8c364ee..ef20351 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -411,13 +411,14 @@ void Bridge::send_irc_user_ping_request(const std::string& irc_hostname, const s irc_responder_callback_t cb = [this, nick=utils::tolower(nick), iq_id, to_jid, irc_hostname, from_jid](const std::string& hostname, const IrcMessage& message) -> bool { - if (irc_hostname != hostname) + if (irc_hostname != hostname || message.arguments.size() < 2) return false; IrcUser user(message.prefix); const std::string body = message.arguments[1]; - if (message.command == "NOTICE" && utils::tolower(user.nick) == nick && - message.arguments.size() >= 2 && body.substr(0, 6) == "\01PING ") + if (message.command == "NOTICE" && utils::tolower(user.nick) == nick + && body.substr(0, 6) == "\01PING ") { + return false; const std::string id = body.substr(6, body.size() - 7); if (id != iq_id) return false; @@ -425,8 +426,7 @@ void Bridge::send_irc_user_ping_request(const std::string& irc_hostname, const s this->xmpp->send_iq_result(iq_id, to_jid, jid.local); return true; } - if (message.command == "401" && message.arguments.size() >= 2 - && message.arguments[1] == nick) + if (message.command == "401" && message.arguments[1] == nick) { std::string error_message = "No such nick"; if (message.arguments.size() >= 3) -- cgit v1.2.3 From 501a3f7be25f4dbb4526bf645d7df8d29f6a54a5 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 19 May 2015 05:13:55 +0200 Subject: Fix the way we we forward an XMPP ping result to the IRC server Our CTCP notice didn't include a \01 char at the end. We thus failed to check the PING id when we received it ourself, because one char was missing --- src/bridge/bridge.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index ef20351..6081986 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -399,7 +399,7 @@ void Bridge::send_xmpp_version_to_irc(const Iid& iid, const std::string& name, c void Bridge::send_irc_ping_result(const Iid& iid, const std::string& id) { - this->send_private_message(iid, "\01PING "s + utils::revstr(id), "NOTICE"); + this->send_private_message(iid, "\01PING "s + utils::revstr(id) + "\01", "NOTICE"); } void Bridge::send_irc_user_ping_request(const std::string& irc_hostname, const std::string& nick, -- cgit v1.2.3 From 2195292919110bad41f507f45fa1b7d86a369539 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 19 May 2015 05:15:49 +0200 Subject: Remove a debug line (breaking our PING stuf) that should not have been commited --- src/bridge/bridge.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 6081986..467923b 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -418,7 +418,6 @@ void Bridge::send_irc_user_ping_request(const std::string& irc_hostname, const s if (message.command == "NOTICE" && utils::tolower(user.nick) == nick && body.substr(0, 6) == "\01PING ") { - return false; const std::string id = body.substr(6, body.size() - 7); if (id != iq_id) return false; -- cgit v1.2.3 From e8d7965115fe6abe25d76bccedd450532549891e Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 19 May 2015 06:16:49 +0200 Subject: Handle errors for the LIST irc command ref #2472 --- src/bridge/bridge.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 467923b..c63b3da 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -317,8 +317,14 @@ void Bridge::send_irc_channel_list_request(const Iid& iid, const std::string& iq if (irc_hostname != iid.get_server()) return false; - if (message.command == "263" || message.command == "RPL_TRYAGAIN") - { // TODO send an error iq + if (message.command == "263" || message.command == "RPL_TRYAGAIN" || + message.command == "ERR_TOOMANYMATCHES" || message.command == "ERR_NOSUCHSERVER") + { + std::string text; + if (message.arguments.size() >= 2) + text = message.arguments[1]; + this->xmpp->send_stanza_error("iq", to_jid, std::to_string(iid), iq_id, + "wait", "service-unavailable", text, false); return true; } else if (message.command == "322" || message.command == "RPL_LIST") -- cgit v1.2.3 From df006a191603c4a9f0bb364affa3731c2944fef5 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 19 Aug 2015 21:21:42 +0200 Subject: //mode with no argument should work The server will respond with the current channel mode, in private or something --- src/bridge/bridge.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index c63b3da..1d46e07 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -181,9 +181,9 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) return ; for (const std::string& line: lines) { - if (line.substr(0, 6) == "/mode ") + if (line.substr(0, 5) == "/mode") { - std::vector args = utils::split(line.substr(6), ' ', false); + std::vector args = utils::split(line.substr(5), ' ', false); irc->send_mode_command(iid.get_local(), args); continue; // We do not want to send that back to the // XMPP user, that’s not a textual message. -- cgit v1.2.3 From f1de6d032091bd141e12e8345969495d6f23c3e6 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 18 Sep 2015 21:58:05 +0200 Subject: Add Bridge::get_bare_jid --- src/bridge/bridge.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 1d46e07..ba70069 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -74,6 +74,12 @@ const std::string& Bridge::get_jid() const return this->user_jid; } +std::string Bridge::get_bare_jid() const +{ + Jid jid(this->user_jid); + return jid.local + "@" + jid.domain; +} + Xmpp::body Bridge::make_xmpp_body(const std::string& str) { std::string res; -- cgit v1.2.3 From 1aa2c2d857037f3274297527ca3971a75203d39c Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 12 Oct 2015 17:14:29 +0200 Subject: Introduce the realname_from_jid option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When set to true, the realname and username are extracted (by default) from the user’s JID fix #3136 --- src/bridge/bridge.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index ba70069..ec143f0 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -90,7 +90,7 @@ Xmpp::body Bridge::make_xmpp_body(const std::string& str) return irc_format_to_xhtmlim(res); } -IrcClient* Bridge::get_irc_client(const std::string& hostname, const std::string& username) +IrcClient* Bridge::make_irc_client(const std::string& hostname, const std::string& nickname) { try { @@ -98,7 +98,18 @@ IrcClient* Bridge::get_irc_client(const std::string& hostname, const std::string } catch (const std::out_of_range& exception) { - this->irc_clients.emplace(hostname, std::make_shared(this->poller, hostname, username, this)); + auto username = nickname; + auto realname = nickname; + if (Config::get("realname_from_jid", "false") == "true") + { + Jid jid(this->user_jid); + username = jid.local; + realname = this->get_bare_jid(); + } + this->irc_clients.emplace(hostname, + std::make_shared(this->poller, hostname, + nickname, username, + realname, this)); std::shared_ptr irc = this->irc_clients.at(hostname); return irc.get(); } @@ -128,9 +139,9 @@ IrcClient* Bridge::find_irc_client(const std::string& hostname) } } -bool Bridge::join_irc_channel(const Iid& iid, const std::string& username, const std::string& password) +bool Bridge::join_irc_channel(const Iid& iid, const std::string& nickname, const std::string& password) { - IrcClient* irc = this->get_irc_client(iid.get_server(), username); + IrcClient* irc = this->make_irc_client(iid.get_server(), nickname); if (iid.get_local().empty()) { // Join the dummy channel if (irc->is_welcomed()) -- cgit v1.2.3 From 6c42286109fceddd70eacc467811b102b41a831e Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 31 Oct 2015 05:36:18 +0100 Subject: Remove some useless includes --- src/bridge/bridge.cpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index ec143f0..18a8d92 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -1,9 +1,6 @@ #include -#include #include #include -#include -#include #include #include #include @@ -12,9 +9,6 @@ #include #include #include -#include -#include -#include using namespace std::string_literals; -- cgit v1.2.3 From 34fc1d4010d23be947c00fc956f2bdded2374cee Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sat, 31 Oct 2015 06:17:35 +0100 Subject: Implement a basic webirc support See https://kiwiirc.com/docs/webirc fix #3135 --- src/bridge/bridge.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 18a8d92..5badb18 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -56,7 +56,8 @@ void Bridge::clean() while (it != this->irc_clients.end()) { IrcClient* client = it->second.get(); - if (!client->is_connected() && !client->is_connecting()) + if (!client->is_connected() && !client->is_connecting() && + !client->get_resolver().is_resolving()) it = this->irc_clients.erase(it); else ++it; @@ -94,16 +95,17 @@ IrcClient* Bridge::make_irc_client(const std::string& hostname, const std::strin { auto username = nickname; auto realname = nickname; + Jid jid(this->user_jid); if (Config::get("realname_from_jid", "false") == "true") { - Jid jid(this->user_jid); username = jid.local; realname = this->get_bare_jid(); } this->irc_clients.emplace(hostname, std::make_shared(this->poller, hostname, nickname, username, - realname, this)); + realname, jid.domain, + this)); std::shared_ptr irc = this->irc_clients.at(hostname); return irc.get(); } -- 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/bridge/bridge.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 5badb18..a1ba71a 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -690,3 +690,8 @@ void Bridge::trigger_on_irc_message(const std::string& irc_hostname, const IrcMe ++it; } } + +std::unordered_map>& Bridge::get_irc_clients() +{ + return this->irc_clients; +} -- 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/bridge/bridge.cpp | 62 +++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index a1ba71a..55f4c51 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -14,7 +14,7 @@ using namespace std::string_literals; static const char* action_prefix = "\01ACTION "; -Bridge::Bridge(const std::string& user_jid, BiboumiComponent* xmpp, std::shared_ptr poller): +Bridge::Bridge(const std::string& user_jid, BiboumiComponent& xmpp, std::shared_ptr poller): user_jid(user_jid), xmpp(xmpp), poller(poller) @@ -105,7 +105,7 @@ IrcClient* Bridge::make_irc_client(const std::string& hostname, const std::strin std::make_shared(this->poller, hostname, nickname, username, realname, jid.domain, - this)); + *this)); std::shared_ptr irc = this->irc_clients.at(hostname); return irc.get(); } @@ -172,7 +172,7 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) { if (iid.get_server().empty()) { - this->xmpp->send_stanza_error("message", this->user_jid, std::to_string(iid), "", + this->xmpp.send_stanza_error("message", this->user_jid, std::to_string(iid), "", "cancel", "remote-server-not-found", std::to_string(iid) + " is not a valid channel name. " "A correct room jid is of the form: #%", @@ -205,7 +205,7 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) irc->send_channel_message(iid.get_local(), action_prefix + line.substr(4) + "\01"); else irc->send_channel_message(iid.get_local(), line); - this->xmpp->send_muc_message(std::to_string(iid), irc->get_own_nick(), + this->xmpp.send_muc_message(std::to_string(iid), irc->get_own_nick(), this->make_xmpp_body(line), this->user_jid); } } @@ -278,7 +278,7 @@ void Bridge::send_private_message(const Iid& iid, const std::string& body, const { if (iid.get_local().empty() || iid.get_server().empty()) { - this->xmpp->send_stanza_error("message", this->user_jid, std::to_string(iid), "", + this->xmpp.send_stanza_error("message", this->user_jid, std::to_string(iid), "", "cancel", "remote-server-not-found", std::to_string(iid) + " is not a valid channel name. " "A correct room jid is of the form: #%", @@ -336,7 +336,7 @@ void Bridge::send_irc_channel_list_request(const Iid& iid, const std::string& iq std::string text; if (message.arguments.size() >= 2) text = message.arguments[1]; - this->xmpp->send_stanza_error("iq", to_jid, std::to_string(iid), iq_id, + this->xmpp.send_stanza_error("iq", to_jid, std::to_string(iid), iq_id, "wait", "service-unavailable", text, false); return true; } @@ -349,7 +349,7 @@ void Bridge::send_irc_channel_list_request(const Iid& iid, const std::string& iq } else if (message.command == "323" || message.command == "RPL_LISTEND") { // Send the iq response with the content of the list - this->xmpp->send_iq_room_list_result(iq_id, to_jid, std::to_string(iid), list); + this->xmpp.send_iq_room_list_result(iq_id, to_jid, std::to_string(iid), list); return true; } return false; @@ -374,7 +374,7 @@ void Bridge::send_irc_kick(const Iid& iid, const std::string& target, const std: const std::string chan_name_later = utils::tolower(message.arguments[0]); if (target_later != target || chan_name_later != iid.get_local()) return false; - this->xmpp->send_iq_result(iq_id, to_jid, std::to_string(iid)); + this->xmpp.send_iq_result(iq_id, to_jid, std::to_string(iid)); } else if (message.command == "401" && message.arguments.size() >= 2) { @@ -384,7 +384,7 @@ void Bridge::send_irc_kick(const Iid& iid, const std::string& target, const std: 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, std::to_string(iid), iq_id, "cancel", "item-not-found", + this->xmpp.send_stanza_error("iq", to_jid, std::to_string(iid), iq_id, "cancel", "item-not-found", error_message, false); } else if (message.command == "482" && message.arguments.size() >= 2) @@ -395,7 +395,7 @@ void Bridge::send_irc_kick(const Iid& iid, const std::string& target, const std: std::string error_message = "You're not channel operator"; if (message.arguments.size() >= 3) error_message = message.arguments[2]; - this->xmpp->send_stanza_error("iq", to_jid, std::to_string(iid), iq_id, "cancel", "not-allowed", + this->xmpp.send_stanza_error("iq", to_jid, std::to_string(iid), iq_id, "cancel", "not-allowed", error_message, false); } return true; @@ -441,7 +441,7 @@ void Bridge::send_irc_user_ping_request(const std::string& irc_hostname, const s if (id != iq_id) return false; Jid jid(from_jid); - this->xmpp->send_iq_result(iq_id, to_jid, jid.local); + this->xmpp.send_iq_result(iq_id, to_jid, jid.local); return true; } if (message.command == "401" && message.arguments[1] == nick) @@ -449,7 +449,7 @@ void Bridge::send_irc_user_ping_request(const std::string& irc_hostname, const s 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", "service-unavailable", + this->xmpp.send_stanza_error("iq", to_jid, from_jid, iq_id, "cancel", "service-unavailable", error_message, true); return true; } @@ -467,13 +467,13 @@ void Bridge::send_irc_participant_ping_request(const Iid& iid, const std::string IrcChannel* chan = irc->get_channel(iid.get_local()); if (!chan->joined) { - this->xmpp->send_stanza_error("iq", to_jid, from_jid, iq_id, "cancel", "not-allowed", + this->xmpp.send_stanza_error("iq", to_jid, from_jid, iq_id, "cancel", "not-allowed", "", true); return; } if (chan->get_self()->nick != nick && !chan->find_user(nick)) { - this->xmpp->send_stanza_error("iq", to_jid, from_jid, iq_id, "cancel", "item-not-found", + this->xmpp.send_stanza_error("iq", to_jid, from_jid, iq_id, "cancel", "item-not-found", "Recipient not in room", true); return; } @@ -487,9 +487,9 @@ void Bridge::on_gateway_ping(const std::string& irc_hostname, const std::string& { Jid jid(from_jid); if (irc_hostname.empty() || this->find_irc_client(irc_hostname)) - this->xmpp->send_iq_result(iq_id, to_jid, jid.local); + this->xmpp.send_iq_result(iq_id, to_jid, jid.local); else - this->xmpp->send_stanza_error("iq", to_jid, from_jid, iq_id, "cancel", "service-unavailable", + this->xmpp.send_stanza_error("iq", to_jid, from_jid, iq_id, "cancel", "service-unavailable", "", true); } @@ -511,7 +511,7 @@ void Bridge::send_irc_version_request(const std::string& irc_hostname, const std { // 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); + this->xmpp.send_version(iq_id, to_jid, from_jid, version); return true; } if (message.command == "401" && message.arguments.size() >= 2 @@ -520,7 +520,7 @@ void Bridge::send_irc_version_request(const std::string& irc_hostname, const std 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", + this->xmpp.send_stanza_error("iq", to_jid, from_jid, iq_id, "cancel", "item-not-found", error_message, true); return true; } @@ -532,7 +532,7 @@ void Bridge::send_irc_version_request(const std::string& irc_hostname, const std void Bridge::send_message(const Iid& iid, const std::string& nick, const std::string& body, const bool muc) { if (muc) - this->xmpp->send_muc_message(std::to_string(iid), nick, + this->xmpp.send_muc_message(std::to_string(iid), nick, this->make_xmpp_body(body), this->user_jid); else { @@ -544,7 +544,7 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st target = it->second; fulljid = true; } - this->xmpp->send_message(target, this->make_xmpp_body(body), + this->xmpp.send_message(target, this->make_xmpp_body(body), this->user_jid, "chat", fulljid); } } @@ -553,12 +553,12 @@ void Bridge::send_presence_error(const Iid& iid, const std::string& nick, const std::string& type, const std::string& condition, const std::string& error_code, const std::string& text) { - this->xmpp->send_presence_error(std::to_string(iid), nick, this->user_jid, type, condition, error_code, text); + this->xmpp.send_presence_error(std::to_string(iid), nick, this->user_jid, type, condition, error_code, text); } void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self) { - this->xmpp->send_muc_leave(std::to_string(iid), std::move(nick), this->make_xmpp_body(message), this->user_jid, self); + this->xmpp.send_muc_leave(std::to_string(iid), std::move(nick), this->make_xmpp_body(message), this->user_jid, self); IrcClient* irc = this->find_irc_client(iid.get_server()); if (irc && irc->number_of_joined_channels() == 0) irc->send_quit_command(""); @@ -574,7 +574,7 @@ void Bridge::send_nick_change(Iid&& iid, std::string role; std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(user_mode); - this->xmpp->send_nick_change(std::to_string(iid), + this->xmpp.send_nick_change(std::to_string(iid), old_nick, new_nick, affiliation, role, this->user_jid, self); } @@ -590,7 +590,7 @@ void Bridge::send_xmpp_message(const std::string& from, const std::string& autho } else body = msg; - this->xmpp->send_message(from, this->make_xmpp_body(body), this->user_jid, "chat"); + this->xmpp.send_message(from, this->make_xmpp_body(body), this->user_jid, "chat"); } void Bridge::send_user_join(const std::string& hostname, @@ -603,13 +603,13 @@ void Bridge::send_user_join(const std::string& hostname, std::string role; std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(user_mode); - this->xmpp->send_user_join(chan_name + utils::empty_if_fixed_server("%" + hostname), user->nick, user->host, + this->xmpp.send_user_join(chan_name + utils::empty_if_fixed_server("%" + hostname), user->nick, user->host, affiliation, role, this->user_jid, self); } void Bridge::send_topic(const std::string& hostname, const std::string& chan_name, const std::string& topic) { - this->xmpp->send_topic(chan_name + utils::empty_if_fixed_server("%" + hostname), this->make_xmpp_body(topic), this->user_jid); + this->xmpp.send_topic(chan_name + utils::empty_if_fixed_server("%" + hostname), this->make_xmpp_body(topic), this->user_jid); } std::string Bridge::get_own_nick(const Iid& iid) @@ -627,12 +627,12 @@ size_t Bridge::active_clients() const void Bridge::kick_muc_user(Iid&& iid, const std::string& target, const std::string& reason, const std::string& author) { - this->xmpp->kick_user(std::to_string(iid), target, reason, author, this->user_jid); + this->xmpp.kick_user(std::to_string(iid), target, reason, author, this->user_jid); } void Bridge::send_nickname_conflict_error(const Iid& iid, const std::string& nickname) { - this->xmpp->send_presence_error(std::to_string(iid), nickname, this->user_jid, "cancel", "conflict", "409", ""); + this->xmpp.send_presence_error(std::to_string(iid), nickname, this->user_jid, "cancel", "conflict", "409", ""); } void Bridge::send_affiliation_role_change(const Iid& iid, const std::string& target, const char mode) @@ -641,12 +641,12 @@ void Bridge::send_affiliation_role_change(const Iid& iid, const std::string& tar std::string affiliation; std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(mode); - this->xmpp->send_affiliation_role_change(std::to_string(iid), target, affiliation, role, this->user_jid); + this->xmpp.send_affiliation_role_change(std::to_string(iid), target, affiliation, role, this->user_jid); } void Bridge::send_iq_version_request(const std::string& nick, const std::string& hostname) { - this->xmpp->send_iq_version_request(nick + "!" + utils::empty_if_fixed_server(hostname), this->user_jid); + this->xmpp.send_iq_version_request(nick + "!" + utils::empty_if_fixed_server(hostname), this->user_jid); } void Bridge::send_xmpp_ping_request(const std::string& nick, const std::string& hostname, @@ -655,7 +655,7 @@ void Bridge::send_xmpp_ping_request(const std::string& nick, const std::string& // Use revstr because the forwarded ping to target XMPP user must not be // the same that the request iq, but we also need to get it back easily // (revstr again) - this->xmpp->send_ping_request(nick + "!" + utils::empty_if_fixed_server(hostname), this->user_jid, utils::revstr(id)); + this->xmpp.send_ping_request(nick + "!" + utils::empty_if_fixed_server(hostname), this->user_jid, utils::revstr(id)); } void Bridge::set_preferred_from_jid(const std::string& nick, const std::string& full_jid) -- cgit v1.2.3 From 79cdf170d2ab6c5378cfbf61d5c8888a4c666190 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 28 Dec 2015 21:25:48 +0100 Subject: Use the configured encoding value when decoding received messages --- src/bridge/bridge.cpp | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 55f4c51..4c97a91 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -9,11 +9,35 @@ #include #include #include +#include using namespace std::string_literals; static const char* action_prefix = "\01ACTION "; + +static std::string out_encoding_for(const Bridge& bridge, const Iid& iid) +{ +#ifdef USE_DATABASE + const auto jid = bridge.get_bare_jid(); + auto options = Database::get_irc_channel_options_with_server_default(jid, iid.get_server(), iid.get_local()); + return options.encodingOut.value(); +#else + return {"ISO-8859-1"}; +#endif +} + +static std::string in_encoding_for(const Bridge& bridge, const Iid& iid) +{ +#ifdef USE_DATABASE + const auto jid = bridge.get_bare_jid(); + auto options = Database::get_irc_channel_options_with_server_default(jid, iid.get_server(), iid.get_local()); + return options.encodingIn.value(); +#else + return {"ISO-8859-1"}; +#endif +} + Bridge::Bridge(const std::string& user_jid, BiboumiComponent& xmpp, std::shared_ptr poller): user_jid(user_jid), xmpp(xmpp), @@ -75,13 +99,13 @@ std::string Bridge::get_bare_jid() const return jid.local + "@" + jid.domain; } -Xmpp::body Bridge::make_xmpp_body(const std::string& str) +Xmpp::body Bridge::make_xmpp_body(const std::string& str, const std::string& encoding) { std::string res; if (utils::is_valid_utf8(str.c_str())) res = str; else - res = utils::convert_to_utf8(str, "ISO-8859-1"); + res = utils::convert_to_utf8(str, encoding.data()); return irc_format_to_xhtmlim(res); } @@ -531,9 +555,10 @@ void Bridge::send_irc_version_request(const std::string& irc_hostname, const std void Bridge::send_message(const Iid& iid, const std::string& nick, const std::string& body, const bool muc) { + const auto encoding = in_encoding_for(*this, iid); if (muc) this->xmpp.send_muc_message(std::to_string(iid), nick, - this->make_xmpp_body(body), this->user_jid); + this->make_xmpp_body(body, encoding), this->user_jid); else { std::string target = std::to_string(iid); @@ -544,7 +569,7 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st target = it->second; fulljid = true; } - this->xmpp.send_message(target, this->make_xmpp_body(body), + this->xmpp.send_message(target, this->make_xmpp_body(body, encoding), this->user_jid, "chat", fulljid); } } @@ -590,7 +615,9 @@ void Bridge::send_xmpp_message(const std::string& from, const std::string& autho } else body = msg; - this->xmpp.send_message(from, this->make_xmpp_body(body), this->user_jid, "chat"); + + const auto encoding = in_encoding_for(*this, {from}); + this->xmpp.send_message(from, this->make_xmpp_body(body, encoding), this->user_jid, "chat"); } void Bridge::send_user_join(const std::string& hostname, @@ -609,7 +636,8 @@ void Bridge::send_user_join(const std::string& hostname, void Bridge::send_topic(const std::string& hostname, const std::string& chan_name, const std::string& topic) { - this->xmpp.send_topic(chan_name + utils::empty_if_fixed_server("%" + hostname), this->make_xmpp_body(topic), this->user_jid); + const auto encoding = in_encoding_for(*this, {chan_name + '%' + hostname}); + this->xmpp.send_topic(chan_name + utils::empty_if_fixed_server("%" + hostname), this->make_xmpp_body(topic, encoding), this->user_jid); } std::string Bridge::get_own_nick(const Iid& iid) -- cgit v1.2.3 From 04d28f968b227067e77e365d317fc251d3c965f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 19 Apr 2016 02:43:26 +0200 Subject: Forward the topic authors, handle the author from 333 messages fix #2 --- src/bridge/bridge.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 4c97a91..2815da9 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -634,10 +634,11 @@ void Bridge::send_user_join(const std::string& hostname, affiliation, role, this->user_jid, self); } -void Bridge::send_topic(const std::string& hostname, const std::string& chan_name, const std::string& topic) +void Bridge::send_topic(const std::string& hostname, const std::string& chan_name, const std::string& topic, const std::string& who) { const auto encoding = in_encoding_for(*this, {chan_name + '%' + hostname}); - this->xmpp.send_topic(chan_name + utils::empty_if_fixed_server("%" + hostname), this->make_xmpp_body(topic, encoding), this->user_jid); + this->xmpp.send_topic(chan_name + utils::empty_if_fixed_server( + "%" + hostname), this->make_xmpp_body(topic, encoding), this->user_jid, who); } std::string Bridge::get_own_nick(const Iid& iid) -- cgit v1.2.3 From af42073830087d97385e507f27f601e8769541b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 4 May 2016 14:16:40 +0200 Subject: Style fix Move all constructors at the top of classes --- src/bridge/bridge.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 2815da9..6008dfc 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -45,10 +45,6 @@ Bridge::Bridge(const std::string& user_jid, BiboumiComponent& xmpp, std::shared_ { } -Bridge::~Bridge() -{ -} - /** * Return the role and affiliation, corresponding to the given irc mode */ static std::tuple get_role_affiliation_from_irc_mode(const char mode) -- 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/bridge/bridge.cpp | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 6008dfc..484c860 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -46,11 +46,12 @@ Bridge::Bridge(const std::string& user_jid, BiboumiComponent& xmpp, std::shared_ } /** - * Return the role and affiliation, corresponding to the given irc mode */ + * Return the role and affiliation, corresponding to the given irc mode + */ static std::tuple get_role_affiliation_from_irc_mode(const char mode) { - if (mode == 'a' || mode == 'q') - return std::make_tuple("moderator", "owner"); + if (mode == 'a' || mode == 'q'){ + return std::make_tuple("moderator", "owner");} else if (mode == 'o') return std::make_tuple("moderator", "admin"); else if (mode == 'h') @@ -720,3 +721,32 @@ std::unordered_map>& Bridge::get_irc_cli { return this->irc_clients; } + +void Bridge::add_resource_to_chan(const std::string& channel, const std::string& resource) +{ + auto it = this->resources_in_chan.find(channel); + if (it == this->resources_in_chan.end()) + this->resources_in_chan[channel] = {resource}; + else + it->second.insert(resource); +} + +void Bridge::remove_resource_from_chan(const std::string& channel, const std::string& resource) +{ + auto it = this->resources_in_chan.find(channel); + if (it != this->resources_in_chan.end()) + { + it->second.erase(resource); + if (it->second.empty()) + this->resources_in_chan.erase(it); + } +} + +bool Bridge::is_resource_in_chan(const std::string& channel, const std::string& resource) const +{ + auto it = this->resources_in_chan.find(channel); + if (it != this->resources_in_chan.end()) + if (it->second.count(resource) == 1) + return true; + return false; +} -- 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/bridge/bridge.cpp | 128 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 100 insertions(+), 28 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 484c860..bfd5d68 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -156,9 +156,15 @@ IrcClient* Bridge::find_irc_client(const std::string& hostname) } } -bool Bridge::join_irc_channel(const Iid& iid, const std::string& nickname, const std::string& password) -{ - IrcClient* irc = this->make_irc_client(iid.get_server(), nickname); +bool Bridge::join_irc_channel(const Iid& iid, const std::string& nickname, const std::string& password, + const std::string& resource) +{ + const auto hostname = iid.get_server(); + IrcClient* irc = this->make_irc_client(hostname, nickname); + this->add_resource_to_server(hostname, resource); + auto res_in_chan = this->is_resource_in_chan(ChannelKey{iid.get_local(), hostname}, resource); + if (!res_in_chan) + this->add_resource_to_chan(ChannelKey{iid.get_local(), hostname}, resource); if (iid.get_local().empty()) { // Join the dummy channel if (irc->is_welcomed()) @@ -185,6 +191,8 @@ bool Bridge::join_irc_channel(const Iid& iid, const std::string& nickname, const { irc->send_join_command(iid.get_local(), password); return true; + } else if (!res_in_chan) { + this->generate_channel_join_for_resource(iid, resource); } return false; } @@ -193,11 +201,12 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) { if (iid.get_server().empty()) { - this->xmpp.send_stanza_error("message", this->user_jid, std::to_string(iid), "", - "cancel", "remote-server-not-found", - std::to_string(iid) + " is not a valid channel name. " - "A correct room jid is of the form: #%", - false); + for (const auto& resource: this->resources_in_chan[ChannelKey{iid.get_local(), iid.get_server()}]) + this->xmpp.send_stanza_error("message", this->user_jid + "/" + resource, std::to_string(iid), "", + "cancel", "remote-server-not-found", + std::to_string(iid) + " is not a valid channel name. " + "A correct room jid is of the form: #%", + false); return; } IrcClient* irc = this->get_irc_client(iid.get_server()); @@ -226,8 +235,9 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) irc->send_channel_message(iid.get_local(), action_prefix + line.substr(4) + "\01"); else irc->send_channel_message(iid.get_local(), line); - this->xmpp.send_muc_message(std::to_string(iid), irc->get_own_nick(), - this->make_xmpp_body(line), this->user_jid); + for (const auto& resource: this->resources_in_chan[ChannelKey{iid.get_local(), iid.get_server()}]) + this->xmpp.send_muc_message(std::to_string(iid), irc->get_own_nick(), + this->make_xmpp_body(line), this->user_jid + "/" + resource); } } @@ -554,8 +564,13 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st { const auto encoding = in_encoding_for(*this, iid); if (muc) - this->xmpp.send_muc_message(std::to_string(iid), nick, - this->make_xmpp_body(body, encoding), this->user_jid); + { + for (const auto& resource: this->resources_in_chan[ChannelKey{iid.get_local(), iid.get_server()}]) + { + this->xmpp.send_muc_message(std::to_string(iid), nick, + this->make_xmpp_body(body, encoding), this->user_jid + "/" + resource); + } + } else { std::string target = std::to_string(iid); @@ -566,8 +581,11 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st target = it->second; fulljid = true; } - this->xmpp.send_message(target, this->make_xmpp_body(body, encoding), - this->user_jid, "chat", fulljid); + for (const auto& resource: this->resources_in_chan[ChannelKey{iid.get_local(), iid.get_server()}]) + { + this->xmpp.send_message(target, this->make_xmpp_body(body, encoding), + this->user_jid + "/" + resource, "chat", fulljid); + } } } @@ -580,7 +598,8 @@ void Bridge::send_presence_error(const Iid& iid, const std::string& nick, void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self) { - this->xmpp.send_muc_leave(std::to_string(iid), std::move(nick), this->make_xmpp_body(message), this->user_jid, self); + for (const auto& resource: this->resources_in_chan[ChannelKey{iid.get_local(), iid.get_server()}]) + this->xmpp.send_muc_leave(std::to_string(iid), std::move(nick), this->make_xmpp_body(message), this->user_jid + "/" + resource, self); IrcClient* irc = this->find_irc_client(iid.get_server()); if (irc && irc->number_of_joined_channels() == 0) irc->send_quit_command(""); @@ -596,8 +615,9 @@ void Bridge::send_nick_change(Iid&& iid, std::string role; std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(user_mode); - this->xmpp.send_nick_change(std::to_string(iid), - old_nick, new_nick, affiliation, role, this->user_jid, self); + for (const auto& resource: this->resources_in_chan[ChannelKey{iid.get_local(), iid.get_server()}]) + this->xmpp.send_nick_change(std::to_string(iid), + old_nick, new_nick, affiliation, role, this->user_jid + "/" + resource, self); } void Bridge::send_xmpp_message(const std::string& from, const std::string& author, const std::string& msg) @@ -614,7 +634,10 @@ void Bridge::send_xmpp_message(const std::string& from, const std::string& autho body = msg; const auto encoding = in_encoding_for(*this, {from}); - this->xmpp.send_message(from, this->make_xmpp_body(body, encoding), this->user_jid, "chat"); + for (const auto& resource: this->resources_in_server[from]) + { + this->xmpp.send_message(from, this->make_xmpp_body(body, encoding), this->user_jid + "/" + resource, "chat"); + } } void Bridge::send_user_join(const std::string& hostname, @@ -627,15 +650,21 @@ void Bridge::send_user_join(const std::string& hostname, std::string role; std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(user_mode); - this->xmpp.send_user_join(chan_name + utils::empty_if_fixed_server("%" + hostname), user->nick, user->host, - affiliation, role, this->user_jid, self); + for (const auto& resource: this->resources_in_chan[ChannelKey{chan_name, hostname}]) + { + this->xmpp.send_user_join(chan_name + utils::empty_if_fixed_server("%" + hostname), user->nick, user->host, + affiliation, role, this->user_jid + "/" + resource, self); + } } void Bridge::send_topic(const std::string& hostname, const std::string& chan_name, const std::string& topic, const std::string& who) { const auto encoding = in_encoding_for(*this, {chan_name + '%' + hostname}); - this->xmpp.send_topic(chan_name + utils::empty_if_fixed_server( - "%" + hostname), this->make_xmpp_body(topic, encoding), this->user_jid, who); + for (const auto& resource: this->resources_in_chan[ChannelKey{chan_name, hostname}]) + { + this->xmpp.send_topic(chan_name + utils::empty_if_fixed_server( + "%" + hostname), this->make_xmpp_body(topic, encoding), this->user_jid + "/" + resource, who); + } } std::string Bridge::get_own_nick(const Iid& iid) @@ -653,12 +682,14 @@ size_t Bridge::active_clients() const void Bridge::kick_muc_user(Iid&& iid, const std::string& target, const std::string& reason, const std::string& author) { - this->xmpp.kick_user(std::to_string(iid), target, reason, author, this->user_jid); + for (const auto& resource: this->resources_in_chan[ChannelKey{iid.get_local(), iid.get_server()}]) + this->xmpp.kick_user(std::to_string(iid), target, reason, author, this->user_jid + "/" + resource); } void Bridge::send_nickname_conflict_error(const Iid& iid, const std::string& nickname) { - this->xmpp.send_presence_error(std::to_string(iid), nickname, this->user_jid, "cancel", "conflict", "409", ""); + for (const auto& resource: this->resources_in_chan[ChannelKey{iid.get_local(), iid.get_server()}]) + this->xmpp.send_presence_error(std::to_string(iid), nickname, this->user_jid + "/" + resource, "cancel", "conflict", "409", ""); } void Bridge::send_affiliation_role_change(const Iid& iid, const std::string& target, const char mode) @@ -667,7 +698,8 @@ void Bridge::send_affiliation_role_change(const Iid& iid, const std::string& tar std::string affiliation; std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(mode); - this->xmpp.send_affiliation_role_change(std::to_string(iid), target, affiliation, role, this->user_jid); + for (const auto& resource: this->resources_in_chan[ChannelKey{iid.get_local(), iid.get_server()}]) + this->xmpp.send_affiliation_role_change(std::to_string(iid), target, affiliation, role, this->user_jid + "/" + resource); } void Bridge::send_iq_version_request(const std::string& nick, const std::string& hostname) @@ -722,7 +754,7 @@ std::unordered_map>& Bridge::get_irc_cli return this->irc_clients; } -void Bridge::add_resource_to_chan(const std::string& channel, const std::string& resource) +void Bridge::add_resource_to_chan(const Bridge::ChannelKey& channel, const std::string& resource) { auto it = this->resources_in_chan.find(channel); if (it == this->resources_in_chan.end()) @@ -731,7 +763,7 @@ void Bridge::add_resource_to_chan(const std::string& channel, const std::string& it->second.insert(resource); } -void Bridge::remove_resource_from_chan(const std::string& channel, const std::string& resource) +void Bridge::remove_resource_from_chan(const Bridge::ChannelKey& channel, const std::string& resource) { auto it = this->resources_in_chan.find(channel); if (it != this->resources_in_chan.end()) @@ -742,7 +774,7 @@ void Bridge::remove_resource_from_chan(const std::string& channel, const std::st } } -bool Bridge::is_resource_in_chan(const std::string& channel, const std::string& resource) const +bool Bridge::is_resource_in_chan(const Bridge::ChannelKey& channel, const std::string& resource) const { auto it = this->resources_in_chan.find(channel); if (it != this->resources_in_chan.end()) @@ -750,3 +782,43 @@ bool Bridge::is_resource_in_chan(const std::string& channel, const std::string& return true; return false; } + +void Bridge::add_resource_to_server(const Bridge::IrcHostname& irc_hostname, const std::string& resource) +{ + auto it = this->resources_in_server.find(irc_hostname); + if (it == this->resources_in_server.end()) + this->resources_in_server[irc_hostname] = {resource}; + else + it->second.insert(resource); +} + +void Bridge::remove_resource_from_server(const Bridge::IrcHostname& irc_hostname, const std::string& resource) +{ + auto it = this->resources_in_server.find(irc_hostname); + if (it != this->resources_in_server.end()) + { + it->second.erase(resource); + if (it->second.empty()) + this->resources_in_server.erase(it); + } +} + +bool Bridge::is_resource_in_server(const Bridge::IrcHostname& irc_hostname, const std::string& resource) const +{ + auto it = this->resources_in_server.find(irc_hostname); + if (it != this->resources_in_server.end()) + if (it->second.count(resource) == 1) + return true; + return false; +} + +void Bridge::generate_channel_join_for_resource(const Iid& iid, const std::string& resource) +{ + IrcClient* irc = this->get_irc_client(iid.get_server()); + IrcChannel* channel = irc->get_channel(iid.get_local()); + // Send the occupant list + for (const auto& user: channel->get_users()) + { + + } +} -- 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/bridge/bridge.cpp | 123 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 89 insertions(+), 34 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index bfd5d68..95ca68e 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -201,7 +201,7 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) { if (iid.get_server().empty()) { - for (const auto& resource: this->resources_in_chan[ChannelKey{iid.get_local(), iid.get_server()}]) + for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) this->xmpp.send_stanza_error("message", this->user_jid + "/" + resource, std::to_string(iid), "", "cancel", "remote-server-not-found", std::to_string(iid) + " is not a valid channel name. " @@ -235,7 +235,7 @@ void Bridge::send_channel_message(const Iid& iid, const std::string& body) irc->send_channel_message(iid.get_local(), action_prefix + line.substr(4) + "\01"); else irc->send_channel_message(iid.get_local(), line); - for (const auto& resource: this->resources_in_chan[ChannelKey{iid.get_local(), iid.get_server()}]) + for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) this->xmpp.send_muc_message(std::to_string(iid), irc->get_own_nick(), this->make_xmpp_body(line), this->user_jid + "/" + resource); } @@ -335,11 +335,29 @@ void Bridge::send_raw_message(const std::string& hostname, const std::string& bo irc->send_raw(body); } -void Bridge::leave_irc_channel(Iid&& iid, std::string&& status_message) +void Bridge::leave_irc_channel(Iid&& iid, std::string&& status_message, const std::string& resource) { IrcClient* irc = this->get_irc_client(iid.get_server()); - irc->send_part_command(iid.get_local(), status_message); -} + const auto key = iid.to_tuple(); + if (!this->is_resource_in_chan(key, resource)) + return ; + + const auto resources = this->number_of_resources_in_chan(key); + if (resources == 1) + irc->send_part_command(iid.get_local(), status_message); + else + { + IrcChannel* chan = irc->get_channel(iid.get_local()); + if (chan) + { + auto nick = chan->get_self()->nick; + this->remove_resource_from_chan(key, resource); + this->send_muc_leave(std::move(iid), std::move(nick), + "Biboumi note: "s + std::to_string(resources - 1) + " resources are still in this channel.", + true, resource); + } + } + } void Bridge::send_irc_nick_change(const Iid& iid, const std::string& new_nick) { @@ -565,7 +583,7 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st const auto encoding = in_encoding_for(*this, iid); if (muc) { - for (const auto& resource: this->resources_in_chan[ChannelKey{iid.get_local(), iid.get_server()}]) + for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) { this->xmpp.send_muc_message(std::to_string(iid), nick, this->make_xmpp_body(body, encoding), this->user_jid + "/" + resource); @@ -574,17 +592,19 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st else { std::string target = std::to_string(iid); - bool fulljid = false; - auto it = this->preferred_user_from.find(iid.get_local()); + const auto it = this->preferred_user_from.find(iid.get_local()); if (it != this->preferred_user_from.end()) { - target = it->second; - fulljid = true; + const auto chan_name = Iid(Jid(it->second).local).get_local(); + for (const auto& resource: this->resources_in_chan[ChannelKey{chan_name, iid.get_server()}]) + this->xmpp.send_message(it->second, this->make_xmpp_body(body, encoding), + this->user_jid + "/" + resource, "chat", true); } - for (const auto& resource: this->resources_in_chan[ChannelKey{iid.get_local(), iid.get_server()}]) + else { - this->xmpp.send_message(target, this->make_xmpp_body(body, encoding), - this->user_jid + "/" + resource, "chat", fulljid); + for (const auto& resource: this->resources_in_server[iid.get_server()]) + this->xmpp.send_message(std::to_string(iid), this->make_xmpp_body(body, encoding), + this->user_jid + "/" + resource, "chat", false); } } } @@ -596,10 +616,15 @@ void Bridge::send_presence_error(const Iid& iid, const std::string& nick, this->xmpp.send_presence_error(std::to_string(iid), nick, this->user_jid, type, condition, error_code, text); } -void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self) +void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self, const std::string& resource) { - for (const auto& resource: this->resources_in_chan[ChannelKey{iid.get_local(), iid.get_server()}]) - this->xmpp.send_muc_leave(std::to_string(iid), std::move(nick), this->make_xmpp_body(message), this->user_jid + "/" + resource, self); + if (!resource.empty()) + this->xmpp.send_muc_leave(std::to_string(iid), std::move(nick), this->make_xmpp_body(message), this->user_jid + "/" + resource, + self); + else + for (const auto& res: this->resources_in_chan[iid.to_tuple()]) + this->xmpp.send_muc_leave(std::to_string(iid), std::move(nick), this->make_xmpp_body(message), this->user_jid + "/" + res, + self); IrcClient* irc = this->find_irc_client(iid.get_server()); if (irc && irc->number_of_joined_channels() == 0) irc->send_quit_command(""); @@ -615,7 +640,7 @@ void Bridge::send_nick_change(Iid&& iid, std::string role; std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(user_mode); - for (const auto& resource: this->resources_in_chan[ChannelKey{iid.get_local(), iid.get_server()}]) + for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) this->xmpp.send_nick_change(std::to_string(iid), old_nick, new_nick, affiliation, role, this->user_jid + "/" + resource, self); } @@ -640,33 +665,43 @@ void Bridge::send_xmpp_message(const std::string& from, const std::string& autho } } -void Bridge::send_user_join(const std::string& hostname, - const std::string& chan_name, - const IrcUser* user, - const char user_mode, - const bool self) +void Bridge::send_user_join(const std::string& hostname, const std::string& chan_name, + const IrcUser* user, const char user_mode, const bool self) +{ + for (const auto& resource: this->resources_in_chan[ChannelKey{chan_name, hostname}]) + this->send_user_join(hostname, chan_name, user, user_mode, self, resource); +} + +void Bridge::send_user_join(const std::string& hostname, const std::string& chan_name, + const IrcUser* user, const char user_mode, + const bool self, const std::string& resource) { std::string affiliation; std::string role; std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(user_mode); - for (const auto& resource: this->resources_in_chan[ChannelKey{chan_name, hostname}]) - { - this->xmpp.send_user_join(chan_name + utils::empty_if_fixed_server("%" + hostname), user->nick, user->host, - affiliation, role, this->user_jid + "/" + resource, self); - } + this->xmpp.send_user_join(chan_name + utils::empty_if_fixed_server("%" + hostname), user->nick, user->host, + affiliation, role, this->user_jid + "/" + resource, self); } void Bridge::send_topic(const std::string& hostname, const std::string& chan_name, const std::string& topic, const std::string& who) { - const auto encoding = in_encoding_for(*this, {chan_name + '%' + hostname}); for (const auto& resource: this->resources_in_chan[ChannelKey{chan_name, hostname}]) { - this->xmpp.send_topic(chan_name + utils::empty_if_fixed_server( - "%" + hostname), this->make_xmpp_body(topic, encoding), this->user_jid + "/" + resource, who); + this->send_topic(hostname, chan_name, topic, who, resource); } } +void Bridge::send_topic(const std::string& hostname, const std::string& chan_name, + const std::string& topic, const std::string& who, + const std::string& resource) +{ + const auto encoding = in_encoding_for(*this, {chan_name + '%' + hostname}); + this->xmpp.send_topic(chan_name + utils::empty_if_fixed_server( + "%" + hostname), this->make_xmpp_body(topic, encoding), this->user_jid + "/" + resource, who); + +} + std::string Bridge::get_own_nick(const Iid& iid) { IrcClient* irc = this->find_irc_client(iid.get_server()); @@ -682,13 +717,13 @@ size_t Bridge::active_clients() const void Bridge::kick_muc_user(Iid&& iid, const std::string& target, const std::string& reason, const std::string& author) { - for (const auto& resource: this->resources_in_chan[ChannelKey{iid.get_local(), iid.get_server()}]) + for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) this->xmpp.kick_user(std::to_string(iid), target, reason, author, this->user_jid + "/" + resource); } void Bridge::send_nickname_conflict_error(const Iid& iid, const std::string& nickname) { - for (const auto& resource: this->resources_in_chan[ChannelKey{iid.get_local(), iid.get_server()}]) + for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) this->xmpp.send_presence_error(std::to_string(iid), nickname, this->user_jid + "/" + resource, "cancel", "conflict", "409", ""); } @@ -698,7 +733,7 @@ void Bridge::send_affiliation_role_change(const Iid& iid, const std::string& tar std::string affiliation; std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(mode); - for (const auto& resource: this->resources_in_chan[ChannelKey{iid.get_local(), iid.get_server()}]) + for (const auto& resource: this->resources_in_chan[iid.to_tuple()]) this->xmpp.send_affiliation_role_change(std::to_string(iid), target, affiliation, role, this->user_jid + "/" + resource); } @@ -812,13 +847,33 @@ bool Bridge::is_resource_in_server(const Bridge::IrcHostname& irc_hostname, cons return false; } +std::size_t Bridge::number_of_resources_in_chan(const Bridge::ChannelKey& channel_key) const +{ + auto it = this->resources_in_chan.find(channel_key); + if (it == this->resources_in_chan.end()) + return 0; + return it->second.size(); +} + void Bridge::generate_channel_join_for_resource(const Iid& iid, const std::string& resource) { IrcClient* irc = this->get_irc_client(iid.get_server()); IrcChannel* channel = irc->get_channel(iid.get_local()); + const auto self = channel->get_self(); + // Send the occupant list for (const auto& user: channel->get_users()) { - + if (user->nick != self->nick) + { + log_debug(user->nick); + this->send_user_join(iid.get_server(), iid.get_local(), + user.get(), user->get_most_significant_mode(irc->get_sorted_user_modes()), + false, resource); + } } + this->send_user_join(iid.get_server(), iid.get_local(), + self, self->get_most_significant_mode(irc->get_sorted_user_modes()), + true, resource); + this->send_topic(iid.get_server(), iid.get_local(), channel->topic, channel->topic_author, resource); } -- cgit v1.2.3 From 272c0e4995f2fe94fb2366c15453fdada341861a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Fri, 10 Jun 2016 10:00:48 +0200 Subject: Reset the preferred private JID when all resources leave a room MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For example if we are talking in private with nick Joe from room #foo, and then we leave that room, we start receiving Joe’s message from the server-wide JID e2e tests included!!! --- src/bridge/bridge.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 95ca68e..3a7a147 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -344,7 +344,12 @@ void Bridge::leave_irc_channel(Iid&& iid, std::string&& status_message, const st const auto resources = this->number_of_resources_in_chan(key); if (resources == 1) - irc->send_part_command(iid.get_local(), status_message); + { + irc->send_part_command(iid.get_local(), status_message); + // Since there are no resources left in that channel, we don't + // want to receive private messages using this room's JID + this->remove_all_preferred_from_jid_of_room(iid.get_local()); + } else { IrcChannel* chan = irc->get_channel(iid.get_local()); @@ -767,6 +772,18 @@ void Bridge::remove_preferred_from_jid(const std::string& nick) this->preferred_user_from.erase(it); } +void Bridge::remove_all_preferred_from_jid_of_room(const std::string& channel_name) +{ + for (auto it = this->preferred_user_from.begin(); it != this->preferred_user_from.end();) + { + Iid iid(Jid(it->second).local); + if (iid.get_local() == channel_name) + it = this->preferred_user_from.erase(it); + else + ++it; + } +} + void Bridge::add_waiting_irc(irc_responder_callback_t&& callback) { this->waiting_irc.emplace_back(std::move(callback)); -- cgit v1.2.3 From 0391f17f999618decffaf3c9261024ab04a33f63 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 21 Jun 2016 23:15:25 +0100 Subject: Add XEP-0106 support to the bridge This allows the user to join channels containing forbidden characters in the local part, like #r&d or #group/project. --- src/bridge/bridge.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 3a7a147..87667db 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -685,7 +685,10 @@ void Bridge::send_user_join(const std::string& hostname, const std::string& chan std::string role; std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(user_mode); - this->xmpp.send_user_join(chan_name + utils::empty_if_fixed_server("%" + hostname), user->nick, user->host, + std::string encoded_chan_name(chan_name); + xep0106::encode(encoded_chan_name); + + this->xmpp.send_user_join(encoded_chan_name + utils::empty_if_fixed_server("%" + hostname), user->nick, user->host, affiliation, role, this->user_jid + "/" + resource, self); } @@ -701,8 +704,10 @@ void Bridge::send_topic(const std::string& hostname, const std::string& chan_nam const std::string& topic, const std::string& who, const std::string& resource) { - const auto encoding = in_encoding_for(*this, {chan_name + '%' + hostname}); - this->xmpp.send_topic(chan_name + utils::empty_if_fixed_server( + std::string encoded_chan_name(chan_name); + xep0106::encode(encoded_chan_name); + const auto encoding = in_encoding_for(*this, {encoded_chan_name + '%' + hostname}); + this->xmpp.send_topic(encoded_chan_name + utils::empty_if_fixed_server( "%" + hostname), this->make_xmpp_body(topic, encoding), this->user_jid + "/" + resource, who); } @@ -884,13 +889,13 @@ void Bridge::generate_channel_join_for_resource(const Iid& iid, const std::strin if (user->nick != self->nick) { log_debug(user->nick); - this->send_user_join(iid.get_server(), iid.get_local(), + this->send_user_join(iid.get_server(), iid.get_encoded_local(), user.get(), user->get_most_significant_mode(irc->get_sorted_user_modes()), false, resource); } } - this->send_user_join(iid.get_server(), iid.get_local(), + this->send_user_join(iid.get_server(), iid.get_encoded_local(), self, self->get_most_significant_mode(irc->get_sorted_user_modes()), true, resource); - this->send_topic(iid.get_server(), iid.get_local(), channel->topic, channel->topic_author, resource); + this->send_topic(iid.get_server(), iid.get_encoded_local(), channel->topic, channel->topic_author, resource); } -- cgit v1.2.3 From 6bd9b1ec1429024a49cf8b6d7be29f90f35110fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Thu, 23 Jun 2016 22:18:42 +0200 Subject: Remove unused function --- src/bridge/bridge.cpp | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 87667db..4976ed2 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -16,17 +16,6 @@ using namespace std::string_literals; static const char* action_prefix = "\01ACTION "; -static std::string out_encoding_for(const Bridge& bridge, const Iid& iid) -{ -#ifdef USE_DATABASE - const auto jid = bridge.get_bare_jid(); - auto options = Database::get_irc_channel_options_with_server_default(jid, iid.get_server(), iid.get_local()); - return options.encodingOut.value(); -#else - return {"ISO-8859-1"}; -#endif -} - static std::string in_encoding_for(const Bridge& bridge, const Iid& iid) { #ifdef USE_DATABASE -- 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/bridge/bridge.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 4976ed2..eee4bd2 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -483,8 +483,7 @@ void Bridge::send_irc_user_ping_request(const std::string& irc_hostname, const s const std::string id = body.substr(6, body.size() - 7); if (id != iq_id) return false; - Jid jid(from_jid); - this->xmpp.send_iq_result(iq_id, to_jid, jid.local); + this->xmpp.send_iq_result_full_jid(iq_id, to_jid, from_jid); return true; } if (message.command == "401" && message.arguments[1] == nick) -- cgit v1.2.3 From 7d2a2dc8cc9d2d9bcd83fb1bd869c29322855fa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Fri, 24 Jun 2016 11:23:51 +0200 Subject: Forward ping requests from IRC to XMPP, to one single resource --- src/bridge/bridge.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index eee4bd2..6de2516 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -746,7 +746,10 @@ void Bridge::send_xmpp_ping_request(const std::string& nick, const std::string& // Use revstr because the forwarded ping to target XMPP user must not be // the same that the request iq, but we also need to get it back easily // (revstr again) - this->xmpp.send_ping_request(nick + "!" + utils::empty_if_fixed_server(hostname), this->user_jid, utils::revstr(id)); + // Forward to the first resource (arbitrary, based on the “order” of the std::set) only + const auto resources = this->resources_in_server[hostname]; + if (resources.begin() != resources.end()) + this->xmpp.send_ping_request(nick + "!" + utils::empty_if_fixed_server(hostname), this->user_jid + "/" + *resources.begin(), utils::revstr(id)); } void Bridge::set_preferred_from_jid(const std::string& nick, const std::string& full_jid) -- cgit v1.2.3 From 0ce75ab52111ba27ca99961057b36b68f0a135a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Sun, 3 Jul 2016 15:43:11 +0200 Subject: Properly remove the resource from the server when we leave the last channel --- src/bridge/bridge.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 6de2516..613e0e2 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -349,9 +349,11 @@ void Bridge::leave_irc_channel(Iid&& iid, std::string&& status_message, const st this->send_muc_leave(std::move(iid), std::move(nick), "Biboumi note: "s + std::to_string(resources - 1) + " resources are still in this channel.", true, resource); + if (this->number_of_channels_the_resource_is_in(iid.get_server(), resource) == 0) + this->remove_resource_from_server(iid.get_server(), resource); } } - } +} void Bridge::send_irc_nick_change(const Iid& iid, const std::string& new_nick) { @@ -868,6 +870,17 @@ std::size_t Bridge::number_of_resources_in_chan(const Bridge::ChannelKey& channe return it->second.size(); } +std::size_t Bridge::number_of_channels_the_resource_is_in(const std::string& irc_hostname, const std::string& resource) const +{ + std::size_t res = 0; + for (auto pair: this->resources_in_chan) + { + if (std::get<0>(pair.first) == irc_hostname && pair.second.count(resource) != 0) + res++; + } + return res; +} + void Bridge::generate_channel_join_for_resource(const Iid& iid, const std::string& resource) { IrcClient* irc = this->get_irc_client(iid.get_server()); -- cgit v1.2.3 From 5321d29cbda7d69d306f36d0f84d2c599c85c90e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 4 Jul 2016 17:00:05 +0200 Subject: List of channels are saved per-request and not globally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The list would keep the previous results in memory, forever, and the list would grow each time a new request was made (even with results from unrelated servers)… --- src/bridge/bridge.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 613e0e2..1ca611a 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -368,11 +368,11 @@ void Bridge::send_irc_channel_list_request(const Iid& iid, const std::string& iq irc->send_list_command(); - irc_responder_callback_t cb = [this, iid, iq_id, to_jid](const std::string& irc_hostname, - const IrcMessage& message) -> bool - { - static std::vector list; + std::vector list; + irc_responder_callback_t cb = [this, iid, iq_id, to_jid, list=std::move(list)](const std::string& irc_hostname, + const IrcMessage& message) mutable -> bool + { if (irc_hostname != iid.get_server()) return false; if (message.command == "263" || message.command == "RPL_TRYAGAIN" || -- cgit v1.2.3 From 03feb403f8fc702481f4e7a0ec0264aa2912ae51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Sun, 3 Jul 2016 16:06:52 +0200 Subject: Send the iq requests to one random resource instead of the bare JID --- src/bridge/bridge.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index 1ca611a..edf1700 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -739,7 +739,9 @@ void Bridge::send_affiliation_role_change(const Iid& iid, const std::string& tar void Bridge::send_iq_version_request(const std::string& nick, const std::string& hostname) { - this->xmpp.send_iq_version_request(nick + "!" + utils::empty_if_fixed_server(hostname), this->user_jid); + const auto resources = this->resources_in_server[hostname]; + if (resources.begin() != resources.end()) + this->xmpp.send_iq_version_request(nick + "!" + utils::empty_if_fixed_server(hostname), this->user_jid + "/" + *resources.begin()); } void Bridge::send_xmpp_ping_request(const std::string& nick, const std::string& hostname, -- cgit v1.2.3 From f0a25ccda4526f5132b459e7e6a48ea08733fb79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 3 Aug 2016 11:46:13 +0200 Subject: Lower case the nick, when forwarding a version or ping request --- src/bridge/bridge.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/bridge/bridge.cpp') diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp index edf1700..17d3ec6 100644 --- a/src/bridge/bridge.cpp +++ b/src/bridge/bridge.cpp @@ -741,7 +741,7 @@ void Bridge::send_iq_version_request(const std::string& nick, const std::string& { const auto resources = this->resources_in_server[hostname]; if (resources.begin() != resources.end()) - this->xmpp.send_iq_version_request(nick + "!" + utils::empty_if_fixed_server(hostname), this->user_jid + "/" + *resources.begin()); + this->xmpp.send_iq_version_request(utils::tolower(nick) + "!" + utils::empty_if_fixed_server(hostname), this->user_jid + "/" + *resources.begin()); } void Bridge::send_xmpp_ping_request(const std::string& nick, const std::string& hostname, @@ -753,7 +753,7 @@ void Bridge::send_xmpp_ping_request(const std::string& nick, const std::string& // Forward to the first resource (arbitrary, based on the “order” of the std::set) only const auto resources = this->resources_in_server[hostname]; if (resources.begin() != resources.end()) - this->xmpp.send_ping_request(nick + "!" + utils::empty_if_fixed_server(hostname), this->user_jid + "/" + *resources.begin(), utils::revstr(id)); + this->xmpp.send_ping_request(utils::tolower(nick) + "!" + utils::empty_if_fixed_server(hostname), this->user_jid + "/" + *resources.begin(), utils::revstr(id)); } void Bridge::set_preferred_from_jid(const std::string& nick, const std::string& full_jid) -- cgit v1.2.3