diff options
author | hiro <hiro@ee746299-78ed-0310-b773-934348b2243d> | 2010-08-05 09:34:25 +0000 |
---|---|---|
committer | hiro <hiro@ee746299-78ed-0310-b773-934348b2243d> | 2010-08-05 09:34:25 +0000 |
commit | 9b7007098c2b9f7c7243af0547c5743e45101077 (patch) | |
tree | de030439de3b197298967f32632bc66ab95bb88d | |
parent | 29d50219202f293966474cb1e823750ec32cf4a2 (diff) |
implemented the import feature of Outlook Express mailboxes (dbx).
git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@2659 ee746299-78ed-0310-b773-934348b2243d
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | src/import.c | 180 |
2 files changed, 182 insertions, 3 deletions
@@ -1,3 +1,8 @@ +2010-08-05 + + * src/import.c: implemented the import feature of Outlook Express + mailboxes (dbx). + 2010-08-04 * plugin/attachment_tool/Makefile.am: fixed. diff --git a/src/import.c b/src/import.c index 955d9982..b0a4c21c 100644 --- a/src/import.c +++ b/src/import.c @@ -1,6 +1,6 @@ /* * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2009 Hiroyuki Yamamoto + * Copyright (C) 1999-2010 Hiroyuki Yamamoto * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,6 +41,8 @@ #include <gtk/gtkprogressbar.h> #include <gtk/gtkmenu.h> +#include <stdio.h> + #include "main.h" #include "inc.h" #include "mbox.h" @@ -59,7 +61,8 @@ enum { IMPORT_MBOX, - IMPORT_EML_FOLDER + IMPORT_EML_FOLDER, + IMPORT_DBX }; static GtkWidget *window; @@ -80,6 +83,8 @@ static void import_create (void); static gint import_do (void); static gint import_eml_folder (FolderItem *dest, const gchar *path); +static gint import_dbx (FolderItem *dest, + const gchar *file); static void import_format_menu_cb (GtkWidget *widget, gpointer data); @@ -180,7 +185,7 @@ static gint import_do(void) filename = g_filename_from_utf8(utf8filename, -1, NULL, NULL, NULL); if (!filename) { - g_warning("faild to convert character set."); + g_warning("failed to convert character set."); filename = g_strdup(utf8filename); } if (!g_file_test(filename, G_FILE_TEST_EXISTS)) { @@ -219,6 +224,8 @@ static gint import_do(void) folder_set_ui_func(dest->folder, NULL, NULL); } else if (type == IMPORT_EML_FOLDER) { ok = import_eml_folder(dest, filename); + } else if (type == IMPORT_DBX) { + ok = import_dbx(dest, filename); } progress_dialog_set_label(progress, _("Scanning folder...")); @@ -291,6 +298,170 @@ static gint import_eml_folder(FolderItem *dest, const gchar *path) return ok; } +static gint32 read_dword(FILE *fp, off_t offset) +{ + gint32 dw; + + if (fseek(fp, offset, SEEK_SET) < 0) { + perror("read_dword: fseek"); + return 0; + } + + if (fread(&dw, sizeof(dw), 1, fp) != 1) + return 0; + + dw = GINT32_FROM_LE(dw); + + return dw; +} + +static void get_dbx_index(FILE *fp, gint32 table_pos, GArray *array) +{ + gint32 another_pos, data_pos; + gint32 num_index, num_elems; + gint i; + + debug_print("get_dbx_index(%08x)\n", table_pos); + + another_pos = read_dword(fp, table_pos + 0x08); + num_elems = read_dword(fp, table_pos + 0x11) & 0x00ffffff; + num_index = read_dword(fp, table_pos + 0x14); + debug_print("table_pos: %08x another_pos: %08x num_elems: %08x num_index: %08x\n", table_pos, another_pos, num_elems, num_index); + if (another_pos > 0 && num_index > 0) + get_dbx_index(fp, another_pos, array); + + table_pos += 0x18; + for (i = 0; i < num_elems; i++) { + data_pos = read_dword(fp, table_pos); + if (data_pos == 0) { + g_warning("get_dbx_index: null data_pos at %08x", + table_pos); + break; + } + g_array_append_val(array, data_pos); + another_pos = read_dword(fp, table_pos + 0x04); + num_index = read_dword(fp, table_pos + 0x08); + debug_print("data_pos: %08x another_pos: %08x num_index: %08x\n", data_pos, another_pos, num_index); + table_pos += 0x0c; + if (another_pos > 0 && num_index > 0) + get_dbx_index(fp, another_pos, array); + } + + debug_print("get_dbx_index end\n"); +} + +static gint get_dbx_data(FILE *fp, gint32 data_pos, FolderItem *dest) +{ + gchar *tmp; + FILE *outfp; + gint32 mail_flag, news_flag; + gint32 data_ptr, data_len, next_ptr; + MsgFlags flags = {MSG_NEW|MSG_UNREAD, MSG_RECEIVED}; + gint ok = 0; + + debug_print("get_dbx_data(%08x)\n", data_pos); + + mail_flag = read_dword(fp, data_pos + 0x18); + news_flag = read_dword(fp, data_pos + 0x1c); + if ((news_flag & 0x0f) == 4) + data_ptr = news_flag; + else if ((mail_flag & 0x0f) == 4) + data_ptr = mail_flag; + else + return 0; + + if ((data_ptr & 0xff) >= 0x80) + data_ptr >>= 8; + else { + guchar b1 = (guchar)(data_ptr >>= 8); + guchar b2 = (guchar)read_dword(fp, data_pos + 0x0a); + data_ptr = read_dword(fp, data_pos + 0x0c + b2 * 4 + b1); + } + if (data_ptr == 0) { + g_warning("get_dbx_data(%08x): could not get data_ptr.", data_pos); + return 0; + } + + tmp = get_tmp_file(); + if ((outfp = g_fopen(tmp, "wb")) == NULL) { + FILE_OP_ERROR(tmp, "fopen"); + ok = -1; + goto finish; + } + + while (data_ptr) { + data_len = read_dword(fp, data_ptr + 0x08); + next_ptr = read_dword(fp, data_ptr + 0x0c); + if (append_file_part(fp, data_ptr + 0x10, data_len, outfp) < 0) { + fclose(outfp); + g_unlink(tmp); + ok = -1; + goto finish; + } + data_ptr = next_ptr; + } + + if (fclose(outfp) == EOF) { + FILE_OP_ERROR(tmp, "fclose"); + g_unlink(tmp); + ok = -1; + goto finish; + } + + if (folder_item_add_msg(dest, tmp, &flags, TRUE) < 0) { + g_warning("get_dbx_data: folder_item_add_msg() failed."); + g_unlink(tmp); + ok = -1; + } + +finish: + g_free(tmp); + return ok; +} + +static gint import_dbx(FolderItem *dest, const gchar *file) +{ + FILE *fp; + gint32 dw; + gint32 table_pos; + gint count = 0; + GArray *array; + gint i; + + g_return_val_if_fail(dest != NULL, -1); + g_return_val_if_fail(file != NULL, -1); + + if ((fp = g_fopen(file, "rb")) == NULL) { + FILE_OP_ERROR(file, "fopen"); + return -1; + } + + if ((dw = read_dword(fp, 0xc4)) == 0) { + fclose(fp); + return -1; + } + + array = g_array_sized_new(FALSE, FALSE, sizeof(gint32), 1024); + + table_pos = read_dword(fp, 0xe4); + if (table_pos > 0) + get_dbx_index(fp, table_pos, array); + + for (i = 0; i < array->len; i++) { + proc_mbox_func(dest->folder, dest, GINT_TO_POINTER(count + 1)); + if (get_dbx_data(fp, g_array_index(array, gint32, i), dest) < 0) + break; + count++; + } + + debug_print("import_dbx: %d imported\n", count); + + g_array_free(array, TRUE); + fclose(fp); + + return 0; +} + static void import_create(void) { GtkWidget *vbox; @@ -358,6 +529,9 @@ static void import_create(void) MENUITEM_ADD(menu, menuitem, _("eml (folder)"), IMPORT_EML_FOLDER); g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(import_format_menu_cb), NULL); + MENUITEM_ADD(menu, menuitem, _("Outlook Express (dbx)"), IMPORT_DBX); + g_signal_connect(G_OBJECT(menuitem), "activate", + G_CALLBACK(import_format_menu_cb), NULL); gtk_option_menu_set_menu(GTK_OPTION_MENU(format_optmenu), menu); |