2007-04-04 Murray Cumming <murrayc@murrayc.com>
[modest] / src / maemo / easysetup / modest-presets.c
1 /* Copyright (c) 2006, 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 #include <string.h> /* for strcmp */
31 #include "modest-presets.h"
32
33 /* Include config.h so that _() works: */
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #define MODEST_PRESETS_KEY_NAME              "Name"
39 #define MODEST_PRESETS_KEY_DOMAIN            "Domain"
40 #define MODEST_PRESETS_KEY_MCC               "MCC"
41 #define MODEST_PRESETS_KEY_INCOMING          "IncomingMailServer"
42 #define MODEST_PRESETS_KEY_OUTGOING          "OutgoingMailServer"
43 #define MODEST_PRESETS_KEY_MAILBOX_TYPE      "MailboxType"
44 #define MODEST_PRESETS_KEY_MAILBOX_TYPE_POP  "pop"
45 #define MODEST_PRESETS_KEY_MAILBOX_TYPE_IMAP "imap"
46 #define MODEST_PRESETS_KEY_APOP              "APOPSecureLogin"
47 #define MODEST_PRESETS_KEY_SECURE_SMTP       "SecureSMTP"
48 #define MODEST_PRESETS_KEY_TRUE              "true"
49
50 /** An efficient way to store the info for each provider.
51  */
52 typedef enum _ModestPresetsInfo {
53         /* two bits for the server type */
54         MODEST_PRESETS_INFO_NONE             = 0x0000,
55         MODEST_PRESETS_INFO_IMAP             = 0x0001,
56         MODEST_PRESETS_INFO_POP              = 0x0002,
57         MODEST_PRESETS_INFO_SMTP             = 0x0003,
58
59         /* one bit for each of these */
60         MODEST_PRESETS_INFO_APOP             = 0x0004,
61         MODEST_PRESETS_INFO_SECURE_SMTP      = 0x0008,
62         MODEST_PRESETS_INFO_SECURE_INCOMING  = 0x000f   
63 } ModestPresetsInfo;
64
65 /**
66  * modest_presets_get_info:
67  * @self: a valid ModestPresets instance
68  * @provider_id: ID of the provider 
69  * @incoming_server: get the incoming mailserver if TRUE, get the
70  * outgoing server otherwise
71  *
72  * get information about some incoming or outgoing mailserver
73  *
74  * Returns: a ModestPresetsInfo with the required information
75  */
76 static ModestPresetsInfo
77 modest_presets_get_info (ModestPresets *self, const gchar *provider_id, gboolean incoming_server);
78                                                     
79
80 ModestPresets*
81 modest_presets_new (const gchar *presetfile)
82 {
83         ModestPresets *presets = NULL;
84         GError        *err     = NULL;
85         
86         g_return_val_if_fail (presetfile, NULL);
87         
88         presets = g_new (ModestPresets, 1);
89         presets->keyfile = g_key_file_new ();
90
91         if (!presets->keyfile) {
92                 g_printerr ("modest: cannot instantiate GKeyFile\n");
93                 g_free (presets);
94                 return NULL;
95         }
96
97         if (!g_key_file_load_from_file (presets->keyfile, presetfile,
98                                         G_KEY_FILE_NONE, &err)) {
99                 g_printerr ("modest: cannot open keyfile from %s:\n  %s\n", presetfile,
100                             err ? err->message : "unknown reason");
101                 g_error_free (err);
102                 g_free (presets);
103                 return NULL;
104         }
105
106         return presets;
107 }
108
109 gchar**
110 modest_presets_get_providers  (ModestPresets *self, guint mcc,
111                                gboolean include_globals, gchar ***provider_ids)
112 {
113         gchar **all_providers = NULL;
114         gchar **all_provider_ids = NULL;
115         gchar **filtered  = NULL;
116         gchar **filtered_ids = NULL;
117         GError *err       = NULL;
118         guint i, j, len;
119         
120         g_return_val_if_fail (self && self->keyfile, NULL);
121
122         /* Get all the provider IDs: */
123         all_provider_ids = g_key_file_get_groups (self->keyfile, NULL);
124         len = g_strv_length(all_provider_ids);
125
126         /* Get the names for all these providers: */
127         all_providers = g_new0(gchar*, len + 1); /* Provider names. */
128         for (i=0; i != len; ++i) {
129                 const gchar * provider_id = all_provider_ids[i];
130                 if(provider_id) {
131                         gchar* name = g_key_file_get_string(self->keyfile, provider_id, 
132                                 MODEST_PRESETS_KEY_NAME, NULL);
133                                 
134                         /* Be forgiving of missing names.
135                          * If we use NULL then we will null-terminate the array.
136                          */
137                         if(!name)
138                                 name = g_strdup("");
139                                 
140                         all_providers[i] = name;        
141                 }
142                 else
143                         all_providers[i] = NULL;
144         };
145                 
146         /* return *all* providers? */
147         if (mcc == 0 && include_globals) {
148                 *provider_ids = all_provider_ids;
149                 return all_providers;
150         }
151         
152         /* nope: filter them */
153
154         filtered = g_new0(gchar*, len + 1); /* Provider names. */
155         filtered_ids = g_new0(gchar*, len + 1); /* Provider IDs */
156
157         for (i=0, j=0; i != len; ++i) {
158
159                 int this_mcc;
160                 this_mcc = g_key_file_get_integer (self->keyfile, all_provider_ids[i],
161                                                    MODEST_PRESETS_KEY_MCC, &err);
162                 if (err) {
163                         g_strfreev (all_providers);
164                         g_strfreev (all_provider_ids);
165                         g_strfreev (filtered);
166                         g_strfreev (filtered_ids);
167                         
168                         g_printerr ("modest: error parsing keyfile: %s\n", err->message);
169                         g_error_free (err);
170                         
171                         return NULL;
172                 }
173                 
174                 if (this_mcc == mcc || (this_mcc == 0 && include_globals)) {
175                         filtered[j]   = all_providers[i];
176                         filtered_ids[j]   = all_provider_ids[i];
177                         ++j;
178                         filtered[j] = NULL; /* the array must be NULL-terminated */
179                         filtered_ids[j] = NULL; /* the array must be NULL-terminated */
180                         
181                         all_providers[i]  = NULL; /*  g_strfreev: leave it alone */
182                         all_provider_ids[i]  = NULL; /*  g_strfreev: leave it alone */
183                 }
184         }
185         
186         g_strfreev (all_providers);
187         g_strfreev (all_provider_ids);
188         
189         *provider_ids = filtered_ids;
190         return filtered;
191 }
192
193
194 gchar*
195 modest_presets_get_server (ModestPresets *self, const gchar *provider_id,
196                            gboolean incoming_server)
197 {       
198         g_return_val_if_fail (self && self->keyfile, NULL);
199         g_return_val_if_fail (provider_id, NULL);
200
201         return g_key_file_get_string (self->keyfile, provider_id, 
202                                       incoming_server ?
203                                       MODEST_PRESETS_KEY_INCOMING :
204                                       MODEST_PRESETS_KEY_OUTGOING,
205                                       NULL);
206 }
207
208 gchar *                   modest_presets_get_domain      (ModestPresets *self,
209                                                           const gchar *provider_id)
210 {       
211         g_return_val_if_fail (self && self->keyfile, NULL);
212         g_return_val_if_fail (provider_id, NULL);
213
214         return g_key_file_get_string (self->keyfile, provider_id, 
215                                       MODEST_PRESETS_KEY_DOMAIN,
216                                       NULL);
217 }               
218
219
220 ModestPresetsInfo
221 modest_presets_get_info (ModestPresets *self, const gchar *provider_id, gboolean incoming_server)
222 {
223         ModestPresetsInfo info = 0;
224         gchar *val = NULL;
225         
226         g_return_val_if_fail (self && self->keyfile, 0);
227
228         if(incoming_server) {
229                 val = g_key_file_get_string (self->keyfile, provider_id,
230                                                 MODEST_PRESETS_KEY_INCOMING, NULL);
231                 if (val) {
232                         g_free (val);
233                         val = g_key_file_get_string (self->keyfile, provider_id,
234                                                      MODEST_PRESETS_KEY_MAILBOX_TYPE, NULL);
235                         if (strcmp (val, MODEST_PRESETS_KEY_MAILBOX_TYPE_POP) == 0)
236                                 info |= MODEST_PRESETS_INFO_POP;
237                         if (strcmp (val, MODEST_PRESETS_KEY_MAILBOX_TYPE_IMAP) == 0)
238                                 info |= MODEST_PRESETS_INFO_IMAP;
239                         g_free (val);
240         
241                         val = g_key_file_get_string (self->keyfile, provider_id,
242                                                      MODEST_PRESETS_KEY_APOP, NULL);
243                         if (val && strcmp(val, MODEST_PRESETS_KEY_TRUE) == 0)
244                                 info |= MODEST_PRESETS_INFO_APOP;
245                         g_free(val);
246                 }
247         }
248         else /* outgoing: */ {
249                 val = g_key_file_get_string (self->keyfile, provider_id,
250                                              MODEST_PRESETS_KEY_OUTGOING, NULL);
251                 if (val) {
252                         g_free (val);
253                         info |= MODEST_PRESETS_INFO_SMTP;
254                         
255                         val = g_key_file_get_string (self->keyfile, provider_id,
256                                                      MODEST_PRESETS_KEY_SECURE_SMTP, NULL);
257                         if (val && strcmp(val,MODEST_PRESETS_KEY_TRUE) == 0)
258                                 info |= MODEST_PRESETS_INFO_SECURE_SMTP;
259                         g_free(val);
260                 }
261         }
262
263         return info;
264 }
265
266 ModestPresetsServerType
267 modest_presets_get_info_server_type (ModestPresets *self,
268                                                     const gchar *provider_id,
269                                                     gboolean incoming_server)
270 {
271         ModestPresetsInfo info = modest_presets_get_info (self, provider_id, incoming_server);
272
273         /* The server type is stored in the first 2 bits: */
274         info = info & 0x03;
275         
276         /* Convert from the internal enum to the public enum: */
277         if(info == MODEST_PRESETS_INFO_IMAP)
278                 return MODEST_PRESETS_SERVER_TYPE_IMAP;
279         else if(info == MODEST_PRESETS_INFO_POP)
280                 return MODEST_PRESETS_SERVER_TYPE_POP;
281         else if(info == MODEST_PRESETS_INFO_SMTP)
282                 return MODEST_PRESETS_SERVER_TYPE_SMTP;
283         else
284                 return MODEST_PRESETS_SERVER_TYPE_NONE;
285 }
286
287 ModestPresetsSecurity
288 modest_presets_get_info_server_security (ModestPresets *self,
289                                                     const gchar *provider_id,
290                                                     gboolean incoming_server)
291 {
292         ModestPresetsInfo info = modest_presets_get_info (self, provider_id, incoming_server);
293
294         /* The security flags are stored in all except the first 4 bits: */
295         info = info && !0x04;
296         
297         /* Convert from the internal flags to the public flags: */
298         ModestPresetsSecurity security = MODEST_PRESETS_SECURITY_NONE;
299         if(info && MODEST_PRESETS_INFO_APOP)
300                 security = security | MODEST_PRESETS_SECURITY_APOP;
301                 
302         if(info && MODEST_PRESETS_INFO_SECURE_SMTP)
303                 security = security | MODEST_PRESETS_SECURITY_SECURE_SMTP;
304                 
305         if(info && MODEST_PRESETS_INFO_SECURE_INCOMING)
306                 security = security | MODEST_PRESETS_SECURITY_SECURE_INCOMING;
307
308         return security;
309 }
310
311                                                         
312         
313         
314 void
315 modest_presets_destroy (ModestPresets *self)
316 {
317         if (!self)
318                 return;
319
320         g_key_file_free (self->keyfile);
321         self->keyfile = NULL;
322         
323         g_free (self);
324 }