diff options
author | Not Zed <NotZed@Ximian.com> | 2004-02-13 18:14:30 +0800 |
---|---|---|
committer | Michael Zucci <zucchi@src.gnome.org> | 2004-02-13 18:14:30 +0800 |
commit | 39f16a70161b982003faca8b1fea7845a4a4e5fc (patch) | |
tree | f757ae0e6cc6957336c07f49781b8bfc50b6f8bc /mail/importers/evolution-outlook-importer.c | |
parent | 1f4808666f7070789ada617b9fbb652d4e9512a0 (diff) | |
download | gsoc2013-evolution-39f16a70161b982003faca8b1fea7845a4a4e5fc.tar gsoc2013-evolution-39f16a70161b982003faca8b1fea7845a4a4e5fc.tar.gz gsoc2013-evolution-39f16a70161b982003faca8b1fea7845a4a4e5fc.tar.bz2 gsoc2013-evolution-39f16a70161b982003faca8b1fea7845a4a4e5fc.tar.lz gsoc2013-evolution-39f16a70161b982003faca8b1fea7845a4a4e5fc.tar.xz gsoc2013-evolution-39f16a70161b982003faca8b1fea7845a4a4e5fc.tar.zst gsoc2013-evolution-39f16a70161b982003faca8b1fea7845a4a4e5fc.zip |
use mail-importer to import the mail tree, fix the account stuff to talk
2004-02-13 Not Zed <NotZed@Ximian.com>
* importers/netscape-importer.c: use mail-importer to import the
mail tree, fix the account stuff to talk directly to mail config.
Added cancel button. etc. This is completely untested apart from
compiling with no warnings.
* importers/mail-importer.c (import_mbox_import): dont re-use the
exception for syncing.
* importers/evolution-outlook-importer.c: major reworking. Some
platform fixes, runs in another thread, simpler/cleaner main loop.
This is completely untested apart from compiling with no warnings.
* importers/evolution-mbox-importer.c (support_format_fn): we dont
want to check the From_ line case insensitive!
(create_control_fn): implement this weird api.
2004-02-12 Not Zed <NotZed@Ximian.com>
* importers/elm-importer.c: rewrote all importing stuff.
* importers/mail-importer.c (mail_importer_import_folders_sync):
split out into a recursive function & entry. Now handles mozilla
format stuff with a flag.
(import_mbox_import): made the cameloperation properly
save/restore multiple registrations.
svn path=/trunk/; revision=24732
Diffstat (limited to 'mail/importers/evolution-outlook-importer.c')
-rw-r--r-- | mail/importers/evolution-outlook-importer.c | 474 |
1 files changed, 298 insertions, 176 deletions
diff --git a/mail/importers/evolution-outlook-importer.c b/mail/importers/evolution-outlook-importer.c index 8233c82ca5..3a8b334ba8 100644 --- a/mail/importers/evolution-outlook-importer.c +++ b/mail/importers/evolution-outlook-importer.c @@ -20,46 +20,68 @@ * Boston, MA 02111-1307, USA. */ - #ifdef HAVE_CONFIG_H #include <config.h> #endif -#include <bonobo/bonobo-object.h> -#include <bonobo/bonobo-generic-factory.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> #include <stdio.h> +#include <ctype.h> +#include <string.h> + +#include <gtk/gtkhbox.h> +#include <gtk/gtklabel.h> +#include <gtk/gtkmessagedialog.h> +#include <gtk/gtkprogressbar.h> + +#include <bonobo/bonobo-control.h> + +#include <camel/camel-exception.h> +#include <camel/camel-folder.h> +#include <camel/camel-stream-mem.h> +#include <camel/camel-store.h> #include <importer/evolution-importer.h> #include <importer/GNOME_Evolution_Importer.h> -#include <camel/camel-exception.h> +#include "mail/em-folder-selection-button.h" -#include "e-util/e-memory.h" -#include "mail/mail-tools.h" #include "mail/mail-component.h" +#include "mail/mail-mt.h" +#include "mail/mail-tools.h" #include "mail-importer.h" -extern char *evolution_dir; +static int mail_importer_import_outlook(const char *path, const char *folderuri, CamelOperation *cancel); + typedef struct { - MailImporter importer; + EvolutionImporter *ii; - char *filename; - gboolean oe4; /* Is file OE4 or not? */ - FILE *handle; - long pos; - off_t size; + GMutex *status_lock; + char *status_what; + int status_pc; + int status_timeout_id; + CamelOperation *cancel; /* cancel/status port */ + + GtkWidget *selector; + GtkWidget *label; + GtkWidget *progressbar; + GtkWidget *dialog; - gboolean busy; + char *uri; } OutlookImporter; struct oe_msg_segmentheader { - int self; - int increase; - int include; - int next; - int usenet; + gint32 self; + gint32 increase; + gint32 include; + gint32 next; + gint32 usenet; }; typedef struct oe_msg_segmentheader oe_msg_segmentheader; @@ -73,104 +95,19 @@ typedef struct oe_msg_segmentheader oe_msg_segmentheader; Copyright (C) 2001 Ximian, Inc. */ static void -process_item_fn (EvolutionImporter *eimporter, - CORBA_Object listener, - void *closure, - CORBA_Environment *ev) +process_item_fn(EvolutionImporter *eimporter, CORBA_Object listener, void *data, CORBA_Environment *ev) { - OutlookImporter *oli = (OutlookImporter *) closure; - MailImporter *importer = (MailImporter *) oli; - oe_msg_segmentheader *header; - gboolean more = TRUE; - char *cb, *sfull, *s; - long end_pos = 0; - int i; - - if (oli->busy == TRUE) { - GNOME_Evolution_ImporterListener_notifyResult (listener, - GNOME_Evolution_ImporterListener_BUSY, - more, ev); - return; - } - - oli->busy = TRUE; - header = g_new (oe_msg_segmentheader, 1); - fread (header, 16, 1, oli->handle); - - /* Write a From line */ - mail_importer_add_line (importer, - "From evolution-outlook-importer", FALSE); - end_pos = oli->pos + header->include; - if (end_pos >= oli->size) { - end_pos = oli->size; - more = FALSE; - } - - oli->pos += 4; - - cb = g_new (char, 4); - sfull = g_new (char, 65536); - s = sfull; - - while (oli->pos < end_pos) { - fread (cb, 1, 4, oli->handle); - for (i = 0; i < 4; i++, oli->pos++) { - if (*(cb + i ) != 0x0d) { - *s++ = *(cb + i); - - if (*(cb + i) == 0x0a) { - *s = '\0'; - mail_importer_add_line (importer, - sfull, FALSE); - s = sfull; - } - } - } - } - - if (s != sfull) { - *s = '\0'; - mail_importer_add_line (importer, sfull, FALSE); - s = sfull; - } - - mail_importer_add_line (importer, "\n", TRUE); - - oli->pos = end_pos; - fseek (oli->handle, oli->pos, SEEK_SET); - - g_free (header); - g_free (sfull); - g_free (cb); - - GNOME_Evolution_ImporterListener_notifyResult (listener, - GNOME_Evolution_ImporterListener_OK, - more, ev); - if (more == FALSE) { - CamelException *ex; - - ex = camel_exception_new (); - camel_folder_thaw (importer->folder); - camel_folder_sync (importer->folder, FALSE, ex); - camel_exception_free (ex); - fclose (oli->handle); - oli->handle = NULL; - } - - oli->busy = FALSE; - return; } /* EvolutionImporterFactory methods */ static gboolean -support_format_fn (EvolutionImporter *importer, - const char *filename, - void *closure) +support_format_fn(EvolutionImporter *importer, const char *filename, void *data) { FILE *handle; - int signature[4]; + guint32 signature[4]; + int ok; /* Outlook Express sniffer. Taken from liboe 0.92 (STABLE) @@ -181,96 +118,118 @@ support_format_fn (EvolutionImporter *importer, return FALSE; /* Can't open file: Can't support it :) */ /* SIGNATURE */ - fread (&signature, 16, 1, handle); - if ((signature[0]!=0xFE12ADCF) || /* OE 5 & OE 5 BETA SIGNATURE */ - (signature[1]!=0x6F74FDC5) || - (signature[2]!=0x11D1E366) || - (signature[3]!=0xC0004E9A)) { - if ((signature[0]==0x36464D4A) && - (signature[1]==0x00010003)) /* OE4 SIGNATURE */ { - fclose (handle); - return TRUE; /* OE 4 */ - } - fclose (handle); - return FALSE; /* Not Outlook 4 or 5 */ - } + fread (&signature, 16, 1, handle); + /* This needs testing */ +#if G_BYTE_ORDER == G_BIG_ENDIAN + signature[0] = GUINT32_TO_BE(signature[0]); + signature[1] = GUINT32_TO_BE(signature[1]); + signature[2] = GUINT32_TO_BE(signature[2]); + signature[3] = GUINT32_TO_BE(signature[3]); +#endif + ok = ((signature[0]!=0xFE12ADCF /* OE 5 & OE 5 BETA SIGNATURE */ + || signature[1]!=0x6F74FDC5 + || signature[2]!=0x11D1E366 + || signature[3]!=0xC0004E9A) + && (signature[0]==0x36464D4A /* OE4 SIGNATURE */ + && signature[1]==0x00010003)); fclose (handle); - return FALSE; /* Can't handle OE 5 yet */ + return ok; /* Can't handle OE 5 yet */ } +/* Note the similarity of most of this code to evolution-mbox-importer. + Yes it should be subclassed, or something ... */ static void -importer_destroy_cb (void *data, GObject *object) +importer_destroy_cb(void *data, GObject *object) { - OutlookImporter *oli = data; - MailImporter *importer = data; + OutlookImporter *importer = data; - if (importer->folder) - camel_object_unref (importer->folder); + if (importer->status_timeout_id) + g_source_remove(importer->status_timeout_id); + g_free(importer->status_what); + g_mutex_free(importer->status_lock); - g_free (oli->filename); - if (oli->handle) - fclose (oli->handle); + if (importer->dialog) + gtk_widget_destroy(importer->dialog); - g_free (oli); + g_free(importer); +} + +static void +outlook_status(CamelOperation *op, const char *what, int pc, void *data) +{ + OutlookImporter *importer = data; + + if (pc == CAMEL_OPERATION_START) + pc = 0; + else if (pc == CAMEL_OPERATION_END) + pc = 100; + + g_mutex_lock(importer->status_lock); + g_free(importer->status_what); + importer->status_what = g_strdup(what); + importer->status_pc = pc; + g_mutex_unlock(importer->status_lock); } static gboolean -load_file_fn (EvolutionImporter *eimporter, - const char *filename, - void *closure) +outlook_status_timeout(void *data) { - OutlookImporter *oli; - MailImporter *importer; - struct stat buf; - long pos = 0x54; - char *uri; + OutlookImporter *importer = data; + int pc; + char *what; - oli = (OutlookImporter *) closure; - importer = (MailImporter *) oli; + if (!importer->status_what) + return TRUE; - oli->filename = g_strdup (filename); - /* Will return TRUE if oe4 format */ - oli->oe4 = support_format_fn (NULL, filename, NULL); - if (oli->oe4 == FALSE) { - g_warning ("Not OE4 format"); - return FALSE; - } + g_mutex_lock(importer->status_lock); + what = importer->status_what; + importer->status_what = NULL; + pc = importer->status_pc; + g_mutex_unlock(importer->status_lock); - oli->handle = fopen (filename, "rb"); - if (oli->handle == NULL) { - g_warning ("Cannot open the file"); - return FALSE; - } - - /* Get size of file */ - if (stat (filename, &buf) == -1) { - g_warning ("Cannot stat file"); - return FALSE; - } + gtk_progress_bar_set_fraction((GtkProgressBar *)importer->progressbar, (gfloat)(pc/100.0)); + gtk_progress_bar_set_text((GtkProgressBar *)importer->progressbar, what); - oli->size = buf.st_size; + return TRUE; +} - /* Set the fposition to the begining */ - fseek (oli->handle, pos, SEEK_SET); - oli->pos = pos; +static void +outlook_importer_response(GtkWidget *w, guint button, void *data) +{ + OutlookImporter *importer = data; - importer->mstream = NULL; + if (button == GTK_RESPONSE_CANCEL + && importer->cancel) + camel_operation_cancel(importer->cancel); +} -#warning "no uri for load file fn" - uri = NULL; - if (uri == NULL || *uri == 0) - importer->folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_INBOX); - else - importer->folder = mail_tool_uri_to_folder (uri, 0, NULL); +static gboolean +load_file_fn(EvolutionImporter *eimporter, const char *filename, void *data) +{ + OutlookImporter *importer = data; - if (importer->folder == NULL){ - g_warning ("Bad folder"); - return FALSE; - } + importer->dialog = gtk_message_dialog_new(NULL, 0/*GTK_DIALOG_NO_SEPARATOR*/, + GTK_MESSAGE_INFO, GTK_BUTTONS_CANCEL, + _("Importing `%s'"), filename); + gtk_window_set_title (GTK_WINDOW (importer->dialog), _("Importing...")); + + importer->label = gtk_label_new (_("Please wait")); + importer->progressbar = gtk_progress_bar_new (); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (importer->dialog)->vbox), importer->label, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (importer->dialog)->vbox), importer->progressbar, FALSE, FALSE, 0); + g_signal_connect(importer->dialog, "response", G_CALLBACK(outlook_importer_response), importer); + gtk_widget_show_all(importer->dialog); + + importer->status_timeout_id = g_timeout_add(100, outlook_status_timeout, importer); + importer->cancel = camel_operation_new(outlook_status, importer); + + mail_msg_wait(mail_importer_import_outlook(filename, importer->uri, importer->cancel)); + + camel_operation_unref(importer->cancel); + g_source_remove(importer->status_timeout_id); + importer->status_timeout_id = 0; - camel_folder_freeze (importer->folder); - oli->busy = FALSE; return TRUE; } @@ -287,3 +246,166 @@ outlook_importer_new(void) return BONOBO_OBJECT (importer); } + +struct _import_outlook_msg { + struct _mail_msg msg; + + char *path; + char *uri; + CamelOperation *cancel; +}; + +static char * +import_outlook_describe(struct _mail_msg *mm, int complete) +{ + return g_strdup (_("Importing mailbox")); +} + +static void +import_outlook_import(struct _mail_msg *mm) +{ + struct _import_outlook_msg *m = (struct _import_outlook_msg *) mm; + struct stat st; + CamelFolder *folder; + + 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)) { + CamelOperation *oldcancel = NULL; + CamelMessageInfo *info; + GByteArray *buffer; + int fd; + off_t pos; + + 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 fail; + } + + if (lseek(fd, 0x54, SEEK_SET) == -1) + goto fail; + + if (m->cancel) + oldcancel = camel_operation_register(m->cancel); + + camel_folder_freeze(folder); + + buffer = g_byte_array_new(); + pos = 0x54; + do { + oe_msg_segmentheader header; + int pc; + size_t len; + CamelStream *mem; + CamelMimeMessage *msg; + + if (st.st_size > 0) + pc = (int)(100.0 * ((double)pos / (double)st.st_size)); + camel_operation_progress(NULL, pc); + + if (read(fd, &header, sizeof(header)) != sizeof(header)) + goto fail2; + + pos += sizeof(header); + +#if G_BYTE_ORDER == G_BIG_ENDIAN + header.include = GUINT32_TO_BE(header.include); +#endif + /* the -4 is some magical value */ + len = header.include - sizeof(header) - 4; + /* sanity check */ + if (len > (pos + st.st_size)) + goto fail2; + g_byte_array_set_size(buffer, len); + if (read(fd, buffer->data, len) != len) + goto fail2; + + pos += len; + + mem = camel_stream_mem_new(); + camel_stream_mem_set_byte_array((CamelStreamMem *)mem, buffer); + + msg = camel_mime_message_new(); + if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)msg, mem) == -1) { + camel_object_unref(msg); + camel_object_unref(mem); + goto fail2; + } + + info = camel_message_info_new(); + /* any headers to read? */ + + camel_folder_append_message(folder, msg, info, NULL, &mm->ex); + + camel_message_info_free(info); + camel_object_unref(msg); + camel_object_unref(mem); + } while (!camel_exception_is_set(&mm->ex) && pos < st.st_size); + + camel_folder_sync(folder, FALSE, NULL); + camel_folder_thaw(folder); + camel_operation_end(NULL); + fail2: + /* TODO: these api's are a bit weird, registering the old is the same as deregistering */ + if (m->cancel) + camel_operation_register(oldcancel); + g_byte_array_free(buffer, TRUE); + } +fail: + camel_object_unref(folder); +} + +static void +import_outlook_done(struct _mail_msg *mm) +{ +} + +static void +import_outlook_free (struct _mail_msg *mm) +{ + struct _import_outlook_msg *m = (struct _import_outlook_msg *)mm; + + if (m->cancel) + camel_operation_unref(m->cancel); + g_free(m->uri); + g_free(m->path); +} + +static struct _mail_msg_op import_outlook_op = { + import_outlook_describe, + import_outlook_import, + import_outlook_done, + import_outlook_free, +}; + +static int +mail_importer_import_outlook(const char *path, const char *folderuri, CamelOperation *cancel) +{ + struct _import_outlook_msg *m; + int id; + + m = mail_msg_new(&import_outlook_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; +} |