diff options
| author | Simeon Simeonov | 2018-02-26 11:23:00 +0100 |
|---|---|---|
| committer | Simeon Simeonov | 2018-02-26 11:23:00 +0100 |
| commit | 0b3cbf57875fd692e4ba0b336fefa4bee1ed00dc (patch) | |
| tree | af916a30553c78ce9d4f2d8658656a175c5b6921 /src/ldif.c | |
Initial commit for sylpheed 3.7.0
Diffstat (limited to 'src/ldif.c')
| -rw-r--r-- | src/ldif.c | 986 |
1 files changed, 986 insertions, 0 deletions
diff --git a/src/ldif.c b/src/ldif.c new file mode 100644 index 0000000..a158faa --- /dev/null +++ b/src/ldif.c | |||
| @@ -0,0 +1,986 @@ | |||
| 1 | /* | ||
| 2 | * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client | ||
| 3 | * Copyright (C) 2001 Match Grun | ||
| 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 2 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, write to the Free Software | ||
| 17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 18 | */ | ||
| 19 | |||
| 20 | /* | ||
| 21 | * Functions necessary to access LDIF files (LDAP Data Interchange Format | ||
| 22 | * files). | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include <glib.h> | ||
| 26 | #include <string.h> | ||
| 27 | #include <sys/stat.h> | ||
| 28 | |||
| 29 | #include "mgutils.h" | ||
| 30 | #include "ldif.h" | ||
| 31 | #include "addritem.h" | ||
| 32 | #include "addrcache.h" | ||
| 33 | |||
| 34 | #include "base64.h" | ||
| 35 | #include "codeconv.h" | ||
| 36 | #include "utils.h" | ||
| 37 | |||
| 38 | /* | ||
| 39 | * Create new object. | ||
| 40 | */ | ||
| 41 | LdifFile *ldif_create() { | ||
| 42 | LdifFile *ldifFile; | ||
| 43 | ldifFile = g_new0( LdifFile, 1 ); | ||
| 44 | ldifFile->path = NULL; | ||
| 45 | ldifFile->file = NULL; | ||
| 46 | ldifFile->bufptr = ldifFile->buffer; | ||
| 47 | ldifFile->hashFields = g_hash_table_new( g_str_hash, g_str_equal ); | ||
| 48 | ldifFile->tempList = NULL; | ||
| 49 | ldifFile->dirtyFlag = TRUE; | ||
| 50 | ldifFile->accessFlag = FALSE; | ||
| 51 | ldifFile->retVal = MGU_SUCCESS; | ||
| 52 | ldifFile->cbProgress = NULL; | ||
| 53 | ldifFile->importCount = 0; | ||
| 54 | return ldifFile; | ||
| 55 | } | ||
| 56 | |||
| 57 | /* | ||
| 58 | * Properties... | ||
| 59 | */ | ||
| 60 | void ldif_set_file( LdifFile *ldifFile, const gchar *value ) { | ||
| 61 | g_return_if_fail( ldifFile != NULL ); | ||
| 62 | |||
| 63 | if( ldifFile->path ) { | ||
| 64 | if( strcmp( ldifFile->path, value ) != 0 ) | ||
| 65 | ldifFile->dirtyFlag = TRUE; | ||
| 66 | } | ||
| 67 | else { | ||
| 68 | ldifFile->dirtyFlag = TRUE; | ||
| 69 | } | ||
| 70 | ldifFile->path = mgu_replace_string( ldifFile->path, value ); | ||
| 71 | g_strstrip( ldifFile->path ); | ||
| 72 | ldifFile->importCount = 0; | ||
| 73 | } | ||
| 74 | void ldif_set_accessed( LdifFile *ldifFile, const gboolean value ) { | ||
| 75 | g_return_if_fail( ldifFile != NULL ); | ||
| 76 | ldifFile->accessFlag = value; | ||
| 77 | } | ||
| 78 | |||
| 79 | /* | ||
| 80 | * Register a callback function. When called, the function will be passed | ||
| 81 | * the following arguments: | ||
| 82 | * LdifFile object, | ||
| 83 | * File size (long), | ||
| 84 | * Current position (long) | ||
| 85 | * This can be used for a progress indicator. | ||
| 86 | */ | ||
| 87 | void ldif_set_callback( LdifFile *ldifFile, void *func ) { | ||
| 88 | ldifFile->cbProgress = func; | ||
| 89 | } | ||
| 90 | |||
| 91 | /* | ||
| 92 | * Create field record object. | ||
| 93 | */ | ||
| 94 | static Ldif_FieldRec *ldif_create_fieldrec( gchar *field ) { | ||
| 95 | Ldif_FieldRec *rec = g_new0( Ldif_FieldRec, 1 ); | ||
| 96 | rec->tagName = g_strdup( field ); | ||
| 97 | rec->userName = NULL; | ||
| 98 | rec->reserved = FALSE; | ||
| 99 | rec->selected = FALSE; | ||
| 100 | return rec; | ||
| 101 | } | ||
| 102 | |||
| 103 | /* | ||
| 104 | * Free field record object. | ||
| 105 | */ | ||
| 106 | static void ldif_free_fieldrec( Ldif_FieldRec *rec ) { | ||
| 107 | if( rec ) { | ||
| 108 | g_free( rec->tagName ); | ||
| 109 | g_free( rec->userName ); | ||
| 110 | rec->tagName = NULL; | ||
| 111 | rec->userName = NULL; | ||
| 112 | rec->reserved = FALSE; | ||
| 113 | rec->selected = FALSE; | ||
| 114 | g_free( rec ); | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | /* | ||
| 119 | * Free hash table entry visitor function. | ||
| 120 | */ | ||
| 121 | static gint ldif_hash_free_vis( gpointer key, gpointer value, gpointer data ) { | ||
| 122 | ldif_free_fieldrec( ( Ldif_FieldRec * ) value ); | ||
| 123 | value = NULL; | ||
| 124 | key = NULL; | ||
| 125 | return -1; | ||
| 126 | } | ||
| 127 | |||
| 128 | /* | ||
| 129 | * Free up object by releasing internal memory. | ||
| 130 | */ | ||
| 131 | void ldif_free( LdifFile *ldifFile ) { | ||
| 132 | g_return_if_fail( ldifFile != NULL ); | ||
| 133 | |||
| 134 | /* Close file */ | ||
| 135 | if( ldifFile->file ) fclose( ldifFile->file ); | ||
| 136 | |||
| 137 | /* Free internal stuff */ | ||
| 138 | g_free( ldifFile->path ); | ||
| 139 | |||
| 140 | /* Free field list */ | ||
| 141 | g_hash_table_foreach_remove( ldifFile->hashFields, ldif_hash_free_vis, NULL ); | ||
| 142 | g_hash_table_destroy( ldifFile->hashFields ); | ||
| 143 | ldifFile->hashFields = NULL; | ||
| 144 | |||
| 145 | /* Clear pointers */ | ||
| 146 | ldifFile->file = NULL; | ||
| 147 | ldifFile->path = NULL; | ||
| 148 | ldifFile->retVal = MGU_SUCCESS; | ||
| 149 | ldifFile->tempList = NULL; | ||
| 150 | ldifFile->dirtyFlag = FALSE; | ||
| 151 | ldifFile->accessFlag = FALSE; | ||
| 152 | ldifFile->cbProgress = NULL; | ||
| 153 | |||
| 154 | /* Now release file object */ | ||
| 155 | g_free( ldifFile ); | ||
| 156 | } | ||
| 157 | |||
| 158 | /* | ||
| 159 | * Display field record. | ||
| 160 | */ | ||
| 161 | void ldif_print_fieldrec( Ldif_FieldRec *rec, FILE *stream ) { | ||
| 162 | fprintf( stream, "\ttag:\t%s", rec->reserved ? "yes" : "no" ); | ||
| 163 | fprintf( stream, "\t%s", rec->selected ? "yes" : "no" ); | ||
| 164 | fprintf( stream, "\t:%s:\t:%s:\n", rec->userName, rec->tagName ); | ||
| 165 | } | ||
| 166 | |||
| 167 | /* | ||
| 168 | * Display field record. | ||
| 169 | * | ||
| 170 | */ | ||
| 171 | static void ldif_print_file_vis( gpointer key, gpointer value, gpointer data ) { | ||
| 172 | Ldif_FieldRec *rec = value; | ||
| 173 | FILE *stream = data; | ||
| 174 | ldif_print_fieldrec( rec, stream ); | ||
| 175 | } | ||
| 176 | |||
| 177 | /* | ||
| 178 | * Display object to specified stream. | ||
| 179 | */ | ||
| 180 | void ldif_print_file( LdifFile *ldifFile, FILE *stream ) { | ||
| 181 | g_return_if_fail( ldifFile != NULL ); | ||
| 182 | fprintf( stream, "LDIF File:\n" ); | ||
| 183 | fprintf( stream, "file spec: '%s'\n", ldifFile->path ); | ||
| 184 | fprintf( stream, " ret val: %d\n", ldifFile->retVal ); | ||
| 185 | fprintf( stream, " fields: {\n" ); | ||
| 186 | g_hash_table_foreach( ldifFile->hashFields, ldif_print_file_vis, stream ); | ||
| 187 | fprintf( stream, "} ---\n" ); | ||
| 188 | } | ||
| 189 | |||
| 190 | /* | ||
| 191 | * Open file for read. | ||
| 192 | * return: TRUE if file opened successfully. | ||
| 193 | */ | ||
| 194 | static gint ldif_open_file( LdifFile* ldifFile ) { | ||
| 195 | /* printf( "Opening file\n" ); */ | ||
| 196 | if( ldifFile->path ) { | ||
| 197 | ldifFile->file = g_fopen( ldifFile->path, "rb" ); | ||
| 198 | if( ! ldifFile->file ) { | ||
| 199 | /* printf( "can't open %s\n", ldifFile->path ); */ | ||
| 200 | ldifFile->retVal = MGU_OPEN_FILE; | ||
| 201 | return ldifFile->retVal; | ||
| 202 | } | ||
| 203 | } | ||
| 204 | else { | ||
| 205 | /* printf( "file not specified\n" ); */ | ||
| 206 | ldifFile->retVal = MGU_NO_FILE; | ||
| 207 | return ldifFile->retVal; | ||
| 208 | } | ||
| 209 | |||
| 210 | /* Setup a buffer area */ | ||
| 211 | ldifFile->buffer[0] = '\0'; | ||
| 212 | ldifFile->bufptr = ldifFile->buffer; | ||
| 213 | ldifFile->retVal = MGU_SUCCESS; | ||
| 214 | return ldifFile->retVal; | ||
| 215 | } | ||
| 216 | |||
| 217 | /* | ||
| 218 | * Close file. | ||
| 219 | */ | ||
| 220 | static void ldif_close_file( LdifFile *ldifFile ) { | ||
| 221 | g_return_if_fail( ldifFile != NULL ); | ||
| 222 | if( ldifFile->file ) fclose( ldifFile->file ); | ||
| 223 | ldifFile->file = NULL; | ||
| 224 | } | ||
| 225 | |||
| 226 | /* | ||
| 227 | * Read line of text from file. | ||
| 228 | * Return: ptr to buffer where line starts. | ||
| 229 | */ | ||
| 230 | static gchar *ldif_get_line( LdifFile *ldifFile ) { | ||
| 231 | gchar buf[ LDIFBUFSIZE ]; | ||
| 232 | |||
| 233 | if( feof( ldifFile->file ) ) | ||
| 234 | return NULL; | ||
| 235 | |||
| 236 | if( fgets( buf, sizeof( buf ), ldifFile->file ) == NULL ) | ||
| 237 | return NULL; | ||
| 238 | |||
| 239 | strretchomp( buf ); | ||
| 240 | |||
| 241 | /* Return a copy of buffer */ | ||
| 242 | return g_strdup( buf ); | ||
| 243 | } | ||
| 244 | |||
| 245 | /* | ||
| 246 | * Parse tag name from line buffer. | ||
| 247 | * Enter: line Buffer. | ||
| 248 | * flag64 Base-64 encoder flag. | ||
| 249 | * Return: Buffer containing the tag name, or NULL if no delimiter char found. | ||
| 250 | * If a double delimiter (::) is found, flag64 is set. | ||
| 251 | */ | ||
| 252 | static gchar *ldif_get_tagname( char* line, gboolean *flag64 ) { | ||
| 253 | gint len = 0; | ||
| 254 | gchar *tag = NULL; | ||
| 255 | gchar *lptr = line; | ||
| 256 | gchar *sptr = NULL; | ||
| 257 | |||
| 258 | while( *lptr++ ) { | ||
| 259 | /* Check for language tag */ | ||
| 260 | if( *lptr == LDIF_LANG_TAG ) { | ||
| 261 | if( sptr == NULL ) sptr = lptr; | ||
| 262 | } | ||
| 263 | |||
| 264 | /* Check for delimiter */ | ||
| 265 | if( *lptr == LDIF_SEP_TAG ) { | ||
| 266 | if( sptr ) { | ||
| 267 | len = sptr - line; | ||
| 268 | } | ||
| 269 | else { | ||
| 270 | len = lptr - line; | ||
| 271 | } | ||
| 272 | |||
| 273 | /* Base-64 encoding? */ | ||
| 274 | if( * ++lptr == LDIF_SEP_TAG ) *flag64 = TRUE; | ||
| 275 | |||
| 276 | tag = g_strndup( line, len+1 ); | ||
| 277 | tag[ len ] = '\0'; | ||
| 278 | g_strdown( tag ); | ||
| 279 | return tag; | ||
| 280 | } | ||
| 281 | } | ||
| 282 | return tag; | ||
| 283 | } | ||
| 284 | |||
| 285 | /* | ||
| 286 | * Parse tag value from line buffer. | ||
| 287 | * Enter: line Buffer. | ||
| 288 | * Return: Buffer containing the tag value. Empty string is returned if | ||
| 289 | * no delimiter char found. | ||
| 290 | */ | ||
| 291 | static gchar *ldif_get_tagvalue( gchar* line ) { | ||
| 292 | gchar *value = NULL; | ||
| 293 | gchar *start = NULL; | ||
| 294 | gchar *lptr; | ||
| 295 | gint len = 0; | ||
| 296 | |||
| 297 | for( lptr = line; *lptr; lptr++ ) { | ||
| 298 | if( *lptr == LDIF_SEP_TAG ) { | ||
| 299 | if( ! start ) | ||
| 300 | start = lptr + 1; | ||
| 301 | } | ||
| 302 | } | ||
| 303 | if( start ) { | ||
| 304 | if( *start == LDIF_SEP_TAG ) start++; | ||
| 305 | len = lptr - start; | ||
| 306 | value = g_strndup( start, len+1 ); | ||
| 307 | g_strstrip( value ); | ||
| 308 | } | ||
| 309 | else { | ||
| 310 | /* Ensure that we get an empty string */ | ||
| 311 | value = g_strndup( "", 1 ); | ||
| 312 | } | ||
| 313 | value[ len ] = '\0'; | ||
| 314 | return value; | ||
| 315 | } | ||
| 316 | |||
| 317 | #if 0 | ||
| 318 | /* | ||
| 319 | * Dump linked lists of character strings (for debug). | ||
| 320 | */ | ||
| 321 | static void ldif_dump_lists( GSList *listName, GSList *listAddr, GSList *listRem, GSList *listID, FILE *stream ) { | ||
| 322 | fprintf( stream, "dump name\n" ); | ||
| 323 | fprintf( stream, "------------\n" ); | ||
| 324 | mgu_print_list( listName, stdout ); | ||
| 325 | fprintf( stream, "dump address\n" ); | ||
| 326 | fprintf( stream, "------------\n" ); | ||
| 327 | mgu_print_list( listAddr, stdout ); | ||
| 328 | fprintf( stream, "dump remarks\n" ); | ||
| 329 | fprintf( stdout, "------------\n" ); | ||
| 330 | mgu_print_list( listRem, stdout ); | ||
| 331 | fprintf( stream, "dump id\n" ); | ||
| 332 | fprintf( stdout, "------------\n" ); | ||
| 333 | mgu_print_list( listID, stdout ); | ||
| 334 | } | ||
| 335 | #endif | ||
| 336 | |||
| 337 | /* | ||
| 338 | * Parsed address data. | ||
| 339 | */ | ||
| 340 | typedef struct _Ldif_ParsedRec_ Ldif_ParsedRec; | ||
| 341 | struct _Ldif_ParsedRec_ { | ||
| 342 | GSList *listCName; | ||
| 343 | GSList *listFName; | ||
| 344 | GSList *listLName; | ||
| 345 | GSList *listNName; | ||
| 346 | GSList *listAddress; | ||
| 347 | GSList *listID; | ||
| 348 | GSList *userAttr; | ||
| 349 | }; | ||
| 350 | |||
| 351 | /* | ||
| 352 | * User attribute data. | ||
| 353 | */ | ||
| 354 | typedef struct _Ldif_UserAttr_ Ldif_UserAttr; | ||
| 355 | struct _Ldif_UserAttr_ { | ||
| 356 | gchar *name; | ||
| 357 | gchar *value; | ||
| 358 | }; | ||
| 359 | |||
| 360 | /* | ||
| 361 | * Build an address list entry and append to list of address items. Name is formatted | ||
| 362 | * as "<first-name> <last-name>". | ||
| 363 | */ | ||
| 364 | static void ldif_build_items( LdifFile *ldifFile, Ldif_ParsedRec *rec, AddressCache *cache ) { | ||
| 365 | GSList *nodeFirst; | ||
| 366 | GSList *nodeAddress; | ||
| 367 | GSList *nodeAttr; | ||
| 368 | gchar *firstName = NULL, *lastName = NULL, *fullName = NULL, *nickName = NULL; | ||
| 369 | gint iLen = 0, iLenT = 0; | ||
| 370 | ItemPerson *person; | ||
| 371 | ItemEMail *email; | ||
| 372 | gboolean familyFirst = FALSE; | ||
| 373 | |||
| 374 | nodeAddress = rec->listAddress; | ||
| 375 | if( nodeAddress == NULL ) return; | ||
| 376 | |||
| 377 | /* Find longest first name in list */ | ||
| 378 | nodeFirst = rec->listFName; | ||
| 379 | while( nodeFirst ) { | ||
| 380 | if( firstName == NULL ) { | ||
| 381 | firstName = nodeFirst->data; | ||
| 382 | iLen = strlen( firstName ); | ||
| 383 | } | ||
| 384 | else { | ||
| 385 | if( ( iLenT = strlen( nodeFirst->data ) ) > iLen ) { | ||
| 386 | firstName = nodeFirst->data; | ||
| 387 | iLen = iLenT; | ||
| 388 | } | ||
| 389 | } | ||
| 390 | nodeFirst = g_slist_next( nodeFirst ); | ||
| 391 | } | ||
| 392 | |||
| 393 | /* Format name */ | ||
| 394 | if( rec->listLName ) { | ||
| 395 | lastName = rec->listLName->data; | ||
| 396 | } | ||
| 397 | if( rec->listCName ) { | ||
| 398 | fullName = g_strdup((gchar *)rec->listCName->data); | ||
| 399 | } | ||
| 400 | |||
| 401 | familyFirst = conv_is_ja_locale(); | ||
| 402 | |||
| 403 | if( fullName == NULL ) { | ||
| 404 | if( familyFirst ) { | ||
| 405 | if( lastName ) { | ||
| 406 | if( firstName ) { | ||
| 407 | fullName = g_strdup_printf( "%s %s", lastName, firstName ); | ||
| 408 | } | ||
| 409 | else { | ||
| 410 | fullName = g_strdup_printf( "%s", lastName ); | ||
| 411 | } | ||
| 412 | } | ||
| 413 | else { | ||
| 414 | if( firstName ) { | ||
| 415 | fullName = g_strdup_printf( "%s", firstName ); | ||
| 416 | } | ||
| 417 | } | ||
| 418 | } else { | ||
| 419 | if( firstName ) { | ||
| 420 | if( lastName ) { | ||
| 421 | fullName = g_strdup_printf( "%s %s", firstName, lastName ); | ||
| 422 | } | ||
| 423 | else { | ||
| 424 | fullName = g_strdup_printf( "%s", firstName ); | ||
| 425 | } | ||
| 426 | } | ||
| 427 | else { | ||
| 428 | if( lastName ) { | ||
| 429 | fullName = g_strdup_printf( "%s", lastName ); | ||
| 430 | } | ||
| 431 | } | ||
| 432 | } | ||
| 433 | } | ||
| 434 | if( fullName ) { | ||
| 435 | g_strstrip( fullName ); | ||
| 436 | } | ||
| 437 | |||
| 438 | if( rec->listNName ) { | ||
| 439 | nickName = rec->listNName->data; | ||
| 440 | } | ||
| 441 | |||
| 442 | person = addritem_create_item_person(); | ||
| 443 | addritem_person_set_common_name( person, fullName ); | ||
| 444 | addritem_person_set_first_name( person, firstName ); | ||
| 445 | addritem_person_set_last_name( person, lastName ); | ||
| 446 | addritem_person_set_nick_name( person, nickName ); | ||
| 447 | addrcache_id_person( cache, person ); | ||
| 448 | addrcache_add_person( cache, person ); | ||
| 449 | ++ldifFile->importCount; | ||
| 450 | |||
| 451 | /* Add address item */ | ||
| 452 | while( nodeAddress ) { | ||
| 453 | email = addritem_create_item_email(); | ||
| 454 | addritem_email_set_address( email, nodeAddress->data ); | ||
| 455 | addrcache_id_email( cache, email ); | ||
| 456 | addrcache_person_add_email( cache, person, email ); | ||
| 457 | nodeAddress = g_slist_next( nodeAddress ); | ||
| 458 | } | ||
| 459 | g_free( fullName ); | ||
| 460 | fullName = firstName = lastName = NULL; | ||
| 461 | |||
| 462 | /* Add user attributes */ | ||
| 463 | nodeAttr = rec->userAttr; | ||
| 464 | while( nodeAttr ) { | ||
| 465 | Ldif_UserAttr *attr = nodeAttr->data; | ||
| 466 | UserAttribute *attrib = addritem_create_attribute(); | ||
| 467 | addritem_attrib_set_name( attrib, attr->name ); | ||
| 468 | addritem_attrib_set_value( attrib, attr->value ); | ||
| 469 | addritem_person_add_attribute( person, attrib ); | ||
| 470 | nodeAttr = g_slist_next( nodeAttr ); | ||
| 471 | } | ||
| 472 | nodeAttr = NULL; | ||
| 473 | } | ||
| 474 | |||
| 475 | /* | ||
| 476 | * Add selected field as user attribute. | ||
| 477 | */ | ||
| 478 | static void ldif_add_user_attr( Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue, GHashTable *hashField ) { | ||
| 479 | Ldif_FieldRec *fld = NULL; | ||
| 480 | Ldif_UserAttr *attr = NULL; | ||
| 481 | gchar *name; | ||
| 482 | |||
| 483 | fld = g_hash_table_lookup( hashField, tagName ); | ||
| 484 | if( fld ) { | ||
| 485 | if( fld->reserved ) return; | ||
| 486 | if( ! fld->selected ) return; | ||
| 487 | |||
| 488 | name = fld->tagName; | ||
| 489 | if( fld->userName && *(fld->userName) ) { | ||
| 490 | name = fld->userName; | ||
| 491 | } | ||
| 492 | attr = g_new0( Ldif_UserAttr, 1 ); | ||
| 493 | attr->name = g_strdup( name ); | ||
| 494 | attr->value = g_strdup( tagValue ); | ||
| 495 | rec->userAttr = g_slist_append( rec->userAttr, attr ); | ||
| 496 | } | ||
| 497 | } | ||
| 498 | |||
| 499 | /* | ||
| 500 | * Add value to parsed data. | ||
| 501 | */ | ||
| 502 | static void ldif_add_value( Ldif_ParsedRec *rec, gchar *tagName, gchar *tagValue, GHashTable *hashField ) { | ||
| 503 | gchar *nm, *val; | ||
| 504 | |||
| 505 | nm = g_strdup( tagName ); | ||
| 506 | g_strdown( nm ); | ||
| 507 | if( tagValue ) { | ||
| 508 | val = g_strdup( tagValue ); | ||
| 509 | } | ||
| 510 | else { | ||
| 511 | val = g_strdup( "" ); | ||
| 512 | } | ||
| 513 | g_strstrip( val ); | ||
| 514 | if( g_ascii_strcasecmp( nm, LDIF_TAG_COMMONNAME ) == 0 ) { | ||
| 515 | rec->listCName = g_slist_append( rec->listCName, val ); | ||
| 516 | } | ||
| 517 | else if( g_ascii_strcasecmp( nm, LDIF_TAG_FIRSTNAME ) == 0 ) { | ||
| 518 | rec->listFName = g_slist_append( rec->listFName, val ); | ||
| 519 | } | ||
| 520 | else if( g_ascii_strcasecmp( nm, LDIF_TAG_LASTNAME ) == 0 ) { | ||
| 521 | rec->listLName = g_slist_append( rec->listLName, val ); | ||
| 522 | } | ||
| 523 | else if( g_ascii_strcasecmp( nm, LDIF_TAG_NICKNAME ) == 0 || | ||
| 524 | g_ascii_strcasecmp( nm, LDIF_TAG_NICKNAME2 ) == 0 || | ||
| 525 | g_ascii_strcasecmp( nm, LDIF_TAG_XNICKNAME ) == 0 ) { | ||
| 526 | rec->listNName = g_slist_append( rec->listNName, val ); | ||
| 527 | } | ||
| 528 | else if( g_ascii_strcasecmp( nm, LDIF_TAG_EMAIL ) == 0 ) { | ||
| 529 | if( g_slist_find_custom( rec->listAddress, val, (GCompareFunc)strcmp2 )) { | ||
| 530 | /* skip duplicated address */ | ||
| 531 | g_free( val ); | ||
| 532 | } else { | ||
| 533 | rec->listAddress = g_slist_append( rec->listAddress, val ); | ||
| 534 | } | ||
| 535 | } | ||
| 536 | else { | ||
| 537 | /* Add field as user attribute */ | ||
| 538 | ldif_add_user_attr( rec, tagName, tagValue, hashField ); | ||
| 539 | g_free( val ); | ||
| 540 | } | ||
| 541 | g_free( nm ); | ||
| 542 | } | ||
| 543 | |||
| 544 | /* | ||
| 545 | * Clear parsed data. | ||
| 546 | */ | ||
| 547 | static void ldif_clear_rec( Ldif_ParsedRec *rec ) { | ||
| 548 | GSList *list; | ||
| 549 | |||
| 550 | /* Free up user attributes */ | ||
| 551 | list = rec->userAttr; | ||
| 552 | while( list ) { | ||
| 553 | Ldif_UserAttr *attr = list->data; | ||
| 554 | g_free( attr->name ); | ||
| 555 | g_free( attr->value ); | ||
| 556 | g_free( attr ); | ||
| 557 | list = g_slist_next( list ); | ||
| 558 | } | ||
| 559 | g_slist_free( rec->userAttr ); | ||
| 560 | |||
| 561 | g_slist_free( rec->listCName ); | ||
| 562 | g_slist_free( rec->listFName ); | ||
| 563 | g_slist_free( rec->listLName ); | ||
| 564 | g_slist_free( rec->listNName ); | ||
| 565 | g_slist_free( rec->listAddress ); | ||
| 566 | g_slist_free( rec->listID ); | ||
| 567 | |||
| 568 | rec->userAttr = NULL; | ||
| 569 | rec->listCName = NULL; | ||
| 570 | rec->listFName = NULL; | ||
| 571 | rec->listLName = NULL; | ||
| 572 | rec->listNName = NULL; | ||
| 573 | rec->listAddress = NULL; | ||
| 574 | rec->listID = NULL; | ||
| 575 | } | ||
| 576 | |||
| 577 | #if 0 | ||
| 578 | /* | ||
| 579 | * Print parsed data. | ||
| 580 | */ | ||
| 581 | static void ldif_print_record( Ldif_ParsedRec *rec, FILE *stream ) { | ||
| 582 | GSList *list; | ||
| 583 | |||
| 584 | fprintf( stream, "LDIF Parsed Record:\n" ); | ||
| 585 | fprintf( stream, "common name:" ); | ||
| 586 | mgu_print_list( rec->listCName, stream ); | ||
| 587 | if( ! rec->listCName ) fprintf( stream, "\n" ); | ||
| 588 | fprintf( stream, "first name:" ); | ||
| 589 | mgu_print_list( rec->listFName, stream ); | ||
| 590 | if( ! rec->listFName ) fprintf( stream, "\n" ); | ||
| 591 | fprintf( stream, "last name:" ); | ||
| 592 | mgu_print_list( rec->listLName, stream ); | ||
| 593 | if( ! rec->listLName ) fprintf( stream, "\n" ); | ||
| 594 | fprintf( stream, "nick name:" ); | ||
| 595 | mgu_print_list( rec->listNName, stream ); | ||
| 596 | if( ! rec->listNName ) fprintf( stream, "\n" ); | ||
| 597 | fprintf( stream, "address:" ); | ||
| 598 | mgu_print_list( rec->listAddress, stream ); | ||
| 599 | if( ! rec->listAddress ) fprintf( stream, "\n" ); | ||
| 600 | fprintf( stream, "id:" ); | ||
| 601 | mgu_print_list( rec->listID, stream ); | ||
| 602 | if( ! rec->listID ) fprintf( stream, "\n" ); | ||
| 603 | |||
| 604 | list = rec->userAttr; | ||
| 605 | while( list ) { | ||
| 606 | Ldif_UserAttr *attr = list->data; | ||
| 607 | fprintf( stream, "n/v:\t%s:\t:%s:\n", attr->name, attr->value ); | ||
| 608 | list = g_slist_next( list ); | ||
| 609 | } | ||
| 610 | list = NULL; | ||
| 611 | } | ||
| 612 | |||
| 613 | static void ldif_dump_b64( gchar *buf ) { | ||
| 614 | Base64Decoder *decoder = NULL; | ||
| 615 | gchar outBuf[8192]; | ||
| 616 | gint len; | ||
| 617 | |||
| 618 | g_print( "base-64 : inbuf : %s\n", buf ); | ||
| 619 | decoder = base64_decoder_new(); | ||
| 620 | len = base64_decoder_decode( decoder, buf, outBuf ); | ||
| 621 | if (len < 0) { | ||
| 622 | g_print( "base-64 : Bad BASE64 content\n" ); | ||
| 623 | } | ||
| 624 | else { | ||
| 625 | outBuf[len] = '\0'; | ||
| 626 | g_print( "base-64 : %d : %s\n\n", len, outBuf ); | ||
| 627 | } | ||
| 628 | base64_decoder_free( decoder ); | ||
| 629 | decoder = NULL; | ||
| 630 | } | ||
| 631 | #endif | ||
| 632 | |||
| 633 | static gchar *ldif_conv_base64( gchar *buf ) { | ||
| 634 | gchar *outbuf; | ||
| 635 | gint len; | ||
| 636 | |||
| 637 | outbuf = g_malloc(strlen(buf) + 1); | ||
| 638 | len = base64_decode((guchar *)outbuf, buf, -1); | ||
| 639 | outbuf[len] = '\0'; | ||
| 640 | if (g_utf8_validate(outbuf, -1, NULL)) | ||
| 641 | return outbuf; | ||
| 642 | else { | ||
| 643 | gchar *utf8str; | ||
| 644 | |||
| 645 | if (conv_is_ja_locale()) | ||
| 646 | utf8str = conv_codeset_strdup(outbuf, NULL, NULL); | ||
| 647 | else | ||
| 648 | utf8str = conv_localetodisp(outbuf, NULL); | ||
| 649 | |||
| 650 | g_free(outbuf); | ||
| 651 | return utf8str; | ||
| 652 | } | ||
| 653 | } | ||
| 654 | |||
| 655 | /* | ||
| 656 | * Read file data into address cache. | ||
| 657 | * Note that one LDIF record identifies one entity uniquely with the | ||
| 658 | * distinguished name (dn) tag. Each person can have multiple E-Mail | ||
| 659 | * addresses. Also, each person can have many common name (cn) tags. | ||
| 660 | */ | ||
| 661 | static void ldif_read_file( LdifFile *ldifFile, AddressCache *cache ) { | ||
| 662 | gchar *tagName = NULL, *tagValue = NULL; | ||
| 663 | gchar *lastTag = NULL; | ||
| 664 | GSList *listValue = NULL; | ||
| 665 | gboolean flagEOF = FALSE, flagEOR = FALSE; | ||
| 666 | gboolean flag64 = FALSE, last64 = FALSE; | ||
| 667 | Ldif_ParsedRec *rec; | ||
| 668 | long posEnd = 0L; | ||
| 669 | long posCur = 0L; | ||
| 670 | GHashTable *hashField; | ||
| 671 | |||
| 672 | hashField = ldifFile->hashFields; | ||
| 673 | rec = g_new0( Ldif_ParsedRec, 1 ); | ||
| 674 | ldif_clear_rec( rec ); | ||
| 675 | |||
| 676 | /* Find EOF for progress indicator */ | ||
| 677 | fseek( ldifFile->file, 0L, SEEK_END ); | ||
| 678 | posEnd = ftell( ldifFile->file ); | ||
| 679 | fseek( ldifFile->file, 0L, SEEK_SET ); | ||
| 680 | |||
| 681 | while( ! flagEOF ) { | ||
| 682 | gchar *line = ldif_get_line( ldifFile ); | ||
| 683 | |||
| 684 | posCur = ftell( ldifFile->file ); | ||
| 685 | if( ldifFile->cbProgress ) { | ||
| 686 | /* Call progress indicator */ | ||
| 687 | ( ldifFile->cbProgress ) ( ldifFile, & posEnd, & posCur ); | ||
| 688 | } | ||
| 689 | |||
| 690 | flag64 = FALSE; | ||
| 691 | if( line == NULL ) { | ||
| 692 | flagEOF = flagEOR = TRUE; | ||
| 693 | } | ||
| 694 | else if( *line == '\0' ) { | ||
| 695 | flagEOR = TRUE; | ||
| 696 | } | ||
| 697 | |||
| 698 | if( flagEOR ) { | ||
| 699 | /* EOR, Output address data */ | ||
| 700 | if( lastTag ) { | ||
| 701 | gchar *fullValue; | ||
| 702 | |||
| 703 | /* Save record */ | ||
| 704 | fullValue = mgu_list_coalesce( listValue ); | ||
| 705 | |||
| 706 | /* Base-64 encoded data */ | ||
| 707 | if( last64 ) { | ||
| 708 | gchar *decValue; | ||
| 709 | decValue = ldif_conv_base64( fullValue ); | ||
| 710 | g_free( fullValue ); | ||
| 711 | fullValue = decValue; | ||
| 712 | } | ||
| 713 | |||
| 714 | ldif_add_value( rec, lastTag, fullValue, hashField ); | ||
| 715 | /* ldif_print_record( rec, stdout ); */ | ||
| 716 | ldif_build_items( ldifFile, rec, cache ); | ||
| 717 | ldif_clear_rec( rec ); | ||
| 718 | g_free( fullValue ); | ||
| 719 | g_free( lastTag ); | ||
| 720 | mgu_free_list( listValue ); | ||
| 721 | lastTag = NULL; | ||
| 722 | listValue = NULL; | ||
| 723 | last64 = FALSE; | ||
| 724 | } | ||
| 725 | } | ||
| 726 | if( line ) { | ||
| 727 | flagEOR = FALSE; | ||
| 728 | if( *line == ' ' ) { | ||
| 729 | /* Continuation line */ | ||
| 730 | listValue = g_slist_append( listValue, g_strdup( line+1 ) ); | ||
| 731 | } | ||
| 732 | else if( *line == '=' ) { | ||
| 733 | /* Base-64 encoded continuation field */ | ||
| 734 | listValue = g_slist_append( listValue, g_strdup( line ) ); | ||
| 735 | } | ||
| 736 | else { | ||
| 737 | /* Parse line */ | ||
| 738 | tagName = ldif_get_tagname( line, &flag64 ); | ||
| 739 | if( tagName ) { | ||
| 740 | tagValue = ldif_get_tagvalue( line ); | ||
| 741 | if( tagValue ) { | ||
| 742 | if( lastTag ) { | ||
| 743 | gchar *fullValue; | ||
| 744 | |||
| 745 | /* Save data */ | ||
| 746 | fullValue = mgu_list_coalesce( listValue ); | ||
| 747 | /* Base-64 encoded data */ | ||
| 748 | if( last64 ) { | ||
| 749 | gchar *decValue; | ||
| 750 | decValue = ldif_conv_base64( fullValue ); | ||
| 751 | g_free( fullValue ); | ||
| 752 | fullValue = decValue; | ||
| 753 | } | ||
| 754 | |||
| 755 | ldif_add_value( rec, lastTag, fullValue, hashField ); | ||
| 756 | g_free( fullValue ); | ||
| 757 | g_free( lastTag ); | ||
| 758 | mgu_free_list( listValue ); | ||
| 759 | lastTag = NULL; | ||
| 760 | listValue = NULL; | ||
| 761 | last64 = FALSE; | ||
| 762 | } | ||
| 763 | |||
| 764 | lastTag = g_strdup( tagName ); | ||
| 765 | listValue = g_slist_append( listValue, g_strdup( tagValue ) ); | ||
| 766 | g_free( tagValue ); | ||
| 767 | last64 = flag64; | ||
| 768 | } | ||
| 769 | g_free( tagName ); | ||
| 770 | } | ||
| 771 | } | ||
| 772 | } | ||
| 773 | g_free( line ); | ||
| 774 | } | ||
| 775 | |||
| 776 | /* Release data */ | ||
| 777 | ldif_clear_rec( rec ); | ||
| 778 | g_free( rec ); | ||
| 779 | g_free( lastTag ); | ||
| 780 | mgu_free_list( listValue ); | ||
| 781 | } | ||
| 782 | |||
| 783 | /* | ||
| 784 | * Add list of field names to hash table. | ||
| 785 | */ | ||
| 786 | static void ldif_hash_add_list( GHashTable *table, GSList *list ) { | ||
| 787 | GSList *node = list; | ||
| 788 | |||
| 789 | /* mgu_print_list( list, stdout ); */ | ||
| 790 | while( node ) { | ||
| 791 | gchar *tag = node->data; | ||
| 792 | if( ! g_hash_table_lookup( table, tag ) ) { | ||
| 793 | Ldif_FieldRec *rec = NULL; | ||
| 794 | gchar *key = g_strdup( tag ); | ||
| 795 | |||
| 796 | rec = ldif_create_fieldrec( tag ); | ||
| 797 | if( g_ascii_strcasecmp( tag, LDIF_TAG_COMMONNAME ) == 0 ) { | ||
| 798 | rec->reserved = TRUE; | ||
| 799 | } | ||
| 800 | else if( g_ascii_strcasecmp( tag, LDIF_TAG_FIRSTNAME ) == 0 ) { | ||
| 801 | rec->reserved = TRUE; | ||
| 802 | } | ||
| 803 | else if( g_ascii_strcasecmp( tag, LDIF_TAG_LASTNAME ) == 0 ) { | ||
| 804 | rec->reserved = TRUE; | ||
| 805 | } | ||
| 806 | else if( g_ascii_strcasecmp( tag, LDIF_TAG_NICKNAME ) == 0 || | ||
| 807 | g_ascii_strcasecmp( tag, LDIF_TAG_XNICKNAME) == 0 || | ||
| 808 | g_ascii_strcasecmp( tag, LDIF_TAG_NICKNAME2) == 0 ) { | ||
| 809 | rec->reserved = TRUE; | ||
| 810 | } | ||
| 811 | else if( g_ascii_strcasecmp( tag, LDIF_TAG_EMAIL ) == 0 ) { | ||
| 812 | rec->reserved = TRUE; | ||
| 813 | } | ||
| 814 | g_hash_table_insert( table, key, rec ); | ||
| 815 | } | ||
| 816 | node = g_slist_next( node ); | ||
| 817 | } | ||
| 818 | } | ||
| 819 | |||
| 820 | /* | ||
| 821 | * Sorted list comparison function. | ||
| 822 | */ | ||
| 823 | static int ldif_field_compare( gconstpointer ptr1, gconstpointer ptr2 ) { | ||
| 824 | const Ldif_FieldRec *rec1 = ptr1; | ||
| 825 | const Ldif_FieldRec *rec2 = ptr2; | ||
| 826 | return g_ascii_strcasecmp( rec1->tagName, rec2->tagName ); | ||
| 827 | } | ||
| 828 | |||
| 829 | /* | ||
| 830 | * Append hash table entry to list - visitor function. | ||
| 831 | */ | ||
| 832 | static void ldif_hash2list_vis( gpointer key, gpointer value, gpointer data ) { | ||
| 833 | LdifFile *ldf = data; | ||
| 834 | ldf->tempList = g_list_insert_sorted( ldf->tempList, value, ldif_field_compare ); | ||
| 835 | } | ||
| 836 | |||
| 837 | /* | ||
| 838 | * Read tag names for file data. | ||
| 839 | */ | ||
| 840 | static void ldif_read_tag_list( LdifFile *ldifFile ) { | ||
| 841 | gchar *tagName = NULL; | ||
| 842 | GSList *listTags = NULL; | ||
| 843 | gboolean flagEOF = FALSE, flagEOR = FALSE, flagMail = FALSE; | ||
| 844 | gboolean flag64 = FALSE; | ||
| 845 | long posEnd = 0L; | ||
| 846 | long posCur = 0L; | ||
| 847 | |||
| 848 | /* Clear hash table */ | ||
| 849 | g_hash_table_foreach_remove( ldifFile->hashFields, ldif_hash_free_vis, NULL ); | ||
| 850 | |||
| 851 | /* Find EOF for progress indicator */ | ||
| 852 | fseek( ldifFile->file, 0L, SEEK_END ); | ||
| 853 | posEnd = ftell( ldifFile->file ); | ||
| 854 | fseek( ldifFile->file, 0L, SEEK_SET ); | ||
| 855 | |||
| 856 | /* Process file */ | ||
| 857 | while( ! flagEOF ) { | ||
| 858 | gchar *line = ldif_get_line( ldifFile ); | ||
| 859 | |||
| 860 | posCur = ftell( ldifFile->file ); | ||
| 861 | if( ldifFile->cbProgress ) { | ||
| 862 | /* Call progress indicator */ | ||
| 863 | ( ldifFile->cbProgress ) ( ldifFile, & posEnd, & posCur ); | ||
| 864 | } | ||
| 865 | |||
| 866 | flag64 = FALSE; | ||
| 867 | if( line == NULL ) { | ||
| 868 | flagEOF = flagEOR = TRUE; | ||
| 869 | } | ||
| 870 | else if( *line == '\0' ) { | ||
| 871 | flagEOR = TRUE; | ||
| 872 | } | ||
| 873 | |||
| 874 | if( flagEOR ) { | ||
| 875 | /* EOR, Output address data */ | ||
| 876 | /* Save field list to hash table */ | ||
| 877 | if( flagMail ) { | ||
| 878 | ldif_hash_add_list( ldifFile->hashFields, listTags ); | ||
| 879 | } | ||
| 880 | mgu_free_list( listTags ); | ||
| 881 | listTags = NULL; | ||
| 882 | flagMail = FALSE; | ||
| 883 | } | ||
| 884 | if( line ) { | ||
| 885 | flagEOR = FALSE; | ||
| 886 | if( *line == ' ' ) { | ||
| 887 | /* Continuation line */ | ||
| 888 | } | ||
| 889 | else if( *line == '=' ) { | ||
| 890 | /* Base-64 encoded continuation field */ | ||
| 891 | } | ||
| 892 | else { | ||
| 893 | /* Parse line */ | ||
| 894 | tagName = ldif_get_tagname( line, &flag64 ); | ||
| 895 | if( tagName ) { | ||
| 896 | /* Add tag to list */ | ||
| 897 | listTags = g_slist_append( listTags, tagName ); | ||
| 898 | if( g_ascii_strcasecmp( tagName, LDIF_TAG_EMAIL ) == 0 ) { | ||
| 899 | flagMail = TRUE; | ||
| 900 | } | ||
| 901 | } | ||
| 902 | } | ||
| 903 | } | ||
| 904 | g_free( line ); | ||
| 905 | } | ||
| 906 | |||
| 907 | /* Release data */ | ||
| 908 | mgu_free_list( listTags ); | ||
| 909 | listTags = NULL; | ||
| 910 | } | ||
| 911 | |||
| 912 | /* | ||
| 913 | * ============================================================================ | ||
| 914 | * Read file into list. Main entry point | ||
| 915 | * Enter: ldifFile LDIF control data. | ||
| 916 | * cache Address cache to load. | ||
| 917 | * Return: Status code. | ||
| 918 | * ============================================================================ | ||
| 919 | */ | ||
| 920 | gint ldif_import_data( LdifFile *ldifFile, AddressCache *cache ) { | ||
| 921 | g_return_val_if_fail( ldifFile != NULL, MGU_BAD_ARGS ); | ||
| 922 | ldifFile->retVal = MGU_SUCCESS; | ||
| 923 | addrcache_clear( cache ); | ||
| 924 | cache->dataRead = FALSE; | ||
| 925 | ldif_open_file( ldifFile ); | ||
| 926 | if( ldifFile->retVal == MGU_SUCCESS ) { | ||
| 927 | /* Read data into the cache */ | ||
| 928 | ldif_read_file( ldifFile, cache ); | ||
| 929 | ldif_close_file( ldifFile ); | ||
| 930 | |||
| 931 | /* Mark cache */ | ||
| 932 | cache->modified = FALSE; | ||
| 933 | cache->dataRead = TRUE; | ||
| 934 | } | ||
| 935 | return ldifFile->retVal; | ||
| 936 | } | ||
| 937 | |||
| 938 | /* | ||
| 939 | * ============================================================================ | ||
| 940 | * Process entire file reading list of unique fields. List of fields may be | ||
| 941 | * accessed with the ldif_get_fieldlist() function. | ||
| 942 | * Enter: ldifFile LDIF control data. | ||
| 943 | * Return: Status code. | ||
| 944 | * ============================================================================ | ||
| 945 | */ | ||
| 946 | gint ldif_read_tags( LdifFile *ldifFile ) { | ||
| 947 | g_return_val_if_fail( ldifFile != NULL, MGU_BAD_ARGS ); | ||
| 948 | ldifFile->retVal = MGU_SUCCESS; | ||
| 949 | if( ldifFile->dirtyFlag ) { | ||
| 950 | ldif_open_file( ldifFile ); | ||
| 951 | if( ldifFile->retVal == MGU_SUCCESS ) { | ||
| 952 | /* Read data into the cache */ | ||
| 953 | ldif_read_tag_list( ldifFile ); | ||
| 954 | ldif_close_file( ldifFile ); | ||
| 955 | ldifFile->dirtyFlag = FALSE; | ||
| 956 | ldifFile->accessFlag = TRUE; | ||
| 957 | } | ||
| 958 | } | ||
| 959 | return ldifFile->retVal; | ||
| 960 | } | ||
| 961 | |||
| 962 | /* | ||
| 963 | * Return list of fields for LDIF file. | ||
| 964 | * Enter: ldifFile LdifFile object. | ||
| 965 | * Return: Linked list of Ldif_FieldRec objects. This list may be g_free'd. | ||
| 966 | * Note that the objects in the list should not be freed since they refer to | ||
| 967 | * objects inside the internal cache. These objects will be freed when | ||
| 968 | * LDIF file object is freed. | ||
| 969 | */ | ||
| 970 | GList *ldif_get_fieldlist( LdifFile *ldifFile ) { | ||
| 971 | GList *list = NULL; | ||
| 972 | |||
| 973 | g_return_val_if_fail( ldifFile != NULL, NULL ); | ||
| 974 | if( ldifFile->hashFields ) { | ||
| 975 | ldifFile->tempList = NULL; | ||
| 976 | g_hash_table_foreach( ldifFile->hashFields, ldif_hash2list_vis, ldifFile ); | ||
| 977 | list = ldifFile->tempList; | ||
| 978 | ldifFile->tempList = NULL; | ||
| 979 | } | ||
| 980 | return list; | ||
| 981 | } | ||
| 982 | |||
| 983 | /* | ||
| 984 | * End of Source. | ||
| 985 | */ | ||
| 986 | |||
