commit 22249a5bdbc5930c0a3069804ba9cdf35ec07dec
parent c03433163c1b3d0d9aaefc82c7c5a5fa2c413a58
Author: Michael Rasmussen <mir@datanom.net>
Date: Sat, 23 Sep 2017 22:55:25 +0200
Merge branch 'master' of ssh+git://git.claws-mail.org/home/git/claws
Diffstat:
22 files changed, 377 insertions(+), 167 deletions(-)
diff --git a/AUTHORS b/AUTHORS
@@ -314,3 +314,5 @@ contributors (in addition to the above; based on Changelog)
Olivier Brunel
Michael Vilain
Orbea
+ Flavio Leitner
+ Thomas Orgis
diff --git a/configure.ac b/configure.ac
@@ -585,7 +585,7 @@ dnl enchant is used for spell checking
AC_MSG_CHECKING([whether to use enchant])
AC_MSG_RESULT($enable_enchant)
if test $enable_enchant = yes; then
- PKG_CHECK_MODULES(ENCHANT, enchant >= 1.0.0,
+ PKG_CHECK_MODULES(ENCHANT, enchant >= 1.4.0,
[
AC_DEFINE(USE_ENCHANT, 1, enchant)
echo "Building with enchant"
diff --git a/doc/man/claws-mail.1 b/doc/man/claws-mail.1
@@ -101,6 +101,8 @@ This list is not complete.
.br
\fB \-\-attach file1 [file2]...\fR
.br
+\fB \-\-insert file1 [file2]...\fR
+.br
\fB \-\-receive\fR
.br
\fB \-\-receive\-all\fR
@@ -283,6 +285,9 @@ Subscribe to the given URI if possible.
\fB\-\-attach file1 [file2]...\fR
Open composition window with specified files attached.
.TP
+\fB\-\-insert file1 [file2]...\fR
+Open composition window with specified files inserted.
+.TP
\fB\-\-compose\fR "mailto:\fI%t\fR?subject=\fI%s\fR&cc=\fI%c\fR&body=\fI%b\fR"
This syntax can be used in web\-browsers and CLI to open a pre\-populated
Compose window. Possible fields after the destination recipient are: subject,
diff --git a/src/account.c b/src/account.c
@@ -1052,6 +1052,8 @@ static void account_clone(GtkWidget *widget, gpointer data)
ac_clon->is_default = FALSE;
ACP_FASSIGN(folder);
+ ACP_FASSIGN(config_version);
+
account_list = g_list_append(account_list, ac_clon);
account_list_view_set();
}
diff --git a/src/compose.c b/src/compose.c
@@ -1226,7 +1226,10 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
for (curr = attach_files ; curr != NULL ; curr = curr->next) {
ainfo = (AttachInfo *) curr->data;
- compose_attach_append(compose, ainfo->file, ainfo->file,
+ if (ainfo->insert)
+ compose_insert_file(compose, ainfo->file);
+ else
+ compose_attach_append(compose, ainfo->file, ainfo->file,
ainfo->content_type, ainfo->charset);
}
}
@@ -5193,9 +5196,9 @@ static gboolean compose_check_entries(Compose *compose, gboolean check_everythin
entry = gtk_editable_get_chars(GTK_EDITABLE(((ComposeHeaderEntry *)list->data)->entry), 0, -1);
g_strstrip(header);
g_strstrip(entry);
- if ((entry[0] != '\0')
- && (strcmp(header, prefs_common_translated_header_name("To:"))
- || strcmp(header, prefs_common_translated_header_name("Cc:")))) {
+ if ((entry[0] != '\0') &&
+ (!strcmp(header, prefs_common_translated_header_name("To:")) ||
+ !strcmp(header, prefs_common_translated_header_name("Cc:")))) {
cnt++;
}
g_free(header);
@@ -11708,6 +11711,8 @@ static gboolean compose_headerentry_button_clicked_cb (GtkWidget *button,
ComposeHeaderEntry *headerentry)
{
gtk_entry_set_text(GTK_ENTRY(headerentry->entry), "");
+ gtk_widget_modify_base(GTK_WIDGET(headerentry->entry), GTK_STATE_NORMAL, NULL);
+ gtk_widget_modify_text(GTK_WIDGET(headerentry->entry), GTK_STATE_NORMAL, NULL);
return FALSE;
}
diff --git a/src/compose.h b/src/compose.h
@@ -262,6 +262,7 @@ struct _AttachInfo
gchar *name;
goffset size;
gchar *charset;
+ gboolean insert;
};
typedef enum
diff --git a/src/gtk/authors.h b/src/gtk/authors.h
@@ -195,6 +195,7 @@ static char *CONTRIBS_LIST[] = {
"Abhay S. Kushwaha",
"Joshua M. Kwan",
"Jean-Yves Lefort",
+"Flavio Leitner",
"Jérôme Lelong",
"Eric Limpens",
"Thomas Link",
@@ -241,6 +242,7 @@ static char *CONTRIBS_LIST[] = {
"Paul Ollis",
"Fredrik Olofssen",
"Orbea",
+"Thomas Orgis",
"Reza Pakdel",
"Richard Palo",
"Marcel Pol",
diff --git a/src/gtk/gtkaspell.c b/src/gtk/gtkaspell.c
@@ -1348,7 +1348,7 @@ static void add_word_to_personal_cb(GtkWidget *w, gpointer data)
{
GtkAspell *gtkaspell = (GtkAspell *) data;
- enchant_dict_add_to_pwl(gtkaspell->gtkaspeller->speller, gtkaspell->theword, strlen(gtkaspell->theword));
+ enchant_dict_add(gtkaspell->gtkaspeller->speller, gtkaspell->theword, strlen(gtkaspell->theword));
gtkaspell->ctx.check_word(gtkaspell->ctx.data);
gtkaspell_dict_changed(gtkaspell);
diff --git a/src/imap.c b/src/imap.c
@@ -77,8 +77,6 @@ typedef struct _IMAPSession IMAPSession;
typedef struct _IMAPNameSpace IMAPNameSpace;
typedef struct _IMAPFolderItem IMAPFolderItem;
-#include "prefs_account.h"
-
#define IMAP_FOLDER(obj) ((IMAPFolder *)obj)
#define IMAP_FOLDER_ITEM(obj) ((IMAPFolderItem *)obj)
#define IMAP_SESSION(obj) ((IMAPSession *)obj)
@@ -427,7 +425,6 @@ static gint imap_get_flags (Folder *folder,
FolderItem *item,
MsgInfoList *msglist,
GHashTable *msgflags);
-static gchar *imap_folder_get_path (Folder *folder);
static gchar *imap_item_get_path (Folder *folder,
FolderItem *item);
static MsgInfo *imap_parse_msg(const gchar *file, FolderItem *item);
@@ -3045,35 +3042,6 @@ static FolderItem *imap_create_special_folder(Folder *folder,
return new_item;
}
-static gchar *imap_folder_get_path(Folder *folder)
-{
- gchar *folder_path;
-
- g_return_val_if_fail(folder != NULL, NULL);
- g_return_val_if_fail(folder->account != NULL, NULL);
-
-#ifdef G_OS_WIN32
- gchar *sanitized_dirname = g_strdup(folder->account->recv_server);
- g_strdelimit(sanitized_dirname, ":", ',');
-#endif
-
- folder_path = g_strconcat(get_imap_cache_dir(),
- G_DIR_SEPARATOR_S,
-#ifdef G_OS_WIN32
- sanitized_dirname,
-#else
- folder->account->recv_server,
-#endif
- G_DIR_SEPARATOR_S,
- folder->account->userid,
- NULL);
-
-#ifdef G_OS_WIN32
- g_free(sanitized_dirname);
-#endif
- return folder_path;
-}
-
#ifdef G_OS_WIN32
static gchar *imap_encode_unsafe_chars(const gchar *str)
{
@@ -3110,8 +3078,9 @@ static gchar *imap_item_get_path(Folder *folder, FolderItem *item)
gchar *item_path = NULL;
g_return_val_if_fail(folder != NULL, NULL);
+ g_return_val_if_fail(folder->account != NULL, NULL);
g_return_val_if_fail(item != NULL, NULL);
- folder_path = imap_folder_get_path(folder);
+ folder_path = prefs_account_cache_dir(folder->account, FALSE);
g_return_val_if_fail(folder_path != NULL, NULL);
diff --git a/src/main.c b/src/main.c
@@ -1250,6 +1250,14 @@ int main(int argc, char *argv[])
folder_system_init();
prefs_common_read_config();
+ if (prefs_update_config_version_common() < 0) {
+ debug_print("Main configuration file version upgrade failed, exiting\n");
+#ifdef G_OS_WIN32
+ win32_close_log();
+#endif
+ exit(200);
+ }
+
prefs_themes_init();
prefs_fonts_init();
prefs_ext_prog_init();
@@ -1326,6 +1334,14 @@ int main(int argc, char *argv[])
prefs_account_init();
account_read_config_all();
+ if (prefs_update_config_version_accounts() < 0) {
+ debug_print("Accounts configuration file version upgrade failed, exiting\n");
+#ifdef G_OS_WIN32
+ win32_close_log();
+#endif
+ exit(201);
+ }
+
#ifdef HAVE_LIBETPAN
imap_main_init(prefs_common.skip_ssl_cert_check);
imap_main_set_timeout(prefs_common.io_timeout_secs);
@@ -1478,17 +1494,8 @@ int main(int argc, char *argv[])
}
if (never_ran) {
- prefs_common_get_prefs()->config_version = CLAWS_CONFIG_VERSION;
prefs_common_write_config();
plugin_load_standard_plugins ();
- } else {
- if (prefs_update_config_version() < 0) {
- exit_claws(mainwin);
-#ifdef G_OS_WIN32
- win32_close_log();
-#endif
- exit(0);
- }
}
/* if not crashed, show window now */
@@ -1861,9 +1868,10 @@ static void parse_cmd_opt(int argc, char *argv[])
cmd.subscribe = TRUE;
cmd.subscribe_uri = p;
}
- } else if (!strncmp(argv[i], "--attach", 8)) {
+ } else if (!strncmp(argv[i], "--attach", 8) || !strncmp(argv[i], "--insert", 8)) {
const gchar *p = (i+1 < argc)?argv[i+1]:NULL;
gchar *file = NULL;
+ gboolean insert = !strncmp(argv[i], "--insert", 8);
while (p && *p != '\0' && *p != '-') {
if ((file = g_filename_from_uri(p, NULL, NULL)) != NULL) {
@@ -1879,8 +1887,10 @@ static void parse_cmd_opt(int argc, char *argv[])
} else if (file == NULL) {
file = g_strdup(p);
}
+
ainfo = g_new0(AttachInfo, 1);
ainfo->file = file;
+ ainfo->insert = insert;
cmd.attach_files = g_list_append(cmd.attach_files, ainfo);
i++;
p = (i+1 < argc)?argv[i+1]:NULL;
@@ -1957,6 +1967,9 @@ static void parse_cmd_opt(int argc, char *argv[])
g_print("%s\n", _(" --attach file1 [file2]...\n"
" open composition window with specified files\n"
" attached"));
+ g_print("%s\n", _(" --insert file1 [file2]...\n"
+ " open composition window with specified files\n"
+ " inserted"));
g_print("%s\n", _(" --receive receive new messages"));
g_print("%s\n", _(" --receive-all receive new messages of all accounts"));
g_print("%s\n", _(" --cancel-receiving cancel receiving of messages"));
@@ -2339,6 +2352,10 @@ static gint prohibit_duplicate_launch(void)
for (curr = cmd.attach_files; curr != NULL ; curr = curr->next) {
str = (gchar *) ((AttachInfo *)curr->data)->file;
+ if (((AttachInfo *)curr->data)->insert)
+ fd_write_all(uxsock, "insert ", strlen("insert "));
+ else
+ fd_write_all(uxsock, "attach ", strlen("attach "));
fd_write_all(uxsock, str, strlen(str));
fd_write_all(uxsock, "\n", 1);
}
@@ -2539,9 +2556,10 @@ static void lock_socket_input_cb(gpointer data,
strretchomp(buf);
if (!strcmp2(buf, "."))
break;
-
+
ainfo = g_new0(AttachInfo, 1);
- ainfo->file = g_strdup(buf);
+ ainfo->file = g_strdup(strstr(buf, " ") + 1);
+ ainfo->insert = !strncmp(buf, "insert ", 7);
files = g_list_append(files, ainfo);
}
open_compose_new(mailto, files);
diff --git a/src/plugins/pgpcore/prefs_gpg.c b/src/plugins/pgpcore/prefs_gpg.c
@@ -87,6 +87,26 @@ struct GPGPage
GtkWidget *gpg_path;
};
+struct GPGAccountPage
+{
+ PrefsPage page;
+
+ GtkWidget *key_default;
+ GtkWidget *key_by_from;
+ GtkWidget *key_custom;
+ GtkWidget *keyid;
+ GtkWidget *keyid_label;
+ GtkWidget *new_key_label;
+ GtkWidget *new_key_btn;
+ GtkWidget *new_key_box;
+
+ PrefsAccount *account;
+};
+
+static struct GPGPage gpg_page;
+static struct GPGAccountPage gpg_account_page;
+static struct GPGAccountPage smime_account_page;
+
static void prefs_gpg_create_widget_func(PrefsPage *_page,
GtkWindow *window,
gpointer data)
@@ -270,22 +290,6 @@ static void prefs_gpg_save_func(PrefsPage *_page)
prefs_gpg_save_config();
}
-struct GPGAccountPage
-{
- PrefsPage page;
-
- GtkWidget *key_default;
- GtkWidget *key_by_from;
- GtkWidget *key_custom;
- GtkWidget *keyid;
- GtkWidget *keyid_label;
- GtkWidget *new_key_label;
- GtkWidget *new_key_btn;
- GtkWidget *new_key_box;
-
- PrefsAccount *account;
-};
-
void key_custom_toggled(GtkToggleButton *togglebutton, gpointer user_data)
{
struct GPGAccountPage *page = (struct GPGAccountPage *) user_data;
@@ -333,6 +337,7 @@ static void prefs_gpg_account_create_widget_func(PrefsPage *_page,
struct GPGAccountPage *page = (struct GPGAccountPage *) _page;
PrefsAccount *account = (PrefsAccount *) data;
GPGAccountConfig *config;
+ SignKeyType sign_key;
GtkWidget *vbox;
GtkWidget *frame1;
@@ -403,7 +408,10 @@ static void prefs_gpg_account_create_widget_func(PrefsPage *_page,
gtk_box_pack_start(GTK_BOX(hbox), keyid, FALSE, FALSE, 0);
config = prefs_gpg_account_get_config(account);
- switch (config->sign_key) {
+
+ sign_key =
+ (page == &smime_account_page ? config->smime_sign_key : config->sign_key);
+ switch (sign_key) {
case SIGN_KEY_DEFAULT:
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(key_default), TRUE);
gtk_widget_set_sensitive(GTK_WIDGET(keyid_label), FALSE);
@@ -441,9 +449,13 @@ static void prefs_gpg_account_create_widget_func(PrefsPage *_page,
gtk_widget_show(new_key_btn);
gtk_box_pack_start(GTK_BOX(hbox), new_key_btn, FALSE, FALSE, 0);
- if (config->sign_key_id != NULL)
- gtk_entry_set_text(GTK_ENTRY(keyid), config->sign_key_id);
-
+ if (page == &smime_account_page) {
+ if (config->smime_sign_key_id != NULL)
+ gtk_entry_set_text(GTK_ENTRY(keyid), config->smime_sign_key_id);
+ } else {
+ if (config->sign_key_id != NULL)
+ gtk_entry_set_text(GTK_ENTRY(keyid), config->sign_key_id);
+ }
g_signal_connect(G_OBJECT(key_custom), "toggled", G_CALLBACK(key_custom_toggled), page);
g_signal_connect(G_OBJECT(new_key_btn), "clicked", G_CALLBACK(new_key_clicked), page);
@@ -473,14 +485,26 @@ static void prefs_gpg_account_save_func(PrefsPage *_page)
config = prefs_gpg_account_get_config(page->account);
- if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->key_default)))
- config->sign_key = SIGN_KEY_DEFAULT;
- else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->key_by_from)))
- config->sign_key = SIGN_KEY_BY_FROM;
- else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->key_custom))) {
- config->sign_key = SIGN_KEY_CUSTOM;
- g_free(config->sign_key_id);
- config->sign_key_id = gtk_editable_get_chars(GTK_EDITABLE(page->keyid), 0, -1);
+ if (page == &smime_account_page) {
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->key_default)))
+ config->smime_sign_key = SIGN_KEY_DEFAULT;
+ else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->key_by_from)))
+ config->smime_sign_key = SIGN_KEY_BY_FROM;
+ else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->key_custom))) {
+ config->smime_sign_key = SIGN_KEY_CUSTOM;
+ g_free(config->smime_sign_key_id);
+ config->smime_sign_key_id = gtk_editable_get_chars(GTK_EDITABLE(page->keyid), 0, -1);
+ }
+ } else {
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->key_default)))
+ config->sign_key = SIGN_KEY_DEFAULT;
+ else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->key_by_from)))
+ config->sign_key = SIGN_KEY_BY_FROM;
+ else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->key_custom))) {
+ config->sign_key = SIGN_KEY_CUSTOM;
+ g_free(config->sign_key_id);
+ config->sign_key_id = gtk_editable_get_chars(GTK_EDITABLE(page->keyid), 0, -1);
+ }
}
prefs_gpg_account_set_config(page->account, config);
@@ -526,26 +550,51 @@ struct GPGAccountConfig *prefs_gpg_account_get_config(PrefsAccount *account)
config = g_new0(GPGAccountConfig, 1);
config->sign_key = SIGN_KEY_DEFAULT;
config->sign_key_id = NULL;
+ config->smime_sign_key = SIGN_KEY_DEFAULT;
+ config->smime_sign_key_id = NULL;
confstr = prefs_account_get_privacy_prefs(account, "gpg");
- if (confstr == NULL)
- return config;
-
- strv = g_strsplit(confstr, ";", 0);
- if (strv[0] != NULL) {
- if (!strcmp(strv[0], "DEFAULT"))
- config->sign_key = SIGN_KEY_DEFAULT;
- if (!strcmp(strv[0], "BY_FROM"))
- config->sign_key = SIGN_KEY_BY_FROM;
- if (!strcmp(strv[0], "CUSTOM")) {
- if (strv[1] != NULL) {
- config->sign_key = SIGN_KEY_CUSTOM;
- config->sign_key_id = g_strdup(strv[1]);
- } else
+ if (confstr != NULL) {
+ strv = g_strsplit(confstr, ";", 0);
+ if (strv[0] != NULL) {
+ if (!strcmp(strv[0], "DEFAULT"))
config->sign_key = SIGN_KEY_DEFAULT;
+ if (!strcmp(strv[0], "BY_FROM"))
+ config->sign_key = SIGN_KEY_BY_FROM;
+ if (!strcmp(strv[0], "CUSTOM")) {
+ if (strv[1] != NULL) {
+ config->sign_key = SIGN_KEY_CUSTOM;
+ config->sign_key_id = g_strdup(strv[1]);
+ } else
+ config->sign_key = SIGN_KEY_DEFAULT;
+ }
}
+ g_strfreev(strv);
+ }
+
+ confstr = prefs_account_get_privacy_prefs(account, "smime");
+ /* If the "smime" section does not yet exist, fall back to
+ * "gpg" section even for smime_ values. This will generally
+ * only happen on first run. */
+ if (confstr == NULL)
+ confstr = prefs_account_get_privacy_prefs(account, "gpg");
+ if (confstr != NULL) {
+ strv = g_strsplit(confstr, ";", 0);
+ if (strv[0] != NULL) {
+ if (!strcmp(strv[0], "DEFAULT"))
+ config->smime_sign_key = SIGN_KEY_DEFAULT;
+ if (!strcmp(strv[0], "BY_FROM"))
+ config->smime_sign_key = SIGN_KEY_BY_FROM;
+ if (!strcmp(strv[0], "CUSTOM")) {
+ if (strv[1] != NULL) {
+ config->smime_sign_key = SIGN_KEY_CUSTOM;
+ config->smime_sign_key_id = g_strdup(strv[1]);
+ } else
+ config->smime_sign_key = SIGN_KEY_DEFAULT;
+ }
+ }
+ g_strfreev(strv);
}
- g_strfreev(strv);
return config;
}
@@ -572,17 +621,35 @@ void prefs_gpg_account_set_config(PrefsAccount *account, GPGAccountConfig *confi
prefs_account_set_privacy_prefs(account, "gpg", confstr);
g_free(confstr);
+ confstr = NULL;
+
+ switch (config->smime_sign_key) {
+ case SIGN_KEY_DEFAULT:
+ confstr = g_strdup("DEFAULT");
+ break;
+ case SIGN_KEY_BY_FROM:
+ confstr = g_strdup("BY_FROM");
+ break;
+ case SIGN_KEY_CUSTOM:
+ confstr = g_strdup_printf("CUSTOM;%s", config->smime_sign_key_id);
+ break;
+ default:
+ confstr = g_strdup("");
+ g_warning("prefs_gpg_account_set_config: bad sign_key val");
+ }
+
+ prefs_account_set_privacy_prefs(account, "smime", confstr);
+
+ g_free(confstr);
}
void prefs_gpg_account_free_config(GPGAccountConfig *config)
{
+ g_free(config->smime_sign_key_id);
g_free(config->sign_key_id);
g_free(config);
}
-static struct GPGPage gpg_page;
-static struct GPGAccountPage gpg_account_page;
-
void prefs_gpg_enable_agent(gboolean enable)
{
if (enable) {
@@ -607,7 +674,7 @@ void prefs_gpg_enable_agent(gboolean enable)
void prefs_gpg_init()
{
- static gchar *path[3];
+ static gchar *path[3], *spath[3];
gchar *rcpath;
const gchar *tmp = NULL;
@@ -635,6 +702,17 @@ void prefs_gpg_init()
gpg_account_page.page.weight = 30.0;
prefs_account_register_page((PrefsPage *) &gpg_account_page);
+
+ spath[0] = _("Plugins");
+ spath[1] = _("S/MIME");
+ spath[2] = NULL;
+ smime_account_page.page.path = spath;
+ smime_account_page.page.create_widget = prefs_gpg_account_create_widget_func;
+ smime_account_page.page.destroy_widget = prefs_gpg_account_destroy_widget_func;
+ smime_account_page.page.save_page = prefs_gpg_account_save_func;
+ smime_account_page.page.weight = 30.0;
+
+ prefs_account_register_page((PrefsPage *) &smime_account_page);
tmp = g_getenv("GPG_AGENT_INFO");
if (tmp)
diff --git a/src/plugins/pgpcore/prefs_gpg.h b/src/plugins/pgpcore/prefs_gpg.h
@@ -50,6 +50,8 @@ struct GPGAccountConfig
{
SignKeyType sign_key;
gchar *sign_key_id;
+ SignKeyType smime_sign_key;
+ gchar *smime_sign_key_id;
};
void prefs_gpg_init(void);
diff --git a/src/plugins/pgpcore/select-keys.c b/src/plugins/pgpcore/select-keys.c
@@ -167,6 +167,9 @@ static void
destroy_key (gpointer data)
{
gpgme_key_t key = data;
+
+ debug_print("unref key %p\n", key);
+
gpgme_key_unref (key);
}
@@ -255,6 +258,7 @@ set_row (GtkCMCList *clist, gpgme_key_t key, gpgme_protocol_t proto)
row = gtk_cmclist_append (clist, (gchar**)text);
g_free (algo_buf);
+ gpgme_key_ref(key);
gtk_cmclist_set_row_data_full (clist, row, key, destroy_key);
}
@@ -298,8 +302,10 @@ fill_clist (struct select_keys_s *sk, const char *pattern, gpgme_protocol_t prot
update_progress (sk, ++running, pattern);
while ( !(err = gpgme_op_keylist_next ( ctx, &key )) ) {
gpgme_user_id_t uid = key->uids;
- if (!key->can_encrypt || key->revoked || key->expired || key->disabled)
+ if (!key->can_encrypt || key->revoked || key->expired || key->disabled) {
+ gpgme_key_unref(key);
continue;
+ }
debug_print ("%% %s:%d: insert\n", __FILE__ ,__LINE__ );
set_row (clist, key, proto );
for (; uid; uid = uid->next) {
@@ -349,7 +355,9 @@ fill_clist (struct select_keys_s *sk, const char *pattern, gpgme_protocol_t prot
if (exact_match && num_results == 1)
return last_key;
- gpgme_key_unref(last_key);
+ if (last_key != NULL)
+ gpgme_key_unref(last_key);
+
return NULL;
}
diff --git a/src/plugins/pgpcore/sgpgme.c b/src/plugins/pgpcore/sgpgme.c
@@ -572,14 +572,30 @@ gboolean sgpgme_setup_signers(gpgme_ctx_t ctx, PrefsAccount *account,
{
GPGAccountConfig *config;
const gchar *signer_addr = account->address;
+ SignKeyType sk;
+ gchar *skid;
+ gboolean smime = FALSE;
gpgme_signers_clear(ctx);
+ if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_CMS)
+ smime = TRUE;
+
if (from_addr)
signer_addr = from_addr;
config = prefs_gpg_account_get_config(account);
- switch(config->sign_key) {
+ if(smime) {
+ debug_print("sgpgme_setup_signers: S/MIME protocol\n");
+ sk = config->smime_sign_key;
+ skid = config->smime_sign_key_id;
+ } else {
+ debug_print("sgpgme_setup_signers: OpenPGP protocol\n");
+ sk = config->sign_key;
+ skid = config->sign_key_id;
+ }
+
+ switch(sk) {
case SIGN_KEY_DEFAULT:
debug_print("using default gnupg key\n");
break;
@@ -587,19 +603,19 @@ gboolean sgpgme_setup_signers(gpgme_ctx_t ctx, PrefsAccount *account,
debug_print("using key for %s\n", signer_addr);
break;
case SIGN_KEY_CUSTOM:
- debug_print("using key for %s\n", config->sign_key_id);
+ debug_print("using key for %s\n", skid);
break;
}
- if (config->sign_key != SIGN_KEY_DEFAULT) {
+ if (sk != SIGN_KEY_DEFAULT) {
const gchar *keyid;
gpgme_key_t key, found_key;
gpgme_error_t err;
- if (config->sign_key == SIGN_KEY_BY_FROM)
+ if (sk == SIGN_KEY_BY_FROM)
keyid = signer_addr;
- else if (config->sign_key == SIGN_KEY_CUSTOM)
- keyid = config->sign_key_id;
+ else if (sk == SIGN_KEY_CUSTOM)
+ keyid = skid;
else
goto bail;
diff --git a/src/prefs_account.c b/src/prefs_account.c
@@ -435,6 +435,9 @@ static PrefParam basic_param[] = {
{"password", NULL, &tmp_ac_prefs.passwd, P_PASSWORD,
NULL, NULL, NULL},
+ {"config_version", "-1", &tmp_ac_prefs.config_version, P_INT,
+ NULL, NULL, NULL},
+
{NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
};
diff --git a/src/prefs_account.h b/src/prefs_account.h
@@ -207,6 +207,8 @@ struct _PrefsAccount
struct _Folder *folder;
GHashTable *privacy_prefs;
SMTPSession *session;
+
+ gint config_version;
};
void prefs_account_init (void);
diff --git a/src/prefs_common.c b/src/prefs_common.c
@@ -41,6 +41,7 @@
#include "prefs_display_header.h"
#include "prefs_summary_column.h"
#include "prefs_folder_column.h"
+#include "prefs_migration.h"
#include "mainwindow.h"
#include "summaryview.h"
#include "folderview.h"
diff --git a/src/prefs_gtk.c b/src/prefs_gtk.c
@@ -440,6 +440,8 @@ void prefs_set_default(PrefParam *param)
if (param[i].defval != NULL)
*((gint *)param[i].data) =
(gint)atoi(param[i].defval);
+ else if (!strcmp(param[i].name, "config_version"))
+ *((gint *)param[i].data) = CLAWS_CONFIG_VERSION;
else
*((gint *)param[i].data) = 0;
break;
diff --git a/src/prefs_migration.c b/src/prefs_migration.c
@@ -34,14 +34,70 @@
#include "prefs_common.h"
#include "alertpanel.h"
-static void _update_config(gint version)
+static gint starting_config_version = 0;
+
+gboolean _version_check(gint ver)
{
- GList *cur;
- PrefsAccount *ac_prefs;
+ if (ver > CLAWS_CONFIG_VERSION) {
+ gchar *msg;
+ gchar *markup;
+ AlertValue av;
+
+ markup = g_strdup_printf(
+ "<a href=\"%s\"><span underline=\"none\">",
+ CONFIG_VERSIONS_URI);
+ msg = g_strdup_printf(
+ _("Your Claws Mail configuration is from a newer "
+ "version than the version which you are currently "
+ "using.\n\n"
+ "This is not recommended.\n\n"
+ "For further information see the %sClaws Mail "
+ "website%s.\n\n"
+ "Do you want to exit now?"),
+ markup, "</span></a>");
+ g_free(markup);
+ av = alertpanel_full(_("Configuration warning"), msg,
+ GTK_STOCK_NO, GTK_STOCK_YES, NULL,
+ FALSE, NULL,
+ ALERT_ERROR, G_ALERTALTERNATE);
+ g_free(msg);
+
+ if (av != G_ALERTDEFAULT)
+ return FALSE; /* abort startup */
+
+ return TRUE; /* hic sunt dracones */
+ }
+
+ return TRUE;
+}
+static void _update_config_common(gint version)
+{
debug_print("Updating config version %d to %d.\n", version, version + 1);
switch (version) {
+ case 1:
+
+ /* The autochk_interval preference is now
+ * interpreted as seconds instead of minutes */
+ prefs_common.autochk_itv *= 60;
+
+ break;
+
+ default:
+
+ /* NOOP */
+
+ break;
+ }
+}
+
+static void _update_config_account(PrefsAccount *ac_prefs, gint version)
+{
+ debug_print("Account '%s': Updating config version from %d to %d.\n",
+ ac_prefs->account_name, version, version + 1);
+
+ switch (version) {
case 0:
/* Removing A_APOP and A_RPOP from RecvProtocol enum,
@@ -54,64 +110,35 @@ static void _update_config(gint version)
* A_IMAP and the rest are from 3 up.
* We can't use the macros, since they may change in the
* future. Numbers do not change. :) */
- for (cur = account_get_list(); cur != NULL; cur = cur->next) {
- ac_prefs = (PrefsAccount *)cur->data;
- if (ac_prefs->protocol == 1) {
- ac_prefs->protocol = 0;
- } else if (ac_prefs->protocol > 2) {
- /* A_IMAP and above gets bumped down by 2. */
- ac_prefs->protocol -= 2;
- }
+ if (ac_prefs->protocol == 1) {
+ ac_prefs->protocol = 0;
+ } else if (ac_prefs->protocol > 2) {
+ /* A_IMAP and above gets bumped down by 2. */
+ ac_prefs->protocol -= 2;
}
break;
- case 1:
+ default:
- /* The autochk_interval preference is now
- * interpreted as seconds instead of minutes */
- prefs_common.autochk_itv *= 60;
+ /* NOOP */
break;
-
- default:
- break;
}
+
+ ac_prefs->config_version = version + 1;
}
-int prefs_update_config_version()
+int prefs_update_config_version_common()
{
gint ver = prefs_common_get_prefs()->config_version;
- if (ver > CLAWS_CONFIG_VERSION) {
- gchar *msg;
- gchar *markup;
- AlertValue av;
-
- markup = g_strdup_printf(
- "<a href=\"%s\"><span underline=\"none\">",
- CONFIG_VERSIONS_URI);
- msg = g_strdup_printf(
- _("Your Claws Mail configuration is from a newer "
- "version than the version which you are currently "
- "using.\n\n"
- "This is not recommended.\n\n"
- "For further information see the %sClaws Mail "
- "website%s.\n\n"
- "Do you want to exit now?"),
- markup, "</span></a>");
- g_free(markup);
- av = alertpanel_full(_("Configuration warning"), msg,
- GTK_STOCK_NO, GTK_STOCK_YES, NULL,
- FALSE, NULL,
- ALERT_ERROR, G_ALERTALTERNATE);
- g_free(msg);
-
- if (av != G_ALERTDEFAULT)
- return -1; /* abort startup */
+ /* Store the starting version number for other components'
+ * migration functions. */
+ starting_config_version = ver;
- return 0; /* hic sunt dracones */
- }
+ if (!_version_check(ver))
+ return -1;
debug_print("Starting config update at config_version %d.\n", ver);
if (ver == CLAWS_CONFIG_VERSION) {
@@ -120,10 +147,46 @@ int prefs_update_config_version()
}
while (ver < CLAWS_CONFIG_VERSION) {
- _update_config(ver++);
+ _update_config_common(ver++);
prefs_common_get_prefs()->config_version = ver;
}
debug_print("Config update done.\n");
return 1; /* update done */
}
+
+int prefs_update_config_version_accounts()
+{
+ GList *cur;
+ PrefsAccount *ac_prefs;
+
+ for (cur = account_get_list(); cur != NULL; cur = cur->next) {
+ ac_prefs = (PrefsAccount *)cur->data;
+
+ if (ac_prefs->config_version == -1) {
+ /* There was no config_version stored in accountrc, let's assume
+ * config_version same as clawsrc started at, to avoid breaking
+ * this account by "upgrading" it unnecessarily. */
+ debug_print("Account '%s': config_version not saved, using one from clawsrc: %d\n", ac_prefs->account_name, starting_config_version);
+ ac_prefs->config_version = starting_config_version;
+ }
+
+ gint ver = ac_prefs->config_version;
+
+ debug_print("Account '%s': Starting config update at config_version %d.\n", ac_prefs->account_name, ver);
+
+ if (!_version_check(ver))
+ return -1;
+
+ if (ver == CLAWS_CONFIG_VERSION) {
+ debug_print("Account '%s': No update necessary, already at latest config_version.\n", ac_prefs->account_name);
+ continue;
+ }
+
+ while (ver < CLAWS_CONFIG_VERSION) {
+ _update_config_account(ac_prefs, ver++);
+ }
+ }
+
+ return 1;
+}
diff --git a/src/prefs_migration.h b/src/prefs_migration.h
@@ -19,6 +19,7 @@
#ifndef __PREFS_MIGRATION_H__
#define __PREFS_MIGRATION_H__
-int prefs_update_config_version();
+int prefs_update_config_version_common();
+int prefs_update_config_version_accounts();
#endif /* __PREFS_MIGRATION_H__ */
diff --git a/src/quote_fmt.c b/src/quote_fmt.c
@@ -93,7 +93,7 @@ static gchar *quote_desc_strings[] = {
"|program{<span style=\"oblique\">sub_expr</span>}\n(|p{<span style=\"oblique\">sub_expr</span>})\n", N_("insert program output:\n<span style=\"oblique\">sub_expr</span> is evaluated as a command-line to get\nthe output from"), /* insert program output */
"|input{<span style=\"oblique\">sub_expr</span>}\n(|i{<span style=\"oblique\">sub_expr</span>})\n", N_("insert user input:\n<span style=\"oblique\">sub_expr</span> is a variable to be replaced by\nuser-entered text"), /* insert user input */
"|attach{<span style=\"oblique\">sub_expr</span>}\n(|a{<span style=\"oblique\">sub_expr</span>})", N_("attach file:\n<span style=\"oblique\">sub_expr</span> is evaluated as the path of the file to attach"), /* attach file */
- "|attach_output{<span style=\"oblique\">sub_expr</span>}\n(|A{<span style=\"oblique\">sub_expr</span>})", N_("attach file:\n<span style=\"oblique\">sub_expr</span> is evaluated as a command-line to get\nthe filename from"), /* attach file whose name's got from program output */
+ "|attach_program{<span style=\"oblique\">sub_expr</span>}\n(|A{<span style=\"oblique\">sub_expr</span>})", N_("attach file:\n<span style=\"oblique\">sub_expr</span> is evaluated as a command-line to get\nthe filename from"), /* attach file whose name's got from program output */
"", NULL,
N_("<span weight=\"bold\">definition of terms:</span>"), NULL,
"<span style=\"oblique\">expr</span>\n", N_("text that can contain any of the symbols or\ncommands above"),
diff --git a/src/summaryview.c b/src/summaryview.c
@@ -163,7 +163,8 @@ static void summary_update_status (SummaryView *summaryview);
static void summary_status_show (SummaryView *summaryview);
static void summary_set_column_titles (SummaryView *summaryview);
static void summary_set_ctree_from_list (SummaryView *summaryview,
- GSList *mlist);
+ GSList *mlist,
+ guint selected_msgnum);
static inline void summary_set_header (SummaryView *summaryview,
gchar *text[],
MsgInfo *msginfo);
@@ -1447,7 +1448,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item)
/* set ctree and hash table from the msginfo list, and
create the thread */
- summary_set_ctree_from_list(summaryview, mlist);
+ summary_set_ctree_from_list(summaryview, mlist, selected_msgnum);
g_slist_free(mlist);
@@ -3090,6 +3091,35 @@ static gboolean summary_thread_is_read(GNode *gnode)
return all_read;
}
+typedef struct _ThreadSelectedData {
+ guint msgnum;
+ gboolean is_selected;
+} ThreadSelectedData;
+
+static gboolean summary_update_is_selected(GNode *gnode, gpointer data)
+{
+ ThreadSelectedData *selected = (ThreadSelectedData *)data;
+ MsgInfo *msginfo = (MsgInfo *)gnode->data;
+
+ if (msginfo->msgnum == selected->msgnum) {
+ selected->is_selected = TRUE;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean summary_thread_is_selected(GNode *gnode, guint selected_msgnum)
+{
+ ThreadSelectedData selected;
+
+ selected.msgnum = selected_msgnum;
+ selected.is_selected = FALSE;
+ g_node_traverse(gnode, G_IN_ORDER, G_TRAVERSE_ALL, -1,
+ summary_update_is_selected, &selected);
+ return selected.is_selected;
+}
+
static gboolean summary_insert_gnode_func(GtkCMCTree *ctree, guint depth, GNode *gnode,
GtkCMCTreeNode *cnode, gpointer data)
{
@@ -3141,7 +3171,7 @@ static gboolean summary_insert_gnode_func(GtkCMCTree *ctree, guint depth, GNode
}
static void summary_set_ctree_from_list(SummaryView *summaryview,
- GSList *mlist)
+ GSList *mlist, guint selected_msgnum)
{
GtkCMCTree *ctree = GTK_CMCTREE(summaryview->ctree);
MsgInfo *msginfo;
@@ -3184,14 +3214,14 @@ static void summary_set_ctree_from_list(SummaryView *summaryview,
for (gnode = root->children; gnode != NULL;
gnode = gnode->next) {
- if (!summaryview->folder_item->hide_read_threads ||
- !summary_thread_is_read(gnode))
- {
- summary_find_thread_age(gnode);
- node = gtk_sctree_insert_gnode
- (ctree, NULL, node, gnode,
- summary_insert_gnode_func, summaryview);
- }
+ if (!summaryview->folder_item->hide_read_threads ||
+ !summary_thread_is_read(gnode) ||
+ summary_thread_is_selected(gnode, selected_msgnum)) {
+ summary_find_thread_age(gnode);
+ node = gtk_sctree_insert_gnode
+ (ctree, NULL, node, gnode,
+ summary_insert_gnode_func, summaryview);
+ }
}
g_node_destroy(root);