Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25dfcba60d | ||
|
|
2217cbeab3 | ||
|
|
69b8797d3b | ||
|
|
3dbbf5910e | ||
|
|
600068440f | ||
|
|
9eb19d53e7 | ||
|
|
c438554f9a | ||
|
|
d8bc3d17bb | ||
|
|
99d7f8a41a | ||
|
|
ff173a8ea3 |
No files matched your search
@@ -1,4 +1,4 @@
|
|||||||
image: debian/buster
|
image: debian/stable
|
||||||
sources:
|
sources:
|
||||||
- https://git.sr.ht/~singpolyma/biboumi
|
- https://git.sr.ht/~singpolyma/biboumi
|
||||||
packages:
|
packages:
|
||||||
@@ -12,8 +12,9 @@ packages:
|
|||||||
- libidn11-dev
|
- libidn11-dev
|
||||||
- libidn2-dev
|
- libidn2-dev
|
||||||
- libudns-dev
|
- libudns-dev
|
||||||
- libbotan-2-dev
|
- libbotan-3-dev
|
||||||
- libsystemd-dev
|
- libsystemd-dev
|
||||||
|
- libcurl4-openssl-dev
|
||||||
artifacts:
|
artifacts:
|
||||||
- biboumi/biboumi
|
- biboumi/biboumi
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
@@ -3,17 +3,144 @@
|
|||||||
(guix packages)
|
(guix packages)
|
||||||
(guix download)
|
(guix download)
|
||||||
(guix git-download)
|
(guix git-download)
|
||||||
|
(guix gexp)
|
||||||
(guix build-system cmake)
|
(guix build-system cmake)
|
||||||
|
(guix build-system gnu)
|
||||||
|
(guix utils)
|
||||||
|
(gnu packages)
|
||||||
|
(gnu packages compression)
|
||||||
(gnu packages crypto)
|
(gnu packages crypto)
|
||||||
|
(gnu packages curl)
|
||||||
(gnu packages databases)
|
(gnu packages databases)
|
||||||
|
(gnu packages gcc)
|
||||||
(gnu packages libidn)
|
(gnu packages libidn)
|
||||||
(gnu packages linux)
|
(gnu packages linux)
|
||||||
(gnu packages python)
|
(gnu packages python)
|
||||||
(gnu packages sqlite)
|
(gnu packages python-xyz)
|
||||||
|
(gnu packages readline)
|
||||||
(gnu packages version-control)
|
(gnu packages version-control)
|
||||||
(gnu packages xml)
|
(gnu packages xml)
|
||||||
|
(ice-9 match)
|
||||||
(ice-9 rdelim)
|
(ice-9 rdelim)
|
||||||
(ice-9 popen))
|
(ice-9 popen)
|
||||||
|
(srfi srfi-26))
|
||||||
|
|
||||||
|
(define (sqlite-uri version year)
|
||||||
|
(let ((numeric-version
|
||||||
|
(match (string-split version #\.)
|
||||||
|
((first-digit other-digits ...)
|
||||||
|
(string-append first-digit
|
||||||
|
(string-pad-right
|
||||||
|
(string-concatenate
|
||||||
|
(map (cut string-pad <> 2 #\0)
|
||||||
|
other-digits))
|
||||||
|
6 #\0))))))
|
||||||
|
(string-append "https://sqlite.org/" (number->string year)
|
||||||
|
"/sqlite-autoconf-" numeric-version ".tar.gz")))
|
||||||
|
|
||||||
|
(define-public sqlite
|
||||||
|
(package
|
||||||
|
(name "sqlite")
|
||||||
|
(version "3.39.3")
|
||||||
|
(source (origin
|
||||||
|
(method url-fetch)
|
||||||
|
(uri (sqlite-uri version 2022))
|
||||||
|
(patches (search-patches "sqlite-hurd.patch"))
|
||||||
|
(sha256
|
||||||
|
(base32
|
||||||
|
"1f922kq16g7f4h3gpzim78lvrp5xw9nvlvqw97s2qgxyh8qgns3q"))))
|
||||||
|
(build-system gnu-build-system)
|
||||||
|
(inputs (list readline))
|
||||||
|
(outputs '("out" "static"))
|
||||||
|
(arguments
|
||||||
|
`(#:configure-flags
|
||||||
|
;; Add -DSQLITE_SECURE_DELETE, -DSQLITE_ENABLE_FTS3,
|
||||||
|
;; -DSQLITE_ENABLE_UNLOCK_NOTIFY and -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||||
|
;; to CFLAGS. GNU Icecat will refuse to use the system SQLite
|
||||||
|
;; unless these options are enabled.
|
||||||
|
(list (string-append "CFLAGS=-O2 -g -DSQLITE_SECURE_DELETE "
|
||||||
|
"-DSQLITE_ENABLE_FTS3 "
|
||||||
|
"-DSQLITE_ENABLE_UNLOCK_NOTIFY "
|
||||||
|
"-DSQLITE_ENABLE_DBSTAT_VTAB "
|
||||||
|
;; Column metadata is required by GNU Jami and Qt, et.al.
|
||||||
|
"-DSQLITE_ENABLE_COLUMN_METADATA"))
|
||||||
|
#:phases (modify-phases %standard-phases
|
||||||
|
(add-after 'install 'move-static-library
|
||||||
|
(lambda* (#:key outputs #:allow-other-keys)
|
||||||
|
(let* ((out (assoc-ref outputs "out"))
|
||||||
|
(static (assoc-ref outputs "static"))
|
||||||
|
(source (string-append out "/lib/libsqlite3.a")))
|
||||||
|
(mkdir-p (string-append static "/lib"))
|
||||||
|
(link source (string-append static "/lib/libsqlite3.a"))
|
||||||
|
(delete-file source)
|
||||||
|
|
||||||
|
;; Remove reference to the static library from the .la file
|
||||||
|
;; so that Libtool looks for it in the usual places.
|
||||||
|
(substitute* (string-append out "/lib/libsqlite3.la")
|
||||||
|
(("^old_library=.*")
|
||||||
|
"old_library=''\n"))
|
||||||
|
#t))))))
|
||||||
|
(home-page "https://www.sqlite.org/")
|
||||||
|
(synopsis "The SQLite database management system")
|
||||||
|
(description
|
||||||
|
"SQLite is a software library that implements a self-contained, serverless,
|
||||||
|
zero-configuration, transactional SQL database engine. SQLite is the most
|
||||||
|
widely deployed SQL database engine in the world. The source code for SQLite
|
||||||
|
is in the public domain.")
|
||||||
|
(license license:public-domain)))
|
||||||
|
|
||||||
|
(define-public botan
|
||||||
|
(package
|
||||||
|
(name "botan")
|
||||||
|
(version "3.9.0")
|
||||||
|
(source (origin
|
||||||
|
(method git-fetch)
|
||||||
|
(uri (git-reference
|
||||||
|
(url "https://github.com/randombit/botan/")
|
||||||
|
(commit version)))
|
||||||
|
(file-name (git-file-name name version))
|
||||||
|
(sha256
|
||||||
|
(base32
|
||||||
|
"1k5dyn39b77bfawly2yms0crbkn6g7msh16q7bxnh7dra4cnkmsn"))))
|
||||||
|
(build-system gnu-build-system)
|
||||||
|
(arguments
|
||||||
|
(list
|
||||||
|
#:phases
|
||||||
|
#~(modify-phases %standard-phases
|
||||||
|
(replace 'configure
|
||||||
|
(lambda* (#:key inputs outputs #:allow-other-keys)
|
||||||
|
;; Upstream tests and benchmarks with -O3.
|
||||||
|
(setenv "CXXFLAGS" "-O3")
|
||||||
|
(invoke "python" "./configure.py"
|
||||||
|
(string-append "--prefix=" #$output)
|
||||||
|
"--disable-static"
|
||||||
|
|
||||||
|
;; Otherwise, the `botan` executable cannot find
|
||||||
|
;; libbotan.
|
||||||
|
(string-append "--ldflags=-Wl,-rpath=" #$output "/lib")
|
||||||
|
|
||||||
|
"--with-os-feature=getentropy"
|
||||||
|
"--with-rst2man"
|
||||||
|
|
||||||
|
;; Recommended by upstream
|
||||||
|
"--with-zlib" "--with-bzip2" "--with-sqlite3")))
|
||||||
|
(add-before 'check 'library-path-for-tests
|
||||||
|
(lambda _ (setenv "LD_LIBRARY_PATH" (getcwd))))
|
||||||
|
(replace 'check
|
||||||
|
(lambda* (#:key tests? #:allow-other-keys)
|
||||||
|
(when tests?
|
||||||
|
(invoke "./botan-test")))))))
|
||||||
|
(native-inputs (list python-wrapper python-docutils gcc-12))
|
||||||
|
(inputs (list sqlite bzip2 zlib))
|
||||||
|
(synopsis "Cryptographic library in C++11")
|
||||||
|
(description "Botan is a cryptography library, written in C++11, offering
|
||||||
|
the tools necessary to implement a range of practical systems, such as TLS/DTLS,
|
||||||
|
PKIX certificate handling, PKCS#11 and TPM hardware support, password hashing,
|
||||||
|
and post-quantum crypto schemes. In addition to the C++, botan has a C89 API
|
||||||
|
specifically designed to be easy to call from other languages. A Python binding
|
||||||
|
using ctypes is included, and several other language bindings are available.")
|
||||||
|
(home-page "https://botan.randombit.net")
|
||||||
|
(license license:bsd-2)))
|
||||||
|
|
||||||
;;;;
|
;;;;
|
||||||
|
|
||||||
@@ -47,9 +174,13 @@
|
|||||||
(lambda* (#:key outputs #:allow-other-keys)
|
(lambda* (#:key outputs #:allow-other-keys)
|
||||||
(substitute* "CMakeLists.txt"
|
(substitute* "CMakeLists.txt"
|
||||||
((".etc.biboumi") (string-append (assoc-ref outputs "out") "/etc/biboumi"))))))))
|
((".etc.biboumi") (string-append (assoc-ref outputs "out") "/etc/biboumi"))))))))
|
||||||
|
(native-inputs
|
||||||
|
'(list
|
||||||
|
gcc-12))
|
||||||
(inputs
|
(inputs
|
||||||
'(list
|
'(list
|
||||||
botan
|
botan
|
||||||
|
curl
|
||||||
expat
|
expat
|
||||||
git
|
git
|
||||||
libidn2
|
libidn2
|
||||||
|
|||||||
@@ -596,6 +596,32 @@ void Bridge::send_irc_nick_change(const Iid& iid, const std::string& new_nick, c
|
|||||||
if (!res_in_chan)
|
if (!res_in_chan)
|
||||||
return;
|
return;
|
||||||
IrcClient* irc = this->get_irc_client(iid.get_server());
|
IrcClient* irc = this->get_irc_client(iid.get_server());
|
||||||
|
if (new_nick == irc->get_own_nick())
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifdef USE_DATABASE
|
||||||
|
auto soptions = Database::get_irc_server_options(this->get_bare_jid(), iid.get_server());
|
||||||
|
const auto& db_nick = soptions.col<Database::Nick>();
|
||||||
|
if (!db_nick.empty())
|
||||||
|
{
|
||||||
|
IrcChannel* channel = irc->get_channel(iid.get_local());
|
||||||
|
const IrcUser* self = channel ? channel->get_self() : nullptr;
|
||||||
|
// Send presence 110+210 to let them know the nick we're actually using
|
||||||
|
if (self)
|
||||||
|
{
|
||||||
|
this->send_user_join(iid.get_server(), iid.get_local(), self,
|
||||||
|
self->get_most_significant_mode(irc->get_sorted_user_modes()),
|
||||||
|
true, requesting_resource);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IrcUser user(irc->get_own_nick());
|
||||||
|
this->send_user_join(iid.get_server(), iid.get_local(), &user, '\0', true, requesting_resource);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
irc->send_nick_command(new_nick);
|
irc->send_nick_command(new_nick);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -526,6 +526,11 @@ void IrcClient::send_user_command(const std::string& username, const std::string
|
|||||||
|
|
||||||
void IrcClient::send_nick_command(const std::string& nick)
|
void IrcClient::send_nick_command(const std::string& nick)
|
||||||
{
|
{
|
||||||
|
if (nick.find(' ') != std::string::npos)
|
||||||
|
{
|
||||||
|
this->on_erroneous_nickname(IrcMessage(std::string(this->hostname), "432", {this->get_own_nick(), nick, "Erroneous nickname"}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
this->send_message(IrcMessage("NICK", {nick}));
|
this->send_message(IrcMessage("NICK", {nick}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
-1
@@ -20,6 +20,10 @@ IrcUri::~IrcUri(void) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CURL_FOUND
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
const std::optional<std::string> IrcUri::get_server(void) const {
|
const std::optional<std::string> IrcUri::get_server(void) const {
|
||||||
#ifdef CURL_FOUND
|
#ifdef CURL_FOUND
|
||||||
char *server;
|
char *server;
|
||||||
@@ -27,7 +31,9 @@ const std::optional<std::string> IrcUri::get_server(void) const {
|
|||||||
if (rc) {
|
if (rc) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
return server;
|
std::string result(server);
|
||||||
|
curl_free(server);
|
||||||
|
return result;
|
||||||
#else
|
#else
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
#endif // CURL_FOUND
|
#endif // CURL_FOUND
|
||||||
@@ -42,6 +48,7 @@ const std::optional<std::string> IrcUri::get_entity(void) const {
|
|||||||
if (rc)
|
if (rc)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
output = entity;
|
output = entity;
|
||||||
|
curl_free(entity);
|
||||||
if (!output.empty())
|
if (!output.empty())
|
||||||
output.erase(0, 1);
|
output.erase(0, 1);
|
||||||
if (output.empty()) {
|
if (output.empty()) {
|
||||||
@@ -49,6 +56,7 @@ const std::optional<std::string> IrcUri::get_entity(void) const {
|
|||||||
if (rc)
|
if (rc)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
output = entity;
|
output = entity;
|
||||||
|
curl_free(entity);
|
||||||
output.insert(0, 1, '#');
|
output.insert(0, 1, '#');
|
||||||
}
|
}
|
||||||
return IrcUri::parse_entity(output);
|
return IrcUri::parse_entity(output);
|
||||||
|
|||||||
@@ -33,3 +33,22 @@ std::string sha1(const std::string& input)
|
|||||||
return digest.str();
|
return digest.str();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string sha1_raw(const std::string& input)
|
||||||
|
{
|
||||||
|
#ifdef BOTAN_FOUND
|
||||||
|
auto sha1 = Botan::HashFunction::create_or_throw("SHA-1");
|
||||||
|
sha1->update(input);
|
||||||
|
const auto digest = sha1->final();
|
||||||
|
return std::string(
|
||||||
|
reinterpret_cast<const char*>(digest.data()),
|
||||||
|
digest.size()
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
#ifdef GCRYPT_FOUND
|
||||||
|
const auto hash_length = gcry_md_get_algo_dlen(GCRY_MD_SHA1);
|
||||||
|
std::string output(hash_length, '\0');
|
||||||
|
gcry_md_hash_buffer(GCRY_MD_SHA1, output.data(), input.data(), input.size());
|
||||||
|
return output;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -3,3 +3,4 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
std::string sha1(const std::string& input);
|
std::string sha1(const std::string& input);
|
||||||
|
std::string sha1_raw(const std::string& input);
|
||||||
@@ -576,9 +576,10 @@ void BiboumiComponent::handle_iq(const Stanza& stanza)
|
|||||||
}
|
}
|
||||||
else if (iid.type == Iid::Type::Server)
|
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();
|
stanza_error.disable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1074,28 +1075,35 @@ void BiboumiComponent::send_self_disco_info(const std::string& id, const std::st
|
|||||||
this->send_stanza(iq);
|
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);
|
Jid from(jid_from);
|
||||||
Stanza iq("iq");
|
Stanza iq("iq");
|
||||||
{
|
iq["type"] = "result";
|
||||||
iq["type"] = "result";
|
XmlSubNode query(iq, "query");
|
||||||
iq["id"] = id;
|
query["xmlns"] = DISCO_INFO_NS;
|
||||||
iq["to"] = jid_to;
|
if (!node.empty())
|
||||||
iq["from"] = jid_from;
|
query["node"] = node;
|
||||||
XmlSubNode query(iq, "query");
|
XmlSubNode identity(query, "identity");
|
||||||
query["xmlns"] = DISCO_INFO_NS;
|
identity["category"] = "gateway";
|
||||||
XmlSubNode identity(query, "identity");
|
identity["type"] = "irc";
|
||||||
identity["category"] = "gateway";
|
identity["name"] = "IRC server " + from.local + " over Biboumi";
|
||||||
identity["type"] = "irc";
|
for (const char *ns: {DISCO_INFO_NS, CAPS_NS, ADHOC_NS, PING_NS, VERSION_NS})
|
||||||
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;
|
||||||
XmlSubNode feature(query, "feature");
|
}
|
||||||
feature["var"] = ns;
|
return iq;
|
||||||
}
|
|
||||||
}
|
|
||||||
this->send_stanza(iq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BiboumiComponent::send_irc_channel_muc_traffic_info(const std::string& id, const std::string& jid_to, const std::string& jid_from)
|
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())
|
if (!id.empty())
|
||||||
presence["id"] = id;
|
presence["id"] = id;
|
||||||
|
|
||||||
if (type.empty() && from == this->served_hostname) {
|
if (type.empty())
|
||||||
XmlSubNode c(presence, "c");
|
{
|
||||||
c["xmlns"] = CAPS_NS;
|
Jid from_jid(from);
|
||||||
c["hash"] = "sha-1";
|
const Iid from_iid(from_jid.local, {'&', '#', '+', '!'});
|
||||||
c["node"] = NODE_NAME;
|
const std::string fixed_irc_server = Config::get("fixed_irc_server", "");
|
||||||
c["ver"] = this->get_self_ver();
|
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);
|
this->send_stanza(presence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,8 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Send a result IQ with the disco informations regarding IRC server JIDs.
|
* 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
|
* Sends the allowed namespaces in MUC message, according to
|
||||||
* http://xmpp.org/extensions/xep-0045.html#impl-service-traffic
|
* 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);
|
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 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 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
|
#ifdef CURL_FOUND
|
||||||
std::optional<Stanza> handle_iq_gateway(const Stanza *stanza, const Jid *from, const std::string to, const std::string id);
|
std::optional<Stanza> handle_iq_gateway(const Stanza *stanza, const Jid *from, const std::string to, const std::string id);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const std::string hash_disco_sha1(const Stanza &stanza) {
|
|||||||
return category_compare;
|
return category_compare;
|
||||||
const std::string type_a = a->get_tag("type");
|
const std::string type_a = a->get_tag("type");
|
||||||
const std::string type_b = b->get_tag("type");
|
const std::string type_b = b->get_tag("type");
|
||||||
const int type_compare = type_a > type_b;
|
const int type_compare = type_a < type_b;
|
||||||
return type_compare;
|
return type_compare;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ const std::string hash_disco_sha1(const Stanza &stanza) {
|
|||||||
[](const XmlNode *a, const XmlNode *b) {
|
[](const XmlNode *a, const XmlNode *b) {
|
||||||
const std::string var_a = a->get_tag("var");
|
const std::string var_a = a->get_tag("var");
|
||||||
const std::string var_b = b->get_tag("var");
|
const std::string var_b = b->get_tag("var");
|
||||||
const int var_compare = var_a > var_b;
|
const int var_compare = var_a < var_b;
|
||||||
return var_compare;
|
return var_compare;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ const std::string hash_disco_sha1(const Stanza &stanza) {
|
|||||||
s += var + "<";
|
s += var + "<";
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string hashed = sha1(s);
|
const std::string hashed = sha1_raw(s);
|
||||||
const std::string encoded = base64::encode(hashed);
|
const std::string encoded = base64::encode(hashed);
|
||||||
|
|
||||||
return encoded;
|
return encoded;
|
||||||
|
|||||||
@@ -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}']"),
|
||||||
|
)
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
from scenarios import *
|
||||||
|
|
||||||
|
scenario = (
|
||||||
|
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(),
|
||||||
|
expect_stanza("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']",
|
||||||
|
"/presence/muc_user:x/muc_user:status[@code='110']"),
|
||||||
|
expect_stanza("/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]"),
|
||||||
|
|
||||||
|
# Attempt to change nick to a nickname containing a space
|
||||||
|
send_stanza("<presence from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}/Nick With Space' />"),
|
||||||
|
expect_stanza("/message[@from='{irc_server_one}'][@to='{jid_one}/{resource_one}']/body[text()='irc.localhost: Erroneous nickname: Nick With Space']"),
|
||||||
|
)
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
from scenarios import *
|
||||||
|
|
||||||
|
scenario = (
|
||||||
|
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(),
|
||||||
|
expect_stanza("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']",
|
||||||
|
"/presence/muc_user:x/muc_user:status[@code='110']"),
|
||||||
|
expect_stanza("/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]"),
|
||||||
|
|
||||||
|
# Configure a nickname in the database for this server
|
||||||
|
send_stanza("<iq type='set' id='conf1' from='{jid_one}/{resource_one}' to='{irc_server_one}'><command xmlns='http://jabber.org/protocol/commands' node='configure' action='execute' /></iq>"),
|
||||||
|
expect_stanza("/iq[@type='result']",
|
||||||
|
after = save_value("sessionid", extract_attribute("/iq[@type='result']/commands:command[@node='configure']", "sessionid"))),
|
||||||
|
send_stanza("<iq type='set' id='conf2' from='{jid_one}/{resource_one}' to='{irc_server_one}'>"
|
||||||
|
"<command xmlns='http://jabber.org/protocol/commands' node='configure' sessionid='{sessionid}' action='complete'>"
|
||||||
|
"<x xmlns='jabber:x:data' type='submit'>"
|
||||||
|
"<field var='nick'><value>{nick_one}</value></field>"
|
||||||
|
"</x></command></iq>"),
|
||||||
|
expect_stanza("/iq[@type='result']/commands:command[@node='configure'][@status='completed']/commands:note[@type='info'][text()='Configuration successfully applied.']"),
|
||||||
|
|
||||||
|
# Now with a DB nick configured, attempt to change nick: should reply with 110 + 210 presence rewriting to DB nick
|
||||||
|
send_stanza("<presence from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}/SomeOtherNick' />"),
|
||||||
|
expect_stanza("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']",
|
||||||
|
"/presence/muc_user:x/muc_user:status[@code='110']",
|
||||||
|
"/presence/muc_user:x/muc_user:status[@code='210']"),
|
||||||
|
)
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
from scenarios import *
|
||||||
|
|
||||||
|
scenario = (
|
||||||
|
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(),
|
||||||
|
expect_stanza("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']",
|
||||||
|
"/presence/muc_user:x/muc_user:status[@code='110']"),
|
||||||
|
expect_stanza("/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]"),
|
||||||
|
|
||||||
|
# Presence with the current nick (status update) should be ignored (no error, no change)
|
||||||
|
send_stanza("<presence from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}/{nick_one}'><show>away</show></presence>"),
|
||||||
|
)
|
||||||
@@ -32,7 +32,7 @@ TEST_CASE("Hash disco 1") {
|
|||||||
|
|
||||||
auto check_stanza = [](const Stanza &stanza) {
|
auto check_stanza = [](const Stanza &stanza) {
|
||||||
const std::string hash = Xmpp::hash_disco_sha1(stanza);
|
const std::string hash = Xmpp::hash_disco_sha1(stanza);
|
||||||
CHECK(hash == "YjVkN2NhODU2ZWQyZjhhNjJjOTE1MWMxYjQ0YmUwM2Q0ODhhZDI2MA==");
|
CHECK(hash == "GRREviyyjLzK2wK4QLX5NNF9FmQ=");
|
||||||
};
|
};
|
||||||
xml.add_stanza_callback([check_stanza](const Stanza &stanza) {
|
xml.add_stanza_callback([check_stanza](const Stanza &stanza) {
|
||||||
check_stanza(stanza);
|
check_stanza(stanza);
|
||||||
@@ -62,7 +62,7 @@ TEST_CASE("Hash disco 2") {
|
|||||||
|
|
||||||
auto check_stanza = [](const Stanza &stanza) {
|
auto check_stanza = [](const Stanza &stanza) {
|
||||||
const std::string hash = Xmpp::hash_disco_sha1(stanza);
|
const std::string hash = Xmpp::hash_disco_sha1(stanza);
|
||||||
CHECK(hash == "ZmY1ZTJjZjUyZjkwMjA2OTliZGFhYzYxMmVmMTI5YjdmYzNhZTIwYw==");
|
CHECK(hash == "ga7DGXbUk3tyt5T/WMlqa5qM0zM=");
|
||||||
};
|
};
|
||||||
xml.add_stanza_callback([check_stanza](const Stanza &stanza) {
|
xml.add_stanza_callback([check_stanza](const Stanza &stanza) {
|
||||||
check_stanza(stanza);
|
check_stanza(stanza);
|
||||||
@@ -91,7 +91,7 @@ TEST_CASE("Hash disco 2 different order") {
|
|||||||
|
|
||||||
auto check_stanza = [](const Stanza &stanza) {
|
auto check_stanza = [](const Stanza &stanza) {
|
||||||
const std::string hash = Xmpp::hash_disco_sha1(stanza);
|
const std::string hash = Xmpp::hash_disco_sha1(stanza);
|
||||||
CHECK(hash == "ZmY1ZTJjZjUyZjkwMjA2OTliZGFhYzYxMmVmMTI5YjdmYzNhZTIwYw==");
|
CHECK(hash == "ga7DGXbUk3tyt5T/WMlqa5qM0zM=");
|
||||||
};
|
};
|
||||||
xml.add_stanza_callback([check_stanza](const Stanza &stanza) {
|
xml.add_stanza_callback([check_stanza](const Stanza &stanza) {
|
||||||
check_stanza(stanza);
|
check_stanza(stanza);
|
||||||
|
|||||||
Reference in new issue
Block a user