feat: obfuscate client identity and improve privacy (#165) #166

Manually merged
jabber.developer merged 2 commits from feat/privacy-enhancements into master 2026-07-10 09:05:11 +00:00
20 changed files with 172 additions and 62 deletions

View File

@@ -42,6 +42,7 @@
#include "ai/ai_client.h" #include "ai/ai_client.h"
static char* _caps_autocomplete(ProfWin* window, const char* const input, gboolean previous);
static char* _sub_autocomplete(ProfWin* window, const char* const input, gboolean previous); static char* _sub_autocomplete(ProfWin* window, const char* const input, gboolean previous);
static char* _notify_autocomplete(ProfWin* window, const char* const input, gboolean previous); static char* _notify_autocomplete(ProfWin* window, const char* const input, gboolean previous);
static char* _theme_autocomplete(ProfWin* window, const char* const input, gboolean previous); static char* _theme_autocomplete(ProfWin* window, const char* const input, gboolean previous);
@@ -151,6 +152,7 @@ static Autocomplete account_clear_ac;
static Autocomplete account_default_ac; static Autocomplete account_default_ac;
static Autocomplete account_status_ac; static Autocomplete account_status_ac;
static Autocomplete disco_ac; static Autocomplete disco_ac;
static Autocomplete caps_subcommands_ac;
static Autocomplete wins_ac; static Autocomplete wins_ac;
static Autocomplete roster_ac; static Autocomplete roster_ac;
static Autocomplete roster_show_ac; static Autocomplete roster_show_ac;
@@ -321,6 +323,7 @@ static Autocomplete* all_acs[] = {
&account_default_ac, &account_default_ac,
&account_status_ac, &account_status_ac,
&disco_ac, &disco_ac,
&caps_subcommands_ac,
&wins_ac, &wins_ac,
&roster_ac, &roster_ac,
&roster_show_ac, &roster_show_ac,
@@ -597,6 +600,8 @@ cmd_ac_init(void)
autocomplete_add(disco_ac, "info"); autocomplete_add(disco_ac, "info");
autocomplete_add(disco_ac, "items"); autocomplete_add(disco_ac, "items");
autocomplete_add(caps_subcommands_ac, "clear");
autocomplete_add(account_ac, "list"); autocomplete_add(account_ac, "list");
autocomplete_add(account_ac, "show"); autocomplete_add(account_ac, "show");
autocomplete_add(account_ac, "add"); autocomplete_add(account_ac, "add");
@@ -1414,6 +1419,7 @@ cmd_ac_init(void)
g_hash_table_insert(ac_funcs, "/ban", _ban_autocomplete); g_hash_table_insert(ac_funcs, "/ban", _ban_autocomplete);
g_hash_table_insert(ac_funcs, "/blocked", _blocked_autocomplete); g_hash_table_insert(ac_funcs, "/blocked", _blocked_autocomplete);
g_hash_table_insert(ac_funcs, "/bookmark", _bookmark_autocomplete); g_hash_table_insert(ac_funcs, "/bookmark", _bookmark_autocomplete);
g_hash_table_insert(ac_funcs, "/caps", _caps_autocomplete);
g_hash_table_insert(ac_funcs, "/clear", _clear_autocomplete); g_hash_table_insert(ac_funcs, "/clear", _clear_autocomplete);
g_hash_table_insert(ac_funcs, "/close", _close_autocomplete); g_hash_table_insert(ac_funcs, "/close", _close_autocomplete);
g_hash_table_insert(ac_funcs, "/cmd", _adhoc_cmd_autocomplete); g_hash_table_insert(ac_funcs, "/cmd", _adhoc_cmd_autocomplete);
@@ -1985,6 +1991,35 @@ _cmd_ac_complete_params(ProfWin* window, const char* const input, gboolean previ
return NULL; return NULL;
} }
static char*
_caps_autocomplete(ProfWin* window, const char* const input, gboolean previous)
{
char* result = NULL;
result = autocomplete_param_with_ac(input, "/caps", caps_subcommands_ac, TRUE, previous);
if (result) {
return result;
}
if (window->type == WIN_MUC) {
ProfMucWin* mucwin = (ProfMucWin*)window;
assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid);
if (nick_ac) {
result = autocomplete_param_with_ac(input, "/caps", nick_ac, TRUE, previous);
}
} else if (connection_get_status() == JABBER_CONNECTED) {
result = autocomplete_param_with_func(input, "/caps", roster_contact_autocomplete, previous, NULL);
if (result) {
return result;
}
result = autocomplete_param_with_func(input, "/caps", roster_barejid_autocomplete, previous, NULL);
if (result) {
return result;
}
result = autocomplete_param_with_func(input, "/caps", roster_fulljid_autocomplete, previous, NULL);
}
return result;
}
static char* static char*
_sub_autocomplete(ProfWin* window, const char* const input, gboolean previous) _sub_autocomplete(ProfWin* window, const char* const input, gboolean previous)
{ {

View File

@@ -427,17 +427,21 @@ static const struct cmd_t command_defs[] = {
CMD_TAG_GROUPCHAT) CMD_TAG_GROUPCHAT)
CMD_SYN( CMD_SYN(
"/caps", "/caps",
"/caps <fulljid>|<nick>") "/caps <fulljid>|<nick>",
"/caps clear")
CMD_DESC( CMD_DESC(
"Find out a contacts, or room members client software capabilities. " "Find out a contacts, or room members client software capabilities. "
"If in private chat initiated from a chat room, no parameter is required.") "If in private chat initiated from a chat room, no parameter is required. "
"Use clear to remove all cached capabilities.")
CMD_ARGS( CMD_ARGS(
{ "<fulljid>", "If in the console or a chat window, the full JID for which you wish to see capabilities." }, { "<fulljid>", "If in the console or a chat window, the full JID for which you wish to see capabilities." },
{ "<nick>", "If in a chat room, nickname for which you wish to see capabilities." }) { "<nick>", "If in a chat room, nickname for which you wish to see capabilities." },
{ "clear", "Clear all cached capabilities." })
CMD_EXAMPLES( CMD_EXAMPLES(
"/caps ran@cold.sea.org/laptop", "/caps ran@cold.sea.org/laptop",
"/caps ran@cold.sea.org/phone", "/caps ran@cold.sea.org/phone",
"/caps aegir") "/caps aegir",
"/caps clear")
}, },
{ CMD_PREAMBLE("/software", { CMD_PREAMBLE("/software",

View File

@@ -70,6 +70,7 @@
#include "xmpp/stanza.h" #include "xmpp/stanza.h"
#include "xmpp/vcard_funcs.h" #include "xmpp/vcard_funcs.h"
#include "xmpp/xmpp.h" #include "xmpp/xmpp.h"
#include "xmpp/capabilities.h"
#ifdef HAVE_LIBOTR #ifdef HAVE_LIBOTR
#include "otr/otr.h" #include "otr/otr.h"
@@ -3387,6 +3388,12 @@ cmd_caps(ProfWin* window, const char* const command, gchar** args)
return TRUE; return TRUE;
} }
if (g_strcmp0(args[0], "clear") == 0) {
caps_cache_clear();
cons_show("Capabilities cache cleared.");
return TRUE;
}
switch (window->type) { switch (window->type) {
case WIN_MUC: case WIN_MUC:
if (args[0]) { if (args[0]) {
@@ -3405,6 +3412,7 @@ cmd_caps(ProfWin* window, const char* const command, gchar** args)
break; break;
case WIN_CHAT: case WIN_CHAT:
case WIN_CONSOLE: case WIN_CONSOLE:
case WIN_XML:
if (args[0]) { if (args[0]) {
auto_jid Jid* jid = jid_create(args[0]); auto_jid Jid* jid = jid_create(args[0]);

View File

@@ -921,7 +921,7 @@ prof_date_time_format_iso8601(GDateTime* dt)
return ret; return ret;
} }
/* build profanity version string. /* build CProof version string.
* example: 0.13.1dev.master.69d8c1f9 * example: 0.13.1dev.master.69d8c1f9
*/ */
gchar* gchar*

View File

@@ -2689,7 +2689,6 @@ _get_default_boolean(preference_t pref)
case PREF_STATUSBAR_SHOW_NUMBER: case PREF_STATUSBAR_SHOW_NUMBER:
case PREF_STATUSBAR_SHOW_READ: case PREF_STATUSBAR_SHOW_READ:
case PREF_STATUSBAR_SHOW_DBBACKEND: case PREF_STATUSBAR_SHOW_DBBACKEND:
case PREF_REVEAL_OS:
case PREF_CORRECTION_ALLOW: case PREF_CORRECTION_ALLOW:
case PREF_RECEIPTS_SEND: case PREF_RECEIPTS_SEND:
case PREF_CARBONS: case PREF_CARBONS:
@@ -2704,6 +2703,7 @@ _get_default_boolean(preference_t pref)
case PREF_STROPHE_SM_RESEND: case PREF_STROPHE_SM_RESEND:
case PREF_AUTOPING_WARNING: case PREF_AUTOPING_WARNING:
return TRUE; return TRUE;
case PREF_REVEAL_OS:
case PREF_SPELLCHECK_ENABLE: case PREF_SPELLCHECK_ENABLE:
case PREF_PGP_PUBKEY_AUTOIMPORT: case PREF_PGP_PUBKEY_AUTOIMPORT:
case PREF_FORCE_ENCRYPTION: case PREF_FORCE_ENCRYPTION:

View File

@@ -77,7 +77,7 @@ main(int argc, char** argv)
if (version == TRUE) { if (version == TRUE) {
auto_gchar gchar* prof_version = prof_get_version(); auto_gchar gchar* prof_version = prof_get_version();
g_print("Profanity, version %s\n", prof_version); g_print("CProof, version %s\n", prof_version);
// lets use fixed email instead of PACKAGE_BUGREPORT // lets use fixed email instead of PACKAGE_BUGREPORT
g_print("Copyright (C) 2012 - 2019 James Booth <boothj5web@gmail.com>.\n"); g_print("Copyright (C) 2012 - 2019 James Booth <boothj5web@gmail.com>.\n");

View File

@@ -253,7 +253,7 @@ _init(char* log_level, char* config_file, char* log_file, char* theme_name)
log_stderr_init(PROF_LEVEL_ERROR); log_stderr_init(PROF_LEVEL_ERROR);
auto_gchar gchar* prof_version = prof_get_version(); auto_gchar gchar* prof_version = prof_get_version();
log_info("Starting Profanity (%s)…", prof_version); log_info("Starting CProof (%s)…", prof_version);
chatlog_init(); chatlog_init();
accounts_load(); accounts_load();

View File

@@ -2830,8 +2830,7 @@ cons_privacy_setting(void)
if (account->client) { if (account->client) {
cons_show("Client name (/account set <account> clientid) : %s", account->client); cons_show("Client name (/account set <account> clientid) : %s", account->client);
} else { } else {
auto_gchar gchar* prof_version = prof_get_version(); cons_show("Client name (/account set <account> clientid) : Pidgin");
cons_show("Client name (/account set <account> clientid) : Profanity %s", prof_version);
} }
if (account->max_sessions > 0) { if (account->max_sessions > 0) {
cons_show("Max sessions alarm (/account set <account> session_alarm) : %d", account->max_sessions); cons_show("Max sessions alarm (/account set <account> session_alarm) : %d", account->max_sessions);

View File

@@ -23,6 +23,7 @@
#include "plugins/plugins.h" #include "plugins/plugins.h"
#include "config/files.h" #include "config/files.h"
#include "config/preferences.h" #include "config/preferences.h"
#include "xmpp/connection.h"
#include "xmpp/xmpp.h" #include "xmpp/xmpp.h"
#include "xmpp/stanza.h" #include "xmpp/stanza.h"
#include "xmpp/form.h" #include "xmpp/form.h"
@@ -271,6 +272,19 @@ caps_map_jid_to_ver(const char* const jid, const char* const ver)
g_hash_table_insert(jid_to_ver, strdup(jid), strdup(ver)); g_hash_table_insert(jid_to_ver, strdup(jid), strdup(ver));
} }
void
caps_cache_clear(void)
{
g_hash_table_remove_all(jid_to_ver);
g_hash_table_remove_all(jid_to_caps);
if (caps_prof_keyfile.keyfile) {
g_key_file_free(caps_prof_keyfile.keyfile);
}
caps_prof_keyfile.keyfile = g_key_file_new();
cache = caps_prof_keyfile.keyfile;
save_keyfile(&caps_prof_keyfile);
}
gboolean gboolean
caps_cache_contains(const char* const ver) caps_cache_contains(const char* const ver)
{ {

View File

@@ -28,5 +28,6 @@ void caps_map_jid_to_ver(const char* const jid, const char* const ver);
gboolean caps_cache_contains(const char* const ver); gboolean caps_cache_contains(const char* const ver);
GList* caps_get_features(void); GList* caps_get_features(void);
char* caps_get_my_sha1(xmpp_ctx_t* const ctx); char* caps_get_my_sha1(xmpp_ctx_t* const ctx);
void caps_cache_clear(void);
#endif #endif

View File

@@ -1681,7 +1681,7 @@ _version_get_handler(xmpp_stanza_t* const stanza)
xmpp_stanza_t* name = xmpp_stanza_new(ctx); xmpp_stanza_t* name = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(name, "name"); xmpp_stanza_set_name(name, "name");
xmpp_stanza_t* name_txt = xmpp_stanza_new(ctx); xmpp_stanza_t* name_txt = xmpp_stanza_new(ctx);
xmpp_stanza_set_text(name_txt, is_custom_client ? client : "Profanity"); xmpp_stanza_set_text(name_txt, is_custom_client ? client : "Pidgin");
xmpp_stanza_add_child(name, name_txt); xmpp_stanza_add_child(name, name_txt);
xmpp_stanza_add_child(query, name); xmpp_stanza_add_child(query, name);
bool include_os = prefs_get_boolean(PREF_REVEAL_OS) && !is_custom_client; bool include_os = prefs_get_boolean(PREF_REVEAL_OS) && !is_custom_client;
@@ -1690,7 +1690,7 @@ _version_get_handler(xmpp_stanza_t* const stanza)
xmpp_stanza_t* version = xmpp_stanza_new(ctx); xmpp_stanza_t* version = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(version, "version"); xmpp_stanza_set_name(version, "version");
xmpp_stanza_t* version_txt = xmpp_stanza_new(ctx); xmpp_stanza_t* version_txt = xmpp_stanza_new(ctx);
auto_gchar gchar* prof_version = prof_get_version(); auto_gchar gchar* prof_version = g_strdup("");
if (!is_custom_client) { if (!is_custom_client) {
xmpp_stanza_set_text(version_txt, prof_version); xmpp_stanza_set_text(version_txt, prof_version);

View File

@@ -280,9 +280,13 @@ jid_fulljid_or_barejid(Jid* jid)
gchar* gchar*
jid_random_resource(void) jid_random_resource(void)
{ {
auto_gchar gchar* rand = get_random_string(4); gchar* rand = g_malloc0(29);
const gchar* digits = "0123456789";
gchar* result = g_strdup_printf("profanity.%s", rand); for (int i = 0; i < 28; i++) {
rand[i] = digits[g_random_int_range(0, 10)];
}
rand[28] = '\0';
return result; return rand;
} }

View File

@@ -178,7 +178,7 @@ session_connect_with_details(const char* const jid, const char* const passwd, co
saved_details.auth_policy = NULL; saved_details.auth_policy = NULL;
} }
// use 'profanity' when no resourcepart in provided jid // use random string when no resourcepart in provided jid
auto_jid Jid* jidp = jid_create(jid); auto_jid Jid* jidp = jid_create(jid);
if (jidp->resourcepart == NULL) { if (jidp->resourcepart == NULL) {
auto_gchar gchar* resource = jid_random_resource(); auto_gchar gchar* resource = jid_random_resource();

View File

@@ -32,6 +32,7 @@
static void _stanza_add_unique_id(xmpp_stanza_t* stanza); static void _stanza_add_unique_id(xmpp_stanza_t* stanza);
static gchar* _stanza_create_sha1_hash(char* str); static gchar* _stanza_create_sha1_hash(char* str);
static const char* _stanza_get_caps_node(const char* const client);
#if 0 #if 0
xmpp_stanza_t* xmpp_stanza_t*
@@ -930,23 +931,22 @@ stanza_create_caps_query_element(xmpp_ctx_t* ctx)
xmpp_stanza_t* identity = xmpp_stanza_new(ctx); xmpp_stanza_t* identity = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(identity, "identity"); xmpp_stanza_set_name(identity, "identity");
xmpp_stanza_set_type(identity, "pc");
xmpp_stanza_set_attribute(identity, "category", "client"); xmpp_stanza_set_attribute(identity, "category", "client");
ProfAccount* account = accounts_get_account(session_get_account_name()); ProfAccount* account = accounts_get_account(session_get_account_name());
gchar* client = account->client;
bool is_custom_client = client != NULL;
GString* name_str = g_string_new(is_custom_client ? client : "Profanity "); auto_gchar gchar* name = g_strdup(account->client ? account->client : "Pidgin");
if (!is_custom_client) {
xmpp_stanza_set_type(identity, "console"); if (account->client) {
auto_gchar gchar* prof_version = prof_get_version(); gchar* space = strchr(name, ' ');
g_string_append(name_str, prof_version); if (space) {
*space = '\0';
}
} }
account_free(account); account_free(account);
xmpp_stanza_set_attribute(identity, "name", name_str->str); xmpp_stanza_set_attribute(identity, "name", name);
g_string_free(name_str, TRUE);
xmpp_stanza_add_child(query, identity); xmpp_stanza_add_child(query, identity);
xmpp_stanza_release(identity); xmpp_stanza_release(identity);
@@ -1994,6 +1994,42 @@ stanza_attach_last_activity(xmpp_ctx_t* const ctx,
xmpp_stanza_release(query); xmpp_stanza_release(query);
} }
static const char*
_stanza_get_caps_node(const char* const client)
{
if (!client || g_strcmp0(client, "") == 0) {
return "http://pidgin.im";
}
auto_gchar gchar* lower = g_ascii_strdown(client, -1);
if (g_str_has_prefix(lower, "pidgin")) {
return "http://pidgin.im";
}
if (g_str_has_prefix(lower, "gajim")) {
return "https://gajim.org";
}
if (g_str_has_prefix(lower, "conversations")) {
return "https://conversations.im";
}
if (g_str_has_prefix(lower, "psi+")) {
return "http://psi-plus.com";
}
if (g_str_has_prefix(lower, "psi")) {
return "http://psi-im.org";
}
if (g_str_has_prefix(lower, "profanity")) {
return "http://profanity-im.github.io";
}
return "";
}
void void
stanza_attach_caps(xmpp_ctx_t* const ctx, xmpp_stanza_t* const presence) stanza_attach_caps(xmpp_ctx_t* const ctx, xmpp_stanza_t* const presence)
{ {
@@ -2002,9 +2038,13 @@ stanza_attach_caps(xmpp_ctx_t* const ctx, xmpp_stanza_t* const presence)
xmpp_stanza_set_ns(caps, STANZA_NS_CAPS); xmpp_stanza_set_ns(caps, STANZA_NS_CAPS);
xmpp_stanza_t* query = stanza_create_caps_query_element(ctx); xmpp_stanza_t* query = stanza_create_caps_query_element(ctx);
ProfAccount* account = accounts_get_account(session_get_account_name());
const char* node = _stanza_get_caps_node(account->client);
account_free(account);
char* sha1 = caps_get_my_sha1(ctx); char* sha1 = caps_get_my_sha1(ctx);
xmpp_stanza_set_attribute(caps, STANZA_ATTR_HASH, "sha-1"); xmpp_stanza_set_attribute(caps, STANZA_ATTR_HASH, "sha-1");
xmpp_stanza_set_attribute(caps, STANZA_ATTR_NODE, "http://profanity-im.github.io"); xmpp_stanza_set_attribute(caps, STANZA_ATTR_NODE, node);
xmpp_stanza_set_attribute(caps, STANZA_ATTR_VER, sha1); xmpp_stanza_set_attribute(caps, STANZA_ATTR_VER, sha1);
xmpp_stanza_add_child(presence, caps); xmpp_stanza_add_child(presence, caps);
xmpp_stanza_release(caps); xmpp_stanza_release(caps);

View File

@@ -601,11 +601,11 @@ prof_connect_with_roster(const char* roster)
assert_true(prof_output_regex(".+online.+ \\(priority 0\\)\\.")); assert_true(prof_output_regex(".+online.+ \\(priority 0\\)\\."));
expect_timeout = EXPECT_TIMEOUT_CONNECT; expect_timeout = EXPECT_TIMEOUT_CONNECT;
// Wait for presence stanza to be sent (content-based, not ID-based) // Wait for presence stanza to be sent
// Match the actual attribute order from stanza_attach_caps // Match the actual attribute order from stanza_attach_caps
assert_true(stbbr_received( assert_true(stbbr_received(
"<presence id=\"*\">" "<presence id=\"*\">"
"<c xmlns=\"http://jabber.org/protocol/caps\" hash=\"sha-1\" node=\"http://profanity-im.github.io\" ver=\"*\"/>" "<c xmlns=\"http://jabber.org/protocol/caps\" hash=\"sha-1\" node=\"*\" ver=\"*\"/>"
"</presence>")); "</presence>"));
} }

View File

@@ -25,7 +25,7 @@ connect_jid_sends_presence_after_receiving_roster(void **state)
assert_true(stbbr_received( assert_true(stbbr_received(
"<presence id='*'>" "<presence id='*'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
} }

View File

@@ -1289,7 +1289,7 @@ _join_muc(const char* room)
snprintf(presence, sizeof(presence), snprintf(presence, sizeof(presence),
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='%s/stabber'>" "<presence id='*' lang='en' to='stabber@localhost/profanity' from='%s/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' " "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' "
"node='http://profanity-im.github.io' ver='*'/>" "node='*' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>" "<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>" "<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
"</x>" "</x>"

View File

@@ -26,7 +26,7 @@ sends_room_join(void **state)
assert_true(stbbr_received( assert_true(stbbr_received(
"<presence id='*' to='testroom@conference.localhost/stabber'>" "<presence id='*' to='testroom@conference.localhost/stabber'>"
"<x xmlns='http://jabber.org/protocol/muc'/>" "<x xmlns='http://jabber.org/protocol/muc'/>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
} }
@@ -41,7 +41,7 @@ sends_room_join_with_nick(void **state)
assert_true(stbbr_received( assert_true(stbbr_received(
"<presence id='*' to='testroom@conference.localhost/testnick'>" "<presence id='*' to='testroom@conference.localhost/testnick'>"
"<x xmlns='http://jabber.org/protocol/muc'/>" "<x xmlns='http://jabber.org/protocol/muc'/>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
} }
@@ -58,7 +58,7 @@ sends_room_join_with_password(void **state)
"<x xmlns='http://jabber.org/protocol/muc'>" "<x xmlns='http://jabber.org/protocol/muc'>"
"<password>testpassword</password>" "<password>testpassword</password>"
"</x>" "</x>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
} }
@@ -75,7 +75,7 @@ sends_room_join_with_nick_and_password(void **state)
"<x xmlns='http://jabber.org/protocol/muc'>" "<x xmlns='http://jabber.org/protocol/muc'>"
"<password>testpassword</password>" "<password>testpassword</password>"
"</x>" "</x>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
} }
@@ -87,7 +87,7 @@ shows_role_and_affiliation_on_join(void **state)
stbbr_for_presence_to("testroom@conference.localhost/stabber", stbbr_for_presence_to("testroom@conference.localhost/stabber",
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>" "<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='*' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>" "<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>" "<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
"</x>" "</x>"
@@ -107,7 +107,7 @@ shows_subject_on_join(void **state)
stbbr_for_presence_to("testroom@conference.localhost/stabber", stbbr_for_presence_to("testroom@conference.localhost/stabber",
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>" "<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='*' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>" "<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>" "<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
"</x>" "</x>"
@@ -135,7 +135,7 @@ shows_history_message(void **state)
stbbr_for_presence_to("testroom@conference.localhost/stabber", stbbr_for_presence_to("testroom@conference.localhost/stabber",
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>" "<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='*' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>" "<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>" "<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
"</x>" "</x>"
@@ -170,7 +170,7 @@ shows_occupant_join(void **state)
stbbr_for_presence_to("testroom@conference.localhost/stabber", stbbr_for_presence_to("testroom@conference.localhost/stabber",
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>" "<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='*' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>" "<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>" "<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
"</x>" "</x>"
@@ -200,7 +200,7 @@ shows_message(void **state)
stbbr_for_presence_to("testroom@conference.localhost/stabber", stbbr_for_presence_to("testroom@conference.localhost/stabber",
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>" "<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='*' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>" "<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>" "<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
"</x>" "</x>"
@@ -227,7 +227,7 @@ shows_me_message_from_occupant(void **state)
stbbr_for_presence_to("testroom@conference.localhost/stabber", stbbr_for_presence_to("testroom@conference.localhost/stabber",
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>" "<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='*' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>" "<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>" "<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
"</x>" "</x>"
@@ -254,7 +254,7 @@ shows_me_message_from_self(void **state)
stbbr_for_presence_to("testroom@conference.localhost/stabber", stbbr_for_presence_to("testroom@conference.localhost/stabber",
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>" "<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='*' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>" "<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>" "<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
"</x>" "</x>"
@@ -281,7 +281,7 @@ shows_all_messages_in_console_when_window_not_focussed(void **state)
stbbr_for_presence_to("testroom@conference.localhost/stabber", stbbr_for_presence_to("testroom@conference.localhost/stabber",
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>" "<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='*' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>" "<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>" "<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
"</x>" "</x>"
@@ -322,7 +322,7 @@ shows_first_message_in_console_when_window_not_focussed(void **state)
stbbr_for_presence_to("testroom@conference.localhost/stabber", stbbr_for_presence_to("testroom@conference.localhost/stabber",
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>" "<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='*' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>" "<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>" "<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
"</x>" "</x>"
@@ -369,7 +369,7 @@ shows_no_message_in_console_when_window_not_focussed(void **state)
stbbr_for_presence_to("testroom@conference.localhost/stabber", stbbr_for_presence_to("testroom@conference.localhost/stabber",
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>" "<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='*' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>" "<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>" "<item role='participant' jid='stabber@localhost/profanity' affiliation='none'/>"
"</x>" "</x>"
@@ -401,7 +401,7 @@ sends_affiliation_list_request(void **state)
stbbr_for_presence_to("testroom@conference.localhost/stabber", stbbr_for_presence_to("testroom@conference.localhost/stabber",
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>" "<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='*' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>" "<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='moderator' jid='stabber@localhost/profanity' affiliation='owner'/>" "<item role='moderator' jid='stabber@localhost/profanity' affiliation='owner'/>"
"</x>" "</x>"
@@ -434,7 +434,7 @@ sends_kick_request(void **state)
stbbr_for_presence_to("testroom@conference.localhost/stabber", stbbr_for_presence_to("testroom@conference.localhost/stabber",
"<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>" "<presence id='*' lang='en' to='stabber@localhost/profanity' from='testroom@conference.localhost/stabber'>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='http://profanity-im.github.io' ver='*'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' node='*' ver='*'/>"
"<x xmlns='http://jabber.org/protocol/muc#user'>" "<x xmlns='http://jabber.org/protocol/muc#user'>"
"<item role='moderator' jid='stabber@localhost/profanity' affiliation='admin'/>" "<item role='moderator' jid='stabber@localhost/profanity' affiliation='admin'/>"
"</x>" "</x>"

View File

@@ -19,7 +19,7 @@ presence_online(void **state)
assert_true(stbbr_received( assert_true(stbbr_received(
"<presence id='*'>" "<presence id='*'>"
"<status>online</status>" "<status>online</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
} }
@@ -36,7 +36,7 @@ presence_online_with_message(void **state)
assert_true(stbbr_received( assert_true(stbbr_received(
"<presence id='*'>" "<presence id='*'>"
"<status>Hi there</status>" "<status>Hi there</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
} }
@@ -54,7 +54,7 @@ presence_away(void **state)
"<presence id='*'>" "<presence id='*'>"
"<show>away</show>" "<show>away</show>"
"<status>away</status>" "<status>away</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
} }
@@ -72,7 +72,7 @@ presence_away_with_message(void **state)
"<presence id='*'>" "<presence id='*'>"
"<show>away</show>" "<show>away</show>"
"<status>I'm not here for a bit</status>" "<status>I'm not here for a bit</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
} }
@@ -90,7 +90,7 @@ presence_xa(void **state)
"<presence id='*'>" "<presence id='*'>"
"<show>xa</show>" "<show>xa</show>"
"<status>xa</status>" "<status>xa</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
} }
@@ -108,7 +108,7 @@ presence_xa_with_message(void **state)
"<presence id='*'>" "<presence id='*'>"
"<show>xa</show>" "<show>xa</show>"
"<status>Gone to the shops</status>" "<status>Gone to the shops</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
} }
@@ -126,7 +126,7 @@ presence_dnd(void **state)
"<presence id='*'>" "<presence id='*'>"
"<show>dnd</show>" "<show>dnd</show>"
"<status>dnd</status>" "<status>dnd</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
} }
@@ -144,7 +144,7 @@ presence_dnd_with_message(void **state)
"<presence id='*'>" "<presence id='*'>"
"<show>dnd</show>" "<show>dnd</show>"
"<status>Working</status>" "<status>Working</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
} }
@@ -162,7 +162,7 @@ presence_chat(void **state)
"<presence id='*'>" "<presence id='*'>"
"<show>chat</show>" "<show>chat</show>"
"<status>chat</status>" "<status>chat</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
} }
@@ -180,7 +180,7 @@ presence_chat_with_message(void **state)
"<presence id='*'>" "<presence id='*'>"
"<show>chat</show>" "<show>chat</show>"
"<status>Free to talk</status>" "<status>Free to talk</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
} }
@@ -197,7 +197,7 @@ presence_set_priority(void **state)
assert_true(stbbr_received( assert_true(stbbr_received(
"<presence id='*'>" "<presence id='*'>"
"<priority>25</priority>" "<priority>25</priority>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
} }
@@ -212,7 +212,7 @@ presence_includes_priority(void **state)
assert_true(stbbr_received( assert_true(stbbr_received(
"<presence id='*'>" "<presence id='*'>"
"<priority>25</priority>" "<priority>25</priority>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
@@ -223,7 +223,7 @@ presence_includes_priority(void **state)
"<priority>25</priority>" "<priority>25</priority>"
"<show>chat</show>" "<show>chat</show>"
"<status>Free to talk</status>" "<status>Free to talk</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
} }
@@ -239,7 +239,7 @@ presence_keeps_status(void **state)
"<presence id='*'>" "<presence id='*'>"
"<show>chat</show>" "<show>chat</show>"
"<status>Free to talk</status>" "<status>Free to talk</status>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
@@ -250,7 +250,7 @@ presence_keeps_status(void **state)
"<show>chat</show>" "<show>chat</show>"
"<status>Free to talk</status>" "<status>Free to talk</status>"
"<priority>25</priority>" "<priority>25</priority>"
"<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='http://profanity-im.github.io'/>" "<c hash='sha-1' xmlns='http://jabber.org/protocol/caps' ver='*' node='*'/>"
"</presence>" "</presence>"
)); ));
} }

View File

@@ -500,6 +500,11 @@ caps_jid_has_feature(const char* const jid, const char* const feature)
return FALSE; return FALSE;
} }
void
caps_cache_clear(void)
{
}
gboolean gboolean
bookmark_add(const char* jid, const char* nick, const char* password, const char* autojoin_str, const char* name) bookmark_add(const char* jid, const char* nick, const char* password, const char* autojoin_str, const char* name)
{ {