* add checks that session != NULL
[modest] / src / modest-tny-account-store.c
index 1dc8cef..9d46e75 100644 (file)
@@ -60,7 +60,7 @@
 
 #ifdef MODEST_PLATFORM_MAEMO
 #include <tny-maemo-conic-device.h>
-#ifdef MODEST_HILDON_VERSION_0
+#ifdef MODEST_HAVE_HILDON0_WIDGETS
 #include <hildon-widgets/hildon-note.h>
 #include <hildon-widgets/hildon-banner.h>
 #else
@@ -81,9 +81,9 @@ static void    modest_tny_account_store_instance_init (ModestTnyAccountStore *ob
 static void    modest_tny_account_store_init          (gpointer g, gpointer iface_data);
 
 
-static void
-get_server_accounts  (TnyAccountStore *self, TnyList *list, TnyAccountType type);
-
+static void    get_server_accounts                    (TnyAccountStore *self, 
+                                                      TnyList *list, 
+                                                      TnyAccountType type);
 
 /* list my signals */
 enum {
@@ -244,6 +244,23 @@ account_list_free (GSList *accounts)
        g_slist_free (accounts);
 }
 
+
+
+/* disconnect the list of TnyAccounts */
+static void
+account_list_disconnect (GSList *accounts)
+{
+       GSList *cursor = accounts;
+
+       while (cursor) {
+               if (TNY_IS_CAMEL_ACCOUNT(cursor->data))  /* check twice... */
+                       tny_camel_account_set_online (TNY_CAMEL_ACCOUNT(cursor->data), FALSE, NULL);
+               cursor = g_slist_next (cursor);
+       }
+}
+
+
+
 static void
 recreate_all_accounts (ModestTnyAccountStore *self)
 {
@@ -317,37 +334,55 @@ on_vfs_volume_unmounted(GnomeVFSVolumeMonitor *volume_monitor,
 }
 
 static void
-on_account_removed (ModestAccountMgr *acc_mgr, const gchar *account, gboolean server_account,
+on_account_removed (ModestAccountMgr *acc_mgr, 
+                   const gchar *account,
+                   gboolean server_account,
                    gpointer user_data)
 {
        ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(user_data);
+       TnyAccount *store_account;
+       
+       /* Clear the account cache */
+       store_account = modest_tny_account_store_get_tny_account_by  (self, 
+                                                                     MODEST_TNY_ACCOUNT_STORE_QUERY_NAME, 
+                                                                     account);
+       if (store_account) {
+               tny_store_account_delete_cache (TNY_STORE_ACCOUNT (store_account));
+               
+               g_signal_emit (G_OBJECT (self), 
+                                        tny_account_store_signals [TNY_ACCOUNT_STORE_ACCOUNT_REMOVED], 
+                                        0, store_account);
+
+               g_object_unref (store_account);
+       } else
+               g_printerr ("modest: cannot find server account for %s", account);
        
-       /* FIXME: make this more finegrained; changes do not really affect _all_
-        * accounts, and some do not affect tny accounts at all (such as 'last_update')
+       /* FIXME: make this more finegrained; changes do not
+        * really affect _all_ accounts, and some do not
+        * affect tny accounts at all (such as 'last_update')
         */
-       if (server_account)
-               recreate_all_accounts (self);
-       
+       recreate_all_accounts (self);
+
        g_signal_emit (G_OBJECT(self), signals[ACCOUNT_UPDATE_SIGNAL], 0,
                       account);
 }
 
 static void
 on_account_changed (ModestAccountMgr *acc_mgr, const gchar *account,
-                   const gchar *key, gboolean server_account, gpointer user_data)
+                   const GSList *keys, gboolean server_account, gpointer user_data)
 
 {
        ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(user_data);
        
        /* Ignore the change if it's a change in the last_updated value */
-       if (g_str_has_suffix (key, MODEST_ACCOUNT_LAST_UPDATED))
+       if (g_slist_length ((GSList *)keys) == 1 &&
+           g_str_has_suffix ((const gchar *) keys->data, MODEST_ACCOUNT_LAST_UPDATED))
                return;
 
        /* FIXME: make this more finegrained; changes do not really affect _all_
-        * accounts, and some do not affect tny accounts at all (such as 'last_update')
+        * accounts
         */
-       if (server_account)
-               recreate_all_accounts (self);
+       recreate_all_accounts (self);
 
        g_signal_emit (G_OBJECT(self), signals[ACCOUNT_UPDATE_SIGNAL], 0,
                       account);
@@ -363,13 +398,15 @@ get_account_store_for_account (TnyAccount *account)
 
 /* This callback will be called by Tinymail when it needs the password
  * from the user, for instance if the password was not remembered.
+ * It also calls forget_password() before calling this,
+ * so that we clear wrong passwords out of our account settings.
  * Note that TnyAccount here will be the server account. */
 static gchar*
-get_password (TnyAccount *account, const gchar *prompt, gboolean *cancel)
+get_password (TnyAccount *account, const gchar * prompt_not_used, gboolean *cancel)
 {
        /* Initialize the output parameter: */
-       if (cancel)
-         *cancel = FALSE;
+         
+       g_return_val_if_fail (account, NULL);
          
        const gchar *key;
        const TnyAccountStore *account_store;
@@ -379,10 +416,22 @@ get_password (TnyAccount *account, const gchar *prompt, gboolean *cancel)
        gchar *pwd = NULL;
        gpointer pwd_ptr;
        gboolean already_asked;
-       
+
+       if (cancel)
+               *cancel = FALSE;
+               
        key           = tny_account_get_id (account);
        account_store = TNY_ACCOUNT_STORE(get_account_store_for_account (account));
-       
+
+       if (!key || !account_store) {
+               g_warning ("BUG: could not retrieve account_store for account %s",
+                          key ? key : "<NULL>");
+               if (cancel)
+                       *cancel = TRUE;
+               
+               return NULL;
+       }
+
        self = MODEST_TNY_ACCOUNT_STORE (account_store);
         priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
        
@@ -390,7 +439,8 @@ get_password (TnyAccount *account, const gchar *prompt, gboolean *cancel)
        /* is it in the hash? if it's already there, it must be wrong... */
        pwd_ptr = (gpointer)&pwd; /* pwd_ptr so the compiler does not complained about
                                   * type-punned ptrs...*/
-       already_asked = g_hash_table_lookup_extended (priv->password_hash,
+       already_asked = priv->password_hash && 
+                               g_hash_table_lookup_extended (priv->password_hash,
                                                      key,
                                                      NULL,
                                                      (gpointer*)&pwd_ptr);
@@ -413,18 +463,25 @@ get_password (TnyAccount *account, const gchar *prompt, gboolean *cancel)
                gboolean remember = FALSE;
                pwd = NULL;
                
-               /* Note that we ignore the returned username here,
-                * because it is enough that it will be stored in gconf 
-                * by the signal handler. */
                g_signal_emit (G_OBJECT(self), signals[PASSWORD_REQUESTED_SIGNAL], 0,
                               account_id, /* server_account_name */
                               &username, &pwd, cancel, &remember);
                
                if (!*cancel) {
-                       if (remember)
+                       /* The password will be returned as the result,
+                        * but we need to tell tinymail about the username too: */
+                       tny_account_set_user (account, username);
+                       
+                       if (remember) {
+                               printf ("%s: Storing username=%s, password=%s\n", 
+                                       __FUNCTION__, username, pwd);
+                               modest_account_mgr_set_string (priv->account_mgr,key,
+                                                              MODEST_ACCOUNT_USERNAME,
+                                                              username, TRUE);
                                modest_account_mgr_set_string (priv->account_mgr,key,
                                                               MODEST_ACCOUNT_PASSWORD,
                                                               pwd, TRUE);
+                       }
                        /* We need to dup the string even knowing that
                           it's already a dup of the contents of an
                           entry, because it if it's wrong, then camel
@@ -504,6 +561,12 @@ modest_tny_account_store_finalize (GObject *obj)
                priv->device = NULL;
        }
 
+       /* disconnect all accounts when we are destroyed */
+       g_debug ("modest: disconnecting all store accounts");
+       account_list_disconnect (priv->store_accounts);
+       g_debug ("modest: disconnecting all transport accounts");
+       account_list_disconnect (priv->transport_accounts);
+               
        /* this includes the local folder */
        account_list_free (priv->store_accounts);
        priv->store_accounts = NULL;
@@ -525,7 +588,7 @@ modest_tny_account_store_new (ModestAccountMgr *account_mgr, TnyDevice *device)
 
        GObject *obj;
        ModestTnyAccountStorePrivate *priv;
-       TnyList *list; 
+//     TnyList *list; 
        
        g_return_val_if_fail (account_mgr, NULL);
        g_return_val_if_fail (device, NULL);
@@ -537,17 +600,14 @@ modest_tny_account_store_new (ModestAccountMgr *account_mgr, TnyDevice *device)
        priv->device = g_object_ref (device);
        
        priv->session = tny_session_camel_new (TNY_ACCOUNT_STORE(obj));
+       if (!priv->session) {
+               g_warning ("failed to get TnySessionCamel");
+               return NULL;
+       }
        
        tny_session_camel_set_ui_locker (priv->session,  tny_gtk_lockable_new ());
-       /* FIXME: unref this in the end? */
        tny_session_camel_set_async_connecting (priv->session, TRUE);
-       
-       /* force a cache fill... ugly */
-       list = TNY_LIST(tny_simple_list_new());
-       tny_account_store_get_accounts (TNY_ACCOUNT_STORE(obj), list,
-                                       TNY_ACCOUNT_STORE_BOTH);
-       g_object_unref(list);
-       
+               
        /* Connect signals */
        g_signal_connect (G_OBJECT(account_mgr), "account_changed",
                                       G_CALLBACK (on_account_changed), obj);
@@ -606,8 +666,9 @@ create_per_account_local_outbox_folders (TnyAccountStore *self)
                                
                accounts = g_slist_append (accounts, tny_account_outbox); /* cache it */
        };
-       
-       g_slist_free (account_names);
+
+       modest_account_mgr_free_account_names (account_names);
+       account_names = NULL;
        
        priv->store_accounts_outboxes = accounts;
 }
@@ -620,8 +681,6 @@ static void
 get_server_accounts  (TnyAccountStore *self, TnyList *list, TnyAccountType type)
 {
        g_return_if_fail (self);
-       
-       /* printf ("DEBUG: %s: list=%p, type=%d\n", __FUNCTION__, list, type); */
                
        ModestTnyAccountStorePrivate *priv = 
                MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
@@ -635,8 +694,8 @@ get_server_accounts  (TnyAccountStore *self, TnyList *list, TnyAccountType type)
                        return;
        }
        
-       GSList                       *account_names = NULL, *cursor = NULL;
-       GSList                       *accounts = NULL;
+       GSList *account_names = NULL, *cursor = NULL;
+       GSList *accounts = NULL;
 
        /* These are account names, not server_account names */
        account_names = modest_account_mgr_account_names (priv->account_mgr,FALSE);
@@ -748,13 +807,11 @@ get_server_accounts  (TnyAccountStore *self, TnyList *list, TnyAccountType type)
                        iter_account_names = g_slist_next (iter_account_names);
                }               
        }
-       
-       g_slist_free (account_names);
+
+       /* free the account_names */
+       modest_account_mgr_free_account_names (account_names);
        account_names = NULL;
-       
-       /* TODO: Delete the strings in the GSList */
-       
-       
+
        /* We also create a per-account local outbox folder (a _store_ account) 
         * for each _transport_ account. */
        if (type == TNY_ACCOUNT_TYPE_TRANSPORT) {
@@ -791,11 +848,13 @@ get_server_accounts  (TnyAccountStore *self, TnyList *list, TnyAccountType type)
                                g_object_ref (outbox_account);
                                accounts = g_slist_append (accounts, outbox_account);
                        }
+               }
+               
+               /* Add a merged folder, merging all the per-account outbox folders: */
+               modest_tny_local_folders_account_add_merged_outbox_folders (
+                       MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (tny_account), priv->store_accounts_outboxes);
                        
-                       /* Add a merged folder, merging all the per-account outbox folders: */
-                       modest_tny_local_folders_account_add_merged_outbox_folders (
-                               MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (tny_account), priv->store_accounts_outboxes);
-       
+               if (priv->store_accounts_outboxes) {
                        /* We have finished with this temporary list, so free it: */
                        account_list_free (priv->store_accounts_outboxes);
                        priv->store_accounts_outboxes = NULL;
@@ -886,35 +945,9 @@ modest_tny_account_store_get_device (TnyAccountStore *self)
 static TnyAccount*
 modest_tny_account_store_find_account_by_url (TnyAccountStore *self, const gchar* url_string)
 {
-       TnyAccount *account = NULL;
-       ModestTnyAccountStorePrivate *priv;     
-       GSList *cursor;
-       
-       g_return_val_if_fail (self, NULL);
-       g_return_val_if_fail (url_string, NULL);
-       
-       priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
-
-       for (cursor = priv->store_accounts; cursor ; cursor = cursor->next) {
-               if (tny_account_matches_url_string (TNY_ACCOUNT(cursor->data), url_string)) {
-                       account = TNY_ACCOUNT(cursor->data);
-                       break;
-               }
-       }
-
-       if (!account) {
-               for (cursor = priv->transport_accounts; !account && cursor ; cursor = cursor->next) {
-                       if (tny_account_matches_url_string (TNY_ACCOUNT(cursor->data), url_string)) {
-                               account = TNY_ACCOUNT(cursor->data);
-                               break;
-                       }
-               }
-       }
-
-       if (account)
-               g_object_ref (G_OBJECT(account));
-
-       return account;
+       return modest_tny_account_store_get_tny_account_by (MODEST_TNY_ACCOUNT_STORE (self), 
+                                                           MODEST_TNY_ACCOUNT_STORE_QUERY_URL,
+                                                           url_string);
 }
 
 
@@ -949,14 +982,16 @@ modest_tny_account_store_alert (TnyAccountStore *self, TnyAlertType type,
                 * specific dialog messages from Chapter 12 of the UI spec.
                 */
                case TNY_ACCOUNT_STORE_ERROR_UNKNOWN_ALERT: 
-                   g_debug ("%s: Handling GError domain=%d, code=%d, message=%s", 
-                               __FUNCTION__, error->domain, error->code, error->message);
+                       /* This debug output is useful. Please keep it uncommented until 
+                        * we have fixed the problems in this function: */
+                   g_debug ("%s: Handling GError domain=%d, code=%d, message=%s", 
+                               __FUNCTION__, error->domain, error->code, error->message);
                        
                        /* TODO: Remove the internal error message for the real release.
                         * This is just so the testers can give us more information: */
                        /* prompt = _("Modest account not yet fully configured."); */
                        prompt = g_strdup_printf(
-                               "%s\n (Internal error message, often very misleading:\n%s", 
+                               "%s\n (Internal error message, often very misleading):\n%s", 
                                _("Incorrect Account Settings"), 
                                error->message);
                                
@@ -1097,36 +1132,84 @@ modest_tny_account_store_get_session  (TnyAccountStore *self)
 }
 
 
+
 TnyAccount*
-modest_tny_account_store_get_tny_account_by_id  (ModestTnyAccountStore *self, const gchar *id)
+modest_tny_account_store_get_tny_account_by (ModestTnyAccountStore *self, 
+                                            ModestTnyAccountStoreQueryType type,
+                                            const gchar *str)
 {
        TnyAccount *account = NULL;
        ModestTnyAccountStorePrivate *priv;     
        GSList *cursor;
-
+       const gchar *val = NULL;
+       TnyList* list; 
+       
+       
        g_return_val_if_fail (self, NULL);
-       g_return_val_if_fail (id, NULL);
+       g_return_val_if_fail (str, NULL);
        
        priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
 
+       /* fill the caches, as that may not have happened yet */
+       list = TNY_LIST(tny_simple_list_new());
+       modest_tny_account_store_get_accounts  (TNY_ACCOUNT_STORE(self),
+                                               list, TNY_ACCOUNT_STORE_BOTH);
+       g_object_unref (list);
 
+       
+       
+       /* Search in store accounts */
        for (cursor = priv->store_accounts; cursor ; cursor = cursor->next) {
-               const gchar *acc_id = tny_account_get_id (TNY_ACCOUNT(cursor->data));
-               if (acc_id && strcmp (acc_id, id) == 0) {
-                       account = TNY_ACCOUNT(cursor->data);
+               switch (type) {
+               case MODEST_TNY_ACCOUNT_STORE_QUERY_ID:
+                       val = tny_account_get_id (TNY_ACCOUNT(cursor->data));
+                       break;
+               case MODEST_TNY_ACCOUNT_STORE_QUERY_NAME:
+                       val = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT(cursor->data));
+                       break;
+               case MODEST_TNY_ACCOUNT_STORE_QUERY_URL:
+                       val = tny_account_get_url_string (TNY_ACCOUNT(cursor->data));
                        break;
                }
+               
+               if (type == MODEST_TNY_ACCOUNT_STORE_QUERY_URL && 
+                   tny_account_matches_url_string (TNY_ACCOUNT(cursor->data), str)) {
+                       account = TNY_ACCOUNT (cursor->data);
+                       goto end;
+               } else {
+                       if (strcmp (val, str) == 0) {
+                               account = TNY_ACCOUNT(cursor->data);
+                               goto end;
+                       }
+               }
        }
                
        /* if we already found something, no need to search the transport accounts */
        for (cursor = priv->transport_accounts; !account && cursor ; cursor = cursor->next) {
-               const gchar *acc_id = tny_account_get_id (TNY_ACCOUNT(cursor->data));
-               if (acc_id && strcmp (acc_id, id) == 0) {
-                       account = TNY_ACCOUNT(cursor->data);
+               switch (type) {
+               case MODEST_TNY_ACCOUNT_STORE_QUERY_ID:
+                       val = tny_account_get_id (TNY_ACCOUNT(cursor->data));
+                       break;
+               case MODEST_TNY_ACCOUNT_STORE_QUERY_NAME:
+                       val = tny_account_get_name (TNY_ACCOUNT(cursor->data));
+                       break;
+               case MODEST_TNY_ACCOUNT_STORE_QUERY_URL:
+                       val = tny_account_get_url_string (TNY_ACCOUNT(cursor->data));
                        break;
                }
+               
+               if (type == MODEST_TNY_ACCOUNT_STORE_QUERY_URL && 
+                   tny_account_matches_url_string (TNY_ACCOUNT(cursor->data), val)) {
+                       account = TNY_ACCOUNT (cursor->data);
+                       goto end;
+               } else {
+                       if (strcmp (val, str) == 0) {
+                               account = TNY_ACCOUNT(cursor->data);
+                               goto end;
+                       }
+               }
        }
-
+ end:
        if (account)
                g_object_ref (G_OBJECT(account));
        
@@ -1159,10 +1242,10 @@ modest_tny_account_store_get_server_account (ModestTnyAccountStore *self,
                }
        } else {
                ModestAccountData *account_data;
-
                account_data = modest_account_mgr_get_account_data (priv->account_mgr, account_name);
                if (!account_data) {
-                       g_printerr ("modest: %s: cannot get account data for account '%s'\n", __FUNCTION__, account_name);
+                       g_printerr ("modest: %s: cannot get account data for account '%s'\n", __FUNCTION__,
+                                   account_name);
                        return NULL;
                }
 
@@ -1178,7 +1261,7 @@ modest_tny_account_store_get_server_account (ModestTnyAccountStore *self,
                g_printerr ("modest: could not get an id for account %s\n",
                            account_name);
        else    
-               account = modest_tny_account_store_get_tny_account_by_id (self, id);
+               account = modest_tny_account_store_get_tny_account_by (self, MODEST_TNY_ACCOUNT_STORE_QUERY_ID, id);
 
        if (!account)
                g_printerr ("modest: could not get tny %s account for %s (id=%s)\n",
@@ -1225,7 +1308,9 @@ get_smtp_specific_transport_account_for_open_connection (ModestTnyAccountStore *
                return NULL; /* No connection-specific SMTP server was specified for this connection. */
        }
                
-       TnyAccount* account = modest_tny_account_store_get_tny_account_by_id (self, server_account_name);
+       TnyAccount* account = modest_tny_account_store_get_tny_account_by (self, 
+                                                                          MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
+                                                                          server_account_name);
 
        /* printf ("DEBUG: %s: account=%p\n", __FUNCTION__, account); */
        g_free (server_account_name);   
@@ -1263,14 +1348,30 @@ modest_tny_account_store_get_transport_account_for_open_connection (ModestTnyAcc
        return account;
 }
 
-gboolean modest_tny_account_is_virtual_local_folders (TnyAccount *self)
+gboolean
+modest_tny_account_is_virtual_local_folders (TnyAccount *self)
 {
        /* We should make this more sophisticated if we ever use ModestTnyLocalFoldersAccount 
         * for anything else. */
        return MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (self);
 }
 
-TnyAccount* modest_tny_account_store_get_local_folders_account (TnyAccountStore *self)
+
+gboolean
+modest_tny_account_is_memory_card_account (TnyAccount *self)
+{
+       if (!self)
+               return FALSE;
+
+       const gchar* account_id = tny_account_get_id (self);
+       if (!account_id)
+               return FALSE;
+       
+       return (strcmp (account_id, MODEST_MMC_ACCOUNT_ID) == 0);
+}
+
+TnyAccount*
+modest_tny_account_store_get_local_folders_account (TnyAccountStore *self)
 {
        TnyAccount *account = NULL;
        ModestTnyAccountStorePrivate *priv;     
@@ -1293,3 +1394,5 @@ TnyAccount* modest_tny_account_store_get_local_folders_account (TnyAccountStore
        
        return account;
 }
+
+