Add log_database_switch_backend() that closes the current backend,
updates PREF_DBLOG preference, and reinitializes with the new backend
without requiring a reconnect or restart.
New command: /history switch sqlite|flatfile
- Validates connection state and backend name
- Skips if already using the requested backend
- Autocomplete support for the subcommand
DRAFT — not yet tested end-to-end with a live XMPP session.
New commands:
/history export [<jid>] — copy messages from SQLite to flat-file
/history import [<jid>] — copy messages from flat-file to SQLite
Both merge with existing data; duplicates are skipped using stanza-id
or a SHA-256 fallback key (timestamp + sender + body prefix).
Implementation (src/database_export.c):
- Export: paginate SQLite via get_previous_chat, read existing flatfile
for dedup, write merged result via ff_write_line + atomic rename
- Import: parse flatfile lines via ff_parse_line, build dedup set from
SQLite, insert new messages via add_incoming (preserves original
timestamps for both directions)
- List all contacts: db_sqlite_list_contacts() queries UNION of
DISTINCT from_jid/to_jid; flatfile enumerates flatlog directories
Wiring:
- database.h: declare export/import functions + db_sqlite_list_contacts
- database_sqlite.c: add db_sqlite_list_contacts()
- cmd_defs.c: add export/import to /history synopsis and args
- cmd_funcs.c: add export/import handlers in cmd_history()
- cmd_ac.c: add 'export' and 'import' to history_ac
- Makefile.am: add database_export.c to core_sources
- stub_database.c: add stubs for test linking
- profanity.1: document export/import in man page
All code guarded with #ifdef HAVE_SQLITE — builds cleanly without it.
Add pluggable storage backend abstraction (vtable) to the database layer,
allowing selection between SQLite (default) and a new flat-file backend
that stores messages as human-readable plain text files.
New files:
- database_sqlite.c: extracted SQLite backend from database.c
- database_flatfile.c: plain text backend with tolerant parser,
LMC correction chains, UTF-8/BOM/CRLF handling, integrity checks
Commands:
- /privacy logging flatfile — switch to flat-file backend
- /history verify [<jid>] — check integrity of stored history
Fixes:
- Add missing 'off' guard in flatfile backend
- Enable CHLOG/HISTORY prefs when switching to flatfile mode
Logs stored in ~/.local/share/profanity/flatlog/{account}/{contact}/{date}.log
Format: {ISO8601} [{type}|{enc}|id:{id}|corrects:{id}] {sender}: {message}
Updated: CHANGELOG, CONTRIBUTING.md, profrc.example, man page, cmd_defs,
Makefile.am, test stubs, functional test support (PROF_FLATFILE=1)
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
- Added null check for `jid` in `cmd_caps` to handle `jid_create` returning NULL.
- Crash occurred when processing malformed inputs like `@example.com` in `/caps`.
- Ensures robust handling of invalid JID strings in `WIN_CHAT` and `WIN_CONSOLE` cases.
Fixes#20
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.
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.
Instead of c&p'ing the same code again and again, put everything in a
struct and loop over it.
This also fixes `vcard` not being in included in `all`.
Fixes: f934c5b59f ("Add vCard support")
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
* use `calloc()` to allocate zero-initialized structs.
* order the allocation of members by their declaration.
* order the freeing of members in reverse order.
* move init of `silent` flag in plugin case.
* fix double free of `tmpname` in `aesgcm_file_get()`.
* make some functions static.
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
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>
In the documentation of the `muc_nick` function we can read:
> The nickname is owned by the chat room and should not be modified or freed
We should reflect that in the return type and `strdup` the value for the
plugin API.
Fixes: https://github.com/profanity-im/profanity/issues/2013
`/url save $someurl` will now download to
`~/.local/share/profanity/downloads/from_jid/date/filename` instead of
`~/.local/share/profanity/downloads`.
Like this the downloaded files should be better ordered.
This will only happen for MUC and 1:1 chat windows.
Private windows might have only a nick or jid. Lets not distinguish
between those two ways. And since the nick option is unreliable to be
the same person lets just put them in the general downloads folder.
As is done with downloads from all other windows as well.
I also had the idea to make this configurable but this suits my needs
and time limits right now.
When a user added an account, set it as autoconnect and then removed
that account. It still was set as the autoconnect account.
```
/account add test
/autoconnect set test
/account remove test
/save
/quit
Start profanity
```
Fix https://github.com/profanity-im/profanity/issues/1976
When users receive a message and a subscription request from a new
contact, and they use `/blocked report-abse JID` or `/blocked
report-spam JID` they most likely want the subscription request to
vanish as well.
According to mdosch Conversations is behaving like this too.
Fix: https://github.com/profanity-im/profanity/issues/1970
## Summary
Partial fix for https://github.com/profanity-im/profanity/issues/1939
> When doing the same in an unencrypted (no e2ee) chat there is no Downloading… message at all but the file is downloaded.
Download a file twice with `/url save`, the second download will not print download progress to the window.
The cause is `HTTPDownload`'s `silent` variable is not initialized; so, `silent` points to a second-hand stack memory address with old data. `silent` references data, so the `if` statement will fail in **src/tools/http_download.c:206** and download progress will not print to the window.
The fix is to initialize `silent` in both encrypted and unencrypted file download scenarios.
## Testing
Valgrind: Yes
- `/url save` without OMEMO
**SUCCESS**: Try three times with the same URL and download status will display every time.
- `/url save` with OMEMO
**SUCCESS**: Try three times with the same URL and download status will display every time.
- `/plugins install https://raw.githubusercontent.com/profanity-im/profanity-plugins/master/stable/sounds.py`
**SUCCESS**: Try once and download progress is hidden.
Use a singleton `Jid` inside the connection instead of always re-creating
a `Jid` from the same string.
Signed-off-by: Steffen Jaeckel <jaeckel-floss@eyet-services.de>
Return static tabmode as default,
separate previous change in `dynamic` mode.
Despite usefulness of the solution,
it was not approved to be a new default.
Vote (link below) amongst users to change default
has shown inconclusive result and it was not representative,
as it had low number of participants.
https://github.com/profanity-im/profanity/pull/1912#issuecomment-1816232546
`/redraw` command allows resolve problem for usual users,
as well as developers.
Incredibly useful when debugging with something that
can trash out the output, like GDB.
Not to mention many asynchronous commands that can break the UI
at any point.
On some commands execution (like `/privacy logging X`
where X is any symbol/group of symbols)
FALSE is being returned.
Which main cycle understands as a signal to exit profanity.
The mistake is common since returns are often used by
developers to communicate success status.
First reported by @doctor in the Profanity MUC,
as exit on `/logging group color` command.
`/executable vcard_photo test`
Printed
`Invalid usage, see '/help card_photo' for details.`
So it used the subcommand instead of the command and lost one of the
letters as well.
This mistake got introduced in 60c197487.
Where we added helper functions for the various `/executable` functions.
Discovered by @H3rnand3zzz with correct solution.
Fix https://github.com/profanity-im/profanity/issues/1921
Commit to allow unicode support in omemo/pgp/otr chars misses
adding support to set correction character.
1f8b1eb740
Further fixing commit also misses adding support to set the unicode character,
it only adds ability to display unicode correction character in the settings.
5cf6ee15cf6ee1bc6d0b99b01891bc455a657bf022a72b0
Before aliases used spaces in their name,
now the alias part is being read only before the first space,
thus allowing execution of complex command with aliases.
Example (with plugin):
`/alias add echo "/system exec echo"`
will allow execution of
`/echo test`
as opposed to prior state when the Profanity will
search for alias "echo tests" and output `Unknown command: /echo test`
Minor change: removed an example with invalid command (`/away`)
`/plugins reload non-existent-plugin` printed:
```
Failed to reload plugin: non-existent-plugin, `:^C
```
There were two mistakes:
error_message instead of error_message->str was passed to cons_show().
And in case of failing to unload the plugin due to not finding it in the
hash table it didn't print an error.
This bug was introduced in cc697de05.