addritem.c (31354B)
1 /* 2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client 3 * Copyright (C) 2001-2017 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 * General primitive address item objects. 21 */ 22 23 #include <glib.h> 24 #include <stdio.h> 25 #include <string.h> 26 27 #include "defs.h" 28 #include "file-utils.h" 29 #include "utils.h" 30 #include "addritem.h" 31 #include "mgutils.h" 32 #include "codeconv.h" 33 34 /** 35 * Create new email address item. 36 * \return Initialized email item. 37 */ 38 ItemEMail *addritem_create_item_email( void ) { 39 ItemEMail *item; 40 item = g_new0( ItemEMail, 1 ); 41 ADDRITEM_TYPE(item) = ITEMTYPE_EMAIL; 42 ADDRITEM_ID(item) = NULL; 43 ADDRITEM_NAME(item) = NULL; 44 ADDRITEM_PARENT(item) = NULL; 45 ADDRITEM_SUBTYPE(item) = 0; 46 item->address = NULL; 47 item->remarks = NULL; 48 return item; 49 } 50 51 /** 52 * Create a shallow copy of specified email address item. 53 * \param item E-Mail to copy. 54 * \return Copy of email, or <i>NULL</i> if null argument supplied. 55 */ 56 ItemEMail *addritem_copy_item_email( ItemEMail *item ) { 57 ItemEMail *itemNew = NULL; 58 if( item ) { 59 itemNew = addritem_create_item_email(); 60 ADDRITEM_NAME(itemNew) = g_strdup( ADDRITEM_NAME(item) ); 61 itemNew->address = g_strdup( item->address ); 62 itemNew->remarks = g_strdup( item->remarks ); 63 } 64 return itemNew; 65 } 66 67 /** 68 * Create a full copy (deep copy) of specified email address item. 69 * \param item E-Mail to copy. 70 * \return Copy of email. 71 */ 72 ItemEMail *addritem_copyfull_item_email( ItemEMail *item ) { 73 ItemEMail *itemNew = NULL; 74 if( item ) { 75 itemNew = addritem_create_item_email(); 76 ADDRITEM_ID(itemNew) = g_strdup( ADDRITEM_ID(item) ); 77 ADDRITEM_NAME(itemNew) = g_strdup( ADDRITEM_NAME(item) ); 78 ADDRITEM_PARENT(itemNew) = ADDRITEM_PARENT(item); 79 itemNew->address = g_strdup( item->address ); 80 itemNew->remarks = g_strdup( item->remarks ); 81 } 82 return itemNew; 83 } 84 85 /** 86 * Specify alias for email. 87 * \param email E-Mail item. 88 * \param value Alias. 89 */ 90 void addritem_email_set_alias( ItemEMail *email, const gchar *value ) { 91 ADDRITEM_NAME(email) = mgu_replace_string( ADDRITEM_NAME(email), value ); 92 } 93 94 /** 95 * Specify address for email. 96 * \param email E-Mail item. 97 * \param value Address. 98 */ 99 void addritem_email_set_address( ItemEMail *email, const gchar *value ) { 100 email->address = mgu_replace_string( email->address, value ); 101 } 102 103 /** 104 * Specify remarks for email. 105 * \param email E-Mail item. 106 * \param value Remarks. 107 */ 108 void addritem_email_set_remarks( ItemEMail *email, const gchar *value ) { 109 email->remarks = mgu_replace_string( email->remarks, value ); 110 } 111 112 /** 113 * Free address item email object. 114 * \param item E-Mail item to free. 115 */ 116 void addritem_free_item_email( ItemEMail *item ) { 117 cm_return_if_fail( item != NULL ); 118 119 /* Free internal stuff */ 120 g_free( ADDRITEM_ID(item) ); 121 g_free( ADDRITEM_NAME(item) ); 122 g_free( item->address ); 123 g_free( item->remarks ); 124 125 ADDRITEM_OBJECT(item)->type = ITEMTYPE_NONE; 126 ADDRITEM_ID(item) = NULL; 127 ADDRITEM_NAME(item) = NULL; 128 ADDRITEM_PARENT(item) = NULL; 129 ADDRITEM_SUBTYPE(item) = 0; 130 item->address = NULL; 131 item->remarks = NULL; 132 g_free( item ); 133 } 134 135 /** 136 * Create new attribute object. 137 * \return Initialized attribute object. 138 */ 139 UserAttribute *addritem_create_attribute( void ) { 140 UserAttribute *item; 141 item = g_new0( UserAttribute, 1 ); 142 item->uid = NULL; 143 item->name = NULL; 144 item->value = NULL; 145 return item; 146 } 147 148 /** 149 * Create copy (deep copy) of specified attribute. 150 * \param item Attribute to copy. 151 * \return Copy of attribute, or <i>NULL</i> if null argument supplied. 152 */ 153 UserAttribute *addritem_copy_attribute( UserAttribute *item ) { 154 UserAttribute *itemNew = NULL; 155 if( item ) { 156 itemNew = addritem_create_attribute(); 157 itemNew->uid = g_strdup( item->uid ); 158 itemNew->name = g_strdup( item->name ); 159 itemNew->value = g_strdup( item->value ); 160 } 161 return itemNew; 162 } 163 164 /** 165 * Specify ID for attribute. 166 * \param item Attribute object. 167 * \param value ID. 168 */ 169 void addritem_attrib_set_id( UserAttribute *item, const gchar *value ) { 170 cm_return_if_fail( item != NULL ); 171 item->uid = mgu_replace_string( item->uid, value ); 172 } 173 174 /** 175 * Specify name for attribute. 176 * \param item Attribute object. 177 * \param value Name. 178 */ 179 void addritem_attrib_set_name( UserAttribute *item, const gchar *value ) { 180 cm_return_if_fail( item != NULL ); 181 item->name = mgu_replace_string( item->name, value ); 182 } 183 184 /** 185 * Specify value for attribute. 186 * \param item Attribute object. 187 * \param value Value. 188 */ 189 void addritem_attrib_set_value( UserAttribute *item, const gchar *value ) { 190 cm_return_if_fail( item != NULL ); 191 item->value = mgu_replace_string( item->value, value ); 192 } 193 194 /** 195 * Free user attribute. 196 * \param item Attribute object to free. 197 */ 198 void addritem_free_attribute( UserAttribute *item ) { 199 cm_return_if_fail( item != NULL ); 200 g_free( item->uid ); 201 g_free( item->name ); 202 g_free( item->value ); 203 item->uid = NULL; 204 item->name = NULL; 205 item->value = NULL; 206 g_free( item ); 207 } 208 209 /** 210 * Create new address book person. 211 * \return Initialized person object. 212 */ 213 ItemPerson *addritem_create_item_person( void ) { 214 ItemPerson *person; 215 person = g_new0( ItemPerson, 1 ); 216 ADDRITEM_TYPE(person) = ITEMTYPE_PERSON; 217 ADDRITEM_ID(person) = NULL; 218 ADDRITEM_NAME(person) = NULL; 219 ADDRITEM_PARENT(person) = NULL; 220 ADDRITEM_SUBTYPE(person) = 0; 221 person->picture = NULL; 222 person->firstName = NULL; 223 person->lastName = NULL; 224 person->nickName = NULL; 225 person->listEMail = NULL; 226 person->listAttrib = NULL; 227 person->externalID = NULL; 228 person->isOpened = FALSE; 229 person->status = NONE; 230 return person; 231 } 232 233 /** 234 * Create a shallow copy of address book person object. 235 * \param item Person to copy. 236 * \return Copy of person, or <i>NULL</i> if null argument supplied. 237 */ 238 ItemPerson *addritem_copy_item_person( ItemPerson *item ) { 239 ItemPerson *itemNew; 240 241 itemNew = NULL; 242 if( item ) { 243 itemNew = addritem_create_item_person(); 244 ADDRITEM_NAME(itemNew) = g_strdup( ADDRITEM_NAME(item) ); 245 itemNew->picture = g_strdup( ADDRITEM_ID(itemNew) ); 246 itemNew->firstName = g_strdup( item->firstName ); 247 itemNew->lastName = g_strdup( item->lastName ); 248 itemNew->nickName = g_strdup( item->nickName ); 249 itemNew->externalID = g_strdup( item->externalID ); 250 itemNew->status = item->status; 251 } 252 return itemNew; 253 } 254 255 /** 256 * Specify picture for person object. 257 * \param person Person object. 258 * \param value Picture. 259 */ 260 void addritem_person_set_picture( ItemPerson *person, const gchar *value ) { 261 if (!value || g_utf8_validate(value, -1, NULL)) 262 person->picture = mgu_replace_string( person->picture, value ); 263 else { 264 gchar *out = conv_codeset_strdup(value, 265 conv_get_locale_charset_str_no_utf8(), 266 CS_INTERNAL); 267 if (out) 268 person->picture = mgu_replace_string( person->picture, out ); 269 g_free(out); 270 } 271 } 272 273 size_t addritem_person_get_picture(char *dst, ItemPerson *person) { 274 if (!person->picture) 275 return 0; 276 char buf[PATH_MAX]; 277 snprintf(buf, sizeof(buf), "%s/%s/%s.png", get_rc_dir(), ADDRBOOK_DIR, person->picture); 278 return strlcpy(dst, buf, sizeof(dst)); 279 } 280 281 int addritem_person_remove_picture(ItemPerson *person) { 282 if (!person->picture) 283 return 0; 284 285 char path[PATH_MAX]; 286 snprintf(path, sizeof(path), "%s/%s/%s", get_rc_dir(), ADDRBOOK_DIR, person->picture); 287 int ret = unlink(path); 288 free(person->picture); 289 person->picture = NULL; 290 return ret; 291 } 292 293 /** 294 * Specify first name for person object. 295 * \param person Person object. 296 * \param value Name. 297 */ 298 void addritem_person_set_first_name( ItemPerson *person, const gchar *value ) { 299 if (!value || g_utf8_validate(value, -1, NULL)) 300 person->firstName = mgu_replace_string( person->firstName, value ); 301 else { 302 gchar *out = conv_codeset_strdup(value, 303 conv_get_locale_charset_str_no_utf8(), 304 CS_INTERNAL); 305 if (out) 306 person->firstName = mgu_replace_string( person->firstName, out ); 307 g_free(out); 308 } 309 } 310 311 /** 312 * Specify last name for person object. 313 * \param person Person object. 314 * \param value name. 315 */ 316 void addritem_person_set_last_name( ItemPerson *person, const gchar *value ) { 317 if (!value || g_utf8_validate(value, -1, NULL)) 318 person->lastName = mgu_replace_string( person->lastName, value ); 319 else { 320 gchar *out = conv_codeset_strdup(value, 321 conv_get_locale_charset_str_no_utf8(), 322 CS_INTERNAL); 323 if (out) 324 person->lastName = mgu_replace_string( person->lastName, out ); 325 g_free(out); 326 } 327 } 328 329 /** 330 * Specify nick name for person object. 331 * \param person Person object. 332 * \param value name. 333 */ 334 void addritem_person_set_nick_name( ItemPerson *person, const gchar *value ) { 335 if (!value || g_utf8_validate(value, -1, NULL)) 336 person->nickName = mgu_replace_string( person->nickName, value ); 337 else { 338 gchar *out = conv_codeset_strdup(value, 339 conv_get_locale_charset_str_no_utf8(), 340 CS_INTERNAL); 341 if (out) 342 person->nickName = mgu_replace_string( person->nickName, out ); 343 g_free(out); 344 } 345 } 346 347 /** 348 * Specify common name for person object. 349 * \param person Person object. 350 * \param value name. 351 */ 352 void addritem_person_set_common_name( ItemPerson *person, const gchar *value ) { 353 if (!value || g_utf8_validate(value, -1, NULL)) 354 ADDRITEM_NAME(person) = mgu_replace_string( ADDRITEM_NAME(person), value ); 355 else { 356 gchar *out = conv_codeset_strdup(value, 357 conv_get_locale_charset_str_no_utf8(), 358 CS_INTERNAL); 359 if (out) 360 ADDRITEM_NAME(person) = mgu_replace_string( ADDRITEM_NAME(person), out ); 361 g_free(out); 362 } 363 } 364 365 /** 366 * Specify external ID for person object. 367 * \param person Person object. 368 * \param value ID. 369 */ 370 void addritem_person_set_external_id( ItemPerson *person, const gchar *value ) { 371 person->externalID = mgu_replace_string( person->externalID, value ); 372 } 373 374 /** 375 * Specify value of open indicator for person object. This is typically used to 376 * simplify open/close folders in the address book GUI. 377 * \param person Person object. 378 * \param value Value for indicator. Set to <i>TRUE</i> if opened. 379 */ 380 void addritem_person_set_opened( ItemPerson *person, const gboolean value ) { 381 person->isOpened = value; 382 } 383 384 /** 385 * Free linked list of item addresses; both addresses and the list are freed. 386 * It is assumed that addresses are *NOT* contained within some other 387 * container. 388 * \param list List of addresses to be freed. 389 */ 390 void addritem_free_list_email( GList *list ) { 391 GList *node = list; 392 while( node ) { 393 ItemEMail *email = node->data; 394 395 addritem_free_item_email( email ); 396 node->data = NULL; 397 node = g_list_next( node ); 398 } 399 g_list_free( list ); 400 list = NULL; 401 } 402 403 /** 404 * Free linked list of attributes; both attributes and the list are freed. 405 * It is assumed that attributes are *NOT* contained within some other 406 * container. 407 * \param list List of attributes to be freed. 408 */ 409 void addritem_free_list_attribute( GList *list ) { 410 GList *node = list; 411 while( node ) { 412 addritem_free_attribute( node->data ); 413 node->data = NULL; 414 node = g_list_next( node ); 415 } 416 g_list_free( list ); 417 } 418 419 /** 420 * Free address person object. 421 * \param person Person object to free. 422 */ 423 void addritem_free_item_person( ItemPerson *person ) { 424 cm_return_if_fail( person != NULL ); 425 426 /* Free internal stuff */ 427 g_free( ADDRITEM_ID(person) ); 428 g_free( ADDRITEM_NAME(person) ); 429 g_free( person->picture ); 430 g_free( person->firstName ); 431 g_free( person->lastName ); 432 g_free( person->nickName ); 433 g_free( person->externalID ); 434 g_list_free( person->listEMail ); 435 addritem_free_list_attribute( person->listAttrib ); 436 437 ADDRITEM_OBJECT(person)->type = ITEMTYPE_NONE; 438 ADDRITEM_ID(person) = NULL; 439 ADDRITEM_NAME(person) = NULL; 440 ADDRITEM_PARENT(person) = NULL; 441 ADDRITEM_SUBTYPE(person) = 0; 442 person->picture = NULL; 443 person->firstName = NULL; 444 person->lastName = NULL; 445 person->nickName = NULL; 446 person->externalID = NULL; 447 person->listEMail = NULL; 448 person->listAttrib = NULL; 449 450 g_free( person ); 451 } 452 453 /** 454 * Print E-Mail address object for debug. 455 * \param item Item to print. 456 * \param stream Output stream. 457 */ 458 void addritem_print_item_email( ItemEMail *item, FILE *stream ) { 459 cm_return_if_fail( item != NULL ); 460 fprintf( stream, "\t\tt/id: %d : '%s'\n", ADDRITEM_TYPE(item), ADDRITEM_ID(item) ); 461 fprintf( stream, "\t\tsubty: %d\n", ADDRITEM_SUBTYPE(item) ); 462 fprintf( stream, "\t\talis: '%s'\n", ADDRITEM_NAME(item) ); 463 fprintf( stream, "\t\taddr: '%s'\n", item->address ); 464 fprintf( stream, "\t\trems: '%s'\n", item->remarks ); 465 fprintf( stream, "\t\t---\n" ); 466 } 467 468 /** 469 * Print user attribute object for debug. 470 * \param item Attribute to print. 471 * \param stream Output stream. 472 */ 473 static void addritem_print_attribute( UserAttribute *item, FILE *stream ) { 474 cm_return_if_fail( item != NULL ); 475 fprintf( stream, "\t\tuid : '%s'\n", item->uid ); 476 fprintf( stream, "\t\tname : '%s'\n", item->name ); 477 fprintf( stream, "\t\tvalue: '%s'\n", item->value ); 478 fprintf( stream, "\t\t---\n" ); 479 } 480 481 /** 482 * Print person item for debug. 483 * \param person Person to print. 484 * \param stream Output stream. 485 */ 486 void addritem_print_item_person( ItemPerson *person, FILE *stream ) { 487 GList *node; 488 cm_return_if_fail( person != NULL ); 489 fprintf( stream, "Person:\n" ); 490 fprintf( stream, "\tt/uid: %d : '%s'\n", ADDRITEM_TYPE(person), ADDRITEM_ID(person) ); 491 fprintf( stream, "\tsubty: %d\n", ADDRITEM_SUBTYPE(person) ); 492 fprintf( stream, "\tcommn: '%s'\n", ADDRITEM_NAME(person) ); 493 fprintf( stream, "\tphoto: '%s'\n", person->picture ); 494 fprintf( stream, "\tfirst: '%s'\n", person->firstName ); 495 fprintf( stream, "\tlast : '%s'\n", person->lastName ); 496 fprintf( stream, "\tnick : '%s'\n", person->nickName ); 497 fprintf( stream, "\textID: '%s'\n", person->externalID ); 498 fprintf( stream, "\teMail:\n" ); 499 fprintf( stream, "\t---\n" ); 500 node = person->listEMail; 501 while( node ) { 502 addritem_print_item_email( node->data, stream ); 503 node = g_list_next( node ); 504 } 505 fprintf( stream, "\tuAttr:\n" ); 506 fprintf( stream, "\t---\n" ); 507 node = person->listAttrib; 508 while( node ) { 509 addritem_print_attribute( node->data, stream ); 510 node = g_list_next( node ); 511 } 512 gchar *current_status; 513 switch (person->status) { 514 case NONE: current_status = g_strdup("Unchanged"); break; 515 case ADD_ENTRY: current_status = g_strdup("New"); break; 516 case UPDATE_ENTRY: current_status = g_strdup("Updated"); break; 517 case DELETE_ENTRY: current_status = g_strdup("Deleted"); break; 518 default: current_status = g_strdup("Unknown"); 519 } 520 fprintf( stream, "\t\tStatus: %s\n", current_status ); 521 if ( current_status ) 522 g_free(current_status); 523 fprintf( stream, "\t===\n" ); 524 } 525 526 /** 527 * Add E-Mail address object to person. 528 * \param person Person. 529 * \param email E-Mail object to add. 530 * \return <i>TRUE</i> if E-Mail added. 531 */ 532 gboolean addritem_person_add_email( ItemPerson *person, ItemEMail *email ) { 533 GList *node; 534 535 cm_return_val_if_fail( person != NULL, FALSE ); 536 cm_return_val_if_fail( email != NULL, FALSE ); 537 538 node = person->listEMail; 539 while( node ) { 540 if( node->data == email ) return FALSE; 541 node = g_list_next( node ); 542 } 543 person->listEMail = g_list_append( person->listEMail, email ); 544 ADDRITEM_PARENT(email) = ADDRITEM_OBJECT(person); 545 return TRUE; 546 } 547 548 /** 549 * Remove email address for specified person. 550 * \param person Person. 551 * \param email EMail to remove. 552 * \return EMail object, or <i>NULL</i> if not found. Note that object should 553 * still be freed after calling this method. 554 */ 555 ItemEMail *addritem_person_remove_email( ItemPerson *person, ItemEMail *email ) { 556 gboolean found = FALSE; 557 GList *node; 558 559 cm_return_val_if_fail( person != NULL, NULL ); 560 if( email == NULL ) return NULL; 561 562 /* Look for email */ 563 node = person->listEMail; 564 while( node ) { 565 if( node-> data == email ) { 566 found = TRUE; 567 break; 568 } 569 node = g_list_next( node ); 570 } 571 572 if( found ) { 573 /* Remove email from person's address list */ 574 if( person->listEMail ) { 575 person->listEMail = g_list_remove( person->listEMail, email ); 576 } 577 /* Unlink reference to person. */ 578 ADDRITEM_PARENT(email) = NULL; 579 return email; 580 } 581 return NULL; 582 } 583 584 /** 585 * Add user attribute to specified person. 586 * \param person Person. 587 * \param attrib Attribute to add. 588 * \return <i>TRUE</i> if item added. 589 */ 590 void addritem_person_add_attribute( 591 ItemPerson *person, UserAttribute *attrib ) 592 { 593 cm_return_if_fail( person != NULL ); 594 person->listAttrib = g_list_append( person->listAttrib, attrib ); 595 } 596 597 /** 598 * Remove user attribute from specified person. 599 * \param person Person. 600 * \param attrib Attribute to remove. 601 */ 602 void addritem_person_remove_attribute( ItemPerson *person, const gchar *attrib ) { 603 cm_return_if_fail( person != NULL && attrib != NULL ); 604 GList *attrib_list; 605 606 attrib_list = person->listAttrib; 607 while (attrib_list) { 608 UserAttribute *user_attrib = attrib_list->data; 609 if (strcmp(user_attrib->name, attrib) == 0) { 610 person->listAttrib = g_list_remove(person->listAttrib, (gconstpointer) user_attrib); 611 break; 612 } 613 attrib_list = g_list_next(attrib_list); 614 } 615 } 616 617 618 /** 619 * Create new address book group object. 620 * \return Initialized group object. 621 */ 622 ItemGroup *addritem_create_item_group( void ) { 623 ItemGroup *group; 624 625 group = g_new0( ItemGroup, 1 ); 626 ADDRITEM_TYPE(group) = ITEMTYPE_GROUP; 627 ADDRITEM_ID(group) = NULL; 628 ADDRITEM_NAME(group) = NULL; 629 ADDRITEM_PARENT(group) = NULL; 630 ADDRITEM_SUBTYPE(group) = 0; 631 group->remarks = NULL; 632 group->listEMail = NULL; 633 return group; 634 } 635 636 /** 637 * Copy (deep copy) address book group. 638 * \param item Group to copy. 639 * \return Copy of the group object, or <i>NULL</i> if null argument supplied. 640 */ 641 ItemGroup *addritem_copy_item_group( ItemGroup *item ) { 642 ItemGroup *itemNew; 643 644 itemNew = NULL; 645 if( item ) { 646 itemNew = addritem_create_item_group(); 647 ADDRITEM_NAME(itemNew) = g_strdup( ADDRITEM_NAME(item) ); 648 itemNew->remarks = g_strdup( item->remarks ); 649 } 650 return itemNew; 651 } 652 653 /** 654 * Specify name to be used for group. 655 * \param group Group object. 656 * \param value Name of group. 657 */ 658 void addritem_group_set_name( ItemGroup *group, const gchar *value ) { 659 ADDRITEM_NAME(group) = mgu_replace_string( ADDRITEM_NAME(group), value ); 660 } 661 662 /** 663 * Free address group object. 664 * \param group Group to free. 665 */ 666 void addritem_free_item_group( ItemGroup *group ) { 667 cm_return_if_fail( group != NULL ); 668 669 /* Free internal stuff */ 670 g_free( ADDRITEM_ID(group) ); 671 g_free( ADDRITEM_NAME(group) ); 672 g_free( group->remarks ); 673 g_list_free( group->listEMail ); 674 675 ADDRITEM_TYPE(group) = ITEMTYPE_NONE; 676 ADDRITEM_ID(group) = NULL; 677 ADDRITEM_NAME(group) = NULL; 678 ADDRITEM_PARENT(group) = NULL; 679 ADDRITEM_SUBTYPE(group) = 0; 680 group->remarks = NULL; 681 group->listEMail = NULL; 682 683 g_free( group ); 684 } 685 686 /** 687 * Add EMail address to group. Note that a reference to an E-Mail item is 688 * added to a group. A person object is the only container that for an 689 * address. 690 * \param group Group. 691 * \param email E-Mail object. 692 * \return <i>TRUE</i> if email item added. 693 */ 694 gboolean addritem_group_add_email( ItemGroup *group, ItemEMail *email ) { 695 GList *node; 696 697 cm_return_val_if_fail( group != NULL, FALSE ); 698 cm_return_val_if_fail( email != NULL, FALSE ); 699 700 node = group->listEMail; 701 while( node ) { 702 if( node->data == email ) return FALSE; 703 node = g_list_next( node ); 704 } 705 group->listEMail = g_list_append( group->listEMail, email ); 706 return TRUE; 707 } 708 709 /** 710 * Remove person object for specified group. 711 * \param group Group from which to remove address. 712 * \param email EMail to remove 713 * \return EMail object, or <i>NULL if email not found in group. Note that 714 * this object is referenced (linked) to a group and should *NOT* 715 * be freed. An E-Mail object object should only be freed after 716 * removing from a person. 717 */ 718 ItemPerson *addritem_folder_remove_person( ItemFolder *group, ItemPerson *person ) { 719 if( group && person ) { 720 GList *node = group->listPerson; 721 while( node ) { 722 if( node->data == person ) { 723 group->listPerson = g_list_remove( group->listPerson, person ); 724 return person; 725 } 726 node = g_list_next( node ); 727 } 728 } 729 return NULL; 730 } 731 732 /** 733 * Print address group item for debug. 734 * \param group Group to print. 735 * \param stream Output stream. 736 */ 737 void addritem_print_item_group( ItemGroup *group, FILE *stream ) { 738 GList *node; 739 ItemPerson *person; 740 ItemEMail *item; 741 cm_return_if_fail( group != NULL ); 742 fprintf( stream, "Group:\n" ); 743 fprintf( stream, "\tt/u: %d : '%s'\n", ADDRITEM_TYPE(group), ADDRITEM_ID(group) ); 744 fprintf( stream, "\tsub: %d\n", ADDRITEM_SUBTYPE(group) ); 745 fprintf( stream, "\tgrp: '%s'\n", ADDRITEM_NAME(group) ); 746 fprintf( stream, "\trem: '%s'\n", group->remarks ); 747 fprintf( stream, "\t---\n" ); 748 node = group->listEMail; 749 while( node ) { 750 item = node->data; 751 person = ( ItemPerson * ) ADDRITEM_PARENT(item); 752 if( person ) { 753 fprintf( stream, "\t\tpid : '%s'\n", ADDRITEM_ID(person) ); 754 fprintf( stream, "\t\tcomn: '%s'\n", ADDRITEM_NAME(person) ); 755 } 756 else { 757 fprintf( stream, "\t\tpid : ???\n" ); 758 fprintf( stream, "\t\tcomn: ???\n" ); 759 } 760 addritem_print_item_email( item, stream ); 761 node = g_list_next( node ); 762 } 763 fprintf( stream, "\t***\n" ); 764 } 765 766 /** 767 * Create new address folder. 768 * \return Initialized address folder object. 769 */ 770 ItemFolder *addritem_create_item_folder( void ) { 771 ItemFolder *folder; 772 folder = g_new0( ItemFolder, 1 ); 773 if (!folder) 774 g_error("could not create new itemFolder"); 775 ADDRITEM_TYPE(folder) = ITEMTYPE_FOLDER; 776 ADDRITEM_ID(folder) = NULL; 777 ADDRITEM_NAME(folder) = NULL; 778 ADDRITEM_PARENT(folder) = NULL; 779 ADDRITEM_SUBTYPE(folder) = 0; 780 folder->remarks = NULL; 781 folder->isRoot = FALSE; 782 folder->listItems = NULL; 783 folder->listFolder = NULL; 784 folder->listPerson = NULL; 785 folder->listGroup = NULL; 786 folder->folderType = ADDRFOLDER_NONE; 787 folder->folderData = NULL; 788 folder->isHidden = FALSE; 789 return folder; 790 } 791 792 /** 793 * Copy address book folder. Note that only the folder and not its contents are 794 * copied. 795 * \param item Folder to copy. 796 * \return A copy of the folder, or <i>NULL</i> if null argument supplied. 797 */ 798 ItemFolder *addritem_copy_item_folder( ItemFolder *item ) { 799 ItemFolder *itemNew = NULL; 800 801 if( item ) { 802 itemNew = addritem_create_item_folder(); 803 ADDRITEM_NAME(itemNew) = g_strdup( ADDRITEM_NAME(item) ); 804 itemNew->folderType = item->folderType; 805 } else 806 g_error("could not create a copy of a null itemFolder"); 807 return itemNew; 808 } 809 810 /** 811 * Specify name to be used for folder. 812 * \param folder Folder. 813 * \param value Name. 814 */ 815 void addritem_folder_set_name( ItemFolder *folder, const gchar *value ) { 816 ADDRITEM_NAME(folder) = mgu_replace_string( ADDRITEM_NAME(folder), value ); 817 } 818 819 /** 820 * Specify remarks to be used for folder. 821 * \param folder Folder. 822 * \param value Remarks. 823 */ 824 void addritem_folder_set_remarks( ItemFolder *folder, const gchar *value ) { 825 folder->remarks = mgu_replace_string( folder->remarks, value ); 826 } 827 828 /** 829 * Specify visibility of folder. 830 * \param folder Folder. 831 * \param value Set to <code>TRUE</code> to hide folder. 832 */ 833 void addritem_folder_set_hidden( ItemFolder *folder, const gboolean value ) { 834 folder->isHidden = value; 835 } 836 837 /** 838 * Free address folder. Note: this does not free up the lists of children 839 * (folders, groups and person). This should be done prior to calling this 840 * function. 841 * \param folder Folder to free. 842 */ 843 void addritem_free_item_folder( ItemFolder *folder ) { 844 cm_return_if_fail( folder != NULL ); 845 846 /* Free internal stuff */ 847 g_free( ADDRITEM_ID(folder) ); 848 g_free( ADDRITEM_NAME(folder) ); 849 g_free( folder->remarks ); 850 g_list_free( folder->listItems ); 851 852 ADDRITEM_TYPE(folder) = ITEMTYPE_NONE; 853 ADDRITEM_ID(folder) = NULL; 854 ADDRITEM_NAME(folder) = NULL; 855 ADDRITEM_PARENT(folder) = NULL; 856 ADDRITEM_SUBTYPE(folder) = 0; 857 folder->isRoot = FALSE; 858 folder->remarks = NULL; 859 folder->listItems = NULL; 860 folder->listFolder = NULL; 861 folder->listGroup = NULL; 862 folder->listPerson = NULL; 863 folder->folderType = ADDRFOLDER_NONE; 864 folder->folderData = NULL; 865 folder->isHidden = FALSE; 866 867 g_free( folder ); 868 } 869 870 /** 871 * Add person into folder. 872 * \param folder Folder. 873 * \param item Person to add. 874 * \return <i>TRUE</i> if person added. 875 */ 876 gboolean addritem_folder_add_person( ItemFolder *folder, ItemPerson *item ) { 877 cm_return_val_if_fail( folder != NULL, FALSE ); 878 cm_return_val_if_fail( item != NULL, FALSE ); 879 880 folder->listPerson = g_list_append( folder->listPerson, item ); 881 ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder); 882 return TRUE; 883 } 884 885 /** 886 * Add folder into folder. 887 * \param folder Folder. 888 * \param item Folder to add. 889 * \return <i>TRUE</i> if folder added. 890 */ 891 gboolean addritem_folder_add_folder( ItemFolder *folder, ItemFolder *item ) { 892 cm_return_val_if_fail( folder != NULL, FALSE ); 893 cm_return_val_if_fail( item != NULL, FALSE ); 894 895 folder->listFolder = g_list_append( folder->listFolder, item ); 896 ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder); 897 return TRUE; 898 } 899 900 /** 901 * Add group into folder. 902 * \param folder Folder. 903 * \param item Group to add. 904 * \return <i>TRUE</i> if group added. 905 */ 906 gboolean addritem_folder_add_group( ItemFolder *folder, ItemGroup *item ) { 907 cm_return_val_if_fail( folder != NULL, FALSE ); 908 cm_return_val_if_fail( item != NULL, FALSE ); 909 910 folder->listGroup = g_list_append( folder->listGroup, item ); 911 ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder); 912 return TRUE; 913 } 914 915 /** 916 * Print address folder item contents for debug. 917 * \param folder Folder to process. 918 * \param stream Output stream. 919 */ 920 void addritem_print_item_folder( ItemFolder *folder, FILE *stream ) { 921 GList *node; 922 /* ItemPerson *person; */ 923 ItemFolder *parent; 924 925 cm_return_if_fail( folder != NULL ); 926 927 fprintf( stream, "Folder:\n" ); 928 fprintf( stream, "\tt/u: %d : '%s'\n", ADDRITEM_TYPE(folder), ADDRITEM_ID(folder) ); 929 fprintf( stream, "\tsub: %d\n", ADDRITEM_SUBTYPE(folder) ); 930 fprintf( stream, "\tnam: '%s'\n", ADDRITEM_NAME(folder) ); 931 fprintf( stream, "\trem: '%s'\n", folder->remarks ); 932 fprintf( stream, "\ttyp: %d\n", folder->folderType ); 933 fprintf( stream, "\thid: %s\n", folder->isHidden ? "hidden" : "visible" ); 934 fprintf( stream, "\t---\n" ); 935 parent = ( ItemFolder * ) ADDRITEM_PARENT(folder); 936 if( parent ) { 937 fprintf( stream, "\tpar: %s : %s\n", ADDRITEM_ID(parent), ADDRITEM_NAME(parent) ); 938 } 939 else { 940 fprintf( stream, "\tpar: NULL\n" ); 941 } 942 node = folder->listFolder; 943 while( node ) { 944 AddrItemObject *aio = node->data; 945 if( aio ) { 946 if( aio->type == ITEMTYPE_FOLDER ) { 947 ItemFolder *item = ( ItemFolder * ) aio; 948 addritem_print_item_folder( item, stream ); 949 } 950 } 951 else { 952 fprintf( stream, "\t\tpid : ???\n" ); 953 } 954 955 node = g_list_next( node ); 956 } 957 958 node = folder->listPerson; 959 while( node ) { 960 AddrItemObject *aio = node->data; 961 if( aio ) { 962 if( aio->type == ITEMTYPE_PERSON ) { 963 ItemPerson *item = ( ItemPerson * ) aio; 964 addritem_print_item_person( item, stream ); 965 } 966 } 967 else { 968 fprintf( stream, "\t\tpid : ???\n" ); 969 } 970 971 node = g_list_next( node ); 972 } 973 974 node = folder->listGroup; 975 while( node ) { 976 AddrItemObject *aio = node->data; 977 if( aio ) { 978 if( aio->type == ITEMTYPE_GROUP ) { 979 ItemGroup *item = ( ItemGroup * ) aio; 980 addritem_print_item_group( item, stream ); 981 } 982 } 983 else { 984 fprintf( stream, "\t\tpid : ???\n" ); 985 } 986 node = g_list_next( node ); 987 } 988 fprintf( stream, "\t###\n" ); 989 } 990 991 /** 992 * Return link list of persons for specified folder. Note that the list contains 993 * references to items and should be g_free() when done. Do *NOT* attempt to use the 994 * addritem_free_xxx() functions... this will destroy the addressbook data! 995 * 996 * \param folder Folder to process. 997 * \return List of items, or <i>NULL</i> if none. 998 */ 999 GList *addritem_folder_get_person_list( ItemFolder *folder ) { 1000 GList *list = NULL; 1001 GList *node = NULL; 1002 1003 cm_return_val_if_fail( folder != NULL, NULL ); 1004 1005 node = folder->listPerson; 1006 while( node ) { 1007 ItemPerson *person = node->data; 1008 list = g_list_prepend( list, person ); 1009 node = g_list_next( node ); 1010 } 1011 return g_list_reverse(list); 1012 } 1013 1014 /** 1015 * Return link list of groups for specified folder. Note that the list contains 1016 * references to items and should be g_free() when done. Do *NOT* attempt to use the 1017 * addritem_free_xxx() functions... this will destroy the addressbook data! 1018 * 1019 * \param folder Folder to process. 1020 * \return List of items, or <i>NULL</i> if none. 1021 */ 1022 GList *addritem_folder_get_group_list( ItemFolder *folder ) { 1023 GList *list = NULL; 1024 GList *node = NULL; 1025 1026 cm_return_val_if_fail( folder != NULL, NULL ); 1027 1028 node = folder->listGroup; 1029 while( node ) { 1030 ItemGroup *group = node->data; 1031 list = g_list_prepend( list, group ); 1032 node = g_list_next( node ); 1033 } 1034 return g_list_reverse(list); 1035 } 1036 1037 /** 1038 * Parse first and last names for person from common name. 1039 * \param person Person to process. 1040 */ 1041 void addritem_parse_first_last( ItemPerson *person ) { 1042 gchar *name; 1043 gchar *fName, *lName; 1044 gchar *p; 1045 gint len, i; 1046 1047 cm_return_if_fail( person != NULL ); 1048 1049 name = ADDRITEM_NAME(person); 1050 if( name == NULL ) return; 1051 1052 fName = NULL; 1053 lName = NULL; 1054 p = strchr( name, ',' ); 1055 if( p ) { 1056 len = ( size_t ) ( p - name ); 1057 lName = g_strndup( name, len ); 1058 fName = g_strdup( p + 1 ); 1059 } 1060 else { 1061 /* Other way around */ 1062 i = strlen( name ); 1063 while( i >= 0 ) { 1064 if( name[i] == ' ' ) { 1065 fName = g_strndup( name, i ); 1066 lName = g_strdup( &name[i] ); 1067 break; 1068 } 1069 i--; 1070 } 1071 if( fName == NULL ) { 1072 fName = g_strdup( name ); 1073 } 1074 } 1075 1076 g_free( person->firstName ); 1077 person->firstName = fName; 1078 if( person->firstName ) 1079 g_strstrip( person->firstName ); 1080 1081 g_free( person->lastName ); 1082 person->lastName = lName; 1083 if( person->lastName ) 1084 g_strstrip( person->lastName ); 1085 } 1086 1087 /** 1088 * Build a path of all ancestor folders for specified folder. 1089 * \param folder Folder. 1090 * \param seq Path sequence, FALSE top down, TRUE bottom up. 1091 * \return List of folders from the top down. 1092 */ 1093 GList *addritem_folder_path( const ItemFolder *folder, const gboolean seq ) { 1094 GList *list; 1095 AddrItemObject *item; 1096 1097 list = NULL; 1098 item = ( AddrItemObject * ) folder; 1099 if( seq ) { 1100 while( item ) { 1101 list = g_list_prepend( list, item ); 1102 item = ADDRITEM_PARENT( item ); 1103 } 1104 } 1105 else { 1106 while( item ) { 1107 list = g_list_append( list, item ); 1108 item = ADDRITEM_PARENT( item ); 1109 } 1110 } 1111 return list; 1112 } 1113 1114 /** 1115 * Format E-Mail address. 1116 * \param email EMail item to format. 1117 * \return Formatted string. Should be freed after use. 1118 */ 1119 gchar *addritem_format_email( ItemEMail *email ) { 1120 gchar *address; 1121 gchar *name; 1122 ItemPerson *person; 1123 1124 address = NULL; 1125 name = NULL; 1126 if( ADDRITEM_NAME( email ) ) { 1127 if( strlen( ADDRITEM_NAME( email ) ) ) { 1128 name = ADDRITEM_NAME( email ); 1129 } 1130 } 1131 if( ! name ) { 1132 person = ( ItemPerson * ) ADDRITEM_PARENT( email ); 1133 name = ADDRITEM_NAME( person ); 1134 } 1135 1136 if( name ) { 1137 if( strchr_with_skip_quote( name, '"', ',' ) ) { 1138 address = g_strdup_printf( "\"%s\" <%s>", name, email->address ); 1139 } 1140 else { 1141 address = g_strdup_printf( "%s <%s>", name, email->address ); 1142 } 1143 } 1144 else { 1145 address = g_strdup_printf( "%s", email->address ); 1146 } 1147 return address; 1148 }