revert: restore pre-upstream-merge baseline (tree of 3b673150b)
All checks were successful
CI Code / Check spelling (pull_request) Successful in 18s
CI Code / Check coding style (pull_request) Successful in 30s
CI Code / Linux (ubuntu) (pull_request) Successful in 4m51s
CI Code / Linux (debian) (pull_request) Successful in 6m59s
CI Code / Linux (arch) (pull_request) Successful in 10m12s
CI Code / Code Coverage (pull_request) Successful in 6m44s
All checks were successful
CI Code / Check spelling (pull_request) Successful in 18s
CI Code / Check coding style (pull_request) Successful in 30s
CI Code / Linux (ubuntu) (pull_request) Successful in 4m51s
CI Code / Linux (debian) (pull_request) Successful in 6m59s
CI Code / Linux (arch) (pull_request) Successful in 10m12s
CI Code / Code Coverage (pull_request) Successful in 6m44s
Roll the tree back to the pre-merge tip3b673150b, undoing the upstream sync merge72f4f186d(303 files) and the 13 post-merge commits layered on top of it. Purpose: restore the last pre-sync baseline so the reported OMEMO/OTR encryption regressions can be reproduced against a known-good state and the upstream sync ruled in or out as the cause. Nothing is dropped from history; the merge and every post-merge commit remain reachable and can be cherry-picked back selectively. Baseline:3b673150bchore(chatlog): disable background message file logging (stage 1) Undoes merge:72f4f186dmerge: sync upstream profanity-im/profanity
This commit is contained in:
286
src/common.c
286
src/common.c
@@ -3,9 +3,35 @@
|
||||
* vim: expandtab:ts=4:sts=4:sw=4
|
||||
*
|
||||
* Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
|
||||
* Copyright (C) 2019 - 2026 Michael Vetter <jubalh@iodoru.org>
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -38,7 +64,6 @@
|
||||
#include "log.h"
|
||||
#include "common.h"
|
||||
#include "config/files.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
#ifdef HAVE_GIT_VERSION
|
||||
#include "gitversion.h"
|
||||
@@ -136,27 +161,20 @@ auto_close_FILE(FILE** fd)
|
||||
log_error("%s", g_strerror(errno));
|
||||
}
|
||||
|
||||
void
|
||||
auto_free_gerror(GError** err)
|
||||
{
|
||||
if (err == NULL)
|
||||
return;
|
||||
|
||||
PROF_GERROR_FREE(*err);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_load_keyfile(prof_keyfile_t* keyfile)
|
||||
{
|
||||
auto_gerror GError* error = NULL;
|
||||
GError* error = NULL;
|
||||
keyfile->keyfile = g_key_file_new();
|
||||
|
||||
if (g_key_file_load_from_file(keyfile->keyfile, keyfile->filename, G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error)) {
|
||||
return TRUE;
|
||||
} else if (error && error->code != G_FILE_ERROR_NOENT) {
|
||||
} else if (error->code != G_FILE_ERROR_NOENT) {
|
||||
log_warning("[Keyfile] error loading %s: %s", keyfile->filename, error->message);
|
||||
g_error_free(error);
|
||||
} else {
|
||||
log_warning("[Keyfile] no such file: %s", keyfile->filename);
|
||||
g_error_free(error);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -194,9 +212,10 @@ load_custom_keyfile(prof_keyfile_t* keyfile, gchar* filename)
|
||||
gboolean
|
||||
save_keyfile(prof_keyfile_t* keyfile)
|
||||
{
|
||||
auto_gerror GError* error = NULL;
|
||||
GError* error = NULL;
|
||||
if (!g_key_file_save_to_file(keyfile->keyfile, keyfile->filename, &error)) {
|
||||
log_error("[Keyfile]: saving file %s failed! %s", STR_MAYBE_NULL(keyfile->filename), PROF_GERROR_MESSAGE(error));
|
||||
log_error("[Keyfile]: saving file %s failed! %s", keyfile->filename, error->message);
|
||||
g_error_free(error);
|
||||
return FALSE;
|
||||
}
|
||||
g_chmod(keyfile->filename, S_IRUSR | S_IWUSR);
|
||||
@@ -235,8 +254,11 @@ copy_file(const char* const sourcepath, const char* const targetpath, const gboo
|
||||
{
|
||||
GFile* source = g_file_new_for_path(sourcepath);
|
||||
GFile* dest = g_file_new_for_path(targetpath);
|
||||
GError* error = NULL;
|
||||
GFileCopyFlags flags = overwrite_existing ? G_FILE_COPY_OVERWRITE : G_FILE_COPY_NONE;
|
||||
gboolean success = g_file_copy(source, dest, flags, NULL, NULL, NULL, NULL);
|
||||
gboolean success = g_file_copy(source, dest, flags, NULL, NULL, NULL, &error);
|
||||
if (error != NULL)
|
||||
g_error_free(error);
|
||||
g_object_unref(source);
|
||||
g_object_unref(dest);
|
||||
return success;
|
||||
@@ -294,7 +316,7 @@ str_replace(const char* string, const char* substr,
|
||||
wr = newstr;
|
||||
|
||||
while ((tok = strstr(head, substr))) {
|
||||
size_t l = g_diff_to_gsize(tok, head);
|
||||
size_t l = tok - head;
|
||||
memcpy(wr, head, l);
|
||||
wr += l;
|
||||
memcpy(wr, replacement, len_replacement);
|
||||
@@ -309,103 +331,33 @@ str_replace(const char* string, const char* substr,
|
||||
return newstr;
|
||||
}
|
||||
|
||||
gsize
|
||||
g_diff_to_gsize(const void* end, const void* start)
|
||||
{
|
||||
if (end < start) {
|
||||
log_error("g_diff_to_gsize: end < start (%p < %p)", end, start);
|
||||
return 0;
|
||||
}
|
||||
return (gsize)((const char*)end - (const char*)start);
|
||||
}
|
||||
|
||||
gboolean
|
||||
strtoi_range(const char* str, int* saveptr, int min, int max, gchar** err_msg)
|
||||
{
|
||||
char* ptr;
|
||||
long lval;
|
||||
int val;
|
||||
if (str == NULL) {
|
||||
if (err_msg)
|
||||
*err_msg = g_strdup_printf("'str' input pointer can not be NULL");
|
||||
return FALSE;
|
||||
}
|
||||
errno = 0;
|
||||
lval = strtol(str, &ptr, 0);
|
||||
val = (int)strtol(str, &ptr, 0);
|
||||
if (errno != 0 || *str == '\0' || *ptr != '\0') {
|
||||
if (err_msg)
|
||||
*err_msg = g_strdup_printf("Could not convert \"%s\" to a number.", str);
|
||||
return FALSE;
|
||||
} else if (lval < (long)min || lval > (long)max) {
|
||||
} else if (val < min || val > max) {
|
||||
if (err_msg)
|
||||
*err_msg = g_strdup_printf("Value %s out of range. Must be in %d..%d.", str, min, max);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*saveptr = (int)lval;
|
||||
*saveptr = val;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
string_matches_one_of(const char* what, const char* is, gboolean is_can_be_null, const char* first, ...)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
va_list ap;
|
||||
const char* cur = first;
|
||||
if (!is)
|
||||
return is_can_be_null;
|
||||
|
||||
va_start(ap, first);
|
||||
while (cur != NULL) {
|
||||
if (g_strcmp0(is, cur) == 0) {
|
||||
ret = TRUE;
|
||||
break;
|
||||
}
|
||||
cur = va_arg(ap, const char*);
|
||||
}
|
||||
va_end(ap);
|
||||
if (!ret && what) {
|
||||
cons_show("Invalid %s: '%s'", what, is);
|
||||
char errmsg[256] = { 0 };
|
||||
size_t sz = 0;
|
||||
int s = snprintf(errmsg, sizeof(errmsg) - sz, "%s must be one of:", what);
|
||||
if (s < 0 || (size_t)s + sz >= sizeof(errmsg))
|
||||
return ret;
|
||||
sz += (size_t)s;
|
||||
|
||||
cur = first;
|
||||
va_start(ap, first);
|
||||
while (cur != NULL) {
|
||||
const char* next = va_arg(ap, const char*);
|
||||
if (next) {
|
||||
s = snprintf(errmsg + sz, sizeof(errmsg) - sz, " '%s',", cur);
|
||||
} else {
|
||||
/* remove last ',' */
|
||||
sz--;
|
||||
errmsg[sz] = '\0';
|
||||
s = snprintf(errmsg + sz, sizeof(errmsg) - sz, " or '%s'.", cur);
|
||||
}
|
||||
if (s < 0 || (size_t)s + sz >= sizeof(errmsg)) {
|
||||
log_debug("Error message too long or some other error occurred (%d).", s);
|
||||
s = -1;
|
||||
break;
|
||||
}
|
||||
sz += (size_t)s;
|
||||
cur = next;
|
||||
}
|
||||
va_end(ap);
|
||||
if (s > 0)
|
||||
cons_show("%s", errmsg);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
valid_tls_policy_option(const char* is)
|
||||
{
|
||||
return string_matches_one_of("TLS policy", is, TRUE, "force", "allow", "trust", "disable", "legacy", "direct", NULL);
|
||||
}
|
||||
|
||||
int
|
||||
utf8_display_len(const char* const str)
|
||||
{
|
||||
@@ -428,33 +380,6 @@ utf8_display_len(const char* const str)
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes illegal XML 1.0 characters from a string.
|
||||
*
|
||||
* This function creates a new string that excludes characters in the range
|
||||
* U+0000 to U+001F, except for U+0009 (TAB), U+000A (LF), and U+000D (CR).
|
||||
*/
|
||||
gchar*
|
||||
str_xml_sanitize(const char* const str)
|
||||
{
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GString* sanitized = g_string_new_len(NULL, (gssize)strlen(str));
|
||||
const char* curr = str;
|
||||
|
||||
while (*curr != '\0') {
|
||||
gunichar c = g_utf8_get_char(curr);
|
||||
if ((c >= 0x20) || (c == 0x09) || (c == 0x0A) || (c == 0x0D)) {
|
||||
g_string_append_unichar(sanitized, c);
|
||||
}
|
||||
curr = g_utf8_next_char(curr);
|
||||
}
|
||||
|
||||
return g_string_free(sanitized, FALSE);
|
||||
}
|
||||
|
||||
char*
|
||||
release_get_latest(void)
|
||||
{
|
||||
@@ -482,15 +407,11 @@ release_get_latest(void)
|
||||
}
|
||||
|
||||
gboolean
|
||||
release_is_new(const char* const curr_version, const char* const found_version)
|
||||
release_is_new(char* found_version)
|
||||
{
|
||||
if (!curr_version || !found_version) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int curr_maj, curr_min, curr_patch, found_maj, found_min, found_patch;
|
||||
|
||||
int parse_curr = sscanf(curr_version, "%d.%d.%d", &curr_maj, &curr_min,
|
||||
int parse_curr = sscanf(PACKAGE_VERSION, "%d.%d.%d", &curr_maj, &curr_min,
|
||||
&curr_patch);
|
||||
int parse_found = sscanf(found_version, "%d.%d.%d", &found_maj, &found_min,
|
||||
&found_patch);
|
||||
@@ -553,32 +474,23 @@ _get_file_or_linked(gchar* loc)
|
||||
char*
|
||||
strip_arg_quotes(const char* const input)
|
||||
{
|
||||
if (input == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
char* unquoted = strdup(input);
|
||||
|
||||
// Unescape and strip quotes
|
||||
GString* unescaped = g_string_new("");
|
||||
for (const char* p = input; *p; p++) {
|
||||
if (*p == '\\' && (*(p + 1) != '\0')) {
|
||||
p++;
|
||||
g_string_append_c(unescaped, *p);
|
||||
} else if (*p == '"') {
|
||||
// Only strip if it's the first char or preceded by a space
|
||||
if (p == input || *(p - 1) == ' ') {
|
||||
continue;
|
||||
}
|
||||
// Or if it's the last char
|
||||
if (*(p + 1) == '\0') {
|
||||
continue;
|
||||
}
|
||||
g_string_append_c(unescaped, *p);
|
||||
} else {
|
||||
g_string_append_c(unescaped, *p);
|
||||
// Remove starting quote if it exists
|
||||
if (strchr(unquoted, '"')) {
|
||||
if (strchr(unquoted, ' ') + 1 == strchr(unquoted, '"')) {
|
||||
memmove(strchr(unquoted, '"'), strchr(unquoted, '"') + 1, strchr(unquoted, '\0') - strchr(unquoted, '"'));
|
||||
}
|
||||
}
|
||||
|
||||
return g_string_free(unescaped, FALSE);
|
||||
// Remove ending quote if it exists
|
||||
if (strchr(unquoted, '"')) {
|
||||
if (strchr(unquoted, '\0') - 1 == strchr(unquoted, '"')) {
|
||||
memmove(strchr(unquoted, '"'), strchr(unquoted, '"') + 1, strchr(unquoted, '\0') - strchr(unquoted, '"'));
|
||||
}
|
||||
}
|
||||
|
||||
return unquoted;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -602,48 +514,36 @@ is_notify_enabled(void)
|
||||
GSList*
|
||||
prof_occurrences(const char* const needle, const char* const haystack, int offset, gboolean whole_word, GSList** result)
|
||||
{
|
||||
if (needle == NULL || haystack == NULL || *needle == '\0') {
|
||||
if (needle == NULL || haystack == NULL) {
|
||||
return *result;
|
||||
}
|
||||
|
||||
size_t needle_len = strlen(needle);
|
||||
gchar* p = g_utf8_offset_to_pointer(haystack, offset);
|
||||
GSList* matches = NULL;
|
||||
|
||||
while (p) {
|
||||
if (g_str_has_prefix(p, needle)) {
|
||||
do {
|
||||
gchar* haystack_curr = g_utf8_offset_to_pointer(haystack, offset);
|
||||
if (g_str_has_prefix(haystack_curr, needle)) {
|
||||
if (whole_word) {
|
||||
gunichar before = 0;
|
||||
gchar* haystack_before_ch = g_utf8_find_prev_char(haystack, p);
|
||||
gchar* haystack_before_ch = g_utf8_find_prev_char(haystack, haystack_curr);
|
||||
if (haystack_before_ch) {
|
||||
before = g_utf8_get_char(haystack_before_ch);
|
||||
}
|
||||
|
||||
gunichar after = 0;
|
||||
gchar* haystack_after_ch = p + needle_len;
|
||||
if (*haystack_after_ch != '\0') {
|
||||
gchar* haystack_after_ch = haystack_curr + strlen(needle);
|
||||
if (haystack_after_ch[0] != '\0') {
|
||||
after = g_utf8_get_char(haystack_after_ch);
|
||||
}
|
||||
|
||||
if (!g_unichar_isalnum(before) && !g_unichar_isalnum(after)) {
|
||||
matches = g_slist_prepend(matches, GINT_TO_POINTER(offset));
|
||||
*result = g_slist_append(*result, GINT_TO_POINTER(offset));
|
||||
}
|
||||
} else {
|
||||
matches = g_slist_prepend(matches, GINT_TO_POINTER(offset));
|
||||
*result = g_slist_append(*result, GINT_TO_POINTER(offset));
|
||||
}
|
||||
}
|
||||
|
||||
if (*p == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
p = g_utf8_next_char(p);
|
||||
offset++;
|
||||
}
|
||||
|
||||
if (matches) {
|
||||
*result = g_slist_concat(*result, g_slist_reverse(matches));
|
||||
}
|
||||
} while (g_strcmp0(g_utf8_offset_to_pointer(haystack, offset), "\0") != 0);
|
||||
|
||||
return *result;
|
||||
}
|
||||
@@ -699,19 +599,19 @@ get_file_paths_recursive(const char* path, GSList** contents)
|
||||
}
|
||||
}
|
||||
|
||||
gchar*
|
||||
get_random_string(size_t length)
|
||||
char*
|
||||
get_random_string(int length)
|
||||
{
|
||||
GRand* prng;
|
||||
gchar* rand;
|
||||
gchar alphabet[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
char* rand;
|
||||
char alphabet[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
int endrange = sizeof(alphabet) - 1;
|
||||
|
||||
rand = g_malloc0(length + 1);
|
||||
rand = calloc(length + 1, sizeof(char));
|
||||
|
||||
prng = g_rand_new();
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
rand[i] = alphabet[g_rand_int_range(prng, 0, endrange)];
|
||||
}
|
||||
g_rand_free(prng);
|
||||
@@ -734,7 +634,7 @@ get_mentions(gboolean whole_word, gboolean case_sensitive, const char* const mes
|
||||
gboolean
|
||||
call_external(gchar** argv)
|
||||
{
|
||||
auto_gerror GError* spawn_error = NULL;
|
||||
GError* spawn_error;
|
||||
gboolean is_successful;
|
||||
|
||||
GSpawnFlags flags = G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL;
|
||||
@@ -747,7 +647,9 @@ call_external(gchar** argv)
|
||||
&spawn_error);
|
||||
if (!is_successful) {
|
||||
auto_gchar gchar* cmd = g_strjoinv(" ", argv);
|
||||
log_error("Spawning '%s' failed with error '%s'", cmd, PROF_GERROR_MESSAGE(spawn_error));
|
||||
log_error("Spawning '%s' failed with error '%s'", cmd, spawn_error ? spawn_error->message : "Unknown, spawn_error is NULL");
|
||||
|
||||
g_error_free(spawn_error);
|
||||
}
|
||||
|
||||
return is_successful;
|
||||
@@ -758,17 +660,17 @@ call_external(gchar** argv)
|
||||
*
|
||||
* This function constructs an argument vector (argv) based on the provided template string, replacing placeholders ("%u" and "%p") with the provided URL and filename, respectively.
|
||||
*
|
||||
* @param template_fmt The template string with placeholders.
|
||||
* @param url The URL to replace "%u" (or NULL to skip).
|
||||
* @param filename The filename to replace "%p" (or NULL to skip).
|
||||
* @return The constructed argument vector (argv) as a null-terminated array of strings.
|
||||
* @param template The template string with placeholders.
|
||||
* @param url The URL to replace "%u" (or NULL to skip).
|
||||
* @param filename The filename to replace "%p" (or NULL to skip).
|
||||
* @return The constructed argument vector (argv) as a null-terminated array of strings.
|
||||
*
|
||||
* @note Remember to free the returned argument vector using `auto_gcharv` or `g_strfreev()`.
|
||||
*/
|
||||
gchar**
|
||||
format_call_external_argv(const char* template_fmt, const char* url, const char* filename)
|
||||
format_call_external_argv(const char* template, const char* url, const char* filename)
|
||||
{
|
||||
gchar** argv = g_strsplit(template_fmt, " ", 0);
|
||||
gchar** argv = g_strsplit(template, " ", 0);
|
||||
|
||||
guint num_args = 0;
|
||||
while (argv[num_args]) {
|
||||
@@ -777,7 +679,7 @@ format_call_external_argv(const char* template_fmt, const char* url, const char*
|
||||
argv[num_args] = g_strdup(url);
|
||||
} else if (0 == g_strcmp0(argv[num_args], "%p") && filename != NULL) {
|
||||
g_free(argv[num_args]);
|
||||
argv[num_args] = g_strdup(filename);
|
||||
argv[num_args] = strdup(filename);
|
||||
}
|
||||
num_args++;
|
||||
}
|
||||
@@ -809,7 +711,7 @@ _unique_filename(const char* filename)
|
||||
return unique;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static bool
|
||||
_has_directory_suffix(const char* path)
|
||||
{
|
||||
return (g_str_has_suffix(path, ".")
|
||||
@@ -907,20 +809,6 @@ unique_filename_from_url(const char* url, const char* path)
|
||||
return unique_filename;
|
||||
}
|
||||
|
||||
/* This returns a timestamp formatted in ISO8601 format.
|
||||
* Either it returns the current time if `dt` is NULL, or
|
||||
* it returns the formatted time value passed in `dt`.
|
||||
*/
|
||||
gchar*
|
||||
prof_date_time_format_iso8601(GDateTime* dt)
|
||||
{
|
||||
GDateTime* dt_ = (dt == NULL) ? g_date_time_new_now_local() : dt;
|
||||
gchar* ret = g_date_time_format_iso8601(dt_);
|
||||
if (dt == NULL)
|
||||
g_date_time_unref(dt_);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* build profanity version string.
|
||||
* example: 0.13.1dev.master.69d8c1f9
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user