Also support caps on irc server JIDs
This commit is contained in:
@@ -576,9 +576,10 @@ void BiboumiComponent::handle_iq(const Stanza& stanza)
|
||||
}
|
||||
else if (iid.type == Iid::Type::Server)
|
||||
{
|
||||
if (node.empty())
|
||||
const std::string expected_node_name = std::string(NODE_NAME) + "#" + get_irc_server_ver(to_str);
|
||||
if (node.empty() || node == expected_node_name)
|
||||
{
|
||||
this->send_irc_server_disco_info(id, from, to_str);
|
||||
this->send_irc_server_disco_info(id, from, to_str, node);
|
||||
stanza_error.disable();
|
||||
}
|
||||
}
|
||||
@@ -1074,28 +1075,35 @@ void BiboumiComponent::send_self_disco_info(const std::string& id, const std::st
|
||||
this->send_stanza(iq);
|
||||
}
|
||||
|
||||
void BiboumiComponent::send_irc_server_disco_info(const std::string& id, const std::string& jid_to, const std::string& jid_from)
|
||||
void BiboumiComponent::send_irc_server_disco_info(const std::string& id, const std::string& jid_to,
|
||||
const std::string& jid_from, const std::string& node)
|
||||
{
|
||||
Stanza iq = get_irc_server_disco_info(jid_from, node);
|
||||
iq["id"] = id;
|
||||
iq["to"] = jid_to;
|
||||
iq["from"] = jid_from;
|
||||
this->send_stanza(iq);
|
||||
}
|
||||
|
||||
Stanza BiboumiComponent::get_irc_server_disco_info(const std::string& jid_from, const std::string& node)
|
||||
{
|
||||
Jid from(jid_from);
|
||||
Stanza iq("iq");
|
||||
{
|
||||
iq["type"] = "result";
|
||||
iq["id"] = id;
|
||||
iq["to"] = jid_to;
|
||||
iq["from"] = jid_from;
|
||||
XmlSubNode query(iq, "query");
|
||||
query["xmlns"] = DISCO_INFO_NS;
|
||||
XmlSubNode identity(query, "identity");
|
||||
identity["category"] = "gateway";
|
||||
identity["type"] = "irc";
|
||||
identity["name"] = "IRC server " + from.local + " over Biboumi";
|
||||
for (const char *ns: {DISCO_INFO_NS, ADHOC_NS, PING_NS, VERSION_NS})
|
||||
{
|
||||
XmlSubNode feature(query, "feature");
|
||||
feature["var"] = ns;
|
||||
}
|
||||
}
|
||||
this->send_stanza(iq);
|
||||
iq["type"] = "result";
|
||||
XmlSubNode query(iq, "query");
|
||||
query["xmlns"] = DISCO_INFO_NS;
|
||||
if (!node.empty())
|
||||
query["node"] = node;
|
||||
XmlSubNode identity(query, "identity");
|
||||
identity["category"] = "gateway";
|
||||
identity["type"] = "irc";
|
||||
identity["name"] = "IRC server " + from.local + " over Biboumi";
|
||||
for (const char *ns: {DISCO_INFO_NS, CAPS_NS, ADHOC_NS, PING_NS, VERSION_NS})
|
||||
{
|
||||
XmlSubNode feature(query, "feature");
|
||||
feature["var"] = ns;
|
||||
}
|
||||
return iq;
|
||||
}
|
||||
|
||||
void BiboumiComponent::send_irc_channel_muc_traffic_info(const std::string& id, const std::string& jid_to, const std::string& jid_from)
|
||||
@@ -1303,13 +1311,24 @@ void BiboumiComponent::send_presence_to_contact(const std::string& from, const s
|
||||
if (!id.empty())
|
||||
presence["id"] = id;
|
||||
|
||||
if (type.empty() && from == this->served_hostname) {
|
||||
XmlSubNode c(presence, "c");
|
||||
c["xmlns"] = CAPS_NS;
|
||||
c["hash"] = "sha-1";
|
||||
c["node"] = NODE_NAME;
|
||||
c["ver"] = this->get_self_ver();
|
||||
}
|
||||
if (type.empty())
|
||||
{
|
||||
Jid from_jid(from);
|
||||
const Iid from_iid(from_jid.local, {'&', '#', '+', '!'});
|
||||
const std::string fixed_irc_server = Config::get("fixed_irc_server", "");
|
||||
const bool is_server_jid = !from_jid.local.empty() && from_jid.resource.empty() &&
|
||||
((fixed_irc_server.empty() && from_iid.type == Iid::Type::Server) ||
|
||||
(!fixed_irc_server.empty() && from_jid.local == fixed_irc_server));
|
||||
if (from == this->served_hostname ||
|
||||
(from_jid.domain == this->served_hostname && is_server_jid))
|
||||
{
|
||||
XmlSubNode c(presence, "c");
|
||||
c["xmlns"] = CAPS_NS;
|
||||
c["hash"] = "sha-1";
|
||||
c["node"] = NODE_NAME;
|
||||
c["ver"] = from == this->served_hostname ? this->get_self_ver() : get_irc_server_ver(from);
|
||||
}
|
||||
}
|
||||
this->send_stanza(presence);
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,8 @@ public:
|
||||
/**
|
||||
* Send a result IQ with the disco informations regarding IRC server JIDs.
|
||||
*/
|
||||
void send_irc_server_disco_info(const std::string& id, const std::string& jid_to, const std::string& jid_from);
|
||||
void send_irc_server_disco_info(const std::string& id, const std::string& jid_to,
|
||||
const std::string& jid_from, const std::string& node);
|
||||
/**
|
||||
* Sends the allowed namespaces in MUC message, according to
|
||||
* http://xmpp.org/extensions/xep-0045.html#impl-service-traffic
|
||||
@@ -93,6 +94,9 @@ private:
|
||||
void send_invitation_from_fulljid(const std::string& room_target, const std::string& jid_to, const std::string& from);
|
||||
static Stanza get_self_disco_info(const std::string &node);
|
||||
static std::string get_self_ver() { return Xmpp::hash_disco_sha1(get_self_disco_info("")); };
|
||||
static Stanza get_irc_server_disco_info(const std::string& jid_from, const std::string& node);
|
||||
static std::string get_irc_server_ver(const std::string& jid_from)
|
||||
{ return Xmpp::hash_disco_sha1(get_irc_server_disco_info(jid_from, "")); }
|
||||
#ifdef CURL_FOUND
|
||||
std::optional<Stanza> handle_iq_gateway(const Stanza *stanza, const Jid *from, const std::string to, const std::string id);
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
from scenarios import *
|
||||
|
||||
scenario = (
|
||||
# IRC server JIDs advertise caps for their own disco info
|
||||
send_stanza("<iq type='get' id='get6' from='{jid_one}/{resource_one}' to='{irc_server_one}'><query xmlns='http://jabber.org/protocol/disco#info'/></iq>"),
|
||||
expect_stanza("/iq[@from='{irc_server_one}'][@to='{jid_one}/{resource_one}'][@type='result']/disco_info:query/disco_info:identity[@category='gateway'][@type='irc']",
|
||||
"/iq/disco_info:query/disco_info:feature[@var='http://jabber.org/protocol/disco#info']",
|
||||
"/iq/disco_info:query/disco_info:feature[@var='http://jabber.org/protocol/caps']"
|
||||
),
|
||||
send_stanza("<presence from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}/{nick_one}'><x xmlns='http://jabber.org/protocol/muc'/></presence>"),
|
||||
sequences.connection(),
|
||||
scenarios.simple_channel_join.expect_self_join_presence(),
|
||||
send_stanza("<presence from='{jid_one}/{resource_one}' to='{irc_server_one}' type='subscribe'/>"),
|
||||
expect_stanza("/presence[@from='{irc_server_one}'][@to='{jid_one}'][@type='subscribed']"),
|
||||
expect_stanza("/presence[@from='{irc_server_one}'][@to='{jid_one}']/caps:c[@hash='sha-1'][@node][@ver]",
|
||||
after = (
|
||||
save_value("server_ver", extract_attribute("/presence/caps:c[@hash='sha-1'][@node][@ver]", "ver")),
|
||||
save_value("server_node", extract_attribute("/presence/caps:c[@hash='sha-1'][@node][@ver]", "node")),
|
||||
)
|
||||
),
|
||||
send_stanza("<iq type='get' id='get8' from='{jid_one}/{resource_one}' to='{irc_server_one}'><query xmlns='http://jabber.org/protocol/disco#info' node='{server_node}#{server_ver}'/></iq>"),
|
||||
expect_stanza("/iq[@from='{irc_server_one}'][@type='result']/disco_info:query[@node='{server_node}#{server_ver}']"),
|
||||
)
|
||||
Reference in New Issue
Block a user