summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorent Le Coz <louiz@louiz.org>2015-02-26 17:43:24 +0100
committerFlorent Le Coz <louiz@louiz.org>2015-02-26 17:43:24 +0100
commit82256d40a32e1401c7884b1c9ff26ea77d775d3d (patch)
tree0661670f87c6cca2b43f2a35bc5c5d71ccfff78a
parentc01befb054075ab414fd602859e5999a138aa5bf (diff)
parentc307df85c8e7d9bcd4570269bf13c3e92c3f5954 (diff)
downloadbiboumi-82256d40a32e1401c7884b1c9ff26ea77d775d3d.tar.gz
biboumi-82256d40a32e1401c7884b1c9ff26ea77d775d3d.tar.bz2
biboumi-82256d40a32e1401c7884b1c9ff26ea77d775d3d.tar.xz
biboumi-82256d40a32e1401c7884b1c9ff26ea77d775d3d.zip
Merge branch 'fixed_server'
-rw-r--r--doc/biboumi.1.md18
-rw-r--r--src/bridge/bridge.cpp9
-rw-r--r--src/irc/iid.cpp41
-rw-r--r--src/irc/iid.hpp4
-rw-r--r--src/test.cpp126
-rw-r--r--src/utils/empty_if_fixed_server.hpp26
6 files changed, 187 insertions, 37 deletions
diff --git a/doc/biboumi.1.md b/doc/biboumi.1.md
index 18df220..3fd5a25 100644
--- a/doc/biboumi.1.md
+++ b/doc/biboumi.1.md
@@ -59,6 +59,24 @@ The configuration file uses a simple format of the form
privileges), for example some administration ad-hoc commands will only be
available to that JID.
+`fixed_irc_server`
+
+ If this option contains the hostname of an IRC server (for example
+ irc.example.org), then biboumi will enforce the connexion to that IRC
+ server only. This means that a JID like "#chan@biboumi.example.com" must
+ be used instead of "#chan%irc.example.org@biboumi.example.com". In that
+ mode, the virtual channel (see *Connect to an IRC server*) is not
+ available and you still need to use the ! separator to send message to an
+ IRC user (for example "foo!@biboumi.example.com" to send a message to
+ foo), although the in-room JID still work as expected
+ ("#channel@biboumi.example.com/Nick"). On the other hand, the '%' lose
+ any meaning. It can appear in the JID but will not be interpreted as a
+ separator (thus the JID "#channel%hello@biboumi.example.com" points to the
+ channel named "#channel%hello" on the configured IRC server) This option
+ can for example be used by an administrator that just wants to let their
+ users join their own IRC server using an XMPP client, while forbidding
+ access to any other IRC server.
+
`log_file`
A filename into which logs are written. If none is provided, the logs are
diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp
index 2e3520d..1a205bd 100644
--- a/src/bridge/bridge.cpp
+++ b/src/bridge/bridge.cpp
@@ -5,6 +5,7 @@
#include <xmpp/xmpp_stanza.hpp>
#include <irc/irc_message.hpp>
#include <network/poller.hpp>
+#include <utils/empty_if_fixed_server.hpp>
#include <utils/encoding.hpp>
#include <utils/tolower.hpp>
#include <logger/logger.hpp>
@@ -580,13 +581,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)
@@ -623,7 +624,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,
@@ -632,7 +633,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)
diff --git a/src/irc/iid.cpp b/src/irc/iid.cpp
index 0bb991f..9d39129 100644
--- a/src/irc/iid.cpp
+++ b/src/irc/iid.cpp
@@ -1,4 +1,5 @@
#include <utils/tolower.hpp>
+#include <config/config.hpp>
#include <irc/iid.hpp>
@@ -6,6 +7,16 @@ Iid::Iid(const std::string& iid):
is_channel(false),
is_user(false)
{
+ const std::string fixed_irc_server = Config::get("fixed_irc_server", "");
+ if (fixed_irc_server.empty())
+ this->init(iid);
+ else
+ this->init_with_fixed_server(iid, fixed_irc_server);
+}
+
+
+void Iid::init(const std::string& iid)
+{
const std::string::size_type sep = iid.find_first_of("%!");
if (sep != std::string::npos)
{
@@ -20,6 +31,26 @@ Iid::Iid(const std::string& iid):
this->set_server(iid);
}
+void Iid::init_with_fixed_server(const std::string& iid, const std::string& hostname)
+{
+ this->set_server(hostname);
+
+ const std::string::size_type sep = iid.find("!");
+
+ // Without any separator, we consider that it's a channel
+ if (sep == std::string::npos)
+ {
+ this->is_channel = true;
+ this->set_local(iid);
+ }
+ else // A separator can be present to differenciate a channel from a user,
+ // but the part behind it (the hostname) is ignored
+ {
+ this->set_local(iid.substr(0, sep));
+ this->is_user = true;
+ }
+}
+
Iid::Iid(const Iid& other):
is_channel(other.is_channel),
is_user(other.is_user),
@@ -66,6 +97,14 @@ std::string Iid::get_sep() const
namespace std {
const std::string to_string(const Iid& iid)
{
- return iid.get_local() + iid.get_sep() + iid.get_server();
+ if (Config::get("fixed_irc_server", "").empty())
+ return iid.get_local() + iid.get_sep() + iid.get_server();
+ else
+ {
+ if (iid.get_sep() == "!")
+ return iid.get_local() + iid.get_sep();
+ else
+ return iid.get_local();
+ }
}
}
diff --git a/src/irc/iid.hpp b/src/irc/iid.hpp
index d30cbaa..91779b2 100644
--- a/src/irc/iid.hpp
+++ b/src/irc/iid.hpp
@@ -57,6 +57,10 @@ public:
std::string get_sep() const;
private:
+
+ void init(const std::string& iid);
+ void init_with_fixed_server(const std::string& iid, const std::string& hostname);
+
std::string local;
std::string server;
diff --git a/src/test.cpp b/src/test.cpp
index a4371b2..553140f 100644
--- a/src/test.cpp
+++ b/src/test.cpp
@@ -303,38 +303,100 @@ int main()
/**
* IID parsing
*/
- std::cout << color << "Testing IID parsing…" << reset << std::endl;
- Iid iid1("foo!irc.example.org");
- std::cout << std::to_string(iid1) << std::endl;
- assert(std::to_string(iid1) == "foo!irc.example.org");
- assert(iid1.get_local() == "foo");
- assert(iid1.get_server() == "irc.example.org");
- assert(!iid1.is_channel);
- assert(iid1.is_user);
-
- Iid iid2("#test%irc.example.org");
- std::cout << std::to_string(iid2) << std::endl;
- assert(std::to_string(iid2) == "#test%irc.example.org");
- assert(iid2.get_local() == "#test");
- assert(iid2.get_server() == "irc.example.org");
- assert(iid2.is_channel);
- assert(!iid2.is_user);
-
- Iid iid3("%irc.example.org");
- std::cout << std::to_string(iid3) << std::endl;
- assert(std::to_string(iid3) == "%irc.example.org");
- assert(iid3.get_local() == "");
- assert(iid3.get_server() == "irc.example.org");
- assert(iid3.is_channel);
- assert(!iid3.is_user);
-
- Iid iid4("irc.example.org");
- std::cout << std::to_string(iid4) << std::endl;
- assert(std::to_string(iid4) == "irc.example.org");
- assert(iid4.get_local() == "");
- assert(iid4.get_server() == "irc.example.org");
- assert(!iid4.is_channel);
- assert(!iid4.is_user);
+ {
+ std::cout << color << "Testing IID parsing…" << reset << std::endl;
+ Iid iid1("foo!irc.example.org");
+ std::cout << std::to_string(iid1) << std::endl;
+ assert(std::to_string(iid1) == "foo!irc.example.org");
+ assert(iid1.get_local() == "foo");
+ assert(iid1.get_server() == "irc.example.org");
+ assert(!iid1.is_channel);
+ assert(iid1.is_user);
+
+ Iid iid2("#test%irc.example.org");
+ std::cout << std::to_string(iid2) << std::endl;
+ assert(std::to_string(iid2) == "#test%irc.example.org");
+ assert(iid2.get_local() == "#test");
+ assert(iid2.get_server() == "irc.example.org");
+ assert(iid2.is_channel);
+ assert(!iid2.is_user);
+
+ Iid iid3("%irc.example.org");
+ std::cout << std::to_string(iid3) << std::endl;
+ assert(std::to_string(iid3) == "%irc.example.org");
+ assert(iid3.get_local() == "");
+ assert(iid3.get_server() == "irc.example.org");
+ assert(iid3.is_channel);
+ assert(!iid3.is_user);
+
+ Iid iid4("irc.example.org");
+ std::cout << std::to_string(iid4) << std::endl;
+ assert(std::to_string(iid4) == "irc.example.org");
+ assert(iid4.get_local() == "");
+ assert(iid4.get_server() == "irc.example.org");
+ assert(!iid4.is_channel);
+ assert(!iid4.is_user);
+
+ Iid iid5("nick!");
+ std::cout << std::to_string(iid5) << std::endl;
+ assert(std::to_string(iid5) == "nick!");
+ assert(iid5.get_local() == "nick");
+ assert(iid5.get_server() == "");
+ assert(!iid5.is_channel);
+ assert(iid5.is_user);
+
+ Iid iid6("##channel%");
+ std::cout << std::to_string(iid6) << std::endl;
+ assert(std::to_string(iid6) == "##channel%");
+ assert(iid6.get_local() == "##channel");
+ assert(iid6.get_server() == "");
+ assert(iid6.is_channel);
+ assert(!iid6.is_user);
+ }
+
+ {
+ std::cout << color << "Testing IID parsing with a fixed server configured…" << reset << std::endl;
+ // Now do the same tests, but with a configured fixed_irc_server
+ Config::set("fixed_irc_server", "fixed.example.com", false);
+
+ Iid iid1("foo!irc.example.org");
+ std::cout << std::to_string(iid1) << std::endl;
+ assert(std::to_string(iid1) == "foo!");
+ assert(iid1.get_local() == "foo");
+ assert(iid1.get_server() == "fixed.example.com");
+ assert(!iid1.is_channel);
+ assert(iid1.is_user);
+
+ Iid iid2("#test%irc.example.org");
+ std::cout << std::to_string(iid2) << std::endl;
+ assert(std::to_string(iid2) == "#test%irc.example.org");
+ assert(iid2.get_local() == "#test%irc.example.org");
+ assert(iid2.get_server() == "fixed.example.com");
+ assert(iid2.is_channel);
+ assert(!iid2.is_user);
+
+ // Note that it is impossible to adress the IRC server directly, or to
+ // use the virtual channel, in that mode
+
+ // Iid iid3("%irc.example.org");
+ // Iid iid4("irc.example.org");
+
+ Iid iid5("nick!");
+ std::cout << std::to_string(iid5) << std::endl;
+ assert(std::to_string(iid5) == "nick!");
+ assert(iid5.get_local() == "nick");
+ assert(iid5.get_server() == "fixed.example.com");
+ assert(!iid5.is_channel);
+ assert(iid5.is_user);
+
+ Iid iid6("##channel%");
+ std::cout << std::to_string(iid6) << std::endl;
+ assert(std::to_string(iid6) == "##channel%");
+ assert(iid6.get_local() == "##channel%");
+ assert(iid6.get_server() == "fixed.example.com");
+ assert(iid6.is_channel);
+ assert(!iid6.is_user);
+ }
return 0;
}
diff --git a/src/utils/empty_if_fixed_server.hpp b/src/utils/empty_if_fixed_server.hpp
new file mode 100644
index 0000000..8739fd9
--- /dev/null
+++ b/src/utils/empty_if_fixed_server.hpp
@@ -0,0 +1,26 @@
+#ifndef EMPTY_IF_FIXED_SERVER_HPP_INCLUDED
+#define EMPTY_IF_FIXED_SERVER_HPP_INCLUDED
+
+#include <string>
+
+#include <config/config.hpp>
+
+namespace utils
+{
+ inline std::string empty_if_fixed_server(std::string&& str)
+ {
+ if (!Config::get("fixed_irc_server", "").empty())
+ return {};
+ return str;
+ }
+
+ inline std::string empty_if_fixed_server(const std::string& str)
+ {
+ if (!Config::get("fixed_irc_server", "").empty())
+ return {};
+ return str;
+ }
+
+}
+
+#endif /* EMPTY_IF_FIXED_SERVER_HPP_INCLUDED */