# HG changeset patch # User Marcus Lundblad # Date 1269294323 0 # Node ID f14cbb6a28a7b09806f9db74ca4a0c01b6ee812f # Parent 93f6a5d48a462b0b5e63fc831cbda529915747c5# Parent 9f59abd49def45e724615a4fdae347db11a6f107 propagate from branch 'im.pidgin.pidgin' (head d2cd6030fc66f726f61a1d7576facd0ef6ea5fe5) to branch 'im.pidgin.cpw.malu.ft_thumbnails' (head 71882b1055f5d7bf391080b3061785a661c5c8e9) diff -r 93f6a5d48a46 -r f14cbb6a28a7 ChangeLog --- a/ChangeLog Sun Mar 21 20:57:29 2010 +0000 +++ b/ChangeLog Mon Mar 22 21:45:23 2010 +0000 @@ -4,6 +4,8 @@ General: * Changed GTK+ minimum version requirement to 2.10.0. * Changed GLib minimum version requirement to 2.12.0. + * Using the --disable-nls argument to configre now works properly. You + will no longer be forced to have intltool to configure and build. Pidgin: * Moved the "Debugging Information" section of the About box to a @@ -23,6 +25,9 @@ * Added a menu set mood globally for all mood-supporting accounts (currently XMPP and ICQ). * Use standard (but small) GTK+ buttons instead of custom "X" symbol. + * Default binding of Ctrl+Shift+v to 'Paste as Plain Text' in + conversation windows. This can be changed in .gtkrc-2.0. For example, + Ctrl+v can be bound to 'Paste as Plain Text' by default. Bonjour: * Added support for IPv6. (Thanks to T_X for testing) @@ -50,6 +55,7 @@ rjoly for testing) * When sending data using in-band-bytestreams, interpret the block-size attribute as the size of the BASE64-encoded representation of the data. + * Validate the hash on incoming BoB data objects (for custom smileys etc.). Yahoo: * Attempt to better handle transparent proxies interfering with HTTP-based diff -r 93f6a5d48a46 -r f14cbb6a28a7 ChangeLog.API --- a/ChangeLog.API Sun Mar 21 20:57:29 2010 +0000 +++ b/ChangeLog.API Mon Mar 22 21:45:23 2010 +0000 @@ -31,6 +31,7 @@ * pidgin_dialogs_developers (should not be used by anything but Pidgin) * pidgin_dialogs_translators (should not be used by anything but Pidgin) * gtk_imhtmltoolbar_switch_active_conversation + * 'paste' signal for GtkIMHtml (more in gtkimhtml-signals.dox) version 2.6.6 (02/18/2010): libpurple: diff -r 93f6a5d48a46 -r f14cbb6a28a7 Makefile.am --- a/Makefile.am Sun Mar 21 20:57:29 2010 +0000 +++ b/Makefile.am Mon Mar 22 21:45:23 2010 +0000 @@ -71,22 +71,24 @@ gpg --verify pidgin-$(PACKAGE_VERSION).tar.gz.asc pidgin-$(PACKAGE_VERSION).tar.gz gpg --verify pidgin-$(PACKAGE_VERSION).tar.bz2.asc pidgin-$(PACKAGE_VERSION).tar.bz2 +if INSTALL_I18N +PO_DIR=po +DESKTOP_FILE=pidgin.desktop + if ENABLE_GTK appsdir = $(datadir)/applications apps_in_files = pidgin.desktop.in apps_DATA = $(apps_in_files:.desktop.in=.desktop) @INTLTOOL_DESKTOP_RULE@ GTK_DIR=pidgin -endif +endif #ENABLE_GTK + +endif #INSTALL_I18N if ENABLE_GNT GNT_DIR=finch endif -if INSTALL_I18N -PO_DIR=po -endif - # This is phony, so that we always try to rebuild it. If it succeeds # in calculating changes, it produces its target; otherwise, its # target does not exist. @@ -146,5 +148,5 @@ distuninstallcheck_listfiles = \ find . -type f -print | grep -v perl | grep -v Purple.3pm -DISTCLEANFILES= pidgin.desktop libpurple/gconf/purple.schemas intltool-extract \ +DISTCLEANFILES= $(DESKTOP_FILE) libpurple/gconf/purple.schemas intltool-extract \ intltool-merge intltool-update diff -r 93f6a5d48a46 -r f14cbb6a28a7 configure.ac --- a/configure.ac Sun Mar 21 20:57:29 2010 +0000 +++ b/configure.ac Mon Mar 22 21:45:23 2010 +0000 @@ -112,61 +112,8 @@ AC_PROG_LIBTOOL LIBTOOL="$LIBTOOL --silent" AC_PROG_INSTALL -AC_PROG_INTLTOOL PKG_PROG_PKG_CONFIG AC_FUNC_ALLOCA -GETTEXT_PACKAGE=pidgin -AC_SUBST(GETTEXT_PACKAGE) - - -# before gettexting, in case iconv matters -case "$host_os" in -darwin*) - AC_CHECK_LIB(resolv, res_query) - - AC_CHECK_HEADER(CoreFoundation/CoreFoundation.h, [ - AC_CHECK_HEADER(IOKit/IOKitLib.h, [ - AC_DEFINE(HAVE_IOKIT, 1, [Define if we have IOKit]) - LIBS="$LIBS -framework IOKit -framework CoreFoundation" - ], []) - ], []) - - AC_MSG_CHECKING([for fink]) - if test -d /sw; then - AC_MSG_RESULT([found, adding /sw to search paths]) - CPPFLAGS="$CPPFLAGS -I/sw/include" - LDFLAGS="$LDFLAGS -L/sw/lib" - else - AC_MSG_RESULT([not found]) - fi - ;; -*) - ;; -esac - -ALL_LINGUAS="af am ar az be@latin bg bn bs ca ca@valencia cs da de dz el en_AU en_CA en_GB eo es et eu fa fi fr ga gl gu he hi hu hy id it ja ka km kn ko ku lo lt mk mn mr ms_MY my_MM nb ne nl nn oc or pa pl pt_BR pt ps ro ru si sk sl sq sr sr@latin sv sw ta te th tr uk ur vi xh zh_CN zh_HK zh_TW" -AM_GLIB_GNU_GETTEXT - -dnl If we don't have msgfmt, then po/ is going to fail -- ensure that -dnl AM_GLIB_GNU_GETTEXT found it. - -if test x$MSGFMT = xno -o x$MSGFMT$GMSGFMT$INTLTOOL_MSGFMT = x -then - AC_MSG_ERROR([ - -The msgfmt command is required to build libpurple. If it is installed -on your system, ensure that it is in your path. If it is not, install -GNU gettext to continue. - -If you have msgfmt installed, but for some reason this error message -is still displayed, you have encountered what appears to be a bug in -third-party configure macros. Try setting the MSGFMT environment -variable to the absolute path to your msgfmt binary and trying -configure again, like this: - -MSGFMT=/path/to/msgfmt ./configure ... -]) -fi dnl Checks for header files. AC_HEADER_STDC @@ -306,6 +253,67 @@ ]) dnl ####################################################################### +dnl # Disable creation and installation of translation files +dnl ####################################################################### +AC_ARG_ENABLE(nls, AC_HELP_STRING([--disable-nls], [disable installation of translation files]), enable_i18n="$enableval", enable_i18n=yes) + +if test x$enable_i18n = xyes; then + AC_PROG_INTLTOOL + GETTEXT_PACKAGE=pidgin + AC_SUBST(GETTEXT_PACKAGE) + + + # before gettexting, in case iconv matters + case "$host_os" in + darwin*) + AC_CHECK_LIB(resolv, res_query) + + AC_CHECK_HEADER(CoreFoundation/CoreFoundation.h, [ + AC_CHECK_HEADER(IOKit/IOKitLib.h, [ + AC_DEFINE(HAVE_IOKIT, 1, [Define if we have IOKit]) + LIBS="$LIBS -framework IOKit -framework CoreFoundation" + ], []) + ], []) + + AC_MSG_CHECKING([for fink]) + if test -d /sw; then + AC_MSG_RESULT([found, adding /sw to search paths]) + CPPFLAGS="$CPPFLAGS -I/sw/include" + LDFLAGS="$LDFLAGS -L/sw/lib" + else + AC_MSG_RESULT([not found]) + fi + ;; + *) + ;; + esac + + ALL_LINGUAS="af am ar az be@latin bg bn bs ca ca@valencia cs da de dz el en_AU en_CA en_GB eo es et eu fa fi fr ga gl gu he hi hu hy id it ja ka km kn ko ku lo lt mk mn mr ms_MY my_MM nb ne nl nn oc or pa pl pt_BR pt ps ro ru si sk sl sq sr sr@latin sv sw ta te th tr uk ur vi xh zh_CN zh_HK zh_TW" + AM_GLIB_GNU_GETTEXT + + dnl If we don't have msgfmt, then po/ is going to fail -- ensure that + dnl AM_GLIB_GNU_GETTEXT found it. + + if test x$MSGFMT = xno -o x$MSGFMT$GMSGFMT$INTLTOOL_MSGFMT = x + then + AC_MSG_ERROR([ + +The msgfmt command is required to build libpurple. If it is installed +on your system, ensure that it is in your path. If it is not, install +GNU gettext to continue. + +If you have msgfmt installed, but for some reason this error message +is still displayed, you have encountered what appears to be a bug in +third-party configure macros. Try setting the MSGFMT environment +variable to the absolute path to your msgfmt binary and trying +configure again, like this: + +MSGFMT=/path/to/msgfmt ./configure ... + ]) + fi +fi #enable_i18n + +dnl ####################################################################### dnl # Check for GLib 2.12 (required) dnl ####################################################################### PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.12.0 gobject-2.0 gmodule-2.0 gthread-2.0], , [ @@ -2443,11 +2451,6 @@ AM_CONDITIONAL(INSTALL_PIXMAPS, test "x$enable_pixmaps" = "xyes") -dnl ####################################################################### -dnl # Disable installation of translation files -dnl ####################################################################### -AC_ARG_ENABLE(nls, AC_HELP_STRING([--disable-nls], [disable installation of translation files]), enable_i18n="$enableval", enable_i18n=yes) - AM_CONDITIONAL(INSTALL_I18N, test "x$enable_i18n" = "xyes") dnl ####################################################################### @@ -2642,7 +2645,13 @@ if test "x$enable_pixmaps" = "xno" ; then echo echo Warning: You have disabled the installation of pixmap data, but Pidgin - echo still requires installed pixmaps. Be sure you know what you\'re doing. + echo still requires installed pixmaps. Be sure you know what you are doing. +fi +if test "x$enable_i18n" = "xno" ; then + echo + echo Warning: You have disabled the building and intallation of translation + echo data. This will prevent building pidgin.desktop and the GConf schemas. + echo Be sure you know what you are doing. fi echo echo configure complete, now type \'make\' diff -r 93f6a5d48a46 -r f14cbb6a28a7 doc/gtkimhtml-signals.dox --- a/doc/gtkimhtml-signals.dox Sun Mar 21 20:57:29 2010 +0000 +++ b/doc/gtkimhtml-signals.dox Mon Mar 22 21:45:23 2010 +0000 @@ -6,6 +6,7 @@ @signal format_function_clear @signal format_function_toggle @signal format_function_update + @paste @endsignals @see gtkimhtml.h @@ -57,6 +58,17 @@ @signaldesc Emitted when the cursor has moved and formatting has changed @param imhtml The GtkIMHtml emitting the signal. @param data User defined data. + + @signaldef paste + @signalproto +void (*paste) (GtkIMHtml *imhtml, char *format) + @endsignalproto + @signaldef Emitted when paste from the clipboard is requested. + @param imhtml The GtkIMHtml emitting the signal. + @param format If 'text', then the formatting of the clipboard content + will be removed before pasting. If empty or 'html', then + the formatting will not be removed. Any other value for + this parameter is ignored and nothing is pasted. @endsignaldef */ // vim: syntax=c.doxygen tw=75 et diff -r 93f6a5d48a46 -r f14cbb6a28a7 doc/gtkrc-2.0 --- a/doc/gtkrc-2.0 Sun Mar 21 20:57:29 2010 +0000 +++ b/doc/gtkrc-2.0 Mon Mar 22 21:45:23 2010 +0000 @@ -81,6 +81,12 @@ bind "F2" { "format_toggle" (2) } # Ctrl-alt-shift-f3 toggles underline bind "F3" { "format_toggle" (4) } + +# Ctrl-v to paste as plain text + bind "v" { "paste" ("text") } + +# Ctrl-Shift-v for normal 'Paste' + bind "v" { "paste" ("html") } } widget "*pidgin_conv_entry" binding "my-bindings" diff -r 93f6a5d48a46 -r f14cbb6a28a7 libpurple/gconf/Makefile.am --- a/libpurple/gconf/Makefile.am Sun Mar 21 20:57:29 2010 +0000 +++ b/libpurple/gconf/Makefile.am Mon Mar 22 21:45:23 2010 +0000 @@ -2,14 +2,17 @@ EXTRA_DIST = purple.schemas.in +if GCONF_SCHEMAS_INSTALL + +if INSTALL_I18N schema_in_files = purple.schemas.in schema_DATA = $(schema_in_files:.schemas.in=.schemas) @INTLTOOL_SCHEMAS_RULE@ +endif #INSTALL_I18N -if GCONF_SCHEMAS_INSTALL install-data-local: GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(schema_DATA) 2>&1 | \ grep -v "^WARNING: failed to install schema" | grep -v "^Attached schema" 1>&2 else install-data-local: -endif +endif #GCONF_SCHEMAS_INSTALL diff -r 93f6a5d48a46 -r f14cbb6a28a7 libpurple/protocols/jabber/auth.c --- a/libpurple/protocols/jabber/auth.c Sun Mar 21 20:57:29 2010 +0000 +++ b/libpurple/protocols/jabber/auth.c Mon Mar 22 21:45:23 2010 +0000 @@ -287,7 +287,7 @@ x = xmlnode_new_child(query, "digest"); s = g_strdup_printf("%s%s", js->stream_id, pw); - hash = jabber_calculate_data_sha1sum(s, strlen(s)); + hash = jabber_calculate_data_hash(s, strlen(s), "sha1"); xmlnode_insert_data(x, hash, -1); g_free(hash); g_free(s); diff -r 93f6a5d48a46 -r f14cbb6a28a7 libpurple/protocols/jabber/buddy.c --- a/libpurple/protocols/jabber/buddy.c Sun Mar 21 20:57:29 2010 +0000 +++ b/libpurple/protocols/jabber/buddy.c Mon Mar 22 21:45:23 2010 +0000 @@ -516,7 +516,8 @@ binval = xmlnode_new_child(photo, "BINVAL"); enc = purple_base64_encode(avatar_data, avatar_len); - js->avatar_hash = jabber_calculate_data_sha1sum(avatar_data, avatar_len); + js->avatar_hash = + jabber_calculate_data_hash(avatar_data, avatar_len, "sha1"); xmlnode_insert_data(binval, enc, -1); g_free(enc); @@ -936,7 +937,7 @@ g_free(bintext); if (data) { - vcard_hash = jabber_calculate_data_sha1sum(data, size); + vcard_hash = jabber_calculate_data_hash(data, size, "sha1"); g_free(data); } } @@ -1185,7 +1186,7 @@ purple_notify_user_info_add_pair(user_info, (photo ? _("Photo") : _("Logo")), img_text); - hash = jabber_calculate_data_sha1sum(data, size); + hash = jabber_calculate_data_hash(data, size, "sha1"); purple_buddy_icons_set_for_user(account, bare_jid, data, size, hash); g_free(hash); g_free(img_text); diff -r 93f6a5d48a46 -r f14cbb6a28a7 libpurple/protocols/jabber/data.c --- a/libpurple/protocols/jabber/data.c Sun Mar 21 20:57:29 2010 +0000 +++ b/libpurple/protocols/jabber/data.c Mon Mar 22 21:45:23 2010 +0000 @@ -39,7 +39,7 @@ gboolean ephemeral, JabberStream *js) { JabberData *data = g_new0(JabberData, 1); - gchar *checksum = jabber_calculate_data_sha1sum(rawdata, size); + gchar *checksum = jabber_calculate_data_hash(rawdata, size, "sha1"); gchar cid[256]; g_snprintf(cid, sizeof(cid), "sha1+%s@bob.xmpp.org", checksum); @@ -55,6 +55,69 @@ return data; } + +static gboolean +jabber_data_has_valid_hash(const JabberData *data) +{ + const gchar *cid = jabber_data_get_cid(data); + gchar **cid_parts = g_strsplit(cid, "@", -1); + gchar **iter; + int num_parts = 0; + + purple_debug_info("jabber", "validating BoB hash %s\n", cid); + + for (iter = cid_parts; *iter != NULL ; iter++) { + num_parts++; + } + + if (num_parts == 2 && purple_strequal(cid_parts[1], "bob.xmpp.org")) { + gchar **sub_parts = g_strsplit(cid_parts[0], "+", -1); + + num_parts = 0; + for (iter = sub_parts ; *iter != NULL ; iter++) { + num_parts++; + } + + if (num_parts == 2) { + const gchar *hash_algo = sub_parts[0]; + const gchar *hash_value = sub_parts[1]; + gchar *digest = + jabber_calculate_data_hash(jabber_data_get_data(data), + jabber_data_get_size(data), hash_algo); + + purple_debug_info("jabber", "BoB expecting hash: %s\n", digest); + + if (digest) { + gboolean result = purple_strequal(digest, hash_value); + + if (!result) { + purple_debug_error("jabber", "invalid BoB hash\n"); + } + g_free(digest); + return result; + } else { + purple_debug_info("jabber", "unknown BoB hash algo\n"); + return FALSE; + } + } else { + return TRUE; + } + } else { + return TRUE; + } +} + +static void +jabber_data_delete(gpointer cbdata) +{ + JabberData *data = cbdata; + g_free(data->cid); + g_free(data->type); + g_free(data->data); + g_free(data); +} + + JabberData * jabber_data_create_from_xml(xmlnode *tag) { @@ -97,6 +160,11 @@ data->cid = g_strdup(cid); data->type = g_strdup(type); + if (!jabber_data_has_valid_hash(data)) { + jabber_data_delete(data); + return NULL; + } + return data; } @@ -212,8 +280,12 @@ if (!ephemeral) { jabber_data_associate_remote(data); } - /* TODO: validate hash */ cb(data, alt, userdata); + } else { + /* could not validate hash when creating data from XML */ + purple_debug_info("jabber", + "hash validation failed on requested BoB object\n"); + cb(NULL, alt, userdata); } } else if (item_not_found) { purple_debug_info("jabber", diff -r 93f6a5d48a46 -r f14cbb6a28a7 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Sun Mar 21 20:57:29 2010 +0000 +++ b/libpurple/protocols/jabber/jabber.c Mon Mar 22 21:45:23 2010 +0000 @@ -980,8 +980,8 @@ image = purple_buddy_icons_find_account_icon(account); if (image != NULL) { js->initial_avatar_hash = - jabber_calculate_data_sha1sum(purple_imgstore_get_data(image), - purple_imgstore_get_size(image)); + jabber_calculate_data_hash(purple_imgstore_get_data(image), + purple_imgstore_get_size(image), "sha1"); purple_imgstore_unref(image); } diff -r 93f6a5d48a46 -r f14cbb6a28a7 libpurple/protocols/jabber/jutil.c --- a/libpurple/protocols/jabber/jutil.c Sun Mar 21 20:57:29 2010 +0000 +++ b/libpurple/protocols/jabber/jutil.c Mon Mar 22 21:45:23 2010 +0000 @@ -728,17 +728,17 @@ return NULL; } -/* The same as purple_util_get_image_checksum, but guaranteed to remain SHA1 */ char * -jabber_calculate_data_sha1sum(gconstpointer data, size_t len) +jabber_calculate_data_hash(gconstpointer data, size_t len, + const gchar *hash_algo) { PurpleCipherContext *context; static gchar digest[41]; - context = purple_cipher_context_new_by_name("sha1", NULL); + context = purple_cipher_context_new_by_name(hash_algo, NULL); if (context == NULL) { - purple_debug_error("jabber", "Could not find sha1 cipher\n"); + purple_debug_error("jabber", "Could not find %s cipher\n", hash_algo); g_return_val_if_reached(NULL); } @@ -746,7 +746,8 @@ purple_cipher_context_append(context, data, len); if (!purple_cipher_context_digest_to_str(context, sizeof(digest), digest, NULL)) { - purple_debug_error("jabber", "Failed to get SHA-1 digest.\n"); + purple_debug_error("jabber", "Failed to get digest for %s cipher.\n", + hash_algo); g_return_val_if_reached(NULL); } purple_cipher_context_destroy(context); diff -r 93f6a5d48a46 -r f14cbb6a28a7 libpurple/protocols/jabber/jutil.h --- a/libpurple/protocols/jabber/jutil.h Sun Mar 21 20:57:29 2010 +0000 +++ b/libpurple/protocols/jabber/jutil.h Mon Mar 22 21:45:23 2010 +0000 @@ -85,5 +85,6 @@ /* show attr (presence stanza) -> state */ JabberBuddyState jabber_buddy_show_get_state(const char *id); -char *jabber_calculate_data_sha1sum(gconstpointer data, size_t len); +char *jabber_calculate_data_hash(gconstpointer data, size_t len, + const gchar *hash_algo); #endif /* PURPLE_JABBER_JUTIL_H_ */ diff -r 93f6a5d48a46 -r f14cbb6a28a7 libpurple/protocols/jabber/message.c --- a/libpurple/protocols/jabber/message.c Sun Mar 21 20:57:29 2010 +0000 +++ b/libpurple/protocols/jabber/message.c Mon Mar 22 21:45:23 2010 +0000 @@ -474,7 +474,10 @@ if (!data && cid != NULL) { /* we haven't cached this already, let's add it */ JabberData *new_data = jabber_data_create_from_xml(data_tag); - jabber_data_associate_remote(new_data); + + if (new_data) { + jabber_data_associate_remote(new_data); + } } } } diff -r 93f6a5d48a46 -r f14cbb6a28a7 libpurple/protocols/jabber/presence.c --- a/libpurple/protocols/jabber/presence.c Sun Mar 21 20:57:29 2010 +0000 +++ b/libpurple/protocols/jabber/presence.c Mon Mar 22 21:45:23 2010 +0000 @@ -457,7 +457,7 @@ data = purple_base64_decode(text, &size); if (data) { - gchar *hash = jabber_calculate_data_sha1sum(data, size); + gchar *hash = jabber_calculate_data_hash(data, size, "sha1"); purple_buddy_icons_set_for_user(js->gc->account, from, data, size, hash); g_free(hash); diff -r 93f6a5d48a46 -r f14cbb6a28a7 libpurple/protocols/jabber/si.c --- a/libpurple/protocols/jabber/si.c Sun Mar 21 20:57:29 2010 +0000 +++ b/libpurple/protocols/jabber/si.c Mon Mar 22 21:45:23 2010 +0000 @@ -290,7 +290,7 @@ jsx->js->user->node, jsx->js->user->domain, jsx->js->user->resource); /* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */ - hash = jabber_calculate_data_sha1sum(dstaddr, strlen(dstaddr)); + hash = jabber_calculate_data_hash(dstaddr, strlen(dstaddr), "sha1"); jsx->connect_data = purple_proxy_connect_socks5(NULL, jsx->gpi, hash, 0, @@ -475,7 +475,7 @@ jsx->js->user->resource, xfer->who); /* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */ - hash = jabber_calculate_data_sha1sum(dstaddr, strlen(dstaddr)); + hash = jabber_calculate_data_hash(dstaddr, strlen(dstaddr), "sha1"); if(strncmp(hash, jsx->rxqueue + 5, 40) || jsx->rxqueue[45] != 0x00 || jsx->rxqueue[46] != 0x00) { diff -r 93f6a5d48a46 -r f14cbb6a28a7 libpurple/protocols/jabber/useravatar.c --- a/libpurple/protocols/jabber/useravatar.c Sun Mar 21 20:57:29 2010 +0000 +++ b/libpurple/protocols/jabber/useravatar.c Mon Mar 22 21:45:23 2010 +0000 @@ -149,8 +149,9 @@ char *lengthstring, *widthstring, *heightstring; /* compute the sha1 hash */ - char *hash = jabber_calculate_data_sha1sum(purple_imgstore_get_data(img), - purple_imgstore_get_size(img)); + char *hash = jabber_calculate_data_hash(purple_imgstore_get_data(img), + purple_imgstore_get_size(img), + "sha1"); char *base64avatar = purple_base64_encode(purple_imgstore_get_data(img), purple_imgstore_get_size(img)); diff -r 93f6a5d48a46 -r f14cbb6a28a7 pidgin/gtkimhtml.c --- a/pidgin/gtkimhtml.c Sun Mar 21 20:57:29 2010 +0000 +++ b/pidgin/gtkimhtml.c Mon Mar 22 21:45:23 2010 +0000 @@ -152,6 +152,7 @@ MESSAGE_SEND, UNDO, REDO, + PASTE, LAST_SIGNAL }; static guint signals [LAST_SIGNAL] = { 0 }; @@ -1343,6 +1344,15 @@ return FALSE; } +static void +imhtml_paste_cb(GtkIMHtml *imhtml, const char *str) +{ + if (!str || !*str || !strcmp(str, "html")) + g_signal_emit_by_name(imhtml, "paste_clipboard"); + else if (!strcmp(str, "text")) + paste_unformatted_cb(NULL, imhtml); +} + static void imhtml_toggle_format(GtkIMHtml *imhtml, GtkIMHtmlButtons buttons) { /* since this function is the handler for the formatting keystrokes, @@ -1513,24 +1523,31 @@ NULL, 0, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - signals [UNDO] = g_signal_new ("undo", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (GtkIMHtmlClass, undo), - NULL, - NULL, - gtksourceview_marshal_VOID__VOID, - G_TYPE_NONE, - 0); - signals [REDO] = g_signal_new ("redo", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (GtkIMHtmlClass, redo), - NULL, - NULL, - gtksourceview_marshal_VOID__VOID, - G_TYPE_NONE, - 0); + signals[PASTE] = g_signal_new("paste", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, + NULL, + 0, g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); + signals [UNDO] = g_signal_new ("undo", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkIMHtmlClass, undo), + NULL, + NULL, + gtksourceview_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + signals [REDO] = g_signal_new ("redo", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkIMHtmlClass, redo), + NULL, + NULL, + gtksourceview_marshal_VOID__VOID, + G_TYPE_NONE, + 0); @@ -1615,10 +1632,10 @@ gtk_binding_entry_add_signal (binding_set, GDK_r, GDK_CONTROL_MASK, "format_function_clear", 0); gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "message_send", 0); gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "message_send", 0); - gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK, "undo", 0); - gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "redo", 0); - gtk_binding_entry_add_signal (binding_set, GDK_F14, 0, "undo", 0); - + gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK, "undo", 0); + gtk_binding_entry_add_signal (binding_set, GDK_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "redo", 0); + gtk_binding_entry_add_signal (binding_set, GDK_F14, 0, "undo", 0); + gtk_binding_entry_add_signal(binding_set, GDK_v, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "paste", 1, G_TYPE_STRING, "text"); } static void gtk_imhtml_init (GtkIMHtml *imhtml) @@ -1689,6 +1706,7 @@ g_signal_connect(G_OBJECT(imhtml), "paste-clipboard", G_CALLBACK(paste_clipboard_cb), NULL); g_signal_connect_after(G_OBJECT(imhtml), "realize", G_CALLBACK(imhtml_realized_remove_primary), NULL); g_signal_connect(G_OBJECT(imhtml), "unrealize", G_CALLBACK(imhtml_destroy_add_primary), NULL); + g_signal_connect(G_OBJECT(imhtml), "paste", G_CALLBACK(imhtml_paste_cb), NULL); #ifndef _WIN32 g_signal_connect_after(G_OBJECT(GTK_IMHTML(imhtml)->text_buffer), "mark-set",