* Fixes NB#91689. fixes a wrong check for ASCII
[modest] / src / modest-tny-local-folders-account.c
1 /* Copyright (c) 2007, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30
31 #include <string.h>
32 #include <stdio.h>
33 #include <config.h>
34 #include <glib/gi18n.h>
35 #include <tny-error.h>
36 #include <modest-tny-local-folders-account.h>
37 #include <modest-tny-outbox-account.h>
38 #include <modest-tny-folder.h>
39 #include <tny-camel-folder.h>
40 #include <tny-merge-folder.h>
41 #include <tny-simple-list.h>
42 #include <tny-gtk-lockable.h>
43
44 G_DEFINE_TYPE (ModestTnyLocalFoldersAccount, 
45         modest_tny_local_folders_account, 
46         TNY_TYPE_CAMEL_STORE_ACCOUNT);
47
48 #define TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE(o) \
49   (G_TYPE_INSTANCE_GET_PRIVATE ((o), MODEST_TYPE_TNY_LOCAL_FOLDERS_ACCOUNT, ModestTnyLocalFoldersAccountPrivate))
50
51 typedef struct _ModestTnyLocalFoldersAccountPrivate ModestTnyLocalFoldersAccountPrivate;
52
53 struct _ModestTnyLocalFoldersAccountPrivate
54 {
55         TnyMergeFolder *outbox_folder;
56 };
57
58 static void         get_folders    (TnyFolderStore *self, 
59                                     TnyList *list, 
60                                     TnyFolderStoreQuery *query,
61                                     gboolean refresh, 
62                                     GError **err);
63
64 static TnyFolder*   create_folder  (TnyFolderStore *self, 
65                                     const gchar *name, 
66                                     GError **err);
67
68 static void
69 modest_tny_local_folders_account_finalize (GObject *object)
70 {
71         ModestTnyLocalFoldersAccountPrivate *priv;
72
73         priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (object);
74         if (priv->outbox_folder) {
75                 g_object_unref (priv->outbox_folder);
76                 priv->outbox_folder = NULL;
77         }
78         G_OBJECT_CLASS (modest_tny_local_folders_account_parent_class)->finalize (object);
79 }
80
81 static void
82 modest_tny_local_folders_account_class_init (ModestTnyLocalFoldersAccountClass *klass)
83 {
84         GObjectClass *object_class = G_OBJECT_CLASS (klass);
85         
86         g_type_class_add_private (klass, sizeof (ModestTnyLocalFoldersAccountPrivate));
87         
88         object_class->finalize = modest_tny_local_folders_account_finalize;
89           
90         /* Override virtual functions from the parent class: */
91         TNY_CAMEL_STORE_ACCOUNT_CLASS(klass)->get_folders = get_folders;
92         TNY_CAMEL_STORE_ACCOUNT_CLASS(klass)->create_folder = create_folder;
93 }
94
95 static void
96 modest_tny_local_folders_account_init (ModestTnyLocalFoldersAccount *self)
97 {
98         /* Do nothing */
99 }
100
101 ModestTnyLocalFoldersAccount*
102 modest_tny_local_folders_account_new (void)
103 {
104   return g_object_new (MODEST_TYPE_TNY_LOCAL_FOLDERS_ACCOUNT, NULL);
105 }
106
107 /**********************************************************/
108 /*          TnyCamelStoreAccount functions redefinitions  */
109 /**********************************************************/
110 static gboolean 
111 modest_tny_local_folders_account_query_passes (TnyFolderStoreQuery *query, TnyFolder *folder)
112 {
113         gboolean retval = FALSE;
114
115         if (query && (tny_list_get_length (tny_folder_store_query_get_items (query)) > 0)) {
116                 TnyList *items = tny_folder_store_query_get_items (query);
117                 TnyIterator *iterator;
118                 iterator = tny_list_create_iterator (items);
119
120                 while (!tny_iterator_is_done (iterator))
121                 {
122                         TnyFolderStoreQueryItem *item = (TnyFolderStoreQueryItem*) tny_iterator_get_current (iterator);
123                         if (item) {
124                                 TnyFolderStoreQueryOption options = tny_folder_store_query_item_get_options (item);
125                                 const regex_t *regex = tny_folder_store_query_item_get_regex (item);
126
127                                 if ((options & TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED) &&
128                                    tny_folder_is_subscribed (folder))
129                                         retval = TRUE;
130
131                                 if ((options & TNY_FOLDER_STORE_QUERY_OPTION_UNSUBSCRIBED) &&
132                                     !(tny_folder_is_subscribed (folder)))
133                                         retval = TRUE;
134
135                                 if (regex && options & TNY_FOLDER_STORE_QUERY_OPTION_MATCH_ON_NAME)
136                                    if (regexec (regex, tny_folder_get_name (folder), 0, NULL, 0) == 0)
137                                         retval = TRUE;
138
139                                 if (regex && options & TNY_FOLDER_STORE_QUERY_OPTION_MATCH_ON_ID)
140                                   if (regexec (regex, tny_folder_get_id (folder), 0, NULL, 0) == 0)
141                                         retval = TRUE;
142
143                                 g_object_unref (G_OBJECT (item));
144                         }
145
146                         tny_iterator_next (iterator);
147                 }
148                  
149                 g_object_unref (G_OBJECT (iterator));
150                 g_object_unref (G_OBJECT (items));
151         } else
152                 retval = TRUE;
153
154         return retval;
155 }
156
157 static void
158 get_folders (TnyFolderStore *self, 
159              TnyList *list, 
160              TnyFolderStoreQuery *query, 
161              gboolean refresh, 
162              GError **err)
163 {
164         TnyCamelStoreAccountClass *parent_class;
165         ModestTnyLocalFoldersAccountPrivate *priv;
166
167         /* Call the base class implementation: */
168         parent_class = g_type_class_peek_parent (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self));
169         parent_class->get_folders (self, list, query, refresh, err);
170         
171         /* Add our extra folder only if it passes the query */
172         priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self);
173                 
174         if (priv->outbox_folder && 
175             modest_tny_local_folders_account_query_passes (query, TNY_FOLDER (priv->outbox_folder)))
176                 tny_list_prepend (list, G_OBJECT (priv->outbox_folder));
177 }
178
179 static TnyFolder*
180 create_folder (TnyFolderStore *self, 
181                const gchar *name, 
182                GError **err)
183 {
184         TnyCamelStoreAccountClass *parent_class;
185
186         parent_class = g_type_class_peek_parent (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT_GET_CLASS (self));
187
188         /* If the folder name is been used by our extra folders */
189         if (modest_tny_local_folders_account_folder_name_in_use (MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (self), name)) {
190                 g_set_error (err, TNY_ERROR_DOMAIN, 
191                              TNY_SERVICE_ERROR_FOLDER_CREATE,
192                              "Folder name already in use");
193                 return NULL;
194         }
195
196         /* Call the base class implementation: */
197         return parent_class->create_folder (self, name, err);
198 }
199
200 /*****************************/
201 /*      Public methods       */ 
202 /*****************************/
203 gboolean
204 modest_tny_local_folders_account_folder_name_in_use (ModestTnyLocalFoldersAccount *self,
205                                                      const gchar *name)
206 {
207         ModestTnyLocalFoldersAccountPrivate *priv;
208         gchar *down_name;
209         const gchar *type_name;
210         gboolean retval;
211         
212         /* Check that we're not trying to create/rename any folder
213            with the same name that our OUTBOX, DRAFT, SENT */
214         priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self);
215         down_name = g_utf8_strdown (name, strlen (name));
216
217         type_name = modest_local_folder_info_get_type_name (TNY_FOLDER_TYPE_OUTBOX);
218         if (!strcmp (type_name, down_name)) {
219                 retval = TRUE;
220         } else {
221                 type_name = modest_local_folder_info_get_type_name (TNY_FOLDER_TYPE_DRAFTS);
222                 if (!strcmp (type_name, down_name)) {
223                         retval = TRUE;
224                 } else {
225                         type_name = modest_local_folder_info_get_type_name (TNY_FOLDER_TYPE_SENT);
226                         if (!strcmp (type_name, down_name)) {
227                                 retval = TRUE;
228                         } else {
229                                 retval = FALSE;
230                         }
231                 }
232         }
233         g_free (down_name);
234
235         return retval;
236 }
237
238 void
239 modest_tny_local_folders_account_add_folder_to_outbox (ModestTnyLocalFoldersAccount *self, 
240                                                        TnyFolder *per_account_outbox)
241 {
242         ModestTnyLocalFoldersAccountPrivate *priv;
243
244         g_return_if_fail (MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (self));
245         g_return_if_fail (TNY_IS_FOLDER (per_account_outbox));
246
247         priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self);
248
249         /* Create on-demand */
250         if (!priv->outbox_folder) {
251                 priv->outbox_folder = TNY_MERGE_FOLDER (tny_merge_folder_new_with_ui_locker (_("mcen_me_folder_outbox"), tny_gtk_lockable_new ()));
252         
253                 /* Set type to outbox */
254                 tny_merge_folder_set_folder_type (priv->outbox_folder, TNY_FOLDER_TYPE_OUTBOX);
255         }
256
257         /* Add outbox to the global OUTBOX folder */
258         tny_merge_folder_add_folder (priv->outbox_folder, per_account_outbox);
259 }
260
261 void 
262 modest_tny_local_folders_account_remove_folder_from_outbox (ModestTnyLocalFoldersAccount *self, 
263                                                             TnyFolder *per_account_outbox)
264 {
265         ModestTnyLocalFoldersAccountPrivate *priv;
266         TnyList *merged_folders = NULL;
267
268         g_return_if_fail (MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (self));
269         g_return_if_fail (TNY_IS_FOLDER (per_account_outbox));
270
271         priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self);
272
273         /* Remove outbox from the global OUTBOX folder */
274         tny_merge_folder_remove_folder (priv->outbox_folder, per_account_outbox);
275
276         /* If there is no folder in the outbox the delete it */
277         merged_folders = tny_simple_list_new ();
278         tny_merge_folder_get_folders (priv->outbox_folder, merged_folders);
279         if (tny_list_get_length (merged_folders) == 0) {
280                 g_object_unref (priv->outbox_folder);
281                 priv->outbox_folder = NULL;
282         }
283         g_object_unref (merged_folders);
284 }
285
286 TnyFolder *
287 modest_tny_local_folders_account_get_merged_outbox (ModestTnyLocalFoldersAccount *self)
288 {
289         ModestTnyLocalFoldersAccountPrivate *priv;
290         g_return_val_if_fail (MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (self), NULL);
291
292         priv = TNY_LOCAL_FOLDERS_ACCOUNT_GET_PRIVATE (self);
293         if (priv->outbox_folder)
294                 return g_object_ref (priv->outbox_folder);
295         else
296                 return NULL;
297 }