comparison libpurple/buddyicon.c @ 20410:522ade544156

propagate im.pidgin.pidgin to im.pidgin.cpw.khc.msnp14
author Ka-Hing Cheung <khc@hxbc.us>
date Sun, 06 May 2007 02:17:45 +0000
parents 9862a82206ba
children a1858493abe2
comparison
equal deleted inserted replaced
20409:7c0a2ef88018 20410:522ade544156
312 312
313 /* purple_buddy_icon_create() sets account & username */ 313 /* purple_buddy_icon_create() sets account & username */
314 if (icon == NULL) 314 if (icon == NULL)
315 icon = purple_buddy_icon_create(account, username); 315 icon = purple_buddy_icon_create(account, username);
316 316
317 /* Take a reference for the caller of this function. */
318 icon->ref_count = 1;
319
320 /* purple_buddy_icon_set_data() sets img, but it 317 /* purple_buddy_icon_set_data() sets img, but it
321 * references img first, so we need to initialize it */ 318 * references img first, so we need to initialize it */
322 icon->img = NULL; 319 icon->img = NULL;
323 purple_buddy_icon_set_data(icon, icon_data, icon_len, checksum); 320 purple_buddy_icon_set_data(icon, icon_data, icon_len, checksum);
324 321
370 { 367 {
371 PurpleConversation *conv; 368 PurpleConversation *conv;
372 PurpleAccount *account; 369 PurpleAccount *account;
373 const char *username; 370 const char *username;
374 PurpleBuddyIcon *icon_to_set; 371 PurpleBuddyIcon *icon_to_set;
375 GSList *sl, *list; 372 GSList *buddies;
376 373
377 g_return_if_fail(icon != NULL); 374 g_return_if_fail(icon != NULL);
378 375
379 account = purple_buddy_icon_get_account(icon); 376 account = purple_buddy_icon_get_account(icon);
380 username = purple_buddy_icon_get_username(icon); 377 username = purple_buddy_icon_get_username(icon);
381 378
382 /* If no data exists, then call the functions below with NULL to 379 /* If no data exists (icon->img == NULL), then call the functions below
383 * unset the icon. They will then unref the icon and it should be 380 * with NULL to unset the icon. They will then unref the icon and it should
384 * destroyed. The only way it wouldn't be destroyed is if someone 381 * be destroyed. The only way it wouldn't be destroyed is if someone
385 * else is holding a reference to it, in which case they can kill 382 * else is holding a reference to it, in which case they can kill
386 * the icon when they realize it has no data. */ 383 * the icon when they realize it has no data. */
387 icon_to_set = icon->img ? icon : NULL; 384 icon_to_set = icon->img ? icon : NULL;
388 385
389 for (list = sl = purple_find_buddies(account, username); 386 /* Ensure that icon remains valid throughout */
390 sl != NULL; 387 if (icon) purple_buddy_icon_ref(icon);
391 sl = sl->next) 388
392 { 389 buddies = purple_find_buddies(account, username);
393 PurpleBuddy *buddy = (PurpleBuddy *)sl->data; 390 while (buddies != NULL)
391 {
392 PurpleBuddy *buddy = (PurpleBuddy *)buddies->data;
394 char *old_icon; 393 char *old_icon;
395 394
396 purple_buddy_set_icon(buddy, icon_to_set); 395 purple_buddy_set_icon(buddy, icon_to_set);
397
398
399 old_icon = g_strdup(purple_blist_node_get_string((PurpleBlistNode *)buddy, 396 old_icon = g_strdup(purple_blist_node_get_string((PurpleBlistNode *)buddy,
400 "buddy_icon")); 397 "buddy_icon"));
401 if (icon->img && purple_buddy_icons_is_caching()) 398 if (icon->img && purple_buddy_icons_is_caching())
402 { 399 {
403 const char *filename = purple_imgstore_get_filename(icon->img); 400 const char *filename = purple_imgstore_get_filename(icon->img);
423 purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "buddy_icon"); 420 purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "buddy_icon");
424 purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "icon_checksum"); 421 purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "icon_checksum");
425 } 422 }
426 unref_filename(old_icon); 423 unref_filename(old_icon);
427 g_free(old_icon); 424 g_free(old_icon);
428 } 425
429 426 buddies = g_slist_delete_link(buddies, buddies);
430 g_slist_free(list); 427 }
431 428
432 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, username, account); 429 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, username, account);
433 430
434 if (conv != NULL) 431 if (conv != NULL)
435 purple_conv_im_set_icon(PURPLE_CONV_IM(conv), icon_to_set); 432 purple_conv_im_set_icon(PURPLE_CONV_IM(conv), icon_to_set);
433
434 /* icon's refcount was incremented above */
435 if (icon) purple_buddy_icon_unref(icon);
436 } 436 }
437 437
438 void 438 void
439 purple_buddy_icon_set_data(PurpleBuddyIcon *icon, guchar *data, 439 purple_buddy_icon_set_data(PurpleBuddyIcon *icon, guchar *data,
440 size_t len, const char *checksum) 440 size_t len, const char *checksum)
452 icon->img = purple_buddy_icon_data_new(data, len, NULL); 452 icon->img = purple_buddy_icon_data_new(data, len, NULL);
453 else 453 else
454 g_free(data); 454 g_free(data);
455 } 455 }
456 456
457 g_free(icon->checksum);
457 icon->checksum = g_strdup(checksum); 458 icon->checksum = g_strdup(checksum);
458 459
459 purple_buddy_icon_update(icon); 460 purple_buddy_icon_update(icon);
460 461
461 purple_imgstore_unref(old_img); 462 purple_imgstore_unref(old_img);
513 void 514 void
514 purple_buddy_icons_set_for_user(PurpleAccount *account, const char *username, 515 purple_buddy_icons_set_for_user(PurpleAccount *account, const char *username,
515 void *icon_data, size_t icon_len, 516 void *icon_data, size_t icon_len,
516 const char *checksum) 517 const char *checksum)
517 { 518 {
518 PurpleBuddyIcon *icon; 519 GHashTable *icon_cache;
520 PurpleBuddyIcon *icon = NULL;
519 521
520 g_return_if_fail(account != NULL); 522 g_return_if_fail(account != NULL);
521 g_return_if_fail(username != NULL); 523 g_return_if_fail(username != NULL);
522 524
523 icon = purple_buddy_icons_find(account, username); 525 icon_cache = g_hash_table_lookup(account_cache, account);
526
527 if (icon_cache != NULL)
528 icon = g_hash_table_lookup(icon_cache, username);
524 529
525 if (icon != NULL) 530 if (icon != NULL)
526 purple_buddy_icon_set_data(icon, icon_data, icon_len, checksum); 531 purple_buddy_icon_set_data(icon, icon_data, icon_len, checksum);
527 else 532 else if (icon_data && icon_len > 0)
528 { 533 {
529 PurpleBuddyIcon *icon = purple_buddy_icon_new(account, username, icon_data, icon_len, checksum); 534 if (icon_data != NULL && icon_len > 0)
530 purple_buddy_icon_unref(icon); 535 {
536 PurpleBuddyIcon *icon = purple_buddy_icon_new(account, username, icon_data, icon_len, checksum);
537
538 /* purple_buddy_icon_new() calls
539 * purple_buddy_icon_set_data(), which calls
540 * purple_buddy_icon_update(), which has the buddy list
541 * and conversations take references as appropriate.
542 * This function doesn't return icon, so we can't
543 * leave a reference dangling. */
544 purple_buddy_icon_unref(icon);
545 }
546 else
547 {
548 /* If the buddy list or a conversation was holding a
549 * reference, we'd have found the icon in the cache.
550 * Since we know we're deleting the icon, we only
551 * need a subset of purple_buddy_icon_update(). */
552
553 GSList *buddies = purple_find_buddies(account, username);
554 while (buddies != NULL)
555 {
556 PurpleBuddy *buddy = (PurpleBuddy *)buddies->data;
557
558 unref_filename(purple_blist_node_get_string((PurpleBlistNode *)buddy, "buddy_icon"));
559 purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "buddy_icon");
560 purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "icon_checksum");
561
562 buddies = g_slist_delete_link(buddies, buddies);
563 }
564
565 }
531 } 566 }
532 } 567 }
533 568
534 char *purple_buddy_icon_get_full_path(PurpleBuddyIcon *icon) 569 char *purple_buddy_icon_get_full_path(PurpleBuddyIcon *icon)
535 { 570 {
615 char *path = g_build_filename(dirname, protocol_icon_file, NULL); 650 char *path = g_build_filename(dirname, protocol_icon_file, NULL);
616 if (read_icon_file(path, &data, &len)) 651 if (read_icon_file(path, &data, &len))
617 { 652 {
618 const char *checksum; 653 const char *checksum;
619 654
620 if (icon == NULL) 655 icon = purple_buddy_icon_create(account, username);
621 icon = purple_buddy_icon_create(account, username);
622 icon->ref_count = 0; 656 icon->ref_count = 0;
623 icon->img = NULL; 657 icon->img = NULL;
624 checksum = g_strdup(purple_blist_node_get_string((PurpleBlistNode*)b, "icon_checksum")); 658 checksum = purple_blist_node_get_string((PurpleBlistNode*)b, "icon_checksum");
625 purple_buddy_icon_set_data(icon, data, len, checksum); 659 purple_buddy_icon_set_data(icon, data, len, checksum);
626 } 660 }
627 g_free(path); 661 g_free(path);
628 } 662 }
629 663
630 purple_buddy_icons_set_caching(caching); 664 purple_buddy_icons_set_caching(caching);
631 } 665 }
632 666
633 return icon; 667 return purple_buddy_icon_ref(icon);
634 } 668 }
635 669
636 gboolean 670 gboolean
637 purple_buddy_icons_has_custom_icon(PurpleContact *contact) 671 purple_buddy_icons_has_custom_icon(PurpleContact *contact)
638 { 672 {