Make the IRC channel configuration form available from the MUC config
fix #3250
This commit is contained in:
@@ -17,6 +17,8 @@ Version 5.0
|
|||||||
- Configuration options can be overridden by values found in the process env.
|
- Configuration options can be overridden by values found in the process env.
|
||||||
- Botan’s TLS policies can be customized by the administrator, for each
|
- Botan’s TLS policies can be customized by the administrator, for each
|
||||||
IRC server, with simple text files.
|
IRC server, with simple text files.
|
||||||
|
- The IRC channel configuration form is now also available using the MUC
|
||||||
|
configuration, in addition to the ad-hoc command.
|
||||||
|
|
||||||
Version 4.3 - 2017-05-02
|
Version 4.3 - 2017-05-02
|
||||||
========================
|
========================
|
||||||
|
|||||||
@@ -418,11 +418,18 @@ void ConfigureIrcChannelStep1(XmppComponent&, AdhocSession& session, XmlNode& co
|
|||||||
{
|
{
|
||||||
const Jid owner(session.get_owner_jid());
|
const Jid owner(session.get_owner_jid());
|
||||||
const Jid target(session.get_target_jid());
|
const Jid target(session.get_target_jid());
|
||||||
|
|
||||||
|
insert_irc_channel_configuration_form(command_node, owner, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert_irc_channel_configuration_form(XmlNode& node, const Jid& requester, const Jid& target)
|
||||||
|
{
|
||||||
const Iid iid(target.local, {});
|
const Iid iid(target.local, {});
|
||||||
auto options = Database::get_irc_channel_options_with_server_default(owner.local + "@" + owner.domain,
|
|
||||||
|
auto options = Database::get_irc_channel_options_with_server_default(requester.local + "@" + requester.domain,
|
||||||
iid.get_server(), iid.get_local());
|
iid.get_server(), iid.get_local());
|
||||||
|
|
||||||
XmlSubNode x(command_node, "jabber:x:data:x");
|
XmlSubNode x(node, "jabber:x:data:x");
|
||||||
x["type"] = "form";
|
x["type"] = "form";
|
||||||
XmlSubNode title(x, "title");
|
XmlSubNode title(x, "title");
|
||||||
title.set_inner("Configure the IRC channel "s + iid.get_local() + " on server "s + iid.get_server());
|
title.set_inner("Configure the IRC channel "s + iid.get_local() + " on server "s + iid.get_server());
|
||||||
@@ -468,17 +475,38 @@ void ConfigureIrcChannelStep1(XmppComponent&, AdhocSession& session, XmlNode& co
|
|||||||
|
|
||||||
void ConfigureIrcChannelStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node)
|
void ConfigureIrcChannelStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node)
|
||||||
{
|
{
|
||||||
const XmlNode* x = command_node.get_child("x", "jabber:x:data");
|
|
||||||
if (x)
|
|
||||||
{
|
|
||||||
const Jid owner(session.get_owner_jid());
|
const Jid owner(session.get_owner_jid());
|
||||||
const Jid target(session.get_target_jid());
|
const Jid target(session.get_target_jid());
|
||||||
const Iid iid(target.local, {});
|
|
||||||
auto options = Database::get_irc_channel_options(owner.local + "@" + owner.domain,
|
if (handle_irc_channel_configuration_form(command_node, owner, target))
|
||||||
iid.get_server(), iid.get_local());
|
|
||||||
for (const XmlNode* field: x->get_children("field", "jabber:x:data"))
|
|
||||||
{
|
{
|
||||||
const XmlNode* value = field->get_child("value", "jabber:x:data");
|
command_node.delete_all_children();
|
||||||
|
XmlSubNode note(command_node, "note");
|
||||||
|
note["type"] = "info";
|
||||||
|
note.set_inner("Configuration successfully applied.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XmlSubNode error(command_node, ADHOC_NS":error");
|
||||||
|
error["type"] = "modify";
|
||||||
|
XmlSubNode condition(error, STANZA_NS":bad-request");
|
||||||
|
session.terminate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handle_irc_channel_configuration_form(const XmlNode& node, const Jid& requester, const Jid& target)
|
||||||
|
{
|
||||||
|
const XmlNode* x = node.get_child("x", "jabber:x:data");
|
||||||
|
if (x)
|
||||||
|
{
|
||||||
|
if (x->get_tag("type") == "submit")
|
||||||
|
{
|
||||||
|
const Iid iid(target.local, {});
|
||||||
|
auto options = Database::get_irc_channel_options(requester.local + "@" + requester.domain,
|
||||||
|
iid.get_server(), iid.get_local());
|
||||||
|
for (const XmlNode *field: x->get_children("field", "jabber:x:data"))
|
||||||
|
{
|
||||||
|
const XmlNode *value = field->get_child("value", "jabber:x:data");
|
||||||
|
|
||||||
if (field->get_tag("var") == "encoding_out" &&
|
if (field->get_tag("var") == "encoding_out" &&
|
||||||
value && !value->get_inner().empty())
|
value && !value->get_inner().empty())
|
||||||
@@ -494,17 +522,10 @@ void ConfigureIrcChannelStep2(XmppComponent&, AdhocSession& session, XmlNode& co
|
|||||||
}
|
}
|
||||||
|
|
||||||
options.update();
|
options.update();
|
||||||
|
|
||||||
command_node.delete_all_children();
|
|
||||||
XmlSubNode note(command_node, "note");
|
|
||||||
note["type"] = "info";
|
|
||||||
note.set_inner("Configuration successfully applied.");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
XmlSubNode error(command_node, ADHOC_NS":error");
|
return true;
|
||||||
error["type"] = "modify";
|
}
|
||||||
XmlSubNode condition(error, STANZA_NS":bad-request");
|
return false;
|
||||||
session.terminate();
|
|
||||||
}
|
}
|
||||||
#endif // USE_DATABASE
|
#endif // USE_DATABASE
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <xmpp/adhoc_command.hpp>
|
#include <xmpp/adhoc_command.hpp>
|
||||||
#include <xmpp/adhoc_session.hpp>
|
#include <xmpp/adhoc_session.hpp>
|
||||||
#include <xmpp/xmpp_stanza.hpp>
|
#include <xmpp/xmpp_stanza.hpp>
|
||||||
|
#include <xmpp/jid.hpp>
|
||||||
|
|
||||||
class XmppComponent;
|
class XmppComponent;
|
||||||
|
|
||||||
@@ -17,7 +18,9 @@ void ConfigureIrcServerStep1(XmppComponent&, AdhocSession& session, XmlNode& com
|
|||||||
void ConfigureIrcServerStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node);
|
void ConfigureIrcServerStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node);
|
||||||
|
|
||||||
void ConfigureIrcChannelStep1(XmppComponent&, AdhocSession& session, XmlNode& command_node);
|
void ConfigureIrcChannelStep1(XmppComponent&, AdhocSession& session, XmlNode& command_node);
|
||||||
|
void insert_irc_channel_configuration_form(XmlNode& node, const Jid& requester, const Jid& target);
|
||||||
void ConfigureIrcChannelStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node);
|
void ConfigureIrcChannelStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node);
|
||||||
|
bool handle_irc_channel_configuration_form(const XmlNode& node, const Jid& requester, const Jid& target);
|
||||||
|
|
||||||
void DisconnectUserFromServerStep1(XmppComponent&, AdhocSession& session, XmlNode& command_node);
|
void DisconnectUserFromServerStep1(XmppComponent&, AdhocSession& session, XmlNode& command_node);
|
||||||
void DisconnectUserFromServerStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node);
|
void DisconnectUserFromServerStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node);
|
||||||
|
|||||||
@@ -392,6 +392,11 @@ void BiboumiComponent::handle_iq(const Stanza& stanza)
|
|||||||
if (this->handle_mam_request(stanza))
|
if (this->handle_mam_request(stanza))
|
||||||
stanza_error.disable();
|
stanza_error.disable();
|
||||||
}
|
}
|
||||||
|
else if ((query = stanza.get_child("query", MUC_OWNER_NS)))
|
||||||
|
{
|
||||||
|
if (this->handle_room_configuration_form(*query, from, to, id))
|
||||||
|
stanza_error.disable();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (type == "get")
|
else if (type == "get")
|
||||||
@@ -529,6 +534,13 @@ void BiboumiComponent::handle_iq(const Stanza& stanza)
|
|||||||
}
|
}
|
||||||
stanza_error.disable();
|
stanza_error.disable();
|
||||||
}
|
}
|
||||||
|
#ifdef USE_DATABASE
|
||||||
|
else if ((query = stanza.get_child("query", MUC_OWNER_NS)))
|
||||||
|
{
|
||||||
|
if (this->handle_room_configuration_form_request(from, to, id))
|
||||||
|
stanza_error.disable();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if (type == "result")
|
else if (type == "result")
|
||||||
{
|
{
|
||||||
@@ -679,6 +691,50 @@ void BiboumiComponent::send_archived_message(const db::MucLogLine& log_line, con
|
|||||||
this->send_stanza(message);
|
this->send_stanza(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BiboumiComponent::handle_room_configuration_form_request(const std::string& from, const Jid& to, const std::string& id)
|
||||||
|
{
|
||||||
|
Iid iid(to.local, {'#', '&'});
|
||||||
|
|
||||||
|
if (iid.type != Iid::Type::Channel)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Stanza iq("iq");
|
||||||
|
{
|
||||||
|
iq["from"] = to.full();
|
||||||
|
iq["to"] = from;
|
||||||
|
iq["id"] = id;
|
||||||
|
iq["type"] = "result";
|
||||||
|
XmlSubNode query(iq, "query");
|
||||||
|
query["xmlns"] = MUC_OWNER_NS;
|
||||||
|
Jid requester(from);
|
||||||
|
insert_irc_channel_configuration_form(query, requester, to);
|
||||||
|
}
|
||||||
|
this->send_stanza(iq);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BiboumiComponent::handle_room_configuration_form(const XmlNode& query, const std::string &from, const Jid &to, const std::string &id)
|
||||||
|
{
|
||||||
|
Iid iid(to.local, {'#', '&'});
|
||||||
|
|
||||||
|
if (iid.type != Iid::Type::Channel)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Jid requester(from);
|
||||||
|
if (!handle_irc_channel_configuration_form(query, requester, to))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Stanza iq("iq");
|
||||||
|
iq["type"] = "result";
|
||||||
|
iq["from"] = to.full();
|
||||||
|
iq["to"] = from;
|
||||||
|
iq["id"] = id;
|
||||||
|
|
||||||
|
this->send_stanza(iq);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Bridge* BiboumiComponent::get_user_bridge(const std::string& user_jid)
|
Bridge* BiboumiComponent::get_user_bridge(const std::string& user_jid)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <xmpp/xmpp_component.hpp>
|
#include <xmpp/xmpp_component.hpp>
|
||||||
|
#include <xmpp/jid.hpp>
|
||||||
|
|
||||||
#include <bridge/bridge.hpp>
|
#include <bridge/bridge.hpp>
|
||||||
|
|
||||||
@@ -97,6 +98,8 @@ public:
|
|||||||
bool handle_mam_request(const Stanza& stanza);
|
bool handle_mam_request(const Stanza& stanza);
|
||||||
void send_archived_message(const db::MucLogLine& log_line, const std::string& from, const std::string& to,
|
void send_archived_message(const db::MucLogLine& log_line, const std::string& from, const std::string& to,
|
||||||
const std::string& queryid);
|
const std::string& queryid);
|
||||||
|
bool handle_room_configuration_form_request(const std::string& from, const Jid& to, const std::string& id);
|
||||||
|
bool handle_room_configuration_form(const XmlNode& query, const std::string& from, const Jid& to, const std::string& id);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#define MUC_NS "http://jabber.org/protocol/muc"
|
#define MUC_NS "http://jabber.org/protocol/muc"
|
||||||
#define MUC_USER_NS MUC_NS"#user"
|
#define MUC_USER_NS MUC_NS"#user"
|
||||||
#define MUC_ADMIN_NS MUC_NS"#admin"
|
#define MUC_ADMIN_NS MUC_NS"#admin"
|
||||||
|
#define MUC_OWNER_NS MUC_NS"#owner"
|
||||||
#define DISCO_NS "http://jabber.org/protocol/disco"
|
#define DISCO_NS "http://jabber.org/protocol/disco"
|
||||||
#define DISCO_ITEMS_NS DISCO_NS"#items"
|
#define DISCO_ITEMS_NS DISCO_NS"#items"
|
||||||
#define DISCO_INFO_NS DISCO_NS"#info"
|
#define DISCO_INFO_NS DISCO_NS"#info"
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ def match(stanza, xpath):
|
|||||||
tree = lxml.etree.parse(io.StringIO(str(stanza)))
|
tree = lxml.etree.parse(io.StringIO(str(stanza)))
|
||||||
matched = tree.xpath(xpath, namespaces={'re': 'http://exslt.org/regular-expressions',
|
matched = tree.xpath(xpath, namespaces={'re': 'http://exslt.org/regular-expressions',
|
||||||
'muc_user': 'http://jabber.org/protocol/muc#user',
|
'muc_user': 'http://jabber.org/protocol/muc#user',
|
||||||
|
'muc_owner': 'http://jabber.org/protocol/muc#owner',
|
||||||
'muc': 'http://jabber.org/protocol/muc',
|
'muc': 'http://jabber.org/protocol/muc',
|
||||||
'disco_info': 'http://jabber.org/protocol/disco#info',
|
'disco_info': 'http://jabber.org/protocol/disco#info',
|
||||||
'muc_traffic': 'http://jabber.org/protocol/muc#traffic',
|
'muc_traffic': 'http://jabber.org/protocol/muc#traffic',
|
||||||
@@ -2382,6 +2383,26 @@ if __name__ == '__main__':
|
|||||||
partial(send_stanza, "<iq type='set' id='id4' from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}'><command xmlns='http://jabber.org/protocol/commands' action='cancel' node='configure' sessionid='{sessionid}' /></iq>"),
|
partial(send_stanza, "<iq type='set' id='id4' from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}'><command xmlns='http://jabber.org/protocol/commands' action='cancel' node='configure' sessionid='{sessionid}' /></iq>"),
|
||||||
partial(expect_stanza, "/iq[@type='result']/commands:command[@node='configure'][@status='canceled']"),
|
partial(expect_stanza, "/iq[@type='result']/commands:command[@node='configure'][@status='canceled']"),
|
||||||
]),
|
]),
|
||||||
|
Scenario("irc_channel_configure_xep0045",
|
||||||
|
[
|
||||||
|
handshake_sequence(),
|
||||||
|
partial(send_stanza, "<iq type='get' id='id1' from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}'><query xmlns='http://jabber.org/protocol/muc#owner'/></iq>"),
|
||||||
|
partial(expect_stanza, ("/iq[@type='result']/muc_owner:query",
|
||||||
|
"/iq/muc_owner:query/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_in']",
|
||||||
|
"/iq/muc_owner:query/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_out']",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
partial(send_stanza, "<iq type='set' id='id2' from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}'>"
|
||||||
|
"<query xmlns='http://jabber.org/protocol/muc#owner'>"
|
||||||
|
"<x xmlns='jabber:x:data' type='submit'>"
|
||||||
|
"<field var='ports' />"
|
||||||
|
"<field var='encoding_out'><value>UTF-8</value></field>"
|
||||||
|
"<field var='encoding_in'><value>latin-1</value></field>"
|
||||||
|
"</x></query></iq>"),
|
||||||
|
partial(expect_stanza, "/iq[@type='result']"),
|
||||||
|
partial(send_stanza, "<iq type='set' id='id3' from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}'><query xmlns='http://jabber.org/protocol/muc#owner'> <x xmlns='jabber:x:data' type='cancel'/></query></iq>"),
|
||||||
|
partial(expect_stanza, "/iq[@type='result']"),
|
||||||
|
]),
|
||||||
Scenario("irc_channel_configure_fixed",
|
Scenario("irc_channel_configure_fixed",
|
||||||
[
|
[
|
||||||
handshake_sequence(),
|
handshake_sequence(),
|
||||||
|
|||||||
Reference in New Issue
Block a user