Write passwordstore into file more often, not just at exit.
[claws.git] / src / prefs_account.c
index 934a1cf6d562ba3d51332ee9363a3f029878ccb4..f31db873f3b9fcccc8dfdcf56449e135517ae059 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2013 Hiroyuki Yamamoto and the Claws Mail team
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2015 Hiroyuki Yamamoto and the Claws Mail team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -14,7 +14,6 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * 
  */
 
 #ifdef HAVE_CONFIG_H
@@ -64,6 +63,7 @@
 #include "privacy.h"
 #include "inputdialog.h"
 #include "ssl_certificate.h"
+#include "passwordstore.h"
 
 static gboolean cancelled;
 static gboolean new_account;
@@ -433,7 +433,7 @@ static PrefParam basic_param[] = {
         &basic_page.uid_entry, prefs_set_data_from_entry, prefs_set_entry},
 
        {"password", NULL, &tmp_ac_prefs.passwd, P_PASSWORD,
-        &basic_page.pass_entry, prefs_set_data_from_entry, prefs_set_entry},
+        NULL, NULL, NULL},
 
        {NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
 };
@@ -537,7 +537,7 @@ static PrefParam send_param[] = {
        {"smtp_user_id", NULL, &tmp_ac_prefs.smtp_userid, P_STRING,
         &send_page.smtp_uid_entry, prefs_set_data_from_entry, prefs_set_entry},
        {"smtp_password", NULL, &tmp_ac_prefs.smtp_passwd, P_PASSWORD,
-        &send_page.smtp_pass_entry, prefs_set_data_from_entry, prefs_set_entry},
+        NULL, NULL, NULL},
 
        {"pop_before_smtp", "FALSE", &tmp_ac_prefs.pop_before_smtp, P_BOOL,
         &send_page.pop_bfr_smtp_checkbtn,
@@ -741,13 +741,13 @@ static PrefParam ssl_param[] = {
         &ssl_page.entry_in_cert_file, prefs_set_data_from_entry, prefs_set_entry},
 
        {"in_ssl_client_cert_pass", "", &tmp_ac_prefs.in_ssl_client_cert_pass, P_PASSWORD,
-        &ssl_page.entry_in_cert_pass, prefs_set_data_from_entry, prefs_set_entry},
+        NULL, NULL, NULL},
 
        {"out_ssl_client_cert_file", "", &tmp_ac_prefs.out_ssl_client_cert_file, P_STRING,
         &ssl_page.entry_out_cert_file, prefs_set_data_from_entry, prefs_set_entry},
 
        {"out_ssl_client_cert_pass", "", &tmp_ac_prefs.out_ssl_client_cert_pass, P_PASSWORD,
-        &ssl_page.entry_out_cert_pass, prefs_set_data_from_entry, prefs_set_entry},
+        NULL, NULL, NULL},
 #else
        {"ssl_pop", "0", &tmp_ac_prefs.ssl_pop, P_ENUM,
         NULL, NULL, NULL},
@@ -1019,6 +1019,7 @@ static void basic_create_widget_func(PrefsPage * _page,
        GtkWidget *auto_configure_lbl;
        GtkListStore *menu;
        GtkTreeIter iter;
+       gchar *buf;
 
        struct BasicProtocol *protocol_optmenu;
        gint i;
@@ -1144,8 +1145,9 @@ static void basic_create_widget_func(PrefsPage * _page,
 
        no_imap_warn_icon = gtk_image_new_from_stock
                         (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
-       no_imap_warn_label = gtk_label_new(_("<span weight=\"bold\">Warning: this version of Claws Mail\n"
-                         "has been built without IMAP and News support.</span>"));
+       no_imap_warn_label = gtk_label_new(g_strconcat("<span weight=\"bold\">",
+                       _("Warning: this version of Claws Mail\n"
+                         "has been built without IMAP and News support."), "</span>", NULL));
        gtk_label_set_use_markup(GTK_LABEL(no_imap_warn_label), TRUE);
 
        gtk_box_pack_start(GTK_BOX (optmenubox), no_imap_warn_icon, FALSE, FALSE, 0);
@@ -1332,7 +1334,6 @@ static void basic_create_widget_func(PrefsPage * _page,
 
        if (new_account) {
                PrefsAccount *def_ac;
-               gchar *buf;
 
                prefs_set_dialog_to_default(basic_param);
                buf = g_strdup_printf(_("Account%d"), ac_prefs->account_id);
@@ -1359,9 +1360,16 @@ static void basic_create_widget_func(PrefsPage * _page,
                                g_free(id);
                        }
                }
-       } else
+       } else {
                prefs_set_dialog(basic_param);
 
+               /* Passwords are handled outside of PrefParams. */
+               buf = passwd_store_get_account(ac_prefs->account_id,
+                               PWS_ACCOUNT_RECV);
+               gtk_entry_set_text(GTK_ENTRY(page->pass_entry), buf);
+               g_free(buf);
+       }
+
        page->vbox = vbox1;
 
        page->page.widget = vbox1;
@@ -1578,12 +1586,14 @@ static void receive_create_widget_func(PrefsPage * _page,
 
        COMBOBOX_ADD (menu, _("Automatic"), 0);
        COMBOBOX_ADD (menu, NULL, 0);
-       COMBOBOX_ADD (menu, "LOGIN", IMAP_AUTH_LOGIN);
+       COMBOBOX_ADD (menu, _("Plain text"), IMAP_AUTH_PLAINTEXT);
        COMBOBOX_ADD (menu, "CRAM-MD5", IMAP_AUTH_CRAM_MD5);
        COMBOBOX_ADD (menu, "ANONYMOUS", IMAP_AUTH_ANON);
        COMBOBOX_ADD (menu, "GSSAPI", IMAP_AUTH_GSSAPI);
        COMBOBOX_ADD (menu, "DIGEST-MD5", IMAP_AUTH_DIGEST_MD5);
        COMBOBOX_ADD (menu, "SCRAM-SHA-1", IMAP_AUTH_SCRAM_SHA1);
+       COMBOBOX_ADD (menu, "PLAIN", IMAP_AUTH_PLAIN);
+       COMBOBOX_ADD (menu, "LOGIN", IMAP_AUTH_LOGIN);
 
        hbox1 = gtk_hbox_new (FALSE, 8);
        gtk_widget_show (hbox1);
@@ -1710,6 +1720,7 @@ static void send_create_widget_func(PrefsPage * _page,
        GtkWidget *pop_bfr_smtp_tm_spinbtn;
        GtkWidget *pop_auth_timeout_lbl;
        GtkWidget *pop_auth_minutes_lbl;
+       gchar *buf;
 
        vbox1 = gtk_vbox_new (FALSE, VSPACING);
        gtk_widget_show (vbox1);
@@ -1886,9 +1897,16 @@ static void send_create_widget_func(PrefsPage * _page,
 
        if (new_account) {
                prefs_set_dialog_to_default(send_param);
-       } else
+       } else {
                prefs_set_dialog(send_param);
 
+               /* Passwords are handled outside of PrefParams. */
+               buf = passwd_store_get_account(ac_prefs->account_id,
+                               PWS_ACCOUNT_SEND);
+               gtk_entry_set_text(GTK_ENTRY(page->smtp_pass_entry), buf);
+               g_free(buf);
+       }
+
        pop_bfr_smtp_tm_set_sens (NULL, NULL);
 
        page->vbox = vbox1;
@@ -2426,6 +2444,7 @@ static void ssl_create_widget_func(PrefsPage * _page,
        GtkWidget *hbox;
        GtkWidget *hbox_spc;
        GtkWidget *label;
+       gchar *buf;
 
        vbox1 = gtk_vbox_new (FALSE, VSPACING);
        gtk_widget_show (vbox1);
@@ -2555,7 +2574,7 @@ static void ssl_create_widget_func(PrefsPage * _page,
        gtk_box_pack_start (GTK_BOX (vbox1), vbox7, FALSE, FALSE, 0);
 
        PACK_CHECK_BUTTON(vbox7, ssl_certs_auto_accept_checkbtn,
-                         _("Automatically accept unknown valid SSL certificates"));
+                         _("Automatically accept valid SSL certificates"));
 
        PACK_CHECK_BUTTON(vbox7, use_nonblocking_ssl_checkbtn,
                          _("Use non-blocking SSL"));
@@ -2606,9 +2625,20 @@ static void ssl_create_widget_func(PrefsPage * _page,
 
        if (new_account) {
                prefs_set_dialog_to_default(ssl_param);
-       } else
+       } else {
                prefs_set_dialog(ssl_param);
 
+               /* Passwords are handled outside of PrefParams. */
+               buf = passwd_store_get_account(ac_prefs->account_id,
+                               PWS_ACCOUNT_RECV_CERT);
+               gtk_entry_set_text(GTK_ENTRY(page->entry_in_cert_pass), buf);
+               g_free(buf);
+               buf = passwd_store_get_account(ac_prefs->account_id,
+                               PWS_ACCOUNT_SEND_CERT);
+               gtk_entry_set_text(GTK_ENTRY(page->entry_out_cert_pass), buf);
+               g_free(buf);
+       }
+
        page->vbox = vbox1;
 
        page->page.widget = vbox1;
@@ -2942,6 +2972,12 @@ static gint prefs_basic_apply(void)
                                tmp_ac_prefs.account_name ? tmp_ac_prefs.account_name : "(null)");
        
        prefs_set_data_from_dialog(basic_param);
+
+       /* Passwords are stored outside of PrefParams. */
+       passwd_store_set_account(tmp_ac_prefs.account_id,
+                       PWS_ACCOUNT_RECV,
+                       gtk_entry_get_text(GTK_ENTRY(basic_page.pass_entry)),
+                       FALSE);
        
        if (protocol == A_IMAP4 || protocol == A_NNTP) {
                new_id = g_strdup_printf("#%s/%s",
@@ -2965,6 +3001,13 @@ static gint prefs_receive_apply(void)
 static gint prefs_send_apply(void)
 {
        prefs_set_data_from_dialog(send_param);
+
+       /* Passwords are stored outside of PrefParams. */
+       passwd_store_set_account(tmp_ac_prefs.account_id,
+                       PWS_ACCOUNT_SEND,
+                       gtk_entry_get_text(GTK_ENTRY(send_page.smtp_pass_entry)),
+                       FALSE);
+
        return 0;
 }
 
@@ -2990,6 +3033,17 @@ static gint prefs_privacy_apply(void)
 static gint prefs_ssl_apply(void)
 {
        prefs_set_data_from_dialog(ssl_param);
+
+       /* Passwords are stored outside of PrefParams. */
+       passwd_store_set_account(tmp_ac_prefs.account_id,
+                       PWS_ACCOUNT_RECV_CERT,
+                       gtk_entry_get_text(GTK_ENTRY(ssl_page.entry_in_cert_pass)),
+                       FALSE);
+       passwd_store_set_account(tmp_ac_prefs.account_id,
+                       PWS_ACCOUNT_SEND_CERT,
+                       gtk_entry_get_text(GTK_ENTRY(ssl_page.entry_out_cert_pass)),
+                       FALSE);
+
        return 0;
 }
 #endif
@@ -3357,26 +3411,27 @@ static gboolean sslcert_get_client_cert_hook(gpointer source, gpointer data)
 {
        SSLClientCertHookData *hookdata = (SSLClientCertHookData *)source;
        PrefsAccount *account = (PrefsAccount *)hookdata->account;
+       gchar *pwd_id;
 
        hookdata->cert_path = NULL;
        hookdata->password = NULL;
 
        if (!g_list_find(account_get_list(), account)) {
-               g_warning("can't find sock account\n");
+               g_warning("can't find account");
                return TRUE;
        }
        
        if (hookdata->is_smtp) {
                if (account->out_ssl_client_cert_file && *account->out_ssl_client_cert_file)
                        hookdata->cert_path = account->out_ssl_client_cert_file;
-               if (account->out_ssl_client_cert_pass && *account->out_ssl_client_cert_pass)
-                       hookdata->password = account->out_ssl_client_cert_pass;
+               pwd_id = PWS_ACCOUNT_SEND_CERT;
        } else {
                if (account->in_ssl_client_cert_file && *account->in_ssl_client_cert_file)
                        hookdata->cert_path = account->in_ssl_client_cert_file;
-               if (account->in_ssl_client_cert_pass && *account->in_ssl_client_cert_pass)
-                       hookdata->password = account->in_ssl_client_cert_pass;
+               pwd_id = PWS_ACCOUNT_RECV_CERT;
        }
+
+       hookdata->password = passwd_store_get_account(account->account_id, pwd_id);
        return TRUE;
 }
 
@@ -3511,7 +3566,7 @@ void prefs_account_read_config(PrefsAccount *ac_prefs, const gchar *label)
        *ac_prefs = tmp_ac_prefs;
        while (*p && !g_ascii_isdigit(*p)) p++;
        id = atoi(p);
-       if (id < 0) g_warning("wrong account id: %d\n", id);
+       if (id < 0) g_warning("wrong account id: %d", id);
        ac_prefs->account_id = id;
 
        if (ac_prefs->protocol == A_APOP) {
@@ -3542,6 +3597,25 @@ void prefs_account_read_config(PrefsAccount *ac_prefs, const gchar *label)
                privacy_prefs = NULL;
        }
 
+       if (ac_prefs->passwd != NULL && strlen(ac_prefs->passwd) > 1) {
+               passwd_store_set_account(ac_prefs->account_id,
+                               PWS_ACCOUNT_RECV, ac_prefs->passwd, TRUE);
+       }
+       if (ac_prefs->smtp_passwd != NULL && strlen(ac_prefs->smtp_passwd) > 1) {
+               passwd_store_set_account(ac_prefs->account_id,
+                               PWS_ACCOUNT_SEND, ac_prefs->smtp_passwd, TRUE);
+       }
+       if (ac_prefs->in_ssl_client_cert_pass != NULL
+                       && strlen(ac_prefs->in_ssl_client_cert_pass) > 1) {
+               passwd_store_set_account(ac_prefs->account_id,
+                               PWS_ACCOUNT_RECV_CERT, ac_prefs->in_ssl_client_cert_pass, TRUE);
+       }
+       if (ac_prefs->out_ssl_client_cert_pass != NULL
+                       && strlen(ac_prefs->out_ssl_client_cert_pass) > 1) {
+               passwd_store_set_account(ac_prefs->account_id,
+                               PWS_ACCOUNT_SEND_CERT, ac_prefs->out_ssl_client_cert_pass, TRUE);
+       }
+
        ac_prefs->receive_in_progress = FALSE;
 
        prefs_custom_header_read_config(ac_prefs);
@@ -3563,7 +3637,7 @@ static void create_privacy_prefs(gpointer key, gpointer _value, gpointer user_da
 
 #define WRITE_PARAM(PARAM_TABLE) \
                if (prefs_write_param(PARAM_TABLE, pfile->fp) < 0) { \
-                       g_warning("failed to write configuration to file\n"); \
+                       g_warning("failed to write configuration to file"); \
                        prefs_file_close_revert(pfile); \
                        g_free(privacy_prefs); \
                        privacy_prefs = NULL; \
@@ -3618,7 +3692,9 @@ void prefs_account_write_config_all(GList *account_list)
        }
 
        if (prefs_file_close(pfile) < 0)
-               g_warning("failed to write configuration to file\n");
+               g_warning("failed to write configuration to file");
+
+       passwd_store_write_config();
 }
 #undef WRITE_PARAM
 
@@ -3730,7 +3806,7 @@ PrefsAccount *prefs_account_open(PrefsAccount *ac_prefs, gboolean *dirty)
 
        prefswindow_open_full(title, prefs_pages, ac_prefs, destroy_dialog,
                        &prefs_common.editaccountwin_width, &prefs_common.editaccountwin_height,
-                       TRUE, NULL, NULL);
+                       TRUE, NULL, NULL, NULL);
        g_free(title);
        gtk_main();
 
@@ -3816,7 +3892,6 @@ static void prefs_account_select_folder_cb(GtkWidget *widget, gpointer data)
 static void auto_configure_cb (GtkWidget *widget, gpointer data)
 {
        gchar *address = NULL;
-       const gchar *domain = NULL;
        AutoConfigureData *recv_data;
        AutoConfigureData *send_data;
        static GCancellable *recv_cancel = NULL;
@@ -3848,8 +3923,8 @@ static void auto_configure_cb (GtkWidget *widget, gpointer data)
                g_free(address);
                gtk_label_set_text(GTK_LABEL(basic_page.auto_configure_lbl),
                           _("Failed (wrong address)"));
+               return;
        }
-       domain = strchr(address, '@') + 1;
 
        if (protocol == A_POP3 || protocol == A_IMAP4) {
                recv_data = g_new0(AutoConfigureData, 1);
@@ -3861,7 +3936,7 @@ static void auto_configure_cb (GtkWidget *widget, gpointer data)
                case A_POP3:
                        recv_data->ssl_service = "pop3s";
                        recv_data->tls_service = "pop3";
-                       recv_data->domain = g_strdup(domain);
+                       recv_data->address = g_strdup(address);
                        recv_data->hostname_entry = GTK_ENTRY(basic_page.recvserv_entry);
                        recv_data->set_port = GTK_TOGGLE_BUTTON(advanced_page.popport_checkbtn);
                        recv_data->port = GTK_SPIN_BUTTON(advanced_page.popport_spinbtn);
@@ -3869,11 +3944,12 @@ static void auto_configure_cb (GtkWidget *widget, gpointer data)
                        recv_data->ssl_checkbtn = GTK_TOGGLE_BUTTON(ssl_page.pop_ssltunnel_radiobtn);
                        recv_data->default_port = 110;
                        recv_data->default_ssl_port = 995;
+                       recv_data->uid_entry = GTK_ENTRY(basic_page.uid_entry);
                        break;
                case A_IMAP4:
                        recv_data->ssl_service = "imaps";
                        recv_data->tls_service = "imap";
-                       recv_data->domain = g_strdup(domain);
+                       recv_data->address = g_strdup(address);
                        recv_data->hostname_entry = GTK_ENTRY(basic_page.recvserv_entry);
                        recv_data->set_port = GTK_TOGGLE_BUTTON(advanced_page.imapport_checkbtn);
                        recv_data->port = GTK_SPIN_BUTTON(advanced_page.imapport_spinbtn);
@@ -3881,6 +3957,7 @@ static void auto_configure_cb (GtkWidget *widget, gpointer data)
                        recv_data->ssl_checkbtn = GTK_TOGGLE_BUTTON(ssl_page.imap_ssltunnel_radiobtn);
                        recv_data->default_port = 143;
                        recv_data->default_ssl_port = 993;
+                       recv_data->uid_entry = GTK_ENTRY(basic_page.uid_entry);
                        break;
                default:
                        cm_return_if_fail(FALSE);
@@ -3896,7 +3973,7 @@ static void auto_configure_cb (GtkWidget *widget, gpointer data)
 
        send_data->ssl_service = NULL;
        send_data->tls_service = "submission";
-       send_data->domain = g_strdup(domain);
+       send_data->address = g_strdup(address);
        send_data->hostname_entry = GTK_ENTRY(basic_page.smtpserv_entry);
        send_data->set_port = GTK_TOGGLE_BUTTON(advanced_page.smtpport_checkbtn);
        send_data->port = GTK_SPIN_BUTTON(advanced_page.smtpport_spinbtn);
@@ -3904,6 +3981,7 @@ static void auto_configure_cb (GtkWidget *widget, gpointer data)
        send_data->ssl_checkbtn = NULL;
        send_data->default_port = 25;
        send_data->default_ssl_port = -1;
+       send_data->uid_entry = NULL;
        send_data->auth_checkbtn = GTK_TOGGLE_BUTTON(send_page.smtp_auth_checkbtn);
 
        auto_configure_service(send_data);