From 6c3cf297c02faf00d5e97754b18ff9b2c4284fe7 Mon Sep 17 00:00:00 2001 From: Match Grun Date: Tue, 5 Aug 2003 04:14:35 +0000 Subject: [PATCH] Add export LDIF. --- ChangeLog.claws | 2 +- configure.ac | 2 +- src/Makefile.am | 2 + src/addressbook.c | 28 ++ src/common/xmlprops.h | 2 +- src/exphtmldlg.c | 151 +++++--- src/exphtmldlg.h | 2 +- src/expldifdlg.c | 849 ++++++++++++++++++++++++++++++++++++++++++ src/expldifdlg.h | 35 ++ src/exportldif.c | 698 ++++++++++++++++++++++++++++++++++ src/exportldif.h | 81 ++++ src/importldif.c | 329 ++++++++++------ src/ldif.c | 466 +++++++++++++++-------- src/ldif.h | 29 +- 14 files changed, 2357 insertions(+), 319 deletions(-) create mode 100644 src/expldifdlg.c create mode 100644 src/expldifdlg.h create mode 100644 src/exportldif.c create mode 100644 src/exportldif.h diff --git a/ChangeLog.claws b/ChangeLog.claws index 5438e7b84..792162aab 100644 --- a/ChangeLog.claws +++ b/ChangeLog.claws @@ -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. diff --git a/configure.ac b/configure.ac index 6732387a6..0abbf752f 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/src/Makefile.am b/src/Makefile.am index e11eb9d10..025b878d6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ diff --git a/src/addressbook.c b/src/addressbook.c index dbf57c5c7..a76ca489c 100644 --- a/src/addressbook.c +++ b/src/addressbook.c @@ -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, ""}, {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, ""}, {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. */ diff --git a/src/common/xmlprops.h b/src/common/xmlprops.h index 95df5265d..49536ab76 100644 --- a/src/common/xmlprops.h +++ b/src/common/xmlprops.h @@ -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/exphtmldlg.c b/src/exphtmldlg.c index ab5371797..1efa08028 100644 --- a/src/exphtmldlg.c +++ b/src/exphtmldlg.c @@ -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 TRUE 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 TRUE 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. + * ============================================================================ + */ diff --git a/src/exphtmldlg.h b/src/exphtmldlg.h index 26addaf26..6d2e5b007 100644 --- a/src/exphtmldlg.h +++ b/src/exphtmldlg.h @@ -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 index 000000000..7d9bb26df --- /dev/null +++ b/src/expldifdlg.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#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 TRUE 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 TRUE 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 index 000000000..5fb28d646 --- /dev/null +++ b/src/expldifdlg.h @@ -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 index 000000000..4ade0fe50 --- /dev/null +++ b/src/exportldif.c @@ -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 +#include +#include +#include +#include +#include + +#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: + *
    + *
  • EXPORT_LDIF_ID_UID - Use Sylpheed UID.
  • + *
  • EXPORT_LDIF_ID_DNAME - Use Sylpheed display name.
  • + *
  • EXPORT_LDIF_ID_EMAIL - Use first E-Mail address.
  • + *
+ */ +void exportldif_set_rdn( ExportLdifCtl *ctl, const gint value ) { + g_return_if_fail( ctl != NULL ); + ctl->rdnIndex = value; +} + +/** + * Specify that DN attribute, if present, should be used as the + * DN for the entry. + * \param ctl Export control data. + * \param value TRUE 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 TRUE 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 TRUE 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 TRUE 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 TRUE 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 TRUE 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 index 000000000..c0a056b79 --- /dev/null +++ b/src/exportldif.h @@ -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 + +#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__ */ + diff --git a/src/importldif.c b/src/importldif.c index a9eacc4ea..03c491e65 100644 --- a/src/importldif.c +++ b/src/importldif.c @@ -54,18 +54,20 @@ #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 TRUE 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 TRUE 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. + * ============================================================================ + */ diff --git a/src/ldif.c b/src/ldif.c index 7ad132ff9..c5dcd7816 100644 --- a/src/ldif.c +++ b/src/ldif.c @@ -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 #include +#include "intl.h" #include "mgutils.h" #include "ldif.h" #include "addritem.h" @@ -33,9 +34,13 @@ #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: + * + *
    + *
  • LdifFile object,
  • + *
  • File size (long),
  • + *
  • Current position (long)
  • + *
+ */ 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 TRUE 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 -1. */ 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 TRUE 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 " ". -*/ -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 " ". + * \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 -1, 0, +1 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 ldif_get_fieldlist() 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 Ldif_FieldRec objects. This list may be + * g_free(). 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 TRUE 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 TRUE 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. + * ============================================================================ + */ diff --git a/src/ldif.h b/src/ldif.h index 822dc545c..e4afb0599 100644 --- a/src/ldif.h +++ b/src/ldif.h @@ -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 @@ -34,15 +34,18 @@ #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__ */ -- 2.25.1