diff options
author | Not Zed <NotZed@Ximian.com> | 2004-02-11 16:26:58 +0800 |
---|---|---|
committer | Michael Zucci <zucchi@src.gnome.org> | 2004-02-11 16:26:58 +0800 |
commit | 06b08adb257351bf8080d960fb98b4265cc43081 (patch) | |
tree | 9f429f497d47c5b933d2c4c98a1058566233a7dc /mail/importers/mail-importer.c | |
parent | 136b8ea938580f3c1d4fb9f92093c4631ec6038b (diff) | |
download | gsoc2013-evolution-06b08adb257351bf8080d960fb98b4265cc43081.tar gsoc2013-evolution-06b08adb257351bf8080d960fb98b4265cc43081.tar.gz gsoc2013-evolution-06b08adb257351bf8080d960fb98b4265cc43081.tar.bz2 gsoc2013-evolution-06b08adb257351bf8080d960fb98b4265cc43081.tar.lz gsoc2013-evolution-06b08adb257351bf8080d960fb98b4265cc43081.tar.xz gsoc2013-evolution-06b08adb257351bf8080d960fb98b4265cc43081.tar.zst gsoc2013-evolution-06b08adb257351bf8080d960fb98b4265cc43081.zip |
Basically rewrote this, the import tasks run in another thread. It tells
2004-02-11 Not Zed <NotZed@Ximian.com>
* importers/pine-importer.c: Basically rewrote this, the import
tasks run in another thread. It tells you more about what's going
on, and its cancellable.
(pine_store_settings): changed the meaning of the settings
slightly, if set it means we've processed them already.
* mail-component-factory.c (factory): hook in importer factory
callback.
2004-02-10 Not Zed <NotZed@Ximian.com>
* importers/*-importer.c: removed module init, just provide a new
method. Updates for api changes.
* Makefile.am: link mail importers in directly.
* mail-importer.c: changed to do stuff in-memory with linked
stuff, moved to importers/.
* importers/GNOME_Evolution_Mail_Importers.server.in.in: merge all
importer .server info's here, point them all to the mailer
factory. Removed the others.
* importers/Makefile.am: remove Mailer.idl stuff. Move all
importers to a single library.
svn path=/trunk/; revision=24701
Diffstat (limited to 'mail/importers/mail-importer.c')
-rw-r--r-- | mail/importers/mail-importer.c | 390 |
1 files changed, 390 insertions, 0 deletions
diff --git a/mail/importers/mail-importer.c b/mail/importers/mail-importer.c new file mode 100644 index 0000000000..1aab7ac2c8 --- /dev/null +++ b/mail/importers/mail-importer.c @@ -0,0 +1,390 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* mail-importer.c + * + * Authors: Iain Holmes <iain@ximian.com> + * Michael Zucchi <notzed@ximian.com> + * + * Copyright (C) 2001-2003 Ximian, Inc. + * Copyright (C) 2004 Novell Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> +#include <sys/types.h> +#include <dirent.h> +#include <gmodule.h> +#include <libgnome/gnome-util.h> +#include <camel/camel-folder.h> +#include <camel/camel-store.h> +#include <camel/camel-mime-message.h> +#include <camel/camel-mime-parser.h> +#include <camel/camel-exception.h> +#include <e-util/e-path.h> + +#include "mail/mail-mt.h" +#include "mail/mail-component.h" +#include "mail/mail-tools.h" + +#include "mail-importer.h" + +/** + * mail_importer_make_local_folder: + * @folderpath: + * + * Check a local folder exists at path @folderpath, and if not, create it. + * + * Return value: The physical uri of the folder, or NULL if the folder did + * not exist and could not be created. + **/ +char * +mail_importer_make_local_folder(const char *folderpath) +{ + return g_strdup_printf("mbox:/home/notzed/.evolution/mail/local/%s", folderpath); +} + +/** + * mail_importer_add_line: + * importer: A MailImporter structure. + * str: Next line of the mbox. + * finished: TRUE if @str is the last line of the message. + * + * Adds lines to the message until it is finished, and then adds + * the complete message to the folder. + */ +void +mail_importer_add_line (MailImporter *importer, + const char *str, + gboolean finished) +{ + CamelMimeMessage *msg; + CamelMessageInfo *info; + CamelException *ex; + + if (importer->mstream == NULL) + importer->mstream = CAMEL_STREAM_MEM (camel_stream_mem_new ()); + + camel_stream_write (CAMEL_STREAM (importer->mstream), str, strlen (str)); + + if (finished == FALSE) + return; + + camel_stream_reset (CAMEL_STREAM (importer->mstream)); + info = g_new0 (CamelMessageInfo, 1); + info->flags = CAMEL_MESSAGE_SEEN; + + msg = camel_mime_message_new (); + camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), + CAMEL_STREAM (importer->mstream)); + + camel_object_unref (importer->mstream); + importer->mstream = NULL; + + ex = camel_exception_new (); + camel_folder_append_message (importer->folder, msg, info, NULL, ex); + camel_object_unref (msg); + + camel_exception_free (ex); + g_free (info); +} + +struct _BonoboObject *mail_importer_factory_cb(struct _BonoboGenericFactory *factory, const char *iid, void *data) +{ + if (strcmp(iid, ELM_INTELLIGENT_IMPORTER_IID) == 0) + return elm_intelligent_importer_new(); + else if (strcmp(iid, PINE_INTELLIGENT_IMPORTER_IID) == 0) + return pine_intelligent_importer_new(); + else if (strcmp(iid, NETSCAPE_INTELLIGENT_IMPORTER_IID) == 0) + return netscape_intelligent_importer_new(); + else if (strcmp(iid, MBOX_IMPORTER_IID) == 0) + return mbox_importer_new(); + else if (strcmp(iid, OUTLOOK_IMPORTER_IID) == 0) + return outlook_importer_new(); + + return NULL; +} + +struct _import_mbox_msg { + struct _mail_msg msg; + + char *path; + char *uri; + CamelOperation *cancel; +}; + +static char * +import_mbox_describe(struct _mail_msg *mm, int complete) +{ + return g_strdup (_("Importing mailbox")); +} + +static struct { + char tag; + guint32 mozflag; + guint32 flag; +} status_flags[] = { + { 'F', MSG_FLAG_MARKED, CAMEL_MESSAGE_FLAGGED }, + { 'A', MSG_FLAG_REPLIED, CAMEL_MESSAGE_ANSWERED }, + { 'D', MSG_FLAG_EXPUNGED, CAMEL_MESSAGE_DELETED }, + { 'R', MSG_FLAG_READ, CAMEL_MESSAGE_SEEN }, +}; + +static guint32 +decode_status(const char *status) +{ + const char *p; + char c; + guint32 flags = 0; + int i; + + p = status; + while ((c = *p++)) { + for (i=0;i<sizeof(status_flags)/sizeof(status_flags[0]);i++) + if (status_flags[i].tag == *p) + flags |= status_flags[i].flag; + } + + return flags; +} + +static guint32 +decode_mozilla_status(const char *tmp) +{ + unsigned long status = strtoul(tmp, NULL, 16); + guint32 flags = 0; + int i; + + for (i=0;i<sizeof(status_flags)/sizeof(status_flags[0]);i++) + if (status_flags[i].mozflag & status) + flags |= status_flags[i].flag; + return flags; +} + +static void +import_mbox_import(struct _mail_msg *mm) +{ + struct _import_mbox_msg *m = (struct _import_mbox_msg *) mm; + CamelFolder *folder; + CamelMimeParser *mp = NULL; + struct stat st; + int fd; + CamelMessageInfo *info; + + if (stat(m->path, &st) == -1) { + g_warning("cannot find source file to import '%s': %s", m->path, g_strerror(errno)); + return; + } + + if (m->uri == NULL || m->uri[0] == 0) + folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_INBOX); + else + folder = mail_tool_uri_to_folder(m->uri, CAMEL_STORE_FOLDER_CREATE, &mm->ex); + + if (folder == NULL) + return; + + if (S_ISREG(st.st_mode)) { + fd = open(m->path, O_RDONLY); + if (fd == -1) { + g_warning("cannot find source file to import '%s': %s", m->path, g_strerror(errno)); + goto fail1; + } + + mp = camel_mime_parser_new(); + camel_mime_parser_scan_from(mp, TRUE); + if (camel_mime_parser_init_with_fd(mp, fd) == -1) { + goto fail2; + } + + if (m->cancel) + camel_operation_register(m->cancel); + + camel_operation_start(NULL, _("Importing `%s'"), folder->full_name); + camel_folder_freeze(folder); + while (camel_mime_parser_step(mp, 0, 0) == CAMEL_MIME_PARSER_STATE_FROM) { + CamelMimeMessage *msg; + const char *tmp; + int pc; + + if (st.st_size > 0) + pc = (int)(100.0 * ((double)camel_mime_parser_tell(mp) / (double)st.st_size)); + camel_operation_progress(NULL, pc); + + msg = camel_mime_message_new(); + if (camel_mime_part_construct_from_parser((CamelMimePart *)msg, mp) == -1) { + /* set exception? */ + camel_object_unref(msg); + break; + } + + info = camel_message_info_new(); + + tmp = camel_medium_get_header((CamelMedium *)msg, "X-Mozilla-Status"); + if (tmp) + info->flags |= decode_mozilla_status(tmp); + tmp = camel_medium_get_header((CamelMedium *)msg, "Status"); + if (tmp) + info->flags |= decode_status(tmp); + tmp = camel_medium_get_header((CamelMedium *)msg, "X-Status"); + if (tmp) + info->flags |= decode_status(tmp); + + camel_folder_append_message(folder, msg, info, NULL, &mm->ex); + camel_message_info_free(info); + camel_object_unref(msg); + + if (camel_exception_is_set(&mm->ex)) + break; + + camel_mime_parser_step(mp, 0, 0); + } + camel_folder_sync(folder, FALSE, &mm->ex); + camel_folder_thaw(folder); + camel_operation_end(NULL); + if (m->cancel) + camel_operation_unregister(m->cancel); + fail2: + camel_object_unref(mp); + } +fail1: + camel_folder_sync(folder, FALSE, &mm->ex); + camel_object_unref(folder); +} + +static void +import_mbox_done(struct _mail_msg *mm) +{ +} + +static void +import_mbox_free (struct _mail_msg *mm) +{ + struct _import_mbox_msg *m = (struct _import_mbox_msg *)mm; + + if (m->cancel) + camel_operation_unref(m->cancel); + g_free(m->uri); + g_free(m->path); +} + +static struct _mail_msg_op import_mbox_op = { + import_mbox_describe, + import_mbox_import, + import_mbox_done, + import_mbox_free, +}; + +int +mail_importer_import_mbox(const char *path, const char *folderuri, CamelOperation *cancel) +{ + struct _import_mbox_msg *m; + int id; + + m = mail_msg_new(&import_mbox_op, NULL, sizeof (*m)); + m->path = g_strdup(path); + m->uri = g_strdup(folderuri); + if (cancel) { + m->cancel = cancel; + camel_operation_ref(cancel); + } + + id = m->msg.seq; + e_thread_put(mail_thread_queued, (EMsg *)m); + + return id; +} + +void +mail_importer_import_mbox_sync(const char *path, const char *folderuri, CamelOperation *cancel) +{ + struct _import_mbox_msg *m; + + m = mail_msg_new(&import_mbox_op, NULL, sizeof (*m)); + m->path = g_strdup(path); + m->uri = g_strdup(folderuri); + if (cancel) { + m->cancel = cancel; + camel_operation_ref(cancel); + } + + import_mbox_import(&m->msg); + import_mbox_done(&m->msg); + mail_msg_free(&m->msg); +} + +/* This should probably take a list of all folders, otherwise we need to duplicate it for netscape folders */ + +/* pass folderparent = NULL first time */ +void +mail_importer_import_folders_sync(const char *filepath, const char *folderparent, MailImporterSpecial special_folders[], CamelOperation *cancel) +{ + DIR *dir; + struct dirent *d; + struct stat st; + char *filefull, *foldersub, *uri; + const char *folder; + + dir = opendir(filepath); + if (dir == NULL) + return; + + camel_operation_start(NULL, _("Scanning %s"), filepath); + + while ( (d=readdir(dir)) ) { + if (strcmp(d->d_name, ".") == 0 + || strcmp(d->d_name, "..") == 0) + continue; + + filefull = g_build_filename(filepath, d->d_name, NULL); + if (stat(filefull, &st) == -1 + || !(S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))) { + g_free(filefull); + continue; + } + + folder = d->d_name; + if (folderparent == NULL) { + int i; + + for (i=0;special_folders[i].orig;i++) + if (strcmp(special_folders[i].orig, folder) == 0) { + folder = special_folders[i].new; + break; + } + /* FIXME: need a better way to get default store location */ + uri = g_strdup_printf("mbox:%s/mail/local#%s", mail_component_peek_base_directory(NULL), folder); + } else { + uri = g_strdup_printf("mbox:%s/mail/local#%s/%s", mail_component_peek_base_directory(NULL), folderparent, folder); + } + + printf("importing to uri %s\n", uri); + mail_importer_import_mbox_sync(filefull, uri, cancel); + g_free(uri); + + if (S_ISDIR(st.st_mode)) { + foldersub = folderparent?g_strdup_printf("%s/%s", folderparent, folder):g_strdup(folder); + import_folders(filefull, foldersub, special_folders, cancel); + g_free(foldersub); + } + + g_free(filefull); + } + + camel_operation_end(NULL); +} |