Commit Graph

5642 Commits

Author SHA1 Message Date
Karel Balej
1458b09e27 fix(omemo): ignore key contents if there is no payload
For key transport messages, Monal at least doesn't append the
authentication tag to the plaintext key contents as that only makes
sense if the key was used to encrypt something. This causes the key
length check to fail and show the

	OMEMO message received but decryption failed.

error to the user which is confusing because there is no user-originated
message involved.

Skip the length check for key transport messages as profanity only uses
these to advance the ratchet and makes no use of the decrypted contents.

Signed-off-by: Karel Balej <balejk@matfyz.cz>
2026-04-09 09:52:10 +02:00
Michael Vetter
35bf9df0a9 refactor: Make Launching the editor more robust
Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-04-03 08:40:14 +02:00
Michael Vetter
2ad3bff8f0 docs: Add eval_password example
And show how to escape whitespaces.

Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-04-03 08:32:31 +02:00
Michael Vetter
c0f96e9b60 Merge pull request #2145 from profanity-im/fix/2143
fix: restore TTY access for eval_password commands
2026-04-02 23:18:07 +02:00
Michael Vetter
c3718e3ae7 cleanup: Remove unused variable
This was forgotten in a refactor commit.

Ref: c43c9567df
Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-04-02 22:47:26 +02:00
Michael Vetter
36ec2b0ae1 feat: implement asynchronous external editor support
Move from blocking fork/wait logic to nonblocking fork and
g_child_watch_add.

This ensures that the Profanity main loop continues to run while an
external editor is open. So we don't loose connection and react to
pings.

We change editor handling also in vcard and muc subject editing.
In the new implementation we are launching the editor and passing a
callback which we will use once the editor exited.

We use the recently added ui_susped() and ui_resume().

To not clutter the UI we need to check whether Profanity UI is suspended
and omit drawing in this case.

Fixes: https://github.com/profanity-im/profanity/issues/1888
Ref: 9b112904a9bc7250dc013d901187ca8622580d98
Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-04-02 22:47:26 +02:00
Michael Vetter
fc66ddc2c1 refactor: Use helper functions in vcard related code
There was way too much repetition here.
This is in preparation for future changes regarding the editor.

Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-04-02 22:47:26 +02:00
Michael Vetter
8675f7be0c fix: Fix removal of entries in account file
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>
2026-04-02 22:47:22 +02:00
Michael Vetter
c9a3823f13 fix: restore TTY access for eval_password commands
Replace g_spawn_command_line_sync with g_spawn_sync with the
G_SPAWN_CHILD_INHERITS_STDIN flag.
This is actually needed to so that interactive commands can access the
terminal.
Otherwise they cannot ask the user for the passphrase.

Ref: f5787fb31f
Fixes: https://github.com/profanity-im/profanity/issues/2143
Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-04-02 16:38:34 +02:00
Michael Vetter
14c0c38acd fix: Fix crash when loading MAM for a contact with empty db
I think this bug happens when a user scrolls up a window, triggering
iq_mam_request_older() to load older history, in the case when the
database is empty for that contact.

The initial MAM fetch is triggered when the window is opened which
should get the latest history.

Fixes: https://github.com/profanity-im/profanity/issues/2142
Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-04-02 13:37:49 +02:00
Michael Vetter
b56498adcb Merge pull request #2139 from profanity-im/fix/1844
Improve autocompleter and command parsing in relation to quoting
2026-04-02 12:31:58 +02:00
Michael Vetter
923dfea71e Merge pull request #2136 from profanity-im/db-dup
refactor(database): enforce unique archive_id for reliable deduplication
2026-04-02 12:31:26 +02:00
Michael Vetter
dfe79038d4 Merge pull request #2140 from profanity-im/fix/1420
fix: handle X11 connection loss gracefully
2026-04-02 12:21:09 +02:00
Michael Vetter
8eac31e5e1 fix: handle X11 connection loss gracefully
Use XSetIOErrorExitHandler on X11 to detect connection loss and
disable GTK features (tray, clipboard, notifications).

Signed-off-by: Michael Vetter <jubalh@iodoru.org>
Signed-off-by: Paul Fertser <fercerpav@gmail.com>
Co-authored-by: Paul Fertser <fercerpav@gmail.com>
2026-04-01 23:14:46 +02:00
Michael Vetter
c43c9567df refactor(database): use ON CONFLICT for deduplication
Replace 'INSERT OR IGNORE' with 'INSERT ... ON CONFLICT(`archive_id`) DO
NOTHING RETURNING id'. This is only available since sqlite 3.35.0.
So deduplication only happens for `archive_id` and we don't silently
ignore other errors or constraints (like not null).

We can now detect if an insertion was skipped due to duplication by
checking the result of 'RETURNING id'.

We don't print out when we don't insert duplicated messages since this
will happen often and will be too noisy. So we match the behaviour of
what Dino is doing.

Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-03-31 15:27:33 +02:00
Michael Vetter
df1f1e5ef1 fix: ensure consistent unescaping and space handling
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>
2026-03-30 18:33:59 +02:00
Michael Vetter
bda5b0f844 fix(tools): implement backslash escaping for contact names
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>
2026-03-29 00:15:23 +01:00
Michael Vetter
247c44be30 fix(xmpp): verify 'by' attribute of stanza-id and MAM result
Implement security checks to ensure the 'archive_id' (XEP-0359) used
for database deduplication originates from a trusted source.

XEP-0359 Section 3.1: "The 'by' attribute MUST be the XMPP
address (JID) of the entity assigning the unique and stable stanza ID."
Furthermore, Section 4 (Security Considerations) specifies: "A client
SHOULD only trust <stanza-id/> elements from its own server or from
a MUC service it is joined to."

XEP-0313 Section 4.1.2: "The 'by' attribute of the <result/> element is
the JID of the archive being queried." and "If the 'by' attribute is not
present, the recipient MUST assume that the results are from their own
personal archive."

Let _handle_chat verify <stanza-id/> 'by' attribute matches our bare JID.
Let _handle_groupchat verify <stanza-id/> 'by' attribute matches the MUC
s bare JID.
Let _handle_mam verify the <result/> 'by' attribute matches the outer
message 'from' (archive JID). If 'by' is missing then 'from' matches our
own bare JID (personal archive).

Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-03-27 23:57:59 +01:00
Michael Vetter
64fcdfaa0f refactor(database): enforce unique archive_id for reliable deduplication
Implement a UNIQUE constraint on the archive_id column (XEP-0359 stanza-id)
to prevent duplicate messages in the chat log. This addresses problems where
the same message could be stored multiple times if received via both MAM
and regular.

Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-03-27 23:25:54 +01:00
Michael Vetter
68085f014f fix(omemo): standardize PreKey management to prevent decryption failures
Standardize how PreKeys are handled during OMEMO message reception to
align with XEP-0384 best practices.

Previously Profanity replaced a consumed PreKey by generating a new
one with the same ID. This behavior could lead to decryption failures if
multiple senders attempted to use the same PreKey ID before the client
could successfully update its bundle on the server.

Remove consumed PreKeys from the local store.
New PreKeys are generated in batches (100) when the local supply runs
low (< 10).
Republish OMEMO bundle after replenishment.

Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-03-27 23:21:03 +01:00
Michael Vetter
84e6eeae92 Merge pull request #2132 from profanity-im/feat/spellcheck
Add spellchecking
2026-03-27 14:32:01 +01:00
Leon Adomaitis
9a501e6ecd fix(omemo): add missing includes for libomemo-c builds
Signed-off-by: Leon Adomaitis <leon@adomaitis.de>
2026-03-27 02:34:26 +01:00
Michael Vetter
ed2fdf88ac feat: Add /spellcheck list command
To list all available dictionaries.

Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-03-26 23:34:13 +01:00
Michael Vetter
4922366366 feat: add spellcheck highlighting support
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>
2026-03-26 23:34:06 +01:00
Michael Vetter
25d2cb0120 fix: Check for necessary pointers in omemo_receive_message
Static analyzer hilighted this.

Ref: e39ffd981
Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-03-26 11:41:20 +01:00
Michael Vetter
63af72773c feat: Implement color coded status messages for file transfers
Introduce meaningful color feedback for background tasks like file
downloads and uploads. Progress is displayed in a neutral color,
while successful completions turn green and failures turn red.

We reuse the existing THEME colors for now.

Add new UI flags ENTRY_COMPLETED and ENTRY_ERROR to
the buffer entry system. So we don't misuse delivery receipts anymore.

Fixes: https://github.com/profanity-im/profanity/issues/1758
Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-03-25 17:40:10 +01:00
Michael Vetter
a9ef000328 fix: Improve status reporting and filename handling for /url save
Use the original aesgcm:// URL when downloading OMEMO downloads.  Then
in the final message use the decrypted file destination instead of the
internal temporary path.

Use the unique download ID instead of the URL for message updates to
have proper progress reporting.

Unify the final transfer status to "done" across both downloads and
uploads.

Fixes: https://github.com/profanity-im/profanity/issues/1939
Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-03-24 22:37:54 +01:00
Michael Vetter
a824b26008 refactor: improve key transport message handling and deduplicate errors
Centralize heartbeat detection and have a function for error to string
mapping. So we don't need the same code in multiple handlers.

Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-03-22 17:42:08 +01:00
Michael Vetter
e4bfda2f8a fix: Incorrect omemo decryption error for Key Transport Messages
Correctly handle OMEMO stanzas that contain a <header> but no <payload>.
These "Key Transport Messages" (heartbeats) are used by some clients
for session maintenance and establishing trust.

Ref: a2726b6a7 made the <payload> element mandatory in the parser.
Ref: 4d49c2b74 the bug became user-visible.

Fixes: https://github.com/profanity-im/profanity/issues/2129
Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-03-22 17:41:57 +01:00
Michael Vetter
53a980cdd3 Merge pull request #2122 from profanity-im/fix-2045
feat(ui): implement dynamic pad resizing
2026-03-21 00:00:06 +01:00
Michael Vetter
4c731f5241 fix: allow adding own JID to roster
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>
2026-03-20 23:48:00 +01:00
Michael Vetter
9035af95cb feat: Add command autocompletion for /stamp
Ref: 2c003dd2
Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-03-20 16:23:46 +01:00
Michael Vetter
b0a89530f2 fix(ui): Fix custom outgoing stamp and fix stamp command help
Replace the hardcoded "me" stamp for outgoing messages that are
sometimes used with the value from PREF_OUTGOING_STAMP.

It was never implemented in all code paths. Like with receipts for
example.

Additionally fix the confusing description and variable names.

Ref: 2c003dd2 (Add /stamp feature)
Ref: 3a4cd7da (Broke the variables)
Fixes: https://github.com/profanity-im/profanity/issues/2125
Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-03-20 16:23:41 +01:00
Michael Vetter
c3fbb89a7a Merge pull request #2123 from profanity-im/ci
ci: Cleanup and improve CI jobs
2026-03-20 15:09:31 +01:00
Michael Vetter
2d7426fb2f fix: Fix rare memleak
Triggered by unit tests. In Profanity itself the situation is probably
rarely happening. We would have to disconnect/exit after receiving
presence but before the roster arrives.
2026-03-20 12:47:39 +01:00
Steffen Jaeckel
613df86450 Check connection state before accepting command.
Prevent `/register` and `/reconnect` if connection is not in correct state.

Fixes: https://github.com/profanity-im/profanity/issues/2083
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
2026-03-20 09:23:41 +01:00
Michael Vetter
3e16ae1def feat(ui): implement dynamic pad resizing
The ncurses pad used for rendering window history had a fixed height of 100
lines, which caused "Ncurses Overflow!" errors and broke scrolling once
the content exceeded this limit.

This commit replaces the fixed limit with a dynamic resizing strategy.
We use a minimum height of 100 lines.
If a pad reaches its threshold of 3000 lines, a full redraw is triggered
to reclaim space from discarded messages and reset the pad height.
Pads are shrunk back to the minimum height during every redraw to
minimize memory usage for inactive windows.

Message history should always be smoothly scrollable now.

d7e46d64fe set it from 1000 to 10000.
f27fa98717 set it from 1000 to 100.
Probably also relevant is 4fe2c423b1.

Close: https://github.com/profanity-im/profanity/pull/2074
Fixes: https://github.com/profanity-im/profanity/issues/2045
2026-03-19 22:10:36 +01:00
Michael Vetter
046eb13e2e Merge pull request #2117 from profanity-im/xep0377
Improve support for XEP-0377
2026-03-19 19:53:22 +01:00
Michael Vetter
27b5f0fbda build(meson): add support for libomemo-c as OMEMO backend
Add the ability to choose between libsignal-protocol-c (default)
and libomemo-c when building with OMEMO support enabled in Meson.

Close: https://github.com/profanity-im/profanity/pull/2020
2026-03-19 19:01:50 +01:00
Michael Vetter
82db360fb9 feat: Improve XEP-0377 support with report-origin and third-party elements
Add support for <report-origin/> and <third-party/>.

When a server forwards a report to an administrator, the original reporter
(report-origin) and the offender (third-party) are preserved even
if the 'from' address is modified during forwarding.

Also display this information in case we receive a report.
2026-03-19 13:31:13 +01:00
Michael Vetter
1d94316937 fix: missing plugins_post_chat_message_display calls
We need the post-display hooks in DB, log, outgoing messages, and carbons as well.
Also add pre-display hook to carbons for consistency.

Fixes: https://github.com/profanity-im/profanity/issues/2011
2026-03-19 11:46:31 +01:00
Michael Vetter
030c0b7999 docs: Improve help for /blocked 2026-03-19 11:07:51 +01:00
Michael Vetter
93918a20d1 feat: Display incoming reports (XEP-0377)
Servers might forward incoming reports to admins. So we need to display
them so they can react upon it.
2026-03-19 10:57:41 +01:00
Michael Vetter
d616e160cd Merge pull request #2116 from profanity-im/sanitzexml
feat: Sanitize illegal XML characters from outgoing messages
2026-03-19 10:40:19 +01:00
Michael Vetter
446f28ac31 fix: Use <body> tag for spam reporting (XEP-0377)
Update `blocked_add` to use the `<body>` tag with the `jabber:client`
namespace when reporting spam, as specified in XEP-0377 Example 5.
Other report types continue to use the `<text>` tag.

Fixes: https://github.com/profanity-im/profanity/issues/1971
2026-03-19 10:36:59 +01:00
Michael Vetter
189050f3f4 feat: Sanitize illegal XML characters from outgoing messages
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
2026-03-19 10:28:49 +01:00
Michael Vetter
1f146d1499 Merge pull request #2113 from profanity-im/omemo-noise
Reduce OMEMO noise
2026-03-19 09:36:53 +01:00
Michael Vetter
e9c6b3b3d8 feat(tools): support UTF-8 characters in autocompletion
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.
2026-03-19 08:41:50 +01:00
Michael Vetter
b7c8f8235c feat(omemo): suppress "new device" alerts for already known devices
Modify omemo_set_device_list to check against the persistent
known_devices.txt file before notifying the user. This prevents
false-positive security alerts on every restart for devices
that have already been registered and trusted.

Check against the persistent known_devices.txt file before notifying
the user. This ensures that "New OMEMO device" alerts are only shown
for devices that are truly new to this client.

Ref: ce9b5140d
2026-03-18 22:19:18 +01:00
Michael Vetter
4253da99c5 feat(omemo): suppress redundant session already exists messages
Removing the UI notification in omemo_start_device_session to reduce
noise during /omemo start.
The information is still available in the debug logs.

And I think for existing sessions its just too much without value.

Ref: b20e3f1a
2026-03-18 22:19:13 +01:00