1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 2003-2012 Match Grun and the Claws Mail team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 /*
21  * Export address book to LDIF file.
22  */
23 #ifdef HAVE_CONFIG_H
24 #  include "config.h"
25 #include "claws-features.h"
26 #endif
27 
28 #include <sys/stat.h>
29 #include <dirent.h>
30 #include <errno.h>
31 #include <time.h>
32 #include <string.h>
33 #include <glib.h>
34 #include <glib/gi18n.h>
35 
36 #include "mgutils.h"
37 #include "utils.h"
38 #include "exportldif.h"
39 #include "xmlprops.h"
40 #include "ldif.h"
41 #include "file-utils.h"
42 
43 
44 #ifdef MKDIR_TAKES_ONE_ARG
45 #undef mkdir
46 #define mkdir(a,b) mkdir(a)
47 #endif
48 
49 #define DFL_DIR_CLAWS_OUT  "claws-mail-out"
50 #define DFL_FILE_CLAWS_OUT "addressbook.ldif"
51 
52 #define FMT_BUFSIZE           2048
53 #define XML_BUFSIZE           2048
54 
55 /* Settings - properties */
56 #define EXML_PROPFILE_NAME    "exportldif.xml"
57 #define EXMLPROP_DIRECTORY    "directory"
58 #define EXMLPROP_FILE         "file"
59 #define EXMLPROP_SUFFIX       "suffix"
60 #define EXMLPROP_RDN_INDEX    "rdn"
61 #define EXMLPROP_USE_DN       "use-dn"
62 #define EXMLPROP_EXCL_EMAIL   "exclude-mail"
63 
64 static gchar *_attrName_UID_   = "uid";
65 static gchar *_attrName_DName_ = "cn";
66 static gchar *_attrName_EMail_ = "mail";
67 
68 /**
69  * Create initialized LDIF export control object.
70  * \return Initialized export control data.
71  */
exportldif_create(void)72 ExportLdifCtl *exportldif_create( void ) {
73 	ExportLdifCtl *ctl = g_new0( ExportLdifCtl, 1 );
74 
75 	ctl->path = NULL;
76 	ctl->dirOutput = NULL;
77 	ctl->fileLdif = NULL;
78 	ctl->suffix = NULL;
79 	ctl->rdnIndex = EXPORT_LDIF_ID_UID;
80 	ctl->useDN = FALSE;
81 	ctl->excludeEMail = TRUE;
82 	ctl->retVal = MGU_SUCCESS;
83 	ctl->rcCreate = 0;
84 	ctl->settingsFile = g_strconcat(
85 		get_rc_dir(), G_DIR_SEPARATOR_S, EXML_PROPFILE_NAME, NULL );
86 
87 	return ctl;
88 }
89 
90 /**
91  * Free up object by releasing internal memory.
92  * \return ctl Export control data.
93  */
exportldif_free(ExportLdifCtl * ctl)94 void exportldif_free( ExportLdifCtl *ctl ) {
95 	cm_return_if_fail( ctl != NULL );
96 
97 	g_free( ctl->path );
98 	g_free( ctl->fileLdif );
99 	g_free( ctl->dirOutput );
100 	g_free( ctl->suffix );
101 	g_free( ctl->settingsFile );
102 
103 	/* Clear pointers */
104 	ctl->path = NULL;
105 	ctl->dirOutput = NULL;
106 	ctl->fileLdif = NULL;
107 	ctl->suffix = NULL;
108 	ctl->rdnIndex = EXPORT_LDIF_ID_UID;
109 	ctl->useDN = FALSE;
110 	ctl->excludeEMail = FALSE;
111 	ctl->retVal = MGU_SUCCESS;
112 	ctl->rcCreate = 0;
113 
114 	/* Now release object */
115 	g_free( ctl );
116 }
117 
118 /**
119  * Specify suffix to be used for creating DN entries.
120  * \param ctl   Export control data.
121  * \param value Suffix.
122  */
exportldif_set_suffix(ExportLdifCtl * ctl,const char * value)123 void exportldif_set_suffix( ExportLdifCtl *ctl, const char *value ) {
124 	cm_return_if_fail( ctl != NULL );
125 	ctl->suffix = mgu_replace_string( ctl->suffix, value );
126 	g_strstrip( ctl->suffix );
127 }
128 
129 /**
130  * Specify index of variable to be used for creating RDN entries.
131  * \param ctl   Export control data.
132  * \param value Index to variable, as follows:
133  * <ul>
134  * <li><code>EXPORT_LDIF_ID_UID</code> - Use Claws Mail UID.</li>
135  * <li><code>EXPORT_LDIF_ID_DNAME</code> - Use Claws Mail display name.</li>
136  * <li><code>EXPORT_LDIF_ID_EMAIL</code> - Use first Email address.</li>
137  * </ul>
138  */
exportldif_set_rdn(ExportLdifCtl * ctl,const gint value)139 void exportldif_set_rdn( ExportLdifCtl *ctl, const gint value ) {
140 	cm_return_if_fail( ctl != NULL );
141 	ctl->rdnIndex = value;
142 }
143 
144 /**
145  * Specify that <code>DN</code> attribute, if present, should be used as the
146  * DN for the entry.
147  * \param ctl   Export control data.
148  * \param value <i>TRUE</i> if DN should be used.
149  */
exportldif_set_use_dn(ExportLdifCtl * ctl,const gboolean value)150 void exportldif_set_use_dn( ExportLdifCtl *ctl, const gboolean value ) {
151 	cm_return_if_fail( ctl != NULL );
152 	ctl->useDN = value;
153 }
154 
155 /**
156  * Specify that records without E-Mail addresses should be excluded.
157  * \param ctl   Export control data.
158  * \param value <i>TRUE</i> if records without E-Mail should be excluded.
159  */
exportldif_set_exclude_email(ExportLdifCtl * ctl,const gboolean value)160 void exportldif_set_exclude_email( ExportLdifCtl *ctl, const gboolean value ) {
161 	cm_return_if_fail( ctl != NULL );
162 	ctl->excludeEMail = value;
163 }
164 
165 /**
166  * Format LDAP value name with no embedded commas.
167  * \param  value Data value to format.
168  * \return Formatted string, should be freed after use.
169  */
exportldif_fmt_value(gchar * value)170 static gchar *exportldif_fmt_value( gchar *value ) {
171 	gchar *dupval;
172 	gchar *src;
173 	gchar *dest;
174 	gchar ch;
175 
176 	/* Duplicate incoming value */
177 	dest = dupval = g_strdup( value );
178 
179 	/* Copy characters, ignoring commas */
180 	src = value;
181 	while( *src ) {
182 		ch = *src;
183 		if( ch != ',' ) {
184 			*dest = ch;
185 			dest++;
186 		}
187 		src++;
188 	}
189 	*dest = '\0';
190 	return dupval;
191 }
192 
193 /**
194  * Build DN for entry.
195  * \param  ctl    Export control data.
196  * \param  person Person to format.
197  * \return Formatted DN entry.
198  */
exportldif_fmt_dn(ExportLdifCtl * ctl,const ItemPerson * person)199 static gchar *exportldif_fmt_dn(
200 		ExportLdifCtl *ctl, const ItemPerson *person )
201 {
202 	gchar buf[ FMT_BUFSIZE + 1 ];
203 	gchar *retVal = NULL;
204 	gchar *attr = NULL;
205 	gchar *value = NULL;
206 	gchar *dupval = NULL;
207 
208 	/* Process RDN */
209 	*buf = '\0';
210 	if( ctl->rdnIndex == EXPORT_LDIF_ID_UID ) {
211 		attr = _attrName_UID_;
212 		value = ADDRITEM_ID( person );
213 	}
214 	else if( ctl->rdnIndex == EXPORT_LDIF_ID_DNAME ) {
215 		attr = _attrName_DName_;
216 		value = ADDRITEM_NAME( person );
217 		dupval = exportldif_fmt_value( value );
218 	}
219 	else if( ctl->rdnIndex == EXPORT_LDIF_ID_EMAIL ) {
220 		GList *node;
221 
222 		node = person->listEMail;
223 		if( node ) {
224 			ItemEMail *email = node->data;
225 
226 			attr = _attrName_EMail_;
227 			value = email->address;
228 			dupval = exportldif_fmt_value( value );
229 		}
230 	}
231 
232 	/* Format DN */
233 	if( attr ) {
234 		if( value ) {
235 			if( strlen( value ) > 0 ) {
236 				strncat( buf, attr, FMT_BUFSIZE - strlen(buf) );
237 				strncat( buf, "=", FMT_BUFSIZE - strlen(buf) );
238 				if( dupval ) {
239 					/* Format and free duplicated value */
240 					strncat( buf, dupval, FMT_BUFSIZE - strlen(buf) );
241 					g_free( dupval );
242 				}
243 				else {
244 					/* Use original value */
245 					strncat( buf, value, FMT_BUFSIZE - strlen(buf) );
246 				}
247 
248 				/* Append suffix */
249 				if( ctl->suffix ) {
250 					if( strlen( ctl->suffix ) > 0 ) {
251 						strncat( buf, ",", FMT_BUFSIZE - strlen(buf) );
252 						strncat( buf, ctl->suffix, FMT_BUFSIZE - strlen(buf) );
253 					}
254 				}
255 
256 				retVal = g_strdup( buf );
257 			}
258 		}
259 	}
260 	return retVal;
261 }
262 
263 /**
264  * Find DN by searching attribute list.
265  * \param  ctl    Export control data.
266  * \param  person Person to format.
267  * \return Formatted DN entry, should be freed after use.
268  */
exportldif_find_dn(ExportLdifCtl * ctl,const ItemPerson * person)269 static gchar *exportldif_find_dn(
270 			ExportLdifCtl *ctl, const ItemPerson *person )
271 {
272 	gchar *retVal = NULL;
273 	const GList *node;
274 
275 	node = person->listAttrib;
276 	while( node ) {
277 		UserAttribute *attrib = node->data;
278 
279 		node = g_list_next( node );
280 		if( g_utf8_collate( attrib->name, LDIF_TAG_DN ) == 0 ) {
281 			retVal = g_strdup( attrib->value );
282 			break;
283 		}
284 	}
285 	return retVal;
286 }
287 
288 /**
289  * Format E-Mail entries for person.
290  * \param  person Person to format.
291  * \param  stream Output stream.
292  * \return <i>TRUE</i> if entry formatted.
293  */
exportldif_fmt_email(const ItemPerson * person,FILE * stream)294 static gboolean exportldif_fmt_email( const ItemPerson *person, FILE *stream ) {
295 	gboolean retVal = FALSE;
296 	const GList *node;
297 
298 	node = person->listEMail;
299 	while( node ) {
300 		ItemEMail *email = node->data;
301 
302 		node = g_list_next( node );
303 		ldif_write_value( stream, LDIF_TAG_EMAIL, email->address );
304 		retVal = TRUE;
305 	}
306 	return retVal;
307 }
308 
309 /**
310  * Test for E-Mail entries for person.
311  * \param  person Person to test.
312  * \return <i>TRUE</i> if person has E-Mail address.
313  */
exportldif_test_email(const ItemPerson * person)314 static gboolean exportldif_test_email( const ItemPerson *person )
315 {
316 	gboolean retVal = FALSE;
317 	const GList *node;
318 
319 	node = person->listEMail;
320 	while( node ) {
321 		ItemEMail *email = node->data;
322 
323 		node = g_list_next( node );
324 		if( email->address ) {
325 			if( strlen( email->address ) > 0 ) {
326 				retVal = TRUE;
327 				break;
328 			}
329 		}
330 		retVal = TRUE;
331 	}
332 	return retVal;
333 }
334 
335 /**
336  * Format other attributes for person.
337  * \param person ItemPerson.
338  * \param stream Output stream.
339  */
exportldif_fmt_other_attributes(ItemPerson * person,FILE * stream)340 static void exportldif_fmt_other_attributes(ItemPerson* person, FILE* stream) {
341     UserAttribute* attr;
342     GList* attrList = NULL;
343     gchar* attrib;
344 
345     if (! person)
346         return;
347     debug_print("cn: %s\n-----------------------------\n", ADDRITEM_NAME(person));
348     attrList = person->listAttrib;
349     while (attrList) {
350         attr = (UserAttribute *) attrList->data;
351         if (attr->uid) {
352             /* Native address book which does not conform to
353              * the LDAP schemas
354              */
355             attrib = g_strdup_printf("# %s", attr->name);
356         }
357         else {
358             attrib = g_strdup(attr->name);
359         }
360         debug_print("name: %s\nvalue: %s\n", attrib, attr->value);
361         ldif_write_value(stream, attrib, attr->value);
362         g_free(attrib);
363         attrList = g_list_next(attrList);
364     }
365     debug_print("-------------------------------\n");
366 }
367 
368 /**
369  * Find persons displayName.
370  * \param person ItemPerson.
371  * \return displayName.
372  */
exportldif_find_displayName(ItemPerson * person)373 static gchar* exportldif_find_displayName(ItemPerson* person) {
374 	gchar* displayName;
375 
376 	if (! person)
377 	    return NULL;
378 
379 	if (person->nickName && strlen(person->nickName) > 0)
380 		displayName = g_strdup(person->nickName);
381 	else
382 		displayName = g_strdup(ADDRITEM_NAME(person));
383 	return displayName;
384 }
385 
386 /**
387  * Format persons in an address book folder.
388  * \param  ctl    Export control data.
389  * \param  stream Output stream.
390  * \param  folder Folder to format.
391  * \return <i>TRUE</i> if no persons were formatted.
392  */
exportldif_fmt_person(ExportLdifCtl * ctl,FILE * stream,const ItemFolder * folder)393 static gboolean exportldif_fmt_person(
394 		ExportLdifCtl *ctl, FILE *stream, const ItemFolder *folder )
395 {
396 	gboolean retVal = TRUE;
397 	const GList *node;
398 	gchar* sn = NULL;
399 	gchar* displayName = NULL;
400 
401 	if( folder->listPerson == NULL ) return retVal;
402 
403 	node = folder->listPerson;
404 	while( node ) {
405 		AddrItemObject *aio = node->data;
406 		node = g_list_next( node );
407 
408 		if( aio && aio->type == ITEMTYPE_PERSON ) {
409 			ItemPerson *person = ( ItemPerson * ) aio;
410 			gboolean classPerson = FALSE;
411 			gboolean classInetP = FALSE;
412 			gchar *dn = NULL;
413 
414 			/* Check for E-Mail */
415 			if( exportldif_test_email( person ) ) {
416 				classInetP = TRUE;
417 			}
418 			else {
419 				/* Bail if no E-Mail address */
420 				if( ctl->excludeEMail ) continue;
421 			}
422 
423 			/* Format DN */
424 			if( ctl->useDN ) {
425 				dn = exportldif_find_dn( ctl, person );
426 			}
427 			if( dn == NULL ) {
428 				dn = exportldif_fmt_dn( ctl, person );
429 			}
430 			if( dn == NULL ) continue;
431 			ldif_write_value( stream, LDIF_TAG_DN, dn );
432 			g_free( dn );
433 
434 			/*
435 			 * Test for schema requirements. This is a simple
436 			 * test and does not trap all LDAP schema errors.
437 			 * These can be detected when the LDIF file is
438 			 * loaded into an LDAP server.
439 			 */
440 			if( person->lastName ) {
441 				if( strlen( person->lastName ) > 0 ) {
442 					classPerson = TRUE;
443 					classInetP = TRUE;
444 				}
445 			}
446 
447 			if( classPerson ) {
448 				ldif_write_value( stream,
449 					LDIF_TAG_OBJECTCLASS, LDIF_CLASS_PERSON );
450 			}
451 			if( classInetP ) {
452 				ldif_write_value( stream,
453 					LDIF_TAG_OBJECTCLASS, LDIF_CLASS_INET_PERSON );
454 			}
455 
456 			/* Format person attributes */
457 			ldif_write_value(
458 				stream, LDIF_TAG_COMMONNAME, ADDRITEM_NAME( person ) );
459 			sn = g_strdup(person->lastName);
460 			if (classPerson || classInetP) {
461 				if(! sn || strcmp("", sn) == 0 || strcmp(" ", sn) == 0) {
462 					g_free(sn);
463 					sn = g_strdup("Some SN");
464 				}
465 			}
466 			ldif_write_value(
467 				stream, LDIF_TAG_LASTNAME, sn );
468 			g_free(sn);
469 			sn = NULL;
470 			ldif_write_value(
471 				stream, LDIF_TAG_FIRSTNAME, person->firstName );
472 
473 			if (! person->externalID)
474 				displayName = exportldif_find_displayName(person);
475 			else
476 				displayName = g_strdup(person->nickName);
477 			ldif_write_value(stream, LDIF_TAG_NICKNAME, displayName);
478 			g_free(displayName);
479 			displayName = NULL;
480 
481 			/* Format E-Mail */
482 			exportldif_fmt_email( person, stream );
483 
484 			/* Handle other attributes */
485 			exportldif_fmt_other_attributes(person, stream);
486 
487 			/* End record */
488 			ldif_write_eor( stream );
489 
490 			retVal = FALSE;
491 		}
492 	}
493 
494 	return retVal;
495 }
496 
497 /**
498  * Format an address book folder.
499  * \param  ctl    Export control data.
500  * \param  stream Output stream.
501  * \param  folder Folder to format.
502  * \return <i>TRUE</i> if no persons were formatted.
503  */
exportldif_fmt_folder(ExportLdifCtl * ctl,FILE * stream,const ItemFolder * folder)504 static void exportldif_fmt_folder(
505 		ExportLdifCtl *ctl, FILE *stream, const ItemFolder *folder )
506 {
507 	const GList *node;
508 
509 	/* Export entries in this folder */
510 	exportldif_fmt_person( ctl, stream, folder );
511 
512 	/* Export entries in sub-folders */
513 	node = folder->listFolder;
514 	while( node ) {
515 		AddrItemObject *aio = node->data;
516 
517 		node = g_list_next( node );
518 		if( aio && aio->type == ITEMTYPE_FOLDER ) {
519 			ItemFolder *subFolder = ( ItemFolder * ) aio;
520 			exportldif_fmt_folder( ctl, stream, subFolder );
521 		}
522 	}
523 }
524 
525 /**
526  * Export address book to LDIF file.
527  * \param  ctl   Export control data.
528  * \param  cache Address book/data source cache.
529  * \return Status.
530  */
exportldif_process(ExportLdifCtl * ctl,AddressCache * cache)531 void exportldif_process( ExportLdifCtl *ctl, AddressCache *cache )
532 {
533 	ItemFolder *rootFolder;
534 	FILE *ldifFile;
535 
536 	ldifFile = claws_fopen( ctl->path, "wb" );
537 	if( ! ldifFile ) {
538 		/* Cannot open file */
539 		ctl->retVal = MGU_OPEN_FILE;
540 		return;
541 	}
542 
543 	rootFolder = cache->rootFolder;
544 	exportldif_fmt_folder( ctl, ldifFile, rootFolder );
545 	claws_safe_fclose( ldifFile );
546 	ctl->retVal = MGU_SUCCESS;
547 }
548 
549 /**
550  * Build full export file specification.
551  * \param ctl  Export control data.
552  */
exportldif_build_filespec(ExportLdifCtl * ctl)553 static void exportldif_build_filespec( ExportLdifCtl *ctl ) {
554 	gchar *fileSpec;
555 
556 	fileSpec = g_strconcat(
557 		ctl->dirOutput, G_DIR_SEPARATOR_S, ctl->fileLdif, NULL );
558 	ctl->path = mgu_replace_string( ctl->path, fileSpec );
559 	g_free( fileSpec );
560 }
561 
562 /**
563  * Parse directory and filename from full export file specification.
564  * \param ctl      Export control data.
565  * \param fileSpec File spec.
566  */
exportldif_parse_filespec(ExportLdifCtl * ctl,gchar * fileSpec)567 void exportldif_parse_filespec( ExportLdifCtl *ctl, gchar *fileSpec ) {
568 	gchar *t;
569 	gchar *base = g_path_get_basename(fileSpec);
570 
571 	ctl->fileLdif =
572 		mgu_replace_string( ctl->fileLdif, base );
573 	g_free(base);
574 	t = g_path_get_dirname( fileSpec );
575 	ctl->dirOutput = mgu_replace_string( ctl->dirOutput, t );
576 	g_free( t );
577 	ctl->path = mgu_replace_string( ctl->path, fileSpec );
578 }
579 
580 /**
581  * Create output directory.
582  * \param  ctl Export control data.
583  * \return TRUE if directory created.
584  */
exportldif_create_dir(ExportLdifCtl * ctl)585 gboolean exportldif_create_dir( ExportLdifCtl *ctl ) {
586 	gboolean retVal = FALSE;
587 
588 	ctl->rcCreate = 0;
589 	if( mkdir( ctl->dirOutput, S_IRWXU ) == 0 ) {
590 		retVal = TRUE;
591 	}
592 	else {
593 		ctl->rcCreate = errno;
594 	}
595 	return retVal;
596 }
597 
598 /**
599  * Retrieve create directory error message.
600  * \param  ctl Export control data.
601  * \return Message.
602  */
exportldif_get_create_msg(ExportLdifCtl * ctl)603 gchar *exportldif_get_create_msg( ExportLdifCtl *ctl ) {
604 	gchar *msg;
605 
606 	if( ctl->rcCreate == EEXIST ) {
607 		msg = _( "Name already exists but is not a directory." );
608 	}
609 	else if( ctl->rcCreate == EACCES ) {
610 		msg = _( "No permissions to create directory." );
611 	}
612 	else if( ctl->rcCreate == ENAMETOOLONG ) {
613 		msg = _( "Name is too long." );
614 	}
615 	else {
616 		msg = _( "Not specified." );
617 	}
618 	return msg;
619 }
620 
621 /**
622  * Set default values.
623  * \param  ctl Export control data.
624  */
exportldif_default_values(ExportLdifCtl * ctl)625 static void exportldif_default_values( ExportLdifCtl *ctl ) {
626 	gchar *str;
627 
628 	str = g_strconcat(
629 		get_home_dir(), G_DIR_SEPARATOR_S,
630 		DFL_DIR_CLAWS_OUT, NULL );
631 
632 	ctl->dirOutput = mgu_replace_string( ctl->dirOutput, str );
633 	g_free( str );
634 
635 	ctl->fileLdif =
636 		mgu_replace_string( ctl->fileLdif, DFL_FILE_CLAWS_OUT );
637 	ctl->suffix = mgu_replace_string( ctl->suffix, "" );
638 
639 	ctl->rdnIndex = EXPORT_LDIF_ID_UID;
640 	ctl->useDN = FALSE;
641 	ctl->retVal = MGU_SUCCESS;
642 }
643 
644 /**
645  * Load settings from XML properties file.
646  * \param  ctl Export control data.
647  */
exportldif_load_settings(ExportLdifCtl * ctl)648 void exportldif_load_settings( ExportLdifCtl *ctl ) {
649 	XmlProperty *props;
650 	gint rc;
651 	gchar buf[ XML_BUFSIZE ];
652 
653 	props = xmlprops_create();
654 	xmlprops_set_path( props, ctl->settingsFile );
655 	rc = xmlprops_load_file( props );
656 	if( rc == 0 ) {
657 		/* Read settings */
658 		*buf = '\0';
659 		xmlprops_get_property_s( props, EXMLPROP_DIRECTORY, buf );
660 		ctl->dirOutput = mgu_replace_string( ctl->dirOutput, buf );
661 
662 		*buf = '\0';
663 		xmlprops_get_property_s( props, EXMLPROP_FILE, buf );
664 		ctl->fileLdif = mgu_replace_string( ctl->fileLdif, buf );
665 
666 		*buf = '\0';
667 		xmlprops_get_property_s( props, EXMLPROP_SUFFIX, buf );
668 		ctl->suffix = mgu_replace_string( ctl->suffix, buf );
669 
670 		ctl->rdnIndex =
671 			xmlprops_get_property_i( props, EXMLPROP_RDN_INDEX );
672 		ctl->useDN =
673 			xmlprops_get_property_b( props, EXMLPROP_USE_DN );
674 		ctl->excludeEMail =
675 			xmlprops_get_property_b( props, EXMLPROP_EXCL_EMAIL );
676 	}
677 	else {
678 		/* Set default values */
679 		exportldif_default_values( ctl );
680 	}
681 	exportldif_build_filespec( ctl );
682 	/* exportldif_print( ctl, stdout ); */
683 
684 	xmlprops_free( props );
685 }
686 
687 /**
688  * Save settings to XML properties file.
689  * \param  ctl Export control data.
690  */
exportldif_save_settings(ExportLdifCtl * ctl)691 void exportldif_save_settings( ExportLdifCtl *ctl ) {
692 	XmlProperty *props;
693 
694 	props = xmlprops_create();
695 	xmlprops_set_path( props, ctl->settingsFile );
696 
697 	xmlprops_set_property( props, EXMLPROP_DIRECTORY, ctl->dirOutput );
698 	xmlprops_set_property( props, EXMLPROP_FILE, ctl->fileLdif );
699 	xmlprops_set_property( props, EXMLPROP_SUFFIX, ctl->suffix );
700 	xmlprops_set_property_i( props, EXMLPROP_RDN_INDEX, ctl->rdnIndex );
701 	xmlprops_set_property_b( props, EXMLPROP_USE_DN, ctl->useDN );
702 	xmlprops_set_property_b( props, EXMLPROP_EXCL_EMAIL, ctl->excludeEMail );
703 	if (xmlprops_save_file( props ) != MGU_SUCCESS)
704 		g_warning("can't save settings");
705 	xmlprops_free( props );
706 }
707 
708 /*
709  * ============================================================================
710  * End of Source.
711  * ============================================================================
712  */
713 
714 
715