Mercurial > pidgin.yaz
changeset 25469:fd6c3dc4641f
propagate from branch 'im.pidgin.pidgin' (head f11ff4f3f5929845b5a51662b200df16da7e550f)
to branch 'im.pidgin.pidgin.yaz' (head 9925ec484dc5ac489c78817cdab384b16b6e4ed0)
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Sat, 28 Apr 2007 03:53:00 +0000 |
parents | bf77cf06b082 (current diff) 8f02e8b1c838 (diff) |
children | 0663e4f77bf5 fb4df531105b |
files | PROGRAMMING_NOTES configure.ac libpurple/conversation.c libpurple/protocols/msn/msn.c libpurple/protocols/oscar/oscar.c libpurple/protocols/yahoo/yahoo.c libpurple/protocols/yahoo/yahoo_profile.c libpurple/util.c libpurple/util.h pidgin/gtkconv.c pidgin/gtkmain.c pidgin/gtkprefs.c pidgin/pixmaps/status/16/rtl/chat.png pidgin/pixmaps/status/22/rtl/chat.png pidgin/pixmaps/status/32/rtl/chat.png pidgin/pixmaps/status/48/rtl/chat.png pidgin/plugins/perl/common/GtkUI.pm pidgin/plugins/perl/common/GtkUI.xs |
diffstat | 155 files changed, 3077 insertions(+), 2180 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile.am Thu Apr 26 21:15:41 2007 +0000 +++ b/Makefile.am Sat Apr 28 03:53:00 2007 +0000 @@ -6,7 +6,6 @@ HACKING \ Makefile.mingw \ PLUGIN_HOWTO \ - PROGRAMMING_NOTES \ README.MTN \ README.mingw \ config.h.mingw \
--- a/PROGRAMMING_NOTES Thu Apr 26 21:15:41 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -Notes on keeping Pidgin, Finch, and libpurple OS independant ------------------------------------------------------------- - -General -------- -- Use G_DIR_SEPARATOR_S and G_DIR_SEPARATOR for paths - -- Use g_getenv, g_snprintf, g_vsnprintf - -- Use purple_home_dir instead of g_get_home_dir or g_getenv("HOME") - -- Make sure when including win32dep.h that it is the last header to - be included. - -- Open binary files when reading or writing with 'b' mode. - - e.g: fopen("somefile", "wb"); - - Not doing so will open files in windows using default translation mode. - i.e. newline -> <CR><LF> - -Paths ------ - -- DATADIR, LOCALEDIR & LIBDIR are defined as functions in the win32 build - Doing the following will therefore break the windows build: - - printf("File in DATADIR is: %s\n", DATADIR G_DIR_SEPARATOR_S "pic.png"); - - it should be: - - printf("File in DATADIR is: %s%s%s\n", DATADIR, G_DIR_SEPARATOR_S, "pic.png"); - -PLUGINS & PROTOS ----------------- - -- G_MODULE_EXPORT all functions which are to be accessed from outside the - scope of its "dll" or "so". (E.G. purple_plugin_init) - -- G_MODULE_IMPORT all global variables which are located outside your - dynamic library. (E.G. connections) - - (Not doing this will cause "Memory Access Violations" in win32)
--- a/config.h.mingw Thu Apr 26 21:15:41 2007 +0000 +++ b/config.h.mingw Sat Apr 28 03:53:00 2007 +0000 @@ -325,7 +325,7 @@ /* #define HAVE_SIGNAL_H 1 */ /* Define if we have silcmime.h */ -/* #undef HAVE_SILCMIME_H */ +#define HAVE_SILCMIME_H 1 /* Define to 1 if you have the <smime.h> header file. */ /* #undef HAVE_SMIME_H */
--- a/configure.ac Thu Apr 26 21:15:41 2007 +0000 +++ b/configure.ac Sat Apr 28 03:53:00 2007 +0000 @@ -807,7 +807,22 @@ AC_CHECK_HEADER(sys/utsname.h) AC_CHECK_FUNC(uname) -AC_ARG_ENABLE(fortify, [AC_HELP_STRING([--disable-fortify], [compile without FORTIFY_SOURCE support])], , enable_fortify=yes) +AC_ARG_ENABLE(fortify, [AC_HELP_STRING([--disable-fortify], [compile without FORTIFY_SOURCE support])], enable_fortify="$enableval", enable_fortify=yes) + +AC_ARG_ENABLE(mcheck, [AC_HELP_STRING([--enable-mcheck], [compile with mcheck (malloc debugging) support])], enable_mcheck="$enableval", enable_mcheck="$enable_debug") +if test "x$enable_mcheck" = "xyes" ; then + orig_LIBS="$LIBS" + LIBS="$LIBS -lmcheck" + AC_MSG_CHECKING(for mcheck support) + AC_TRY_COMPILE([], [ + int main() {return 0;} + ], [ + AC_MSG_RESULT(yes) + ], [ + AC_MSG_RESULT(no) + LIBS="$orig_LIBS" + ]) +fi if test "x$GCC" = "xyes"; then dnl We enable -Wall later.
--- a/doc/funniest_home_convos.txt Thu Apr 26 21:15:41 2007 +0000 +++ b/doc/funniest_home_convos.txt Sat Apr 28 03:53:00 2007 +0000 @@ -451,3 +451,12 @@ (07:54:03 PM) clueless21: what's an im client? (07:54:25 PM) Nathan Walp: it lets you chat with other people, like we are chatting now (07:54:45 PM) clueless21: oooooooooo... thanks + +23:58 -!- seanegan is now known as beta7 +23:58 <beta7> Hey, guys, remember me? +23:59 <beta7> We were all supposed to be working on getting me out. +23:59 <beta7> you guys remember that? +23:59 -!- mode/#pidgin [+o elb] by ChanServ +23:59 -!- beta7 was kicked from #pidgin by elb [getting feisty, are we?] +23:59 -!- mode/#pidgin [-o elb] by ChanServ +23:59 <marv> elb: good job getting beta7 out
--- a/finch/Makefile.am Thu Apr 26 21:15:41 2007 +0000 +++ b/finch/Makefile.am Sat Apr 28 03:53:00 2007 +0000 @@ -1,5 +1,3 @@ -if ENABLE_GNT - EXTRA_DIST = \ getopt.c \ getopt.h \ @@ -7,8 +5,12 @@ SUBDIRS = libgnt plugins +if ENABLE_GNT + bin_PROGRAMS = finch +endif + finch_SOURCES = \ gntaccount.c \ gntblist.c \ @@ -74,4 +76,3 @@ $(DBUS_CFLAGS) \ $(LIBXML_CFLAGS) \ $(GNT_CFLAGS) -endif
--- a/finch/finch.c Thu Apr 26 21:15:41 2007 +0000 +++ b/finch/finch.c Sat Apr 28 03:53:00 2007 +0000 @@ -202,6 +202,11 @@ {0, 0, 0, 0} }; +#ifdef PURPLE_FATAL_ASSERTS + /* Make g_return_... functions fatal. */ + g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL); +#endif + #ifdef ENABLE_NLS bindtextdomain(PACKAGE, LOCALEDIR); bind_textdomain_codeset(PACKAGE, "UTF-8"); @@ -272,9 +277,32 @@ * Fire up this baby. */ - /* Because we don't want debug-messages to show up and corrup the display */ + /* We don't want debug-messages to show up and corrupt the display */ purple_debug_set_enabled(debug_enabled); + /* If we're using a custom configuration directory, we + * do NOT want to migrate, or weird things will happen. */ + if (opt_config_dir_arg == NULL) + { + if (!purple_core_migrate()) + { + char *old = g_strconcat(purple_home_dir(), + G_DIR_SEPARATOR_S ".gaim", NULL); + char *text = g_strdup_printf(_( + "%s encountered errors migrating your settings " + "from %s to %s. Please investigate and complete the " + "migration by hand."), _("Finch"), + old, purple_user_dir()); + + g_free(old); + + purple_print_utf8_to_console(stderr, text); + g_free(text); + + return 0; + } + } + purple_core_set_ui_ops(gnt_core_get_ui_ops()); purple_eventloop_set_ui_ops(gnt_eventloop_get_ui_ops()); purple_idle_set_ui_ops(finch_idle_get_ui_ops());
--- a/finch/gntaccount.c Thu Apr 26 21:15:41 2007 +0000 +++ b/finch/gntaccount.c Sat Apr 28 03:53:00 2007 +0000 @@ -611,10 +611,10 @@ prompt = g_strdup_printf(_("Are you sure you want to delete %s?"), purple_account_get_username(account)); - purple_request_action(account, _("Delete Account"), prompt, NULL, 0, account, 2, - _("Delete"), really_delete_account, _("Cancel"), - account, NULL, NULL, - NULL); + purple_request_action(account, _("Delete Account"), prompt, NULL, 0, + account, NULL, NULL, account, 2, + _("Delete"), really_delete_account, + _("Cancel"), NULL); g_free(prompt); }
--- a/finch/gntblist.c Thu Apr 26 21:15:41 2007 +0000 +++ b/finch/gntblist.c Sat Apr 28 03:53:00 2007 +0000 @@ -114,6 +114,7 @@ static void account_signed_on_cb(void); /* Sort functions */ +static int blist_node_compare_position(PurpleBlistNode *n1, PurpleBlistNode *n2); static int blist_node_compare_text(PurpleBlistNode *n1, PurpleBlistNode *n2); static int blist_node_compare_status(PurpleBlistNode *n1, PurpleBlistNode *n2); static int blist_node_compare_log(PurpleBlistNode *n1, PurpleBlistNode *n2); @@ -1778,6 +1779,15 @@ } static int +blist_node_compare_position(PurpleBlistNode *n1, PurpleBlistNode *n2) +{ + while ((n1 = n1->prev) != NULL) + if (n1 == n2) + return 1; + return -1; +} + +static int blist_node_compare_text(PurpleBlistNode *n1, PurpleBlistNode *n2) { const char *s1, *s2; @@ -1788,10 +1798,6 @@ switch (n1->type) { - case PURPLE_BLIST_GROUP_NODE: - s1 = ((PurpleGroup*)n1)->name; - s2 = ((PurpleGroup*)n2)->name; - break; case PURPLE_BLIST_CHAT_NODE: s1 = purple_chat_get_name((PurpleChat*)n1); s2 = purple_chat_get_name((PurpleChat*)n2); @@ -1805,7 +1811,7 @@ s2 = purple_contact_get_alias((PurpleContact*)n2); break; default: - return -1; + return blist_node_compare_position(n1, n2); } us1 = g_utf8_strup(s1, -1); @@ -1836,6 +1842,7 @@ return ret; break; default: + return blist_node_compare_position(n1, n2); break; } @@ -1882,6 +1889,7 @@ return ret; break; default: + return blist_node_compare_position(n1, n2); break; } ret = blist_node_compare_text(n1, n2);
--- a/finch/libgnt/gntwm.c Thu Apr 26 21:15:41 2007 +0000 +++ b/finch/libgnt/gntwm.c Sat Apr 28 03:53:00 2007 +0000 @@ -905,6 +905,32 @@ return FALSE; } +static gboolean +toggle_clipboard(GntBindable *bindable, GList *n) +{ + static GntWidget *clip; + gchar *text; + int maxx, maxy; + if (clip) { + gnt_widget_destroy(clip); + clip = NULL; + return TRUE; + } + getmaxyx(stdscr, maxy, maxx); + text = gnt_get_clipboard_string(); + clip = gnt_hwindow_new(FALSE); + GNT_WIDGET_SET_FLAGS(clip, GNT_WIDGET_TRANSIENT); + GNT_WIDGET_SET_FLAGS(clip, GNT_WIDGET_NO_BORDER); + gnt_box_set_pad(GNT_BOX(clip), 0); + gnt_box_add_widget(GNT_BOX(clip), gnt_label_new(" ")); + gnt_box_add_widget(GNT_BOX(clip), gnt_label_new(text)); + gnt_box_add_widget(GNT_BOX(clip), gnt_label_new(" ")); + gnt_widget_set_position(clip, 0, 0); + gnt_widget_draw(clip); + g_free(text); + return TRUE; +} + static void gnt_wm_class_init(GntWMClass *klass) { @@ -1039,6 +1065,8 @@ "\033" GNT_KEY_CTRL_K, NULL); gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "help-for-widget", help_for_widget, "\033" "/", NULL); + gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "toggle-clipboard", + toggle_clipboard, "\033" "C", NULL); gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
--- a/finch/libgnt/wms/s.c Thu Apr 26 21:15:41 2007 +0000 +++ b/finch/libgnt/wms/s.c Sat Apr 28 03:53:00 2007 +0000 @@ -168,32 +168,6 @@ return TRUE; } -static gboolean -toggle_clipboard(GntBindable *bindable, GList *n) -{ - static GntWidget *clip; - gchar *text; - int maxx, maxy; - if (clip) { - gnt_widget_destroy(clip); - clip = NULL; - return TRUE; - } - getmaxyx(stdscr, maxy, maxx); - text = gnt_get_clipboard_string(); - clip = gnt_hwindow_new(FALSE); - GNT_WIDGET_SET_FLAGS(clip, GNT_WIDGET_TRANSIENT); - GNT_WIDGET_SET_FLAGS(clip, GNT_WIDGET_NO_BORDER); - gnt_box_set_pad(GNT_BOX(clip), 0); - gnt_box_add_widget(GNT_BOX(clip), gnt_label_new(" ")); - gnt_box_add_widget(GNT_BOX(clip), gnt_label_new(text)); - gnt_box_add_widget(GNT_BOX(clip), gnt_label_new(" ")); - gnt_widget_set_position(clip, 0, 0); - gnt_widget_draw(clip); - g_free(text); - return TRUE; -} - static void s_class_init(SClass *klass) { @@ -208,8 +182,6 @@ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "toggle-buddylist", toggle_buddylist, "\033" "b", NULL); - gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "toggle-clipboard", - toggle_clipboard, "\033" "C", NULL); gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass)); GNTDEBUG; }
--- a/libpurple/account.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/account.c Sat Apr 28 03:53:00 2007 +0000 @@ -347,12 +347,6 @@ xmlnode_insert_data(child, tmp, -1); } - if ((tmp = purple_account_get_buddy_icon(account)) != NULL) - { - child = xmlnode_new_child(node, "buddyicon"); - xmlnode_insert_data(child, tmp, -1); - } - if (g_hash_table_size(account->settings) > 0) { child = xmlnode_new_child(node, "settings"); @@ -742,11 +736,21 @@ g_free(data); } - /* Read the buddyicon */ + /* Read an old buddyicon */ child = xmlnode_get_child(node, "buddyicon"); if ((child != NULL) && ((data = xmlnode_get_data(child)) != NULL)) { - purple_account_set_buddy_icon(ret, data); + const char *dirname = purple_buddy_icons_get_cache_dir(); + char *filename = g_build_filename(dirname, data, NULL); + gchar *contents; + gsize len; + + if (g_file_get_contents(filename, &contents, &len, NULL)) + { + purple_buddy_icons_set_account_icon(ret, (guchar *)contents, len); + } + + g_free(filename); g_free(data); } @@ -788,6 +792,8 @@ } xmlnode_free(node); + + purple_buddy_icons_account_loaded_cb(); } @@ -880,7 +886,6 @@ g_free(account->alias); g_free(account->password); g_free(account->user_info); - g_free(account->buddy_icon); g_free(account->buddy_icon_path); g_free(account->protocol_id); @@ -1320,56 +1325,6 @@ schedule_accounts_save(); } -void -purple_account_set_buddy_icon(PurpleAccount *account, const char *icon) -{ - g_return_if_fail(account != NULL); - - /* Delete an existing icon from the cache. */ - if (account->buddy_icon != NULL && (icon == NULL || strcmp(account->buddy_icon, icon))) - { - const char *dirname = purple_buddy_icons_get_cache_dir(); - - if (g_file_test(account->buddy_icon, G_FILE_TEST_IS_REGULAR)) - { - /* The file exists. This is a full path. */ - - /* XXX: This is a hack so we only delete the file if it's - * in the cache dir. Otherwise, people who upgrade (who - * may have buddy icon filenames set outside of the cache - * dir) could lose files. */ - if (!strncmp(dirname, account->buddy_icon, strlen(dirname))) - g_unlink(account->buddy_icon); - } - else - { - char *filename = g_build_filename(dirname, account->buddy_icon, NULL); - g_unlink(filename); - g_free(filename); - } - } - - g_free(account->buddy_icon); - account->buddy_icon = g_strdup(icon); - if (purple_account_is_connected(account)) - { - PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info; - - gc = purple_account_get_connection(account); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); - - if (prpl_info && prpl_info->set_buddy_icon) - { - char *cached_path = purple_buddy_icons_get_full_path(icon); - prpl_info->set_buddy_icon(gc, cached_path); - g_free(cached_path); - } - } - - schedule_accounts_save(); -} - void purple_account_set_buddy_icon_path(PurpleAccount *account, const char *path) { g_return_if_fail(account != NULL); @@ -1745,14 +1700,6 @@ } const char * -purple_account_get_buddy_icon(const PurpleAccount *account) -{ - g_return_val_if_fail(account != NULL, NULL); - - return account->buddy_icon; -} - -const char * purple_account_get_buddy_icon_path(const PurpleAccount *account) { g_return_val_if_fail(account != NULL, NULL); @@ -2279,7 +2226,7 @@ purple_pounce_destroy_all_by_account(account); /* This will cause the deletion of an old buddy icon. */ - purple_account_set_buddy_icon(account, NULL); + purple_buddy_icons_set_account_icon(account, NULL, 0); purple_account_destroy(account); }
--- a/libpurple/account.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/account.h Sat Apr 28 03:53:00 2007 +0000 @@ -75,7 +75,6 @@ char *password; /**< The account password. */ char *user_info; /**< User information. */ - char *buddy_icon; /**< The buddy icon's cached path. */ char *buddy_icon_path; /**< The buddy icon's non-cached path. */ gboolean remember_pass; /**< Remember the password. */ @@ -284,14 +283,6 @@ void purple_account_set_user_info(PurpleAccount *account, const char *user_info); /** - * Sets the account's buddy icon. - * - * @param account The account. - * @param icon The buddy icon file. - */ -void purple_account_set_buddy_icon(PurpleAccount *account, const char *icon); - -/** * Sets the account's buddy icon path. * * @param account The account. @@ -525,15 +516,6 @@ const char *purple_account_get_user_info(const PurpleAccount *account); /** - * Returns the account's buddy icon filename. - * - * @param account The account. - * - * @return The buddy icon filename. - */ -const char *purple_account_get_buddy_icon(const PurpleAccount *account); - -/** * Gets the account's buddy icon path. * * @param account The account.
--- a/libpurple/blist.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/blist.c Sat Apr 28 03:53:00 2007 +0000 @@ -605,6 +605,9 @@ } xmlnode_free(purple); + + /* This tells the buddy icon code to do its thing. */ + purple_buddy_icons_blist_loaded_cb(); } @@ -1141,20 +1144,12 @@ { g_return_if_fail(buddy != NULL); - if (buddy->icon != icon) { - if (buddy->icon != NULL) - purple_buddy_icon_unref(buddy->icon); - + if (buddy->icon != icon) + { + purple_buddy_icon_unref(buddy->icon); buddy->icon = (icon != NULL ? purple_buddy_icon_ref(icon) : NULL); } - if (buddy->icon) - purple_buddy_icon_cache(icon, buddy); - else - purple_buddy_icon_uncache(buddy); - - purple_blist_schedule_save(); - purple_signal_emit(purple_blist_get_handle(), "buddy-icon-changed", buddy); purple_blist_update_buddy_icon(buddy); @@ -1783,9 +1778,6 @@ contact = (PurpleContact *)cnode; group = (PurpleGroup *)gnode; - /* Delete any buddy icon. */ - purple_buddy_icon_uncache(buddy); - /* Remove the node from its parent */ if (node->prev) node->prev->next = node->next; @@ -1831,8 +1823,7 @@ purple_signal_emit(purple_blist_get_handle(), "buddy-removed", buddy); /* Delete the node */ - if (buddy->icon != NULL) - purple_buddy_icon_unref(buddy->icon); + purple_buddy_icon_unref(buddy->icon); g_hash_table_destroy(buddy->node.settings); purple_presence_remove_buddy(buddy->presence, buddy); purple_presence_destroy(buddy->presence); @@ -2343,7 +2334,6 @@ buddy = (PurpleBuddy *)bnode; if (account == buddy->account) { PurplePresence *presence; - recompute = TRUE; presence = purple_buddy_get_presence(buddy); @@ -2363,8 +2353,14 @@ if (!g_list_find(list, presence)) list = g_list_prepend(list, presence); - if (ops && ops->remove) + if (contact->priority == buddy) + purple_contact_invalidate_priority_buddy(contact); + else + recompute = TRUE; + + if (ops && ops->remove) { ops->remove(purplebuddylist, bnode); + } } } if (recompute) {
--- a/libpurple/buddyicon.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/buddyicon.c Sat Apr 28 03:53:00 2007 +0000 @@ -24,26 +24,257 @@ */ #include "internal.h" #include "buddyicon.h" +#include "cipher.h" #include "conversation.h" #include "dbus-maybe.h" #include "debug.h" +#include "imgstore.h" #include "util.h" +typedef struct _PurpleBuddyIconData PurpleBuddyIconData; + +/* NOTE: Instances of this struct are allocated without zeroing the memory, so + * NOTE: be sure to update purple_buddy_icon_new() if you add members. */ +struct _PurpleBuddyIcon +{ + PurpleAccount *account; /**< The account the user is on. */ + PurpleStoredImage *img; /**< The id of the stored image with the + the icon data. */ + char *username; /**< The username the icon belongs to. */ + char *checksum; /**< The protocol checksum. */ + int ref_count; /**< The buddy icon reference count. */ +}; + static GHashTable *account_cache = NULL; +static GHashTable *icon_data_cache = NULL; +static GHashTable *icon_file_cache = NULL; + +/* This one is used for both custom buddy icons + * on PurpleContacts and account icons. */ +static GHashTable *pointer_icon_cache = NULL; + static char *cache_dir = NULL; static gboolean icon_caching = TRUE; +/* For ~/.gaim to ~/.purple migration. */ +static char *old_icons_dir = NULL; + +static void +ref_filename(const char *filename) +{ + int refs; + + g_return_if_fail(filename != NULL); + + refs = GPOINTER_TO_INT(g_hash_table_lookup(icon_file_cache, filename)); + + g_hash_table_insert(icon_file_cache, g_strdup(filename), + GINT_TO_POINTER(refs + 1)); +} + +static void +unref_filename(const char *filename) +{ + int refs; + + if (filename == NULL) + return; + + refs = GPOINTER_TO_INT(g_hash_table_lookup(icon_file_cache, filename)); + + if (refs == 1) + { + g_hash_table_remove(icon_file_cache, filename); + } + else + { + g_hash_table_insert(icon_file_cache, g_strdup(filename), + GINT_TO_POINTER(refs - 1)); + } +} + +static char * +purple_buddy_icon_data_calculate_filename(guchar *icon_data, size_t icon_len) +{ + PurpleCipherContext *context; + gchar digest[41]; + + context = purple_cipher_context_new_by_name("sha1", NULL); + if (context == NULL) + { + purple_debug_error("buddyicon", "Could not find sha1 cipher\n"); + g_return_val_if_reached(NULL); + } + + /* Hash the icon data */ + purple_cipher_context_append(context, icon_data, icon_len); + if (!purple_cipher_context_digest_to_str(context, sizeof(digest), digest, NULL)) + { + purple_debug_error("buddyicon", "Failed to get SHA-1 digest.\n"); + g_return_val_if_reached(NULL); + } + purple_cipher_context_destroy(context); + + /* Return the filename */ + return g_strdup_printf("%s.%s", digest, + purple_util_get_image_extension(icon_data, icon_len)); +} + +static void +purple_buddy_icon_data_cache(PurpleStoredImage *img) +{ + const char *dirname; + char *path; + FILE *file = NULL; + + g_return_if_fail(img != NULL); + + if (!purple_buddy_icons_is_caching()) + return; + + dirname = purple_buddy_icons_get_cache_dir(); + path = g_build_filename(dirname, purple_imgstore_get_filename(img), NULL); + + if (!g_file_test(dirname, G_FILE_TEST_IS_DIR)) + { + purple_debug_info("buddyicon", "Creating icon cache directory.\n"); + + if (g_mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR) < 0) + { + purple_debug_error("buddyicon", + "Unable to create directory %s: %s\n", + dirname, strerror(errno)); + } + } + + if ((file = g_fopen(path, "wb")) != NULL) + { + if (!fwrite(purple_imgstore_get_data(img), purple_imgstore_get_size(img), 1, file)) + { + purple_debug_error("buddyicon", "Error writing %s: %s\n", + path, strerror(errno)); + } + else + purple_debug_info("buddyicon", "Wrote cache file: %s\n", path); + + fclose(file); + } + else + { + purple_debug_error("buddyicon", "Unable to create file %s: %s\n", + path, strerror(errno)); + g_free(path); + return; + } + g_free(path); +} + +static void +purple_buddy_icon_data_uncache_file(const char *filename) +{ + const char *dirname; + char *path; + + g_return_if_fail(filename != NULL); + + /* It's possible that there are other references to this icon + * cache file that are not currently loaded into memory. */ + if (GPOINTER_TO_INT(g_hash_table_lookup(icon_file_cache, filename))) + return; + + dirname = purple_buddy_icons_get_cache_dir(); + path = g_build_filename(dirname, filename, NULL); + + if (g_file_test(path, G_FILE_TEST_EXISTS)) + { + if (g_unlink(path)) + { + purple_debug_error("buddyicon", "Failed to delete %s: %s\n", + path, strerror(errno)); + } + else + { + purple_debug_info("buddyicon", "Deleted cache file: %s\n", path); + } + } + + g_free(path); +} + +static gboolean +value_equals(gpointer key, gpointer value, gpointer user_data) +{ + return (value == user_data); +} + +static void +image_deleting_cb(PurpleStoredImage *img, gpointer data) +{ + const char *filename = purple_imgstore_get_filename(img); + + if (img == g_hash_table_lookup(icon_data_cache, filename)) + { + purple_buddy_icon_data_uncache_file(filename); + g_hash_table_remove(icon_data_cache, filename); + + /* We could make this O(1) by using another hash table, but + * this is probably good enough. */ + g_hash_table_foreach_remove(pointer_icon_cache, value_equals, img); + } +} + +static PurpleStoredImage * +purple_buddy_icon_data_new(guchar *icon_data, size_t icon_len, const char *filename) +{ + char *file; + PurpleStoredImage *img; + + g_return_val_if_fail(icon_data != NULL, NULL); + g_return_val_if_fail(icon_len > 0, NULL); + + if (filename == NULL) + { + file = purple_buddy_icon_data_calculate_filename(icon_data, icon_len); + if (file == NULL) + { + g_free(icon_data); + return NULL; + } + } + else + file = g_strdup(filename); + + if ((img = g_hash_table_lookup(icon_data_cache, file))) + { + g_free(file); + g_free(icon_data); + return purple_imgstore_ref(img); + } + + img = purple_imgstore_add(icon_data, icon_len, file); + + /* This will take ownership of file and g_free it either now or later. */ + g_hash_table_insert(icon_data_cache, file, img); + + purple_buddy_icon_data_cache(img); + + return img; +} + static PurpleBuddyIcon * purple_buddy_icon_create(PurpleAccount *account, const char *username) { PurpleBuddyIcon *icon; GHashTable *icon_cache; - icon = g_new0(PurpleBuddyIcon, 1); + /* This does not zero. See purple_buddy_icon_new() for + * information on which function allocates which member. */ + icon = g_slice_new(PurpleBuddyIcon); PURPLE_DBUS_REGISTER_POINTER(icon, PurpleBuddyIcon); - purple_buddy_icon_set_account(icon, account); - purple_buddy_icon_set_username(icon, username); + icon->account = account; + icon->username = g_strdup(username); + icon->checksum = NULL; icon_cache = g_hash_table_lookup(account_cache, account); @@ -55,13 +286,14 @@ } g_hash_table_insert(icon_cache, - (char *)purple_buddy_icon_get_username(icon), icon); + (char *)purple_buddy_icon_get_username(icon), icon); return icon; } PurpleBuddyIcon * purple_buddy_icon_new(PurpleAccount *account, const char *username, - void *icon_data, size_t icon_len) + void *icon_data, size_t icon_len, + const char *checksum) { PurpleBuddyIcon *icon; @@ -70,76 +302,25 @@ g_return_val_if_fail(icon_data != NULL, NULL); g_return_val_if_fail(icon_len > 0, NULL); + /* purple_buddy_icons_find() does allocation, so be + * sure to update it as well when members are added. */ icon = purple_buddy_icons_find(account, username); + /* purple_buddy_icon_create() sets account & username */ if (icon == NULL) icon = purple_buddy_icon_create(account, username); - purple_buddy_icon_ref(icon); - purple_buddy_icon_set_data(icon, icon_data, icon_len); - purple_buddy_icon_set_path(icon, NULL); + /* Take a reference for the caller of this function. */ + icon->ref_count = 1; - /* purple_buddy_icon_set_data() makes blist.c or - * conversation.c, or both, take a reference. - * - * Plus, we leave one for the caller of this function. - */ + /* purple_buddy_icon_set_data() sets img, but it + * references img first, so we need to initialize it */ + icon->img = NULL; + purple_buddy_icon_set_data(icon, icon_data, icon_len, checksum); return icon; } -void -purple_buddy_icon_destroy(PurpleBuddyIcon *icon) -{ - PurpleConversation *conv; - PurpleAccount *account; - GHashTable *icon_cache; - const char *username; - GSList *sl, *list; - - g_return_if_fail(icon != NULL); - - if (icon->ref_count > 0) - { - /* If the ref count is greater than 0, then we weren't called from - * purple_buddy_icon_unref(). So we go through and ask everyone to - * unref us. Then we return, since we know somewhere along the - * line we got called recursively by one of the unrefs, and the - * icon is already destroyed. - */ - account = purple_buddy_icon_get_account(icon); - username = purple_buddy_icon_get_username(icon); - - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, username, account); - if (conv != NULL) - purple_conv_im_set_icon(PURPLE_CONV_IM(conv), NULL); - - for (list = sl = purple_find_buddies(account, username); sl != NULL; - sl = sl->next) - { - PurpleBuddy *buddy = (PurpleBuddy *)sl->data; - - purple_buddy_set_icon(buddy, NULL); - } - - g_slist_free(list); - - return; - } - - icon_cache = g_hash_table_lookup(account_cache, - purple_buddy_icon_get_account(icon)); - - if (icon_cache != NULL) - g_hash_table_remove(icon_cache, purple_buddy_icon_get_username(icon)); - - g_free(icon->username); - g_free(icon->data); - g_free(icon->path); - PURPLE_DBUS_UNREGISTER_POINTER(icon); - g_free(icon); -} - PurpleBuddyIcon * purple_buddy_icon_ref(PurpleBuddyIcon *icon) { @@ -153,14 +334,26 @@ PurpleBuddyIcon * purple_buddy_icon_unref(PurpleBuddyIcon *icon) { - g_return_val_if_fail(icon != NULL, NULL); + if (icon == NULL) + return NULL; + g_return_val_if_fail(icon->ref_count > 0, NULL); icon->ref_count--; if (icon->ref_count == 0) { - purple_buddy_icon_destroy(icon); + GHashTable *icon_cache = g_hash_table_lookup(account_cache, purple_buddy_icon_get_account(icon)); + + if (icon_cache != NULL) + g_hash_table_remove(icon_cache, purple_buddy_icon_get_username(icon)); + + g_free(icon->username); + g_free(icon->checksum); + purple_imgstore_unref(icon->img); + + PURPLE_DBUS_UNREGISTER_POINTER(icon); + g_slice_free(PurpleBuddyIcon, icon); return NULL; } @@ -174,6 +367,7 @@ PurpleConversation *conv; PurpleAccount *account; const char *username; + PurpleBuddyIcon *icon_to_set; GSList *sl, *list; g_return_if_fail(icon != NULL); @@ -181,12 +375,52 @@ account = purple_buddy_icon_get_account(icon); username = purple_buddy_icon_get_username(icon); - for (list = sl = purple_find_buddies(account, username); sl != NULL; - sl = sl->next) + /* If no data exists, then call the functions below with NULL to + * unset the icon. They will then unref the icon and it should be + * destroyed. The only way it wouldn't be destroyed is if someone + * else is holding a reference to it, in which case they can kill + * the icon when they realize it has no data. */ + icon_to_set = icon->img ? icon : NULL; + + for (list = sl = purple_find_buddies(account, username); + sl != NULL; + sl = sl->next) { PurpleBuddy *buddy = (PurpleBuddy *)sl->data; + char *old_icon; - purple_buddy_set_icon(buddy, icon); + purple_buddy_set_icon(buddy, icon_to_set); + + + old_icon = g_strdup(purple_blist_node_get_string((PurpleBlistNode *)buddy, + "buddy_icon")); + if (icon->img && purple_buddy_icons_is_caching()) + { + const char *filename = purple_imgstore_get_filename(icon->img); + purple_blist_node_set_string((PurpleBlistNode *)buddy, + "buddy_icon", + filename); + + if (icon->checksum && *icon->checksum) + { + purple_blist_node_set_string((PurpleBlistNode *)buddy, + "icon_checksum", + icon->checksum); + } + else + { + purple_blist_node_remove_setting((PurpleBlistNode *)buddy, + "icon_checksum"); + } + ref_filename(filename); + } + else + { + purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "buddy_icon"); + purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "icon_checksum"); + } + unref_filename(old_icon); + g_free(old_icon); } g_slist_free(list); @@ -194,160 +428,33 @@ conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, username, account); if (conv != NULL) - purple_conv_im_set_icon(PURPLE_CONV_IM(conv), icon); -} - -static void -delete_icon_cache_file(const char *dirname, const char *old_icon) -{ - struct stat st; - - g_return_if_fail(dirname != NULL); - g_return_if_fail(old_icon != NULL); - - if (g_stat(old_icon, &st) == 0) - g_unlink(old_icon); - else - { - char *filename = g_build_filename(dirname, old_icon, NULL); - if (g_stat(filename, &st) == 0) - g_unlink(filename); - g_free(filename); - } - purple_debug_info("buddyicon", "Uncached file %s\n", old_icon); + purple_conv_im_set_icon(PURPLE_CONV_IM(conv), icon_to_set); } void -purple_buddy_icon_cache(PurpleBuddyIcon *icon, PurpleBuddy *buddy) +purple_buddy_icon_set_data(PurpleBuddyIcon *icon, guchar *data, + size_t len, const char *checksum) { - const guchar *data; - const char *dirname; - char *random; - char *filename; - const char *old_icon; - size_t len = 0; - FILE *file = NULL; + PurpleStoredImage *old_img; - g_return_if_fail(icon != NULL); - g_return_if_fail(buddy != NULL); - - if (!purple_buddy_icons_is_caching()) - return; - - data = purple_buddy_icon_get_data(icon, &len); - - random = g_strdup_printf("%x", g_random_int()); - dirname = purple_buddy_icons_get_cache_dir(); - filename = g_build_filename(dirname, random, NULL); - old_icon = purple_blist_node_get_string((PurpleBlistNode*)buddy, "buddy_icon"); + g_return_if_fail(icon != NULL); - if (!g_file_test(dirname, G_FILE_TEST_IS_DIR)) - { - purple_debug_info("buddyicon", "Creating icon cache directory.\n"); - - if (g_mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR) < 0) - { - purple_debug_error("buddyicon", - "Unable to create directory %s: %s\n", - dirname, strerror(errno)); - } - } + old_img = icon->img; + icon->img = NULL; - if ((file = g_fopen(filename, "wb")) != NULL) + if (data != NULL) { - fwrite(data, 1, len, file); - fclose(file); - purple_debug_info("buddyicon", "Wrote file %s\n", filename); - } - else - { - purple_debug_error("buddyicon", "Unable to create file %s: %s\n", - filename, strerror(errno)); - g_free(filename); - g_free(random); - return; + if (len > 0) + icon->img = purple_buddy_icon_data_new(data, len, NULL); + else + g_free(data); } - g_free(filename); - - if (old_icon != NULL) - delete_icon_cache_file(dirname, old_icon); - - purple_blist_node_set_string((PurpleBlistNode *)buddy, "buddy_icon", random); - - g_free(random); -} - -void -purple_buddy_icon_uncache(PurpleBuddy *buddy) -{ - const char *old_icon; - - g_return_if_fail(buddy != NULL); - - old_icon = purple_blist_node_get_string((PurpleBlistNode *)buddy, "buddy_icon"); - - if (old_icon != NULL) - delete_icon_cache_file(purple_buddy_icons_get_cache_dir(), old_icon); - - purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "buddy_icon"); - - /* Unset the icon in case this function is called from - * something other than purple_buddy_set_icon(). */ - if (buddy->icon != NULL) - { - purple_buddy_icon_unref(buddy->icon); - buddy->icon = NULL; - } -} - -void -purple_buddy_icon_set_account(PurpleBuddyIcon *icon, PurpleAccount *account) -{ - g_return_if_fail(icon != NULL); - g_return_if_fail(account != NULL); - - icon->account = account; -} - -void -purple_buddy_icon_set_username(PurpleBuddyIcon *icon, const char *username) -{ - g_return_if_fail(icon != NULL); - g_return_if_fail(username != NULL); - - g_free(icon->username); - icon->username = g_strdup(username); -} - -void -purple_buddy_icon_set_data(PurpleBuddyIcon *icon, void *data, size_t len) -{ - g_return_if_fail(icon != NULL); - - g_free(icon->data); - - if (data != NULL && len > 0) - { - icon->data = g_memdup(data, len); - icon->len = len; - } - else - { - icon->data = NULL; - icon->len = 0; - } + icon->checksum = g_strdup(checksum); purple_buddy_icon_update(icon); -} -void -purple_buddy_icon_set_path(PurpleBuddyIcon *icon, const gchar *path) -{ - g_return_if_fail(icon != NULL); - - g_free(icon->path); - icon->path = g_strdup(path); + purple_imgstore_unref(old_img); } PurpleAccount * @@ -366,121 +473,607 @@ return icon->username; } -const guchar * +const char * +purple_buddy_icon_get_checksum(const PurpleBuddyIcon *icon) +{ + g_return_val_if_fail(icon != NULL, NULL); + + return icon->checksum; +} + +gconstpointer purple_buddy_icon_get_data(const PurpleBuddyIcon *icon, size_t *len) { g_return_val_if_fail(icon != NULL, NULL); - if (len != NULL) - *len = icon->len; - - return icon->data; -} + if (icon->img) + { + if (len != NULL) + *len = purple_imgstore_get_size(icon->img); -const char * -purple_buddy_icon_get_path(PurpleBuddyIcon *icon) -{ - g_return_val_if_fail(icon != NULL, NULL); + return purple_imgstore_get_data(icon->img); + } - return icon->path; + return NULL; } const char * -purple_buddy_icon_get_type(const PurpleBuddyIcon *icon) +purple_buddy_icon_get_extension(const PurpleBuddyIcon *icon) { - const void *data; - size_t len; - - g_return_val_if_fail(icon != NULL, NULL); - - data = purple_buddy_icon_get_data(icon, &len); - - /* TODO: Find a way to do this with GDK */ - if (len >= 4) - { - if (!strncmp(data, "BM", 2)) - return "bmp"; - else if (!strncmp(data, "GIF8", 4)) - return "gif"; - else if (!strncmp(data, "\xff\xd8\xff\xe0", 4)) - return "jpg"; - else if (!strncmp(data, "\x89PNG", 4)) - return "png"; - } + if (icon->img != NULL) + return purple_imgstore_get_extension(icon->img); return NULL; } void purple_buddy_icons_set_for_user(PurpleAccount *account, const char *username, - void *icon_data, size_t icon_len) + void *icon_data, size_t icon_len, + const char *checksum) { + PurpleBuddyIcon *icon; + g_return_if_fail(account != NULL); g_return_if_fail(username != NULL); - if (icon_data == NULL || icon_len == 0) - { - PurpleBuddyIcon *buddy_icon; + icon = purple_buddy_icons_find(account, username); - buddy_icon = purple_buddy_icons_find(account, username); - - if (buddy_icon != NULL) - purple_buddy_icon_destroy(buddy_icon); - } + if (icon != NULL) + purple_buddy_icon_set_data(icon, icon_data, icon_len, checksum); else { - PurpleBuddyIcon *icon = purple_buddy_icon_new(account, username, icon_data, icon_len); + PurpleBuddyIcon *icon = purple_buddy_icon_new(account, username, icon_data, icon_len, checksum); purple_buddy_icon_unref(icon); } } +char *purple_buddy_icon_get_full_path(PurpleBuddyIcon *icon) +{ + char *path; + + g_return_val_if_fail(icon != NULL, NULL); + + if (icon->img == NULL) + return NULL; + + path = g_build_filename(purple_buddy_icons_get_cache_dir(), + purple_imgstore_get_filename(icon->img), NULL); + if (!g_file_test(path, G_FILE_TEST_EXISTS)) + { + g_free(path); + return NULL; + } + return path; +} + +const char * +purple_buddy_icons_get_checksum_for_user(PurpleBuddy *buddy) +{ + return purple_blist_node_get_string((PurpleBlistNode*)buddy, + "icon_checksum"); +} + +static gboolean +read_icon_file(const char *path, guchar **data, size_t *len) +{ + GError *err = NULL; + + if (!g_file_get_contents(path, (gchar **)data, len, &err)) + { + purple_debug_error("buddyicon", "Error reading %s: %s\n", + path, err->message); + g_error_free(err); + + return FALSE; + } + + return TRUE; +} + PurpleBuddyIcon * purple_buddy_icons_find(PurpleAccount *account, const char *username) { GHashTable *icon_cache; - PurpleBuddyIcon *ret = NULL; - char *filename = NULL; + PurpleBuddyIcon *icon = NULL; g_return_val_if_fail(account != NULL, NULL); g_return_val_if_fail(username != NULL, NULL); icon_cache = g_hash_table_lookup(account_cache, account); - if ((icon_cache == NULL) || ((ret = g_hash_table_lookup(icon_cache, username)) == NULL)) { - const char *file; - struct stat st; + if ((icon_cache == NULL) || ((icon = g_hash_table_lookup(icon_cache, username)) == NULL)) + { PurpleBuddy *b = purple_find_buddy(account, username); + const char *protocol_icon_file; + const char *dirname; + gboolean caching; + guchar *data; + size_t len; if (!b) return NULL; - if ((file = purple_blist_node_get_string((PurpleBlistNode*)b, "buddy_icon")) == NULL) + protocol_icon_file = purple_blist_node_get_string((PurpleBlistNode*)b, "buddy_icon"); + + if (protocol_icon_file == NULL) return NULL; - if (!g_stat(file, &st)) - filename = g_strdup(file); - else - filename = g_build_filename(purple_buddy_icons_get_cache_dir(), file, NULL); + dirname = purple_buddy_icons_get_cache_dir(); + + caching = purple_buddy_icons_is_caching(); + /* By disabling caching temporarily, we avoid a loop + * and don't have to add special code through several + * functions. */ + purple_buddy_icons_set_caching(FALSE); + + if (protocol_icon_file != NULL) + { + char *path = g_build_filename(dirname, protocol_icon_file, NULL); + if (read_icon_file(path, &data, &len)) + { + const char *checksum; + + if (icon == NULL) + icon = purple_buddy_icon_create(account, username); + icon->ref_count = 0; + icon->img = NULL; + checksum = g_strdup(purple_blist_node_get_string((PurpleBlistNode*)b, "icon_checksum")); + purple_buddy_icon_set_data(icon, data, len, checksum); + } + g_free(path); + } + + purple_buddy_icons_set_caching(caching); + } + + return icon; +} + +gboolean +purple_buddy_icons_has_custom_icon(PurpleContact *contact) +{ + g_return_val_if_fail(contact != NULL, FALSE); + + return (purple_blist_node_get_string((PurpleBlistNode*)contact, "custom_buddy_icon") != NULL); +} + +PurpleStoredImage * +purple_buddy_icons_find_account_icon(PurpleAccount *account) +{ + PurpleStoredImage *img; + const char *account_icon_file; + const char *dirname; + char *path; + guchar *data; + size_t len; + + g_return_val_if_fail(account != NULL, NULL); + + if ((img = g_hash_table_lookup(pointer_icon_cache, account))) + { + return purple_imgstore_ref(img); + } + + account_icon_file = purple_account_get_string(account, "buddy_icon", NULL); + + if (account_icon_file == NULL) + return NULL; + + dirname = purple_buddy_icons_get_cache_dir(); + path = g_build_filename(dirname, account_icon_file, NULL); + + if (read_icon_file(path, &data, &len)) + { + g_free(path); + img = purple_buddy_icon_data_new(data, len, account_icon_file); + g_hash_table_insert(pointer_icon_cache, account, img); + return img; + } + g_free(path); + + return NULL; +} + +PurpleStoredImage * +purple_buddy_icons_set_account_icon(PurpleAccount *account, + guchar *icon_data, size_t icon_len) +{ + PurpleStoredImage *old_img; + PurpleStoredImage *img = NULL; + char *old_icon; + + old_img = g_hash_table_lookup(pointer_icon_cache, account); + + if (icon_data != NULL && icon_len > 0) + { + img = purple_buddy_icon_data_new(icon_data, icon_len, NULL); + } + + old_icon = g_strdup(purple_account_get_string(account, "buddy_icon", NULL)); + if (img && purple_buddy_icons_is_caching()) + { + const char *filename = purple_imgstore_get_filename(img); + purple_account_set_string(account, "buddy_icon", filename); + ref_filename(filename); + } + else + { + purple_account_set_string(account, "buddy_icon", NULL); + } + unref_filename(old_icon); + + if (img) + g_hash_table_insert(pointer_icon_cache, account, img); + else + g_hash_table_remove(pointer_icon_cache, account); + + if (purple_account_is_connected(account)) + { + PurpleConnection *gc; + PurplePluginProtocolInfo *prpl_info; + + gc = purple_account_get_connection(account); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + + if (prpl_info && prpl_info->set_buddy_icon) + prpl_info->set_buddy_icon(gc, img); + } + + if (old_img) + purple_imgstore_unref(old_img); + else + { + /* The old icon may not have been loaded into memory. In that + * case, we'll need to uncache the filename. The filenames + * are ref-counted, so this is safe. */ + purple_buddy_icon_data_uncache_file(old_icon); + } + g_free(old_icon); + + return img; +} + +PurpleStoredImage * +purple_buddy_icons_find_custom_icon(PurpleContact *contact) +{ + PurpleStoredImage *img; + const char *custom_icon_file; + const char *dirname; + char *path; + guchar *data; + size_t len; + + g_return_val_if_fail(contact != NULL, NULL); + + if ((img = g_hash_table_lookup(pointer_icon_cache, contact))) + { + return purple_imgstore_ref(img); + } + + custom_icon_file = purple_blist_node_get_string((PurpleBlistNode*)contact, "custom_buddy_icon"); + + if (custom_icon_file == NULL) + return NULL; + + dirname = purple_buddy_icons_get_cache_dir(); + path = g_build_filename(dirname, custom_icon_file, NULL); + + if (read_icon_file(path, &data, &len)) + { + g_free(path); + img = purple_buddy_icon_data_new(data, len, custom_icon_file); + g_hash_table_insert(pointer_icon_cache, contact, img); + return img; + } + g_free(path); + + return NULL; +} - if (!g_stat(filename, &st)) { - FILE *f = g_fopen(filename, "rb"); - if (f) { - char *data = g_malloc(st.st_size); - fread(data, 1, st.st_size, f); - fclose(f); - ret = purple_buddy_icon_create(account, username); - purple_buddy_icon_ref(ret); - purple_buddy_icon_set_data(ret, data, st.st_size); - purple_buddy_icon_unref(ret); - g_free(data); - g_free(filename); - return ret; +PurpleStoredImage * +purple_buddy_icons_set_custom_icon(PurpleContact *contact, + guchar *icon_data, size_t icon_len) +{ + PurpleStoredImage *old_img; + PurpleStoredImage *img = NULL; + char *old_icon; + PurpleBlistNode *child; + + old_img = g_hash_table_lookup(pointer_icon_cache, contact); + + if (icon_data != NULL && icon_len > 0) + { + img = purple_buddy_icon_data_new(icon_data, icon_len, NULL); + } + + old_icon = g_strdup(purple_blist_node_get_string((PurpleBlistNode *)contact, + "custom_buddy_icon")); + if (img && purple_buddy_icons_is_caching()) + { + const char *filename = purple_imgstore_get_filename(img); + purple_blist_node_set_string((PurpleBlistNode *)contact, + "custom_buddy_icon", + filename); + ref_filename(filename); + } + else + { + purple_blist_node_remove_setting((PurpleBlistNode *)contact, + "custom_buddy_icon"); + } + unref_filename(old_icon); + + if (img) + g_hash_table_insert(pointer_icon_cache, contact, img); + else + g_hash_table_remove(pointer_icon_cache, contact); + + for (child = contact->node.child ; child ; child = child->next) + { + PurpleBuddy *buddy; + PurpleConversation *conv; + + if (!PURPLE_BLIST_NODE_IS_BUDDY(child)) + continue; + + buddy = (PurpleBuddy *)child; + + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, + purple_buddy_get_name(buddy), + purple_buddy_get_account(buddy)); + if (conv) + purple_conversation_update(conv, PURPLE_CONV_UPDATE_ICON); + + purple_blist_update_buddy_icon(buddy); + } + + if (old_img) + purple_imgstore_unref(old_img); + else + { + /* The old icon may not have been loaded into memory. In that + * case, we'll need to uncache the filename. The filenames + * are ref-counted, so this is safe. */ + purple_buddy_icon_data_uncache_file(old_icon); + } + g_free(old_icon); + + return img; +} + +void +purple_buddy_icon_set_old_icons_dir(const char *dirname) +{ + old_icons_dir = g_strdup(dirname); +} + +static void +delete_buddy_icon_settings(PurpleBlistNode *node, const char *setting_name) +{ + purple_blist_node_remove_setting(node, setting_name); + + if (!strcmp(setting_name, "buddy_icon")) + { + purple_blist_node_remove_setting(node, "avatar_hash"); + purple_blist_node_remove_setting(node, "icon_checksum"); + } +} + +static void +migrate_buddy_icon(PurpleBlistNode *node, const char *setting_name, + const char *dirname, const char *filename) +{ + char *path; + + if (filename[0] != '/') + { + path = g_build_filename(dirname, filename, NULL); + if (g_file_test(path, G_FILE_TEST_EXISTS)) + { + g_free(path); + return; + } + g_free(path); + + path = g_build_filename(old_icons_dir, filename, NULL); + } + else + path = g_strdup(filename); + + if (g_file_test(path, G_FILE_TEST_EXISTS)) + { + guchar *icon_data; + size_t icon_len; + FILE *file; + char *new_filename; + + if (!read_icon_file(path, &icon_data, &icon_len) || + icon_data == NULL || icon_len > 0) + { + delete_buddy_icon_settings(node, setting_name); + g_free(path); + return; + } + + g_free(path); + + new_filename = purple_buddy_icon_data_calculate_filename(icon_data, icon_len); + if (new_filename == NULL) + { + delete_buddy_icon_settings(node, setting_name); + return; + } + + path = g_build_filename(dirname, new_filename, NULL); + if ((file = g_fopen(path, "wb")) != NULL) + { + if (!fwrite(icon_data, icon_len, 1, file)) + { + purple_debug_error("buddyicon", "Error writing %s: %s\n", + path, strerror(errno)); + } + else + purple_debug_info("buddyicon", "Wrote migrated cache file: %s\n", path); + + fclose(file); + } + else + { + purple_debug_error("buddyicon", "Unable to create file %s: %s\n", + path, strerror(errno)); + g_free(new_filename); + g_free(path); + + delete_buddy_icon_settings(node, setting_name); + return; + } + g_free(path); + + purple_blist_node_set_string(node, + setting_name, + new_filename); + ref_filename(new_filename); + + g_free(new_filename); + + if (!strcmp(setting_name, "buddy_icon")) + { + const char *hash; + + hash = purple_blist_node_get_string(node, "avatar_hash"); + if (hash != NULL) + { + purple_blist_node_set_string(node, "icon_checksum", hash); + purple_blist_node_remove_setting(node, "avatar_hash"); + } + else + { + int checksum = purple_blist_node_get_int(node, "icon_checksum"); + if (checksum != 0) + { + char *checksum_str = g_strdup_printf("%i", checksum); + purple_blist_node_remove_setting(node, "icon_checksum"); + purple_blist_node_set_string(node, "icon_checksum", checksum_str); + g_free(checksum_str); + } } } - g_free(filename); + } + else + { + /* If the icon is gone, drop the setting... */ + delete_buddy_icon_settings(node, setting_name); + g_free(path); + } +} + +void +purple_buddy_icons_account_loaded_cb() +{ + const char *dirname = purple_buddy_icons_get_cache_dir(); + GList *cur; + + for (cur = purple_accounts_get_all(); cur != NULL; cur = cur->next) + { + PurpleAccount *account = cur->data; + const char *account_icon_file = purple_account_get_string(account, "buddy_icon", NULL); + + if (account_icon_file != NULL) + { + char *path = g_build_filename(dirname, account_icon_file, NULL); + if (!g_file_test(path, G_FILE_TEST_EXISTS)) + { + purple_account_set_string(account, "buddy_icon", NULL); + } else { + ref_filename(account_icon_file); + } + g_free(path); + } + } +} + +void +purple_buddy_icons_blist_loaded_cb() +{ + PurpleBlistNode *node = purple_blist_get_root(); + const char *dirname = purple_buddy_icons_get_cache_dir(); + + /* Doing this once here saves having to check it inside a loop. */ + if (old_icons_dir != NULL) + { + if (!g_file_test(dirname, G_FILE_TEST_IS_DIR)) + { + purple_debug_info("buddyicon", "Creating icon cache directory.\n"); + + if (g_mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR) < 0) + { + purple_debug_error("buddyicon", + "Unable to create directory %s: %s\n", + dirname, strerror(errno)); + } + } } - return ret; + while (node != NULL) + { + if (PURPLE_BLIST_NODE_IS_BUDDY(node)) + { + const char *filename; + + filename = purple_blist_node_get_string(node, "buddy_icon"); + if (filename != NULL) + { + if (old_icons_dir != NULL) + { + migrate_buddy_icon(node, + "buddy_icon", + dirname, filename); + } + else + { + char *path = g_build_filename(dirname, filename, NULL); + if (!g_file_test(path, G_FILE_TEST_EXISTS)) + { + purple_blist_node_remove_setting(node, + "buddy_icon"); + purple_blist_node_remove_setting(node, + "icon_checksum"); + } + else + ref_filename(filename); + g_free(path); + } + } + } + else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) + { + const char *filename; + + filename = purple_blist_node_get_string(node, "custom_buddy_icon"); + if (filename != NULL) + { + if (old_icons_dir != NULL) + { + migrate_buddy_icon(node, + "custom_buddy_icon", + dirname, filename); + } + else + { + char *path = g_build_filename(dirname, filename, NULL); + if (!g_file_test(path, G_FILE_TEST_EXISTS)) + { + purple_blist_node_remove_setting(node, + "custom_buddy_icon"); + } + else + ref_filename(filename); + g_free(path); + } + } + } + node = purple_blist_node_next(node, TRUE); + } } void @@ -510,16 +1103,6 @@ return cache_dir; } -char *purple_buddy_icons_get_full_path(const char *icon) { - if (icon == NULL) - return NULL; - - if (g_file_test(icon, G_FILE_TEST_IS_REGULAR)) - return g_strdup(icon); - else - return g_build_filename(purple_buddy_icons_get_cache_dir(), icon, NULL); -} - void * purple_buddy_icons_get_handle() { @@ -535,13 +1118,28 @@ g_direct_hash, g_direct_equal, NULL, (GFreeFunc)g_hash_table_destroy); + icon_data_cache = g_hash_table_new(g_str_hash, g_str_equal); + icon_file_cache = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); + pointer_icon_cache = g_hash_table_new(g_direct_hash, g_direct_equal); + cache_dir = g_build_filename(purple_user_dir(), "icons", NULL); + + purple_signal_connect(purple_imgstore_get_handle(), "image-deleting", + purple_buddy_icons_get_handle(), + G_CALLBACK(image_deleting_cb), NULL); } void purple_buddy_icons_uninit() { + purple_signals_disconnect_by_handle(purple_buddy_icons_get_handle()); + g_hash_table_destroy(account_cache); + g_hash_table_destroy(icon_data_cache); + g_hash_table_destroy(icon_file_cache); + g_hash_table_destroy(pointer_icon_cache); + g_free(old_icons_dir); } void purple_buddy_icon_get_scale_size(PurpleBuddyIconSpec *spec, int *width, int *height) @@ -572,4 +1170,3 @@ *width = new_width; *height = new_height; } -
--- a/libpurple/buddyicon.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/buddyicon.h Sat Apr 28 03:53:00 2007 +0000 @@ -29,51 +29,36 @@ #include "account.h" #include "blist.h" +#include "imgstore.h" #include "prpl.h" -struct _PurpleBuddyIcon -{ - PurpleAccount *account; /**< The account the user is on. */ - char *username; /**< The username the icon belongs to. */ - - void *data; /**< The buddy icon data. */ - size_t len; /**< The length of the buddy icon data. */ - char *path; /**< The buddy icon's non-cached path. */ - - int ref_count; /**< The buddy icon reference count. */ -}; - #ifdef __cplusplus extern "C" { #endif + /**************************************************************************/ /** @name Buddy Icon API */ /**************************************************************************/ /*@{*/ /** - * Creates a new buddy icon structure. + * Creates a new buddy icon structure and populate it. + * + * If the buddy icon already exists, you'll get a reference to that structure, + * which will have been updated with the data supplied. * * @param account The account the user is on. * @param username The username the icon belongs to. * @param icon_data The buddy icon data. * @param icon_len The buddy icon length. + * @param checksum A protocol checksum from the prpl or @c NULL. * * @return The buddy icon structure. */ PurpleBuddyIcon *purple_buddy_icon_new(PurpleAccount *account, const char *username, - void *icon_data, size_t icon_len); - -/** - * Destroys a buddy icon structure. - * - * If the buddy icon's reference count is greater than 1, this will - * just decrease the reference count and return. - * - * @param icon The buddy icon structure to destroy. - */ -void purple_buddy_icon_destroy(PurpleBuddyIcon *icon); + void *icon_data, size_t icon_len, + const char *checksum); /** * Increments the reference count on a buddy icon. @@ -103,52 +88,17 @@ void purple_buddy_icon_update(PurpleBuddyIcon *icon); /** - * Caches a buddy icon associated with a specific buddy to disk. - * - * @param icon The buddy icon. - * @param buddy The buddy that this icon belongs to. - */ -void purple_buddy_icon_cache(PurpleBuddyIcon *icon, PurpleBuddy *buddy); - -/** - * Removes cached buddy icon for a specific buddy. - * - * @param buddy The buddy for which to remove the cached icon. - */ -void purple_buddy_icon_uncache(PurpleBuddy *buddy); - -/** - * Sets the buddy icon's account. - * - * @param icon The buddy icon. - * @param account The account. - */ -void purple_buddy_icon_set_account(PurpleBuddyIcon *icon, PurpleAccount *account); - -/** - * Sets the buddy icon's username. - * - * @param icon The buddy icon. - * @param username The username. - */ -void purple_buddy_icon_set_username(PurpleBuddyIcon *icon, const char *username); - -/** - * Sets the buddy icon's icon data. + * Sets the buddy icon's data. * * @param icon The buddy icon. - * @param data The buddy icon data. - * @param len The length of the icon data. + * @param data The buddy icon data, which the buddy icon code + * takes ownership of and will free. + * @param len The length of the data in @a data. + * @param checksum A protocol checksum from the prpl or @c NULL. */ -void purple_buddy_icon_set_data(PurpleBuddyIcon *icon, void *data, size_t len); - -/** - * Sets the buddy icon's path. - * - * @param icon The buddy icon. - * @param path The buddy icon's non-cached path. - */ -void purple_buddy_icon_set_path(PurpleBuddyIcon *icon, const gchar *path); +void +purple_buddy_icon_set_data(PurpleBuddyIcon *icon, guchar *data, + size_t len, const char *checksum); /** * Returns the buddy icon's account. @@ -169,32 +119,52 @@ const char *purple_buddy_icon_get_username(const PurpleBuddyIcon *icon); /** + * Returns the buddy icon's checksum. + * + * This function is really only for prpl use. + * + * @param icon The buddy icon. + * + * @return The checksum. + */ +const char *purple_buddy_icon_get_checksum(const PurpleBuddyIcon *icon); + +/** * Returns the buddy icon's data. * * @param icon The buddy icon. - * @param len The returned icon length. + * @param len If not @c NULL, the length of the icon data returned will be + * set in the location pointed to by this. * - * @return The icon data. + * @return A pointer to the icon data. */ -const guchar *purple_buddy_icon_get_data(const PurpleBuddyIcon *icon, size_t *len); - -/** - * Returns the buddy icon's path. - * - * @param icon The buddy icon. - * - * @return The buddy icon's non-cached path. - */ -const gchar *purple_buddy_icon_get_path(PurpleBuddyIcon *icon); +gconstpointer purple_buddy_icon_get_data(const PurpleBuddyIcon *icon, size_t *len); /** * Returns an extension corresponding to the buddy icon's file type. * * @param icon The buddy icon. * - * @return The icon's extension. + * @return The icon's extension, "icon" if unknown, or @c NULL if + * the image data has disappeared. */ -const char *purple_buddy_icon_get_type(const PurpleBuddyIcon *icon); +const char *purple_buddy_icon_get_extension(const PurpleBuddyIcon *icon); + +/** + * Returns a full path to an icon. + * + * If the icon has data and the file exists in the cache, this will return + * a full path to the cache file. + * + * In general, it is not appropriate to be poking in the icon cache + * directly. If you find yourself wanting to use this function, think + * very long and hard about it, and then don't. + * + * @param icon The buddy icon + * + * @return A full path to the file, or @c NULL under various conditions. + */ +char *purple_buddy_icon_get_full_path(PurpleBuddyIcon *icon); /*@}*/ @@ -208,13 +178,30 @@ * * @param account The account the user is on. * @param username The username of the user. - * @param icon_data The icon data. + * @param icon_data The buddy icon data, which the buddy icon code + * takes ownership of and will free. * @param icon_len The length of the icon data. + * @param checksum A protocol checksum from the prpl or @c NULL. * * @return The buddy icon set, or NULL if no icon was set. */ -void purple_buddy_icons_set_for_user(PurpleAccount *account, const char *username, - void *icon_data, size_t icon_len); +void +purple_buddy_icons_set_for_user(PurpleAccount *account, const char *username, + void *icon_data, size_t icon_len, + const char *checksum); + +/** + * Returns the checksum for the buddy icon of a specified buddy. + * + * This avoids loading the icon image data from the cache if it's + * not already loaded for some other reason. + * + * @param buddy The buddy + * + * @return The checksum. + */ +const char * +purple_buddy_icons_get_checksum_for_user(PurpleBuddy *buddy); /** * Returns the buddy icon information for a user. @@ -224,8 +211,90 @@ * * @return The icon data if found, or @c NULL if not found. */ -PurpleBuddyIcon *purple_buddy_icons_find(PurpleAccount *account, - const char *username); +PurpleBuddyIcon * +purple_buddy_icons_find(PurpleAccount *account, const char *username); + +/** + * Returns a boolean indicating if a given contact has a custom buddy icon. + * + * @param contact The contact + * + * @return A boolean indicating if @a contact has a custom buddy icon. + */ +gboolean +purple_buddy_icons_has_custom_icon(PurpleContact *contact); + +/** + * Returns the buddy icon image for an account. + * + * The caller owns a reference to the image in the store, and must dereference + * the image with purple_imgstore_unref() for it to be freed. + * + * This function deals with loading the icon from the cache, if + * needed, so it should be called in any case where you want the + * appropriate icon. + * + * @param account The account + * + * @return The account's buddy icon image. + */ +PurpleStoredImage * +purple_buddy_icons_find_account_icon(PurpleAccount *account); + +/** + * Sets a buddy icon for an account. + * + * This function will deal with saving a record of the icon, + * caching the data, etc. + * + * @param account The account for which to set a custom icon. + * @param icon_data The image data of the icon, which the + * buddy icon code will free. + * @param icon_len The length of the data in @a icon_data. + * + * @return The icon that was set. The caller does NOT own + * a reference to this, and must call purple_imgstore_ref() + * if it wants one. + */ +PurpleStoredImage * +purple_buddy_icons_set_account_icon(PurpleAccount *account, + guchar *icon_data, size_t icon_len); + +/** + * Returns the custom buddy icon image for a contact. + * + * The caller owns a reference to the image in the store, and must dereference + * the image with purple_imgstore_unref() for it to be freed. + * + * This function deals with loading the icon from the cache, if + * needed, so it should be called in any case where you want the + * appropriate icon. + * + * @param contact The contact + * + * @return The custom buddy icon image. + */ +PurpleStoredImage * +purple_buddy_icons_find_custom_icon(PurpleContact *contact); + +/** + * Sets a custom buddy icon for a user. + * + * This function will deal with saving a record of the icon, + * caching the data, etc. + * + * @param contact The contact for which to set a custom icon. + * @param icon_data The image data of the icon, which the + * buddy icon code will free. + * @param icon_len The length of the data in @a icon_data. + * + * @return The icon that was set. The caller does NOT own + * a reference to this, and must call purple_imgstore_ref() + * if it wants one. + */ +PurpleStoredImage * +purple_buddy_icons_set_custom_icon(PurpleContact *contact, + guchar *icon_data, size_t icon_len); /** * Sets whether or not buddy icon caching is enabled. @@ -263,18 +332,6 @@ const char *purple_buddy_icons_get_cache_dir(void); /** - * Takes a buddy icon and returns a full path. - * - * If @a icon is a full path to an existing file, a copy of - * @a icon is returned. Otherwise, a newly allocated string - * consiting of purple_buddy_icons_get_cache_dir() + @a icon is - * returned. - * - * @return The full path for an icon. - */ -char *purple_buddy_icons_get_full_path(const char *icon); - -/** * Returns the buddy icon subsystem handle. * * @return The subsystem handle.
--- a/libpurple/conversation.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/conversation.c Sat Apr 28 03:53:00 2007 +0000 @@ -425,8 +425,7 @@ purple_conv_im_stop_typing_timeout(conv->u.im); purple_conv_im_stop_send_typed_timeout(conv->u.im); - if (conv->u.im->icon != NULL) - purple_buddy_icon_unref(conv->u.im->icon); + purple_buddy_icon_unref(conv->u.im->icon); conv->u.im->icon = NULL; PURPLE_DBUS_UNREGISTER_POINTER(conv->u.im); @@ -941,8 +940,7 @@ if (im->icon != icon) { - if (im->icon != NULL) - purple_buddy_icon_unref(im->icon); + purple_buddy_icon_unref(im->icon); im->icon = (icon == NULL ? NULL : purple_buddy_icon_ref(icon)); }
--- a/libpurple/core.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/core.c Sat Apr 28 03:53:00 2007 +0000 @@ -31,6 +31,7 @@ #include "dnsquery.h" #include "ft.h" #include "idle.h" +#include "imgstore.h" #include "network.h" #include "notify.h" #include "plugin.h" @@ -44,6 +45,7 @@ #include "sslconn.h" #include "status.h" #include "stun.h" +#include "util.h" #ifdef HAVE_DBUS # include "dbus-server.h" @@ -123,6 +125,9 @@ purple_plugins_init(); purple_plugins_probe(G_MODULE_SUFFIX); + /* The buddy icon code uses the imgstore, so init it early. */ + purple_imgstore_init(); + /* Accounts use status and buddy icons, so initialize these before accounts */ purple_status_init(); purple_buddy_icons_init(); @@ -189,6 +194,7 @@ purple_xfers_uninit(); purple_proxy_uninit(); purple_dnsquery_uninit(); + purple_imgstore_uninit(); purple_debug_info("main", "Unloading all plugins\n"); purple_plugins_destroy_all(); @@ -268,3 +274,376 @@ { return _ops; } + +static gboolean +move_and_symlink_dir(const char *path, const char *basename, const char *old_base, const char *new_base, const char *relative) +{ + char *new_name = g_build_filename(new_base, basename, NULL); +#ifndef _WIN32 + char *old_name; +#endif + if (g_rename(path, new_name)) + { + purple_debug_error("core", "Error renaming %s to %s: %s\n", + path, new_name, strerror(errno)); + g_free(new_name); + return FALSE; + } + g_free(new_name); + +#ifndef _WIN32 + /* NOTE: This new_name is relative. */ + new_name = g_build_filename(relative, basename, NULL); + old_name = g_build_filename(old_base, basename, NULL); + if (symlink(new_name, old_name)) + { + purple_debug_warning("core", "Error symlinking %s to %s: %s\n", + old_name, new_name, strerror(errno)); + } + g_free(old_name); + g_free(new_name); +#endif + + return TRUE; +} + +gboolean +purple_core_migrate(void) +{ + const char *user_dir = purple_user_dir(); + char *old_user_dir = g_strconcat(purple_home_dir(), + G_DIR_SEPARATOR_S ".gaim", NULL); + char *status_file; + FILE *fp; + GDir *dir; + GError *err; + const char *entry; +#ifndef _WIN32 + char *logs_dir; +#endif + char *old_icons_dir; + + if (!g_file_test(old_user_dir, G_FILE_TEST_EXISTS)) + { + /* ~/.gaim doesn't exist, so there's nothing to migrate. */ + g_free(old_user_dir); + return TRUE; + } + + status_file = g_strconcat(user_dir, G_DIR_SEPARATOR_S "migrating", NULL); + + if (g_file_test(user_dir, G_FILE_TEST_EXISTS)) + { + /* If we're here, we have both ~/.gaim and .purple. */ + + if (!g_file_test(status_file, G_FILE_TEST_EXISTS)) + { + /* There's no "migrating" status file, + * so ~/.purple is all up to date. */ + g_free(status_file); + g_free(old_user_dir); + return TRUE; + } + } + + /* If we're here, it's time to migrate from ~/.gaim to ~/.purple. */ + + /* Ensure the user directory exists */ + if (!g_file_test(user_dir, G_FILE_TEST_IS_DIR)) + { + if (g_mkdir(user_dir, S_IRUSR | S_IWUSR | S_IXUSR) == -1) + { + purple_debug_error("core", "Error creating directory %s: %s\n", + user_dir, strerror(errno)); + g_free(status_file); + g_free(old_user_dir); + return FALSE; + } + } + + /* This writes ~/.purple/migrating, which allows us to detect + * incomplete migrations and properly retry. */ + if (!(fp = g_fopen(status_file, "w"))) + { + purple_debug_error("core", "Error opening file %s for writing: %s\n", + status_file, strerror(errno)); + g_free(status_file); + g_free(old_user_dir); + return FALSE; + } + fclose(fp); + + /* Open ~/.gaim so we can loop over its contents. */ + err = NULL; + if (!(dir = g_dir_open(old_user_dir, 0, &err))) + { + purple_debug_error("core", "Error opening directory %s: %s\n", + status_file, + (err ? err->message : "Unknown error")); + if (err) + g_error_free(err); + g_free(status_file); + g_free(old_user_dir); + return FALSE; + } + + /* Loop over the contents of ~/.gaim */ + while ((entry = g_dir_read_name(dir))) + { + char *name = g_build_filename(old_user_dir, entry, NULL); + +#ifndef _WIN32 + /* Deal with symlinks... */ + if (g_file_test(name, G_FILE_TEST_IS_SYMLINK)) + { + /* We're only going to duplicate a logs symlink. */ + if (!strcmp(entry, "logs")) + { + char buf[MAXPATHLEN]; + + if (readlink(name, buf, sizeof(buf) - 1) == -1) + { + purple_debug_error("core", "Error reading symlink %s: %s\n", + name, strerror(errno)); + g_free(name); + g_dir_close(dir); + g_free(status_file); + g_free(old_user_dir); + return FALSE; + } + buf[sizeof(buf) - 1] = '\0'; + + logs_dir = g_strconcat(user_dir, G_DIR_SEPARATOR_S "logs", NULL); + + if (!strcmp(buf, "../.purple/logs") || !strcmp(buf, logs_dir)) + { + /* If the symlink points to the new directory, we're + * likely just trying again after a failed migration, + * so there's no need to fail here. */ + g_free(logs_dir); + continue; + } + + /* In case we are trying again after a failed migration, we need + * to unlink any existing symlink. If it's a directory, this + * will fail, and so will the symlink below, which is good + * because the user should sort things out. */ + g_unlink(logs_dir); + + /* Relative links will most likely still be + * valid from ~/.purple, though not it's not + * guaranteed. Oh well. */ + if (symlink(buf, logs_dir)) + { + purple_debug_error("core", "Error symlinking %s to %s: %s\n", + logs_dir, buf, strerror(errno)); + g_free(name); + g_free(logs_dir); + g_dir_close(dir); + g_free(status_file); + g_free(old_user_dir); + return FALSE; + } + + g_free(logs_dir); + continue; + } + + /* Ignore all other symlinks. */ + continue; + } +#endif + + /* Deal with directories... */ + if (g_file_test(name, G_FILE_TEST_IS_DIR)) + { + if (!strcmp(entry, "icons")) + { + /* This is a special case for the Album plugin, which + * stores data in the icons folder. We're not copying + * the icons directory over because previous bugs + * meant that it filled up with junk for many users. + * This is a great time to purge it. */ + + GDir *icons_dir; + char *new_icons_dir; + const char *icons_entry; + + err = NULL; + if (!(icons_dir = g_dir_open(name, 0, &err))) + { + purple_debug_error("core", "Error opening directory %s: %s\n", + name, + (err ? err->message : "Unknown error")); + if (err) + g_error_free(err); + g_free(name); + g_dir_close(dir); + g_free(status_file); + g_free(old_user_dir); + return FALSE; + } + + new_icons_dir = g_build_filename(user_dir, "icons", NULL); + /* Ensure the new icon directory exists */ + if (!g_file_test(new_icons_dir, G_FILE_TEST_IS_DIR)) + { + if (g_mkdir(new_icons_dir, S_IRUSR | S_IWUSR | S_IXUSR) == -1) + { + purple_debug_error("core", "Error creating directory %s: %s\n", + new_icons_dir, strerror(errno)); + g_free(new_icons_dir); + g_dir_close(icons_dir); + g_free(name); + g_dir_close(dir); + g_free(status_file); + g_free(old_user_dir); + return FALSE; + } + } + + while ((icons_entry = g_dir_read_name(icons_dir))) + { + char *icons_name = g_build_filename(name, icons_entry, NULL); + + if (g_file_test(icons_name, G_FILE_TEST_IS_DIR)) + { + if (!move_and_symlink_dir(icons_name, icons_entry, + name, new_icons_dir, "../../.purple/icons")) + { + g_free(icons_name); + g_free(new_icons_dir); + g_dir_close(icons_dir); + g_free(name); + g_dir_close(dir); + g_free(status_file); + g_free(old_user_dir); + return FALSE; + } + } + g_free(icons_name); + } + + g_dir_close(icons_dir); + } + else if (!strcmp(entry, "plugins")) + { + /* Do nothing, because we broke plugin compatibility. + * This means that the plugins directory gets left behind. */ + } + else + { + /* All other directories are moved and symlinked. */ + if (!move_and_symlink_dir(name, entry, old_user_dir, user_dir, "../.purple")) + { + g_free(name); + g_dir_close(dir); + g_free(status_file); + g_free(old_user_dir); + return FALSE; + } + } + } + else if (g_file_test(name, G_FILE_TEST_IS_REGULAR)) + { + /* Regular files are copied. */ + + char *new_name; + FILE *new_file; + + if (!(fp = g_fopen(name, "rb"))) + { + purple_debug_error("core", "Error opening file %s for reading: %s\n", + name, strerror(errno)); + g_free(name); + g_dir_close(dir); + g_free(status_file); + g_free(old_user_dir); + return FALSE; + } + + new_name = g_build_filename(user_dir, entry, NULL); + if (!(new_file = g_fopen(new_name, "wb"))) + { + purple_debug_error("core", "Error opening file %s for writing: %s\n", + new_name, strerror(errno)); + fclose(fp); + g_free(new_name); + g_free(name); + g_dir_close(dir); + g_free(status_file); + g_free(old_user_dir); + return FALSE; + } + + while (!feof(fp)) + { + unsigned char buf[256]; + size_t size; + + size = fread(buf, 1, sizeof(buf), fp); + if (size != sizeof(buf) && !feof(fp)) + { + purple_debug_error("core", "Error reading %s: %s\n", + name, strerror(errno)); + fclose(new_file); + fclose(fp); + g_free(new_name); + g_free(name); + g_dir_close(dir); + g_free(status_file); + g_free(old_user_dir); + return FALSE; + } + + if (!fwrite(buf, size, 1, new_file) && ferror(new_file) != 0) + { + purple_debug_error("core", "Error writing %s: %s\n", + new_name, strerror(errno)); + fclose(new_file); + fclose(fp); + g_free(new_name); + g_free(name); + g_dir_close(dir); + g_free(status_file); + g_free(old_user_dir); + return FALSE; + } + } + + if (fclose(new_file)) + { + purple_debug_error("core", "Error writing: %s: %s\n", + new_name, strerror(errno)); + } + if (fclose(fp)) + { + purple_debug_warning("core", "Error closing %s: %s\n", + name, strerror(errno)); + } + g_free(new_name); + } + else + purple_debug_warning("core", "Not a regular file or directory: %s\n", name); + + g_free(name); + } + + /* The migration was successful, so delete the status file. */ + if (g_unlink(status_file)) + { + purple_debug_error("core", "Error unlinking file %s: %s\n", + status_file, strerror(errno)); + g_free(status_file); + return FALSE; + } + + old_icons_dir = g_build_filename(old_user_dir, "icons", NULL); + purple_buddy_icon_set_old_icons_dir(old_icons_dir); + g_free(old_icons_dir); + + g_free(old_user_dir); + + g_free(status_file); + return TRUE; +}
--- a/libpurple/core.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/core.h Sat Apr 28 03:53:00 2007 +0000 @@ -106,6 +106,17 @@ */ PurpleCoreUiOps *purple_core_get_ui_ops(void); +/** + * Migrates from .gaim to .purple. + * + * UIs MUST NOT call this if they have been told to use a custom + * user directory. + * + * @return A boolean indicating success or migration failure. On failure, + * the application must display an error to the user and then exit. + */ +gboolean purple_core_migrate(void); + #ifdef __cplusplus } #endif
--- a/libpurple/gaim-compat.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/gaim-compat.h Sat Apr 28 03:53:00 2007 +0000 @@ -27,6 +27,8 @@ #ifndef _GAIM_COMPAT_H_ #define _GAIM_COMPAT_H_ +#include <glib.h> + /* from account.h */ #define GaimAccountUiOps PurpleAccountUiOps #define GaimAccount PurpleAccount @@ -51,7 +53,6 @@ #define gaim_account_set_password purple_account_set_password #define gaim_account_set_alias purple_account_set_alias #define gaim_account_set_user_info purple_account_set_user_info -#define gaim_account_set_buddy_icon purple_account_set_buddy_icon #define gaim_account_set_buddy_icon_path purple_account_set_buddy_icon_path #define gaim_account_set_protocol_id purple_account_set_protocol_id #define gaim_account_set_connection purple_account_set_connection @@ -81,7 +82,6 @@ #define gaim_account_get_password purple_account_get_password #define gaim_account_get_alias purple_account_get_alias #define gaim_account_get_user_info purple_account_get_user_info -#define gaim_account_get_buddy_icon purple_account_get_buddy_icon #define gaim_account_get_buddy_icon_path purple_account_get_buddy_icon_path #define gaim_account_get_protocol_id purple_account_get_protocol_id #define gaim_account_get_protocol_name purple_account_get_protocol_name @@ -338,32 +338,27 @@ #define GaimBuddyIcon PurpleBuddyIcon -#define gaim_buddy_icon_new purple_buddy_icon_new -#define gaim_buddy_icon_destroy purple_buddy_icon_destroy +#define gaim_buddy_icon_new(account, username, icon_data, icon_len)\ + purple_buddy_icon_new(account, username, g_memdup(icon_data, icon_len), icon_len) #define gaim_buddy_icon_ref purple_buddy_icon_ref #define gaim_buddy_icon_unref purple_buddy_icon_unref #define gaim_buddy_icon_update purple_buddy_icon_update -#define gaim_buddy_icon_cache purple_buddy_icon_cache -#define gaim_buddy_icon_uncache purple_buddy_icon_uncache - -#define gaim_buddy_icon_set_account purple_buddy_icon_set_account -#define gaim_buddy_icon_set_username purple_buddy_icon_set_username -#define gaim_buddy_icon_set_data purple_buddy_icon_set_data -#define gaim_buddy_icon_set_path purple_buddy_icon_set_path + +#define gaim_buddy_icon_set_data(icon, data, len) \ + purple_buddy_icon_set_protocol_data(icon, g_memdup(data, len), len, NULL); #define gaim_buddy_icon_get_account purple_buddy_icon_get_account #define gaim_buddy_icon_get_username purple_buddy_icon_get_username #define gaim_buddy_icon_get_data purple_buddy_icon_get_data -#define gaim_buddy_icon_get_path purple_buddy_icon_get_path -#define gaim_buddy_icon_get_type purple_buddy_icon_get_type - -#define gaim_buddy_icons_set_for_user purple_buddy_icons_set_for_user +#define gaim_buddy_icon_get_type purple_buddy_icon_get_extension + +#define gaim_buddy_icons_set_for_user(icon, data, len) \ + purple_buddy_icons_set_for_user(icon, g_memdup(data, len), len) #define gaim_buddy_icons_find purple_buddy_icons_find #define gaim_buddy_icons_set_caching purple_buddy_icons_set_caching #define gaim_buddy_icons_is_caching purple_buddy_icons_is_caching #define gaim_buddy_icons_set_cache_dir purple_buddy_icons_set_cache_dir #define gaim_buddy_icons_get_cache_dir purple_buddy_icons_get_cache_dir -#define gaim_buddy_icons_get_full_path purple_buddy_icons_get_full_path #define gaim_buddy_icons_get_handle purple_buddy_icons_get_handle #define gaim_buddy_icons_init purple_buddy_icons_init @@ -949,7 +944,6 @@ /* from gaim-client.h */ -/* XXX: should this be purple_init, or pidgin_init */ #define gaim_init purple_init /* from idle.h */ @@ -967,13 +961,13 @@ #define GaimStoredImage PurpleStoredImage -#define gaim_imgstore_add purple_imgstore_add -#define gaim_imgstore_get purple_imgstore_get +#define gaim_imgstore_add(data, size, filename) purple_imgstore_add_with_id(g_memdup(data, size), size, filename) +#define gaim_imgstore_get purple_imgstore_find_by_id #define gaim_imgstore_get_data purple_imgstore_get_data #define gaim_imgstore_get_size purple_imgstore_get_size #define gaim_imgstore_get_filename purple_imgstore_get_filename -#define gaim_imgstore_ref purple_imgstore_ref -#define gaim_imgstore_unref purple_imgstore_unref +#define gaim_imgstore_ref purple_imgstore_ref_by_id +#define gaim_imgstore_unref purple_imgstore_unref_by_id /* from log.h */ @@ -2237,7 +2231,7 @@ #define gaim_value_new_outgoing purple_value_new_outgoing #define gaim_value_destroy purple_value_destroy #define gaim_value_dup purple_value_dup -#define gaim_value_get_type purple_value_get_type +#define gaim_value_purple_buddy_icon_get_extensionget_type purple_value_get_type #define gaim_value_get_subtype purple_value_get_subtype #define gaim_value_get_specific_type purple_value_get_specific_type #define gaim_value_is_outgoing purple_value_is_outgoing
--- a/libpurple/imgstore.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/imgstore.c Sat Apr 28 03:53:00 2007 +0000 @@ -27,140 +27,170 @@ #include <glib.h> #include "debug.h" #include "imgstore.h" +#include "util.h" -static GSList *imgstore = NULL; +static GHashTable *imgstore; static int nextid = 0; /** * Stored image * - * Represents a single IM image awaiting display and/or transmission. - * Now that this type is basicly private too, these two structs could - * probably be combined. + * NOTE: purple_imgstore_add() creates these without zeroing the memory, so + * NOTE: make sure to update that function when adding members. */ struct _PurpleStoredImage { - char *data; /**< The image data. */ + int id; + guint8 refcount; size_t size; /**< The image data's size. */ char *filename; /**< The filename (for the UI) */ + gpointer data; /**< The image data. */ }; -typedef struct +PurpleStoredImage * +purple_imgstore_add(gpointer data, size_t size, const char *filename) { - int id; - int refcount; PurpleStoredImage *img; -} PurpleStoredImagePriv; -/* private functions */ + g_return_val_if_fail(data != NULL, 0); + g_return_val_if_fail(size > 0, 0); -static PurpleStoredImagePriv *purple_imgstore_get_priv(int id) { - GSList *tmp = imgstore; - PurpleStoredImagePriv *priv = NULL; + img = g_new(PurpleStoredImage, 1); + img->data = data; + img->size = size; + img->filename = g_strdup(filename); + img->refcount = 1; + img->id = 0; + + return img; +} + +int +purple_imgstore_add_with_id(gpointer data, size_t size, const char *filename) +{ + PurpleStoredImage *img = purple_imgstore_add(data, size, filename); + img->id = ++nextid; - g_return_val_if_fail(id > 0, NULL); + g_hash_table_insert(imgstore, &(img->id), img); + + return img->id; +} - while (tmp && !priv) { - PurpleStoredImagePriv *tmp_priv = tmp->data; +PurpleStoredImage *purple_imgstore_find_by_id(int id) { + PurpleStoredImage *img = g_hash_table_lookup(imgstore, &id); - if (tmp_priv->id == id) - priv = tmp_priv; + if (img != NULL) + purple_debug_misc("imgstore", "retrieved image id %d\n", img->id); - tmp = tmp->next; - } + return img; +} + +gconstpointer purple_imgstore_get_data(PurpleStoredImage *img) { + g_return_val_if_fail(img != NULL, NULL); - if (!priv) - purple_debug(PURPLE_DEBUG_ERROR, "imgstore", "failed to find image id %d\n", id); + return img->data; +} - return priv; +size_t purple_imgstore_get_size(PurpleStoredImage *img) +{ + g_return_val_if_fail(img != NULL, 0); + + return img->size; } -static void purple_imgstore_free_priv(PurpleStoredImagePriv *priv) { - PurpleStoredImage *img = NULL; +const char *purple_imgstore_get_filename(PurpleStoredImage *img) +{ + g_return_val_if_fail(img != NULL, NULL); + + return img->filename; +} + +const char *purple_imgstore_get_extension(PurpleStoredImage *img) +{ + g_return_val_if_fail(img != NULL, NULL); + + return purple_util_get_image_extension(img->data, img->size); +} + +void purple_imgstore_ref_by_id(int id) +{ + PurpleStoredImage *img = purple_imgstore_find_by_id(id); + + g_return_if_fail(img != NULL); + + purple_imgstore_ref(img); +} + +void purple_imgstore_unref_by_id(int id) +{ + PurpleStoredImage *img = purple_imgstore_find_by_id(id); + + g_return_if_fail(img != NULL); - g_return_if_fail(priv != NULL); + purple_imgstore_unref(img); +} + +PurpleStoredImage * +purple_imgstore_ref(PurpleStoredImage *img) +{ + g_return_val_if_fail(img != NULL, NULL); + + img->refcount++; + + return img; +} - img = priv->img; - if (img) { +PurpleStoredImage * +purple_imgstore_unref(PurpleStoredImage *img) +{ + if (img == NULL) + return NULL; + + g_return_val_if_fail(img->refcount > 0, NULL); + + img->refcount--; + + if (img->refcount == 0) + { + purple_signal_emit(purple_imgstore_get_handle(), + "image-deleting", img); + if (img->id) + g_hash_table_remove(imgstore, &img->id); + g_free(img->data); g_free(img->filename); g_free(img); } - purple_debug(PURPLE_DEBUG_INFO, "imgstore", "freed image id %d\n", priv->id); - - g_free(priv); - - imgstore = g_slist_remove(imgstore, priv); + return img; } -/* public functions */ - -int purple_imgstore_add(const void *data, size_t size, const char *filename) { - PurpleStoredImagePriv *priv; - PurpleStoredImage *img; - - g_return_val_if_fail(data != NULL, 0); - g_return_val_if_fail(size > 0, 0); +void * +purple_imgstore_get_handle() +{ + static int handle; - img = g_new0(PurpleStoredImage, 1); - img->data = g_memdup(data, size); - img->size = size; - img->filename = g_strdup(filename); - - priv = g_new0(PurpleStoredImagePriv, 1); - priv->id = ++nextid; - priv->refcount = 1; - priv->img = img; - - imgstore = g_slist_append(imgstore, priv); - purple_debug(PURPLE_DEBUG_INFO, "imgstore", "added image id %d\n", priv->id); - - return priv->id; + return &handle; } -PurpleStoredImage *purple_imgstore_get(int id) { - PurpleStoredImagePriv *priv = purple_imgstore_get_priv(id); - - g_return_val_if_fail(priv != NULL, NULL); - - purple_debug(PURPLE_DEBUG_INFO, "imgstore", "retrieved image id %d\n", priv->id); - - return priv->img; -} +void +purple_imgstore_init() +{ + void *handle = purple_imgstore_get_handle(); -gpointer purple_imgstore_get_data(PurpleStoredImage *i) { - return i->data; -} + purple_signal_register(handle, "image-deleting", + purple_marshal_VOID__POINTER, NULL, + 1, + purple_value_new(PURPLE_TYPE_SUBTYPE, + PURPLE_SUBTYPE_STORED_IMAGE)); -size_t purple_imgstore_get_size(PurpleStoredImage *i) { - return i->size; -} - -const char *purple_imgstore_get_filename(PurpleStoredImage *i) { - return i->filename; + imgstore = g_hash_table_new(g_int_hash, g_int_equal); } -void purple_imgstore_ref(int id) { - PurpleStoredImagePriv *priv = purple_imgstore_get_priv(id); - - g_return_if_fail(priv != NULL); - - (priv->refcount)++; - - purple_debug(PURPLE_DEBUG_INFO, "imgstore", "referenced image id %d (count now %d)\n", priv->id, priv->refcount); -} +void +purple_imgstore_uninit() +{ + g_hash_table_destroy(imgstore); -void purple_imgstore_unref(int id) { - PurpleStoredImagePriv *priv = purple_imgstore_get_priv(id); - - g_return_if_fail(priv != NULL); - g_return_if_fail(priv->refcount > 0); - - (priv->refcount)--; - - purple_debug(PURPLE_DEBUG_INFO, "imgstore", "unreferenced image id %d (count now %d)\n", priv->id, priv->refcount); - - if (priv->refcount == 0) - purple_imgstore_free_priv(priv); + purple_signals_unregister_by_instance(purple_imgstore_get_handle()); }
--- a/libpurple/imgstore.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/imgstore.h Sat Apr 28 03:53:00 2007 +0000 @@ -26,6 +26,8 @@ #ifndef _PURPLE_IMGSTORE_H_ #define _PURPLE_IMGSTORE_H_ +#include <glib.h> + struct _PurpleStoredImage; typedef struct _PurpleStoredImage PurpleStoredImage; @@ -34,17 +36,41 @@ #endif /** - * Add an image to the store. The caller owns a reference - * to the image in the store, and must dereference the image - * with purple_imgstore_unref for it to be freed. + * Add an image to the store. + * + * The caller owns a reference to the image in the store, and must dereference + * the image with purple_imgstore_unref() for it to be freed. + * + * No ID is allocated when using this function. If you need to reference the + * image by an ID, use purple_imgstore_add_with_id() instead. + * + * @param data Pointer to the image data, which the imgstore will take + * ownership of and free as appropriate. If you want a + * copy of the data, make it before calling this function. + * @param size Image data's size. + * @param filename Filename associated with image. * - * @param data Pointer to the image data. + * @return The stored image. + */ +PurpleStoredImage * +purple_imgstore_add(gpointer data, size_t size, const char *filename); + +/** + * Add an image to the store, allocating an ID. + * + * The caller owns a reference to the image in the store, and must dereference + * the image with purple_imgstore_unref_by_id() or purple_imgstore_unref() + * for it to be freed. + * + * @param data Pointer to the image data, which the imgstore will take + * ownership of and free as appropriate. If you want a + * copy of the data, make it before calling this function. * @param size Image data's size. * @param filename Filename associated with image. * @return ID for the image. */ -int purple_imgstore_add(const void *data, size_t size, const char *filename); +int purple_imgstore_add_with_id(gpointer data, size_t size, const char *filename); /** * Retrieve an image from the store. The caller does not own a @@ -54,55 +80,107 @@ * * @return A pointer to the requested image, or NULL if it was not found. */ -PurpleStoredImage *purple_imgstore_get(int id); +PurpleStoredImage *purple_imgstore_find_by_id(int id); /** * Retrieves a pointer to the image's data. * - * @param i The Image + * @param img The Image * * @return A pointer to the data, which must not * be freed or modified. */ -gpointer purple_imgstore_get_data(PurpleStoredImage *i); +gconstpointer purple_imgstore_get_data(PurpleStoredImage *img); /** * Retrieves the length of the image's data. * - * @param i The Image + * @param img The Image * * @return The size of the data that the pointer returned by * purple_imgstore_get_data points to. */ -size_t purple_imgstore_get_size(PurpleStoredImage *i); +size_t purple_imgstore_get_size(PurpleStoredImage *img); /** * Retrieves a pointer to the image's filename. * - * @param i The Image + * @param img The image * * @return A pointer to the filename, which must not * be freed or modified. */ -const char *purple_imgstore_get_filename(PurpleStoredImage *i); +const char *purple_imgstore_get_filename(PurpleStoredImage *img); + +/** + * Returns an extension corresponding to the image's file type. + * + * @param img The image. + * + * @return The icon's extension or "icon" if unknown. + */ +const char *purple_imgstore_get_extension(PurpleStoredImage *img); /** - * Increment the reference count for an image in the store. The - * image will be removed from the store when the reference count - * is zero. + * Increment the reference count. + * + * @param img The image. + * + * @return @a img + */ +PurpleStoredImage * +purple_imgstore_ref(PurpleStoredImage *img); + +/** + * Decrement the reference count. + * + * If the reference count reaches zero, the image will be freed. + * + * @param img The image. + * + * @return @a img or @c NULL if the reference count reached zero. + */ +PurpleStoredImage * +purple_imgstore_unref(PurpleStoredImage *img); + +/** + * Increment the reference count using an ID. + * + * This is a convience wrapper for purple_imgstore_find_by_id() and + * purple_imgstore_ref(), so if you have a PurpleStoredImage, it'll + * be more efficient to call purple_imgstore_ref() directly. * * @param id The ID for the image. */ -void purple_imgstore_ref(int id); +void purple_imgstore_ref_by_id(int id); /** - * Decrement the reference count for an image in the store. The - * image will be removed from the store when the reference count - * is zero. + * Decrement the reference count using an ID. + * + * This is a convience wrapper for purple_imgstore_find_by_id() and + * purple_imgstore_unref(), so if you have a PurpleStoredImage, it'll + * be more efficient to call purple_imgstore_unref() directly. * * @param id The ID for the image. */ -void purple_imgstore_unref(int id); +void purple_imgstore_unref_by_id(int id); + +/** + * Returns the image store subsystem handle. + * + * @return The subsystem handle. + */ +void *purple_imgstore_get_handle(void); + +/** + * Initializes the image store subsystem. + */ +void purple_imgstore_init(void); + +/** + * Uninitializes the image store subsystem. + */ +void purple_imgstore_uninit(void); #ifdef __cplusplus }
--- a/libpurple/internal.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/internal.h Sat Apr 28 03:53:00 2007 +0000 @@ -184,4 +184,20 @@ #define PURPLE_WEBSITE "http://pidgin.im/" +/* This is for the accounts code to notify the buddy icon code that + * it's done loading. We may want to replace this with a signal. */ +void +purple_buddy_icons_account_loaded_cb(void); + +/* This is for the buddy list to notify the buddy icon code that + * it's done loading. We may want to replace this with a signal. */ +void +purple_buddy_icons_blist_loaded_cb(void); + +/* This is for the purple_core_migrate() code to tell the buddy + * icon subsystem about the old icons directory so it can + * migrate any icons in use. */ +void +purple_buddy_icon_set_old_icons_dir(const char *dirname); + #endif /* _PURPLE_INTERNAL_H_ */
--- a/libpurple/plugins/perl/Makefile.am Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/plugins/perl/Makefile.am Sat Apr 28 03:53:00 2007 +0000 @@ -1,13 +1,11 @@ plugindir = $(libdir)/purple -hackdir = $(plugindir)/private perl_dirs = common plugin_LTLIBRARIES = perl.la -hack_LTLIBRARIES = libpurpleperl.la perl_la_LDFLAGS = -module -avoid-version -perl_la_LIBADD = $(GLIB_LIBS) $(PERL_LIBS) libpurpleperl.la +perl_la_LIBADD = $(GLIB_LIBS) $(PERL_LIBS) perl_la_SOURCES = \ perl.c \ perl-common.c \ @@ -17,12 +15,7 @@ perl_la_DEPENDENCIES = \ .libs/libperl_orig.a \ - .libs/DynaLoader.a \ - libpurpleperl.la - -libpurpleperl_la_LDFLAGS = -module -avoid-version -libpurpleperl_la_LIBADD = $(GLIB_LIBS) -libpurpleperl_la_SOURCES = libpurpleperl.c + .libs/DynaLoader.a .libs/libperl_orig.a: @mkdir -p .libs @@ -42,55 +35,52 @@ $(LN_S) $(DYNALOADER_A) .libs/DynaLoader.a; \ fi - common_sources = \ - common/Account.xs \ - common/AccountOpts.xs \ - common/BuddyIcon.xs \ - common/BuddyList.xs \ - common/Cipher.xs \ - common/Cmds.xs \ - common/Core.xs \ - common/Connection.xs \ - common/Conversation.xs \ - common/Debug.xs \ - common/FT.xs \ - common/ImgStore.xs \ - common/Log.xs \ - common/Makefile.PL.in \ - common/Network.xs \ - common/Notify.xs \ - common/Plugin.xs \ - common/PluginPref.xs \ - common/Pounce.xs \ - common/Prefs.xs \ - common/Privacy.xs \ - common/Proxy.xs \ - common/Prpl.xs \ - common/Purple.pm \ - common/Purple.xs \ - common/Request.xs \ - common/Roomlist.xs \ - common/SSLConn.xs \ - common/SavedStatuses.xs \ - common/Server.xs \ - common/Signal.xs \ - common/Sound.xs \ - common/Status.xs \ - common/Stringref.xs \ - common/Util.xs \ - common/XMLNode.xs \ - common/fallback/const-c.inc \ - common/fallback/const-xs.inc \ - common/module.h \ - common/typemap - + common/Account.xs \ + common/AccountOpts.xs \ + common/BuddyIcon.xs \ + common/BuddyList.xs \ + common/Cipher.xs \ + common/Cmds.xs \ + common/Core.xs \ + common/Connection.xs \ + common/Conversation.xs \ + common/Debug.xs \ + common/FT.xs \ + common/ImgStore.xs \ + common/Log.xs \ + common/Makefile.PL.in \ + common/Network.xs \ + common/Notify.xs \ + common/Plugin.xs \ + common/PluginPref.xs \ + common/Pounce.xs \ + common/Prefs.xs \ + common/Privacy.xs \ + common/Proxy.xs \ + common/Prpl.xs \ + common/Purple.pm \ + common/Purple.xs \ + common/Request.xs \ + common/Roomlist.xs \ + common/SSLConn.xs \ + common/SavedStatuses.xs \ + common/Server.xs \ + common/Signal.xs \ + common/Sound.xs \ + common/Status.xs \ + common/Stringref.xs \ + common/Util.xs \ + common/XMLNode.xs \ + common/module.h \ + common/typemap \ + common/fallback/const-c.inc \ + common/fallback/const-xs.inc EXTRA_DIST = \ Makefile.mingw \ common/Makefile.mingw \ - $(common_sources) \ - libpurpleperl.c + $(common_sources) common/Makefile: common/Makefile.PL @if test "x${top_srcdir}" != "x${top_builddir}"; then \ @@ -157,7 +147,6 @@ done; \ fi - AM_CPPFLAGS = \ -DVERSION=\"$(VERSION)\" \ -I$(top_srcdir) \
--- a/libpurple/plugins/perl/common/Account.xs Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/plugins/perl/common/Account.xs Sat Apr 28 03:53:00 2007 +0000 @@ -59,7 +59,7 @@ const char *user_info void -purple_account_set_buddy_icon(account, icon) +purple_account_set_buddy_icon_path(account, icon) Purple::Account account const char *icon @@ -144,7 +144,7 @@ Purple::Account account const char * -purple_account_get_buddy_icon(account) +purple_account_get_buddy_icon_path(account) Purple::Account account const char *
--- a/libpurple/plugins/perl/common/BuddyIcon.xs Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/plugins/perl/common/BuddyIcon.xs Sat Apr 28 03:53:00 2007 +0000 @@ -3,10 +3,6 @@ MODULE = Purple::Buddy::Icon PACKAGE = Purple::Buddy::Icon PREFIX = purple_buddy_icon_ PROTOTYPES: ENABLE -void -purple_buddy_icon_destroy(icon) - Purple::Buddy::Icon icon - Purple::Buddy::Icon purple_buddy_icon_ref(icon) Purple::Buddy::Icon icon @@ -20,25 +16,11 @@ Purple::Buddy::Icon icon void -purple_buddy_icon_cache(icon, buddy) - Purple::Buddy::Icon icon - Purple::BuddyList::Buddy buddy - -void -purple_buddy_icon_set_account(icon, account) - Purple::Buddy::Icon icon - Purple::Account account - -void -purple_buddy_icon_set_username(icon, username) - Purple::Buddy::Icon icon - const char * username - -void -purple_buddy_icon_set_data(icon, data, len) +purple_buddy_icon_set_data(icon, data, len, checksum) Purple::Buddy::Icon icon void * data size_t len + char *checksum Purple::Account purple_buddy_icon_get_account(icon) @@ -54,7 +36,7 @@ size_t &len const char * -purple_buddy_icon_get_type(icon) +purple_buddy_icon_get_extension(icon) Purple::Buddy::Icon icon void
--- a/libpurple/plugins/perl/common/ImgStore.xs Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/plugins/perl/common/ImgStore.xs Sat Apr 28 03:53:00 2007 +0000 @@ -3,17 +3,23 @@ MODULE = Purple::ImgStore PACKAGE = Purple::ImgStore PREFIX = purple_imgstore_ PROTOTYPES: ENABLE -int +Purple::StoredImage purple_imgstore_add(data, size, filename) void *data size_t size const char *filename +int +purple_imgstore_add_with_id(data, size, filename) + void *data + size_t size + const char *filename + Purple::StoredImage -purple_imgstore_get(id) +purple_imgstore_find_by_id(id) int id -gpointer +gconstpointer purple_imgstore_get_data(i) Purple::StoredImage i @@ -25,11 +31,23 @@ purple_imgstore_get_size(i) Purple::StoredImage i -void +const char * +purple_imgstore_get_extension(i) + Purple::StoredImage i + +Purple::StoredImage purple_imgstore_ref(id) + Purple::StoredImage id + +Purple::StoredImage +purple_imgstore_unref(id) + Purple::StoredImage id + +void +purple_imgstore_ref_by_id(id) int id -void -purple_imgstore_unref(id) +void +purple_imgstore_unref_by_id(id) int id
--- a/libpurple/plugins/perl/common/Makefile.PL.in Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/plugins/perl/common/Makefile.PL.in Sat Apr 28 03:53:00 2007 +0000 @@ -1,18 +1,18 @@ use 5.006; use ExtUtils::MakeMaker; -# See lib/ExtUtils/MakeMaker.pm for details of how to influence -# the contents of the Makefile that is written. +# See lib/ExtUtils/MakeMaker.pm for details of how to influence the contents +# of the Makefile that is written. WriteMakefile( - 'NAME' => 'Purple', - 'VERSION_FROM' => '@srcdir@/Purple.pm', # finds $VERSION - 'PREREQ_PM' => {}, # e.g., Module::Name => 1.1 - ($] >= 5.005 ? ## Add these new keywords supported since 5.005 - (ABSTRACT_FROM => '@srcdir@/Purple.pm', # retrieve abstract from module - AUTHOR => 'Purple <http://pidgin.im/>') : ()), - 'LIBS' => [''], # e.g., '-lm' - 'DEFINE' => '@DEBUG_CFLAGS@', # e.g., '-DHAVE_SOMETHING' - 'INC' => '-I. -I@srcdir@ -I@top_srcdir@ -I@top_srcdir@/libpurple @GLIB_CFLAGS@', # e.g., '-I. -I/usr/include/other' - 'OBJECT' => '$(O_FILES)', # link all the C files too + 'NAME' => 'Purple', + 'VERSION_FROM' => '@srcdir@/Purple.pm', # finds $VERSION + 'PREREQ_PM' => {}, # e.g., Module::Name => 1.1 + ($] >= 5.005 ? ## Add these new keywords supported since 5.005 + (ABSTRACT_FROM => '@srcdir@/Purple.pm', # finds $ABSTRACT + AUTHOR => 'Purple <http://pidgin.im/>') : ()), + 'DEFINE' => '@DEBUG_CFLAGS@', + 'INC' => '-I. -I@srcdir@ -I@top_srcdir@ -I@top_srcdir@/libpurple @GLIB_CFLAGS@', + 'OBJECT' => '$(O_FILES)', # link all the C files too +# 'OPTIMIZE' => '-g', # For debugging ); if (eval {require ExtUtils::Constant; 1}) {
--- a/libpurple/plugins/perl/common/Makefile.mingw Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/plugins/perl/common/Makefile.mingw Sat Apr 28 03:53:00 2007 +0000 @@ -66,7 +66,7 @@ Status.xs \ Stringref.xs \ Util.xs \ - XMLNode.xs \ + XMLNode.xs FALLBACKS = const-c.inc const-xs.inc C_FILES = $(XS_FILES:%.xs=%.c)
--- a/libpurple/plugins/perl/common/Purple.pm Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/plugins/perl/common/Purple.pm Sat Apr 28 03:53:00 2007 +0000 @@ -58,7 +58,7 @@ =head1 NAME -libpurple - Perl extension to the libpurple instant messenger library. +Purple - Perl extension to the libpurple instant messenger library. =head1 SYNOPSIS
--- a/libpurple/plugins/perl/perl.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/plugins/perl/perl.c Sat Apr 28 03:53:00 2007 +0000 @@ -93,6 +93,8 @@ #include "perl-common.h" #include "perl-handlers.h" +#include <gmodule.h> + #define PERL_PLUGIN_ID "core-perl" PerlInterpreter *my_perl = NULL; @@ -578,11 +580,11 @@ PURPLE_PLUGIN_MAGIC, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, - PURPLE_PLUGIN_LOADER, /**< type */ + PURPLE_PLUGIN_LOADER, /**< type */ NULL, /**< ui_requirement */ 0, /**< flags */ NULL, /**< dependencies */ - PURPLE_PRIORITY_DEFAULT, /**< priority */ + PURPLE_PRIORITY_DEFAULT, /**< priority */ PERL_PLUGIN_ID, /**< id */ N_("Perl Plugin Loader"), /**< name */ @@ -590,7 +592,7 @@ N_("Provides support for loading perl plugins."), /**< summary */ N_("Provides support for loading perl plugins."), /**< description */ "Christian Hammond <chipx86@gnupdate.org>", /**< author */ - PURPLE_WEBSITE, /**< homepage */ + PURPLE_WEBSITE, /**< homepage */ plugin_load, /**< load */ plugin_unload, /**< unload */ @@ -608,4 +610,23 @@ loader_info.exts = g_list_append(loader_info.exts, "pl"); } +#ifdef __SUNPRO_C +#pragma init (my_init) +#else +void __attribute__ ((constructor)) my_init(void); +#endif + +void +my_init(void) +{ + /* Mostly evil hack... puts perl.so's symbols in the global table but + * does not create a circular dependency because g_module_open will + * only open the library once. */ + /* Do we need to keep track of the returned GModule here so that we + * can g_module_close it when this plugin gets unloaded? + * At the moment I don't think this plugin can ever get unloaded but + * in case that becomes possible this wants to get noted. */ + g_module_open("perl.so", 0); +} + PURPLE_INIT_PLUGIN(perl, init_plugin, info)
--- a/libpurple/prefs.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/prefs.c Sat Apr 28 03:53:00 2007 +0000 @@ -1102,13 +1102,14 @@ static void purple_prefs_rename_node(struct purple_pref *oldpref, struct purple_pref *newpref) { - struct purple_pref *child; + struct purple_pref *child, *next; char *oldname, *newname; /* if we're a parent, rename the kids first */ - for(child = oldpref->first_child; child != NULL; child = child->sibling) + for(child = oldpref->first_child; child != NULL; child = next) { struct purple_pref *newchild; + next = child->sibling; for(newchild = newpref->first_child; newchild != NULL; newchild = newchild->sibling) { if(!strcmp(child->name, newchild->name)) @@ -1120,7 +1121,7 @@ if(newchild == NULL) { /* no rename happened, we weren't able to find the new pref */ char *tmpname = pref_full_name(child); - purple_debug_error("prefs", "Unable to find rename pref for %s", tmpname); + purple_debug_error("prefs", "Unable to find rename pref for %s\n", tmpname); g_free(tmpname); } } @@ -1327,6 +1328,8 @@ void purple_prefs_update_old() { + purple_prefs_rename("/core", "/purple"); + /* Remove some no-longer-used prefs */ purple_prefs_remove("/purple/away/auto_response/enabled"); purple_prefs_remove("/purple/away/auto_response/idle_only"); @@ -1360,7 +1363,6 @@ purple_prefs_set_int("/purple/sound/while_status", 3); } purple_prefs_remove("/purple/sound/while_away"); - purple_prefs_rename("/core", "/purple"); } void *
--- a/libpurple/protocols/jabber/auth.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/jabber/auth.c Sat Apr 28 03:53:00 2007 +0000 @@ -294,7 +294,7 @@ purple_request_yes_no(js->gc, _("Plaintext Authentication"), _("Plaintext Authentication"), _("This server requires plaintext authentication over an unencrypted connection. Allow this and continue authentication?"), - 2, js->gc->account, + 2, js->gc->account, NULL, NULL, NULL, allow_cyrus_plaintext_auth, disallow_plaintext_auth); return;
--- a/libpurple/protocols/jabber/buddy.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/jabber/buddy.c Sat Apr 28 03:53:00 2007 +0000 @@ -383,7 +383,6 @@ JabberIq *iq; JabberStream *js = gc->proto_data; xmlnode *vc_node; - char *avatar_file = NULL; struct tag_attr *tag_attr; g_free(js->avatar_hash); @@ -393,7 +392,6 @@ * Send only if there's actually any *information* to send */ vc_node = info ? xmlnode_from_str(info, -1) : NULL; - avatar_file = purple_buddy_icons_get_full_path(purple_account_get_buddy_icon(gc->account)); if(!vc_node) { vc_node = xmlnode_new("vCard"); @@ -403,27 +401,29 @@ if (vc_node->name && !g_ascii_strncasecmp(vc_node->name, "vCard", 5)) { - GError *error = NULL; - gchar *avatar_data_tmp; - guchar *avatar_data; - gsize avatar_len; + PurpleStoredImage *img; - if(avatar_file && g_file_get_contents(avatar_file, &avatar_data_tmp, &avatar_len, &error)) { + if ((img = purple_buddy_icons_find_account_icon(gc->account))) { + gconstpointer avatar_data; + gsize avatar_len; xmlnode *photo, *binval; gchar *enc; int i; unsigned char hashval[20]; char *p, hash[41]; - avatar_data = (guchar *) avatar_data_tmp; + avatar_data = purple_imgstore_get_data(img); + avatar_len = purple_imgstore_get_size(img); photo = xmlnode_new_child(vc_node, "PHOTO"); binval = xmlnode_new_child(photo, "BINVAL"); enc = purple_base64_encode(avatar_data, avatar_len); - purple_cipher_digest_region("sha1", (guchar *)avatar_data, + purple_cipher_digest_region("sha1", avatar_data, avatar_len, sizeof(hashval), hashval, NULL); + purple_imgstore_unref(img); + p = hash; for(i=0; i<20; i++, p+=2) snprintf(p, 3, "%02x", hashval[i]); @@ -431,11 +431,7 @@ xmlnode_insert_data(binval, enc, -1); g_free(enc); - g_free(avatar_data); - } else if (error != NULL) { - g_error_free(error); } - g_free(avatar_file); iq = jabber_iq_new(js, JABBER_IQ_SET); xmlnode_insert_child(iq->node, vc_node); @@ -445,7 +441,7 @@ } } -void jabber_set_buddy_icon(PurpleConnection *gc, const char *iconfile) +void jabber_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img) { PurplePresence *gpresence; PurpleStatus *status; @@ -715,7 +711,7 @@ purple_notify_user_info_destroy(user_info); while(jbi->vcard_imgids) { - purple_imgstore_unref(GPOINTER_TO_INT(jbi->vcard_imgids->data)); + purple_imgstore_unref_by_id(GPOINTER_TO_INT(jbi->vcard_imgids->data)); jbi->vcard_imgids = g_slist_delete_link(jbi->vcard_imgids, jbi->vcard_imgids); } @@ -959,25 +955,23 @@ gboolean photo = (strcmp(child->name, "PHOTO") == 0); data = purple_base64_decode(bintext, &size); - - jbi->vcard_imgids = g_slist_prepend(jbi->vcard_imgids, GINT_TO_POINTER(purple_imgstore_add(data, size, "logo.png"))); - g_string_append_printf(info_text, - "<b>%s:</b> <img id='%d'><br/>", - photo ? _("Photo") : _("Logo"), - GPOINTER_TO_INT(jbi->vcard_imgids->data)); - - purple_buddy_icons_set_for_user(js->gc->account, bare_jid, - data, size); + if (data) { + jbi->vcard_imgids = g_slist_prepend(jbi->vcard_imgids, GINT_TO_POINTER(purple_imgstore_add_with_id(g_memdup(data, size), size, "logo.png"))); + g_string_append_printf(info_text, + "<b>%s:</b> <img id='%d'><br/>", + photo ? _("Photo") : _("Logo"), + GPOINTER_TO_INT(jbi->vcard_imgids->data)); + + purple_cipher_digest_region("sha1", (guchar *)data, size, + sizeof(hashval), hashval, NULL); + p = hash; + for(i=0; i<20; i++, p+=2) + snprintf(p, 3, "%02x", hashval[i]); - purple_cipher_digest_region("sha1", (guchar *)data, size, - sizeof(hashval), hashval, NULL); - p = hash; - for(i=0; i<20; i++, p+=2) - snprintf(p, 3, "%02x", hashval[i]); - purple_blist_node_set_string((PurpleBlistNode*)b, "avatar_hash", hash); - - g_free(data); - g_free(bintext); + purple_buddy_icons_set_for_user(js->gc->account, bare_jid, + data, size, hash); + g_free(bintext); + } } } g_free(text);
--- a/libpurple/protocols/jabber/buddy.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/jabber/buddy.h Sat Apr 28 03:53:00 2007 +0000 @@ -91,7 +91,7 @@ void jabber_set_info(PurpleConnection *gc, const char *info); void jabber_setup_set_info(PurplePluginAction *action); -void jabber_set_buddy_icon(PurpleConnection *gc, const char *iconfile); +void jabber_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img); const char *jabber_buddy_state_get_name(JabberBuddyState state); const char *jabber_buddy_state_get_status_id(JabberBuddyState state);
--- a/libpurple/protocols/jabber/presence.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/jabber/presence.c Sat Apr 28 03:53:00 2007 +0000 @@ -201,7 +201,6 @@ static void jabber_vcard_parse_avatar(JabberStream *js, xmlnode *packet, gpointer blah) { JabberBuddy *jb = NULL; - PurpleBuddy *b = NULL; xmlnode *vcard, *photo, *binval; char *text; guchar *data; @@ -221,22 +220,19 @@ (( (binval = xmlnode_get_child(photo, "BINVAL")) && (text = xmlnode_get_data(binval))) || (text = xmlnode_get_data(photo)))) { + unsigned char hashval[20]; + char hash[41], *p; + int i; + data = purple_base64_decode(text, &size); - purple_buddy_icons_set_for_user(js->gc->account, from, data, size); - if((b = purple_find_buddy(js->gc->account, from))) { - unsigned char hashval[20]; - char hash[41], *p; - int i; + purple_cipher_digest_region("sha1", data, size, + sizeof(hashval), hashval, NULL); + p = hash; + for(i=0; i<20; i++, p+=2) + snprintf(p, 3, "%02x", hashval[i]); - purple_cipher_digest_region("sha1", data, size, - sizeof(hashval), hashval, NULL); - p = hash; - for(i=0; i<20; i++, p+=2) - snprintf(p, 3, "%02x", hashval[i]); - purple_blist_node_set_string((PurpleBlistNode*)b, "avatar_hash", hash); - } - g_free(data); + purple_buddy_icons_set_for_user(js->gc->account, from, data, size, hash); g_free(text); } } @@ -521,7 +517,7 @@ } if(avatar_hash) { - const char *avatar_hash2 = purple_blist_node_get_string((PurpleBlistNode*)b, "avatar_hash"); + const char *avatar_hash2 = purple_buddy_icons_get_checksum_for_user(b); if(!avatar_hash2 || strcmp(avatar_hash, avatar_hash2)) { JabberIq *iq; xmlnode *vcard;
--- a/libpurple/protocols/msn/msn.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/msn/msn.c Sat Apr 28 03:53:00 2007 +0000 @@ -1310,7 +1310,7 @@ } static void -msn_set_buddy_icon(PurpleConnection *gc, const char *filename) +msn_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img) { MsnSession *session; MsnUser *user; @@ -1318,7 +1318,7 @@ session = gc->proto_data; user = session->user; - msn_user_set_buddy_icon(user, filename); + msn_user_set_buddy_icon(user, img); msn_change_status(session); } @@ -1889,7 +1889,7 @@ { char buf[1024]; purple_debug_info("msn", "%s is %d bytes\n", photo_url_text, len); - id = purple_imgstore_add(url_text, len, NULL); + id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL); g_snprintf(buf, sizeof(buf), "<img id=\"%d\"><br>", id); purple_notify_user_info_prepend_pair(user_info, NULL, buf); } @@ -1908,7 +1908,7 @@ g_free(photo_url_text); g_free(info2_data); if (id != -1) - purple_imgstore_unref(id); + purple_imgstore_unref_by_id(id); #endif }
--- a/libpurple/protocols/msn/object.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/msn/object.c Sat Apr 28 03:53:00 2007 +0000 @@ -111,11 +111,12 @@ g_free(obj->creator); g_free(obj->location); - g_free(obj->real_location); g_free(obj->friendly); g_free(obj->sha1d); g_free(obj->sha1c); + purple_imgstore_unref(obj->img); + if (obj->local) local_objs = g_list_remove(local_objs, obj); @@ -317,21 +318,19 @@ } void -msn_object_set_real_location(MsnObject *obj, const char *real_location) +msn_object_set_image(MsnObject *obj, PurpleStoredImage *img) { g_return_if_fail(obj != NULL); + g_return_if_fail(img != NULL); /* obj->local = TRUE; */ - if (obj->real_location != NULL) - g_free(obj->real_location); - - obj->real_location = - (real_location == NULL ? NULL : g_strdup(real_location)); + purple_imgstore_unref(obj->img); + obj->img = purple_imgstore_ref(img); } -const char * -msn_object_get_real_location(const MsnObject *obj) +PurpleStoredImage * +msn_object_get_image(const MsnObject *obj) { MsnObject *local_obj; @@ -340,7 +339,7 @@ local_obj = msn_object_find_local(msn_object_get_sha1(obj)); if (local_obj != NULL) - return local_obj->real_location; + return local_obj->img; return NULL; }
--- a/libpurple/protocols/msn/object.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/msn/object.h Sat Apr 28 03:53:00 2007 +0000 @@ -24,6 +24,8 @@ #ifndef _MSN_OBJECT_H_ #define _MSN_OBJECT_H_ +#include "imgstore.h" + #include "internal.h" typedef enum @@ -44,7 +46,7 @@ char *creator; int size; MsnObjectType type; - char *real_location; + PurpleStoredImage *img; char *location; char *friendly; char *sha1d; @@ -134,6 +136,14 @@ void msn_object_set_sha1c(MsnObject *obj, const char *sha1c); /** + * Associates an image with a MsnObject. + * + * @param obj The object. + * @param img The image to associate. + */ +void msn_object_set_image(MsnObject *obj, PurpleStoredImage *img); + +/** * Returns a MsnObject's creator value. * * @param obj The object. @@ -205,9 +215,15 @@ */ const char *msn_object_get_sha1(const MsnObject *obj); +/** + * Returns the image associated with the MsnObject. + * + * @param obj The object. + * + * @return The associated image. + */ +PurpleStoredImage *msn_object_get_image(const MsnObject *obj); + void msn_object_set_local(MsnObject *obj); -const char *msn_object_get_real_location(const MsnObject *obj); -void msn_object_set_real_location(MsnObject *obj, - const char *real_location); #endif /* _MSN_OBJECT_H_ */
--- a/libpurple/protocols/msn/session.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/msn/session.c Sat Apr 28 03:53:00 2007 +0000 @@ -384,7 +384,7 @@ { PurpleAccount *account; PurpleConnection *gc; - char *icon; + PurpleStoredImage *img; if (session->logged_in) return; @@ -392,9 +392,9 @@ account = session->account; gc = purple_account_get_connection(account); - icon = purple_buddy_icons_get_full_path(purple_account_get_buddy_icon(session->account)); - msn_user_set_buddy_icon(session->user, icon); - g_free(icon); + img = purple_buddy_icons_find_account_icon(session->account); + msn_user_set_buddy_icon(session->user, img); + purple_imgstore_unref(img); session->logged_in = TRUE;
--- a/libpurple/protocols/msn/slp.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/msn/slp.c Sat Apr 28 03:53:00 2007 +0000 @@ -248,14 +248,14 @@ if (!strcmp(euf_guid, "A4268EEC-FEC5-49E5-95C3-F126696BDBF6")) { /* Emoticon or UserDisplay */ + char *content; + gsize len; MsnSlpSession *slpsession; MsnSlpLink *slplink; MsnSlpMessage *slpmsg; MsnObject *obj; char *msnobj_data; - const char *file_name; - char *content; - gsize len; + PurpleStoredImage *img; int type; /* Send Ok */ @@ -281,9 +281,8 @@ g_return_if_reached(); } - file_name = msn_object_get_real_location(obj); - - if (file_name == NULL) + img = msn_object_get_image(obj); + if (img == NULL) { purple_debug_error("msn", "Wrong object.\n"); msn_object_destroy(obj); @@ -314,7 +313,7 @@ #ifdef MSN_DEBUG_SLP slpmsg->info = "SLP DATA"; #endif - msn_slpmsg_open_file(slpmsg, file_name); + msn_slpmsg_set_image(slpmsg, img); msn_slplink_queue_slpmsg(slplink, slpmsg); } else if (!strcmp(euf_guid, "5D3E02AB-6190-11D3-BBBB-00C04F795683")) @@ -870,7 +869,7 @@ if (buddy == NULL) return FALSE; - old = purple_blist_node_get_string((PurpleBlistNode *)buddy, "icon_checksum"); + old = purple_buddy_icons_get_checksum_for_user(buddy); new = msn_object_get_sha1(obj); if (new == NULL) @@ -878,7 +877,7 @@ /* If the old and new checksums are the same, and the file actually exists, * then return TRUE */ - if (old != NULL && !strcmp(old, new) && (purple_buddy_icons_find(account, purple_buddy_get_name(buddy)) != NULL)) + if (old != NULL && !strcmp(old, new)) return TRUE; return FALSE; @@ -956,22 +955,7 @@ if (obj == NULL) { - /* It seems the user has not set a msnobject */ - GSList *sl, *list; - - list = purple_find_buddies(account, user->passport); - - for (sl = list; sl != NULL; sl = sl->next) - { - PurpleBuddy *buddy = (PurpleBuddy *)sl->data; - if (buddy->icon) - purple_blist_node_remove_setting((PurpleBlistNode*)buddy, "icon_checksum"); - } - g_slist_free(list); - - /* TODO: I think we need better buddy icon core functions. */ - purple_buddy_icons_set_for_user(account, user->passport, NULL, 0); - + purple_buddy_icons_set_for_user(account, user->passport, NULL, 0, NULL); return; } @@ -1001,7 +985,6 @@ MsnUserList *userlist; const char *info; PurpleAccount *account; - GSList *sl, *list; g_return_if_fail(slpcall != NULL); @@ -1013,18 +996,8 @@ userlist = slpcall->slplink->session->userlist; account = slpcall->slplink->session->account; - /* TODO: I think we need better buddy icon core functions. */ purple_buddy_icons_set_for_user(account, slpcall->slplink->remote_user, - (void *)data, size); - - list = purple_find_buddies(account, slpcall->slplink->remote_user); - - for (sl = list; sl != NULL; sl = sl->next) - { - PurpleBuddy *buddy = (PurpleBuddy *)sl->data; - purple_blist_node_set_string((PurpleBlistNode*)buddy, "icon_checksum", info); - } - g_slist_free(list); + g_memdup(data, size), size, info); #if 0 /* Free one window slot */ @@ -1101,9 +1074,8 @@ else { MsnObject *my_obj = NULL; - gchar *data = NULL; - gsize len = 0; - GSList *sl, *list; + gconstpointer data = NULL; + size_t len = 0; #ifdef MSN_DEBUG_UD purple_debug_info("msn", "Requesting our own user display\n"); @@ -1113,24 +1085,12 @@ if (my_obj != NULL) { - const char *filename = msn_object_get_real_location(my_obj); - - if (filename != NULL) - g_file_get_contents(filename, &data, &len, NULL); + PurpleStoredImage *img = msn_object_get_image(my_obj); + data = purple_imgstore_get_data(img); + len = purple_imgstore_get_size(img); } - /* TODO: I think we need better buddy icon core functions. */ - purple_buddy_icons_set_for_user(account, user->passport, (void *)data, len); - g_free(data); - - list = purple_find_buddies(account, user->passport); - - for (sl = list; sl != NULL; sl = sl->next) - { - PurpleBuddy *buddy = (PurpleBuddy *)sl->data; - purple_blist_node_set_string((PurpleBlistNode*)buddy, "icon_checksum", info); - } - g_slist_free(list); + purple_buddy_icons_set_for_user(account, user->passport, g_memdup(data, len), len, info); /* Free one window slot */ session->userlist->buddy_icon_window++;
--- a/libpurple/protocols/msn/slpmsg.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/msn/slpmsg.c Sat Apr 28 03:53:00 2007 +0000 @@ -65,7 +65,11 @@ if (slpmsg->fp != NULL) fclose(slpmsg->fp); - if (slpmsg->buffer != NULL) + purple_imgstore_unref(slpmsg->img); + + /* We don't want to free the data of the PurpleStoredImage, + * but to avoid code duplication, it's sharing buffer. */ + if (slpmsg->img == NULL) g_free(slpmsg->buffer); #ifdef MSN_DEBUG_SLP @@ -101,6 +105,11 @@ msn_slpmsg_set_body(MsnSlpMessage *slpmsg, const char *body, long long size) { + /* We can only have one data source at a time. */ + g_return_if_fail(slpmsg->buffer == NULL); + g_return_if_fail(slpmsg->img == NULL); + g_return_if_fail(slpmsg->fp == NULL); + if (body != NULL) slpmsg->buffer = g_memdup(body, size); else @@ -110,10 +119,28 @@ } void +msn_slpmsg_set_image(MsnSlpMessage *slpmsg, PurpleStoredImage *img) +{ + /* We can only have one data source at a time. */ + g_return_if_fail(slpmsg->buffer == NULL); + g_return_if_fail(slpmsg->img == NULL); + g_return_if_fail(slpmsg->fp == NULL); + + slpmsg->img = purple_imgstore_ref(img); + slpmsg->buffer = (guchar *)purple_imgstore_get_data(img); + slpmsg->size = purple_imgstore_get_size(img); +} + +void msn_slpmsg_open_file(MsnSlpMessage *slpmsg, const char *file_name) { struct stat st; + /* We can only have one data source at a time. */ + g_return_if_fail(slpmsg->buffer == NULL); + g_return_if_fail(slpmsg->img == NULL); + g_return_if_fail(slpmsg->fp == NULL); + slpmsg->fp = g_fopen(file_name, "rb"); if (g_stat(file_name, &st) == 0)
--- a/libpurple/protocols/msn/slpmsg.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/msn/slpmsg.h Sat Apr 28 03:53:00 2007 +0000 @@ -26,6 +26,8 @@ typedef struct _MsnSlpMessage MsnSlpMessage; +#include "imgstore.h" + #include "slpsession.h" #include "slpcall.h" #include "slplink.h" @@ -57,6 +59,7 @@ long flags; FILE *fp; + PurpleStoredImage *img; guchar *buffer; long long offset; long long size; @@ -90,6 +93,7 @@ void msn_slpmsg_set_body(MsnSlpMessage *slpmsg, const char *body, long long size); +void msn_slpmsg_set_image(MsnSlpMessage *slpmsg, PurpleStoredImage *img); void msn_slpmsg_open_file(MsnSlpMessage *slpmsg, const char *file_name); MsnSlpMessage * msn_slpmsg_sip_new(MsnSlpCall *slpcall, int cseq,
--- a/libpurple/protocols/msn/user.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/msn/user.c Sat Apr 28 03:53:00 2007 +0000 @@ -151,23 +151,20 @@ } void -msn_user_set_buddy_icon(MsnUser *user, const char *filename) +msn_user_set_buddy_icon(MsnUser *user, PurpleStoredImage *img) { - struct stat st; - FILE *fp; MsnObject *msnobj = msn_user_get_object(user); g_return_if_fail(user != NULL); - if (filename == NULL || g_stat(filename, &st) == -1) - { + if (img == NULL) msn_user_set_object(user, NULL); - } - else if ((fp = g_fopen(filename, "rb")) != NULL) + else { PurpleCipherContext *ctx; char *buf; - gsize len; + gconstpointer data = purple_imgstore_get_data(img); + size_t size = purple_imgstore_get_size(img); char *base64; unsigned char digest[20]; @@ -182,26 +179,20 @@ msn_user_set_object(user, msnobj); } - msn_object_set_real_location(msnobj, filename); - - buf = g_malloc(st.st_size); - len = fread(buf, 1, st.st_size, fp); - - fclose(fp); + msn_object_set_image(msnobj, img); /* Compute the SHA1D field. */ memset(digest, 0, sizeof(digest)); ctx = purple_cipher_context_new_by_name("sha1", NULL); - purple_cipher_context_append(ctx, (const guchar *)buf, st.st_size); + purple_cipher_context_append(ctx, data, size); purple_cipher_context_digest(ctx, sizeof(digest), digest, NULL); - g_free(buf); base64 = purple_base64_encode(digest, sizeof(digest)); msn_object_set_sha1d(msnobj, base64); g_free(base64); - msn_object_set_size(msnobj, st.st_size); + msn_object_set_size(msnobj, size); /* Compute the SHA1C field. */ buf = g_strdup_printf( @@ -216,7 +207,7 @@ memset(digest, 0, sizeof(digest)); purple_cipher_context_reset(ctx, NULL); - purple_cipher_context_append(ctx, (const guchar *)buf, strlen(buf)); + purple_cipher_context_append(ctx, data, strlen((char *)data)); purple_cipher_context_digest(ctx, sizeof(digest), digest, NULL); purple_cipher_context_destroy(ctx); g_free(buf); @@ -225,11 +216,6 @@ msn_object_set_sha1c(msnobj, base64); g_free(base64); } - else - { - purple_debug_error("msn", "Unable to open buddy icon %s!\n", filename); - msn_user_set_object(user, NULL); - } } void
--- a/libpurple/protocols/msn/user.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/msn/user.h Sat Apr 28 03:53:00 2007 +0000 @@ -138,9 +138,9 @@ * Sets the buddy icon for a local user. * * @param user The user. - * @param filename The path to the buddy icon. + * @param img The buddy icon image */ -void msn_user_set_buddy_icon(MsnUser *user, const char *filename); +void msn_user_set_buddy_icon(MsnUser *user, PurpleStoredImage *img); /** * Sets the group ID list for a user.
--- a/libpurple/protocols/oscar/odc.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/oscar/odc.c Sat Apr 28 03:53:00 2007 +0000 @@ -353,7 +353,7 @@ if ((embedded_data != NULL) && (embedded_data->size == size)) { - imgid = purple_imgstore_add(embedded_data->data, size, src); + imgid = purple_imgstore_add_with_id(g_memdup(embedded_data->data, size), size, src); /* Record the image number */ images = g_slist_append(images, GINT_TO_POINTER(imgid)); @@ -406,7 +406,7 @@ { GSList *l; for (l = images; l != NULL; l = l->next) - purple_imgstore_unref(GPOINTER_TO_INT(l->data)); + purple_imgstore_unref_by_id(GPOINTER_TO_INT(l->data)); g_slist_free(images); }
--- a/libpurple/protocols/oscar/oscar.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/oscar/oscar.c Sat Apr 28 03:53:00 2007 +0000 @@ -1864,34 +1864,14 @@ bi->ipaddr = info->icqinfo.ipaddr; if (info->iconcsumlen) { - const char *filename, *saved_b16 = NULL; - char *b16 = NULL, *filepath = NULL; + const char *saved_b16 = NULL; + char *b16 = NULL; PurpleBuddy *b = NULL; b16 = purple_base16_encode(info->iconcsum, info->iconcsumlen); b = purple_find_buddy(account, info->sn); - /* - * If for some reason the checksum is valid, but cached file is not.. - * we want to know. - */ if (b != NULL) - filename = purple_blist_node_get_string((PurpleBlistNode*)b, "buddy_icon"); - else - filename = NULL; - if (filename != NULL) { - if (g_file_test(filename, G_FILE_TEST_EXISTS)) - saved_b16 = purple_blist_node_get_string((PurpleBlistNode*)b, - "icon_checksum"); - else { - filepath = g_build_filename(purple_buddy_icons_get_cache_dir(), - filename, NULL); - if (g_file_test(filepath, G_FILE_TEST_EXISTS)) - saved_b16 = purple_blist_node_get_string((PurpleBlistNode*)b, - "icon_checksum"); - g_free(filepath); - } - } else - saved_b16 = NULL; + saved_b16 = purple_buddy_icons_get_checksum_for_user(b); if (!b16 || !saved_b16 || strcmp(b16, saved_b16)) { GSList *cur = od->requesticon; @@ -1938,7 +1918,7 @@ PurpleAccount *account = purple_connection_get_account(gc); PurpleMessageFlags flags = 0; struct buddyinfo *bi; - char *iconfile; + PurpleStoredImage *img; GString *message; gchar *tmp; aim_mpmsg_section_t *curpart; @@ -1975,33 +1955,19 @@ } } - iconfile = purple_buddy_icons_get_full_path(purple_account_get_buddy_icon(account)); - if ((iconfile != NULL) && + img = purple_buddy_icons_find_account_icon(account); + if ((img != NULL) && (args->icbmflags & AIM_IMFLAGS_BUDDYREQ) && !bi->ico_sent && bi->ico_informed) { - FILE *file; - struct stat st; - - if (!g_stat(iconfile, &st)) { - guchar *buf = g_malloc(st.st_size); - file = g_fopen(iconfile, "rb"); - if (file) { - /* XXX - Use g_file_get_contents() */ - /* g_file_get_contents(iconfile, &data, &len, NULL); */ - int len = fread(buf, 1, st.st_size, file); - purple_debug_info("oscar", - "Sending buddy icon to %s (%d bytes, " - "%lu reported)\n", - userinfo->sn, len, st.st_size); - aim_im_sendch2_icon(od, userinfo->sn, buf, st.st_size, - st.st_mtime, aimutil_iconsum(buf, st.st_size)); - fclose(file); - } else - purple_debug_error("oscar", "Can't open buddy icon file!\n"); - g_free(buf); - } else - purple_debug_error("oscar", "Can't stat buddy icon file!\n"); - } - g_free(iconfile); + gconstpointer data = purple_imgstore_get_data(img); + size_t len = purple_imgstore_get_size(img); + purple_debug_info("oscar", + "Sending buddy icon to %s (%d bytes)\n", + userinfo->sn, len); + /* TODO: XXX: FIXME: Does this actually need the mtime of the file? */ + aim_im_sendch2_icon(od, userinfo->sn, data, len, + time(NULL), aimutil_iconsum(data, len)); + } + purple_imgstore_unref(img); message = g_string_new(""); curpart = args->mpmsg.parts; @@ -2204,8 +2170,9 @@ else if (args->type & OSCAR_CAPABILITY_BUDDYICON) { purple_buddy_icons_set_for_user(account, userinfo->sn, - args->info.icon.icon, - args->info.icon.length); + g_memdup(args->info.icon.icon, args->info.icon.length), + args->info.icon.length, + NULL); } else if (args->type & OSCAR_CAPABILITY_ICQSERVERRELAY) @@ -3305,16 +3272,10 @@ * no icon is set. Ignore these. */ if ((iconlen > 0) && (iconlen != 90)) { - char *b16; - PurpleBuddy *b; + char *b16 = purple_base16_encode(iconcsum, iconcsumlen); purple_buddy_icons_set_for_user(purple_connection_get_account(gc), - sn, icon, iconlen); - b16 = purple_base16_encode(iconcsum, iconcsumlen); - b = purple_find_buddy(gc->account, sn); - if ((b16 != NULL) && (b != NULL)) { - purple_blist_node_set_string((PurpleBlistNode*)b, "icon_checksum", b16); - g_free(b16); - } + sn, g_memdup(icon, iconlen), iconlen, b16); + g_free(b16); } cur = od->requesticon; @@ -3352,29 +3313,17 @@ } if (od->set_icon) { - struct stat st; - char *iconfile = purple_buddy_icons_get_full_path(purple_account_get_buddy_icon(purple_connection_get_account(gc))); - if (iconfile == NULL) { + PurpleAccount *account = purple_connection_get_account(gc); + PurpleStoredImage *img = purple_buddy_icons_find_account_icon(account); + if (img == NULL) { aim_ssi_delicon(od); - } else if (!g_stat(iconfile, &st)) { - guchar *buf = g_malloc(st.st_size); - FILE *file = g_fopen(iconfile, "rb"); - if (file) { - /* XXX - Use g_file_get_contents()? */ - fread(buf, 1, st.st_size, file); - fclose(file); - purple_debug_info("oscar", - "Uploading icon to icon server\n"); - aim_bart_upload(od, buf, st.st_size); - } else - purple_debug_error("oscar", - "Can't open buddy icon file!\n"); - g_free(buf); } else { - purple_debug_error("oscar", - "Can't stat buddy icon file!\n"); + purple_debug_info("oscar", + "Uploading icon to icon server\n"); + aim_bart_upload(od, purple_imgstore_get_data(img), + purple_imgstore_get_size(img)); + purple_imgstore_unref(img); } - g_free(iconfile); od->set_icon = FALSE; } @@ -4172,11 +4121,11 @@ id = g_datalist_get_data(&attribs, "id"); /* ... if it refers to a valid purple image ... */ - if (id && (image = purple_imgstore_get(atoi(id)))) { + if (id && (image = purple_imgstore_find_by_id(atoi(id)))) { /* ... append the message from start to the tag ... */ unsigned long size = purple_imgstore_get_size(image); const char *filename = purple_imgstore_get_filename(image); - gpointer imgdata = purple_imgstore_get_data(image); + gconstpointer imgdata = purple_imgstore_get_data(image); oscar_id++; @@ -4235,13 +4184,11 @@ PurpleAccount *account; PeerConnection *conn; int ret; - char *iconfile; char *tmp1, *tmp2; od = (OscarData *)gc->proto_data; account = purple_connection_get_account(gc); ret = 0; - iconfile = purple_buddy_icons_get_full_path(purple_account_get_buddy_icon(account)); if (imflags & PURPLE_MESSAGE_AUTO_RESP) tmp1 = purple_str_sub_away_formatters(message, name); @@ -4256,9 +4203,9 @@ } else { struct buddyinfo *bi; struct aim_sendimext_args args; - struct stat st; gsize len; PurpleConversation *conv; + PurpleStoredImage *img; conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, account); @@ -4307,44 +4254,38 @@ bi->ico_need = FALSE; } - if (iconfile && !g_stat(iconfile, &st)) { - FILE *file = g_fopen(iconfile, "rb"); - if (file) { - guchar *buf = g_malloc(st.st_size); - /* TODO: Use g_file_get_contents()? */ - fread(buf, 1, st.st_size, file); - fclose(file); - - args.iconlen = st.st_size; - args.iconsum = aimutil_iconsum(buf, st.st_size); - args.iconstamp = st.st_mtime; - - if ((args.iconlen != bi->ico_me_len) || (args.iconsum != bi->ico_me_csum) || (args.iconstamp != bi->ico_me_time)) { - bi->ico_informed = FALSE; - bi->ico_sent = FALSE; - } - - /* - * TODO: - * For some reason sending our icon to people only works - * when we're the ones who initiated the conversation. If - * the other person sends the first IM then they never get - * the icon. We should fix that. - */ - if (!bi->ico_informed) { - purple_debug_info("oscar", - "Claiming to have a buddy icon\n"); - args.flags |= AIM_IMFLAGS_HASICON; - bi->ico_me_len = args.iconlen; - bi->ico_me_csum = args.iconsum; - bi->ico_me_time = args.iconstamp; - bi->ico_informed = TRUE; - } - - g_free(buf); + img = purple_buddy_icons_find_account_icon(account); + if (img) { + gconstpointer data = purple_imgstore_get_data(img); + args.iconlen = purple_imgstore_get_size(img); + args.iconsum = aimutil_iconsum(data, args.iconlen); + /* TODO: XXX: FIXME: Deal with the timestamp issue. */ + args.iconstamp = time(NULL); + + if ((args.iconlen != bi->ico_me_len) || (args.iconsum != bi->ico_me_csum) || (args.iconstamp != bi->ico_me_time)) { + bi->ico_informed = FALSE; + bi->ico_sent = FALSE; } + + /* + * TODO: + * For some reason sending our icon to people only works + * when we're the ones who initiated the conversation. If + * the other person sends the first IM then they never get + * the icon. We should fix that. + */ + if (!bi->ico_informed) { + purple_debug_info("oscar", + "Claiming to have a buddy icon\n"); + args.flags |= AIM_IMFLAGS_HASICON; + bi->ico_me_len = args.iconlen; + bi->ico_me_csum = args.iconsum; + bi->ico_me_time = args.iconstamp; + bi->ico_informed = TRUE; + } + + purple_imgstore_unref(img); } - g_free(iconfile); args.destsn = name; @@ -4819,8 +4760,7 @@ PurpleBuddy *b; struct aim_ssi_item *curitem; guint32 tmp; - const char *icon_path; - char *cached_icon_path; + PurpleStoredImage *img; va_list ap; guint16 fmtver, numitems; guint32 timestamp; @@ -5053,10 +4993,9 @@ * the event that the local user set a new icon while this * account was offline. */ - icon_path = purple_account_get_buddy_icon(account); - cached_icon_path = purple_buddy_icons_get_full_path(icon_path); - oscar_set_icon(gc, cached_icon_path); - g_free(cached_icon_path); + img = purple_buddy_icons_find_account_icon(account); + oscar_set_icon(gc, img); + purple_imgstore_unref(img); return 1; } @@ -5661,37 +5600,27 @@ od->set_icon = TRUE; aim_srv_requestnew(od, SNAC_FAMILY_BART); } else { - struct stat st; - char *iconfile = purple_buddy_icons_get_full_path(purple_account_get_buddy_icon(purple_connection_get_account(gc))); - if (iconfile == NULL) { + PurpleAccount *account = purple_connection_get_account(gc); + PurpleStoredImage *img = purple_buddy_icons_find_account_icon(account); + if (img == NULL) { aim_ssi_delicon(od); - } else if (!g_stat(iconfile, &st)) { - guchar *buf = g_malloc(st.st_size); - FILE *file = g_fopen(iconfile, "rb"); - if (file) { - /* XXX - Use g_file_get_contents()? */ - fread(buf, 1, st.st_size, file); - fclose(file); - purple_debug_info("oscar", - "Uploading icon to icon server\n"); - aim_bart_upload(od, buf, st.st_size); - } else - purple_debug_error("oscar", - "Can't open buddy icon file!\n"); - g_free(buf); } else { - purple_debug_error("oscar", - "Can't stat buddy icon file!\n"); + + purple_debug_info("oscar", + "Uploading icon to icon server\n"); + aim_bart_upload(od, purple_imgstore_get_data(img), + purple_imgstore_get_size(img)); + purple_imgstore_unref(img); } - g_free(iconfile); } } else if (flags == 0x81) { - char *iconfile = purple_buddy_icons_get_full_path(purple_account_get_buddy_icon(purple_connection_get_account(gc))); - if (iconfile == NULL) + PurpleAccount *account = purple_connection_get_account(gc); + PurpleStoredImage *img = purple_buddy_icons_find_account_icon(account); + if (img == NULL) aim_ssi_delicon(od); else { aim_ssi_seticon(od, md5, length); - g_free(iconfile); + purple_imgstore_unref(img); } } } break; @@ -6281,41 +6210,28 @@ purple_notify_uri(gc, "http://mymobile.aol.com/dbreg/register?action=imf&clientID=1"); } -void oscar_set_icon(PurpleConnection *gc, const char *iconfile) +void oscar_set_icon(PurpleConnection *gc, PurpleStoredImage *img) { OscarData *od = gc->proto_data; - FILE *file; - struct stat st; - - if (iconfile == NULL) { + + if (img == NULL) { aim_ssi_delicon(od); - } else if (!g_stat(iconfile, &st)) { - guchar *buf = g_malloc(st.st_size); - file = g_fopen(iconfile, "rb"); - if (file) - { - PurpleCipher *cipher; - PurpleCipherContext *context; - guchar md5[16]; - int len; - - /* XXX - Use g_file_get_contents()? */ - len = fread(buf, 1, st.st_size, file); - fclose(file); - - cipher = purple_ciphers_find_cipher("md5"); - context = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_append(context, buf, len); - purple_cipher_context_digest(context, 16, md5, NULL); - purple_cipher_context_destroy(context); - - aim_ssi_seticon(od, md5, 16); - } else - purple_debug_error("oscar", - "Can't open buddy icon file!\n"); - g_free(buf); - } else - purple_debug_error("oscar", "Can't stat buddy icon file!\n"); + } else { + PurpleCipher *cipher; + PurpleCipherContext *context; + guchar md5[16]; + gconstpointer data = purple_imgstore_get_data(img); + size_t len = purple_imgstore_get_size(img); + + + cipher = purple_ciphers_find_cipher("md5"); + context = purple_cipher_context_new(cipher, NULL); + purple_cipher_context_append(context, data, len); + purple_cipher_context_digest(context, 16, md5, NULL); + purple_cipher_context_destroy(context); + + aim_ssi_seticon(od, md5, 16); + } } /**
--- a/libpurple/protocols/oscar/oscarcommon.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/oscar/oscarcommon.h Sat Apr 28 03:53:00 2007 +0000 @@ -81,7 +81,7 @@ void oscar_rename_group(PurpleConnection *gc, const char *old_name, PurpleGroup *group, GList *moved_buddies); void oscar_convo_closed(PurpleConnection *gc, const char *who); const char *oscar_normalize(const PurpleAccount *account, const char *str); -void oscar_set_icon(PurpleConnection *gc, const char *iconfile); +void oscar_set_icon(PurpleConnection *gc, PurpleStoredImage *img); gboolean oscar_can_receive_file(PurpleConnection *gc, const char *who); void oscar_send_file(PurpleConnection *gc, const char *who, const char *file); PurpleXfer *oscar_new_xfer(PurpleConnection *gc, const char *who);
--- a/libpurple/protocols/qq/buddy_info.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/qq/buddy_info.c Sat Apr 28 03:53:00 2007 +0000 @@ -532,27 +532,21 @@ qq_send_packet_get_info(gc, qd->uid, FALSE); } -void qq_set_buddy_icon_for_user(PurpleAccount *account, const gchar *who, const gchar *iconfile) +void qq_set_buddy_icon_for_user(PurpleAccount *account, const gchar *who, const gchar *icon_num, const gchar *iconfile) { - FILE *file; - struct stat st; + gchar *data; + gsize len; - g_return_if_fail(g_stat(iconfile, &st) == 0); - file = g_fopen(iconfile, "rb"); - if (file) { - PurpleBuddyIcon *icon; - size_t data_len; - gchar *data = g_new(gchar, st.st_size + 1); - data_len = fread(data, 1, st.st_size, file); - fclose(file); - purple_buddy_icons_set_for_user(account, who, data, data_len); - icon = purple_buddy_icons_find(account, who); - purple_buddy_icon_set_path(icon, iconfile); + if (!g_file_get_contents(iconfile, &data, &len, NULL)) + g_return_if_reached(); + else + { + purple_buddy_icons_set_for_user(account, who, data, len, icon_num); } } /* TODO: custom faces for QQ members and users with level >= 16 */ -void qq_set_my_buddy_icon(PurpleConnection *gc, const gchar *iconfile) +void qq_set_my_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img) { gchar *icon; gint icon_num; @@ -601,25 +595,29 @@ /* tell server my icon changed */ _qq_send_packet_modify_face(gc, icon_num); /* display in blist */ - qq_set_buddy_icon_for_user(account, account->username, icon_path); + qq_set_buddy_icon_for_user(account, account->username, icon, icon_path); } static void _qq_update_buddy_icon(PurpleAccount *account, const gchar *name, gint face) { - gchar *icon_path; PurpleBuddyIcon *icon = purple_buddy_icons_find(account, name); gchar *icon_num_str = face_to_icon_str(face); - const gchar *old_path = purple_buddy_icon_get_path(icon); - const gchar *buddy_icon_dir = qq_buddy_icon_dir(); + const gchar *old_icon_num = purple_buddy_icon_get_checksum(icon); + + if (icon == NULL || old_icon_num == NULL || + strcmp(icon_num_str, old_icon_num)) + { + gchar *icon_path; - icon_path = g_strconcat(buddy_icon_dir, G_DIR_SEPARATOR_S, QQ_ICON_PREFIX, - icon_num_str, QQ_ICON_SUFFIX, NULL); - if (icon == NULL || old_path == NULL - || g_ascii_strcasecmp(icon_path, old_path) != 0) - qq_set_buddy_icon_for_user(account, name, icon_path); + icon_path = g_strconcat(qq_buddy_icon_dir(), G_DIR_SEPARATOR_S, + QQ_ICON_PREFIX, icon_num_str, + QQ_ICON_SUFFIX, NULL); + + qq_set_buddy_icon_for_user(account, name, icon_num_str, icon_path); + g_free(icon_path); + } g_free(icon_num_str); - g_free(icon_path); } /* after getting info or modify myself, refresh the buddy list accordingly */
--- a/libpurple/protocols/qq/buddy_info.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/qq/buddy_info.h Sat Apr 28 03:53:00 2007 +0000 @@ -86,8 +86,8 @@ void qq_refresh_buddy_and_myself(contact_info *info, PurpleConnection *gc); void qq_send_packet_get_info(PurpleConnection *gc, guint32 uid, gboolean show_window); -void qq_set_my_buddy_icon(PurpleConnection *gc, const gchar *iconfile); -void qq_set_buddy_icon_for_user(PurpleAccount *account, const gchar *who, const gchar *iconfile); +void qq_set_my_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img); +void qq_set_buddy_icon_for_user(PurpleAccount *account, const gchar *who, const gchar *icon_num, const gchar *iconfile); void qq_prepare_modify_info(PurpleConnection *gc); void qq_process_modify_info_reply(guint8 *buf, gint buf_len, PurpleConnection *gc); void qq_process_get_info_reply(guint8 *buf, gint buf_len, PurpleConnection *gc);
--- a/libpurple/protocols/sametime/sametime.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/sametime/sametime.c Sat Apr 28 03:53:00 2007 +0000 @@ -2698,8 +2698,7 @@ cid = make_cid(cid); /* add image to the purple image store */ - img = purple_imgstore_add(d_dat, d_len, cid); - g_free(d_dat); + img = purple_imgstore_add_with_id(d_dat, d_len, cid); /* map the cid to the image store identifier */ g_hash_table_insert(img_by_cid, cid, GINT_TO_POINTER(img)); @@ -2772,7 +2771,7 @@ /* dereference all the imgages */ while(images) { - purple_imgstore_unref(GPOINTER_TO_INT(images->data)); + purple_imgstore_unref_by_id(GPOINTER_TO_INT(images->data)); images = g_list_delete_link(images, images); } } @@ -3859,7 +3858,7 @@ /* find the imgstore data by the id tag */ id = g_datalist_get_data(&attr, "id"); if(id && *id) - img = purple_imgstore_get(atoi(id)); + img = purple_imgstore_find_by_id(atoi(id)); if(img) { char *cid; @@ -3885,9 +3884,8 @@ /* obtain and base64 encode the image data, and put it in the mime part */ - data = purple_imgstore_get_data(img); size = purple_imgstore_get_size(img); - data = purple_base64_encode(data, (gsize) size); + data = purple_base64_encode(purple_imgstore_get_data(img), (gsize) size); purple_mime_part_set_data(part, data); g_free(data);
--- a/libpurple/protocols/silc/buddy.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/silc/buddy.c Sat Apr 28 03:53:00 2007 +0000 @@ -987,8 +987,10 @@ const unsigned char *data; SilcUInt32 data_len; data = silc_mime_get_data(m, &data_len); - if (data) - purple_buddy_icons_set_for_user(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), (void *)data, data_len); + if (data) { + /* TODO: Check if SILC gives us something to use as the checksum instead */ + purple_buddy_icons_set_for_user(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), g_memdup(data, data_len), data_len, NULL); + } } silc_mime_free(m); } @@ -1681,48 +1683,31 @@ } #ifdef SILC_ATTRIBUTE_USER_ICON -void silcpurple_buddy_set_icon(PurpleConnection *gc, const char *iconfile) +void silcpurple_buddy_set_icon(PurpleConnection *gc, PurpleStoredImage *img) { SilcPurple sg = gc->proto_data; SilcClient client = sg->client; SilcClientConnection conn = sg->conn; SilcMime mime; - PurpleBuddyIcon ic; char type[32]; unsigned char *icon; const char *t; - struct stat st; - FILE *fp; SilcAttributeObjMime obj; /* Remove */ - if (!iconfile) { + if (!img) { silc_client_attribute_del(client, conn, SILC_ATTRIBUTE_USER_ICON, NULL); return; } /* Add */ - if (g_stat(iconfile, &st) < 0) - return; - fp = g_fopen(iconfile, "rb"); - if (!fp) - return; - ic.data = g_malloc(st.st_size); - if (!ic.data) + mime = silc_mime_alloc(); + if (!mime) return; - ic.len = fread(ic.data, 1, st.st_size, fp); - fclose(fp); - mime = silc_mime_alloc(); - if (!mime) { - g_free(ic.data); - return; - } - - t = purple_buddy_icon_get_type((const PurpleBuddyIcon *)&ic); - if (!t) { - g_free(ic.data); + t = purple_util_get_image_extension(purple_imgstore_get_data(img), purple_imgstore_get_size(img)); + if (!t || !strcmp(t, "icon")) { silc_mime_free(mime); return; } @@ -1730,7 +1715,7 @@ t = "jpeg"; g_snprintf(type, sizeof(type), "image/%s", t); silc_mime_add_field(mime, "Content-Type", type); - silc_mime_add_data(mime, ic.data, ic.len); + silc_mime_add_data(mime, purple_imgstore_get_data(img), purple_imgstore_get_size(img)); obj.mime = icon = silc_mime_encode(mime, &obj.mime_len); if (obj.mime) @@ -1738,7 +1723,6 @@ SILC_ATTRIBUTE_USER_ICON, &obj, sizeof(obj)); silc_free(icon); - g_free(ic.data); silc_mime_free(mime); } #endif
--- a/libpurple/protocols/silc/ops.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/silc/ops.c Sat Apr 28 03:53:00 2007 +0000 @@ -161,7 +161,7 @@ if (channel && !convo) goto out; - imgid = purple_imgstore_add(data, data_len, ""); + imgid = purple_imgstore_add_with_id(g_memdup(data, data_len), data_len, ""); if (imgid) { cflags |= PURPLE_MESSAGE_IMAGES | PURPLE_MESSAGE_RECV; g_snprintf(tmp, sizeof(tmp), "<IMG ID=\"%d\">", imgid); @@ -177,7 +177,7 @@ sender->nickname : "<unknown>", tmp, cflags, time(NULL)); - purple_imgstore_unref(imgid); + purple_imgstore_unref_by_id(imgid); cflags = 0; } goto out;
--- a/libpurple/protocols/silc/silc.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/silc/silc.c Sat Apr 28 03:53:00 2007 +0000 @@ -194,7 +194,7 @@ SilcUInt32 mask; const char *tmp; #ifdef SILC_ATTRIBUTE_USER_ICON - char *icon; + PurpleStoredImage *img; #endif #ifdef HAVE_SYS_UTSNAME_H struct utsname u; @@ -233,9 +233,9 @@ #ifdef SILC_ATTRIBUTE_USER_ICON /* Set our buddy icon */ - icon = purple_buddy_icons_get_full_path(purple_account_get_buddy_icon(account)); - silcpurple_buddy_set_icon(gc, icon); - g_free(icon); + img = purple_buddy_icons_find_account_icon(account); + silcpurple_buddy_set_icon(gc, img); + purple_imgstore_unref(img); #endif }
--- a/libpurple/protocols/silc/silcpurple.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/silc/silcpurple.h Sat Apr 28 03:53:00 2007 +0000 @@ -145,7 +145,7 @@ char **contactstr, char **langstr, char **devicestr, char **tzstr, char **geostr); #ifdef SILC_ATTRIBUTE_USER_ICON -void silcpurple_buddy_set_icon(PurpleConnection *gc, const char *iconfile); +void silcpurple_buddy_set_icon(PurpleConnection *gc, PurpleStoredImage *img); #endif #ifdef HAVE_SILCMIME_H char *silcpurple_file2mime(const char *filename);
--- a/libpurple/protocols/silc/util.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/silc/util.c Sat Apr 28 03:53:00 2007 +0000 @@ -676,9 +676,9 @@ } id = g_datalist_get_data(&attribs, "id"); - if (id && (image = purple_imgstore_get(atoi(id)))) { + if (id && (image = purple_imgstore_find_by_id(atoi(id)))) { unsigned long imglen = purple_imgstore_get_size(image); - gpointer img = purple_imgstore_get_data(image); + gconstpointer img = purple_imgstore_get_data(image); p = silc_mime_alloc();
--- a/libpurple/protocols/yahoo/yahoo.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Sat Apr 28 03:53:00 2007 +0000 @@ -342,7 +342,10 @@ } case 192: /* Pictures, aka Buddy Icons, checksum */ { + /* FIXME: Please, if you know this protocol, + * FIXME: fix up the strtol() stuff if possible. */ int cksum = strtol(pair->value, NULL, 10); + const char *locksum = NULL; PurpleBuddy *b; if (!name) @@ -353,9 +356,7 @@ if (!cksum || (cksum == -1)) { if (f) yahoo_friend_set_buddy_icon_need_request(f, TRUE); - purple_buddy_icons_set_for_user(gc->account, name, NULL, 0); - if (b) - purple_blist_node_remove_setting((PurpleBlistNode *)b, YAHOO_ICON_CHECKSUM_KEY); + purple_buddy_icons_set_for_user(gc->account, name, NULL, 0, NULL); break; } @@ -363,7 +364,8 @@ break; yahoo_friend_set_buddy_icon_need_request(f, FALSE); - if (b && cksum != purple_blist_node_get_int((PurpleBlistNode*)b, YAHOO_ICON_CHECKSUM_KEY)) + if (b && (locksum = purple_buddy_icons_get_checksum_for_user(b)) != NULL && + cksum != strtol(locksum, NULL, 10)) yahoo_send_picture_request(gc, name); break; @@ -2686,11 +2688,10 @@ static void yahoo_picture_check(PurpleAccount *account) { PurpleConnection *gc = purple_account_get_connection(account); - char *buddyicon; - - buddyicon = purple_buddy_icons_get_full_path(purple_account_get_buddy_icon(account)); - yahoo_set_buddy_icon(gc, buddyicon); - g_free(buddyicon); + PurpleStoredImage *img = purple_buddy_icons_find_account_icon(account); + + yahoo_set_buddy_icon(gc, img); + purple_imgstore_unref(img); } static int get_yahoo_status_from_purple_status(PurpleStatus *status)
--- a/libpurple/protocols/yahoo/yahoo.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo.h Sat Apr 28 03:53:00 2007 +0000 @@ -48,7 +48,6 @@ #define WEBMESSENGER_URL "http://login.yahoo.com/config/login?.src=pg" -#define YAHOO_ICON_CHECKSUM_KEY "icon_checksum" #define YAHOO_PICURL_SETTING "picture_url" #define YAHOO_PICCKSUM_SETTING "picture_checksum" #define YAHOO_PICEXPIRE_SETTING "picture_expire"
--- a/libpurple/protocols/yahoo/yahoo_picture.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo_picture.c Sat Apr 28 03:53:00 2007 +0000 @@ -49,7 +49,6 @@ { struct yahoo_fetch_picture_data *d; struct yahoo_data *yd; - PurpleBuddy *b; d = user_data; yd = d->gc->proto_data; @@ -60,10 +59,9 @@ } else if (len == 0) { purple_debug_error("yahoo", "Fetched an icon with length 0. Strange.\n"); } else { - purple_buddy_icons_set_for_user(purple_connection_get_account(d->gc), d->who, (void *)pic_data, len); - b = purple_find_buddy(purple_connection_get_account(d->gc), d->who); - if (b) - purple_blist_node_set_int((PurpleBlistNode*)b, YAHOO_ICON_CHECKSUM_KEY, d->checksum); + char *checksum = g_strdup_printf("%i", d->checksum); + purple_buddy_icons_set_for_user(purple_connection_get_account(d->gc), d->who, g_memdup(pic_data, len), len, checksum); + g_free(checksum); } g_free(d->who); @@ -117,7 +115,11 @@ PurpleUtilFetchUrlData *url_data; struct yahoo_fetch_picture_data *data; PurpleBuddy *b = purple_find_buddy(gc->account, who); - if (b && (checksum == purple_blist_node_get_int((PurpleBlistNode*)b, YAHOO_ICON_CHECKSUM_KEY))) + const char *locksum = NULL; + + /* FIXME: Cleanup this strtol() stuff if possible. */ + if (b && (locksum = purple_buddy_icons_get_checksum_for_user(b)) != NULL && + (checksum == strtol(locksum, NULL, 10))) return; data = g_new0(struct yahoo_fetch_picture_data, 1); @@ -166,11 +168,8 @@ if (icon == 2) yahoo_send_picture_request(gc, who); else if ((icon == 0) || (icon == 1)) { - PurpleBuddy *b = purple_find_buddy(gc->account, who); YahooFriend *f; - purple_buddy_icons_set_for_user(gc->account, who, NULL, 0); - if (b) - purple_blist_node_remove_setting((PurpleBlistNode *)b, YAHOO_ICON_CHECKSUM_KEY); + purple_buddy_icons_set_for_user(gc->account, who, NULL, 0, NULL); if ((f = yahoo_friend_find(gc, who))) yahoo_friend_set_buddy_icon_need_request(f, TRUE); purple_debug_misc("yahoo", "Setting user %s's icon to NULL.\n", who); @@ -203,7 +202,11 @@ if (who) { PurpleBuddy *b = purple_find_buddy(gc->account, who); - if (b && (checksum != purple_blist_node_get_int((PurpleBlistNode*)b, YAHOO_ICON_CHECKSUM_KEY))) + const char *locksum = NULL; + + /* FIXME: Cleanup this strtol() stuff if possible. */ + if (b && (locksum = purple_buddy_icons_get_checksum_for_user(b)) != NULL && + (checksum != strtol(locksum, NULL, 10))) yahoo_send_picture_request(gc, who); } } @@ -276,11 +279,8 @@ if (avatar == 2) yahoo_send_picture_request(gc, who); else if ((avatar == 0) || (avatar == 1)) { - PurpleBuddy *b = purple_find_buddy(gc->account, who); YahooFriend *f; - purple_buddy_icons_set_for_user(gc->account, who, NULL, 0); - if (b) - purple_blist_node_remove_setting((PurpleBlistNode *)b, YAHOO_ICON_CHECKSUM_KEY); + purple_buddy_icons_set_for_user(gc->account, who, NULL, 0, NULL); if ((f = yahoo_friend_find(gc, who))) yahoo_friend_set_buddy_icon_need_request(f, TRUE); purple_debug_misc("yahoo", "Setting user %s's icon to NULL.\n", who); @@ -518,15 +518,12 @@ } } -void yahoo_set_buddy_icon(PurpleConnection *gc, const char *iconfile) +void yahoo_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img) { struct yahoo_data *yd = gc->proto_data; PurpleAccount *account = gc->account; - gchar *icondata; - gsize len; - GError *error = NULL; - if (iconfile == NULL) { + if (img == NULL) { g_free(yd->picture_url); yd->picture_url = NULL; @@ -537,14 +534,19 @@ /* Tell everyone we ain't got one no more */ yahoo_send_picture_update(gc, 0); - } else if (g_file_get_contents(iconfile, &icondata, &len, &error)) { - GString *s = g_string_new_len(icondata, len); + } else { + gconstpointer data = purple_imgstore_get_data(img); + size_t len = purple_imgstore_get_size(img); + GString *s = g_string_new_len(data, len); struct yahoo_buddy_icon_upload_data *d; int oldcksum = purple_account_get_int(account, YAHOO_PICCKSUM_SETTING, 0); int expire = purple_account_get_int(account, YAHOO_PICEXPIRE_SETTING, 0); const char *oldurl = purple_account_get_string(account, YAHOO_PICURL_SETTING, NULL); + char *iconfile; - g_free(icondata); + /* TODO: At some point, it'd be nice to fix this for real, or + * TODO: at least change it to be something like: + * TODO: purple_imgstore_get_filename(img); */ yd->picture_checksum = g_string_hash(s); if ((yd->picture_checksum == oldcksum) && @@ -557,11 +559,15 @@ return; } + /* TODO: FIXME: This is completely wrong. The upload code needs to + * TODO: be modified to work with a PurpleStoredImage. */ + iconfile = g_build_filename(purple_buddy_icons_get_cache_dir(), + purple_imgstore_get_filename(img), NULL); d = g_new0(struct yahoo_buddy_icon_upload_data, 1); d->gc = gc; d->str = s; d->fd = -1; - d->filename = g_strdup(iconfile); + d->filename = iconfile; if (!yd->logged_in) { yd->picture_upload_todo = d; @@ -570,10 +576,5 @@ yahoo_buddy_icon_upload(gc, d); - } else { - purple_debug_error("yahoo", - "Could not read buddy icon file '%s': %s\n", - iconfile, error->message); - g_error_free(error); } }
--- a/libpurple/protocols/yahoo/yahoo_picture.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo_picture.h Sat Apr 28 03:53:00 2007 +0000 @@ -37,7 +37,7 @@ void yahoo_process_avatar_update(PurpleConnection *gc, struct yahoo_packet *pkt); -void yahoo_set_buddy_icon(PurpleConnection *gc, const char *iconfile); +void yahoo_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img); void yahoo_buddy_icon_upload(PurpleConnection *gc, struct yahoo_buddy_icon_upload_data *d); void yahoo_buddy_icon_upload_data_free(struct yahoo_buddy_icon_upload_data *d);
--- a/libpurple/protocols/yahoo/yahoo_profile.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo_profile.c Sat Apr 28 03:53:00 2007 +0000 @@ -1027,7 +1027,7 @@ photo_url_text, url_text); } else { purple_debug_info("yahoo", "%s is %d bytes\n", photo_url_text, len); - id = purple_imgstore_add(url_text, len, NULL); + id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL); tmp = g_strdup_printf("<img id=\"%d\"><br>", id); purple_notify_user_info_add_pair(user_info, NULL, tmp); @@ -1241,7 +1241,7 @@ g_free(photo_url_text); g_free(info2_data); if (id != -1) - purple_imgstore_unref(id); + purple_imgstore_unref_by_id(id); #endif }
--- a/libpurple/prpl.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/prpl.h Sat Apr 28 03:53:00 2007 +0000 @@ -59,6 +59,7 @@ #include "blist.h" #include "conversation.h" #include "ft.h" +#include "imgstore.h" #include "notify.h" #include "proxy.h" #include "plugin.h" @@ -284,7 +285,9 @@ const char *(*normalize)(const PurpleAccount *, const char *); - void (*set_buddy_icon)(PurpleConnection *, const char *cached_path); + /* The prpl does NOT own a reference to img. If it needs one, it + * must purple_imgstore_ref(img) itself. */ + void (*set_buddy_icon)(PurpleConnection *, PurpleStoredImage *img); void (*remove_group)(PurpleConnection *gc, PurpleGroup *group);
--- a/libpurple/request.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/request.h Sat Apr 28 03:53:00 2007 +0000 @@ -1332,7 +1332,7 @@ * @param cancel_text The text for the @c Cancel button. * @param cancel_cb The callback for the @c Cancel button. * @param account The PurpleAccount associated with this request, or NULL if none is - * @param who The username of the buddy assocaited with this request, or NULL if none is + * @param who The username of the buddy associated with this request, or NULL if none is * @param conv The PurpleConversation associated with this request, or NULL if none is * @param user_data The data to pass to the callback. *
--- a/libpurple/status.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/status.c Sat Apr 28 03:53:00 2007 +0000 @@ -597,8 +597,6 @@ notify_buddy_status_update(PurpleBuddy *buddy, PurplePresence *presence, PurpleStatus *old_status, PurpleStatus *new_status) { - PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); - if (purple_prefs_get_bool("/purple/logging/log_system")) { time_t current_time = time(NULL); @@ -637,9 +635,6 @@ g_free(tmp); } - - if (ops != NULL && ops->update != NULL) - ops->update(purple_get_blist(), (PurpleBlistNode*)buddy); } static void
--- a/libpurple/tests/check_libpurple.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/tests/check_libpurple.c Sat Apr 28 03:53:00 2007 +0000 @@ -54,7 +54,14 @@ int main(void) { int number_failed; - SRunner *sr = srunner_create (master_suite()); + SRunner *sr; + + /* Make g_return_... functions fatal, ALWAYS. + * As this is the test code, this is NOT controlled + * by PURPLE_FATAL_ASSERTS. */ + g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL); + + sr = srunner_create (master_suite()); srunner_add_suite(sr, cipher_suite()); srunner_add_suite(sr, jabber_jutil_suite());
--- a/libpurple/util.c Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/util.c Sat Apr 28 03:53:00 2007 +0000 @@ -65,7 +65,7 @@ }; static char custom_home_dir[MAXPATHLEN]; -static char home_dir[MAXPATHLEN]; +static char home_dir[MAXPATHLEN] = ""; PurpleMenuAction * purple_menu_action_new(const char *label, PurpleCallback callback, gpointer data, @@ -2247,25 +2247,17 @@ #endif } -/* Returns the argument passed to -c IFF it was present, or ~/.gaim IFF it - * exists, else ~/.purple. */ +/* Returns the argument passed to -c IFF it was present, or ~/.purple. */ const char * purple_user_dir(void) { - if (custom_home_dir != NULL && strlen(custom_home_dir) > 0) { + if (custom_home_dir != NULL && *custom_home_dir) { strcpy ((char*) &home_dir, (char*) &custom_home_dir); - } else { + } else if (!*home_dir) { const gchar *hd = purple_home_dir(); if (hd) { g_strlcpy((char*) &home_dir, hd, sizeof(home_dir)); - g_strlcat((char*) &home_dir, G_DIR_SEPARATOR_S ".gaim", - sizeof(home_dir)); - - if (g_file_test(home_dir, G_FILE_TEST_EXISTS)) - return home_dir; - - g_strlcpy((char*) &home_dir, hd, sizeof(home_dir)); g_strlcat((char*) &home_dir, G_DIR_SEPARATOR_S ".purple", sizeof(home_dir)); } @@ -2579,6 +2571,27 @@ return fp; } +const char * +purple_util_get_image_extension(gconstpointer data, size_t len) +{ + g_return_val_if_fail(data != NULL, NULL); + g_return_val_if_fail(len > 0, NULL); + + if (len >= 4) + { + if (!strncmp((char *)data, "BM", 2)) + return "bmp"; + else if (!strncmp((char *)data, "GIF8", 4)) + return "gif"; + else if (!strncmp((char *)data, "\xff\xd8\xff\xe0", 4)) + return "jpg"; + else if (!strncmp((char *)data, "\x89PNG", 4)) + return "png"; + } + + return "icon"; +} + gboolean purple_program_is_valid(const char *program) { @@ -2656,7 +2669,7 @@ gboolean purple_running_osx(void) { -#if defined(__APPLE__) +#if defined(__APPLE__) return TRUE; #else return FALSE; @@ -2685,6 +2698,7 @@ purple_normalize(const PurpleAccount *account, const char *str) { const char *ret = NULL; + static char buf[BUF_LEN]; if (account != NULL) { @@ -2701,7 +2715,6 @@ if (ret == NULL) { - static char buf[BUF_LEN]; char *tmp; tmp = g_utf8_normalize(str, -1, G_NORMALIZE_DEFAULT); @@ -4196,7 +4209,7 @@ signal(SIGABRT, SIG_DFL); /* 6: abort program */ #ifdef SIGPOLL - signal(SIGPOLL, SIG_DFL); /* 7: pollable event (POSIX) */ + signal(SIGPOLL, SIG_DFL); /* 7: pollable event (POSIX) */ #endif /* SIGPOLL */ #ifdef SIGEMT @@ -4212,7 +4225,7 @@ signal(SIGTERM, SIG_DFL); /* 15: software termination signal */ signal(SIGCHLD, SIG_DFL); /* 20: child status has changed */ signal(SIGXCPU, SIG_DFL); /* 24: exceeded CPU time limit */ - signal(SIGXFSZ, SIG_DFL); /* 25: exceeded file size limit */ + signal(SIGXFSZ, SIG_DFL); /* 25: exceeded file size limit */ #endif /* HAVE_SIGNAL_H */ #endif /* !_WIN32 */ }
--- a/libpurple/util.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/util.h Sat Apr 28 03:53:00 2007 +0000 @@ -469,7 +469,7 @@ * the first character of the entity. If given an unrecognized entity, the function * returns @c NULL. * - * Note that this function, unlike purple_unescape_html(), does not search + * Note that this function, unlike purple_unescape_html(), does not search * the string for the entity, does not replace the entity, and does not * return a newly allocated string. * @@ -598,6 +598,25 @@ FILE *purple_mkstemp(char **path, gboolean binary); /** + * Returns an extension corresponding to the image data's file type. + * + * @param data A pointer to the image data + * @param len The length of the image data + * + * @return The appropriate extension, or "icon" if unknown. + */ +const char * +purple_util_get_image_extension(gconstpointer data, size_t len); + +/*@}*/ + + +/**************************************************************************/ +/** @name Environment Detection Functions */ +/**************************************************************************/ +/*@{*/ + +/** * Checks if the given program name is valid and executable. * * @param program The file name of the application. @@ -1118,6 +1137,7 @@ * inherit the handlers of the parent. */ void purple_restore_default_signal_handlers(void); + #ifdef __cplusplus } #endif
--- a/libpurple/value.h Thu Apr 26 21:15:41 2007 +0000 +++ b/libpurple/value.h Sat Apr 28 03:53:00 2007 +0000 @@ -76,7 +76,8 @@ PURPLE_SUBTYPE_XFER, PURPLE_SUBTYPE_SAVEDSTATUS, PURPLE_SUBTYPE_XMLNODE, - PURPLE_SUBTYPE_USERINFO + PURPLE_SUBTYPE_USERINFO, + PURPLE_SUBTYPE_STORED_IMAGE } PurpleSubType; /**
--- a/pidgin.desktop.in Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin.desktop.in Sat Apr 28 03:53:00 2007 +0000 @@ -4,7 +4,7 @@ _GenericName=Internet Messenger _Comment=Send instant messages over multiple protocols Exec=pidgin -Icon=pidgin.png +Icon=pidgin StartupNotify=true Terminal=false Type=Application
--- a/pidgin.spec.in Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin.spec.in Sat Apr 28 03:53:00 2007 +0000 @@ -227,8 +227,10 @@ # Delete files that we don't want to put in any of the RPMs rm -f $RPM_BUILD_ROOT%{_libdir}/finch/*.la rm -f $RPM_BUILD_ROOT%{_libdir}/pidgin/*.la -rm -f $RPM_BUILD_ROOT%{_libdir}/libpurple/*.la -rm -f $RPM_BUILD_ROOT%{_libdir}/libpurple/private/*.la +rm -f $RPM_BUILD_ROOT%{_libdir}/purple/*.la +rm -f $RPM_BUILD_ROOT%{_libdir}/purple/liboscar.so +rm -f $RPM_BUILD_ROOT%{_libdir}/purple/libjabber.so +rm -f $RPM_BUILD_ROOT%{_libdir}/purple/private/*.la rm -f $RPM_BUILD_ROOT%{_libdir}/*.la rm -f $RPM_BUILD_ROOT%{perl_archlib}/perllocal.pod find $RPM_BUILD_ROOT -type f -name .packlist -exec rm -f {} ';'
--- a/pidgin/gtkaccount.c Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/gtkaccount.c Sat Apr 28 03:53:00 2007 +0000 @@ -122,8 +122,7 @@ GtkWidget *icon_filesel; GtkWidget *icon_preview; GtkWidget *icon_text; - char *cached_icon_path; - char *icon_path; + PurpleStoredImage *icon_img; /* Protocol Options */ GtkWidget *protocol_frame; @@ -195,20 +194,25 @@ } static void -set_dialog_icon(AccountPrefsDialog *dialog, gchar *new_cached_icon_path, gchar *new_icon_path) +set_dialog_icon(AccountPrefsDialog *dialog, gpointer *data, size_t len, gchar *new_icon_path) { - char *filename; GdkPixbuf *pixbuf = NULL; - g_free(dialog->cached_icon_path); - g_free(dialog->icon_path); - dialog->cached_icon_path = new_cached_icon_path; - dialog->icon_path = new_icon_path; - - filename = purple_buddy_icons_get_full_path(dialog->cached_icon_path); - if (filename != NULL) { - pixbuf = gdk_pixbuf_new_from_file(filename, NULL); - g_free(filename); + purple_imgstore_unref(dialog->icon_img); + if (data != NULL) + { + if (len > 0) + dialog->icon_img = purple_imgstore_add(data, len, new_icon_path); + else + g_free(data); + } + + if (dialog->icon_img != NULL) { + GdkPixbufLoader *loader = gdk_pixbuf_loader_new(); + gdk_pixbuf_loader_write(loader, purple_imgstore_get_data(dialog->icon_img), + purple_imgstore_get_size(dialog->icon_img), NULL); + gdk_pixbuf_loader_close(loader, NULL); + pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); } if (pixbuf && dialog->prpl_info && @@ -298,12 +302,14 @@ static void icon_filesel_choose_cb(const char *filename, gpointer data) { - AccountPrefsDialog *dialog; - - dialog = data; + AccountPrefsDialog *dialog = data; if (filename != NULL) - set_dialog_icon(dialog, pidgin_convert_buddy_icon(dialog->plugin, filename), g_strdup(filename)); + { + size_t len; + gpointer data = pidgin_convert_buddy_icon(dialog->plugin, filename, &len); + set_dialog_icon(dialog, data, len, g_strdup(filename)); + } dialog->icon_filesel = NULL; } @@ -318,7 +324,7 @@ static void icon_reset_cb(GtkWidget *button, AccountPrefsDialog *dialog) { - set_dialog_icon(dialog, NULL, NULL); + set_dialog_icon(dialog, NULL, 0, NULL); } static void @@ -333,6 +339,9 @@ if (!g_ascii_strncasecmp(name, "file://", 7)) { GError *converr = NULL; gchar *tmp, *rtmp; + gpointer data; + size_t len; + /* It looks like we're dealing with a local file. */ if(!(tmp = g_filename_from_uri(name, NULL, &converr))) { purple_debug(PURPLE_DEBUG_ERROR, "buddyicon", "%s\n", @@ -342,8 +351,10 @@ } if ((rtmp = strchr(tmp, '\r')) || (rtmp = strchr(tmp, '\n'))) *rtmp = '\0'; - set_dialog_icon(dialog, pidgin_convert_buddy_icon(dialog->plugin, tmp), g_strdup(tmp)); - g_free(tmp); + + data = pidgin_convert_buddy_icon(dialog->plugin, tmp, &len); + /* This takes ownership of tmp */ + set_dialog_icon(dialog, data, len, tmp); } gtk_drag_finish(dc, TRUE, FALSE, t); } @@ -591,8 +602,8 @@ gtk_widget_show(dialog->icon_entry); /* TODO: Uh, isn't this next line pretty useless? */ pidgin_set_accessible_label (dialog->icon_entry, label); - dialog->cached_icon_path = NULL; - dialog->icon_path = NULL; + purple_imgstore_unref(dialog->icon_img); + dialog->icon_img = NULL; vbox2 = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 0); @@ -617,19 +628,27 @@ } if (dialog->account != NULL) { + PurpleStoredImage *img; + gpointer data = NULL; + size_t len = 0; + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->new_mail_check), purple_account_get_check_mail(dialog->account)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->icon_check), !purple_account_get_bool(dialog->account, "use-global-buddyicon", TRUE)); - set_dialog_icon(dialog, - g_strdup(purple_account_get_ui_string(dialog->account, - PIDGIN_UI, "non-global-buddyicon-cached-path", NULL)), - g_strdup(purple_account_get_ui_string(dialog->account, - PIDGIN_UI, "non-global-buddyicon-path", NULL))); + + img = purple_buddy_icons_find_account_icon(dialog->account); + if (img) + { + len = purple_imgstore_get_size(img); + data = g_memdup(purple_imgstore_get_data(img), len); + } + set_dialog_icon(dialog, data, len, + g_strdup(purple_account_get_buddy_icon_path(dialog->account))); } else { - set_dialog_icon(dialog, NULL, NULL); + set_dialog_icon(dialog, NULL, 0, NULL); } if (!dialog->prpl_info || @@ -1072,22 +1091,7 @@ g_list_free(dialog->protocol_opt_entries); g_free(dialog->protocol_id); - if (dialog->cached_icon_path != NULL) - { - const char *icon = purple_account_get_ui_string(dialog->account, PIDGIN_UI, "non-global-buddyicon-cached-path", NULL); - if (dialog->cached_icon_path != NULL && (icon == NULL || strcmp(dialog->cached_icon_path, icon))) - { - /* The user set an icon, which would've been cached by convert_buddy_icon, - * but didn't save the changes. Delete the cache file. */ - char *filename = g_build_filename(purple_buddy_icons_get_cache_dir(), dialog->cached_icon_path, NULL); - g_unlink(filename); - g_free(filename); - } - - g_free(dialog->cached_icon_path); - } - - g_free(dialog->icon_path); + purple_imgstore_unref(dialog->icon_img); if (dialog->icon_filesel) gtk_widget_destroy(dialog->icon_filesel); @@ -1143,26 +1147,37 @@ prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(dialog->plugin); if (prpl_info != NULL && prpl_info->icon_spec.format != NULL) { + const char *filename; + if (new || purple_account_get_bool(account, "use-global-buddyicon", TRUE) == gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->icon_check))) { icon_change = TRUE; } purple_account_set_bool(account, "use-global-buddyicon", !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->icon_check))); - purple_account_set_ui_string(account, PIDGIN_UI, "non-global-buddyicon-cached-path", dialog->cached_icon_path); - purple_account_set_ui_string(account, PIDGIN_UI, "non-global-buddyicon-path", dialog->icon_path); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->icon_check))) { - purple_account_set_buddy_icon_path(account, dialog->icon_path); - purple_account_set_buddy_icon(account, dialog->cached_icon_path); + if (dialog->icon_img) + { + size_t len = purple_imgstore_get_size(dialog->icon_img); + purple_buddy_icons_set_account_icon(account, + g_memdup(purple_imgstore_get_data(dialog->icon_img), len), + len); + purple_account_set_buddy_icon_path(account, purple_imgstore_get_filename(dialog->icon_img)); + } + else + { + purple_buddy_icons_set_account_icon(account, NULL, 0); + purple_account_set_buddy_icon_path(account, NULL); + } } - else if (purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon") && icon_change) + else if ((filename = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon")) && icon_change) { - const char *filename = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon"); - char *icon = pidgin_convert_buddy_icon(dialog->plugin, filename); + size_t len; + gpointer data = pidgin_convert_buddy_icon(dialog->plugin, filename, &len); purple_account_set_buddy_icon_path(account, filename); - purple_account_set_buddy_icon(account, icon); - g_free(icon); + purple_buddy_icons_set_account_icon(account, data, len); } } @@ -1977,7 +1992,7 @@ set_account(GtkListStore *store, GtkTreeIter *iter, PurpleAccount *account, GdkPixbuf *global_buddyicon) { GdkPixbuf *pixbuf, *buddyicon = NULL; - const char *path = NULL; + PurpleStoredImage *img = NULL; pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM); if ((pixbuf != NULL) && purple_account_is_disconnected(account)) @@ -1988,12 +2003,22 @@ buddyicon = g_object_ref(G_OBJECT(global_buddyicon)); /* This is for when set_account() is called for a single account */ else - path = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon"); - } else - path = purple_account_get_ui_string(account, PIDGIN_UI, "non-global-buddyicon-path", NULL); - - if (path != NULL) { - GdkPixbuf *buddyicon_pixbuf = gdk_pixbuf_new_from_file(path, NULL); + img = purple_buddy_icons_find_account_icon(account); + } else { + img = purple_buddy_icons_find_account_icon(account); + } + + if (img != NULL) { + GdkPixbufLoader *loader = gdk_pixbuf_loader_new(); + GdkPixbuf *buddyicon_pixbuf; + + gdk_pixbuf_loader_write(loader, purple_imgstore_get_data(img), + purple_imgstore_get_size(img), NULL); + gdk_pixbuf_loader_close(loader, NULL); + buddyicon_pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); + + purple_imgstore_unref(img); + if (buddyicon_pixbuf != NULL) { buddyicon = gdk_pixbuf_scale_simple(buddyicon_pixbuf, 22, 22, GDK_INTERP_HYPER); g_object_unref(G_OBJECT(buddyicon_pixbuf));
--- a/pidgin/gtkblist.c Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/gtkblist.c Sat Apr 28 03:53:00 2007 +0000 @@ -2155,7 +2155,7 @@ static GdkPixbuf *pidgin_blist_get_buddy_icon(PurpleBlistNode *node, - gboolean scaled, gboolean greyed, gboolean custom) + gboolean scaled, gboolean greyed) { GdkPixbuf *buf, *ret = NULL; GdkPixbufLoader *loader; @@ -2163,24 +2163,22 @@ const guchar *data = NULL; gsize len; PurpleBuddy *buddy = NULL; - PurpleChat *chat = NULL; PurpleAccount *account = NULL; PurplePluginProtocolInfo *prpl_info = NULL; + PurpleStoredImage *custom_img; if(PURPLE_BLIST_NODE_IS_CONTACT(node)) { buddy = purple_contact_get_priority_buddy((PurpleContact*)node); } else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { buddy = (PurpleBuddy*)node; - } else if(PURPLE_BLIST_NODE_IS_CHAT(node)) { - chat = (PurpleChat*)node; } else { return NULL; } - if(buddy != NULL) - account = purple_buddy_get_account(buddy); - else if(chat != NULL) - account = chat->account; + if(buddy == NULL) + return NULL; + + account = purple_buddy_get_account(buddy); if(account && account->gc) prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(account->gc->prpl); @@ -2190,44 +2188,34 @@ return NULL; #endif - if (custom) { - const char *file = purple_blist_node_get_string((PurpleBlistNode*)purple_buddy_get_contact(buddy), - "custom_buddy_icon"); - if (file && *file) { - char *contents; - GError *err = NULL; - if (!g_file_get_contents(file, &contents, &len, &err)) { - purple_debug_info("custom -icon", "Could not open custom-icon %s for %s\n", - file, purple_buddy_get_name(buddy), err->message); - g_error_free(err); - } else - data = (const guchar*)contents; - } + custom_img = purple_buddy_icons_find_custom_icon(purple_buddy_get_contact(buddy)); + if (custom_img) + { + data = purple_imgstore_get_data(custom_img); + len = purple_imgstore_get_size(custom_img); } if (data == NULL) { - if(buddy != NULL) { - if (!(icon = purple_buddy_get_icon(buddy))) - if (!(icon = purple_buddy_icons_find(buddy->account, buddy->name))) /* Not sure I like this...*/ - return NULL; - data = purple_buddy_icon_get_data(icon, &len); - } - custom = FALSE; /* We are not using the custom icon */ - } - - if(data == NULL) - return NULL; + if (!(icon = purple_buddy_get_icon(buddy))) + if (!(icon = purple_buddy_icons_find(buddy->account, buddy->name))) /* Not sure I like this...*/ + return NULL; + data = purple_buddy_icon_get_data(icon, &len); + + if(data == NULL) + return NULL; + } loader = gdk_pixbuf_loader_new(); gdk_pixbuf_loader_write(loader, data, len, NULL); gdk_pixbuf_loader_close(loader, NULL); + + purple_imgstore_unref(custom_img); + buf = gdk_pixbuf_loader_get_pixbuf(loader); if (buf) g_object_ref(G_OBJECT(buf)); g_object_unref(G_OBJECT(loader)); - if (custom) - g_free((void*)data); if (buf) { int orig_width, orig_height; int scale_width, scale_height; @@ -2335,7 +2323,7 @@ } td->status_icon = pidgin_blist_get_status_icon(node, PIDGIN_STATUS_ICON_LARGE); - td->avatar = pidgin_blist_get_buddy_icon(node, !full, FALSE, TRUE); + td->avatar = pidgin_blist_get_buddy_icon(node, !full, FALSE); td->prpl_icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); tooltip_text = pidgin_get_tooltip_text(node, full); td->layout = gtk_widget_create_pango_layout(gtkblist->tipwindow, NULL); @@ -4894,7 +4882,7 @@ status = pidgin_blist_get_status_icon((PurpleBlistNode*)buddy, PIDGIN_STATUS_ICON_SMALL); - avatar = pidgin_blist_get_buddy_icon((PurpleBlistNode *)buddy, TRUE, TRUE, TRUE); + avatar = pidgin_blist_get_buddy_icon((PurpleBlistNode *)buddy, TRUE, TRUE); if (!avatar) { g_object_ref(G_OBJECT(gtkblist->empty_avatar)); avatar = gtkblist->empty_avatar; @@ -5079,7 +5067,7 @@ status = pidgin_blist_get_status_icon(node, PIDGIN_STATUS_ICON_SMALL); emblem = pidgin_blist_get_emblem(node); - avatar = pidgin_blist_get_buddy_icon(node, TRUE, FALSE, TRUE); + avatar = pidgin_blist_get_buddy_icon(node, TRUE, FALSE); mark = g_markup_escape_text(purple_chat_get_name(chat), -1);
--- a/pidgin/gtkconv.c Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/gtkconv.c Sat Apr 28 03:53:00 2007 +0000 @@ -2488,23 +2488,6 @@ fclose(fp); } -static const char * -custom_icon_pref_name(PidginConversation *gtkconv) -{ - PurpleConversation *conv; - PurpleAccount *account; - PurpleBuddy *buddy; - - conv = gtkconv->active_conv; - account = purple_conversation_get_account(conv); - buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); - if (buddy) { - PurpleContact *contact = purple_buddy_get_contact(buddy); - return purple_blist_node_get_string((PurpleBlistNode*)contact, "custom_buddy_icon"); - } - return NULL; -} - static void custom_icon_sel_cb(const char *filename, gpointer data) { @@ -2544,9 +2527,7 @@ g_return_if_fail(conv != NULL); - ext = purple_buddy_icon_get_type(purple_conv_im_get_icon(PURPLE_CONV_IM(conv))); - if (ext == NULL) - ext = "icon"; + ext = purple_buddy_icon_get_extension(purple_conv_im_get_icon(PURPLE_CONV_IM(conv))); buf = g_strdup_printf("%s.%s", purple_normalize(conv->account, conv->name), ext); @@ -2584,7 +2565,8 @@ icon_menu(GtkObject *obj, GdkEventButton *e, PidginConversation *gtkconv) { static GtkWidget *menu = NULL; - const char *pref; + PurpleConversation *conv; + PurpleBuddy *buddy; if (e->button != 3 || e->type != GDK_BUTTON_PRESS) return FALSE; @@ -2618,11 +2600,18 @@ 0, 0, NULL); /* Is there a custom icon for this person? */ - pref = custom_icon_pref_name(gtkconv); - if (pref && *pref) { - pidgin_new_item_from_stock(menu, _("Remove Custom Icon"), NULL, - G_CALLBACK(remove_custom_icon_cb), gtkconv, - 0, 0, NULL); + conv = gtkconv->active_conv; + buddy = purple_find_buddy(purple_conversation_get_account(conv), + purple_conversation_get_name(conv)); + if (buddy) + { + PurpleContact *contact = purple_buddy_get_contact(buddy); + if (contact && purple_buddy_icons_has_custom_icon(contact)) + { + pidgin_new_item_from_stock(menu, _("Remove Custom Icon"), NULL, + G_CALLBACK(remove_custom_icon_cb), gtkconv, + 0, 0, NULL); + } } gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, e->button, e->time); @@ -6210,12 +6199,14 @@ PidginConversation *gtkconv; PidginWindow *win; + PurpleBuddy *buddy; + GdkPixbufLoader *loader; GdkPixbufAnimation *anim; GError *err = NULL; - const char *custom = NULL; - const void *data = NULL; + PurpleStoredImage *custom_img = NULL; + gconstpointer data = NULL; size_t len; GdkPixbuf *buf; @@ -6272,17 +6263,18 @@ if (purple_conversation_get_gc(conv) == NULL) return; - custom = custom_icon_pref_name(gtkconv); - if (custom) { - /* There is a custom icon for this user */ - char *contents = NULL; - if (!g_file_get_contents(custom, &contents, &len, &err)) { - purple_debug_warning("custom icon", "could not load custom icon %s for %s\n", - custom, purple_conversation_get_name(conv)); - g_error_free(err); - err = NULL; - } else - data = contents; + buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); + if (buddy) + { + PurpleContact *contact = purple_buddy_get_contact(buddy); + if (contact) { + custom_img = purple_buddy_icons_find_custom_icon(contact); + if (custom_img) { + /* There is a custom icon for this user */ + data = purple_imgstore_get_data(custom_img); + len = purple_imgstore_get_size(custom_img); + } + } } if (data == NULL) { @@ -6292,20 +6284,22 @@ return; data = purple_buddy_icon_get_data(icon, &len); - custom = NULL; + + if (data == NULL) + return; } loader = gdk_pixbuf_loader_new(); gdk_pixbuf_loader_write(loader, data, len, NULL); gdk_pixbuf_loader_close(loader, &err); + + purple_imgstore_unref(custom_img); + anim = gdk_pixbuf_loader_get_animation(loader); if (anim) g_object_ref(G_OBJECT(anim)); g_object_unref(loader); - if (custom) - g_free((void*)data); - if (!anim) return; gtkconv->u.im->anim = anim; @@ -6316,9 +6310,6 @@ g_error_free(err); } - if (!gtkconv->u.im->anim) - return; - if (gdk_pixbuf_animation_is_static_image(gtkconv->u.im->anim)) { gtkconv->u.im->iter = NULL; buf = gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim);
--- a/pidgin/gtkdocklet-x11.c Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/gtkdocklet-x11.c Sat Apr 28 03:53:00 2007 +0000 @@ -25,6 +25,7 @@ #include "internal.h" #include "pidgin.h" #include "debug.h" +#include "prefs.h" #include "pidginstock.h" #include "gtkdialogs.h" @@ -32,7 +33,8 @@ #include "eggtrayicon.h" #include "gtkdocklet.h" -#define EMBED_TIMEOUT 5000 +#define SHORT_EMBED_TIMEOUT 5000 +#define LONG_EMBED_TIMEOUT 15000 /* globals */ static EggTrayIcon *docklet = NULL; @@ -44,12 +46,12 @@ static int docklet_height = 0; /* protos */ -static void docklet_x11_create(void); +static void docklet_x11_create(gboolean); static gboolean -docklet_x11_create_cb() +docklet_x11_recreate_cb() { - docklet_x11_create(); + docklet_x11_create(TRUE); return FALSE; /* for when we're called by the glib idle handler */ } @@ -62,6 +64,7 @@ g_source_remove(embed_timeout); embed_timeout = 0; pidgin_docklet_embedded(); + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/x11/embedded", FALSE); } static void @@ -74,7 +77,7 @@ g_object_unref(G_OBJECT(docklet)); docklet = NULL; - g_idle_add(docklet_x11_create_cb, NULL); + g_idle_add(docklet_x11_recreate_cb, NULL); } static void @@ -236,7 +239,7 @@ } static void -docklet_x11_create() +docklet_x11_create(gboolean recreate) { GtkWidget *box; @@ -272,17 +275,35 @@ * previous visibility state. If the docklet does not get embedded within * the timeout, it will be removed as a visibility manager until it does * get embedded. Ideally, we would only call docklet_embedded() when the - * icon was actually embedded. + * icon was actually embedded. This only happens when the docklet is first + * created, not when being recreated. + * + * The x11 docklet tracks whether it successfully embedded in a pref and + * allows for a longer timeout period if it successfully embedded the last + * time it was run. This should hopefully solve problems with the buddy + * list not properly starting hidden when gaim is started on login. */ - pidgin_docklet_embedded(); - embed_timeout = g_timeout_add(EMBED_TIMEOUT, docklet_x11_embed_timeout_cb, NULL); + if(!recreate) { + pidgin_docklet_embedded(); + if(purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/x11/embedded")) { + embed_timeout = g_timeout_add(LONG_EMBED_TIMEOUT, docklet_x11_embed_timeout_cb, NULL); + } else { + embed_timeout = g_timeout_add(SHORT_EMBED_TIMEOUT, docklet_x11_embed_timeout_cb, NULL); + } + } purple_debug(PURPLE_DEBUG_INFO, "docklet", "created\n"); } +static void +docklet_x11_create_ui_op() +{ + docklet_x11_create(FALSE); +} + static struct docklet_ui_ops ui_ops = { - docklet_x11_create, + docklet_x11_create_ui_op, docklet_x11_destroy, docklet_x11_update_icon, docklet_x11_blank_icon, @@ -298,4 +319,6 @@ docklet_ui_init() { pidgin_docklet_set_ui_ops(&ui_ops); + purple_prefs_add_none(PIDGIN_PREFS_ROOT "/docklet/x11"); + purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/docklet/x11/embedded", FALSE); }
--- a/pidgin/gtkimhtmltoolbar.c Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/gtkimhtmltoolbar.c Sat Apr 28 03:53:00 2007 +0000 @@ -481,8 +481,7 @@ name = strrchr(filename, G_DIR_SEPARATOR) + 1; - id = purple_imgstore_add(filedata, size, name); - g_free(filedata); + id = purple_imgstore_add_with_id(filedata, size, name); if (id == 0) { buf = g_strdup_printf(_("Failed to store image: %s\n"), filename); @@ -500,7 +499,7 @@ gtk_text_buffer_get_iter_at_mark(gtk_text_view_get_buffer(GTK_TEXT_VIEW(toolbar->imhtml)), &iter, ins); gtk_imhtml_insert_image_at_iter(GTK_IMHTML(toolbar->imhtml), id, &iter); - purple_imgstore_unref(id); + purple_imgstore_unref_by_id(id); }
--- a/pidgin/gtkmain.c Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/gtkmain.c Sat Apr 28 03:53:00 2007 +0000 @@ -145,7 +145,7 @@ static void sighandler(int sig); /** - * Reap all our dead children. Sometimes Purple forks off a separate + * Reap all our dead children. Sometimes libpurple forks off a separate * process to do some stuff. When that process exits we are * informed about it so that we can call waitpid() and let it * stop being a zombie. @@ -160,7 +160,7 @@ * it continues with the initialization process. This means that * we have a race condition where GStreamer is waitpid()ing for its * child to die and we're catching the SIGCHLD signal. If GStreamer - * is awarded the zombied process then everything is ok. But if Purple + * is awarded the zombied process then everything is ok. But if libpurple * reaps the zombie process then the GStreamer initialization sequence * fails. * @@ -242,11 +242,15 @@ GdkPixbuf *icon = NULL; char *icon_path; int i; - const char *icon_sizes[] = { - "16x16", - "24x24", - "32x32", - "48x48" + struct { + const char *dir; + const char *filename; + } icon_sizes[] = { + {"16x16", "pidgin.png"}, + {"24x24", "pidgin.png"}, + {"32x32", "pidgin.png"}, + {"48x48", "pidgin.png"}, + {"scalable", "pidgin.svg"} }; #endif @@ -258,7 +262,7 @@ #ifndef _WIN32 /* use the nice PNG icon for all the windows */ for(i=0; i<G_N_ELEMENTS(icon_sizes); i++) { - icon_path = g_build_filename(DATADIR, "icons", "hicolor", icon_sizes[i], "apps", "pidgin.png", NULL); + icon_path = g_build_filename(DATADIR, "icons", "hicolor", icon_sizes[i].dir, "apps", icon_sizes[i].filename, NULL); icon = gdk_pixbuf_new_from_file(icon_path, NULL); g_free(icon_path); if (icon) { @@ -448,6 +452,7 @@ int opt; gboolean gui_check; gboolean debug_enabled; + gboolean migration_failed = FALSE; struct option long_options[] = { {"config", required_argument, NULL, 'c'}, @@ -641,6 +646,15 @@ purple_debug_set_enabled(debug_enabled); + /* If we're using a custom configuration directory, we + * do NOT want to migrate, or weird things will happen. */ + if (opt_config_dir_arg == NULL) + { + if (!purple_core_migrate()) + { + migration_failed = TRUE; + } + } search_path = g_build_filename(purple_user_dir(), "gtkrc-2.0", NULL); gtk_rc_add_default_file(search_path); @@ -665,6 +679,37 @@ winpidgin_init(hint); #endif + if (migration_failed) + { + char *old = g_strconcat(purple_home_dir(), + G_DIR_SEPARATOR_S ".gaim", NULL); + const char *text = _( + "%s encountered errors migrating your settings " + "from %s to %s. Please investigate and complete the " + "migration by hand."); + GtkWidget *dialog; + + dialog = gtk_message_dialog_new(NULL, + 0, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + text, PIDGIN_NAME, + old, purple_user_dir()); + g_free(old); + + g_signal_connect_swapped(dialog, "response", + G_CALLBACK(gtk_main_quit), NULL); + + gtk_widget_show_all(dialog); + + gtk_main(); + +#ifdef HAVE_SIGNAL_H + g_free(segfault_message); +#endif + return 0; + } + purple_core_set_ui_ops(pidgin_core_get_ui_ops()); purple_eventloop_set_ui_ops(pidgin_eventloop_get_ui_ops());
--- a/pidgin/gtkprefs.c Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/gtkprefs.c Sat Apr 28 03:53:00 2007 +0000 @@ -2029,8 +2029,6 @@ void pidgin_prefs_init(void) { - /* only change this when we have a sane prefs migration path */ - purple_prefs_add_none("/gaim"); purple_prefs_add_none(PIDGIN_PREFS_ROOT ""); purple_prefs_add_none("/plugins/gtk"); @@ -2061,7 +2059,12 @@ smiley_theme_pref_cb, NULL); } -void pidgin_prefs_update_old() { +void pidgin_prefs_update_old() +{ + const char *str; + + purple_prefs_rename("/gaim/gtk", PIDGIN_PREFS_ROOT); + /* Rename some old prefs */ purple_prefs_rename(PIDGIN_PREFS_ROOT "/logging/log_ims", "/purple/logging/log_ims"); purple_prefs_rename(PIDGIN_PREFS_ROOT "/logging/log_chats", "/purple/logging/log_chats"); @@ -2076,6 +2079,9 @@ /* this string pref moved into the core, try to be friendly */ purple_prefs_rename(PIDGIN_PREFS_ROOT "/idle/reporting_method", "/purple/away/idle_reporting"); + if ((str = purple_prefs_get_string("/purple/away/idle_reporting")) && + strcmp(str, "gaim") == 0) + purple_prefs_set_string("/purple/away/idle_reporting", "purple"); /* Remove some no-longer-used prefs */ purple_prefs_remove(PIDGIN_PREFS_ROOT "/blist/auto_expand_contacts"); @@ -2125,5 +2131,4 @@ purple_prefs_remove(PIDGIN_PREFS_ROOT "/away/queue_messages"); purple_prefs_remove(PIDGIN_PREFS_ROOT "/away"); purple_prefs_remove("/plugins/gtk/docklet/queue_messages"); - purple_prefs_rename("/gaim/gtk", "/pidgin"); }
--- a/pidgin/gtkstatusbox.c Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/gtkstatusbox.c Sat Apr 28 03:53:00 2007 +0000 @@ -42,8 +42,10 @@ #include <gdk/gdkkeysyms.h> #include "account.h" +#include "buddyicon.h" #include "core.h" #include "internal.h" +#include "imgstore.h" #include "network.h" #include "savedstatuses.h" #include "status.h" @@ -383,13 +385,26 @@ if (status_box->account && !purple_account_get_bool(status_box->account, "use-global-buddyicon", TRUE)) { - char *string = purple_buddy_icons_get_full_path(purple_account_get_buddy_icon(status_box->account)); - pidgin_status_box_set_buddy_icon(status_box, string); - g_free(string); + PurpleStoredImage *img = purple_buddy_icons_find_account_icon(status_box->account); + pidgin_status_box_set_buddy_icon(status_box, img); + purple_imgstore_unref(img); } else { - pidgin_status_box_set_buddy_icon(status_box, purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon")); + const char *filename = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon"); + PurpleStoredImage *img = NULL; + + if (filename != NULL) + { + gchar *contents; + gsize size; + if (g_file_get_contents(filename, &contents, &size, NULL)) + { + img = purple_imgstore_add(contents, size, filename); + } + } + + pidgin_status_box_set_buddy_icon(status_box, img); } status_box->hand_cursor = gdk_cursor_new (GDK_HAND2); @@ -422,6 +437,8 @@ gdk_cursor_unref(statusbox->hand_cursor); gdk_cursor_unref(statusbox->arrow_cursor); + purple_imgstore_unref(statusbox->buddy_icon_img); + g_object_unref(G_OBJECT(statusbox->buddy_icon)); g_object_unref(G_OBJECT(statusbox->buddy_icon_hover)); @@ -431,12 +448,10 @@ if (statusbox->icon_box_menu) gtk_widget_destroy(statusbox->icon_box_menu); - g_free(statusbox->buddy_icon_path); - statusbox->icon = NULL; statusbox->icon_box = NULL; statusbox->icon_box_menu = NULL; - statusbox->buddy_icon_path = NULL; + statusbox->buddy_icon_img = NULL; statusbox->buddy_icon = NULL; statusbox->buddy_icon_hover = NULL; statusbox->hand_cursor = NULL; @@ -489,14 +504,13 @@ gdk_cursor_unref(statusbox->hand_cursor); gdk_cursor_unref(statusbox->arrow_cursor); + purple_imgstore_unref(statusbox->buddy_icon_img); g_object_unref(G_OBJECT(statusbox->buddy_icon)); g_object_unref(G_OBJECT(statusbox->buddy_icon_hover)); if (statusbox->buddy_icon_sel) gtk_widget_destroy(statusbox->buddy_icon_sel); - g_free(statusbox->buddy_icon_path); - G_OBJECT_CLASS(parent_class)->finalize(obj); } @@ -1402,20 +1416,21 @@ static void buddy_icon_set_cb(const char *filename, PidginStatusBox *box) { + PurpleStoredImage *img = NULL; if (box->account) { PurplePlugin *plug = purple_find_prpl(purple_account_get_protocol_id(box->account)); if (plug) { PurplePluginProtocolInfo *prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plug); if (prplinfo && prplinfo->icon_spec.format) { - char *icon = NULL; + gpointer data = NULL; + size_t len = 0; if (filename) - icon = pidgin_convert_buddy_icon(plug, filename); + data = pidgin_convert_buddy_icon(plug, filename, &len); + img = purple_buddy_icons_set_account_icon(box->account, data, len); + purple_account_set_buddy_icon_path(box->account, filename); + purple_account_set_bool(box->account, "use-global-buddyicon", (filename != NULL)); - purple_account_set_ui_string(box->account, PIDGIN_UI, "non-global-buddyicon-cached-path", icon); - purple_account_set_buddy_icon_path(box->account, filename); - purple_account_set_buddy_icon(box->account, icon); - g_free(icon); } } } else { @@ -1428,17 +1443,20 @@ if (prplinfo != NULL && purple_account_get_bool(account, "use-global-buddyicon", TRUE) && prplinfo->icon_spec.format) { - char *icon = NULL; + gpointer data = NULL; + size_t len = 0; if (filename) - icon = pidgin_convert_buddy_icon(plug, filename); - purple_account_set_buddy_icon_path(account, filename); - purple_account_set_buddy_icon(account, icon); - g_free(icon); + data = pidgin_convert_buddy_icon(plug, filename, &len); + img = purple_buddy_icons_set_account_icon(box->account, data, len); + purple_account_set_buddy_icon_path(box->account, filename); + + purple_account_set_bool(box->account, "use-global-buddyicon", (filename != NULL)); } } } } - pidgin_status_box_set_buddy_icon(box, filename); + + pidgin_status_box_set_buddy_icon(box, img); } static void @@ -1996,6 +2014,17 @@ } static void +pixbuf_size_prepared_cb(GdkPixbufLoader *loader, int width, int height, gpointer data) +{ +#if GTK_CHECK_VERSION(2,2,0) + int w, h; + GtkIconSize icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MEDIUM); + gtk_icon_size_lookup(icon_size, &w, &h); + gdk_pixbuf_loader_set_size(loader, w, h); +#endif +} + +static void pidgin_status_box_redisplay_buddy_icon(PidginStatusBox *status_box) { @@ -2010,10 +2039,15 @@ status_box->buddy_icon = NULL; status_box->buddy_icon_hover = NULL; - if ((status_box->buddy_icon_path != NULL) && - (*status_box->buddy_icon_path != '\0')) - status_box->buddy_icon = gdk_pixbuf_new_from_file_at_scale(status_box->buddy_icon_path, - status_box->icon_size, status_box->icon_size, FALSE, NULL); + if (status_box->buddy_icon_img != NULL) + { + GdkPixbufLoader *loader = gdk_pixbuf_loader_new(); + g_signal_connect(G_OBJECT(loader), "size-prepared", G_CALLBACK(pixbuf_size_prepared_cb), NULL); + gdk_pixbuf_loader_write(loader, purple_imgstore_get_data(status_box->buddy_icon_img), + purple_imgstore_get_size(status_box->buddy_icon_img), NULL); + gdk_pixbuf_loader_close(loader, NULL); + status_box->buddy_icon = gdk_pixbuf_loader_get_pixbuf(loader); + } if (status_box->buddy_icon == NULL) { @@ -2025,7 +2059,7 @@ } if (status_box->buddy_icon != NULL) { - status_box->icon_opaque = pidgin_gdk_pixbuf_is_opaque(status_box->buddy_icon); + status_box->icon_opaque = pidgin_gdk_pixbuf_is_opaque(status_box->buddy_icon); gtk_image_set_from_pixbuf(GTK_IMAGE(status_box->icon), status_box->buddy_icon); status_box->buddy_icon_hover = gdk_pixbuf_copy(status_box->buddy_icon); do_colorshift(status_box->buddy_icon_hover, status_box->buddy_icon_hover, 32); @@ -2034,20 +2068,14 @@ } void -pidgin_status_box_set_buddy_icon(PidginStatusBox *status_box, const char *filename) +pidgin_status_box_set_buddy_icon(PidginStatusBox *status_box, PurpleStoredImage *img) { - g_free(status_box->buddy_icon_path); - status_box->buddy_icon_path = g_strdup(filename); + purple_imgstore_unref(status_box->buddy_icon_img); + status_box->buddy_icon_img = purple_imgstore_ref(img); pidgin_status_box_redisplay_buddy_icon(status_box); } -const char* -pidgin_status_box_get_buddy_icon(PidginStatusBox *box) -{ - return box->buddy_icon_path; -} - void pidgin_status_box_pulse_connecting(PidginStatusBox *status_box) {
--- a/pidgin/gtkstatusbox.h Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/gtkstatusbox.h Sat Apr 28 03:53:00 2007 +0000 @@ -30,6 +30,7 @@ #include <gtk/gtk.h> #include "gtkimhtml.h" #include "account.h" +#include "imgstore.h" #include "savedstatuses.h" #include "status.h" #include <gtk/gtktreemodel.h> @@ -89,7 +90,7 @@ GtkWidget *vbox, *sw; GtkWidget *imhtml; - char *buddy_icon_path; + PurpleStoredImage *buddy_icon_img; GdkPixbuf *buddy_icon; GdkPixbuf *buddy_icon_hover; GtkWidget *buddy_icon_sel; @@ -176,10 +177,7 @@ pidgin_status_box_pulse_connecting(PidginStatusBox *status_box); void -pidgin_status_box_set_buddy_icon(PidginStatusBox *status_box, const char *filename); - -const char * -pidgin_status_box_get_buddy_icon(PidginStatusBox *status_box); +pidgin_status_box_set_buddy_icon(PidginStatusBox *status_box, PurpleStoredImage *img); char *pidgin_status_box_get_message(PidginStatusBox *status_box);
--- a/pidgin/gtkutils.c Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/gtkutils.c Sat Apr 28 03:53:00 2007 +0000 @@ -78,12 +78,12 @@ } static GtkIMHtmlFuncs gtkimhtml_cbs = { - (GtkIMHtmlGetImageFunc)purple_imgstore_get, + (GtkIMHtmlGetImageFunc)purple_imgstore_find_by_id, (GtkIMHtmlGetImageDataFunc)purple_imgstore_get_data, (GtkIMHtmlGetImageSizeFunc)purple_imgstore_get_size, (GtkIMHtmlGetImageFilenameFunc)purple_imgstore_get_filename, - purple_imgstore_ref, - purple_imgstore_unref, + purple_imgstore_ref_by_id, + purple_imgstore_unref_by_id, }; void @@ -1350,13 +1350,12 @@ return; } - id = purple_imgstore_add(filedata, size, data->filename); - g_free(filedata); + id = purple_imgstore_add_with_id(filedata, size, data->filename); gtk_text_buffer_get_iter_at_mark(GTK_IMHTML(gtkconv->entry)->text_buffer, &iter, gtk_text_buffer_get_insert(GTK_IMHTML(gtkconv->entry)->text_buffer)); gtk_imhtml_insert_image_at_iter(GTK_IMHTML(gtkconv->entry), id, &iter); - purple_imgstore_unref(id); + purple_imgstore_unref_by_id(id); break; } @@ -2418,15 +2417,14 @@ } #endif -char * -pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path) +gpointer +pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path, size_t *len) { PurplePluginProtocolInfo *prpl_info; #if GTK_CHECK_VERSION(2,2,0) char **prpl_formats; int width, height; char **pixbuf_formats = NULL; - struct stat st; GdkPixbufFormat *format; GdkPixbuf *pixbuf; #if !GTK_CHECK_VERSION(2,4,0) @@ -2435,28 +2433,11 @@ #endif gchar *contents; gsize length; - const char *dirname; - char *random; - char *filename; prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); g_return_val_if_fail(prpl_info->icon_spec.format != NULL, NULL); - dirname = purple_buddy_icons_get_cache_dir(); - if (!g_file_test(dirname, G_FILE_TEST_IS_DIR)) { - purple_debug_info("buddyicon", "Creating icon cache directory.\n"); - - if (g_mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR) < 0) { - purple_debug_error("buddyicon", - "Unable to create directory %s: %s\n", - dirname, strerror(errno)); - return NULL; - } - } - - random = g_strdup_printf("%x", g_random_int()); - filename = g_build_filename(dirname, random, NULL); #if GTK_CHECK_VERSION(2,2,0) #if GTK_CHECK_VERSION(2,4,0) @@ -2487,47 +2468,21 @@ prpl_info->icon_spec.max_height >= height))) /* The icon is the correct size */ #endif { - FILE *image; - #if GTK_CHECK_VERSION(2,2,0) g_strfreev(prpl_formats); g_strfreev(pixbuf_formats); #endif - - /* We don't need to scale the image, so copy it to the cache folder verbatim */ + /* We don't need to scale the image. */ contents = NULL; - if (!g_file_get_contents(path, &contents, &length, NULL) || - (image = g_fopen(filename, "wb")) == NULL) + if (!g_file_get_contents(path, &contents, &length, NULL)) { - g_free(random); - g_free(filename); g_free(contents); #if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0) - g_object_unref(G_OBJECT(pixbuf)); + g_object_unref(G_OBJECT(pixbuf)); #endif return NULL; } - - if (fwrite(contents, 1, length, image) != length) - { - fclose(image); - g_unlink(filename); - - g_free(random); - g_free(filename); - g_free(contents); -#if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0) - g_object_unref(G_OBJECT(pixbuf)); -#endif - return NULL; - } - fclose(image); - g_free(contents); - -#if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0) - g_object_unref(G_OBJECT(pixbuf)); -#endif } #if GTK_CHECK_VERSION(2,2,0) else @@ -2536,6 +2491,7 @@ GError *error = NULL; GdkPixbuf *scale; gboolean success = FALSE; + char *filename = NULL; g_strfreev(pixbuf_formats); @@ -2543,8 +2499,6 @@ if (error) { purple_debug_error("buddyicon", "Could not open icon for conversion: %s\n", error->message); g_error_free(error); - g_free(random); - g_free(filename); g_strfreev(prpl_formats); return NULL; } @@ -2567,6 +2521,17 @@ } for (i = 0; prpl_formats[i]; i++) { + FILE *fp; + + g_free(filename); + fp = purple_mkstemp(&filename, TRUE); + if (!fp) + { + g_free(filename); + return NULL; + } + fclose(fp); + purple_debug_info("buddyicon", "Converting buddy icon to %s as %s\n", prpl_formats[i], filename); /* The "compression" param wasn't supported until gdk-pixbuf 2.8. * Using it in previous versions causes the save to fail (and an assert message). */ @@ -2595,29 +2560,33 @@ g_object_unref(G_OBJECT(pixbuf)); if (!success) { purple_debug_error("buddyicon", "Could not convert icon to usable format.\n"); - g_free(random); + return NULL; + } + + contents = NULL; + if (!g_file_get_contents(filename, &contents, &length, NULL)) + { + purple_debug_error("buddyicon", + "Could not read '%s', which we just wrote to disk.\n", + filename); + + g_free(contents); g_free(filename); return NULL; } + + g_unlink(filename); + g_free(filename); } - if (g_stat(filename, &st) != 0) { - purple_debug_error("buddyicon", - "Could not stat '%s', which we just wrote to disk: %s\n", - filename, strerror(errno)); - g_free(random); - g_free(filename); - return NULL; - } - - /* Check the file size */ + /* Check the image size */ /* * TODO: If the file is too big, it would be cool if we checked if * the prpl supported jpeg, and then we could convert to that * and use a lower quality setting. */ if ((prpl_info->icon_spec.max_filesize != 0) && - (st.st_size > prpl_info->icon_spec.max_filesize)) + (length > prpl_info->icon_spec.max_filesize)) { gchar *tmp; tmp = g_strdup_printf(_("The file '%s' is too large for %s. Please try a smaller image.\n"), @@ -2627,16 +2596,15 @@ purple_debug_info("buddyicon", "'%s' was converted to an image which is %" G_GSIZE_FORMAT " bytes, but the maximum icon size for %s is %" G_GSIZE_FORMAT - " bytes\n", path, st.st_size, plugin->info->name, + " bytes\n", path, length, plugin->info->name, prpl_info->icon_spec.max_filesize); g_free(tmp); - g_free(random); - g_free(filename); return NULL; } - g_free(filename); - return random; + if (len) + *len = length; + return contents; #else /* * The chosen icon wasn't the right size, and we're using @@ -2789,10 +2757,10 @@ void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename) { - PurpleConversation *conv; PurpleBuddy *buddy; - PurpleBlistNode *node; - char *path = NULL; + PurpleContact *contact; + gpointer data = NULL; + size_t len = 0; buddy = purple_find_buddy(account, who); if (!buddy) { @@ -2800,35 +2768,20 @@ return; } - node = (PurpleBlistNode*)purple_buddy_get_contact(buddy); - path = (char*)purple_blist_node_get_string(node, "custom_buddy_icon"); - if (path) { - struct stat st; - if (g_stat(path, &st) == 0) - g_unlink(path); - path = NULL; - } + contact = purple_buddy_get_contact(buddy); if (filename) { - char *newfile; - - newfile = pidgin_convert_buddy_icon(purple_find_prpl(purple_account_get_protocol_id(account)), - filename); - path = purple_buddy_icons_get_full_path(newfile); - g_free(newfile); + const char *prpl_id = purple_account_get_protocol_id(account); + PurplePlugin *prpl = purple_find_prpl(prpl_id); + + data = pidgin_convert_buddy_icon(prpl, filename, &len); + + /* We don't want to delete the old icon if the new one didn't load. */ + if (data == NULL) + return; } - purple_blist_node_set_string(node, "custom_buddy_icon", path); - g_free(path); - - /* Update the conversation */ - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, account); - if (conv) - purple_conversation_update(conv, PURPLE_CONV_UPDATE_ICON); - - /* Update the buddylist */ - if (buddy) - purple_blist_update_buddy_icon(buddy); + purple_buddy_icons_set_custom_icon(contact, data, len); } char *pidgin_make_pretty_arrows(const char *str)
--- a/pidgin/gtkutils.h Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/gtkutils.h Sat Apr 28 03:53:00 2007 +0000 @@ -445,11 +445,13 @@ /** * Converts a buddy icon to the required size and format * - * @param plugin The prpl to conver the icon - * @param path The path of a buddy icon to convert - * @return The name of a new buddy icon + * @param plugin The prpl to convert the icon + * @param path The path of a file to convert + * @param len If not @c NULL, the length of the returned data will be set here. + * + * @return The converted image data, or @c NULL if an error occurred. */ -char* pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path); +gpointer pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path, size_t *len); #if !GTK_CHECK_VERSION(2,6,0) /**
--- a/pidgin/pixmaps/emblems/16/scalable/secure.svg Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/pixmaps/emblems/16/scalable/secure.svg Sat Apr 28 03:53:00 2007 +0000 @@ -7,96 +7,81 @@ xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/s odipodi-0.dtd" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="16" - height="16" - id="svg2" + width="16px" + height="16px" + id="svg4220" sodipodi:version="0.32" - inkscape:version="0.43" - version="1.0" - sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/emblems/scalable" + inkscape:version="0.44.1" + sodipodi:docbase="/home/hbons/code/pidgin-mtn/pidgin/pixmaps/emblems/16/scalable" sodipodi:docname="secure.svg" - inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/emblems/secure.png" + inkscape:export-filename="/home/hbons/code/pidgin-mtn/pidgin/pixmaps/emblems/16/secure.png" inkscape:export-xdpi="90" inkscape:export-ydpi="90"> <defs - id="defs4"> + id="defs4222"> <linearGradient inkscape:collect="always" - id="linearGradient2193"> - <stop - style="stop-color:#555753;stop-opacity:1;" - offset="0" - id="stop2195" /> - <stop - style="stop-color:#555753;stop-opacity:0;" - offset="1" - id="stop2197" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient2351"> + id="linearGradient5170"> <stop style="stop-color:#eeeeec;stop-opacity:1;" offset="0" - id="stop2353" /> + id="stop5172" /> <stop style="stop-color:#eeeeec;stop-opacity:0;" offset="1" - id="stop2355" /> + id="stop5174" /> + </linearGradient> + <linearGradient + id="linearGradient5160"> + <stop + style="stop-color:#c4a000;stop-opacity:1;" + offset="0" + id="stop5162" /> + <stop + style="stop-color:#c4a000;stop-opacity:0;" + offset="1" + id="stop5164" /> </linearGradient> <linearGradient inkscape:collect="always" - id="linearGradient2343"> + id="linearGradient5127"> <stop - style="stop-color:#babdb6;stop-opacity:1;" + style="stop-color:white;stop-opacity:1;" offset="0" - id="stop2345" /> + id="stop5129" /> <stop - style="stop-color:#babdb6;stop-opacity:0;" + style="stop-color:white;stop-opacity:0;" offset="1" - id="stop2347" /> - </linearGradient> - <linearGradient - id="linearGradient2276"> - <stop - style="stop-color:#f57900;stop-opacity:1;" - offset="0" - id="stop2278" /> - <stop - style="stop-color:#fcaf3e;stop-opacity:1;" - offset="1" - id="stop2280" /> + id="stop5131" /> </linearGradient> <linearGradient inkscape:collect="always" - xlink:href="#linearGradient2343" - id="linearGradient2349" - x1="12.515625" - y1="8.7261219" - x2="12.515625" - y2="0.68458056" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.661626,0,0,0.669831,0.220067,-0.15079)" /> + xlink:href="#linearGradient5127" + id="linearGradient5133" + x1="-8.5730524" + y1="8.1949167" + x2="-8.5730524" + y2="14.091002" + gradientUnits="userSpaceOnUse" /> <linearGradient inkscape:collect="always" - xlink:href="#linearGradient2351" - id="linearGradient2357" - x1="12.488563" - y1="5.8544211" - x2="12.488563" - y2="19.066195" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.571617,0,0,0.664095,1.361509,-0.130758)" /> + xlink:href="#linearGradient5160" + id="linearGradient5166" + x1="-5.2575259" + y1="14.311456" + x2="-10.187596" + y2="11.560035" + gradientUnits="userSpaceOnUse" /> <linearGradient inkscape:collect="always" - xlink:href="#linearGradient2193" - id="linearGradient2199" - x1="8.5" - y1="11.038469" - x2="8.5" - y2="13" + xlink:href="#linearGradient5170" + id="linearGradient5176" + x1="-7.5400991" + y1="0.79740471" + x2="-7.5400991" + y2="4.7783289" gradientUnits="userSpaceOnUse" /> </defs> <sodipodi:namedview @@ -106,20 +91,21 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="39.000666" - inkscape:cx="12.56383" - inkscape:cy="9.2861054" - inkscape:document-units="px" + inkscape:zoom="22.197802" + inkscape:cx="8.5405941" + inkscape:cy="8.0965274" inkscape:current-layer="layer1" showgrid="true" - fill="#eeeeec" - inkscape:window-width="1268" - inkscape:window-height="972" - inkscape:window-x="6" - inkscape:window-y="21" - inkscape:grid-points="true" /> + inkscape:grid-bbox="true" + inkscape:document-units="px" + showguides="true" + inkscape:guide-bbox="true" + inkscape:window-width="872" + inkscape:window-height="625" + inkscape:window-x="47" + inkscape:window-y="150" /> <metadata - id="metadata7"> + id="metadata4225"> <rdf:RDF> <cc:Work rdf:about=""> @@ -130,47 +116,46 @@ </rdf:RDF> </metadata> <g + id="layer1" inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1"> - <path - style="fill:url(#linearGradient2349);fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:0.99999934;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="M 6.1333463,1.5028569 C 5.2074147,1.597488 4.4999578,2.402644 4.4999578,3.3658261 L 4.4999578,7.656935 C 4.4999578,8.6843293 5.3046208,9.4989715 6.3194286,9.4989715 L 10.661348,9.4989715 C 11.676156,9.4989715 12.501495,8.6843293 12.501495,7.656935 L 12.501495,3.3658261 C 12.501495,2.3384316 11.676156,1.5028569 10.661348,1.5028569 L 6.3194286,1.5028569 C 6.256003,1.5028569 6.1950751,1.496548 6.1333463,1.5028569 z M 7.2911913,3.5332839 C 7.3292999,3.5284078 7.3757891,3.5332839 7.4152465,3.5332839 L 9.5862055,3.5332839 C 9.8150574,3.5332839 10.026054,3.623525 10.185805,3.7635385 C 10.201979,3.7784151 10.232757,3.8103245 10.247831,3.8263353 C 10.272321,3.8536261 10.309391,3.9008527 10.330534,3.9309964 C 10.428638,4.0782548 10.49594,4.2625583 10.49594,4.4543024 L 10.49594,6.5893908 C 10.49594,7.1007088 10.091261,7.5104093 9.5862055,7.5104093 L 7.4152465,7.5104093 C 7.1232614,7.5104093 6.8582226,7.3694453 6.691593,7.1545613 C 6.5780448,7.000656 6.5055108,6.7971136 6.5055108,6.5893908 L 6.5055108,4.4543024 C 6.5055108,4.2625583 6.5728119,4.0782548 6.6709171,3.9309964 C 6.7301189,3.8465936 6.8149822,3.7606775 6.8983509,3.7007419 C 7.0135024,3.6221117 7.1463786,3.5518132 7.2911913,3.5332839 z " - id="rect1437" /> + inkscape:groupmode="layer"> <rect - style="fill:#edd400;fill-opacity:1;fill-rule:evenodd;stroke:#c4a000;stroke-width:0.97247171;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="rect1435" - width="10.030794" - height="8.0158854" - x="3.4845238" - y="6.4937477" - ry="2.1756756" - rx="2.1756771" /> + style="opacity:1;fill:#fce94f;fill-opacity:1;stroke:#c4a000;stroke-width:0.52907252;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect4238" + width="5.7297029" + height="6.3509903" + x="-6" + y="6" + transform="matrix(2.268879,0,0,1.574557,15.11327,-3.947338)" + rx="0.44198585" + ry="0.60082906" /> <rect - style="opacity:0.4;fill:url(#linearGradient2357);fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00000024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="rect2312" - width="8.0056992" - height="5.982585" - x="4.4973445" - y="7.5063467" - ry="1.1603612" - rx="1.1603615" /> + style="opacity:1;fill:url(#linearGradient5166);fill-opacity:1.0;stroke:url(#linearGradient5133);stroke-width:0.50402278;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect5125" + width="5.6391087" + height="2.9732673" + x="-11" + y="10.458911" + transform="matrix(1.950662,0,0,2.017983,23.95729,-12.6059)" /> + <rect + style="opacity:0.56331877;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect5156" + width="5.1252475" + height="2.6569307" + x="-14" + y="6" + transform="matrix(2.34135,0,0,0.752748,34.7789,1.48351)" /> <path - sodipodi:type="arc" - style="fill:#555753;fill-opacity:1;stroke:none;stroke-width:0.86272454;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path2325" - sodipodi:cx="12.265541" - sodipodi:cy="14" - sodipodi:rx="0.73445857" - sodipodi:ry="1" - d="M 13 14 A 0.73445857 1 0 1 1 11.531083,14 A 0.73445857 1 0 1 1 13 14 z" - transform="matrix(2.042319,0,0,1.5,-16.55015,-11.5)" /> - <rect - style="fill:url(#linearGradient2199);fill-opacity:1.0;stroke:none;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="rect2333" - width="1" - height="3" - x="8" - y="10" /> + transform="translate(15,0)" + style="fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1" + d="M -9.4188119,0.5 C -10.500938,0.5 -11.5,1.4812151 -11.5,2.4460396 L -11.5,7.5 L -9.5,7.5 L -9.4549505,4.0089109 C -9.4549505,2.4726571 -9.4588865,2.5 -8.1034653,2.5 L -5.9866337,2.5 C -4.4993176,2.5 -4.5,2.5177763 -4.5,4.0539604 L -4.5,7.5 L -2.5,7.5 L -2.5,2.4910891 C -2.5,1.6080661 -3.5388679,0.54504951 -4.4460396,0.54504951 L -9.4188119,0.5 z " + id="path5168" + sodipodi:nodetypes="ccccccccccccc" /> + <path + transform="translate(15,0)" + style="fill:url(#linearGradient5176);fill-opacity:1.0;stroke:#888a85;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1" + d="M -9.4188119,0.5 C -10.500938,0.5 -11.5,1.4812151 -11.5,2.4460396 L -11.5,6.4638614 C -11.5,7.8729886 -9.5,7.6557806 -9.5,6.5089109 L -9.4549505,4.0089109 C -9.4549505,2.4726571 -9.4588865,2.5 -8.1034653,2.5 L -5.9866337,2.5 C -4.4993176,2.5 -4.5,2.5177763 -4.5,4.0539604 L -4.5,6.5539604 C -4.5450495,7.8163699 -2.5,7.594009 -2.5,6.5539604 L -2.5,2.4910891 C -2.5,1.6080661 -3.5388679,0.54504951 -4.4460396,0.54504951 L -9.4188119,0.5 z " + id="rect5149" + sodipodi:nodetypes="ccccccccccccc" /> </g> </svg>
--- a/pidgin/pixmaps/icons/32/scalable/pidgin.svg Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/pixmaps/icons/32/scalable/pidgin.svg Sat Apr 28 03:53:00 2007 +0000 @@ -14,9 +14,9 @@ id="svg4345" sodipodi:version="0.32" inkscape:version="0.44.1" - sodipodi:docbase="/home/hbons/Desktop/icons/32/scalable" + sodipodi:docbase="/home/hbons/code/pidgin-mtn/pidgin/pixmaps/icons/32/scalable" sodipodi:docname="pidgin.svg" - inkscape:export-filename="/home/hbons/Desktop/pidgin32.png" + inkscape:export-filename="/home/hbons/code/pidgin-mtn/pidgin/pixmaps/icons/32/pidgin.png" inkscape:export-xdpi="90" inkscape:export-ydpi="90" version="1.0"> @@ -231,7 +231,7 @@ inkscape:pageshadow="2" inkscape:zoom="21.220032" inkscape:cx="25.558911" - inkscape:cy="16.938593" + inkscape:cy="16.91503" inkscape:current-layer="layer1" showgrid="true" inkscape:grid-bbox="true" @@ -398,12 +398,6 @@ id="rect5189" sodipodi:nodetypes="cccc" /> <path - transform="matrix(0.798987,0,0,0.495994,22.79842,2.215302)" - style="fill:url(#linearGradient6569);fill-opacity:1;stroke:none;stroke-width:1.0283047;stroke-miterlimit:4;stroke-opacity:1" - d="M -0.99929609,42.004237 C 3.5188333,45.348102 4.1278823,38.950282 4.9828709,38.950282 C 5.8260957,38.950282 6.1724645,45.375511 10.014606,42.007796 C 9.2074596,43.955072 6.7265914,47.014858 5.6807127,47.014858 C 4.6230593,47.014858 0.31231911,44.880662 -0.99929609,42.004237 z " - id="path6561" - sodipodi:nodetypes="czczc" /> - <path transform="matrix(0.798987,0,0,0.495994,8.99846,-1.319104)" style="fill:url(#linearGradient6823);fill-opacity:1.0;stroke:none;stroke-width:1.0283047;stroke-miterlimit:4;stroke-opacity:1" d="M -0.99929609,42.004237 C 2.9290204,42.117701 4.1278823,38.950282 4.9828709,38.950282 C 5.8260957,38.950282 7.1161651,42.240122 10.014606,42.007796 C 9.2074596,43.955072 6.7265914,47.014858 5.6807127,47.014858 C 4.6230593,47.014858 0.31231911,44.880662 -0.99929609,42.004237 z "
--- a/pidgin/pixmaps/icons/48/scalable/Makefile.am Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/pixmaps/icons/48/scalable/Makefile.am Sat Apr 28 03:53:00 2007 +0000 @@ -1,1 +1,6 @@ -EXTRA_DIST = pidgin.svg +EXTRA_DIST = pidgin.svg + +pidginiconspixdir = $(datadir)/icons/hicolor/scalable/apps + +pidginiconspix_DATA = $(EXTRA_DIST) +
--- a/pidgin/pixmaps/icons/Makefile.mingw Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/pixmaps/icons/Makefile.mingw Sat Apr 28 03:53:00 2007 +0000 @@ -7,8 +7,11 @@ include ./Makefile.am install: + +install_real: if test '$(SUBDIRS)'; then \ list='$(SUBDIRS)'; for subdir in $$list; do \ $(MAKE) -C $$subdir -f Makefile.mingw install || exit 1; \ done; \ fi; +
--- a/pidgin/pixmaps/status/16/Makefile.mingw Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/pixmaps/status/16/Makefile.mingw Sat Apr 28 03:53:00 2007 +0000 @@ -18,3 +18,5 @@ cp $(pidginstatuspix_DATA) $(pidginstatuspixdir); \ fi; + $(MAKE) -C rtl -f Makefile.mingw install || exit 1; \ +
--- a/pidgin/pixmaps/status/16/rtl/Makefile.am Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/pixmaps/status/16/rtl/Makefile.am Sat Apr 28 03:53:00 2007 +0000 @@ -1,4 +1,4 @@ -EXTRA_DIST = chat.png extended-away.png +EXTRA_DIST = extended-away.png pidginstatuspixdir = $(datadir)/pixmaps/pidgin/status/16/rtl
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/16/rtl/Makefile.mingw Sat Apr 28 03:53:00 2007 +0000 @@ -0,0 +1,20 @@ +# +# Makefile.mingw +# +# Description: Makefile for win32 (mingw) version of Pidgin pixmaps +# + +PIDGIN_TREE_TOP := ../../../../.. +include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak + +datadir = $(PIDGIN_INSTALL_DIR) +include ./Makefile.am + +.PHONY: install + +install: + if test '$(pidginstatuspix_DATA)'; then \ + mkdir -p $(pidginstatuspixdir); \ + cp $(pidginstatuspix_DATA) $(pidginstatuspixdir); \ + fi; +
--- a/pidgin/pixmaps/status/22/Makefile.mingw Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/pixmaps/status/22/Makefile.mingw Sat Apr 28 03:53:00 2007 +0000 @@ -18,3 +18,5 @@ cp $(pidginstatuspix_DATA) $(pidginstatuspixdir); \ fi; + $(MAKE) -C rtl -f Makefile.mingw install || exit 1; \ +
--- a/pidgin/pixmaps/status/22/rtl/Makefile.am Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/pixmaps/status/22/rtl/Makefile.am Sat Apr 28 03:53:00 2007 +0000 @@ -1,4 +1,4 @@ -EXTRA_DIST = chat.png extended-away.png +EXTRA_DIST = extended-away.png pidginstatuspixdir = $(datadir)/pixmaps/pidgin/status/22/rtl
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/22/rtl/Makefile.mingw Sat Apr 28 03:53:00 2007 +0000 @@ -0,0 +1,20 @@ +# +# Makefile.mingw +# +# Description: Makefile for win32 (mingw) version of Pidgin pixmaps +# + +PIDGIN_TREE_TOP := ../../../../.. +include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak + +datadir = $(PIDGIN_INSTALL_DIR) +include ./Makefile.am + +.PHONY: install + +install: + if test '$(pidginstatuspix_DATA)'; then \ + mkdir -p $(pidginstatuspixdir); \ + cp $(pidginstatuspix_DATA) $(pidginstatuspixdir); \ + fi; +
--- a/pidgin/pixmaps/status/32/Makefile.mingw Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/pixmaps/status/32/Makefile.mingw Sat Apr 28 03:53:00 2007 +0000 @@ -18,3 +18,5 @@ cp $(pidginstatuspix_DATA) $(pidginstatuspixdir); \ fi; + $(MAKE) -C rtl -f Makefile.mingw install || exit 1; \ +
--- a/pidgin/pixmaps/status/32/rtl/Makefile.am Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/pixmaps/status/32/rtl/Makefile.am Sat Apr 28 03:53:00 2007 +0000 @@ -1,4 +1,4 @@ -EXTRA_DIST = chat.png extended-away.png +EXTRA_DIST = extended-away.png pidginstatuspixdir = $(datadir)/pixmaps/pidgin/status/32/rtl
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/32/rtl/Makefile.mingw Sat Apr 28 03:53:00 2007 +0000 @@ -0,0 +1,20 @@ +# +# Makefile.mingw +# +# Description: Makefile for win32 (mingw) version of Pidgin pixmaps +# + +PIDGIN_TREE_TOP := ../../../../.. +include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak + +datadir = $(PIDGIN_INSTALL_DIR) +include ./Makefile.am + +.PHONY: install + +install: + if test '$(pidginstatuspix_DATA)'; then \ + mkdir -p $(pidginstatuspixdir); \ + cp $(pidginstatuspix_DATA) $(pidginstatuspixdir); \ + fi; +
--- a/pidgin/pixmaps/status/48/Makefile.mingw Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/pixmaps/status/48/Makefile.mingw Sat Apr 28 03:53:00 2007 +0000 @@ -18,3 +18,5 @@ cp $(pidginstatuspix_DATA) $(pidginstatuspixdir); \ fi; + $(MAKE) -C rtl -f Makefile.mingw install || exit 1; \ +
--- a/pidgin/pixmaps/status/48/rtl/Makefile.am Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/pixmaps/status/48/rtl/Makefile.am Sat Apr 28 03:53:00 2007 +0000 @@ -1,4 +1,4 @@ -EXTRA_DIST = chat.png extended-away.png +EXTRA_DIST = extended-away.png pidginstatuspixdir = $(datadir)/pixmaps/pidgin/status/48/rtl
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pixmaps/status/48/rtl/Makefile.mingw Sat Apr 28 03:53:00 2007 +0000 @@ -0,0 +1,20 @@ +# +# Makefile.mingw +# +# Description: Makefile for win32 (mingw) version of Pidgin pixmaps +# + +PIDGIN_TREE_TOP := ../../../../.. +include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak + +datadir = $(PIDGIN_INSTALL_DIR) +include ./Makefile.am + +.PHONY: install + +install: + if test '$(pidginstatuspix_DATA)'; then \ + mkdir -p $(pidginstatuspixdir); \ + cp $(pidginstatuspix_DATA) $(pidginstatuspixdir); \ + fi; +
--- a/pidgin/pixmaps/status/Makefile.am Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/pixmaps/status/Makefile.am Sat Apr 28 03:53:00 2007 +0000 @@ -3,7 +3,11 @@ EXTRA_DIST = \ Makefile.mingw \ 16/Makefile.mingw \ + 16/rtl/Makefile.mingw \ 22/Makefile.mingw \ + 22/rtl/Makefile.mingw \ 32/Makefile.mingw \ - 48/Makefile.mingw + 32/rtl/Makefile.mingw \ + 48/Makefile.mingw \ + 48/rtl/Makefile.mingw
--- a/pidgin/plugins/perl/Makefile.am Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/plugins/perl/Makefile.am Sat Apr 28 03:53:00 2007 +0000 @@ -24,10 +24,10 @@ common/GtkSound.xs \ common/GtkStatusBox.xs \ common/GtkThemes.xs \ - common/GtkUI.pm \ - common/GtkUI.xs \ common/GtkUtils.xs \ common/Makefile.PL.in \ + common/Pidgin.pm \ + common/Pidgin.xs \ common/gtkmodule.h \ common/typemap
--- a/pidgin/plugins/perl/common/GtkSession.xs Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/plugins/perl/common/GtkSession.xs Sat Apr 28 03:53:00 2007 +0000 @@ -1,6 +1,6 @@ #include "gtkmodule.h" -MODULE = Purple::GtkUI::Session PACKAGE = Purple::GtkUI::Session PREFIX = gaim_gtk_session_ +MODULE = Pidgin::Session PACKAGE = Pidgin::Session PREFIX = pidgin_session_ PROTOTYPES: ENABLE void
--- a/pidgin/plugins/perl/common/GtkStatusBox.xs Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/plugins/perl/common/GtkStatusBox.xs Sat Apr 28 03:53:00 2007 +0000 @@ -37,13 +37,9 @@ Pidgin::StatusBox status_box void -pidgin_status_box_set_buddy_icon(status_box, filename) +pidgin_status_box_set_buddy_icon(status_box, img) Pidgin::StatusBox status_box - const char * filename - -const char * -pidgin_status_box_get_buddy_icon(status_box) - Pidgin::StatusBox status_box + Purple::StoredImage img gchar_own * pidgin_status_box_get_message(status_box)
--- a/pidgin/plugins/perl/common/GtkUI.pm Thu Apr 26 21:15:41 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -package Purple::GtkUI; - -use 5.008; -use strict; -use warnings; -use Carp; - -our $VERSION = '0.01'; - -use Purple; - -require XSLoader; -XSLoader::load('Purple::GtkUI', $VERSION); - -1; -__END__ - -=head1 NAME - -Purple::GtkUI - Perl extension for the Pidgin instant messenger. - -=head1 SYNOPSIS - - use Purple::GtkUI; - -=head1 ABSTRACT - - This module provides the interface for using perl scripts as plugins in - Pidgin, with access to the Pidgin Gtk interface functions. - -=head1 DESCRIPTION - -This module provides the interface for using perl scripts as plugins in Pidgin, -with access to the Pidgin Gtk interface functions. With this, developers can -write perl scripts that can be loaded in Pidgin as plugins. The script can -interact with IMs, chats, accounts, the buddy list, pidgin signals, and more. - -The API for the perl interface is very similar to that of the Pidgin C API, -which can be viewed at http://developer.pidgin.im/doxygen/ or in the header files -in the Pidgin source tree. - -=head1 FUNCTIONS - -=over - -=back - -=head1 SEE ALSO -Pidgin C API documentation - http://developer.pidgin.im/doxygen/ - -The Pidgin perl module. - -Pidgin website - http://pidgin.im/ - -=head1 AUTHOR - -Etan Reisner, E<lt>deryni@gmail.comE<gt> - -=head1 COPYRIGHT AND LICENSE - -Copyright 2006 by Etan Reisner
--- a/pidgin/plugins/perl/common/GtkUI.xs Thu Apr 26 21:15:41 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -#include "gtkmodule.h" - -/* Prototypes for the BOOT section below. */ -PURPLE_PERL_BOOT_PROTO(GtkUI__Account); -PURPLE_PERL_BOOT_PROTO(GtkUI__BuddyList); -PURPLE_PERL_BOOT_PROTO(GtkUI__Connection); -PURPLE_PERL_BOOT_PROTO(GtkUI__Conversation); -PURPLE_PERL_BOOT_PROTO(GtkUI__Conversation__Window); -PURPLE_PERL_BOOT_PROTO(GtkUI__Debug); -PURPLE_PERL_BOOT_PROTO(GtkUI__Dialogs); -PURPLE_PERL_BOOT_PROTO(GtkUI__IMHtml); -PURPLE_PERL_BOOT_PROTO(GtkUI__IMHtmlToolbar); -PURPLE_PERL_BOOT_PROTO(GtkUI__Log); -PURPLE_PERL_BOOT_PROTO(GtkUI__MenuTray); -PURPLE_PERL_BOOT_PROTO(GtkUI__Plugin); -PURPLE_PERL_BOOT_PROTO(GtkUI__PluginPref); -PURPLE_PERL_BOOT_PROTO(GtkUI__Pounce); -PURPLE_PERL_BOOT_PROTO(GtkUI__Prefs); -PURPLE_PERL_BOOT_PROTO(GtkUI__Privacy); -PURPLE_PERL_BOOT_PROTO(GtkUI__Roomlist); -PURPLE_PERL_BOOT_PROTO(GtkUI__Status); -#ifndef _WIN32 -PURPLE_PERL_BOOT_PROTO(GtkUI__Session); -#endif -PURPLE_PERL_BOOT_PROTO(GtkUI__Sound); -PURPLE_PERL_BOOT_PROTO(GtkUI__StatusBox); -PURPLE_PERL_BOOT_PROTO(GtkUI__Themes); -PURPLE_PERL_BOOT_PROTO(GtkUI__Utils); -PURPLE_PERL_BOOT_PROTO(GtkUI__Xfer); - -MODULE = Purple::GtkUI PACKAGE = Purple::GtkUI PREFIX = pidgin_ -PROTOTYPES: ENABLE - -BOOT: - PURPLE_PERL_BOOT(GtkUI__Account); - PURPLE_PERL_BOOT(GtkUI__BuddyList); - PURPLE_PERL_BOOT(GtkUI__Connection); - PURPLE_PERL_BOOT(GtkUI__Conversation); - PURPLE_PERL_BOOT(GtkUI__Conversation__Window); - PURPLE_PERL_BOOT(GtkUI__Debug); - PURPLE_PERL_BOOT(GtkUI__Dialogs); - PURPLE_PERL_BOOT(GtkUI__IMHtml); - PURPLE_PERL_BOOT(GtkUI__IMHtmlToolbar); - PURPLE_PERL_BOOT(GtkUI__Log); - PURPLE_PERL_BOOT(GtkUI__MenuTray); - PURPLE_PERL_BOOT(GtkUI__Plugin); - PURPLE_PERL_BOOT(GtkUI__PluginPref); - PURPLE_PERL_BOOT(GtkUI__Pounce); - PURPLE_PERL_BOOT(GtkUI__Prefs); - PURPLE_PERL_BOOT(GtkUI__Privacy); - PURPLE_PERL_BOOT(GtkUI__Roomlist); - PURPLE_PERL_BOOT(GtkUI__Status); -#ifndef _WIN32 - PURPLE_PERL_BOOT(GtkUI__Session); -#endif - PURPLE_PERL_BOOT(GtkUI__Sound); - PURPLE_PERL_BOOT(GtkUI__StatusBox); - PURPLE_PERL_BOOT(GtkUI__Themes); - PURPLE_PERL_BOOT(GtkUI__Utils); - PURPLE_PERL_BOOT(GtkUI__Xfer);
--- a/pidgin/plugins/perl/common/GtkUtils.xs Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/plugins/perl/common/GtkUtils.xs Sat Apr 28 03:53:00 2007 +0000 @@ -11,6 +11,7 @@ pidgin_load_accels() gchar_own * -pidgin_convert_buddy_icon(plugin, path) +pidgin_convert_buddy_icon(plugin, path, size) Purple::Plugin plugin const char * path + size_t *size
--- a/pidgin/plugins/perl/common/MANIFEST Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/plugins/perl/common/MANIFEST Sat Apr 28 03:53:00 2007 +0000 @@ -21,8 +21,8 @@ GtkSound.xs GtkStatusBox.xs GtkThemes.xs -GtkUI.pm -GtkUI.xs GtkUtils.xs MANIFEST +Pidgin.pm +Pidgin.xs typemap
--- a/pidgin/plugins/perl/common/Makefile.PL.in Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/plugins/perl/common/Makefile.PL.in Sat Apr 28 03:53:00 2007 +0000 @@ -1,20 +1,16 @@ use 5.006; use ExtUtils::MakeMaker; - +# See lib/ExtUtils/MakeMaker.pm for details of how to influence the contents +# of the Makefile that is written. WriteMakefile( - 'NAME' => 'Purple::GtkUI', - 'VERSION_FROM' => '@srcdir@/GtkUI.pm', # finds $VERSION + 'NAME' => 'Pidgin', + 'VERSION_FROM' => '@srcdir@/Pidgin.pm', # finds $VERSION ($] >= 5.005 ? ## Add these new keywords supported since 5.005 - ('ABSTRACT_FROM' => '@srcdir@/GtkUI.pm', # finds $ABSTRACT - 'AUTHOR' => 'Pidgin <http://pidgin.im/>') : ()), + ('ABSTRACT_FROM' => '@srcdir@/Pidgin.pm', # finds $ABSTRACT + 'AUTHOR' => 'Pidgin <http://pidgin.im/>') : ()), 'DEFINE' => '@DEBUG_CFLAGS@', 'INC' => '-I. -I@srcdir@ -I@top_srcdir@ -I@top_srcdir@/libpurple -I@top_srcdir@/pidgin @GTK_CFLAGS@', -# 'PREREQ_PM' => { 'Pidgin' => '@VERSION@'}, - # Do this because the MakeMaker Makefile is dumb, and on clean it moves - # Makefile to the default setting for MAKEFILE_OLD which is Makefile.old - # but this breaks running make clean more than once in a row. - 'MAKEFILE_OLD' => "Makefile", - 'OBJECT' => '$(O_FILES)', + 'OBJECT' => '$(O_FILES)', # link all the C files too 'TYPEMAPS' => ["@top_srcdir@/libpurple/plugins/perl/common/typemap"], # 'OPTIMIZE' => '-g', # For debugging. );
--- a/pidgin/plugins/perl/common/Makefile.mingw Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/plugins/perl/common/Makefile.mingw Sat Apr 28 03:53:00 2007 +0000 @@ -39,7 +39,7 @@ ## SOURCES, OBJECTS ## XS_FILES = \ - GtkUI.xs \ + Pidgin.xs \ GtkAccount.xs \ GtkBlist.xs \ GtkConn.xs \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/plugins/perl/common/Pidgin.pm Sat Apr 28 03:53:00 2007 +0000 @@ -0,0 +1,61 @@ +package Pidgin; + +use 5.008; +use strict; +use warnings; +use Carp; + +our $VERSION = '0.01'; + +use Purple; + +require XSLoader; +XSLoader::load('Pidgin', $VERSION); + +1; +__END__ + +=head1 NAME + +Pidgin - Perl extension for the Pidgin instant messenger. + +=head1 SYNOPSIS + + use Pidgin; + +=head1 ABSTRACT + + This module provides the interface for using perl scripts as plugins in + Pidgin, with access to the Pidgin Gtk interface functions. + +=head1 DESCRIPTION + +This module provides the interface for using perl scripts as plugins in Pidgin, +with access to the Pidgin Gtk interface functions. With this, developers can +write perl scripts that can be loaded in Pidgin as plugins. The script can +interact with IMs, chats, accounts, the buddy list, pidgin signals, and more. + +The API for the perl interface is very similar to that of the Pidgin C API, +which can be viewed at http://developer.pidgin.im/doxygen/ or in the header files +in the Pidgin source tree. + +=head1 FUNCTIONS + +=over + +=back + +=head1 SEE ALSO +Pidgin C API documentation - http://developer.pidgin.im/doxygen/ + +The Pidgin perl module. + +Pidgin website - http://pidgin.im/ + +=head1 AUTHOR + +Etan Reisner, E<lt>deryni@gmail.comE<gt> + +=head1 COPYRIGHT AND LICENSE + +Copyright 2006 by Etan Reisner
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/plugins/perl/common/Pidgin.xs Sat Apr 28 03:53:00 2007 +0000 @@ -0,0 +1,66 @@ +#define PIDGIN_PERL_BOOT_PROTO(x) \ + void boot_Pidgin__##x(pTHX_ CV *cv) + +#define PIDGIN_PERL_BOOT(x) \ + purple_perl_callXS(boot_Pidgin__##x, cv, mark) + +#include "gtkmodule.h" + +/* Prototypes for the BOOT section below. */ +PIDGIN_PERL_BOOT_PROTO(Account); +PIDGIN_PERL_BOOT_PROTO(BuddyList); +PIDGIN_PERL_BOOT_PROTO(Connection); +PIDGIN_PERL_BOOT_PROTO(Conversation); +PIDGIN_PERL_BOOT_PROTO(Conversation__Window); +PIDGIN_PERL_BOOT_PROTO(Debug); +PIDGIN_PERL_BOOT_PROTO(Dialogs); +PIDGIN_PERL_BOOT_PROTO(IMHtml); +PIDGIN_PERL_BOOT_PROTO(IMHtmlToolbar); +PIDGIN_PERL_BOOT_PROTO(Log); +PIDGIN_PERL_BOOT_PROTO(MenuTray); +PIDGIN_PERL_BOOT_PROTO(Plugin); +PIDGIN_PERL_BOOT_PROTO(PluginPref); +PIDGIN_PERL_BOOT_PROTO(Pounce); +PIDGIN_PERL_BOOT_PROTO(Prefs); +PIDGIN_PERL_BOOT_PROTO(Privacy); +PIDGIN_PERL_BOOT_PROTO(Roomlist); +PIDGIN_PERL_BOOT_PROTO(Status); +#ifndef _WIN32 +PIDGIN_PERL_BOOT_PROTO(Session); +#endif +PIDGIN_PERL_BOOT_PROTO(Sound); +PIDGIN_PERL_BOOT_PROTO(StatusBox); +PIDGIN_PERL_BOOT_PROTO(Themes); +PIDGIN_PERL_BOOT_PROTO(Utils); +PIDGIN_PERL_BOOT_PROTO(Xfer); + +MODULE = Pidgin PACKAGE = Pidgin PREFIX = pidgin_ +PROTOTYPES: ENABLE + +BOOT: + PIDGIN_PERL_BOOT(Account); + PIDGIN_PERL_BOOT(BuddyList); + PIDGIN_PERL_BOOT(Connection); + PIDGIN_PERL_BOOT(Conversation); + PIDGIN_PERL_BOOT(Conversation__Window); + PIDGIN_PERL_BOOT(Debug); + PIDGIN_PERL_BOOT(Dialogs); + PIDGIN_PERL_BOOT(IMHtml); + PIDGIN_PERL_BOOT(IMHtmlToolbar); + PIDGIN_PERL_BOOT(Log); + PIDGIN_PERL_BOOT(MenuTray); + PIDGIN_PERL_BOOT(Plugin); + PIDGIN_PERL_BOOT(PluginPref); + PIDGIN_PERL_BOOT(Pounce); + PIDGIN_PERL_BOOT(Prefs); + PIDGIN_PERL_BOOT(Privacy); + PIDGIN_PERL_BOOT(Roomlist); + PIDGIN_PERL_BOOT(Status); +#ifndef _WIN32 + PIDGIN_PERL_BOOT(Session); +#endif + PIDGIN_PERL_BOOT(Sound); + PIDGIN_PERL_BOOT(StatusBox); + PIDGIN_PERL_BOOT(Themes); + PIDGIN_PERL_BOOT(Utils); + PIDGIN_PERL_BOOT(Xfer);
--- a/pidgin/win32/nsis/langmacros.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/langmacros.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -40,11 +40,6 @@ ; Components Page !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT PIDGIN_SECTION_TITLE ${CUR_LANG} !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT GTK_SECTION_TITLE ${CUR_LANG} - !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT GTK_THEMES_SECTION_TITLE ${CUR_LANG} - !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT GTK_NOTHEME_SECTION_TITLE ${CUR_LANG} - !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT GTK_WIMP_SECTION_TITLE ${CUR_LANG} - !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT GTK_BLUECURVE_SECTION_TITLE ${CUR_LANG} - !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT GTK_LIGHTHOUSEBLUE_SECTION_TITLE ${CUR_LANG} !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT PIDGIN_SHORTCUTS_SECTION_TITLE ${CUR_LANG} !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE ${CUR_LANG} !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE ${CUR_LANG} @@ -69,9 +64,6 @@ !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT GTK_INSTALL_ERROR ${CUR_LANG} !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT GTK_BAD_INSTALL_PATH ${CUR_LANG} - ; GTK+ Themes section - !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT GTK_NO_THEME_INSTALL_RIGHTS ${CUR_LANG} - ; URI Handler section !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT URI_HANDLERS_SECTION_TITLE ${CUR_LANG}
--- a/pidgin/win32/nsis/pidgin-installer.nsi Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/pidgin-installer.nsi Sat Apr 28 03:53:00 2007 +0000 @@ -326,7 +326,6 @@ !ifdef WITH_GTK Section $(GTK_SECTION_TITLE) SecGtk - SectionIn 1 RO Call CheckUserInstallRights Pop $R1 @@ -1065,11 +1064,11 @@ StrCmp $1 "HKCU" 0 +2 ; if HKLM can upgrade.. StrCmp $2 "HKLM" no_gtk ; have hkcu rights.. if found hklm ver can't upgrade.. Push $2 - IntCmp $3 1 +3 - Push "1" ; Optional Upgrade - Goto done - Push "2" ; Mandatory Upgrade - Goto done + IntCmp $3 1 +3 + Push "1" ; Optional Upgrade + Goto done + Push "2" ; Mandatory Upgrade + Goto done good_version: StrCmp $2 "HKLM" have_hklm_gtk have_hkcu_gtk @@ -1095,11 +1094,11 @@ done: ; The top two items on the stack are what we want to return Exch 4 + Pop $1 + Exch 4 Pop $0 - Exch 4 Pop $3 Pop $2 - Pop $1 FunctionEnd @@ -1199,6 +1198,7 @@ StrCpy $INSTDIR "$R2\Pidgin" instdir_done: +;LogSet on Pop $R0 FunctionEnd @@ -1275,7 +1275,7 @@ ; Page enter and exit functions.. Function preWelcomePage - Push R0 + Push $R0 !ifndef WITH_GTK ; If this installer dosn't have GTK, check whether we need it. @@ -1292,7 +1292,16 @@ done: !else - Push R1 + Push $R1 + Push $R2 + + ; Make the GTK+ Section RO if it is required. + Call DoWeNeedGtk + Pop $R0 + Pop $R2 + IntCmp $R0 1 gtk_not_mandatory gtk_not_mandatory + !insertmacro SetSectionFlag ${SecGtk} ${SF_RO} + gtk_not_mandatory: ; If on Win95/98/ME warn them that the GTK+ version wont work Call GetWindowsVersion @@ -1304,22 +1313,13 @@ win_ver_bad: !insertmacro UnselectSection ${SecGtk} - !insertmacro SetSectionFlag ${SecGtkNone} ${SF_RO} - !insertmacro UnselectSection ${SecGtkNone} - !insertmacro SetSectionFlag ${SecGtkWimp} ${SF_RO} - !insertmacro UnselectSection ${SecGtkWimp} - !insertmacro SetSectionFlag ${SecGtkBluecurve} ${SF_RO} - !insertmacro UnselectSection ${SecGtkBluecurve} - !insertmacro SetSectionFlag ${SecGtkLighthouseblue} ${SF_RO} - !insertmacro UnselectSection ${SecGtkLighthouseblue} + !insertmacro SetSectionFlag ${SecGtk} ${SF_RO} MessageBox MB_OK $(GTK_WINDOWS_INCOMPATIBLE) /SD IDOK - Call DoWeNeedGtk - Pop $R0 - Pop $R1 IntCmp $R0 1 done done ; Upgrade isn't optional - abort if we don't have a suitable version Quit done: + Pop $R2 Pop $R1 !endif Pop $R0
--- a/pidgin/win32/nsis/translations/albanian.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/albanian.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -18,11 +18,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Klient Shkëmbimi Mesazhesh të Atypëratyshëm Pidgin (i nevojshëm)" !define GTK_SECTION_TITLE "GTK+ Runtime Environment (i nevojshëm)" -!define GTK_THEMES_SECTION_TITLE "Tema GTK+" -!define GTK_NOTHEME_SECTION_TITLE "Pa Tema" -!define GTK_WIMP_SECTION_TITLE "Temë Wimp" -!define GTK_BLUECURVE_SECTION_TITLE "Temë Bluecurve" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Temë Light House Blue" !define PIDGIN_SECTION_DESCRIPTION "Kartela dhe dll bazë të Pidgin-it" !define GTK_SECTION_DESCRIPTION "Një grup mjetesh shumëplatformësh për GUI, përdorur nga Pidgin-i" @@ -40,9 +35,6 @@ !define GTK_INSTALL_ERROR "gabim gjatë instalimit të GTK+ runtime." !define GTK_BAD_INSTALL_PATH "Shtegu që treguat nuk mund të arrihet ose krijohet." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Nuk keni leje të instaloni tema GTK+." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "Çinstaluesi nuk gjeti dot zëra regjistri për Pidgin-in.$\rKa mundësi që këtë zbatim ta ketë instaluar një tjetër përdorues." !define un.PIDGIN_UNINSTALL_ERROR_2 "Nuk keni leje të çinstaloni këtë zbatim."
--- a/pidgin/win32/nsis/translations/bulgarian.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/bulgarian.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -14,11 +14,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin ( )" !define GTK_SECTION_TITLE "GTK+ Runtime (required)" -!define GTK_THEMES_SECTION_TITLE "GTK+ " -!define GTK_NOTHEME_SECTION_TITLE " " -!define GTK_WIMP_SECTION_TITLE "Wimp " -!define GTK_BLUECURVE_SECTION_TITLE "Bluecurve " -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Blue " !define PIDGIN_SECTION_DESCRIPTION " Pidgin " !define GTK_SECTION_DESCRIPTION " , Pidgin" @@ -33,9 +28,6 @@ !define GTK_INSTALL_ERROR " GTK+ runtime." !define GTK_BAD_INSTALL_PATH " ." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS " GTK+ ." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 " Pidgin.$\r ." !define un.PIDGIN_UNINSTALL_ERROR_2 " ."
--- a/pidgin/win32/nsis/translations/catalan.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/catalan.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -21,11 +21,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Client Pidgin de Missatgeria Instantnia (necessari)" !define GTK_SECTION_TITLE "Entorn d'Execuci GTK+ (necessari)" -!define GTK_THEMES_SECTION_TITLE "Temes GTK+" -!define GTK_NOTHEME_SECTION_TITLE "Sense tema" -!define GTK_WIMP_SECTION_TITLE "Tema Imwi" -!define GTK_BLUECURVE_SECTION_TITLE "Tema Corba Blava" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Tema Light House Blue" !define PIDGIN_SHORTCUTS_SECTION_TITLE "Enllaos directes" !define PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "Escriptori" !define PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "Menu Inici" @@ -51,9 +46,6 @@ !define GTK_INSTALL_ERROR "Error installlant l'entorn d'execuci GTK+." !define GTK_BAD_INSTALL_PATH "El directori que has introdut no pot sser accedit o creat." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "No tens permisos per instal.lar un tema GTK+." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "L'instal.lador podria no trobar les entrades del registre de Pidgin.$\rProbablement un altre usuari ha instal.lat aquesta aplicaci." !define un.PIDGIN_UNINSTALL_ERROR_2 "No tens perms per desinstal.lar aquesta aplicaci."
--- a/pidgin/win32/nsis/translations/czech.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/czech.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -18,11 +18,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin Instant Messaging Client (nutn)" !define GTK_SECTION_TITLE "GTK+ Runtime Environment (nutn)" -!define GTK_THEMES_SECTION_TITLE "GTK+ tmata" -!define GTK_NOTHEME_SECTION_TITLE "Bez tmat" -!define GTK_WIMP_SECTION_TITLE "Wimp tma" -!define GTK_BLUECURVE_SECTION_TITLE "Bluecurve tma" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Blue tma" !define PIDGIN_SECTION_DESCRIPTION "Zkladn soubory a DLL pro Pidgin" !define GTK_SECTION_DESCRIPTION "Multi-platform GUI toolkit pouvan Pidginem" @@ -40,9 +35,6 @@ !define GTK_INSTALL_ERROR "Chyba pi instalaci GTK+ runtime." !define GTK_BAD_INSTALL_PATH "Zadan cesta je nedostupn, nebo ji nelze vytvoit." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Nemte oprvnn k instalaci GTK+ tmatu." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "Odinstaln proces neme najt zznamy pro Pidgin v registrech.$\rPravdpodobn instalaci tto aplikace provedl jin uivatel." !define un.PIDGIN_UNINSTALL_ERROR_2 "Nemte oprvnn k odinstalaci tto aplikace."
--- a/pidgin/win32/nsis/translations/danish.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/danish.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -18,11 +18,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin Instant Messaging Client (obligatorisk)" !define GTK_SECTION_TITLE "GTK+ Runtime Environment (obligatorisk)" -!define GTK_THEMES_SECTION_TITLE "GTK+ Temaer" -!define GTK_NOTHEME_SECTION_TITLE "Intet Tema" -!define GTK_WIMP_SECTION_TITLE "Wimp Tema" -!define GTK_BLUECURVE_SECTION_TITLE "Bluecurve Tema" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Blue Tema" !define PIDGIN_SECTION_DESCRIPTION "Basale Pidgin filer og biblioteker" !define GTK_SECTION_DESCRIPTION "Et multi-platform grafisk interface udviklingsvrktj, bruges af Pidgin" @@ -40,9 +35,6 @@ !define GTK_INSTALL_ERROR "Fejl under installeringen af GTK+ runtime." !define GTK_BAD_INSTALL_PATH "Stien du har angivet kan ikke findes eller oprettes." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Du har ikke tilladelse til at installere et GTK+ tema." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "Afinstallationen kunne ikke finde Pidgin i registreringsdatabasen.$\rMuligvis har en anden bruger installeret programmet." !define un.PIDGIN_UNINSTALL_ERROR_2 "Du har ikke tilladelse til at afinstallere dette program."
--- a/pidgin/win32/nsis/translations/dutch.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/dutch.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -21,11 +21,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin Instant Messaging Client (vereist)" !define GTK_SECTION_TITLE "GTK+ runtime-omgeving (vereist)" -!define GTK_THEMES_SECTION_TITLE "GTK+ thema's" -!define GTK_NOTHEME_SECTION_TITLE "Geen thema" -!define GTK_WIMP_SECTION_TITLE "Wimp thema" -!define GTK_BLUECURVE_SECTION_TITLE "Bluecurve thema" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Blue thema" !define PIDGIN_SECTION_DESCRIPTION "Pidgin hoofdbestanden en dlls" !define GTK_SECTION_DESCRIPTION "Een multi-platform gebruikersinterface, gebruikt door Pidgin" @@ -43,9 +38,6 @@ !define GTK_INSTALL_ERROR "Fout bij installatie van GTK+ runtime omgeving." !define GTK_BAD_INSTALL_PATH "Het door u gegeven pad kan niet benaderd worden." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "U heeft geen toestemming om een GTK+ thema te installeren." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "Het verwijderingsprogramma voor Pidgin kon geen register-ingangen voor Pidgin vinden.$\rWaarschijnlijk heeft een andere gebruiker het programma genstalleerd." !define un.PIDGIN_UNINSTALL_ERROR_2 "U mag dit programma niet verwijderen."
--- a/pidgin/win32/nsis/translations/english.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/english.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -22,12 +22,7 @@ ; Components Page !insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_SECTION_TITLE "Pidgin Instant Messaging Client (required)" -!insertmacro PIDGIN_MACRO_DEFAULT_STRING GTK_SECTION_TITLE "GTK+ Runtime Environment (required)" -!insertmacro PIDGIN_MACRO_DEFAULT_STRING GTK_THEMES_SECTION_TITLE "GTK+ Themes" -!insertmacro PIDGIN_MACRO_DEFAULT_STRING GTK_NOTHEME_SECTION_TITLE "No Theme" -!insertmacro PIDGIN_MACRO_DEFAULT_STRING GTK_WIMP_SECTION_TITLE "MS-Windows (WIMP) Theme" -!insertmacro PIDGIN_MACRO_DEFAULT_STRING GTK_BLUECURVE_SECTION_TITLE "Bluecurve Theme" -!insertmacro PIDGIN_MACRO_DEFAULT_STRING GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Blue Theme" +!insertmacro PIDGIN_MACRO_DEFAULT_STRING GTK_SECTION_TITLE "GTK+ Runtime (required if not present)" !insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_SHORTCUTS_SECTION_TITLE "Shortcuts" !insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "Desktop" !insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "Start Menu" @@ -53,9 +48,6 @@ !insertmacro PIDGIN_MACRO_DEFAULT_STRING GTK_INSTALL_ERROR "Error installing GTK+ runtime." !insertmacro PIDGIN_MACRO_DEFAULT_STRING GTK_BAD_INSTALL_PATH "The path you entered can not be accessed or created." -; GTK+ Themes section -!insertmacro PIDGIN_MACRO_DEFAULT_STRING GTK_NO_THEME_INSTALL_RIGHTS "You do not have permission to install a GTK+ theme." - ; URL Handler section !insertmacro PIDGIN_MACRO_DEFAULT_STRING URI_HANDLERS_SECTION_TITLE "URI Handlers"
--- a/pidgin/win32/nsis/translations/finnish.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/finnish.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -18,11 +18,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin Suoraviestintohjelma (required)" !define GTK_SECTION_TITLE "GTK+ runtime ymprist (required)" -!define GTK_THEMES_SECTION_TITLE "GTK+ Teemat" -!define GTK_NOTHEME_SECTION_TITLE "Ei teemaa" -!define GTK_WIMP_SECTION_TITLE "Wimp Teema" -!define GTK_BLUECURVE_SECTION_TITLE "Bluecurve Teema" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Blue Teema" !define PIDGIN_SECTION_DESCRIPTION "Pidfinin ytimen tiedostot ja dll:t" !define GTK_SECTION_DESCRIPTION "Monipohjainen GUI (kyttjulkoasu) tykalupakki, Pidginin kyttm" @@ -39,9 +34,6 @@ !define GTK_INSTALL_ERROR "Virhe asennettaessa GTK+ runtime." !define GTK_BAD_INSTALL_PATH "Antamasi polku ei toimi tai sit ei voi luoda." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Sinulla ei ole valtuuksia asentaa GTK+ teemaa." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "Asennuksen poistaja ei lytnyt reksiterist tietoja Pidginista.$\rOn todennkist ett joku muu kyttj on asentanut ohjelman." !define un.PIDGIN_UNINSTALL_ERROR_2 "Sinulla ei ole valtuuksia poistaa ohjelmaa."
--- a/pidgin/win32/nsis/translations/french.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/french.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -24,11 +24,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin client de messagerie instantane (obligatoire)" !define GTK_SECTION_TITLE "Bibliothques GTK+ (obligatoire)" -!define GTK_THEMES_SECTION_TITLE "Thmes GTK+" -!define GTK_NOTHEME_SECTION_TITLE "Pas de thme" -!define GTK_WIMP_SECTION_TITLE "Thme Wimp" -!define GTK_BLUECURVE_SECTION_TITLE "Thme Bluecurve" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Thme Light House Blue" !define PIDGIN_SHORTCUTS_SECTION_TITLE "Raccourcis" !define PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "Bureau" !define PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "Menu Dmarrer" @@ -52,9 +47,6 @@ !define GTK_INSTALL_ERROR "Erreur lors de l'installation des bibliothques GTK+" !define GTK_BAD_INSTALL_PATH "Le dossier d'installation ne peut pas tre cr ou n'est pas accessible." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Vous n'avez pas les permissions pour installer un thme GTK+." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "Le programme de dsinstallation n'a pas retrouv les entres de Pidgin dans la base de registres.$\rL'application a peut-tre t installe par un utilisateur diffrent." !define un.PIDGIN_UNINSTALL_ERROR_2 "Vous n'avez pas les permissions pour supprimer cette application."
--- a/pidgin/win32/nsis/translations/galician.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/galician.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -18,11 +18,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Cliente de mensaxera instantnea de Pidgin (necesario)" !define GTK_SECTION_TITLE "Entorno de execucin de GTK+ (necesario)" -!define GTK_THEMES_SECTION_TITLE "Temas GTK+" -!define GTK_NOTHEME_SECTION_TITLE "Sen tema" -!define GTK_WIMP_SECTION_TITLE "Tema Wimp" -!define GTK_BLUECURVE_SECTION_TITLE "Tema Bluecurve" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Tema Light House Blue" !define PIDGIN_SECTION_DESCRIPTION "Ficheiros e dlls principais de Core" !define GTK_SECTION_DESCRIPTION "Unha suite de ferramentas GUI multiplataforma, utilizada por Pidgin" @@ -40,9 +35,6 @@ !define GTK_INSTALL_ERROR "Erro ao instalar o executable GTK+." !define GTK_BAD_INSTALL_PATH "Non se puido acceder ou crear a ruta que vd. indicou." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Non ten permisos para instalar un tema GTK+." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "O desinstalador non puido atopar as entradas no rexistro de Pidgin.$\r probable que outro usuario instalara a aplicacin." !define un.PIDGIN_UNINSTALL_ERROR_2 "Non ten permisos para desinstalar esta aplicacin."
--- a/pidgin/win32/nsis/translations/german.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/german.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -21,11 +21,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin Instant Messaging Client (erforderlich)" !define GTK_SECTION_TITLE "GTK+ Runtime Umgebung (erforderlich)" -!define GTK_THEMES_SECTION_TITLE "GTK+ Themen" -!define GTK_NOTHEME_SECTION_TITLE "Kein Thema" -!define GTK_WIMP_SECTION_TITLE "Wimp Thema" -!define GTK_BLUECURVE_SECTION_TITLE "Bluecurve Thema" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Blue Thema" !define PIDGIN_SHORTCUTS_SECTION_TITLE "Verknpfungen" !define PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "Desktop" !define PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "Startmen" @@ -48,9 +43,6 @@ ; GTK+ Section Prompts !define GTK_INSTALL_ERROR "Fehler beim Installieren der GTK+ Runtime." !define GTK_BAD_INSTALL_PATH "Der Pfad, den Sie eingegeben haben, existiert nicht und kann nicht erstellt werden." - -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Sie haben keine Berechtigung, ein GTK+ Thema zu installieren." ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "Der Deinstaller konnte keine Registrierungsschlssel fr Pidgin finden.$\rEs ist wahrscheinlich, da ein anderer Benutzer diese Anwendung installiert hat."
--- a/pidgin/win32/nsis/translations/hebrew.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/hebrew.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -18,11 +18,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "() .Pidgin " !define GTK_SECTION_TITLE "() .GTK+ " -!define GTK_THEMES_SECTION_TITLE "GTK+ " -!define GTK_NOTHEME_SECTION_TITLE " " -!define GTK_WIMP_SECTION_TITLE "Wimp " -!define GTK_BLUECURVE_SECTION_TITLE "Bluecurve " -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Blue " !define PIDGIN_SECTION_DESCRIPTION ". DLL- Pidgin " !define GTK_SECTION_DESCRIPTION ".- GUI " @@ -39,9 +34,6 @@ !define GTK_INSTALL_ERROR ".GTK+ " !define GTK_BAD_INSTALL_PATH ". " -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS ".GTK+ " - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 ".GTK+ $\r. " !define un.PIDGIN_UNINSTALL_ERROR_2 ". "
--- a/pidgin/win32/nsis/translations/hungarian.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/hungarian.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -20,11 +20,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin azonnali zen kliens (szksges)" !define GTK_SECTION_TITLE "GTK+ futtat krnyezet (szksges)" -!define GTK_THEMES_SECTION_TITLE "GTK+ tmk" -!define GTK_NOTHEME_SECTION_TITLE "Nincs tma" -!define GTK_WIMP_SECTION_TITLE "Wimp tma" -!define GTK_BLUECURVE_SECTION_TITLE "Bluecurve tma" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Blue tma" !define PIDGIN_SHORTCUTS_SECTION_TITLE "Parancsikonok" !define PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "Asztal" !define PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "Start Men" @@ -51,9 +46,6 @@ !define GTK_INSTALL_ERROR "Hiba a GTK+ futtatkrnyezet teleptse kzben." !define GTK_BAD_INSTALL_PATH "A megadott elrsi t nem rhet el, vagy nem hozhat ltre." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Nincs jogosultsga a GTK+ tmk teleptshez." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "Az eltvolt nem tallta a Pidgin registry bejegyzseket.$\rValsznleg egy msik felhasznl teleptette az alkalmazst." !define un.PIDGIN_UNINSTALL_ERROR_2 "Nincs jogosultsga az alkalmazs eltvoltshoz."
--- a/pidgin/win32/nsis/translations/italian.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/italian.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -18,11 +18,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin - Client per Messaggi Immediati (richiesto)" !define GTK_SECTION_TITLE "Ambiente di Runtime GTK+ (richiesto)" -!define GTK_THEMES_SECTION_TITLE "Temi GTK+" -!define GTK_NOTHEME_SECTION_TITLE "Nessun Tema" -!define GTK_WIMP_SECTION_TITLE "Tema Wimp" -!define GTK_BLUECURVE_SECTION_TITLE "Tema Bluecurve" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Tema Light House Blue" !define PIDGIN_SECTION_DESCRIPTION "File principali di Pidgin e dll" !define GTK_SECTION_DESCRIPTION "Un toolkit multipiattaforma per interfacce grafiche, usato da Pidgin" @@ -39,9 +34,6 @@ !define GTK_INSTALL_ERROR "Errore di installazione di GTK+." !define GTK_BAD_INSTALL_PATH "Il percorso scelto non pu essere raggiunto o creato." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Non hai il permesso per installare un tema GTK+." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "Il programma di rimozione non in grado di trovare le voci di registro per Pidgin.$\rProbabilmente un altro utente ha installato questa applicazione." !define un.PIDGIN_UNINSTALL_ERROR_2 "Non hai il permesso per rimuovere questa applicazione."
--- a/pidgin/win32/nsis/translations/japanese.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/japanese.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -21,11 +21,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "PidginCX^gbZW (K{)" !define GTK_SECTION_TITLE "GTK+ Runtime Environment (K{)" -!define GTK_THEMES_SECTION_TITLE "GTK+̃e[}" -!define GTK_NOTHEME_SECTION_TITLE "e[}Ȃ" -!define GTK_WIMP_SECTION_TITLE "Wimpe[}" -!define GTK_BLUECURVE_SECTION_TITLE "Bluecurvee[}" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Bluee[}" !define PIDGIN_SHORTCUTS_SECTION_TITLE "V[gJbg" !define PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "fXNgbv" !define PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "X^[gAbv" @@ -50,9 +45,6 @@ !define GTK_INSTALL_ERROR "GTK+^C̃CXg[ŃG[܂B" !define GTK_BAD_INSTALL_PATH "Ȃ̓͂pXɃANZX܂͍쐬ł܂B" -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "ȂGTK+̃e[}CXg[錠Ă܂B" - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "ACXg[PidgiñWXgGgł܂łB$\r炭ʂ̃[UɃCXg[ꂽł傤B" !define un.PIDGIN_UNINSTALL_ERROR_2 "Ȃ͂̃AvP[VACXg[錠Ă܂B"
--- a/pidgin/win32/nsis/translations/korean.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/korean.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -13,11 +13,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE " (ʼ)" !define GTK_SECTION_TITLE "GTK+ Ÿ ȯ (ʼ)" -!define GTK_THEMES_SECTION_TITLE "GTK+ " -!define GTK_NOTHEME_SECTION_TITLE " " -!define GTK_WIMP_SECTION_TITLE " " -!define GTK_BLUECURVE_SECTION_TITLE "Ŀ " -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Blue " !define PIDGIN_SECTION_DESCRIPTION " ھ ϰ dll" !define GTK_SECTION_DESCRIPTION " ϴ Ƽ ÷ GUI Ŷ" @@ -31,9 +26,6 @@ !define GTK_INSTALL_ERROR "GTK+ Ÿ ġ ." !define GTK_BAD_INSTALL_PATH "ԷϽ ο ų ϴ." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "GTK+ ġ ϴ." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "ν緯 Ʈ Ʈ ã ϴ.$\r α ٸ ġ ϴ." !define un.PIDGIN_UNINSTALL_ERROR_2 " α ִ ϴ."
--- a/pidgin/win32/nsis/translations/kurdish.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/kurdish.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -21,11 +21,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin Instant Messaging Client (pwst)" !define GTK_SECTION_TITLE "GTK+ Runtime Environment (pwst)" -!define GTK_THEMES_SECTION_TITLE "Dirbn GTK+" -!define GTK_NOTHEME_SECTION_TITLE "Dirb tunebe" -!define GTK_WIMP_SECTION_TITLE "Dirb Wimp" -!define GTK_BLUECURVE_SECTION_TITLE "Dirb Bluecurve" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Dirb Light House Blue" !define PIDGIN_SHORTCUTS_SECTION_TITLE "Riyn kin" !define PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "Sermas" !define PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "Menuya destpk" @@ -49,9 +44,6 @@ !define GTK_INSTALL_ERROR "Di sazkirina GTK+ de ewt derket." !define GTK_BAD_INSTALL_PATH "rya te nivsand nay gihitin an afirandin." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Destra sazkirina dirbek GTK+ tune." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "Raker tketiyn registry yn Pidgin nedt. $\rQey bikarhnereke din v bername saz kir." !define un.PIDGIN_UNINSTALL_ERROR_2 "Destra te ji bo rakirina v bernamey tune."
--- a/pidgin/win32/nsis/translations/lithuanian.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/lithuanian.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -18,11 +18,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin pokalbi klientas (btinas)" !define GTK_SECTION_TITLE "GTK+ vykdymo meto aplinka (btina)" -!define GTK_THEMES_SECTION_TITLE "GTK+ apipavidalinimai" -!define GTK_NOTHEME_SECTION_TITLE "Jokio apipavidalinimo" -!define GTK_WIMP_SECTION_TITLE "Wimp apipavidalinimas" -!define GTK_BLUECURVE_SECTION_TITLE "Bluecurve apipavidalinimas" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Blue apipavidalinimas" !define PIDGIN_SHORTCUTS_SECTION_TITLE "Nuorodos" !define PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "Darbalaukyje" !define PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "Pradiniame meniu" @@ -46,9 +41,6 @@ !define GTK_INSTALL_ERROR "GTK+ vykdymo meto aplinkos diegimo klaida." !define GTK_BAD_INSTALL_PATH "Js nurodytas katalogas neprieinamas ar negali bti sukurtas." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Neturite teisi diegti GTK+ apipavidalinim." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "alinimo programa nerado Pidgin registro ra.$\rGalbt kitas vartotojas instaliavo i program." !define un.PIDGIN_UNINSTALL_ERROR_2 "Neturite teisi paalinti ios programos."
--- a/pidgin/win32/nsis/translations/norwegian.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/norwegian.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -20,11 +20,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin Hurtigmeldingsklient (obligatorisk)" !define GTK_SECTION_TITLE "GTK+ Runtime Environment (obligatorisk)" -!define GTK_THEMES_SECTION_TITLE "GTK+ Tema" -!define GTK_NOTHEME_SECTION_TITLE "Ingen tema" -!define GTK_WIMP_SECTION_TITLE "Wimp-tema" -!define GTK_BLUECURVE_SECTION_TITLE "Bluecurve-tema" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Blue-tema" !define PIDGIN_SHORTCUTS_SECTION_TITLE "Snarveier" !define PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "Skrivebord" !define PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "Startmeny" @@ -48,9 +43,6 @@ !define GTK_INSTALL_ERROR "En feil oppstod ved installering av GTK+ runtime." !define GTK_BAD_INSTALL_PATH "Stien du oppga kan ikke aksesseres eller lages." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Du har ikke rettigheter til installere et GTK+ tema." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "Avinstalleringsprogrammet kunne ikke finne noen registeroppfring for Pidgin.$\rTrolig har en annen bruker avinstallert denne applikasjonen." !define un.PIDGIN_UNINSTALL_ERROR_2 "Du har ikke rettigheter til avinstallere denne applikasjonen."
--- a/pidgin/win32/nsis/translations/polish.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/polish.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -18,11 +18,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Wymagany jest Pidgin Instant Messaging Client" !define GTK_SECTION_TITLE "Wymagany jest runtime rodowiska GTK+" -!define GTK_THEMES_SECTION_TITLE "Temat GTK+" -!define GTK_NOTHEME_SECTION_TITLE "Brak tematw" -!define GTK_WIMP_SECTION_TITLE "Temat Wimp" -!define GTK_BLUECURVE_SECTION_TITLE "Temat Bluecurve " -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Temat Light House Blue" !define PIDGIN_SECTION_DESCRIPTION "Zbiory Core Pidgin oraz dll" !define GTK_SECTION_DESCRIPTION "Wieloplatformowe narzdzie GUI, uywane w Pidgin" @@ -39,9 +34,6 @@ !define GTK_INSTALL_ERROR "Bd instalacji runtime-a GTK+." !define GTK_BAD_INSTALL_PATH "Nie ma dostpu do wybranej cieki / aty." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Nie masz uprawnie do zainstalowania tematu GTK+." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "Deinstalator nie moe znale rejestrw dla Pidgin.$\r Wskazuje to na to, e instalacj przeprowadzi inny uytkownik." !define un.PIDGIN_UNINSTALL_ERROR_2 "Nie masz uprawnie do deinstalacji tej aplikacji."
--- a/pidgin/win32/nsis/translations/portuguese-br.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/portuguese-br.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -18,11 +18,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Cliente de mensagens instantneas Pidgin (requerido)" !define GTK_SECTION_TITLE "Ambiente de tempo de execuo do GTK+ (requerido)" -!define GTK_THEMES_SECTION_TITLE "Temas do GTK+" -!define GTK_NOTHEME_SECTION_TITLE "Nenhum tema" -!define GTK_WIMP_SECTION_TITLE "Tema 'Wimp'" -!define GTK_BLUECURVE_SECTION_TITLE "Tema 'Bluecurve'" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Tema 'Light House Blue'" !define PIDGIN_SHORTCUTS_SECTION_TITLE "Atalhos" !define PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "rea de Trabalho" !define PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "Menu Iniciar" @@ -43,9 +38,6 @@ !define GTK_INSTALL_ERROR "Erro ao instalar o ambiente de tempo de execuo do GTK+." !define GTK_BAD_INSTALL_PATH "O caminho que voc digitou no pde ser acessado ou criado." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Voc no tem permisso para instalar um tema do GTK+." - ; Installer Finish Page !define PIDGIN_FINISH_VISIT_WEB_SITE "Visite a pgina da web do Pidgin para Windows"
--- a/pidgin/win32/nsis/translations/portuguese.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/portuguese.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -20,11 +20,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Cliente de Mensagens Instantneas Pidgin (obrigatrio)" !define GTK_SECTION_TITLE "Ambiente de Execuo GTK+ (obrigatrio)" -!define GTK_THEMES_SECTION_TITLE "Temas do GTK+" -!define GTK_NOTHEME_SECTION_TITLE "Nenhum tema" -!define GTK_WIMP_SECTION_TITLE "Tema Wimp" -!define GTK_BLUECURVE_SECTION_TITLE "Tema Bluecurve" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Tema Light House Blue" !define PIDGIN_SHORTCUTS_SECTION_TITLE "Atalhos" !define PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "Ambiente de Trabalho" !define PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "Menu de Iniciar" @@ -48,9 +43,6 @@ !define GTK_INSTALL_ERROR "Erro ao instalar o ambiente de execuo GTK+." !define GTK_BAD_INSTALL_PATH "O caminho que digitou no pode ser acedido nem criado." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "No tem permisso para instalar um tema do GTK+." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "O desinstalador no encontrou entradas de registo do Pidgin.$\r provvel que outro utilizador tenha instalado este programa." !define un.PIDGIN_UNINSTALL_ERROR_2 "No tem permisso para desinstalar este programa."
--- a/pidgin/win32/nsis/translations/romanian.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/romanian.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -19,11 +19,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Client de mesagerie instant (obligatoriu)" !define GTK_SECTION_TITLE "Mediu GTK+ (obligatoriu)" -!define GTK_THEMES_SECTION_TITLE "Teme GTK+" -!define GTK_NOTHEME_SECTION_TITLE "Fr teme" -!define GTK_WIMP_SECTION_TITLE "Tem Wimp" -!define GTK_BLUECURVE_SECTION_TITLE "Tem Bluecurve" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Tem Light House Blue" !define PIDGIN_SHORTCUTS_SECTION_TITLE "Scurtturi" !define PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "Desktop" !define PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "Meniu Start" @@ -47,9 +42,6 @@ !define GTK_INSTALL_ERROR "Eroare la instalarea mediului GTK+." !define GTK_BAD_INSTALL_PATH "Directorul specificat nu poate fi accesat sau creat." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Nu avei drepturile de acces necesare instalrii unei teme GTK+." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "Programul de dezinstalare nu a gsit intrri Pidgin n regitri.$\rProbabil un alt utilizator a instalat aceast aplicaie." !define un.PIDGIN_UNINSTALL_ERROR_2 "Nu avei drepturile de acces necesare dezinstalrii acestei aplicaii."
--- a/pidgin/win32/nsis/translations/russian.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/russian.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -18,11 +18,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin - ()." !define GTK_SECTION_TITLE "GTK+ ()." -!define GTK_THEMES_SECTION_TITLE " GTK+." -!define GTK_NOTHEME_SECTION_TITLE " ." -!define GTK_WIMP_SECTION_TITLE " 'Wimp Theme'" -!define GTK_BLUECURVE_SECTION_TITLE " 'Bluecurve'." -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE " 'Light House Blue'." !define PIDGIN_SECTION_DESCRIPTION " Pidgin ." !define GTK_SECTION_DESCRIPTION " , Pidgin." @@ -39,9 +34,6 @@ !define GTK_INSTALL_ERROR " GTK+." !define GTK_BAD_INSTALL_PATH " ." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS " GTK+." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 " Pidgin ..$\r ." !define un.PIDGIN_UNINSTALL_ERROR_2 " ."
--- a/pidgin/win32/nsis/translations/serbian-latin.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/serbian-latin.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -13,11 +13,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin klijent za brze poruke (neophodno)" !define GTK_SECTION_TITLE "GTK+ okolina za izvravanje (neophodno)" -!define GTK_THEMES_SECTION_TITLE "GTK+ teme" -!define GTK_NOTHEME_SECTION_TITLE "Bez teme" -!define GTK_WIMP_SECTION_TITLE "Wimp tema" -!define GTK_BLUECURVE_SECTION_TITLE "Bluecurve tema" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Blue tema" !define PIDGIN_SECTION_DESCRIPTION "Osnovne Pidgin datoteke i dinamike biblioteke" !define GTK_SECTION_DESCRIPTION "Skup orua za grafiko okruenje, za vie platformi, koristi ga Pidgin " @@ -31,9 +26,6 @@ !define GTK_INSTALL_ERROR "Greka prilikom instalacije GTK+ okoline za izvravanje." !define GTK_BAD_INSTALL_PATH "Putanja koju ste naveli se ne moe ni napraviti niti joj se moe prii." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Nemate ovlaenja za instalaciju GTK+ teme." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "Program za uklanjanje instalacije ne moe da pronae stavke registra za Pidgin.$\rVerovatno je ovu aplikaciju instalirao drugi korisnik." !define un.PIDGIN_UNINSTALL_ERROR_2 "Nemate ovlaenja za deinstalaciju ove aplikacije."
--- a/pidgin/win32/nsis/translations/simp-chinese.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/simp-chinese.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -20,11 +20,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin ʱͨѶ()" !define GTK_SECTION_TITLE "GTK+ ʱ̻()" -!define GTK_THEMES_SECTION_TITLE "GTK+ " -!define GTK_NOTHEME_SECTION_TITLE "" -!define GTK_WIMP_SECTION_TITLE "Wimp " -!define GTK_BLUECURVE_SECTION_TITLE "Bluecurve " -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Blue " !define PIDGIN_SHORTCUTS_SECTION_TITLE "ݷʽ" !define PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "" !define PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "ʼ˵" @@ -48,9 +43,6 @@ !define GTK_INSTALL_ERROR "װ GTK+ ʱʧܡ" !define GTK_BAD_INSTALL_PATH "ʻ·" -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "ûȨްװ GTK+ ⡣" - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "жسҲ Pidgin עĿ$\rûװ˴˳" !define un.PIDGIN_UNINSTALL_ERROR_2 "ûȨжش˳"
--- a/pidgin/win32/nsis/translations/slovak.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/slovak.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -20,11 +20,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin Instant Messaging Klient (nevyhnutn)" !define GTK_SECTION_TITLE "GTK+ Runtime prostredie (nevyhnutn)" -!define GTK_THEMES_SECTION_TITLE "GTK+ tmy" -!define GTK_NOTHEME_SECTION_TITLE "iadna grafick tma" -!define GTK_WIMP_SECTION_TITLE "Wimp grafick tma" -!define GTK_BLUECURVE_SECTION_TITLE "Bluecurve grafick tma" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Blue grafick tma" !define PIDGIN_SHORTCUTS_SECTION_TITLE "Zstupcovia" !define PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "Plocha" !define PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "tart Menu" @@ -48,9 +43,6 @@ !define GTK_INSTALL_ERROR "Chyba pri intalcii GTK+ runtime." !define GTK_BAD_INSTALL_PATH "Zadan cesta nie je prstupn alebo ju nie je mon vytvori." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Nemte oprvnenie na intalciu GTK+ grafickej tmy." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "Intaltoru sa nepodarilo njs poloky v registri pre Pidgin.$\rJe mon, e tto aplikciu naintaloval in pouvate." !define un.PIDGIN_UNINSTALL_ERROR_2 "Nemte oprvnenie na odintalciu tejto aplikcie."
--- a/pidgin/win32/nsis/translations/slovenian.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/slovenian.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -20,11 +20,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin - odjemalec za klepet (zahtevano)" !define GTK_SECTION_TITLE "GTK+ izvajalno okolje (zahtevano)" -!define GTK_THEMES_SECTION_TITLE "Teme GTK+" -!define GTK_NOTHEME_SECTION_TITLE "Brez teme" -!define GTK_WIMP_SECTION_TITLE "Tema Wimp" -!define GTK_BLUECURVE_SECTION_TITLE "Tema Bluecurve" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Tema Light House Blue" !define PIDGIN_SHORTCUTS_SECTION_TITLE "Blinjice" !define PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "Namizje" !define PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "Zaetni meni" @@ -48,9 +43,6 @@ !define GTK_INSTALL_ERROR "Napaka pri namestitvi izvajalnega okolja GTK+." !define GTK_BAD_INSTALL_PATH "Pot, ki ste jo vnesli, ni dosegljiva ali je ni mogoe ustvariti." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Za namestitev teme GTK+ nimate ustreznih pravic." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "Vnosov za Pidgin v registru ni mogoe najti.$\rNajverjetneje je ta program namestil drug uporabnik." !define un.PIDGIN_UNINSTALL_ERROR_2 "Za odstranitev programa nimate ustreznih pravic."
--- a/pidgin/win32/nsis/translations/spanish.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/spanish.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -18,11 +18,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Cliente de mensajera instantnea de Pidgin (necesario)" !define GTK_SECTION_TITLE "Entorno de ejecucin de GTK+ (necesario)" -!define GTK_THEMES_SECTION_TITLE "Temas GTK+" -!define GTK_NOTHEME_SECTION_TITLE "Sin tema" -!define GTK_WIMP_SECTION_TITLE "Tema Wimp" -!define GTK_BLUECURVE_SECTION_TITLE "Tema Bluecurve" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Tema Light House Blue" !define PIDGIN_SECTION_DESCRIPTION "Ficheros y dlls principales de Core" !define GTK_SECTION_DESCRIPTION "Una suite de herramientas GUI multiplataforma, utilizada por Pidgin" @@ -39,9 +34,6 @@ !define GTK_INSTALL_ERROR "Error al instalar el ejecutable GTK+." !define GTK_BAD_INSTALL_PATH "No se pudo acceder o crear la ruta que vd. indic." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "No tiene permisos para instalar un tema GTK+." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "El desinstalador no pudo encontrar las entradas en el registro de Pidgin.$\rEs probable que otro usuario instalara la aplicacin." !define un.PIDGIN_UNINSTALL_ERROR_2 "No tiene permisos para desinstalar esta aplicacin."
--- a/pidgin/win32/nsis/translations/swedish.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/swedish.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -23,11 +23,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin Snabbmeddelandeklient (obligatorisk)" !define GTK_SECTION_TITLE "GTK+-krmilj (obligatorisk)" -!define GTK_THEMES_SECTION_TITLE "GTK+-teman" -!define GTK_NOTHEME_SECTION_TITLE "Inget tema" -!define GTK_WIMP_SECTION_TITLE "Wimp-tema" -!define GTK_BLUECURVE_SECTION_TITLE "Bluecurve-tema" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Blue-tema" !define PIDGIN_SHORTCUTS_SECTION_TITLE "Genvgar" !define PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "Skrivbord" !define PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "Startmeny" @@ -51,9 +46,6 @@ !define GTK_INSTALL_ERROR "Fel vid installation av GTK+ runtime." !define GTK_BAD_INSTALL_PATH "Den skvg du angivit gr inte att komma t eller skapa." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Du har inte rttigheter att installera ett GTK+tema." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "Avinstalleraren kunde inte hitta registervrden fr Pidgin.$\rAntagligen har en annan anvndare installerat applikationen." !define un.PIDGIN_UNINSTALL_ERROR_2 "Du har inte rttigheter att avinstallera den hr applikationen."
--- a/pidgin/win32/nsis/translations/trad-chinese.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/trad-chinese.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -22,11 +22,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Pidgin D{ ()" !define GTK_SECTION_TITLE "GTK+ ()" -!define GTK_THEMES_SECTION_TITLE "GTK+ GDD" -!define GTK_NOTHEME_SECTION_TITLE "w˧GDD" -!define GTK_WIMP_SECTION_TITLE "Wimp GDD" -!define GTK_BLUECURVE_SECTION_TITLE "Bluecurve GDD" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Blue GDD" !define PIDGIN_SHORTCUTS_SECTION_TITLE "|" !define PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "ୱ|" !define PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "}l\" @@ -50,9 +45,6 @@ !define GTK_INSTALL_ERROR "w GTK+ ҮɵoͿ~C" !define GTK_BAD_INSTALL_PATH "zҿJw˥ؿLksΫإߡC" -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "zثevLkw GTK+ GDDC" - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "{Lk Pidgin w˸TC$\roӬOLϥΪ̭swˤFoӵ{C" !define un.PIDGIN_UNINSTALL_ERROR_2 "zثevLk Pidgin C"
--- a/pidgin/win32/nsis/translations/valencian.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/valencian.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -23,11 +23,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Client Mensageria Instantanea Pidgin (necessari)" !define GTK_SECTION_TITLE "Entorn d'Eixecucio GTK+ (necessari)" -!define GTK_THEMES_SECTION_TITLE "Temes GTK+" -!define GTK_NOTHEME_SECTION_TITLE "Sense Tema" -!define GTK_WIMP_SECTION_TITLE "Tema Wimp" -!define GTK_BLUECURVE_SECTION_TITLE "Tema Bluecurve" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Tema Light House Blue" !define PIDGIN_SHORTCUTS_SECTION_TITLE "Enllaos directes" !define PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "Escritori" !define PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "Menu d'Inici" @@ -51,9 +46,6 @@ !define GTK_INSTALL_ERROR "Erro instalant l'entorn GTK+." !define GTK_BAD_INSTALL_PATH "La ruta introduida no pot ser accedida o creada." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "No tens permissos per a instalar un tema GTK+." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "El desinstalador podria no trobar les entrades del registre de Pidgin.$\rProbablement un atre usuari instal esta aplicacio." !define un.PIDGIN_UNINSTALL_ERROR_2 "No tens permis per a desinstalar esta aplicacio."
--- a/pidgin/win32/nsis/translations/vietnamese.nsh Thu Apr 26 21:15:41 2007 +0000 +++ b/pidgin/win32/nsis/translations/vietnamese.nsh Sat Apr 28 03:53:00 2007 +0000 @@ -19,11 +19,6 @@ ; Components Page !define PIDGIN_SECTION_TITLE "Trình Khách Thông Điệp Tức Thời Pidgin (phải có)" !define GTK_SECTION_TITLE "GTK+ Runtime Environment (phải có)" -!define GTK_THEMES_SECTION_TITLE "GTK+ Theme" -!define GTK_NOTHEME_SECTION_TITLE "Không có Theme" -!define GTK_WIMP_SECTION_TITLE "Wimp Theme" -!define GTK_BLUECURVE_SECTION_TITLE "Bluecurve Theme" -!define GTK_LIGHTHOUSEBLUE_SECTION_TITLE "Light House Blue Theme" !define PIDGIN_SECTION_DESCRIPTION "Các tập tin Pidgin chính và dlls" !define GTK_SECTION_DESCRIPTION "Bộ công cụ giao diện đồ họa đa nền để dùng cho Pidgin" @@ -40,9 +35,6 @@ !define GTK_INSTALL_ERROR "Lỗi cài đặt GTK+ runtime." !define GTK_BAD_INSTALL_PATH "Đường dẫn mà bạn nhập có thể không truy cập được hay không tạo được." -; GTK+ Themes section -!define GTK_NO_THEME_INSTALL_RIGHTS "Bạn không có quyền hạn để cài đặt GTK+ theme." - ; Uninstall Section Prompts !define un.PIDGIN_UNINSTALL_ERROR_1 "Trình gỡ cài đặt không tìm được các registry entry cho Pidgin.$\rCó thể là chương trình được người dùng khác cài đặt." !define un.PIDGIN_UNINSTALL_ERROR_2 "Bạn không có quyền hạn để gỡ bỏ chương trình này."