Add export LDIF.
authorMatch Grun <match@dimensional.com>
Tue, 5 Aug 2003 04:14:35 +0000 (04:14 +0000)
committerMatch Grun <match@dimensional.com>
Tue, 5 Aug 2003 04:14:35 +0000 (04:14 +0000)
14 files changed:
ChangeLog.claws
configure.ac
src/Makefile.am
src/addressbook.c
src/common/xmlprops.h
src/exphtmldlg.c
src/exphtmldlg.h
src/expldifdlg.c [new file with mode: 0644]
src/expldifdlg.h [new file with mode: 0644]
src/exportldif.c [new file with mode: 0644]
src/exportldif.h [new file with mode: 0644]
src/importldif.c
src/ldif.c
src/ldif.h

index 5438e7b..792162a 100644 (file)
@@ -11,7 +11,7 @@
        * src/exportldif.[ch]                   ** NEW **
        * src/expldifdlg.[ch]                   ** NEW **
        * src/addressbook.[ch]
-       * po/Makefile.in
+       * src/Makefile.am
                export of LDIF files.
                documented.
 
index 6732387..0abbf75 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=9
 MICRO_VERSION=4
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=1
+EXTRA_VERSION=2
 if test $EXTRA_VERSION -eq 0; then
     VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.${MICRO_VERSION}claws
 else
index e11eb9d..025b878 100644 (file)
@@ -31,8 +31,10 @@ sylpheed_SOURCES = \
        editvcard.c \
        enriched.c \
        exphtmldlg.c \
+       expldifdlg.c \
        export.c \
        exporthtml.c \
+       exportldif.c \
        filtering.c \
        folder.c \
        folder_item_prefs.c \
index dbf57c5..a76ca48 100644 (file)
@@ -96,6 +96,7 @@
 #include "addrgather.h"
 #include "adbookbase.h"
 #include "exphtmldlg.h"
+#include "expldifdlg.h"
 
 typedef enum
 {
@@ -340,6 +341,7 @@ static void addressbook_import_ldif_cb              ( void );
 static void addressbook_import_mutt_cb         ( void );
 static void addressbook_import_pine_cb         ( void );
 static void addressbook_export_html_cb         ( void );
+static void addressbook_export_ldif_cb         ( void );
 static void addressbook_clip_cut_cb            ( void );
 static void addressbook_clip_copy_cb           ( void );
 static void addressbook_clip_paste_cb          ( void );
@@ -384,6 +386,7 @@ static GtkItemFactoryEntry addressbook_entries[] =
        {N_("/_Tools/Import _Pine file..."), NULL,      addressbook_import_pine_cb,     0, NULL},
        {N_("/_Tools/---"),             NULL,           NULL, 0, "<Separator>"},
        {N_("/_Tools/Export _HTML..."), NULL,           addressbook_export_html_cb,     0, NULL},
+       {N_("/_Tools/Export LDI_F..."), NULL,           addressbook_export_ldif_cb,     0, NULL},
        {N_("/_Help"),                  NULL,           NULL, 0, "<LastBranch>"},
        {N_("/_Help/_About"),           NULL,           about_show, 0, NULL}
 };
@@ -1271,6 +1274,7 @@ static void addressbook_menuitem_set_sensitive( AddressObject *obj, GtkCTreeNode
 
        /* Export data */
        menu_set_sensitive( addrbook.menu_factory, "/Tools/Export HTML...", canExport );
+       menu_set_sensitive( addrbook.menu_factory, "/Tools/Export LDIF...", canExport );
 }
 
 static void addressbook_tree_selected(GtkCTree *ctree, GtkCTreeNode *node,
@@ -4122,6 +4126,30 @@ static void addressbook_export_html_cb( void ) {
        addressbook_exp_html( cache );
 }
 
+/*
+* Export LDIF file.
+*/
+static void addressbook_export_ldif_cb( void ) {
+       GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
+       AddressObject *obj;
+       AddressDataSource *ds = NULL;
+       AddrBookBase *adbase;
+       AddressCache *cache;
+       GtkCTreeNode *node = NULL;
+
+       if( ! addrbook.treeSelected ) return;
+       node = addrbook.treeSelected;
+       if( GTK_CTREE_ROW(node)->level == 1 ) return;
+       obj = gtk_ctree_node_get_row_data( ctree, node );
+       if( obj == NULL ) return;
+
+       ds = addressbook_find_datasource( node );
+       if( ds == NULL ) return;
+       adbase = ( AddrBookBase * ) ds->rawDataSource;
+       cache = adbase->addressCache;
+       addressbook_exp_ldif( cache );
+}
+
 /*
 * End of Source.
 */
index 95df526..49536ab 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 2002 Match Grun
+ * Copyright (C) 2002-2003 Match Grun
  *
  * 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
index ab53717..1efa080 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 2002 Match Grun
+ * Copyright (C) 2002-2003 Match Grun
  *
  * 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
@@ -54,6 +54,9 @@
 #define EXPORTHTML_WIDTH           480
 #define EXPORTHTML_HEIGHT          -1
 
+/**
+ * Dialog object.
+ */
 static struct _ExpHtml_Dlg {
        GtkWidget *window;
        GtkWidget *notebook;
@@ -79,6 +82,10 @@ static struct _AddressFileSelection _exp_html_file_selector_;
 static ExportHtmlCtl *_exportCtl_ = NULL;
 static AddressCache *_addressCache_ = NULL;
 
+/**
+ * Display message in status field.
+ * \param msg Message to display.
+ */
 static void export_html_status_show( gchar *msg ) {
        if( exphtml_dlg.statusbar != NULL ) {
                gtk_statusbar_pop(
@@ -92,6 +99,9 @@ static void export_html_status_show( gchar *msg ) {
        }
 }
 
+/**
+ * Select and display status message appropriate for the page being displayed.
+ */
 static void export_html_message( void ) {
        gchar *sMsg = NULL;
        gint pageNum;
@@ -109,6 +119,11 @@ static void export_html_message( void ) {
        export_html_status_show( sMsg );
 }
 
+/**
+ * Callback function to cancel HTML file selection dialog.
+ * \param widget Widget (button).
+ * \param data   User data.
+ */
 static void export_html_cancel( GtkWidget *widget, gpointer data ) {
        gint pageNum;
 
@@ -119,22 +134,34 @@ static void export_html_cancel( GtkWidget *widget, gpointer data ) {
        gtk_main_quit();
 }
 
+/**
+ * Callback function to handle dialog close event.
+ * \param widget Widget (dialog).
+ * \param event  Event object.
+ * \param data   User data.
+ */
 static gint export_html_delete_event( GtkWidget *widget, GdkEventAny *event, gpointer data ) {
        export_html_cancel( widget, data );
        return TRUE;
 }
 
+/**
+ * Callback function to respond to dialog key press events.
+ * \param widget Widget.
+ * \param event  Event object.
+ * \param data   User data.
+ */
 static void export_html_key_pressed( GtkWidget *widget, GdkEventKey *event, gpointer data ) {
        if (event && event->keyval == GDK_Escape) {
                export_html_cancel( widget, data );
        }
 }
 
-/*
- * Move off file info page.
- * return: TRUE if OK to move off page.
+/**
+ * Test whether we can move off file page.
+ * \return <i>TRUE</i> if OK to move off page.
  */
-static gboolean exp_html_move_file() {
+static gboolean exp_html_move_file( void ) {
        gchar *sFile, *msg, *reason;
        AlertValue aval;
 
@@ -174,11 +201,12 @@ static gboolean exp_html_move_file() {
        return TRUE;
 }
 
-/*
- * Move off format page.
- * return: TRUE if OK to move off page.
+/**
+ * Test whether we can move off format page.
+ * \return <i>TRUE</i> if OK to move off page.
  */
-static gboolean exp_html_move_format() {
+static gboolean exp_html_move_format( void ) {
+       gboolean retVal = FALSE;
        GtkWidget *menu, *menuItem;
        gint id;
 
@@ -206,21 +234,27 @@ static gboolean exp_html_move_format() {
 
        /* Process export */
        exporthtml_process( _exportCtl_, _addressCache_ );
-
-       return TRUE;
+       if( _exportCtl_->retVal == MGU_SUCCESS ) {
+               retVal = TRUE;
+       }
+       else {
+               export_html_status_show( _( "Error creating HTML file" ) );
+       }
+       return retVal;
 }
 
-/*
+/**
  * Display finish page.
  */
-static void exp_html_finish_show() {
+static void exp_html_finish_show( void ) {
        gtk_label_set_text( GTK_LABEL(exphtml_dlg.labelOutFile), _exportCtl_->path );
        gtk_widget_set_sensitive( exphtml_dlg.btnNext, FALSE );
        gtk_widget_grab_focus( exphtml_dlg.btnCancel );
 }
 
-/*
- * Previous button handler.
+/**
+ * Callback function to select previous page.
+ * \param widget Widget (button).
  */
 static void export_html_prev( GtkWidget *widget ) {
        gint pageNum;
@@ -241,8 +275,9 @@ static void export_html_prev( GtkWidget *widget ) {
        export_html_message();
 }
 
-/*
- * Next button handler.
+/**
+ * Callback function to select previous page.
+ * \param widget Widget (button).
  */
 static void export_html_next( GtkWidget *widget ) {
        gint pageNum;
@@ -255,6 +290,7 @@ static void export_html_next( GtkWidget *widget ) {
                                GTK_NOTEBOOK(exphtml_dlg.notebook), PAGE_FORMAT );
                        gtk_widget_set_sensitive( exphtml_dlg.btnPrev, TRUE );
                }
+               export_html_message();
        }
        else if( pageNum == PAGE_FORMAT ) {
                /* Goto finish page */
@@ -263,13 +299,15 @@ static void export_html_next( GtkWidget *widget ) {
                                GTK_NOTEBOOK(exphtml_dlg.notebook), PAGE_FINISH );
                        exp_html_finish_show();
                        exporthtml_save_settings( _exportCtl_ );
+                       export_html_message();
                }
        }
-       export_html_message();
 }
 
-/*
+/**
  * Open file with web browser.
+ * \param widget Widget (button).
+ * \param data   User data.
  */
 static void export_html_browse( GtkWidget *widget, gpointer data ) {
        gchar *uri;
@@ -279,8 +317,10 @@ static void export_html_browse( GtkWidget *widget, gpointer data ) {
        g_free( uri );
 }
 
-/*
- * Output file - Ok.
+/**
+ * Callback function to accept HTML file selection.
+ * \param widget Widget (button).
+ * \param data   User data.
  */
 static void exp_html_file_ok( GtkWidget *widget, gpointer data ) {
        gchar *sFile;
@@ -298,8 +338,10 @@ static void exp_html_file_ok( GtkWidget *widget, gpointer data ) {
        gtk_widget_grab_focus( exphtml_dlg.entryHtml );
 }
 
-/*
- * Output file - Cancel.
+/**
+ * Callback function to cancel HTML file selection dialog.
+ * \param widget Widget (button).
+ * \param data   User data.
  */
 static void exp_html_file_cancel( GtkWidget *widget, gpointer data ) {
        AddressFileSelection *afs = ( AddressFileSelection * ) data;
@@ -309,8 +351,9 @@ static void exp_html_file_cancel( GtkWidget *widget, gpointer data ) {
        gtk_widget_grab_focus( exphtml_dlg.entryHtml );
 }
 
-/*
- * Output file - Create.
+/**
+ * Create HTML file selection dialog.
+ * \param afs Address file selection data.
  */
 static void exp_html_file_select_create( AddressFileSelection *afs ) {
        GtkWidget *fileSelector;
@@ -326,8 +369,8 @@ static void exp_html_file_select_create( AddressFileSelection *afs ) {
        afs->cancelled = TRUE;
 }
 
-/*
- * Output file - Handle file selection.
+/**
+ * Callback function to display HTML file selection dialog.
  */
 static void exp_html_file_select( void ) {
        gchar *sFile;
@@ -343,6 +386,11 @@ static void exp_html_file_select( void ) {
        gtk_grab_add( _exp_html_file_selector_.fileSelector );
 }
 
+/**
+ * Format notebook file specification page.
+ * \param pageNum Page (tab) number.
+ * \param pageLbl Page (tab) label.
+ */
 static void export_html_page_file( gint pageNum, gchar *pageLbl ) {
        GtkWidget *vbox;
        GtkWidget *table;
@@ -407,6 +455,11 @@ static void export_html_page_file( gint pageNum, gchar *pageLbl ) {
        exphtml_dlg.entryHtml = entryHtml;
 }
 
+/**
+ * Format notebook format page.
+ * \param pageNum Page (tab) number.
+ * \param pageLbl Page (tab) label.
+ */
 static void export_html_page_format( gint pageNum, gchar *pageLbl ) {
        GtkWidget *vbox;
        GtkWidget *table;
@@ -445,7 +498,7 @@ static void export_html_page_format( gint pageNum, gchar *pageLbl ) {
                GTK_FILL, 0, 0, 0);
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 
-       menu = gtk_menu_new ();
+       menu = gtk_menu_new();
 
        menuItem = gtk_menu_item_new_with_label( _( "None" ) );
        gtk_object_set_user_data( GTK_OBJECT( menuItem ),
@@ -502,7 +555,7 @@ static void export_html_page_format( gint pageNum, gchar *pageLbl ) {
                GTK_FILL, 0, 0, 0);
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 
-       menu = gtk_menu_new ();
+       menu = gtk_menu_new();
 
        menuItem = gtk_menu_item_new_with_label( _( "First Name, Last Name" ) );
        gtk_object_set_user_data( GTK_OBJECT( menuItem ),
@@ -549,6 +602,11 @@ static void export_html_page_format( gint pageNum, gchar *pageLbl ) {
        exphtml_dlg.checkAttributes = checkAttributes;
 }
 
+/**
+ * Format notebook finish page.
+ * \param pageNum Page (tab) number.
+ * \param pageLbl Page (tab) label.
+ */
 static void export_html_page_finish( gint pageNum, gchar *pageLbl ) {
        GtkWidget *vbox;
        GtkWidget *table;
@@ -576,9 +634,9 @@ static void export_html_page_finish( gint pageNum, gchar *pageLbl ) {
 
        /* First row */
        top = 0;
-       label = gtk_label_new( _( "Address Book" ) );
+       label = gtk_label_new( _( "Address Book :" ) );
        gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
-       gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+       gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
 
        labelBook = gtk_label_new("Full name of address book goes here");
        gtk_table_attach(GTK_TABLE(table), labelBook, 1, 2, top, (top + 1), GTK_FILL, 0, 0, 0);
@@ -586,9 +644,9 @@ static void export_html_page_finish( gint pageNum, gchar *pageLbl ) {
 
        /* Second row */
        top++;
-       label = gtk_label_new( _( "File Name" ) );
+       label = gtk_label_new( _( "File Name :" ) );
        gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
-       gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+       gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
 
        labelFile = gtk_label_new("File name goes here");
        gtk_table_attach(GTK_TABLE(table), labelFile, 1, 2, top, (top + 1), GTK_FILL, 0, 0, 0);
@@ -609,7 +667,10 @@ static void export_html_page_finish( gint pageNum, gchar *pageLbl ) {
        exphtml_dlg.labelOutFile = labelFile;
 }
 
-static void export_html_dialog_create() {
+/**
+ * Create main dialog decorations (excluding notebook pages).
+ */
+static void export_html_dialog_create( void ) {
        GtkWidget *window;
        GtkWidget *vbox;
        GtkWidget *vnbox;
@@ -646,7 +707,7 @@ static void export_html_dialog_create() {
 
        /* Notebook */
        notebook = gtk_notebook_new();
-       gtk_notebook_set_show_tabs( GTK_NOTEBOOK(notebook), FALSE );
+       gtk_notebook_set_show_tabs( GTK_NOTEBOOK(notebook), FALSE ); /* Hide */
        /* gtk_notebook_set_show_tabs( GTK_NOTEBOOK(notebook), TRUE ); */
        gtk_widget_show(notebook);
        gtk_box_pack_start(GTK_BOX(vnbox), notebook, TRUE, TRUE, 0);
@@ -684,10 +745,12 @@ static void export_html_dialog_create() {
        exphtml_dlg.statusbar  = statusbar;
        exphtml_dlg.status_cid = gtk_statusbar_get_context_id(
                        GTK_STATUSBAR(statusbar), "Export HTML Dialog" );
-
 }
 
-static void export_html_create() {
+/**
+ * Create export HTML dialog.
+ */
+static void export_html_create( void ) {
        export_html_dialog_create();
        export_html_page_file( PAGE_FILE_INFO, _( "File Info" ) );
        export_html_page_format( PAGE_FORMAT, _( "Format" ) );
@@ -695,9 +758,9 @@ static void export_html_create() {
        gtk_widget_show_all( exphtml_dlg.window );
 }
 
-/*
+/**
  * Populate fields from control data.
- * Enter:  ctl   Export control data.
+ * \param ctl Export control data.
  */
 static void export_html_fill_fields( ExportHtmlCtl *ctl ) {
        gtk_entry_set_text( GTK_ENTRY(exphtml_dlg.entryHtml), "" );
@@ -718,9 +781,9 @@ static void export_html_fill_fields( ExportHtmlCtl *ctl ) {
                GTK_TOGGLE_BUTTON( exphtml_dlg.checkAttributes ), ctl->showAttribs );
 }
 
-/*
+/**
  * Process export address dialog.
- * Enter: cache Address book/data source cache.
+ * \param cache Address book/data source cache.
  */
 void addressbook_exp_html( AddressCache *cache ) {
        /* Set references to control data */
@@ -757,6 +820,8 @@ void addressbook_exp_html( AddressCache *cache ) {
 }
 
 /*
-* End of Source.
-*/
+ * ============================================================================
+ * End of Source.
+ * ============================================================================
+ */
 
index 26addaf..6d2e5b0 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 2002 Match Grun
+ * Copyright (C) 2002-2003 Match Grun
  *
  * 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
diff --git a/src/expldifdlg.c b/src/expldifdlg.c
new file mode 100644 (file)
index 0000000..7d9bb26
--- /dev/null
@@ -0,0 +1,849 @@
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2003 Match Grun
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+/*
+ * Export address book to LDIF file.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include "defs.h"
+
+#include <glib.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkwindow.h>
+#include <gtk/gtksignal.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtktable.h>
+#include <gtk/gtkbutton.h>
+
+#include "intl.h"
+#include "gtkutils.h"
+#include "prefs_common.h"
+#include "alertpanel.h"
+#include "mgutils.h"
+#include "addrcache.h"
+#include "addressitem.h"
+#include "exportldif.h"
+#include "utils.h"
+#include "manage_window.h"
+
+#define PAGE_FILE_INFO             0
+#define PAGE_DN                    1
+#define PAGE_FINISH                2
+
+#define EXPORTLDIF_WIDTH           480
+#define EXPORTLDIF_HEIGHT          -1
+
+/**
+ * Dialog object.
+ */
+static struct _ExpLdif_Dlg {
+       GtkWidget *window;
+       GtkWidget *notebook;
+       GtkWidget *labelBook;
+       GtkWidget *entryLdif;
+       GtkWidget *entrySuffix;
+       GtkWidget *optmenuRDN;
+       GtkWidget *checkUseDN;
+       GtkWidget *checkEMail;
+       GtkWidget *labelOutBook;
+       GtkWidget *labelOutFile;
+       GtkWidget *btnPrev;
+       GtkWidget *btnNext;
+       GtkWidget *btnCancel;
+       GtkWidget *statusbar;
+       gint      status_cid;
+       gboolean  cancelled;
+} expldif_dlg;
+
+static struct _AddressFileSelection _exp_ldif_file_selector_;
+
+static ExportLdifCtl *_exportCtl_ = NULL;
+static AddressCache *_addressCache_ = NULL;
+
+/**
+ * Display message in status field.
+ * \param msg Message to display.
+ */
+static void export_ldif_status_show( gchar *msg ) {
+       if( expldif_dlg.statusbar != NULL ) {
+               gtk_statusbar_pop(
+                       GTK_STATUSBAR(expldif_dlg.statusbar),
+                       expldif_dlg.status_cid );
+               if( msg ) {
+                       gtk_statusbar_push(
+                               GTK_STATUSBAR(expldif_dlg.statusbar),
+                               expldif_dlg.status_cid, msg );
+               }
+       }
+}
+
+/**
+ * Select and display status message appropriate for the page being displayed.
+ */
+static void export_ldif_message( void ) {
+       gchar *sMsg = NULL;
+       gint pageNum;
+
+       pageNum = gtk_notebook_current_page( GTK_NOTEBOOK(expldif_dlg.notebook) );
+       if( pageNum == PAGE_FILE_INFO ) {
+               sMsg = _( "Please specify output directory and LDIF filename to create." );
+       }
+       else if( pageNum == PAGE_DN ) {
+               sMsg = _( "Specify parameters to format distinguished name." );
+       }
+       else if( pageNum == PAGE_FINISH ) {
+               sMsg = _( "File exported successfully." );
+       }
+       export_ldif_status_show( sMsg );
+}
+
+/**
+ * Callback function to cancel LDIF file selection dialog.
+ * \param widget Widget (button).
+ * \param data   User data.
+ */
+static void export_ldif_cancel( GtkWidget *widget, gpointer data ) {
+       gint pageNum;
+
+       pageNum = gtk_notebook_current_page( GTK_NOTEBOOK(expldif_dlg.notebook) );
+       if( pageNum != PAGE_FINISH ) {
+               expldif_dlg.cancelled = TRUE;
+       }
+       gtk_main_quit();
+}
+
+/**
+ * Callback function to handle dialog close event.
+ * \param widget Widget (dialog).
+ * \param event  Event object.
+ * \param data   User data.
+ */
+static gint export_ldif_delete_event( GtkWidget *widget, GdkEventAny *event, gpointer data ) {
+       export_ldif_cancel( widget, data );
+       return TRUE;
+}
+
+/**
+ * Callback function to respond to dialog key press events.
+ * \param widget Widget.
+ * \param event  Event object.
+ * \param data   User data.
+ */
+static void export_ldif_key_pressed( GtkWidget *widget, GdkEventKey *event, gpointer data ) {
+       if (event && event->keyval == GDK_Escape) {
+               export_ldif_cancel( widget, data );
+       }
+}
+
+/**
+ * Test whether we can move off file page.
+ * \return <i>TRUE</i> if OK to move off page.
+ */
+static gboolean exp_ldif_move_file( void ) {
+       gchar *sFile, *msg, *reason;
+       gboolean errFlag = FALSE;
+       AlertValue aval;
+
+       sFile = gtk_editable_get_chars( GTK_EDITABLE(expldif_dlg.entryLdif), 0, -1 );
+       g_strchug( sFile ); g_strchomp( sFile );
+       gtk_entry_set_text( GTK_ENTRY(expldif_dlg.entryLdif), sFile );
+       exportldif_parse_filespec( _exportCtl_, sFile );
+
+       /* Test that something was supplied */
+       if( *sFile == '\0'|| strlen( sFile ) < 1 ) {
+               gtk_widget_grab_focus( expldif_dlg.entryLdif );
+               errFlag = TRUE;
+       }
+       g_free( sFile );
+       if( errFlag ) return FALSE;
+
+       /* Test for directory */
+       if( exportldif_test_dir( _exportCtl_ ) ) {
+               return TRUE;
+       }
+
+       /* Prompt to create */
+       msg = g_strdup_printf( _(
+               "LDIF Output Directory '%s'\n" \
+               "does not exist. OK to create new directory?" ),
+               _exportCtl_->dirOutput );
+       aval = alertpanel( _("Create Directory" ),
+               msg, _( "Yes" ), _( "No" ), NULL );
+       g_free( msg );
+       if( aval != G_ALERTDEFAULT ) return FALSE;
+
+       /* Create directory */
+       if( ! exportldif_create_dir( _exportCtl_ ) ) {
+               reason = exportldif_get_create_msg( _exportCtl_ );
+               msg = g_strdup_printf( _(
+                       "Could not create output directory for LDIF file:\n%s" ),
+                       reason );
+               aval = alertpanel( _( "Failed to Create Directory" ),
+                       msg, _( "Close" ), NULL, NULL );
+               g_free( msg );
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+/**
+ * Test whether we can move off distinguished name page.
+ * \return <i>TRUE</i> if OK to move off page.
+ */
+static gboolean exp_ldif_move_dn( void ) {
+       gboolean retVal = FALSE;
+       gboolean errFlag = FALSE;
+       gchar *suffix;
+       GtkWidget *menu, *menuItem;
+       gint id;
+
+       /* Set suffix */
+       suffix = gtk_editable_get_chars( GTK_EDITABLE(expldif_dlg.entrySuffix), 0, -1 );
+       g_strchug( suffix ); g_strchomp( suffix );
+
+       /* Set RDN format */
+       menu = gtk_option_menu_get_menu( GTK_OPTION_MENU( expldif_dlg.optmenuRDN ) );
+       menuItem = gtk_menu_get_active( GTK_MENU( menu ) );
+       id = GPOINTER_TO_INT( gtk_object_get_user_data(GTK_OBJECT(menuItem)) );
+       exportldif_set_rdn( _exportCtl_, id );
+
+       exportldif_set_suffix( _exportCtl_, suffix );
+       exportldif_set_use_dn( _exportCtl_,
+               gtk_toggle_button_get_active(
+                       GTK_TOGGLE_BUTTON( expldif_dlg.checkUseDN ) ) );
+       exportldif_set_exclude_email( _exportCtl_,
+               gtk_toggle_button_get_active(
+                       GTK_TOGGLE_BUTTON( expldif_dlg.checkEMail ) ) );
+
+       if( *suffix == '\0' || strlen( suffix ) < 1 ) {
+               AlertValue aval;
+
+               aval = alertpanel(
+                       _( "Suffix was not supplied" ),
+                       _(
+                               "A suffix is required if data is to be used " \
+                               "for an LDAP server. Are you sure you wish " \
+                               "to proceed without a suffix?"
+                        ),
+                       _( "Yes" ), _( "No" ), NULL );
+               if( aval != G_ALERTDEFAULT ) {
+                       gtk_widget_grab_focus( expldif_dlg.entrySuffix );
+                       errFlag = TRUE;
+               }
+       }
+
+       if( ! errFlag ) {
+               /* Process export */
+               exportldif_process( _exportCtl_, _addressCache_ );
+               if( _exportCtl_->retVal == MGU_SUCCESS ) {
+                       retVal = TRUE;
+               }
+               else {
+                       export_ldif_status_show( _( "Error creating LDIF file" ) );
+               }
+       }
+
+       return retVal;
+}
+
+/**
+ * Display finish page.
+ */
+static void exp_ldif_finish_show( void ) {
+       gtk_label_set_text( GTK_LABEL(expldif_dlg.labelOutFile), _exportCtl_->path );
+       gtk_widget_set_sensitive( expldif_dlg.btnNext, FALSE );
+       gtk_widget_grab_focus( expldif_dlg.btnCancel );
+}
+
+/**
+ * Callback function to select previous page.
+ * \param widget Widget (button).
+ */
+static void export_ldif_prev( GtkWidget *widget ) {
+       gint pageNum;
+
+       pageNum = gtk_notebook_current_page( GTK_NOTEBOOK(expldif_dlg.notebook) );
+       if( pageNum == PAGE_DN ) {
+               /* Goto file page stuff */
+               gtk_notebook_set_page(
+                       GTK_NOTEBOOK(expldif_dlg.notebook), PAGE_FILE_INFO );
+               gtk_widget_set_sensitive( expldif_dlg.btnPrev, FALSE );
+       }
+       else if( pageNum == PAGE_FINISH ) {
+               /* Goto format page */
+               gtk_notebook_set_page(
+                       GTK_NOTEBOOK(expldif_dlg.notebook), PAGE_DN );
+               gtk_widget_set_sensitive( expldif_dlg.btnNext, TRUE );
+       }
+       export_ldif_message();
+}
+
+/**
+ * Callback function to select next page.
+ * \param widget Widget (button).
+ */
+static void export_ldif_next( GtkWidget *widget ) {
+       gint pageNum;
+
+       pageNum = gtk_notebook_current_page( GTK_NOTEBOOK(expldif_dlg.notebook) );
+       if( pageNum == PAGE_FILE_INFO ) {
+               /* Goto distinguished name page */
+               if( exp_ldif_move_file() ) {
+                       gtk_notebook_set_page(
+                               GTK_NOTEBOOK(expldif_dlg.notebook), PAGE_DN );
+                       gtk_widget_set_sensitive( expldif_dlg.btnPrev, TRUE );
+               }
+               export_ldif_message();
+       }
+       else if( pageNum == PAGE_DN ) {
+               /* Goto finish page */
+               if( exp_ldif_move_dn() ) {
+                       gtk_notebook_set_page(
+                               GTK_NOTEBOOK(expldif_dlg.notebook), PAGE_FINISH );
+                       exp_ldif_finish_show();
+                       exportldif_save_settings( _exportCtl_ );
+                       export_ldif_message();
+               }
+       }
+}
+
+/**
+ * Callback function to accept LDIF file selection.
+ * \param widget Widget (button).
+ * \param data   User data.
+ */
+static void exp_ldif_file_ok( GtkWidget *widget, gpointer data ) {
+       gchar *sFile;
+       AddressFileSelection *afs;
+       GtkWidget *fileSel;
+
+       afs = ( AddressFileSelection * ) data;
+       fileSel = afs->fileSelector;
+       sFile = gtk_file_selection_get_filename( GTK_FILE_SELECTION(fileSel) );
+
+       afs->cancelled = FALSE;
+       gtk_entry_set_text( GTK_ENTRY(expldif_dlg.entryLdif), sFile );
+       gtk_widget_hide( afs->fileSelector );
+       gtk_grab_remove( afs->fileSelector );
+       gtk_widget_grab_focus( expldif_dlg.entryLdif );
+}
+
+/**
+ * Callback function to cancel LDIF file selection dialog.
+ * \param widget Widget (button).
+ * \param data   User data.
+ */
+static void exp_ldif_file_cancel( GtkWidget *widget, gpointer data ) {
+       AddressFileSelection *afs = ( AddressFileSelection * ) data;
+       afs->cancelled = TRUE;
+       gtk_widget_hide( afs->fileSelector );
+       gtk_grab_remove( afs->fileSelector );
+       gtk_widget_grab_focus( expldif_dlg.entryLdif );
+}
+
+/**
+ * Create LDIF file selection dialog.
+ * \param afs Address file selection data.
+ */
+static void exp_ldif_file_select_create( AddressFileSelection *afs ) {
+       GtkWidget *fileSelector;
+
+       fileSelector = gtk_file_selection_new( _("Select LDIF Output File") );
+       gtk_file_selection_hide_fileop_buttons( GTK_FILE_SELECTION(fileSelector) );
+       gtk_file_selection_complete( GTK_FILE_SELECTION(fileSelector), "*.html" );
+       gtk_signal_connect( GTK_OBJECT (GTK_FILE_SELECTION(fileSelector)->ok_button),
+               "clicked", GTK_SIGNAL_FUNC (exp_ldif_file_ok), ( gpointer ) afs );
+       gtk_signal_connect( GTK_OBJECT (GTK_FILE_SELECTION(fileSelector)->cancel_button),
+               "clicked", GTK_SIGNAL_FUNC (exp_ldif_file_cancel), ( gpointer ) afs );
+       afs->fileSelector = fileSelector;
+       afs->cancelled = TRUE;
+}
+
+/**
+ * Callback function to display LDIF file selection dialog.
+ */
+static void exp_ldif_file_select( void ) {
+       gchar *sFile;
+       if( ! _exp_ldif_file_selector_.fileSelector )
+               exp_ldif_file_select_create( & _exp_ldif_file_selector_ );
+
+       sFile = gtk_editable_get_chars( GTK_EDITABLE(expldif_dlg.entryLdif), 0, -1 );
+       gtk_file_selection_set_filename(
+               GTK_FILE_SELECTION( _exp_ldif_file_selector_.fileSelector ),
+               sFile );
+       g_free( sFile );
+       gtk_widget_show( _exp_ldif_file_selector_.fileSelector );
+       gtk_grab_add( _exp_ldif_file_selector_.fileSelector );
+}
+
+/**
+ * Format notebook file specification page.
+ * \param pageNum Page (tab) number.
+ * \param pageLbl Page (tab) label.
+ */
+static void export_ldif_page_file( gint pageNum, gchar *pageLbl ) {
+       GtkWidget *vbox;
+       GtkWidget *table;
+       GtkWidget *label;
+       GtkWidget *labelBook;
+       GtkWidget *entryLdif;
+       GtkWidget *btnFile;
+       gint top;
+
+       vbox = gtk_vbox_new(FALSE, 8);
+       gtk_container_add( GTK_CONTAINER( expldif_dlg.notebook ), vbox );
+       gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
+
+       label = gtk_label_new( pageLbl );
+       gtk_widget_show( label );
+       gtk_notebook_set_tab_label(
+               GTK_NOTEBOOK( expldif_dlg.notebook ),
+               gtk_notebook_get_nth_page(
+                       GTK_NOTEBOOK( expldif_dlg.notebook ), pageNum ),
+               label );
+
+       table = gtk_table_new( 3, 3, FALSE );
+       gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
+       gtk_container_set_border_width( GTK_CONTAINER(table), 8 );
+       gtk_table_set_row_spacings(GTK_TABLE(table), 8);
+       gtk_table_set_col_spacings(GTK_TABLE(table), 8 );
+
+       /* First row */
+       top = 0;
+       label = gtk_label_new( _( "Address Book" ) );
+       gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1),
+               GTK_FILL, 0, 0, 0);
+       gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+
+       labelBook = gtk_label_new( "Address book name goes here" );
+       gtk_table_attach(GTK_TABLE(table), labelBook, 1, 2, top, (top + 1),
+               GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
+       gtk_misc_set_alignment(GTK_MISC(labelBook), 0, 0.5);
+
+       /* Second row */
+       top++;
+       label = gtk_label_new( _( "LDIF Output File" ) );
+       gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1),
+               GTK_FILL, 0, 0, 0);
+       gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+
+       entryLdif = gtk_entry_new();
+       gtk_table_attach(GTK_TABLE(table), entryLdif, 1, 2, top, (top + 1),
+               GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
+
+       btnFile = gtk_button_new_with_label( _(" ... "));
+       gtk_table_attach(GTK_TABLE(table), btnFile, 2, 3, top, (top + 1),
+               GTK_FILL, 0, 3, 0);
+
+       gtk_widget_show_all(vbox);
+
+       /* Button handler */
+       gtk_signal_connect(GTK_OBJECT(btnFile), "clicked",
+                          GTK_SIGNAL_FUNC(exp_ldif_file_select), NULL);
+
+       expldif_dlg.labelBook = labelBook;
+       expldif_dlg.entryLdif = entryLdif;
+}
+
+/**
+ * Format notebook distinguished name page.
+ * \param pageNum Page (tab) number.
+ * \param pageLbl Page (tab) label.
+ */
+static void export_ldif_page_dn( gint pageNum, gchar *pageLbl ) {
+       GtkWidget *vbox;
+       GtkWidget *table;
+       GtkWidget *label;
+       GtkWidget *entrySuffix;
+       GtkWidget *optmenuRDN;
+       GtkWidget *checkUseDN;
+       GtkWidget *checkEMail;
+       GtkWidget *menu;
+       GtkWidget *menuItem;
+       GtkTooltips *toolTip;
+       gint top;
+
+       vbox = gtk_vbox_new(FALSE, 8);
+       gtk_container_add( GTK_CONTAINER( expldif_dlg.notebook ), vbox );
+       gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
+
+       label = gtk_label_new( pageLbl );
+       gtk_widget_show( label );
+       gtk_notebook_set_tab_label(
+               GTK_NOTEBOOK( expldif_dlg.notebook ),
+               gtk_notebook_get_nth_page(
+                       GTK_NOTEBOOK( expldif_dlg.notebook ), pageNum ),
+               label );
+
+       table = gtk_table_new( 5, 2, FALSE );
+       gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
+       gtk_container_set_border_width( GTK_CONTAINER(table), 8 );
+       gtk_table_set_row_spacings(GTK_TABLE(table), 8);
+       gtk_table_set_col_spacings(GTK_TABLE(table), 8 );
+
+       /* First row */
+       top = 0;
+       label = gtk_label_new( _( "Suffix" ) );
+       gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1),
+               GTK_FILL, 0, 0, 0);
+       gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+
+       entrySuffix = gtk_entry_new();
+       gtk_table_attach(GTK_TABLE(table), entrySuffix, 1, 2, top, (top + 1),
+               GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
+
+       toolTip = gtk_tooltips_new();
+       gtk_tooltips_set_tip(
+               GTK_TOOLTIPS(toolTip), entrySuffix, _(
+               "The suffix is used to create a \"Distinguished Name\" " \
+               "(or DN) for an LDAP entry. Examples include:\n" \
+               "  dc=sylpheed,dc=org\n" \
+               "  ou=people,dc=domainname,dc=com\n" \
+               "  o=Organization Name,c=Country\n"
+               ), NULL );
+
+       /* Second row */
+       top++;
+       label = gtk_label_new( _( "Relative DN" ) );
+       gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1),
+               GTK_FILL, 0, 0, 0);
+       gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+
+       menu = gtk_menu_new();
+
+       menuItem = gtk_menu_item_new_with_label( _( "Unique ID" ) );
+       gtk_object_set_user_data( GTK_OBJECT( menuItem ),
+                       GINT_TO_POINTER( EXPORT_LDIF_ID_UID ) );
+       gtk_menu_append( GTK_MENU(menu), menuItem );
+       gtk_widget_show( menuItem );
+       toolTip = gtk_tooltips_new();
+       gtk_tooltips_set_tip(
+               GTK_TOOLTIPS(toolTip), menuItem, _(
+               "The address book Unique ID is used to create a DN that is " \
+               "formatted similar to:\n" \
+               "  uid=102376,ou=people,dc=sylpheed,dc=org"
+               ), NULL );
+
+       menuItem = gtk_menu_item_new_with_label( _( "Display Name" ) );
+       gtk_object_set_user_data( GTK_OBJECT( menuItem ),
+                       GINT_TO_POINTER( EXPORT_LDIF_ID_DNAME ) );
+       gtk_menu_append( GTK_MENU(menu), menuItem );
+       gtk_widget_show( menuItem );
+       toolTip = gtk_tooltips_new();
+       gtk_tooltips_set_tip(
+               GTK_TOOLTIPS(toolTip), menuItem, _(
+               "The address book Display Name is used to create a DN that " \
+               "is formatted similar to:\n" \
+               "  cn=John Doe,ou=people,dc=sylpheed,dc=org"
+               ), NULL );
+
+       menuItem = gtk_menu_item_new_with_label( _( "E-Mail Address" ) );
+       gtk_object_set_user_data( GTK_OBJECT( menuItem ),
+                       GINT_TO_POINTER( EXPORT_LDIF_ID_EMAIL ) );
+       gtk_menu_append( GTK_MENU(menu), menuItem );
+       gtk_widget_show( menuItem );
+       toolTip = gtk_tooltips_new();
+       gtk_tooltips_set_tip(
+               GTK_TOOLTIPS(toolTip), menuItem, _(
+               "The first E-Mail Address belonging to a person is used to " \
+               "create a DN that is formatted similar to:\n" \
+               "  mail=john.doe@domain.com,ou=people,dc=sylpheed,dc=org"
+               ), NULL );
+
+       optmenuRDN = gtk_option_menu_new();
+       gtk_option_menu_set_menu( GTK_OPTION_MENU( optmenuRDN ), menu );
+
+       gtk_table_attach(GTK_TABLE(table), optmenuRDN, 1, 2, top, (top + 1),
+               GTK_FILL, 0, 0, 0);
+
+       toolTip = gtk_tooltips_new();
+       gtk_tooltips_set_tip(
+               GTK_TOOLTIPS(toolTip), optmenuRDN, _(
+               "The LDIF file contains several data records that " \
+               "are usually loaded into an LDAP server. Each data " \
+               "record in the LDIF file is uniquely identified by " \
+               "a \"Distinguished Name\" (or DN). The suffix is " \
+               "appended to the \"Relative Distinguished Name\" "\
+               "(or RDN) to create the DN. Please select one of " \
+               "the available RDN options that will be used to " \
+               "create the DN."
+               ), NULL );
+
+       /* Third row */
+       top++;
+       checkUseDN = gtk_check_button_new_with_label(
+                       _( "Use DN attribute if present in data" ) );
+       gtk_table_attach(GTK_TABLE(table), checkUseDN, 1, 2, top, (top + 1),
+               GTK_FILL, 0, 0, 0);
+
+       toolTip = gtk_tooltips_new();
+       gtk_tooltips_set_tip(
+               GTK_TOOLTIPS(toolTip), checkUseDN, _(
+               "The addressbook may contain entries that were " \
+               "previously imported from an LDIF file. The " \
+               "\"Distinguished Name\" (DN) user attribute, if " \
+               "present in the address book data, may be used in " \
+               "the exported LDIF file. The RDN selected above " \
+               "will be used if the DN user attribute is not found."
+               ), NULL );
+
+       /* Fourth row */
+       top++;
+       checkEMail = gtk_check_button_new_with_label(
+                       _( "Exclude record if no E-Mail Address" ) );
+       gtk_table_attach(GTK_TABLE(table), checkEMail, 1, 2, top, (top + 1),
+               GTK_FILL, 0, 0, 0);
+
+       toolTip = gtk_tooltips_new();
+       gtk_tooltips_set_tip(
+               GTK_TOOLTIPS(toolTip), checkEMail, _(
+               "An addressbook may contain entries without " \
+               "E-Mail Addresses. Check this option to ignore " \
+               "these records."
+               ), NULL );
+
+
+       gtk_widget_show_all(vbox);
+
+       expldif_dlg.entrySuffix = entrySuffix;
+       expldif_dlg.optmenuRDN  = optmenuRDN;
+       expldif_dlg.checkUseDN  = checkUseDN;
+       expldif_dlg.checkEMail  = checkEMail;
+}
+
+/**
+ * Format notebook finish page.
+ * \param pageNum Page (tab) number.
+ * \param pageLbl Page (tab) label.
+ */
+static void export_ldif_page_finish( gint pageNum, gchar *pageLbl ) {
+       GtkWidget *vbox;
+       GtkWidget *table;
+       GtkWidget *label;
+       GtkWidget *labelBook;
+       GtkWidget *labelFile;
+       gint top;
+
+       vbox = gtk_vbox_new(FALSE, 8);
+       gtk_container_add( GTK_CONTAINER( expldif_dlg.notebook ), vbox );
+       gtk_container_set_border_width( GTK_CONTAINER (vbox), BORDER_WIDTH );
+
+       label = gtk_label_new( pageLbl );
+       gtk_widget_show( label );
+       gtk_notebook_set_tab_label(
+               GTK_NOTEBOOK( expldif_dlg.notebook ),
+               gtk_notebook_get_nth_page( GTK_NOTEBOOK( expldif_dlg.notebook ), pageNum ), label );
+
+       table = gtk_table_new( 3, 3, FALSE );
+       gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
+       gtk_container_set_border_width( GTK_CONTAINER(table), 8 );
+       gtk_table_set_row_spacings(GTK_TABLE(table), 8);
+       gtk_table_set_col_spacings(GTK_TABLE(table), 8 );
+
+       /* First row */
+       top = 0;
+       label = gtk_label_new( _( "Address Book :" ) );
+       gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
+       gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
+
+       labelBook = gtk_label_new("Full name of address book goes here");
+       gtk_table_attach(GTK_TABLE(table), labelBook, 1, 2, top, (top + 1), GTK_FILL, 0, 0, 0);
+       gtk_misc_set_alignment(GTK_MISC(labelBook), 0, 0.5);
+
+       /* Second row */
+       top++;
+       label = gtk_label_new( _( "File Name :" ) );
+       gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
+       gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
+
+       labelFile = gtk_label_new("File name goes here");
+       gtk_table_attach(GTK_TABLE(table), labelFile, 1, 2, top, (top + 1), GTK_FILL, 0, 0, 0);
+       gtk_misc_set_alignment(GTK_MISC(labelFile), 0, 0.5);
+
+       gtk_widget_show_all(vbox);
+
+       expldif_dlg.labelOutBook = labelBook;
+       expldif_dlg.labelOutFile = labelFile;
+}
+
+/**
+ * Create main dialog decorations (excluding notebook pages).
+ */
+static void export_ldif_dialog_create( void ) {
+       GtkWidget *window;
+       GtkWidget *vbox;
+       GtkWidget *vnbox;
+       GtkWidget *notebook;
+       GtkWidget *hbbox;
+       GtkWidget *btnPrev;
+       GtkWidget *btnNext;
+       GtkWidget *btnCancel;
+       GtkWidget *hsbox;
+       GtkWidget *statusbar;
+
+       window = gtk_window_new(GTK_WINDOW_DIALOG);
+       gtk_widget_set_usize(window, EXPORTLDIF_WIDTH, EXPORTLDIF_HEIGHT );
+       gtk_container_set_border_width( GTK_CONTAINER(window), 0 );
+       gtk_window_set_title( GTK_WINDOW(window),
+               _("Export Address Book to LDIF File") );
+       gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
+       gtk_window_set_modal(GTK_WINDOW(window), TRUE); 
+       gtk_signal_connect(GTK_OBJECT(window), "delete_event",
+                          GTK_SIGNAL_FUNC(export_ldif_delete_event),
+                          NULL );
+       gtk_signal_connect(GTK_OBJECT(window), "key_press_event",
+                          GTK_SIGNAL_FUNC(export_ldif_key_pressed),
+                          NULL );
+
+       vbox = gtk_vbox_new(FALSE, 4);
+       gtk_widget_show(vbox);
+       gtk_container_add(GTK_CONTAINER(window), vbox);
+
+       vnbox = gtk_vbox_new(FALSE, 4);
+       gtk_container_set_border_width(GTK_CONTAINER(vnbox), 4);
+       gtk_widget_show(vnbox);
+       gtk_box_pack_start(GTK_BOX(vbox), vnbox, TRUE, TRUE, 0);
+
+       /* Notebook */
+       notebook = gtk_notebook_new();
+       gtk_notebook_set_show_tabs( GTK_NOTEBOOK(notebook), FALSE ); /* Hide */
+       /* gtk_notebook_set_show_tabs( GTK_NOTEBOOK(notebook), TRUE ); */
+       gtk_widget_show(notebook);
+       gtk_box_pack_start(GTK_BOX(vnbox), notebook, TRUE, TRUE, 0);
+       gtk_container_set_border_width(GTK_CONTAINER(notebook), 6);
+
+       /* Status line */
+       hsbox = gtk_hbox_new(FALSE, 0);
+       gtk_box_pack_end(GTK_BOX(vbox), hsbox, FALSE, FALSE, BORDER_WIDTH);
+       statusbar = gtk_statusbar_new();
+       gtk_box_pack_start(GTK_BOX(hsbox), statusbar, TRUE, TRUE, BORDER_WIDTH);
+
+       /* Button panel */
+       gtkut_button_set_create(&hbbox, &btnPrev, _( "Prev" ),
+                               &btnNext, _( "Next" ),
+                               &btnCancel, _( "Cancel" ) );
+       gtk_box_pack_end(GTK_BOX(vbox), hbbox, FALSE, FALSE, 0);
+       gtk_container_set_border_width(GTK_CONTAINER(hbbox), 2);
+       gtk_widget_grab_default(btnNext);
+
+       /* Button handlers */
+       gtk_signal_connect(GTK_OBJECT(btnPrev), "clicked",
+                          GTK_SIGNAL_FUNC(export_ldif_prev), NULL);
+       gtk_signal_connect(GTK_OBJECT(btnNext), "clicked",
+                          GTK_SIGNAL_FUNC(export_ldif_next), NULL);
+       gtk_signal_connect(GTK_OBJECT(btnCancel), "clicked",
+                          GTK_SIGNAL_FUNC(export_ldif_cancel), NULL);
+
+       gtk_widget_show_all(vbox);
+
+       expldif_dlg.window     = window;
+       expldif_dlg.notebook   = notebook;
+       expldif_dlg.btnPrev    = btnPrev;
+       expldif_dlg.btnNext    = btnNext;
+       expldif_dlg.btnCancel  = btnCancel;
+       expldif_dlg.statusbar  = statusbar;
+       expldif_dlg.status_cid = gtk_statusbar_get_context_id(
+                       GTK_STATUSBAR(statusbar), "Export LDIF Dialog" );
+}
+
+/**
+ * Create export LDIF dialog.
+ */
+static void export_ldif_create( void ) {
+       export_ldif_dialog_create();
+       export_ldif_page_file( PAGE_FILE_INFO, _( "File Info" ) );
+       export_ldif_page_dn( PAGE_DN, _( "Distguished Name" ) );
+       export_ldif_page_finish( PAGE_FINISH, _( "Finish" ) );
+       gtk_widget_show_all( expldif_dlg.window );
+}
+
+/**
+ * Populate fields from control data.
+ * \param ctl   Export control data.
+ */
+static void export_ldif_fill_fields( ExportLdifCtl *ctl ) {
+       gtk_entry_set_text( GTK_ENTRY(expldif_dlg.entryLdif), "" );
+       if( ctl->path ) {
+               gtk_entry_set_text( GTK_ENTRY(expldif_dlg.entryLdif),
+                       ctl->path );
+       }
+       gtk_entry_set_text( GTK_ENTRY(expldif_dlg.entrySuffix), "" );
+       if( ctl->suffix ) {
+               gtk_entry_set_text( GTK_ENTRY(expldif_dlg.entrySuffix),
+                       ctl->suffix );
+       }
+
+       gtk_option_menu_set_history(
+               GTK_OPTION_MENU( expldif_dlg.optmenuRDN ), ctl->rdnIndex );
+       gtk_toggle_button_set_active(
+               GTK_TOGGLE_BUTTON( expldif_dlg.checkUseDN ), ctl->useDN );
+       gtk_toggle_button_set_active(
+               GTK_TOGGLE_BUTTON( expldif_dlg.checkEMail ), ctl->excludeEMail );
+}
+
+/**
+ * Process export address dialog.
+ * \param cache Address book/data source cache.
+ */
+void addressbook_exp_ldif( AddressCache *cache ) {
+       /* Set references to control data */
+       _addressCache_ = cache;
+
+       _exportCtl_ = exportldif_create();
+       exportldif_load_settings( _exportCtl_ );
+
+       /* Setup GUI */
+       if( ! expldif_dlg.window )
+               export_ldif_create();
+       expldif_dlg.cancelled = FALSE;
+       gtk_widget_show(expldif_dlg.window);
+       manage_window_set_transient(GTK_WINDOW(expldif_dlg.window));
+
+       gtk_label_set_text( GTK_LABEL(expldif_dlg.labelBook), cache->name );
+       gtk_label_set_text( GTK_LABEL(expldif_dlg.labelOutBook), cache->name );
+       export_ldif_fill_fields( _exportCtl_ );
+
+       gtk_widget_grab_default(expldif_dlg.btnNext);
+       gtk_notebook_set_page( GTK_NOTEBOOK(expldif_dlg.notebook), PAGE_FILE_INFO );
+       gtk_widget_set_sensitive( expldif_dlg.btnPrev, FALSE );
+       gtk_widget_set_sensitive( expldif_dlg.btnNext, TRUE );
+
+       export_ldif_message();
+       gtk_widget_grab_focus(expldif_dlg.entryLdif);
+
+       gtk_main();
+       gtk_widget_hide(expldif_dlg.window);
+       exportldif_free( _exportCtl_ );
+       _exportCtl_ = NULL;
+
+       _addressCache_ = NULL;
+}
+
+/*
+ * ============================================================================
+ * End of Source.
+ * ============================================================================
+ */
+
diff --git a/src/expldifdlg.h b/src/expldifdlg.h
new file mode 100644 (file)
index 0000000..5fb28d6
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2003 Match Grun
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+/*
+ * Export addressbook to HTML file.
+ */
+
+#ifndef __EXPORT_HTML_H__
+#define __EXPORT_HTML_H__
+
+/* Function prototypes */
+void addressbook_exp_html( AddressCache *cache );
+
+#endif /* __EXPORT_HTML_H__ */
+
+/*
+* End of Source.
+*/
+
diff --git a/src/exportldif.c b/src/exportldif.c
new file mode 100644 (file)
index 0000000..4ade0fe
--- /dev/null
@@ -0,0 +1,698 @@
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2003 Match Grun
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+/*
+ * Export address book to LDIF file.
+ */
+
+#include <sys/stat.h>
+#include <dirent.h>
+#include <errno.h>
+#include <time.h>
+#include <string.h>
+#include <glib.h>
+
+#include "intl.h"
+#include "mgutils.h"
+#include "utils.h"
+#include "exportldif.h"
+#include "xmlprops.h"
+#include "ldif.h"
+
+#define DFL_DIR_SYLPHEED_OUT  "sylpheed-out"
+#define DFL_FILE_SYLPHEED_OUT "addressbook.ldif"
+
+#define FMT_BUFSIZE           2048
+#define XML_BUFSIZE           2048
+
+/* Settings - properties */
+#define EXML_PROPFILE_NAME    "exportldif.xml"
+#define EXMLPROP_DIRECTORY    "directory"
+#define EXMLPROP_FILE         "file"
+#define EXMLPROP_SUFFIX       "suffix"
+#define EXMLPROP_RDN_INDEX    "rdn"
+#define EXMLPROP_USE_DN       "use-dn"
+#define EXMLPROP_EXCL_EMAIL   "exclude-mail"
+
+static gchar *_attrName_UID_   = "uid";
+static gchar *_attrName_DName_ = "cn";
+static gchar *_attrName_EMail_ = "mail";
+
+/**
+ * Create initialized LDIF export control object.
+ * \return Initialized export control data.
+ */
+ExportLdifCtl *exportldif_create( void ) {
+       ExportLdifCtl *ctl = g_new0( ExportLdifCtl, 1 );
+
+       ctl->path = NULL;
+       ctl->dirOutput = NULL;
+       ctl->fileLdif = NULL;
+       ctl->suffix = NULL;
+       ctl->rdnIndex = EXPORT_LDIF_ID_UID;
+       ctl->useDN = FALSE;
+       ctl->excludeEMail = TRUE;
+       ctl->retVal = MGU_SUCCESS;
+       ctl->rcCreate = 0;
+       ctl->settingsFile = g_strconcat(
+               get_rc_dir(), G_DIR_SEPARATOR_S, EXML_PROPFILE_NAME, NULL );
+
+       return ctl;
+}
+
+/**
+ * Free up object by releasing internal memory.
+ * \return ctl Export control data.
+ */
+void exportldif_free( ExportLdifCtl *ctl ) {
+       GList *node;
+
+       g_return_if_fail( ctl != NULL );
+
+       g_free( ctl->path );
+       g_free( ctl->fileLdif );
+       g_free( ctl->dirOutput );
+       g_free( ctl->suffix );
+       g_free( ctl->settingsFile );
+
+       /* Clear pointers */
+       ctl->path = NULL;
+       ctl->dirOutput = NULL;
+       ctl->fileLdif = NULL;
+       ctl->suffix = NULL;
+       ctl->rdnIndex = EXPORT_LDIF_ID_UID;
+       ctl->useDN = FALSE;
+       ctl->excludeEMail = FALSE;
+       ctl->retVal = MGU_SUCCESS;
+       ctl->rcCreate = 0;
+
+       /* Now release object */
+       g_free( ctl );
+}
+
+/**
+ * Print control object.
+ * \param ctl    Export control data.
+ * \param stream Output stream.
+ */
+void exportldif_print( ExportLdifCtl *ctl, FILE *stream ) {
+       fprintf( stream, "ExportLdifCtl:\n" );
+       fprintf( stream, "     path: %s\n", ctl->path );
+       fprintf( stream, "directory: %s\n", ctl->dirOutput );
+       fprintf( stream, "     file: %s\n", ctl->fileLdif );
+       fprintf( stream, "   suffix: %s\n", ctl->suffix );
+       fprintf( stream, "      rdn: %d\n", ctl->rdnIndex );
+       fprintf( stream, "   use DN: %s\n", ctl->useDN ? "y" : "n" );
+       fprintf( stream, " ex EMail: %s\n", ctl->excludeEMail ? "y" : "n" );
+       fprintf( stream, " settings: %s\n", ctl->settingsFile );
+}
+
+/**
+ * Specify directory where LDIF files are created.
+ * \param ctl   Export control data.
+ * \param value Full directory path.
+ */
+void exportldif_set_output_dir( ExportLdifCtl *ctl, const gchar *value ) {
+       g_return_if_fail( ctl != NULL );
+       ctl->dirOutput = mgu_replace_string( ctl->dirOutput, value );
+       g_strstrip( ctl->dirOutput );
+}
+
+/**
+ * Specify full file specification of LDIF file.
+ * \param ctl   Export control data.
+ * \param value Full file specification.
+ */
+void exportldif_set_path( ExportLdifCtl *ctl, const gchar *value ) {
+       g_return_if_fail( ctl != NULL );
+       ctl->path = mgu_replace_string( ctl->path, value );
+       g_strstrip( ctl->path );
+}
+
+/**
+ * Specify file name of LDIF file.
+ * \param ctl   Export control data.
+ * \param value File name.
+ */
+void exportldif_set_file_ldif( ExportLdifCtl *ctl, const gchar *value ) {
+       g_return_if_fail( ctl != NULL );
+       ctl->fileLdif = mgu_replace_string( ctl->fileLdif, value );
+       g_strstrip( ctl->fileLdif );
+}
+
+/**
+ * Specify suffix to be used for creating DN entries.
+ * \param ctl   Export control data.
+ * \param value Suffix.
+ */
+void exportldif_set_suffix( ExportLdifCtl *ctl, const char *value ) {
+       g_return_if_fail( ctl != NULL );
+       ctl->suffix = mgu_replace_string( ctl->suffix, value );
+       g_strstrip( ctl->suffix );
+}
+
+/**
+ * Specify index of variable to be used for creating RDN entries.
+ * \param ctl   Export control data.
+ * \param value Index to variable, as follows:
+ * <ul>
+ * <li><code>EXPORT_LDIF_ID_UID</code> - Use Sylpheed UID.</li>
+ * <li><code>EXPORT_LDIF_ID_DNAME</code> - Use Sylpheed display name.</li>
+ * <li><code>EXPORT_LDIF_ID_EMAIL</code> - Use first E-Mail address.</li>
+ * </ul>
+ */
+void exportldif_set_rdn( ExportLdifCtl *ctl, const gint value ) {
+       g_return_if_fail( ctl != NULL );
+       ctl->rdnIndex = value;
+}
+
+/**
+ * Specify that <code>DN</code> attribute, if present, should be used as the
+ * DN for the entry.
+ * \param ctl   Export control data.
+ * \param value <i>TRUE</i> if DN should be used.
+ */
+void exportldif_set_use_dn( ExportLdifCtl *ctl, const gboolean value ) {
+       g_return_if_fail( ctl != NULL );
+       ctl->useDN = value;
+}
+
+/**
+ * Specify that records without E-Mail addresses should be excluded.
+ * \param ctl   Export control data.
+ * \param value <i>TRUE</i> if records without E-Mail should be excluded.
+ */
+void exportldif_set_exclude_email( ExportLdifCtl *ctl, const gboolean value ) {
+       g_return_if_fail( ctl != NULL );
+       ctl->excludeEMail = value;
+}
+
+/**
+ * Format LDAP value name with no embedded commas.
+ * \param  value Data value to format.
+ * \return Formatted string, should be freed after use.
+ */
+static gchar *exportldif_fmt_value( gchar *value ) {
+       gchar *dupval;
+       gchar *src;
+       gchar *dest;
+       gchar ch;
+
+       /* Duplicate incoming value */
+       dest = dupval = g_strdup( value );
+
+       /* Copy characters, ignoring commas */
+       src = value;
+       while( *src ) {
+               ch = *src;
+               if( ch != ',' ) {
+                       *dest = ch;
+                       dest++;
+               }
+               src++;
+       }
+       *dest = '\0';
+       return dupval;
+}
+
+/**
+ * Build DN for entry.
+ * \param  ctl    Export control data.
+ * \param  person Person to format.
+ * \return Formatted DN entry.
+ */
+static gchar *exportldif_fmt_dn(
+               ExportLdifCtl *ctl, const ItemPerson *person )
+{
+       gchar buf[ FMT_BUFSIZE ];
+       gchar *retVal = NULL;
+       gchar *attr = NULL;
+       gchar *value = NULL;
+       gchar *dupval = NULL;
+
+       /* Process RDN */
+       *buf = '\0';
+       if( ctl->rdnIndex == EXPORT_LDIF_ID_UID ) {
+               attr = _attrName_UID_;
+               value = ADDRITEM_ID( person );
+       }
+       else if( ctl->rdnIndex == EXPORT_LDIF_ID_DNAME ) {
+               attr = _attrName_DName_;
+               value = ADDRITEM_NAME( person );
+               dupval = exportldif_fmt_value( value );
+       }
+       else if( ctl->rdnIndex == EXPORT_LDIF_ID_EMAIL ) {
+               GList *node;
+
+               node = person->listEMail;
+               if( node ) {
+                       ItemEMail *email = node->data;
+
+                       attr = _attrName_EMail_;
+                       value = email->address;
+                       dupval = exportldif_fmt_value( value );
+               }
+       }
+
+       /* Format DN */
+       if( attr ) {
+               if( value ) {
+                       if( strlen( value ) > 0 ) {
+                               strcat( buf, attr );
+                               strcat( buf, "=" );
+                               if( dupval ) {
+                                       /* Format and free duplicated value */
+                                       strcat( buf, dupval );
+                                       g_free( dupval );
+                               }
+                               else {
+                                       /* Use original value */
+                                       strcat( buf, value );
+                               }
+
+                               /* Append suffix */
+                               if( ctl->suffix ) {
+                                       if( strlen( ctl->suffix ) > 0 ) {
+                                               strcat( buf, "," );
+                                               strcat( buf, ctl->suffix );
+                                       }
+                               }
+
+                               retVal = g_strdup( buf );
+                       }
+               }
+       }
+       return retVal;
+}
+
+/**
+ * Find DN by searching attribute list.
+ * \param  ctl    Export control data.
+ * \param  person Person to format.
+ * \return Formatted DN entry, should be freed after use.
+ */
+static gchar *exportldif_find_dn(
+                       ExportLdifCtl *ctl, const ItemPerson *person )
+{
+       gchar *retVal = NULL;
+       const GList *node;
+
+       node = person->listAttrib;
+       while( node ) {
+               UserAttribute *attrib = node->data;
+
+               node = g_list_next( node );
+               if( g_strcasecmp( attrib->name, LDIF_TAG_DN ) == 0 ) {
+                       retVal = g_strdup( attrib->value );
+                       break;
+               }
+       }
+       return retVal;
+}
+
+/**
+ * Format E-Mail entries for person.
+ * \param  person Person to format.
+ * \param  stream Output stream.
+ * \return <i>TRUE</i> if entry formatted.
+ */
+static gboolean exportldif_fmt_email( const ItemPerson *person, FILE *stream ) {
+       gboolean retVal = FALSE;
+       const GList *node;
+
+       node = person->listEMail;
+       while( node ) {
+               ItemEMail *email = node->data;
+
+               node = g_list_next( node );
+               ldif_write_value( stream, LDIF_TAG_EMAIL, email->address );
+               retVal = TRUE;
+       }
+       return retVal;
+}
+
+/**
+ * Test for E-Mail entries for person.
+ * \param  person Person to test.
+ * \return <i>TRUE</i> if person has E-Mail address.
+ */
+static gboolean exportldif_test_email( const ItemPerson *person )
+{
+       gboolean retVal = FALSE;
+       const GList *node;
+
+       node = person->listEMail;
+       while( node ) {
+               ItemEMail *email = node->data;
+
+               node = g_list_next( node );
+               if( email->address ) {
+                       if( strlen( email->address ) > 0 ) {
+                               retVal = TRUE;
+                               break;
+                       }
+               }
+               retVal = TRUE;
+       }
+       return retVal;
+}
+
+/**
+ * Format persons in an address book folder.
+ * \param  ctl    Export control data.
+ * \param  stream Output stream.
+ * \param  folder Folder to format.
+ * \return <i>TRUE</i> if no persons were formatted.
+ */
+static gboolean exportldif_fmt_person(
+               ExportLdifCtl *ctl, FILE *stream, const ItemFolder *folder )
+{
+       gboolean retVal = TRUE;
+       const GList *node;
+
+       if( folder->listPerson == NULL ) return retVal;
+
+       node = folder->listPerson;
+       while( node ) {
+               AddrItemObject *aio = node->data;
+               node = g_list_next( node );
+
+               if( aio && aio->type == ITEMTYPE_PERSON ) {
+                       ItemPerson *person = ( ItemPerson * ) aio;
+                       gboolean classPerson = FALSE;
+                       gboolean classInetP = FALSE;
+                       gchar *dn = NULL;
+
+                       /* Check for E-Mail */
+                       if( exportldif_test_email( person ) ) {
+                               classInetP = TRUE;
+                       }
+                       else {
+                               /* Bail if no E-Mail address */
+                               if( ctl->excludeEMail ) continue;
+                       }
+
+                       /* Format DN */
+                       if( ctl->useDN ) {
+                               dn = exportldif_find_dn( ctl, person );
+                       }
+                       if( dn == NULL ) {
+                               dn = exportldif_fmt_dn( ctl, person );
+                       }
+                       if( dn == NULL ) continue;
+                       ldif_write_value( stream, LDIF_TAG_DN, dn );
+                       g_free( dn );
+
+                       /*
+                        * Test for schema requirements. This is a simple
+                        * test and does not trap all LDAP schema errors.
+                        * These can be detected when the LDIF file is
+                        * loaded into an LDAP server.
+                        */
+                       if( person->lastName ) {
+                               if( strlen( person->lastName ) > 0 ) {
+                                       classPerson = TRUE;
+                                       classInetP = TRUE;
+                               }
+                       }
+
+                       if( classPerson ) {
+                               ldif_write_value( stream,
+                                       LDIF_TAG_OBJECTCLASS, LDIF_CLASS_PERSON );
+                       }
+                       if( classInetP ) {
+                               ldif_write_value( stream,
+                                       LDIF_TAG_OBJECTCLASS, LDIF_CLASS_INET_PERSON );
+                       }
+
+                       /* Format person attributes */
+                       ldif_write_value(
+                               stream, LDIF_TAG_COMMONNAME, ADDRITEM_NAME( person ) );
+                       ldif_write_value(
+                               stream, LDIF_TAG_LASTNAME, person->lastName );
+                       ldif_write_value(
+                               stream, LDIF_TAG_FIRSTNAME, person->firstName );
+                       ldif_write_value(
+                               stream, LDIF_TAG_NICKNAME, person->nickName );
+
+                       /* Format E-Mail */
+                       exportldif_fmt_email( person, stream );
+
+                       /* End record */
+                       ldif_write_eor( stream );
+
+                       retVal = FALSE;
+               }
+       }
+
+       return retVal;
+}
+
+/**
+ * Format an address book folder.
+ * \param  ctl    Export control data.
+ * \param  stream Output stream.
+ * \param  folder Folder to format.
+ * \return <i>TRUE</i> if no persons were formatted.
+ */
+static void exportldif_fmt_folder(
+               ExportLdifCtl *ctl, FILE *stream, const ItemFolder *folder )
+{
+       const GList *node;
+
+       /* Export entries in this folder */
+       exportldif_fmt_person( ctl, stream, folder );
+
+       /* Export entries in sub-folders */
+       node = folder->listFolder;
+       while( node ) {
+               AddrItemObject *aio = node->data;
+
+               node = g_list_next( node );
+               if( aio && aio->type == ITEMTYPE_FOLDER ) {
+                       ItemFolder *subFolder = ( ItemFolder * ) aio;
+                       exportldif_fmt_folder( ctl, stream, subFolder );
+               }
+       }
+}
+
+/**
+ * Export address book to LDIF file.
+ * \param  ctl   Export control data.
+ * \param  cache Address book/data source cache.
+ * \return Status.
+ */
+void exportldif_process( ExportLdifCtl *ctl, AddressCache *cache )
+{
+       ItemFolder *rootFolder;
+       FILE *ldifFile;
+
+       ldifFile = fopen( ctl->path, "wb" );
+       if( ! ldifFile ) {
+               /* Cannot open file */
+               ctl->retVal = MGU_OPEN_FILE;
+               return;
+       }
+
+       rootFolder = cache->rootFolder;
+       exportldif_fmt_folder( ctl, ldifFile, rootFolder );
+       fclose( ldifFile );
+       ctl->retVal = MGU_SUCCESS;
+}
+
+/**
+ * Build full export file specification.
+ * \param ctl  Export control data.
+ */
+static void exportldif_build_filespec( ExportLdifCtl *ctl ) {
+       gchar *fileSpec;
+
+       fileSpec = g_strconcat(
+               ctl->dirOutput, G_DIR_SEPARATOR_S, ctl->fileLdif, NULL );
+       ctl->path = mgu_replace_string( ctl->path, fileSpec );
+       g_free( fileSpec );
+}
+
+/**
+ * Parse directory and filename from full export file specification.
+ * \param ctl      Export control data.
+ * \param fileSpec File spec.
+ */
+void exportldif_parse_filespec( ExportLdifCtl *ctl, gchar *fileSpec ) {
+       gchar *t;
+
+       ctl->fileLdif =
+               mgu_replace_string( ctl->fileLdif, g_basename( fileSpec ) );
+       t = g_dirname( fileSpec );
+       ctl->dirOutput = mgu_replace_string( ctl->dirOutput, t );
+       g_free( t );
+       ctl->path = mgu_replace_string( ctl->path, fileSpec );
+}
+
+/**
+ * Test whether output directory exists.
+ * \param  ctl Export control data.
+ * \return TRUE if exists.
+ */
+gboolean exportldif_test_dir( ExportLdifCtl *ctl ) {
+       gboolean retVal;
+       DIR *dp;
+
+       retVal = FALSE;
+       if((dp = opendir( ctl->dirOutput )) != NULL) {
+               retVal = TRUE;
+               closedir( dp );
+       }
+       return retVal;
+}
+
+/**
+ * Create output directory.
+ * \param  ctl Export control data.
+ * \return TRUE if directory created.
+ */
+gboolean exportldif_create_dir( ExportLdifCtl *ctl ) {
+       gboolean retVal = FALSE;
+
+       ctl->rcCreate = 0;
+       if( mkdir( ctl->dirOutput, S_IRWXU ) == 0 ) {
+               retVal = TRUE;
+       }
+       else {
+               ctl->rcCreate = errno;
+       }
+       return retVal;
+}
+
+/**
+ * Retrieve create directory error message.
+ * \param  ctl Export control data.
+ * \return Message.
+ */
+gchar *exportldif_get_create_msg( ExportLdifCtl *ctl ) {
+       gchar *msg;
+
+       if( ctl->rcCreate == EEXIST ) {
+               msg = _( "Name already exists but is not a directory." );
+       }
+       else if( ctl->rcCreate == EACCES ) {
+               msg = _( "No permissions to create directory." );
+       }
+       else if( ctl->rcCreate == ENAMETOOLONG ) {
+               msg = _( "Name is too long." );
+       }
+       else {
+               msg = _( "Not specified." );
+       }
+       return msg;
+}
+
+/**
+ * Set default values.
+ * \param  ctl Export control data.
+ */
+static void exportldif_default_values( ExportLdifCtl *ctl ) {
+       gchar *str;
+
+       str = g_strconcat(
+               g_get_home_dir(), G_DIR_SEPARATOR_S,
+               DFL_DIR_SYLPHEED_OUT, NULL );
+
+       ctl->dirOutput = mgu_replace_string( ctl->dirOutput, str );
+       g_free( str );
+
+       ctl->fileLdif =
+               mgu_replace_string( ctl->fileLdif, DFL_FILE_SYLPHEED_OUT );
+       ctl->suffix = mgu_replace_string( ctl->suffix, "" );
+
+       ctl->rdnIndex = EXPORT_LDIF_ID_UID;
+       ctl->useDN = FALSE;
+       ctl->retVal = MGU_SUCCESS;
+}
+
+/**
+ * Load settings from XML properties file.
+ * \param  ctl Export control data.
+ */
+void exportldif_load_settings( ExportLdifCtl *ctl ) {
+       XmlProperty *props;
+       gint rc;
+       gchar buf[ XML_BUFSIZE ];
+
+       props = xmlprops_create();
+       xmlprops_set_path( props, ctl->settingsFile );
+       rc = xmlprops_load_file( props );
+       if( rc == 0 ) {
+               /* Read settings */
+               *buf = '\0';
+               xmlprops_get_property_s( props, EXMLPROP_DIRECTORY, buf );
+               ctl->dirOutput = mgu_replace_string( ctl->dirOutput, buf );
+
+               *buf = '\0';
+               xmlprops_get_property_s( props, EXMLPROP_FILE, buf );
+               ctl->fileLdif = mgu_replace_string( ctl->fileLdif, buf );
+
+               *buf = '\0';
+               xmlprops_get_property_s( props, EXMLPROP_SUFFIX, buf );
+               ctl->suffix = mgu_replace_string( ctl->suffix, buf );
+
+               ctl->rdnIndex =
+                       xmlprops_get_property_i( props, EXMLPROP_RDN_INDEX );
+               ctl->useDN =
+                       xmlprops_get_property_b( props, EXMLPROP_USE_DN );
+               ctl->excludeEMail =
+                       xmlprops_get_property_b( props, EXMLPROP_EXCL_EMAIL );
+       }
+       else {
+               /* Set default values */
+               exportldif_default_values( ctl );
+       }
+       exportldif_build_filespec( ctl );
+       /* exportldif_print( ctl, stdout ); */
+
+       xmlprops_free( props );
+}
+
+/**
+ * Save settings to XML properties file.
+ * \param  ctl Export control data.
+ */
+void exportldif_save_settings( ExportLdifCtl *ctl ) {
+       XmlProperty *props;
+
+       props = xmlprops_create();
+       xmlprops_set_path( props, ctl->settingsFile );
+
+       xmlprops_set_property( props, EXMLPROP_DIRECTORY, ctl->dirOutput );
+       xmlprops_set_property( props, EXMLPROP_FILE, ctl->fileLdif );
+       xmlprops_set_property( props, EXMLPROP_SUFFIX, ctl->suffix );
+       xmlprops_set_property_i( props, EXMLPROP_RDN_INDEX, ctl->rdnIndex );
+       xmlprops_set_property_b( props, EXMLPROP_USE_DN, ctl->useDN );
+       xmlprops_set_property_b( props, EXMLPROP_EXCL_EMAIL, ctl->excludeEMail );
+       xmlprops_save_file( props );
+       xmlprops_free( props );
+}
+
+/*
+ * ============================================================================
+ * End of Source.
+ * ============================================================================
+ */
+
+
diff --git a/src/exportldif.h b/src/exportldif.h
new file mode 100644 (file)
index 0000000..c0a056b
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2003 Match Grun
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+/*
+ * Definitions for export to LDIF file.
+ */
+
+#ifndef __EXPORT_LDIF_H__
+#define __EXPORT_LDIF_H__
+
+#include <glib.h>
+
+#include "addrcache.h"
+
+/* RDN ID's */
+#define EXPORT_LDIF_ID_UID      0
+#define EXPORT_LDIF_ID_DNAME    1
+#define EXPORT_LDIF_ID_EMAIL    2
+
+#define EXPORT_LDIF_FIRST_LAST  0
+#define EXPORT_LDIF_LAST_FIRST  1
+
+/* Export LDIF control data */
+typedef struct _ExportLdifCtl ExportLdifCtl;
+struct _ExportLdifCtl {
+       gchar    *path;
+       gchar    *dirOutput;
+       gchar    *fileLdif;
+       gchar    *settingsFile;
+       gchar    *suffix;
+       gint     rdnIndex;
+       gboolean useDN;
+       gboolean excludeEMail;
+       gint     retVal;
+       gint     rcCreate;
+};
+
+/* Function prototypes */
+ExportLdifCtl *exportldif_create       ( void );
+void exportldif_free                   ( ExportLdifCtl *ctl );
+void exportldif_set_path               ( ExportLdifCtl *ctl,
+                                         const gchar *value );
+void exportldif_set_file_html          ( ExportLdifCtl *ctl,
+                                         const gchar *value );
+void exportldif_set_suffix             ( ExportLdifCtl *ctl,
+                                         const gchar *value );
+void exportldif_set_rdn                        ( ExportLdifCtl *ctl,
+                                         const gint value );
+void exportldif_set_use_dn             ( ExportLdifCtl *ctl,
+                                         const gboolean value );
+void exportldif_set_exclude_email      ( ExportLdifCtl *ctl,
+                                         const gboolean value );
+void exportldif_process                        ( ExportLdifCtl *ctl,
+                                         AddressCache *cache );
+gboolean exportldif_test_dir           ( ExportLdifCtl *ctl );
+gboolean exportldif_create_dir         ( ExportLdifCtl *ctl );
+gchar *exportldif_get_create_msg       ( ExportLdifCtl *ctl );
+
+void exportldif_parse_filespec         ( ExportLdifCtl *ctl,
+                                         gchar *fileSpec );
+void exportldif_load_settings          ( ExportLdifCtl *ctl );
+void exportldif_save_settings          ( ExportLdifCtl *ctl );
+
+#endif /* __EXPORT_LDIF_H__ */
+
index a9eacc4..03c491e 100644 (file)
 #define PAGE_ATTRIBUTES            1
 #define PAGE_FINISH                2
 
-#define IMPORTLDIF_WIDTH           380
+#define IMPORTLDIF_WIDTH           390
 #define IMPORTLDIF_HEIGHT          300
 
-#define FIELDS_N_COLS              3
+#define FIELDS_N_COLS              4
+#define FIELDS_COL_WIDTH_RESERVED  10
 #define FIELDS_COL_WIDTH_SELECT    10
 #define FIELDS_COL_WIDTH_FIELD     140
 #define FIELDS_COL_WIDTH_ATTRIB    140
 
 typedef enum {
-       FIELD_COL_SELECT  = 0,
-       FIELD_COL_FIELD   = 1,
-       FIELD_COL_ATTRIB  = 2
+       FIELD_COL_RESERVED = 0,
+       FIELD_COL_SELECT   = 1,
+       FIELD_COL_FIELD    = 2,
+       FIELD_COL_ATTRIB   = 3
 } ImpLdif_FieldColPos;
 
 /**
@@ -74,12 +76,13 @@ typedef enum {
 static struct _ImpLdif_Dlg {
        GtkWidget *window;
        GtkWidget *notebook;
-       GtkWidget *file_entry;
-       GtkWidget *name_entry;
+       GtkWidget *entryFile;
+       GtkWidget *entryName;
        GtkWidget *clist_field;
-       GtkWidget *name_ldif;
-       GtkWidget *name_attrib;
-       GtkWidget *check_select;
+       GtkWidget *entryField;
+       GtkWidget *entryAttrib;
+       GtkWidget *checkSelect;
+       GtkWidget *btnModify;
        GtkWidget *labelBook;
        GtkWidget *labelFile;
        GtkWidget *labelRecords;
@@ -207,9 +210,10 @@ static void imp_ldif_update_row( GtkCList *clist ) {
        row = impldif_dlg.rowIndSelect;
 
        rec = gtk_clist_get_row_data( clist, row );
-       text[ FIELD_COL_SELECT ] = "";
-       text[ FIELD_COL_FIELD  ] = rec->tagName;
-       text[ FIELD_COL_ATTRIB ] = rec->userName;
+       text[ FIELD_COL_RESERVED ] = "";
+       text[ FIELD_COL_SELECT   ] = "";
+       text[ FIELD_COL_FIELD    ] = rec->tagName;
+       text[ FIELD_COL_ATTRIB   ] = rec->userName;
 
        gtk_clist_freeze( clist );
        gtk_clist_remove( clist, row );
@@ -219,8 +223,14 @@ static void imp_ldif_update_row( GtkCList *clist ) {
        else {
                gtk_clist_insert( clist, row, text );
        }
-       if( rec->selected )
-               gtk_clist_set_pixmap( clist, row, FIELD_COL_SELECT, markxpm, markxpmmask );
+       if( rec->selected ) {
+               gtk_clist_set_pixmap(
+                       clist, row, FIELD_COL_SELECT, markxpm, markxpmmask );
+       }
+       if( rec->reserved ) {
+               gtk_clist_set_pixmap(
+                       clist, row, FIELD_COL_RESERVED, markxpm, markxpmmask );
+       }
 
        gtk_clist_set_row_data( clist, row, rec );
        gtk_clist_thaw( clist );
@@ -245,18 +255,21 @@ static void imp_ldif_load_fields( LdifFile *ldf ) {
                Ldif_FieldRec *rec = node->data;
                gint row;
 
-               if( ! rec->reserved ) {
-                       text[ FIELD_COL_SELECT ] = "";
-                       text[ FIELD_COL_FIELD  ] = rec->tagName;
-                       text[ FIELD_COL_ATTRIB ] = rec->userName;
-                       row = gtk_clist_append( clist, text );
-                       gtk_clist_set_row_data( clist, row, rec );
-                       if( rec->selected )
-                               gtk_clist_set_pixmap(
-                                       clist, row, FIELD_COL_SELECT, markxpm,
-                                       markxpmmask );
-                       impldif_dlg.rowCount++;
+               text[ FIELD_COL_RESERVED ] = "";
+               text[ FIELD_COL_SELECT   ] = "";
+               text[ FIELD_COL_FIELD    ] = rec->tagName;
+               text[ FIELD_COL_ATTRIB   ] = rec->userName;
+               row = gtk_clist_append( clist, text );
+               gtk_clist_set_row_data( clist, row, rec );
+               if( rec->selected ) {
+                       gtk_clist_set_pixmap( clist, row,
+                               FIELD_COL_SELECT, markxpm, markxpmmask );
+               }
+               if( rec->reserved ) {
+                       gtk_clist_set_pixmap( clist, row,
+                               FIELD_COL_RESERVED, markxpm, markxpmmask );
                }
+               impldif_dlg.rowCount++;
                node = g_list_next( node );
        }
        g_list_free( list );
@@ -264,6 +277,14 @@ static void imp_ldif_load_fields( LdifFile *ldf ) {
        ldif_set_accessed( ldf, FALSE );
 }
 
+/**
+ * Callback function when list iterm selected.
+ * \param clist List widget.
+ * \param row   Row.
+ * \param col   Column.
+ * \param event Event object.
+ * \param data  User data.
+ */
 static void imp_ldif_field_list_selected(
                GtkCList *clist, gint row, gint column, GdkEvent *event,
                gpointer data )
@@ -271,17 +292,27 @@ static void imp_ldif_field_list_selected(
        Ldif_FieldRec *rec = gtk_clist_get_row_data( clist, row );
 
        impldif_dlg.rowIndSelect = row;
-       gtk_entry_set_text( GTK_ENTRY(impldif_dlg.name_attrib), "" );
+       gtk_entry_set_text( GTK_ENTRY(impldif_dlg.entryAttrib), "" );
        if( rec ) {
-               gtk_label_set_text( GTK_LABEL(impldif_dlg.name_ldif), rec->tagName );
+               /* Update widget contents */
+               gtk_label_set_text(
+                       GTK_LABEL(impldif_dlg.entryField), rec->tagName );
                if( rec->userName )
                        gtk_entry_set_text(
-                               GTK_ENTRY(impldif_dlg.name_attrib), rec->userName );
+                               GTK_ENTRY(impldif_dlg.entryAttrib), rec->userName );
                gtk_toggle_button_set_active(
-                       GTK_TOGGLE_BUTTON( impldif_dlg.check_select),
+                       GTK_TOGGLE_BUTTON( impldif_dlg.checkSelect),
                        rec->selected );
+
+               /* Disable widgets for reserved fields */
+               gtk_widget_set_sensitive(
+                       impldif_dlg.entryAttrib, ! rec->reserved );
+               gtk_widget_set_sensitive(
+                       impldif_dlg.checkSelect, ! rec->reserved );
+               gtk_widget_set_sensitive(
+                       impldif_dlg.btnModify,   ! rec->reserved );
        }
-       gtk_widget_grab_focus(impldif_dlg.name_attrib);
+       gtk_widget_grab_focus(impldif_dlg.entryAttrib);
 }
 
 /**
@@ -299,14 +330,14 @@ static void imp_ldif_field_list_toggle(
        if( ! event ) return;
        if( impldif_dlg.rowIndSelect < 0 ) return;
        if( event->button == 1 ) {
-               /* If single click in first column */
+               /* If single click in select column */
                if( event->type == GDK_BUTTON_PRESS ) {
                        gint x = event->x;
                        gint y = event->y;
                        gint row, col;
 
                        gtk_clist_get_selection_info( clist, x, y, &row, &col );
-                       if( col > 0 ) return;
+                       if( col != FIELD_COL_SELECT ) return;
                        if( row > impldif_dlg.rowCount ) return;
 
                        /* Set row */
@@ -324,7 +355,7 @@ static void imp_ldif_field_list_toggle(
                rec = gtk_clist_get_row_data(
                        clist, impldif_dlg.rowIndSelect );
                if( rec ) {
-                       rec->selected = ! rec->selected;
+                       ldif_field_toggle( rec );
                        imp_ldif_update_row( clist );
                }
        }
@@ -344,23 +375,22 @@ static void imp_ldif_modify_pressed( GtkWidget *widget, gpointer data ) {
        row = impldif_dlg.rowIndSelect;
        rec = gtk_clist_get_row_data( clist, impldif_dlg.rowIndSelect );
 
-       g_free( rec->userName );
-       rec->userName = gtk_editable_get_chars(
-                               GTK_EDITABLE(impldif_dlg.name_attrib), 0, -1 );
-       rec->selected = gtk_toggle_button_get_active(
-                               GTK_TOGGLE_BUTTON( impldif_dlg.check_select) );
+       ldif_field_set_name( rec, gtk_editable_get_chars(
+               GTK_EDITABLE(impldif_dlg.entryAttrib), 0, -1 ) );
+       ldif_field_set_selected( rec, gtk_toggle_button_get_active(
+               GTK_TOGGLE_BUTTON( impldif_dlg.checkSelect) ) );
        imp_ldif_update_row( clist );
        gtk_clist_select_row( clist, row, 0 );
-       gtk_label_set_text( GTK_LABEL(impldif_dlg.name_ldif), "" );
-       gtk_entry_set_text( GTK_ENTRY(impldif_dlg.name_attrib), "" );
+       gtk_label_set_text( GTK_LABEL(impldif_dlg.entryField), "" );
+       gtk_entry_set_text( GTK_ENTRY(impldif_dlg.entryAttrib), "" );
        gtk_toggle_button_set_active(
-               GTK_TOGGLE_BUTTON( impldif_dlg.check_select), FALSE );
+               GTK_TOGGLE_BUTTON( impldif_dlg.checkSelect), FALSE );
 }
 
-/*
-* Move off fields page.
-* return: TRUE if OK to move off page.
-*/
+/**
+ * Test whether we can move off fields page.
+ * \return <i>TRUE</i> if OK to move off page.
+ */
 static gboolean imp_ldif_field_move() {
        gboolean retVal = FALSE;
        gchar *newFile;
@@ -391,7 +421,7 @@ static gboolean imp_ldif_field_move() {
 }
 
 /**
- * Test whether we can move of file page.
+ * Test whether we can move off file page.
  * \return <i>TRUE</i> if OK to move off page.
  */
 static gboolean imp_ldif_file_move() {
@@ -401,10 +431,10 @@ static gboolean imp_ldif_file_move() {
        gchar *sMsg = NULL;
        gboolean errFlag = FALSE;
 
-       sFile = gtk_editable_get_chars( GTK_EDITABLE(impldif_dlg.file_entry), 0, -1 );
+       sFile = gtk_editable_get_chars( GTK_EDITABLE(impldif_dlg.entryFile), 0, -1 );
        g_strchug( sFile ); g_strchomp( sFile );
 
-       sName = gtk_editable_get_chars( GTK_EDITABLE(impldif_dlg.name_entry), 0, -1 );
+       sName = gtk_editable_get_chars( GTK_EDITABLE(impldif_dlg.entryName), 0, -1 );
        g_strchug( sName ); g_strchomp( sName );
 
        g_free( impldif_dlg.nameBook );
@@ -412,18 +442,18 @@ static gboolean imp_ldif_file_move() {
        impldif_dlg.nameBook = sName;
        impldif_dlg.fileName = sFile;
 
-       gtk_entry_set_text( GTK_ENTRY(impldif_dlg.file_entry), sFile );
-       gtk_entry_set_text( GTK_ENTRY(impldif_dlg.name_entry), sName );
+       gtk_entry_set_text( GTK_ENTRY(impldif_dlg.entryFile), sFile );
+       gtk_entry_set_text( GTK_ENTRY(impldif_dlg.entryName), sName );
 
        if( *sFile == '\0'|| strlen( sFile ) < 1 ) {
                sMsg = _( "Please select a file." );
-               gtk_widget_grab_focus(impldif_dlg.file_entry);
+               gtk_widget_grab_focus(impldif_dlg.entryFile);
                errFlag = TRUE;
        }
 
        if( *sName == '\0'|| strlen( sName ) < 1 ) {
                if( ! errFlag ) sMsg = _( "Address book name must be supplied." );
-               gtk_widget_grab_focus(impldif_dlg.name_entry);
+               gtk_widget_grab_focus(impldif_dlg.entryName);
                errFlag = TRUE;
        }
 
@@ -452,7 +482,7 @@ static void imp_ldif_finish_show() {
        gchar *sMsg;
        gchar *name;
 
-       name = gtk_editable_get_chars( GTK_EDITABLE(impldif_dlg.name_entry), 0, -1 );
+       name = gtk_editable_get_chars( GTK_EDITABLE(impldif_dlg.entryName), 0, -1 );
        gtk_label_set_text( GTK_LABEL(impldif_dlg.labelBook), name );
        g_free( name );
        gtk_label_set_text( GTK_LABEL(impldif_dlg.labelFile), _ldifFile_->path );
@@ -546,10 +576,10 @@ static void imp_ldif_file_ok( GtkWidget *widget, gpointer data ) {
        sFile = gtk_file_selection_get_filename( GTK_FILE_SELECTION(fileSel) );
 
        afs->cancelled = FALSE;
-       gtk_entry_set_text( GTK_ENTRY(impldif_dlg.file_entry), sFile );
+       gtk_entry_set_text( GTK_ENTRY(impldif_dlg.entryFile), sFile );
        gtk_widget_hide( afs->fileSelector );
        gtk_grab_remove( afs->fileSelector );
-       gtk_widget_grab_focus( impldif_dlg.file_entry );
+       gtk_widget_grab_focus( impldif_dlg.entryFile );
 }
 
 /**
@@ -562,7 +592,7 @@ static void imp_ldif_file_cancel( GtkWidget *widget, gpointer data ) {
        afs->cancelled = TRUE;
        gtk_widget_hide( afs->fileSelector );
        gtk_grab_remove( afs->fileSelector );
-       gtk_widget_grab_focus( impldif_dlg.file_entry );
+       gtk_widget_grab_focus( impldif_dlg.entryFile );
 }
 
 /**
@@ -590,7 +620,7 @@ static void imp_ldif_file_select( void ) {
        if( ! _imp_ldif_file_selector_.fileSelector )
                imp_ldif_file_select_create( & _imp_ldif_file_selector_ );
 
-       sFile = gtk_editable_get_chars( GTK_EDITABLE(impldif_dlg.file_entry), 0, -1 );
+       sFile = gtk_editable_get_chars( GTK_EDITABLE(impldif_dlg.entryFile), 0, -1 );
        gtk_file_selection_set_filename(
                GTK_FILE_SELECTION( _imp_ldif_file_selector_.fileSelector ),
                sFile );
@@ -631,9 +661,10 @@ static void imp_ldif_page_file( gint pageNum, gchar *pageLbl ) {
        GtkWidget *vbox;
        GtkWidget *table;
        GtkWidget *label;
-       GtkWidget *file_entry;
-       GtkWidget *name_entry;
-       GtkWidget *file_btn;
+       GtkWidget *entryFile;
+       GtkWidget *entryName;
+       GtkWidget *btnFile;
+       GtkTooltips *toolTip;
        gint top;
 
        vbox = gtk_vbox_new(FALSE, 8);
@@ -661,10 +692,16 @@ static void imp_ldif_page_file( gint pageNum, gchar *pageLbl ) {
                GTK_FILL, 0, 0, 0);
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 
-       name_entry = gtk_entry_new();
-       gtk_table_attach(GTK_TABLE(table), name_entry, 1, 2, top, (top + 1),
+       entryName = gtk_entry_new();
+       gtk_table_attach(GTK_TABLE(table), entryName, 1, 2, top, (top + 1),
                GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
 
+       toolTip = gtk_tooltips_new();
+       gtk_tooltips_set_tip( toolTip, entryName, _( 
+               "Specify the name for the address book that will " \
+               "be created from the LDIF file data." ),
+               NULL );
+
        /* Second row */
        top = 1;
        label = gtk_label_new(_("File Name"));
@@ -672,22 +709,32 @@ static void imp_ldif_page_file( gint pageNum, gchar *pageLbl ) {
                GTK_FILL, 0, 0, 0);
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 
-       file_entry = gtk_entry_new();
-       gtk_table_attach(GTK_TABLE(table), file_entry, 1, 2, top, (top + 1),
+       entryFile = gtk_entry_new();
+       gtk_table_attach(GTK_TABLE(table), entryFile, 1, 2, top, (top + 1),
                GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
 
-       file_btn = gtk_button_new_with_label( _(" ... "));
-       gtk_table_attach(GTK_TABLE(table), file_btn, 2, 3, top, (top + 1),
+       toolTip = gtk_tooltips_new();
+       gtk_tooltips_set_tip( toolTip, entryFile,
+               _( "The full file specification of the LDIF file to import." ),
+               NULL );
+
+       btnFile = gtk_button_new_with_label( _(" ... "));
+       gtk_table_attach(GTK_TABLE(table), btnFile, 2, 3, top, (top + 1),
                GTK_FILL, 0, 3, 0);
 
+       toolTip = gtk_tooltips_new();
+       gtk_tooltips_set_tip( toolTip, btnFile,
+               _( "Select the LDIF file to import." ),
+               NULL );
+
        gtk_widget_show_all(vbox);
 
        /* Button handler */
-       gtk_signal_connect(GTK_OBJECT(file_btn), "clicked",
+       gtk_signal_connect(GTK_OBJECT(btnFile), "clicked",
                           GTK_SIGNAL_FUNC(imp_ldif_file_select), NULL);
 
-       impldif_dlg.file_entry = file_entry;
-       impldif_dlg.name_entry = name_entry;
+       impldif_dlg.entryFile = entryFile;
+       impldif_dlg.entryName = entryName;
 }
 
 /**
@@ -699,23 +746,25 @@ static void imp_ldif_page_fields( gint pageNum, gchar *pageLbl ) {
        GtkWidget *vbox;
        GtkWidget *vboxt;
        GtkWidget *vboxb;
-       GtkWidget *buttonMod;
-
        GtkWidget *table;
        GtkWidget *label;
        GtkWidget *clist_swin;
        GtkWidget *clist_field;
-       GtkWidget *name_ldif;
-       GtkWidget *name_attrib;
-       GtkWidget *check_select;
+       GtkWidget *entryField;
+       GtkWidget *entryAttrib;
+       GtkWidget *checkSelect;
+       GtkWidget *btnModify;
+       GtkWidget *eventBox;
+       GtkTooltips *toolTip;
        gint top;
 
        gchar *titles[ FIELDS_N_COLS ];
        gint i;
 
-       titles[ FIELD_COL_SELECT ] = _("S");
-       titles[ FIELD_COL_FIELD  ] = _("LDIF Field");
-       titles[ FIELD_COL_ATTRIB ] = _("Attribute Name");
+       titles[ FIELD_COL_RESERVED ] = _("R");
+       titles[ FIELD_COL_SELECT   ] = _("S");
+       titles[ FIELD_COL_FIELD    ] = _("LDIF Field Name");
+       titles[ FIELD_COL_ATTRIB   ] = _("Attribute Name");
 
        vbox = gtk_vbox_new(FALSE, 8);
        gtk_container_add( GTK_CONTAINER( impldif_dlg.notebook ), vbox );
@@ -740,16 +789,23 @@ static void imp_ldif_page_fields( gint pageNum, gchar *pageLbl ) {
 
        clist_field = gtk_clist_new_with_titles( FIELDS_N_COLS, titles );
        gtk_container_add( GTK_CONTAINER(clist_swin), clist_field );
-       gtk_clist_set_selection_mode( GTK_CLIST(clist_field), GTK_SELECTION_BROWSE );
-       gtk_clist_set_column_width(
-                       GTK_CLIST(clist_field), FIELD_COL_SELECT, FIELDS_COL_WIDTH_SELECT );
-       gtk_clist_set_column_width(
-                       GTK_CLIST(clist_field), FIELD_COL_FIELD, FIELDS_COL_WIDTH_FIELD );
-       gtk_clist_set_column_width(
-                       GTK_CLIST(clist_field), FIELD_COL_ATTRIB, FIELDS_COL_WIDTH_ATTRIB );
-
-       for( i = 0; i < FIELDS_N_COLS; i++ )
-               GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist_field)->column[i].button, GTK_CAN_FOCUS);
+       gtk_clist_set_selection_mode(
+               GTK_CLIST(clist_field), GTK_SELECTION_BROWSE );
+       gtk_clist_set_column_width( GTK_CLIST(clist_field),
+               FIELD_COL_RESERVED, FIELDS_COL_WIDTH_RESERVED );
+       gtk_clist_set_column_width( GTK_CLIST(clist_field),
+               FIELD_COL_SELECT, FIELDS_COL_WIDTH_SELECT );
+       gtk_clist_set_column_width( GTK_CLIST(clist_field),
+               FIELD_COL_FIELD, FIELDS_COL_WIDTH_FIELD );
+       gtk_clist_set_column_width( GTK_CLIST(clist_field),
+               FIELD_COL_ATTRIB, FIELDS_COL_WIDTH_ATTRIB );
+
+       /* Remove focus capability for column headers */
+       for( i = 0; i < FIELDS_N_COLS; i++ ) {
+               GTK_WIDGET_UNSET_FLAGS(
+                       GTK_CLIST(clist_field)->column[i].button,
+                       GTK_CAN_FOCUS);
+       }
 
        /* Lower area - Edit area */
        vboxb = gtk_vbox_new( FALSE, 4 );
@@ -768,9 +824,9 @@ static void imp_ldif_page_fields( gint pageNum, gchar *pageLbl ) {
                GTK_FILL, 0, 0, 0);
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 
-       name_ldif = gtk_label_new( "" );
-       gtk_misc_set_alignment(GTK_MISC(name_ldif), 0.01, 0.5);
-       gtk_table_attach(GTK_TABLE(table), name_ldif, 1, 3, top, (top + 1),
+       entryField = gtk_label_new( "" );
+       gtk_misc_set_alignment(GTK_MISC(entryField), 0.01, 0.5);
+       gtk_table_attach(GTK_TABLE(table), entryField, 1, 3, top, (top + 1),
                GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
 
        /* Second row */
@@ -780,25 +836,65 @@ static void imp_ldif_page_fields( gint pageNum, gchar *pageLbl ) {
                GTK_FILL, 0, 0, 0);
        gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 
-       name_attrib = gtk_entry_new();
-       gtk_table_attach(GTK_TABLE(table), name_attrib, 1, 3, top, (top + 1),
+       entryAttrib = gtk_entry_new();
+       gtk_table_attach(GTK_TABLE(table), entryAttrib, 1, 3, top, (top + 1),
                GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
 
+       toolTip = gtk_tooltips_new();
+       gtk_tooltips_set_tip( toolTip, entryAttrib,
+               _( "The LDIF field can be renamed to the User Attribute name." ),
+               NULL );
+
        /* Next row */
        ++top;
-       label = gtk_label_new(_("Select"));
+       label = gtk_label_new( _( "???" ) );
+       /*
        gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1),
                GTK_FILL, 0, 0, 0);
-       gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+       */
+       gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
+
+       /*
+        * Use an event box to attach some help in the form of a tooltip.
+        * Tried this for the clist but it looked bad.
+        */
+       eventBox = gtk_event_box_new();
+       gtk_container_add( GTK_CONTAINER(eventBox), label );
+       gtk_table_attach(GTK_TABLE(table), eventBox, 0, 1, top, (top + 1),
+               GTK_FILL, 0, 0, 0);
 
-       check_select = gtk_check_button_new();
-       gtk_table_attach(GTK_TABLE(table), check_select, 1, 2, top, (top + 1),
+       toolTip = gtk_tooltips_new();
+       gtk_tooltips_set_tip( toolTip, eventBox, _(
+               "Choose the LDIF field that will be renamed or selected " \
+               "for import in the list above. Reserved fields (marked " \
+               "with a tick in the \"R\" column), are automatically " \
+               "imported and cannot be renamed. A single click in the " \
+               "Select (\"S\") column will select the field for import " \
+               "with a tick. A single click anywhere in the row will " \
+               "select that field for rename in the input area below " \
+               "the list. A double click anywhere in the row will also " \
+               "select the field for import."
+               ), NULL );
+
+
+       checkSelect = gtk_check_button_new_with_label( _( "Select for Import" ) );
+       gtk_table_attach(GTK_TABLE(table), checkSelect, 1, 2, top, (top + 1),
                GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
 
-       buttonMod = gtk_button_new_with_label( _("Modify"));
-       gtk_table_attach(GTK_TABLE(table), buttonMod, 2, 3, top, (top + 1),
+       toolTip = gtk_tooltips_new();
+       gtk_tooltips_set_tip( toolTip, checkSelect,
+               _( "Select the LDIF field for import into the address book." ),
+               NULL );
+
+       btnModify = gtk_button_new_with_label( _(" Modify "));
+       gtk_table_attach(GTK_TABLE(table), btnModify, 2, 3, top, (top + 1),
                GTK_FILL, 0, 3, 0);
 
+       toolTip = gtk_tooltips_new();
+       gtk_tooltips_set_tip( toolTip, btnModify,
+               _( "This button will update the list above with the data supplied." ),
+               NULL );
+
        gtk_widget_show_all(vbox);
 
        /* Event handlers */
@@ -806,13 +902,14 @@ static void imp_ldif_page_fields( gint pageNum, gchar *pageLbl ) {
                        GTK_SIGNAL_FUNC(imp_ldif_field_list_selected), NULL );
        gtk_signal_connect( GTK_OBJECT(clist_field), "button_press_event",
                        GTK_SIGNAL_FUNC(imp_ldif_field_list_toggle), NULL );
-       gtk_signal_connect( GTK_OBJECT(buttonMod), "clicked",
+       gtk_signal_connect( GTK_OBJECT(btnModify), "clicked",
                        GTK_SIGNAL_FUNC(imp_ldif_modify_pressed), NULL );
 
-       impldif_dlg.clist_field  = clist_field;
-       impldif_dlg.name_ldif    = name_ldif;
-       impldif_dlg.name_attrib  = name_attrib;
-       impldif_dlg.check_select = check_select;
+       impldif_dlg.clist_field = clist_field;
+       impldif_dlg.entryField  = entryField;
+       impldif_dlg.entryAttrib = entryAttrib;
+       impldif_dlg.checkSelect = checkSelect;
+       impldif_dlg.btnModify   = btnModify;
 }
 
 /**
@@ -844,11 +941,11 @@ static void imp_ldif_page_finish( gint pageNum, gchar *pageLbl ) {
        gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
        gtk_container_set_border_width( GTK_CONTAINER(table), 8 );
        gtk_table_set_row_spacings(GTK_TABLE(table), 8);
-       gtk_table_set_col_spacings(GTK_TABLE(table), 8 );
+       gtk_table_set_col_spacings(GTK_TABLE(table), 8);
 
        /* First row */
        top = 0;
-       label = gtk_label_new(_("Address Book :"));
+       label = gtk_label_new( _( "Address Book :" ) );
        gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
 
@@ -858,7 +955,7 @@ static void imp_ldif_page_finish( gint pageNum, gchar *pageLbl ) {
 
        /* Second row */
        top++;
-       label = gtk_label_new(_("File Name :"));
+       label = gtk_label_new( _( "File Name :" ) );
        gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
 
@@ -868,7 +965,7 @@ static void imp_ldif_page_finish( gint pageNum, gchar *pageLbl ) {
 
        /* Third row */
        top++;
-       label = gtk_label_new(_("Records :"));
+       label = gtk_label_new( _("Records Imported :") );
        gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
        gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
 
@@ -988,10 +1085,10 @@ AddressBookFile *addressbook_imp_ldif( AddressIndex *addrIndex ) {
        manage_window_set_transient(GTK_WINDOW(impldif_dlg.window));
        gtk_widget_grab_default(impldif_dlg.btnNext);
 
-       gtk_entry_set_text( GTK_ENTRY(impldif_dlg.name_entry), IMPORTLDIF_GUESS_NAME );
-       gtk_entry_set_text( GTK_ENTRY(impldif_dlg.file_entry), "" );
-       gtk_label_set_text( GTK_LABEL(impldif_dlg.name_ldif), "" );
-       gtk_entry_set_text( GTK_ENTRY(impldif_dlg.name_attrib), "" );
+       gtk_entry_set_text( GTK_ENTRY(impldif_dlg.entryName), IMPORTLDIF_GUESS_NAME );
+       gtk_entry_set_text( GTK_ENTRY(impldif_dlg.entryFile), "" );
+       gtk_label_set_text( GTK_LABEL(impldif_dlg.entryField), "" );
+       gtk_entry_set_text( GTK_ENTRY(impldif_dlg.entryAttrib), "" );
        gtk_clist_clear( GTK_CLIST(impldif_dlg.clist_field) );
        gtk_notebook_set_page( GTK_NOTEBOOK(impldif_dlg.notebook), PAGE_FILE_INFO );
        gtk_widget_set_sensitive( impldif_dlg.btnPrev, FALSE );
@@ -999,7 +1096,7 @@ AddressBookFile *addressbook_imp_ldif( AddressIndex *addrIndex ) {
        stock_pixmap_gdk( impldif_dlg.window, STOCK_PIXMAP_MARK,
                          &markxpm, &markxpmmask );
        imp_ldif_message();
-       gtk_widget_grab_focus(impldif_dlg.file_entry);
+       gtk_widget_grab_focus(impldif_dlg.entryFile);
 
        impldif_dlg.rowIndSelect = -1;
        impldif_dlg.rowCount = 0;
@@ -1025,6 +1122,8 @@ AddressBookFile *addressbook_imp_ldif( AddressIndex *addrIndex ) {
 }
 
 /*
-* End of Source.
-*/
+ * ============================================================================
+ * End of Source.
+ * ============================================================================
+ */
 
index 7ad132f..c5dcd78 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 2001 Match Grun
+ * Copyright (C) 2001-2003 Match Grun
  *
  * 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
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <sys/stat.h>
 
+#include "intl.h"
 #include "mgutils.h"
 #include "ldif.h"
 #include "addritem.h"
 
 #include "base64.h"
 
-/*
-* Create new object.
-*/
+#define        LDIF_SEP_TAG    ':'
+#define        LDIF_LANG_TAG   ';'
+
+/**
+ * Create new object.
+ * \return Initialized LDIF file object.
+ */
 LdifFile *ldif_create() {
        LdifFile *ldifFile;
        ldifFile = g_new0( LdifFile, 1 );
@@ -52,9 +57,11 @@ LdifFile *ldif_create() {
        return ldifFile;
 }
 
-/*
-* Properties...
-*/
+/**
+ * Specify full file specification of LDIF file.
+ * \param ldifFile LDIF import control object.
+ * \param value    Value of access flag.
+ */
 void ldif_set_file( LdifFile *ldifFile, const gchar *value ) {
        g_return_if_fail( ldifFile != NULL );
 
@@ -69,27 +76,39 @@ void ldif_set_file( LdifFile *ldifFile, const gchar *value ) {
        g_strstrip( ldifFile->path );
        ldifFile->importCount = 0;
 }
+
+/**
+ * Set the file access indicator.
+ * \param ldifFile LDIF import control object.
+ * \param value    File specification.
+ */
 void ldif_set_accessed( LdifFile *ldifFile, const gboolean value ) {
        g_return_if_fail( ldifFile != NULL );
        ldifFile->accessFlag = value;
 }
 
-/*
-* Register a callback function. When called, the function will be passed
-* the following arguments:
-*      LdifFile object,
-*      File size (long),
-*      Current position (long)
-* This can be used for a progress indicator.
-*/
+/**
+ * Register a progress indicator callback function.
+ *
+ * \param ldifFile LDIF import control object.
+ * \param func     Function to be called. When called, the function will be
+ *                 passed the following arguments:
+ *
+ * <ul>
+ * <li>LdifFile object,</li>
+ * <li>File size (long),</li>
+ * <li>Current position (long)</li>
+ * </ul>
+ */
 void ldif_set_callback( LdifFile *ldifFile, void *func ) {
        ldifFile->cbProgress = func;
 }
 
-/*
-* Create field record object.
-*/
-static Ldif_FieldRec *ldif_create_fieldrec( gchar *field ) {
+/**
+ * Create field record object.
+ * \return Initialized LDIF field object.
+ */
+static Ldif_FieldRec *ldif_create_fieldrec( const gchar *field ) {
        Ldif_FieldRec *rec = g_new0( Ldif_FieldRec, 1 );
        rec->tagName = g_strdup( field );
        rec->userName = NULL;
@@ -98,9 +117,10 @@ static Ldif_FieldRec *ldif_create_fieldrec( gchar *field ) {
        return rec;
 }
 
-/*
-* Free field record object.
-*/
+/**
+ * Free field record object.
+ * \param rec LDIF field object.
+ */
 static void ldif_free_fieldrec( Ldif_FieldRec *rec ) {
        if( rec ) {
                g_free( rec->tagName );
@@ -113,8 +133,54 @@ static void ldif_free_fieldrec( Ldif_FieldRec *rec ) {
        }
 }
 
-/*
-* Free hash table entry visitor function.
+/**
+ * Set user name for field record.
+ * \param rec   LDIF field object.
+ * \param value User name to set. Note that reserved fields cannot be
+ *              named.
+ */
+void ldif_field_set_name( Ldif_FieldRec *rec, const gchar *value ) {
+       g_return_if_fail( rec != NULL );
+
+       if( ! rec->reserved ) {
+               rec->userName = mgu_replace_string( rec->userName, value );
+               g_strstrip( rec->userName );
+       }
+}
+
+/**
+ * Specify selection for field record.
+ * \param rec   LDIF field object.
+ * \param value Set to <i>TRUE</i> to select field. Note that reserved
+ *              fields cannot be unselected.
+ */
+void ldif_field_set_selected( Ldif_FieldRec *rec, const gboolean value ) {
+       g_return_if_fail( rec != NULL );
+
+       if( ! rec->reserved ) {
+               rec->selected = value;
+       }
+}
+
+/**
+ * Toggle selection for field record. Note that reserved fields cannot be
+ * toggled.
+ * \param rec   LDIF field object.
+ */
+void ldif_field_toggle( Ldif_FieldRec *rec ) {
+       g_return_if_fail( rec != NULL );
+
+       if( ! rec->reserved ) {
+               rec->selected = !rec->selected;
+       }
+}
+
+/**
+ * Free hash table entry visitor function.
+ * \param  key   Key.
+ * \param  value Value (the LDIF field record).
+ * \param  data  User data.
+ * \return <code>-1</code>.
 */
 static gint ldif_hash_free_vis( gpointer key, gpointer value, gpointer data ) {
        ldif_free_fieldrec( ( Ldif_FieldRec * ) value );
@@ -123,9 +189,10 @@ static gint ldif_hash_free_vis( gpointer key, gpointer value, gpointer data ) {
        return -1;
 }
 
-/*
-* Free up object by releasing internal memory.
-*/
+/**
+ * Free up object by releasing internal memory.
+ * \param ldifFile LDIF import control object.
+ */
 void ldif_free( LdifFile *ldifFile ) {
        g_return_if_fail( ldifFile != NULL );
 
@@ -153,28 +220,35 @@ void ldif_free( LdifFile *ldifFile ) {
        g_free( ldifFile );
 }
 
-/*
-* Display field record.
-*/
+/**
+ * Display field record.
+ * \param rec    LDIF field object.
+ * \param stream File output stream.
+ */
 void ldif_print_fieldrec( Ldif_FieldRec *rec, FILE *stream ) {
        fprintf( stream, "\ttag:\t%s", rec->reserved ? "yes" : "no" );
        fprintf( stream, "\t%s", rec->selected ? "yes" : "no" );
        fprintf( stream, "\t:%s:\t:%s:\n", rec->userName, rec->tagName );
 }
 
-/*
-* Display field record.
+/**
+ * Display field record.
+ * \param key   Key.
+ * \param value Value (the LDIF field record).
+ * \param data  User data (file output stream).
  * 
-*/
+ */
 static void ldif_print_file_vis( gpointer key, gpointer value, gpointer data ) {
        Ldif_FieldRec *rec = value;
        FILE *stream = data;
        ldif_print_fieldrec( rec, stream );
 }
 
-/*
-* Display object to specified stream.
-*/
+/**
+ * Display object to specified stream.
+ * \param ldifFile LDIF import control object.
+ * \param stream   File output stream.
+ */
 void ldif_print_file( LdifFile *ldifFile, FILE *stream ) {
        g_return_if_fail( ldifFile != NULL );
        fprintf( stream, "LDIF File:\n" );
@@ -185,10 +259,11 @@ void ldif_print_file( LdifFile *ldifFile, FILE *stream ) {
        fprintf( stream, "} ---\n" );
 }
 
-/*
-* Open file for read.
-* return: TRUE if file opened successfully.
-*/
+/**
+ * Open file for read.
+ * \param  ldifFile LDIF import control object.
+ * \return <i>TRUE</i> if file opened successfully.
+ */
 static gint ldif_open_file( LdifFile* ldifFile ) {
        /* printf( "Opening file\n" ); */
        if( ldifFile->path ) {
@@ -212,19 +287,21 @@ static gint ldif_open_file( LdifFile* ldifFile ) {
        return ldifFile->retVal;
 }
 
-/*
-* Close file.
-*/
+/**
+ * Close file.
+ * \param  ldifFile LDIF import control object.
+ */
 static void ldif_close_file( LdifFile *ldifFile ) {
        g_return_if_fail( ldifFile != NULL );
        if( ldifFile->file ) fclose( ldifFile->file );
        ldifFile->file = NULL;
 }
 
-/*
-* Read line of text from file.
-* Return: ptr to buffer where line starts.
-*/
+/**
+ * Read line of text from file.
+ * \param  ldifFile LDIF import control object.
+ * \return ptr to buffer where line starts.
+ */
 static gchar *ldif_get_line( LdifFile *ldifFile ) {
        gchar buf[ LDIFBUFSIZE ];
        gint ch;
@@ -253,13 +330,13 @@ static gchar *ldif_get_line( LdifFile *ldifFile ) {
        return g_strdup( buf );
 }
 
-/*
-* Parse tag name from line buffer.
-* Enter: line   Buffer.
-*        flag64 Base-64 encoder flag.
-* Return: Buffer containing the tag name, or NULL if no delimiter char found.
-* If a double delimiter (::) is found, flag64 is set.
-*/
+/**
+ * Parse tag name from line buffer.
+ * \param  line Buffer.
+ * \param  flag64 Base-64 encoder flag.
+ * \return Buffer containing the tag name, or NULL if no delimiter char found.
+ *         If a double delimiter (::) is found, flag64 is set.
+ */
 static gchar *ldif_get_tagname( char* line, gboolean *flag64 ) {
        gint len = 0;
        gchar *tag = NULL;
@@ -293,12 +370,12 @@ static gchar *ldif_get_tagname( char* line, gboolean *flag64 ) {
        return tag;
 }
 
-/*
-* Parse tag value from line buffer.
-* Enter: line   Buffer.
-* Return: Buffer containing the tag value. Empty string is returned if
-* no delimiter char found.
-*/
+/**
+ * Parse tag value from line buffer.
+ * \param  line Buffer.
+ * \return Buffer containing the tag value. Empty string is returned if
+ *         no delimiter char found.
+ */
 static gchar *ldif_get_tagvalue( gchar* line ) {
        gchar *value = NULL;
        gchar *start = NULL;
@@ -325,9 +402,9 @@ static gchar *ldif_get_tagvalue( gchar* line ) {
        return value;
 }
 
-/*
-* Parsed address data.
-*/
+/**
+ * Parsed address data record.
+ */
 typedef struct _Ldif_ParsedRec_ Ldif_ParsedRec;
 struct _Ldif_ParsedRec_ {
        GSList *listCName;
@@ -339,24 +416,30 @@ struct _Ldif_ParsedRec_ {
        GSList *userAttr;
 };
 
-/*
-* User attribute data.
-*/
+/**
+ * User attribute data record.
+ */
 typedef struct _Ldif_UserAttr_ Ldif_UserAttr;
 struct _Ldif_UserAttr_ {
        gchar *name;
        gchar *value;
 };
 
-/*
-* Build an address list entry and append to list of address items. Name is formatted
-* as "<first-name> <last-name>".
-*/
-static void ldif_build_items( LdifFile *ldifFile, Ldif_ParsedRec *rec, AddressCache *cache ) {
+/**
+ * Build an address list entry and append to list of address items in the
+ * address cache. Name is formatted as "<first-name> <last-name>".
+ * \param ldifFile LDIF import control object.
+ * \param rec      LDIF field object.
+ * \param cache    Address cache to be populated with data.
+ */
+static void ldif_build_items(
+               LdifFile *ldifFile, Ldif_ParsedRec *rec, AddressCache *cache )
+{
        GSList *nodeFirst;
        GSList *nodeAddress;
        GSList *nodeAttr;
-       gchar *firstName = NULL, *lastName = NULL, *fullName = NULL, *nickName = NULL;
+       gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
+       gchar *nickName = NULL;
        gint iLen = 0, iLenT = 0;
        ItemPerson *person;
        ItemEMail *email;
@@ -387,7 +470,8 @@ static void ldif_build_items( LdifFile *ldifFile, Ldif_ParsedRec *rec, AddressCa
 
        if( firstName ) {
                if( lastName ) {
-                       fullName = g_strdup_printf( "%s %s", firstName, lastName );
+                       fullName = g_strdup_printf(
+                               "%s %s", firstName, lastName );
                }
                else {
                        fullName = g_strdup_printf( "%s", firstName );
@@ -439,17 +523,23 @@ static void ldif_build_items( LdifFile *ldifFile, Ldif_ParsedRec *rec, AddressCa
        nodeAttr = NULL;
 }
 
-/*
-* Add selected field as user attribute.
-*/
-static void ldif_add_user_attr( Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue, GHashTable *hashField ) {
+/**
+ * Add selected field as user attribute.
+ * \param rec       LDIF field object.
+ * \param tagName   LDIF tag name.
+ * \param tagValue  Data value.
+ * \param hashField Hash table to populate.
+ */
+static void ldif_add_user_attr(
+               Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue,
+               GHashTable *hashField )
+{
        Ldif_FieldRec *fld = NULL;
        Ldif_UserAttr *attr = NULL;
        gchar *name;
 
        fld = g_hash_table_lookup( hashField, tagName );
        if( fld ) {
-               if( fld->reserved ) return;
                if( ! fld->selected ) return;
 
                name = fld->tagName;
@@ -463,10 +553,17 @@ static void ldif_add_user_attr( Ldif_ParsedRec *rec, gchar *tagName, gchar *tagV
        }
 }
 
-/*
-* Add value to parsed data.
-*/
-static void ldif_add_value( Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue, GHashTable *hashField ) {
+/**
+ * Add value to parsed data.
+ * \param rec       LDIF field object.
+ * \param tagName   LDIF tag name.
+ * \param tagValue  Data value.
+ * \param hashField Hash table to populate.
+ */
+static void ldif_add_value(
+              Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue,
+              GHashTable *hashField )
+{
        gchar *nm, *val;
 
        nm = g_strdup( tagName );
@@ -478,6 +575,7 @@ static void ldif_add_value( Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue
                val = g_strdup( "" );
        }
        g_strstrip( val );
+
        if( g_strcasecmp( nm, LDIF_TAG_COMMONNAME ) == 0 ) {
                rec->listCName = g_slist_append( rec->listCName, val );
        }
@@ -500,9 +598,10 @@ static void ldif_add_value( Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue
        g_free( nm );
 }
 
-/*
-* Clear parsed data.
-*/
+/**
+ * Clear parsed data record.
+ * \param rec LDIF field object.
+ */
 static void ldif_clear_rec( Ldif_ParsedRec *rec ) {
        GSList *list;
 
@@ -533,10 +632,12 @@ static void ldif_clear_rec( Ldif_ParsedRec *rec ) {
        rec->listID = NULL;
 }
 
-/*
-* Print parsed data.
-*/
 #if 0
+/**
+ * Print parsed data.
+ * \param rec    LDIF field object.
+ * \param stream Output stream.
+ */
 static void ldif_print_record( Ldif_ParsedRec *rec, FILE *stream ) {
        GSList *list;
 
@@ -570,12 +671,15 @@ static void ldif_print_record( Ldif_ParsedRec *rec, FILE *stream ) {
 }
 #endif
 
-/*
-* Read file data into address cache.
-* Note that one LDIF record identifies one entity uniquely with the
-* distinguished name (dn) tag. Each person can have multiple E-Mail
-* addresses. Also, each person can have many common name (cn) tags.
-*/
+/**
+ * Read file data into address cache.
+ * Note that one LDIF record identifies one entity uniquely with the
+ * distinguished name (dn) tag. Each person can have multiple E-Mail
+ * addresses. Also, each person can have many common name (cn) tags.
+ *
+ * \param  ldifFile LDIF import control object.
+ * \param  cache    Address cache to be populated with data.
+ */
 static void ldif_read_file( LdifFile *ldifFile, AddressCache *cache ) {
        gchar *tagName = NULL, *tagValue = NULL;
        gchar *lastTag = NULL, *fullValue = NULL;
@@ -641,11 +745,13 @@ static void ldif_read_file( LdifFile *ldifFile, AddressCache *cache ) {
                        flagEOR = FALSE;
                        if( *line == ' ' ) {
                                /* Continuation line */
-                               listValue = g_slist_append( listValue, g_strdup( line+1 ) );
+                               listValue = g_slist_append(
+                                       listValue, g_strdup( line+1 ) );
                        }
                        else if( *line == '=' ) {
                                /* Base-64 encoded continuation field */
-                               listValue = g_slist_append( listValue, g_strdup( line ) );
+                               listValue = g_slist_append(
+                                       listValue, g_strdup( line ) );
                        }
                        else {
                                /* Parse line */
@@ -655,7 +761,8 @@ static void ldif_read_file( LdifFile *ldifFile, AddressCache *cache ) {
                                        if( tagValue ) {
                                                if( lastTag ) {
                                                        /* Save data */
-                                                       fullValue = mgu_list_coalesce( listValue );
+                                                       fullValue =
+                                                               mgu_list_coalesce( listValue );
                                                        /* Base-64 encoded data */
                                                        /*
                                                        if( last64 ) {
@@ -663,7 +770,9 @@ static void ldif_read_file( LdifFile *ldifFile, AddressCache *cache ) {
                                                        }
                                                        */
 
-                                                       ldif_add_value( rec, lastTag, fullValue, hashField );
+                                                       ldif_add_value(
+                                                               rec, lastTag, fullValue,
+                                                               hashField );
                                                        g_free( lastTag );
                                                        mgu_free_list( listValue );
                                                        lastTag = NULL;
@@ -672,7 +781,9 @@ static void ldif_read_file( LdifFile *ldifFile, AddressCache *cache ) {
                                                }
 
                                                lastTag = g_strdup( tagName );
-                                               listValue = g_slist_append( listValue, g_strdup( tagValue ) );
+                                               listValue = g_slist_append(
+                                                       listValue,
+                                                       g_strdup( tagValue ) );
                                                g_free( tagValue );
                                                last64 = flag64;
                                        }
@@ -690,9 +801,11 @@ static void ldif_read_file( LdifFile *ldifFile, AddressCache *cache ) {
        mgu_free_list( listValue );
 }
 
-/*
-* Add list of field names to hash table.
-*/
+/**
+ * Add list of field names to hash table.
+ * \param table Hashtable.
+ * \param list  List of fields.
+ */
 static void ldif_hash_add_list( GHashTable *table, GSList *list ) {
        GSList *node = list;
 
@@ -704,20 +817,29 @@ static void ldif_hash_add_list( GHashTable *table, GSList *list ) {
                        gchar *key = g_strdup( tag );
 
                        rec = ldif_create_fieldrec( tag );
-                       if( g_strcasecmp( tag, LDIF_TAG_COMMONNAME ) == 0 ) {
-                               rec->reserved = TRUE;
+                       if( g_strcasecmp( tag, LDIF_TAG_DN ) == 0 ) {
+                               rec->reserved = rec->selected = TRUE;
+                               rec->userName = g_strdup( "dn" );
+                       }
+                       else if( g_strcasecmp( tag, LDIF_TAG_COMMONNAME ) == 0 ) {
+                               rec->reserved = rec->selected = TRUE;
+                               rec->userName = g_strdup( _( "Display Name" ) );
                        }
                        else if( g_strcasecmp( tag, LDIF_TAG_FIRSTNAME ) == 0 ) {
-                               rec->reserved = TRUE;
+                               rec->reserved = rec->selected = TRUE;
+                               rec->userName = g_strdup( _( "First Name" ) );
                        }
                        else if( g_strcasecmp( tag, LDIF_TAG_LASTNAME ) == 0 ) {
-                               rec->reserved = TRUE;
+                               rec->reserved = rec->selected = TRUE;
+                               rec->userName = g_strdup( _( "Last Name" ) );
                        }
                        else if( g_strcasecmp( tag, LDIF_TAG_NICKNAME ) == 0 ) {
-                               rec->reserved = TRUE;
+                               rec->reserved = rec->selected = TRUE;
+                               rec->userName = g_strdup( _( "Nick Name" ) );
                        }
                        else if( g_strcasecmp( tag, LDIF_TAG_EMAIL ) == 0 ) {
-                               rec->reserved = TRUE;
+                               rec->reserved = rec->selected = TRUE;
+                               rec->userName = g_strdup( _( "E-Mail Address" ) );
                        }
                        g_hash_table_insert( table, key, rec );
                }
@@ -725,26 +847,46 @@ static void ldif_hash_add_list( GHashTable *table, GSList *list ) {
        }
 }
 
-/*
-* Sorted list comparison function.
-*/
-static int ldif_field_compare( gconstpointer ptr1, gconstpointer ptr2 ) {
+/**
+ * Sorted list comparison function.
+ * \param  ptr1 First field.
+ * \param  ptr2 Second field.
+ * \return <code>-1, 0, +1</code> if first record less than, equal,
+ *         greater than second.
+ */
+static gint ldif_field_compare( gconstpointer ptr1, gconstpointer ptr2 ) {
        const Ldif_FieldRec *rec1 = ptr1;
        const Ldif_FieldRec *rec2 = ptr2;
+
+       if( rec1->reserved ) {
+               if( ! rec2->reserved ) {
+                       return +1;
+               }
+       }
+       else {
+               if( rec2->reserved ) {
+                       return -1;
+               }
+       }
        return g_strcasecmp( rec1->tagName, rec2->tagName );
 }
 
 /*
-* Append hash table entry to list - visitor function.
-*/
+ * Append hash table entry to list - visitor function.
+ * \param key   Key.
+ * \param value Data value.
+ * \param data  User data (the LDIF import control object).
+ */
 static void ldif_hash2list_vis( gpointer key, gpointer value, gpointer data ) {
        LdifFile *ldf = data;
-       ldf->tempList = g_list_insert_sorted( ldf->tempList, value, ldif_field_compare );
+       ldf->tempList =
+               g_list_insert_sorted( ldf->tempList, value, ldif_field_compare );
 }
 
-/*
-* Read tag names for file data.
-*/
+/**
+ * Read tag names for file data.
+ * \param  ldifFile LDIF import control object.
+ */
 static void ldif_read_tag_list( LdifFile *ldifFile ) {
        gchar *tagName = NULL;
        GSList *listTags = NULL;
@@ -754,7 +896,8 @@ static void ldif_read_tag_list( LdifFile *ldifFile ) {
        long posCur = 0L;
 
        /* Clear hash table */
-       g_hash_table_foreach_remove( ldifFile->hashFields, ldif_hash_free_vis, NULL );
+       g_hash_table_foreach_remove(
+               ldifFile->hashFields, ldif_hash_free_vis, NULL );
 
        /* Find EOF for progress indicator */
        fseek( ldifFile->file, 0L, SEEK_END );
@@ -783,7 +926,8 @@ static void ldif_read_tag_list( LdifFile *ldifFile ) {
                        /* EOR, Output address data */
                        /* Save field list to hash table */
                        if( flagMail ) {
-                               ldif_hash_add_list( ldifFile->hashFields, listTags );
+                               ldif_hash_add_list(
+                                       ldifFile->hashFields, listTags );
                        }
                        mgu_free_list( listTags );
                        listTags = NULL;
@@ -803,7 +947,9 @@ static void ldif_read_tag_list( LdifFile *ldifFile ) {
                                if( tagName ) {
                                        /* Add tag to list */
                                        listTags = g_slist_append( listTags, tagName );
-                                       if( g_strcasecmp( tagName, LDIF_TAG_EMAIL ) == 0 ) {
+                                       if( g_strcasecmp(
+                                               tagName, LDIF_TAG_EMAIL ) == 0 )
+                                       {
                                                flagMail = TRUE;
                                        }
                                }
@@ -817,14 +963,12 @@ static void ldif_read_tag_list( LdifFile *ldifFile ) {
        listTags = NULL;
 }
 
-/*
-* ============================================================================
-* Read file into list. Main entry point
-* Enter:  ldifFile LDIF control data.
-*         cache    Address cache to load.
-* Return: Status code.
-* ============================================================================
-*/
+/**
+ * Read file into list. Main entry point
+ * \param  ldifFile LDIF import control object.
+ * \param  cache    Address cache to load.
+ * \return Status code.
+ */
 gint ldif_import_data( LdifFile *ldifFile, AddressCache *cache ) {
        g_return_val_if_fail( ldifFile != NULL, MGU_BAD_ARGS );
        ldifFile->retVal = MGU_SUCCESS;
@@ -843,14 +987,12 @@ gint ldif_import_data( LdifFile *ldifFile, AddressCache *cache ) {
        return ldifFile->retVal;
 }
 
-/*
-* ============================================================================
-* Process entire file reading list of unique fields. List of fields may be
-* accessed with the ldif_get_fieldlist() function.
-* Enter:  ldifFile LDIF control data.
-* Return: Status code.
-* ============================================================================
-*/
+/**
+ * Process entire file reading list of unique fields. List of fields may be
+ * accessed with the <code>ldif_get_fieldlist()</code> function.
+ * \param  ldifFile LDIF import control object.
+ * \return Status code.
+ */
 gint ldif_read_tags( LdifFile *ldifFile ) {
        g_return_val_if_fail( ldifFile != NULL, MGU_BAD_ARGS );
        ldifFile->retVal = MGU_SUCCESS;
@@ -867,14 +1009,14 @@ gint ldif_read_tags( LdifFile *ldifFile ) {
        return ldifFile->retVal;
 }
 
-/*
-* Return list of fields for LDIF file.
-* Enter: ldifFile LdifFile object.
-* Return: Linked list of Ldif_FieldRec objects. This list may be g_free'd.
-* Note that the objects in the list should not be freed since they refer to
-* objects inside the internal cache. These objects will be freed when
-* LDIF file object is freed.
-*/
+/**
+ * Return list of fields for LDIF file.
+ * \param  ldifFile LDIF import control object.
+ * \return Linked list of <code>Ldif_FieldRec</code> objects. This list may be
+ *         <code>g_free()</code>. Note that the objects in the list should not
+ *         be freed since they refer to objects inside the internal cache.
+ *         These objects will be freed when LDIF file object is freed.
+ */
 GList *ldif_get_fieldlist( LdifFile *ldifFile ) {
        GList *list = NULL;
 
@@ -888,7 +1030,37 @@ GList *ldif_get_fieldlist( LdifFile *ldifFile ) {
        return list;
 }
 
+/**
+ * Output LDIF name-value pair to stream. Only non-empty names and values will
+ * be output to file.
+ * \param stream File output stream.
+ * \param name   Name.
+ * \param value  Data value.
+ * \return <i>TRUE</i> if data output.
+ */
+gboolean ldif_write_value( FILE *stream, const gchar *name, const gchar *value ) {
+       if( name == NULL ) return FALSE;
+       if( value == NULL ) return FALSE;
+       if( strlen( name ) < 1 ) return FALSE;
+       if( strlen( value ) < 1 ) return FALSE;
+       fprintf( stream, "%s: ", name );
+       fprintf( stream, "%s\n", value );
+       return TRUE;
+}
+
+/**
+ * Output LDIF End of Record to stream.
+ * \param stream File output stream.
+ * \return <i>TRUE</i> if data output.
+ */
+void ldif_write_eor( FILE *stream ) {
+       /* Simple but caller should not need to know how to end record. */
+       fprintf( stream, "\n" );
+}
+
 /*
-* End of Source.
-*/
+ * ============================================================================
+ * End of Source.
+ * ============================================================================
+ */
 
index 822dc54..e4afb05 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 2001 Match Grun
+ * Copyright (C) 2001-2003 Match Grun
  *
  * 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
 
 #define LDIFBUFSIZE         2048
 
-/* Reserved tag names - for address book import */
-#define        LDIF_TAG_COMMONNAME "cn"
-#define        LDIF_TAG_FIRSTNAME  "givenname"
-#define        LDIF_TAG_LASTNAME   "sn"
-#define LDIF_TAG_NICKNAME   "xmozillanickname"
-#define        LDIF_TAG_EMAIL      "mail"
+/* Common tag names - for address book import/export */
+#define        LDIF_TAG_DN            "dn"
+#define        LDIF_TAG_COMMONNAME    "cn"
+#define        LDIF_TAG_FIRSTNAME     "givenname"
+#define        LDIF_TAG_LASTNAME      "sn"
+#define LDIF_TAG_NICKNAME      "xmozillanickname"
+#define        LDIF_TAG_EMAIL         "mail"
+#define        LDIF_TAG_OBJECTCLASS   "objectclass"
 
-#define        LDIF_SEP_TAG        ':'
-#define        LDIF_LANG_TAG       ';'
+/* Object classes */
+#define LDIF_CLASS_PERSON      "person"
+#define LDIF_CLASS_INET_PERSON "inetOrgPerson"
 
 /*
 * Typical LDIF entry (similar to that generated by Netscape):
@@ -94,7 +97,7 @@ struct _LdifFile {
        gint       importCount;
 };
 
-/* Field list structure */
+/* LDIF field record structure */
 typedef struct _Ldif_FieldRec_ Ldif_FieldRec;
 struct _Ldif_FieldRec_ {
        gchar *tagName;
@@ -108,12 +111,18 @@ LdifFile *ldif_create             ( void );
 void ldif_set_file             ( LdifFile* ldifFile, const gchar *value );
 void ldif_set_accessed         ( LdifFile* ldifFile, const gboolean value );
 void ldif_set_callback         ( LdifFile *ldifFile, void *func );
+void ldif_field_set_name       ( Ldif_FieldRec *rec, const gchar *value );
+void ldif_field_set_selected   ( Ldif_FieldRec *rec, const gboolean value );
+void ldif_field_toggle         ( Ldif_FieldRec *rec );
 void ldif_free                 ( LdifFile *ldifFile );
 void ldif_print_fieldrec       ( Ldif_FieldRec *rec, FILE *stream );
 void ldif_print_file           ( LdifFile *ldifFile, FILE *stream );
 gint ldif_import_data          ( LdifFile *ldifFile, AddressCache *cache );
 gint ldif_read_tags            ( LdifFile *ldifFile );
 GList *ldif_get_fieldlist      ( LdifFile *ldifFile );
+gboolean ldif_write_value      ( FILE *stream, const gchar *name,
+                                 const gchar *value );
+void ldif_write_eor            ( FILE *stream );
 
 #endif /* __LDIF_H__ */