Provide a JID for IRC users, and add a stringprep dependency for this
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <irc/irc_client.hpp>
|
||||
#include <bridge/colors.hpp>
|
||||
#include <irc/irc_user.hpp>
|
||||
#include <irc/iid.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
@@ -56,7 +57,9 @@ public:
|
||||
/**
|
||||
* Send the presence of a new user in the MUC.
|
||||
*/
|
||||
void send_user_join(const std::string& hostname, const std::string& chan_name, const std::string nick);
|
||||
void send_user_join(const std::string& hostname,
|
||||
const std::string& chan_name,
|
||||
const IrcUser* user);
|
||||
/**
|
||||
* Send the self presence of an user when the MUC is fully joined.
|
||||
*/
|
||||
|
||||
@@ -193,11 +193,11 @@ void IrcClient::set_and_forward_user_list(const IrcMessage& message)
|
||||
std::vector<std::string> nicks = utils::split(message.arguments[3], ' ');
|
||||
for (const std::string& nick: nicks)
|
||||
{
|
||||
IrcUser* user = channel->add_user(nick);
|
||||
const IrcUser* user = channel->add_user(nick);
|
||||
if (user->nick != channel->get_self()->nick)
|
||||
{
|
||||
log_debug("Adding user [" << nick << "] to chan " << chan_name);
|
||||
this->bridge->send_user_join(this->hostname, chan_name, user->nick);
|
||||
this->bridge->send_user_join(this->hostname, chan_name, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,8 +214,8 @@ void IrcClient::on_channel_join(const IrcMessage& message)
|
||||
}
|
||||
else
|
||||
{
|
||||
IrcUser* user = channel->add_user(nick);
|
||||
this->bridge->send_user_join(this->hostname, chan_name, user->nick);
|
||||
const IrcUser* user = channel->add_user(nick);
|
||||
this->bridge->send_user_join(this->hostname, chan_name, user);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ IrcMessage::IrcMessage(std::string&& line)
|
||||
if (line[0] == ':')
|
||||
{
|
||||
pos = line.find(" ");
|
||||
this->prefix = line.substr(1, pos);
|
||||
this->prefix = line.substr(1, pos - 1);
|
||||
line = line.substr(pos + 1, std::string::npos);
|
||||
}
|
||||
// command
|
||||
|
||||
@@ -148,6 +148,11 @@ int main()
|
||||
assert(jid2.domain == "ツ.coucou");
|
||||
assert(jid2.resource == "coucou@coucou/coucou");
|
||||
|
||||
// Nodeprep
|
||||
const std::string& badjid("~louiz@EpiK-7D9D1FDE.poez.io");
|
||||
const std::string correctjid = jidprep(badjid);
|
||||
assert(correctjid == "~louiz@epik-7d9d1fde.poez.io");
|
||||
|
||||
/**
|
||||
* Config
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
#include <xmpp/jid.hpp>
|
||||
#include <config.h>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef LIBIDN_FOUND
|
||||
#include <stringprep.h>
|
||||
#endif
|
||||
|
||||
#include <logger/logger.hpp>
|
||||
|
||||
Jid::Jid(const std::string& jid)
|
||||
{
|
||||
@@ -19,3 +27,41 @@ Jid::Jid(const std::string& jid)
|
||||
|
||||
this->domain = jid.substr(at, slash - at);
|
||||
}
|
||||
|
||||
#include <iostream>
|
||||
|
||||
static constexpr size_t max_jid_part_len = 1023;
|
||||
|
||||
std::string jidprep(const std::string& original)
|
||||
{
|
||||
#ifdef LIBIDN_FOUND
|
||||
// TODO: cache the result
|
||||
const std::string error_msg("Failed to convert " + original + " into a valid JID:");
|
||||
Jid jid(original);
|
||||
|
||||
char local[max_jid_part_len] = {};
|
||||
memcpy(local, jid.local.data(), jid.local.size());
|
||||
Stringprep_rc rc = static_cast<Stringprep_rc>(::stringprep(local, max_jid_part_len,
|
||||
static_cast<Stringprep_profile_flags>(0), stringprep_xmpp_nodeprep));
|
||||
if (rc != STRINGPREP_OK)
|
||||
{
|
||||
log_error(error_msg + stringprep_strerror(rc));
|
||||
return "";
|
||||
}
|
||||
|
||||
char domain[max_jid_part_len] = {};
|
||||
memcpy(domain, jid.domain.data(), jid.domain.size());
|
||||
rc = static_cast<Stringprep_rc>(::stringprep(domain, max_jid_part_len,
|
||||
static_cast<Stringprep_profile_flags>(0), stringprep_nameprep));
|
||||
if (rc != STRINGPREP_OK)
|
||||
{
|
||||
log_error(error_msg + stringprep_strerror(rc));
|
||||
return "";
|
||||
}
|
||||
|
||||
return std::string(local) + "@" + domain;
|
||||
#else
|
||||
(void)original;
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -22,5 +22,15 @@ private:
|
||||
Jid& operator=(Jid&&) = delete;
|
||||
};
|
||||
|
||||
/**
|
||||
* Prepare the given UTF-8 string according to the XMPP node stringprep
|
||||
* identifier profile. This is used to send properly-formed JID to the XMPP
|
||||
* server.
|
||||
*
|
||||
* If the stringprep library is not found, we return an empty string. When
|
||||
* this function is used, the result must always be checked for an empty
|
||||
* value, and if this is the case it must not be used as a JID.
|
||||
*/
|
||||
std::string jidprep(const std::string& original);
|
||||
|
||||
#endif // JID_INCLUDED
|
||||
|
||||
@@ -267,7 +267,10 @@ void XmppComponent::send_message(const std::string& from, Xmpp::body&& body, con
|
||||
this->send_stanza(node);
|
||||
}
|
||||
|
||||
void XmppComponent::send_user_join(const std::string& from, const std::string& nick, const std::string& to)
|
||||
void XmppComponent::send_user_join(const std::string& from,
|
||||
const std::string& nick,
|
||||
const std::string& realjid,
|
||||
const std::string& to)
|
||||
{
|
||||
XmlNode node("presence");
|
||||
node["to"] = to;
|
||||
@@ -280,6 +283,12 @@ void XmppComponent::send_user_join(const std::string& from, const std::string& n
|
||||
XmlNode item("item");
|
||||
item["affiliation"] = "member";
|
||||
item["role"] = "participant";
|
||||
if (!realjid.empty())
|
||||
{
|
||||
const std::string preped_jid = jidprep(realjid);
|
||||
if (!preped_jid.empty())
|
||||
item["jid"] = preped_jid;
|
||||
}
|
||||
item.close();
|
||||
x.add_child(std::move(item));
|
||||
x.close();
|
||||
@@ -408,7 +417,7 @@ void XmppComponent::send_nick_change(const std::string& muc_name, const std::str
|
||||
if (self)
|
||||
this->send_self_join(muc_name, new_nick, jid_to);
|
||||
else
|
||||
this->send_user_join(muc_name, new_nick, jid_to);
|
||||
this->send_user_join(muc_name, new_nick, "", jid_to);
|
||||
}
|
||||
|
||||
void XmppComponent::kick_user(const std::string& muc_name,
|
||||
|
||||
@@ -62,7 +62,10 @@ public:
|
||||
/**
|
||||
* Send a join from a new participant
|
||||
*/
|
||||
void send_user_join(const std::string& from, const std::string& nick, const std::string& to);
|
||||
void send_user_join(const std::string& from,
|
||||
const std::string& nick,
|
||||
const std::string& realjid,
|
||||
const std::string& to);
|
||||
/**
|
||||
* Send the self join to the user
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user