Compare commits

...

7 Commits

Author SHA1 Message Date
04dafdf36f Revert "build(pikaur): Fix failure due to duplicated flag and warnings"
Some checks failed
CI Code / Check coding style (pull_request) Successful in 1m41s
CI Code / Check spelling (pull_request) Successful in 17s
CI Code / Linux (arch) (pull_request) Failing after 5m41s
CI Code / Code Coverage (pull_request) Failing after 5m40s
CI Code / Linux (debian) (pull_request) Successful in 7m44s
CI Code / Linux (ubuntu) (pull_request) Successful in 7m46s
This reverts commit 0722dc9e36.
2026-04-21 10:17:44 +00:00
0feacbc9da ci: simulate Pikaur flag duplication in Arch Linux CI
All checks were successful
CI Code / Check spelling (pull_request) Successful in 17s
CI Code / Check coding style (pull_request) Successful in 30s
CI Code / Code Coverage (pull_request) Successful in 3m1s
CI Code / Linux (ubuntu) (pull_request) Successful in 4m31s
CI Code / Linux (debian) (pull_request) Successful in 7m36s
CI Code / Linux (arch) (pull_request) Successful in 9m52s
CI Code / Check spelling (push) Successful in 18s
CI Code / Check coding style (push) Successful in 32s
CI Code / Linux (debian) (push) Successful in 4m51s
CI Code / Linux (arch) (push) Successful in 5m35s
CI Code / Linux (ubuntu) (push) Successful in 6m36s
CI Code / Code Coverage (push) Successful in 7m21s
Inject system flags from /etc/makepkg.conf into the CI environment to
detect build collisions caused by Pikaur's configuration bug.

Pikaur's cascading logic causes flags from /etc/makepkg.conf to be
merged into the build environment. This creates collisions with flags
defined in the project's Makefile.am (e.g., duplicate -D_FORTIFY_SOURCE
definitions), which can cause builds to fail for users.

By exporting these flags in the CI environment, we ensure that any
code change that is sensitive to flag duplication will trigger a
failure in our Arch Linux CI matrix, preventing broken builds from
reaching users.

Implementation details:
- Detects Arch Linux via /etc/os-release.
- Uses a sed-based flattener to handle multi-line variables and
  trailing backslashes in makepkg.conf.
- Exports the flags to the shell environment so that 'configure'
  and 'make' inherit them naturally, maintaining parity with a
  real Pikaur session.
2026-04-21 10:17:44 +00:00
0722dc9e36 build(pikaur): Fix failure due to duplicated flag and warnings
All checks were successful
CI Code / Check spelling (pull_request) Successful in 20s
CI Code / Check coding style (pull_request) Successful in 35s
CI Code / Linux (ubuntu) (pull_request) Successful in 6m42s
CI Code / Linux (debian) (pull_request) Successful in 6m47s
CI Code / Code Coverage (pull_request) Successful in 7m3s
CI Code / Linux (arch) (pull_request) Successful in 9m33s
CI Code / Check spelling (push) Successful in 20s
CI Code / Check coding style (push) Successful in 39s
CI Code / Code Coverage (push) Successful in 2m53s
CI Code / Linux (debian) (push) Successful in 4m8s
CI Code / Linux (ubuntu) (push) Successful in 4m35s
CI Code / Linux (arch) (push) Successful in 10m28s
2026-04-13 19:52:24 +00:00
f84ed1bf6a perf(functests): speedup — profrc pre-baking, pty-close shutdown, parallel port pools
All checks were successful
CI Code / Check spelling (pull_request) Successful in 18s
CI Code / Check coding style (pull_request) Successful in 32s
CI Code / Code Coverage (pull_request) Successful in 2m46s
CI Code / Linux (debian) (pull_request) Successful in 4m30s
CI Code / Linux (ubuntu) (pull_request) Successful in 4m29s
CI Code / Linux (arch) (pull_request) Successful in 4m44s
CI Code / Check spelling (push) Successful in 18s
CI Code / Check coding style (push) Successful in 33s
CI Code / Code Coverage (push) Successful in 3m4s
CI Code / Linux (ubuntu) (push) Successful in 4m29s
CI Code / Linux (debian) (push) Successful in 4m33s
CI Code / Linux (arch) (push) Successful in 4m48s
Replace 16 interactive UI setup commands with pre-written profrc file
containing [ui] and [notifications] sections (~1800ms saved per test).

Replace sleep(1) + blocking waitpid with close(pty fd) → SIGHUP →
polling waitpid(WNOHANG) → SIGTERM/SIGKILL fallback chain (~4900ms
saved per test).

Remove post-stbbr_start() and post-stbbr_stop() sleeps — bind+listen
completes synchronously before stbbr_start() returns, and
pthread_join() in stbbr_stop() guarantees socket cleanup (~200ms saved).

Add PORTS_PER_GROUP=50 isolated port ranges per test group to enable
safe parallel execution of 4 groups without port conflicts.
2026-03-12 18:20:35 +03:00
9ec01fa8cc fix: CWE-134 format string audit and compiler hardening
All checks were successful
CI Code / Check spelling (push) Successful in 20s
CI Code / Check coding style (push) Successful in 36s
CI Code / Code Coverage (push) Successful in 5m38s
CI Code / Linux (ubuntu) (push) Successful in 7m1s
CI Code / Linux (debian) (push) Successful in 7m5s
CI Code / Linux (arch) (push) Successful in 7m19s
Security:
Fix CWE-134 in iq.c: user-controlled string passed as format argument
Add G_GNUC_PRINTF annotations to all variadic printf-like wrappers
in ui.h, log.h and http_common.h
Compiler flags (configure.ac):

Replace basic -Wformat/-Wformat-nonliteral with -Wformat=2
Add -Wextra, -Wnull-dereference, -Wpointer-arith,
-Wimplicit-function-declaration, -Wundef, -Wfloat-equal,
-Wredundant-decls, -Walloc-zero
Add -fstack-protector-strong, -fno-common, -D_FORTIFY_SOURCE=2
Add GCC-specific flags via AC_COMPILE_IFELSE: -Wlogical-op,
-Wduplicated-cond, -Wduplicated-branches, -Wstringop-overflow,
-Warray-bounds=2
Suppress noisy -Wextra sub-warnings: -Wno-unused-parameter,
-Wno-missing-field-initializers, -Wno-sign-compare,
-Wno-cast-function-type
Remove AM_CFLAGS/CFLAGS duplication
Bug fixes found by new warnings:

chatlog.c: non-MUCPM redact path passed resourcepart instead of NULL
rosterwin.c: merge duplicated if/else branches into single condition
omemo.c: redundant else-if in omemo_automatic_start; remove
unnecessary scope block and goto, use early return
console.c: pointer compared to integer 0 instead of NULL
stanza.c: increase pri_str/idle_str buffers from 10 to 12 bytes
(INT_MIN = -2147483648 needs 12 bytes including NUL)
vcard.c: NULL guard for filename before g_file_set_contents
api.c: broken log_warning() calls with extra format argument
Format mismatch fixes:

chatwin.c: Jid* → char* for %s
connection.c: %x → %lx for long flags
cmd_funcs.c: %d → %zu for size_t; cast gpointer to char* for %s
cmd_defs.c: %d → %u for g_list_length() return (guint)
iq.c: barejid → fulljid for from_jid
console.c, mucwin.c, privwin.c, account.c, omemo.c, presence.c:
gpointer → (char*) casts for %s
Const-correctness and cleanup:

database.c: const for type, query, sort variables
form.c/xmpp.h: const for form_set_value parameter
files.c: refactor to early return, eliminating NULL logfile path
muc.c/muc.h: remove meaningless top-level const on return type
common.c: const for URL string literal
Remove stale declarations: cons_show_desktop_prefs (ui.h),
connection_set_priority (connection.h),
omemo_devicelist_configure_and_request (omemo.h)
test_common.c: add currb NULL check to silence -Wnull-dereference
Tooling (check-cwe134.sh):

Reduce from 5 checks to 2 (checks 1-3 redundant with -Wformat=2)
Check 1: verify known wrappers have G_GNUC_PRINTF attribute
Check 2: auto-detect unannotated variadic printf-like functions
Match both const char* and const gchar* in variadic patterns

Author: jabber.developer2 <jabber.developer2@jabber.space>
2026-03-07 11:55:50 +01:00
1508f27e73 Merge branch 'ci/separate-build-step'
All checks were successful
CI Code / Check spelling (push) Successful in 21s
CI Code / Check coding style (push) Successful in 37s
CI Code / Code Coverage (push) Successful in 5m35s
CI Code / Linux (debian) (push) Successful in 6m56s
CI Code / Linux (ubuntu) (push) Successful in 7m2s
CI Code / Linux (arch) (push) Successful in 7m24s
2026-03-05 18:36:13 +01:00
d4254db814 CI: Separate build and test steps
All checks were successful
CI Code / Check coding style (pull_request) Successful in 32s
CI Code / Check spelling (pull_request) Successful in 24s
CI Code / Code Coverage (pull_request) Successful in 4m46s
CI Code / Linux (debian) (pull_request) Successful in 6m5s
CI Code / Linux (ubuntu) (pull_request) Successful in 6m11s
CI Code / Linux (arch) (pull_request) Successful in 6m25s
2026-03-04 23:04:51 +03:00
35 changed files with 401 additions and 260 deletions

View File

@@ -29,10 +29,10 @@ jobs:
name: Linux
steps:
- uses: actions/checkout@v4
- name: Build
run: docker build -f Dockerfile.${{ matrix.flavor }} -t profanity .
- name: Run tests
run: |
docker build -f Dockerfile.${{ matrix.flavor }} -t profanity .
docker run profanity ./ci-build.sh
run: docker run profanity ./ci-build.sh
code-style:
runs-on: ubuntu-latest
@@ -107,7 +107,7 @@ jobs:
name: Code Coverage
steps:
- uses: actions/checkout@v4
- name: Build and run coverage
run: |
docker build -f Dockerfile.arch -t profanity-cov .
docker run profanity-cov ./ci-build.sh --coverage-only
- name: Build
run: docker build -f Dockerfile.arch -t profanity-cov .
- name: Run coverage
run: docker run profanity-cov ./ci-build.sh --coverage-only

View File

@@ -1,8 +1,14 @@
#!/bin/bash
# check-cwe134.sh - Static analysis for CWE-134 format string vulnerabilities
# check-cwe134.sh - Verify __attribute__((format)) on printf-like wrappers
#
# This script detects potentially unsafe usage of format string functions
# where user-controlled data may be passed without "%s" wrapper.
# CWE-134 format string vulnerabilities are caught at compile time by
# -Wformat=2 (includes -Wformat-security + -Wformat-nonliteral), BUT only
# for functions annotated with __attribute__((format(printf, N, M))) or
# G_GNUC_PRINTF(N, M).
#
# This script ensures every variadic function whose last fixed parameter
# looks like a format string has the annotation. Without it, the compiler
# silently ignores format misuse.
#
# Usage: ./check-cwe134.sh [directory]
@@ -10,59 +16,103 @@ set -e
DIR="${1:-src}"
echo "=== CWE-134 Format String Vulnerability Check ==="
echo "=== CWE-134: format attribute audit ==="
echo "Scanning: $DIR"
echo ""
# Functions that accept format strings
FORMAT_FUNCS="cons_show|cons_debug|cons_show_error|log_info|log_error|log_warning|log_debug|win_println|win_print"
ERRORS=0
echo "Checking for unsafe format string usage..."
# --------------------------------------------------------------------- #
# Known printf-like wrappers that MUST have the attribute #
# --------------------------------------------------------------------- #
REQUIRED_ATTRIBUTED=(
"cons_show"
"cons_debug"
"cons_show_error"
"cons_show_padded"
"log_debug"
"log_info"
"log_warning"
"log_error"
"win_print"
"win_println"
"win_println_indent"
"win_println_va"
"win_append"
"win_appendln"
"win_append_highlight"
"win_appendln_highlight"
"win_command_exec_error"
)
echo "Check 1: Known wrappers must have G_GNUC_PRINTF / __attribute__((format))"
echo ""
# Pattern 1: function call with single variable argument (no format string)
# Example: cons_show(variable); - BAD
# Example: cons_show("%s", variable); - OK
# Matches: func(identifier) or func(identifier->member) or func(identifier[index])
RESULTS=$(grep -rn --include="*.c" -P "($FORMAT_FUNCS)\s*\(\s*[a-zA-Z_][a-zA-Z0-9_]*(\s*->\s*\w+|\s*\[\s*\w+\s*\])?\s*\)\s*;" "$DIR" 2>/dev/null || true)
for func in "${REQUIRED_ATTRIBUTED[@]}"; do
HAS_ATTR=$(grep -B1 --include="*.h" -rn "void ${func}\s*(" "$DIR" 2>/dev/null \
| grep -Ec "format\(printf|G_GNUC_PRINTF" || true)
if [ "$HAS_ATTR" -eq 0 ]; then
echo "$func — missing format attribute"
ERRORS=$((ERRORS + 1))
fi
done
# Filter out function definitions, declarations, and safe api_* wrappers
RESULTS=$(echo "$RESULTS" | grep -v "const char\|void \|^[^:]*:[0-9]*:[a-z_]*(\|api_cons_show\|api_log_" || true)
if [ "$ERRORS" -eq 0 ]; then
echo " ✅ All known wrappers annotated."
fi
if [ -n "$RESULTS" ]; then
echo "❌ POTENTIAL CWE-134 VULNERABILITIES FOUND:"
# --------------------------------------------------------------------- #
# Auto-detect new variadic functions that look like printf wrappers #
# but are NOT in the known list and NOT annotated. #
# Heuristic: declaration has (... const char* ..., ...) and no attribute #
# --------------------------------------------------------------------- #
echo ""
echo "Check 2: Detect unannotated printf-like variadic declarations in headers"
echo ""
KNOWN_RE=$(IFS="|"; echo "${REQUIRED_ATTRIBUTED[*]}")
# Find variadic declarations with a const char* / gchar* parameter followed by ...)
# that do NOT have a format attribute on the preceding line
NEW_ISSUES=$(grep -B1 -rn --include="*.h" \
'const g\?char\s*\*.*,\s*\.\.\.)' "$DIR" 2>/dev/null \
| awk '
/format\(printf|G_GNUC_PRINTF/ { skip=1; next }
/const g?char.*,.*\.\.\.\)/ {
if (skip) { skip=0; next }
print
}
{ skip=0 }
' \
| grep -E "void\s+\w+\s*\(" \
| grep -Ev "($KNOWN_RE)" \
|| true)
if [ -n "$NEW_ISSUES" ]; then
echo " ⚠️ Possibly unannotated new printf-like functions:"
echo ""
echo "$RESULTS"
echo "$NEW_ISSUES"
echo ""
ERRORS=$(echo "$RESULTS" | wc -l)
NEW_COUNT=$(echo "$NEW_ISSUES" | wc -l)
ERRORS=$((ERRORS + NEW_COUNT))
else
echo "✅ No obvious CWE-134 issues found."
fi
# Additional check: GString->str passed directly (not as %s argument)
echo ""
echo "Checking for GString->str passed to format functions..."
GSTRING_RESULTS=$(grep -rn --include="*.c" -P "($FORMAT_FUNCS)\s*\([^)]*->str\s*\)" "$DIR" 2>/dev/null | grep -v '"%s"' || true)
if [ -n "$GSTRING_RESULTS" ]; then
echo "⚠️ GString->str passed without \"%s\" (review manually):"
echo ""
echo "$GSTRING_RESULTS"
echo ""
echo " ✅ No unannotated variadic printf-like functions found."
fi
# --------------------------------------------------------------------- #
# Summary #
# --------------------------------------------------------------------- #
echo ""
echo "=== Summary ==="
echo "Critical issues: $ERRORS"
echo "Issues: $ERRORS"
echo ""
if [ "$ERRORS" -gt 0 ]; then
echo "Fix: add the attribute before the declaration in the .h file:"
echo " G_GNUC_PRINTF(N, M) // N = format arg, M = first vararg"
echo " void my_func(ProfWin* w, const char* fmt, ...);"
echo ""
echo "Fix by adding \"%s\" format specifier:"
echo " BAD: cons_show(variable);"
echo " GOOD: cons_show(\"%s\", variable);"
echo "The compiler flag -Wformat=2 will then catch all misuse automatically."
exit 1
fi

View File

@@ -86,7 +86,6 @@ extract_test_count() {
# and checks that the test framework reports the failure correctly
verify_test_failure_detection()
{
echo
echo "==> Verifying test failure detection..."
# Create a simple failing test
@@ -205,6 +204,13 @@ case "$ARCH" in
""
)
source /etc/profile.d/debuginfod.sh 2>/dev/null || true
if grep -q 'ID=arch' /etc/os-release 2>/dev/null && [ -f /etc/makepkg.conf ]; then
echo "--> [Parity Mode] Simulating Pikaur collision..."
set -a
source /etc/makepkg.conf
set +a
fi
;;
darwin*)
# 4 configurations for parallel CI

View File

@@ -385,9 +385,41 @@ AC_CHECK_LIB([util], [forkpty], [AM_CONDITIONAL([HAVE_FORKPTY], [true]) FORKPTY_
AC_SUBST([FORKPTY_LIB])
## Default parameters
AM_CFLAGS="$AM_CFLAGS -Wall -Wno-deprecated-declarations -std=gnu99 -ggdb3"
AM_CFLAGS="$AM_CFLAGS -Wall -Wextra -Wformat=2 -Wno-format-zero-length"
AM_CFLAGS="$AM_CFLAGS -Wno-deprecated-declarations -Wno-unused-parameter -Wno-missing-field-initializers -Wno-sign-compare -Wno-cast-function-type"
AM_CFLAGS="$AM_CFLAGS -Wnull-dereference -Wpointer-arith"
AM_CFLAGS="$AM_CFLAGS -Wimplicit-function-declaration"
AM_CFLAGS="$AM_CFLAGS -Wundef"
AM_CFLAGS="$AM_CFLAGS -Wfloat-equal -Wredundant-decls"
AM_CFLAGS="$AM_CFLAGS -fstack-protector-strong -fno-common"
AM_CFLAGS="$AM_CFLAGS -D_FORTIFY_SOURCE=2"
AM_CFLAGS="$AM_CFLAGS -std=gnu99 -ggdb3"
# GCC-specific warnings (not supported by clang) — test each one
saved_CFLAGS="$CFLAGS"
for _flag in -Wlogical-op -Wduplicated-cond -Wduplicated-branches \
-Wstringop-overflow -Warray-bounds=2 -Walloc-zero; do
AC_MSG_CHECKING([whether $CC supports $_flag])
CFLAGS="$saved_CFLAGS $_flag -Werror"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
[AC_MSG_RESULT([yes]); AM_CFLAGS="$AM_CFLAGS $_flag"],
[AC_MSG_RESULT([no])])
done
CFLAGS="$saved_CFLAGS"
AM_LDFLAGS="$AM_LDFLAGS -export-dynamic"
# Linker hardening (RELRO + immediate binding)
saved_LDFLAGS="$LDFLAGS"
for _flag in -Wl,-z,relro -Wl,-z,now; do
AC_MSG_CHECKING([whether linker supports $_flag])
LDFLAGS="$saved_LDFLAGS $_flag"
AC_LINK_IFELSE([AC_LANG_PROGRAM()],
[AC_MSG_RESULT([yes]); AM_LDFLAGS="$AM_LDFLAGS $_flag"],
[AC_MSG_RESULT([no])])
done
LDFLAGS="$saved_LDFLAGS"
AS_IF([test "x$enable_coverage" = xyes],
[AM_CFLAGS="$AM_CFLAGS --coverage -O0"
AM_LDFLAGS="$AM_LDFLAGS --coverage"
@@ -401,7 +433,7 @@ AS_IF([test "x$PLATFORM" = xosx],
AM_CFLAGS="$AM_CFLAGS $PTHREAD_CFLAGS $glib_CFLAGS $gio_CFLAGS $curl_CFLAGS ${SQLITE_CFLAGS}"
AM_CFLAGS="$AM_CFLAGS $libnotify_CFLAGS ${GTK_CFLAGS} $python_CFLAGS"
AM_CFLAGS="$AM_CFLAGS -DTHEMES_PATH=\"\\\"$THEMES_PATH\\\"\" -DICONS_PATH=\"\\\"$ICONS_PATH\\\"\" -DGLOBAL_PYTHON_PLUGINS_PATH=\"\\\"$GLOBAL_PYTHON_PLUGINS_PATH\\\"\" -DGLOBAL_C_PLUGINS_PATH=\"\\\"$GLOBAL_C_PLUGINS_PATH\\\"\""
AM_CFLAGS="$AM_CFLAGS $CFLAGS"
LIBS="$glib_LIBS $gio_LIBS $PTHREAD_LIBS $curl_LIBS $libnotify_LIBS $python_LIBS ${GTK_LIBS} ${SQLITE_LIBS} $LIBS"
AC_SUBST(AM_LDFLAGS)

View File

@@ -204,7 +204,7 @@ chat_log_omemo_msg_in(ProfMessage* message)
if (message->type == PROF_MSG_TYPE_MUCPM) {
_chat_log_chat(mybarejid, message->from_jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, message->from_jid->resourcepart);
} else {
_chat_log_chat(mybarejid, message->from_jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, message->from_jid->resourcepart);
_chat_log_chat(mybarejid, message->from_jid->barejid, "[redacted]", PROF_IN_LOG, message->timestamp, NULL);
}
}
}

View File

@@ -3067,7 +3067,7 @@ command_docgen(void)
fclose(toc_fragment);
fclose(main_fragment);
printf("\nProcessed %d commands.\n\n", g_list_length(cmds));
printf("\nProcessed %u commands.\n\n", g_list_length(cmds));
g_list_free(cmds);
}
@@ -3145,7 +3145,7 @@ command_mangen(void)
curr = g_list_next(curr);
}
printf("\nProcessed %d commands.\n\n", g_list_length(cmds));
printf("\nProcessed %u commands.\n\n", g_list_length(cmds));
g_list_free(cmds);
}

View File

@@ -2271,7 +2271,7 @@ cmd_group(ProfWin* window, const char* const command, gchar** args)
if (curr) {
cons_show("Groups:");
while (curr) {
cons_show(" %s", curr->data);
cons_show(" %s", (char*)curr->data);
curr = g_list_next(curr);
}
@@ -3109,7 +3109,7 @@ cmd_blocked(ProfWin* window, const char* const command, gchar** args)
if (curr) {
cons_show("Blocked users:");
while (curr) {
cons_show(" %s", curr->data);
cons_show(" %s", (char*)curr->data);
curr = g_list_next(curr);
}
} else {
@@ -5190,7 +5190,7 @@ cmd_charset(ProfWin* window, const char* const command, gchar** args)
if (codeset) {
cons_show(" CODESET: %s", codeset);
}
cons_show(" MB_CUR_MAX: %d", MB_CUR_MAX);
cons_show(" MB_CUR_MAX: %zu", MB_CUR_MAX);
cons_show(" MB_LEN_MAX: %d", MB_LEN_MAX);
return TRUE;
@@ -5624,7 +5624,7 @@ cmd_notify(ProfWin* window, const char* const command, gchar** args)
cons_show("No room notification triggers");
}
while (curr) {
cons_show(" %s", curr->data);
cons_show(" %s", (char*)curr->data);
curr = g_list_next(curr);
}
g_list_free_full(triggers, free);
@@ -6299,7 +6299,7 @@ cmd_reconnect(ProfWin* window, const char* const command, gchar** args)
} else if (strtoi_range(value, &intval, 0, INT_MAX, &err_msg)) {
prefs_set_reconnect(intval);
if (intval == 0) {
cons_show("Reconnect disabled.", intval);
cons_show("Reconnect disabled.");
} else {
cons_show("Reconnect interval set to %d seconds.", intval);
}
@@ -6858,7 +6858,7 @@ cmd_plugins_install(ProfWin* window, const char* const command, gchar** args)
cons_show("");
cons_show("Installed and loaded plugins (%u):", g_slist_length(curr));
while (curr) {
cons_show(" %s", curr->data);
cons_show(" %s", (char*)curr->data);
curr = g_slist_next(curr);
}
}
@@ -6867,7 +6867,7 @@ cmd_plugins_install(ProfWin* window, const char* const command, gchar** args)
cons_show("");
cons_show("Failed installs (%u):", g_slist_length(curr));
while (curr) {
cons_show(" %s", curr->data);
cons_show(" %s", (char*)curr->data);
curr = g_slist_next(curr);
}
}
@@ -6969,7 +6969,7 @@ cmd_plugins_load(ProfWin* window, const char* const command, gchar** args)
cons_show("Loaded plugins:");
GSList* curr = loaded;
while (curr) {
cons_show(" %s", curr->data);
cons_show(" %s", (char*)curr->data);
curr = g_slist_next(curr);
}
g_slist_free_full(loaded, g_free);
@@ -7101,7 +7101,7 @@ cmd_plugins(ProfWin* window, const char* const command, gchar** args)
GSList* curr = unloaded_plugins;
cons_show("The following plugins already installed and can be loaded:");
while (curr) {
cons_show(" %s", curr->data);
cons_show(" %s", (char*)curr->data);
curr = g_slist_next(curr);
}
g_slist_free_full(unloaded_plugins, g_free);
@@ -7111,7 +7111,7 @@ cmd_plugins(ProfWin* window, const char* const command, gchar** args)
GList* curr = plugins;
cons_show("Loaded plugins:");
while (curr) {
cons_show(" %s", curr->data);
cons_show(" %s", (char*)curr->data);
curr = g_list_next(curr);
}
g_list_free(plugins);

View File

@@ -383,7 +383,7 @@ utf8_display_len(const char* const str)
char*
release_get_latest(void)
{
char* url = "https://profanity-im.github.io/profanity_version.txt";
const char* url = "https://profanity-im.github.io/profanity_version.txt";
CURL* handle = curl_easy_init();
struct curl_data_t output;

View File

@@ -189,7 +189,7 @@ account_eval_password(ProfAccount* account)
int exit_status = pclose(stream);
if (exit_status > 0) {
log_error("Command for `eval_password` returned error status (%s).",
log_error("Command for `eval_password` returned error status (%d).",
exit_status);
return FALSE;
} else if (exit_status < 0) {

View File

@@ -114,30 +114,26 @@ gchar*
files_get_log_file(const char* const log_file)
{
auto_gchar gchar* xdg_data = _files_get_xdg_data_home();
GString* logfile;
if (log_file) {
auto_gchar gchar* log_path = g_path_get_dirname(log_file);
if (!create_dir(log_path)) {
log_error("Error while creating directory %s", log_path);
}
logfile = g_string_new(log_file);
} else {
logfile = g_string_new(xdg_data);
g_string_append(logfile, "/profanity/logs/profanity");
if (!prefs_get_boolean(PREF_LOG_SHARED)) {
g_string_append_printf(logfile, "%d", getpid());
}
g_string_append(logfile, ".log");
return g_strdup(log_file);
}
GString* logfile = g_string_new(xdg_data);
g_string_append(logfile, "/profanity/logs/profanity");
if (!prefs_get_boolean(PREF_LOG_SHARED)) {
g_string_append_printf(logfile, "%d", getpid());
}
g_string_append(logfile, ".log");
gchar* result = g_strdup(logfile->str);
g_string_free(logfile, TRUE);
return result;
}

View File

@@ -55,7 +55,7 @@
static sqlite3* g_chatlog_database;
static void _add_to_db(ProfMessage* message, char* type, const Jid* const from_jid, const Jid* const to_jid);
static void _add_to_db(ProfMessage* message, const char* type, const Jid* const from_jid, const Jid* const to_jid);
static char* _get_db_filename(ProfAccount* account);
static prof_msg_type_t _get_message_type_type(const char* const type);
static prof_enc_t _get_message_enc_type(const char* const encstr);
@@ -167,22 +167,22 @@ log_database_init(ProfAccount* account)
// replace_id is the ID from XEP-0308: Last Message Correction
// replaces_db_id is ID (primary key) of the original message that LMC message corrects/replaces
// replaced_by_db_id is ID (primary key) of the last correcting (LMC) message for the original message
char* query = "CREATE TABLE IF NOT EXISTS `ChatLogs` ("
"`id` INTEGER PRIMARY KEY AUTOINCREMENT, "
"`from_jid` TEXT NOT NULL, "
"`to_jid` TEXT NOT NULL, "
"`from_resource` TEXT, "
"`to_resource` TEXT, "
"`message` TEXT, "
"`timestamp` TEXT, "
"`type` TEXT, "
"`stanza_id` TEXT, "
"`archive_id` TEXT, "
"`encryption` TEXT, "
"`marked_read` INTEGER, "
"`replace_id` TEXT, "
"`replaces_db_id` INTEGER, "
"`replaced_by_db_id` INTEGER)";
const char* query = "CREATE TABLE IF NOT EXISTS `ChatLogs` ("
"`id` INTEGER PRIMARY KEY AUTOINCREMENT, "
"`from_jid` TEXT NOT NULL, "
"`to_jid` TEXT NOT NULL, "
"`from_resource` TEXT, "
"`to_resource` TEXT, "
"`message` TEXT, "
"`timestamp` TEXT, "
"`type` TEXT, "
"`stanza_id` TEXT, "
"`archive_id` TEXT, "
"`encryption` TEXT, "
"`marked_read` INTEGER, "
"`replace_id` TEXT, "
"`replaces_db_id` INTEGER, "
"`replaced_by_db_id` INTEGER)";
if (SQLITE_OK != sqlite3_exec(g_chatlog_database, query, NULL, 0, &err_msg)) {
goto out;
}
@@ -272,7 +272,7 @@ log_database_add_incoming(ProfMessage* message)
}
static void
_log_database_add_outgoing(char* type, const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc)
_log_database_add_outgoing(const char* type, const char* const id, const char* const barejid, const char* const message, const char* const replace_id, prof_enc_t enc)
{
ProfMessage* msg = message_init();
@@ -379,8 +379,8 @@ log_database_get_previous_chat(const gchar* const contact_barejid, const gchar*
}
// Flip order when querying older pages
gchar* sort1 = from_start ? "ASC" : "DESC";
gchar* sort2 = !flip ? "ASC" : "DESC";
const gchar* sort1 = from_start ? "ASC" : "DESC";
const gchar* sort2 = !flip ? "ASC" : "DESC";
GDateTime* now = g_date_time_new_now_local();
auto_gchar gchar* end_date_fmt = end_time ? g_strdup(end_time) : g_date_time_format_iso8601(now);
auto_sqlite gchar* query = sqlite3_mprintf("SELECT * FROM ("
@@ -499,7 +499,7 @@ _get_message_enc_type(const char* const encstr)
}
static void
_add_to_db(ProfMessage* message, char* type, const Jid* const from_jid, const Jid* const to_jid)
_add_to_db(ProfMessage* message, const char* type, const Jid* const from_jid, const Jid* const to_jid)
{
auto_gchar gchar* pref_dblog = prefs_get_string(PREF_DBLOG);
sqlite_int64 original_message_id = -1;

View File

@@ -54,9 +54,13 @@ void log_init(log_level_t filter, const char* const log_file);
log_level_t log_get_filter(void);
void log_close(void);
const gchar* get_log_file_location(void);
G_GNUC_PRINTF(1, 2)
void log_debug(const char* const msg, ...);
G_GNUC_PRINTF(1, 2)
void log_info(const char* const msg, ...);
G_GNUC_PRINTF(1, 2)
void log_warning(const char* const msg, ...);
G_GNUC_PRINTF(1, 2)
void log_error(const char* const msg, ...);
void log_msg(log_level_t level, const char* const area, const char* const msg);
int log_level_from_string(char* log_level, log_level_t* level);

View File

@@ -537,7 +537,7 @@ omemo_set_device_list(const char* const from, GList* device_list)
g_hash_table_iter_init(&iter, known_identities);
while (g_hash_table_iter_next(&iter, &key, &value)) {
if (device_id->data == value) {
cons_show("OMEMO: Adding firstusage trust for %s device %d - Fingerprint %s", jid->barejid, device_id->data, omemo_format_fingerprint(key));
cons_show("OMEMO: Adding firstusage trust for %s device %d - Fingerprint %s", jid->barejid, GPOINTER_TO_INT(device_id->data), omemo_format_fingerprint(key));
omemo_trust(jid->barejid, omemo_format_fingerprint(key));
}
}
@@ -744,8 +744,8 @@ omemo_on_message_send(ProfWin* win, const char* const message, gboolean request_
GList* recipient_device_id = NULL;
recipient_device_id = g_hash_table_lookup(omemo_ctx.device_list, recipients_iter->data);
if (!recipient_device_id) {
log_warning("[OMEMO][SEND] cannot find device ids for %s", recipients_iter->data);
win_println(win, THEME_ERROR, "!", "Can't find a OMEMO device id for %s.\n", recipients_iter->data);
log_warning("[OMEMO][SEND] cannot find device ids for %s", (char*)recipients_iter->data);
win_println(win, THEME_ERROR, "!", "Can't find a OMEMO device id for %s.\n", (char*)recipients_iter->data);
continue;
}
@@ -769,7 +769,7 @@ omemo_on_message_send(ProfWin* win, const char* const message, gboolean request_
}
}
log_debug("[OMEMO][SEND] recipients with device id %d for %s", GPOINTER_TO_INT(device_ids_iter->data), recipients_iter->data);
log_debug("[OMEMO][SEND] recipients with device id %d for %s", GPOINTER_TO_INT(device_ids_iter->data), (char*)recipients_iter->data);
res = session_cipher_create(&cipher, omemo_ctx.store, &address, omemo_ctx.signal);
if (res != SG_SUCCESS) {
log_error("[OMEMO][SEND] cannot create cipher for %s device id %d - code: %d", address.name, address.device_id, res);
@@ -1304,7 +1304,7 @@ _handle_own_device_list(const char* const jid, GList* device_list)
{
// We didn't find the own device id -> publish
if (!g_list_find(device_list, GINT_TO_POINTER(omemo_ctx.device_id))) {
cons_show("Could not find own OMEMO device ID. Going to publish own device ID: %d", GINT_TO_POINTER(omemo_ctx.device_id));
cons_show("Could not find own OMEMO device ID. Going to publish own device ID: %d", omemo_ctx.device_id);
log_debug("[OMEMO] No device ID for our device. Publishing device list");
device_list = g_list_copy(device_list);
device_list = g_list_append(device_list, GINT_TO_POINTER(omemo_ctx.device_id));
@@ -1406,8 +1406,6 @@ omemo_automatic_start(const char* const recipient)
case PROF_OMEMOPOLICY_AUTOMATIC:
if (g_list_find_custom(account->omemo_enabled, recipient, (GCompareFunc)g_strcmp0)) {
result = TRUE;
} else if (g_list_find_custom(account->omemo_disabled, recipient, (GCompareFunc)g_strcmp0)) {
result = FALSE;
} else {
result = FALSE;
}

View File

@@ -532,7 +532,7 @@ api_encryption_reset(const char* const barejid)
ProfChatWin* chatwin = wins_get_chat(barejid);
if (chatwin == NULL) {
log_warning("%s", "api_encryption_reset failed, could not find chat window for %s", barejid);
log_warning("api_encryption_reset failed, could not find chat window for %s", barejid);
return;
}
@@ -566,7 +566,7 @@ api_chat_set_titlebar_enctext(const char* const barejid, const char* const encte
ProfChatWin* chatwin = wins_get_chat(barejid);
if (chatwin == NULL) {
log_warning("%s", "api_chat_set_titlebar_enctext failed, could not find chat window for %s", barejid);
log_warning("api_chat_set_titlebar_enctext failed, could not find chat window for %s", barejid);
return 0;
}
@@ -585,7 +585,7 @@ api_chat_unset_titlebar_enctext(const char* const barejid)
ProfChatWin* chatwin = wins_get_chat(barejid);
if (chatwin == NULL) {
log_warning("%s", "api_chat_unset_titlebar_enctext failed, could not find chat window for %s", barejid);
log_warning("api_chat_unset_titlebar_enctext failed, could not find chat window for %s", barejid);
return 0;
}
@@ -614,7 +614,7 @@ api_chat_set_incoming_char(const char* const barejid, const char* const ch)
ProfChatWin* chatwin = wins_get_chat(barejid);
if (chatwin == NULL) {
log_warning("%s", "api_chat_set_incoming_char failed, could not find chat window for %s", barejid);
log_warning("api_chat_set_incoming_char failed, could not find chat window for %s", barejid);
return 0;
}
@@ -633,7 +633,7 @@ api_chat_unset_incoming_char(const char* const barejid)
ProfChatWin* chatwin = wins_get_chat(barejid);
if (chatwin == NULL) {
log_warning("%s", "api_chat_unset_incoming_char failed, could not find chat window for %s", barejid);
log_warning("api_chat_unset_incoming_char failed, could not find chat window for %s", barejid);
return 0;
}
@@ -662,7 +662,7 @@ api_chat_set_outgoing_char(const char* const barejid, const char* const ch)
ProfChatWin* chatwin = wins_get_chat(barejid);
if (chatwin == NULL) {
log_warning("%s", "api_chat_set_outgoing_char failed, could not find chat window for %s", barejid);
log_warning("api_chat_set_outgoing_char failed, could not find chat window for %s", barejid);
return 0;
}
@@ -681,7 +681,7 @@ api_chat_unset_outgoing_char(const char* const barejid)
ProfChatWin* chatwin = wins_get_chat(barejid);
if (chatwin == NULL) {
log_warning("%s", "api_chat_unset_outgoing_char failed, could not find chat window for %s", barejid);
log_warning("api_chat_unset_outgoing_char failed, could not find chat window for %s", barejid);
return 0;
}
@@ -705,7 +705,7 @@ api_room_set_titlebar_enctext(const char* const roomjid, const char* const encte
ProfMucWin* mucwin = wins_get_muc(roomjid);
if (mucwin == NULL) {
log_warning("%s", "api_room_set_titlebar_enctext failed, could not find room window for %s", roomjid);
log_warning("api_room_set_titlebar_enctext failed, could not find room window for %s", roomjid);
return 0;
}
@@ -724,7 +724,7 @@ api_room_unset_titlebar_enctext(const char* const roomjid)
ProfMucWin* mucwin = wins_get_muc(roomjid);
if (mucwin == NULL) {
log_warning("%s", "api_room_unset_titlebar_enctext failed, could not find room window for %s", roomjid);
log_warning("api_room_unset_titlebar_enctext failed, could not find room window for %s", roomjid);
return 0;
}
@@ -753,7 +753,7 @@ api_room_set_message_char(const char* const roomjid, const char* const ch)
ProfMucWin* mucwin = wins_get_muc(roomjid);
if (mucwin == NULL) {
log_warning("%s", "api_room_set_message_char failed, could not find room window for %s", roomjid);
log_warning("api_room_set_message_char failed, could not find room window for %s", roomjid);
return 0;
}
@@ -772,7 +772,7 @@ api_room_unset_message_char(const char* const roomjid)
ProfMucWin* mucwin = wins_get_muc(roomjid);
if (mucwin == NULL) {
log_warning("%s", "api_room_unset_message_char failed, could not find room window for %s", roomjid);
log_warning("api_room_unset_message_char failed, could not find room window for %s", roomjid);
return 0;
}
@@ -796,7 +796,7 @@ api_chat_show(const char* const barejid, const char* message)
ProfChatWin* chatwin = wins_get_chat(barejid);
if (chatwin == NULL) {
log_warning("%s", "api_chat_show failed, could not find chat window for %s", barejid);
log_warning("api_chat_show failed, could not find chat window for %s", barejid);
return 0;
}
@@ -832,7 +832,7 @@ api_chat_show_themed(const char* const barejid, const char* const group, const c
ProfChatWin* chatwin = wins_get_chat(barejid);
if (chatwin == NULL) {
log_warning("%s", "api_chat_show_themed failed, could not find chat window for %s", barejid);
log_warning("api_chat_show_themed failed, could not find chat window for %s", barejid);
return 0;
}
@@ -859,7 +859,7 @@ api_room_show(const char* const roomjid, const char* message)
ProfMucWin* mucwin = wins_get_muc(roomjid);
if (mucwin == NULL) {
log_warning("%s", "api_room_show failed, could not find room window for %s", roomjid);
log_warning("api_room_show failed, could not find room window for %s", roomjid);
return 0;
}
@@ -895,7 +895,7 @@ api_room_show_themed(const char* const roomjid, const char* const group, const c
ProfMucWin* mucwin = wins_get_muc(roomjid);
if (mucwin == NULL) {
log_warning("%s", "api_room_show_themed failed, could not find room window for %s", roomjid);
log_warning("api_room_show_themed failed, could not find room window for %s", roomjid);
return 0;
}

View File

@@ -36,9 +36,12 @@
#ifndef TOOLS_HTTP_COMMON_H
#define TOOLS_HTTP_COMMON_H
#include <glib.h>
#include "ui/window.h"
G_GNUC_PRINTF(3, 4)
void http_print_transfer(ProfWin* window, char* id, const char* fmt, ...);
G_GNUC_PRINTF(3, 4)
void http_print_transfer_update(ProfWin* window, char* id, const char* fmt, ...);
#endif

View File

@@ -303,7 +303,7 @@ chatwin_incoming_msg(ProfChatWin* chatwin, ProfMessage* message, gboolean win_cr
assert(chatwin != NULL);
if (message->plain == NULL) {
log_error("chatwin_incoming_msg: Message with no plain field from: %s", message->from_jid);
log_error("chatwin_incoming_msg: Message with no plain field from: %s", message->from_jid->fulljid);
return;
}

View File

@@ -470,10 +470,10 @@ cons_show_wins(gboolean unread)
GSList* curr = window_strings;
while (curr) {
if (g_strstr_len(curr->data, strlen(curr->data), " unread") > 0) {
win_println(console, THEME_CMD_WINS_UNREAD, "-", "%s", curr->data);
if (g_strstr_len((char*)curr->data, strlen((char*)curr->data), " unread") != NULL) {
win_println(console, THEME_CMD_WINS_UNREAD, "-", "%s", (char*)curr->data);
} else {
win_println(console, THEME_DEFAULT, "-", "%s", curr->data);
win_println(console, THEME_DEFAULT, "-", "%s", (char*)curr->data);
}
curr = g_slist_next(curr);
}
@@ -491,10 +491,10 @@ cons_show_wins_attention()
GSList* curr = window_strings;
while (curr) {
if (g_strstr_len(curr->data, strlen(curr->data), " unread") > 0) {
win_println(console, THEME_CMD_WINS_UNREAD, "-", "%s", curr->data);
if (g_strstr_len((char*)curr->data, strlen((char*)curr->data), " unread") != NULL) {
win_println(console, THEME_CMD_WINS_UNREAD, "-", "%s", (char*)curr->data);
} else {
win_println(console, THEME_DEFAULT, "-", "%s", curr->data);
win_println(console, THEME_DEFAULT, "-", "%s", (char*)curr->data);
}
curr = g_slist_next(curr);
}
@@ -512,7 +512,7 @@ cons_show_room_invites(GList* invites)
} else {
cons_show("Chat room invites, use /join or /decline commands:");
while (invites) {
cons_show(" %s", invites->data);
cons_show(" %s", (char*)invites->data);
invites = g_list_next(invites);
}
}
@@ -591,7 +591,7 @@ cons_show_caps(const char* const fulljid, resource_presence_t presence)
win_println(console, THEME_DEFAULT, "-", "Features:");
GSList* feature = caps->features;
while (feature) {
win_println(console, THEME_DEFAULT, "-", " %s", feature->data);
win_println(console, THEME_DEFAULT, "-", " %s", (char*)feature->data);
feature = g_slist_next(feature);
}
}
@@ -611,10 +611,10 @@ cons_show_received_subs(void)
if (received == NULL) {
cons_show("No outstanding subscription requests.");
} else {
cons_show("Outstanding subscription requests from:",
cons_show("Outstanding subscription requests from (%d):",
g_list_length(received));
while (received) {
cons_show(" %s", received->data);
cons_show(" %s", (char*)received->data);
received = g_list_next(received);
}
g_list_free_full(received, g_free);
@@ -782,7 +782,7 @@ cons_show_disco_info(const char* jid, GSList* identities, GSList* features)
cons_show(" Features:");
}
while (features) {
cons_show(" %s", features->data);
cons_show(" %s", (char*)features->data);
features = g_slist_next(features);
}
@@ -2297,7 +2297,7 @@ cons_show_themes(GSList* themes)
} else {
cons_show("Available themes:");
while (themes) {
cons_show("%s", themes->data);
cons_show("%s", (char*)themes->data);
themes = g_slist_next(themes);
}
}
@@ -2315,7 +2315,7 @@ cons_show_scripts(GSList* scripts)
} else {
cons_show("Scripts:");
while (scripts) {
cons_show("%s", scripts->data);
cons_show("%s", (char*)scripts->data);
scripts = g_slist_next(scripts);
}
}
@@ -2333,7 +2333,7 @@ cons_show_script(const char* const script, GSList* commands)
} else {
cons_show("%s:", script);
while (commands) {
cons_show(" %s", commands->data);
cons_show(" %s", (char*)commands->data);
commands = g_slist_next(commands);
}
}

View File

@@ -218,7 +218,7 @@ mucwin_room_disco_info(ProfMucWin* mucwin, GSList* identities, GSList* features)
win_println(window, THEME_DEFAULT, "!", "Features:");
}
while (features) {
win_println(window, THEME_DEFAULT, "!", " %s", features->data);
win_println(window, THEME_DEFAULT, "!", " %s", (char*)features->data);
features = g_slist_next(features);
}
win_println(window, THEME_DEFAULT, "-", "");
@@ -534,7 +534,7 @@ mucwin_incoming_msg(ProfMucWin* mucwin, const ProfMessage* const message, GSList
int flags = 0;
if (message->plain == NULL) {
log_error("mucwin_incoming_msg: Message with no plain field from: %s", message->from_jid);
log_error("mucwin_incoming_msg: Message with no plain field from: %s", message->from_jid->fulljid);
return;
}

View File

@@ -52,7 +52,7 @@ privwin_incoming_msg(ProfPrivateWin* privatewin, ProfMessage* message)
assert(privatewin != NULL);
if (message->plain == NULL) {
log_error("privwin_incoming_msg: Message with no plain field from: %s", message->from_jid);
log_error("privwin_incoming_msg: Message with no plain field from: %s", message->from_jid->fulljid);
return;
}

View File

@@ -981,9 +981,7 @@ _rosterwin_unsubscribed_header(ProfLayoutSplit* layout, GList* wins)
auto_gchar gchar* countpref = prefs_get_string(PREF_ROSTER_COUNT);
if (g_strcmp0(countpref, "items") == 0) {
int itemcount = g_list_length(wins);
if (itemcount == 0 && prefs_get_boolean(PREF_ROSTER_COUNT_ZERO)) {
g_string_append_printf(header, " (%d)", itemcount);
} else {
if (itemcount != 0 || prefs_get_boolean(PREF_ROSTER_COUNT_ZERO)) {
g_string_append_printf(header, " (%d)", itemcount);
}
} else if (g_strcmp0(countpref, "unread") == 0) {
@@ -994,9 +992,7 @@ _rosterwin_unsubscribed_header(ProfLayoutSplit* layout, GList* wins)
unreadcount += chatwin->unread;
curr = g_list_next(curr);
}
if (unreadcount == 0 && prefs_get_boolean(PREF_ROSTER_COUNT_ZERO)) {
g_string_append_printf(header, " (%d)", unreadcount);
} else if (unreadcount > 0) {
if (unreadcount != 0 || prefs_get_boolean(PREF_ROSTER_COUNT_ZERO)) {
g_string_append_printf(header, " (%d)", unreadcount);
}
}
@@ -1026,9 +1022,7 @@ _rosterwin_contacts_header(ProfLayoutSplit* layout, const char* const title, GSL
auto_gchar gchar* countpref = prefs_get_string(PREF_ROSTER_COUNT);
if (g_strcmp0(countpref, "items") == 0) {
int itemcount = g_slist_length(contacts);
if (itemcount == 0 && prefs_get_boolean(PREF_ROSTER_COUNT_ZERO)) {
g_string_append_printf(header, " (%d)", itemcount);
} else {
if (itemcount != 0 || prefs_get_boolean(PREF_ROSTER_COUNT_ZERO)) {
g_string_append_printf(header, " (%d)", itemcount);
}
} else if (g_strcmp0(countpref, "unread") == 0) {
@@ -1043,9 +1037,7 @@ _rosterwin_contacts_header(ProfLayoutSplit* layout, const char* const title, GSL
}
curr = g_slist_next(curr);
}
if (unreadcount == 0 && prefs_get_boolean(PREF_ROSTER_COUNT_ZERO)) {
g_string_append_printf(header, " (%d)", unreadcount);
} else if (unreadcount > 0) {
if (unreadcount != 0 || prefs_get_boolean(PREF_ROSTER_COUNT_ZERO)) {
g_string_append_printf(header, " (%d)", unreadcount);
}
}
@@ -1136,9 +1128,7 @@ _rosterwin_private_header(ProfLayoutSplit* layout, GList* privs)
auto_gchar gchar* countpref = prefs_get_string(PREF_ROSTER_COUNT);
if (g_strcmp0(countpref, "items") == 0) {
int itemcount = g_list_length(privs);
if (itemcount == 0 && prefs_get_boolean(PREF_ROSTER_COUNT_ZERO)) {
g_string_append_printf(title_str, " (%d)", itemcount);
} else if (itemcount > 0) {
if (itemcount != 0 || prefs_get_boolean(PREF_ROSTER_COUNT_ZERO)) {
g_string_append_printf(title_str, " (%d)", itemcount);
}
} else if (g_strcmp0(countpref, "unread") == 0) {
@@ -1149,9 +1139,7 @@ _rosterwin_private_header(ProfLayoutSplit* layout, GList* privs)
unreadcount += privwin->unread;
curr = g_list_next(curr);
}
if (unreadcount == 0 && prefs_get_boolean(PREF_ROSTER_COUNT_ZERO)) {
g_string_append_printf(title_str, " (%d)", unreadcount);
} else if (unreadcount > 0) {
if (unreadcount != 0 || prefs_get_boolean(PREF_ROSTER_COUNT_ZERO)) {
g_string_append_printf(title_str, " (%d)", unreadcount);
}
}

View File

@@ -244,7 +244,9 @@ char* inp_readline(void);
void inp_nonblocking(gboolean reset);
// Console window
G_GNUC_PRINTF(1, 2)
void cons_show(const char* const msg, ...);
G_GNUC_PRINTF(2, 3)
void cons_show_padded(int pad, const char* const msg, ...);
void cons_about(void);
void cons_help(void);
@@ -263,7 +265,9 @@ void cons_show_pgp_prefs(void);
void cons_show_omemo_prefs(void);
void cons_show_ox_prefs(void);
void cons_show_account(ProfAccount* account);
G_GNUC_PRINTF(1, 2)
void cons_debug(const char* const msg, ...);
G_GNUC_PRINTF(1, 2)
void cons_show_error(const char* const cmd, ...);
void cons_show_contacts(GSList* list);
void cons_show_roster(GSList* list);
@@ -318,7 +322,6 @@ void cons_wrap_setting(void);
void cons_time_setting(void);
void cons_wintitle_setting(void);
void cons_notify_setting(void);
void cons_show_desktop_prefs(void);
void cons_states_setting(void);
void cons_outtype_setting(void);
void cons_intype_setting(void);
@@ -393,16 +396,24 @@ void win_show_subwin(ProfWin* window);
void win_refresh_without_subwin(ProfWin* window);
void win_refresh_with_subwin(ProfWin* window);
G_GNUC_PRINTF(4, 5)
void win_print(ProfWin* window, theme_item_t theme_item, const char* show_char, const char* const message, ...);
G_GNUC_PRINTF(4, 5)
void win_println(ProfWin* window, theme_item_t theme_item, const char* show_char, const char* const message, ...);
G_GNUC_PRINTF(3, 4)
void win_println_indent(ProfWin* window, int pad, const char* const message, ...);
G_GNUC_PRINTF(4, 0)
void win_println_va(ProfWin* window, theme_item_t theme_item, const char* show_char, const char* const message, va_list arg);
G_GNUC_PRINTF(3, 4)
void win_append(ProfWin* window, theme_item_t theme_item, const char* const message, ...);
G_GNUC_PRINTF(3, 4)
void win_appendln(ProfWin* window, theme_item_t theme_item, const char* const message, ...);
G_GNUC_PRINTF(3, 4)
void win_append_highlight(ProfWin* window, theme_item_t theme_item, const char* const message, ...);
G_GNUC_PRINTF(3, 4)
void win_appendln_highlight(ProfWin* window, theme_item_t theme_item, const char* const message, ...);
gchar* win_get_title(ProfWin* window);
@@ -416,6 +427,7 @@ void win_clear(ProfWin* window);
char* win_get_tab_identifier(ProfWin* window);
gchar* win_to_string(ProfWin* window);
void win_command_list_error(ProfWin* window, const char* const error);
G_GNUC_PRINTF(3, 4)
void win_command_exec_error(ProfWin* window, const char* const command, const char* const error, ...);
void win_handle_command_list(ProfWin* window, GSList* cmds);
void win_handle_command_exec_status(ProfWin* window, const char* const type, const char* const value);

View File

@@ -239,7 +239,7 @@ _conn_apply_settings(const char* const jid, const char* const passwd, const char
}
if (xmpp_conn_set_flags(conn.xmpp_conn, flags)) {
log_error("libstrophe doesn't accept this combination of flags: 0x%x", flags);
log_error("libstrophe doesn't accept this combination of flags: 0x%lx", flags);
conn.conn_status = JABBER_DISCONNECTED;
return FALSE;
}

View File

@@ -51,7 +51,6 @@ jabber_conn_status_t connection_register(const char* const altdomain, int port,
void connection_set_disconnected(void);
void connection_set_priority(const int priority);
void connection_set_priority(int priority);
void connection_set_disco_items(GSList* items);
xmpp_conn_t* connection_get_conn(void);

View File

@@ -458,7 +458,7 @@ form_get_field_type(DataForm* form, const char* const tag)
}
void
form_set_value(DataForm* form, const char* const tag, char* value)
form_set_value(DataForm* form, const char* const tag, const char* value)
{
char* var = g_hash_table_lookup(form->tag_to_var, tag);
if (var) {

View File

@@ -921,7 +921,7 @@ _caps_response_id_handler(xmpp_stanza_t* const stanza, void* const userdata)
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
auto_char char* error_message = stanza_get_error_message(stanza);
log_warning("Error received for capabilities response from %s: ", from, error_message);
log_warning("Error received for capabilities response from %s: %s", from, error_message);
return 0;
}
@@ -996,7 +996,7 @@ _caps_response_for_jid_id_handler(xmpp_stanza_t* const stanza, void* const userd
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
auto_char char* error_message = stanza_get_error_message(stanza);
log_warning("Error received for capabilities response from %s: ", from, error_message);
log_warning("Error received for capabilities response from %s: %s", from, error_message);
return 0;
}
@@ -1054,7 +1054,7 @@ _caps_response_legacy_id_handler(xmpp_stanza_t* const stanza, void* const userda
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
auto_char char* error_message = stanza_get_error_message(stanza);
log_warning("Error received for capabilities response from %s: ", from, error_message);
log_warning("Error received for capabilities response from %s: %s", from, error_message);
return 0;
}
@@ -1254,7 +1254,7 @@ _command_exec_response_handler(xmpp_stanza_t* const stanza, void* const userdata
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
auto_char char* error_message = stanza_get_error_message(stanza);
log_debug("Error executing command %s for %s: %s", command, from, error_message);
win_command_exec_error(win, command, error_message);
win_command_exec_error(win, command, "%s", error_message);
return 0;
}

View File

@@ -427,7 +427,7 @@ muc_rooms(void)
* Return current users nickname for the specified room
* The nickname is owned by the chat room and should not be modified or freed
*/
const char* const
const char*
muc_nick(const char* const room)
{
ChatRoom* chat_room = g_hash_table_lookup(rooms, room);

View File

@@ -93,7 +93,7 @@ GList* muc_rooms(void);
void muc_set_features(const char* const room, GSList* features);
const char* const muc_nick(const char* const room);
const char* muc_nick(const char* const room);
char* muc_password(const char* const room);
void muc_nick_change_start(const char* const room, const char* const new_nick);

View File

@@ -353,6 +353,7 @@ omemo_receive_message(xmpp_stanza_t* const stanza, gboolean* trusted)
{
char* plaintext = NULL;
const char* type = xmpp_stanza_get_type(stanza);
const char* from = xmpp_stanza_get_from(stanza);
GList* keys = NULL;
unsigned char* iv_raw = NULL;
unsigned char* payload_raw = NULL;
@@ -434,8 +435,6 @@ omemo_receive_message(xmpp_stanza_t* const stanza, gboolean* trusted)
keys = g_list_append(keys, key);
}
const char* from = xmpp_stanza_get_from(stanza);
plaintext = omemo_on_message_recv(from, sid, iv_raw, iv_len,
keys, payload_raw, payload_len,
g_strcmp0(type, STANZA_TYPE_GROUPCHAT) == 0, trusted);
@@ -471,7 +470,8 @@ _omemo_receive_devicelist(xmpp_stanza_t* const stanza, void* const userdata)
const char* code = xmpp_stanza_get_attribute(error, "code");
if (g_strcmp0(code, "404") == 0) {
goto out;
omemo_set_device_list(from, NULL);
return 1;
}
}
@@ -517,7 +517,8 @@ _omemo_receive_devicelist(xmpp_stanza_t* const stanza, void* const userdata)
log_warning("[OMEMO] User %s has a non 'current' device item list: %s.", from, xmpp_stanza_get_id(first));
item = first;
} else {
goto out;
omemo_set_device_list(from, device_list);
return 1;
}
xmpp_stanza_t* list = xmpp_stanza_get_child_by_ns(item, STANZA_NS_OMEMO);
@@ -539,7 +540,6 @@ _omemo_receive_devicelist(xmpp_stanza_t* const stanza, void* const userdata)
}
}
out:
omemo_set_device_list(from, device_list);
return 1;

View File

@@ -38,7 +38,6 @@
#include "xmpp/iq.h"
void omemo_devicelist_subscribe(void);
void omemo_devicelist_configure_and_request(void);
void omemo_devicelist_publish(GList* device_list);
void omemo_devicelist_request(const char* const jid);
void omemo_bundle_publish(gboolean first);

View File

@@ -501,7 +501,7 @@ _subscribe_handler(xmpp_stanza_t* const stanza)
{
const char* from = xmpp_stanza_get_from(stanza);
if (!from) {
log_warning("Subscribe presence handler received with no from attribute", from);
log_warning("Subscribe presence handler received with no from attribute");
}
log_debug("Subscribe presence handler fired for %s", from);

View File

@@ -1948,7 +1948,7 @@ stanza_attach_priority(xmpp_ctx_t* const ctx, xmpp_stanza_t* const presence, con
return;
}
char pri_str[10];
char pri_str[12];
snprintf(pri_str, sizeof(pri_str), "%d", pri);
xmpp_stanza_t* priority = xmpp_stanza_new(ctx);
@@ -2007,7 +2007,7 @@ stanza_attach_last_activity(xmpp_ctx_t* const ctx,
xmpp_stanza_t* query = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(query, STANZA_NAME_QUERY);
xmpp_stanza_set_ns(query, STANZA_NS_LASTACTIVITY);
char idle_str[10];
char idle_str[12];
snprintf(idle_str, sizeof(idle_str), "%d", idle);
xmpp_stanza_set_attribute(query, STANZA_ATTR_SECONDS, idle_str);
xmpp_stanza_add_child(presence, query);

View File

@@ -1300,7 +1300,7 @@ _vcard_photo_result(xmpp_stanza_t* const stanza, void* userdata)
return 1;
}
GString* filename;
GString* filename = NULL;
if (!data->filename) {
auto_gchar gchar* path = files_get_data_path(DIR_PHOTOS);
@@ -1340,6 +1340,11 @@ _vcard_photo_result(xmpp_stanza_t* const stanza, void* userdata)
GError* err = NULL;
if (!filename) {
cons_show_error("Unable to determine filename for photo");
return 1;
}
if (g_file_set_contents(filename->str, (gchar*)photo->data, photo->length, &err) == FALSE) {
cons_show_error("Unable to save photo: %s", err->message);
g_error_free(err);

View File

@@ -305,7 +305,7 @@ char* blocked_ac_find(const char* const search_str, gboolean previous, void* con
void blocked_ac_reset(void);
void form_destroy(DataForm* form);
void form_set_value(DataForm* form, const char* const tag, char* value);
void form_set_value(DataForm* form, const char* const tag, const char* value);
gboolean form_add_unique_value(DataForm* form, const char* const tag, char* value);
void form_add_value(DataForm* form, const char* const tag, char* value);
gboolean form_remove_value(DataForm* form, const char* const tag, char* value);

View File

@@ -12,6 +12,7 @@
#include <fcntl.h>
#include <sys/select.h>
#include <regex.h>
#include <signal.h>
#include <stabber.h>
@@ -20,11 +21,41 @@
/* Number of parallel test groups for CI builds */
#define TEST_GROUPS 4
/* Number of ports reserved per test group; allows skipping TIME_WAIT ports */
#define PORTS_PER_GROUP 50
/* Base port and fallback scan range for stabber */
#define BASE_PORT 5230
#define FALLBACK_PORT_RANGE (TEST_GROUPS * PORTS_PER_GROUP)
/* Shutdown polling: interval and maximum attempts before escalating signals */
#define MS_TO_US 1000
#define SHUTDOWN_POLL_MS 50
#define SHUTDOWN_POLL_MAX 100 /* 100 x 50ms = 5s */
#define SIGTERM_POLL_MAX 20 /* 20 x 50ms = 1s */
#define QUIT_GRACE_MS 100 /* grace for /quit to be read from pty */
#define INIT_WAIT_MS 50 /* wait for child process to initialize */
#define INPUT_DELAY_MS 10 /* let profanity process input */
#define OUTPUT_POLL_MS 50 /* polling interval for output checks */
#define READ_TIMEOUT_MS 100 /* select() timeout for pty reads */
/* Expect timeouts (seconds) */
#define EXPECT_TIMEOUT_DEFAULT 30
#define EXPECT_TIMEOUT_CONNECT 60
/* Terminal dimensions for forkpty */
#define PTY_ROWS 24
#define PTY_COLS 300
/* Preprocessor stringification (for setenv from numeric #define) */
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
char *config_orig;
char *data_orig;
int fd = 0;
int stub_port = 5230;
int stub_port = BASE_PORT;
pid_t child_pid = 0;
/*
@@ -44,7 +75,7 @@ static char output_buffer[OUTPUT_BUF_SIZE];
static size_t output_len = 0;
/* Timeout for expect operations in seconds */
static int expect_timeout = 30;
static int expect_timeout = EXPECT_TIMEOUT_DEFAULT;
gboolean
_create_dir(const char *name)
@@ -153,6 +184,12 @@ _cleanup_dirs(void)
}
}
static void
sleep_ms(int ms)
{
usleep(ms * MS_TO_US);
}
/*
* Read available data from fd into output_buffer with timeout.
* Returns number of bytes read, 0 on timeout, -1 on error.
@@ -166,8 +203,8 @@ _read_output(int timeout_ms)
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
tv.tv_sec = timeout_ms / 1000;
tv.tv_usec = (timeout_ms % 1000) * 1000;
tv.tv_sec = timeout_ms / MS_TO_US;
tv.tv_usec = (timeout_ms % MS_TO_US) * MS_TO_US;
int ret = select(fd + 1, &readfds, NULL, NULL, &tv);
if (ret <= 0) {
@@ -198,8 +235,8 @@ void
prof_start(void)
{
struct winsize ws;
ws.ws_row = 24;
ws.ws_col = 300; /* Match COLUMNS=300 from start_profanity.sh */
ws.ws_row = PTY_ROWS;
ws.ws_col = PTY_COLS;
ws.ws_xpixel = 0;
ws.ws_ypixel = 0;
@@ -216,7 +253,7 @@ prof_start(void)
if (child_pid == 0) {
/* Child process */
setenv("COLUMNS", "300", 1);
setenv("COLUMNS", STRINGIFY(PTY_COLS), 1);
setenv("TERM", "xterm", 1);
execl("./profanity", "./profanity", "-l", "DEBUG", NULL);
@@ -232,7 +269,7 @@ prof_start(void)
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
/* Brief wait for process to initialize */
usleep(50000); /* 50ms */
sleep_ms(INIT_WAIT_MS);
}
int
@@ -246,38 +283,41 @@ init_prof_test(void **state)
const char *build_env = getenv("PROF_BUILD_INDEX");
int build_idx = build_env ? atoi(build_env) : 0;
/* Calculate port base: each build uses a different range of TEST_GROUPS ports.
* Build 0 (local/default): 5230-5233, Full: 5230-5233, Minimal: 5234-5237, etc.
* Build 0 and Full share the same range because build 0 is for local runs or sequential run (no parallel builds),
* while Full/Minimal/NoEncrypt/Default are used in CI where they run in parallel. */
int port_base = 5230 + ((build_idx > 0 ? build_idx - 1 : 0) * TEST_GROUPS);
/* Calculate port base: each build uses a different range of
* TEST_GROUPS * PORTS_PER_GROUP ports.
* Build 0 (local/default): 5230-5429, Full: 5230-5429, Minimal: 5430-5629, etc.
* Build 0 and Full share the same range because build 0 is for local runs
* or sequential run (no parallel builds), while Full/Minimal/NoEncrypt/Default
* are used in CI where they run in parallel. */
int port_base = BASE_PORT + ((build_idx > 0 ? build_idx - 1 : 0) * TEST_GROUPS * PORTS_PER_GROUP);
/* Static resource allocation to avoid conflicts in parallel execution.
* Group 1-4: use static port assignment.
* Group 0 (all groups): use dynamic allocation as fallback. */
/* Each group gets a dedicated range of ports for parallel execution.
* Group 1: port_base..port_base+PORTS_PER_GROUP-1
* Group 2: port_base+PORTS_PER_GROUP..port_base+2*PORTS_PER_GROUP-1, etc.
* Ports in TIME_WAIT from previous tests are skipped automatically. */
gboolean started = FALSE;
if (group >= 1 && group <= TEST_GROUPS) {
/* Static allocation: each group gets a dedicated port */
stub_port = port_base + group - 1;
printf("[PROF_TEST] Build %d, Group %d: trying port %d\n", build_idx, group, stub_port);
if (stbbr_start(STBBR_LOGDEBUG, stub_port, 0) == 0) {
started = TRUE;
printf("[PROF_TEST] Started stabber on port %d\n", stub_port);
} else {
printf("[PROF_TEST] Failed to start stabber on port %d\n", stub_port);
}
}
/* Fallback to dynamic allocation if static failed or group=0 */
if (!started) {
printf("[PROF_TEST] Using dynamic port allocation\n");
for (int p = port_base; p < port_base + 20; ++p) {
int group_port_base = port_base + (group - 1) * PORTS_PER_GROUP;
for (int p = group_port_base; p < group_port_base + PORTS_PER_GROUP && !started; p++) {
if (stbbr_start(STBBR_LOGDEBUG, p, 0) == 0) {
stub_port = p;
started = TRUE;
}
}
if (!started) {
fprintf(stderr, "[PROF_TEST] Failed to start stabber on ports %d-%d\n",
group_port_base, group_port_base + PORTS_PER_GROUP - 1);
}
}
/* Fallback to dynamic allocation if static failed or group=0 */
if (!started) {
for (int p = port_base; p < port_base + FALLBACK_PORT_RANGE; ++p) {
if (stbbr_start(STBBR_LOGDEBUG, p, 0) == 0) {
stub_port = p;
started = TRUE;
printf("[PROF_TEST] Started stabber on port %d\n", stub_port);
break;
}
}
@@ -299,9 +339,6 @@ init_prof_test(void **state)
printf("[PROF_TEST] Group %d using directories: config=%s, data=%s\n",
group, xdg_config_home, xdg_data_home);
// Give stabber server thread time to start listening
usleep(100000); // 100ms
config_orig = getenv("XDG_CONFIG_HOME");
data_orig = getenv("XDG_DATA_HOME");
@@ -315,38 +352,37 @@ init_prof_test(void **state)
_create_chatlogs_dir();
_create_logs_dir();
/* Pre-write profrc with UI/notification defaults to ensure consistent,
* deterministic output across tests (no timestamps, no roster/occupants
* panels, low input-blocking delay for fast command processing). */
char profrc_path[512];
snprintf(profrc_path, sizeof(profrc_path),
"%s/profanity/profrc", xdg_config_home);
FILE* prc = fopen(profrc_path, "w");
if (prc) {
fprintf(prc,
"[ui]\n"
"inpblock=5\n"
"inpblock.dynamic=false\n"
"wrap=false\n"
"roster=false\n"
"occupants=false\n"
"time.console=off\n"
"time.chat=off\n"
"time.muc=off\n"
"time.config=off\n"
"time.private=off\n"
"time.xmlconsole=off\n"
"[notifications]\n"
"message=false\n"
"room=false\n");
fclose(prc);
}
prof_start();
int prof_started = prof_output_regex("CProof\\. Type /help for help information\\.");
assert_true(prof_started);
// set UI options to make expect assertions faster and more reliable
prof_input("/inpblock timeout 5");
assert_true(prof_output_regex("Input blocking set to 5 milliseconds"));
prof_input("/inpblock dynamic off");
assert_true(prof_output_regex("Dynamic input blocking disabled"));
prof_input("/notify chat off");
assert_true(prof_output_regex("Chat notifications disabled"));
prof_input("/notify room off");
assert_true(prof_output_regex("Room notifications disabled"));
prof_input("/wrap off");
assert_true(prof_output_regex("Word wrap disabled"));
prof_input("/roster hide");
assert_true(prof_output_regex("Roster disabled"));
prof_input("/occupants default hide");
assert_true(prof_output_regex("Occupant list disabled"));
prof_input("/time console off");
prof_input("/time console off");
assert_true(prof_output_regex("Console time display disabled\\."));
prof_input("/time chat off");
assert_true(prof_output_regex("Chat time display disabled\\."));
prof_input("/time muc off");
assert_true(prof_output_regex("MUC time display disabled\\."));
prof_input("/time config off");
assert_true(prof_output_regex("Config time display disabled\\."));
prof_input("/time private off");
assert_true(prof_output_regex("Private chat time display disabled\\."));
prof_input("/time xml off");
assert_true(prof_output_regex("XML Console time display disabled\\."));
return 0;
}
@@ -355,11 +391,31 @@ close_prof_test(void **state)
{
if (fd > 0 && child_pid > 0) {
prof_input("/quit");
// Give profanity time to process quit command
sleep(1);
waitpid(child_pid, NULL, 0);
/* Close pty master after brief grace — child gets SIGHUP which
* accelerates shutdown instead of waiting for XMPP disconnect
* timeout (~5s). */
sleep_ms(QUIT_GRACE_MS);
close(fd);
fd = 0;
int exited = 0;
for (int i = 0; i < SHUTDOWN_POLL_MAX; i++) {
if (waitpid(child_pid, NULL, WNOHANG) != 0) {
exited = 1;
break;
}
sleep_ms(SHUTDOWN_POLL_MS);
}
if (!exited) {
kill(child_pid, SIGTERM);
for (int i = 0; i < SIGTERM_POLL_MAX; i++) {
if (waitpid(child_pid, NULL, WNOHANG) != 0) { exited = 1; break; }
sleep_ms(SHUTDOWN_POLL_MS);
}
if (!exited) {
kill(child_pid, SIGKILL);
waitpid(child_pid, NULL, 0);
}
}
child_pid = 0;
}
@@ -371,13 +427,6 @@ close_prof_test(void **state)
}
stbbr_stop();
/*
* TODO: Replace with proper synchronization.
* stabber doesn't provide wait_stopped() API yet, so we use delay
* to ensure the port is released before the next test starts.
* See: https://git.jabber.space/devs/stabber/issues/3
*/
usleep(100000); // 100ms
return 0;
}
@@ -391,7 +440,7 @@ prof_input(const char *input)
g_string_free(inp_str, TRUE);
/* Small delay to let profanity process input */
usleep(10000);
sleep_ms(INPUT_DELAY_MS);
}
/*
@@ -405,7 +454,7 @@ prof_output_exact(const char *text)
while (time(NULL) - start < expect_timeout) {
/* Read any available output */
while (_read_output(100) > 0) {
while (_read_output(READ_TIMEOUT_MS) > 0) {
/* Keep reading while data available */
}
@@ -414,7 +463,7 @@ prof_output_exact(const char *text)
return 1;
}
usleep(50000); /* 50ms */
sleep_ms(OUTPUT_POLL_MS);
}
return 0;
@@ -439,7 +488,7 @@ prof_output_regex(const char *pattern)
while (time(NULL) - start < expect_timeout) {
/* Read any available output */
while (_read_output(100) > 0) {
while (_read_output(READ_TIMEOUT_MS) > 0) {
/* Keep reading while data available */
}
@@ -450,7 +499,7 @@ prof_output_regex(const char *pattern)
return 1;
}
usleep(50000); /* 50ms */
sleep_ms(OUTPUT_POLL_MS);
}
/* Timeout reached - log diagnostic info */
@@ -492,12 +541,12 @@ prof_connect_with_roster(const char *roster)
assert_true(prof_output_regex("password:"));
prof_input("password");
expect_timeout = 60;
expect_timeout = EXPECT_TIMEOUT_CONNECT;
assert_true(prof_output_regex("Connecting as stabber@localhost"));
assert_true(prof_output_regex("logged in successfully"));
assert_true(prof_output_regex(".+online.+ \\(priority 0\\)\\."));
expect_timeout = 60;
expect_timeout = EXPECT_TIMEOUT_CONNECT;
// Wait for presence stanza to be sent (content-based, not ID-based)
// Match the actual attribute order from stanza_attach_caps
assert_true(stbbr_received(
@@ -516,7 +565,7 @@ prof_timeout(int timeout)
void
prof_timeout_reset(void)
{
expect_timeout = 60;
expect_timeout = EXPECT_TIMEOUT_CONNECT;
}
void

View File

@@ -515,7 +515,7 @@ _lists_equal(GSList* a, GSList* b)
GSList* curra = a;
GSList* currb = b;
while (curra) {
while (curra && currb) {
int aval = GPOINTER_TO_INT(curra->data);
int bval = GPOINTER_TO_INT(currb->data);