Commit Graph

402 Commits

Author SHA1 Message Date
9b03e3a508 refactor: address PR #105 review (#1222, #1226)
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 2m36s
CI Code / Linux (debian) (pull_request) Successful in 4m39s
CI Code / Linux (ubuntu) (pull_request) Successful in 4m48s
CI Code / Linux (arch) (pull_request) Successful in 5m36s
#1222 (src/xmpp/roster_list.c): remove dead 'resource = NULL' inside
roster_update_presence() — assigning to a value parameter never
affects the caller. Document the ownership contract: the function
consumes 'resource' on every return path and callers must null
their own pointer afterwards. The existing caller in
roster_process_pending_presence already does that, and
resource_destroy() is NULL-safe.

#1226 (src/tools/editor.{c,h}): remove get_message_from_editor[_async]
and the surrounding async-editor infrastructure (editor_thread,
editor_task global, editor_process polling, EditorTask typedef).
The upstream callback-based launch_editor API has replaced every
call site (cmd_funcs.c, inputwin.c). Also drop the now-unused
'background_mode' global (only the obsolete async path ever set it
to TRUE) and the editor_process() call in profanity.c main loop.

Verified with ci-build.sh in Debian docker — all 4 build configs
pass (644/0, 605/0, 605/0, 644/0 unit + 130/0 functional each).
2026-05-21 12:50:19 +03:00
508de43da9 Merge branch 'master' into merge/upstream-full
Some checks failed
CI Code / Check spelling (pull_request) Successful in 17s
CI Code / Check coding style (pull_request) Successful in 31s
CI Code / Linux (debian) (pull_request) Failing after 39s
CI Code / Linux (ubuntu) (pull_request) Failing after 42s
CI Code / Linux (arch) (pull_request) Failing after 4m59s
CI Code / Code Coverage (pull_request) Failing after 4m48s
Resolve conflicts after master gained the flat-file database backend,
AI client, and other cproof-fork features:

- CHANGELOG: keep cproof-fork unreleased section atop full upstream
  history (0.17.0 / 0.16.0 / 0.15.1)
- src/command/cmd_ac.c: keep both upstream spellcheck AC and cproof
  /history switch|verify|export|import autocompletion
- src/config/preferences.c: merge upstream [spellcheck] group with the
  cproof [ai]/[ai/<provider>] groups
- src/database.c: take master (thin dispatcher); upstream SQLite
  improvements (v3 migration, auto_gchar) belong in database_sqlite.c
  and will land in a follow-up commit
- src/tools/autocomplete.c: take upstream unescape of search_str
- src/ui/statusbar.c: keep guint signatures (per project preference)
  and adapt _status_bar_draw_dbbackend to guint as well
- src/xmpp/jid.c: combine the new jid_is_valid/jid_is_valid_user_jid
  with the "(null)" legacy-placeholder guard in
  jid_create_from_bare_and_resource; use auto_gchar
- tests/functionaltests/proftest.c: keep unsigned-safe pre-check on
  output_len before subtracting OUTPUT_BUF_SIZE
- tests/unittests/unittests.c: keep upstream subdirectory include
  layout plus cproof-only test_ai_client/database_export/database_stress
- tests/unittests/test_jid.c: drop orphan top-level copy (the
  restructured version lives in tests/unittests/xmpp/test_jid.c)

Upstream is included up to 1ac05754b (release 0.18.0 era). Follow-up:
pull 1ac05754b..upstream/master (esp. 42a849d16 db migration fix and
4749645c7 receipt-request restore), and adapt the SQLite improvements
into database_sqlite.c.
2026-05-18 11:42:48 +03:00
9e5dfb14f8 feat(ai): add AI client with multi-provider chat support
All checks were successful
CI Code / Check spelling (push) Successful in 18s
CI Code / Check coding style (push) Successful in 29s
CI Code / Code Coverage (push) Successful in 2m44s
CI Code / Linux (debian) (push) Successful in 4m46s
CI Code / Linux (ubuntu) (push) Successful in 4m59s
CI Code / Linux (arch) (push) Successful in 5m56s
Add an AI client module that integrates with OpenAI-compatible API
providers (OpenAI, Perplexity, and custom endpoints) to provide
AI-assisted chat within CProof. Users can start sessions with /ai start,
send prompts, receive responses in a dedicated AI window, switch between
providers and models, and manage API keys — all with tab-completion.

Providers are configured via /ai set commands with per-provider API keys,
endpoints, default models, and custom settings. Two default providers
(openai, perplexity) are seeded on first use. Provider state persists in
[ai/<name>] sections of the preferences keyfile with automatic migration
from the previous flat-key format.

The /ai command integrates into the existing command system with 8
subcommands covering provider management, session lifecycle, model
fetching, and conversation clearing. Autocomplete uses the standard
flat prefix-matching chain for reliable tab-completion at every nesting
level. A new ProfAiWin window type is added to the window system.

Architecture:

Async design: HTTP requests run on a background thread (pthread) to avoid blocking the ncurses UI loop; results are displayed on the main thread via direct function calls
Thread safety: AIProvider and AISession use atomic ref-counting and mutex-protected session state; the request thread snapshots all session data before making the HTTP call
Window validation: wins_ai_exists() prevents use-after-free when the user closes the AI window during an in-flight HTTP request (~60s)
Privacy: store:false is sent with every request to prevent providers from persisting conversations or using them for training
Response size limit: 10MB cap with immediate curl abort via CURL_WRITEFUNC_ERROR to prevent OOM
JSON parsing uses unified helpers for both chat responses and error
envelopes with consistent escape decoding. The response parser tries
Perplexity /v1/responses "text" field first, then falls back to OpenAI
"content". Error parsing extracts provider error.message from the
standard envelope format. Model parsing handles multiple API response
formats (OpenAI list, Perplexity, array) including edge cases.

Tests include 470+ lines of unit tests covering provider management,
session lifecycle, JSON parsing (multiple formats), autocomplete cycling,
and error handling, plus functional tests for /ai command dispatch.
A stub_ai.c module isolates unit tests from UI dependencies.
2026-05-15 02:21:54 +00:00
a5fe32b245 Merge remote-tracking branch 'upstream/master' into merge/upstream-full
# Conflicts:
#	CONTRIBUTING.md
#	src/profanity.c
#	src/tools/editor.c
2026-04-18 12:26:52 +03:00
Michael Vetter
dd76f9087f fix: resolve issues with async editor
If we build Profanity without GTK we dont iterate the context so we will
never know when the editor exited. Calling `g_main_context_iteration()`
or finally switching to GMainLoop fixes this.
So far calling `tray_update()` does this for us in GTK builds.
So this went unnoticed.

The editor will inherit ignored signal handlers (SIGINT, SIGTSTP, SIGPIPE)
from us. Neovim uses libuv which seems to check SIGINT on startup to
determine whether the environment is interactive or not.
We now reset these signals to SIG_DFL in the child process before execvp.

Profanity uses readline which still competed for terminal input with the
editor. We only took care about other Profanity UI processes in our
previous commit. This led to misordered characters in the editor.

In my tests with vim everything worked fine and these bugs were
discovered when a user used neovim.

Fixes: https://github.com/profanity-im/profanity/issues/2148
Ref: 36ec2b0ae1
Signed-off-by: Michael Vetter <jubalh@iodoru.org>
2026-04-11 23:45:36 +02:00
4319172758 Merge upstream/master into merge/upstream-full
All checks were successful
CI Code / Check coding style (pull_request) Successful in 32s
CI Code / Check spelling (pull_request) Successful in 15s
CI Code / Linux (debian) (pull_request) Successful in 6m43s
CI Code / Linux (ubuntu) (pull_request) Successful in 6m49s
CI Code / Linux (arch) (pull_request) Successful in 8m52s
CI Code / Code Coverage (pull_request) Successful in 7m19s
Merge profanity-im/profanity master (373 commits) into cproof fork.

Source changes (manual merge):
- src/command/: cmd_defs, cmd_funcs, cmd_ac — upstream g_new0, auto_gchar,
  launch_editor callback; keep our XEP-0308 LMC, force-encryption, CWE-134
- src/config/: preferences, tlscerts, account — upstream UNIQUE dedup,
  dynamic pad capacity; keep our db_history_result_t, scroll logic
- src/database.*: upstream g_new0 memory mgmt; keep our return types,
  add null-check fix for msg->timestamp
- src/omemo/, src/pgp/: upstream _gpgme_key_get_email, g_new0;
  keep our replace_id in omemo_on_message_send
- src/tools/: editor, http_upload, bookmark_ignore — upstream launch_editor
  callback API
- src/ui/: console, window, chatwin, mucwin, inputwin, buffer —
  upstream win_warn_needed/sent dedup, PAD_MIN_HEIGHT dynamic pads;
  keep our y_start_pos scroll, _truncate_datetime_suffix
- src/xmpp/: message, stanza, presence, roster_list, iq, session —
  upstream connection_get_available_resources; keep our LMC stanza logic
- src/common.c: fix format-security (cons_show)

Build system:
- Makefile.am: updated test paths to subdirectory structure, added
  test_cmd_ac, test_forced_encryption
- Restored autotools files deleted by upstream meson migration:
  bootstrap.sh, autogen.sh, m4/ax_valgrind_check.m4, configure-debug

Tests:
- Unit tests: upstream unittests.c base + our forced_encryption tests
  (482 passed, 0 failed across all 4 configurations)
- Functional tests: kept our version (93 passed, 0 failed)
  upstream version requires stbbr_for_xmlns not yet in our stabber fork
- Updated test stubs: stub_xmpp.c, stub_omemo.c from upstream

Compile fixes:
- src/common.c: cons_show(errmsg) -> cons_show("%s", errmsg)
- src/database.c: null-check before msg->timestamp access
- src/ui/console.c: size_t -> (int) cast for format width
- src/config/tlscerts.c: %d -> %zu for size_t
2026-04-11 13:44:50 +03: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
798edce22a chore: Move to SPDX license header 2026-03-09 12:55:37 +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
48205fc6de cleanup: Initialize waittime to 0
This fixes a -fanalyzer uninitialized value warning.
2026-02-26 19:21:45 +01:00
Michael Vetter
f1acf702a9 chore: Update copyright year 2026-02-20 16:13:31 +01:00
467222d0ca fix(ui,db): harden NULL handling, fix CWE-134, optimize iterations
Some checks failed
CI Code / Code Coverage (push) Failing after 10m34s
CI Code / Check spelling (push) Failing after 10m47s
CI Code / Check coding style (push) Failing after 11m4s
CI Code / Linux (ubuntu) (push) Failing after 11m19s
CI Code / Linux (debian) (push) Failing after 11m28s
CI Code / Linux (arch) (push) Failing after 11m38s
security(CWE-134): fix format string injections + add CI check
fix(ui): subwindow lifecycle, newwin/newpad guards, fallback timestamps
fix(db): sqlite cleanup on failures, sqlite3_close_v2
fix(xmpp): queued_messages loop, barejid leak
perf(core): g_hash_table_iter_init instead of g_hash_table_get_keys
refactor(ui): CLAMP macro in _check_subwin_width
test: XEP-0012 and XEP-0045 functional tests

Author: jabber.developer2
Closes #58, #85
2026-02-06 19:27:40 +01:00
Karel Balej
7c83c2608d exit gracefully on SIGTERM and SIGHUP
Make profanity exit gracefully when it receives either SIGTERM or
SIGHUP. This means that various cleanups will happen as if the user
issued the /quit command, whereas before these signals would terminate
profanity immediately leaving for instance the connection to the server
unterminated.

The main motivation for this change is so that profanity will exit
gracefully when the user closes the terminal that it's running in, which
is a handy shortcut (but can also happen on accident) and won't now lead
to the connection slowly timing out on the server instead. Similarly for
SIGTERM: profanity now for instance needs not be manually closed before
shutting down the computer to avoid the above as it will instead receive
this signal from the init process.
2026-01-22 13:37:56 +01:00
ad294cdd6d feat(editor): add asynchronous external editor support
Some checks failed
CI / Check spelling (pull_request) Successful in 18s
CI / Check coding style (pull_request) Successful in 31s
CI / Linux (fedora) (pull_request) Failing after 1m14s
CI / Linux (debian) (pull_request) Successful in 10m19s
CI / Linux (ubuntu) (pull_request) Successful in 10m42s
CI / Linux (arch) (pull_request) Successful in 13m2s
The synchronous `get_message_from_editor` blocked the main loop (`prof_run`) while launching an external editor like `vim`, halting network I/O in `session_process_events` and preventing incoming message reception.

Introduced `get_message_from_editor_async` for `cmd_editor` to run the editor asynchronously. It forks and execs the editor in a thread (`editor_thread`), suspending NCurses to free the terminal. The main loop skips `inp_readline` and `ui_update` via a new `background_mode` flag while the editor runs, allowing `session_process_events` to keep the connection alive.

On editor completion, `editor_process` (called per loop iteration) resumes NCurses with `ui_resize`, inserts the result into the readline buffer and clears `background_mode`.

Retained synchronous `get_message_from_editor` for ~20 existing code paths (e.g., `vcard_nickname`) to avoid breaking them.

Tested with `vim` and `nano`: confirms no rendering conflicts, messages received during editing, and seamless resume. Edge cases like editor crashes handled via error logging and seamless resume.
2025-08-07 03:03:43 +02:00
Michael Vetter
07dfeec816 Release 0.15.0 2025-03-27 20:06:38 +01:00
Steffen Jaeckel
c0da36c48d Rage-cleanup.
While trying to get the unit tests working again I stumbled over all those
things that I thought could be better^TM.

Now we also know "TODO: why does this make the test fail?" - because
the unit tests are brittle AF ... and we have to init the subsystems
we use in the test, otherwise the cleanup will fail...

BTW. you can now also only run a single test ... or a pattern or so ...
you'd have to read how `cmocka_set_test_filter()` works exactly.

Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
2025-03-10 11:45:15 +01:00
Steffen Jaeckel
c5a131ee46 Introduce our own shutdown callback mechanism.
Instead of adding stuff to `_shutdown()`, we can now register a shutdown
routine from the respective `init()` function of our modules.

This also has the advantage, that we're sure they're called in reverse
order from how the initialization happened.

I didn't simply use `atexit()` because POSIX says that the number of
possible callbacks is limited (min 32) and I was not sure whether
we will maybe extend this number at one point.

Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
2025-03-07 21:09:16 +01:00
Steffen Jaeckel
662a0be633 Add --cmd option
This allows to kind of automate what profanity should do as first jobs,
e.g. `--cmd /foo --cmd /bar --cmd /quit` so one can easily check for memory
leaks.

Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
2025-03-07 21:09:16 +01:00
Steffen Jaeckel
8151dfa3b4 /quit now exits from the event loop
Before this change issuing `/quit` directly called `exit(0)` and did not
invoke all the graceful shutdown routines. Now we first try to exit from
the event loop, which includes cleaning up everything.
In case the event loop is stuck for some reason, you could try to issue a
second `/quit`, which will then directly call `exit(0)`.

Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
2025-01-28 16:43:13 +01:00
Michael Vetter
88b26cfdb9 Undo gmainloop related changes
Revert "Merge pull request #1943 from H3rnand3zzz/gmainloop

This reverts commit 609fde0998, reversing
changes made to 2ec94064ed.

Revert "Merge pull request #1948 from H3rnand3zzz/fix/rl-less-refreshes"

This reverts commit 11762fd2b0, reversing
changes made to 609fde0998.

We have got several issues, that we don't quite see how to solve, with
the merge of the gmainloop PR.

* Slashguard is broken (#1955) (though #1956 could fix that)
* One person reported problems with copy paste selection via mouse
* Some input buffer seems not to be cleared correctly
  It happened that I was debugging profanity used `/connect` and typed
  the password. I then debugged so long that a time out occurred, so
  profanity disconnected. Then it printed "unknown command: $password".

There was something else that I forgot now.

Bottomline is: so far we didn't get it right so we will undo these
changes until someone proposes a working solution.

We got a slight performance increase (apparently noticable when
alt+mouse scrolling) but got too many issues with this change.
2024-02-19 17:41:06 +01:00
Michael Vetter
569e37f018 Update copyright to 2024 2024-01-22 16:03:48 +01:00
John Hernandez
f322639668 Fix chat state updating
Previous commits introduced a problem that chat state
stopped working, this commit resolves it by updating it on each cycle.
2023-12-28 18:09:50 +01:00
Rodrigo Arias
7eac636fc8 Implement keyboard input using GIOChannel 2023-12-28 18:09:50 +01:00
Rodrigo Arias
f995944734 Run the main loop with GMainLoop 2023-12-28 18:09:50 +01:00
Steffen Jaeckel
31c6d5f09a Improve shutdown
1. close logfile as last action
2. Fix `plugins_shutdown()` accessing `((ProfPlugin*)curr->data)->lang`
   after `curr->data` had already potentially been free'd.

Signed-off-by: Steffen Jaeckel <jaeckel-floss@eyet-services.de>
2023-12-12 16:31:42 +01:00
Michael Vetter
22b1d14b67 Add helper function to create version string
And remove all the duplicate code.

Depending on the situation prof_get_version() will return:
* 0.13.1
* 0.13.1dev
* 0.13.1dev.master.69d8c1f9
2023-07-25 20:58:15 +02:00
John Hernandez
7f3fca2bd0 Cleanup: gchar as gchar instead of char
Use gchar instead of char in most of the cases where gchar is intended.

Reason: improve compatibility and stability. Issue #1819

Minor refactoring.
2023-05-04 16:15:09 +02:00
Martin Dosch
e1ffc64a65 User proper ellipsis char
As stated in
https://github.com/profanity-im/profanity/pull/1820#issuecomment-1498083383
profanity uses "..." (three dots) in a lot of places instead the proper
ellipsis char "…".
2023-04-09 12:19:18 +02:00
Steffen Jaeckel
e9aaba938b minor changes
* fix typo
* less code duplication
* less `GString` usage
* more `auto_gchar` usage
* document connecting to servers supporting SASL ANONYMOUS
* ignore valgrind output

Signed-off-by: Steffen Jaeckel <jaeckel-floss@eyet-services.de>
2023-01-18 20:02:46 +01:00
Michael Vetter
3adc399da0 Update copyright year 2023-01-10 10:37:25 +01:00
Steffen Jaeckel
095d40d3bd tell the user to which file we're logging
Signed-off-by: Steffen Jaeckel <jaeckel-floss@eyet-services.de>
2022-09-07 10:04:00 +02:00
Michael Vetter
585f68f4f7 Split log.c into log.c and chatlog.c 2022-06-28 20:08:38 +02:00
Michael Vetter
1330ad4e1e Update copyright year 2022-05-09 15:43:33 +02:00
Michael Vetter
46c8245af9 Format new register code correctly 2021-10-13 21:32:44 +02:00
swirl
2cc354b6ae fixed some bugs, added some more
- Added JABBER_RAW_CONNECT[ING/ED] connection states
- Added cl_ev_connect_raw and session_connect_raw to conform to normal
connection functions
- Fixed SIGABRT during registration
- Added a check in cmd_register to ensure it's actually connected before
registering--but this will always fail atm
2021-08-17 14:09:48 -04:00
Michael Vetter
5d2037aa0c profanity.c: move var into function 2021-03-16 14:41:52 +01:00
Michael Vetter
8c08e64f37 Update copyright 2021-01-08 16:36:30 +01:00
Michael Vetter
a2726b6a7d Apply coding style 2020-07-07 14:18:57 +02:00
Michael Vetter
a4cadf78fa Revert "Apply coding style"
This reverts commit 9b55f2dec0.

Sorting the includes creates some problems.
2020-07-07 13:53:30 +02:00
Michael Vetter
9b55f2dec0 Apply coding style
Regards https://github.com/profanity-im/profanity/issues/1396
2020-07-07 09:43:28 +02:00
Michael Vetter
e5ac12afa6 Remove prefs_free_string()
It just does a free.
Related to b580b9ef11
2020-07-02 11:34:12 +02:00
Michael Vetter
0e1bccda18 Define lock in profanity.h as extern
Fix https://github.com/profanity-im/profanity/issues/1314
2020-04-17 10:14:27 +02:00
Michael Vetter
4f19ea2642 Add -t theme option
`profanity -t bios` loads the bios theme now.

Fix https://github.com/profanity-im/profanity/issues/1286
2020-03-24 23:00:39 +01:00
Michael Vetter
75cfe38808 Allow setting custom log file via -f FILENAME
`profanity -f TEST` will use `~/.local/share/profanity/logs/TEST.log` as
the log file.
2020-02-21 21:10:00 +01:00
Michael Vetter
be13e98fe7 Update my Copyright to 2020 2020-01-03 19:52:31 +01:00
Michael Vetter
46fd7150e5 Add vim modeline 2019-11-13 12:11:05 +01:00
Michael Vetter
10ca3e8c31 Possibility to specify alternative config file
Introduce `profanity -c` to specify an alternative config file.
2019-08-02 15:55:47 +02:00
Michael Vetter
199162b11a Add omemo_close function
We call omemo_init() when starting profanity and should have an
omemo_close() at exit.

For now we free the fingerprint autocompleter in there.

Fixes valgrind:
```
==13226== 24 bytes in 1 blocks are definitely lost in loss record 2,855
of 6,958
==13226==    at 0x483677F: malloc (in
/usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==13226==    by 0x48AD39: autocomplete_new (autocomplete.c:57)
==13226==    by 0x4AB89F: omemo_init (omemo.c:127)
==13226==    by 0x42C283: _init (profanity.c:206)
==13226==    by 0x42BFF3: prof_run (profanity.c:98)
==13226==    by 0x4B25E6: main (main.c:172)
```

Regards https://github.com/profanity-im/profanity/issues/1131
2019-07-04 10:30:56 +02:00
Michael Vetter
40b72ffe55 Add myself to copyright
Like discussed with James.
2019-06-17 10:44:08 +02:00
Paul Fariello
2602cbf785 Move OMEMO initialization to profanity intialization
Also store identity keys into account
2019-04-10 15:37:22 +02:00