merge: sync upstream profanity-im/profanity
All checks were successful
CI Code / Check spelling (push) Successful in 18s
CI Code / Check coding style (push) Successful in 34s
CI Code / Code Coverage (push) Successful in 2m36s
CI Code / Linux (debian) (push) Successful in 4m41s
CI Code / Linux (ubuntu) (push) Successful in 4m52s
CI Code / Linux (arch) (push) Successful in 5m40s
All checks were successful
CI Code / Check spelling (push) Successful in 18s
CI Code / Check coding style (push) Successful in 34s
CI Code / Code Coverage (push) Successful in 2m36s
CI Code / Linux (debian) (push) Successful in 4m41s
CI Code / Linux (ubuntu) (push) Successful in 4m52s
CI Code / Linux (arch) (push) Successful in 5m40s
Sync with upstream profanity-im/profanity.
Major upstream changes incorporated:
Memory management
- Replace malloc+memset with g_new0 throughout codebase
- Adopt auto_gchar / auto_gcharv / auto_gerror / auto_jid cleanup macros
- Replace free() with g_free() for GAlloc'd memory
Editor rewrite
- Remove pthread-based async editor; use GChildWatch callback API
- New launch_editor(initial_content, callback, user_data) interface
- Proper signal handling (SIGINT, SIGTSTP, SIGPIPE reset in child)
- ui_suspend()/ui_resume() integration for TTY management
OMEMO improvements
- Dual backend support: libsignal-protocol-c and libomemo-c
- Proper pre-key removal after use (XEP-0384 compliance)
- Automatic pre-key regeneration when store drops below threshold
- New functions: omemo_is_device_active(), omemo_is_jid_trusted()
- omemo_get_jid_untrusted_fingerprints() for better error messages
- Fingerprint notifications on new device identity discovery
- Deterministic pre-key ID generation tracking max_pre_key_id
- omemo_trust_changed() UI updates on trust state changes
JID validation
- RFC 6122-compliant validation in jid_is_valid()
- Character-level checks (RFC 6122 forbidden chars: & ' / : < > @)
- Length limits: 1023 per component, 3071 total
- New jid_is_valid_user_jid() for user vs. service JID distinction
Database
- Schema migration v3: UNIQUE constraint on archive_id for deduplication
- Triggers for corrected message tracking (replaces_db_id / replaced_by_db_id)
- db_history_result_t return type, _truncate_datetime_suffix()
UI / console
- win_warn_needed() / win_warn_sent() warning deduplication hash table
- PAD_MIN_HEIGHT dynamic pad sizing with PAD_THRESHOLD auto-cleanup
- Spellcheck integration in input field with Unicode word detection
- cons_spellcheck_setting() for /settings ui output
- /[command]? shortcut for command help
Account config
- Account name sanitization for GKeyFile special chars ([ ] = # \n \r)
- Replace popen() with g_spawn_sync() for eval_password
- TLS policy: add "direct" option alongside legacy
Connection
- Port validation with g_assert (0–65535)
- SHA-256 certificate fingerprint support (XMPP_CERT_PUBKEY_FINGERPRINT_SHA256)
- "direct" TLS policy alias for legacy SSL
Common utilities
- str_xml_sanitize() for XML 1.0 illegal character removal
- string_matches_one_of() with formatted error messages
- valid_tls_policy_option() helper
- prof_date_time_format_iso8601() utility
- Improved strip_arg_quotes() with backslash unescaping
- prof_occurrences() uses g_slist_prepend + reverse for performance
PGP / OX
- Proper GPGME resource cleanup with goto-cleanup pattern
- g_string_free(xmppuri) leak fix in _ox_key_lookup
CSV export
- Use GString + g_file_set_contents instead of raw write() syscalls
Tests
- Restructured into subdirectories: command/, config/, xmpp/, ui/, omemo/, otr/, pgp/
- New test_cmd_ac.c for autocompleter unit tests
- Updated stubs for new UI suspend/resume functions
License headers
- Migrate to SPDX-3.0 identifiers (GPL-3.0-or-later WITH OpenSSL-exception)
────────────────────────────────────────────────────
cproof-specific preservations:
- XEP-0308 LMC: replace_id ?: id logic in message/stanza/omemo
- Force encryption: cmd_force_encryption, test_forced_encryption
- CWE-134: format string protection (cons_show("%s", ...))
- y_start_pos-based paging in window.c
- db_history_result_t return type, _truncate_datetime_suffix()
Merge-time fixes:
- common.c: format-security (-Werror) — cons_show(errmsg) → cons_show("%s", errmsg)
- database.c: null-deref guard — !msg->timestamp → msg && !msg->timestamp
- console.c: implicit size_t → int cast — (int)(maxlen + 1)
- tlscerts.c: %d for size_t — %zu
Build system:
- Kept autotools (Makefile.am, configure.ac); upstream uses Meson
- Restored deleted files: bootstrap.sh, autogen.sh, ax_valgrind_check.m4, configure-debug
- Updated Makefile.am test paths for subdirectory structure
- Added test_cmd_ac, test_forced_encryption to test sources
Functional tests:
- Use cproof version; upstream requires stbbr_for_xmlns from updated stabber
- Not yet available in devs/stabber fork
Closes #64
Merge author: jabber.developer2
Commits authors:
Michael Vetter <jubalh@iodoru.org>
& Steffen Jaeckel <s@jaeckel.eu>
This commit is contained in:
@@ -4,33 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -39,6 +13,7 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
@@ -59,7 +34,7 @@ account_new(gchar* name, gchar* jid, gchar* password, gchar* eval_password, gboo
|
||||
gchar* startscript, gchar* theme, gchar* tls_policy, gchar* auth_policy,
|
||||
gchar* client, int max_sessions)
|
||||
{
|
||||
ProfAccount* new_account = calloc(1, sizeof(ProfAccount));
|
||||
ProfAccount* new_account = g_new0(ProfAccount, 1);
|
||||
|
||||
new_account->name = name;
|
||||
|
||||
@@ -144,13 +119,13 @@ account_new(gchar* name, gchar* jid, gchar* password, gchar* eval_password, gboo
|
||||
return new_account;
|
||||
}
|
||||
|
||||
char*
|
||||
gchar*
|
||||
account_create_connect_jid(ProfAccount* account)
|
||||
{
|
||||
if (account->resource) {
|
||||
return create_fulljid(account->jid, account->resource);
|
||||
} else {
|
||||
return strdup(account->jid);
|
||||
return g_strdup(account->jid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,53 +135,41 @@ account_eval_password(ProfAccount* account)
|
||||
assert(account != NULL);
|
||||
assert(account->eval_password != NULL);
|
||||
|
||||
errno = 0;
|
||||
gchar* stdout_buf = NULL;
|
||||
GError* error = NULL;
|
||||
gint exit_status = 0;
|
||||
gchar** argv = NULL;
|
||||
|
||||
FILE* stream = popen(account->eval_password, "r");
|
||||
if (stream == NULL) {
|
||||
const char* errmsg = strerror(errno);
|
||||
if (errmsg) {
|
||||
log_error("Could not execute `eval_password` command (%s).",
|
||||
errmsg);
|
||||
} else {
|
||||
log_error("Failed to allocate memory for `eval_password` command.");
|
||||
if (!g_shell_parse_argv(account->eval_password, NULL, &argv, &error)) {
|
||||
log_error("Failed to parse `eval_password` command: %s", error->message);
|
||||
g_error_free(error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!g_spawn_sync(NULL, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_CHILD_INHERITS_STDIN, NULL, NULL, &stdout_buf, NULL, &exit_status, &error)) {
|
||||
log_error("Failed to execute `eval_password` command: %s", error->message);
|
||||
g_strfreev(argv);
|
||||
g_error_free(error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_strfreev(argv);
|
||||
|
||||
if (WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == 0) {
|
||||
account->password = stdout_buf;
|
||||
g_strstrip(account->password);
|
||||
if (account->password[0] == '\0') {
|
||||
log_error("Empty password returned by `eval_password` command.");
|
||||
g_free(account->password);
|
||||
account->password = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
} else {
|
||||
log_error("`eval_password` command failed with status %d", exit_status);
|
||||
g_free(stdout_buf);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
account->password = g_malloc(READ_BUF_SIZE);
|
||||
if (!account->password) {
|
||||
log_error("Failed to allocate enough memory to read `eval_password` "
|
||||
"output.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
account->password = fgets(account->password, READ_BUF_SIZE, stream);
|
||||
if (!account->password) {
|
||||
log_error("Failed to read password from stream.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int exit_status = pclose(stream);
|
||||
if (exit_status > 0) {
|
||||
log_error("Command for `eval_password` returned error status (%d).",
|
||||
exit_status);
|
||||
return FALSE;
|
||||
} else if (exit_status < 0) {
|
||||
log_error("Failed to close stream for `eval_password` command output "
|
||||
"(%s).",
|
||||
strerror(errno));
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
// Remove leading and trailing whitespace from output.
|
||||
g_strstrip(account->password);
|
||||
if (!account->password) {
|
||||
log_error("Empty password returned by `eval_password` command.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -4,33 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_ACCOUNT_H
|
||||
@@ -84,7 +58,7 @@ ProfAccount* account_new(gchar* name, gchar* jid, gchar* password, gchar* eval_p
|
||||
GList* ox_enabled, GList* pgp_enabled, gchar* pgp_keyid,
|
||||
gchar* startscript, gchar* theme, gchar* tls_policy, gchar* auth_policy,
|
||||
gchar* client, int max_sessions);
|
||||
char* account_create_connect_jid(ProfAccount* account);
|
||||
gchar* account_create_connect_jid(ProfAccount* account);
|
||||
gboolean account_eval_password(ProfAccount* account);
|
||||
void account_free(ProfAccount* account);
|
||||
void account_set_server(ProfAccount* account, const char* server);
|
||||
|
||||
@@ -3,35 +3,9 @@
|
||||
* vim: expandtab:ts=4:sts=4:sw=4
|
||||
*
|
||||
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
||||
* Copyright (C) 2019 - 2025 Michael Vetter <jubalh@iodoru.org>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
* Copyright (C) 2019 - 2026 Michael Vetter <jubalh@iodoru.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -59,7 +33,74 @@ static GKeyFile* accounts;
|
||||
static Autocomplete all_ac;
|
||||
static Autocomplete enabled_ac;
|
||||
|
||||
static void _save_accounts(void);
|
||||
static gchar*
|
||||
_sanitize_account_name(const char* const name)
|
||||
{
|
||||
if (!name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gchar* sanitized = g_strdup(name);
|
||||
gchar* p = sanitized;
|
||||
while (*p) {
|
||||
// GKeyFile special characters: [ ] = # \n \r
|
||||
if (*p == '[' || *p == ']' || *p == '=' || *p == '#' || *p == '\n' || *p == '\r') {
|
||||
*p = '_';
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
return sanitized;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_accounts_has_group(const char* account_name)
|
||||
{
|
||||
if (!account_name || !accounts)
|
||||
return FALSE;
|
||||
|
||||
auto_gchar gchar* sanitized = _sanitize_account_name(account_name);
|
||||
return g_key_file_has_group(accounts, sanitized);
|
||||
}
|
||||
|
||||
static void
|
||||
_accounts_save(const char* account_name)
|
||||
{
|
||||
prof_keyfile_t current;
|
||||
|
||||
if (!load_data_keyfile(¤t, FILE_ACCOUNTS)) {
|
||||
log_error("Could not load accounts");
|
||||
return;
|
||||
}
|
||||
|
||||
auto_gchar gchar* sanitized = _sanitize_account_name(account_name);
|
||||
|
||||
if (_accounts_has_group(sanitized)) {
|
||||
// Remove keys from file that are no longer in memory
|
||||
gsize nkeys_disk;
|
||||
auto_gcharv gchar** keys_disk = g_key_file_get_keys(current.keyfile, sanitized, &nkeys_disk, NULL);
|
||||
if (keys_disk) {
|
||||
for (gsize j = 0; j < nkeys_disk; ++j) {
|
||||
if (!g_key_file_has_key(accounts_prof_keyfile.keyfile, sanitized, keys_disk[j], NULL)) {
|
||||
g_key_file_remove_key(current.keyfile, sanitized, keys_disk[j], NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gsize nkeys;
|
||||
auto_gcharv gchar** keys = g_key_file_get_keys(accounts_prof_keyfile.keyfile, sanitized, &nkeys, NULL);
|
||||
if (keys) {
|
||||
for (gsize j = 0; j < nkeys; ++j) {
|
||||
auto_gchar gchar* new_value = g_key_file_get_value(accounts_prof_keyfile.keyfile, sanitized, keys[j], NULL);
|
||||
g_key_file_set_value(current.keyfile, sanitized, keys[j], new_value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
g_key_file_remove_group(current.keyfile, sanitized, NULL);
|
||||
}
|
||||
save_keyfile(¤t);
|
||||
free_keyfile(¤t);
|
||||
}
|
||||
|
||||
static void
|
||||
_accounts_close(void)
|
||||
@@ -79,7 +120,9 @@ accounts_load(void)
|
||||
|
||||
all_ac = autocomplete_new();
|
||||
enabled_ac = autocomplete_new();
|
||||
load_data_keyfile(&accounts_prof_keyfile, FILE_ACCOUNTS);
|
||||
if (!load_data_keyfile(&accounts_prof_keyfile, FILE_ACCOUNTS)) {
|
||||
log_error("Could not load accounts");
|
||||
}
|
||||
accounts = accounts_prof_keyfile.keyfile;
|
||||
|
||||
// create the logins searchable list for autocompletion
|
||||
@@ -132,54 +175,58 @@ accounts_add(const char* account_name, const char* altdomain, const int port, co
|
||||
}
|
||||
}
|
||||
|
||||
if (g_key_file_has_group(accounts, account_name)) {
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
|
||||
if (_accounts_has_group(sanitized_account_name)) {
|
||||
log_error("Can't add account \"%s\", it already exists.", account_name);
|
||||
return;
|
||||
}
|
||||
|
||||
g_key_file_set_boolean(accounts, account_name, "enabled", TRUE);
|
||||
g_key_file_set_string(accounts, account_name, "jid", barejid);
|
||||
g_key_file_set_string(accounts, account_name, "resource", resource);
|
||||
g_key_file_set_boolean(accounts, sanitized_account_name, "enabled", TRUE);
|
||||
g_key_file_set_string(accounts, sanitized_account_name, "jid", barejid);
|
||||
g_key_file_set_string(accounts, sanitized_account_name, "resource", resource);
|
||||
if (altdomain) {
|
||||
g_key_file_set_string(accounts, account_name, "server", altdomain);
|
||||
g_key_file_set_string(accounts, sanitized_account_name, "server", altdomain);
|
||||
}
|
||||
if (port != 0) {
|
||||
g_key_file_set_integer(accounts, account_name, "port", port);
|
||||
g_key_file_set_integer(accounts, sanitized_account_name, "port", port);
|
||||
}
|
||||
if (tls_policy) {
|
||||
g_key_file_set_string(accounts, account_name, "tls.policy", tls_policy);
|
||||
g_key_file_set_string(accounts, sanitized_account_name, "tls.policy", tls_policy);
|
||||
}
|
||||
if (auth_policy) {
|
||||
g_key_file_set_string(accounts, account_name, "auth.policy", auth_policy);
|
||||
g_key_file_set_string(accounts, sanitized_account_name, "auth.policy", auth_policy);
|
||||
}
|
||||
|
||||
auto_jid Jid* jidp = jid_create(barejid);
|
||||
|
||||
if (jidp->localpart == NULL) {
|
||||
g_key_file_set_string(accounts, account_name, "muc.nick", jidp->domainpart);
|
||||
g_key_file_set_string(accounts, sanitized_account_name, "muc.nick", jidp->domainpart);
|
||||
} else {
|
||||
g_key_file_set_string(accounts, account_name, "muc.nick", jidp->localpart);
|
||||
g_key_file_set_string(accounts, sanitized_account_name, "muc.nick", jidp->localpart);
|
||||
}
|
||||
|
||||
g_key_file_set_string(accounts, account_name, "presence.last", "online");
|
||||
g_key_file_set_string(accounts, account_name, "presence.login", "online");
|
||||
g_key_file_set_integer(accounts, account_name, "priority.online", 0);
|
||||
g_key_file_set_integer(accounts, account_name, "priority.chat", 0);
|
||||
g_key_file_set_integer(accounts, account_name, "priority.away", 0);
|
||||
g_key_file_set_integer(accounts, account_name, "priority.xa", 0);
|
||||
g_key_file_set_integer(accounts, account_name, "priority.dnd", 0);
|
||||
g_key_file_set_string(accounts, sanitized_account_name, "presence.last", "online");
|
||||
g_key_file_set_string(accounts, sanitized_account_name, "presence.login", "online");
|
||||
g_key_file_set_integer(accounts, sanitized_account_name, "priority.online", 0);
|
||||
g_key_file_set_integer(accounts, sanitized_account_name, "priority.chat", 0);
|
||||
g_key_file_set_integer(accounts, sanitized_account_name, "priority.away", 0);
|
||||
g_key_file_set_integer(accounts, sanitized_account_name, "priority.xa", 0);
|
||||
g_key_file_set_integer(accounts, sanitized_account_name, "priority.dnd", 0);
|
||||
|
||||
_save_accounts();
|
||||
autocomplete_add(all_ac, account_name);
|
||||
autocomplete_add(enabled_ac, account_name);
|
||||
_accounts_save(account_name);
|
||||
autocomplete_add(all_ac, sanitized_account_name);
|
||||
autocomplete_add(enabled_ac, sanitized_account_name);
|
||||
}
|
||||
|
||||
int
|
||||
gboolean
|
||||
accounts_remove(const char* account_name)
|
||||
{
|
||||
int r = g_key_file_remove_group(accounts, account_name, NULL);
|
||||
_save_accounts();
|
||||
autocomplete_remove(all_ac, account_name);
|
||||
autocomplete_remove(enabled_ac, account_name);
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
gboolean r = g_key_file_remove_group(accounts, sanitized_account_name, NULL);
|
||||
_accounts_save(account_name);
|
||||
autocomplete_remove(all_ac, sanitized_account_name);
|
||||
autocomplete_remove(enabled_ac, sanitized_account_name);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -189,167 +236,123 @@ accounts_get_list(void)
|
||||
return g_key_file_get_groups(accounts, NULL);
|
||||
}
|
||||
|
||||
ProfAccount*
|
||||
accounts_get_account(const char* const name)
|
||||
static GList*
|
||||
_g_strv_to_glist(gchar** in, gsize length)
|
||||
{
|
||||
if (!g_key_file_has_group(accounts, name)) {
|
||||
if (in == NULL)
|
||||
return NULL;
|
||||
GList* out = NULL;
|
||||
for (gsize i = 0; i < length; i++) {
|
||||
out = g_list_append(out, in[i]);
|
||||
}
|
||||
g_free(in);
|
||||
return out;
|
||||
}
|
||||
|
||||
static GList*
|
||||
_accounts_get_glist(const gchar* sanitized_account_name,
|
||||
const gchar* key)
|
||||
{
|
||||
gsize length = 0;
|
||||
gchar** list = g_key_file_get_string_list(accounts, sanitized_account_name, key, &length, NULL);
|
||||
return _g_strv_to_glist(list, length);
|
||||
}
|
||||
|
||||
ProfAccount*
|
||||
accounts_get_account(const char* const account_name)
|
||||
{
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (!_accounts_has_group(sanitized_account_name)) {
|
||||
return NULL;
|
||||
} else {
|
||||
gchar* jid = g_key_file_get_string(accounts, name, "jid", NULL);
|
||||
gchar* jid = g_key_file_get_string(accounts, sanitized_account_name, "jid", NULL);
|
||||
|
||||
// fix accounts that have no jid property by setting to name
|
||||
// fix accounts that have no jid property by setting to account_name
|
||||
if (jid == NULL) {
|
||||
g_key_file_set_string(accounts, name, "jid", name);
|
||||
_save_accounts();
|
||||
g_key_file_set_string(accounts, sanitized_account_name, "jid", account_name);
|
||||
_accounts_save(account_name);
|
||||
}
|
||||
|
||||
gchar* password = g_key_file_get_string(accounts, name, "password", NULL);
|
||||
gchar* eval_password = g_key_file_get_string(accounts, name, "eval_password", NULL);
|
||||
gboolean enabled = g_key_file_get_boolean(accounts, name, "enabled", NULL);
|
||||
gchar* password = g_key_file_get_string(accounts, sanitized_account_name, "password", NULL);
|
||||
gchar* eval_password = g_key_file_get_string(accounts, sanitized_account_name, "eval_password", NULL);
|
||||
gboolean enabled = g_key_file_get_boolean(accounts, sanitized_account_name, "enabled", NULL);
|
||||
|
||||
gchar* server = g_key_file_get_string(accounts, name, "server", NULL);
|
||||
gchar* resource = g_key_file_get_string(accounts, name, "resource", NULL);
|
||||
int port = g_key_file_get_integer(accounts, name, "port", NULL);
|
||||
gchar* server = g_key_file_get_string(accounts, sanitized_account_name, "server", NULL);
|
||||
gchar* resource = g_key_file_get_string(accounts, sanitized_account_name, "resource", NULL);
|
||||
int port = g_key_file_get_integer(accounts, sanitized_account_name, "port", NULL);
|
||||
|
||||
gchar* last_presence = g_key_file_get_string(accounts, name, "presence.last", NULL);
|
||||
gchar* login_presence = g_key_file_get_string(accounts, name, "presence.login", NULL);
|
||||
gchar* last_presence = g_key_file_get_string(accounts, sanitized_account_name, "presence.last", NULL);
|
||||
gchar* login_presence = g_key_file_get_string(accounts, sanitized_account_name, "presence.login", NULL);
|
||||
|
||||
int priority_online = g_key_file_get_integer(accounts, name, "priority.online", NULL);
|
||||
int priority_chat = g_key_file_get_integer(accounts, name, "priority.chat", NULL);
|
||||
int priority_away = g_key_file_get_integer(accounts, name, "priority.away", NULL);
|
||||
int priority_xa = g_key_file_get_integer(accounts, name, "priority.xa", NULL);
|
||||
int priority_dnd = g_key_file_get_integer(accounts, name, "priority.dnd", NULL);
|
||||
int priority_online = g_key_file_get_integer(accounts, sanitized_account_name, "priority.online", NULL);
|
||||
int priority_chat = g_key_file_get_integer(accounts, sanitized_account_name, "priority.chat", NULL);
|
||||
int priority_away = g_key_file_get_integer(accounts, sanitized_account_name, "priority.away", NULL);
|
||||
int priority_xa = g_key_file_get_integer(accounts, sanitized_account_name, "priority.xa", NULL);
|
||||
int priority_dnd = g_key_file_get_integer(accounts, sanitized_account_name, "priority.dnd", NULL);
|
||||
|
||||
gchar* muc_service = NULL;
|
||||
if (g_key_file_has_key(accounts, name, "muc.service", NULL)) {
|
||||
muc_service = g_key_file_get_string(accounts, name, "muc.service", NULL);
|
||||
if (g_key_file_has_key(accounts, sanitized_account_name, "muc.service", NULL)) {
|
||||
muc_service = g_key_file_get_string(accounts, sanitized_account_name, "muc.service", NULL);
|
||||
} else {
|
||||
jabber_conn_status_t conn_status = connection_get_status();
|
||||
if (conn_status == JABBER_CONNECTED) {
|
||||
const char* conf_jid = connection_jid_for_feature(XMPP_FEATURE_MUC);
|
||||
if (conf_jid) {
|
||||
muc_service = strdup(conf_jid);
|
||||
muc_service = g_strdup(conf_jid);
|
||||
}
|
||||
}
|
||||
}
|
||||
gchar* muc_nick = g_key_file_get_string(accounts, name, "muc.nick", NULL);
|
||||
gchar* muc_nick = g_key_file_get_string(accounts, sanitized_account_name, "muc.nick", NULL);
|
||||
|
||||
gchar* otr_policy = NULL;
|
||||
if (g_key_file_has_key(accounts, name, "otr.policy", NULL)) {
|
||||
otr_policy = g_key_file_get_string(accounts, name, "otr.policy", NULL);
|
||||
}
|
||||
gchar* otr_policy = g_key_file_get_string(accounts, sanitized_account_name, "otr.policy", NULL);
|
||||
GList* otr_manual = _accounts_get_glist(sanitized_account_name, "otr.manual");
|
||||
GList* otr_opportunistic = _accounts_get_glist(sanitized_account_name, "otr.opportunistic");
|
||||
GList* otr_always = _accounts_get_glist(sanitized_account_name, "otr.always");
|
||||
|
||||
gsize length;
|
||||
GList* otr_manual = NULL;
|
||||
auto_gcharv gchar** manual = g_key_file_get_string_list(accounts, name, "otr.manual", &length, NULL);
|
||||
if (manual) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
otr_manual = g_list_append(otr_manual, strdup(manual[i]));
|
||||
}
|
||||
}
|
||||
gchar* omemo_policy = g_key_file_get_string(accounts, sanitized_account_name, "omemo.policy", NULL);
|
||||
GList* omemo_enabled = _accounts_get_glist(sanitized_account_name, "omemo.enabled");
|
||||
GList* omemo_disabled = _accounts_get_glist(sanitized_account_name, "omemo.disabled");
|
||||
|
||||
GList* otr_opportunistic = NULL;
|
||||
auto_gcharv gchar** opportunistic = g_key_file_get_string_list(accounts, name, "otr.opportunistic", &length, NULL);
|
||||
if (opportunistic) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
otr_opportunistic = g_list_append(otr_opportunistic, strdup(opportunistic[i]));
|
||||
}
|
||||
}
|
||||
GList* ox_enabled = _accounts_get_glist(sanitized_account_name, "ox.enabled");
|
||||
|
||||
GList* otr_always = NULL;
|
||||
auto_gcharv gchar** always = g_key_file_get_string_list(accounts, name, "otr.always", &length, NULL);
|
||||
if (always) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
otr_always = g_list_append(otr_always, strdup(always[i]));
|
||||
}
|
||||
}
|
||||
GList* pgp_enabled = _accounts_get_glist(sanitized_account_name, "pgp.enabled");
|
||||
|
||||
gchar* omemo_policy = NULL;
|
||||
if (g_key_file_has_key(accounts, name, "omemo.policy", NULL)) {
|
||||
omemo_policy = g_key_file_get_string(accounts, name, "omemo.policy", NULL);
|
||||
}
|
||||
gchar* pgp_keyid = g_key_file_get_string(accounts, sanitized_account_name, "pgp.keyid", NULL);
|
||||
|
||||
GList* omemo_enabled = NULL;
|
||||
auto_gcharv gchar** omemo_enabled_list = g_key_file_get_string_list(accounts, name, "omemo.enabled", &length, NULL);
|
||||
if (omemo_enabled_list) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
omemo_enabled = g_list_append(omemo_enabled, strdup(omemo_enabled_list[i]));
|
||||
}
|
||||
}
|
||||
gchar* startscript = g_key_file_get_string(accounts, sanitized_account_name, "script.start", NULL);
|
||||
|
||||
GList* omemo_disabled = NULL;
|
||||
auto_gcharv gchar** omemo_disabled_list = g_key_file_get_string_list(accounts, name, "omemo.disabled", &length, NULL);
|
||||
if (omemo_disabled_list) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
omemo_disabled = g_list_append(omemo_disabled, strdup(omemo_disabled_list[i]));
|
||||
}
|
||||
}
|
||||
gchar* client = g_key_file_get_string(accounts, sanitized_account_name, "client.account_name", NULL);
|
||||
|
||||
GList* ox_enabled = NULL;
|
||||
auto_gcharv gchar** ox_enabled_list = g_key_file_get_string_list(accounts, name, "ox.enabled", &length, NULL);
|
||||
if (ox_enabled_list) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
ox_enabled = g_list_append(ox_enabled, strdup(ox_enabled_list[i]));
|
||||
}
|
||||
}
|
||||
gchar* theme = g_key_file_get_string(accounts, sanitized_account_name, "theme", NULL);
|
||||
|
||||
GList* pgp_enabled = NULL;
|
||||
auto_gcharv gchar** pgp_enabled_list = g_key_file_get_string_list(accounts, name, "pgp.enabled", &length, NULL);
|
||||
if (pgp_enabled_list) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
pgp_enabled = g_list_append(pgp_enabled, strdup(pgp_enabled_list[i]));
|
||||
}
|
||||
}
|
||||
|
||||
gchar* pgp_keyid = NULL;
|
||||
if (g_key_file_has_key(accounts, name, "pgp.keyid", NULL)) {
|
||||
pgp_keyid = g_key_file_get_string(accounts, name, "pgp.keyid", NULL);
|
||||
}
|
||||
|
||||
gchar* startscript = NULL;
|
||||
if (g_key_file_has_key(accounts, name, "script.start", NULL)) {
|
||||
startscript = g_key_file_get_string(accounts, name, "script.start", NULL);
|
||||
}
|
||||
|
||||
gchar* client = NULL;
|
||||
if (g_key_file_has_key(accounts, name, "client.name", NULL)) {
|
||||
client = g_key_file_get_string(accounts, name, "client.name", NULL);
|
||||
}
|
||||
|
||||
gchar* theme = NULL;
|
||||
if (g_key_file_has_key(accounts, name, "theme", NULL)) {
|
||||
theme = g_key_file_get_string(accounts, name, "theme", NULL);
|
||||
}
|
||||
|
||||
gchar* tls_policy = g_key_file_get_string(accounts, name, "tls.policy", NULL);
|
||||
if (tls_policy && ((g_strcmp0(tls_policy, "force") != 0) && (g_strcmp0(tls_policy, "allow") != 0) && (g_strcmp0(tls_policy, "trust") != 0) && (g_strcmp0(tls_policy, "disable") != 0) && (g_strcmp0(tls_policy, "legacy") != 0))) {
|
||||
gchar* tls_policy = g_key_file_get_string(accounts, sanitized_account_name, "tls.policy", NULL);
|
||||
if (tls_policy && !valid_tls_policy_option(tls_policy)) {
|
||||
g_free(tls_policy);
|
||||
tls_policy = NULL;
|
||||
}
|
||||
|
||||
gchar* auth_policy = g_key_file_get_string(accounts, name, "auth.policy", NULL);
|
||||
gchar* auth_policy = g_key_file_get_string(accounts, sanitized_account_name, "auth.policy", NULL);
|
||||
|
||||
int max_sessions = g_key_file_get_integer(accounts, name, "max.sessions", 0);
|
||||
int max_sessions = g_key_file_get_integer(accounts, sanitized_account_name, "max.sessions", 0);
|
||||
|
||||
ProfAccount* new_account = account_new(g_strdup(name), jid, password, eval_password, enabled,
|
||||
server, port, resource, last_presence, login_presence,
|
||||
priority_online, priority_chat, priority_away, priority_xa,
|
||||
priority_dnd, muc_service, muc_nick, otr_policy, otr_manual,
|
||||
otr_opportunistic, otr_always, omemo_policy, omemo_enabled,
|
||||
omemo_disabled, ox_enabled, pgp_enabled, pgp_keyid,
|
||||
startscript, theme, tls_policy, auth_policy, client, max_sessions);
|
||||
|
||||
return new_account;
|
||||
return account_new(g_strdup(account_name), jid, password, eval_password, enabled,
|
||||
server, port, resource, last_presence, login_presence,
|
||||
priority_online, priority_chat, priority_away, priority_xa,
|
||||
priority_dnd, muc_service, muc_nick, otr_policy, otr_manual,
|
||||
otr_opportunistic, otr_always, omemo_policy, omemo_enabled,
|
||||
omemo_disabled, ox_enabled, pgp_enabled, pgp_keyid,
|
||||
startscript, theme, tls_policy, auth_policy, client, max_sessions);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
accounts_enable(const char* const name)
|
||||
accounts_enable(const char* const account_name)
|
||||
{
|
||||
if (g_key_file_has_group(accounts, name)) {
|
||||
g_key_file_set_boolean(accounts, name, "enabled", TRUE);
|
||||
_save_accounts();
|
||||
autocomplete_add(enabled_ac, name);
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (_accounts_has_group(sanitized_account_name)) {
|
||||
g_key_file_set_boolean(accounts, sanitized_account_name, "enabled", TRUE);
|
||||
_accounts_save(account_name);
|
||||
autocomplete_add(enabled_ac, sanitized_account_name);
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
@@ -357,12 +360,13 @@ accounts_enable(const char* const name)
|
||||
}
|
||||
|
||||
gboolean
|
||||
accounts_disable(const char* const name)
|
||||
accounts_disable(const char* const account_name)
|
||||
{
|
||||
if (g_key_file_has_group(accounts, name)) {
|
||||
g_key_file_set_boolean(accounts, name, "enabled", FALSE);
|
||||
_save_accounts();
|
||||
autocomplete_remove(enabled_ac, name);
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (_accounts_has_group(sanitized_account_name)) {
|
||||
g_key_file_set_boolean(accounts, sanitized_account_name, "enabled", FALSE);
|
||||
_accounts_save(account_name);
|
||||
autocomplete_remove(enabled_ac, sanitized_account_name);
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
@@ -372,63 +376,33 @@ accounts_disable(const char* const name)
|
||||
gboolean
|
||||
accounts_rename(const char* const account_name, const char* const new_name)
|
||||
{
|
||||
if (g_key_file_has_group(accounts, new_name)) {
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
auto_gchar gchar* sanitized_new_account_name = _sanitize_account_name(new_name);
|
||||
|
||||
if (_accounts_has_group(sanitized_new_account_name)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!g_key_file_has_group(accounts, account_name)) {
|
||||
if (!_accounts_has_group(sanitized_account_name)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// treat all properties as strings for copy
|
||||
gchar* string_keys[] = {
|
||||
"enabled",
|
||||
"jid",
|
||||
"server",
|
||||
"port",
|
||||
"resource",
|
||||
"password",
|
||||
"eval_password",
|
||||
"presence.last",
|
||||
"presence.laststatus",
|
||||
"presence.login",
|
||||
"priority.online",
|
||||
"priority.chat",
|
||||
"priority.away",
|
||||
"priority.xa",
|
||||
"priority.dnd",
|
||||
"muc.service",
|
||||
"muc.nick",
|
||||
"otr.policy",
|
||||
"otr.manual",
|
||||
"otr.opportunistic",
|
||||
"otr.always",
|
||||
"omemo.policy",
|
||||
"omemo.enabled",
|
||||
"omemo.disabled",
|
||||
"ox.enabled",
|
||||
"pgp.enabled",
|
||||
"pgp.keyid",
|
||||
"last.activity",
|
||||
"script.start",
|
||||
"tls.policy"
|
||||
};
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(string_keys); i++) {
|
||||
auto_gchar gchar* value = g_key_file_get_string(accounts, account_name, string_keys[i], NULL);
|
||||
if (value) {
|
||||
g_key_file_set_string(accounts, new_name, string_keys[i], value);
|
||||
}
|
||||
gsize nkeys;
|
||||
auto_gcharv gchar** keys = g_key_file_get_keys(accounts, sanitized_account_name, &nkeys, NULL);
|
||||
for (gsize i = 0; i < nkeys; i++) {
|
||||
auto_gchar gchar* new_value = g_key_file_get_value(accounts, sanitized_account_name, keys[i], NULL);
|
||||
g_key_file_set_value(accounts, sanitized_new_account_name, keys[i], new_value);
|
||||
}
|
||||
|
||||
g_key_file_remove_group(accounts, account_name, NULL);
|
||||
_save_accounts();
|
||||
g_key_file_remove_group(accounts, sanitized_account_name, NULL);
|
||||
_accounts_save(account_name);
|
||||
_accounts_save(new_name);
|
||||
|
||||
autocomplete_remove(all_ac, account_name);
|
||||
autocomplete_add(all_ac, new_name);
|
||||
if (g_key_file_get_boolean(accounts, new_name, "enabled", NULL)) {
|
||||
autocomplete_remove(enabled_ac, account_name);
|
||||
autocomplete_add(enabled_ac, new_name);
|
||||
autocomplete_remove(all_ac, sanitized_account_name);
|
||||
autocomplete_remove(enabled_ac, sanitized_account_name);
|
||||
autocomplete_add(all_ac, sanitized_new_account_name);
|
||||
if (g_key_file_get_boolean(accounts, sanitized_new_account_name, "enabled", NULL)) {
|
||||
autocomplete_add(enabled_ac, sanitized_new_account_name);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -437,7 +411,7 @@ accounts_rename(const char* const account_name, const char* const new_name)
|
||||
gboolean
|
||||
accounts_account_exists(const char* const account_name)
|
||||
{
|
||||
return g_key_file_has_group(accounts, account_name);
|
||||
return _accounts_has_group(account_name);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -445,19 +419,20 @@ accounts_set_jid(const char* const account_name, const char* const value)
|
||||
{
|
||||
auto_jid Jid* jid = jid_create(value);
|
||||
if (jid) {
|
||||
if (accounts_account_exists(account_name)) {
|
||||
g_key_file_set_string(accounts, account_name, "jid", jid->barejid);
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (_accounts_has_group(sanitized_account_name)) {
|
||||
g_key_file_set_string(accounts, sanitized_account_name, "jid", jid->barejid);
|
||||
if (jid->resourcepart) {
|
||||
g_key_file_set_string(accounts, account_name, "resource", jid->resourcepart);
|
||||
g_key_file_set_string(accounts, sanitized_account_name, "resource", jid->resourcepart);
|
||||
}
|
||||
|
||||
if (jid->localpart == NULL) {
|
||||
g_key_file_set_string(accounts, account_name, "muc.nick", jid->domainpart);
|
||||
g_key_file_set_string(accounts, sanitized_account_name, "muc.nick", jid->domainpart);
|
||||
} else {
|
||||
g_key_file_set_string(accounts, account_name, "muc.nick", jid->localpart);
|
||||
g_key_file_set_string(accounts, sanitized_account_name, "muc.nick", jid->localpart);
|
||||
}
|
||||
|
||||
_save_accounts();
|
||||
_accounts_save(account_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -465,9 +440,10 @@ accounts_set_jid(const char* const account_name, const char* const value)
|
||||
void
|
||||
accounts_set_server(const char* const account_name, const char* const value)
|
||||
{
|
||||
if (accounts_account_exists(account_name)) {
|
||||
g_key_file_set_string(accounts, account_name, "server", value);
|
||||
_save_accounts();
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (_accounts_has_group(sanitized_account_name)) {
|
||||
g_key_file_set_string(accounts, sanitized_account_name, "server", value);
|
||||
_accounts_save(account_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -475,35 +451,41 @@ void
|
||||
accounts_set_port(const char* const account_name, const int value)
|
||||
{
|
||||
if (value != 0) {
|
||||
g_key_file_set_integer(accounts, account_name, "port", value);
|
||||
_save_accounts();
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (_accounts_has_group(sanitized_account_name)) {
|
||||
g_key_file_set_integer(accounts, sanitized_account_name, "port", value);
|
||||
_accounts_save(account_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_accounts_set_string_option(const char* account_name, const char* const option, const char* const value)
|
||||
{
|
||||
if (accounts_account_exists(account_name)) {
|
||||
g_key_file_set_string(accounts, account_name, option, value ?: "");
|
||||
_save_accounts();
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (_accounts_has_group(sanitized_account_name)) {
|
||||
g_key_file_set_string(accounts, sanitized_account_name, option, value ?: "");
|
||||
_accounts_save(account_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_accounts_set_int_option(const char* account_name, const char* const option, int value)
|
||||
{
|
||||
if (accounts_account_exists(account_name)) {
|
||||
g_key_file_set_integer(accounts, account_name, option, value);
|
||||
_save_accounts();
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (_accounts_has_group(sanitized_account_name)) {
|
||||
g_key_file_set_integer(accounts, sanitized_account_name, option, value);
|
||||
_accounts_save(account_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_accounts_clear_string_option(const char* account_name, const char* const option)
|
||||
{
|
||||
if (accounts_account_exists(account_name)) {
|
||||
g_key_file_remove_key(accounts, account_name, option, NULL);
|
||||
_save_accounts();
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (_accounts_has_group(sanitized_account_name)) {
|
||||
g_key_file_remove_key(accounts, sanitized_account_name, option, NULL);
|
||||
_accounts_save(account_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -630,83 +612,88 @@ accounts_clear_max_sessions(const char* const account_name)
|
||||
void
|
||||
accounts_add_otr_policy(const char* const account_name, const char* const contact_jid, const char* const policy)
|
||||
{
|
||||
if (accounts_account_exists(account_name)) {
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (_accounts_has_group(sanitized_account_name)) {
|
||||
GString* key = g_string_new("otr.");
|
||||
g_string_append(key, policy);
|
||||
conf_string_list_add(accounts, account_name, key->str, contact_jid);
|
||||
conf_string_list_add(accounts, sanitized_account_name, key->str, contact_jid);
|
||||
g_string_free(key, TRUE);
|
||||
|
||||
// check for and remove from other lists
|
||||
if (strcmp(policy, "manual") == 0) {
|
||||
conf_string_list_remove(accounts, account_name, "otr.opportunistic", contact_jid);
|
||||
conf_string_list_remove(accounts, account_name, "otr.always", contact_jid);
|
||||
conf_string_list_remove(accounts, sanitized_account_name, "otr.opportunistic", contact_jid);
|
||||
conf_string_list_remove(accounts, sanitized_account_name, "otr.always", contact_jid);
|
||||
}
|
||||
if (strcmp(policy, "opportunistic") == 0) {
|
||||
conf_string_list_remove(accounts, account_name, "otr.manual", contact_jid);
|
||||
conf_string_list_remove(accounts, account_name, "otr.always", contact_jid);
|
||||
conf_string_list_remove(accounts, sanitized_account_name, "otr.manual", contact_jid);
|
||||
conf_string_list_remove(accounts, sanitized_account_name, "otr.always", contact_jid);
|
||||
}
|
||||
if (strcmp(policy, "always") == 0) {
|
||||
conf_string_list_remove(accounts, account_name, "otr.opportunistic", contact_jid);
|
||||
conf_string_list_remove(accounts, account_name, "otr.manual", contact_jid);
|
||||
conf_string_list_remove(accounts, sanitized_account_name, "otr.opportunistic", contact_jid);
|
||||
conf_string_list_remove(accounts, sanitized_account_name, "otr.manual", contact_jid);
|
||||
}
|
||||
|
||||
_save_accounts();
|
||||
_accounts_save(account_name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
accounts_add_omemo_state(const char* const account_name, const char* const contact_jid, gboolean enabled)
|
||||
{
|
||||
if (accounts_account_exists(account_name)) {
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (_accounts_has_group(sanitized_account_name)) {
|
||||
if (enabled) {
|
||||
conf_string_list_add(accounts, account_name, "omemo.enabled", contact_jid);
|
||||
conf_string_list_remove(accounts, account_name, "omemo.disabled", contact_jid);
|
||||
conf_string_list_add(accounts, sanitized_account_name, "omemo.enabled", contact_jid);
|
||||
conf_string_list_remove(accounts, sanitized_account_name, "omemo.disabled", contact_jid);
|
||||
} else {
|
||||
conf_string_list_add(accounts, account_name, "omemo.disabled", contact_jid);
|
||||
conf_string_list_remove(accounts, account_name, "omemo.enabled", contact_jid);
|
||||
conf_string_list_add(accounts, sanitized_account_name, "omemo.disabled", contact_jid);
|
||||
conf_string_list_remove(accounts, sanitized_account_name, "omemo.enabled", contact_jid);
|
||||
}
|
||||
|
||||
_save_accounts();
|
||||
_accounts_save(account_name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
accounts_add_ox_state(const char* const account_name, const char* const contact_jid, gboolean enabled)
|
||||
{
|
||||
if (accounts_account_exists(account_name)) {
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (_accounts_has_group(sanitized_account_name)) {
|
||||
if (enabled) {
|
||||
conf_string_list_add(accounts, account_name, "ox.enabled", contact_jid);
|
||||
conf_string_list_add(accounts, sanitized_account_name, "ox.enabled", contact_jid);
|
||||
} else {
|
||||
conf_string_list_remove(accounts, account_name, "ox.enabled", contact_jid);
|
||||
conf_string_list_remove(accounts, sanitized_account_name, "ox.enabled", contact_jid);
|
||||
}
|
||||
|
||||
_save_accounts();
|
||||
_accounts_save(account_name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
accounts_add_pgp_state(const char* const account_name, const char* const contact_jid, gboolean enabled)
|
||||
{
|
||||
if (accounts_account_exists(account_name)) {
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (_accounts_has_group(sanitized_account_name)) {
|
||||
if (enabled) {
|
||||
conf_string_list_add(accounts, account_name, "pgp.enabled", contact_jid);
|
||||
conf_string_list_remove(accounts, account_name, "pgp.disabled", contact_jid);
|
||||
conf_string_list_add(accounts, sanitized_account_name, "pgp.enabled", contact_jid);
|
||||
conf_string_list_remove(accounts, sanitized_account_name, "pgp.disabled", contact_jid);
|
||||
} else {
|
||||
conf_string_list_add(accounts, account_name, "pgp.disabled", contact_jid);
|
||||
conf_string_list_remove(accounts, account_name, "pgp.enabled", contact_jid);
|
||||
conf_string_list_add(accounts, sanitized_account_name, "pgp.disabled", contact_jid);
|
||||
conf_string_list_remove(accounts, sanitized_account_name, "pgp.enabled", contact_jid);
|
||||
}
|
||||
|
||||
_save_accounts();
|
||||
_accounts_save(account_name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
accounts_clear_omemo_state(const char* const account_name, const char* const contact_jid)
|
||||
{
|
||||
if (accounts_account_exists(account_name)) {
|
||||
conf_string_list_remove(accounts, account_name, "omemo.enabled", contact_jid);
|
||||
conf_string_list_remove(accounts, account_name, "omemo.disabled", contact_jid);
|
||||
_save_accounts();
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (_accounts_has_group(sanitized_account_name)) {
|
||||
conf_string_list_remove(accounts, sanitized_account_name, "omemo.enabled", contact_jid);
|
||||
conf_string_list_remove(accounts, sanitized_account_name, "omemo.disabled", contact_jid);
|
||||
_accounts_save(account_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -779,7 +766,8 @@ accounts_set_priority_dnd(const char* const account_name, const gint value)
|
||||
void
|
||||
accounts_set_priority_all(const char* const account_name, const gint value)
|
||||
{
|
||||
if (accounts_account_exists(account_name)) {
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (_accounts_has_group(sanitized_account_name)) {
|
||||
accounts_set_priority_online(account_name, value);
|
||||
accounts_set_priority_chat(account_name, value);
|
||||
accounts_set_priority_away(account_name, value);
|
||||
@@ -793,22 +781,23 @@ accounts_get_priority_for_presence_type(const char* const account_name,
|
||||
resource_presence_t presence_type)
|
||||
{
|
||||
gint result;
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
|
||||
switch (presence_type) {
|
||||
case (RESOURCE_ONLINE):
|
||||
result = g_key_file_get_integer(accounts, account_name, "priority.online", NULL);
|
||||
result = g_key_file_get_integer(accounts, sanitized_account_name, "priority.online", NULL);
|
||||
break;
|
||||
case (RESOURCE_CHAT):
|
||||
result = g_key_file_get_integer(accounts, account_name, "priority.chat", NULL);
|
||||
result = g_key_file_get_integer(accounts, sanitized_account_name, "priority.chat", NULL);
|
||||
break;
|
||||
case (RESOURCE_AWAY):
|
||||
result = g_key_file_get_integer(accounts, account_name, "priority.away", NULL);
|
||||
result = g_key_file_get_integer(accounts, sanitized_account_name, "priority.away", NULL);
|
||||
break;
|
||||
case (RESOURCE_XA):
|
||||
result = g_key_file_get_integer(accounts, account_name, "priority.xa", NULL);
|
||||
result = g_key_file_get_integer(accounts, sanitized_account_name, "priority.xa", NULL);
|
||||
break;
|
||||
default:
|
||||
result = g_key_file_get_integer(accounts, account_name, "priority.dnd", NULL);
|
||||
result = g_key_file_get_integer(accounts, sanitized_account_name, "priority.dnd", NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -833,7 +822,8 @@ accounts_set_last_status(const char* const account_name, const char* const value
|
||||
void
|
||||
accounts_set_last_activity(const char* const account_name)
|
||||
{
|
||||
if (accounts_account_exists(account_name)) {
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (_accounts_has_group(sanitized_account_name)) {
|
||||
GDateTime* nowdt = g_date_time_new_now_utc();
|
||||
GTimeVal nowtv;
|
||||
gboolean res = g_date_time_to_timeval(nowdt, &nowtv);
|
||||
@@ -841,8 +831,8 @@ accounts_set_last_activity(const char* const account_name)
|
||||
|
||||
if (res) {
|
||||
auto_char char* timestr = g_time_val_to_iso8601(&nowtv);
|
||||
g_key_file_set_string(accounts, account_name, "last.activity", timestr);
|
||||
_save_accounts();
|
||||
g_key_file_set_string(accounts, sanitized_account_name, "last.activity", timestr);
|
||||
_accounts_save(account_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -850,8 +840,9 @@ accounts_set_last_activity(const char* const account_name)
|
||||
gchar*
|
||||
accounts_get_last_activity(const char* const account_name)
|
||||
{
|
||||
if (accounts_account_exists(account_name)) {
|
||||
return g_key_file_get_string(accounts, account_name, "last.activity", NULL);
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (_accounts_has_group(sanitized_account_name)) {
|
||||
return g_key_file_get_string(accounts, sanitized_account_name, "last.activity", NULL);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
@@ -860,27 +851,30 @@ accounts_get_last_activity(const char* const account_name)
|
||||
gchar*
|
||||
accounts_get_resource(const char* const account_name)
|
||||
{
|
||||
if (!accounts_account_exists(account_name)) {
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (!_accounts_has_group(sanitized_account_name)) {
|
||||
return NULL;
|
||||
}
|
||||
return g_key_file_get_string(accounts, account_name, "resource", NULL);
|
||||
return g_key_file_get_string(accounts, sanitized_account_name, "resource", NULL);
|
||||
}
|
||||
|
||||
int
|
||||
accounts_get_max_sessions(const char* const account_name)
|
||||
{
|
||||
if (!accounts_account_exists(account_name)) {
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (!_accounts_has_group(sanitized_account_name)) {
|
||||
return 0;
|
||||
}
|
||||
return g_key_file_get_integer(accounts, account_name, "max.sessions", 0);
|
||||
return g_key_file_get_integer(accounts, sanitized_account_name, "max.sessions", 0);
|
||||
}
|
||||
|
||||
void
|
||||
accounts_set_login_presence(const char* const account_name, const char* const value)
|
||||
{
|
||||
if (accounts_account_exists(account_name)) {
|
||||
g_key_file_set_string(accounts, account_name, "presence.login", value);
|
||||
_save_accounts();
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
if (_accounts_has_group(sanitized_account_name)) {
|
||||
g_key_file_set_string(accounts, sanitized_account_name, "presence.login", value);
|
||||
_accounts_save(account_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -888,7 +882,8 @@ resource_presence_t
|
||||
accounts_get_last_presence(const char* const account_name)
|
||||
{
|
||||
resource_presence_t result;
|
||||
auto_gchar gchar* setting = g_key_file_get_string(accounts, account_name, "presence.last", NULL);
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
auto_gchar gchar* setting = g_key_file_get_string(accounts, sanitized_account_name, "presence.last", NULL);
|
||||
|
||||
if (setting == NULL || (strcmp(setting, "online") == 0)) {
|
||||
result = RESOURCE_ONLINE;
|
||||
@@ -912,14 +907,16 @@ accounts_get_last_presence(const char* const account_name)
|
||||
char*
|
||||
accounts_get_last_status(const char* const account_name)
|
||||
{
|
||||
return g_key_file_get_string(accounts, account_name, "presence.laststatus", NULL);
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
return g_key_file_get_string(accounts, sanitized_account_name, "presence.laststatus", NULL);
|
||||
}
|
||||
|
||||
resource_presence_t
|
||||
accounts_get_login_presence(const char* const account_name)
|
||||
{
|
||||
resource_presence_t result;
|
||||
auto_gchar gchar* setting = g_key_file_get_string(accounts, account_name, "presence.login", NULL);
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
auto_gchar gchar* setting = g_key_file_get_string(accounts, sanitized_account_name, "presence.login", NULL);
|
||||
|
||||
if (setting == NULL || (strcmp(setting, "online") == 0)) {
|
||||
result = RESOURCE_ONLINE;
|
||||
@@ -944,7 +941,8 @@ accounts_get_login_presence(const char* const account_name)
|
||||
char*
|
||||
accounts_get_login_status(const char* const account_name)
|
||||
{
|
||||
auto_gchar gchar* setting = g_key_file_get_string(accounts, account_name, "presence.login", NULL);
|
||||
auto_gchar gchar* sanitized_account_name = _sanitize_account_name(account_name);
|
||||
auto_gchar gchar* setting = g_key_file_get_string(accounts, sanitized_account_name, "presence.login", NULL);
|
||||
gchar* status = NULL;
|
||||
|
||||
if (g_strcmp0(setting, "last") == 0) {
|
||||
@@ -953,9 +951,3 @@ accounts_get_login_status(const char* const account_name)
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
_save_accounts(void)
|
||||
{
|
||||
save_keyfile(&accounts_prof_keyfile);
|
||||
}
|
||||
|
||||
@@ -4,33 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_ACCOUNTS_H
|
||||
@@ -48,7 +22,7 @@ char* accounts_find_enabled(const char* const prefix, gboolean previous, void* c
|
||||
void accounts_reset_all_search(void);
|
||||
void accounts_reset_enabled_search(void);
|
||||
void accounts_add(const char* jid, const char* altdomain, const int port, const char* const tls_policy, const char* const auth_policy);
|
||||
int accounts_remove(const char* jid);
|
||||
gboolean accounts_remove(const char* jid);
|
||||
gchar** accounts_get_list(void);
|
||||
ProfAccount* accounts_get_account(const char* const name);
|
||||
gboolean accounts_enable(const char* const name);
|
||||
|
||||
@@ -4,33 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2022 Steffen Jaeckel <jaeckel-floss@eyet-services.de>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -53,8 +27,7 @@ _cafile_name(void)
|
||||
if (!create_dir(certs_dir)) {
|
||||
return NULL;
|
||||
}
|
||||
gchar* filename = g_strdup_printf("%s/CAfile.pem", certs_dir);
|
||||
return filename;
|
||||
return g_strdup_printf("%s/CAfile.pem", certs_dir);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -70,21 +43,25 @@ cafile_add(const TLSCertificate* cert)
|
||||
auto_gchar gchar* contents = NULL;
|
||||
auto_gchar gchar* new_contents = NULL;
|
||||
gsize length;
|
||||
GError* glib_error = NULL;
|
||||
auto_gerror GError* glib_error = NULL;
|
||||
if (g_file_test(cafile, G_FILE_TEST_EXISTS)) {
|
||||
if (!g_file_get_contents(cafile, &contents, &length, &glib_error)) {
|
||||
log_error("[CAfile] could not read from %s: %s", cafile, glib_error ? glib_error->message : "No GLib error given");
|
||||
log_error("[CAfile] could not read from %s: %s", cafile, PROF_GERROR_MESSAGE(glib_error));
|
||||
return;
|
||||
}
|
||||
if (strstr(contents, cert->fingerprint)) {
|
||||
log_debug("[CAfile] fingerprint %s already stored", cert->fingerprint);
|
||||
return;
|
||||
}
|
||||
if (strstr(contents, cert->fingerprint_sha1)) {
|
||||
log_debug("[CAfile] fingerprint %s already stored", cert->fingerprint_sha1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
const char* header = "# Profanity CAfile\n# DO NOT EDIT - this file is automatically generated";
|
||||
new_contents = g_strdup_printf("%s\n\n# %s\n%s", contents ? contents : header, cert->fingerprint, cert->pem);
|
||||
new_contents = g_strdup_printf("%s\n# %s\n%s", contents ? contents : header, cert->fingerprint, cert->pem);
|
||||
if (!g_file_set_contents(cafile, new_contents, -1, &glib_error))
|
||||
log_error("[CAfile] could not write to %s: %s", cafile, glib_error ? glib_error->message : "No GLib error given");
|
||||
log_error("[CAfile] could not write to %s: %s", cafile, PROF_GERROR_MESSAGE(glib_error));
|
||||
}
|
||||
|
||||
gchar*
|
||||
|
||||
@@ -4,33 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2022 Steffen Jaeckel <jaeckel-floss@eyet-services.de>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_CAFILE_H
|
||||
|
||||
@@ -3,35 +3,9 @@
|
||||
* vim: expandtab:ts=4:sts=4:sw=4
|
||||
*
|
||||
* Copyright (C) 2019 Aurelien Aptel <aurelien.aptel@gmail.com>
|
||||
* Copyright (C) 2019 - 2025 Michael Vetter <jubalh@iodoru.org>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
* Copyright (C) 2019 - 2026 Michael Vetter <jubalh@iodoru.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -59,7 +33,7 @@ static struct color_pair_cache
|
||||
{
|
||||
struct
|
||||
{
|
||||
int16_t fg, bg;
|
||||
short fg, bg;
|
||||
}* pairs;
|
||||
int size;
|
||||
int capacity;
|
||||
@@ -341,14 +315,18 @@ color_distance(const struct color_def* a, const struct color_def* b)
|
||||
return h * h + s * s + l * l;
|
||||
}
|
||||
|
||||
static int
|
||||
/* Indices into the 256-colour palette and ncurses palette IDs are
|
||||
* 16-bit (the size_t-or-short distinction in ncurses init_pair).
|
||||
* Use `short` end-to-end so the caller boundaries don't need casts.
|
||||
*/
|
||||
static short
|
||||
find_closest_col(int h, int s, int l)
|
||||
{
|
||||
struct color_def a = { h, s, l };
|
||||
int min = 0;
|
||||
struct color_def a = { (uint16_t)h, (uint8_t)s, (uint8_t)l, NULL };
|
||||
short min = 0;
|
||||
int dmin = color_distance(&a, &color_names[0]);
|
||||
|
||||
for (int i = 1; i < COLOR_NAME_SIZE; i++) {
|
||||
for (short i = 1; i < COLOR_NAME_SIZE; i++) {
|
||||
int d = color_distance(&a, &color_names[i]);
|
||||
if (d < dmin) {
|
||||
dmin = d;
|
||||
@@ -358,8 +336,8 @@ find_closest_col(int h, int s, int l)
|
||||
return min;
|
||||
}
|
||||
|
||||
static int
|
||||
find_col(const char* col_name, int n)
|
||||
static short
|
||||
find_col(const char* col_name, size_t n)
|
||||
{
|
||||
char name[32] = { 0 };
|
||||
|
||||
@@ -371,7 +349,7 @@ find_col(const char* col_name, int n)
|
||||
|
||||
if (n >= sizeof(name)) {
|
||||
/* truncate */
|
||||
log_error("Color: <%s,%d> bigger than %zu", col_name, n, sizeof(name));
|
||||
log_error("Color: <%s,%zu> bigger than %zu", col_name, n, sizeof(name));
|
||||
n = sizeof(name) - 1;
|
||||
}
|
||||
memcpy(name, col_name, n);
|
||||
@@ -380,7 +358,7 @@ find_col(const char* col_name, int n)
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < COLOR_NAME_SIZE; i++) {
|
||||
for (short i = 0; i < COLOR_NAME_SIZE; i++) {
|
||||
if (g_ascii_strcasecmp(name, color_names[i].name) == 0) {
|
||||
return i;
|
||||
}
|
||||
@@ -389,13 +367,13 @@ find_col(const char* col_name, int n)
|
||||
return COL_ERR;
|
||||
}
|
||||
|
||||
static int
|
||||
static short
|
||||
color_hash(const char* str, color_profile profile)
|
||||
{
|
||||
GChecksum* cs = NULL;
|
||||
guint8 buf[256] = { 0 };
|
||||
gsize len = 256;
|
||||
int rc = -1; /* default ncurse color */
|
||||
short rc = -1; /* default ncurse color */
|
||||
|
||||
cs = g_checksum_new(G_CHECKSUM_SHA1);
|
||||
if (!cs)
|
||||
@@ -464,7 +442,7 @@ color_pair_cache_reset(void)
|
||||
}
|
||||
|
||||
static int
|
||||
_color_pair_cache_get(int fg, int bg)
|
||||
_color_pair_cache_get(short fg, short bg)
|
||||
{
|
||||
if (COLORS < 256) {
|
||||
if (fg > 7 || bg > 7) {
|
||||
@@ -489,10 +467,13 @@ _color_pair_cache_get(int fg, int bg)
|
||||
}
|
||||
|
||||
int i = cache.size;
|
||||
// TODO: init_pair uses 15-bit palette indices. Terminals exposing
|
||||
// extended colour palettes (>32767) need init_extended_pair here.
|
||||
// Upstream-inherited limitation.
|
||||
cache.pairs[i].fg = fg;
|
||||
cache.pairs[i].bg = bg;
|
||||
/* (re-)define the new pair in curses */
|
||||
init_pair(i, fg, bg);
|
||||
init_pair((short)i, fg, bg);
|
||||
|
||||
cache.size++;
|
||||
|
||||
@@ -511,8 +492,8 @@ _color_pair_cache_get(int fg, int bg)
|
||||
int
|
||||
color_pair_cache_hash_str(const char* str, color_profile profile)
|
||||
{
|
||||
int fg = color_hash(str, profile);
|
||||
int bg = -1;
|
||||
short fg = color_hash(str, profile);
|
||||
short bg = -1;
|
||||
|
||||
auto_char char* bkgnd = theme_get_bkgnd();
|
||||
if (bkgnd) {
|
||||
@@ -532,7 +513,7 @@ int
|
||||
color_pair_cache_get(const char* pair_name)
|
||||
{
|
||||
const char* sep;
|
||||
int fg, bg;
|
||||
short fg, bg;
|
||||
|
||||
sep = strchr(pair_name, '_');
|
||||
if (!sep) {
|
||||
@@ -540,7 +521,7 @@ color_pair_cache_get(const char* pair_name)
|
||||
return -1;
|
||||
}
|
||||
|
||||
fg = find_col(pair_name, sep - pair_name);
|
||||
fg = find_col(pair_name, (size_t)(sep - pair_name));
|
||||
bg = find_col(sep + 1, strlen(sep));
|
||||
if (fg == COL_ERR || bg == COL_ERR) {
|
||||
log_error("Color: bad color name %s", pair_name);
|
||||
|
||||
@@ -4,33 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2019 Aurelien Aptel <aurelien.aptel@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#ifndef _COLOR_H_
|
||||
|
||||
@@ -4,33 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -66,9 +40,7 @@ conf_string_list_add(GKeyFile* keyfile, const char* const group, const char* con
|
||||
|
||||
// Add item to the existing list
|
||||
const gchar** new_list = g_new(const gchar*, length + 2);
|
||||
for (gsize i = 0; i < length; ++i) {
|
||||
new_list[i] = list[i];
|
||||
}
|
||||
memcpy(new_list, list, sizeof(list[0]) * length);
|
||||
new_list[length] = item;
|
||||
new_list[length + 1] = NULL;
|
||||
|
||||
@@ -89,33 +61,28 @@ conf_string_list_remove(GKeyFile* keyfile, const char* const group, const char*
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GList* glist = NULL;
|
||||
gsize new_length = 0;
|
||||
const gchar** new_list = g_new(const gchar*, length + 1);
|
||||
gboolean deleted = FALSE;
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
for (gsize i = 0; i < length; i++) {
|
||||
if (strcmp(list[i], item) == 0) {
|
||||
deleted = TRUE;
|
||||
continue;
|
||||
}
|
||||
glist = g_list_append(glist, strdup(list[i]));
|
||||
new_list[new_length++] = list[i];
|
||||
}
|
||||
new_list[new_length] = NULL;
|
||||
|
||||
if (deleted) {
|
||||
if (g_list_length(glist) == 0) {
|
||||
if (new_length == 0) {
|
||||
g_key_file_remove_key(keyfile, group, key, NULL);
|
||||
} else {
|
||||
const gchar* new_list[g_list_length(glist) + 1];
|
||||
int i = 0;
|
||||
|
||||
for (GList* curr = glist; curr; curr = g_list_next(curr)) {
|
||||
new_list[i++] = curr->data;
|
||||
}
|
||||
|
||||
new_list[i] = NULL;
|
||||
g_key_file_set_string_list(keyfile, group, key, new_list, g_list_length(glist));
|
||||
g_key_file_set_string_list(keyfile, group, key, new_list, new_length);
|
||||
}
|
||||
}
|
||||
|
||||
g_list_free_full(glist, g_free);
|
||||
g_free(new_list);
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
@@ -4,33 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_CONFLISTS_H
|
||||
|
||||
@@ -3,35 +3,9 @@
|
||||
* vim: expandtab:ts=4:sts=4:sw=4
|
||||
*
|
||||
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
||||
* Copyright (C) 2020 - 2025 Michael Vetter <jubalh@iodoru.org>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
* Copyright (C) 2020 - 2026 Michael Vetter <jubalh@iodoru.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
|
||||
@@ -3,35 +3,9 @@
|
||||
* vim: expandtab:ts=4:sts=4:sw=4
|
||||
*
|
||||
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
||||
* Copyright (C) 2018 - 2025 Michael Vetter <jubalh@iodoru.org>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
* Copyright (C) 2018 - 2026 Michael Vetter <jubalh@iodoru.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_FILES_H
|
||||
|
||||
@@ -3,35 +3,9 @@
|
||||
* vim: expandtab:ts=4:sts=4:sw=4
|
||||
*
|
||||
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
||||
* Copyright (C) 2019 - 2025 Michael Vetter <jubalh@iodoru.org>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
* Copyright (C) 2019 - 2026 Michael Vetter <jubalh@iodoru.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -49,6 +23,7 @@
|
||||
#include "tools/autocomplete.h"
|
||||
#include "config/files.h"
|
||||
#include "config/conflists.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
// preference groups refer to the sections in .profrc or theme files
|
||||
// for example [ui] but not [colours] which is handled in theme.c
|
||||
@@ -66,6 +41,7 @@
|
||||
#define PREF_GROUP_MUC "muc"
|
||||
#define PREF_GROUP_PLUGINS "plugins"
|
||||
#define PREF_GROUP_EXECUTABLES "executables"
|
||||
#define PREF_GROUP_SPELLCHECK "spellcheck"
|
||||
#define PREF_GROUP_AI "ai"
|
||||
#define PREF_GROUP_AI_PREFIX "ai/" /* per-provider subsection prefix: [ai/<provider>] */
|
||||
#define PREF_AI_SETTING_PREFIX "setting." /* per-provider custom setting key prefix */
|
||||
@@ -80,10 +56,10 @@ static Autocomplete boolean_choice_ac;
|
||||
static Autocomplete room_trigger_ac;
|
||||
|
||||
static void _save_prefs(void);
|
||||
static const char* _get_group(preference_t pref);
|
||||
static const char* _get_key(preference_t pref);
|
||||
static const gchar* _get_group(preference_t pref);
|
||||
static const gchar* _get_key(preference_t pref);
|
||||
static gboolean _get_default_boolean(preference_t pref);
|
||||
static char* _get_default_string(preference_t pref);
|
||||
static gchar* _get_default_string(preference_t pref);
|
||||
|
||||
static void
|
||||
_prefs_load(void)
|
||||
@@ -92,7 +68,7 @@ _prefs_load(void)
|
||||
log_maxsize = g_key_file_get_integer(prefs, PREF_GROUP_LOGGING, "maxsize", &err);
|
||||
if (err) {
|
||||
log_maxsize = 0;
|
||||
g_error_free(err);
|
||||
PROF_GERROR_FREE(err);
|
||||
}
|
||||
|
||||
// move pre 0.5.0 autoaway.time to autoaway.awaytime
|
||||
@@ -112,7 +88,7 @@ _prefs_load(void)
|
||||
// migrate pre 0.5.0 time settings
|
||||
if (g_key_file_has_key(prefs, PREF_GROUP_UI, "time", NULL)) {
|
||||
auto_gchar gchar* time = g_key_file_get_string(prefs, PREF_GROUP_UI, "time", NULL);
|
||||
char* val = time ? time : "off";
|
||||
gchar* val = time ? time : "off";
|
||||
g_key_file_set_string(prefs, PREF_GROUP_UI, "time.console", val);
|
||||
g_key_file_set_string(prefs, PREF_GROUP_UI, "time.chat", val);
|
||||
g_key_file_set_string(prefs, PREF_GROUP_UI, "time.muc", val);
|
||||
@@ -181,7 +157,7 @@ _prefs_load(void)
|
||||
if (values && !g_key_file_has_key(prefs, PREF_GROUP_EXECUTABLES, "url.open.cmd", NULL)) {
|
||||
// First value in array is `require_save` option -- we ignore that
|
||||
// one as there is no such option anymore.
|
||||
char* executable = values[1];
|
||||
gchar* executable = values[1];
|
||||
|
||||
g_key_file_set_string(prefs, PREF_GROUP_EXECUTABLES, "url.open.cmd", executable);
|
||||
g_key_file_set_comment(prefs, PREF_GROUP_EXECUTABLES, "url.open.cmd", " Migrated from url.open.cmd[DEF]. `require_save` option has been removed in v0.10 and was discarded.", NULL);
|
||||
@@ -318,7 +294,7 @@ _prefs_load(void)
|
||||
gsize len = 0;
|
||||
auto_gcharv gchar** triggers = g_key_file_get_string_list(prefs, PREF_GROUP_NOTIFICATIONS, "room.trigger.list", &len, NULL);
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
for (gsize i = 0; i < len; i++) {
|
||||
autocomplete_add(room_trigger_ac, triggers[i]);
|
||||
}
|
||||
}
|
||||
@@ -340,7 +316,7 @@ prefs_reload(void)
|
||||
}
|
||||
|
||||
void
|
||||
prefs_load(const char* config_file)
|
||||
prefs_load(const gchar* config_file)
|
||||
{
|
||||
if (config_file == NULL) {
|
||||
load_config_keyfile(&prefs_prof_keyfile, FILE_PROFRC);
|
||||
@@ -352,6 +328,77 @@ prefs_load(const char* config_file)
|
||||
_prefs_load();
|
||||
}
|
||||
|
||||
static void
|
||||
prefs_changes_print(const gchar* key, const gchar* newval, const gchar* oldval, gboolean* banner_shown)
|
||||
{
|
||||
#define PREFS_CHANGES_FORMAT_STRING "%-32s | %-20s | %-20s"
|
||||
if (!*banner_shown) {
|
||||
cons_show(PREFS_CHANGES_FORMAT_STRING, "Key", "New value", "Old value");
|
||||
*banner_shown = TRUE;
|
||||
}
|
||||
cons_show(PREFS_CHANGES_FORMAT_STRING, key, newval, oldval);
|
||||
#undef PREFS_CHANGES_FORMAT_STRING
|
||||
}
|
||||
|
||||
void
|
||||
prefs_changes(void)
|
||||
{
|
||||
const gchar* undef = "";
|
||||
prof_keyfile_t saved;
|
||||
if (!load_custom_keyfile(&saved, g_strdup(prefs_prof_keyfile.filename)))
|
||||
return;
|
||||
gsize ngroups, nsavedgroups, g;
|
||||
auto_gcharv gchar** groups = g_key_file_get_groups(prefs_prof_keyfile.keyfile, &ngroups);
|
||||
gboolean banner_shown = FALSE;
|
||||
for (g = 0; g < ngroups; ++g) {
|
||||
gsize nkeys, k;
|
||||
gboolean saved_has_group = g_key_file_has_group(saved.keyfile, groups[g]);
|
||||
auto_gcharv gchar** keys = g_key_file_get_keys(prefs_prof_keyfile.keyfile, groups[g], &nkeys, NULL);
|
||||
for (k = 0; k < nkeys; ++k) {
|
||||
auto_gerror GError* err = NULL;
|
||||
auto_gchar gchar* full_key = g_strdup_printf("%s.%s", groups[g], keys[k]);
|
||||
auto_gchar gchar* new_value = g_key_file_get_value(prefs_prof_keyfile.keyfile, groups[g], keys[k], &err);
|
||||
if (err || !new_value) {
|
||||
cons_show_error("%s: New value (%s) error: %s", full_key, STR_MAYBE_NULL(new_value), PROF_GERROR_MESSAGE(err));
|
||||
continue;
|
||||
}
|
||||
if (!saved_has_group
|
||||
|| !g_key_file_has_key(saved.keyfile, groups[g], keys[k], NULL)) {
|
||||
prefs_changes_print(full_key, new_value, undef, &banner_shown);
|
||||
continue;
|
||||
}
|
||||
auto_gchar gchar* old_value = g_key_file_get_value(saved.keyfile, groups[g], keys[k], &err);
|
||||
if (err || !old_value) {
|
||||
cons_show_error("%s: Old value (%s) error: %s", full_key, STR_MAYBE_NULL(old_value), PROF_GERROR_MESSAGE(err));
|
||||
continue;
|
||||
}
|
||||
if (!g_str_equal(old_value, new_value)) {
|
||||
prefs_changes_print(full_key, new_value, old_value, &banner_shown);
|
||||
}
|
||||
}
|
||||
}
|
||||
auto_gcharv gchar** savedgroups = g_key_file_get_groups(saved.keyfile, &nsavedgroups);
|
||||
for (g = 0; g < nsavedgroups; ++g) {
|
||||
gsize nkeys, k;
|
||||
auto_gcharv gchar** keys = g_key_file_get_keys(saved.keyfile, savedgroups[g], &nkeys, NULL);
|
||||
for (k = 0; k < nkeys; ++k) {
|
||||
if (g_key_file_has_key(prefs_prof_keyfile.keyfile, savedgroups[g], keys[k], NULL))
|
||||
continue;
|
||||
auto_gerror GError* err = NULL;
|
||||
auto_gchar gchar* full_key = g_strdup_printf("%s.%s", groups[g], keys[k]);
|
||||
auto_gchar gchar* old_value = g_key_file_get_value(saved.keyfile, groups[g], keys[k], &err);
|
||||
if (err || !old_value) {
|
||||
cons_show_error("%s: Old value (%s) error: %s", full_key, STR_MAYBE_NULL(old_value), PROF_GERROR_MESSAGE(err));
|
||||
continue;
|
||||
}
|
||||
prefs_changes_print(full_key, undef, old_value, &banner_shown);
|
||||
}
|
||||
}
|
||||
free_keyfile(&saved);
|
||||
if (!banner_shown)
|
||||
cons_show("No changes to saved preferences.");
|
||||
}
|
||||
|
||||
void
|
||||
prefs_save(void)
|
||||
{
|
||||
@@ -368,7 +415,7 @@ prefs_close(void)
|
||||
}
|
||||
|
||||
gchar*
|
||||
prefs_autocomplete_boolean_choice(const char* const prefix, gboolean previous, void* context)
|
||||
prefs_autocomplete_boolean_choice(const gchar* const prefix, gboolean previous, void* context)
|
||||
{
|
||||
return autocomplete_complete(boolean_choice_ac, prefix, TRUE, previous);
|
||||
}
|
||||
@@ -380,7 +427,7 @@ prefs_reset_boolean_choice(void)
|
||||
}
|
||||
|
||||
gchar*
|
||||
prefs_autocomplete_room_trigger(const char* const prefix, gboolean previous, void* context)
|
||||
prefs_autocomplete_room_trigger(const gchar* const prefix, gboolean previous, void* context)
|
||||
{
|
||||
return autocomplete_complete(room_trigger_ac, prefix, TRUE, previous);
|
||||
}
|
||||
@@ -406,7 +453,7 @@ prefs_do_chat_notify(gboolean current_win)
|
||||
}
|
||||
|
||||
GList*
|
||||
prefs_message_get_triggers(const char* const message)
|
||||
prefs_message_get_triggers(const gchar* const message)
|
||||
{
|
||||
GList* result = NULL;
|
||||
|
||||
@@ -414,7 +461,7 @@ prefs_message_get_triggers(const char* const message)
|
||||
gsize len = 0;
|
||||
auto_gcharv gchar** triggers = g_key_file_get_string_list(prefs, PREF_GROUP_NOTIFICATIONS, "room.trigger.list", &len, NULL);
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
for (gsize i = 0; i < len; i++) {
|
||||
auto_gchar gchar* trigger_lower = g_utf8_strdown(triggers[i], -1);
|
||||
if (g_strrstr(message_lower, trigger_lower)) {
|
||||
result = g_list_append(result, strdup(triggers[i]));
|
||||
@@ -425,8 +472,8 @@ prefs_message_get_triggers(const char* const message)
|
||||
}
|
||||
|
||||
gboolean
|
||||
prefs_do_room_notify(gboolean current_win, const char* const roomjid, const char* const mynick,
|
||||
const char* const theirnick, const char* const message, gboolean mention, gboolean trigger_found)
|
||||
prefs_do_room_notify(gboolean current_win, const gchar* const roomjid, const gchar* const mynick,
|
||||
const gchar* const theirnick, const gchar* const message, gboolean mention, gboolean trigger_found)
|
||||
{
|
||||
if (g_strcmp0(mynick, theirnick) == 0) {
|
||||
return FALSE;
|
||||
@@ -475,7 +522,7 @@ prefs_do_room_notify(gboolean current_win, const char* const roomjid, const char
|
||||
}
|
||||
|
||||
gboolean
|
||||
prefs_do_room_notify_mention(const char* const roomjid, int unread, gboolean mention, gboolean trigger)
|
||||
prefs_do_room_notify_mention(const gchar* const roomjid, int unread, gboolean mention, gboolean trigger)
|
||||
{
|
||||
gboolean notify_room = FALSE;
|
||||
if (g_key_file_has_key(prefs, roomjid, "notify", NULL)) {
|
||||
@@ -511,61 +558,61 @@ prefs_do_room_notify_mention(const char* const roomjid, int unread, gboolean men
|
||||
}
|
||||
|
||||
void
|
||||
prefs_set_room_notify(const char* const roomjid, gboolean value)
|
||||
prefs_set_room_notify(const gchar* const roomjid, gboolean value)
|
||||
{
|
||||
g_key_file_set_boolean(prefs, roomjid, "notify", value);
|
||||
}
|
||||
|
||||
void
|
||||
prefs_set_room_notify_mention(const char* const roomjid, gboolean value)
|
||||
prefs_set_room_notify_mention(const gchar* const roomjid, gboolean value)
|
||||
{
|
||||
g_key_file_set_boolean(prefs, roomjid, "notify.mention", value);
|
||||
}
|
||||
|
||||
void
|
||||
prefs_set_room_notify_trigger(const char* const roomjid, gboolean value)
|
||||
prefs_set_room_notify_trigger(const gchar* const roomjid, gboolean value)
|
||||
{
|
||||
g_key_file_set_boolean(prefs, roomjid, "notify.trigger", value);
|
||||
}
|
||||
|
||||
gboolean
|
||||
prefs_has_room_notify(const char* const roomjid)
|
||||
prefs_has_room_notify(const gchar* const roomjid)
|
||||
{
|
||||
return g_key_file_has_key(prefs, roomjid, "notify", NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
prefs_has_room_notify_mention(const char* const roomjid)
|
||||
prefs_has_room_notify_mention(const gchar* const roomjid)
|
||||
{
|
||||
return g_key_file_has_key(prefs, roomjid, "notify.mention", NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
prefs_has_room_notify_trigger(const char* const roomjid)
|
||||
prefs_has_room_notify_trigger(const gchar* const roomjid)
|
||||
{
|
||||
return g_key_file_has_key(prefs, roomjid, "notify.trigger", NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
prefs_get_room_notify(const char* const roomjid)
|
||||
prefs_get_room_notify(const gchar* const roomjid)
|
||||
{
|
||||
return g_key_file_get_boolean(prefs, roomjid, "notify", NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
prefs_get_room_notify_mention(const char* const roomjid)
|
||||
prefs_get_room_notify_mention(const gchar* const roomjid)
|
||||
{
|
||||
return g_key_file_get_boolean(prefs, roomjid, "notify.mention", NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
prefs_get_room_notify_trigger(const char* const roomjid)
|
||||
prefs_get_room_notify_trigger(const gchar* const roomjid)
|
||||
{
|
||||
return g_key_file_get_boolean(prefs, roomjid, "notify.trigger", NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
prefs_reset_room_notify(const char* const roomjid)
|
||||
prefs_reset_room_notify(const gchar* const roomjid)
|
||||
{
|
||||
if (g_key_file_has_group(prefs, roomjid)) {
|
||||
g_key_file_remove_group(prefs, roomjid, NULL);
|
||||
@@ -578,8 +625,8 @@ prefs_reset_room_notify(const char* const roomjid)
|
||||
gboolean
|
||||
prefs_get_boolean(preference_t pref)
|
||||
{
|
||||
const char* group = _get_group(pref);
|
||||
const char* key = _get_key(pref);
|
||||
const gchar* group = _get_group(pref);
|
||||
const gchar* key = _get_key(pref);
|
||||
gboolean def = _get_default_boolean(pref);
|
||||
|
||||
if (!g_key_file_has_key(prefs, group, key, NULL)) {
|
||||
@@ -592,8 +639,8 @@ prefs_get_boolean(preference_t pref)
|
||||
void
|
||||
prefs_set_boolean(preference_t pref, gboolean value)
|
||||
{
|
||||
const char* group = _get_group(pref);
|
||||
const char* key = _get_key(pref);
|
||||
const gchar* group = _get_group(pref);
|
||||
const gchar* key = _get_key(pref);
|
||||
g_key_file_set_boolean(prefs, group, key, value);
|
||||
}
|
||||
|
||||
@@ -608,9 +655,9 @@ prefs_set_boolean(preference_t pref, gboolean value)
|
||||
gchar*
|
||||
prefs_get_string(preference_t pref)
|
||||
{
|
||||
const char* group = _get_group(pref);
|
||||
const char* key = _get_key(pref);
|
||||
char* def = _get_default_string(pref);
|
||||
const gchar* group = _get_group(pref);
|
||||
const gchar* key = _get_key(pref);
|
||||
gchar* def = _get_default_string(pref);
|
||||
|
||||
gchar* result = g_key_file_get_string(prefs, group, key, NULL);
|
||||
|
||||
@@ -637,9 +684,9 @@ prefs_get_string(preference_t pref)
|
||||
gchar*
|
||||
prefs_get_string_with_locale(preference_t pref, gchar* locale)
|
||||
{
|
||||
const char* group = _get_group(pref);
|
||||
const char* key = _get_key(pref);
|
||||
char* def = _get_default_string(pref);
|
||||
const gchar* group = _get_group(pref);
|
||||
const gchar* key = _get_key(pref);
|
||||
gchar* def = _get_default_string(pref);
|
||||
|
||||
gchar* result = g_key_file_get_locale_string(prefs, group, key, locale, NULL);
|
||||
|
||||
@@ -668,8 +715,8 @@ prefs_get_string_with_locale(preference_t pref, gchar* locale)
|
||||
void
|
||||
prefs_set_string(preference_t pref, const gchar* new_value)
|
||||
{
|
||||
const char* group = _get_group(pref);
|
||||
const char* key = _get_key(pref);
|
||||
const gchar* group = _get_group(pref);
|
||||
const gchar* key = _get_key(pref);
|
||||
if (new_value == NULL) {
|
||||
g_key_file_remove_key(prefs, group, key, NULL);
|
||||
} else {
|
||||
@@ -678,10 +725,10 @@ prefs_set_string(preference_t pref, const gchar* new_value)
|
||||
}
|
||||
|
||||
void
|
||||
prefs_set_string_with_option(preference_t pref, char* option, char* value)
|
||||
prefs_set_string_with_option(preference_t pref, gchar* option, gchar* value)
|
||||
{
|
||||
const char* group = _get_group(pref);
|
||||
const char* key = _get_key(pref);
|
||||
const gchar* group = _get_group(pref);
|
||||
const gchar* key = _get_key(pref);
|
||||
if (value == NULL) {
|
||||
g_key_file_remove_key(prefs, group, key, NULL);
|
||||
} else {
|
||||
@@ -690,10 +737,10 @@ prefs_set_string_with_option(preference_t pref, char* option, char* value)
|
||||
}
|
||||
|
||||
void
|
||||
prefs_set_string_list_with_option(preference_t pref, char* option, const gchar* const* values)
|
||||
prefs_set_string_list_with_option(preference_t pref, gchar* option, const gchar* const* values)
|
||||
{
|
||||
const char* group = _get_group(pref);
|
||||
const char* key = _get_key(pref);
|
||||
const gchar* group = _get_group(pref);
|
||||
const gchar* key = _get_key(pref);
|
||||
if (values == NULL || *values == NULL) {
|
||||
if (g_strcmp0(option, "*") == 0) {
|
||||
g_key_file_set_string_list(prefs, group, key, NULL, 0);
|
||||
@@ -713,11 +760,11 @@ prefs_set_string_list_with_option(preference_t pref, char* option, const gchar*
|
||||
}
|
||||
}
|
||||
|
||||
char*
|
||||
gchar*
|
||||
prefs_get_tls_certpath(void)
|
||||
{
|
||||
const char* group = _get_group(PREF_TLS_CERTPATH);
|
||||
const char* key = _get_key(PREF_TLS_CERTPATH);
|
||||
const gchar* group = _get_group(PREF_TLS_CERTPATH);
|
||||
const gchar* key = _get_key(PREF_TLS_CERTPATH);
|
||||
|
||||
auto_gchar gchar* setting = g_key_file_get_string(prefs, group, key, NULL);
|
||||
|
||||
@@ -745,7 +792,7 @@ prefs_get_tls_certpath(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* result = strdup(setting);
|
||||
gchar* result = g_strdup(setting);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -949,14 +996,14 @@ prefs_get_plugins(void)
|
||||
}
|
||||
|
||||
void
|
||||
prefs_add_plugin(const char* const name)
|
||||
prefs_add_plugin(const gchar* const name)
|
||||
{
|
||||
conf_string_list_add(prefs, PREF_GROUP_PLUGINS, "load", name);
|
||||
_save_prefs();
|
||||
}
|
||||
|
||||
void
|
||||
prefs_remove_plugin(const char* const name)
|
||||
prefs_remove_plugin(const gchar* const name)
|
||||
{
|
||||
conf_string_list_remove(prefs, PREF_GROUP_PLUGINS, "load", name);
|
||||
_save_prefs();
|
||||
@@ -990,7 +1037,7 @@ prefs_get_occupants_char(void)
|
||||
}
|
||||
|
||||
void
|
||||
prefs_set_occupants_char(char* ch)
|
||||
prefs_set_occupants_char(gchar* ch)
|
||||
{
|
||||
if (g_utf8_strlen(ch, 4) == 1) {
|
||||
g_key_file_set_string(prefs, PREF_GROUP_UI, "occupants.char", ch);
|
||||
@@ -1035,7 +1082,7 @@ prefs_get_occupants_header_char(void)
|
||||
}
|
||||
|
||||
void
|
||||
prefs_set_occupants_header_char(char* ch)
|
||||
prefs_set_occupants_header_char(gchar* ch)
|
||||
{
|
||||
if (g_utf8_strlen(ch, 4) == 1) {
|
||||
g_key_file_set_string(prefs, PREF_GROUP_UI, "occupants.header.char", ch);
|
||||
@@ -1069,7 +1116,7 @@ prefs_get_roster_size(void)
|
||||
}
|
||||
|
||||
static gchar*
|
||||
_prefs_get_encryption_char(const char* const ch, const char* const pref_group, const char* const key)
|
||||
_prefs_get_encryption_char(const gchar* const ch, const gchar* const pref_group, const gchar* const key)
|
||||
{
|
||||
gchar* result = NULL;
|
||||
|
||||
@@ -1084,7 +1131,7 @@ _prefs_get_encryption_char(const char* const ch, const char* const pref_group, c
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_prefs_set_encryption_char(const char* const ch, const char* const pref_group, const char* const key)
|
||||
_prefs_set_encryption_char(const gchar* const ch, const gchar* const pref_group, const gchar* const key)
|
||||
{
|
||||
if (g_utf8_strlen(ch, 4) == 1) {
|
||||
g_key_file_set_string(prefs, pref_group, key, ch);
|
||||
@@ -1102,7 +1149,7 @@ prefs_get_otr_char(void)
|
||||
}
|
||||
|
||||
gboolean
|
||||
prefs_set_otr_char(char* ch)
|
||||
prefs_set_otr_char(gchar* ch)
|
||||
{
|
||||
return _prefs_set_encryption_char(ch, PREF_GROUP_OTR, "otr.char");
|
||||
}
|
||||
@@ -1114,7 +1161,7 @@ prefs_get_pgp_char(void)
|
||||
}
|
||||
|
||||
gboolean
|
||||
prefs_set_pgp_char(char* ch)
|
||||
prefs_set_pgp_char(gchar* ch)
|
||||
{
|
||||
return _prefs_set_encryption_char(ch, PREF_GROUP_PGP, "pgp.char");
|
||||
}
|
||||
@@ -1126,7 +1173,7 @@ prefs_get_ox_char(void)
|
||||
}
|
||||
|
||||
gboolean
|
||||
prefs_set_ox_char(char* ch)
|
||||
prefs_set_ox_char(gchar* ch)
|
||||
{
|
||||
return _prefs_set_encryption_char(ch, PREF_GROUP_OX, "ox.char");
|
||||
}
|
||||
@@ -1138,7 +1185,7 @@ prefs_get_omemo_char(void)
|
||||
}
|
||||
|
||||
gboolean
|
||||
prefs_set_omemo_char(char* ch)
|
||||
prefs_set_omemo_char(gchar* ch)
|
||||
{
|
||||
return _prefs_set_encryption_char(ch, PREF_GROUP_OMEMO, "omemo.char");
|
||||
}
|
||||
@@ -1150,7 +1197,7 @@ prefs_get_roster_header_char(void)
|
||||
}
|
||||
|
||||
void
|
||||
prefs_set_roster_header_char(char* ch)
|
||||
prefs_set_roster_header_char(gchar* ch)
|
||||
{
|
||||
if (g_utf8_strlen(ch, 4) == 1) {
|
||||
g_key_file_set_string(prefs, PREF_GROUP_UI, "roster.header.char", ch);
|
||||
@@ -1172,7 +1219,7 @@ prefs_get_roster_contact_char(void)
|
||||
}
|
||||
|
||||
void
|
||||
prefs_set_roster_contact_char(char* ch)
|
||||
prefs_set_roster_contact_char(gchar* ch)
|
||||
{
|
||||
if (g_utf8_strlen(ch, 4) == 1) {
|
||||
g_key_file_set_string(prefs, PREF_GROUP_UI, "roster.contact.char", ch);
|
||||
@@ -1194,7 +1241,7 @@ prefs_get_roster_resource_char(void)
|
||||
}
|
||||
|
||||
void
|
||||
prefs_set_roster_resource_char(char* ch)
|
||||
prefs_set_roster_resource_char(gchar* ch)
|
||||
{
|
||||
if (g_utf8_strlen(ch, 4) == 1) {
|
||||
g_key_file_set_string(prefs, PREF_GROUP_UI, "roster.resource.char", ch);
|
||||
@@ -1216,7 +1263,7 @@ prefs_get_roster_private_char(void)
|
||||
}
|
||||
|
||||
void
|
||||
prefs_set_roster_private_char(char* ch)
|
||||
prefs_set_roster_private_char(gchar* ch)
|
||||
{
|
||||
if (g_utf8_strlen(ch, 4) == 1) {
|
||||
g_key_file_set_string(prefs, PREF_GROUP_UI, "roster.private.char", ch);
|
||||
@@ -1238,7 +1285,7 @@ prefs_get_roster_room_char(void)
|
||||
}
|
||||
|
||||
void
|
||||
prefs_set_roster_room_char(char* ch)
|
||||
prefs_set_roster_room_char(gchar* ch)
|
||||
{
|
||||
if (g_utf8_strlen(ch, 4) == 1) {
|
||||
g_key_file_set_string(prefs, PREF_GROUP_UI, "roster.rooms.char", ch);
|
||||
@@ -1260,7 +1307,7 @@ prefs_get_roster_room_private_char(void)
|
||||
}
|
||||
|
||||
void
|
||||
prefs_set_roster_room_private_char(char* ch)
|
||||
prefs_set_roster_room_private_char(gchar* ch)
|
||||
{
|
||||
if (g_utf8_strlen(ch, 4) == 1) {
|
||||
g_key_file_set_string(prefs, PREF_GROUP_UI, "roster.rooms.private.char", ch);
|
||||
@@ -1347,7 +1394,7 @@ prefs_get_correction_char(void)
|
||||
}
|
||||
|
||||
void
|
||||
prefs_set_correction_char(char* ch)
|
||||
prefs_set_correction_char(gchar* ch)
|
||||
{
|
||||
if (g_utf8_strlen(ch, 4) == 1) {
|
||||
g_key_file_set_string(prefs, PREF_GROUP_UI, "correction.char", ch);
|
||||
@@ -1357,7 +1404,7 @@ prefs_set_correction_char(char* ch)
|
||||
}
|
||||
|
||||
gboolean
|
||||
prefs_add_room_notify_trigger(const char* const text)
|
||||
prefs_add_room_notify_trigger(const gchar* const text)
|
||||
{
|
||||
gboolean res = conf_string_list_add(prefs, PREF_GROUP_NOTIFICATIONS, "room.trigger.list", text);
|
||||
|
||||
@@ -1369,7 +1416,7 @@ prefs_add_room_notify_trigger(const char* const text)
|
||||
}
|
||||
|
||||
gboolean
|
||||
prefs_remove_room_notify_trigger(const char* const text)
|
||||
prefs_remove_room_notify_trigger(const gchar* const text)
|
||||
{
|
||||
gboolean res = conf_string_list_remove(prefs, PREF_GROUP_NOTIFICATIONS, "room.trigger.list", text);
|
||||
_save_prefs();
|
||||
@@ -1388,7 +1435,7 @@ prefs_get_room_notify_triggers(void)
|
||||
gsize len = 0;
|
||||
auto_gcharv gchar** triggers = g_key_file_get_string_list(prefs, PREF_GROUP_NOTIFICATIONS, "room.trigger.list", &len, NULL);
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
for (gsize i = 0; i < len; i++) {
|
||||
result = g_list_append(result, strdup(triggers[i]));
|
||||
}
|
||||
|
||||
@@ -1398,7 +1445,7 @@ prefs_get_room_notify_triggers(void)
|
||||
ProfWinPlacement*
|
||||
prefs_create_profwin_placement(int titlebar, int mainwin, int statusbar, int inputwin)
|
||||
{
|
||||
ProfWinPlacement* placement = malloc(sizeof(ProfWinPlacement));
|
||||
ProfWinPlacement* placement = g_new0(ProfWinPlacement, 1);
|
||||
placement->titlebar_pos = titlebar;
|
||||
placement->mainwin_pos = mainwin;
|
||||
placement->statusbar_pos = statusbar;
|
||||
@@ -1689,7 +1736,7 @@ prefs_inputwin_pos_down(void)
|
||||
}
|
||||
|
||||
gboolean
|
||||
prefs_add_alias(const char* const name, const char* const value)
|
||||
prefs_add_alias(const gchar* const name, const gchar* const value)
|
||||
{
|
||||
if (g_key_file_has_key(prefs, PREF_GROUP_ALIAS, name, NULL)) {
|
||||
return FALSE;
|
||||
@@ -1700,13 +1747,13 @@ prefs_add_alias(const char* const name, const char* const value)
|
||||
}
|
||||
|
||||
gchar*
|
||||
prefs_get_alias(const char* const name)
|
||||
prefs_get_alias(const gchar* const name)
|
||||
{
|
||||
return g_key_file_get_string(prefs, PREF_GROUP_ALIAS, name, NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
prefs_remove_alias(const char* const name)
|
||||
prefs_remove_alias(const gchar* const name)
|
||||
{
|
||||
if (!g_key_file_has_key(prefs, PREF_GROUP_ALIAS, name, NULL)) {
|
||||
return FALSE;
|
||||
@@ -1735,14 +1782,14 @@ prefs_get_aliases(void)
|
||||
gsize len;
|
||||
auto_gcharv gchar** keys = g_key_file_get_keys(prefs, PREF_GROUP_ALIAS, &len, NULL);
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
char* name = keys[i];
|
||||
for (gsize i = 0; i < len; i++) {
|
||||
gchar* name = keys[i];
|
||||
auto_gchar gchar* value = g_key_file_get_string(prefs, PREF_GROUP_ALIAS, name, NULL);
|
||||
|
||||
if (value) {
|
||||
ProfAlias* alias = malloc(sizeof(struct prof_alias_t));
|
||||
alias->name = strdup(name);
|
||||
alias->value = strdup(value);
|
||||
ProfAlias* alias = g_new0(struct prof_alias_t, 1);
|
||||
alias->name = g_strdup(name);
|
||||
alias->value = g_strdup(value);
|
||||
|
||||
result = g_list_insert_sorted(result, alias, (GCompareFunc)_alias_cmp);
|
||||
}
|
||||
@@ -1755,9 +1802,9 @@ prefs_get_aliases(void)
|
||||
void
|
||||
_free_alias(ProfAlias* alias)
|
||||
{
|
||||
FREE_SET_NULL(alias->name);
|
||||
FREE_SET_NULL(alias->value);
|
||||
FREE_SET_NULL(alias);
|
||||
GFREE_SET_NULL(alias->name);
|
||||
GFREE_SET_NULL(alias->value);
|
||||
GFREE_SET_NULL(alias);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2135,7 +2182,7 @@ prefs_free_ai_settings(GList* settings)
|
||||
// get the preference group for a specific preference
|
||||
// for example the PREF_BEEP setting ("beep" in .profrc, see _get_key) belongs
|
||||
// to the [ui] section.
|
||||
static const char*
|
||||
static const gchar*
|
||||
_get_group(preference_t pref)
|
||||
{
|
||||
switch (pref) {
|
||||
@@ -2292,6 +2339,9 @@ _get_group(preference_t pref)
|
||||
return PREF_GROUP_OMEMO;
|
||||
case PREF_OX_LOG:
|
||||
return PREF_GROUP_OX;
|
||||
case PREF_SPELLCHECK_ENABLE:
|
||||
case PREF_SPELLCHECK_LANG:
|
||||
return PREF_GROUP_SPELLCHECK;
|
||||
case PREF_AI_PROVIDER:
|
||||
case PREF_AI_API_KEY:
|
||||
return PREF_GROUP_AI;
|
||||
@@ -2302,7 +2352,7 @@ _get_group(preference_t pref)
|
||||
|
||||
// get the key used in .profrc for the preference
|
||||
// for example the PREF_AUTOAWAY_MODE maps to "autoaway.mode" in .profrc
|
||||
static const char*
|
||||
static const gchar*
|
||||
_get_key(preference_t pref)
|
||||
{
|
||||
switch (pref) {
|
||||
@@ -2592,6 +2642,10 @@ _get_key(preference_t pref)
|
||||
return "force-encryption.enabled";
|
||||
case PREF_FORCE_ENCRYPTION_MODE:
|
||||
return "force-encryption.policy";
|
||||
case PREF_SPELLCHECK_ENABLE:
|
||||
return "enabled";
|
||||
case PREF_SPELLCHECK_LANG:
|
||||
return "lang";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
@@ -2646,6 +2700,7 @@ _get_default_boolean(preference_t pref)
|
||||
case PREF_STROPHE_SM_ENABLED:
|
||||
case PREF_STROPHE_SM_RESEND:
|
||||
return TRUE;
|
||||
case PREF_SPELLCHECK_ENABLE:
|
||||
case PREF_PGP_PUBKEY_AUTOIMPORT:
|
||||
case PREF_FORCE_ENCRYPTION:
|
||||
default:
|
||||
@@ -2655,7 +2710,7 @@ _get_default_boolean(preference_t pref)
|
||||
|
||||
// the default setting for a string type preference
|
||||
// if it is not specified in .profrc
|
||||
static char*
|
||||
static gchar*
|
||||
_get_default_string(preference_t pref)
|
||||
{
|
||||
switch (pref) {
|
||||
@@ -2756,6 +2811,8 @@ _get_default_string(preference_t pref)
|
||||
return "on";
|
||||
case PREF_FORCE_ENCRYPTION_MODE:
|
||||
return "resend-to-confirm";
|
||||
case PREF_SPELLCHECK_LANG:
|
||||
return "en_US";
|
||||
case PREF_AI_PROVIDER:
|
||||
return "openai";
|
||||
case PREF_AI_API_KEY:
|
||||
|
||||
@@ -3,35 +3,9 @@
|
||||
* vim: expandtab:ts=4:sts=4:sw=4
|
||||
*
|
||||
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
||||
* Copyright (C) 2019 - 2025 Michael Vetter <jubalh@iodoru.org>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
* Copyright (C) 2019 - 2026 Michael Vetter <jubalh@iodoru.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_PREFERENCES_H
|
||||
@@ -192,7 +166,9 @@ typedef enum {
|
||||
PREF_VCARD_PHOTO_CMD,
|
||||
PREF_STATUSBAR_TABMODE,
|
||||
PREF_FORCE_ENCRYPTION,
|
||||
PREF_FORCE_ENCRYPTION_MODE
|
||||
PREF_FORCE_ENCRYPTION_MODE,
|
||||
PREF_SPELLCHECK_ENABLE,
|
||||
PREF_SPELLCHECK_LANG,
|
||||
} preference_t;
|
||||
|
||||
typedef struct prof_alias_t
|
||||
@@ -209,15 +185,16 @@ typedef struct prof_winplacement_t
|
||||
int inputwin_pos;
|
||||
} ProfWinPlacement;
|
||||
|
||||
void prefs_load(const char* config_file);
|
||||
void prefs_load(const gchar* config_file);
|
||||
void prefs_changes(void);
|
||||
void prefs_save(void);
|
||||
void prefs_close(void);
|
||||
void prefs_reload(void);
|
||||
|
||||
gchar* prefs_autocomplete_boolean_choice(const char* const prefix, gboolean previous, void* context);
|
||||
gchar* prefs_autocomplete_boolean_choice(const gchar* const prefix, gboolean previous, void* context);
|
||||
void prefs_reset_boolean_choice(void);
|
||||
|
||||
gchar* prefs_autocomplete_room_trigger(const char* const prefix, gboolean previous, void* context);
|
||||
gchar* prefs_autocomplete_room_trigger(const gchar* const prefix, gboolean previous, void* context);
|
||||
void prefs_reset_room_trigger_ac(void);
|
||||
|
||||
gint prefs_get_gone(void);
|
||||
@@ -254,42 +231,42 @@ gint prefs_get_autoxa_time(void);
|
||||
void prefs_set_autoxa_time(gint value);
|
||||
|
||||
gchar** prefs_get_plugins(void);
|
||||
void prefs_add_plugin(const char* const name);
|
||||
void prefs_remove_plugin(const char* const name);
|
||||
void prefs_add_plugin(const gchar* const name);
|
||||
void prefs_remove_plugin(const gchar* const name);
|
||||
|
||||
gchar* prefs_get_otr_char(void);
|
||||
gboolean prefs_set_otr_char(char* ch);
|
||||
gboolean prefs_set_otr_char(gchar* ch);
|
||||
gchar* prefs_get_pgp_char(void);
|
||||
gboolean prefs_set_pgp_char(char* ch);
|
||||
gboolean prefs_set_pgp_char(gchar* ch);
|
||||
gchar* prefs_get_omemo_char(void);
|
||||
gboolean prefs_set_omemo_char(char* ch);
|
||||
gboolean prefs_set_omemo_char(gchar* ch);
|
||||
// XEP-0373: OpenPGP for XMPP
|
||||
char* prefs_get_ox_char(void);
|
||||
gboolean prefs_set_ox_char(char* ch);
|
||||
gboolean prefs_set_ox_char(gchar* ch);
|
||||
|
||||
gchar* prefs_get_roster_header_char(void);
|
||||
void prefs_set_roster_header_char(char* ch);
|
||||
void prefs_set_roster_header_char(gchar* ch);
|
||||
void prefs_clear_roster_header_char(void);
|
||||
gchar* prefs_get_roster_contact_char(void);
|
||||
void prefs_set_roster_contact_char(char* ch);
|
||||
void prefs_set_roster_contact_char(gchar* ch);
|
||||
void prefs_clear_roster_contact_char(void);
|
||||
gchar* prefs_get_roster_resource_char(void);
|
||||
void prefs_set_roster_resource_char(char* ch);
|
||||
void prefs_set_roster_resource_char(gchar* ch);
|
||||
void prefs_clear_roster_resource_char(void);
|
||||
gchar* prefs_get_roster_private_char(void);
|
||||
void prefs_set_roster_private_char(char* ch);
|
||||
void prefs_set_roster_private_char(gchar* ch);
|
||||
void prefs_clear_roster_private_char(void);
|
||||
gchar* prefs_get_roster_room_char(void);
|
||||
void prefs_set_roster_room_char(char* ch);
|
||||
void prefs_set_roster_room_char(gchar* ch);
|
||||
void prefs_clear_roster_room_char(void);
|
||||
gchar* prefs_get_roster_room_private_char(void);
|
||||
void prefs_set_roster_room_private_char(char* ch);
|
||||
void prefs_set_roster_room_private_char(gchar* ch);
|
||||
void prefs_clear_roster_room_private_char(void);
|
||||
gchar* prefs_get_occupants_char(void);
|
||||
void prefs_set_occupants_char(char* ch);
|
||||
void prefs_set_occupants_char(gchar* ch);
|
||||
void prefs_clear_occupants_char(void);
|
||||
gchar* prefs_get_occupants_header_char(void);
|
||||
void prefs_set_occupants_header_char(char* ch);
|
||||
void prefs_set_occupants_header_char(gchar* ch);
|
||||
void prefs_clear_occupants_header_char(void);
|
||||
|
||||
gint prefs_get_roster_contact_indent(void);
|
||||
@@ -302,21 +279,21 @@ gint prefs_get_occupants_indent(void);
|
||||
void prefs_set_occupants_indent(gint value);
|
||||
|
||||
gchar* prefs_get_correction_char(void);
|
||||
void prefs_set_correction_char(char* ch);
|
||||
void prefs_set_correction_char(gchar* ch);
|
||||
|
||||
void prefs_add_login(const char* jid);
|
||||
void prefs_add_login(const gchar* jid);
|
||||
|
||||
void prefs_set_tray_timer(gint value);
|
||||
gint prefs_get_tray_timer(void);
|
||||
|
||||
gboolean prefs_add_alias(const char* const name, const char* const value);
|
||||
gboolean prefs_remove_alias(const char* const name);
|
||||
gchar* prefs_get_alias(const char* const name);
|
||||
gboolean prefs_add_alias(const gchar* const name, const gchar* const value);
|
||||
gboolean prefs_remove_alias(const gchar* const name);
|
||||
gchar* prefs_get_alias(const gchar* const name);
|
||||
GList* prefs_get_aliases(void);
|
||||
void prefs_free_aliases(GList* aliases);
|
||||
|
||||
gboolean prefs_add_room_notify_trigger(const char* const text);
|
||||
gboolean prefs_remove_room_notify_trigger(const char* const text);
|
||||
gboolean prefs_add_room_notify_trigger(const gchar* const text);
|
||||
gboolean prefs_remove_room_notify_trigger(const gchar* const text);
|
||||
GList* prefs_get_room_notify_triggers(void);
|
||||
|
||||
ProfWinPlacement* prefs_get_win_placement(void);
|
||||
|
||||
@@ -4,33 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@@ -4,33 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_SCRIPTS_H
|
||||
|
||||
@@ -3,35 +3,9 @@
|
||||
* vim: expandtab:ts=4:sts=4:sw=4
|
||||
*
|
||||
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
||||
* Copyright (C) 2019 - 2025 Michael Vetter <jubalh@iodoru.org>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
* Copyright (C) 2019 - 2026 Michael Vetter <jubalh@iodoru.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -117,6 +91,7 @@ theme_init(const char* const theme_name)
|
||||
g_hash_table_insert(defaults, strdup("mention"), strdup("yellow"));
|
||||
g_hash_table_insert(defaults, strdup("trigger"), strdup("yellow"));
|
||||
g_hash_table_insert(defaults, strdup("input.text"), strdup("default"));
|
||||
g_hash_table_insert(defaults, strdup("input.misspelled"), strdup("red"));
|
||||
g_hash_table_insert(defaults, strdup("main.time"), strdup("default"));
|
||||
g_hash_table_insert(defaults, strdup("titlebar.text"), strdup("white"));
|
||||
g_hash_table_insert(defaults, strdup("titlebar.brackets"), strdup("cyan"));
|
||||
@@ -533,7 +508,7 @@ _theme_find(const char* const theme_name)
|
||||
g_string_append(path, "/");
|
||||
g_string_append(path, theme_name);
|
||||
if (!g_file_test(path->str, G_FILE_TEST_EXISTS)) {
|
||||
g_string_free(path, true);
|
||||
g_string_free(path, TRUE);
|
||||
path = NULL;
|
||||
}
|
||||
}
|
||||
@@ -667,25 +642,17 @@ _theme_prep_fgnd(char* setting, GString* lookup_str, gboolean* bold)
|
||||
}
|
||||
}
|
||||
|
||||
char*
|
||||
gchar*
|
||||
theme_get_string(char* str)
|
||||
{
|
||||
gchar* res = g_key_file_get_string(theme, "colours", str, NULL);
|
||||
if (!res) {
|
||||
return strdup(g_hash_table_lookup(defaults, str));
|
||||
return g_strdup(g_hash_table_lookup(defaults, str));
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
theme_free_string(char* str)
|
||||
{
|
||||
if (str) {
|
||||
g_free(str);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
theme_hash_attrs(const char* str)
|
||||
{
|
||||
@@ -748,6 +715,9 @@ theme_attrs(theme_item_t attrs)
|
||||
case THEME_INPUT_TEXT:
|
||||
_theme_prep_fgnd("input.text", lookup_str, &bold);
|
||||
break;
|
||||
case THEME_INPUT_MISSPELLED:
|
||||
_theme_prep_fgnd("input.misspelled", lookup_str, &bold);
|
||||
break;
|
||||
case THEME_TIME:
|
||||
_theme_prep_fgnd("main.time", lookup_str, &bold);
|
||||
break;
|
||||
|
||||
@@ -4,33 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_THEME_H
|
||||
@@ -53,6 +27,7 @@ typedef enum {
|
||||
THEME_MENTION,
|
||||
THEME_TRIGGER,
|
||||
THEME_INPUT_TEXT,
|
||||
THEME_INPUT_MISSPELLED,
|
||||
THEME_TIME,
|
||||
THEME_TITLE_TEXT,
|
||||
THEME_TITLE_BRACKET,
|
||||
@@ -152,7 +127,6 @@ void theme_close(void);
|
||||
int theme_hash_attrs(const char* str);
|
||||
int theme_attrs(theme_item_t attrs);
|
||||
char* theme_get_string(char* str);
|
||||
void theme_free_string(char* str);
|
||||
theme_item_t theme_main_presence_attrs(const char* const presence);
|
||||
theme_item_t theme_roster_unread_presence_attrs(const char* const presence);
|
||||
theme_item_t theme_roster_active_presence_attrs(const char* const presence);
|
||||
|
||||
@@ -4,33 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -54,7 +28,7 @@ static void _save_tlscerts(void);
|
||||
|
||||
static Autocomplete certs_ac;
|
||||
|
||||
static char* current_fp;
|
||||
static gchar* current_fp;
|
||||
|
||||
static void
|
||||
_tlscerts_close(void)
|
||||
@@ -62,7 +36,7 @@ _tlscerts_close(void)
|
||||
free_keyfile(&tlscerts_prof_keyfile);
|
||||
tlscerts = NULL;
|
||||
|
||||
free(current_fp);
|
||||
g_free(current_fp);
|
||||
current_fp = NULL;
|
||||
|
||||
autocomplete_free(certs_ac);
|
||||
@@ -82,7 +56,7 @@ tlscerts_init(void)
|
||||
gsize len = 0;
|
||||
auto_gcharv gchar** groups = g_key_file_get_groups(tlscerts, &len);
|
||||
|
||||
for (int i = 0; i < g_strv_length(groups); i++) {
|
||||
for (guint i = 0; i < g_strv_length(groups); i++) {
|
||||
autocomplete_add(certs_ac, groups[i]);
|
||||
}
|
||||
|
||||
@@ -90,33 +64,116 @@ tlscerts_init(void)
|
||||
}
|
||||
|
||||
void
|
||||
tlscerts_set_current(const char* const fp)
|
||||
tlscerts_set_current(const TLSCertificate* cert)
|
||||
{
|
||||
if (current_fp) {
|
||||
free(current_fp);
|
||||
g_free(current_fp);
|
||||
}
|
||||
current_fp = strdup(fp);
|
||||
current_fp = g_strdup(cert->fingerprint);
|
||||
}
|
||||
|
||||
char*
|
||||
tlscerts_get_current(void)
|
||||
gboolean
|
||||
tlscerts_current_fingerprint_equals(const TLSCertificate* cert)
|
||||
{
|
||||
return current_fp;
|
||||
return g_strcmp0(current_fp, cert->fingerprint) == 0;
|
||||
}
|
||||
|
||||
void
|
||||
tlscerts_clear_current(void)
|
||||
{
|
||||
if (current_fp) {
|
||||
free(current_fp);
|
||||
g_free(current_fp);
|
||||
current_fp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
tlscerts_exists(const char* const fingerprint)
|
||||
tlscerts_exists(const TLSCertificate* cert)
|
||||
{
|
||||
return g_key_file_has_group(tlscerts, fingerprint);
|
||||
return g_key_file_has_group(tlscerts, cert->fingerprint);
|
||||
}
|
||||
|
||||
#define _name_to_tlscert_name(in, cert, which) \
|
||||
do { \
|
||||
_name_to_tlscert_name_(in, &cert->which, #which); \
|
||||
} while (0)
|
||||
static void
|
||||
_name_to_tlscert_name_(const char* in, tls_cert_name_t* out, const char* name);
|
||||
|
||||
static TLSCertificate*
|
||||
_tlscerts_new(gchar* fingerprint_sha1, int version, gchar* serialnumber, gchar* subjectname,
|
||||
gchar* issuername, gchar* notbefore, gchar* notafter,
|
||||
gchar* key_alg, gchar* signature_alg, gchar* pem,
|
||||
gchar* fingerprint_sha256, gchar* pubkey_fingerprint)
|
||||
{
|
||||
TLSCertificate* cert = g_new0(TLSCertificate, 1);
|
||||
|
||||
if (fingerprint_sha256 && fingerprint_sha1) {
|
||||
cert->fingerprint_sha256 = fingerprint_sha256;
|
||||
cert->fingerprint_sha1 = fingerprint_sha1;
|
||||
cert->fingerprint = cert->fingerprint_sha256;
|
||||
} else {
|
||||
if (fingerprint_sha256) {
|
||||
size_t s = strlen(fingerprint_sha256);
|
||||
switch (s) {
|
||||
case 40:
|
||||
cert->fingerprint_sha1 = fingerprint_sha256;
|
||||
cert->fingerprint = cert->fingerprint_sha1;
|
||||
break;
|
||||
case 64:
|
||||
cert->fingerprint_sha256 = fingerprint_sha256;
|
||||
cert->fingerprint = cert->fingerprint_sha256;
|
||||
break;
|
||||
default:
|
||||
log_error("fingerprint_sha256 of length %zu unexpected: %s", s, fingerprint_sha256);
|
||||
}
|
||||
} else {
|
||||
cert->fingerprint_sha1 = fingerprint_sha1;
|
||||
cert->fingerprint = cert->fingerprint_sha1;
|
||||
}
|
||||
}
|
||||
|
||||
cert->version = version;
|
||||
cert->serialnumber = serialnumber;
|
||||
cert->subjectname = subjectname;
|
||||
cert->issuername = issuername;
|
||||
cert->notbefore = notbefore;
|
||||
cert->notafter = notafter;
|
||||
cert->key_alg = key_alg;
|
||||
cert->signature_alg = signature_alg;
|
||||
cert->pem = pem;
|
||||
cert->pubkey_fingerprint = pubkey_fingerprint;
|
||||
|
||||
/* Do this check after assigning all values, in order to not leak them,
|
||||
* even though the situation is most likely already FUBAR */
|
||||
if (!fingerprint_sha256 && !fingerprint_sha1) {
|
||||
log_error("No TLSCertificate w/o fingerprint");
|
||||
tlscerts_free(cert);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_name_to_tlscert_name(subjectname, cert, subject);
|
||||
_name_to_tlscert_name(issuername, cert, issuer);
|
||||
|
||||
return cert;
|
||||
}
|
||||
|
||||
static TLSCertificate*
|
||||
_get_TLSCertificate(const gchar* fingerprint)
|
||||
{
|
||||
int version = g_key_file_get_integer(tlscerts, fingerprint, "version", NULL);
|
||||
gchar* serialnumber = g_key_file_get_string(tlscerts, fingerprint, "serialnumber", NULL);
|
||||
gchar* subjectname = g_key_file_get_string(tlscerts, fingerprint, "subjectname", NULL);
|
||||
gchar* issuername = g_key_file_get_string(tlscerts, fingerprint, "issuername", NULL);
|
||||
gchar* notbefore = g_key_file_get_string(tlscerts, fingerprint, "start", NULL);
|
||||
gchar* notafter = g_key_file_get_string(tlscerts, fingerprint, "end", NULL);
|
||||
gchar* keyalg = g_key_file_get_string(tlscerts, fingerprint, "keyalg", NULL);
|
||||
gchar* signaturealg = g_key_file_get_string(tlscerts, fingerprint, "signaturealg", NULL);
|
||||
gchar* fingerprint_sha1 = g_key_file_get_string(tlscerts, fingerprint, "fingerprint_sha1", NULL);
|
||||
gchar* pubkey_fingerprint = g_key_file_get_string(tlscerts, fingerprint, "pubkey_fingerprint", NULL);
|
||||
|
||||
return _tlscerts_new(fingerprint_sha1, version, serialnumber, subjectname, issuername, notbefore,
|
||||
notafter, keyalg, signaturealg, NULL, g_strdup(fingerprint), pubkey_fingerprint);
|
||||
}
|
||||
|
||||
GList*
|
||||
@@ -126,125 +183,81 @@ tlscerts_list(void)
|
||||
gsize len = 0;
|
||||
auto_gcharv gchar** groups = g_key_file_get_groups(tlscerts, &len);
|
||||
|
||||
for (int i = 0; i < g_strv_length(groups); i++) {
|
||||
char* fingerprint = strdup(groups[i]);
|
||||
int version = g_key_file_get_integer(tlscerts, fingerprint, "version", NULL);
|
||||
auto_gchar gchar* serialnumber = g_key_file_get_string(tlscerts, fingerprint, "serialnumber", NULL);
|
||||
auto_gchar gchar* subjectname = g_key_file_get_string(tlscerts, fingerprint, "subjectname", NULL);
|
||||
auto_gchar gchar* issuername = g_key_file_get_string(tlscerts, fingerprint, "issuername", NULL);
|
||||
auto_gchar gchar* notbefore = g_key_file_get_string(tlscerts, fingerprint, "start", NULL);
|
||||
auto_gchar gchar* notafter = g_key_file_get_string(tlscerts, fingerprint, "end", NULL);
|
||||
auto_gchar gchar* keyalg = g_key_file_get_string(tlscerts, fingerprint, "keyalg", NULL);
|
||||
auto_gchar gchar* signaturealg = g_key_file_get_string(tlscerts, fingerprint, "signaturealg", NULL);
|
||||
|
||||
TLSCertificate* cert = tlscerts_new(fingerprint, version, serialnumber, subjectname, issuername, notbefore,
|
||||
notafter, keyalg, signaturealg, NULL);
|
||||
|
||||
res = g_list_append(res, cert);
|
||||
for (gsize i = 0; i < len; i++) {
|
||||
res = g_list_append(res, _get_TLSCertificate(groups[i]));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
TLSCertificate*
|
||||
tlscerts_new(const char* const fingerprint, int version, const char* const serialnumber, const char* const subjectname,
|
||||
const char* const issuername, const char* const notbefore, const char* const notafter,
|
||||
const char* const key_alg, const char* const signature_alg, const char* const pem)
|
||||
static void
|
||||
_name_to_tlscert_name_(const char* in, tls_cert_name_t* out, const char* name)
|
||||
{
|
||||
TLSCertificate* cert = calloc(1, sizeof(TLSCertificate));
|
||||
|
||||
if (fingerprint) {
|
||||
cert->fingerprint = strdup(fingerprint);
|
||||
}
|
||||
cert->version = version;
|
||||
if (serialnumber) {
|
||||
cert->serialnumber = strdup(serialnumber);
|
||||
}
|
||||
if (subjectname) {
|
||||
cert->subjectname = strdup(subjectname);
|
||||
}
|
||||
if (issuername) {
|
||||
cert->issuername = strdup(issuername);
|
||||
}
|
||||
if (notbefore) {
|
||||
cert->notbefore = strdup(notbefore);
|
||||
}
|
||||
if (notafter) {
|
||||
cert->notafter = strdup(notafter);
|
||||
}
|
||||
if (key_alg) {
|
||||
cert->key_alg = strdup(key_alg);
|
||||
}
|
||||
if (signature_alg) {
|
||||
cert->signature_alg = strdup(signature_alg);
|
||||
}
|
||||
if (pem) {
|
||||
cert->pem = strdup(pem);
|
||||
}
|
||||
|
||||
auto_gcharv gchar** fields = g_strsplit(subjectname, "/", 0);
|
||||
for (int i = 0; i < g_strv_length(fields); i++) {
|
||||
auto_gcharv gchar** fields = g_strsplit(in, "/", 0);
|
||||
const guint fields_num = g_strv_length(fields);
|
||||
for (guint i = 0; i < fields_num; i++) {
|
||||
auto_gcharv gchar** keyval = g_strsplit(fields[i], "=", 2);
|
||||
if (g_strv_length(keyval) == 2) {
|
||||
|
||||
#define tls_cert_name_set(which) \
|
||||
do { \
|
||||
if (out->which) { \
|
||||
log_warning("%s." #which " already set, skip %s", name, keyval[1]); \
|
||||
continue; \
|
||||
} \
|
||||
out->which = g_strdup(keyval[1]); \
|
||||
} while (0)
|
||||
|
||||
if ((g_strcmp0(keyval[0], "C") == 0) || (g_strcmp0(keyval[0], "countryName") == 0)) {
|
||||
cert->subject_country = strdup(keyval[1]);
|
||||
tls_cert_name_set(country);
|
||||
}
|
||||
if ((g_strcmp0(keyval[0], "ST") == 0) || (g_strcmp0(keyval[0], "stateOrProvinceName") == 0)) {
|
||||
cert->subject_state = strdup(keyval[1]);
|
||||
tls_cert_name_set(state);
|
||||
}
|
||||
if (g_strcmp0(keyval[0], "dnQualifier") == 0) {
|
||||
cert->subject_distinguishedname = strdup(keyval[1]);
|
||||
tls_cert_name_set(distinguishedname);
|
||||
}
|
||||
if (g_strcmp0(keyval[0], "serialnumber") == 0) {
|
||||
cert->subject_serialnumber = strdup(keyval[1]);
|
||||
tls_cert_name_set(serialnumber);
|
||||
}
|
||||
if ((g_strcmp0(keyval[0], "CN") == 0) || (g_strcmp0(keyval[0], "commonName") == 0)) {
|
||||
cert->subject_commonname = strdup(keyval[1]);
|
||||
tls_cert_name_set(commonname);
|
||||
}
|
||||
if ((g_strcmp0(keyval[0], "O") == 0) || (g_strcmp0(keyval[0], "organizationName") == 0)) {
|
||||
cert->subject_organisation = strdup(keyval[1]);
|
||||
tls_cert_name_set(organisation);
|
||||
}
|
||||
if ((g_strcmp0(keyval[0], "OU") == 0) || (g_strcmp0(keyval[0], "organizationalUnitName") == 0)) {
|
||||
cert->subject_organisation_unit = strdup(keyval[1]);
|
||||
tls_cert_name_set(organisation_unit);
|
||||
}
|
||||
if (g_strcmp0(keyval[0], "emailAddress") == 0) {
|
||||
cert->subject_email = strdup(keyval[1]);
|
||||
tls_cert_name_set(email);
|
||||
}
|
||||
#undef tls_cert_name_set
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto_gcharv gchar** fields2 = g_strsplit(issuername, "/", 0);
|
||||
for (int i = 0; i < g_strv_length(fields2); i++) {
|
||||
auto_gcharv gchar** keyval = g_strsplit(fields2[i], "=", 2);
|
||||
if (g_strv_length(keyval) == 2) {
|
||||
if ((g_strcmp0(keyval[0], "C") == 0) || (g_strcmp0(keyval[0], "countryName") == 0)) {
|
||||
cert->issuer_country = strdup(keyval[1]);
|
||||
}
|
||||
if ((g_strcmp0(keyval[0], "ST") == 0) || (g_strcmp0(keyval[0], "stateOrProvinceName") == 0)) {
|
||||
cert->issuer_state = strdup(keyval[1]);
|
||||
}
|
||||
if (g_strcmp0(keyval[0], "dnQualifier") == 0) {
|
||||
cert->issuer_distinguishedname = strdup(keyval[1]);
|
||||
}
|
||||
if (g_strcmp0(keyval[0], "serialnumber") == 0) {
|
||||
cert->issuer_serialnumber = strdup(keyval[1]);
|
||||
}
|
||||
if ((g_strcmp0(keyval[0], "CN") == 0) || (g_strcmp0(keyval[0], "commonName") == 0)) {
|
||||
cert->issuer_commonname = strdup(keyval[1]);
|
||||
}
|
||||
if ((g_strcmp0(keyval[0], "O") == 0) || (g_strcmp0(keyval[0], "organizationName") == 0)) {
|
||||
cert->issuer_organisation = strdup(keyval[1]);
|
||||
}
|
||||
if ((g_strcmp0(keyval[0], "OU") == 0) || (g_strcmp0(keyval[0], "organizationalUnitName") == 0)) {
|
||||
cert->issuer_organisation_unit = strdup(keyval[1]);
|
||||
}
|
||||
if (g_strcmp0(keyval[0], "emailAddress") == 0) {
|
||||
cert->issuer_email = strdup(keyval[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
TLSCertificate*
|
||||
tlscerts_new(const char* fingerprint_sha1, int version, const char* serialnumber, const char* subjectname,
|
||||
const char* issuername, const char* notbefore, const char* notafter,
|
||||
const char* key_alg, const char* signature_alg, const char* pem,
|
||||
const char* fingerprint_sha256, const char* pubkey_fingerprint)
|
||||
{
|
||||
return _tlscerts_new(g_strdup(fingerprint_sha1), version, g_strdup(serialnumber), g_strdup(subjectname),
|
||||
g_strdup(issuername), g_strdup(notbefore), g_strdup(notafter),
|
||||
g_strdup(key_alg), g_strdup(signature_alg), g_strdup(pem),
|
||||
g_strdup(fingerprint_sha256), g_strdup(pubkey_fingerprint));
|
||||
}
|
||||
|
||||
return cert;
|
||||
static void
|
||||
_checked_g_key_file_set_string(GKeyFile* key_file,
|
||||
const gchar* group_name,
|
||||
const gchar* key,
|
||||
const gchar* string)
|
||||
{
|
||||
if (string == NULL)
|
||||
return;
|
||||
g_key_file_set_string(key_file, group_name, key, string);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -261,33 +274,21 @@ tlscerts_add(const TLSCertificate* cert)
|
||||
autocomplete_add(certs_ac, cert->fingerprint);
|
||||
|
||||
g_key_file_set_integer(tlscerts, cert->fingerprint, "version", cert->version);
|
||||
if (cert->serialnumber) {
|
||||
g_key_file_set_string(tlscerts, cert->fingerprint, "serialnumber", cert->serialnumber);
|
||||
}
|
||||
if (cert->subjectname) {
|
||||
g_key_file_set_string(tlscerts, cert->fingerprint, "subjectname", cert->subjectname);
|
||||
}
|
||||
if (cert->issuername) {
|
||||
g_key_file_set_string(tlscerts, cert->fingerprint, "issuername", cert->issuername);
|
||||
}
|
||||
if (cert->notbefore) {
|
||||
g_key_file_set_string(tlscerts, cert->fingerprint, "start", cert->notbefore);
|
||||
}
|
||||
if (cert->notafter) {
|
||||
g_key_file_set_string(tlscerts, cert->fingerprint, "end", cert->notafter);
|
||||
}
|
||||
if (cert->key_alg) {
|
||||
g_key_file_set_string(tlscerts, cert->fingerprint, "keyalg", cert->key_alg);
|
||||
}
|
||||
if (cert->signature_alg) {
|
||||
g_key_file_set_string(tlscerts, cert->fingerprint, "signaturealg", cert->signature_alg);
|
||||
}
|
||||
_checked_g_key_file_set_string(tlscerts, cert->fingerprint, "serialnumber", cert->serialnumber);
|
||||
_checked_g_key_file_set_string(tlscerts, cert->fingerprint, "subjectname", cert->subjectname);
|
||||
_checked_g_key_file_set_string(tlscerts, cert->fingerprint, "issuername", cert->issuername);
|
||||
_checked_g_key_file_set_string(tlscerts, cert->fingerprint, "start", cert->notbefore);
|
||||
_checked_g_key_file_set_string(tlscerts, cert->fingerprint, "end", cert->notafter);
|
||||
_checked_g_key_file_set_string(tlscerts, cert->fingerprint, "keyalg", cert->key_alg);
|
||||
_checked_g_key_file_set_string(tlscerts, cert->fingerprint, "signaturealg", cert->signature_alg);
|
||||
_checked_g_key_file_set_string(tlscerts, cert->fingerprint, "fingerprint_sha1", cert->fingerprint_sha1);
|
||||
_checked_g_key_file_set_string(tlscerts, cert->fingerprint, "pubkey_fingerprint", cert->pubkey_fingerprint);
|
||||
|
||||
_save_tlscerts();
|
||||
}
|
||||
|
||||
gboolean
|
||||
tlscerts_revoke(const char* const fingerprint)
|
||||
tlscerts_revoke(const char* fingerprint)
|
||||
{
|
||||
gboolean result = g_key_file_remove_group(tlscerts, fingerprint, NULL);
|
||||
if (result) {
|
||||
@@ -300,28 +301,24 @@ tlscerts_revoke(const char* const fingerprint)
|
||||
}
|
||||
|
||||
TLSCertificate*
|
||||
tlscerts_get_trusted(const char* const fingerprint)
|
||||
tlscerts_get_trusted(const gchar* fingerprint)
|
||||
{
|
||||
if (!g_key_file_has_group(tlscerts, fingerprint)) {
|
||||
gsize len = 0;
|
||||
auto_gcharv gchar** groups = g_key_file_get_groups(tlscerts, &len);
|
||||
for (gsize i = 0; i < len; i++) {
|
||||
auto_gchar gchar* fingerprint_sha1 = g_key_file_get_string(tlscerts, groups[i], "fingerprint_sha1", NULL);
|
||||
if (g_strcmp0(fingerprint, fingerprint_sha1) == 0) {
|
||||
return _get_TLSCertificate(fingerprint_sha1);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int version = g_key_file_get_integer(tlscerts, fingerprint, "version", NULL);
|
||||
auto_gchar gchar* serialnumber = g_key_file_get_string(tlscerts, fingerprint, "serialnumber", NULL);
|
||||
auto_gchar gchar* subjectname = g_key_file_get_string(tlscerts, fingerprint, "subjectname", NULL);
|
||||
auto_gchar gchar* issuername = g_key_file_get_string(tlscerts, fingerprint, "issuername", NULL);
|
||||
auto_gchar gchar* notbefore = g_key_file_get_string(tlscerts, fingerprint, "start", NULL);
|
||||
auto_gchar gchar* notafter = g_key_file_get_string(tlscerts, fingerprint, "end", NULL);
|
||||
auto_gchar gchar* keyalg = g_key_file_get_string(tlscerts, fingerprint, "keyalg", NULL);
|
||||
auto_gchar gchar* signaturealg = g_key_file_get_string(tlscerts, fingerprint, "signaturealg", NULL);
|
||||
|
||||
TLSCertificate* cert = tlscerts_new(fingerprint, version, serialnumber, subjectname, issuername, notbefore,
|
||||
notafter, keyalg, signaturealg, NULL);
|
||||
return cert;
|
||||
return _get_TLSCertificate(fingerprint);
|
||||
}
|
||||
|
||||
char*
|
||||
tlscerts_complete(const char* const prefix, gboolean previous, void* context)
|
||||
tlscerts_complete(const char* prefix, gboolean previous, void* context)
|
||||
{
|
||||
return autocomplete_complete(certs_ac, prefix, TRUE, previous);
|
||||
}
|
||||
@@ -332,40 +329,37 @@ tlscerts_reset_ac(void)
|
||||
autocomplete_reset(certs_ac);
|
||||
}
|
||||
|
||||
static void
|
||||
_tls_cert_name_free(tls_cert_name_t* name)
|
||||
{
|
||||
g_free(name->country);
|
||||
g_free(name->state);
|
||||
g_free(name->distinguishedname);
|
||||
g_free(name->serialnumber);
|
||||
g_free(name->commonname);
|
||||
g_free(name->organisation);
|
||||
g_free(name->organisation_unit);
|
||||
g_free(name->email);
|
||||
}
|
||||
|
||||
void
|
||||
tlscerts_free(TLSCertificate* cert)
|
||||
{
|
||||
if (cert) {
|
||||
free(cert->serialnumber);
|
||||
_tls_cert_name_free(&cert->subject);
|
||||
_tls_cert_name_free(&cert->issuer);
|
||||
|
||||
free(cert->subjectname);
|
||||
free(cert->subject_country);
|
||||
free(cert->subject_state);
|
||||
free(cert->subject_distinguishedname);
|
||||
free(cert->subject_serialnumber);
|
||||
free(cert->subject_commonname);
|
||||
free(cert->subject_organisation);
|
||||
free(cert->subject_organisation_unit);
|
||||
free(cert->subject_email);
|
||||
|
||||
free(cert->issuername);
|
||||
free(cert->issuer_country);
|
||||
free(cert->issuer_state);
|
||||
free(cert->issuer_distinguishedname);
|
||||
free(cert->issuer_serialnumber);
|
||||
free(cert->issuer_commonname);
|
||||
free(cert->issuer_organisation);
|
||||
free(cert->issuer_organisation_unit);
|
||||
free(cert->issuer_email);
|
||||
|
||||
free(cert->notbefore);
|
||||
free(cert->notafter);
|
||||
free(cert->fingerprint);
|
||||
|
||||
free(cert->key_alg);
|
||||
free(cert->signature_alg);
|
||||
|
||||
free(cert->pem);
|
||||
g_free(cert->pubkey_fingerprint);
|
||||
g_free(cert->pem);
|
||||
g_free(cert->signature_alg);
|
||||
g_free(cert->key_alg);
|
||||
g_free(cert->notafter);
|
||||
g_free(cert->notbefore);
|
||||
g_free(cert->issuername);
|
||||
g_free(cert->subjectname);
|
||||
g_free(cert->serialnumber);
|
||||
g_free(cert->fingerprint_sha1);
|
||||
g_free(cert->fingerprint_sha256);
|
||||
|
||||
free(cert);
|
||||
}
|
||||
|
||||
@@ -4,33 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give permission to
|
||||
* link the code of portions of this program with the OpenSSL library under
|
||||
* certain conditions as described in each individual source file, and
|
||||
* distribute linked combinations including the two.
|
||||
*
|
||||
* You must obey the GNU General Public License in all respects for all of the
|
||||
* code used other than OpenSSL. If you modify file(s) with this exception, you
|
||||
* may extend this exception to your version of the file(s), but you are not
|
||||
* obligated to do so. If you do not wish to do so, delete this exception
|
||||
* statement from your version. If you delete this exception statement from all
|
||||
* source files in the program, then also delete it here.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_TLSCERTS_H
|
||||
@@ -38,61 +12,63 @@
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
typedef struct tls_cert_name_t
|
||||
{
|
||||
gchar* country;
|
||||
gchar* state;
|
||||
gchar* distinguishedname;
|
||||
gchar* serialnumber;
|
||||
gchar* commonname;
|
||||
gchar* organisation;
|
||||
gchar* organisation_unit;
|
||||
gchar* email;
|
||||
} tls_cert_name_t;
|
||||
|
||||
typedef struct tls_cert_t
|
||||
{
|
||||
int version;
|
||||
char* serialnumber;
|
||||
char* subjectname;
|
||||
char* subject_country;
|
||||
char* subject_state;
|
||||
char* subject_distinguishedname;
|
||||
char* subject_serialnumber;
|
||||
char* subject_commonname;
|
||||
char* subject_organisation;
|
||||
char* subject_organisation_unit;
|
||||
char* subject_email;
|
||||
char* issuername;
|
||||
char* issuer_country;
|
||||
char* issuer_state;
|
||||
char* issuer_distinguishedname;
|
||||
char* issuer_serialnumber;
|
||||
char* issuer_commonname;
|
||||
char* issuer_organisation;
|
||||
char* issuer_organisation_unit;
|
||||
char* issuer_email;
|
||||
char* notbefore;
|
||||
char* notafter;
|
||||
char* fingerprint;
|
||||
char* key_alg;
|
||||
char* signature_alg;
|
||||
char* pem;
|
||||
const gchar* fingerprint;
|
||||
gchar* serialnumber;
|
||||
gchar* subjectname;
|
||||
tls_cert_name_t subject;
|
||||
gchar* issuername;
|
||||
tls_cert_name_t issuer;
|
||||
gchar* notbefore;
|
||||
gchar* notafter;
|
||||
gchar* fingerprint_sha1;
|
||||
gchar* fingerprint_sha256;
|
||||
gchar* key_alg;
|
||||
gchar* signature_alg;
|
||||
gchar* pem;
|
||||
gchar* pubkey_fingerprint;
|
||||
} TLSCertificate;
|
||||
|
||||
void tlscerts_init(void);
|
||||
|
||||
TLSCertificate* tlscerts_new(const char* const fingerprint, int version, const char* const serialnumber, const char* const subjectname,
|
||||
const char* const issuername, const char* const notbefore, const char* const notafter,
|
||||
const char* const key_alg, const char* const signature_alg, const char* const pem);
|
||||
TLSCertificate* tlscerts_new(const char* fingerprint_sha1, int version, const char* serialnumber, const char* subjectname,
|
||||
const char* issuername, const char* notbefore, const char* notafter,
|
||||
const char* key_alg, const char* signature_alg, const char* pem,
|
||||
const char* fingerprint_sha256, const char* pubkey_fingerprint);
|
||||
|
||||
void tlscerts_set_current(const char* const fp);
|
||||
void tlscerts_set_current(const TLSCertificate* cert);
|
||||
|
||||
char* tlscerts_get_current(void);
|
||||
gboolean tlscerts_current_fingerprint_equals(const TLSCertificate* cert);
|
||||
|
||||
void tlscerts_clear_current(void);
|
||||
|
||||
gboolean tlscerts_exists(const char* const fingerprint);
|
||||
gboolean tlscerts_exists(const TLSCertificate* cert);
|
||||
|
||||
void tlscerts_add(const TLSCertificate* cert);
|
||||
|
||||
gboolean tlscerts_revoke(const char* const fingerprint);
|
||||
gboolean tlscerts_revoke(const char* fingerprint);
|
||||
|
||||
TLSCertificate* tlscerts_get_trusted(const char* const fingerprint);
|
||||
TLSCertificate* tlscerts_get_trusted(const char* fingerprint);
|
||||
|
||||
void tlscerts_free(TLSCertificate* cert);
|
||||
|
||||
GList* tlscerts_list(void);
|
||||
|
||||
char* tlscerts_complete(const char* const prefix, gboolean previous, void* context);
|
||||
char* tlscerts_complete(const char* prefix, gboolean previous, void* context);
|
||||
|
||||
void tlscerts_reset_ac(void);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user