mirror of
https://github.com/profanity-im/profanity.git
synced 2024-12-04 14:46:46 -05:00
Add optional pgp public key autoimport
Refactor `p_gpg_list_keys` Add `/pgp autoimport` command, it's not described in XEP-0027, but used in some clients, such as PSI, Pidgin. It will autoimport keys received with `/pgp sendpub`, in plain text as a message, or using features, provided in other clients. It doesn't autoassign them, but shows command to assign, letting user to decide. Improve documentation for some preexisting functions Add contact argument to `/pgp sendpub`
This commit is contained in:
parent
349e4cb322
commit
36784738fc
@ -238,6 +238,7 @@ static Autocomplete reconnect_ac;
|
||||
static Autocomplete pgp_ac;
|
||||
static Autocomplete pgp_log_ac;
|
||||
static Autocomplete pgp_sendfile_ac;
|
||||
static Autocomplete pgp_autoimport_ac;
|
||||
static Autocomplete ox_ac;
|
||||
static Autocomplete ox_log_ac;
|
||||
#endif
|
||||
@ -911,6 +912,7 @@ cmd_ac_init(void)
|
||||
autocomplete_add(pgp_ac, "char");
|
||||
autocomplete_add(pgp_ac, "sendfile");
|
||||
autocomplete_add(pgp_ac, "sendpub");
|
||||
autocomplete_add(pgp_ac, "autoimport");
|
||||
|
||||
pgp_log_ac = autocomplete_new();
|
||||
autocomplete_add(pgp_log_ac, "on");
|
||||
@ -921,6 +923,10 @@ cmd_ac_init(void)
|
||||
autocomplete_add(pgp_sendfile_ac, "on");
|
||||
autocomplete_add(pgp_sendfile_ac, "off");
|
||||
|
||||
pgp_autoimport_ac = autocomplete_new();
|
||||
autocomplete_add(pgp_autoimport_ac, "on");
|
||||
autocomplete_add(pgp_autoimport_ac, "off");
|
||||
|
||||
ox_ac = autocomplete_new();
|
||||
autocomplete_add(ox_ac, "keys");
|
||||
autocomplete_add(ox_ac, "contacts");
|
||||
@ -1675,6 +1681,7 @@ cmd_ac_reset(ProfWin* window)
|
||||
autocomplete_reset(pgp_ac);
|
||||
autocomplete_reset(pgp_log_ac);
|
||||
autocomplete_reset(pgp_sendfile_ac);
|
||||
autocomplete_reset(pgp_autoimport_ac);
|
||||
autocomplete_reset(ox_ac);
|
||||
autocomplete_reset(ox_log_ac);
|
||||
#endif
|
||||
@ -1857,6 +1864,7 @@ cmd_ac_uninit(void)
|
||||
autocomplete_free(pgp_ac);
|
||||
autocomplete_free(pgp_log_ac);
|
||||
autocomplete_free(pgp_sendfile_ac);
|
||||
autocomplete_free(pgp_autoimport_ac);
|
||||
autocomplete_free(ox_ac);
|
||||
autocomplete_free(ox_log_ac);
|
||||
#endif
|
||||
@ -2737,6 +2745,11 @@ _pgp_autocomplete(ProfWin* window, const char* const input, gboolean previous)
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
|
||||
found = autocomplete_param_with_func(input, "/pgp sendpub", roster_contact_autocomplete, previous, NULL);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
found = autocomplete_param_with_ac(input, "/pgp log", pgp_log_ac, TRUE, previous);
|
||||
@ -2749,6 +2762,11 @@ _pgp_autocomplete(ProfWin* window, const char* const input, gboolean previous)
|
||||
return found;
|
||||
}
|
||||
|
||||
found = autocomplete_param_with_ac(input, "/pgp autoimport", pgp_autoimport_ac, TRUE, previous);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
|
||||
gboolean result;
|
||||
auto_gcharv gchar** args = parse_args(input, 2, 3, &result);
|
||||
if ((strncmp(input, "/pgp", 4) == 0) && (result == TRUE)) {
|
||||
|
@ -1706,7 +1706,7 @@ static const struct cmd_t command_defs[] = {
|
||||
"/pgp log on|off|redact",
|
||||
"/pgp char <char>",
|
||||
"/pgp sendfile on|off",
|
||||
"/pgp sendpub")
|
||||
"/pgp sendpub [<contact>]")
|
||||
CMD_DESC(
|
||||
"Open PGP commands to manage keys, and perform PGP encryption during chat sessions. "
|
||||
"See the /account command to set your own PGP key.")
|
||||
@ -1721,7 +1721,8 @@ static const struct cmd_t command_defs[] = {
|
||||
{ "log redact", "Log PGP encrypted messages, but replace the contents with [redacted]. This is the default." },
|
||||
{ "char <char>", "Set the character to be displayed next to PGP encrypted messages." },
|
||||
{ "sendfile on|off", "Allow /sendfile to send unencrypted files while otherwise using PGP." },
|
||||
{ "sendpub", "Used in chat. Sends a message to the current recipient with your PGP public key." })
|
||||
{ "autoimport on|off", "Autoimport PGP keys from messages." },
|
||||
{ "sendpub [<contact>]", "Sends a message to the current recipient with your PGP public key, current contact will be used if not specified." })
|
||||
CMD_EXAMPLES(
|
||||
"/pgp log off",
|
||||
"/pgp setkey odin@valhalla.edda BA19CACE5A9592C5",
|
||||
|
@ -7361,7 +7361,9 @@ cmd_pgp(ProfWin* window, const char* const command, gchar** args)
|
||||
}
|
||||
cons_bad_cmd_usage(command);
|
||||
return TRUE;
|
||||
} else if (g_strcmp0(args[0], "log") == 0) {
|
||||
}
|
||||
|
||||
if (g_strcmp0(args[0], "log") == 0) {
|
||||
char* choice = args[1];
|
||||
if (g_strcmp0(choice, "on") == 0) {
|
||||
prefs_set_string(PREF_PGP_LOG, "on");
|
||||
@ -7384,6 +7386,11 @@ cmd_pgp(ProfWin* window, const char* const command, gchar** args)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (g_strcmp0(args[0], "autoimport") == 0) {
|
||||
_cmd_set_boolean_preference(args[1], "PGP keys autoimport from messages", PREF_PGP_PUBKEY_AUTOIMPORT);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (g_strcmp0(args[0], "keys") == 0) {
|
||||
GHashTable* keys = p_gpg_list_keys();
|
||||
if (!keys || g_hash_table_size(keys) == 0) {
|
||||
@ -7494,7 +7501,7 @@ cmd_pgp(ProfWin* window, const char* const command, gchar** args)
|
||||
}
|
||||
|
||||
if (window->type != WIN_CHAT && args[1] == NULL) {
|
||||
cons_show("You must be in a regular chat window to start PGP encryption.");
|
||||
cons_show("You must set recipient in an argument or be in a regular chat window to start PGP encryption.");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -7587,11 +7594,17 @@ cmd_pgp(ProfWin* window, const char* const command, gchar** args)
|
||||
}
|
||||
|
||||
if (g_strcmp0(args[0], "sendpub") == 0) {
|
||||
if (window->type != WIN_CHAT) {
|
||||
cons_show_error("Please, use this command only in chat windows.");
|
||||
jabber_conn_status_t conn_status = connection_get_status();
|
||||
if (conn_status != JABBER_CONNECTED) {
|
||||
cons_show("You must be connected to share your PGP public key.");
|
||||
return TRUE;
|
||||
}
|
||||
ProfChatWin* chatwin = (ProfChatWin*)window;
|
||||
|
||||
if (window->type != WIN_CHAT && args[1] == NULL) {
|
||||
cons_show("You must set recipient in an argument or use this command in a regular chat window to share your PGP key.");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ProfAccount* account = accounts_get_account(session_get_account_name());
|
||||
|
||||
if (account->pgp_keyid == NULL) {
|
||||
@ -7605,7 +7618,28 @@ cmd_pgp(ProfWin* window, const char* const command, gchar** args)
|
||||
account_free(account);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ProfChatWin* chatwin = NULL;
|
||||
|
||||
if (args[1]) {
|
||||
char* contact = args[1];
|
||||
char* barejid = roster_barejid_from_name(contact);
|
||||
if (barejid == NULL) {
|
||||
barejid = contact;
|
||||
}
|
||||
|
||||
chatwin = wins_get_chat(barejid);
|
||||
if (!chatwin) {
|
||||
chatwin = chatwin_new(barejid);
|
||||
}
|
||||
ui_focus_win((ProfWin*)chatwin);
|
||||
} else {
|
||||
chatwin = (ProfChatWin*)window;
|
||||
assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
|
||||
}
|
||||
|
||||
cl_ev_send_msg(chatwin, pubkey, NULL);
|
||||
win_update_entry_message((ProfWin*)chatwin, chatwin->last_msg_id, "[you shared your PGP key]");
|
||||
cons_show("PGP key has been shared with %s.", chatwin->barejid);
|
||||
account_free(account);
|
||||
return TRUE;
|
||||
|
@ -1863,6 +1863,7 @@ _get_group(preference_t pref)
|
||||
return PREF_GROUP_OTR;
|
||||
case PREF_PGP_LOG:
|
||||
case PREF_PGP_SENDFILE:
|
||||
case PREF_PGP_PUBKEY_AUTOIMPORT:
|
||||
return PREF_GROUP_PGP;
|
||||
case PREF_BOOKMARK_INVITE:
|
||||
case PREF_ROOM_LIST_CACHE:
|
||||
@ -2084,6 +2085,8 @@ _get_key(preference_t pref)
|
||||
return "log";
|
||||
case PREF_PGP_SENDFILE:
|
||||
return "sendfile";
|
||||
case PREF_PGP_PUBKEY_AUTOIMPORT:
|
||||
return "pgp.pubkey.autoimport";
|
||||
case PREF_TLS_CERTPATH:
|
||||
return "tls.certpath";
|
||||
case PREF_TLS_SHOW:
|
||||
@ -2215,6 +2218,7 @@ _get_default_boolean(preference_t pref)
|
||||
case PREF_STROPHE_SM_ENABLED:
|
||||
case PREF_STROPHE_SM_RESEND:
|
||||
return TRUE;
|
||||
case PREF_PGP_PUBKEY_AUTOIMPORT:
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -147,6 +147,7 @@ typedef enum {
|
||||
PREF_TITLEBAR_MUC_TITLE_NAME,
|
||||
PREF_PGP_LOG,
|
||||
PREF_PGP_SENDFILE,
|
||||
PREF_PGP_PUBKEY_AUTOIMPORT,
|
||||
PREF_TLS_CERTPATH,
|
||||
PREF_TLS_SHOW,
|
||||
PREF_LASTACTIVITY,
|
||||
|
204
src/pgp/gpg.c
204
src/pgp/gpg.c
@ -53,10 +53,12 @@
|
||||
#include "tools/autocomplete.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
#define PGP_SIGNATURE_HEADER "-----BEGIN PGP SIGNATURE-----"
|
||||
#define PGP_SIGNATURE_FOOTER "-----END PGP SIGNATURE-----"
|
||||
#define PGP_MESSAGE_HEADER "-----BEGIN PGP MESSAGE-----"
|
||||
#define PGP_MESSAGE_FOOTER "-----END PGP MESSAGE-----"
|
||||
#define PGP_SIGNATURE_HEADER "-----BEGIN PGP SIGNATURE-----"
|
||||
#define PGP_SIGNATURE_FOOTER "-----END PGP SIGNATURE-----"
|
||||
#define PGP_MESSAGE_HEADER "-----BEGIN PGP MESSAGE-----"
|
||||
#define PGP_MESSAGE_FOOTER "-----END PGP MESSAGE-----"
|
||||
#define PGP_PUBLIC_KEY_HEADER "-----BEGIN PGP PUBLIC KEY BLOCK-----"
|
||||
#define PGP_PUBLIC_KEY_FOOTER "-----END PGP PUBLIC KEY BLOCK-----"
|
||||
|
||||
static const char* libversion = NULL;
|
||||
static GHashTable* pubkeys;
|
||||
@ -73,6 +75,7 @@ static char* _remove_header_footer(char* str, const char* const footer);
|
||||
static char* _add_header_footer(const char* const str, const char* const header, const char* const footer);
|
||||
static char* _gpgme_data_to_char(gpgme_data_t data);
|
||||
static void _save_pubkeys(void);
|
||||
static ProfPGPKey* _gpgme_key_to_ProfPGPKey(gpgme_key_t key);
|
||||
|
||||
void
|
||||
_p_gpg_free_pubkeyid(ProfPGPPubKeyId* pubkeyid)
|
||||
@ -304,6 +307,21 @@ p_gpg_free_key(ProfPGPKey* key)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a list of GPG keys and create a hash table of ProfPGPKey objects.
|
||||
*
|
||||
* This function utilizes the GPGME library to retrieve both public and secret keys.
|
||||
* It iterates over the keys and their subkeys to populate a hash table with ProfPGPKey objects.
|
||||
* The key name is used as the key in the hash table, and the ProfPGPKey object is the corresponding value.
|
||||
*
|
||||
* @return A newly created GHashTable* containing ProfPGPKey objects, with the key name as the key.
|
||||
* Returns NULL if an error occurs during key retrieval or if memory allocation fails.
|
||||
*
|
||||
* @note The returned hash table should be released using p_gpg_free_keys()
|
||||
* when they are no longer needed to avoid memory leaks.
|
||||
*
|
||||
* @note This function may perform additional operations, such as autocomplete, related to the retrieved keys.
|
||||
*/
|
||||
GHashTable*
|
||||
p_gpg_list_keys(void)
|
||||
{
|
||||
@ -312,48 +330,23 @@ p_gpg_list_keys(void)
|
||||
|
||||
gpgme_ctx_t ctx;
|
||||
error = gpgme_new(&ctx);
|
||||
|
||||
if (error) {
|
||||
log_error("GPG: Could not list keys. %s %s", gpgme_strsource(error), gpgme_strerror(error));
|
||||
log_error("GPG: Could not create GPGME context. %s %s", gpgme_strsource(error), gpgme_strerror(error));
|
||||
g_hash_table_destroy(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
error = gpgme_op_keylist_start(ctx, NULL, 0);
|
||||
if (error == GPG_ERR_NO_ERROR) {
|
||||
gpgme_key_t key;
|
||||
|
||||
error = gpgme_op_keylist_next(ctx, &key);
|
||||
while (!error) {
|
||||
gpgme_subkey_t sub = key->subkeys;
|
||||
|
||||
ProfPGPKey* p_pgpkey = p_gpg_key_new();
|
||||
p_pgpkey->id = strdup(sub->keyid);
|
||||
p_pgpkey->name = strdup(key->uids->uid);
|
||||
p_pgpkey->fp = strdup(sub->fpr);
|
||||
if (sub->can_encrypt)
|
||||
p_pgpkey->encrypt = TRUE;
|
||||
if (sub->can_authenticate)
|
||||
p_pgpkey->authenticate = TRUE;
|
||||
if (sub->can_certify)
|
||||
p_pgpkey->certify = TRUE;
|
||||
if (sub->can_sign)
|
||||
p_pgpkey->sign = TRUE;
|
||||
|
||||
sub = sub->next;
|
||||
while (sub) {
|
||||
if (sub->can_encrypt)
|
||||
p_pgpkey->encrypt = TRUE;
|
||||
if (sub->can_authenticate)
|
||||
p_pgpkey->authenticate = TRUE;
|
||||
if (sub->can_certify)
|
||||
p_pgpkey->certify = TRUE;
|
||||
if (sub->can_sign)
|
||||
p_pgpkey->sign = TRUE;
|
||||
|
||||
sub = sub->next;
|
||||
ProfPGPKey* p_pgpkey = _gpgme_key_to_ProfPGPKey(key);
|
||||
if (p_pgpkey != NULL) {
|
||||
g_hash_table_insert(result, strdup(p_pgpkey->name), p_pgpkey);
|
||||
}
|
||||
|
||||
g_hash_table_insert(result, strdup(p_pgpkey->name), p_pgpkey);
|
||||
|
||||
gpgme_key_unref(key);
|
||||
error = gpgme_op_keylist_next(ctx, &key);
|
||||
}
|
||||
@ -382,6 +375,7 @@ p_gpg_list_keys(void)
|
||||
|
||||
gpgme_release(ctx);
|
||||
|
||||
// TODO: move autocomplete in other place
|
||||
autocomplete_clear(key_ac);
|
||||
GList* ids = g_hash_table_get_keys(result);
|
||||
GList* curr = ids;
|
||||
@ -761,10 +755,13 @@ p_gpg_format_fp_str(char* fp)
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Function to extract specific public key from PGP
|
||||
* \param keyid Key ID that will be used to search key in the current PGP context, if NULL returns null
|
||||
* \returns null-terminated char* string with the the public key in armored format, that must be free'd to avoid memory leaks
|
||||
* or NULL on error
|
||||
* Returns the public key data for the given key ID.
|
||||
*
|
||||
* @param keyid The key ID for which to retrieve the public key data.
|
||||
* If the key ID is empty or NULL, returns NULL.
|
||||
* @return The public key data as a null-terminated char* string allocated using malloc.
|
||||
* The returned string should be freed by the caller.
|
||||
* Returns NULL on error, and errors are written to the error log.
|
||||
*/
|
||||
char*
|
||||
p_gpg_get_pubkey(const char* keyid)
|
||||
@ -802,10 +799,135 @@ cleanup:
|
||||
return _gpgme_data_to_char(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the provided buffer has the format of an armored public key.
|
||||
*
|
||||
* This function only briefly checks for presence of armored header and footer.
|
||||
*
|
||||
* @param buffer The buffer containing the key data.
|
||||
* @return TRUE if the buffer has the expected header and footer of an armored public key, FALSE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
p_gpg_is_public_key_format(const char* buffer)
|
||||
{
|
||||
if (buffer == NULL || buffer[0] == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* headerPos = strstr(buffer, PGP_PUBLIC_KEY_HEADER);
|
||||
if (headerPos == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* footerPos = strstr(buffer, PGP_PUBLIC_KEY_FOOTER);
|
||||
|
||||
return (footerPos != NULL && footerPos > headerPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports a PGP public key(s) from a buffer.
|
||||
*
|
||||
* @param buffer The buffer containing the PGP key data.
|
||||
* @return A pointer to the first imported ProfPGPKey structure, or NULL if an error occurs.
|
||||
*
|
||||
* @note The caller is responsible for freeing the memory of the returned ProfPGPKey structure
|
||||
* by calling p_gpg_free_key() to avoid resource leaks.
|
||||
*/
|
||||
ProfPGPKey*
|
||||
p_gpg_import_pubkey(const char* buffer)
|
||||
{
|
||||
gpgme_ctx_t ctx;
|
||||
ProfPGPKey* result = NULL;
|
||||
gpgme_error_t error = gpgme_new(&ctx);
|
||||
if (error != GPG_ERR_NO_ERROR) {
|
||||
log_error("GPG: Error creating GPGME context");
|
||||
goto out;
|
||||
}
|
||||
|
||||
gpgme_data_t key_data;
|
||||
error = gpgme_data_new_from_mem(&key_data, buffer, strlen(buffer), 1);
|
||||
if (error != GPG_ERR_NO_ERROR) {
|
||||
log_error("GPG: Error creating GPGME data from buffer");
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = gpgme_op_import(ctx, key_data);
|
||||
|
||||
gpgme_data_release(key_data);
|
||||
|
||||
if (error != GPG_ERR_NO_ERROR) {
|
||||
log_error("GPG: Error importing key data");
|
||||
goto out;
|
||||
}
|
||||
|
||||
gpgme_import_result_t import_result = gpgme_op_import_result(ctx);
|
||||
gpgme_import_status_t status = import_result->imports;
|
||||
gboolean is_valid = (status && status->result == GPG_ERR_NO_ERROR);
|
||||
|
||||
if (!is_valid) {
|
||||
log_error("GPG: Error importing PGP key (%s).", status ? gpgme_strerror(status->result) : "Invalid import status.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
gpgme_key_t key = NULL;
|
||||
error = gpgme_get_key(ctx, status->fpr, &key, 0);
|
||||
if (error != GPG_ERR_NO_ERROR) {
|
||||
log_error("GPG: Unable to find imported PGP key (%s).", gpgme_strerror(error));
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = _gpgme_key_to_ProfPGPKey(key);
|
||||
gpgme_key_release(key);
|
||||
|
||||
out:
|
||||
gpgme_release(ctx);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a GPGME key struct to a ProfPGPKey struct.
|
||||
*
|
||||
* @param key The GPGME key struct to convert.
|
||||
* @return A newly allocated ProfPGPKey struct populated with the converted data,
|
||||
* or NULL if an error occurs.
|
||||
*
|
||||
* @note The caller is responsible for freeing the memory of the returned ProfPGPKey structure
|
||||
* by calling p_gpg_free_key() to avoid resource leaks.
|
||||
*/
|
||||
static ProfPGPKey*
|
||||
_gpgme_key_to_ProfPGPKey(gpgme_key_t key)
|
||||
{
|
||||
if (key == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ProfPGPKey* p_pgpkey = p_gpg_key_new();
|
||||
gpgme_subkey_t sub = key->subkeys;
|
||||
p_pgpkey->id = strdup(sub->keyid);
|
||||
p_pgpkey->name = strdup(key->uids->uid);
|
||||
p_pgpkey->fp = strdup(sub->fpr);
|
||||
|
||||
while (sub) {
|
||||
if (sub->can_encrypt)
|
||||
p_pgpkey->encrypt = TRUE;
|
||||
if (sub->can_authenticate)
|
||||
p_pgpkey->authenticate = TRUE;
|
||||
if (sub->can_certify)
|
||||
p_pgpkey->certify = TRUE;
|
||||
if (sub->can_sign)
|
||||
p_pgpkey->sign = TRUE;
|
||||
|
||||
sub = sub->next;
|
||||
}
|
||||
return p_pgpkey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a gpgme_data_t object to a null-terminated char* string.
|
||||
* The returned string is allocated using malloc and should be freed by the caller.
|
||||
* If an error occurs or the data is empty, NULL is returned and errors written to the error log.
|
||||
*
|
||||
* @param data The gpgme_data_t object to convert.
|
||||
* @return The converted string allocated using malloc, which should be freed by the caller.
|
||||
* If an error occurs or the data is empty, NULL is returned and errors are written to the error log.
|
||||
*/
|
||||
static char*
|
||||
_gpgme_data_to_char(gpgme_data_t data)
|
||||
|
@ -74,6 +74,8 @@ char* p_gpg_autocomplete_key(const char* const search_str, gboolean previous, vo
|
||||
void p_gpg_autocomplete_key_reset(void);
|
||||
char* p_gpg_format_fp_str(char* fp);
|
||||
char* p_gpg_get_pubkey(const char* const keyid);
|
||||
gboolean p_gpg_is_public_key_format(const char* buffer);
|
||||
ProfPGPKey* p_gpg_import_pubkey(const char* buffer);
|
||||
|
||||
ProfPGPKey* p_gpg_key_new(void);
|
||||
void p_gpg_free_key(ProfPGPKey* key);
|
||||
|
@ -53,6 +53,9 @@
|
||||
#ifdef HAVE_LIBOTR
|
||||
#include "otr/otr.h"
|
||||
#endif
|
||||
#ifdef HAVE_LIBGPGME
|
||||
#include "pgp/gpg.h"
|
||||
#endif
|
||||
#ifdef HAVE_OMEMO
|
||||
#include "omemo/omemo.h"
|
||||
#endif
|
||||
@ -320,6 +323,7 @@ chatwin_incoming_msg(ProfChatWin* chatwin, ProfMessage* message, gboolean win_cr
|
||||
char* old_plain = message->plain;
|
||||
|
||||
message->plain = plugins_pre_chat_message_display(message->from_jid->barejid, message->from_jid->resourcepart, message->plain);
|
||||
gboolean show_message = true;
|
||||
|
||||
ProfWin* window = (ProfWin*)chatwin;
|
||||
int num = wins_get_num(window);
|
||||
@ -333,12 +337,29 @@ chatwin_incoming_msg(ProfChatWin* chatwin, ProfMessage* message, gboolean win_cr
|
||||
}
|
||||
free(mybarejid);
|
||||
|
||||
#ifdef HAVE_LIBGPGME
|
||||
if (prefs_get_boolean(PREF_PGP_PUBKEY_AUTOIMPORT)) {
|
||||
if (p_gpg_is_public_key_format(message->plain)) {
|
||||
ProfPGPKey* key = p_gpg_import_pubkey(message->plain);
|
||||
if (key != NULL) {
|
||||
show_message = false;
|
||||
win_println(window, THEME_DEFAULT, "-", "Received and imported PGP key %s: \"%s\". To assign it to the correspondent using /pgp setkey %s %s", key->fp, key->name, display_name, key->id);
|
||||
p_gpg_free_key(key);
|
||||
} else {
|
||||
win_println(window, THEME_DEFAULT, "-", "Received PGP key, but couldn't import PGP key above.");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
gboolean is_current = wins_is_current(window);
|
||||
gboolean notify = prefs_do_chat_notify(is_current) && !message->is_mam;
|
||||
|
||||
// currently viewing chat window with sender
|
||||
if (wins_is_current(window)) {
|
||||
win_print_incoming(window, display_name, message);
|
||||
if (show_message) {
|
||||
win_print_incoming(window, display_name, message);
|
||||
}
|
||||
title_bar_set_typing(FALSE);
|
||||
status_bar_active(num, WIN_CHAT, chatwin->barejid);
|
||||
|
||||
@ -377,7 +398,9 @@ chatwin_incoming_msg(ProfChatWin* chatwin, ProfMessage* message, gboolean win_cr
|
||||
}
|
||||
|
||||
win_insert_last_read_position_marker((ProfWin*)chatwin, chatwin->barejid);
|
||||
win_print_incoming(window, display_name, message);
|
||||
if (show_message) {
|
||||
win_print_incoming(window, display_name, message);
|
||||
}
|
||||
}
|
||||
|
||||
if (!message->is_mam) {
|
||||
|
@ -103,4 +103,16 @@ char*
|
||||
p_gpg_get_pubkey(const char* const keyid)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
p_gpg_is_public_key_format(const char* buffer)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ProfPGPKey*
|
||||
p_gpg_import_pubkey(const char* buffer)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ cmd_pgp_start_shows_message_when_no_arg_in_wintype(win_type_t wintype)
|
||||
|
||||
will_return(connection_get_status, JABBER_CONNECTED);
|
||||
|
||||
expect_cons_show("You must be in a regular chat window to start PGP encryption.");
|
||||
expect_cons_show("You must set recipient in an argument or be in a regular chat window to start PGP encryption.");
|
||||
|
||||
gboolean result = cmd_pgp(&window, CMD_PGP, args);
|
||||
assert_true(result);
|
||||
|
Loading…
Reference in New Issue
Block a user