/*
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 2001 Match Grun
+ * Copyright (C) 2001-2012 Match Grun and the Claws Mail team
*
* 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* 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.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
*/
/*
- * Functions necessary to access LDIF files (LDAP Data Interchange Format files).
+ * Functions necessary to access LDIF files (LDAP Data Interchange Format
+ * files).
*/
-#include <sys/stat.h>
#include <glib.h>
+#include <glib/gi18n.h>
+#include <string.h>
+#include <sys/stat.h>
#include "mgutils.h"
#include "ldif.h"
#include "addritem.h"
#include "addrcache.h"
-/*
-* Create new cardfile object.
-*/
+#include "utils.h"
+
+#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 );
ldifFile->path = NULL;
ldifFile->file = NULL;
- ldifFile->bufptr = ldifFile->buffer;
+ ldifFile->hashFields = g_hash_table_new( g_str_hash, g_str_equal );
+ ldifFile->tempList = NULL;
+ ldifFile->dirtyFlag = TRUE;
+ ldifFile->accessFlag = FALSE;
ldifFile->retVal = MGU_SUCCESS;
+ ldifFile->cbProgress = NULL;
+ ldifFile->importCount = 0;
return ldifFile;
}
-/*
-* Properties...
-*/
-void ldif_set_file( LdifFile* ldifFile, const gchar *value ) {
- g_return_if_fail( ldifFile != NULL );
+/**
+ * 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 ) {
+ cm_return_if_fail( ldifFile != NULL );
+
+ if( ldifFile->path ) {
+ if( strcmp( ldifFile->path, value ) != 0 )
+ ldifFile->dirtyFlag = TRUE;
+ }
+ else {
+ ldifFile->dirtyFlag = TRUE;
+ }
ldifFile->path = mgu_replace_string( ldifFile->path, value );
g_strstrip( ldifFile->path );
+ ldifFile->importCount = 0;
}
-/*
-* Free up cardfile object by releasing internal memory.
+/**
+ * Set the file access indicator.
+ * \param ldifFile LDIF import control object.
+ * \param value File specification.
+ */
+void ldif_set_accessed( LdifFile *ldifFile, const gboolean value ) {
+ cm_return_if_fail( ldifFile != NULL );
+ ldifFile->accessFlag = value;
+}
+
+/**
+ * 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;
+ rec->reserved = FALSE;
+ rec->selected = FALSE;
+ return rec;
+}
+
+/**
+ * Free field record object.
+ * \param rec LDIF field object.
+ */
+static void ldif_free_fieldrec( Ldif_FieldRec *rec ) {
+ if( rec ) {
+ g_free( rec->tagName );
+ g_free( rec->userName );
+ rec->tagName = NULL;
+ rec->userName = NULL;
+ rec->reserved = FALSE;
+ rec->selected = FALSE;
+ g_free( rec );
+ }
+}
+
+/**
+ * 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 ) {
+ cm_return_if_fail( rec != NULL );
+
+ if( ! rec->reserved ) {
+ rec->userName = mgu_replace_string( rec->userName, value );
+ g_strstrip( rec->userName );
+ }
+}
+
+/**
+ * Specify selection for field record.
+ * \param rec LDIF field object.
+ * \param value Set to <i>TRUE</i> to select field. Note that reserved
+ * fields cannot be unselected.
+ */
+void ldif_field_set_selected( Ldif_FieldRec *rec, const gboolean value ) {
+ cm_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 ) {
+ cm_return_if_fail( rec != NULL );
+
+ if( ! rec->reserved ) {
+ rec->selected = !rec->selected;
+ }
+}
+
+/**
+ * Free hash table entry visitor function.
+ * \param key Key.
+ * \param value Value (the LDIF field record).
+ * \param data User data.
+ * \return <code>-1</code>.
*/
+static gint ldif_hash_free_vis( gpointer key, gpointer value, gpointer data ) {
+ ldif_free_fieldrec( ( Ldif_FieldRec * ) value );
+ return -1;
+}
+
+/**
+ * Free up object by releasing internal memory.
+ * \param ldifFile LDIF import control object.
+ */
void ldif_free( LdifFile *ldifFile ) {
- g_return_if_fail( ldifFile != NULL );
+ cm_return_if_fail( ldifFile != NULL );
/* Close file */
if( ldifFile->file ) fclose( ldifFile->file );
/* Free internal stuff */
g_free( ldifFile->path );
+ /* Free field list */
+ g_hash_table_foreach_remove( ldifFile->hashFields, ldif_hash_free_vis, NULL );
+ g_hash_table_destroy( ldifFile->hashFields );
+ ldifFile->hashFields = NULL;
+
/* Clear pointers */
ldifFile->file = NULL;
ldifFile->path = NULL;
ldifFile->retVal = MGU_SUCCESS;
+ ldifFile->tempList = NULL;
+ ldifFile->dirtyFlag = FALSE;
+ ldifFile->accessFlag = FALSE;
+ ldifFile->cbProgress = NULL;
/* Now release file object */
g_free( ldifFile );
-
-}
-
-/*
-* Display object to specified stream.
-*/
-void ldif_print_file( LdifFile *ldifFile, FILE *stream ) {
- g_return_if_fail( ldifFile != NULL );
- fprintf( stream, "LDIF File:\n" );
- fprintf( stream, "file spec: '%s'\n", ldifFile->path );
- fprintf( stream, " ret val: %d\n", ldifFile->retVal );
}
-/*
-* Open file for read.
-* return: TRUE if file opened successfully.
-*/
+/**
+ * Open file for read.
+ * \param ldifFile LDIF import control object.
+ * \return <i>TRUE</i> if file opened successfully.
+ */
static gint ldif_open_file( LdifFile* ldifFile ) {
- /* printf( "Opening file\n" ); */
+ /* g_print( "Opening file\n" ); */
if( ldifFile->path ) {
- ldifFile->file = fopen( ldifFile->path, "r" );
+ ldifFile->file = g_fopen( ldifFile->path, "rb" );
if( ! ldifFile->file ) {
- /* printf( "can't open %s\n", ldifFile->path ); */
+ /* g_print( "can't open %s\n", ldifFile->path ); */
ldifFile->retVal = MGU_OPEN_FILE;
return ldifFile->retVal;
}
}
else {
- /* printf( "file not specified\n" ); */
+ /* g_print( "file not specified\n" ); */
ldifFile->retVal = MGU_NO_FILE;
return ldifFile->retVal;
}
/* Setup a buffer area */
- ldifFile->buffer[0] = '\0';
- ldifFile->bufptr = ldifFile->buffer;
ldifFile->retVal = MGU_SUCCESS;
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 );
+ cm_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 ];
- gchar ch;
- gchar *ptr;
-
- if( feof( ldifFile->file ) ) return NULL;
+ gchar *buf = g_malloc(LDIFBUFSIZE);
+ gint ch;
+ int i = 0;
+ int cur_alloc = LDIFBUFSIZE;
+
+ if( feof( ldifFile->file ) ) {
+ g_free(buf);
+ return NULL;
+ }
- ptr = buf;
- while( TRUE ) {
- *ptr = '\0';
+ while( i < cur_alloc-1 ) {
ch = fgetc( ldifFile->file );
+ if (ferror( ldifFile->file ))
+ ldifFile->retVal = MGU_ERROR_READ;
if( ch == '\0' || ch == EOF ) {
- if( *buf == '\0' ) return NULL;
+ if( i == 0 ) return NULL;
break;
}
- if( ch == '\n' ) break;
- *ptr = ch;
- ptr++;
+#if HAVE_DOSISH_SYSTEM
+#else
+ if( ch == '\r' )
+ continue;
+#endif
+ if( ch == '\n' )
+ break;
+ buf[i] = ch;
+ i++;
+ if (i == cur_alloc-1 && cur_alloc < LDIFBUFSIZE * 32) {
+ cur_alloc += LDIFBUFSIZE;
+ buf = g_realloc(buf, cur_alloc);
+ }
}
+ buf[i] = '\0';
- /* Copy into private buffer */
+ /* Return a copy of buffer */
return g_strdup( buf );
}
-/*
-* Parse tag name from line buffer.
-* Return: Buffer containing the tag name, or NULL if no delimiter char found.
-*/
-static gchar *ldif_get_tagname( char* line, gchar dlm ) {
+/**
+ * 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;
gchar *lptr = line;
+ gchar *sptr = NULL;
+
while( *lptr++ ) {
- if( *lptr == dlm ) {
- len = lptr - line;
+ /* Check for language tag */
+ if( *lptr == LDIF_LANG_TAG ) {
+ if( sptr == NULL ) sptr = lptr;
+ }
+
+ /* Check for delimiter */
+ if( *lptr == LDIF_SEP_TAG ) {
+ if( sptr ) {
+ len = sptr - line;
+ }
+ else {
+ len = lptr - line;
+ }
+
+ /* Base-64 encoding? */
+ if( * ++lptr == LDIF_SEP_TAG ) *flag64 = TRUE;
+
tag = g_strndup( line, len+1 );
tag[ len ] = '\0';
- g_strdown( tag );
- return tag;
+ return tag;
}
}
return tag;
}
-/*
-* Parse tag value from 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 dlm ) {
+/**
+ * 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;
gchar *lptr;
gint len = 0;
for( lptr = line; *lptr; lptr++ ) {
- if( *lptr == dlm ) {
+ if( *lptr == LDIF_SEP_TAG ) {
if( ! start )
start = lptr + 1;
}
}
if( start ) {
+ if( *start == LDIF_SEP_TAG ) start++;
len = lptr - start;
value = g_strndup( start, len+1 );
+ g_strstrip( value );
}
else {
/* Ensure that we get an empty string */
return value;
}
-/*
-* Dump linked lists of character strings (for debug).
-*/
-static void ldif_dump_lists( GSList *listName, GSList *listAddr, GSList *listRem, GSList *listID, FILE *stream ) {
- fprintf( stream, "dump name\n" );
- fprintf( stream, "------------\n" );
- mgu_print_list( listName, stdout );
- fprintf( stream, "dump address\n" );
- fprintf( stream, "------------\n" );
- mgu_print_list( listAddr, stdout );
- fprintf( stream, "dump remarks\n" );
- fprintf( stdout, "------------\n" );
- mgu_print_list( listRem, stdout );
- fprintf( stream, "dump id\n" );
- fprintf( stdout, "------------\n" );
- mgu_print_list( listID, stdout );
-}
-
+/**
+ * Parsed address data record.
+ */
typedef struct _Ldif_ParsedRec_ Ldif_ParsedRec;
struct _Ldif_ParsedRec_ {
GSList *listCName;
GSList *listNName;
GSList *listAddress;
GSList *listID;
+ GSList *userAttr;
};
-/*
-* Build an address list entry and append to list of address items. Name is formatted
-* as "<first-name> <last-name>".
-*/
-static void ldif_build_items( LdifFile *ldifFile, Ldif_ParsedRec *rec, AddressCache *cache ) {
+/**
+ * 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 in the
+ * address cache. Name is formatted as "<first-name> <last-name>".
+ * \param ldifFile LDIF import control object.
+ * \param rec LDIF field object.
+ * \param cache Address cache to be populated with data.
+ */
+static void ldif_build_items(
+ LdifFile *ldifFile, Ldif_ParsedRec *rec, AddressCache *cache )
+{
GSList *nodeFirst;
GSList *nodeAddress;
- gchar *firstName = NULL, *lastName = NULL, *fullName = NULL, *nickName = NULL;
+ GSList *nodeAttr;
+ gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
+ gchar *nickName = NULL;
gint iLen = 0, iLenT = 0;
ItemPerson *person;
ItemEMail *email;
nodeAddress = rec->listAddress;
- if( nodeAddress == NULL ) return;
+// if( nodeAddress == NULL ) return;
/* Find longest first name in list */
nodeFirst = rec->listFName;
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 );
fullName = g_strdup_printf( "%s", lastName );
}
}
+
+ if (!fullName || strlen(fullName) == 0) {
+ g_free(fullName);
+ fullName = NULL;
+ if (rec->listCName)
+ fullName = g_strdup(rec->listCName->data);
+ }
+
if( fullName ) {
g_strchug( fullName ); g_strchomp( fullName );
}
addritem_person_set_nick_name( person, nickName );
addrcache_id_person( cache, person );
addrcache_add_person( cache, person );
+ ++ldifFile->importCount;
/* Add address item */
while( nodeAddress ) {
g_free( fullName );
fullName = firstName = lastName = NULL;
+ /* Add user attributes */
+ nodeAttr = rec->userAttr;
+ while( nodeAttr ) {
+ Ldif_UserAttr *attr = nodeAttr->data;
+ UserAttribute *attrib = addritem_create_attribute();
+ addritem_attrib_set_name( attrib, attr->name );
+ addritem_attrib_set_value( attrib, attr->value );
+ addritem_person_add_attribute( person, attrib );
+ nodeAttr = g_slist_next( nodeAttr );
+ }
+ nodeAttr = NULL;
+}
+
+/**
+ * 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->selected ) return;
+
+ name = fld->tagName;
+ if( fld->userName ) {
+ name = fld->userName;
+ }
+ attr = g_new0( Ldif_UserAttr, 1 );
+ attr->name = g_strdup( name );
+ attr->value = g_strdup( tagValue );
+ rec->userAttr = g_slist_append( rec->userAttr, attr );
+ }
}
-static void ldif_add_value( Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue ) {
+/**
+ * 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 );
- g_strdown( nm );
+ nm = g_utf8_strdown( tagName, -1 );
if( tagValue ) {
val = g_strdup( tagValue );
}
val = g_strdup( "" );
}
g_strstrip( val );
- if( strcmp( nm, LDIF_TAG_COMMONNAME ) == 0 ) {
+
+ if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_COMMONNAME, -1 ) ) == 0 ) {
rec->listCName = g_slist_append( rec->listCName, val );
}
- else if( strcmp( nm, LDIF_TAG_FIRSTNAME ) == 0 ) {
+ else if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_FIRSTNAME, -1 ) ) == 0 ) {
rec->listFName = g_slist_append( rec->listFName, val );
}
- else if( strcmp( nm, LDIF_TAG_LASTNAME ) == 0 ) {
+ else if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_LASTNAME, -1 ) ) == 0 ) {
rec->listLName = g_slist_append( rec->listLName, val );
}
- else if( strcmp( nm, LDIF_TAG_NICKNAME ) == 0 ) {
+ else if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_NICKNAME, -1 ) ) == 0 ) {
rec->listNName = g_slist_append( rec->listNName, val );
}
- else if( strcmp( nm, LDIF_TAG_EMAIL ) == 0 ) {
+ else if( g_utf8_collate( nm, g_utf8_strdown( LDIF_TAG_EMAIL, -1 ) ) == 0 ) {
rec->listAddress = g_slist_append( rec->listAddress, val );
}
+ else {
+ /* Add field as user attribute */
+ ldif_add_user_attr( rec, tagName, tagValue, hashField );
+ }
g_free( nm );
}
+/**
+ * Clear parsed data record.
+ * \param rec LDIF field object.
+ */
static void ldif_clear_rec( Ldif_ParsedRec *rec ) {
+ GSList *list;
+
+ /* Free up user attributes */
+ list = rec->userAttr;
+ while( list ) {
+ Ldif_UserAttr *attr = list->data;
+ g_free( attr->name );
+ g_free( attr->value );
+ g_free( attr );
+ list = g_slist_next( list );
+ }
+ g_slist_free( rec->userAttr );
+
g_slist_free( rec->listCName );
g_slist_free( rec->listFName );
g_slist_free( rec->listLName );
g_slist_free( rec->listNName );
g_slist_free( rec->listAddress );
g_slist_free( rec->listID );
+
+ rec->userAttr = NULL;
rec->listCName = NULL;
rec->listFName = NULL;
rec->listLName = NULL;
rec->listID = NULL;
}
-#if 0
-static void ldif_print_record( Ldif_ParsedRec *rec, FILE *stream ) {
- fprintf( stdout, "LDIF Parsed Record:\n" );
- fprintf( stdout, "common name:" );
- mgu_print_list( rec->listCName, stdout );
- if( ! rec->listCName ) fprintf( stdout, "\n" );
- fprintf( stdout, "first name:" );
- mgu_print_list( rec->listFName, stdout );
- if( ! rec->listFName ) fprintf( stdout, "\n" );
- fprintf( stdout, "last name:" );
- mgu_print_list( rec->listLName, stdout );
- if( ! rec->listLName ) fprintf( stdout, "\n" );
- fprintf( stdout, "nick name:" );
- mgu_print_list( rec->listNName, stdout );
- if( ! rec->listNName ) fprintf( stdout, "\n" );
- fprintf( stdout, "address:" );
- mgu_print_list( rec->listAddress, stdout );
- if( ! rec->listAddress ) fprintf( stdout, "\n" );
- fprintf( stdout, "id:" );
- mgu_print_list( rec->listID, stdout );
- if( ! rec->listID ) fprintf( stdout, "\n" );
-}
-#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;
GSList *listValue = NULL;
gboolean flagEOF = FALSE, flagEOR = FALSE;
+ gboolean flag64 = FALSE, last64 = FALSE;
Ldif_ParsedRec *rec;
+ long posEnd = 0L;
+ long posCur = 0L;
+ GHashTable *hashField;
+ gsize len;
+ hashField = ldifFile->hashFields;
rec = g_new0( Ldif_ParsedRec, 1 );
ldif_clear_rec( rec );
+ /* Find EOF for progress indicator */
+ fseek( ldifFile->file, 0L, SEEK_END );
+ posEnd = ftell( ldifFile->file );
+ fseek( ldifFile->file, 0L, SEEK_SET );
+
while( ! flagEOF ) {
gchar *line = ldif_get_line( ldifFile );
+
+ posCur = ftell( ldifFile->file );
+ if( ldifFile->cbProgress ) {
+ /* Call progress indicator */
+ ( ldifFile->cbProgress ) ( ldifFile, & posEnd, & posCur );
+ }
+
+ flag64 = FALSE;
if( line == NULL ) {
flagEOF = flagEOR = TRUE;
}
if( lastTag ) {
/* Save record */
fullValue = mgu_list_coalesce( listValue );
- ldif_add_value( rec, lastTag, fullValue );
+ if (fullValue && last64) {
+ gchar *tmp = g_base64_decode_zero(fullValue, &len);
+ g_free(fullValue);
+ fullValue = tmp;
+ }
+
+ ldif_add_value( rec, lastTag, fullValue, hashField );
/* ldif_print_record( rec, stdout ); */
ldif_build_items( ldifFile, rec, cache );
ldif_clear_rec( rec );
g_free( lastTag );
mgu_free_list( listValue );
+ g_free(fullValue);
lastTag = NULL;
listValue = NULL;
+ last64 = FALSE;
}
}
if( line ) {
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 binary encode field */
- listValue = g_slist_append( listValue, g_strdup( line ) );
+ /* Base-64 encoded continuation field */
+ listValue = g_slist_append(
+ listValue, g_strdup( line ) );
}
else {
/* Parse line */
- tagName = ldif_get_tagname( line, LDIF_SEP_TAG );
+ tagName = ldif_get_tagname( line, &flag64 );
if( tagName ) {
- tagValue = ldif_get_tagvalue( line, LDIF_SEP_TAG );
+ tagValue = ldif_get_tagvalue( line );
if( tagValue ) {
if( lastTag ) {
/* Save data */
- fullValue = mgu_list_coalesce( listValue );
- ldif_add_value( rec, lastTag, fullValue );
+ fullValue =
+ mgu_list_coalesce( listValue );
+ if (fullValue && last64) {
+ gchar *tmp = g_base64_decode_zero(fullValue, &len);
+ g_free(fullValue);
+ fullValue = tmp;
+ }
+ /* Base-64 encoded data */
+ /*
+ if( last64 ) {
+ ldif_dump_b64( fullValue );
+ }
+ */
+
+ ldif_add_value(
+ rec, lastTag, fullValue,
+ hashField );
g_free( lastTag );
mgu_free_list( listValue );
lastTag = NULL;
}
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;
}
g_free( tagName );
}
}
}
-
+ g_free( line );
}
/* Release data */
g_free( rec );
g_free( lastTag );
mgu_free_list( listValue );
+}
+/**
+ * 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;
+
+ /* mgu_print_list( list, stdout ); */
+ while( node ) {
+ gchar *tag = node->data;
+ if( ! g_hash_table_lookup( table, tag ) ) {
+ Ldif_FieldRec *rec = NULL;
+ gchar *key = g_utf8_strdown( tag, -1 );
+
+ rec = ldif_create_fieldrec( tag );
+ if( g_utf8_collate( key, LDIF_TAG_DN ) == 0 ) {
+ rec->reserved = rec->selected = TRUE;
+ rec->userName = g_strdup( "dn" );
+ }
+ else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_COMMONNAME, -1 ) ) == 0 ) {
+ rec->reserved = rec->selected = TRUE;
+ rec->userName = g_strdup( _( "Display Name" ) );
+ }
+ else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_FIRSTNAME, -1 ) ) == 0 ) {
+ rec->reserved = rec->selected = TRUE;
+ rec->userName = g_strdup( _( "First Name" ) );
+ }
+ else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_LASTNAME, -1 ) ) == 0 ) {
+ rec->reserved = rec->selected = TRUE;
+ rec->userName = g_strdup( _( "Last Name" ) );
+ }
+ else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_NICKNAME, -1 ) ) == 0 ) {
+ rec->reserved = rec->selected = TRUE;
+ rec->userName = g_strdup( _( "Nick Name" ) );
+ }
+ else if( g_utf8_collate( key, g_utf8_strdown( LDIF_TAG_EMAIL, -1 ) ) == 0 ) {
+ rec->reserved = rec->selected = TRUE;
+ rec->userName = g_strdup( _( "Email Address" ) );
+ }
+ g_hash_table_insert( table, key, rec );
+ }
+ node = g_slist_next( node );
+ }
+}
+
+/**
+ * Sorted list comparison function.
+ * \param ptr1 First field.
+ * \param ptr2 Second field.
+ * \return <code>-1, 0, +1</code> if first record less than, equal,
+ * greater than second.
+ */
+static gint ldif_field_compare( gconstpointer ptr1, gconstpointer ptr2 ) {
+ const Ldif_FieldRec *rec1 = ptr1;
+ const Ldif_FieldRec *rec2 = ptr2;
+
+ if( rec1->reserved ) {
+ if( ! rec2->reserved ) {
+ return +1;
+ }
+ }
+ else {
+ if( rec2->reserved ) {
+ return -1;
+ }
+ }
+ return g_utf8_collate( rec1->tagName, rec2->tagName );
}
/*
-* ============================================================================================
-* Read file into list. Main entry point
-* Enter: ldifFile LDIF control data.
-* cache Address cache to load.
-* Return: Status code.
-* ============================================================================================
-*/
+ * 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 );
+}
+
+/**
+ * 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;
+ gboolean flagEOF = FALSE, flagEOR = FALSE, flagMail = FALSE;
+ gboolean flag64 = FALSE;
+ long posEnd = 0L;
+ long posCur = 0L;
+
+ /* Clear hash table */
+ g_hash_table_foreach_remove(
+ ldifFile->hashFields, ldif_hash_free_vis, NULL );
+
+ /* Find EOF for progress indicator */
+ fseek( ldifFile->file, 0L, SEEK_END );
+ posEnd = ftell( ldifFile->file );
+ fseek( ldifFile->file, 0L, SEEK_SET );
+
+ if (posEnd == 0) {
+ ldifFile->retVal = MGU_EOF;
+ return;
+ }
+
+ /* Process file */
+ while( ! flagEOF ) {
+ gchar *line = ldif_get_line( ldifFile );
+ posCur = ftell( ldifFile->file );
+ if( ldifFile->cbProgress ) {
+ /* Call progress indicator */
+ ( ldifFile->cbProgress ) ( ldifFile, & posEnd, & posCur );
+ }
+
+ flag64 = FALSE;
+ if( line == NULL ) {
+ flagEOF = flagEOR = TRUE;
+ }
+ else if( *line == '\0' ) {
+ flagEOR = TRUE;
+ }
+
+ if( flagEOR ) {
+ /* EOR, Output address data */
+ /* Save field list to hash table */
+ if( flagMail ) {
+ ldif_hash_add_list(
+ ldifFile->hashFields, listTags );
+ }
+ mgu_free_list( listTags );
+ listTags = NULL;
+ flagMail = FALSE;
+ }
+ if( line ) {
+ flagEOR = FALSE;
+ if( *line == ' ' ) {
+ /* Continuation line */
+ }
+ else if( *line == '=' ) {
+ /* Base-64 encoded continuation field */
+ }
+ else {
+ /* Parse line */
+ tagName = ldif_get_tagname( line, &flag64 );
+ if( tagName ) {
+ /* Add tag to list */
+ listTags = g_slist_append( listTags, tagName );
+
+ if( g_utf8_collate(
+ tagName, LDIF_TAG_EMAIL ) == 0 )
+ {
+ flagMail = TRUE;
+ }
+ } else {
+ g_strstrip(line);
+ if (*line != '\0') {
+ debug_print("ldif: bad format: '%s'\n", line);
+ ldifFile->retVal = MGU_BAD_FORMAT;
+ }
+ }
+ }
+ }
+ g_free( line );
+ }
+
+ /* Release data */
+ mgu_free_list( listTags );
+ listTags = NULL;
+}
+
+/**
+ * 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 );
+ cm_return_val_if_fail( ldifFile != NULL, MGU_BAD_ARGS );
ldifFile->retVal = MGU_SUCCESS;
addrcache_clear( cache );
cache->dataRead = FALSE;
return ldifFile->retVal;
}
+/**
+ * Process entire file reading list of unique fields. List of fields may be
+ * accessed with the <code>ldif_get_fieldlist()</code> function.
+ * \param ldifFile LDIF import control object.
+ * \return Status code.
+ */
+gint ldif_read_tags( LdifFile *ldifFile ) {
+ cm_return_val_if_fail( ldifFile != NULL, MGU_BAD_ARGS );
+ ldifFile->retVal = MGU_SUCCESS;
+ if( ldifFile->dirtyFlag ) {
+ ldif_open_file( ldifFile );
+ if( ldifFile->retVal == MGU_SUCCESS ) {
+ /* Read data into the cache */
+ ldif_read_tag_list( ldifFile );
+ ldif_close_file( ldifFile );
+ ldifFile->dirtyFlag = FALSE;
+ ldifFile->accessFlag = TRUE;
+ }
+ }
+ return ldifFile->retVal;
+}
+
+/**
+ * Return list of fields for LDIF file.
+ * \param ldifFile LDIF import control object.
+ * \return Linked list of <code>Ldif_FieldRec</code> objects. This list may be
+ * <code>g_free()</code>. Note that the objects in the list should not
+ * be freed since they refer to objects inside the internal cache.
+ * These objects will be freed when LDIF file object is freed.
+ */
+GList *ldif_get_fieldlist( LdifFile *ldifFile ) {
+ GList *list = NULL;
+
+ cm_return_val_if_fail( ldifFile != NULL, NULL );
+ if( ldifFile->hashFields ) {
+ ldifFile->tempList = NULL;
+ g_hash_table_foreach( ldifFile->hashFields, ldif_hash2list_vis, ldifFile );
+ list = ldifFile->tempList;
+ ldifFile->tempList = NULL;
+ }
+ return list;
+}
+
+/**
+ * Output LDIF name-value pair to stream. Only non-empty names and values will
+ * be output to file.
+ * \param stream File output stream.
+ * \param name Name.
+ * \param value Data value.
+ * \return <i>TRUE</i> if data output.
+ */
+gboolean ldif_write_value( FILE *stream, const gchar *name, const gchar *value ) {
+ if( name == NULL ) return FALSE;
+ if( value == NULL ) return FALSE;
+ if( strlen( name ) < 1 ) return FALSE;
+ if( strlen( value ) < 1 ) return FALSE;
+ fprintf( stream, "%s: ", name );
+ fprintf( stream, "%s\n", value );
+ return TRUE;
+}
+
+/**
+ * Output LDIF End of Record to stream.
+ * \param stream File output stream.
+ * \return <i>TRUE</i> if data output.
+ */
+void ldif_write_eor( FILE *stream ) {
+ /* Simple but caller should not need to know how to end record. */
+ fprintf( stream, "\n" );
+}
+
/*
-* End of Source.
-*/
+ * ============================================================================
+ * End of Source.
+ * ============================================================================
+ */