Commit Graph

5582 Commits

Author SHA1 Message Date
Michael Vetter
624585572e fix: Dont OMEMO trust check so often
a26cdf386b / #2104 added OMEMO trust status to the
title bar, but it was being re-calculated on UI refresh.

Update only on certain operations (like `/omemo trust`, new device
discoveries and even incoming OMEMO messages for example).
2026-03-09 11:38:51 +01:00
Michael Vetter
a26cdf386b Merge pull request #2104 from profanity-im/omemo-ux
Improve OMEMO UX
2026-03-09 09:15:24 +01:00
Michael Vetter
e39ffd981f refactor: Refactor OMEMO error handling and add non-null attributes
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.
2026-03-09 08:48:41 +01:00
Michael Vetter
3e2673aad2 cleanup: Cleanup types 2026-03-09 07:52:21 +01:00
Michael Vetter
4d49c2b746 feat: Provide descriptive fallback messages for OMEMO decryption failures
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.
2026-03-09 07:49:03 +01:00
Michael Vetter
b20e3f1a0c feat: Improve feedback during OMEMO session Initiation
After typing `/omemo start` a user was not informed of what exactly
happens.
Profanity is fetching the device list and the key bundle for each
device. This happens asynchronously. It could be that it takes some time
and the user already starts typing a message, believing OMEMO is
working.

Now we print:
* Initiating OMEMO session..
* Fetching device list and key bundles
* OMEMO session ready

So the user understands much better the current situation.
2026-03-09 07:49:03 +01:00
Michael Vetter
5a3083f273 feat: Show active and trust status in /omemo fingerprint
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.
2026-03-09 07:49:03 +01:00
Michael Vetter
99c03f8c3b feat: Provide detailed encryption failure messages for OMEMO
When OMEMO encryption failed due to untrusted devices, the
user was presented with a generic error message. This made it difficult
to identify which specific fingerprints were causing the issue, forcing
users to manually hunt for untrusted keys using /omemo fingerprint.

New function `omemo_get_jid_untrusted_fingerprints` to specifically
identify unverified identities for a contact.
`omemo_on_message_send` will now catch encryption failures and
explicitly list the untrusted fingerprints in the chat window.
2026-03-09 07:49:03 +01:00
Michael Vetter
ce9b5140d5 feat: Notify users when new OMEMO devices or fingerprints are discovered
Previously, Profanity silently updated OMEMO device lists and identity
caches in the background. This often led to confusion when a contact
added a new device, as encryption or decryption would eventually fail
due to untrusted keys without any prior warning to the user.

The `notifying` flag will distinguish between initial data loading and
realtime discovery.

We now print a message both when a contact publishes a new device ID or
when a new fingerprint is discovered.
2026-03-09 07:49:03 +01:00
Michael Vetter
ded2f6afc0 feat: Add OMEMO trust status indicators to the titlebar
Previously the titlebar only showed [OMEMO], regardless of whether the
active session contained untrusted devices. This forced users to manually
run /omemo fingerprint to check the security status of their conversation,
making it difficult to know at a glance if a session was truly secure.

New function `omemo_is_jid_trusted()` to check if all active devices for a JID are trusted.
Update chat and MUC titlebar to display [trusted] or [untrusted] tags when an OMEMO session is active.
Not sure if MUC makes sense here?
2026-03-09 07:49:03 +01:00
Michael Vetter
bfc9eb259c fix: Sanitize account names
GKeyFile parses ini-like config files. So the characters '[', ']',
and '=' cannot be used.
We will replace them with '_' now.

This bug was found when a user wanted to connect to an IPv6 address (user@[ipv6:address]).

One problem could be that we get duplicate account names with they would
use one of those 3 characters. But I consider this very unlikely.

Fix https://github.com/profanity-im/profanity/issues/2103
2026-03-08 21:45:35 +01:00
Michael Vetter
40963c702e fix: database return NULL if no history limits are found
log_database_get_limits_info should return NULL when a contact has no
history in the database.

We hit a bug with `/msg adsf@asd` before.
2026-03-06 15:05:57 +01:00
Michael Vetter
f251cc8bb3 feat: handle and allow JIDs with trailing slashes
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`.
2026-03-06 15:05:52 +01:00
Michael Vetter
35a2f2990a fix: Correct handling of create_fulljid without resource
If resource was NULL/"" we otherwise had a trailing slash.
2026-03-06 13:09:49 +01:00
Michael Vetter
fa64b135df refactor: Centralize validation within jid_is_valid 2026-03-06 13:08:06 +01:00
Michael Vetter
d6705362a2 fix: Only allow /msg with valid JIDs
Only allow to message someone who has a nick in roster or when we pass a
user JID.
Otherwise notify the user.
2026-03-06 12:36:53 +01:00
Michael Vetter
5bcf859e92 feat: Add jid_is_valid_user_jid() to check for valid user JIDs
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.
2026-03-06 12:35:30 +01:00
Michael Vetter
09757da5df feat: Improve validation of JIDs
Add new `jid_is_valid()` function and improve the adherence to XMPP RFCs
in jid_create().

Add unit tests for them as well.
2026-03-06 12:11:30 +01:00
Michael Vetter
421bb2e261 feat: Only request receipts when supported
Only request delivery receipts if the recipient is known to support them
via entity capabilities
As mentioned in the recommendations of XEP-0184.
2026-03-05 20:21:47 +01:00
Michael Vetter
11bc6ea22b fix: Fix usage error in /time command
When targeting a specific preference (`/time console off`)
the loop would continue to iterate through the remaining
categories after finding and applying the setting.

Because subsequent items would not match, it always resulted in
"invalid usage" printed as well after the success message.
2026-03-04 22:23:31 +01:00
Michael Vetter
99e7057a36 fix: Increase max arguments for /connect to 9
The /connect command supports several optional parameters
server, port, tls, and auth.

This was implemented in ac410445af but
this change in the command definitions probably were forgotten.
2026-03-04 22:20:31 +01:00
Michael Vetter
8dbd1e3253 fix: Fix file autocompletion bugs and restore cycling
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
2026-03-01 01:26:14 +01:00
Michael Vetter
612cc0e59e Merge pull request #2099 from profanity-im/clean-unittests
Cleanup unittests and improve documentation for new contibutors
2026-02-28 15:15:13 +01:00
Michael Vetter
b0abb64950 refactor: Fix clang-format expansion of table
By removing the trailing comma from the array initialization we hint
clang-format to maintain the compact layout.
2026-02-28 14:52:36 +01:00
Michael Vetter
d8c16640c5 Merge pull request #2097 from profanity-im/fix/731-pseudo-join
fix: Ignore self-presence for untracked MUC rooms
2026-02-28 11:32:24 +01:00
Michael Vetter
e18b71576e Merge pull request #2096 from profanity-im/fix/1997-floatingpoint
fix: Fix Floating Point Exception in OMEMO session building
2026-02-28 11:07:35 +01:00
Michael Vetter
9fb45b543b fix: Ignore self-presence for untracked MUC rooms
Only handle self-presence for rooms we are actively managing.

Earlier we blindly react to any self-presence
stanza by calling 'ui_room_join'.

The join could have been initiated by another client or an external
Gateway. In the case of #731 this was Slack.
I remember that more people reported this kind of bug in our MUC.

We then would open a window and the nick would be (null) because we
don't have any nickname for that room set.

So only react on self-presence if we manage the MUC.
Other XMPP clients do the same.

Fix https://github.com/profanity-im/profanity/issues/731
2026-02-28 10:42:03 +01:00
Michael Vetter
bc13a726b6 fix: Fix Floating Point Exception in OMEMO session building
When an OMEMO bundle is received with an empty <prekeys/> element,
`prekeys_list` remains empty. In omemo_start_device_session(),
performing a modulo operation on the length of an empty list
(0) triggered a SIGFPE (Floating point exception).

torsocks likely affected the network environment where such empty
or incomplete bundles could be intercepted.

Fix https://github.com/profanity-im/profanity/issues/1997
2026-02-28 10:28:26 +01:00
Michael Vetter
ab4adf19d0 refactor: Refactor form_set_value to use glib list management
Simplify how field values are updated and ensure memory is correctly
managed.

The previous implementation relied on manual manipulation of the
GSList internal `data` member and only handled cases where a field
had zero or one existing value.

The function now correctly handles fields that may
already contain multiple values by using 'g_slist_free_full' to
clear the entire list and its contents before setting the new
value.
2026-02-28 10:02:26 +01:00
Michael Vetter
434a887834 Fix -Wanalyzer-deref-before-check warning in get_message_from_editor
Let's add an explicit check.
2026-02-28 09:55:33 +01:00
Michael Vetter
c24cdcd671 fix: Fix -Wanalyzer-deref-before-check warning in cmd_ac_complete
Adding an explicit NULL check for 'input' at the start of
cmd_ac_complete to prevent a potential crash and resolve
a GCC static analyzer warning.

Quirk Explanation:
The analyzer found  a "deref-before-check" warning for:
`if ((strncmp(input, "/", 1) == 0) && (!strchr(input, ' ')))`

The analyzer interpreted 'strchr(input, ' ')' as a point where the
validity of 'input' is being questioned (a "check"), even though it is
actually checking the return value. This is due to GCC's internal model
of certain standard string functions having a 'nonnull' attribute or
being categorized as pointer "interrogations" in its state machine.

Because 'strncmp' dereferences 'input' earlier in the same line, the
analyzer saw a logical contradiction: "You treat it as safe in strncmp,
but then you call a function (strchr) that 'requires/checks' it to be
safe, implying you weren't sure."
2026-02-28 09:44:27 +01:00
Michael Vetter
02cde29b65 cleanup: use g_new() instead of malloc in prof_add_shutdown_routine() 2026-02-27 22:29:45 +01:00
Michael Vetter
051f986774 cleanup: make _connection_handler() safer
Check for the memory before using it.
2026-02-27 22:29:45 +01:00
Michael Vetter
10ef8505f8 cleanup: Cleanup log modul
* _rotate_log_file(): guard against NULL mainlogfile before g_strdup/strlen
* log_stderr_init(): move dup2 after malloc checks to avoid fd leak on
  allocation failure.
  Also remove explicit close(STDERR_FILENO) before dup2
  since dup2 closes the target atomically. Close the fd returned by
  dup2 immediately.
2026-02-27 22:29:45 +01:00
Michael Vetter
35030b7a7e cleanup: use g_new0 instead of malloc in buffer_get_entry_by_id() 2026-02-27 22:29:45 +01:00
Michael Vetter
7876645cb0 cleanup: be a bit more defensive in 2026-02-27 22:29:45 +01:00
Michael Vetter
7b0232c11c wleanup: be a bit more defensive in server_events.c 2026-02-27 22:29:45 +01:00
Michael Vetter
286e563fbe fix: fix redundant error reporting in http download
We were sequentially checking for errors from 'curl_easy_perform',
'ftell', and 'fclose'. Each time overwriting the last one, resulting in
a leak. This commit ensures that 'err' is only set if it is currently
NULL, preserving the first and most specific error encountered.
2026-02-27 22:29:45 +01:00
Michael Vetter
f5787fb31f cleanup: refactor account_eval_password to use glib
Move from popen() to g_spawn_command_line_sync().
Which is nicer and gets rid of a resource leak that was present here.
2026-02-27 22:29:45 +01:00
Michael Vetter
5d31f376dd cleanup: check for strdup() success in stanza_create_http_upload_request() 2026-02-27 22:29:45 +01:00
Michael Vetter
0218ba26c8 fix: fix memory leak and potential crash in iq_id_handler_add
`userdata` was not freed if a handler could not be registered.

This occurs when the 'id' parameter is NULL. In such cases, the
handler cannot be stored in the 'id_handlers' table, but ownership
of 'userdata' has already been transferred to this function. This
commit ensures 'free_func' is called if 'id' is NULL since we always
need to have an ID.
2026-02-27 22:29:45 +01:00
Michael Vetter
e15f659277 fix: Fix NULL dereference and memory leak in _mam_rsm_id_handler
Add NULL checks before calling 'strlen' and also ensures that the string
is long enough before attempting to offset it by 3.
2026-02-27 22:29:45 +01:00
Michael Vetter
776bc262d0 refactor: change vcard_print() checks
data is allocated via g_new0() so cannot be NULL here.
And it was used before the check already so that didn't make any sense
in the first place.
2026-02-27 22:29:45 +01:00
Michael Vetter
1ec536d343 fix: fix api_get_current_occupants() memory problems
Fix a potential NULL pointer dereference. And free the list properly.
2026-02-27 22:29:45 +01:00
Michael Vetter
2406413e14 fix: fix NULL dereference and memory leaks in OX logic
recp elements were accessed without verifying the success of
_ox_key_lookup().

Also fix several memory leaks.

gpgme_data_new() followed 'gpgme_data_new_from_mem' was redundant.
2026-02-27 22:29:42 +01:00
Michael Vetter
16080ab985 cleanup: Fix potential null pointer dereference 2026-02-27 19:45:57 +01:00
Michael Vetter
f74501e97e cleanup: add a defensive check in cmd_process_input() 2026-02-27 19:36:47 +01:00
Michael Vetter
d8a7b234bb fix: segfault when using /command help
Usually we use `/help command`. Additionally there is a shortcut
`/comamnd?`. 54fea4afcf tried to introduce
to have `/command help`. Which doesn't really work since most commands
get this as parameters. So it never worked. Additionally it introduced
at segfault because it tried to set *question_mark to NULL even we can
also get there without the `?` but by having the `help` as parameter.
2026-02-27 19:33:28 +01:00
Michael Vetter
373ec4a7e3 refactor: replace malloc with g_new0 in many occasions 2026-02-27 19:26:42 +01:00
Michael Vetter
de5949e8eb refactor: partly move plugins to glib
That's not very nice yet but we have to start somewhere.
2026-02-27 19:26:42 +01:00