Commit 82256d40 authored by louiz’'s avatar louiz’

Merge branch 'fixed_server'

parents c01befb0 c307df85
...@@ -59,6 +59,24 @@ The configuration file uses a simple format of the form ...@@ -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 privileges), for example some administration ad-hoc commands will only be
available to that JID. 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` `log_file`
A filename into which logs are written. If none is provided, the logs are A filename into which logs are written. If none is provided, the logs are
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <xmpp/xmpp_stanza.hpp> #include <xmpp/xmpp_stanza.hpp>
#include <irc/irc_message.hpp> #include <irc/irc_message.hpp>
#include <network/poller.hpp> #include <network/poller.hpp>
#include <utils/empty_if_fixed_server.hpp>
#include <utils/encoding.hpp> #include <utils/encoding.hpp>
#include <utils/tolower.hpp> #include <utils/tolower.hpp>
#include <logger/logger.hpp> #include <logger/logger.hpp>
...@@ -580,13 +581,13 @@ void Bridge::send_user_join(const std::string& hostname, ...@@ -580,13 +581,13 @@ void Bridge::send_user_join(const std::string& hostname,
std::string role; std::string role;
std::tie(role, affiliation) = get_role_affiliation_from_irc_mode(user_mode); 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); 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); 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) 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 ...@@ -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) 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, 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& ...@@ -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 // 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 // the same that the request iq, but we also need to get it back easily
// (revstr again) // (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) void Bridge::set_preferred_from_jid(const std::string& nick, const std::string& full_jid)
......
#include <utils/tolower.hpp> #include <utils/tolower.hpp>
#include <config/config.hpp>
#include <irc/iid.hpp> #include <irc/iid.hpp>
Iid::Iid(const std::string& iid): Iid::Iid(const std::string& iid):
is_channel(false), is_channel(false),
is_user(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("%!"); const std::string::size_type sep = iid.find_first_of("%!");
if (sep != std::string::npos) if (sep != std::string::npos)
...@@ -20,6 +31,26 @@ Iid::Iid(const std::string& iid): ...@@ -20,6 +31,26 @@ Iid::Iid(const std::string& iid):
this->set_server(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): Iid::Iid(const Iid& other):
is_channel(other.is_channel), is_channel(other.is_channel),
is_user(other.is_user), is_user(other.is_user),
...@@ -66,6 +97,14 @@ std::string Iid::get_sep() const ...@@ -66,6 +97,14 @@ std::string Iid::get_sep() const
namespace std { namespace std {
const std::string to_string(const Iid& iid) 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();
}
} }
} }
...@@ -57,6 +57,10 @@ public: ...@@ -57,6 +57,10 @@ public:
std::string get_sep() const; std::string get_sep() const;
private: 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 local;
std::string server; std::string server;
......
...@@ -303,38 +303,100 @@ int main() ...@@ -303,38 +303,100 @@ int main()
/** /**
* IID parsing * IID parsing
*/ */
std::cout << color << "Testing IID parsing…" << reset << std::endl; {
Iid iid1("foo!irc.example.org"); std::cout << color << "Testing IID parsing…" << reset << std::endl;
std::cout << std::to_string(iid1) << std::endl; Iid iid1("foo!irc.example.org");
assert(std::to_string(iid1) == "foo!irc.example.org"); std::cout << std::to_string(iid1) << std::endl;
assert(iid1.get_local() == "foo"); assert(std::to_string(iid1) == "foo!irc.example.org");
assert(iid1.get_server() == "irc.example.org"); assert(iid1.get_local() == "foo");
assert(!iid1.is_channel); assert(iid1.get_server() == "irc.example.org");
assert(iid1.is_user); assert(!iid1.is_channel);
assert(iid1.is_user);
Iid iid2("#test%irc.example.org");
std::cout << std::to_string(iid2) << std::endl; Iid iid2("#test%irc.example.org");
assert(std::to_string(iid2) == "#test%irc.example.org"); std::cout << std::to_string(iid2) << std::endl;
assert(iid2.get_local() == "#test"); assert(std::to_string(iid2) == "#test%irc.example.org");
assert(iid2.get_server() == "irc.example.org"); assert(iid2.get_local() == "#test");
assert(iid2.is_channel); assert(iid2.get_server() == "irc.example.org");
assert(!iid2.is_user); assert(iid2.is_channel);
assert(!iid2.is_user);
Iid iid3("%irc.example.org");
std::cout << std::to_string(iid3) << std::endl; Iid iid3("%irc.example.org");
assert(std::to_string(iid3) == "%irc.example.org"); std::cout << std::to_string(iid3) << std::endl;
assert(iid3.get_local() == ""); assert(std::to_string(iid3) == "%irc.example.org");
assert(iid3.get_server() == "irc.example.org"); assert(iid3.get_local() == "");
assert(iid3.is_channel); assert(iid3.get_server() == "irc.example.org");
assert(!iid3.is_user); assert(iid3.is_channel);
assert(!iid3.is_user);
Iid iid4("irc.example.org");
std::cout << std::to_string(iid4) << std::endl; Iid iid4("irc.example.org");
assert(std::to_string(iid4) == "irc.example.org"); std::cout << std::to_string(iid4) << std::endl;
assert(iid4.get_local() == ""); assert(std::to_string(iid4) == "irc.example.org");
assert(iid4.get_server() == "irc.example.org"); assert(iid4.get_local() == "");
assert(!iid4.is_channel); assert(iid4.get_server() == "irc.example.org");
assert(!iid4.is_user); 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; return 0;
} }
#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 */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment