1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-09-22 19:45:54 -04:00

Merge branch 'master' into plugins

Conflicts:
	src/config/preferences.h
	src/event/client_events.c
	src/event/server_events.c
	src/ui/core.c
This commit is contained in:
James Booth 2015-08-26 01:45:19 +01:00
commit ade1070c8e
19 changed files with 374 additions and 121 deletions

View File

@ -60,6 +60,9 @@
#ifdef PROF_HAVE_LIBOTR
#include "otr/otr.h"
#endif
#ifdef PROF_HAVE_LIBGPGME
#include "pgp/gpg.h"
#endif
#include "profanity.h"
#include "tools/autocomplete.h"
#include "tools/parser.h"
@ -1143,38 +1146,43 @@ static struct cmd_t command_defs[] =
{ "/pgp",
cmd_pgp, parse_args, 1, 3, NULL,
CMD_TAGS(
CMD_TAG_CHAT)
CMD_TAG_CHAT,
CMD_TAG_UI)
CMD_SYN(
"/pgp libver",
"/pgp keys",
"/pgp fps",
"/pgp contacts",
"/pgp setkey <contact> <keyid>",
"/pgp start [<contact>]",
"/pgp end",
"/pgp log on|off|redact")
"/pgp log on|off|redact",
"/pgp char <char>")
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.")
CMD_ARGS(
{ "libver", "Show which version of the libgpgme library is being used." },
{ "keys", "List all keys." },
{ "fps", "Show known fingerprints." },
{ "setkey <contact> <keyid>", "Manually associate a key ID with a JID." },
{ "keys", "List all keys known to the system." },
{ "contacts", "Show contacts with assigned public keys." },
{ "setkey <contact> <keyid>", "Manually associate a contact with a public key." },
{ "start [<contact>]", "Start PGP encrypted chat, current contact will be used if not specified." },
{ "end", "End PGP encrypted chat with the current recipient." },
{ "log on|off", "Enable or disable plaintext logging of PGP encrypted messages." },
{ "log redact", "Log PGP encrypted messages, but replace the contents with [redacted]. This is the default." })
{ "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." })
CMD_EXAMPLES(
"/pgp log off",
"/pgp setkey buddy@buddychat.org BA19CACE5A9592C5",
"/pgp start buddy@buddychat.org",
"/pgp end")
"/pgp end",
"/pgp char P")
},
{ "/otr",
cmd_otr, parse_args, 1, 3, NULL,
CMD_TAGS(
CMD_TAG_CHAT)
CMD_TAG_CHAT,
CMD_TAG_UI)
CMD_SYN(
"/otr libver",
"/otr gen",
@ -1186,7 +1194,8 @@ static struct cmd_t command_defs[] =
"/otr question <question> <answer>",
"/otr answer <answer>",
"/otr policy manual|opportunistic|always",
"/otr log on|off|redact")
"/otr log on|off|redact",
"/otr char <char>")
CMD_DESC(
"Off The Record (OTR) commands to manage keys, and perform OTR encryption during chat sessions.")
CMD_ARGS(
@ -1204,7 +1213,8 @@ static struct cmd_t command_defs[] =
{ "policy opportunistic", "Set the global OTR policy to opportunistic, and OTR sessions will be attempted upon starting a conversation." },
{ "policy always", "Set the global OTR policy to always, an error will be displayed if an OTR session cannot be initiated upon starting a conversation." },
{ "log on|off", "Enable or disable plaintext logging of OTR encrypted messages." },
{ "log redact", "Log OTR encrypted messages, but replace the contents with [redacted]. This is the default." })
{ "log redact", "Log OTR encrypted messages, but replace the contents with [redacted]. This is the default." },
{ "char <char>", "Set the character to be displayed next to OTR encrypted messages." })
CMD_EXAMPLES(
"/otr log off",
"/otr policy manual",
@ -1213,7 +1223,8 @@ static struct cmd_t command_defs[] =
"/otr myfp",
"/otr theirfp",
"/otr question \"What is the name of my rabbit?\" fiffi",
"/otr end")
"/otr end",
"/otr char *")
},
{ "/outtype",
@ -1958,6 +1969,7 @@ cmd_init(void)
autocomplete_add(otr_ac, "policy");
autocomplete_add(otr_ac, "question");
autocomplete_add(otr_ac, "answer");
autocomplete_add(otr_ac, "char");
otr_log_ac = autocomplete_new();
autocomplete_add(otr_log_ac, "on");
@ -2065,12 +2077,13 @@ cmd_init(void)
pgp_ac = autocomplete_new();
autocomplete_add(pgp_ac, "keys");
autocomplete_add(pgp_ac, "fps");
autocomplete_add(pgp_ac, "contacts");
autocomplete_add(pgp_ac, "setkey");
autocomplete_add(pgp_ac, "libver");
autocomplete_add(pgp_ac, "start");
autocomplete_add(pgp_ac, "end");
autocomplete_add(pgp_ac, "log");
autocomplete_add(pgp_ac, "char");
pgp_log_ac = autocomplete_new();
autocomplete_add(pgp_log_ac, "on");
@ -2254,6 +2267,9 @@ cmd_reset_autocomplete(ProfWin *window)
accounts_reset_enabled_search();
prefs_reset_boolean_choice();
presence_reset_sub_request_search();
#ifdef PROF_HAVE_LIBGPGME
p_gpg_autocomplete_key_reset();
#endif
autocomplete_reset(help_ac);
autocomplete_reset(help_commands_ac);
autocomplete_reset(notify_ac);
@ -3005,6 +3021,26 @@ _pgp_autocomplete(ProfWin *window, const char * const input)
return found;
}
#ifdef PROF_HAVE_LIBGPGME
gboolean result;
gchar **args = parse_args(input, 2, 3, &result);
if ((strncmp(input, "/pgp", 4) == 0) && (result == TRUE)) {
GString *beginning = g_string_new("/pgp ");
g_string_append(beginning, args[0]);
if (args[1]) {
g_string_append(beginning, " ");
g_string_append(beginning, args[1]);
}
found = autocomplete_param_with_func(input, beginning->str, p_gpg_autocomplete_key);
g_string_free(beginning, TRUE);
if (found) {
g_strfreev(args);
return found;
}
}
g_strfreev(args);
#endif
found = autocomplete_param_with_func(input, "/pgp setkey", roster_barejid_autocomplete);
if (found) {
return found;
@ -3605,6 +3641,17 @@ _account_autocomplete(ProfWin *window, const char * const input)
g_strfreev(args);
return found;
}
#ifdef PROF_HAVE_LIBGPGME
} else if ((g_strv_length(args) > 3) && (g_strcmp0(args[2], "pgpkeyid")) == 0) {
g_string_append(beginning, " ");
g_string_append(beginning, args[2]);
found = autocomplete_param_with_func(input, beginning->str, p_gpg_autocomplete_key);
g_string_free(beginning, TRUE);
if (found) {
g_strfreev(args);
return found;
}
#endif
} else {
found = autocomplete_param_with_ac(input, beginning->str, account_set_ac, TRUE);
g_string_free(beginning, TRUE);

View File

@ -4220,7 +4220,17 @@ cmd_pgp(ProfWin *window, const char * const command, gchar **args)
return TRUE;
}
if (g_strcmp0(args[0], "log") == 0) {
if (strcmp(args[0], "char") == 0) {
if (args[1] == NULL) {
cons_bad_cmd_usage(command);
} else if (strlen(args[1]) != 1) {
cons_bad_cmd_usage(command);
} else {
prefs_set_pgp_char(args[1][0]);
cons_show("PGP char set to %c.", args[1][0]);
}
return TRUE;
} else if (g_strcmp0(args[0], "log") == 0) {
char *choice = args[1];
if (g_strcmp0(choice, "on") == 0) {
prefs_set_string(PREF_PGP_LOG, "on");
@ -4299,25 +4309,29 @@ cmd_pgp(ProfWin *window, const char * const command, gchar **args)
return TRUE;
}
if (g_strcmp0(args[0], "fps") == 0) {
if (g_strcmp0(args[0], "contacts") == 0) {
jabber_conn_status_t conn_status = jabber_get_connection_status();
if (conn_status != JABBER_CONNECTED) {
cons_show("You are not currently connected.");
return TRUE;
}
GHashTable *fingerprints = p_gpg_fingerprints();
GList *jids = g_hash_table_get_keys(fingerprints);
GHashTable *pubkeys = p_gpg_pubkeys();
GList *jids = g_hash_table_get_keys(pubkeys);
if (!jids) {
cons_show("No PGP fingerprints available.");
cons_show("No contacts found with PGP public keys assigned.");
return TRUE;
}
cons_show("Known PGP fingerprints:");
cons_show("Assigned PGP public keys:");
GList *curr = jids;
while (curr) {
char *jid = curr->data;
char *fingerprint = g_hash_table_lookup(fingerprints, jid);
cons_show(" %s: %s", jid, fingerprint);
ProfPGPPubKeyId *pubkeyid = g_hash_table_lookup(pubkeys, jid);
if (pubkeyid->received) {
cons_show(" %s: %s (received)", jid, pubkeyid->id);
} else {
cons_show(" %s: %s (stored)", jid, pubkeyid->id);
}
curr = g_list_next(curr);
}
g_list_free(jids);
@ -4438,7 +4452,17 @@ cmd_otr(ProfWin *window, const char * const command, gchar **args)
return TRUE;
}
if (strcmp(args[0], "log") == 0) {
if (strcmp(args[0], "char") == 0) {
if (args[1] == NULL) {
cons_bad_cmd_usage(command);
} else if (strlen(args[1]) != 1) {
cons_bad_cmd_usage(command);
} else {
prefs_set_otr_char(args[1][0]);
cons_show("OTR char set to %c.", args[1][0]);
}
return TRUE;
} else if (strcmp(args[0], "log") == 0) {
char *choice = args[1];
if (g_strcmp0(choice, "on") == 0) {
prefs_set_string(PREF_OTR_LOG, "on");

View File

@ -389,6 +389,60 @@ prefs_get_roster_size(void)
}
}
char
prefs_get_otr_char(void)
{
char result = '~';
char *resultstr = g_key_file_get_string(prefs, PREF_GROUP_OTR, "otr.char", NULL);
if (!resultstr) {
result = '~';
} else {
result = resultstr[0];
}
free(resultstr);
return result;
}
void
prefs_set_otr_char(char ch)
{
char str[2];
str[0] = ch;
str[1] = '\0';
g_key_file_set_string(prefs, PREF_GROUP_OTR, "otr.char", str);
_save_prefs();
}
char
prefs_get_pgp_char(void)
{
char result = '~';
char *resultstr = g_key_file_get_string(prefs, PREF_GROUP_PGP, "pgp.char", NULL);
if (!resultstr) {
result = '~';
} else {
result = resultstr[0];
}
free(resultstr);
return result;
}
void
prefs_set_pgp_char(char ch)
{
char str[2];
str[0] = ch;
str[1] = '\0';
g_key_file_set_string(prefs, PREF_GROUP_PGP, "pgp.char", str);
_save_prefs();
}
gboolean
prefs_add_alias(const char * const name, const char * const value)
{

View File

@ -145,6 +145,11 @@ void prefs_set_autoaway_time(gint value);
gchar** prefs_get_plugins(void);
char prefs_get_otr_char(void);
void prefs_set_otr_char(char ch);
char prefs_get_pgp_char(void);
void prefs_set_pgp_char(char ch);
void prefs_add_login(const char *jid);
gboolean prefs_add_alias(const char * const name, const char * const value);

View File

@ -465,6 +465,21 @@ _load_preferences(void)
_set_boolean_preference("intype", PREF_INTYPE);
_set_boolean_preference("enc.warn", PREF_ENC_WARN);
if (g_key_file_has_key(theme, "ui", "otr.char", NULL)) {
gchar *ch = g_key_file_get_string(theme, "ui", "otr.char", NULL);
if (ch && strlen(ch) > 0) {
prefs_set_otr_char(ch[0]);
g_free(ch);
}
}
if (g_key_file_has_key(theme, "ui", "pgp.char", NULL)) {
gchar *ch = g_key_file_get_string(theme, "ui", "pgp.char", NULL);
if (ch && strlen(ch) > 0) {
prefs_set_pgp_char(ch[0]);
g_free(ch);
}
}
}
static gchar *

View File

@ -99,13 +99,13 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char * const msg)
if (!handled) {
char *id = message_send_chat(chatwin->barejid, plugin_msg);
chat_log_msg_out(chatwin->barejid, plugin_msg);
ui_outgoing_chat_msg(chatwin, plugin_msg, id);
ui_outgoing_chat_msg(chatwin, plugin_msg, id, PROF_ENC_NONE);
free(id);
}
} else { // enc_mode = PROF_ENC_PGP
char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg);
chat_log_pgp_msg_out(chatwin->barejid, plugin_msg);
ui_outgoing_chat_msg(chatwin, plugin_msg, id);
ui_outgoing_chat_msg(chatwin, plugin_msg, id, PROF_ENC_PGP);
free(id);
}
return;
@ -119,7 +119,7 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char * const msg)
if (!handled) {
char *id = message_send_chat(chatwin->barejid, plugin_msg);
chat_log_msg_out(chatwin->barejid, plugin_msg);
ui_outgoing_chat_msg(chatwin, plugin_msg, id);
ui_outgoing_chat_msg(chatwin, plugin_msg, id, PROF_ENC_NONE);
free(id);
}
return;
@ -133,12 +133,12 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char * const msg)
if (enc_mode == PROF_ENC_NONE) {
char *id = message_send_chat(chatwin->barejid, plugin_msg);
chat_log_msg_out(chatwin->barejid, plugin_msg);
ui_outgoing_chat_msg(chatwin, plugin_msg, id);
ui_outgoing_chat_msg(chatwin, plugin_msg, id, PROF_ENC_NONE);
free(id);
} else if (enc_mode == PROF_ENC_PGP) {
char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg);
chat_log_pgp_msg_out(chatwin->barejid, plugin_msg);
ui_outgoing_chat_msg(chatwin, plugin_msg, id);
ui_outgoing_chat_msg(chatwin, plugin_msg, id, PROF_ENC_PGP);
free(id);
}
return;
@ -150,7 +150,7 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char * const msg)
#ifndef PROF_HAVE_LIBGPGME
char *id = message_send_chat(chatwin->barejid, plugin_msg);
chat_log_msg_out(chatwin->barejid, plugin_msg);
ui_outgoing_chat_msg(chatwin, plugin_msg, id);
ui_outgoing_chat_msg(chatwin, plugin_msg, id, PROF_ENC_NONE);
free(id);
return;
#endif

View File

@ -101,7 +101,7 @@ sv_ev_lost_connection(void)
muc_invites_clear();
chat_sessions_clear();
ui_disconnected();
#ifdef HAVE_LIBGPGME
#ifdef PROF_HAVE_LIBGPGME
p_gpg_on_disconnect();
#endif
}
@ -197,7 +197,7 @@ sv_ev_incoming_carbon(char *barejid, char *resource, char *message)
new_win = TRUE;
}
ui_incoming_msg(chatwin, resource, message, NULL, new_win);
ui_incoming_msg(chatwin, resource, message, NULL, new_win, PROF_ENC_NONE);
chat_log_msg_in(barejid, message);
}
@ -225,12 +225,12 @@ sv_ev_incoming_message(char *barejid, char *resource, char *message, char *enc_m
if (enc_mode == PROF_ENC_NONE) {
win_println((ProfWin*)chatwin, 0, "PGP encryption enabled.");
}
ui_incoming_msg(chatwin, resource, decrypted, NULL, new_win);
ui_incoming_msg(chatwin, resource, decrypted, NULL, new_win, PROF_ENC_PGP);
chat_log_pgp_msg_in(barejid, decrypted);
chatwin->enc_mode = PROF_ENC_PGP;
p_gpg_free_decrypted(decrypted);
} else {
ui_incoming_msg(chatwin, resource, message, NULL, new_win);
ui_incoming_msg(chatwin, resource, message, NULL, new_win, PROF_ENC_NONE);
chat_log_msg_in(barejid, message);
chatwin->enc_mode = PROF_ENC_NONE;
}
@ -238,14 +238,18 @@ sv_ev_incoming_message(char *barejid, char *resource, char *message, char *enc_m
} else {
if (enc_mode == PROF_ENC_PGP) {
win_println((ProfWin*)chatwin, 0, "PGP encryption disabled.");
ui_incoming_msg(chatwin, resource, message, NULL, new_win);
ui_incoming_msg(chatwin, resource, message, NULL, new_win, PROF_ENC_NONE);
chat_log_msg_in(barejid, message);
chatwin->enc_mode = PROF_ENC_NONE;
} else {
gboolean decrypted = FALSE;
char *otr_res = otr_on_message_recv(barejid, resource, message, &decrypted);
if (otr_res) {
ui_incoming_msg(chatwin, resource, otr_res, NULL, new_win);
if (decrypted && g_strrstr(message, otr_res) == NULL) {
ui_incoming_msg(chatwin, resource, otr_res, NULL, new_win, PROF_ENC_OTR);
} else {
ui_incoming_msg(chatwin, resource, otr_res, NULL, new_win, PROF_ENC_NONE);
}
chat_log_otr_msg_in(barejid, otr_res, decrypted);
otr_free_message(otr_res);
}
@ -261,7 +265,11 @@ sv_ev_incoming_message(char *barejid, char *resource, char *message, char *enc_m
gboolean decrypted = FALSE;
char *otr_res = otr_on_message_recv(barejid, resource, message, &decrypted);
if (otr_res) {
ui_incoming_msg(chatwin, resource, otr_res, NULL, new_win);
if (decrypted && g_strrstr(message, otr_res) == NULL) {
ui_incoming_msg(chatwin, resource, otr_res, NULL, new_win, PROF_ENC_OTR);
} else {
ui_incoming_msg(chatwin, resource, otr_res, NULL, new_win, PROF_ENC_NONE);
}
chat_log_otr_msg_in(barejid, otr_res, decrypted);
otr_free_message(otr_res);
}
@ -275,17 +283,17 @@ sv_ev_incoming_message(char *barejid, char *resource, char *message, char *enc_m
if (enc_message) {
char *decrypted = p_gpg_decrypt(enc_message);
if (decrypted) {
ui_incoming_msg(chatwin, resource, decrypted, NULL, new_win);
ui_incoming_msg(chatwin, resource, decrypted, NULL, new_win, PROF_ENC_PGP);
chat_log_pgp_msg_in(barejid, decrypted);
chatwin->enc_mode = PROF_ENC_PGP;
p_gpg_free_decrypted(decrypted);
} else {
ui_incoming_msg(chatwin, resource, message, NULL, new_win);
ui_incoming_msg(chatwin, resource, message, NULL, new_win, PROF_ENC_NONE);
chat_log_msg_in(barejid, message);
chatwin->enc_mode = PROF_ENC_NONE;
}
} else {
ui_incoming_msg(chatwin, resource, message, NULL, new_win);
ui_incoming_msg(chatwin, resource, message, NULL, new_win, PROF_ENC_NONE);
chat_log_msg_in(barejid, message);
chatwin->enc_mode = PROF_ENC_NONE;
}
@ -296,7 +304,7 @@ sv_ev_incoming_message(char *barejid, char *resource, char *message, char *enc_m
// OTR unsupported, PGP unsupported
#ifndef PROF_HAVE_LIBOTR
#ifndef PROF_HAVE_LIBGPGME
ui_incoming_msg(chatwin, resource, message, NULL, new_win);
ui_incoming_msg(chatwin, resource, message, NULL, new_win, PROF_ENC_NONE);
chat_log_msg_in(barejid, message);
chatwin->enc_mode = PROF_ENC_NONE;
return;
@ -325,7 +333,7 @@ sv_ev_delayed_message(char *barejid, char *message, GDateTime *timestamp)
new_win = TRUE;
}
ui_incoming_msg(chatwin, NULL, message, timestamp, new_win);
ui_incoming_msg(chatwin, NULL, message, timestamp, new_win, PROF_ENC_NONE);
chat_log_msg_in_delayed(barejid, message, timestamp);
}

View File

@ -325,7 +325,7 @@ otr_on_message_send(ProfChatWin *chatwin, const char * const message)
if (encrypted) {
id = message_send_chat_otr(chatwin->barejid, encrypted);
chat_log_otr_msg_out(chatwin->barejid, message);
ui_outgoing_chat_msg(chatwin, message, id);
ui_outgoing_chat_msg(chatwin, message, id, PROF_ENC_OTR);
otr_free_message(encrypted);
free(id);
return TRUE;
@ -345,7 +345,7 @@ otr_on_message_send(ProfChatWin *chatwin, const char * const message)
if (policy == PROF_OTRPOLICY_OPPORTUNISTIC) {
char *otr_tagged_msg = otr_tag_message(message);
id = message_send_chat_otr(chatwin->barejid, otr_tagged_msg);
ui_outgoing_chat_msg(chatwin, message, id);
ui_outgoing_chat_msg(chatwin, message, id, PROF_ENC_NONE);
chat_log_msg_out(chatwin->barejid, message);
free(otr_tagged_msg);
free(id);

View File

@ -47,6 +47,7 @@
#include "pgp/gpg.h"
#include "log.h"
#include "common.h"
#include "tools/autocomplete.h"
#define PGP_SIGNATURE_HEADER "-----BEGIN PGP SIGNATURE-----"
#define PGP_SIGNATURE_FOOTER "-----END PGP SIGNATURE-----"
@ -54,14 +55,25 @@
#define PGP_MESSAGE_FOOTER "-----END PGP MESSAGE-----"
static const char *libversion;
static GHashTable *fingerprints;
static GHashTable *pubkeys;
static gchar *fpsloc;
static GKeyFile *fpskeyfile;
static gchar *pubsloc;
static GKeyFile *pubkeyfile;
static Autocomplete key_ac;
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 void _save_fps(void);
static void _save_pubkeys(void);
void
_p_gpg_free_pubkeyid(ProfPGPPubKeyId *pubkeyid)
{
if (pubkeyid) {
free(pubkeyid->id);
}
free(pubkeyid);
}
void
p_gpg_init(void)
@ -70,65 +82,72 @@ p_gpg_init(void)
log_debug("GPG: Found gpgme version: %s", libversion);
gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
fingerprints = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
pubkeys = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)_p_gpg_free_pubkeyid);
key_ac = autocomplete_new();
GHashTable *keys = p_gpg_list_keys();
p_gpg_free_keys(keys);
}
void
p_gpg_close(void)
{
if (fingerprints) {
g_hash_table_destroy(fingerprints);
fingerprints = NULL;
if (pubkeys) {
g_hash_table_destroy(pubkeys);
pubkeys = NULL;
}
if (fpskeyfile) {
g_key_file_free(fpskeyfile);
fpskeyfile = NULL;
if (pubkeyfile) {
g_key_file_free(pubkeyfile);
pubkeyfile = NULL;
}
free(fpsloc);
fpsloc = NULL;
free(pubsloc);
pubsloc = NULL;
autocomplete_free(key_ac);
key_ac = NULL;
}
void
p_gpg_on_connect(const char * const barejid)
{
gchar *data_home = xdg_get_data_home();
GString *fpsfile = g_string_new(data_home);
GString *pubsfile = g_string_new(data_home);
free(data_home);
gchar *account_dir = str_replace(barejid, "@", "_at_");
g_string_append(fpsfile, "/profanity/pgp/");
g_string_append(fpsfile, account_dir);
g_string_append(pubsfile, "/profanity/pgp/");
g_string_append(pubsfile, account_dir);
free(account_dir);
// mkdir if doesn't exist for account
errno = 0;
int res = g_mkdir_with_parents(fpsfile->str, S_IRWXU);
int res = g_mkdir_with_parents(pubsfile->str, S_IRWXU);
if (res == -1) {
char *errmsg = strerror(errno);
if (errmsg) {
log_error("Error creating directory: %s, %s", fpsfile->str, errmsg);
log_error("Error creating directory: %s, %s", pubsfile->str, errmsg);
} else {
log_error("Error creating directory: %s", fpsfile->str);
log_error("Error creating directory: %s", pubsfile->str);
}
}
// create or read fingerprints keyfile
g_string_append(fpsfile, "/fingerprints");
fpsloc = fpsfile->str;
g_string_free(fpsfile, FALSE);
// create or read publickeys
g_string_append(pubsfile, "/pubkeys");
pubsloc = pubsfile->str;
g_string_free(pubsfile, FALSE);
if (g_file_test(fpsloc, G_FILE_TEST_EXISTS)) {
g_chmod(fpsloc, S_IRUSR | S_IWUSR);
if (g_file_test(pubsloc, G_FILE_TEST_EXISTS)) {
g_chmod(pubsloc, S_IRUSR | S_IWUSR);
}
fpskeyfile = g_key_file_new();
g_key_file_load_from_file(fpskeyfile, fpsloc, G_KEY_FILE_KEEP_COMMENTS, NULL);
pubkeyfile = g_key_file_new();
g_key_file_load_from_file(pubkeyfile, pubsloc, G_KEY_FILE_KEEP_COMMENTS, NULL);
// load each keyid
gsize len = 0;
gchar **jids = g_key_file_get_groups(fpskeyfile, &len);
gchar **jids = g_key_file_get_groups(pubkeyfile, &len);
gpgme_ctx_t ctx;
gpgme_error_t error = gpgme_new(&ctx);
@ -143,21 +162,24 @@ p_gpg_on_connect(const char * const barejid)
for (i = 0; i < len; i++) {
GError *gerr = NULL;
gchar *jid = jids[i];
gchar *keyid = g_key_file_get_string(fpskeyfile, jid, "keyid", &gerr);
gchar *keyid = g_key_file_get_string(pubkeyfile, jid, "keyid", &gerr);
if (gerr) {
log_error("Error loading PGP key id for %s", jid);
g_error_free(gerr);
g_free(keyid);
} else {
gpgme_key_t key = NULL;
error = gpgme_get_key(ctx, keyid, &key, 1);
g_free(keyid);
error = gpgme_get_key(ctx, keyid, &key, 0);
if (error || key == NULL) {
log_warning("GPG: Failed to get key for %s: %s %s", jid, gpgme_strsource(error), gpgme_strerror(error));
continue;
}
g_hash_table_replace(fingerprints, strdup(jid), strdup(key->subkeys->fpr));
ProfPGPPubKeyId *pubkeyid = malloc(sizeof(ProfPGPPubKeyId));
pubkeyid->id = strdup(keyid);
pubkeyid->received = FALSE;
g_hash_table_replace(pubkeys, strdup(jid), pubkeyid);
g_free(keyid);
gpgme_key_unref(key);
}
}
@ -165,24 +187,24 @@ p_gpg_on_connect(const char * const barejid)
gpgme_release(ctx);
g_strfreev(jids);
_save_fps();
_save_pubkeys();
}
void
p_gpg_on_disconnect(void)
{
if (fingerprints) {
g_hash_table_destroy(fingerprints);
fingerprints = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
if (pubkeys) {
g_hash_table_destroy(pubkeys);
pubkeys = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)_p_gpg_free_pubkeyid);
}
if (fpskeyfile) {
g_key_file_free(fpskeyfile);
fpskeyfile = NULL;
if (pubkeyfile) {
g_key_file_free(pubkeyfile);
pubkeyfile = NULL;
}
free(fpsloc);
fpsloc = NULL;
free(pubsloc);
pubsloc = NULL;
}
gboolean
@ -196,7 +218,7 @@ p_gpg_addkey(const char * const jid, const char * const keyid)
}
gpgme_key_t key = NULL;
error = gpgme_get_key(ctx, keyid, &key, 1);
error = gpgme_get_key(ctx, keyid, &key, 0);
gpgme_release(ctx);
if (error || key == NULL) {
@ -204,12 +226,15 @@ p_gpg_addkey(const char * const jid, const char * const keyid)
return FALSE;
}
// save to ID keyfile
g_key_file_set_string(fpskeyfile, jid, "keyid", keyid);
_save_fps();
// save to public key file
g_key_file_set_string(pubkeyfile, jid, "keyid", keyid);
_save_pubkeys();
// update in memory fingerprint list
g_hash_table_replace(fingerprints, strdup(jid), strdup(key->subkeys->fpr));
// update in memory pubkeys list
ProfPGPPubKeyId *pubkeyid = malloc(sizeof(ProfPGPPubKeyId));
pubkeyid->id = strdup(keyid);
pubkeyid->received = FALSE;
g_hash_table_replace(pubkeys, strdup(jid), pubkeyid);
gpgme_key_unref(key);
return TRUE;
@ -312,6 +337,16 @@ p_gpg_list_keys(void)
gpgme_release(ctx);
autocomplete_clear(key_ac);
GList *ids = g_hash_table_get_keys(result);
GList *curr = ids;
while (curr) {
ProfPGPKey *key = g_hash_table_lookup(result, curr->data);
autocomplete_add(key_ac, key->id);
curr = curr->next;
}
g_list_free(ids);
return result;
}
@ -323,9 +358,9 @@ p_gpg_free_keys(GHashTable *keys)
GHashTable *
p_gpg_fingerprints(void)
p_gpg_pubkeys(void)
{
return fingerprints;
return pubkeys;
}
const char*
@ -366,8 +401,8 @@ p_gpg_valid_key(const char * const keyid)
gboolean
p_gpg_available(const char * const barejid)
{
char *fp = g_hash_table_lookup(fingerprints, barejid);
return (fp != NULL);
char *pubkey = g_hash_table_lookup(pubkeys, barejid);
return (pubkey != NULL);
}
void
@ -406,8 +441,19 @@ p_gpg_verify(const char * const barejid, const char *const sign)
gpgme_verify_result_t result = gpgme_op_verify_result(ctx);
if (result) {
if (result->signatures) {
log_debug("Fingerprint found for %s: %s ", barejid, result->signatures->fpr);
g_hash_table_replace(fingerprints, strdup(barejid), strdup(result->signatures->fpr));
gpgme_key_t key = NULL;
error = gpgme_get_key(ctx, result->signatures->fpr, &key, 0);
if (error) {
log_debug("Could not find PGP key with ID %s for %s", result->signatures->fpr, barejid);
} else {
log_debug("Fingerprint found for %s: %s ", barejid, key->subkeys->fpr);
ProfPGPPubKeyId *pubkeyid = malloc(sizeof(ProfPGPPubKeyId));
pubkeyid->id = strdup(key->subkeys->keyid);
pubkeyid->received = TRUE;
g_hash_table_replace(pubkeys, strdup(barejid), pubkeyid);
}
gpgme_key_unref(key);
}
}
@ -485,9 +531,11 @@ p_gpg_sign(const char * const str, const char * const fp)
char *
p_gpg_encrypt(const char * const barejid, const char * const message)
{
char *fp = g_hash_table_lookup(fingerprints, barejid);
if (!fp) {
ProfPGPPubKeyId *pubkeyid = g_hash_table_lookup(pubkeys, barejid);
if (!pubkeyid) {
return NULL;
}
if (!pubkeyid->id) {
return NULL;
}
@ -504,7 +552,7 @@ p_gpg_encrypt(const char * const barejid, const char * const message)
}
gpgme_key_t key;
error = gpgme_get_key(ctx, fp, &key, 0);
error = gpgme_get_key(ctx, pubkeyid->id, &key, 0);
if (error || key == NULL) {
log_error("GPG: Failed to get key. %s %s", gpgme_strsource(error), gpgme_strerror(error));
@ -580,7 +628,7 @@ p_gpg_decrypt(const char * const cipher)
gpgme_recipient_t recipient = res->recipients;
if (recipient) {
gpgme_key_t key;
error = gpgme_get_key(ctx, recipient->keyid, &key, 0);
error = gpgme_get_key(ctx, recipient->keyid, &key, 1);
if (!error && key) {
const char *addr = gpgme_key_get_string_attr(key, GPGME_ATTR_EMAIL, NULL, 0);
@ -611,6 +659,18 @@ p_gpg_free_decrypted(char *decrypted)
g_free(decrypted);
}
char *
p_gpg_autocomplete_key(const char * const search_str)
{
return autocomplete_complete(key_ac, search_str, TRUE);
}
void
p_gpg_autocomplete_key_reset(void)
{
autocomplete_reset(key_ac);
}
static char*
_remove_header_footer(char *str, const char * const footer)
{
@ -653,11 +713,11 @@ _add_header_footer(const char * const str, const char * const header, const char
}
static void
_save_fps(void)
_save_pubkeys(void)
{
gsize g_data_size;
gchar *g_fps_data = g_key_file_to_data(fpskeyfile, &g_data_size, NULL);
g_file_set_contents(fpsloc, g_fps_data, g_data_size, NULL);
g_chmod(fpsloc, S_IRUSR | S_IWUSR);
g_free(g_fps_data);
gchar *g_pubkeys_data = g_key_file_to_data(pubkeyfile, &g_data_size, NULL);
g_file_set_contents(pubsloc, g_pubkeys_data, g_data_size, NULL);
g_chmod(pubsloc, S_IRUSR | S_IWUSR);
g_free(g_pubkeys_data);
}

View File

@ -46,6 +46,11 @@ typedef struct pgp_key_t {
gboolean secret;
} ProfPGPKey;
typedef struct pgp_pubkeyid_t {
char *id;
gboolean received;
} ProfPGPPubKeyId;
void p_gpg_init(void);
void p_gpg_close(void);
void p_gpg_on_connect(const char * const barejid);
@ -53,7 +58,7 @@ void p_gpg_on_disconnect(void);
GHashTable* p_gpg_list_keys(void);
void p_gpg_free_keys(GHashTable *keys);
gboolean p_gpg_addkey(const char * const jid, const char * const keyid);
GHashTable* p_gpg_fingerprints(void);
GHashTable* p_gpg_pubkeys(void);
gboolean p_gpg_valid_key(const char * const keyid);
gboolean p_gpg_available(const char * const barejid);
const char* p_gpg_libver(void);
@ -62,5 +67,7 @@ void p_gpg_verify(const char * const barejid, const char *const sign);
char* p_gpg_encrypt(const char * const barejid, const char * const message);
char* p_gpg_decrypt(const char * const cipher);
void p_gpg_free_decrypted(char *decrypted);
char* p_gpg_autocomplete_key(const char * const search_str);
void p_gpg_autocomplete_key_reset(void);
#endif

View File

@ -1453,6 +1453,9 @@ cons_show_otr_prefs(void)
}
prefs_free_string(log_value);
char ch = prefs_get_otr_char();
cons_show("OTR char (/otr char) : %c", ch);
cons_alert();
}
@ -1472,6 +1475,9 @@ cons_show_pgp_prefs(void)
}
prefs_free_string(log_value);
char ch = prefs_get_pgp_char();
cons_show("PGP char (/pgp char) : %c", ch);
cons_alert();
}

View File

@ -412,7 +412,7 @@ ui_message_receipt(const char * const barejid, const char * const id)
}
void
ui_incoming_msg(ProfChatWin *chatwin, const char * const resource, const char * const message, GDateTime *timestamp, gboolean win_created)
ui_incoming_msg(ProfChatWin *chatwin, const char * const resource, const char * const message, GDateTime *timestamp, gboolean win_created, prof_enc_t enc_mode)
{
char *plugin_message = plugins_pre_chat_message_display(chatwin->barejid, message);
@ -423,7 +423,7 @@ ui_incoming_msg(ProfChatWin *chatwin, const char * const resource, const char *
// currently viewing chat window with sender
if (wins_is_current(window)) {
win_print_incoming_message(window, timestamp, display_name, plugin_message);
win_print_incoming_message(window, timestamp, display_name, plugin_message, enc_mode);
title_bar_set_typing(FALSE);
status_bar_active(num);
@ -449,7 +449,7 @@ ui_incoming_msg(ProfChatWin *chatwin, const char * const resource, const char *
}
}
win_print_incoming_message(window, timestamp, display_name, plugin_message);
win_print_incoming_message(window, timestamp, display_name, plugin_message, enc_mode);
}
if (prefs_get_boolean(PREF_BEEP)) {
@ -483,7 +483,7 @@ ui_incoming_private_msg(const char * const fulljid, const char * const message,
// currently viewing chat window with sender
if (wins_is_current(window)) {
win_print_incoming_message(window, timestamp, display_from, message);
win_print_incoming_message(window, timestamp, display_from, message, PROF_ENC_NONE);
title_bar_set_typing(FALSE);
status_bar_active(num);
@ -492,7 +492,7 @@ ui_incoming_private_msg(const char * const fulljid, const char * const message,
privatewin->unread++;
status_bar_new(num);
cons_show_incoming_message(display_from, num);
win_print_incoming_message(window, timestamp, display_from, message);
win_print_incoming_message(window, timestamp, display_from, message, PROF_ENC_NONE);
if (prefs_get_boolean(PREF_FLASH)) {
flash();
@ -1292,12 +1292,19 @@ ui_new_chat_win(const char * const barejid)
}
void
ui_outgoing_chat_msg(ProfChatWin *chatwin, const char * const message, char *id)
ui_outgoing_chat_msg(ProfChatWin *chatwin, const char * const message, char *id, prof_enc_t enc_mode)
{
char enc_char = '-';
if (enc_mode == PROF_ENC_OTR) {
enc_char = prefs_get_otr_char();
} else if (enc_mode == PROF_ENC_PGP) {
enc_char = prefs_get_pgp_char();
}
if (prefs_get_boolean(PREF_RECEIPTS_REQUEST) && id) {
win_print_with_receipt((ProfWin*)chatwin, '-', 0, NULL, 0, THEME_TEXT_ME, "me", message, id);
win_print_with_receipt((ProfWin*)chatwin, enc_char, 0, NULL, 0, THEME_TEXT_ME, "me", message, id);
} else {
win_print((ProfWin*)chatwin, '-', 0, NULL, 0, THEME_TEXT_ME, "me", message);
win_print((ProfWin*)chatwin, enc_char, 0, NULL, 0, THEME_TEXT_ME, "me", message);
}
}

View File

@ -102,14 +102,14 @@ void ui_handle_stanza(const char * const msg);
// ui events
void ui_contact_online(char *barejid, Resource *resource, GDateTime *last_activity);
void ui_contact_typing(const char * const barejid, const char * const resource);
void ui_incoming_msg(ProfChatWin *chatwin, const char * const resource, const char * const message, GDateTime *timestamp, gboolean win_created);
void ui_incoming_msg(ProfChatWin *chatwin, const char * const resource, const char * const message, GDateTime *timestamp, gboolean win_created, prof_enc_t enc_mode);
void ui_incoming_private_msg(const char * const fulljid, const char * const message, GDateTime *timestamp);
void ui_message_receipt(const char * const barejid, const char * const id);
void ui_disconnected(void);
void ui_recipient_gone(const char * const barejid, const char * const resource);
void ui_outgoing_chat_msg(ProfChatWin *chatwin, const char * const message, char *id);
void ui_outgoing_chat_msg(ProfChatWin *chatwin, const char * const message, char *id, prof_enc_t enc_mode);
void ui_outgoing_chat_msg_carbon(const char * const barejid, const char * const message);
void ui_outgoing_private_msg(ProfPrivateWin *privwin, const char * const message);

View File

@ -896,11 +896,20 @@ win_show_status_string(ProfWin *window, const char * const from,
void
win_print_incoming_message(ProfWin *window, GDateTime *timestamp,
const char * const from, const char * const message)
const char * const from, const char * const message, prof_enc_t enc_mode)
{
char enc_char = '-';
switch (window->type)
{
case WIN_CHAT:
if (enc_mode == PROF_ENC_OTR) {
enc_char = prefs_get_otr_char();
} else if (enc_mode == PROF_ENC_PGP) {
enc_char = prefs_get_pgp_char();
}
win_print(window, enc_char, 0, timestamp, NO_ME, THEME_TEXT_THEM, from, message);
break;
case WIN_PRIVATE:
win_print(window, '-', 0, timestamp, NO_ME, THEME_TEXT_THEM, from, message);
break;

View File

@ -60,7 +60,7 @@ void win_show_status_string(ProfWin *window, const char * const from,
GDateTime *last_activity, const char * const pre,
const char * const default_show);
void win_print_incoming_message(ProfWin *window, GDateTime *timestamp,
const char * const from, const char * const message);
const char * const from, const char * const message, prof_enc_t enc_mode);
void win_print_with_receipt(ProfWin *window, const char show_char, int pad_indent, GTimeVal *tstamp, int flags,
theme_item_t theme_item, const char * const from, const char * const message, char *id);
void win_newline(ProfWin *window);

View File

@ -11,7 +11,7 @@ GHashTable* p_gpg_list_keys(void)
}
GHashTable*
p_gpg_fingerprints(void)
p_gpg_pubkeys(void)
{
return NULL;
}
@ -54,3 +54,10 @@ void p_gpg_free_decrypted(char *decrypted) {}
void p_gpg_free_keys(GHashTable *keys) {}
void p_gpg_autocomplete_key_reset(void) {}
char * p_gpg_autocomplete_key(const char * const search_str)
{
return NULL;
}

View File

@ -179,7 +179,7 @@ void ui_contact_online(char *barejid, Resource *resource, GDateTime *last_activi
}
void ui_contact_typing(const char * const barejid, const char * const resource) {}
void ui_incoming_msg(ProfChatWin *chatwin, const char * const resource, const char * const message, GDateTime *timestamp, gboolean win_created) {}
void ui_incoming_msg(ProfChatWin *chatwin, const char * const resource, const char * const message, GDateTime *timestamp, gboolean win_created, prof_enc_t enc_mode) {}
void ui_message_receipt(const char * const barejid, const char * const id) {}
void ui_incoming_private_msg(const char * const fulljid, const char * const message, GDateTime *timestamp) {}
@ -187,7 +187,7 @@ void ui_incoming_private_msg(const char * const fulljid, const char * const mess
void ui_disconnected(void) {}
void ui_recipient_gone(const char * const barejid, const char * const resource) {}
void ui_outgoing_chat_msg(ProfChatWin *chatwin, const char * const message, char *id) {}
void ui_outgoing_chat_msg(ProfChatWin *chatwin, const char * const message, char *id, prof_enc_t enc_mode) {}
void ui_outgoing_chat_msg_carbon(const char * const barejid, const char * const message) {}
void ui_outgoing_private_msg(ProfPrivateWin *privwin, const char * const message) {}

View File

@ -75,3 +75,5 @@ occupants=
occupants.size=
occupants.jid=
wins.autotidy=
otr.char=
pgp.char=

View File

@ -75,3 +75,5 @@ occupants=true
occupants.size=15
occupants.jid=false
wins.autotidy=true
otr.char=@
pgp.char=%