Apply fixes, refactors and test additions requested by reviewer on PR #105.
Fixes:
- database: warn and notify user on duplicate archive_id instead of
silently debug-logging it (R05).
- database: add missing '[' in "[DB Migration]" log prefix (R06).
- xmpp/resource: NULL-out name/status after g_free to avoid double-free
via roster_list.c cleanup path (R09, R23).
- common: widen strtoi_range internal storage from int to long so that
values in (INT_MAX, LONG_MAX] are rejected as out-of-range instead of
being silently truncated on 64-bit platforms (R25).
Refactors:
- xmpp/message: extract _receive_omemo helper, removing three copies of
the OMEMO receive block in groupchat / MUC-PM / chat handlers (R04).
- omemo: flatten deeply nested device-list processing via guard-clause
continues (R11).
- tools/autocomplete: merge two nested ifs into a single && condition
(R13).
- ui/titlebar: extract _show_trust_indicator and inline _wprintw_withattr
wrapper, collapsing three near-identical trust-indicator blocks (R22).
- config/tlscerts: drop _checked_g_strdup wrapper; g_strdup is
NULL-safe per glib documentation (R19).
- ui/inputwin: use auto_gchar for spellcheck word instead of manual
g_free (R20).
- tools/editor: drop outdated "Deprecated synchronous" comment that
no longer matches the callback-based implementation (R28).
Tests:
- tests/command/cmd_ac: rename segfaults_when_empty ->
no_segfault_when_empty; expand cycling coverage to three files plus
backward SHIFT-TAB traversal (R16, R17).
- tests/common: add strtoi_range overflow/underflow and strtol-parsing
consistency tests (R25).
- tests/xmpp/jid: add test for '@' inside resourcepart per RFC 6122
section 2.4 (R26).
Misc:
- xmpp/omemo: change omemo_error_to_string return type from char* to
gchar* for glib consistency (R01).
- subprojects/libstrophe: point wrap-git at our fork at
git.jabber.space/devs/libstrophe-gh (R24).
- RELEASE_GUIDE: drop "Updating website" section referring to an
upstream site that is not ours (R18).
Commit 81f92f1fe introduced a selective update mechanism to
_accounts_save() to prevent overwrites when running multiple instances
by only modifying the specific account being saved.
Commit 5c484c fixed a problem with that commit regarding empty accounts.
It turns there was another bug introduced:
The new implementation only set the keys that existed in memory.
So removal of keys was not possible anymore.
Fixes: 81f92f1fed
Ref: 5c484c26ed
Signed-off-by: Michael Vetter <jubalh@iodoru.org>
Unescape any character following a backslash. This fixes autocompletion
for names with escaped spaces.
For example: `/msg Thor\ Odinson hello`
Signed-off-by: Michael Vetter <jubalh@iodoru.org>
Implement backslash based escaping in the command parser and autocompletion
logic to handle contact names containing double quotes.
This stops the parser from splitting nicknames into multiple tokens, which
previously caused "Invalid usage" errors.
The parser now sees \ as an escape character for quotes and spaces in
_parse_args_helper, count_tokens and get_start. Autocomplete results are
escaped when they contain spaces, and search prefixes are unescaped before
matching. strip_arg_quotes() has also been updated to handle unescaping.
Fixes: https://github.com/profanity-im/profanity/issues/1844
Signed-off-by: Michael Vetter <jubalh@iodoru.org>
Introduce optional spellcheck highlighting in the input window using
the Enchant-2 library.
```
/spellcheck on
/spellcheck lang en_US
```
New theme color `input.misspelled`.
Fixes: https://github.com/profanity-im/profanity/issues/183
Signed-off-by: Michael Vetter <jubalh@iodoru.org>
Enable adding oneself to the roster.
Self subscriptions are implicit according to XEP-0060 / XEP-0163.
So we adapt the /sub command to handle this gracefully by just printing
an informative message.
Profanitys logic didn't handle own presence/when adding to roster
correctly. This got fixed now.
Fixes: https://github.com/profanity-im/profanity/issues/2084
Signed-off-by: Michael Vetter <jubalh@iodoru.org>
Filter out control characters (U+0000 to U+001F) from outgoing
messages, as they are illegal in XML 1.0 (except for \t, \n, and \r).
This prevents XMPP servers from closing the connection when such
characters are accidentally or intentionally included in a message.
Fixes: https://github.com/profanity-im/profanity/issues/1437
Autocompletion failed for nicknames using non Latin scripts. We used
`g_str_to_ascii`, which replaces characters it cannot transliterate with
'?', leading search failures and false matches between different
scripts.
Now we do:
Use `g_utf8_casefold` for case-insensitive UTF-8 comparison. This
ensures that like 'Σ' correctly match 'σ' across all Unicode scripts,
providing correct results for non English nicknames.
If we don't fine anything typing a base ASCII character matches an
accented one (typing `e` matches `è`). This pass uses `g_str_to_ascii`
followed by `g_ascii_strdown` for comparison. It is now restricted to
run if the search string itself is valid ASCII, preventing the
"everything matches '?'" bug in non Latin scripts.
Autocomplete items are sorted using `strcmp`. `g_utf8_collate` provides
linguistical ordering for a specific language. But its behavior is
locale dependent and undefined when comparing strings from different
scripts. `strcmp` does byte-wise ordering that correctly follows Unicode
code order for UTF-8 strings.
When sending OMEMO messages, we print a warning message for every
participant without a device ID on every single send:
```
Can't find a OMEMO device id for my@jid.org
```
This clutters the UI due to the high volume of repetitive information.
This is solved by tracking suppressed warnings within the window
structure. A warning for a specific JID and type is only shown once
per window context.
Suppression state is stored in the base ProfWin structure and managed
via helper functions (win_warn_needed, win_warn_sent). The state is
lazily initialized to save resources and automatically cleaned up when
the window is closed.
Warnings are explicitly reset when an OMEMO session is started or
ended to ensure users see fresh alerts when toggling encryption.
Add __attribute__((nonnull) hints to omemo_receive_message and
omemo_on_message_recv declarations to catch NULL arguments at
compiletime.
So we can set the error state unconditionally in the functions.
If an incoming OMEMO message failed to decrypt (due to missing session
keys or untrusted identities), Profanity would fall back to displaying
the raw XMPP body. This usually contained a generic string like "This
message is encrypted with OMEMO,".
We wrote the detailed reason in the debug logs but the user only saw the
fallback message and probably wondered *why* the message wasn't
displayed properly.
I'm unsure if we should display the fallback message as well though.
The /omemo fingerprint command provided a list of all keys ever
seen for a contact but did not indicate which keys were currently "active"
(present in the latest server device list). This made it difficult for users
to identify which fingerprints actually required verification to fix
encryption issues.
Users can now easily distinguish between devices currently in use and
historical keys that no longer matter.
When encryption fails users can immediately see which "active" key is
"untrusted," allowing them to verify the correct fingerprint fast.
Function `omemo_is_device_active` will check if a fingerprint belongs
to a device currently announced by the contacts server.
Make jid_is_valid() allow JIDs ending with a slash (`user@domain/`).
In these cases, the parser now treats the input as a Bare JID with no
resource part, rather than rejecting it as invalid.
We will then just get `user@domain`.
This one will need a localpart as well.
It should be used when we want to message a user for example.
While jid_is_valid() also returns TRUE for domain/server JIDs.
Fix several issues in cmd_ac_complete_filepath:
* Prevent a segfault when input is empty.
* Fix a double free where acstring was managed by both auto_gchar and GArray.
* Fix a memory leak when reassigning inpcp during quote stripping.
* Restore the ability to cycle through files on repeated TAB presses by
caching the last input and skipping updates if the input is already a
known completion.
* Preserve user input style (e.g. ~, ./) in autocompletion strings to
ensure matches are correctly displayed and filtered.
Bug got introduced when "cleaning" code with new compiler flags and
sanitizers: aec8e48268.
Add unit tests so this doesn't happen again.
Before that commit we didn't use the static variable but used
autocomplete_update instead. Now we avoid redundat updates and preserve
the state across tab presses. We should look at this again later.
Fix https://github.com/profanity-im/profanity/issues/2098
Use a behavior-driven naming convention for unit tests.
Functions are now named using the pattern: [unit]__[verb]__[scenario]
The __ works as a semantic separator.
Examples:
* jid_create__returns__null_from_null()
* cmd_connect__shows__usage_when_no_server_value
Benefits:
* Easy to find all tests associated with a specific function using the
mandatory prefix.
* Test output in CI now explicitly describes the unit, the expected
outcome, and the scenario being tested.
Also disabled keyhandlers tests due to missing code in src/ui.
For example cmd_account() is located in src/command/cmd_funcs.c.
The unit test was located in tests/unittests/test_cmd_account.c.
Let's move it to a subdirectory like tests/unittests/command/test_cmd_account.c
to correpsond to the same structure.
Migrate structure allocations from calloc to glibs g_new0 macro to
improve type safety and memory robustness.
* Type Safety: The macro takes the type name directly, ensuring the
allocated size always matches the pointer type.
* Static Analysis: It guarantees a non-NULL return by aborting on
failure, which silences -fanalyzer warnings regarding potential NULL
pointer dereferences.
* Readability: Removes redundant sizeof() calls and is the glib way
Also refactor the function so we pass it the current version
and don't rely on the define inside of it.
This function only allows version format in the style of "x.y.z".
Optimize prof_occurrences by using pointer arithmetic and
g_utf8_next_char instead of calls to g_utf8_offset_to_pointer.
Improve list construction efficiency in prof_occurrences by
using g_slist_prepend and g_slist_reverse instead of appends.
Also fix a slight oversight that could lead to trouble:
When empty search strings (e.g. empty nicks) are passed
it caused matches at every position.
Update the test case to test for empty nicks.
See last commit with comment regarding cons_show().
In this test here we can see that if we pass NULL cons_show() isn't
called. Making it a bit different that other invalid test cases.
It seems like we didn't even check whether the operations succeed or
not.
* `clear_empty()`
Add assertion to confirm a newly created autocomplete object is empty.
* `find_after_create()`:
Add assertion to ensure `autocomplete_complete()` returns NULL when no
entries are present in th object.
Remove autodisable logic (prefs_set_autoping(0)) and early return in autoping
to treat intermittent false negatives from connection_supports(XMPP_FEATURE_PING).
Add one-time error display with debug features print for monitoring; warn on first failing
check without aborting to maintain functionality while investigating root cause.
Includes were updated in 988d366, but the change did not propagate to forced_encryption.c due to the gap between the upstream Profanity and the CProof.
As 9f2abc75 accidentally got the ordering of some of the includes wrong,
I decided to propose my initial solution again.
Additional to that, I've opened a MR against CMocka to solve this on
their side, since I believe that the current way this is done is not
sustainable [0].
[0] https://gitlab.com/cmocka/cmocka/-/merge_requests/91
Fixes: 9f2abc75 ("Fix tests with gcc15 (uintptr_t)")
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
CProof note: our new tests need to also be updated.
fixes: error: ‘uintptr_t’ undeclared, defined in header ‘<stdint.h>
(cherry picked from commit 9f2abc75ad)
Author: Andreas Stieger <Andreas.Stieger@gmx.de>
Added null check for jidp in cmd_sub to handle jid_create returning NULL.
Crash occurred when processing malformed JID inputs like @example.com.
Ensures robust handling of invalid JIDs.
Fixes#22
Implement /force-encryption command to configure forced encryption
settings with on|off and policy resend-to-confirm|block options.
The changes enhance user experience by clarifying encryption requirements
and providing actionable commands. Users can now press Enter again to
confirm unencrypted messages in resend-to-confirm mode.
As 9f2abc75 accidentally got the ordering of some of the includes wrong,
I decided to propose my initial solution again.
Additional to that, I've opened a MR against CMocka to solve this on
their side, since I believe that the current way this is done is not
sustainable [0].
[0] https://gitlab.com/cmocka/cmocka/-/merge_requests/91
Fixes: 9f2abc75 ("Fix tests with gcc15 (uintptr_t)")
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>