summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bridge/bridge.cpp30
-rw-r--r--src/bridge/bridge.hpp16
-rw-r--r--src/xmpp/xmpp_component.cpp36
-rw-r--r--src/xmpp/xmpp_component.hpp6
4 files changed, 77 insertions, 11 deletions
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);
+}
diff --git a/src/bridge/bridge.hpp b/src/bridge/bridge.hpp
index 814222b..8711829 100644
--- a/src/bridge/bridge.hpp
+++ b/src/bridge/bridge.hpp
@@ -123,6 +123,14 @@ public:
* Get the number of server to which this bridge is connected or connecting.
*/
size_t active_clients() const;
+ /**
+ * Add (or replace the existing) <nick, jid> into the preferred_user_from map
+ */
+ void set_preferred_from_jid(const std::string& nick, const std::string& full_jid);
+ /**
+ * Remove the preferred jid for the given IRC nick
+ */
+ void remove_preferred_from_jid(const std::string& nick);
private:
/**
@@ -157,6 +165,14 @@ private:
* their sockets.
*/
std::shared_ptr<Poller> poller;
+ /**
+ * A map of <nick, full_jid>. For example if this map contains <"toto",
+ * "#somechan%server@biboumi/ToTo">, whenever a private message is
+ * received from the user "toto", instead of forwarding it to XMPP with
+ * from='toto!server@biboumi', we use instead
+ * from='#somechan%server@biboumi/ToTo'
+ */
+ std::unordered_map<std::string, std::string> preferred_user_from;
Bridge(const Bridge&) = delete;
Bridge(Bridge&& other) = delete;
diff --git a/src/xmpp/xmpp_component.cpp b/src/xmpp/xmpp_component.cpp
index ec8517c..da9cded 100644
--- a/src/xmpp/xmpp_component.cpp
+++ b/src/xmpp/xmpp_component.cpp
@@ -1,4 +1,5 @@
#include <utils/scopeguard.hpp>
+#include <utils/tolower.hpp>
#include <logger/logger.hpp>
#include <xmpp/xmpp_component.hpp>
@@ -351,13 +352,14 @@ void XmppComponent::handle_message(const Stanza& stanza)
utils::ScopeGuard stanza_error([&](){
this->send_stanza_error("message", from, to_str, id,
error_type, error_name, "");
- });
+ });
XmlNode* body = stanza.get_child("body", COMPONENT_NS);
if (type == "groupchat" && iid.is_channel)
{
- if (to.resource.empty())
- if (body && !body->get_inner().empty())
+ if (body && !body->get_inner().empty())
+ {
bridge->send_channel_message(iid, body->get_inner());
+ }
XmlNode* subject = stanza.get_child("subject", COMPONENT_NS);
if (subject)
bridge->set_channel_topic(iid, subject->get_inner());
@@ -374,15 +376,30 @@ void XmppComponent::handle_message(const Stanza& stanza)
{
const XmlNode* condition = error->get_last_child();
if (kickable_errors.find(condition->get_name()) == kickable_errors.end())
- kickable_error = false;
+ kickable_error = false;
}
if (kickable_error)
bridge->shutdown("Error from remote client");
}
- else if (type == "chat" && iid.is_user && !iid.get_local().empty())
+ else if (type == "chat")
{
if (body && !body->get_inner().empty())
- bridge->send_private_message(iid, body->get_inner());
+ {
+ // a message for nick!server
+ if (iid.is_user && !iid.get_local().empty())
+ {
+ bridge->send_private_message(iid, body->get_inner());
+ bridge->remove_preferred_from_jid(iid.get_local());
+ }
+ else if (!iid.is_user && !to.resource.empty())
+ { // a message for chan%server@biboumi/Nick or
+ // server@biboumi/Nick
+ // Convert that into a message to nick!server
+ Iid user_iid(utils::tolower(to.resource) + "!" + iid.get_server());
+ bridge->send_private_message(user_iid, body->get_inner());
+ bridge->set_preferred_from_jid(user_iid.get_local(), to_str);
+ }
+ }
}
else if (iid.is_user)
this->send_invalid_user_error(to.local, from);
@@ -571,11 +588,14 @@ void* XmppComponent::get_receive_buffer(const size_t size) const
return this->parser.get_buffer(size);
}
-void XmppComponent::send_message(const std::string& from, Xmpp::body&& body, const std::string& to, const std::string& type)
+void XmppComponent::send_message(const std::string& from, Xmpp::body&& body, const std::string& to, const std::string& type, const bool fulljid)
{
XmlNode node("message");
node["to"] = to;
- node["from"] = from + "@" + this->served_hostname;
+ if (fulljid)
+ node["from"] = from;
+ else
+ node["from"] = from + "@" + this->served_hostname;
if (!type.empty())
node["type"] = type;
XmlNode body_node("body");
diff --git a/src/xmpp/xmpp_component.hpp b/src/xmpp/xmpp_component.hpp
index f1806de..17462f4 100644
--- a/src/xmpp/xmpp_component.hpp
+++ b/src/xmpp/xmpp_component.hpp
@@ -111,9 +111,13 @@ public:
void close_document();
/**
* Send a message from from@served_hostname, with the given body
+ *
+ * If fulljid is false, the provided 'from' doesn't contain the
+ * server-part of the JID and must be added.
*/
void send_message(const std::string& from, Xmpp::body&& body,
- const std::string& to, const std::string& type);
+ const std::string& to, const std::string& type,
+ const bool fulljid=false);
/**
* Send a join from a new participant
*/