No issues found
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2 of the License, or (at your option) version 3.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with the program; if not, see <http://www.gnu.org/licenses/>
14 *
15 *
16 * Authors:
17 * Iain Holmes <iain@ximian.com>
18 * Michael Zucchi <notzed@ximian.com>
19 *
20 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
21 *
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdio.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <unistd.h>
33 #include <dirent.h>
34 #include <string.h>
35
36 #include <gtk/gtk.h>
37 #include <glib/gi18n.h>
38
39 #include "mail-importer.h"
40
41 #include "libemail-utils/mail-mt.h"
42 #include "mail/e-mail-backend.h"
43 #include "e-util/e-import.h"
44 #include "shell/e-shell.h"
45
46 #define d(x)
47
48 struct _elm_import_msg {
49 MailMsg base;
50
51 EImport *import;
52 EImportTargetHome *target;
53
54 GMutex *status_lock;
55 gchar *status_what;
56 gint status_pc;
57 gint status_timeout_id;
58 GCancellable *status;
59 };
60
61 static GHashTable *
62 parse_elm_rc (const gchar *elmrc)
63 {
64 gchar line[4096];
65 FILE *handle;
66 GHashTable *prefs;
67
68 prefs = g_hash_table_new_full (
69 g_str_hash, g_str_equal,
70 (GDestroyNotify) g_free,
71 (GDestroyNotify) g_free);
72
73 if (!g_file_test (elmrc, G_FILE_TEST_IS_REGULAR))
74 return prefs;
75
76 handle = fopen (elmrc, "r");
77 if (handle == NULL)
78 return prefs;
79
80 while (fgets (line, 4096, handle) != NULL) {
81 gchar *linestart, *end;
82 gchar *key, *value;
83 if (*line == '#' &&
84 (line[1] != '#' && line[2] != '#')) {
85 continue;
86 } else if (*line == '\n') {
87 continue;
88 } else if (*line == '#' && line[1] == '#' && line[2] == '#') {
89 linestart = line + 4;
90 } else {
91 linestart = line;
92 }
93
94 end = strstr (linestart, " = ");
95 if (end == NULL) {
96 g_warning ("Broken line");
97 continue;
98 }
99
100 *end = 0;
101 key = g_strdup (linestart);
102
103 linestart = end + 3;
104 end = strchr (linestart, '\n');
105 if (end == NULL) {
106 g_warning ("Broken line");
107 g_free (key);
108 continue;
109 }
110
111 *end = 0;
112 value = g_strdup (linestart);
113
114 g_hash_table_insert (prefs, key, value);
115 }
116
117 fclose (handle);
118
119 return prefs;
120 }
121
122 static gchar *
123 elm_get_rc (EImport *ei,
124 const gchar *name)
125 {
126 GHashTable *prefs;
127 gchar *elmrc;
128
129 prefs = g_object_get_data ((GObject *) ei, "elm-rc");
130 if (prefs == NULL) {
131 elmrc = g_build_filename (g_get_home_dir (), ".elm/elmrc", NULL);
132 prefs = parse_elm_rc (elmrc);
133 g_free (elmrc);
134 g_object_set_data ((GObject *) ei, "elm-rc", prefs);
135 }
136
137 if (prefs == NULL)
138 return NULL;
139 else
140 return g_hash_table_lookup (prefs, name);
141 }
142
143 static gboolean
144 elm_supported (EImport *ei,
145 EImportTarget *target,
146 EImportImporter *im)
147 {
148 const gchar *maildir;
149 gchar *elmdir;
150 gboolean mailexists, exists;
151
152 if (target->type != E_IMPORT_TARGET_HOME)
153 return FALSE;
154
155 elmdir = g_build_filename (g_get_home_dir (), ".elm", NULL);
156 exists = g_file_test (elmdir, G_FILE_TEST_IS_DIR);
157 g_free (elmdir);
158 if (!exists)
159 return FALSE;
160
161 maildir = elm_get_rc (ei, "maildir");
162 if (maildir == NULL)
163 maildir = "Mail";
164
165 if (!g_path_is_absolute (maildir))
166 elmdir = g_build_filename (g_get_home_dir (), maildir, NULL);
167 else
168 elmdir = g_strdup (maildir);
169
170 mailexists = g_file_test (elmdir, G_FILE_TEST_IS_DIR);
171 g_free (elmdir);
172
173 return mailexists;
174 }
175
176 static gchar *
177 elm_import_desc (struct _elm_import_msg *m)
178 {
179 return g_strdup (_("Importing Elm data"));
180 }
181
182 static MailImporterSpecial elm_special_folders[] = {
183 { "received", "Inbox" },
184 { NULL },
185 };
186
187 static void
188 elm_import_exec (struct _elm_import_msg *m,
189 GCancellable *cancellable,
190 GError **error)
191 {
192 EShell *shell;
193 EShellBackend *shell_backend;
194 EMailSession *session;
195 const gchar *maildir;
196 gchar *elmdir;
197
198 /* XXX Dig up the EMailSession from the default EShell.
199 * Since the EImport framework doesn't allow for user
200 * data, I don't see how else to get to it. */
201 shell = e_shell_get_default ();
202 shell_backend = e_shell_get_backend_by_name (shell, "mail");
203 session = e_mail_backend_get_session (E_MAIL_BACKEND (shell_backend));
204
205 maildir = elm_get_rc (m->import, "maildir");
206 if (maildir == NULL)
207 maildir = "Mail";
208
209 if (!g_path_is_absolute (maildir))
210 elmdir = g_build_filename (g_get_home_dir (), maildir, NULL);
211 else
212 elmdir = g_strdup (maildir);
213
214 mail_importer_import_folders_sync (
215 session, elmdir, elm_special_folders, 0, m->status);
216 g_free (elmdir);
217 }
218
219 static void
220 elm_import_done (struct _elm_import_msg *m)
221 {
222 e_import_complete (m->import, (EImportTarget *) m->target);
223 }
224
225 static void
226 elm_import_free (struct _elm_import_msg *m)
227 {
228 g_object_unref (m->status);
229
230 g_free (m->status_what);
231 g_mutex_free (m->status_lock);
232
233 g_source_remove (m->status_timeout_id);
234 m->status_timeout_id = 0;
235
236 g_object_unref (m->import);
237 }
238
239 static void
240 elm_status (CamelOperation *op,
241 const gchar *what,
242 gint pc,
243 gpointer data)
244 {
245 struct _elm_import_msg *importer = data;
246
247 g_mutex_lock (importer->status_lock);
248 g_free (importer->status_what);
249 importer->status_what = g_strdup (what);
250 importer->status_pc = pc;
251 g_mutex_unlock (importer->status_lock);
252 }
253
254 static gboolean
255 elm_status_timeout (gpointer data)
256 {
257 struct _elm_import_msg *importer = data;
258 gint pc;
259 gchar *what;
260
261 if (importer->status_what) {
262 g_mutex_lock (importer->status_lock);
263 what = importer->status_what;
264 importer->status_what = NULL;
265 pc = importer->status_pc;
266 g_mutex_unlock (importer->status_lock);
267
268 e_import_status (
269 importer->import, (EImportTarget *)
270 importer->target, what, pc);
271 }
272
273 return TRUE;
274 }
275
276 static MailMsgInfo elm_import_info = {
277 sizeof (struct _elm_import_msg),
278 (MailMsgDescFunc) elm_import_desc,
279 (MailMsgExecFunc) elm_import_exec,
280 (MailMsgDoneFunc) elm_import_done,
281 (MailMsgFreeFunc) elm_import_free
282 };
283
284 static gint
285 mail_importer_elm_import (EImport *ei,
286 EImportTarget *target)
287 {
288 struct _elm_import_msg *m;
289 gint id;
290
291 m = mail_msg_new (&elm_import_info);
292 g_datalist_set_data (&target->data, "elm-msg", m);
293 m->import = ei;
294 g_object_ref (m->import);
295 m->target = (EImportTargetHome *) target;
296 m->status_timeout_id = g_timeout_add (100, elm_status_timeout, m);
297 m->status_lock = g_mutex_new ();
298 m->status = camel_operation_new ();
299
300 g_signal_connect (
301 m->status, "status",
302 G_CALLBACK (elm_status), m);
303
304 id = m->base.seq;
305
306 mail_msg_fast_ordered_push (m);
307
308 return id;
309 }
310
311 static void
312 checkbox_toggle_cb (GtkToggleButton *tb,
313 EImportTarget *target)
314 {
315 g_datalist_set_data (
316 &target->data, "elm-do-mail",
317 GINT_TO_POINTER (gtk_toggle_button_get_active (tb)));
318 }
319
320 static GtkWidget *
321 elm_getwidget (EImport *ei,
322 EImportTarget *target,
323 EImportImporter *im)
324 {
325 GtkWidget *box, *w;
326
327 g_datalist_set_data (
328 &target->data, "elm-do-mail", GINT_TO_POINTER (TRUE));
329
330 box = gtk_vbox_new (FALSE, 2);
331
332 w = gtk_check_button_new_with_label (_("Mail"));
333 gtk_toggle_button_set_active ((GtkToggleButton *) w, TRUE);
334 g_signal_connect (
335 w, "toggled",
336 G_CALLBACK (checkbox_toggle_cb), target);
337
338 gtk_box_pack_start ((GtkBox *) box, w, FALSE, FALSE, 0);
339 gtk_widget_show_all (box);
340
341 return box;
342 }
343
344 static void
345 elm_import (EImport *ei,
346 EImportTarget *target,
347 EImportImporter *im)
348 {
349 if (GPOINTER_TO_INT (g_datalist_get_data (&target->data, "elm-do-mail")))
350 mail_importer_elm_import (ei, target);
351 else
352 e_import_complete (ei, target);
353 }
354
355 static void
356 elm_cancel (EImport *ei,
357 EImportTarget *target,
358 EImportImporter *im)
359 {
360 struct _elm_import_msg *m = g_datalist_get_data (&target->data, "elm-msg");
361
362 if (m)
363 g_cancellable_cancel (m->status);
364 }
365
366 static EImportImporter elm_importer = {
367 E_IMPORT_TARGET_HOME,
368 0,
369 elm_supported,
370 elm_getwidget,
371 elm_import,
372 elm_cancel,
373 NULL, /* get_preview */
374 };
375
376 EImportImporter *
377 elm_importer_peek (void)
378 {
379 elm_importer.name = _("Evolution Elm importer");
380 elm_importer.description = _("Import mail from Elm.");
381
382 return &elm_importer;
383 }