1 /*
2 * Copyright (C) 2015 SUSE (www.suse.com)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with the program; if not, see <http://www.gnu.org/licenses/>
16 *
17 * Authors:
18 * David Liang <dliang@suse.com>
19 *
20 */
21
22 #include "evolution-config.h"
23
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30
31 #include <glib.h>
32 #include <glib/gi18n-lib.h>
33 #include <glib/gstdio.h>
34 #include <gio/gio.h>
35
36 #include <libebook/libebook.h>
37
38 #include "shell/e-shell.h"
39 #include "mail/e-mail-backend.h"
40
41 #include "kmail-libs.h"
42
43 static GSList *kmail_read_folder (const gchar *path, GSList *list);
44
45 const CamelStore *
evolution_get_local_store(void)46 evolution_get_local_store (void)
47 {
48 EShell *shell;
49 EShellBackend *shell_backend;
50 EMailBackend *backend;
51 EMailSession *session;
52 static CamelStore *local_store = NULL;
53
54 if (local_store)
55 return local_store;
56 /* XXX Dig up the mail backend from the default EShell.
57 * Since the EImport framework doesn't allow for user
58 * data, I don't see how else to get to it. */
59 shell = e_shell_get_default ();
60 shell_backend = e_shell_get_backend_by_name (shell, "mail");
61
62 backend = E_MAIL_BACKEND (shell_backend);
63 session = e_mail_backend_get_session (backend);
64
65 local_store = e_mail_session_get_local_store (session);
66
67 return local_store;
68 }
69
70 static gboolean
is_kmail_box(const gchar * k_folder)71 is_kmail_box (const gchar *k_folder)
72 {
73 const gchar *special_folders []= {"cur", "tmp", "new", NULL};
74 gchar *source_dir;
75 GDir *dir;
76 gint i;
77
78 for (i = 0; special_folders[i]; i++) {
79 source_dir = g_build_filename (k_folder, special_folders[i], NULL);
80 dir = g_dir_open (source_dir, 0, NULL);
81 if (!dir) {
82 /* If we did not find the subdir with 'cur' 'tmp' and 'new',
83 we don't take it as the kmail box. */
84 g_free (source_dir);
85 return FALSE;
86 }
87 g_dir_close (dir);
88 g_free (source_dir);
89 }
90
91 /* No matter whether the folder was empty, we return it to the importer */
92 return TRUE;
93 }
94
95 static gboolean
is_kmail_directory(const gchar * folder)96 is_kmail_directory (const gchar *folder)
97 {
98 if (g_str_has_prefix (folder, ".") && g_str_has_suffix (folder, ".directory"))
99 return TRUE;
100 else
101 return FALSE;
102 }
103
104 gchar *
kmail_get_base_dir(void)105 kmail_get_base_dir (void)
106 {
107 gchar *base_dir;
108
109 base_dir = g_build_filename (g_get_home_dir (), KMAIL_4_3_DIR, NULL);
110
111 return base_dir;
112 }
113
114 gchar *
kuri_to_euri(const gchar * k_uri)115 kuri_to_euri (const gchar *k_uri)
116 {
117 gchar *base_dir;
118 gchar *p;
119 gchar **folders;
120 GString *e_folder = NULL;
121 gint i;
122 gboolean dropped = FALSE;
123
124 e_folder = g_string_new (EVOLUTION_LOCAL_BASE);
125 base_dir = g_build_filename (g_get_home_dir (), KMAIL_4_3_DIR, NULL);
126 p = (gchar *) k_uri + strlen (base_dir) + 1;
127 folders = g_strsplit (p, "/", -1);
128
129 for (i = 0; folders[i]; i++) {
130 gchar *folder = folders[i];
131 if (g_str_has_prefix (folder, ".") && g_str_has_suffix (folder, ".directory")) {
132 folder ++;
133 p = g_strrstr (folder, ".directory");
134 *p = '\0';
135 }
136 if (i == 0) {
137 /* Some local folders */
138 if ((strcasecmp (folder, "Inbox") == 0) || (strcmp (folder, _("Inbox")) == 0)) {
139 folder = (gchar *)"Inbox";
140 } else if ((strcasecmp (folder, "Outbox") == 0) || (strcmp (folder, _("Outbox")) == 0)) {
141 folder = (gchar *)"Outbox";
142 } else if ((strcasecmp (folder, "sent-mail") == 0) || (strcmp (folder, _("Sent")) == 0)) {
143 folder = (gchar *)"Sent";
144 } else if ((strcasecmp (folder, "drafts") == 0) || (strcmp (folder, _("Drafts")) == 0)) {
145 folder = (gchar *)"Drafts";
146 } else if ((strcasecmp (folder, "templates") == 0) || (strcmp (folder, _("Templates")) == 0)) {
147 folder = (gchar *)"Templates";
148 break;
149 } else if ((strcasecmp (folder, "trash") == 0) || (strcmp (folder, _("Trash")) == 0)) {
150 dropped = TRUE;
151 break;
152 }
153 }
154 g_string_append_printf (e_folder, "/%s", folder);
155 }
156
157 g_strfreev (folders);
158 return g_string_free (e_folder, dropped);
159 }
160
161 static GSList *
kmail_read_folder(const gchar * path,GSList * kmail_list)162 kmail_read_folder (const gchar *path, GSList *kmail_list)
163 {
164 GDir *dir;
165 gchar *filename;
166 const gchar *d;
167 struct stat st;
168
169 dir = g_dir_open (path, 0, NULL);
170
171 while ((d = g_dir_read_name (dir))) {
172 if ((strcmp (d, ".") == 0) || (strcmp (d, "..") == 0)) {
173 continue;
174 }
175
176 filename = g_build_filename (path, d, NULL);
177 /* skip non files and directories, and skip directories in mozilla mode */
178 if (g_stat (filename, &st) == -1) {
179 g_free (filename);
180 continue;
181 }
182 if (S_ISDIR (st.st_mode)) {
183 if (is_kmail_directory (d)) {
184 kmail_list = kmail_read_folder (filename, kmail_list);
185 } else if (is_kmail_box (filename)) {
186 kmail_list = g_slist_prepend (kmail_list, g_strdup (filename));
187 }
188 }
189 g_free (filename);
190 }
191 g_dir_close (dir);
192
193 return kmail_list;
194 }
195
196 GSList *
kmail_get_folders(gchar * path)197 kmail_get_folders (gchar *path)
198 {
199 GSList *list = NULL;
200
201 list = kmail_read_folder (path, list);
202
203 return list;
204 }
205
206 /* Copied from addressbook/util/eab-book-util.c:eab_contact_list_from_string */
207 static GSList *
get_contact_list_from_string(const gchar * str)208 get_contact_list_from_string (const gchar *str)
209 {
210 GSList *contacts = NULL;
211 GString *gstr = g_string_new (NULL);
212 gchar *str_stripped;
213 gchar *p = (gchar *) str;
214 gchar *q;
215 if (!p)
216 return NULL;
217
218 if (!strncmp (p, "Book: ", 6)) {
219 p = strchr (p, '\n');
220 if (!p) {
221 g_warning (G_STRLOC ": Got book but no newline!");
222 return NULL;
223 }
224 p++;
225 }
226
227 while (*p) {
228 if (*p != '\r') g_string_append_c (gstr, *p);
229
230 p++;
231 }
232
233 p = str_stripped = g_string_free (gstr, FALSE);
234
235 for (p = camel_strstrcase (p, "BEGIN:VCARD"); p; p = camel_strstrcase (q, "\nBEGIN:VCARD")) {
236 gchar *card_str;
237
238 if (*p == '\n')
239 p++;
240
241 for (q = camel_strstrcase (p, "END:VCARD"); q; q = camel_strstrcase (q, "END:VCARD")) {
242 gchar *temp;
243
244 q += 9;
245 temp = q;
246 if (*temp)
247 temp += strspn (temp, "\r\n\t ");
248
249 if (*temp == '\0' || !g_ascii_strncasecmp (temp, "BEGIN:VCARD", 11))
250 break; /* Found the outer END:VCARD */
251 }
252
253 if (!q)
254 break;
255 card_str = g_strndup (p, q - p);
256 contacts = g_slist_prepend (contacts, e_contact_new_from_vcard (card_str));
257 g_free (card_str);
258 }
259
260 g_free (str_stripped);
261
262 return g_slist_reverse (contacts);
263 }
264
265 static gchar *
get_kcontact_folder(void)266 get_kcontact_folder (void)
267 {
268 gchar *folder;
269
270 folder = g_build_filename (g_get_home_dir (), KCONTACT_4_3_DIR, NULL);
271
272 return folder;
273 }
274
275 GSList *
kcontact_get_list(void)276 kcontact_get_list (void)
277 {
278 GSList *list = NULL;
279 gchar *foldername = NULL;
280 gchar *filename;
281 const gchar *d;
282 GDir *dir;
283 struct stat st;
284
285 foldername = get_kcontact_folder ();
286 if (!foldername)
287 return NULL;
288 dir = g_dir_open (foldername, 0, NULL);
289
290 while ((d = g_dir_read_name (dir))) {
291 if ((strcmp (d, ".") == 0) || (strcmp (d, "..") == 0)) {
292 continue;
293 }
294 if (!g_str_has_suffix (d, ".vcf")) {
295 continue;
296 }
297 filename = g_build_filename (foldername, d, NULL);
298 if (g_stat (filename, &st) == -1) {
299 g_free (filename);
300 continue;
301 }
302 if (S_ISREG (st.st_mode)) {
303 list = g_slist_prepend (list, filename);
304 }
305 }
306
307 g_free (foldername);
308 g_dir_close (dir);
309
310 return list;
311 }
312
313 void
kcontact_load(GSList * files)314 kcontact_load (GSList *files)
315 {
316 GSList *contactlist = NULL;
317 GSList *l;
318
319 GError *error = NULL;
320 GString *vcards = NULL;
321 EBookClient *book_client;
322 EClient *client;
323 EShell *shell;
324 ESourceRegistry *registry;
325 EClientCache *client_cache;
326 ESource *primary;
327
328 if (!files)
329 return;
330
331 shell = e_shell_get_default ();
332 registry = e_shell_get_registry (shell);
333
334 primary = e_source_registry_ref_default_address_book (registry);
335 if (!primary) {
336 printf ("%s: No default address book found\n", G_STRFUNC);
337 return;
338 }
339
340 client_cache = e_shell_get_client_cache (shell);
341 client = e_client_cache_get_client_sync (client_cache, primary, E_SOURCE_EXTENSION_ADDRESS_BOOK, 15, NULL, &error);
342
343 if (!client) {
344 printf ("%s: Failed to open address book '%s': %s\n", G_STRFUNC, e_source_get_display_name (primary), error ? error->message : "Unknown error");
345 g_clear_object (&primary);
346 g_clear_error (&error);
347 return;
348 }
349 g_clear_object (&primary);
350
351 book_client = E_BOOK_CLIENT (client);
352
353 for (l = files; l; l = l->next) {
354 const gchar *filename;
355 gchar *contents = NULL;
356
357 filename = (gchar *) l->data;
358 if (g_file_get_contents (filename, &contents, NULL, NULL)) {
359 if (vcards == NULL) {
360 vcards = g_string_new (contents);
361 } else {
362 g_string_append_c (vcards, '\n');
363 g_string_append (vcards, contents);
364 }
365 g_free (contents);
366 }
367 }
368
369 if (vcards) {
370 contactlist = get_contact_list_from_string (vcards->str);
371 }
372
373 if (contactlist) {
374 e_book_client_add_contacts_sync (book_client, contactlist, E_BOOK_OPERATION_FLAG_NONE, NULL, NULL, &error);
375
376 if (error) {
377 printf ("%s: Failed to add contacts: %s\n", G_STRFUNC, error->message);
378 g_error_free (error);
379 }
380 }
381
382 if (vcards)
383 g_string_free (vcards, TRUE);
384 if (contactlist)
385 g_slist_free_full (contactlist, g_object_unref);
386 g_object_unref (book_client);
387 }
388
389 gboolean
kmail_is_supported(void)390 kmail_is_supported (void)
391 {
392 gchar *kmaildir;
393 gboolean exists;
394
395 kmaildir = g_build_filename (g_get_home_dir (), KMAIL_4_3_DIR, NULL);
396 exists = g_file_test (kmaildir, G_FILE_TEST_IS_DIR);
397 g_free (kmaildir);
398
399 if (!exists)
400 return FALSE;
401
402 return TRUE;
403 }
404