Some checks failed
CI Code / Check coding style (pull_request) Failing after 5s
CI Code / Check spelling (pull_request) Successful in 15s
CI Code / Linux (ubuntu) (pull_request) Successful in 4m29s
CI Code / Linux (arch) (pull_request) Successful in 4m38s
CI Code / Linux (debian) (pull_request) Successful in 7m25s
CI Code / Code Coverage (pull_request) Successful in 7m28s
Merge profanity-im/profanity master (373 commits) into cproof fork.
Source changes (manual merge):
- src/command/: cmd_defs, cmd_funcs, cmd_ac — upstream g_new0, auto_gchar,
launch_editor callback; keep our XEP-0308 LMC, force-encryption, CWE-134
- src/config/: preferences, tlscerts, account — upstream UNIQUE dedup,
dynamic pad capacity; keep our db_history_result_t, scroll logic
- src/database.*: upstream g_new0 memory mgmt; keep our return types,
add null-check fix for msg->timestamp
- src/omemo/, src/pgp/: upstream _gpgme_key_get_email, g_new0;
keep our replace_id in omemo_on_message_send
- src/tools/: editor, http_upload, bookmark_ignore — upstream launch_editor
callback API
- src/ui/: console, window, chatwin, mucwin, inputwin, buffer —
upstream win_warn_needed/sent dedup, PAD_MIN_HEIGHT dynamic pads;
keep our y_start_pos scroll, _truncate_datetime_suffix
- src/xmpp/: message, stanza, presence, roster_list, iq, session —
upstream connection_get_available_resources; keep our LMC stanza logic
- src/common.c: fix format-security (cons_show)
Build system:
- Makefile.am: updated test paths to subdirectory structure, added
test_cmd_ac, test_forced_encryption
- Restored autotools files deleted by upstream meson migration:
bootstrap.sh, autogen.sh, m4/ax_valgrind_check.m4, configure-debug
Tests:
- Unit tests: upstream unittests.c base + our forced_encryption tests
(482 passed, 0 failed across all 4 configurations)
- Functional tests: kept our version (93 passed, 0 failed)
upstream version requires stbbr_for_xmlns not yet in our stabber fork
- Updated test stubs: stub_xmpp.c, stub_omemo.c from upstream
Compile fixes:
- src/common.c: cons_show(errmsg) -> cons_show("%s", errmsg)
- src/database.c: null-check before msg->timestamp access
- src/ui/console.c: size_t -> (int) cast for format width
- src/config/tlscerts.c: %d -> %zu for size_t
125 lines
3.1 KiB
C
125 lines
3.1 KiB
C
/*
|
|
* disco.c
|
|
* vim: expandtab:ts=4:sts=4:sw=4
|
|
*
|
|
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
|
*
|
|
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <glib.h>
|
|
|
|
// features to reference count map
|
|
static GHashTable* features = NULL;
|
|
|
|
// plugin to feature map
|
|
static GHashTable* plugin_to_features = NULL;
|
|
|
|
static void
|
|
_free_features(GHashTable* features)
|
|
{
|
|
g_hash_table_destroy(features);
|
|
}
|
|
|
|
void
|
|
disco_add_feature(const char* plugin_name, char* feature)
|
|
{
|
|
if (feature == NULL || plugin_name == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (!features) {
|
|
features = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
|
|
}
|
|
if (!plugin_to_features) {
|
|
plugin_to_features = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)_free_features);
|
|
}
|
|
|
|
GHashTable* plugin_features = g_hash_table_lookup(plugin_to_features, plugin_name);
|
|
gboolean added = FALSE;
|
|
if (plugin_features == NULL) {
|
|
plugin_features = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
|
|
g_hash_table_add(plugin_features, g_strdup(feature));
|
|
g_hash_table_insert(plugin_to_features, g_strdup(plugin_name), plugin_features);
|
|
added = TRUE;
|
|
} else if (!g_hash_table_contains(plugin_features, feature)) {
|
|
g_hash_table_add(plugin_features, g_strdup(feature));
|
|
added = TRUE;
|
|
}
|
|
|
|
if (added == FALSE) {
|
|
return;
|
|
}
|
|
|
|
if (!g_hash_table_contains(features, feature)) {
|
|
g_hash_table_insert(features, g_strdup(feature), GINT_TO_POINTER(1));
|
|
} else {
|
|
void* refcountp = g_hash_table_lookup(features, feature);
|
|
int refcount = GPOINTER_TO_INT(refcountp);
|
|
refcount++;
|
|
g_hash_table_replace(features, g_strdup(feature), GINT_TO_POINTER(refcount));
|
|
}
|
|
}
|
|
|
|
void
|
|
disco_remove_features(const char* plugin_name)
|
|
{
|
|
if (!features) {
|
|
return;
|
|
}
|
|
if (!plugin_to_features) {
|
|
return;
|
|
}
|
|
|
|
GHashTable* plugin_features_set = g_hash_table_lookup(plugin_to_features, plugin_name);
|
|
if (!plugin_features_set) {
|
|
return;
|
|
}
|
|
|
|
GHashTableIter iter;
|
|
gpointer key, value;
|
|
g_hash_table_iter_init(&iter, plugin_features_set);
|
|
while (g_hash_table_iter_next(&iter, &key, &value)) {
|
|
char* feature = (char*)key;
|
|
if (g_hash_table_contains(features, feature)) {
|
|
void* refcountp = g_hash_table_lookup(features, feature);
|
|
int refcount = GPOINTER_TO_INT(refcountp);
|
|
if (refcount == 1) {
|
|
g_hash_table_remove(features, feature);
|
|
} else {
|
|
refcount--;
|
|
g_hash_table_replace(features, g_strdup(feature), GINT_TO_POINTER(refcount));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
GList*
|
|
disco_get_features(void)
|
|
{
|
|
if (features == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
return g_hash_table_get_keys(features);
|
|
}
|
|
|
|
void
|
|
disco_close(void)
|
|
{
|
|
if (features) {
|
|
g_hash_table_destroy(features);
|
|
features = NULL;
|
|
}
|
|
|
|
if (plugin_to_features) {
|
|
g_hash_table_destroy(plugin_to_features);
|
|
plugin_to_features = NULL;
|
|
}
|
|
}
|