# HG changeset patch # User Richard Laager # Date 1333686600 0 # Node ID f01d6c9f34921b0d837aa900411eff769a6f4a2b # Parent cc258d58ee56cd524834146ea05d15dd300f23c5# Parent 2908b16efa070107ff541d4694795c02c298e246 explicit merge of 'c5b3879b829a5067b2189e4393ca3b80f6fd96c3' and '90634d4a19f4639f388839e3efc46791f1ee31ab' to branch 'im.pidgin.pidgin' diff -r 2908b16efa07 -r f01d6c9f3492 COPYRIGHT --- a/COPYRIGHT Mon Apr 02 23:36:20 2012 +0000 +++ b/COPYRIGHT Fri Apr 06 04:30:00 2012 +0000 @@ -24,6 +24,7 @@ Manuel Amador Matt Amato Josef Andrysek +Flavius Anton Geoffrey Antos Daniel Atallah Paul Aurich @@ -107,6 +108,7 @@ Ka-Hing Cheung Sadrul Habib Chowdhury Brian Chu +Howard Chu Arturo Cisneros, Jr. Vincas Ciziunas Jonathan Clark @@ -428,6 +430,7 @@ David Reiss Luoh Ren-Shan Noa Resare +Tim Retout Daniele Ricci Kristian Rietveld Pekka Riikonen diff -r 2908b16efa07 -r f01d6c9f3492 ChangeLog --- a/ChangeLog Mon Apr 02 23:36:20 2012 +0000 +++ b/ChangeLog Fri Apr 06 04:30:00 2012 +0000 @@ -1,5 +1,51 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +version 3.0.0 (??/??/????): + Finch: + * Support the conversation-extended signal for extending the + conversation menu. (Howard Chu) (#14818) + + AIM and ICQ: + * Make buddy list management code more efficient. (Oliver) (#4816) + + Bonjour: + * Support file transfers up to ~9 EiB. + + Gadu-Gadu: + * Possibility to require encryption. Also, using encryption when + available is default option now. (Tomasz Wasilczyk) + * Show local time for incoming messages. (Tomasz Wasilczyk) (#4579) + * Fixed password change dialog and problems with connecting to accounts + with non-ASCII passwords. (Tomasz Wasilczyk) (#14652) + * Option to show links from strangers. (Tomasz Wasilczyk) (#10591) + * Better handling of "invisible" and "chatty" statuses. (Tomasz + Wasilczyk) (#13836) + + MSN: + * Fix file transfer with older Mac MSN clients. + * Support file transfers up to ~9 EiB. + * Fix buddies not going offline. + + MXit: + * Remove all reference to Hidden Number. + * Fix decoding of font-size changes in the markup of received messages. + * Ignore new invites to join a GroupChat if you're already joined, or + still have a pending invite. + * The buddy's name was not centered vertically in the buddy-list if they + did not have a status-message or mood set. + + XMPP: + * Strip element prefixes from XHTML-IM messages as they're presented + to the core (and UIs) as incoming messages (Thijs Alkemade). + (#14529) + * Support file transfers up to ~9 EiB. + + Plugins: + * The Voice/Video Settings plugin supports using the sndio GStreamer + backends. (Brad Smith) (#14414) + * The Offline Message Emulation plugin now adds a note that the message + was an offline message. (Flavius Anton) (#2497) + version 2.10.4: TODO diff -r 2908b16efa07 -r f01d6c9f3492 ChangeLog.API --- a/ChangeLog.API Mon Apr 02 23:36:20 2012 +0000 +++ b/ChangeLog.API Fri Apr 06 04:30:00 2012 +0000 @@ -1,5 +1,252 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +version 3.0.0 (??/??/????): + libpurple: + Added: + * pidgin_create_webview + * purple_account_is_disconnecting + * purple_account_get_ui_data + * purple_account_set_ui_data + * purple_account_register_completed + * purple_certificate_get_der_data + * purple_certificate_get_display_string + * purple_conv_chat_cb_get_alias + * purple_conv_chat_cb_get_flags + * purple_conv_chat_cb_is_buddy + * purple_conv_chat_cb_get_ui_data + * purple_conv_chat_cb_set_ui_data + * purple_connection_get_flags + * purple_connection_set_flags + * purple_connection_update_last_received + * purple_conversation_get_ui_data + * purple_conversation_set_ui_data + * purple_conversation_message_get_alias + * purple_conversation_message_get_conv + * purple_contact_get_contact_size + * purple_notify_searchresult_column_get_title + * purple_notify_searchresult_column_is_visible + * purple_notify_searchresult_column_set_visible + * purple_notify_user_info_prepend_pair_plaintext + * purple_menu_action_get_callback + * purple_menu_action_get_children + * purple_menu_action_get_data + * purple_menu_action_set_label + * purple_menu_action_set_data + * purple_menu_action_set_callback + * purple_menu_action_set_children + * purple_request_certificate + * purple_request_field_certificate_new + * purple_request_field_certificate_get_value + * purple_request_field_get_tooltip + * purple_request_field_group_get_fields_list + * purple_request_field_set_tooltip + * purple_request_fields_get_ui_data + * purple_request_fields_set_ui_data + * purple_roomlist_get_account + * purple_roomlist_get_proto_data + * purple_roomlist_get_ui_data + * purple_roomlist_room_get_expanded_once + * purple_roomlist_room_set_expanded_once + * purple_roomlist_set_proto_data + * purple_roomlist_set_ui_data + * purple_whiteboard_get_account + * purple_whiteboard_get_draw_list + * purple_whiteboard_set_draw_list + * purple_whiteboard_get_protocol_data + * purple_whiteboard_set_protocol_data + * purple_whiteboard_get_state + * purple_whiteboard_set_state + * purple_whiteboard_get_ui_data + * purple_whiteboard_set_ui_data + * purple_whiteboard_get_who + * purple_xfer_get_fd + * purple_xfer_get_protocol_data + * purple_xfer_get_ui_data + * purple_xfer_get_watcher + * purple_xfer_set_fd + * purple_xfer_set_local_port + * purple_xfer_set_protocol_data + * purple_xfer_set_status + * purple_xfer_set_ui_data + * purple_xfer_set_watcher + * Various WebKit-related functions in gtkwebview.h + * xmlnode_get_default_namespace + * xmlnode_strip_prefixes + + Changed: + * purple_account_add_buddy now takes an invite message as the last + parameter + * purple_account_add_buddies now takes an invite message as the last + parameter + * purple_certificate_check_signature_chain now returns a list of failing + PurpleCertificate*s as the second parameter + * purple_connection_error now takes a PurpleConnectionError + as the second parameter + * purple_conversation_get_gc renamed to + purple_conversation_get_connection + * purple_dnsquery_a now takes a PurpleAccount as the first parameter + * purple_network_listen now takes the protocol family as the second + parameter + * purple_network_listen now takes a boolean indicating external port + mapping as the fourth parameter + * purple_network_listen_range now takes a boolean indicating external + port mapping as the fifth parameter + * purple_network_listen_range now takes the protocol family as the + third parameter + * purple_notify_user_info_add_pair renamed to + purple_notify_user_info_add_pair_html + * purple_notify_user_info_get_entries returns a GQueue instead of + a GList + * purple_notify_user_info_prepend_pair renamed to + purple_notify_user_info_prepend_pair_html + * purple_srv_resolve now takes a PurpleAccount as the first parameter + * purple_str_size_to_units now takes a goffset as the size parameter + * purple_txt_resolve now takes a PurpleAccount as the first parameter + * purple_util_fetch_url_request now takes a PurpleAccount as + the first parameter + * purple_util_fetch_url_request now takes a length as the eighth + parameter + * purple_util_fetch_url_len now takes a length as the fifth parameter + * purple_xfer_get_bytes_remaining now returns a goffset + * purple_xfer_get_bytes_sent now returns a goffset + * purple_xfer_get_size now returns a goffset + * purple_xfer_is_canceled renamed to purple_xfer_is_cancelled + * purple_xfer_set_bytes_sent now takes a goffset as the bytes_sent + parameter + * purple_xfer_set_size now takes a goffset as the size parameter + * PurpleConnectionUiOps.report_disconnect now passes a + PurpleConnectionError as the second parameter + * PurpleXfer.bytes_remaining is now a goffset + * PurpleXfer.bytes_sent is now a goffset + * PurpleXfer.size is now a goffset + + Removed: + * _GntFileType + * _GntKeyPressMode + * _GntMouseEvent + * _GntParamFlags + * _GntProgressBarOrientation + * _GntTreeColumnFlag + * _GntWidgetFlags + * _PurpleCipherBatchMode + * _PurpleCipherCaps + * _PurpleCmdFlag + * _PurpleCmdPriority + * _PurpleCmdRet + * _PurpleCmdStatus + * _PurplePrefType + * _PurplePrivacyType + * _PurpleSoundEventID + * _XMLNodeType + * GtkIMHtml.clipboard_html_string + * GtkIMHtml.clipboard_text_string + * GtkIMHtmlFontDetail + * gtk_imhtml_animation_free + * gtk_imhtml_animation_new + * gtk_imhtml_image_add_to + * gtk_imhtml_image_free + * gtk_imhtml_image_new + * gtk_imhtml_image_scale + * pidgin_blist_update_account_error_state + * pidgin_check_if_dir + * PIDGIN_DIALOG + * pidgin_dialogs_alias_contact + * pidgin_set_custom_buddy_icon + * pidgin_setup_screenname_autocomplete + * PidginBuddyList.connection_errors + * PidginConversation.sg + * purple_account_add_buddies_with_invite + * purple_account_add_buddy_with_invite + * purple_blist_update_buddy_icon + * purple_buddy_get_local_alias + * purple_buddy_icons_has_custom_icon + * purple_buddy_icons_find_custom_icon + * purple_buddy_icons_set_custom_icon + * purple_certificate_check_signature_chain_with_failing. Use + purple_certificate_check_signature_chain, instead + * purple_certificate_display_x509. Use purple_request_certificate, + instead + * purple_connection_error_reason + * purple_connection_new + * purple_connection_new_unregister + * purple_connection_destroy + * purple_contact_set_alias + * purple_conv_chat_set_users + * purple_core_migrate + * purple_dnsquery_a_account + * purple_network_listen_family. Use purple_network_listen, instead. + * purple_network_listen_map_external + * purple_network_listen_range_family. Use purple_network_listen, + instead. + * purple_notify_searchresults_column_get_title + * purple_notify_searchresults_get_columns_count + * purple_notify_searchresults_get_rows_count + * purple_notify_searchresults_row_get + * purple_plugins_register_load_notify_cb + * purple_plugins_register_probe_notify_cb + * purple_plugins_register_unload_notify_cb + * purple_plugins_unregister_load_notify_cb + * purple_plugins_unregister_probe_notify_cb + * purple_plugins_unregister_unload_notify_cb + * purple_presence_add_status + * purple_presence_add_list + * purple_proxy_connect_socks5 + * purple_request_field_list_add + * purple_srv_cancel + * purple_srv_resolve_account + * purple_ssl_connect_fd + * purple_status_set_attr_boolean + * purple_status_set_attr_int + * purple_status_set_attr_string + * purple_status_type_add_attr + * purple_status_type_add_attrs + * purple_status_type_add_attrs_vargs + * purple_status_type_get_primary_attr + * purple_status_type_set_primary_attr + * purple_strlcat + * purple_strlcpy + * purple_txt_cancel + * purple_txt_resolve_account + * purple_util_fetch_url_len. Use purple_util_fetch_url, instead. + * purple_util_fetch_url_request_len. Use + * purple_util_fetch_url_request, instead. + * purple_util_fetch_url_request_len_with_account. Use + purple_util_fetch_url_request, instead. + * PurpleConnectionUiOps.report_disconnect_reason + * PurplePluginProtocolInfo.add_buddy_with_invite + * PurplePluginProtocolInfo.add_buddies_with_invite + * PurplePluginProtocolInfo.get_cb_away + * serv_got_attention + * serv_send_attention + * struct _GtkIMHtmlAnimation + * struct _GtkIMHtmlFontDetail + * struct _GtkIMHtmlHr + * struct _GtkIMHtmlImage + * struct _GtkIMHtmlScalable + * struct _GtkSmileyTree + * struct _PidginChatPane + * struct _PidginImPane + * struct _PurpleAttentionType + * struct _PurpleConversation + * struct _PurpleConvChat + * struct _PurpleConvChatBuddy + * struct _PurpleConvIm + * struct _PurpleConvMessage + * struct _PurpleMenuAction + * struct _PurplePounce + * struct _PurpleProxyInfo + * struct _PurpleRequestField + * struct _PurpleRoomlist + * struct _PurpleRoomlistField + * struct _PurpleRoomlistRoom + * struct _PurpleWhiteboard + * struct PurpleAccountOption + * struct PurpleAccountUserSplit + * struct PurpleNotifySearchColumn + * wpurple_g_access + * xmlnode_set_attrib_with_namespace + * xmlnode_set_attrib_with_prefix + version 2.10.3: * No changes diff -r 2908b16efa07 -r f01d6c9f3492 Makefile.am --- a/Makefile.am Mon Apr 02 23:36:20 2012 +0000 +++ b/Makefile.am Fri Apr 06 04:30:00 2012 +0000 @@ -11,8 +11,6 @@ config.h.mingw \ doxy2devhelp.xsl \ fix-casts.sh \ - gaim.pc.in \ - gaim-uninstalled.pc.in \ intltool-extract.in \ intltool-merge.in \ intltool-update.in \ diff -r 2908b16efa07 -r f01d6c9f3492 configure.ac --- a/configure.ac Mon Apr 02 23:36:20 2012 +0000 +++ b/configure.ac Fri Apr 06 04:30:00 2012 +0000 @@ -43,10 +43,10 @@ # # Make sure to update finch/libgnt/configure.ac with libgnt version changes. # -m4_define([purple_lt_current], [10]) -m4_define([purple_major_version], [2]) -m4_define([purple_minor_version], [10]) -m4_define([purple_micro_version], [4]) +m4_define([purple_lt_current], [20]) +m4_define([purple_major_version], [3]) +m4_define([purple_minor_version], [0]) +m4_define([purple_micro_version], [0]) m4_define([purple_version_suffix], [devel]) m4_define([purple_version], [purple_major_version.purple_minor_version.purple_micro_version]) @@ -202,10 +202,10 @@ dnl FreeBSD doesn't have libdl, dlopen is provided by libc AC_CHECK_FUNC(dlopen, LIBDL="", [AC_CHECK_LIB(dl, dlopen, LIBDL="-ldl")]) -dnl Haiku does not use libm for the math functions, they are part +dnl Windows and Haiku do not use libm for the math functions, they are part dnl of the C library AC_SEARCH_LIBS([ceil], [m], [], [ - AC_MSG_ERROR([unable to find the floor() function]) + AC_MSG_ERROR([unable to find the ceil() function]) ]) AC_MSG_CHECKING(for fileno()) @@ -334,6 +334,9 @@ dnl ####################################################################### dnl # Check for GLib 2.16 (required) dnl ####################################################################### +# TODO: gmodule-2.0 is only needed if enable_plugins is 'yes'. It +# might be nice to change this check so that it's not required +# if enable_plugins is 'no'. PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.16.0 gobject-2.0 gmodule-2.0 gthread-2.0], , [ AC_MSG_RESULT(no) AC_MSG_ERROR([ @@ -404,6 +407,10 @@ [AC_HELP_STRING([--disable-gestures], [compile without the gestures plugin])], enable_gestures="$enableval", enable_gestures="yes") +AC_ARG_ENABLE(gcr, + [AC_HELP_STRING([--enable-gcr], + [compile with GCR certificate widgets])], + enable_gcr="$enableval", enable_gcr="no") AC_PATH_XTRA # We can't assume that $x_libraries will be set, because autoconf does not @@ -437,6 +444,16 @@ PKG_CHECK_MODULES(PANGO, [pango >= 1.4.0], AC_DEFINE(HAVE_PANGO14, 1, [Define if we have Pango 1.4 or newer.]),:) + PKG_CHECK_MODULES(WEBKIT, [webkit-1.0 >= 1.1.1], , [ + AC_MSG_RESULT(no) + AC_MSG_ERROR([ +You must have WebKit 1.1.1 or newer development headers installed to compile +Pidgin. If you want to build only Finch then specify --disable-gtkui when +running configure. +])]) + AC_SUBST(WEBKIT_CFLAGS) + AC_SUBST(WEBKIT_LIBS) + dnl ####################################################################### dnl # Check if we should compile with X support dnl ####################################################################### @@ -607,9 +624,26 @@ ]) fi]) fi - + + dnl ####################################################################### + dnl # Check for GCR for its certificate widgets + dnl ####################################################################### + if test "x$enable_gcr" = "xyes"; then + PKG_CHECK_MODULES(GCR, gcr-0, [ + AC_DEFINE(ENABLE_GCR, 1, [Define to 1 if GCR is found.])], [ + AC_MSG_RESULT(no) + enable_gcr="no" + if test "x$force_deps" = "xyes" ; then + AC_MSG_ERROR([ +GCR development headers not found. +Use --disable-gcr if you do not need GCR certificate widgets. +]) + fi]) + fi + else # GTK + enable_gcr=no enable_cap=no enable_gevolution=no enable_gtkspell=no @@ -622,6 +656,7 @@ AM_CONDITIONAL(BUILD_GEVOLUTION, test "x$enable_gevolution" = "xyes") AM_CONDITIONAL(ENABLE_CAP, test "x$enable_cap" = "xyes") AM_CONDITIONAL(ENABLE_GESTURES, test "x$enable_gestures" = "xyes") +AM_CONDITIONAL(ENABLE_GCR, test "x$enable_gcr" = "xyes") dnl ####################################################################### @@ -944,25 +979,6 @@ ], [ have_silc="no" ]) - if test "x$have_silc" = "xno"; then - PKG_CHECK_MODULES(SILC, silcclient, [ - have_silc="yes" - silc10includes="yes" - silc10client="yes" - ], [ - have_silc="no" - ]) - dnl If silcclient.pc wasn't found, check for just silc.pc - if test "x$have_silc" = "xno"; then - PKG_CHECK_MODULES(SILC, silc, [ - have_silc="yes" - silc10includes="yes" - silc10client="yes" - ], [ - have_silc="no" - ]) - fi - fi else if test "$ac_silc_includes" != "no"; then SILC_CFLAGS="-I$ac_silc_includes" @@ -980,17 +996,6 @@ if test "x$silcincludes" = "xyes" -a "x$silcclient" = "xyes"; then have_silc="yes" - else - CPPFLAGS_save="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $SILC_CFLAGS" - AC_CHECK_HEADER(silcincludes.h, [silc10includes=yes]) - CPPFLAGS="$CPPFLAGS_save" - - SILC_LIBS="$SILC_LIBS -lsilc -lsilcclient -lpthread $LIBDL" - AC_CHECK_LIB(silcclient, silc_client_init, [silc10client=yes], , $SILC_LIBS) - if test "x$silc10includes" = "xyes" -a "x$silc10client" = "xyes"; then - have_silc="yes" - fi fi fi AC_SUBST(SILC_LIBS) @@ -998,20 +1003,6 @@ dnl SILC Toolkit >= 1.0.1 has a new MIME API if test "x$silcclient" = "xyes"; then AC_DEFINE(HAVE_SILCMIME_H, 1, [Define if we have silcmime.h]) -elif test "x$silc10client" = "xyes"; then - CPPFLAGS_save="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $SILC_CFLAGS" - AC_MSG_CHECKING(for silcmime.h) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include -#include - ]], [[]])], [ - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_SILCMIME_H, 1, [Define if we have silcmime.h]) - ], [ - AC_MSG_RESULT(no) - ]) - CPPFLAGS="$CPPFLAGS_save" fi dnl ####################################################################### @@ -1117,7 +1108,7 @@ fi if test "x$STATIC_PRPLS" = "xall" ; then - STATIC_PRPLS="bonjour gg irc jabber msn myspace mxit novell oscar sametime silc simple yahoo zephyr" + STATIC_PRPLS="bonjour gg irc jabber msn mxit myspace novell oscar sametime silc simple yahoo zephyr" fi if test "x$have_meanwhile" != "xyes" ; then STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/sametime//'` @@ -1126,10 +1117,7 @@ STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/bonjour//'` fi if test "x$silcincludes" != "xyes" -o "x$silcclient" != "xyes"; then - STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc/silc10/'` -fi -if test "x$silc10includes" != "xyes" -o "x$silc10client" != "xyes"; then - STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc10//'` + STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc//'` fi AC_SUBST(STATIC_PRPLS) STATIC_LINK_LIBS= @@ -1153,8 +1141,6 @@ else if test "x$i" = "xsilc"; then STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib${i}purple.la" - elif test "x$i" = "xsilc10"; then - STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/libsilcpurple.la" else STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib$i.la" fi @@ -1167,15 +1153,14 @@ irc) static_irc=yes ;; jabber) static_jabber=yes ;; msn) static_msn=yes ;; + mxit) static_mxit=yes ;; myspace) static_myspace=yes ;; - mxit) static_mxit=yes ;; novell) static_novell=yes ;; oscar) static_oscar=yes ;; aim) static_oscar=yes ;; icq) static_oscar=yes ;; sametime) static_sametime=yes ;; silc) static_silc=yes ;; - silc10) static_silc=yes ;; simple) static_simple=yes ;; yahoo) static_yahoo=yes ;; zephyr) static_zephyr=yes ;; @@ -1187,8 +1172,8 @@ AM_CONDITIONAL(STATIC_IRC, test "x$static_irc" = "xyes") AM_CONDITIONAL(STATIC_JABBER, test "x$static_jabber" = "xyes") AM_CONDITIONAL(STATIC_MSN, test "x$static_msn" = "xyes") +AM_CONDITIONAL(STATIC_MXIT, test "x$static_mxit" = "xyes") AM_CONDITIONAL(STATIC_MYSPACE, test "x$static_myspace" = "xyes") -AM_CONDITIONAL(STATIC_MXIT, test "x$static_mxit" = "xyes") AM_CONDITIONAL(STATIC_NOVELL, test "x$static_novell" = "xyes") AM_CONDITIONAL(STATIC_OSCAR, test "x$static_oscar" = "xyes") AM_CONDITIONAL(STATIC_SAMETIME, test "x$static_sametime" = "xyes" -a "x$have_meanwhile" = "xyes") @@ -1202,7 +1187,7 @@ AC_ARG_WITH(dynamic_prpls, [AC_HELP_STRING([--with-dynamic-prpls], [specify which protocols to build dynamically])], [DYNAMIC_PRPLS=`echo $withval | $sedpath 's/,/ /g'`]) if test "x$DYNAMIC_PRPLS" = "xall" ; then - DYNAMIC_PRPLS="bonjour gg irc jabber msn myspace mxit novell oscar sametime silc simple yahoo zephyr" + DYNAMIC_PRPLS="bonjour gg irc jabber msn mxit myspace novell oscar sametime silc simple yahoo zephyr" fi if test "x$have_meanwhile" != "xyes"; then DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/sametime//'` @@ -1211,10 +1196,7 @@ DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/bonjour//'` fi if test "x$silcincludes" != "xyes" -o "x$silcclient" != "xyes"; then - DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc/silc10/'` -fi -if test "x$silc10includes" != "xyes" -o "x$silc10client" != "xyes"; then - DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc10//'` + DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc//'` fi AC_SUBST(DYNAMIC_PRPLS) for i in $DYNAMIC_PRPLS ; do @@ -1224,8 +1206,8 @@ irc) dynamic_irc=yes ;; jabber) dynamic_jabber=yes ;; msn) dynamic_msn=yes ;; + mxit) dynamic_mxit=yes ;; myspace) dynamic_myspace=yes ;; - mxit) dynamic_mxit=yes ;; novell) dynamic_novell=yes ;; null) dynamic_null=yes ;; oscar) dynamic_oscar=yes ;; @@ -1233,7 +1215,6 @@ icq) dynamic_oscar=yes ;; sametime) dynamic_sametime=yes ;; silc) dynamic_silc=yes ;; - silc10) dynamic_silc=yes ;; simple) dynamic_simple=yes ;; yahoo) dynamic_yahoo=yes ;; zephyr) dynamic_zephyr=yes ;; @@ -2536,10 +2517,8 @@ m4macros/Makefile pidgin.apspec pidgin/Makefile - pidgin/pidgin.pc - pidgin/pidgin-uninstalled.pc - pidgin/pidgin-2.pc - pidgin/pidgin-2-uninstalled.pc + pidgin/pidgin-3.pc + pidgin/pidgin-3-uninstalled.pc pidgin/pixmaps/Makefile pidgin/pixmaps/emotes/default/24/Makefile pidgin/pixmaps/emotes/none/Makefile @@ -2553,13 +2532,12 @@ pidgin/plugins/perl/Makefile pidgin/plugins/perl/common/Makefile.PL pidgin/plugins/ticker/Makefile + pidgin/themes/Makefile libpurple/ciphers/Makefile libpurple/example/Makefile libpurple/gconf/Makefile - libpurple/purple.pc - libpurple/purple-uninstalled.pc - libpurple/purple-2.pc - libpurple/purple-2-uninstalled.pc + libpurple/purple-3.pc + libpurple/purple-3-uninstalled.pc libpurple/plugins/Makefile libpurple/plugins/mono/Makefile libpurple/plugins/mono/api/Makefile @@ -2582,7 +2560,6 @@ libpurple/protocols/oscar/Makefile libpurple/protocols/sametime/Makefile libpurple/protocols/silc/Makefile - libpurple/protocols/silc10/Makefile libpurple/protocols/simple/Makefile libpurple/protocols/yahoo/Makefile libpurple/protocols/zephyr/Makefile @@ -2639,6 +2616,7 @@ echo Use X Session Management...... : $enable_sm echo Use startup notification...... : $enable_startup_notification echo Build with GtkSpell support... : $enable_gtkspell +echo Build with GCR widgets........ : $enable_gcr echo echo Build with plugin support..... : $enable_plugins echo Build with Mono support....... : $enable_mono diff -r 2908b16efa07 -r f01d6c9f3492 doc/account-signals.dox --- a/doc/account-signals.dox Mon Apr 02 23:36:20 2012 +0000 +++ b/doc/account-signals.dox Fri Apr 06 04:30:00 2012 +0000 @@ -34,7 +34,6 @@ @signaldesc Emitted when an account is created by calling purple_account_new. @param account The account. - @since 2.6.0 @endsignaldef @signaldef account-destroying @@ -44,7 +43,6 @@ @signaldesc Emitted when an account is about to be destroyed. @param account The account. - @since 2.6.0 @endsignaldef @signaldef account-added @@ -156,7 +154,6 @@ @return Less than zero to deny the request without prompting, greater than zero if the request should be granted. If zero is returned, then the user will be prompted with the request. - @since 2.3.0 @endsignaldef @signaldef account-authorization-requested-with-message @@ -173,7 +170,6 @@ get informed, PURPLE_ACCOUNT_RESPONSE_ACCEPT if the request should be granted. If PURPLE_ACCOUNT_RESPONSE_PASS is returned, then the user will be prompted with the request. - @since 2.8.0 @endsignaldef @signaldef account-authorization-denied @@ -184,7 +180,6 @@ Emitted when the authorization request for a buddy is denied. @param account The account. @param user The name of the user requesting authorization. - @since 2.3.0 @endsignaldef @signaldef account-authorization-granted @@ -195,7 +190,6 @@ Emitted when the authorization request for a buddy is granted. @param account The account. @param user The name of the user requesting authorization. - @since 2.3.0 @endsignaldef @signaldef account-error-changed @@ -214,7 +208,6 @@ pointer just after the next time this signal is emitted for this @a account. @see purple_account_get_current_error() - @since 2.3.0 @endsignaldef @signaldef account-signed-on @@ -224,7 +217,6 @@ @signaldesc Emitted when an account has signed on. @param account The account that has signed on. - @since 2.7.0 @endsignaldef @signaldef account-signed-off @@ -234,7 +226,6 @@ @signaldesc Emitted when an account has signed off. @param account The account that has signed off. - @since 2.7.0 @endsignaldef @signaldef account-connection-error @@ -246,7 +237,6 @@ @param account The account on which the error has occurred @param err The error that occurred @param desc A description of the error, giving more information. - @since 2.7.0 @endsignaldef */ // vim: syntax=c.doxygen tw=75 et diff -r 2908b16efa07 -r f01d6c9f3492 doc/blist-signals.dox --- a/doc/blist-signals.dox Mon Apr 02 23:36:20 2012 +0000 +++ b/doc/blist-signals.dox Fri Apr 06 04:30:00 2012 +0000 @@ -136,7 +136,6 @@ @param buddy The buddy @param newcaps @param oldcaps - @since 2.7.0 @endsignaldef @signaldef ui-caps-changed @@ -147,7 +146,6 @@ Emitted when updating the media capabilities of the UI. @param newcaps @param oldcaps - @since 2.7.0 @endsignaldef */ diff -r 2908b16efa07 -r f01d6c9f3492 doc/connection-signals.dox --- a/doc/connection-signals.dox Mon Apr 02 23:36:20 2012 +0000 +++ b/doc/connection-signals.dox Fri Apr 06 04:30:00 2012 +0000 @@ -44,7 +44,6 @@ @return @c TRUE if the signal was handled or @c FALSE otherwise. In practice, the return value is irrelevant, as it really only exists so plugins can block the UI's autojoin. - @since 2.7.0 @endsignaldef @signaldef signing-off diff -r 2908b16efa07 -r f01d6c9f3492 doc/conversation-signals.dox --- a/doc/conversation-signals.dox Mon Apr 02 23:36:20 2012 +0000 +++ b/doc/conversation-signals.dox Fri Apr 06 04:30:00 2012 +0000 @@ -149,7 +149,6 @@ @param message The message that was blocked. @param flags The IM message flags. @param when The time the message was sent. - @since 2.5.0 @endsignaldef @signaldef writing-chat-msg @@ -436,7 +435,6 @@ @param name The name of the chat invited to. @param message The invitation message sent. @param data Hashtable containing data about the invited chat. - @since 2.5.0 @endsignaldef @signaldef chat-joined @@ -477,7 +475,6 @@ conversation. @param conv The conversation. @param list A pointer to the list of actions. - @since 2.1.0 @endsignaldef @signaldef cleared-message-history @@ -487,7 +484,6 @@ @signaldesc Emitted when the conversation history is cleared. @param conv The conversation. - @since 2.8.0 @endsignaldef @signaldef sent-attention @@ -501,7 +497,6 @@ @param who The name of the person receiving the attention @param conv The conversation @param type The attention type (an index starting at 0) - @since 2.7.0 @endsignaldef @signaldef got-attention @@ -515,7 +510,6 @@ @param who The name of the person sending the attention @param conv The conversation @param type The attention type (an index starting at 0) - @since 2.7.0 @endsignaldef */ // vim: syntax=c.doxygen tw=75 et diff -r 2908b16efa07 -r f01d6c9f3492 doc/gtkconv-signals.dox --- a/doc/gtkconv-signals.dox Mon Apr 02 23:36:20 2012 +0000 +++ b/doc/gtkconv-signals.dox Fri Apr 06 04:30:00 2012 +0000 @@ -129,7 +129,6 @@ @signaldesc Emitted immediately before an existing conversation is hidden. @param gtkconv The PidginConversation - @since 2.2.0 @endsignaldef @signaldef conversation-displayed @@ -139,7 +138,6 @@ @signaldesc Emitted right after the Pidgin UI is attached to a new or a hidden conversation. @param gtkconv The PidginConversation - @since 2.2.0 @endsignaldef */ diff -r 2908b16efa07 -r f01d6c9f3492 doc/notify-signals.dox --- a/doc/notify-signals.dox Mon Apr 02 23:36:20 2012 +0000 +++ b/doc/notify-signals.dox Fri Apr 06 04:30:00 2012 +0000 @@ -35,7 +35,6 @@ @param from Who the email is from. @param to Who the email is to. @param url A url to view the email. - @since 2.1.0 @endsignaldef @signaldef displaying-emails-notification @@ -53,7 +52,6 @@ @param tos Who the emails are to. @param urls The urls to view the emails. @param count Number of emails being notified of. - @since 2.1.0 @endsignaldef */ diff -r 2908b16efa07 -r f01d6c9f3492 finch/Makefile.am --- a/finch/Makefile.am Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/Makefile.am Fri Apr 06 04:30:00 2012 +0000 @@ -27,6 +27,7 @@ gntidle.c \ gntlog.c \ gntmedia.c \ + gntmenuutil.c \ gntnotify.c \ gntplugin.c \ gntpounce.c \ @@ -49,6 +50,7 @@ gntidle.h \ gntlog.h \ gntmedia.h \ + gntmenuutil.h \ gntnotify.h \ gntplugin.h \ gntpounce.h \ diff -r 2908b16efa07 -r f01d6c9f3492 finch/finch.c --- a/finch/finch.c Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/finch.c Fri Apr 06 04:30:00 2012 +0000 @@ -339,7 +339,17 @@ /* set a user-specified config directory */ if (opt_config_dir_arg != NULL) { - purple_util_set_user_dir(opt_config_dir_arg); + if (g_path_is_absolute(opt_config_dir_arg)) { + purple_util_set_user_dir(opt_config_dir_arg); + } else { + /* Make an absolute (if not canonical) path */ + char *cwd = g_get_current_dir(); + char *path = g_build_path(G_DIR_SEPARATOR_S, cwd, opt_config_dir_arg, NULL); + purple_util_set_user_dir(path); + g_free(path); + g_free(cwd); + } + g_free(opt_config_dir_arg); } @@ -351,29 +361,6 @@ /* 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. Please report this error at http://developer.pidgin.im"), _("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()); diff -r 2908b16efa07 -r f01d6c9f3492 finch/gntaccount.h --- a/finch/gntaccount.h Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/gntaccount.h Fri Apr 06 04:30:00 2012 +0000 @@ -59,8 +59,6 @@ * Show the edit dialog for an account. * * @param account The account to edit, or @c NULL to create a new account. - * - * @since 2.2.0 */ void finch_account_dialog_show(PurpleAccount *account); diff -r 2908b16efa07 -r f01d6c9f3492 finch/gntblist.c --- a/finch/gntblist.c Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/gntblist.c Fri Apr 06 04:30:00 2012 +0000 @@ -50,6 +50,7 @@ #include "gntmenu.h" #include "gntmenuitem.h" #include "gntmenuitemcheck.h" +#include "gntmenuutil.h" #include "gntpounce.h" #include "gntstyle.h" #include "gnttree.h" @@ -169,7 +170,7 @@ if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { PurpleBuddy *buddy = (PurpleBuddy*)node; - FinchBlistNode *fnode = FINCH_GET_DATA(node); + FinchBlistNode *fnode = purple_blist_node_get_ui_data(node); if (!purple_buddy_get_contact(buddy)) return FALSE; /* When a new buddy is added and show-offline is set */ if (PURPLE_BUDDY_IS_ONLINE(buddy)) @@ -329,11 +330,11 @@ static FinchBlistNode * create_finch_blist_node(PurpleBlistNode *node, gpointer row) { - FinchBlistNode *fnode = FINCH_GET_DATA(node); + FinchBlistNode *fnode = purple_blist_node_get_ui_data(node); if (!fnode) { fnode = g_new0(FinchBlistNode, 1); fnode->signed_timer = 0; - FINCH_SET_DATA(node, fnode); + purple_blist_node_set_ui_data(node, fnode); } fnode->row = row; return fnode; @@ -342,13 +343,13 @@ static void reset_blist_node_ui_data(PurpleBlistNode *node) { - FinchBlistNode *fnode = FINCH_GET_DATA(node); + FinchBlistNode *fnode = purple_blist_node_get_ui_data(node); if (fnode == NULL) return; if (fnode->signed_timer) purple_timeout_remove(fnode->signed_timer); g_free(fnode); - FINCH_SET_DATA(node, NULL); + purple_blist_node_set_ui_data(node, NULL); } static int @@ -381,7 +382,7 @@ get_blist_node_flag(PurpleBlistNode *node) { GntTextFormatFlags flag = 0; - FinchBlistNode *fnode = FINCH_GET_DATA(node); + FinchBlistNode *fnode = purple_blist_node_get_ui_data(node); if (ggblist->tagged && g_list_find(ggblist->tagged, node)) flag |= GNT_TEXT_FLAG_BOLD; @@ -390,7 +391,7 @@ flag |= GNT_TEXT_FLAG_BLINK; else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { node = PURPLE_BLIST_NODE(purple_contact_get_priority_buddy(PURPLE_CONTACT(node))); - fnode = FINCH_GET_DATA(node); + fnode = purple_blist_node_get_ui_data(node); if (fnode && fnode->signed_timer) flag |= GNT_TEXT_FLAG_BLINK; } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { @@ -406,7 +407,7 @@ node = purple_blist_node_get_sibling_next(node)) { PurpleBlistNode *pnode; pnode = purple_contact_get_priority_buddy((PurpleContact*)node); - fnode = FINCH_GET_DATA(node); + fnode = purple_blist_node_get_ui_data(node); if (fnode && fnode->signed_timer) { flag |= GNT_TEXT_FLAG_BLINK; break; @@ -433,7 +434,7 @@ PurpleBlistNode *node; for (node = purple_blist_node_get_first_child(((PurpleBlistNode*)contact)); node; node = purple_blist_node_get_sibling_next(node)) { - FinchBlistNode *fnode = FINCH_GET_DATA(node); + FinchBlistNode *fnode = purple_blist_node_get_ui_data(node); if (PURPLE_BUDDY_IS_ONLINE((PurpleBuddy*)node) || (fnode && fnode->signed_timer)) return TRUE; @@ -465,7 +466,7 @@ static void add_node(PurpleBlistNode *node, FinchBlist *ggblist) { - if (FINCH_GET_DATA(node)) + if (purple_blist_node_get_ui_data(node)) return; if (!ggblist->manager->can_add_node(node)) @@ -502,7 +503,7 @@ FinchBlist *ggblist = FINCH_GET_DATA(list); PurpleBlistNode *parent; - if (ggblist == NULL || FINCH_GET_DATA(node) == NULL) + if (ggblist == NULL || purple_blist_node_get_ui_data(node) == NULL) return; if (PURPLE_BLIST_NODE_IS_GROUP(node) && ggblist->new_group) { @@ -543,7 +544,7 @@ if (ggblist->window == NULL) return; - if (FINCH_GET_DATA(node)!= NULL) { + if (purple_blist_node_get_ui_data(node)!= NULL) { gnt_tree_change_text(GNT_TREE(ggblist->tree), node, 0, get_display_name(node)); gnt_tree_sort_row(GNT_TREE(ggblist->tree), node); @@ -560,7 +561,7 @@ } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { add_node(node, FINCH_GET_DATA(list)); } else if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { - if (FINCH_GET_DATA(node)== NULL) { + if (purple_blist_node_get_ui_data(node)== NULL) { /* The core seems to expect the UI to add the buddies. */ for (node = purple_blist_node_get_first_child(node); node; node = purple_blist_node_get_sibling_next(node)) add_node(node, FINCH_GET_DATA(list)); @@ -663,7 +664,7 @@ purple_blist_add_buddy(buddy, NULL, grp, NULL); } - purple_account_add_buddy_with_invite(account, buddy, invite); + purple_account_add_buddy(account, buddy, invite); } static void @@ -839,7 +840,7 @@ /* Select the group */ if (ggblist->tree) { - FinchBlistNode *fnode = FINCH_GET_DATA((PurpleBlistNode*)grp); + FinchBlistNode *fnode = purple_blist_node_get_ui_data((PurpleBlistNode*)grp); if (!fnode) add_node((PurpleBlistNode*)grp, ggblist); gnt_tree_set_selected(GNT_TREE(ggblist->tree), grp); @@ -887,7 +888,7 @@ { gpointer parent; PurpleBlistNode *node = (PurpleBlistNode *)group; - if (FINCH_GET_DATA(node)) + if (purple_blist_node_get_ui_data(node)) return; parent = ggblist->manager->find_parent((PurpleBlistNode*)group); create_finch_blist_node(node, gnt_tree_add_row_after(GNT_TREE(ggblist->tree), group, @@ -960,7 +961,7 @@ { gpointer parent; PurpleBlistNode *node = (PurpleBlistNode *)chat; - if (FINCH_GET_DATA(node)) + if (purple_blist_node_get_ui_data(node)) return; if (!purple_account_is_connected(purple_chat_get_account(chat))) return; @@ -979,7 +980,7 @@ PurpleBlistNode *node = (PurpleBlistNode*)contact; const char *name; - if (FINCH_GET_DATA(node)) + if (purple_blist_node_get_ui_data(node)) return; name = get_display_name(node); @@ -1002,7 +1003,7 @@ PurpleBlistNode *node = (PurpleBlistNode *)buddy; PurpleContact *contact; - if (FINCH_GET_DATA(node)) + if (purple_blist_node_get_ui_data(node)) return; contact = purple_buddy_get_contact(buddy); @@ -1060,7 +1061,7 @@ purple_buddy_get_account(buddy), purple_buddy_get_name(buddy)); } else { - FinchConv *ggconv = FINCH_GET_DATA(conv); + FinchConv *ggconv = FINCH_CONV(conv); gnt_window_present(ggconv->window); } finch_conversation_set_active(conv); @@ -1072,43 +1073,6 @@ } static void -context_menu_callback(GntMenuItem *item, gpointer data) -{ - PurpleMenuAction *action = data; - PurpleBlistNode *node = ggblist->cnode; - if (action) { - void (*callback)(PurpleBlistNode *, gpointer); - callback = (void (*)(PurpleBlistNode *, gpointer))action->callback; - if (callback) - callback(node, action->data); - else - return; - } -} - -static void -gnt_append_menu_action(GntMenu *menu, PurpleMenuAction *action, gpointer parent) -{ - GList *list; - GntMenuItem *item; - - if (action == NULL) - return; - - item = gnt_menuitem_new(action->label); - if (action->callback) - gnt_menuitem_set_callback(GNT_MENU_ITEM(item), context_menu_callback, action); - gnt_menu_add_item(menu, GNT_MENU_ITEM(item)); - - if (action->children) { - GntWidget *sub = gnt_menu_new(GNT_MENU_POPUP); - gnt_menuitem_set_submenu(item, GNT_MENU(sub)); - for (list = action->children; list; list = list->next) - gnt_append_menu_action(GNT_MENU(sub), list->data, action); - } -} - -static void append_proto_menu(GntMenu *menu, PurpleConnection *gc, PurpleBlistNode *node) { GList *list; @@ -1123,10 +1087,8 @@ PurpleMenuAction *act = (PurpleMenuAction *) list->data; if (!act) continue; - act->data = node; - gnt_append_menu_action(menu, act, NULL); - g_signal_connect_swapped(G_OBJECT(menu), "destroy", - G_CALLBACK(purple_menu_action_free), act); + purple_menu_action_set_data(act, node); + gnt_append_menu_action(menu, act, node); } } @@ -1136,8 +1098,6 @@ { PurpleMenuAction *action = purple_menu_action_new(label, callback, data, NULL); gnt_append_menu_action(menu, action, NULL); - g_signal_connect_swapped(G_OBJECT(menu), "destroy", - G_CALLBACK(purple_menu_action_free), action); } static void @@ -1216,7 +1176,7 @@ autojoin_toggled(GntMenuItem *item, gpointer data) { PurpleMenuAction *action = data; - purple_blist_node_set_bool(action->data, "gnt-autojoin", + purple_blist_node_set_bool(purple_menu_action_get_data(action), "gnt-autojoin", gnt_menuitem_check_get_checked(GNT_MENU_ITEM_CHECK(item))); } @@ -1224,7 +1184,8 @@ create_chat_menu(GntMenu *menu, PurpleChat *chat) { PurpleMenuAction *action = purple_menu_action_new(_("Auto-join"), NULL, chat, NULL); - GntMenuItem *check = gnt_menuitem_check_new(action->label); + GntMenuItem *check = gnt_menuitem_check_new( + purple_menu_action_get_label(action)); gnt_menuitem_check_set_checked(GNT_MENU_ITEM_CHECK(check), purple_blist_node_get_bool((PurpleBlistNode*)chat, "gnt-autojoin")); gnt_menu_add_item(menu, check); @@ -1268,7 +1229,7 @@ { PurpleNotifyUserInfo *info = purple_notify_user_info_new(); gpointer uihandle; - purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving...")); + purple_notify_user_info_add_pair_plaintext(info, _("Information"), _("Retrieving...")); uihandle = purple_notify_userinfo(conn, name, info, NULL, NULL); purple_notify_user_info_destroy(info); @@ -1375,9 +1336,7 @@ for (iter = purple_blist_node_get_extended_menu(node); iter; iter = g_list_delete_link(iter, iter)) { - gnt_append_menu_action(menu, iter->data, NULL); - g_signal_connect_swapped(G_OBJECT(menu), "destroy", - G_CALLBACK(purple_menu_action_free), iter->data); + gnt_append_menu_action(menu, iter->data, node); } } @@ -1557,7 +1516,7 @@ if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { PurpleContact *c = (PurpleContact*)node; name = purple_contact_get_alias(c); - if (c->totalsize > 1) + if (purple_contact_get_contact_size(c, TRUE) > 1) sec = _("Removing this contact will also remove all the buddies in the contact"); } else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { name = purple_buddy_get_name((PurpleBuddy*)node); @@ -1783,15 +1742,13 @@ presence = purple_buddy_get_presence(buddy); if (!full || g_utf8_collate(purple_buddy_get_name(buddy), alias)) { - char *esc = g_markup_escape_text(alias, -1); - purple_notify_user_info_add_pair(user_info, _("Nickname"), esc); - g_free(esc); + purple_notify_user_info_add_pair_plaintext(user_info, _("Nickname"), alias); } tmp = g_strdup_printf("%s (%s)", purple_account_get_username(account), purple_account_get_protocol_name(account)); - purple_notify_user_info_add_pair(user_info, _("Account"), tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Account"), tmp); g_free(tmp); prpl = purple_find_prpl(purple_account_get_protocol_id(account)); @@ -1806,7 +1763,7 @@ time_t idle = purple_presence_get_idle_time(pre); if (idle > 0) { char *st = purple_str_seconds_to_string(time(NULL) - idle); - purple_notify_user_info_add_pair(user_info, _("Idle"), st); + purple_notify_user_info_add_pair_plaintext(user_info, _("Idle"), st); g_free(st); } } @@ -2543,7 +2500,7 @@ buddy_recent_signed_on_off(gpointer data) { PurpleBlistNode *node = data; - FinchBlistNode *fnode = FINCH_GET_DATA(node); + FinchBlistNode *fnode = purple_blist_node_get_ui_data(node); purple_timeout_remove(fnode->signed_timer); fnode->signed_timer = 0; @@ -2563,7 +2520,7 @@ buddy_signed_on_off_cb(gpointer data) { PurpleBlistNode *node = data; - FinchBlistNode *fnode = FINCH_GET_DATA(node); + FinchBlistNode *fnode = purple_blist_node_get_ui_data(node); if (!ggblist || !fnode) return FALSE; diff -r 2908b16efa07 -r f01d6c9f3492 finch/gntblist.h --- a/finch/gntblist.h Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/gntblist.h Fri Apr 06 04:30:00 2012 +0000 @@ -115,15 +115,12 @@ * @param name The user to get information about. * * @return Returns the ui-handle for the userinfo notification. - * - * @since 2.1.0 */ gpointer finch_retrieve_user_info(PurpleConnection *conn, const char *name); /** * Get the tree list of the buddy list. * @return The GntTree widget. - * @since 2.4.0 */ GntTree * finch_blist_get_tree(void); @@ -131,7 +128,6 @@ * Add an alternate buddy list manager. * * @param manager The alternate buddylist manager. - * @since 2.4.0 */ void finch_blist_install_manager(const FinchBlistManager *manager); @@ -139,7 +135,6 @@ * Remove an alternate buddy list manager. * * @param manager The buddy list manager to remove. - * @since 2.4.0 */ void finch_blist_uninstall_manager(const FinchBlistManager *manager); @@ -149,7 +144,6 @@ * @param id The identifier for the desired buddy list manager. * * @return The manager with the requested identifier, if available. @c NULL otherwise. - * @since 2.4.0 */ FinchBlistManager * finch_blist_manager_find(const char *id); @@ -157,7 +151,6 @@ * Request the active buddy list manager to add a node. * * @param node The node to add - * @since 2.4.0 */ void finch_blist_manager_add_node(PurpleBlistNode *node); diff -r 2908b16efa07 -r f01d6c9f3492 finch/gntconn.c --- a/finch/gntconn.c Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/gntconn.c Fri Apr 06 04:30:00 2012 +0000 @@ -165,7 +165,6 @@ NULL, /* connected */ NULL, /* disconnected */ NULL, /* notice */ - NULL, NULL, /* network_connected */ NULL, /* network_disconnected */ finch_connection_report_disconnect, diff -r 2908b16efa07 -r f01d6c9f3492 finch/gntconv.c --- a/finch/gntconv.c Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/gntconv.c Fri Apr 06 04:30:00 2012 +0000 @@ -52,6 +52,7 @@ #include "gntmenu.h" #include "gntmenuitem.h" #include "gntmenuitemcheck.h" +#include "gntmenuutil.h" #include "gntstyle.h" #include "gnttextview.h" #include "gnttree.h" @@ -123,7 +124,7 @@ if (send || (purple_conv_im_get_type_again(im) != 0 && time(NULL) > purple_conv_im_get_type_again(im))) { unsigned int timeout; - timeout = serv_send_typing(purple_conversation_get_gc(conv), + timeout = serv_send_typing(purple_conversation_get_connection(conv), purple_conversation_get_name(conv), PURPLE_TYPING); purple_conv_im_set_type_again(im, timeout); @@ -131,7 +132,7 @@ } else { purple_conv_im_stop_send_typed_timeout(im); - serv_send_typing(purple_conversation_get_gc(conv), + serv_send_typing(purple_conversation_get_connection(conv), purple_conversation_get_name(conv), PURPLE_NOT_TYPING); } @@ -282,7 +283,7 @@ return; im = PURPLE_CONV_IM(conv); - ggc = FINCH_GET_DATA(conv); + ggc = FINCH_CONV(conv); if (purple_conv_im_get_typing_state(im) == PURPLE_TYPING) { int scroll; @@ -321,7 +322,7 @@ PurpleConversation *conv = find_conv_with_contact(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy)); if (conv == NULL) return; - generate_send_to_menu(FINCH_GET_DATA(conv)); + generate_send_to_menu(FINCH_CONV(conv)); } static void @@ -333,7 +334,7 @@ PurpleConversation *cc = find_conv_with_contact( purple_conversation_get_account(conv), purple_conversation_get_name(conv)); if (cc) - generate_send_to_menu(FINCH_GET_DATA(cc)); + generate_send_to_menu(FINCH_CONV(cc)); list = list->next; } @@ -398,12 +399,36 @@ static void cleared_message_history_cb(PurpleConversation *conv, gpointer data) { - FinchConv *ggc = FINCH_GET_DATA(conv); + FinchConv *ggc = FINCH_CONV(conv); if (ggc) gnt_text_view_clear(GNT_TEXT_VIEW(ggc->tv)); } static void +gg_extended_menu(FinchConv *ggc) +{ + GntWidget *sub; + GList *list; + + sub = gnt_menu_new(GNT_MENU_POPUP); + gnt_menuitem_set_submenu(ggc->plugins, GNT_MENU(sub)); + + for (list = purple_conversation_get_extended_menu(ggc->active_conv); + list; list = g_list_delete_link(list, list)) + { + gnt_append_menu_action(GNT_MENU(sub), list->data, ggc->active_conv); + } +} + +static void +conv_updated(PurpleConversation *conv, PurpleConvUpdateType type) +{ + if (type == PURPLE_CONV_UPDATE_FEATURES) { + gg_extended_menu(purple_conversation_get_ui_data(conv)); + } +} + +static void clear_scrollback_cb(GntMenuItem *item, gpointer ggconv) { FinchConv *ggc = ggconv; @@ -414,7 +439,7 @@ send_file_cb(GntMenuItem *item, gpointer ggconv) { FinchConv *ggc = ggconv; - serv_send_file(purple_conversation_get_gc(ggc->active_conv), + serv_send_file(purple_conversation_get_connection(ggc->active_conv), purple_conversation_get_name(ggc->active_conv), NULL); } @@ -431,7 +456,7 @@ get_info_cb(GntMenuItem *item, gpointer ggconv) { FinchConv *ggc = ggconv; - finch_retrieve_user_info(purple_conversation_get_gc(ggc->active_conv), + finch_retrieve_user_info(purple_conversation_get_connection(ggc->active_conv), purple_conversation_get_name(ggc->active_conv)); } @@ -595,6 +620,12 @@ } static void +plugin_changed_cb(PurplePlugin *p, gpointer data) +{ + gg_extended_menu(data); +} + +static void gg_create_menu(FinchConv *ggc) { GntWidget *menu, *sub; @@ -665,6 +696,12 @@ !(ggc->flags & FINCH_CONV_NO_SOUND)); gnt_menu_add_item(GNT_MENU(sub), item); gnt_menuitem_set_callback(item, toggle_sound_cb, ggc); + + item = gnt_menuitem_new(_("Plugins")); + gnt_menu_add_item(GNT_MENU(menu), item); + ggc->plugins = item; + + gg_extended_menu(ggc); } static void @@ -683,7 +720,7 @@ name = gnt_tree_get_selection_data(GNT_TREE(widget)); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_cb_real_name)) realname = prpl_info->get_cb_real_name(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(fc->active_conv)), name); else @@ -749,7 +786,7 @@ static void finch_create_conversation(PurpleConversation *conv) { - FinchConv *ggc = FINCH_GET_DATA(conv); + FinchConv *ggc = FINCH_CONV(conv); char *title; PurpleConversationType type; PurpleConversation *cc; @@ -763,8 +800,8 @@ account = purple_conversation_get_account(conv); cc = find_conv_with_contact(account, purple_conversation_get_name(conv)); - if (cc && FINCH_GET_DATA(cc)) - ggc = FINCH_GET_DATA(cc); + if (cc && FINCH_CONV(cc)) + ggc = FINCH_CONV(cc); else ggc = g_new0(FinchConv, 1); @@ -776,9 +813,9 @@ ggc->list = g_list_prepend(ggc->list, conv); ggc->active_conv = conv; - FINCH_SET_DATA(conv, ggc); + purple_conversation_set_ui_data(conv, ggc); - if (cc && FINCH_GET_DATA(cc) && cc != conv) { + if (cc && FINCH_CONV(cc) && cc != conv) { finch_conversation_set_active(conv); return; } @@ -876,6 +913,11 @@ purple_signal_connect(purple_cmds_get_handle(), "cmd-removed", ggc, G_CALLBACK(cmd_removed_cb), ggc); + purple_signal_connect(purple_plugins_get_handle(), "plugin-load", ggc, + PURPLE_CALLBACK(plugin_changed_cb), ggc); + purple_signal_connect(purple_plugins_get_handle(), "plugin-unload", ggc, + PURPLE_CALLBACK(plugin_changed_cb), ggc); + g_free(title); gnt_box_give_focus_to_child(GNT_BOX(ggc->window), ggc->entry); g_signal_connect(G_OBJECT(ggc->window), "gained-focus", G_CALLBACK(gained_focus_cb), ggc); @@ -885,7 +927,7 @@ finch_destroy_conversation(PurpleConversation *conv) { /* do stuff here */ - FinchConv *ggc = FINCH_GET_DATA(conv); + FinchConv *ggc = FINCH_CONV(conv); ggc->list = g_list_remove(ggc->list, conv); if (ggc->list && conv == ggc->active_conv) { ggc->active_conv = ggc->list->data; @@ -905,7 +947,7 @@ finch_write_common(PurpleConversation *conv, const char *who, const char *message, PurpleMessageFlags flags, time_t mtime) { - FinchConv *ggconv = FINCH_GET_DATA(conv); + FinchConv *ggconv = FINCH_CONV(conv); char *strip, *newline; GntTextFormatFlags fl = 0; int pos; @@ -1069,7 +1111,7 @@ static void finch_chat_add_users(PurpleConversation *conv, GList *users, gboolean new_arrivals) { - FinchConv *ggc = FINCH_GET_DATA(conv); + FinchConv *ggc = FINCH_CONV(conv); GntEntry *entry = GNT_ENTRY(ggc->entry); if (!new_arrivals) @@ -1084,10 +1126,10 @@ for (iter = users; iter; iter = iter->next) { PurpleConvChatBuddy *cbuddy = iter->data; - char *str; + const char *str; - if ((str = cbuddy->alias) == NULL) - str = cbuddy->name; + if ((str = purple_conv_chat_cb_get_alias(cbuddy)) == NULL) + str = purple_conv_chat_cb_get_name(cbuddy); g_string_append_printf(string, "[ %s ]", str); } @@ -1100,10 +1142,10 @@ { PurpleConvChatBuddy *cbuddy = users->data; GntTree *tree = GNT_TREE(ggc->u.chat->userlist); - gnt_entry_add_suggest(entry, cbuddy->name); - gnt_entry_add_suggest(entry, cbuddy->alias); - gnt_tree_add_row_after(tree, g_strdup(cbuddy->name), - gnt_tree_create_row(tree, chat_flag_text(cbuddy->flags), cbuddy->alias), NULL, NULL); + gnt_entry_add_suggest(entry, purple_conv_chat_cb_get_name(cbuddy)); + gnt_entry_add_suggest(entry, purple_conv_chat_cb_get_alias(cbuddy)); + gnt_tree_add_row_after(tree, g_strdup(purple_conv_chat_cb_get_name(cbuddy)), + gnt_tree_create_row(tree, chat_flag_text(purple_conv_chat_cb_get_flags(cbuddy)), purple_conv_chat_cb_get_alias(cbuddy)), NULL, NULL); } } @@ -1111,7 +1153,7 @@ finch_chat_rename_user(PurpleConversation *conv, const char *old, const char *new_n, const char *new_a) { /* Update the name for string completion */ - FinchConv *ggc = FINCH_GET_DATA(conv); + FinchConv *ggc = FINCH_CONV(conv); GntEntry *entry = GNT_ENTRY(ggc->entry); GntTree *tree = GNT_TREE(ggc->u.chat->userlist); PurpleConvChatBuddy *cb = purple_conv_chat_cb_find(PURPLE_CONV_CHAT(conv), new_n); @@ -1122,14 +1164,14 @@ gnt_entry_add_suggest(entry, new_n); gnt_entry_add_suggest(entry, new_a); gnt_tree_add_row_after(tree, g_strdup(new_n), - gnt_tree_create_row(tree, chat_flag_text(cb->flags), new_a), NULL, NULL); + gnt_tree_create_row(tree, chat_flag_text(purple_conv_chat_cb_get_flags(cb)), new_a), NULL, NULL); } static void finch_chat_remove_users(PurpleConversation *conv, GList *list) { /* Remove the name from string completion */ - FinchConv *ggc = FINCH_GET_DATA(conv); + FinchConv *ggc = FINCH_CONV(conv); GntEntry *entry = GNT_ENTRY(ggc->entry); for (; list; list = list->next) { GntTree *tree = GNT_TREE(ggc->u.chat->userlist); @@ -1142,8 +1184,8 @@ finch_chat_update_user(PurpleConversation *conv, const char *user) { PurpleConvChatBuddy *cb = purple_conv_chat_cb_find(PURPLE_CONV_CHAT(conv), user); - FinchConv *ggc = FINCH_GET_DATA(conv); - gnt_tree_change_text(GNT_TREE(ggc->u.chat->userlist), (gpointer)user, 0, chat_flag_text(cb->flags)); + FinchConv *ggc = FINCH_CONV(conv); + gnt_tree_change_text(GNT_TREE(ggc->u.chat->userlist), (gpointer)user, 0, chat_flag_text(purple_conv_chat_cb_get_flags(cb))); } static void @@ -1368,7 +1410,7 @@ static PurpleCmdRet users_command_cb(PurpleConversation *conv, const char *cmd, char **args, char **error, gpointer data) { - FinchConv *fc = FINCH_GET_DATA(conv); + FinchConv *fc = FINCH_CONV(conv); FinchConvChat *ch; if (!fc) return PURPLE_CMD_RET_FAILED; @@ -1475,6 +1517,8 @@ PURPLE_CALLBACK(chat_left_cb), NULL); purple_signal_connect(purple_conversations_get_handle(), "cleared-message-history", finch_conv_get_handle(), PURPLE_CALLBACK(cleared_message_history_cb), NULL); + purple_signal_connect(purple_conversations_get_handle(), "conversation-updated", finch_conv_get_handle(), + PURPLE_CALLBACK(conv_updated), NULL); purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", finch_conv_get_handle(), PURPLE_CALLBACK(buddy_signed_on_off), NULL); purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", finch_conv_get_handle(), @@ -1494,7 +1538,7 @@ void finch_conversation_set_active(PurpleConversation *conv) { - FinchConv *ggconv = FINCH_GET_DATA(conv); + FinchConv *ggconv = FINCH_CONV(conv); PurpleAccount *account; char *title; @@ -1513,7 +1557,7 @@ void finch_conversation_set_info_widget(PurpleConversation *conv, GntWidget *widget) { - FinchConv *fc = FINCH_GET_DATA(conv); + FinchConv *fc = FINCH_CONV(conv); int height, width; gnt_box_remove_all(GNT_BOX(fc->info)); diff -r 2908b16efa07 -r f01d6c9f3492 finch/gntconv.h --- a/finch/gntconv.h Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/gntconv.h Fri Apr 06 04:30:00 2012 +0000 @@ -33,7 +33,7 @@ #include "conversation.h" /* Grabs the conv out of a PurpleConverstation */ -#define FINCH_CONV(conv) ((FinchConv *)(conv)->ui_data) +#define FINCH_CONV(conv) ((FinchConv *)purple_conversation_get_ui_data(conv)) /*************************************************************************** * @name GNT Conversations API @@ -59,6 +59,7 @@ GntWidget *tv; /* text-view */ GntWidget *menu; GntWidget *info; + GntMenuItem *plugins; FinchConversationFlag flags; union diff -r 2908b16efa07 -r f01d6c9f3492 finch/gntft.c --- a/finch/gntft.c Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/gntft.c Fri Apr 06 04:30:00 2012 +0000 @@ -42,9 +42,6 @@ #include "gntft.h" #include "prefs.h" -#define FINCHXFER(xfer) \ - (PurpleGntXferUiData *)FINCH_GET_DATA(xfer) - typedef struct { gboolean keep_open; @@ -152,7 +149,7 @@ while (iter) { PurpleXfer *xfer = iter->data; iter = iter->next; - if (purple_xfer_is_completed(xfer) || purple_xfer_is_canceled(xfer)) + if (purple_xfer_is_completed(xfer) || purple_xfer_is_cancelled(xfer)) finch_xfer_dialog_remove_xfer(xfer); } } @@ -163,7 +160,7 @@ { PurpleXfer *selected_xfer = gnt_tree_get_selection_data(GNT_TREE(xfer_dialog->tree)); if (selected_xfer && (purple_xfer_is_completed(selected_xfer) || - purple_xfer_is_canceled(selected_xfer))) { + purple_xfer_is_cancelled(selected_xfer))) { finch_xfer_dialog_remove_xfer(selected_xfer); } } @@ -262,7 +259,7 @@ for (iter = purple_xfers_get_all(); iter; iter = iter->next) { PurpleXfer *xfer = (PurpleXfer *)iter->data; - PurpleGntXferUiData *data = FINCHXFER(xfer); + PurpleGntXferUiData *data = purple_xfer_get_ui_data(xfer); if (data->in_list) { finch_xfer_dialog_add_xfer(xfer); finch_xfer_dialog_update_xfer(xfer); @@ -302,7 +299,7 @@ purple_xfer_ref(xfer); - data = FINCHXFER(xfer); + data = purple_xfer_get_ui_data(xfer); data->in_list = TRUE; finch_xfer_dialog_show(); @@ -340,7 +337,7 @@ g_return_if_fail(xfer_dialog != NULL); g_return_if_fail(xfer != NULL); - data = FINCHXFER(xfer); + data = purple_xfer_get_ui_data(xfer); if (data == NULL) return; @@ -370,7 +367,7 @@ g_return_if_fail(xfer_dialog != NULL); g_return_if_fail(xfer != NULL); - data = FINCHXFER(xfer); + data = purple_xfer_get_ui_data(xfer); if (data == NULL) return; @@ -385,7 +382,7 @@ update_title_progress(); - if (purple_xfer_is_canceled(xfer)) + if (purple_xfer_is_cancelled(xfer)) status = _("Cancelled"); else status = _("Failed"); @@ -416,7 +413,7 @@ g_return_if_fail(xfer_dialog != NULL); g_return_if_fail(xfer != NULL); - if ((data = FINCHXFER(xfer)) == NULL) + if ((data = purple_xfer_get_ui_data(xfer)) == NULL) return; if (data->in_list == FALSE || data->notified) @@ -471,9 +468,9 @@ { PurpleGntXferUiData *data; - /* This is where we're setting xfer->ui_data for the first time. */ + /* This is where we're setting xfer's "ui_data" for the first time. */ data = g_new0(PurpleGntXferUiData, 1); - FINCH_SET_DATA(xfer, data); + purple_xfer_set_ui_data(xfer, data); } static void @@ -481,11 +478,11 @@ { PurpleGntXferUiData *data; - data = FINCHXFER(xfer); + data = purple_xfer_get_ui_data(xfer); if (data) { g_free(data->name); g_free(data); - FINCH_SET_DATA(xfer, NULL); + purple_xfer_set_ui_data(xfer, NULL); } } diff -r 2908b16efa07 -r f01d6c9f3492 finch/gntmenuutil.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/finch/gntmenuutil.c Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,79 @@ +/** + * @file gntmenuutil.c GNT Menu Utility Functions + * @ingroup finch + */ + +/* finch + * + * Finch is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include +#include "finch.h" + +#include "gnt.h" +#include "gntmenu.h" +#include "gntmenuitem.h" +#include "gntmenuutil.h" + +static void +context_menu_callback(GntMenuItem *item, gpointer data) +{ + PurpleMenuAction *action = data; + if (action) { + void (*callback)(gpointer, gpointer); + callback = (void (*)(gpointer, gpointer)) + purple_menu_action_get_callback(action); + if (callback) { + gpointer ctx = g_object_get_data(G_OBJECT(item), "menuctx"); + callback(ctx, purple_menu_action_get_data(action)); + } + } +} + +void +gnt_append_menu_action(GntMenu *menu, PurpleMenuAction *action, gpointer ctx) +{ + GList *list; + GntMenuItem *item; + + if (action == NULL) + return; + + item = gnt_menuitem_new(purple_menu_action_get_label(action)); + if (purple_menu_action_get_callback(action)) { + gnt_menuitem_set_callback(item, context_menu_callback, action); + g_object_set_data(G_OBJECT(item), "menuctx", ctx); + } + gnt_menu_add_item(menu, item); + + list = purple_menu_action_get_children(action); + + if (list) { + GntWidget *sub = gnt_menu_new(GNT_MENU_POPUP); + gnt_menuitem_set_submenu(item, GNT_MENU(sub)); + for (; list; list = g_list_delete_link(list, list)) + gnt_append_menu_action(GNT_MENU(sub), list->data, action); + purple_menu_action_set_children(action, NULL); + } + + g_signal_connect_swapped(G_OBJECT(menu), "destroy", + G_CALLBACK(purple_menu_action_free), action); +} + diff -r 2908b16efa07 -r f01d6c9f3492 finch/gntmenuutil.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/finch/gntmenuutil.h Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,49 @@ +/** + * @file gntmenuutil.h GNT Menu Utility Functions + * @ingroup finch + */ + +/* finch + * + * Finch is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef _GNT_MENUUTIL_H +#define _GNT_MENUUTIL_H + +#include +#include + +/*************************************************************************** + * @name GNT Menu Utility Functions + ***************************************************************************/ +/*@{*/ + +/** + * Add a PurpleMenuAction to a GntMenu. + * + * @param menu the GntMenu to add to + * @param action the PurpleMenuAction to add + * @param ctx the callback context, passed as the first argument to + * the PurpleMenuAction's PurpleCallback function. + */ +void gnt_append_menu_action(GntMenu *menu, PurpleMenuAction *action, gpointer ctx); + +/*@}*/ + +#endif diff -r 2908b16efa07 -r f01d6c9f3492 finch/gntnotify.c --- a/finch/gntnotify.c Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/gntnotify.c Fri Apr 06 04:30:00 2012 +0000 @@ -290,7 +290,7 @@ text = g_string_new(""); - for (l = purple_notify_user_info_get_entries(user_info); l != NULL; + for (l = purple_notify_user_info_get_entries(user_info)->head; l != NULL; l = l->next) { PurpleNotifyUserInfoEntry *user_info_entry = l->data; PurpleNotifyUserInfoEntryType type = purple_notify_user_info_entry_get_type(user_info_entry); @@ -386,6 +386,7 @@ { GntTree *tree = GNT_TREE(data); GList *o; + GntTreeRow *prev = NULL; /* XXX: Do I need to empty the tree here? */ @@ -393,10 +394,17 @@ { gnt_tree_add_row_after(GNT_TREE(tree), o->data, gnt_tree_create_row_from_list(GNT_TREE(tree), o->data), - NULL, NULL); + NULL, prev); + prev = o->data; } } +static void +notify_sr_destroy_cb(GntWidget *window, void *data) +{ + purple_notify_close(PURPLE_NOTIFY_SEARCHRESULTS, window); +} + static void * finch_notify_searchresults(PurpleConnection *gc, const char *title, const char *primary, const char *secondary, @@ -429,7 +437,10 @@ for (iter = results->columns; iter; iter = iter->next) { PurpleNotifySearchColumn *column = iter->data; - gnt_tree_set_column_title(GNT_TREE(tree), i, column->title); + gnt_tree_set_column_title(GNT_TREE(tree), i, purple_notify_searchresult_column_get_title(column)); + + if (!purple_notify_searchresult_column_is_visible(column)) + gnt_tree_set_column_visible(GNT_TREE(tree), i, FALSE); i++; } @@ -478,6 +489,8 @@ } gnt_box_add_widget(GNT_BOX(window), box); + g_signal_connect(G_OBJECT(tree), "destroy", + G_CALLBACK(notify_sr_destroy_cb), NULL); finch_notify_sr_new_rows(gc, results, tree); diff -r 2908b16efa07 -r f01d6c9f3492 finch/gntprefs.c --- a/finch/gntprefs.c Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/gntprefs.c Fri Apr 06 04:30:00 2012 +0000 @@ -62,14 +62,6 @@ void finch_prefs_update_old() { - const char *str = NULL; - - purple_prefs_rename("/gaim/gnt", "/finch"); - purple_prefs_rename("/purple/gnt", "/finch"); - - if ((str = purple_prefs_get_string("/purple/away/idle_reporting")) && - strcmp(str, "gaim") == 0) - purple_prefs_set_string("/purple/away/idle_reporting", "purple"); } typedef struct diff -r 2908b16efa07 -r f01d6c9f3492 finch/gntrequest.c --- a/finch/gntrequest.c Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/gntrequest.c Fri Apr 06 04:30:00 2012 +0000 @@ -41,12 +41,6 @@ #include "debug.h" #include "util.h" -/* XXX: Until gobjectification ... */ -#undef FINCH_GET_DATA -#undef FINCH_SET_DATA -#define FINCH_GET_DATA(obj) purple_request_field_get_ui_data(obj) -#define FINCH_SET_DATA(obj, data) purple_request_field_set_ui_data(obj, data) - typedef struct { void *user_data; @@ -323,26 +317,26 @@ continue; if (type == PURPLE_REQUEST_FIELD_BOOLEAN) { - GntWidget *check = FINCH_GET_DATA(field); + GntWidget *check = purple_request_field_get_ui_data(field); gboolean value = gnt_check_box_get_checked(GNT_CHECK_BOX(check)); purple_request_field_bool_set_value(field, value); } else if (type == PURPLE_REQUEST_FIELD_STRING) { - GntWidget *entry = FINCH_GET_DATA(field); + GntWidget *entry = purple_request_field_get_ui_data(field); const char *text = gnt_entry_get_text(GNT_ENTRY(entry)); purple_request_field_string_set_value(field, (text && *text) ? text : NULL); } else if (type == PURPLE_REQUEST_FIELD_INTEGER) { - GntWidget *entry = FINCH_GET_DATA(field); + GntWidget *entry = purple_request_field_get_ui_data(field); const char *text = gnt_entry_get_text(GNT_ENTRY(entry)); int value = (text && *text) ? atoi(text) : 0; purple_request_field_int_set_value(field, value); } else if (type == PURPLE_REQUEST_FIELD_CHOICE) { - GntWidget *combo = FINCH_GET_DATA(field); + GntWidget *combo = purple_request_field_get_ui_data(field); int id; id = GPOINTER_TO_INT(gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo))); purple_request_field_choice_set_value(field, id); @@ -352,7 +346,7 @@ GList *list = NULL, *iter; if (purple_request_field_list_get_multi_select(field)) { - GntWidget *tree = FINCH_GET_DATA(field); + GntWidget *tree = purple_request_field_get_ui_data(field); iter = purple_request_field_list_get_items(field); for (; iter; iter = iter->next) @@ -365,7 +359,7 @@ } else { - GntWidget *combo = FINCH_GET_DATA(field); + GntWidget *combo = purple_request_field_get_ui_data(field); gpointer data = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo)); iter = purple_request_field_list_get_items(field); @@ -384,7 +378,7 @@ } else if (type == PURPLE_REQUEST_FIELD_ACCOUNT) { - GntWidget *combo = FINCH_GET_DATA(field); + GntWidget *combo = purple_request_field_get_ui_data(field); PurpleAccount *acc = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(combo)); purple_request_field_account_set_value(field, acc); } @@ -577,6 +571,22 @@ return combo; } +static GntWidget* +create_certificate_field(PurpleRequestField *field) +{ + GntWidget *w; + PurpleCertificate *cert; + char *str; + + cert = purple_request_field_certificate_get_value(field); + str = purple_certificate_get_display_string(cert); + w = gnt_label_new(str); + + g_free(str); + + return w; +} + static void * finch_request_fields(const char *title, const char *primary, const char *secondary, PurpleRequestFields *allfields, @@ -633,36 +643,40 @@ if (type == PURPLE_REQUEST_FIELD_BOOLEAN) { - FINCH_SET_DATA(field, create_boolean_field(field)); + purple_request_field_set_ui_data(field, create_boolean_field(field)); } else if (type == PURPLE_REQUEST_FIELD_STRING) { - FINCH_SET_DATA(field, create_string_field(field, &username)); + purple_request_field_set_ui_data(field, create_string_field(field, &username)); } else if (type == PURPLE_REQUEST_FIELD_INTEGER) { - FINCH_SET_DATA(field, create_integer_field(field)); + purple_request_field_set_ui_data(field, create_integer_field(field)); } else if (type == PURPLE_REQUEST_FIELD_CHOICE) { - FINCH_SET_DATA(field, create_choice_field(field)); + purple_request_field_set_ui_data(field, create_choice_field(field)); } else if (type == PURPLE_REQUEST_FIELD_LIST) { - FINCH_SET_DATA(field, create_list_field(field)); + purple_request_field_set_ui_data(field, create_list_field(field)); } else if (type == PURPLE_REQUEST_FIELD_ACCOUNT) { accountlist = create_account_field(field); - FINCH_SET_DATA(field, accountlist); + purple_request_field_set_ui_data(field, accountlist); + } + else if (type == PURPLE_REQUEST_FIELD_CERTIFICATE) + { + purple_request_field_set_ui_data(field, create_certificate_field(field)); } else { - FINCH_SET_DATA(field, gnt_label_new_with_format(_("Not implemented yet."), + purple_request_field_set_ui_data(field, gnt_label_new_with_format(_("Not implemented yet."), GNT_TEXT_FLAG_BOLD)); } gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID); - gnt_box_add_widget(GNT_BOX(hbox), GNT_WIDGET(FINCH_GET_DATA(field))); + gnt_box_add_widget(GNT_BOX(hbox), GNT_WIDGET(purple_request_field_get_ui_data(field))); } if (grlist->next) gnt_box_add_widget(GNT_BOX(box), gnt_hline_new()); diff -r 2908b16efa07 -r f01d6c9f3492 finch/gntrequest.h --- a/finch/gntrequest.h Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/gntrequest.h Fri Apr 06 04:30:00 2012 +0000 @@ -63,7 +63,6 @@ * @param field The request field. * * @return A GntWidget for the request field. - * @since 2.4.0 */ GntWidget *finch_request_field_get_widget(PurpleRequestField *field); /*@}*/ diff -r 2908b16efa07 -r f01d6c9f3492 finch/gntroomlist.c --- a/finch/gntroomlist.c Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/gntroomlist.c Fri Apr 06 04:30:00 2012 +0000 @@ -41,6 +41,7 @@ #define PREF_ROOT "/finch/roomlist" + /* Yes, just one roomlist at a time. Let's not get greedy. Aight? */ struct _FinchRoomlist { @@ -146,9 +147,9 @@ purple_roomlist_room_join(froomlist.roomlist, room); break; case PURPLE_ROOMLIST_ROOMTYPE_CATEGORY: - if (!room->expanded_once) { + if (!purple_roomlist_room_get_expanded_once(room)) { purple_roomlist_expand_category(froomlist.roomlist, room); - room->expanded_once = TRUE; + purple_roomlist_room_set_expanded_once(room, TRUE); } break; } @@ -343,7 +344,7 @@ static void fl_create(PurpleRoomlist *list) { - FINCH_SET_DATA(list, &froomlist); + purple_roomlist_set_ui_data(list, &froomlist); setup_roomlist(NULL); update_roomlist(list); } diff -r 2908b16efa07 -r f01d6c9f3492 finch/gntsound.c --- a/finch/gntsound.c Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/gntsound.c Fri Apr 06 04:30:00 2012 +0000 @@ -150,7 +150,7 @@ return ret; account = purple_conversation_get_account(conv); - nick = g_strdup(purple_normalize(account, chat->nick)); + nick = g_strdup(purple_normalize(account, purple_conv_chat_get_nick(chat))); name = g_strdup(purple_normalize(account, aname)); if (g_utf8_collate(nick, name) == 0) @@ -268,7 +268,7 @@ if (chat_nick_matches_name(conv, sender)) return; - if (flags & PURPLE_MESSAGE_NICK || purple_utf8_has_word(message, chat->nick)) + if (flags & PURPLE_MESSAGE_NICK || purple_utf8_has_word(message, purple_conv_chat_get_nick(chat))) play_conv_event(conv, PURPLE_SOUND_CHAT_NICK); else play_conv_event(conv, event); diff -r 2908b16efa07 -r f01d6c9f3492 finch/gntsound.h --- a/finch/gntsound.h Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/gntsound.h Fri Apr 06 04:30:00 2012 +0000 @@ -37,8 +37,6 @@ * Get the name of the active sound profile. * * @return The name of the profile - * - * @since 2.1.0 */ const char *finch_sound_get_active_profile(void); @@ -46,8 +44,6 @@ * Set the active profile. If the profile doesn't exist, nothing is changed. * * @param name The name of the profile - * - * @since 2.1.0 */ void finch_sound_set_active_profile(const char *name); @@ -56,8 +52,6 @@ * * @return A list of strings denoting sound profile names. * Caller must free the list (but not the data). - * - * @since 2.1.0 */ GList *finch_sound_get_profiles(void); @@ -66,8 +60,6 @@ * * @return Returns FALSE if preference is set to 'No sound', or if volume is * set to zero. - * - * @since 2.2.0 */ gboolean finch_sound_is_enabled(void); @@ -75,15 +67,11 @@ * Gets GNT sound UI ops. * * @return The UI operations structure. - * - * @since 2.1.0 */ PurpleSoundUiOps *finch_sound_get_ui_ops(void); /** * Show the sound settings dialog. - * - * @since 2.1.0 */ void finch_sounds_show_all(void); diff -r 2908b16efa07 -r f01d6c9f3492 finch/libgnt/gntfilesel.h --- a/finch/libgnt/gntfilesel.h Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/libgnt/gntfilesel.h Fri Apr 06 04:30:00 2012 +0000 @@ -81,7 +81,7 @@ void (*gnt_reserved4)(void); }; -typedef enum _GntFileType +typedef enum { GNT_FILE_REGULAR, GNT_FILE_DIR diff -r 2908b16efa07 -r f01d6c9f3492 finch/libgnt/gntprogressbar.h --- a/finch/libgnt/gntprogressbar.h Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/libgnt/gntprogressbar.h Fri Apr 06 04:30:00 2012 +0000 @@ -37,7 +37,7 @@ #define GNT_IS_PROGRESS_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GNT_TYPE_PROGRESS_BAR)) #define GNT_PROGRESS_BAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GNT_TYPE_PROGRESS_BAR, GntProgressBarClass)) -typedef enum _GntProgressBarOrientation +typedef enum { GNT_PROGRESS_LEFT_TO_RIGHT, GNT_PROGRESS_RIGHT_TO_LEFT, diff -r 2908b16efa07 -r f01d6c9f3492 finch/libgnt/gnttree.h --- a/finch/libgnt/gnttree.h Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/libgnt/gnttree.h Fri Apr 06 04:30:00 2012 +0000 @@ -47,7 +47,7 @@ typedef struct _GntTreeRow GntTreeRow; typedef struct _GntTreeCol GntTreeCol; -typedef enum _GntTreeColumnFlag { +typedef enum { GNT_TREE_COLUMN_INVISIBLE = 1 << 0, GNT_TREE_COLUMN_FIXED_SIZE = 1 << 1, GNT_TREE_COLUMN_BINARY_DATA = 1 << 2, diff -r 2908b16efa07 -r f01d6c9f3492 finch/libgnt/gntwidget.h --- a/finch/libgnt/gntwidget.h Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/libgnt/gntwidget.h Fri Apr 06 04:30:00 2012 +0000 @@ -49,7 +49,7 @@ typedef struct _GntWidgetPriv GntWidgetPriv; typedef struct _GntWidgetClass GntWidgetClass; -typedef enum _GntWidgetFlags +typedef enum { GNT_WIDGET_DESTROYING = 1 << 0, GNT_WIDGET_CAN_TAKE_FOCUS = 1 << 1, @@ -69,7 +69,7 @@ } GntWidgetFlags; /* XXX: This will probably move elsewhere */ -typedef enum _GntMouseEvent +typedef enum { GNT_LEFT_MOUSE_DOWN = 1, GNT_RIGHT_MOUSE_DOWN, @@ -80,7 +80,7 @@ } GntMouseEvent; /* XXX: I'll have to ask grim what he's using this for in guifications. */ -typedef enum _GntParamFlags +typedef enum { GNT_PARAM_SERIALIZABLE = 1 << G_PARAM_USER_SHIFT } GntParamFlags; diff -r 2908b16efa07 -r f01d6c9f3492 finch/libgnt/gntwm.h --- a/finch/libgnt/gntwm.h Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/libgnt/gntwm.h Fri Apr 06 04:30:00 2012 +0000 @@ -41,7 +41,7 @@ #define GNT_IS_WM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GNT_TYPE_WM)) #define GNT_WM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNT_TYPE_WM, GntWMClass)) -typedef enum _GntKeyPressMode +typedef enum { GNT_KP_MODE_NORMAL, GNT_KP_MODE_RESIZE, diff -r 2908b16efa07 -r f01d6c9f3492 finch/plugins/gntgf.c --- a/finch/plugins/gntgf.c Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/plugins/gntgf.c Fri Apr 06 04:30:00 2012 +0000 @@ -168,7 +168,7 @@ beep(); if (conv != NULL) { - FinchConv *fc = conv->ui_data; + FinchConv *fc = FINCH_CONV(conv); if (gnt_widget_has_focus(fc->window)) return; } @@ -256,7 +256,7 @@ if (flags & PURPLE_MESSAGE_WHISPER) return; - nick = PURPLE_CONV_CHAT(conv)->nick; + nick = purple_conv_chat_get_nick(PURPLE_CONV_CHAT(conv)); if (g_utf8_collate(sender, nick) == 0) return; diff -r 2908b16efa07 -r f01d6c9f3492 finch/plugins/gnttinyurl.c --- a/finch/plugins/gnttinyurl.c Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/plugins/gnttinyurl.c Fri Apr 06 04:30:00 2012 +0000 @@ -319,7 +319,7 @@ url = g_strdup_printf("%s%s", purple_prefs_get_string(PREF_URL), purple_url_encode(tmp)); } g_free(tmp); - purple_util_fetch_url(url, TRUE, "finch", FALSE, url_fetched, cbdata); + purple_util_fetch_url(url, TRUE, "finch", FALSE, -1, url_fetched, cbdata); i = gnt_text_view_get_lines_below(tv); str = g_strdup_printf(_("\nFetching TinyURL...")); gnt_text_view_append_text_with_tag((tv), str, GNT_TEXT_FLAG_DIM, cbdata->tag); @@ -383,7 +383,7 @@ /* Store the return value of _fetch_url and destroy that when win is destroyed, so that the callback for _fetch_url does not try to molest a non-existent window */ - urlcb = purple_util_fetch_url(fullurl, TRUE, "finch", FALSE, tinyurl_notify_fetch_cb, win); + urlcb = purple_util_fetch_url(fullurl, TRUE, "finch", FALSE, -1, tinyurl_notify_fetch_cb, win); g_free(fullurl); g_signal_connect_swapped(G_OBJECT(win), "destroy", G_CALLBACK(purple_util_fetch_url_cancel), urlcb); diff -r 2908b16efa07 -r f01d6c9f3492 finch/plugins/grouping.c --- a/finch/plugins/grouping.c Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/plugins/grouping.c Fri Apr 06 04:30:00 2012 +0000 @@ -54,7 +54,7 @@ case PURPLE_BLIST_CONTACT_NODE: { PurpleContact *contact = (PurpleContact*)node; - if (contact->currentsize > 0) + if (purple_contact_get_contact_size(contact, FALSE) > 0) return TRUE; return FALSE; } diff -r 2908b16efa07 -r f01d6c9f3492 finch/plugins/lastlog.c --- a/finch/plugins/lastlog.c Mon Apr 02 23:36:20 2012 +0000 +++ b/finch/plugins/lastlog.c Fri Apr 06 04:30:00 2012 +0000 @@ -60,7 +60,7 @@ static PurpleCmdRet lastlog_cb(PurpleConversation *conv, const char *cmd, char **args, char **error, gpointer null) { - FinchConv *ggconv = conv->ui_data; + FinchConv *ggconv = FINCH_CONV(conv); char **strings = g_strsplit(GNT_TEXT_VIEW(ggconv->tv)->string->str, "\n", 0); GntWidget *win, *tv; int i, j; diff -r 2908b16efa07 -r f01d6c9f3492 gaim-uninstalled.pc.in --- a/gaim-uninstalled.pc.in Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ -datarootdir=@datarootdir@ -datadir=@datadir@ -sysconfdir=@sysconfdir@ - -Name: Pidgin (Gaim compatibility) -Description: Pidgin is a GTK2-based instant messenger application. -Version: @VERSION@ -Requires: glib-2.0 -Cflags: -I${pc_top_builddir}/${pcfiledir}/libpurple -I${pc_top_builddir}/${pcfiledir}/pidgin -Libs: ${pc_top_builddir}/${pcfiledir}/libpurple/libpurple.la diff -r 2908b16efa07 -r f01d6c9f3492 gaim.pc.in --- a/gaim.pc.in Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ -datarootdir=@datarootdir@ -datadir=@datadir@ -sysconfdir=@sysconfdir@ - -Name: Pidgin (Gaim compatibility) -Description: Pidgin is a GTK2-based instant messenger application. -Version: @VERSION@ -Requires: glib-2.0 -Cflags: -I${includedir}/libpurple -Libs: -L${libdir} -lpurple diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/Makefile.am --- a/libpurple/Makefile.am Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/Makefile.am Fri Apr 06 04:30:00 2012 +0000 @@ -9,8 +9,8 @@ purple-send-async \ purple-url-handler \ purple.h.in \ - purple.pc.in \ - purple-uninstalled.pc.in \ + purple-3.pc.in \ + purple-3-uninstalled.pc.in \ version.h.in \ Makefile.mingw \ win32/global.mak \ @@ -30,7 +30,7 @@ endif pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = purple.pc +pkgconfig_DATA = purple-3.pc SUBDIRS = $(GCONF_DIR) plugins protocols ciphers . tests example @@ -117,7 +117,6 @@ desktopitem.h \ eventloop.h \ ft.h \ - gaim-compat.h \ idle.h \ imgstore.h \ log.h \ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/account.c --- a/libpurple/account.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/account.c Fri Apr 06 04:30:00 2012 +0000 @@ -41,14 +41,6 @@ #include "util.h" #include "xmlnode.h" -typedef struct -{ - PurpleConnectionErrorInfo *current_error; -} PurpleAccountPrivate; - -#define PURPLE_ACCOUNT_GET_PRIVATE(account) \ - ((PurpleAccountPrivate *) (account->priv)) - /* TODO: Should use PurpleValue instead of this? What about "ui"? */ typedef struct { @@ -361,8 +353,6 @@ static xmlnode * account_to_xmlnode(PurpleAccount *account) { - PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); - xmlnode *node, *child; const char *tmp; PurplePresence *presence; @@ -419,7 +409,7 @@ xmlnode_insert_child(node, child); } - child = current_error_to_xmlnode(priv->current_error); + child = current_error_to_xmlnode(account->current_error); xmlnode_insert_child(node, child); return node; @@ -874,7 +864,7 @@ return NULL; } - ret = purple_account_new(name, _purple_oscar_convert(name, protocol_id)); /* XXX: */ + ret = purple_account_new(name, protocol_id); g_free(name); g_free(protocol_id); @@ -924,15 +914,6 @@ { purple_buddy_icons_set_account_icon(ret, (guchar *)contents, len); } - else - { - /* Try to see if the icon got left behind in the old cache. */ - g_free(filename); - filename = g_build_filename(g_get_home_dir(), ".gaim", "icons", data, NULL); - 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); @@ -1005,7 +986,6 @@ purple_account_new(const char *username, const char *protocol_id) { PurpleAccount *account = NULL; - PurpleAccountPrivate *priv = NULL; PurplePlugin *prpl = NULL; PurplePluginProtocolInfo *prpl_info = NULL; PurpleStatusType *status_type; @@ -1020,8 +1000,6 @@ account = g_new0(PurpleAccount, 1); PURPLE_DBUS_REGISTER_POINTER(account, PurpleAccount); - priv = g_new0(PurpleAccountPrivate, 1); - account->priv = priv; purple_account_set_username(account, username); @@ -1064,7 +1042,6 @@ void purple_account_destroy(PurpleAccount *account) { - PurpleAccountPrivate *priv = NULL; GList *l; g_return_if_fail(account != NULL); @@ -1095,7 +1072,8 @@ purple_account_set_status_types(account, NULL); - purple_presence_destroy(account->presence); + if (account->presence) + purple_presence_destroy(account->presence); if(account->system_log) purple_log_free(account->system_log); @@ -1110,13 +1088,11 @@ account->permit = g_slist_delete_link(account->permit, account->permit); } - priv = PURPLE_ACCOUNT_GET_PRIVATE(account); - PURPLE_DBUS_UNREGISTER_POINTER(priv->current_error); - if (priv->current_error) { - g_free(priv->current_error->description); - g_free(priv->current_error); + PURPLE_DBUS_UNREGISTER_POINTER(account->current_error); + if (account->current_error) { + g_free(account->current_error->description); + g_free(account->current_error); } - g_free(priv); PURPLE_DBUS_UNREGISTER_POINTER(account); g_free(account); @@ -1143,6 +1119,15 @@ } void +purple_account_register_completed(PurpleAccount *account, gboolean succeeded) +{ + g_return_if_fail(account != NULL); + + if (account->registration_cb) + (account->registration_cb)(account, succeeded, account->registration_cb_user_data); +} + +void purple_account_unregister(PurpleAccount *account, PurpleAccountUnregistrationCb cb, void *user_data) { g_return_if_fail(account != NULL); @@ -1289,6 +1274,14 @@ account->disconnecting = FALSE; } +gboolean +purple_account_is_disconnecting(const PurpleAccount *account) +{ + g_return_val_if_fail(account != NULL, TRUE); + + return account->disconnecting; +} + void purple_account_notify_added(PurpleAccount *account, const char *remote_user, const char *id, const char *alias, @@ -1615,7 +1608,7 @@ purple_request_input(gc, _("Set User Info"), primary, NULL, purple_account_get_user_info(account), TRUE, FALSE, ((gc != NULL) && - (gc->flags & PURPLE_CONNECTION_HTML) ? "html" : NULL), + (purple_connection_get_flags(gc) & PURPLE_CONNECTION_HTML) ? "html" : NULL), _("Save"), G_CALLBACK(set_user_info_cb), _("Cancel"), NULL, account, NULL, NULL, @@ -2495,6 +2488,24 @@ return setting->value.boolean; } +gpointer +purple_account_get_ui_data(const PurpleAccount *account) +{ + g_return_val_if_fail(account != NULL, NULL); + + return account->ui_data; +} + +void +purple_account_set_ui_data(PurpleAccount *account, + gpointer ui_data) +{ + g_return_if_fail(account != NULL); + + account->ui_data = ui_data; +} + + PurpleLog * purple_account_get_log(PurpleAccount *account, gboolean create) { @@ -2527,7 +2538,7 @@ } void -purple_account_add_buddy(PurpleAccount *account, PurpleBuddy *buddy) +purple_account_add_buddy(PurpleAccount *account, PurpleBuddy *buddy, const char *message) { PurplePluginProtocolInfo *prpl_info = NULL; PurpleConnection *gc; @@ -2544,40 +2555,13 @@ prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); if (prpl_info != NULL) { - if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddy_with_invite)) - prpl_info->add_buddy_with_invite(gc, buddy, purple_buddy_get_group(buddy), NULL); - else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddy)) - prpl_info->add_buddy(gc, buddy, purple_buddy_get_group(buddy)); + if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddy)) + prpl_info->add_buddy(gc, buddy, purple_buddy_get_group(buddy), message); } } void -purple_account_add_buddy_with_invite(PurpleAccount *account, PurpleBuddy *buddy, const char *message) -{ - PurplePluginProtocolInfo *prpl_info = NULL; - PurpleConnection *gc; - PurplePlugin *prpl = NULL; - - g_return_if_fail(account != NULL); - g_return_if_fail(buddy != NULL); - - gc = purple_account_get_connection(account); - if (gc != NULL) - prpl = purple_connection_get_prpl(gc); - - if (prpl != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if (prpl_info != NULL) { - if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddy_with_invite)) - prpl_info->add_buddy_with_invite(gc, buddy, purple_buddy_get_group(buddy), message); - else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddy)) - prpl_info->add_buddy(gc, buddy, purple_buddy_get_group(buddy)); - } -} - -void -purple_account_add_buddies(PurpleAccount *account, GList *buddies) +purple_account_add_buddies(PurpleAccount *account, GList *buddies, const char *message) { PurplePluginProtocolInfo *prpl_info = NULL; PurpleConnection *gc = purple_account_get_connection(account); @@ -2598,73 +2582,13 @@ groups = g_list_append(groups, purple_buddy_get_group(buddy)); } - if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddies_with_invite)) - prpl_info->add_buddies_with_invite(gc, buddies, groups, NULL); - else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddies)) - prpl_info->add_buddies(gc, buddies, groups); - else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddy_with_invite)) { - GList *curb = buddies, *curg = groups; - - while ((curb != NULL) && (curg != NULL)) { - prpl_info->add_buddy_with_invite(gc, curb->data, curg->data, NULL); - curb = curb->next; - curg = curg->next; - } - } + if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddies)) + prpl_info->add_buddies(gc, buddies, groups, message); else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddy)) { GList *curb = buddies, *curg = groups; while ((curb != NULL) && (curg != NULL)) { - prpl_info->add_buddy(gc, curb->data, curg->data); - curb = curb->next; - curg = curg->next; - } - } - - g_list_free(groups); - } -} - -void -purple_account_add_buddies_with_invite(PurpleAccount *account, GList *buddies, const char *message) -{ - PurplePluginProtocolInfo *prpl_info = NULL; - PurpleConnection *gc = purple_account_get_connection(account); - PurplePlugin *prpl = NULL; - - if (gc != NULL) - prpl = purple_connection_get_prpl(gc); - - if (prpl != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if (prpl_info) { - GList *cur, *groups = NULL; - - /* Make a list of what group each buddy is in */ - for (cur = buddies; cur != NULL; cur = cur->next) { - PurpleBuddy *buddy = cur->data; - groups = g_list_append(groups, purple_buddy_get_group(buddy)); - } - - if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddies_with_invite)) - prpl_info->add_buddies_with_invite(gc, buddies, groups, message); - else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddy_with_invite)) { - GList *curb = buddies, *curg = groups; - - while ((curb != NULL) && (curg != NULL)) { - prpl_info->add_buddy_with_invite(gc, curb->data, curg->data, message); - curb = curb->next; - curg = curg->next; - } - } - else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddies)) - prpl_info->add_buddies(gc, buddies, groups); - else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, add_buddy)) { - GList *curb = buddies, *curg = groups; - - while ((curb != NULL) && (curg != NULL)) { - prpl_info->add_buddy(gc, curb->data, curg->data); + prpl_info->add_buddy(gc, curb->data, curg->data, message); curb = curb->next; curg = curg->next; } @@ -2804,18 +2728,16 @@ static void set_current_error(PurpleAccount *account, PurpleConnectionErrorInfo *new_err) { - PurpleAccountPrivate *priv; PurpleConnectionErrorInfo *old_err; g_return_if_fail(account != NULL); - priv = PURPLE_ACCOUNT_GET_PRIVATE(account); - old_err = priv->current_error; + old_err = account->current_error; if(new_err == old_err) return; - priv->current_error = new_err; + account->current_error = new_err; purple_signal_emit(purple_accounts_get_handle(), "account-error-changed", @@ -2857,8 +2779,7 @@ const PurpleConnectionErrorInfo * purple_account_get_current_error(PurpleAccount *account) { - PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); - return priv->current_error; + return account->current_error; } void diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/account.h --- a/libpurple/account.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/account.h Fri Apr 06 04:30:00 2012 +0000 @@ -168,12 +168,10 @@ PurpleAccountRegistrationCb registration_cb; void *registration_cb_user_data; - gpointer priv; /**< Pointer to opaque private data. */ + PurpleConnectionErrorInfo *current_error; /**< Errors */ }; -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Account API */ @@ -221,6 +219,15 @@ void purple_account_register(PurpleAccount *account); /** + * Registration of the account was completed. + * Calls the registration call-back set with purple_account_set_register_callback(). + * + * @param account The account being registered. + * @param succeeded Was the account registration successful? + */ +void purple_account_register_completed(PurpleAccount *account, gboolean succeeded); + +/** * Unregisters an account (deleting it from the server). * * @param account The account to unregister. @@ -237,6 +244,15 @@ void purple_account_disconnect(PurpleAccount *account); /** + * Indicates if the account is currently being disconnected. + * + * @param account The account + * + * @return TRUE if the account is being disconnected. + */ +gboolean purple_account_is_disconnecting(const PurpleAccount *account); + +/** * Notifies the user that the account was added to a remote user's * buddy list. * @@ -433,8 +449,6 @@ * * @param account The account. * @param privacy_type The privacy type. - * - * @since 2.7.0 */ void purple_account_set_privacy_type(PurpleAccount *account, PurplePrivacyType privacy_type); @@ -491,8 +505,6 @@ * is successfully set on the server (or NULL). * @param failure_cb A callback which will be called if the alias * is not successfully set on the server (or NULL). - * - * @since 2.7.0 */ void purple_account_set_public_alias(PurpleAccount *account, const char *alias, PurpleSetPublicAliasSuccessCallback success_cb, @@ -506,7 +518,6 @@ * @param success_cb A callback which will be called with the alias * @param failure_cb A callback which will be called if the prpl is * unable to retrieve the server-side alias. - * @since 2.7.0 */ void purple_account_get_public_alias(PurpleAccount *account, PurpleGetPublicAliasSuccessCallback success_cb, @@ -542,8 +553,6 @@ * * @param account The account. * @param setting The setting to remove. - * - * @since 2.6.0 */ void purple_account_remove_setting(PurpleAccount *account, const char *setting); @@ -610,6 +619,25 @@ const char *name, gboolean value); /** + * Returns the UI data associated with this account. + * + * @param account The account. + * + * @return The UI data associated with this object. This is a + * convenience field provided to the UIs--it is not + * used by the libuprple core. + */ +gpointer purple_account_get_ui_data(const PurpleAccount *account); + +/** + * Set the UI data associated with this account. + * + * @param account The account. + * @param ui_data A pointer to associate with this object. + */ +void purple_account_set_ui_data(PurpleAccount *account, gpointer ui_data); + +/** * Returns whether or not the account is connected. * * @param account The account. @@ -717,8 +745,6 @@ * @param account The account. * * @return The name to display. - * - * @since 2.7.0 */ const gchar *purple_account_get_name_for_display(const PurpleAccount *account); @@ -767,8 +793,6 @@ * @param account The account. * * @return The privacy type. - * - * @since 2.7.0 */ PurplePrivacyType purple_account_get_privacy_type(const PurpleAccount *account); @@ -958,40 +982,18 @@ * * @param account The account. * @param buddy The buddy to add. - * - * @deprecated Use purple_account_add_buddy_with_invite and \c NULL message. + * @param message The invite message. This may be ignored by a prpl. */ -void purple_account_add_buddy(PurpleAccount *account, PurpleBuddy *buddy); -/** - * Adds a buddy to the server-side buddy list for the specified account. - * - * @param account The account. - * @param buddy The buddy to add. - * @param message The invite message. This may be ignored by a prpl. - * - * @since 2.8.0 - */ -void purple_account_add_buddy_with_invite(PurpleAccount *account, PurpleBuddy *buddy, const char *message); +void purple_account_add_buddy(PurpleAccount *account, PurpleBuddy *buddy, const char *message); /** * Adds a list of buddies to the server-side buddy list. * * @param account The account. * @param buddies The list of PurpleBlistNodes representing the buddies to add. - * - * @deprecated Use purple_account_add_buddies_with_invite and \c NULL message. + * @param message The invite message. This may be ignored by a prpl. */ -void purple_account_add_buddies(PurpleAccount *account, GList *buddies); -/** - * Adds a list of buddies to the server-side buddy list. - * - * @param account The account. - * @param buddies The list of PurpleBlistNodes representing the buddies to add. - * @param message The invite message. This may be ignored by a prpl. - * - * @since 2.8.0 - */ -void purple_account_add_buddies_with_invite(PurpleAccount *account, GList *buddies, const char *message); +void purple_account_add_buddies(PurpleAccount *account, GList *buddies, const char *message); /** * Removes a buddy from the server-side buddy list. @@ -1187,8 +1189,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_ACCOUNT_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/accountopt.c --- a/libpurple/accountopt.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/accountopt.c Fri Apr 06 04:30:00 2012 +0000 @@ -28,6 +28,51 @@ #include "accountopt.h" #include "util.h" +/** + * An option for an account. + * + * This is set by protocol plugins, and appears in the account settings + * dialogs. + */ +struct _PurpleAccountOption +{ + PurplePrefType type; /**< The type of value. */ + + char *text; /**< The text that will appear to the user. */ + char *pref_name; /**< The name of the associated preference. */ + + union + { + gboolean boolean; /**< The default boolean value. */ + int integer; /**< The default integer value. */ + char *string; /**< The default string value. */ + GList *list; /**< The default list value. */ + + } default_value; + + gboolean masked; /**< Whether the value entered should be + * obscured from view (for passwords and + * similar options) + */ +}; + +/** + * A username split. + * + * This is used by some protocols to separate the fields of the username + * into more human-readable components. + */ +struct _PurpleAccountUserSplit +{ + char *text; /**< The text that will appear to the user. */ + char *default_value; /**< The default value. */ + char field_sep; /**< The field separator. */ + gboolean reverse; /**< TRUE if the separator should be found + starting a the end of the string, FALSE + otherwise */ +}; + + PurpleAccountOption * purple_account_option_new(PurplePrefType type, const char *text, const char *pref_name) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/accountopt.h --- a/libpurple/accountopt.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/accountopt.h Fri Apr 06 04:30:00 2012 +0000 @@ -28,54 +28,16 @@ #include "prefs.h" -/** - * An option for an account. - * - * This is set by protocol plugins, and appears in the account settings - * dialogs. - */ -typedef struct -{ - PurplePrefType type; /**< The type of value. */ - - char *text; /**< The text that will appear to the user. */ - char *pref_name; /**< The name of the associated preference. */ - - union - { - gboolean boolean; /**< The default boolean value. */ - int integer; /**< The default integer value. */ - char *string; /**< The default string value. */ - GList *list; /**< The default list value. */ - - } default_value; +/**************************************************************************/ +/** Data Structures */ +/**************************************************************************/ - gboolean masked; /**< Whether the value entered should be - * obscured from view (for passwords and - * similar options) - */ -} PurpleAccountOption; +/** @copydoc _PurpleAccountOption */ +typedef struct _PurpleAccountOption PurpleAccountOption; +/** @copydoc _PurpleAccountUserSplit */ +typedef struct _PurpleAccountUserSplit PurpleAccountUserSplit; -/** - * A username split. - * - * This is used by some protocols to separate the fields of the username - * into more human-readable components. - */ -typedef struct -{ - char *text; /**< The text that will appear to the user. */ - char *default_value; /**< The default value. */ - char field_sep; /**< The field separator. */ - gboolean reverse; /**< TRUE if the separator should be found - starting a the end of the string, FALSE - otherwise */ - -} PurpleAccountUserSplit; - -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Account Option API */ @@ -388,8 +350,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_ACCOUNTOPT_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/blist.c --- a/libpurple/blist.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/blist.c Fri Apr 06 04:30:00 2012 +0000 @@ -314,7 +314,7 @@ node = xmlnode_new("account"); xmlnode_set_attrib(node, "proto", purple_account_get_protocol_id(account)); xmlnode_set_attrib(node, "name", purple_account_get_username(account)); - g_snprintf(buf, sizeof(buf), "%d", account->perm_deny); + g_snprintf(buf, sizeof(buf), "%d", purple_account_get_privacy_type(account)); xmlnode_set_attrib(node, "mode", buf); for (cur = account->permit; cur; cur = cur->next) @@ -461,19 +461,16 @@ PurpleAccount *account; PurpleBuddy *buddy; char *name = NULL, *alias = NULL; - const char *acct_name, *proto, *protocol; + const char *acct_name, *proto; xmlnode *x; acct_name = xmlnode_get_attrib(bnode, "account"); - protocol = xmlnode_get_attrib(bnode, "protocol"); - protocol = _purple_oscar_convert(acct_name, protocol); /* XXX: Remove */ proto = xmlnode_get_attrib(bnode, "proto"); - proto = _purple_oscar_convert(acct_name, proto); /* XXX: Remove */ - - if (!acct_name || (!proto && !protocol)) + + if (!acct_name || !proto) return; - account = purple_accounts_find(acct_name, proto ? proto : protocol); + account = purple_accounts_find(acct_name, proto); if (!account) return; @@ -532,19 +529,18 @@ { PurpleChat *chat; PurpleAccount *account; - const char *acct_name, *proto, *protocol; + const char *acct_name, *proto; xmlnode *x; char *alias = NULL; GHashTable *components; acct_name = xmlnode_get_attrib(cnode, "account"); - protocol = xmlnode_get_attrib(cnode, "protocol"); proto = xmlnode_get_attrib(cnode, "proto"); - if (!acct_name || (!proto && !protocol)) + if (!acct_name || !proto) return; - account = purple_accounts_find(acct_name, proto ? proto : protocol); + account = purple_accounts_find(acct_name, proto); if (!account) return; @@ -630,23 +626,22 @@ xmlnode *x; PurpleAccount *account; int imode; - const char *acct_name, *proto, *mode, *protocol; + const char *acct_name, *proto, *mode; acct_name = xmlnode_get_attrib(anode, "name"); - protocol = xmlnode_get_attrib(anode, "protocol"); proto = xmlnode_get_attrib(anode, "proto"); mode = xmlnode_get_attrib(anode, "mode"); - if (!acct_name || (!proto && !protocol) || !mode) + if (!acct_name || !proto || !mode) continue; - account = purple_accounts_find(acct_name, proto ? proto : protocol); + account = purple_accounts_find(acct_name, proto); if (!account) continue; imode = atoi(mode); - account->perm_deny = (imode != 0 ? imode : PURPLE_PRIVACY_ALLOW_ALL); + purple_account_set_privacy_type(account, (imode != 0 ? imode : PURPLE_PRIVACY_ALLOW_ALL)); for (x = anode->child; x; x = x->next) { char *name; @@ -961,12 +956,6 @@ ops->update(purplebuddylist, node); } -void -purple_blist_update_buddy_icon(PurpleBuddy *buddy) -{ - purple_blist_update_node_icon((PurpleBlistNode *)buddy); -} - /* * TODO: Maybe remove the call to this from server.c and call it * from oscar.c and toc.c instead? @@ -1318,7 +1307,7 @@ purple_account_remove_buddies(account, buddies, groups); g_list_free(groups); - purple_account_add_buddies(account, buddies); + purple_account_add_buddies(account, buddies, NULL); } g_list_free(buddies); @@ -1748,11 +1737,6 @@ return (PurpleGroup *)(((PurpleBlistNode *)contact)->parent); } -void purple_contact_set_alias(PurpleContact *contact, const char *alias) -{ - purple_blist_alias_contact(contact,alias); -} - const char *purple_contact_get_alias(PurpleContact* contact) { g_return_val_if_fail(contact != NULL, NULL); @@ -1790,6 +1774,13 @@ contact->priority_valid = FALSE; } +int purple_contact_get_contact_size(PurpleContact *contact, gboolean offline) +{ + g_return_val_if_fail(contact != NULL, 0); + + return offline ? contact->totalsize : contact->currentsize; +} + PurpleGroup *purple_group_new(const char *name) { PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); @@ -2380,26 +2371,6 @@ return NULL; } -const char *purple_buddy_get_local_alias(PurpleBuddy *buddy) -{ - PurpleContact *c; - - g_return_val_if_fail(buddy != NULL, NULL); - - /* Search for an alias for the buddy. In order of precedence: */ - /* The buddy alias */ - if (buddy->alias != NULL) - return buddy->alias; - - /* The contact alias */ - c = purple_buddy_get_contact(buddy); - if ((c != NULL) && (c->alias != NULL)) - return c->alias; - - /* The buddy's user name (i.e. no alias) */ - return buddy->name; -} - const char *purple_chat_get_name(PurpleChat *chat) { char *ret = NULL; @@ -2937,6 +2908,17 @@ return node->type; } +gboolean +purple_blist_node_has_setting(PurpleBlistNode* node, const char *key) +{ + g_return_val_if_fail(node != NULL, FALSE); + g_return_val_if_fail(node->settings != NULL, FALSE); + g_return_val_if_fail(key != NULL, FALSE); + + /* Boxed type, so it won't ever be NULL, so no need for _extended */ + return (g_hash_table_lookup(node->settings, key) != NULL); +} + void purple_blist_node_set_bool(PurpleBlistNode* node, const char *key, gboolean data) { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/blist.h --- a/libpurple/blist.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/blist.h Fri Apr 06 04:30:00 2012 +0000 @@ -75,9 +75,6 @@ } PurpleBlistNodeFlags; -/** - * @since 2.6.0 - */ #define PURPLE_BLIST_NODE(obj) ((PurpleBlistNode *)(obj)) #define PURPLE_BLIST_NODE_HAS_FLAG(b, f) (purple_blist_node_get_flags((PurpleBlistNode*)(b)) & (f)) @@ -86,24 +83,12 @@ #define PURPLE_BLIST_NODE_NAME(n) (purple_blist_node_get_type(n) == PURPLE_BLIST_CHAT_NODE ? purple_chat_get_name((PurpleChat*)n) : \ purple_blist_node_get_type(n) == PURPLE_BLIST_BUDDY_NODE ? purple_buddy_get_name((PurpleBuddy*)n) : NULL) -/** - * @since 2.6.0 - */ #define PURPLE_GROUP(obj) ((PurpleGroup *)(obj)) -/** - * @since 2.6.0 - */ #define PURPLE_CONTACT(obj) ((PurpleContact *)(obj)) -/** - * @since 2.6.0 - */ #define PURPLE_BUDDY(obj) ((PurpleBuddy *)(obj)) -/** - * @since 2.6.0 - */ #define PURPLE_CHAT(obj) ((PurpleChat *)(obj)) #include "account.h" @@ -226,8 +211,6 @@ * previous libpurple versions. * * @param node The node which has been modified. - * - * @since 2.6.0. */ void (*save_node)(PurpleBlistNode *node); @@ -241,7 +224,6 @@ * previous libpurple versions. * * @param node The node which has been modified. - * @since 2.6.0. */ void (*remove_node)(PurpleBlistNode *node); @@ -256,16 +238,13 @@ * * @param account The account whose data to save. If NULL, save all data * for all accounts. - * @since 2.6.0. */ void (*save_account)(PurpleAccount *account); void (*_purple_reserved1)(void); }; -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Buddy List API */ @@ -311,7 +290,6 @@ * freeing the list. * * @see purple_find_buddies - * @since 2.6.0 */ GSList *purple_blist_get_buddies(void); @@ -319,8 +297,6 @@ * Returns the UI data for the list. * * @return The UI data for the list. - * - * @since 2.6.0 */ gpointer purple_blist_get_ui_data(void); @@ -328,8 +304,6 @@ * Sets the UI data for the list. * * @param ui_data The UI data for the list. - * - * @since 2.6.0 */ void purple_blist_set_ui_data(gpointer ui_data); @@ -352,7 +326,7 @@ * * @param node A node. * @return The parent node. - * @since 2.4.0 + * * @see purple_blist_node_get_first_child * @see purple_blist_node_get_sibling_next * @see purple_blist_node_get_sibling_prev @@ -365,7 +339,7 @@ * * @param node A node. * @return The child node. - * @since 2.4.0 + * * @see purple_blist_node_get_parent * @see purple_blist_node_get_sibling_next * @see purple_blist_node_get_sibling_prev @@ -378,7 +352,7 @@ * * @param node A node. * @return The sibling node. - * @since 2.4.0 + * * @see purple_blist_node_get_parent * @see purple_blist_node_get_first_child * @see purple_blist_node_get_sibling_prev @@ -391,7 +365,7 @@ * * @param node A node. * @return The sibling node. - * @since 2.4.0 + * * @see purple_blist_node_get_parent * @see purple_blist_node_get_first_child * @see purple_blist_node_get_sibling_next @@ -404,7 +378,6 @@ * * @param node The node. * @return The UI data. - * @since 2.6.0 */ gpointer purple_blist_node_get_ui_data(const PurpleBlistNode *node); @@ -413,8 +386,6 @@ * * @param node The node. * @param ui_data The UI data. - * - * @since 2.6.0 */ void purple_blist_node_set_ui_data(PurpleBlistNode *node, gpointer ui_data); @@ -454,21 +425,9 @@ * Updates a node's custom icon. * * @param node The PurpleBlistNode whose custom icon has changed. - * - * @since 2.5.0 */ void purple_blist_update_node_icon(PurpleBlistNode *node); -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_BLIST_C_) -/** - * Updates a buddy's icon. - * - * @param buddy The buddy whose buddy icon has changed - * @deprecated Use purple_blist_update_node_icon() instead. - */ -void purple_blist_update_buddy_icon(PurpleBuddy *buddy); -#endif - /** * Renames a buddy in the buddy list. * @@ -623,7 +582,6 @@ * @return The protocol data. * * @see purple_buddy_set_protocol_data() - * @since 2.6.0 */ gpointer purple_buddy_get_protocol_data(const PurpleBuddy *buddy); @@ -636,7 +594,6 @@ * @param data The data. * * @see purple_buddy_get_protocol_data() - * @since 2.6.0 */ void purple_buddy_set_protocol_data(PurpleBuddy *buddy, gpointer data); @@ -663,8 +620,6 @@ * * @param buddy The buddy. * @return The media caps. - * - * @since 2.7.0 */ PurpleMediaCaps purple_buddy_get_media_caps(const PurpleBuddy *buddy); @@ -739,8 +694,6 @@ * * @param contact The contact * @return The group - * - * @since 2.7.0 */ PurpleGroup *purple_contact_get_group(const PurpleContact *contact); @@ -774,18 +727,6 @@ */ PurpleBuddy *purple_contact_get_priority_buddy(PurpleContact *contact); -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_BLIST_C_) -/** - * Sets the alias for a contact. - * - * @param contact The contact - * @param alias The alias to set, or NULL to unset - * - * @deprecated Use purple_blist_alias_contact() instead. - */ -void purple_contact_set_alias(PurpleContact *contact, const char *alias); -#endif - /** * Gets the alias for a contact. * @@ -813,6 +754,15 @@ void purple_contact_invalidate_priority_buddy(PurpleContact *contact); /** + * Determines the total size of a contact. + * + * @param contact The contact + * @param offline Count buddies in offline accounts + * @return The number of buddies in the contact + */ +int purple_contact_get_contact_size(PurpleContact *contact, gboolean offline); + +/** * Removes a buddy from the buddy list and frees the memory allocated to it. * This doesn't actually try to remove the buddy from the server list. * @@ -876,19 +826,6 @@ */ const char *purple_buddy_get_contact_alias(PurpleBuddy *buddy); -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_BLIST_C_) -/** - * Returns the correct alias for this user, ignoring server aliases. Used - * when a user-recognizable name is required. In order: buddy's alias; buddy's - * contact alias; buddy's user name. - * - * @param buddy The buddy whose alias will be returned. - * @return The appropriate name or alias. - * @deprecated Try purple_buddy_get_alias(), if server aliases are okay. - */ -const char *purple_buddy_get_local_alias(PurpleBuddy *buddy); -#endif - /** * Returns the correct name to display for a buddy. In order of precedence: * the buddy's alias; the buddy's server alias; the buddy's contact alias; @@ -904,8 +841,6 @@ * * @param buddy The buddy * @return The local alias for the buddy - * - * @since 2.6.0 */ const char *purple_buddy_get_local_buddy_alias(PurpleBuddy *buddy); @@ -981,8 +916,6 @@ * @param chat The chat. * * @return The account the chat belongs to. - * - * @since 2.4.0 */ PurpleAccount *purple_chat_get_account(PurpleChat *chat); @@ -992,8 +925,6 @@ * @param chat The chat. * * @constreturn The hashtable. - * - * @since 2.4.0 */ GHashTable *purple_chat_get_components(PurpleChat *chat); @@ -1121,6 +1052,16 @@ void purple_blist_request_add_group(void); /** + * Checks whether a named setting exists for a node in the buddy list + * + * @param node The node to check from which to check settings + * @param key The identifier of the data + * + * @return TRUE if a value exists, or FALSE if there is no setting + */ +gboolean purple_blist_node_has_setting(PurpleBlistNode *node, const char *key); + +/** * Associates a boolean with a node in the buddy list * * @param node The node to associate the data with @@ -1211,8 +1152,6 @@ * @param node The node. * * @return The type of the node. - * - * @since 2.1.0 */ PurpleBlistNodeType purple_blist_node_get_type(PurpleBlistNode *node); @@ -1271,8 +1210,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_BLIST_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/buddyicon.c --- a/libpurple/buddyicon.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/buddyicon.c Fri Apr 06 04:30:00 2012 +0000 @@ -105,9 +105,6 @@ /** "Should icons be cached to disk?" */ static gboolean icon_caching = TRUE; -/* For ~/.gaim to ~/.purple migration. */ -static char *old_icons_dir = NULL; - static void delete_buddy_icon_settings(PurpleBlistNode *node, const char *setting_name); /* @@ -759,7 +756,7 @@ else g_hash_table_remove(pointer_icon_cache, account); - if (purple_account_is_connected(account)) + if (!purple_account_is_disconnected(account)) { PurpleConnection *gc; PurplePluginProtocolInfo *prpl_info; @@ -958,31 +955,6 @@ return purple_buddy_icons_node_set_custom_icon(node, data, len); } -gboolean -purple_buddy_icons_has_custom_icon(PurpleContact *contact) -{ - return purple_buddy_icons_node_has_custom_icon((PurpleBlistNode*)contact); -} - -PurpleStoredImage * -purple_buddy_icons_find_custom_icon(PurpleContact *contact) -{ - return purple_buddy_icons_node_find_custom_icon((PurpleBlistNode*)contact); -} - -PurpleStoredImage * -purple_buddy_icons_set_custom_icon(PurpleContact *contact, guchar *icon_data, - size_t icon_len) -{ - return purple_buddy_icons_node_set_custom_icon((PurpleBlistNode*)contact, icon_data, icon_len); -} - -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) { @@ -995,133 +967,6 @@ } } -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)) - { - g_free(path); - delete_buddy_icon_settings(node, setting_name); - return; - } - - if (icon_data == NULL || icon_len <= 0) - { - /* This really applies to the icon_len check. - * icon_data should never be NULL if - * read_icon_file() returns TRUE. */ - purple_debug_error("buddyicon", "Empty buddy icon file: %s\n", path); - delete_buddy_icon_settings(node, setting_name); - g_free(path); - return; - } - - g_free(path); - - new_filename = purple_util_get_image_filename(icon_data, icon_len); - if (new_filename == NULL) - { - purple_debug_error("buddyicon", - "New icon filename is NULL. This should never happen! " - "The old filename was: %s\n", path); - delete_buddy_icon_settings(node, setting_name); - g_return_if_reached(); - } - - 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, g_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, g_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 (purple_strequal(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 - { - PurpleAccount *account = purple_buddy_get_account((PurpleBuddy *)node); - const char *prpl_id = purple_account_get_protocol_id(account); - - if (g_str_equal(prpl_id, "prpl-yahoo") || g_str_equal(prpl_id, "prpl-yahoojp")) - { - 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); - } - } - } - } - } - else - { - purple_debug_error("buddyicon", "Old icon file doesn't exist: %s\n", path); - delete_buddy_icon_settings(node, setting_name); - g_free(path); - } -} - void _purple_buddy_icons_account_loaded_cb() { @@ -1153,22 +998,6 @@ 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, g_strerror(errno)); - } - } - } - while (node != NULL) { if (PURPLE_BLIST_NODE_IS_BUDDY(node)) @@ -1178,26 +1007,17 @@ filename = purple_blist_node_get_string(node, "buddy_icon"); if (filename != NULL) { - if (old_icons_dir != NULL) + char *path = g_build_filename(dirname, filename, NULL); + if (!g_file_test(path, G_FILE_TEST_EXISTS)) { - migrate_buddy_icon(node, - "buddy_icon", - dirname, filename); + purple_blist_node_remove_setting(node, + "buddy_icon"); + purple_blist_node_remove_setting(node, + "icon_checksum"); } 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); - } + ref_filename(filename); + g_free(path); } } else if (PURPLE_BLIST_NODE_IS_CONTACT(node) || @@ -1209,24 +1029,15 @@ filename = purple_blist_node_get_string(node, "custom_buddy_icon"); if (filename != NULL) { - if (old_icons_dir != NULL) + char *path = g_build_filename(dirname, filename, NULL); + if (!g_file_test(path, G_FILE_TEST_EXISTS)) { - migrate_buddy_icon(node, - "custom_buddy_icon", - dirname, filename); + purple_blist_node_remove_setting(node, + "custom_buddy_icon"); } 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); - } + ref_filename(filename); + g_free(path); } } node = purple_blist_node_next(node, TRUE); @@ -1298,11 +1109,9 @@ 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); g_free(cache_dir); cache_dir = NULL; - old_icons_dir = NULL; } void purple_buddy_icon_get_scale_size(PurpleBuddyIconSpec *spec, int *width, int *height) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/buddyicon.h --- a/libpurple/buddyicon.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/buddyicon.h Fri Apr 06 04:30:00 2012 +0000 @@ -39,10 +39,7 @@ #include "prpl.h" #include "util.h" -#ifdef __cplusplus -extern "C" { -#endif - +G_BEGIN_DECLS /**************************************************************************/ /** @name Buddy Icon API */ @@ -275,7 +272,6 @@ * @param node The blist node. * * @return A boolean indicating if @a node has a custom buddy icon. - * @since 2.5.0 */ gboolean purple_buddy_icons_node_has_custom_icon(PurpleBlistNode *node); @@ -293,7 +289,6 @@ * @param node The node. * * @return The custom buddy icon. - * @since 2.5.0 */ PurpleStoredImage * purple_buddy_icons_node_find_custom_icon(PurpleBlistNode *node); @@ -311,7 +306,6 @@ * * @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. - * @since 2.5.0 */ PurpleStoredImage * purple_buddy_icons_node_set_custom_icon(PurpleBlistNode *node, @@ -329,45 +323,11 @@ * * @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. - * @since 2.5.0 */ PurpleStoredImage * purple_buddy_icons_node_set_custom_icon_from_file(PurpleBlistNode *node, const gchar *filename); -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_BUDDYICON_C_) -/** - * PurpleContact version of purple_buddy_icons_node_has_custom_icon. - * - * @copydoc purple_buddy_icons_node_has_custom_icon() - * - * @deprecated Use purple_buddy_icons_node_has_custom_icon instead. - */ -gboolean -purple_buddy_icons_has_custom_icon(PurpleContact *contact); - -/** - * PurpleContact version of purple_buddy_icons_node_find_custom_icon. - * - * @copydoc purple_buddy_icons_node_find_custom_icon() - * - * @deprecated Use purple_buddy_icons_node_find_custom_icon instead. - */ -PurpleStoredImage * -purple_buddy_icons_find_custom_icon(PurpleContact *contact); - -/** - * PurpleContact version of purple_buddy_icons_node_set_custom_icon. - * - * @copydoc purple_buddy_icons_node_set_custom_icon() - * - * @deprecated Use purple_buddy_icons_node_set_custom_icon instead. - */ -PurpleStoredImage * -purple_buddy_icons_set_custom_icon(PurpleContact *contact, - guchar *icon_data, size_t icon_len); -#endif - /** * Sets whether or not buddy icon caching is enabled. * @@ -434,8 +394,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_BUDDYICON_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/certificate.c --- a/libpurple/certificate.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/certificate.c Fri Apr 06 04:30:00 2012 +0000 @@ -275,7 +275,7 @@ } gboolean -purple_certificate_check_signature_chain_with_failing(GList *chain, +purple_certificate_check_signature_chain(GList *chain, PurpleCertificate **failing) { GList *cur; @@ -363,12 +363,6 @@ return TRUE; } -gboolean -purple_certificate_check_signature_chain(GList *chain) -{ - return purple_certificate_check_signature_chain_with_failing(chain, NULL); -} - PurpleCertificate * purple_certificate_import(PurpleCertificateScheme *scheme, const gchar *filename) { @@ -505,6 +499,42 @@ return (scheme->get_times)(crt, activation, expiration); } +GByteArray * +purple_certificate_get_der_data(PurpleCertificate *crt) +{ + PurpleCertificateScheme *scheme; + GByteArray *data; + + g_return_val_if_fail(crt, NULL); + g_return_val_if_fail(crt->scheme, NULL); + + scheme = crt->scheme; + + g_return_val_if_fail(scheme->get_der_data, NULL); + + data = (scheme->get_der_data)(crt); + + return data; +} + +gchar * +purple_certificate_get_display_string(PurpleCertificate *crt) +{ + PurpleCertificateScheme *scheme; + gchar *str; + + g_return_val_if_fail(crt, NULL); + g_return_val_if_fail(crt->scheme, NULL); + + scheme = crt->scheme; + + g_return_val_if_fail(scheme->get_display_string, NULL); + + str = (scheme->get_display_string)(crt); + + return str; +} + gchar * purple_certificate_pool_mkpath(PurpleCertificatePool *pool, const gchar *id) { @@ -650,77 +680,62 @@ /****************************************************************************/ static void -x509_singleuse_verify_cb (PurpleCertificateVerificationRequest *vrq, gint id) +x509_singleuse_verify_accept_cb(PurpleCertificateVerificationRequest *vrq) { g_return_if_fail(vrq); purple_debug_info("certificate/x509_singleuse", - "VRQ on cert from %s gave %d\n", - vrq->subject_name, id); + "VRQ on cert from %s accepted\n", + vrq->subject_name); + + purple_certificate_verify_complete(vrq, PURPLE_CERTIFICATE_VALID); +} - /* Signal what happened back to the caller */ - if (1 == id) { - /* Accepted! */ - purple_certificate_verify_complete(vrq, - PURPLE_CERTIFICATE_VALID); - } else { - /* Not accepted */ - purple_certificate_verify_complete(vrq, - PURPLE_CERTIFICATE_INVALID); +static void +x509_singleuse_verify_reject_cb(PurpleCertificateVerificationRequest *vrq) +{ + g_return_if_fail(vrq); - } + purple_debug_info("certificate/x509_singleuse", + "VRQ on cert from %s rejected\n", + vrq->subject_name); + + purple_certificate_verify_complete(vrq, PURPLE_CERTIFICATE_INVALID); } static void x509_singleuse_start_verify (PurpleCertificateVerificationRequest *vrq) { - gchar *sha_asc; - GByteArray *sha_bin; gchar *cn; const gchar *cn_match; gchar *primary, *secondary; - PurpleCertificate *crt = (PurpleCertificate *) vrq->cert_chain->data; + PurpleCertificate *crt = (PurpleCertificate *)vrq->cert_chain->data; - /* Pull out the SHA1 checksum */ - sha_bin = purple_certificate_get_fingerprint_sha1(crt); - /* Now decode it for display */ - sha_asc = purple_base16_encode_chunked(sha_bin->data, - sha_bin->len); - - /* Get the cert Common Name */ cn = purple_certificate_get_subject_name(crt); - /* Determine whether the name matches */ if (purple_certificate_check_subject_name(crt, vrq->subject_name)) { - cn_match = ""; + cn_match = _("(MATCH)"); } else { cn_match = _("(DOES NOT MATCH)"); } - /* Make messages */ primary = g_strdup_printf(_("%s has presented the following certificate for just-this-once use:"), vrq->subject_name); - secondary = g_strdup_printf(_("Common name: %s %s\nFingerprint (SHA1): %s"), cn, cn_match, sha_asc); + secondary = g_strdup_printf(_("Common name: %s %s"), cn, cn_match); /* Make a semi-pretty display */ - purple_request_accept_cancel( + purple_request_certificate( vrq->cb_data, /* TODO: Find what the handle ought to be */ _("Single-use Certificate Verification"), primary, secondary, - 0, /* Accept by default */ - NULL, /* No account */ - NULL, /* No other user */ - NULL, /* No associated conversation */ - vrq, - x509_singleuse_verify_cb, - x509_singleuse_verify_cb ); + crt, + _("Accept"), G_CALLBACK(x509_singleuse_verify_accept_cb), + _("Reject"), G_CALLBACK(x509_singleuse_verify_reject_cb), + vrq); - /* Cleanup */ g_free(cn); g_free(primary); g_free(secondary); - g_free(sha_asc); - g_byte_array_free(sha_bin, TRUE); } static void @@ -1277,102 +1292,34 @@ static PurpleCertificateVerifier x509_tls_cached; -/* The following is several hacks piled together and needs to be fixed. - * It exists because show_cert (see its comments) needs the original reason - * given to user_auth in order to rebuild the dialog. - */ -/* TODO: This will cause a ua_ctx to become memleaked if the request(s) get - closed by handle or otherwise abnormally. */ -typedef struct { - PurpleCertificateVerificationRequest *vrq; - gchar *reason; -} x509_tls_cached_ua_ctx; - -static x509_tls_cached_ua_ctx * -x509_tls_cached_ua_ctx_new(PurpleCertificateVerificationRequest *vrq, - const gchar *reason) +static void +x509_tls_cached_user_auth_accept_cb(PurpleCertificateVerificationRequest *vrq) { - x509_tls_cached_ua_ctx *c; + PurpleCertificatePool *tls_peers; + gchar *cache_id; - c = g_new0(x509_tls_cached_ua_ctx, 1); - c->vrq = vrq; - c->reason = g_strdup(reason); + g_return_if_fail(vrq); + + tls_peers = purple_certificate_find_pool("x509", "tls_peers"); - return c; -} - + cache_id = vrq->subject_name; + purple_debug_info("certificate/x509/tls_cached", + "User ACCEPTED cert\nCaching first in chain for future use as %s...\n", + cache_id); -static void -x509_tls_cached_ua_ctx_free(x509_tls_cached_ua_ctx *c) -{ - g_return_if_fail(c); - g_free(c->reason); - g_free(c); + purple_certificate_pool_store(tls_peers, cache_id, vrq->cert_chain->data); + + purple_certificate_verify_complete(vrq, PURPLE_CERTIFICATE_VALID); } static void -x509_tls_cached_user_auth(PurpleCertificateVerificationRequest *vrq, - const gchar *reason); - -static void -x509_tls_cached_show_cert(x509_tls_cached_ua_ctx *c, gint id) +x509_tls_cached_user_auth_reject_cb(PurpleCertificateVerificationRequest *vrq) { - PurpleCertificate *disp_crt = c->vrq->cert_chain->data; - - /* Since clicking a button closes the request, show it again */ - x509_tls_cached_user_auth(c->vrq, c->reason); - - /* Show the certificate AFTER re-opening the dialog so that this - appears above the other */ - purple_certificate_display_x509(disp_crt); - - x509_tls_cached_ua_ctx_free(c); -} - -static void -x509_tls_cached_user_auth_cb (x509_tls_cached_ua_ctx *c, gint id) -{ - PurpleCertificateVerificationRequest *vrq; - PurpleCertificatePool *tls_peers; - - g_return_if_fail(c); - g_return_if_fail(c->vrq); - - vrq = c->vrq; - - x509_tls_cached_ua_ctx_free(c); + g_return_if_fail(vrq); - tls_peers = purple_certificate_find_pool("x509","tls_peers"); - - if (2 == id) { - gchar *cache_id = vrq->subject_name; - purple_debug_info("certificate/x509/tls_cached", - "User ACCEPTED cert\nCaching first in chain for future use as %s...\n", - cache_id); - - purple_certificate_pool_store(tls_peers, cache_id, - vrq->cert_chain->data); + purple_debug_warning("certificate/x509/tls_cached", "User REJECTED cert\n"); - purple_certificate_verify_complete(vrq, - PURPLE_CERTIFICATE_VALID); - } else { - purple_debug_warning("certificate/x509/tls_cached", - "User REJECTED cert\n"); - purple_certificate_verify_complete(vrq, - PURPLE_CERTIFICATE_INVALID); - } -} - -static void -x509_tls_cached_user_auth_accept_cb(x509_tls_cached_ua_ctx *c, gint ignore) -{ - x509_tls_cached_user_auth_cb(c, 2); -} - -static void -x509_tls_cached_user_auth_reject_cb(x509_tls_cached_ua_ctx *c, gint ignore) -{ - x509_tls_cached_user_auth_cb(c, 1); + purple_certificate_verify_complete(vrq, PURPLE_CERTIFICATE_INVALID); } /** Validates a certificate by asking the user @@ -1386,27 +1333,19 @@ { gchar *primary; - /* Make messages */ primary = g_strdup_printf(_("Accept certificate for %s?"), vrq->subject_name); - /* Make a semi-pretty display */ - purple_request_action( + purple_request_certificate( vrq->cb_data, /* TODO: Find what the handle ought to be */ _("SSL Certificate Verification"), primary, reason, - 0, /* Accept by default */ - NULL, /* No account */ - NULL, /* No other user */ - NULL, /* No associated conversation */ - x509_tls_cached_ua_ctx_new(vrq, reason), - 3, /* Number of actions */ - _("Accept"), x509_tls_cached_user_auth_accept_cb, - _("Reject"), x509_tls_cached_user_auth_reject_cb, - _("_View Certificate..."), x509_tls_cached_show_cert); + vrq->cert_chain->data, + _("Accept"), G_CALLBACK(x509_tls_cached_user_auth_accept_cb), + _("Reject"), G_CALLBACK(x509_tls_cached_user_auth_reject_cb), + vrq); - /* Cleanup */ g_free(primary); } @@ -1622,7 +1561,7 @@ ca = purple_certificate_find_pool(x509_tls_cached.scheme_name, "ca"); /* Next, check that the certificate chain is valid */ - if (!purple_certificate_check_signature_chain_with_failing(chain, + if (!purple_certificate_check_signature_chain(chain, &failing_crt)) { gboolean chain_validated = FALSE; @@ -1704,7 +1643,7 @@ flags |= PURPLE_CERTIFICATE_CA_UNKNOWN; purple_debug_warning("certificate/x509/tls_cached", - "No Certificate Authorities with either DN found " + "No Certificate Authorities with either DN " "found. I'll prompt the user, I guess.\n"); x509_tls_cached_check_subject_name(vrq, flags); @@ -2153,63 +2092,6 @@ /* Scheme-specific functions */ /****************************************************************************/ -void -purple_certificate_display_x509(PurpleCertificate *crt) -{ - gchar *sha_asc; - GByteArray *sha_bin; - gchar *cn; - time_t activation, expiration; - gchar *activ_str, *expir_str; - gchar *secondary; - - /* Pull out the SHA1 checksum */ - sha_bin = purple_certificate_get_fingerprint_sha1(crt); - /* Now decode it for display */ - sha_asc = purple_base16_encode_chunked(sha_bin->data, - sha_bin->len); - - /* Get the cert Common Name */ - /* TODO: Will break on CA certs */ - cn = purple_certificate_get_subject_name(crt); - - /* Get the certificate times */ - /* TODO: Check the times against localtime */ - /* TODO: errorcheck? */ - if (!purple_certificate_get_times(crt, &activation, &expiration)) { - purple_debug_error("certificate", - "Failed to get certificate times!\n"); - activation = expiration = 0; - } - activ_str = g_strdup(ctime(&activation)); - expir_str = g_strdup(ctime(&expiration)); - - /* Make messages */ - secondary = g_strdup_printf(_("Common name: %s\n\n" - "Fingerprint (SHA1): %s\n\n" - "Activation date: %s\n" - "Expiration date: %s\n"), - cn ? cn : "(null)", - sha_asc ? sha_asc : "(null)", - activ_str ? activ_str : "(null)", - expir_str ? expir_str : "(null)"); - - /* Make a semi-pretty display */ - purple_notify_info( - NULL, /* TODO: Find what the handle ought to be */ - _("Certificate Information"), - "", - secondary); - - /* Cleanup */ - g_free(cn); - g_free(secondary); - g_free(sha_asc); - g_free(activ_str); - g_free(expir_str); - g_byte_array_free(sha_bin, TRUE); -} - void purple_certificate_add_ca_search_path(const char *path) { if (g_list_find_custom(x509_ca_paths, path, (GCompareFunc)strcmp)) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/certificate.h --- a/libpurple/certificate.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/certificate.h Fri Apr 06 04:30:00 2012 +0000 @@ -2,7 +2,6 @@ * @file certificate.h Public-Key Certificate API * @ingroup core * @see @ref certificate-signals - * @since 2.2.0 */ /* @@ -35,11 +34,6 @@ #include -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - - typedef enum { PURPLE_CERTIFICATE_INVALID = 0, @@ -258,9 +252,25 @@ */ GSList * (* import_certificates)(const gchar * filename); + /** + * Retrieves the certificate data in DER form + * + * @param crt Certificate instance + * @return Binary DER representation of certificate - must be freed using + * g_byte_array_free() + */ + GByteArray * (* get_der_data)(PurpleCertificate *crt); + + /** + * Retrieves a string representation of the certificate suitable for display + * + * @param crt Certificate instance + * @return User-displayable string representation of certificate - must be + * freed using g_free(). + */ + gchar * (* get_display_string)(PurpleCertificate *crt); + void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); }; /** A set of operations used to provide logic for verifying a Certificate's @@ -350,6 +360,8 @@ gpointer cb_data; }; +G_BEGIN_DECLS + /*****************************************************************************/ /** @name Certificate Verification Functions */ /*****************************************************************************/ @@ -462,33 +474,12 @@ * chain fails to validate, this will be set to the * certificate whose signature could not be validated. * @return TRUE if the chain is valid. See description. - * - * @since 2.6.0 - * @deprecated This function will become - * purple_certificate_check_signature_chain in 3.0.0 */ gboolean -purple_certificate_check_signature_chain_with_failing(GList *chain, +purple_certificate_check_signature_chain(GList *chain, PurpleCertificate **failing); /** - * Check that a certificate chain is valid - * - * Uses purple_certificate_signed_by() to verify that each PurpleCertificate - * in the chain carries a valid signature from the next. A single-certificate - * chain is considered to be valid. - * - * @param chain List of PurpleCertificate instances comprising the chain, - * in the order certificate, issuer, issuer's issuer, etc. - * @return TRUE if the chain is valid. See description. - * @todo Specify which certificate in the chain caused a failure - * @deprecated This function will be removed in 3.0.0 and replaced with - * purple_certificate_check_signature_chain_with_failing - */ -gboolean -purple_certificate_check_signature_chain(GList *chain); - -/** * Imports a PurpleCertificate from a file * * @param scheme Scheme to import under @@ -583,6 +574,28 @@ gboolean purple_certificate_get_times(PurpleCertificate *crt, time_t *activation, time_t *expiration); +/** + * Retrieves the certificate data in DER form. + * + * @param crt Certificate instance + * + * @return Binary DER representation of the certificate - must be freed using + * g_byte_array_free(). + */ +GByteArray * +purple_certificate_get_der_data(PurpleCertificate *crt); + +/** + * Retrieves a string suitable for displaying a certificate to the user. + * + * @param crt Certificate instance + * + * @return String representing the certificate that may be displayed to the user + * - must be freed using g_free(). + */ +char * +purple_certificate_get_display_string(PurpleCertificate *crt); + /*@}*/ /*****************************************************************************/ @@ -821,23 +834,12 @@ /** - * Displays a window showing X.509 certificate information - * - * @param crt Certificate under an "x509" Scheme - * @todo Will break on CA certs, as they have no Common Name - */ -void -purple_certificate_display_x509(PurpleCertificate *crt); - -/** * Add a search path for certificates. * * @param path Path to search for certificates. */ void purple_certificate_add_ca_search_path(const char *path); -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS #endif /* _PURPLE_CERTIFICATE_H */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/cipher.h --- a/libpurple/cipher.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/cipher.h Fri Apr 06 04:30:00 2012 +0000 @@ -41,7 +41,7 @@ /** * Modes for batch encrypters */ -typedef enum _PurpleCipherBatchMode { +typedef enum { PURPLE_CIPHER_BATCH_MODE_ECB, PURPLE_CIPHER_BATCH_MODE_CBC } PurpleCipherBatchMode; @@ -49,7 +49,7 @@ /** * The operation flags for a cipher */ -typedef enum _PurpleCipherCaps { +typedef enum { PURPLE_CIPHER_CAPS_SET_OPT = 1 << 1, /**< Set option flag */ PURPLE_CIPHER_CAPS_GET_OPT = 1 << 2, /**< Get option flag */ PURPLE_CIPHER_CAPS_INIT = 1 << 3, /**< Init flag */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/circbuffer.h --- a/libpurple/circbuffer.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/circbuffer.h Fri Apr 06 04:30:00 2012 +0000 @@ -26,10 +26,6 @@ #include -#ifdef __cplusplus -extern "C" { -#endif - typedef struct _PurpleCircBuffer { /** A pointer to the starting address of our chunk of memory. */ @@ -55,6 +51,8 @@ } PurpleCircBuffer; +G_BEGIN_DECLS + /** * Creates a new circular buffer. This will not allocate any memory for the * actual buffer until data is appended to it. @@ -111,8 +109,6 @@ */ gboolean purple_circ_buffer_mark_read(PurpleCircBuffer *buf, gsize len); -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _CIRCBUFFER_H */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/cmds.c --- a/libpurple/cmds.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/cmds.c Fri Apr 06 04:30:00 2012 +0000 @@ -385,5 +385,10 @@ void purple_cmds_uninit(void) { purple_signals_unregister_by_instance(purple_cmds_get_handle()); + + while (cmds) { + purple_cmd_free(cmds->data); + cmds = g_list_delete_link(cmds, cmds); + } } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/cmds.h --- a/libpurple/cmds.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/cmds.h Fri Apr 06 04:30:00 2012 +0000 @@ -32,7 +32,7 @@ /*@{*/ /** The possible results of running a command with purple_cmd_do_command(). */ -typedef enum _PurpleCmdStatus { +typedef enum { PURPLE_CMD_STATUS_OK, PURPLE_CMD_STATUS_FAILED, PURPLE_CMD_STATUS_NOT_FOUND, @@ -48,7 +48,7 @@ * #PURPLE_CMD_RET_CONTINUE to cause the core to fall through to other * commands with the same name. */ -typedef enum _PurpleCmdRet { +typedef enum { PURPLE_CMD_RET_OK, /**< Everything's okay; Don't look for another command to call. */ PURPLE_CMD_RET_FAILED, /**< The command failed, but stop looking.*/ PURPLE_CMD_RET_CONTINUE /**< Continue, looking for other commands with the same name to call. */ @@ -68,7 +68,7 @@ */ typedef guint PurpleCmdId; -typedef enum _PurpleCmdPriority { +typedef enum { PURPLE_CMD_P_VERY_LOW = -1000, PURPLE_CMD_P_LOW = 0, PURPLE_CMD_P_DEFAULT = 1000, @@ -85,7 +85,7 @@ * * @see purple_cmd_register */ -typedef enum _PurpleCmdFlag { +typedef enum { /** Command is usable in IMs. */ PURPLE_CMD_FLAG_IM = 0x01, /** Command is usable in multi-user chats. */ @@ -99,9 +99,7 @@ /*@}*/ -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Commands API */ @@ -225,26 +223,21 @@ /** * Get the handle for the commands API * @return The handle - * @since 2.5.0 */ gpointer purple_cmds_get_handle(void); /** * Initialize the commands subsystem. - * @since 2.5.0 */ void purple_cmds_init(void); /** * Uninitialize the commands subsystem. - * @since 2.5.0 */ void purple_cmds_uninit(void); /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_CMDS_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/connection.c --- a/libpurple/connection.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/connection.c Fri Apr 06 04:30:00 2012 +0000 @@ -92,12 +92,6 @@ } void -purple_connection_new(PurpleAccount *account, gboolean regist, const char *password) -{ - _purple_connection_new(account, regist, password); -} - -void _purple_connection_new(PurpleAccount *account, gboolean regist, const char *password) { PurpleConnection *gc; @@ -171,11 +165,6 @@ prpl_info->login(account); } } -void -purple_connection_new_unregister(PurpleAccount *account, const char *password, PurpleAccountUnregistrationCb cb, void *user_data) -{ - _purple_connection_new_unregister(account, password, cb, user_data); -} void _purple_connection_new_unregister(PurpleAccount *account, const char *password, PurpleAccountUnregistrationCb cb, void *user_data) @@ -234,12 +223,6 @@ } void -purple_connection_destroy(PurpleConnection *gc) -{ - _purple_connection_destroy(gc); -} - -void _purple_connection_destroy(PurpleConnection *gc) { PurpleAccount *account; @@ -404,6 +387,14 @@ } void +purple_connection_set_flags(PurpleConnection *gc, PurpleConnectionFlags flags) +{ + g_return_if_fail(gc != NULL); + + gc->flags = flags; +} + +void purple_connection_set_account(PurpleConnection *gc, PurpleAccount *account) { g_return_if_fail(gc != NULL); @@ -436,6 +427,14 @@ return gc->state; } +PurpleConnectionFlags +purple_connection_get_flags(const PurpleConnection *gc) +{ + g_return_val_if_fail(gc != NULL, 0); + + return gc->flags; +} + PurpleAccount * purple_connection_get_account(const PurpleConnection *gc) { @@ -457,7 +456,7 @@ { g_return_val_if_fail(gc != NULL, NULL); - return gc->password ? gc->password : gc->account->password; + return gc->password ? gc->password : purple_account_get_password(gc->account); } const char * @@ -528,22 +527,7 @@ } void -purple_connection_error(PurpleConnection *gc, const char *text) -{ - /* prpls that have not been updated to use disconnection reasons will - * be setting wants_to_die before calling this function, so choose - * PURPLE_CONNECTION_ERROR_OTHER_ERROR (which is fatal) if it's true, - * and PURPLE_CONNECTION_ERROR_NETWORK_ERROR (which isn't) if not. See - * the documentation in connection.h. - */ - PurpleConnectionError reason = gc->wants_to_die - ? PURPLE_CONNECTION_ERROR_OTHER_ERROR - : PURPLE_CONNECTION_ERROR_NETWORK_ERROR; - purple_connection_error_reason (gc, reason, text); -} - -void -purple_connection_error_reason (PurpleConnection *gc, +purple_connection_error (PurpleConnection *gc, PurpleConnectionError reason, const char *description) { @@ -557,13 +541,13 @@ */ if (reason > PURPLE_CONNECTION_ERROR_OTHER_ERROR) { purple_debug_error("connection", - "purple_connection_error_reason: reason %u isn't a " + "purple_connection_error: reason %u isn't a " "valid reason\n", reason); reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR; } if (description == NULL) { - purple_debug_error("connection", "purple_connection_error_reason called with NULL description\n"); + purple_debug_error("connection", "purple_connection_error called with NULL description\n"); description = _("Unknown error"); } @@ -578,13 +562,8 @@ ops = purple_connections_get_ui_ops(); - if (ops != NULL) - { - if (ops->report_disconnect_reason != NULL) - ops->report_disconnect_reason (gc, reason, description); - if (ops->report_disconnect != NULL) - ops->report_disconnect (gc, description); - } + if (ops && ops->report_disconnect) + ops->report_disconnect(gc, reason, description); purple_signal_emit(purple_connections_get_handle(), "connection-error", gc, reason, description); @@ -615,7 +594,7 @@ reason = PURPLE_CONNECTION_ERROR_CERT_OTHER_ERROR; } - purple_connection_error_reason (gc, reason, + purple_connection_error (gc, reason, purple_ssl_strerror(ssl_error)); } @@ -648,6 +627,13 @@ } } +void purple_connection_update_last_received(PurpleConnection *gc) +{ + g_return_if_fail(gc != NULL); + + gc->last_received = time(NULL); +} + void purple_connections_disconnect_all(void) { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/connection.h --- a/libpurple/connection.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/connection.h Fri Apr 06 04:30:00 2012 +0000 @@ -59,8 +59,6 @@ /** * Possible errors that can cause a connection to be closed. - * - * @since 2.3.0 */ typedef enum { @@ -128,7 +126,7 @@ /** Some other error occurred which fits into none of the other * categories. */ - /* purple_connection_error_reason() in connection.c uses the fact that + /* purple_connection_error() in connection.c uses the fact that * this is the last member of the enum when sanity-checking; if other * reasons are added after it, the check must be updated. */ @@ -194,16 +192,6 @@ void (*notice)(PurpleConnection *gc, const char *text); /** - * Called when an error causes a connection to be disconnected. - * Called before #disconnected. - * @param text a localized error message. - * @see #purple_connection_error - * @deprecated in favour of - * #PurpleConnectionUiOps.report_disconnect_reason. - */ - void (*report_disconnect)(PurpleConnection *gc, const char *text); - - /** * Called when libpurple discovers that the computer's network * connection is active. On Linux, this uses Network Manager if * available; on Windows, it uses Win32's network change notification @@ -219,21 +207,17 @@ /** * Called when an error causes a connection to be disconnected. - * Called before #disconnected. This op is intended to replace - * #report_disconnect. If both are implemented, this will be called - * first; however, there's no real reason to implement both. + * Called before #disconnected. * - * @param reason why the connection ended, if known, or - * #PURPLE_CONNECTION_ERROR_OTHER_ERROR, if not. - * @param text a localized message describing the disconnection - * in more detail to the user. - * @see #purple_connection_error_reason - * - * @since 2.3.0 + * @param reason why the connection ended, if known, or + * #PURPLE_CONNECTION_ERROR_OTHER_ERROR, if not. + * @param text a localized message describing the disconnection + * in more detail to the user. + * @see #purple_connection_error */ - void (*report_disconnect_reason)(PurpleConnection *gc, - PurpleConnectionError reason, - const char *text); + void (*report_disconnect)(PurpleConnection *gc, + PurpleConnectionError reason, + const char *text); void (*_purple_reserved1)(void); void (*_purple_reserved2)(void); @@ -251,7 +235,6 @@ PurpleAccount *account; /**< The account being connected to. */ char *password; /**< The password used. */ - int inpa; /**< The input watcher. */ GSList *buddy_chats; /**< A list of active chats (#PurpleConversation structs of type @@ -264,7 +247,7 @@ /** Wants to Die state. This is set when the user chooses to log out, or * when the protocol is disconnected and should not be automatically * reconnected (incorrect password, etc.). prpls should rely on - * purple_connection_error_reason() to set this for them rather than + * purple_connection_error() to set this for them rather than * setting it themselves. * @see purple_connection_error_is_fatal */ @@ -275,72 +258,13 @@ prpl to avoid sending unneeded keepalives */ }; -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Connection API */ /**************************************************************************/ /*@{*/ -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_CONNECTION_C_) -/** - * This function should only be called by purple_account_connect() - * in account.c. If you're trying to sign on an account, use that - * function instead. - * - * Creates a connection to the specified account and either connects - * or attempts to register a new account. If you are logging in, - * the connection uses the current active status for this account. - * So if you want to sign on as "away," for example, you need to - * have called purple_account_set_status(account, "away"). - * (And this will call purple_account_connect() automatically). - * - * @param account The account the connection should be connecting to. - * @param regist Whether we are registering a new account or just - * trying to do a normal signon. - * @param password The password to use. - * - * @deprecated As this is internal, we should make it private in 3.0.0. - */ -void purple_connection_new(PurpleAccount *account, gboolean regist, - const char *password); -#endif - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_CONNECTION_C_) -/** - * This function should only be called by purple_account_unregister() - * in account.c. - * - * Tries to unregister the account on the server. If the account is not - * connected, also creates a new connection. - * - * @param account The account to unregister - * @param password The password to use. - * @param cb Optional callback to be called when unregistration is complete - * @param user_data user data to pass to the callback - * - * @deprecated As this is internal, we should make it private in 3.0.0. - */ -void purple_connection_new_unregister(PurpleAccount *account, const char *password, PurpleAccountUnregistrationCb cb, void *user_data); -#endif - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_CONNECTION_C_) -/** - * Disconnects and destroys a PurpleConnection. - * - * This function should only be called by purple_account_disconnect() - * in account.c. If you're trying to sign off an account, use that - * function instead. - * - * @param gc The purple connection to destroy. - * - * @deprecated As this is internal, we should make it private in 3.0.0. - */ -void purple_connection_destroy(PurpleConnection *gc); -#endif - /** * Sets the connection state. PRPLs should call this and pass in * the state #PURPLE_CONNECTED when the account is completely @@ -354,6 +278,14 @@ void purple_connection_set_state(PurpleConnection *gc, PurpleConnectionState state); /** + * Sets the connection flags. + * + * @param gc The connection. + * @param flags The flags. + */ +void purple_connection_set_flags(PurpleConnection *gc, PurpleConnectionFlags flags); + +/** * Sets the connection's account. * * @param gc The connection. @@ -374,8 +306,6 @@ * * @param connection The PurpleConnection. * @param proto_data The protocol data to set for the connection. - * - * @since 2.6.0 */ void purple_connection_set_protocol_data(PurpleConnection *connection, void *proto_data); @@ -389,6 +319,15 @@ PurpleConnectionState purple_connection_get_state(const PurpleConnection *gc); /** + * Returns the connection flags. + * + * @param gc The connection. + * + * @return The connection flags. + */ +PurpleConnectionFlags purple_connection_get_flags(const PurpleConnection *gc); + +/** * Returns TRUE if the account is connected, otherwise returns FALSE. * * @return TRUE if the account is connected, otherwise returns FALSE. @@ -411,8 +350,6 @@ * @param gc The connection. * * @return The protocol plugin. - * - * @since 2.4.0 */ PurplePlugin * purple_connection_get_prpl(const PurpleConnection *gc); @@ -440,8 +377,6 @@ * @param connection The PurpleConnection. * * @return The protocol data for the connection. - * - * @since 2.6.0 */ void *purple_connection_get_protocol_data(const PurpleConnection *connection); @@ -465,21 +400,6 @@ void purple_connection_notice(PurpleConnection *gc, const char *text); /** - * Closes a connection with an error. - * - * @param gc The connection. - * @param reason The error text, which may not be @c NULL. - * @deprecated in favour of #purple_connection_error_reason. Calling - * @c purple_connection_error(gc, text) is equivalent to calling - * @c purple_connection_error_reason(gc, reason, text) where @c reason is - * #PURPLE_CONNECTION_ERROR_OTHER_ERROR if @c gc->wants_to_die is @c TRUE, and - * #PURPLE_CONNECTION_ERROR_NETWORK_ERROR if not. (This is to keep - * auto-reconnection behaviour the same when using old prpls which don't use - * reasons yet.) - */ -void purple_connection_error(PurpleConnection *gc, const char *reason); - -/** * Closes a connection with an error and a human-readable description of the * error. It also sets @c gc->wants_to_die to the value of * #purple_connection_error_is_fatal(@a reason), mainly for @@ -488,20 +408,16 @@ * @param gc the connection which is closing. * @param reason why the connection is closing. * @param description a non-@c NULL localized description of the error. - * - * @since 2.3.0 */ void -purple_connection_error_reason (PurpleConnection *gc, - PurpleConnectionError reason, - const char *description); +purple_connection_error(PurpleConnection *gc, + PurpleConnectionError reason, + const char *description); /** * Closes a connection due to an SSL error; this is basically a shortcut to * turning the #PurpleSslErrorType into a #PurpleConnectionError and a - * human-readable string and then calling purple_connection_error_reason(). - * - * @since 2.3.0 + * human-readable string and then calling purple_connection_error(). */ void purple_connection_ssl_error (PurpleConnection *gc, @@ -524,12 +440,18 @@ * * @return @c TRUE if the account should not be automatically reconnected, and * @c FALSE otherwise. - * - * @since 2.3.0 */ gboolean purple_connection_error_is_fatal (PurpleConnectionError reason); +/** + * Indicate that a packet was received on the connection. + * Set by the prpl to avoid sending unneeded keepalives. + * + * @param gc The connection. + */ +void purple_connection_update_last_received(PurpleConnection *gc); + /*@}*/ /**************************************************************************/ @@ -619,8 +541,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_CONNECTION_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/conversation.c --- a/libpurple/conversation.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/conversation.c Fri Apr 06 04:30:00 2012 +0000 @@ -35,6 +35,131 @@ #define SEND_TYPED_TIMEOUT_SECONDS 5 +/** + * Data specific to Chats. + */ +struct _PurpleConvChat +{ + PurpleConversation *conv; /**< The parent conversation. */ + + GList *in_room; /**< The users in the room. + * @deprecated Will be removed in 3.0.0 + */ + GList *ignored; /**< Ignored users. */ + char *who; /**< The person who set the topic. */ + char *topic; /**< The topic. */ + int id; /**< The chat ID. */ + char *nick; /**< Your nick in this chat. */ + + gboolean left; /**< We left the chat and kept the window open */ + GHashTable *users; /**< Hash table of the users in the room. */ +}; + +/** + * Data specific to Instant Messages. + */ +struct _PurpleConvIm +{ + PurpleConversation *conv; /**< The parent conversation. */ + + PurpleTypingState typing_state; /**< The current typing state. */ + guint typing_timeout; /**< The typing timer handle. */ + time_t type_again; /**< The type again time. */ + guint send_typed_timeout; /**< The type again timer handle. */ + + PurpleBuddyIcon *icon; /**< The buddy icon. */ +}; + +/** + * Data for "Chat Buddies" + */ +struct _PurpleConvChatBuddy +{ + /** The chat participant's name in the chat. */ + char *name; + + /** The chat participant's alias, if known; @a NULL otherwise. */ + char *alias; + + /** + * A string by which this buddy will be sorted, or @c NULL if the + * buddy should be sorted by its @c name. (This is currently always + * @c NULL. + */ + char *alias_key; + + /** + * @a TRUE if this chat participant is on the buddy list; + * @a FALSE otherwise. + */ + gboolean buddy; + + /** + * A bitwise OR of flags for this participant, such as whether they + * are a channel operator. + */ + PurpleConvChatBuddyFlags flags; + + /** + * A hash table of attributes about the user, such as real name, + * user\@host, etc. + */ + GHashTable *attributes; + + /** The UI can put whatever it wants here. */ + gpointer ui_data; +}; + +/** + * A core representation of a conversation between two or more people. + * + * The conversation can be an IM or a chat. + */ +struct _PurpleConversation +{ + PurpleConversationType type; /**< The type of conversation. */ + + PurpleAccount *account; /**< The user using this conversation. */ + + + char *name; /**< The name of the conversation. */ + char *title; /**< The window title. */ + + gboolean logging; /**< The status of logging. */ + + GList *logs; /**< This conversation's logs */ + + union + { + PurpleConvIm *im; /**< IM-specific data. */ + PurpleConvChat *chat; /**< Chat-specific data. */ + void *misc; /**< Misc. data. */ + + } u; + + PurpleConversationUiOps *ui_ops; /**< UI-specific operations. */ + void *ui_data; /**< UI-specific data. */ + + GHashTable *data; /**< Plugin-specific data. */ + + PurpleConnectionFlags features; /**< The supported features */ + GList *message_history; /**< Message history, as a GList of PurpleConvMessage's */ +}; + +/** + * Description of a conversation message + */ +struct _PurpleConvMessage +{ + char *who; + char *what; + PurpleMessageFlags flags; + time_t when; + PurpleConversation *conv; + char *alias; +}; + + static GList *conversations = NULL; static GList *ims = NULL; static GList *chats = NULL; @@ -116,7 +241,7 @@ g_return_val_if_fail(conv != NULL, FALSE); - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); name = purple_conversation_get_name(conv); if (gc != NULL && name != NULL) { @@ -146,7 +271,7 @@ return; account = purple_conversation_get_account(conv); - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); g_return_if_fail(account != NULL); g_return_if_fail(gc != NULL); @@ -262,7 +387,7 @@ if (gc) me = purple_connection_get_display_name(gc); if (!me) - me = conv->account->username; + me = purple_account_get_username(conv->account); who = me; } @@ -381,7 +506,7 @@ conv->data = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); /* copy features from the connection. */ - conv->features = gc->flags; + conv->features = purple_connection_get_flags(gc); if (type == PURPLE_CONV_TYPE_IM) { @@ -416,7 +541,7 @@ chats = g_list_prepend(chats, conv); - if ((disp = purple_connection_get_display_name(account->gc))) + if ((disp = purple_connection_get_display_name(purple_account_get_connection(account)))) purple_conv_chat_set_nick(conv->u.chat, disp); else purple_conv_chat_set_nick(conv->u.chat, @@ -469,7 +594,7 @@ purple_request_close_with_handle(conv); ops = purple_conversation_get_ui_ops(conv); - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); name = purple_conversation_get_name(conv); if (gc != NULL) @@ -694,7 +819,7 @@ } PurpleConnection * -purple_conversation_get_gc(const PurpleConversation *conv) +purple_conversation_get_connection(const PurpleConversation *conv) { PurpleAccount *account; @@ -705,7 +830,7 @@ if (account == NULL) return NULL; - return account->gc; + return purple_account_get_connection(account); } void @@ -990,7 +1115,7 @@ purple_account_get_username(account)); if (purple_account_get_alias(account) != NULL) - alias = account->alias; + alias = purple_account_get_alias(account); else if (b != NULL && !purple_strequal(purple_buddy_get_name(b), purple_buddy_get_contact_alias(b))) alias = purple_buddy_get_contact_alias(b); else if (purple_connection_get_display_name(gc) != NULL) @@ -1379,16 +1504,6 @@ } GList * -purple_conv_chat_set_users(PurpleConvChat *chat, GList *users) -{ - g_return_val_if_fail(chat != NULL, NULL); - - chat->in_room = users; - - return users; -} - -GList * purple_conv_chat_get_users(const PurpleConvChat *chat) { g_return_val_if_fail(chat != NULL, NULL); @@ -1544,7 +1659,7 @@ g_return_if_fail(message != NULL); conv = purple_conv_chat_get_conversation(chat); - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); account = purple_connection_get_account(gc); /* Don't display this if the person who wrote it is ignored. */ @@ -1660,7 +1775,7 @@ conv = purple_conv_chat_get_conversation(chat); ops = purple_conversation_get_ui_ops(conv); - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); g_return_if_fail(gc != NULL); prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); g_return_if_fail(prpl_info != NULL); @@ -1687,7 +1802,7 @@ } } else { PurpleBuddy *buddy; - if ((buddy = purple_find_buddy(gc->account, user)) != NULL) + if ((buddy = purple_find_buddy(purple_connection_get_account(gc), user)) != NULL) alias = purple_buddy_get_contact_alias(buddy); } } @@ -1761,7 +1876,7 @@ conv = purple_conv_chat_get_conversation(chat); ops = purple_conversation_get_ui_ops(conv); - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); g_return_if_fail(gc != NULL); prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); g_return_if_fail(prpl_info != NULL); @@ -1780,12 +1895,12 @@ { const char *display_name = purple_connection_get_display_name(gc); if (display_name != NULL) - alias = display_name; + new_alias = display_name; } } } else if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { PurpleBuddy *buddy; - if ((buddy = purple_find_buddy(gc->account, new_user)) != NULL) + if ((buddy = purple_find_buddy(purple_connection_get_account(gc), new_user)) != NULL) new_alias = purple_buddy_get_contact_alias(buddy); } @@ -1834,9 +1949,9 @@ if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { PurpleBuddy *buddy; - if ((buddy = purple_find_buddy(gc->account, old_user)) != NULL) + if ((buddy = purple_find_buddy(purple_connection_get_account(gc), old_user)) != NULL) old_alias = purple_buddy_get_contact_alias(buddy); - if ((buddy = purple_find_buddy(gc->account, new_user)) != NULL) + if ((buddy = purple_find_buddy(purple_connection_get_account(gc), new_user)) != NULL) new_alias = purple_buddy_get_contact_alias(buddy); } @@ -1880,7 +1995,7 @@ conv = purple_conv_chat_get_conversation(chat); - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); g_return_if_fail(gc != NULL); prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); g_return_if_fail(prpl_info != NULL); @@ -1911,7 +2026,7 @@ if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { PurpleBuddy *buddy; - if ((buddy = purple_find_buddy(gc->account, user)) != NULL) + if ((buddy = purple_find_buddy(purple_connection_get_account(gc), user)) != NULL) alias = purple_buddy_get_contact_alias(buddy); } @@ -2065,7 +2180,7 @@ conv = (PurpleConversation *)l->data; if (purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)) == id && - purple_conversation_get_gc(conv) == gc) + purple_conversation_get_connection(conv) == gc) return conv; } @@ -2093,7 +2208,7 @@ user = purple_request_fields_get_string(fields, "screenname"); message = purple_request_fields_get_string(fields, "message"); - serv_chat_invite(purple_conversation_get_gc(conv), chat->id, message, user); + serv_chat_invite(purple_conversation_get_connection(conv), chat->id, message, user); } void purple_conv_chat_invite_user(PurpleConvChat *chat, const char *user, @@ -2194,14 +2309,51 @@ g_free(cb); } +void purple_conv_chat_cb_set_ui_data(PurpleConvChatBuddy *cb, gpointer ui_data) +{ + g_return_if_fail(cb != NULL); + + cb->ui_data = ui_data; +} + +gpointer purple_conv_chat_cb_get_ui_data(const PurpleConvChatBuddy *cb) +{ + g_return_val_if_fail(cb != NULL, NULL); + + return cb->ui_data; +} + const char * -purple_conv_chat_cb_get_name(PurpleConvChatBuddy *cb) +purple_conv_chat_cb_get_alias(const PurpleConvChatBuddy *cb) +{ + g_return_val_if_fail(cb != NULL, NULL); + + return cb->alias; +} + +const char * +purple_conv_chat_cb_get_name(const PurpleConvChatBuddy *cb) { g_return_val_if_fail(cb != NULL, NULL); return cb->name; } +PurpleConvChatBuddyFlags +purple_conv_chat_cb_get_flags(const PurpleConvChatBuddy *cb) +{ + g_return_val_if_fail(cb != NULL, PURPLE_CBFLAGS_NONE); + + return cb->flags; +} + +gboolean purple_conv_chat_cb_is_buddy(const PurpleConvChatBuddy *cb) +{ + g_return_val_if_fail(cb != NULL, FALSE); + + return cb->buddy; +} + const char * purple_conv_chat_cb_get_attribute(PurpleConvChatBuddy *cb, const char *key) { @@ -2299,30 +2451,57 @@ return conv->message_history; } -const char *purple_conversation_message_get_sender(PurpleConvMessage *msg) +const char *purple_conversation_message_get_sender(const PurpleConvMessage *msg) { g_return_val_if_fail(msg, NULL); return msg->who; } -const char *purple_conversation_message_get_message(PurpleConvMessage *msg) +const char *purple_conversation_message_get_message(const PurpleConvMessage *msg) { g_return_val_if_fail(msg, NULL); return msg->what; } -PurpleMessageFlags purple_conversation_message_get_flags(PurpleConvMessage *msg) +PurpleMessageFlags purple_conversation_message_get_flags(const PurpleConvMessage *msg) { g_return_val_if_fail(msg, 0); return msg->flags; } -time_t purple_conversation_message_get_timestamp(PurpleConvMessage *msg) +time_t purple_conversation_message_get_timestamp(const PurpleConvMessage *msg) { g_return_val_if_fail(msg, 0); return msg->when; } +const char *purple_conversation_message_get_alias(const PurpleConvMessage *msg) +{ + g_return_val_if_fail(msg, NULL); + return msg->alias; +} + +PurpleConversation *purple_conversation_message_get_conv(const PurpleConvMessage *msg) +{ + g_return_val_if_fail(msg, NULL); + return msg->conv; +} + +void purple_conversation_set_ui_data(PurpleConversation *conv, gpointer ui_data) +{ + g_return_if_fail(conv != NULL); + + conv->ui_data = ui_data; +} + +gpointer purple_conversation_get_ui_data(const PurpleConversation *conv) +{ + g_return_val_if_fail(conv != NULL, NULL); + + return conv->ui_data; +} + + gboolean purple_conversation_do_command(PurpleConversation *conv, const gchar *cmdline, const gchar *markup, gchar **error) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/conversation.h --- a/libpurple/conversation.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/conversation.h Fri Apr 06 04:30:00 2012 +0000 @@ -125,7 +125,7 @@ PURPLE_MESSAGE_IMAGES = 0x1000, /**< Message contains images */ PURPLE_MESSAGE_NOTIFY = 0x2000, /**< Message is a notification */ PURPLE_MESSAGE_NO_LINKIFY = 0x4000, /**< Message should not be auto- - linkified @since 2.1.0 */ + linkified */ PURPLE_MESSAGE_INVISIBLE = 0x8000 /**< Message should not be displayed */ } PurpleMessageFlags; @@ -140,7 +140,7 @@ PURPLE_CBFLAGS_OP = 0x0004, /**< Channel Op or Moderator */ PURPLE_CBFLAGS_FOUNDER = 0x0008, /**< Channel Founder */ PURPLE_CBFLAGS_TYPING = 0x0010, /**< Currently typing */ - PURPLE_CBFLAGS_AWAY = 0x0020 /**< Currently away. @since 2.8.0 */ + PURPLE_CBFLAGS_AWAY = 0x0020 /**< Currently away. */ } PurpleConvChatBuddyFlags; @@ -249,123 +249,7 @@ void (*_purple_reserved4)(void); }; -/** - * Data specific to Instant Messages. - */ -struct _PurpleConvIm -{ - PurpleConversation *conv; /**< The parent conversation. */ - - PurpleTypingState typing_state; /**< The current typing state. */ - guint typing_timeout; /**< The typing timer handle. */ - time_t type_again; /**< The type again time. */ - guint send_typed_timeout; /**< The type again timer handle. */ - - PurpleBuddyIcon *icon; /**< The buddy icon. */ -}; - -/** - * Data specific to Chats. - */ -struct _PurpleConvChat -{ - PurpleConversation *conv; /**< The parent conversation. */ - - GList *in_room; /**< The users in the room. - * @deprecated Will be removed in 3.0.0 - */ - GList *ignored; /**< Ignored users. */ - char *who; /**< The person who set the topic. */ - char *topic; /**< The topic. */ - int id; /**< The chat ID. */ - char *nick; /**< Your nick in this chat. */ - - gboolean left; /**< We left the chat and kept the window open */ - GHashTable *users; /**< Hash table of the users in the room. - * @since 2.9.0 - */ -}; - -/** - * Data for "Chat Buddies" - */ -struct _PurpleConvChatBuddy -{ - char *name; /**< The chat participant's name in the chat. */ - char *alias; /**< The chat participant's alias, if known; - * @a NULL otherwise. - */ - char *alias_key; /**< A string by which this buddy will be sorted, - * or @c NULL if the buddy should be sorted by - * its @c name. (This is currently always @c - * NULL.) - */ - gboolean buddy; /**< @a TRUE if this chat participant is on the - * buddy list; @a FALSE otherwise. - */ - PurpleConvChatBuddyFlags flags; /**< A bitwise OR of flags for this participant, - * such as whether they are a channel operator. - */ - GHashTable *attributes; /**< A hash table of attributes about the user, such as - * real name, user@host, etc. - */ - gpointer ui_data; /** < The UI can put whatever it wants here. */ -}; - -/** - * Description of a conversation message - * - * @since 2.2.0 - */ -struct _PurpleConvMessage -{ - char *who; - char *what; - PurpleMessageFlags flags; - time_t when; - PurpleConversation *conv; /**< @since 2.3.0 */ - char *alias; /**< @since 2.3.0 */ -}; - -/** - * A core representation of a conversation between two or more people. - * - * The conversation can be an IM or a chat. - */ -struct _PurpleConversation -{ - PurpleConversationType type; /**< The type of conversation. */ - - PurpleAccount *account; /**< The user using this conversation. */ - - - char *name; /**< The name of the conversation. */ - char *title; /**< The window title. */ - - gboolean logging; /**< The status of logging. */ - - GList *logs; /**< This conversation's logs */ - - union - { - PurpleConvIm *im; /**< IM-specific data. */ - PurpleConvChat *chat; /**< Chat-specific data. */ - void *misc; /**< Misc. data. */ - - } u; - - PurpleConversationUiOps *ui_ops; /**< UI-specific operations. */ - void *ui_data; /**< UI-specific data. */ - - GHashTable *data; /**< Plugin-specific data. */ - - PurpleConnectionFlags features; /**< The supported features */ - GList *message_history; /**< Message history, as a GList of PurpleConvMessage's */ -}; - -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Conversation API */ @@ -469,13 +353,11 @@ /** * Returns the specified conversation's purple_connection. * - * This is the same as purple_conversation_get_user(conv)->gc. - * * @param conv The conversation. * * @return The conversation's purple_connection. */ -PurpleConnection *purple_conversation_get_gc(const PurpleConversation *conv); +PurpleConnection *purple_conversation_get_connection(const PurpleConversation *conv); /** * Sets the specified conversation's title. @@ -744,8 +626,6 @@ * @return A GList of PurpleConvMessage's. The must not modify the list or the data within. * The list contains the newest message at the beginning, and the oldest message at * the end. - * - * @since 2.2.0 */ GList *purple_conversation_get_message_history(PurpleConversation *conv); @@ -753,8 +633,6 @@ * Clear the message history of a conversation. * * @param conv The conversation - * - * @since 2.2.0 */ void purple_conversation_clear_message_history(PurpleConversation *conv); @@ -764,10 +642,8 @@ * @param msg A PurpleConvMessage * * @return The name of the sender of the message - * - * @since 2.2.0 */ -const char *purple_conversation_message_get_sender(PurpleConvMessage *msg); +const char *purple_conversation_message_get_sender(const PurpleConvMessage *msg); /** * Get the message from a PurpleConvMessage @@ -775,10 +651,8 @@ * @param msg A PurpleConvMessage * * @return The name of the sender of the message - * - * @since 2.2.0 */ -const char *purple_conversation_message_get_message(PurpleConvMessage *msg); +const char *purple_conversation_message_get_message(const PurpleConvMessage *msg); /** * Get the message-flags of a PurpleConvMessage @@ -786,10 +660,8 @@ * @param msg A PurpleConvMessage * * @return The message flags - * - * @since 2.2.0 */ -PurpleMessageFlags purple_conversation_message_get_flags(PurpleConvMessage *msg); +PurpleMessageFlags purple_conversation_message_get_flags(const PurpleConvMessage *msg); /** * Get the timestamp of a PurpleConvMessage @@ -797,10 +669,45 @@ * @param msg A PurpleConvMessage * * @return The timestamp of the message + */ +time_t purple_conversation_message_get_timestamp(const PurpleConvMessage *msg); + +/** + * Get the alias from a PurpleConvMessage * - * @since 2.2.0 + * @param msg A PurpleConvMessage + * + * @return The alias of the sender of the message + */ +const char *purple_conversation_message_get_alias(const PurpleConvMessage *msg); + +/** + * Get the conversation associated with the PurpleConvMessage + * + * @param msg A PurpleConvMessage + * + * @return The conversation */ -time_t purple_conversation_message_get_timestamp(PurpleConvMessage *msg); +PurpleConversation *purple_conversation_message_get_conv(const PurpleConvMessage *msg); + +/** + * Set the UI data associated with this conversation. + * + * @param conv The conversation. + * @param ui_data A pointer to associate with this conversation. + */ +void purple_conversation_set_ui_data(PurpleConversation *conv, gpointer ui_data); + +/** + * Get the UI data associated with this conversation. + * + * @param conv The conversation. + * + * @return The UI data associated with this conversation. This is a + * convenience field provided to the UIs--it is not + * used by the libpurple core. + */ +gpointer purple_conversation_get_ui_data(const PurpleConversation *conv); /*@}*/ @@ -1061,22 +968,6 @@ PurpleConversation *purple_conv_chat_get_conversation(const PurpleConvChat *chat); /** - * Sets the list of users in the chat room. - * - * @note Calling this function will not update the display of the users. - * Please use purple_conv_chat_add_user(), purple_conv_chat_add_users(), - * purple_conv_chat_remove_user(), and purple_conv_chat_remove_users() instead. - * - * @param chat The chat. - * @param users The list of users. - * - * @return The list passed. - * - * @deprecated This function will be removed in 3.0.0. You shouldn't be using it anyway. - */ -GList *purple_conv_chat_set_users(PurpleConvChat *chat, GList *users); - -/** * Returns a list of users in the chat room. The members of the list * are PurpleConvChatBuddy objects. * @@ -1362,8 +1253,6 @@ * @param message The message to send with the invitation. * @param confirm Prompt before sending the invitation. The user is always * prompted if either \a user or \a message is @c NULL. - * - * @since 2.6.0 */ void purple_conv_chat_invite_user(PurpleConvChat *chat, const char *user, const char *message, gboolean confirm); @@ -1400,13 +1289,59 @@ PurpleConvChatBuddy *purple_conv_chat_cb_find(PurpleConvChat *chat, const char *name); /** + * Set the UI data associated with this chat buddy. + * + * @param cb The chat buddy + * @param ui_data A pointer to associate with this chat buddy. + */ +void purple_conv_chat_cb_set_ui_data(PurpleConvChatBuddy *cb, gpointer ui_data); + +/** + * Get the UI data associated with this chat buddy. + * + * @param cb The chat buddy. + * + * @return The UI data associated with this chat buddy. This is a + * convenience field provided to the UIs--it is not + * used by the libpurple core. + */ +gpointer purple_conv_chat_cb_get_ui_data(const PurpleConvChatBuddy *conv); + +/** + * Get the alias of a chat buddy + * + * @param cb The chat buddy. + * + * @return The alias of the chat buddy. + */ +const char *purple_conv_chat_cb_get_alias(const PurpleConvChatBuddy *cb); + +/** * Get the name of a chat buddy * * @param cb The chat buddy. * * @return The name of the chat buddy. */ -const char *purple_conv_chat_cb_get_name(PurpleConvChatBuddy *cb); +const char *purple_conv_chat_cb_get_name(const PurpleConvChatBuddy *cb); + +/** + * Get the flags of a chat buddy. + * + * @param cb The chat buddy. + * + * @return The flags of the chat buddy. + */ +PurpleConvChatBuddyFlags purple_conv_chat_cb_get_flags(const PurpleConvChatBuddy *cb); + +/** + * Indicates if this chat buddy is on the buddy list. + * + * @param cb The chat buddy. + * + * @return TRUE if the chat buddy is on the buddy list. + */ +gboolean purple_conv_chat_cb_is_buddy(const PurpleConvChatBuddy *cb); /** * Destroys a chat buddy @@ -1423,8 +1358,6 @@ * @return A list of PurpleMenuAction items, harvested by the * chat-extended-menu signal. The list and the menuaction * items should be freed by the caller. - * - * @since 2.1.0 */ GList * purple_conversation_get_extended_menu(PurpleConversation *conv); @@ -1438,8 +1371,6 @@ * message, if not @c NULL. It must be freed by the caller with g_free(). * * @return @c TRUE if the command was executed successfully, @c FALSE otherwise. - * - * @since 2.1.0 */ gboolean purple_conversation_do_command(PurpleConversation *conv, const gchar *cmdline, const gchar *markup, gchar **error); @@ -1469,8 +1400,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_CONVERSATION_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/core.c --- a/libpurple/core.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/core.c Fri Apr 06 04:30:00 2012 +0000 @@ -371,386 +371,6 @@ return is_single_instance; } -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. Please report this at " PURPLE_DEVEL_WEBSITE "\n", - path, new_name, g_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. Please report this at " PURPLE_DEVEL_WEBSITE "\n", - old_name, new_name, g_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. Please report this at " PURPLE_DEVEL_WEBSITE "\n", - user_dir, g_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. Please report this at " PURPLE_DEVEL_WEBSITE "\n", - status_file, g_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. Please report this at " PURPLE_DEVEL_WEBSITE "\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 (purple_strequal(entry, "logs")) - { - char *link; - err = NULL; - - if ((link = g_file_read_link(name, &err)) == NULL) - { - char *name_utf8 = g_filename_to_utf8(name, -1, NULL, NULL, NULL); - purple_debug_error("core", "Error reading symlink %s: %s. Please report this at " PURPLE_DEVEL_WEBSITE "\n", - name_utf8 ? name_utf8 : name, err->message); - g_free(name_utf8); - g_error_free(err); - g_free(name); - g_dir_close(dir); - g_free(status_file); - g_free(old_user_dir); - return FALSE; - } - - logs_dir = g_build_filename(user_dir, "logs", NULL); - - if (purple_strequal(link, "../.purple/logs") || - purple_strequal(link, 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(link); - 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 it's not - * guaranteed. Oh well. */ - if (symlink(link, logs_dir)) - { - purple_debug_error("core", "Error symlinking %s to %s: %s. Please report this at " PURPLE_DEVEL_WEBSITE "\n", - logs_dir, link, g_strerror(errno)); - g_free(link); - g_free(name); - g_free(logs_dir); - g_dir_close(dir); - g_free(status_file); - g_free(old_user_dir); - return FALSE; - } - - g_free(link); - 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 (purple_strequal(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. Please report this at " PURPLE_DEVEL_WEBSITE "\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. Please report this at " PURPLE_DEVEL_WEBSITE "\n", - new_icons_dir, g_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 (purple_strequal(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. Please report this at " PURPLE_DEVEL_WEBSITE "\n", - name, g_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. Please report this at " PURPLE_DEVEL_WEBSITE "\n", - new_name, g_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. Please report this at " PURPLE_DEVEL_WEBSITE "\n", - name, g_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. Please report this at " PURPLE_DEVEL_WEBSITE "\n", - new_name, g_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. Please report this at " PURPLE_DEVEL_WEBSITE "\n", - new_name, g_strerror(errno)); - } - if (fclose(fp)) - { - purple_debug_warning("core", "Error closing %s: %s\n", - name, g_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. Please report this at " PURPLE_DEVEL_WEBSITE "\n", - status_file, g_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; -} - GHashTable* purple_core_get_ui_info() { PurpleCoreUiOps *ops = purple_core_get_ui_ops(); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/core.h --- a/libpurple/core.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/core.h Fri Apr 06 04:30:00 2012 +0000 @@ -76,9 +76,7 @@ void (*_purple_reserved3)(void); } PurpleCoreUiOps; -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /** * Initializes the core of purple. @@ -156,17 +154,6 @@ 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); - -/** * Ensures that only one instance is running. If libpurple is built with D-Bus * support, this checks if another process owns the libpurple bus name and if * so whether that process is using the same configuration directory as this @@ -174,8 +161,6 @@ * * @return @c TRUE if this is the first instance of libpurple running; * @c FALSE if there is another instance running. - * - * @since 2.1.0 */ gboolean purple_core_ensure_single_instance(void); @@ -207,14 +192,10 @@ * @return A GHashTable with strings for keys and values. This * hash table must not be freed and should not be modified. * - * @since 2.1.0 - * */ GHashTable* purple_core_get_ui_info(void); -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_CORE_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/dbus-analyze-functions.py --- a/libpurple/dbus-analyze-functions.py Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/dbus-analyze-functions.py Fri Apr 06 04:30:00 2012 +0000 @@ -29,7 +29,11 @@ # Similar to the above: "purple_account_set_register_callback", "purple_account_unregister", - "purple_connection_new_unregister", + + # Similar to the above, again + "purple_menu_action_new", + "purple_menu_action_set_callback", + "purple_menu_action_get_callback", # These functions are excluded because they involve setting arbitrary # data via pointers for protocols and UIs. This just won't work. @@ -491,7 +495,7 @@ if self.function.name in stringlists: self.cdecls.append("\tchar **%s;" % name) self.ccode.append("\tlist = %s;" % self.call) - self.ccode.append("\t%s = (char **)purple_%s_to_array(list, FALSE, &%s_LEN);" % \ + self.ccode.append("\t%s = (char **)purple_%s_to_array(list, &%s_LEN);" % \ (name, type[0], name)) self.cparamsout.append("DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &%s, %s_LEN" \ % (name, name)) @@ -503,7 +507,7 @@ else: self.cdecls.append("\tdbus_int32_t *%s;" % name) self.ccode.append("\tlist = %s;" % self.call) - self.ccode.append("\t%s = purple_dbusify_%s(list, FALSE, &%s_LEN);" % \ + self.ccode.append("\t%s = purple_dbusify_%s(list, &%s_LEN);" % \ (name, type[0], name)) if (not (self.function.name in constlists)): self.ccode.append("\tg_%s_free(list);" % type[0].lower()[1:]) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/dbus-bindings.h --- a/libpurple/dbus-bindings.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/dbus-bindings.h Fri Apr 06 04:30:00 2012 +0000 @@ -32,9 +32,7 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS gint purple_dbus_pointer_to_id(gconstpointer node); gpointer purple_dbus_id_to_pointer(gint id, PurpleDBusType *type); @@ -84,14 +82,10 @@ int first_arg_type, va_list var_args); -dbus_int32_t* purple_dbusify_GList(GList *list, gboolean free_memory, - dbus_int32_t *len); -dbus_int32_t* purple_dbusify_GSList(GSList *list, gboolean free_memory, - dbus_int32_t *len); -gpointer* purple_GList_to_array(GList *list, gboolean free_memory, - dbus_int32_t *len); -gpointer* purple_GSList_to_array(GSList *list, gboolean free_memory, - dbus_int32_t *len); +dbus_int32_t* purple_dbusify_GList(GList *list, dbus_int32_t *len); +dbus_int32_t* purple_dbusify_GSList(GSList *list, dbus_int32_t *len); +gpointer* purple_GList_to_array(GList *list, dbus_int32_t *len); +gpointer* purple_GSList_to_array(GSList *list, dbus_int32_t *len); GHashTable *purple_dbus_iter_hash_table(DBusMessageIter *iter, DBusError *error); const char* empty_to_null(const char *str); @@ -107,8 +101,6 @@ DBusConnection *purple_dbus_get_connection(void); -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/dbus-server.c --- a/libpurple/dbus-server.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/dbus-server.c Fri Apr 06 04:30:00 2012 +0000 @@ -300,7 +300,7 @@ } dbus_int32_t * -purple_dbusify_GList(GList *list, gboolean free_memory, dbus_int32_t *len) +purple_dbusify_GList(GList *list, dbus_int32_t *len) { dbus_int32_t *array; int i; @@ -311,14 +311,11 @@ for (i = 0, elem = list; elem != NULL; elem = elem->next, i++) array[i] = purple_dbus_pointer_to_id(elem->data); - if (free_memory) - g_list_free(list); - return array; } dbus_int32_t * -purple_dbusify_GSList(GSList *list, gboolean free_memory, dbus_int32_t *len) +purple_dbusify_GSList(GSList *list, dbus_int32_t *len) { dbus_int32_t *array; int i; @@ -329,14 +326,11 @@ for (i = 0, elem = list; elem != NULL; elem = elem->next, i++) array[i] = purple_dbus_pointer_to_id(elem->data); - if (free_memory) - g_slist_free(list); - return array; } gpointer * -purple_GList_to_array(GList *list, gboolean free_memory, dbus_int32_t *len) +purple_GList_to_array(GList *list, dbus_int32_t *len) { gpointer *array; int i; @@ -347,14 +341,11 @@ for (i = 0, elem = list; elem != NULL; elem = elem->next, i++) array[i] = elem->data; - if (free_memory) - g_list_free(list); - return array; } gpointer * -purple_GSList_to_array(GSList *list, gboolean free_memory, dbus_int32_t *len) +purple_GSList_to_array(GSList *list, dbus_int32_t *len) { gpointer *array; int i; @@ -365,9 +356,6 @@ for (i = 0, elem = list; elem != NULL; elem = elem->next, i++) array[i] = elem->data; - if (free_memory) - g_slist_free(list); - return array; } @@ -711,7 +699,7 @@ g_return_val_if_fail(ptr, TRUE); } - switch (purple_values[i]->type) + switch (purple_value_get_type(purple_values[i])) { case PURPLE_TYPE_INT: case PURPLE_TYPE_ENUM: diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/dbus-server.h --- a/libpurple/dbus-server.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/dbus-server.h Fri Apr 06 04:30:00 2012 +0000 @@ -173,8 +173,6 @@ /** * Determines whether this instance owns the DBus service name - * - * @since 2.1.0 */ gboolean purple_dbus_is_owner(void); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/dbus-useful.c --- a/libpurple/dbus-useful.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/dbus-useful.c Fri Apr 06 04:30:00 2012 +0000 @@ -25,7 +25,7 @@ if (who && strcmp(purple_normalize(NULL, purple_account_get_username(account)), who)) continue; - if (protocol_id && strcmp(account->protocol_id, protocol_id)) + if (protocol_id && strcmp(purple_account_get_protocol_id(account), protocol_id)) continue; if (account_test && !account_test(account)) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/dbus-useful.h --- a/libpurple/dbus-useful.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/dbus-useful.h Fri Apr 06 04:30:00 2012 +0000 @@ -1,5 +1,7 @@ #include "conversation.h" +G_BEGIN_DECLS + PurpleAccount *purple_accounts_find_ext(const char *name, const char *protocol_id, gboolean (*account_test)(const PurpleAccount *account)); @@ -7,7 +9,5 @@ PurpleAccount *purple_accounts_find_connected(const char *name, const char *protocol); - +G_END_DECLS - - diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/debug.c --- a/libpurple/debug.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/debug.c Fri Apr 06 04:30:00 2012 +0000 @@ -224,12 +224,5 @@ purple_debug_set_verbose(TRUE); purple_prefs_add_none("/purple/debug"); - - /* - * This pref is obsolete and no longer referenced anywhere. It only - * survives here because it would be an API break if we removed it. - * Remove this when we get to 3.0.0 :) - */ - purple_prefs_add_bool("/purple/debug/timestamps", TRUE); } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/debug.h --- a/libpurple/debug.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/debug.h Fri Apr 06 04:30:00 2012 +0000 @@ -59,9 +59,7 @@ void (*_purple_reserved4)(void); } PurpleDebugUiOps; -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Debug API */ @@ -161,8 +159,6 @@ * plugins. * * @param verbose TRUE to enable verbose debugging or FALSE to disable it. - * - * @since 2.6.0 */ void purple_debug_set_verbose(gboolean verbose); @@ -170,8 +166,6 @@ * Check if verbose logging is enabled. * * @return TRUE if verbose debugging is enabled, FALSE if it is not. - * - * @since 2.6.0 */ gboolean purple_debug_is_verbose(void); @@ -183,8 +177,6 @@ * @param unsafe TRUE to enable debug logging of messages that could * potentially contain passwords and other sensitive information. * FALSE to disable it. - * - * @since 2.6.0 */ void purple_debug_set_unsafe(gboolean unsafe); @@ -194,8 +186,6 @@ * @return TRUE if the debug logging of all messages is enabled, FALSE * if messages that could potentially contain passwords and other * sensitive information are not logged. - * - * @since 2.6.0 */ gboolean purple_debug_is_unsafe(void); @@ -236,8 +226,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_DEBUG_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/dnsquery.c --- a/libpurple/dnsquery.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/dnsquery.c Fri Apr 06 04:30:00 2012 +0000 @@ -297,6 +297,10 @@ } rc = read(child_in, &dns_params, sizeof(dns_params_t)); if (rc < 0) { + if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { + /* Try again */ + continue; + } fprintf(stderr, "dns[%d]: Error: Could not read dns_params: " "%s\n", getpid(), strerror(errno)); break; @@ -910,7 +914,7 @@ } PurpleDnsQueryData * -purple_dnsquery_a_account(PurpleAccount *account, const char *hostname, int port, +purple_dnsquery_a(PurpleAccount *account, const char *hostname, int port, PurpleDnsQueryConnectFunction callback, gpointer data) { PurpleDnsQueryData *query_data; @@ -940,13 +944,6 @@ return query_data; } -PurpleDnsQueryData * -purple_dnsquery_a(const char *hostname, int port, - PurpleDnsQueryConnectFunction callback, gpointer data) -{ - return purple_dnsquery_a_account(NULL, hostname, port, callback, data); -} - void purple_dnsquery_destroy(PurpleDnsQueryData *query_data) { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/dnsquery.h --- a/libpurple/dnsquery.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/dnsquery.h Fri Apr 06 04:30:00 2012 +0000 @@ -76,9 +76,7 @@ void (*_purple_reserved4)(void); } PurpleDnsQueryUiOps; -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name DNS query API */ @@ -88,7 +86,7 @@ /** * Perform an asynchronous DNS query. * - * @param account the account that the query is being done for (or NULL) + * @param account The account that the query is being done for (or NULL) * @param hostname The hostname to resolve. * @param port A port number which is stored in the struct sockaddr. * @param callback The callback function to call after resolving. @@ -98,27 +96,8 @@ * a data structure that can be used to cancel the pending * DNS query, if needed. * - * @since 2.8.0 */ -PurpleDnsQueryData *purple_dnsquery_a_account(PurpleAccount *account, const char *hostname, int port, PurpleDnsQueryConnectFunction callback, gpointer data); - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_DNSQUERY_C_) -/** - * Perform an asynchronous DNS query. - * - * @param hostname The hostname to resolve. - * @param port A port number which is stored in the struct sockaddr. - * @param callback The callback function to call after resolving. - * @param data Extra data to pass to the callback function. - * - * @return NULL if there was an error, otherwise return a reference to - * a data structure that can be used to cancel the pending - * DNS query, if needed. - * - * @deprecated Use purple_dnsquery_a_account instead - */ -PurpleDnsQueryData *purple_dnsquery_a(const char *hostname, int port, PurpleDnsQueryConnectFunction callback, gpointer data); -#endif +PurpleDnsQueryData *purple_dnsquery_a(PurpleAccount *account, const char *hostname, int port, PurpleDnsQueryConnectFunction callback, gpointer data); /** * Cancel a DNS query and destroy the associated data structure. @@ -173,8 +152,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_DNSQUERY_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/dnssrv.c --- a/libpurple/dnssrv.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/dnssrv.c Fri Apr 06 04:30:00 2012 +0000 @@ -725,15 +725,7 @@ #endif PurpleSrvTxtQueryData * -purple_srv_resolve(const char *protocol, const char *transport, - const char *domain, PurpleSrvCallback cb, gpointer extradata) -{ - return purple_srv_resolve_account(NULL, protocol, transport, domain, - cb, extradata); -} - -PurpleSrvTxtQueryData * -purple_srv_resolve_account(PurpleAccount *account, const char *protocol, +purple_srv_resolve(PurpleAccount *account, const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata) { @@ -798,6 +790,12 @@ return NULL; } + /* + * TODO: We should put a cap on the number of forked processes that we + * allow at any given time. If we get too many requests they + * should be put into a queue and handled later. (This is what + * we do for A record lookups.) + */ pid = fork(); if (pid == -1) { purple_debug_error("dnssrv", "Could not create process!\n"); @@ -863,13 +861,7 @@ #endif } -PurpleSrvTxtQueryData *purple_txt_resolve(const char *owner, - const char *domain, PurpleTxtCallback cb, gpointer extradata) -{ - return purple_txt_resolve_account(NULL, owner, domain, cb, extradata); -} - -PurpleSrvTxtQueryData *purple_txt_resolve_account(PurpleAccount *account, +PurpleSrvTxtQueryData *purple_txt_resolve(PurpleAccount *account, const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata) { @@ -929,6 +921,12 @@ return NULL; } + /* + * TODO: We should put a cap on the number of forked processes that we + * allow at any given time. If we get too many requests they + * should be put into a queue and handled later. (This is what + * we do for A record lookups.) + */ pid = fork(); if (pid == -1) { purple_debug_error("dnssrv", "Could not create process!\n"); @@ -994,18 +992,6 @@ #endif } -void -purple_txt_cancel(PurpleSrvTxtQueryData *query_data) -{ - purple_srv_txt_query_destroy(query_data); -} - -void -purple_srv_cancel(PurpleSrvTxtQueryData *query_data) -{ - purple_srv_txt_query_destroy(query_data); -} - const gchar * purple_txt_response_get_content(PurpleTxtResponse *resp) { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/dnssrv.h --- a/libpurple/dnssrv.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/dnssrv.h Fri Apr 06 04:30:00 2012 +0000 @@ -24,18 +24,10 @@ #ifndef _PURPLE_DNSSRV_H #define _PURPLE_DNSSRV_H -#ifdef __cplusplus -extern "C" { -#endif - typedef struct _PurpleSrvTxtQueryData PurpleSrvTxtQueryData; typedef struct _PurpleSrvResponse PurpleSrvResponse; typedef struct _PurpleTxtResponse PurpleTxtResponse; -/* For compatibility, should be removed for 3.0.0 - */ -typedef struct _PurpleSrvTxtQueryData PurpleSrvQueryData; - #include enum PurpleDnsType { @@ -74,7 +66,7 @@ /** Called just before @a query_data is freed; this should cancel any * further use of @a query_data the UI would make. Unneeded if - * #resolve_host is not implemented. + * #resolve is not implemented. */ void (*destroy)(PurpleSrvTxtQueryData *query_data); @@ -100,89 +92,45 @@ */ typedef void (*PurpleTxtCallback)(GList *responses, gpointer data); -/** - * Queries an SRV record. - * - * @param account the account that the query is being done for (or NULL) - * @param protocol Name of the protocol (e.g. "sip") - * @param transport Name of the transport ("tcp" or "udp") - * @param domain Domain name to query (e.g. "blubb.com") - * @param cb A callback which will be called with the results - * @param extradata Extra data to be passed to the callback - * - * @since 2.8.0 - */ -PurpleSrvTxtQueryData *purple_srv_resolve_account(PurpleAccount *account, const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata); +G_BEGIN_DECLS -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_DNSSRV_C_) /** * Queries an SRV record. * - * @param protocol Name of the protocol (e.g. "sip") + * @param account The account that the query is being done for (or NULL) + * @param protocol Name of the protocol (e.g. "sip") * @param transport Name of the transport ("tcp" or "udp") - * @param domain Domain name to query (e.g. "blubb.com") - * @param cb A callback which will be called with the results + * @param domain Domain name to query (e.g. "blubb.com") + * @param cb A callback which will be called with the results * @param extradata Extra data to be passed to the callback * - * @deprecated Use purple_srv_resolve_account instead + * @return NULL if there was an error, otherwise return a reference to + * a data structure that can be used to cancel the pending + * DNS query, if needed. */ -PurpleSrvTxtQueryData *purple_srv_resolve(const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata); -#endif - -/** - * Cancel an SRV or DNS query. - * - * @param query_data The request to cancel. - * - * @deprecated Use purple_srv_txt_query_destroy instead - */ -void purple_srv_cancel(PurpleSrvTxtQueryData *query_data); +PurpleSrvTxtQueryData *purple_srv_resolve(PurpleAccount *account, const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata); /** * Queries an TXT record. * - * @param account the account that the query is being done for (or NULL) - * @param owner Name of the protocol (e.g. "_xmppconnect") - * @param domain Domain name to query (e.g. "blubb.com") - * @param cb A callback which will be called with the results + * @param account The account that the query is being done for (or NULL) + * @param owner Name of the protocol (e.g. "_xmppconnect") + * @param domain Domain name to query (e.g. "blubb.com") + * @param cb A callback which will be called with the results * @param extradata Extra data to be passed to the callback * - * @since 2.8.0 + * @return NULL if there was an error, otherwise return a reference to + * a data structure that can be used to cancel the pending + * DNS query, if needed. */ -PurpleSrvTxtQueryData *purple_txt_resolve_account(PurpleAccount *account, const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata); - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_DNSSRV_C_) -/** - * Queries an TXT record. - * - * @param owner Name of the protocol (e.g. "_xmppconnect") - * @param domain Domain name to query (e.g. "blubb.com") - * @param cb A callback which will be called with the results - * @param extradata Extra data to be passed to the callback - * - * @deprecated Use purple_txt_resolve_account instead - * - * @since 2.6.0 - */ -PurpleSrvTxtQueryData *purple_txt_resolve(const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata); -#endif - -/** - * Cancel an TXT DNS query. - * - * @param query_data The request to cancel. - * @since 2.6.0 - * - * @deprecated Use purple_srv_txt_query_destroy instead - */ -void purple_txt_cancel(PurpleSrvTxtQueryData *query_data); +PurpleSrvTxtQueryData *purple_txt_resolve(PurpleAccount *account, const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata); /** * Get the value of the current TXT record. * * @param response The TXT response record - * @returns The value of the current TXT record. - * @since 2.6.0 + * + * @return The value of the current TXT record. */ const gchar *purple_txt_response_get_content(PurpleTxtResponse *response); @@ -190,7 +138,6 @@ * Destroy a TXT DNS response object. * * @param response The PurpleTxtResponse to destroy. - * @since 2.6.0 */ void purple_txt_response_destroy(PurpleTxtResponse *response); @@ -220,7 +167,7 @@ PurpleSrvTxtQueryUiOps *purple_srv_txt_query_get_ui_ops(void); /** - * Get the query from a PurpleDnsQueryData + * Get the query from a PurpleSrvTxtQueryData * * @param query_data The SRV/TXT query * @return The query. @@ -228,15 +175,14 @@ char *purple_srv_txt_query_get_query(PurpleSrvTxtQueryData *query_data); /** - * Get the type from a PurpleDnsQueryData (TXT or SRV) + * Get the type from a PurpleSrvTxtQueryData (TXT or SRV) * * @param query_data The query * @return The query. */ int purple_srv_txt_query_get_type(PurpleSrvTxtQueryData *query_data); -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_DNSSRV_H */ + diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/eventloop.h --- a/libpurple/eventloop.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/eventloop.h Fri Apr 06 04:30:00 2012 +0000 @@ -28,10 +28,6 @@ #include -#ifdef __cplusplus -extern "C" { -#endif - /** * An input condition. */ @@ -145,7 +141,6 @@ * #timeout_add. * * @see purple_timeout_add_seconds() - * @since 2.1.0 **/ guint (*timeout_add_seconds)(guint interval, GSourceFunc function, gpointer data); @@ -155,6 +150,8 @@ void (*_purple_reserved4)(void); }; +G_BEGIN_DECLS + /**************************************************************************/ /** @name Event Loop API */ /**************************************************************************/ @@ -192,8 +189,6 @@ * @param data data to pass to @a function. * @return A handle to the timer which can be passed to * purple_timeout_remove() to remove the timer. - * - * @since 2.1.0 */ guint purple_timeout_add_seconds(guint interval, GSourceFunc function, gpointer data); @@ -269,8 +264,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_EVENTLOOP_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/example/nullclient.c --- a/libpurple/example/nullclient.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/example/nullclient.c Fri Apr 06 04:30:00 2012 +0000 @@ -237,7 +237,7 @@ signed_on(PurpleConnection *gc, gpointer null) { PurpleAccount *account = purple_connection_get_account(gc); - printf("Account connected: %s %s\n", account->username, account->protocol_id); + printf("Account connected: %s %s\n", purple_account_get_username(account), purple_account_get_protocol_id(account)); } static void diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/ft.c --- a/libpurple/ft.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/ft.c Fri Apr 06 04:30:00 2012 +0000 @@ -220,7 +220,7 @@ purple_xfer_destroy(xfer); } -static void +void purple_xfer_set_status(PurpleXfer *xfer, PurpleXferStatusType status) { g_return_if_fail(xfer != NULL); @@ -490,7 +490,7 @@ purple_xfer_ask_recv(PurpleXfer *xfer) { char *buf, *size_buf; - size_t size; + goffset size; gconstpointer thumb; gsize thumb_size; @@ -720,6 +720,20 @@ purple_xfer_unref(xfer); } +int purple_xfer_get_fd(PurpleXfer *xfer) +{ + g_return_val_if_fail(xfer != NULL, 0); + + return xfer->fd; +} + +int purple_xfer_get_watcher(PurpleXfer *xfer) +{ + g_return_val_if_fail(xfer != NULL, 0); + + return xfer->watcher; +} + PurpleXferType purple_xfer_get_type(const PurpleXfer *xfer) { @@ -751,9 +765,8 @@ return xfer->status; } -/* FIXME: Rename with cancelled for 3.0.0. */ gboolean -purple_xfer_is_canceled(const PurpleXfer *xfer) +purple_xfer_is_cancelled(const PurpleXfer *xfer) { g_return_val_if_fail(xfer != NULL, TRUE); @@ -788,7 +801,7 @@ return xfer->local_filename; } -size_t +goffset purple_xfer_get_bytes_sent(const PurpleXfer *xfer) { g_return_val_if_fail(xfer != NULL, 0); @@ -796,7 +809,7 @@ return xfer->bytes_sent; } -size_t +goffset purple_xfer_get_bytes_remaining(const PurpleXfer *xfer) { g_return_val_if_fail(xfer != NULL, 0); @@ -804,7 +817,7 @@ return xfer->bytes_remaining; } -size_t +goffset purple_xfer_get_size(const PurpleXfer *xfer) { g_return_val_if_fail(xfer != NULL, 0); @@ -864,6 +877,20 @@ return xfer->end_time; } +void purple_xfer_set_fd(PurpleXfer *xfer, int fd) +{ + g_return_if_fail(xfer != NULL); + + xfer->fd = fd; +} + +void purple_xfer_set_watcher(PurpleXfer *xfer, int watcher) +{ + g_return_if_fail(xfer != NULL); + + xfer->watcher = watcher; +} + void purple_xfer_set_completed(PurpleXfer *xfer, gboolean completed) { @@ -938,7 +965,7 @@ } void -purple_xfer_set_size(PurpleXfer *xfer, size_t size) +purple_xfer_set_size(PurpleXfer *xfer, goffset size) { g_return_if_fail(xfer != NULL); @@ -947,7 +974,15 @@ } void -purple_xfer_set_bytes_sent(PurpleXfer *xfer, size_t bytes_sent) +purple_xfer_set_local_port(PurpleXfer *xfer, unsigned int local_port) +{ + g_return_if_fail(xfer != NULL); + + xfer->local_port = local_port; +} + +void +purple_xfer_set_bytes_sent(PurpleXfer *xfer, goffset bytes_sent) { g_return_if_fail(xfer != NULL); @@ -1404,13 +1439,6 @@ purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_STARTED); - /* - * FIXME 3.0.0 -- there's too much broken code depending on fd == 0 - * meaning "don't use a real fd" - */ - if (fd == 0) - fd = -1; - if (type == PURPLE_XFER_RECEIVE) { cond = PURPLE_INPUT_READ; @@ -1701,6 +1729,37 @@ } } +void +purple_xfer_set_protocol_data(PurpleXfer *xfer, gpointer proto_data) +{ + g_return_if_fail(xfer != NULL); + + xfer->proto_data = proto_data; +} + +gpointer +purple_xfer_get_protocol_data(const PurpleXfer *xfer) +{ + g_return_val_if_fail(xfer != NULL, NULL); + + return xfer->proto_data; +} + +void purple_xfer_set_ui_data(PurpleXfer *xfer, gpointer ui_data) +{ + g_return_if_fail(xfer != NULL); + + xfer->ui_data = ui_data; +} + +gpointer purple_xfer_get_ui_data(const PurpleXfer *xfer) +{ + g_return_val_if_fail(xfer != NULL, NULL); + + return xfer->ui_data; +} + + /************************************************************************** * File Transfer Subsystem API **************************************************************************/ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/ft.h --- a/libpurple/ft.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/ft.h Fri Apr 06 04:30:00 2012 +0000 @@ -87,7 +87,6 @@ * * @return size if the write was successful, or a value between 0 and * size on error. - * @since 2.6.0 */ gssize (*ui_write)(PurpleXfer *xfer, const guchar *buffer, gssize size); @@ -102,7 +101,6 @@ * @returns The amount of data in the buffer, 0 if nothing is available, * and a negative value if an error occurred and the transfer * should be cancelled (libpurple will cancel). - * @since 2.6.0 */ gssize (*ui_read)(PurpleXfer *xfer, guchar **buffer, gssize size); @@ -115,8 +113,6 @@ * @param xfer The file transfer structure * @param buffer A pointer to the beginning of the unwritten data. * @param size The amount of unwritten data. - * - * @since 2.6.0 */ void (*data_not_sent)(PurpleXfer *xfer, const guchar *buffer, gsize size); @@ -144,7 +140,7 @@ char *message; /**< A message sent with the request */ char *filename; /**< The name sent over the network. */ char *local_filename; /**< The name on the local hard drive. */ - size_t size; /**< The size of the file. */ + goffset size; /**< The size of the file. */ FILE *dest_fp; /**< The destination file pointer. */ @@ -155,8 +151,8 @@ int fd; /**< The socket file descriptor. */ int watcher; /**< Watcher. */ - size_t bytes_sent; /**< The number of bytes sent. */ - size_t bytes_remaining; /**< The number of bytes remaining. */ + goffset bytes_sent; /**< The number of bytes sent. */ + goffset bytes_remaining; /**< The number of bytes remaining. */ time_t start_time; /**< When the transfer of data began. */ time_t end_time; /**< When the transfer of data ended. */ @@ -185,12 +181,10 @@ PurpleXferUiOps *ui_ops; /**< UI-specific operations. */ void *ui_data; /**< UI-specific data. */ - void *data; /**< prpl-specific data. */ + void *proto_data; /**< prpl-specific data. */ }; -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name File Transfer API */ @@ -266,6 +260,24 @@ void purple_xfer_request_denied(PurpleXfer *xfer); /** + * Returns the socket file descriptor. + * + * @param xfer The file transfer. + * + * @return The socket file descriptor. + */ +int purple_xfer_get_fd(PurpleXfer *xfer); + +/** + * Returns the Watcher for the transfer. + * + * @param xfer The file transfer. + * + * @return The watcher. + */ +int purple_xfer_get_watcher(PurpleXfer *xfer); + +/** * Returns the type of file transfer. * * @param xfer The file transfer. @@ -289,8 +301,6 @@ * @param xfer The file transfer. * * @return The name of the remote user. - * - * @since 2.1.0 */ const char *purple_xfer_get_remote_user(const PurpleXfer *xfer); @@ -309,9 +319,8 @@ * @param xfer The file transfer. * * @return Whether or not the transfer was cancelled. - * FIXME: This should be renamed using cancelled for 3.0.0. */ -gboolean purple_xfer_is_canceled(const PurpleXfer *xfer); +gboolean purple_xfer_is_cancelled(const PurpleXfer *xfer); /** * Returns the completed state for a file transfer. @@ -347,7 +356,7 @@ * * @return The number of bytes sent. */ -size_t purple_xfer_get_bytes_sent(const PurpleXfer *xfer); +goffset purple_xfer_get_bytes_sent(const PurpleXfer *xfer); /** * Returns the number of bytes remaining to send or receive. @@ -356,7 +365,7 @@ * * @return The number of bytes remaining. */ -size_t purple_xfer_get_bytes_remaining(const PurpleXfer *xfer); +goffset purple_xfer_get_bytes_remaining(const PurpleXfer *xfer); /** * Returns the size of the file being sent or received. @@ -365,7 +374,7 @@ * * @return The total size of the file. */ -size_t purple_xfer_get_size(const PurpleXfer *xfer); +goffset purple_xfer_get_size(const PurpleXfer *xfer); /** * Returns the current percentage of progress of the transfer. @@ -411,7 +420,6 @@ * @param xfer The file transfer. * * @return The time when the transfer started. - * @since 2.4.0 */ time_t purple_xfer_get_start_time(const PurpleXfer *xfer); @@ -421,11 +429,26 @@ * @param xfer The file transfer. * * @return The time when the transfer ended. - * @since 2.4.0 */ time_t purple_xfer_get_end_time(const PurpleXfer *xfer); /** + * Sets the socket file descriptor. + * + * @param xfer The file transfer. + * @param fd The file descriptor. + */ +void purple_xfer_set_fd(PurpleXfer *xfer, int fd); + +/** + * Sets the watcher for the file transfer. + * + * @param xfer The file transfer. + * @param watcher The watcher. + */ +void purple_xfer_set_watcher(PurpleXfer *xfer, int watcher); + +/** * Sets the completed state for the file transfer. * * @param xfer The file transfer. @@ -434,6 +457,14 @@ void purple_xfer_set_completed(PurpleXfer *xfer, gboolean completed); /** + * Sets the current status for the file transfer. + * + * @param xfer The file transfer. + * @param status The current status. + */ +void purple_xfer_set_status(PurpleXfer *xfer, PurpleXferStatusType status); + +/** * Sets the filename for the file transfer. * * @param xfer The file transfer. @@ -463,7 +494,15 @@ * @param xfer The file transfer. * @param size The size of the file. */ -void purple_xfer_set_size(PurpleXfer *xfer, size_t size); +void purple_xfer_set_size(PurpleXfer *xfer, goffset size); + +/** + * Sets the local port of the file transfer. + * + * @param xfer The file transfer. + * @param local_port The local port. + */ +void purple_xfer_set_local_port(PurpleXfer *xfer, unsigned int local_port); /** * Sets the current working position in the active file transfer. This @@ -478,7 +517,7 @@ * send. If we're receiving a file, this is the * next byte that we expect to receive. */ -void purple_xfer_set_bytes_sent(PurpleXfer *xfer, size_t bytes_sent); +void purple_xfer_set_bytes_sent(PurpleXfer *xfer, goffset bytes_sent); /** * Returns the UI operations structure for a file transfer. @@ -596,11 +635,8 @@ * file receive transfer. On send, @a fd must be specified, and * @a ip and @a port are ignored. * - * Prior to libpurple 2.6.0, passing '0' to @a fd was special-cased to - * allow the protocol plugin to facilitate the file transfer itself. As of - * 2.6.0, this is supported (for backward compatibility), but will be - * removed in libpurple 3.0.0. If a prpl detects that the running libpurple - * is running 2.6.0 or higher, it should use the invalid fd '-1'. + * Passing @a fd as '-1' is a special-case and indicates to the + * protocol plugin to facilitate the file transfer itself. * * @param xfer The file transfer. * @param fd The file descriptor for the socket. @@ -677,8 +713,6 @@ * read/write/data_not_sent UI ops. * * @param xfer The file transfer which is ready. - * - * @since 2.6.0 */ void purple_xfer_ui_ready(PurpleXfer *xfer); @@ -688,8 +722,6 @@ * ops and cannot/does not provide a raw fd to the core. * * @param xfer The file transfer which is ready. - * - * @since 2.6.0 */ void purple_xfer_prpl_ready(PurpleXfer *xfer); @@ -700,7 +732,6 @@ * @param len If not @c NULL, the length of the thumbnail data returned * will be set in the location pointed to by this. * @return The thumbnail data, or NULL if there is no thumbnail - * @since 2.7.0 */ gconstpointer purple_xfer_get_thumbnail(const PurpleXfer *xfer, gsize *len); @@ -709,7 +740,6 @@ * * @param xfer The file transfer to get the mimetype for * @return The mimetype of the thumbnail, or @c NULL if not thumbnail is set - * @since 2.7.0 */ const gchar *purple_xfer_get_thumbnail_mimetype(const PurpleXfer *xfer); @@ -721,7 +751,6 @@ * @param thumbnail A pointer to the thumbnail data, this will be copied * @param size The size in bytes of the passed in thumbnail data * @param mimetype The mimetype of the generated thumbnail - * @since 2.7.0 */ void purple_xfer_set_thumbnail(PurpleXfer *xfer, gconstpointer thumbnail, gsize size, const gchar *mimetype); @@ -733,10 +762,44 @@ * @param xfer The file transfer to create a thumbnail for * @param formats A comma-separated list of mimetypes for image formats * the protocols can use for thumbnails. - * @since 2.7.0 */ void purple_xfer_prepare_thumbnail(PurpleXfer *xfer, const gchar *formats); +/** + * Sets the protocol data for a file transfer. + * + * @param xfer The file transfer. + * @param proto_data The protocol data to set for the file transfer. + */ +void purple_xfer_set_protocol_data(PurpleXfer *xfer, gpointer proto_data); + +/** + * Gets the protocol data for a file transfer. + * + * @param xfer The file transfer. + * + * @return The protocol data for the file transfer. + */ +gpointer purple_xfer_get_protocol_data(const PurpleXfer *xfer); + +/** + * Set the UI data associated with this file transfer. + * + * @param xfer The file transfer. + * @param ui_data A pointer to associate with this file transfer. + */ +void purple_xfer_set_ui_data(PurpleXfer *xfer, gpointer ui_data); + +/** + * Get the UI data associated with this file transfer. + * + * @param xfer The file transfer. + * + * @return The UI data associated with this file transfer. This is a + * convenience field provided to the UIs--it is not + * used by the libpurple core. + */ +gpointer purple_xfer_get_ui_data(const PurpleXfer *xfer); /*@}*/ @@ -778,8 +841,7 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_FT_H_ */ + diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/gaim-compat.h --- a/libpurple/gaim-compat.h Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2317 +0,0 @@ -/** - * @file gaim-compat.h Gaim Compat macros - * @ingroup core - */ - -/* pidgin - * - * Pidgin is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ -#ifndef _GAIM_COMPAT_H_ -#define _GAIM_COMPAT_H_ - -#include - -/* from account.h */ -#define GaimAccountUiOps PurpleAccountUiOps -#define GaimAccount PurpleAccount - -#define GaimFilterAccountFunc PurpleFilterAccountFunc -#define GaimAccountRequestAuthorizationCb PurpleAccountRequestAuthorizationCb - -#define gaim_account_new purple_account_new -#define gaim_account_destroy purple_account_destroy -#define gaim_account_connect purple_account_connect -#define gaim_account_register purple_account_register -#define gaim_account_disconnect purple_account_disconnect -#define gaim_account_notify_added purple_account_notify_added -#define gaim_account_request_add purple_account_request_add -#define gaim_account_request_close purple_account_request_close - -#define gaim_account_request_authorization purple_account_request_authorization -#define gaim_account_request_change_password purple_account_request_change_password -#define gaim_account_request_change_user_info purple_account_request_change_user_info - -#define gaim_account_set_username purple_account_set_username -#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_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 -#define gaim_account_set_remember_password purple_account_set_remember_password -#define gaim_account_set_check_mail purple_account_set_check_mail -#define gaim_account_set_enabled purple_account_set_enabled -#define gaim_account_set_proxy_info purple_account_set_proxy_info -#define gaim_account_set_status_types purple_account_set_status_types -#define gaim_account_set_status purple_account_set_status -#define gaim_account_set_status_list purple_account_set_status_list - -#define gaim_account_clear_settings purple_account_clear_settings - -#define gaim_account_set_int purple_account_set_int -#define gaim_account_set_string purple_account_set_string -#define gaim_account_set_bool purple_account_set_bool - -#define gaim_account_set_ui_int purple_account_set_ui_int -#define gaim_account_set_ui_string purple_account_set_ui_string -#define gaim_account_set_ui_bool purple_account_set_ui_bool - -#define gaim_account_is_connected purple_account_is_connected -#define gaim_account_is_connecting purple_account_is_connecting -#define gaim_account_is_disconnected purple_account_is_disconnected - -#define gaim_account_get_username purple_account_get_username -#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_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 -#define gaim_account_get_connection purple_account_get_connection -#define gaim_account_get_remember_password purple_account_get_remember_password -#define gaim_account_get_check_mail purple_account_get_check_mail -#define gaim_account_get_enabled purple_account_get_enabled -#define gaim_account_get_proxy_info purple_account_get_proxy_info -#define gaim_account_get_active_status purple_account_get_active_status -#define gaim_account_get_status purple_account_get_status -#define gaim_account_get_status_type purple_account_get_status_type -#define gaim_account_get_status_type_with_primitive \ - purple_account_get_status_type_with_primitive - -#define gaim_account_get_presence purple_account_get_presence -#define gaim_account_is_status_active purple_account_is_status_active -#define gaim_account_get_status_types purple_account_get_status_types - -#define gaim_account_get_int purple_account_get_int -#define gaim_account_get_string purple_account_get_string -#define gaim_account_get_bool purple_account_get_bool - -#define gaim_account_get_ui_int purple_account_get_ui_int -#define gaim_account_get_ui_string purple_account_get_ui_string -#define gaim_account_get_ui_bool purple_account_get_ui_bool - - -#define gaim_account_get_log purple_account_get_log -#define gaim_account_destroy_log purple_account_destroy_log - -#define gaim_account_add_buddy purple_account_add_buddy -#define gaim_account_add_buddies purple_account_add_buddies -#define gaim_account_remove_buddy purple_account_remove_buddy -#define gaim_account_remove_buddies purple_account_remove_buddies - -#define gaim_account_remove_group purple_account_remove_group - -#define gaim_account_change_password purple_account_change_password - -#define gaim_account_supports_offline_message purple_account_supports_offline_message - -#define gaim_accounts_add purple_accounts_add -#define gaim_accounts_remove purple_accounts_remove -#define gaim_accounts_delete purple_accounts_delete -#define gaim_accounts_reorder purple_accounts_reorder - -#define gaim_accounts_get_all purple_accounts_get_all -#define gaim_accounts_get_all_active purple_accounts_get_all_active - -#define gaim_accounts_find purple_accounts_find - -#define gaim_accounts_restore_current_statuses purple_accounts_restore_current_statuses - -#define gaim_accounts_set_ui_ops purple_accounts_set_ui_ops -#define gaim_accounts_get_ui_ops purple_accounts_get_ui_ops - -#define gaim_accounts_get_handle purple_accounts_get_handle - -#define gaim_accounts_init purple_accounts_init -#define gaim_accounts_uninit purple_accounts_uninit - -/* from accountopt.h */ - -#define GaimAccountOption PurpleAccountOption -#define GaimAccountUserSplit PurpleAccountUserSplit - -#define gaim_account_option_new purple_account_option_new -#define gaim_account_option_bool_new purple_account_option_bool_new -#define gaim_account_option_int_new purple_account_option_int_new -#define gaim_account_option_string_new purple_account_option_string_new -#define gaim_account_option_list_new purple_account_option_list_new - -#define gaim_account_option_destroy purple_account_option_destroy - -#define gaim_account_option_set_default_bool purple_account_option_set_default_bool -#define gaim_account_option_set_default_int purple_account_option_set_default_int -#define gaim_account_option_set_default_string purple_account_option_set_default_string - -#define gaim_account_option_set_masked purple_account_option_set_masked - -#define gaim_account_option_set_list purple_account_option_set_list - -#define gaim_account_option_add_list_item purple_account_option_add_list_item - -#define gaim_account_option_get_type purple_account_option_get_type -#define gaim_account_option_get_text purple_account_option_get_text -#define gaim_account_option_get_setting purple_account_option_get_setting - -#define gaim_account_option_get_default_bool purple_account_option_get_default_bool -#define gaim_account_option_get_default_int purple_account_option_get_default_int -#define gaim_account_option_get_default_string purple_account_option_get_default_string -#define gaim_account_option_get_default_list_value purple_account_option_get_default_list_value - -#define gaim_account_option_get_masked purple_account_option_get_masked -#define gaim_account_option_get_list purple_account_option_get_list - -#define gaim_account_user_split_new purple_account_user_split_new -#define gaim_account_user_split_destroy purple_account_user_split_destroy - -#define gaim_account_user_split_get_text purple_account_user_split_get_text -#define gaim_account_user_split_get_default_value purple_account_user_split_get_default_value -#define gaim_account_user_split_get_separator purple_account_user_split_get_separator - -/* from blist.h */ - -#define GaimBuddyList PurpleBuddyList -#define GaimBlistUiOps PurpleBlistUiOps -#define GaimBlistNode PurpleBlistNode - -#define GaimChat PurpleChat -#define GaimGroup PurpleGroup -#define GaimContact PurpleContact -#define GaimBuddy PurpleBuddy - -#define GAIM_BLIST_GROUP_NODE PURPLE_BLIST_GROUP_NODE -#define GAIM_BLIST_CONTACT_NODE PURPLE_BLIST_CONTACT_NODE -#define GAIM_BLIST_BUDDY_NODE PURPLE_BLIST_BUDDY_NODE -#define GAIM_BLIST_CHAT_NODE PURPLE_BLIST_CHAT_NODE -#define GAIM_BLIST_OTHER_NODE PURPLE_BLIST_OTHER_NODE -#define GaimBlistNodeType PurpleBlistNodeType - -#define GAIM_BLIST_NODE_IS_CHAT PURPLE_BLIST_NODE_IS_CHAT -#define GAIM_BLIST_NODE_IS_BUDDY PURPLE_BLIST_NODE_IS_BUDDY -#define GAIM_BLIST_NODE_IS_CONTACT PURPLE_BLIST_NODE_IS_CONTACT -#define GAIM_BLIST_NODE_IS_GROUP PURPLE_BLIST_NODE_IS_GROUP - -#define GAIM_BUDDY_IS_ONLINE PURPLE_BUDDY_IS_ONLINE - -#define GAIM_BLIST_NODE_FLAG_NO_SAVE PURPLE_BLIST_NODE_FLAG_NO_SAVE -#define GaimBlistNodeFlags PurpleBlistNodeFlags - -#define GAIM_BLIST_NODE_HAS_FLAG PURPLE_BLIST_NODE_HAS_FLAG -#define GAIM_BLIST_NODE_SHOULD_SAVE PURPLE_BLIST_NODE_SHOULD_SAVE - -#define GAIM_BLIST_NODE_NAME PURPLE_BLIST_NODE_NAME - - -#define gaim_blist_new purple_blist_new -#define gaim_set_blist purple_set_blist -#define gaim_get_blist purple_get_blist - -#define gaim_blist_get_root purple_blist_get_root -#define gaim_blist_node_next purple_blist_node_next - -#define gaim_blist_show purple_blist_show - -#define gaim_blist_destroy purple_blist_destroy - -#define gaim_blist_set_visible purple_blist_set_visible - -#define gaim_blist_update_buddy_status purple_blist_update_buddy_status -#define gaim_blist_update_buddy_icon purple_blist_update_buddy_icon - - -#define gaim_blist_alias_contact purple_blist_alias_contact -#define gaim_blist_alias_buddy purple_blist_alias_buddy -#define gaim_blist_server_alias_buddy purple_blist_server_alias_buddy -#define gaim_blist_alias_chat purple_blist_alias_chat - -#define gaim_blist_rename_buddy purple_blist_rename_buddy -#define gaim_blist_rename_group purple_blist_rename_group - -#define gaim_chat_new purple_chat_new -#define gaim_blist_add_chat purple_blist_add_chat - -#define gaim_buddy_new purple_buddy_new -#define gaim_buddy_set_icon purple_buddy_set_icon -#define gaim_buddy_get_account purple_buddy_get_account -#define gaim_buddy_get_name purple_buddy_get_name -#define gaim_buddy_get_icon purple_buddy_get_icon -#define gaim_buddy_get_contact purple_buddy_get_contact -#define gaim_buddy_get_presence purple_buddy_get_presence - -#define gaim_blist_add_buddy purple_blist_add_buddy - -#define gaim_group_new purple_group_new - -#define gaim_blist_add_group purple_blist_add_group - -#define gaim_contact_new purple_contact_new - -#define gaim_blist_add_contact purple_blist_add_contact -#define gaim_blist_merge_contact purple_blist_merge_contact - -#define gaim_contact_get_priority_buddy purple_contact_get_priority_buddy -#define gaim_contact_set_alias purple_contact_set_alias -#define gaim_contact_get_alias purple_contact_get_alias -#define gaim_contact_on_account purple_contact_on_account - -#define gaim_contact_invalidate_priority_buddy purple_contact_invalidate_priority_buddy - -#define gaim_blist_remove_buddy purple_blist_remove_buddy -#define gaim_blist_remove_contact purple_blist_remove_contact -#define gaim_blist_remove_chat purple_blist_remove_chat -#define gaim_blist_remove_group purple_blist_remove_group - -#define gaim_buddy_get_alias_only purple_buddy_get_alias_only -#define gaim_buddy_get_server_alias purple_buddy_get_server_alias -#define gaim_buddy_get_contact_alias purple_buddy_get_contact_alias -#define gaim_buddy_get_local_alias purple_buddy_get_local_alias -#define gaim_buddy_get_alias purple_buddy_get_alias - -#define gaim_chat_get_name purple_chat_get_name - -#define gaim_find_buddy purple_find_buddy -#define gaim_find_buddy_in_group purple_find_buddy_in_group -#define gaim_find_buddies purple_find_buddies - -#define gaim_find_group purple_find_group - -#define gaim_blist_find_chat purple_blist_find_chat - -#define gaim_chat_get_group purple_chat_get_group -#define gaim_buddy_get_group purple_buddy_get_group - -#define gaim_group_get_accounts purple_group_get_accounts -#define gaim_group_on_account purple_group_on_account - -#define gaim_blist_add_account purple_blist_add_account -#define gaim_blist_remove_account purple_blist_remove_account - -#define gaim_blist_get_group_size purple_blist_get_group_size -#define gaim_blist_get_group_online_count purple_blist_get_group_online_count - -#define gaim_blist_load purple_blist_load -#define gaim_blist_schedule_save purple_blist_schedule_save - -#define gaim_blist_request_add_buddy purple_blist_request_add_buddy -#define gaim_blist_request_add_chat purple_blist_request_add_chat -#define gaim_blist_request_add_group purple_blist_request_add_group - -#define gaim_blist_node_set_bool purple_blist_node_set_bool -#define gaim_blist_node_get_bool purple_blist_node_get_bool -#define gaim_blist_node_set_int purple_blist_node_set_int -#define gaim_blist_node_get_int purple_blist_node_get_int -#define gaim_blist_node_set_string purple_blist_node_set_string -#define gaim_blist_node_get_string purple_blist_node_get_string - -#define gaim_blist_node_remove_setting purple_blist_node_remove_setting - -#define gaim_blist_node_set_flags purple_blist_node_set_flags -#define gaim_blist_node_get_flags purple_blist_node_get_flags - -#define gaim_blist_node_get_extended_menu purple_blist_node_get_extended_menu - -#define gaim_blist_set_ui_ops purple_blist_set_ui_ops -#define gaim_blist_get_ui_ops purple_blist_get_ui_ops - -#define gaim_blist_get_handle purple_blist_get_handle - -#define gaim_blist_init purple_blist_init -#define gaim_blist_uninit purple_blist_uninit - - -#define GaimBuddyIcon PurpleBuddyIcon - -#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_set_data(icon, data, len) \ - purple_buddy_icon_set_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_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, NULL) -#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_handle purple_buddy_icons_get_handle - -#define gaim_buddy_icons_init purple_buddy_icons_init -#define gaim_buddy_icons_uninit purple_buddy_icons_uninit - -#define gaim_buddy_icon_get_scale_size purple_buddy_icon_get_scale_size - -/* from cipher.h */ - -#define GAIM_CIPHER PURPLE_CIPHER -#define GAIM_CIPHER_OPS PURPLE_CIPHER_OPS -#define GAIM_CIPHER_CONTEXT PURPLE_CIPHER_CONTEXT - -#define GaimCipher PurpleCipher -#define GaimCipherOps PurpleCipherOps -#define GaimCipherContext PurpleCipherContext - -#define GAIM_CIPHER_CAPS_SET_OPT PURPLE_CIPHER_CAPS_SET_OPT -#define GAIM_CIPHER_CAPS_GET_OPT PURPLE_CIPHER_CAPS_GET_OPT -#define GAIM_CIPHER_CAPS_INIT PURPLE_CIPHER_CAPS_INIT -#define GAIM_CIPHER_CAPS_RESET PURPLE_CIPHER_CAPS_RESET -#define GAIM_CIPHER_CAPS_UNINIT PURPLE_CIPHER_CAPS_UNINIT -#define GAIM_CIPHER_CAPS_SET_IV PURPLE_CIPHER_CAPS_SET_IV -#define GAIM_CIPHER_CAPS_APPEND PURPLE_CIPHER_CAPS_APPEND -#define GAIM_CIPHER_CAPS_DIGEST PURPLE_CIPHER_CAPS_DIGEST -#define GAIM_CIPHER_CAPS_ENCRYPT PURPLE_CIPHER_CAPS_ENCRYPT -#define GAIM_CIPHER_CAPS_DECRYPT PURPLE_CIPHER_CAPS_DECRYPT -#define GAIM_CIPHER_CAPS_SET_SALT PURPLE_CIPHER_CAPS_SET_SALT -#define GAIM_CIPHER_CAPS_GET_SALT_SIZE PURPLE_CIPHER_CAPS_GET_SALT_SIZE -#define GAIM_CIPHER_CAPS_SET_KEY PURPLE_CIPHER_CAPS_SET_KEY -#define GAIM_CIPHER_CAPS_GET_KEY_SIZE PURPLE_CIPHER_CAPS_GET_KEY_SIZE -#define GAIM_CIPHER_CAPS_UNKNOWN PURPLE_CIPHER_CAPS_UNKNOWN - -#define gaim_cipher_get_name purple_cipher_get_name -#define gaim_cipher_get_capabilities purple_cipher_get_capabilities -#define gaim_cipher_digest_region purple_cipher_digest_region - -#define gaim_ciphers_find_cipher purple_ciphers_find_cipher -#define gaim_ciphers_register_cipher purple_ciphers_register_cipher -#define gaim_ciphers_unregister_cipher purple_ciphers_unregister_cipher -#define gaim_ciphers_get_ciphers purple_ciphers_get_ciphers - -#define gaim_ciphers_get_handle purple_ciphers_get_handle -#define gaim_ciphers_init purple_ciphers_init -#define gaim_ciphers_uninit purple_ciphers_uninit - -#define gaim_cipher_context_set_option purple_cipher_context_set_option -#define gaim_cipher_context_get_option purple_cipher_context_get_option - -#define gaim_cipher_context_new purple_cipher_context_new -#define gaim_cipher_context_new_by_name purple_cipher_context_new_by_name -#define gaim_cipher_context_reset purple_cipher_context_reset -#define gaim_cipher_context_destroy purple_cipher_context_destroy -#define gaim_cipher_context_set_iv purple_cipher_context_set_iv -#define gaim_cipher_context_append purple_cipher_context_append -#define gaim_cipher_context_digest purple_cipher_context_digest -#define gaim_cipher_context_digest_to_str purple_cipher_context_digest_to_str -#define gaim_cipher_context_encrypt purple_cipher_context_encrypt -#define gaim_cipher_context_decrypt purple_cipher_context_decrypt -#define gaim_cipher_context_set_salt purple_cipher_context_set_salt -#define gaim_cipher_context_get_salt_size purple_cipher_context_get_salt_size -#define gaim_cipher_context_set_key purple_cipher_context_set_key -#define gaim_cipher_context_get_key_size purple_cipher_context_get_key_size -#define gaim_cipher_context_set_data purple_cipher_context_set_data -#define gaim_cipher_context_get_data purple_cipher_context_get_data - -#define gaim_cipher_http_digest_calculate_session_key \ - purple_cipher_http_digest_calculate_session_key - -#define gaim_cipher_http_digest_calculate_response \ - purple_cipher_http_digest_calculate_response - -/* from circbuffer.h */ - -#define GaimCircBuffer PurpleCircBuffer - -#define gaim_circ_buffer_new purple_circ_buffer_new -#define gaim_circ_buffer_destroy purple_circ_buffer_destroy -#define gaim_circ_buffer_append purple_circ_buffer_append -#define gaim_circ_buffer_get_max_read purple_circ_buffer_get_max_read -#define gaim_circ_buffer_mark_read purple_circ_buffer_mark_read - -/* from cmds.h */ - -#define GaimCmdPriority PurpleCmdPriority -#define GaimCmdFlag PurpleCmdFlag -#define GaimCmdStatus PurpleCmdStatus -#define GaimCmdRet PurpleCmdRet - -#define GAIM_CMD_STATUS_OK PURPLE_CMD_STATUS_OK -#define GAIM_CMD_STATUS_FAILED PURPLE_CMD_STATUS_FAILED -#define GAIM_CMD_STATUS_NOT_FOUND PURPLE_CMD_STATUS_NOT_FOUND -#define GAIM_CMD_STATUS_WRONG_ARGS PURPLE_CMD_STATUS_WRONG_ARGS -#define GAIM_CMD_STATUS_WRONG_PRPL PURPLE_CMD_STATUS_WRONG_PRPL -#define GAIM_CMD_STATUS_WRONG_TYPE PURPLE_CMD_STATUS_WRONG_TYPE - -#define GAIM_CMD_FUNC PURPLE_CMD_FUNC - -#define GAIM_CMD_RET_OK PURPLE_CMD_RET_OK -#define GAIM_CMD_RET_FAILED PURPLE_CMD_RET_FAILED -#define GAIM_CMD_RET_CONTINUE PURPLE_CMD_RET_CONTINUE - -#define GAIM_CMD_P_VERY_LOW PURPLE_CMD_P_VERY_LOW -#define GAIM_CMD_P_LOW PURPLE_CMD_P_LOW -#define GAIM_CMD_P_DEFAULT PURPLE_CMD_P_DEFAULT -#define GAIM_CMD_P_PRPL PURPLE_CMD_P_PRPL -#define GAIM_CMD_P_PLUGIN PURPLE_CMD_P_PLUGIN -#define GAIM_CMD_P_ALIAS PURPLE_CMD_P_ALIAS -#define GAIM_CMD_P_HIGH PURPLE_CMD_P_HIGH -#define GAIM_CMD_P_VERY_HIGH PURPLE_CMD_P_VERY_HIGH - -#define GAIM_CMD_FLAG_IM PURPLE_CMD_FLAG_IM -#define GAIM_CMD_FLAG_CHAT PURPLE_CMD_FLAG_CHAT -#define GAIM_CMD_FLAG_PRPL_ONLY PURPLE_CMD_FLAG_PRPL_ONLY -#define GAIM_CMD_FLAG_ALLOW_WRONG_ARGS PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS - - -#define GaimCmdFunc PurpleCmdFunc - -#define GaimCmdId PurpleCmdId - -#define gaim_cmd_register purple_cmd_register -#define gaim_cmd_unregister purple_cmd_unregister -#define gaim_cmd_do_command purple_cmd_do_command -#define gaim_cmd_list purple_cmd_list -#define gaim_cmd_help purple_cmd_help - -/* from connection.h */ - -#define GaimConnection PurpleConnection - -#define GAIM_CONNECTION_HTML PURPLE_CONNECTION_HTML -#define GAIM_CONNECTION_NO_BGCOLOR PURPLE_CONNECTION_NO_BGCOLOR -#define GAIM_CONNECTION_AUTO_RESP PURPLE_CONNECTION_AUTO_RESP -#define GAIM_CONNECTION_FORMATTING_WBFO PURPLE_CONNECTION_FORMATTING_WBFO -#define GAIM_CONNECTION_NO_NEWLINES PURPLE_CONNECTION_NO_NEWLINES -#define GAIM_CONNECTION_NO_FONTSIZE PURPLE_CONNECTION_NO_FONTSIZE -#define GAIM_CONNECTION_NO_URLDESC PURPLE_CONNECTION_NO_URLDESC -#define GAIM_CONNECTION_NO_IMAGES PURPLE_CONNECTION_NO_IMAGES - -#define GaimConnectionFlags PurpleConnectionFlags - -#define GAIM_DISCONNECTED PURPLE_DISCONNECTED -#define GAIM_CONNECTED PURPLE_CONNECTED -#define GAIM_CONNECTING PURPLE_CONNECTING - -#define GaimConnectionState PurpleConnectionState - -#define GaimConnectionUiOps PurpleConnectionUiOps - -#define gaim_connection_new purple_connection_new -#define gaim_connection_destroy purple_connection_destroy - -#define gaim_connection_set_state purple_connection_set_state -#define gaim_connection_set_account purple_connection_set_account -#define gaim_connection_set_display_name purple_connection_set_display_name -#define gaim_connection_get_state purple_connection_get_state - -#define GAIM_CONNECTION_IS_CONNECTED PURPLE_CONNECTION_IS_CONNECTED - -#define gaim_connection_get_account purple_connection_get_account -#define gaim_connection_get_password purple_connection_get_password -#define gaim_connection_get_display_name purple_connection_get_display_name - -#define gaim_connection_update_progress purple_connection_update_progress - -#define gaim_connection_notice purple_connection_notice -#define gaim_connection_error purple_connection_error - -#define gaim_connections_disconnect_all purple_connections_disconnect_all - -#define gaim_connections_get_all purple_connections_get_all -#define gaim_connections_get_connecting purple_connections_get_connecting - -#define GAIM_CONNECTION_IS_VALID PURPLE_CONNECTION_IS_VALID - -#define gaim_connections_set_ui_ops purple_connections_set_ui_ops -#define gaim_connections_get_ui_ops purple_connections_get_ui_ops - -#define gaim_connections_init purple_connections_init -#define gaim_connections_uninit purple_connections_uninit -#define gaim_connections_get_handle purple_connections_get_handle - - -/* from conversation.h */ - -#define GaimConversationUiOps PurpleConversationUiOps -#define GaimConversation PurpleConversation -#define GaimConvIm PurpleConvIm -#define GaimConvChat PurpleConvChat -#define GaimConvChatBuddy PurpleConvChatBuddy - -#define GAIM_CONV_TYPE_UNKNOWN PURPLE_CONV_TYPE_UNKNOWN -#define GAIM_CONV_TYPE_IM PURPLE_CONV_TYPE_IM -#define GAIM_CONV_TYPE_CHAT PURPLE_CONV_TYPE_CHAT -#define GAIM_CONV_TYPE_MISC PURPLE_CONV_TYPE_MISC -#define GAIM_CONV_TYPE_ANY PURPLE_CONV_TYPE_ANY - -#define GaimConversationType PurpleConversationType - -#define GAIM_CONV_UPDATE_ADD PURPLE_CONV_UPDATE_ADD -#define GAIM_CONV_UPDATE_REMOVE PURPLE_CONV_UPDATE_REMOVE -#define GAIM_CONV_UPDATE_ACCOUNT PURPLE_CONV_UPDATE_ACCOUNT -#define GAIM_CONV_UPDATE_TYPING PURPLE_CONV_UPDATE_TYPING -#define GAIM_CONV_UPDATE_UNSEEN PURPLE_CONV_UPDATE_UNSEEN -#define GAIM_CONV_UPDATE_LOGGING PURPLE_CONV_UPDATE_LOGGING -#define GAIM_CONV_UPDATE_TOPIC PURPLE_CONV_UPDATE_TOPIC -#define GAIM_CONV_ACCOUNT_ONLINE PURPLE_CONV_ACCOUNT_ONLINE -#define GAIM_CONV_ACCOUNT_OFFLINE PURPLE_CONV_ACCOUNT_OFFLINE -#define GAIM_CONV_UPDATE_AWAY PURPLE_CONV_UPDATE_AWAY -#define GAIM_CONV_UPDATE_ICON PURPLE_CONV_UPDATE_ICON -#define GAIM_CONV_UPDATE_TITLE PURPLE_CONV_UPDATE_TITLE -#define GAIM_CONV_UPDATE_CHATLEFT PURPLE_CONV_UPDATE_CHATLEFT -#define GAIM_CONV_UPDATE_FEATURES PURPLE_CONV_UPDATE_FEATURES - -#define GaimConvUpdateType PurpleConvUpdateType - -#define GAIM_NOT_TYPING PURPLE_NOT_TYPING -#define GAIM_TYPING PURPLE_TYPING -#define GAIM_TYPED PURPLE_TYPED - -#define GaimTypingState PurpleTypingState - -#define GAIM_MESSAGE_SEND PURPLE_MESSAGE_SEND -#define GAIM_MESSAGE_RECV PURPLE_MESSAGE_RECV -#define GAIM_MESSAGE_SYSTEM PURPLE_MESSAGE_SYSTEM -#define GAIM_MESSAGE_AUTO_RESP PURPLE_MESSAGE_AUTO_RESP -#define GAIM_MESSAGE_ACTIVE_ONLY PURPLE_MESSAGE_ACTIVE_ONLY -#define GAIM_MESSAGE_NICK PURPLE_MESSAGE_NICK -#define GAIM_MESSAGE_NO_LOG PURPLE_MESSAGE_NO_LOG -#define GAIM_MESSAGE_WHISPER PURPLE_MESSAGE_WHISPER -#define GAIM_MESSAGE_ERROR PURPLE_MESSAGE_ERROR -#define GAIM_MESSAGE_DELAYED PURPLE_MESSAGE_DELAYED -#define GAIM_MESSAGE_RAW PURPLE_MESSAGE_RAW -#define GAIM_MESSAGE_IMAGES PURPLE_MESSAGE_IMAGES - -#define GaimMessageFlags PurpleMessageFlags - -#define GAIM_CBFLAGS_NONE PURPLE_CBFLAGS_NONE -#define GAIM_CBFLAGS_VOICE PURPLE_CBFLAGS_VOICE -#define GAIM_CBFLAGS_HALFOP PURPLE_CBFLAGS_HALFOP -#define GAIM_CBFLAGS_OP PURPLE_CBFLAGS_OP -#define GAIM_CBFLAGS_FOUNDER PURPLE_CBFLAGS_FOUNDER -#define GAIM_CBFLAGS_TYPING PURPLE_CBFLAGS_TYPING - -#define GaimConvChatBuddyFlags PurpleConvChatBuddyFlags - -#define gaim_conversations_set_ui_ops purple_conversations_set_ui_ops - -#define gaim_conversation_new purple_conversation_new -#define gaim_conversation_destroy purple_conversation_destroy -#define gaim_conversation_present purple_conversation_present -#define gaim_conversation_get_type purple_conversation_get_type -#define gaim_conversation_set_ui_ops purple_conversation_set_ui_ops -#define gaim_conversation_get_ui_ops purple_conversation_get_ui_ops -#define gaim_conversation_set_account purple_conversation_set_account -#define gaim_conversation_get_account purple_conversation_get_account -#define gaim_conversation_get_gc purple_conversation_get_gc -#define gaim_conversation_set_title purple_conversation_set_title -#define gaim_conversation_get_title purple_conversation_get_title -#define gaim_conversation_autoset_title purple_conversation_autoset_title -#define gaim_conversation_set_name purple_conversation_set_name -#define gaim_conversation_get_name purple_conversation_get_name -#define gaim_conversation_set_logging purple_conversation_set_logging -#define gaim_conversation_is_logging purple_conversation_is_logging -#define gaim_conversation_close_logs purple_conversation_close_logs -#define gaim_conversation_get_im_data purple_conversation_get_im_data - -#define GAIM_CONV_IM PURPLE_CONV_IM - -#define gaim_conversation_get_chat_data purple_conversation_get_chat_data - -#define GAIM_CONV_CHAT PURPLE_CONV_CHAT - -#define gaim_conversation_set_data purple_conversation_set_data -#define gaim_conversation_get_data purple_conversation_get_data - -#define gaim_get_conversations purple_get_conversations -#define gaim_get_ims purple_get_ims -#define gaim_get_chats purple_get_chats - -#define gaim_find_conversation_with_account \ - purple_find_conversation_with_account - -#define gaim_conversation_write purple_conversation_write -#define gaim_conversation_set_features purple_conversation_set_features -#define gaim_conversation_get_features purple_conversation_get_features -#define gaim_conversation_has_focus purple_conversation_has_focus -#define gaim_conversation_update purple_conversation_update -#define gaim_conversation_foreach purple_conversation_foreach - -#define gaim_conv_im_get_conversation purple_conv_im_get_conversation -#define gaim_conv_im_set_icon purple_conv_im_set_icon -#define gaim_conv_im_get_icon purple_conv_im_get_icon -#define gaim_conv_im_set_typing_state purple_conv_im_set_typing_state -#define gaim_conv_im_get_typing_state purple_conv_im_get_typing_state - -#define gaim_conv_im_start_typing_timeout purple_conv_im_start_typing_timeout -#define gaim_conv_im_stop_typing_timeout purple_conv_im_stop_typing_timeout -#define gaim_conv_im_get_typing_timeout purple_conv_im_get_typing_timeout -#define gaim_conv_im_set_type_again purple_conv_im_set_type_again -#define gaim_conv_im_get_type_again purple_conv_im_get_type_again - -#define gaim_conv_im_start_send_typed_timeout \ - purple_conv_im_start_send_typed_timeout - -#define gaim_conv_im_stop_send_typed_timeout \ - purple_conv_im_stop_send_typed_timeout - -#define gaim_conv_im_get_send_typed_timeout \ - purple_conv_im_get_send_typed_timeout - -#define gaim_conv_present_error purple_conv_present_error -#define gaim_conv_send_confirm purple_conv_send_confirm - -#define gaim_conv_im_update_typing purple_conv_im_update_typing -#define gaim_conv_im_write purple_conv_im_write -#define gaim_conv_im_send purple_conv_im_send -#define gaim_conv_im_send_with_flags purple_conv_im_send_with_flags - -#define gaim_conv_custom_smiley_add purple_conv_custom_smiley_add -#define gaim_conv_custom_smiley_write purple_conv_custom_smiley_write -#define gaim_conv_custom_smiley_close purple_conv_custom_smiley_close - -#define gaim_conv_chat_get_conversation purple_conv_chat_get_conversation -#define gaim_conv_chat_set_users purple_conv_chat_set_users -#define gaim_conv_chat_get_users purple_conv_chat_get_users -#define gaim_conv_chat_ignore purple_conv_chat_ignore -#define gaim_conv_chat_unignore purple_conv_chat_unignore -#define gaim_conv_chat_set_ignored purple_conv_chat_set_ignored -#define gaim_conv_chat_get_ignored purple_conv_chat_get_ignored -#define gaim_conv_chat_get_ignored_user purple_conv_chat_get_ignored_user -#define gaim_conv_chat_is_user_ignored purple_conv_chat_is_user_ignored -#define gaim_conv_chat_set_topic purple_conv_chat_set_topic -#define gaim_conv_chat_get_topic purple_conv_chat_get_topic -#define gaim_conv_chat_set_id purple_conv_chat_set_id -#define gaim_conv_chat_get_id purple_conv_chat_get_id -#define gaim_conv_chat_write purple_conv_chat_write -#define gaim_conv_chat_send purple_conv_chat_send -#define gaim_conv_chat_send_with_flags purple_conv_chat_send_with_flags -#define gaim_conv_chat_add_user purple_conv_chat_add_user -#define gaim_conv_chat_add_users purple_conv_chat_add_users -#define gaim_conv_chat_rename_user purple_conv_chat_rename_user -#define gaim_conv_chat_remove_user purple_conv_chat_remove_user -#define gaim_conv_chat_remove_users purple_conv_chat_remove_users -#define gaim_conv_chat_find_user purple_conv_chat_find_user -#define gaim_conv_chat_user_set_flags purple_conv_chat_user_set_flags -#define gaim_conv_chat_user_get_flags purple_conv_chat_user_get_flags -#define gaim_conv_chat_clear_users purple_conv_chat_clear_users -#define gaim_conv_chat_set_nick purple_conv_chat_set_nick -#define gaim_conv_chat_get_nick purple_conv_chat_get_nick -#define gaim_conv_chat_left purple_conv_chat_left -#define gaim_conv_chat_has_left purple_conv_chat_has_left - -#define gaim_find_chat purple_find_chat - -#define gaim_conv_chat_cb_new purple_conv_chat_cb_new -#define gaim_conv_chat_cb_find purple_conv_chat_cb_find -#define gaim_conv_chat_cb_get_name purple_conv_chat_cb_get_name -#define gaim_conv_chat_cb_destroy purple_conv_chat_cb_destroy - -#define gaim_conversations_get_handle purple_conversations_get_handle -#define gaim_conversations_init purple_conversations_init -#define gaim_conversations_uninit purple_conversations_uninit - -/* from core.h */ - -#define GaimCore PurpleCore - -#define GaimCoreUiOps PurpleCoreUiOps - -#define gaim_core_init purple_core_init -#define gaim_core_quit purple_core_quit - -#define gaim_core_quit_cb purple_core_quit_cb -#define gaim_core_get_version purple_core_get_version -#define gaim_core_get_ui purple_core_get_ui -#define gaim_get_core purple_get_core -#define gaim_core_set_ui_ops purple_core_set_ui_ops -#define gaim_core_get_ui_ops purple_core_get_ui_ops - -/* from debug.h */ - -#define GAIM_DEBUG_ALL PURPLE_DEBUG_ALL -#define GAIM_DEBUG_MISC PURPLE_DEBUG_MISC -#define GAIM_DEBUG_INFO PURPLE_DEBUG_INFO -#define GAIM_DEBUG_WARNING PURPLE_DEBUG_WARNING -#define GAIM_DEBUG_ERROR PURPLE_DEBUG_ERROR -#define GAIM_DEBUG_FATAL PURPLE_DEBUG_FATAL - -#define GaimDebugLevel PurpleDebugLevel - -#define GaimDebugUiOps PurpleDebugUiOps - - -#define gaim_debug purple_debug -#define gaim_debug_misc purple_debug_misc -#define gaim_debug_info purple_debug_info -#define gaim_debug_warning purple_debug_warning -#define gaim_debug_error purple_debug_error -#define gaim_debug_fatal purple_debug_fatal - -#define gaim_debug_set_enabled purple_debug_set_enabled -#define gaim_debug_is_enabled purple_debug_is_enabled - -#define gaim_debug_set_ui_ops purple_debug_set_ui_ops -#define gaim_debug_get_ui_ops purple_debug_get_ui_ops - -#define gaim_debug_init purple_debug_init - -/* from desktopitem.h */ - -#define GAIM_DESKTOP_ITEM_TYPE_NULL PURPLE_DESKTOP_ITEM_TYPE_NULL -#define GAIM_DESKTOP_ITEM_TYPE_OTHER PURPLE_DESKTOP_ITEM_TYPE_OTHER -#define GAIM_DESKTOP_ITEM_TYPE_APPLICATION PURPLE_DESKTOP_ITEM_TYPE_APPLICATION -#define GAIM_DESKTOP_ITEM_TYPE_LINK PURPLE_DESKTOP_ITEM_TYPE_LINK -#define GAIM_DESKTOP_ITEM_TYPE_FSDEVICE PURPLE_DESKTOP_ITEM_TYPE_FSDEVICE -#define GAIM_DESKTOP_ITEM_TYPE_MIME_TYPE PURPLE_DESKTOP_ITEM_TYPE_MIME_TYPE -#define GAIM_DESKTOP_ITEM_TYPE_DIRECTORY PURPLE_DESKTOP_ITEM_TYPE_DIRECTORY -#define GAIM_DESKTOP_ITEM_TYPE_SERVICE PURPLE_DESKTOP_ITEM_TYPE_SERVICE -#define GAIM_DESKTOP_ITEM_TYPE_SERVICE_TYPE PURPLE_DESKTOP_ITEM_TYPE_SERVICE_TYPE - -#define GaimDesktopItemType PurpleDesktopItemType - -#define GaimDesktopItem PurpleDesktopItem - -#define GAIM_TYPE_DESKTOP_ITEM PURPLE_TYPE_DESKTOP_ITEM -#define gaim_desktop_item_get_type purple_desktop_item_get_type - -/* standard */ -/* ugh, i'm just copying these as strings, rather than pidginifying them */ -#define GAIM_DESKTOP_ITEM_ENCODING "Encoding" /* string */ -#define GAIM_DESKTOP_ITEM_VERSION "Version" /* numeric */ -#define GAIM_DESKTOP_ITEM_NAME "Name" /* localestring */ -#define GAIM_DESKTOP_ITEM_GENERIC_NAME "GenericName" /* localestring */ -#define GAIM_DESKTOP_ITEM_TYPE "Type" /* string */ -#define GAIM_DESKTOP_ITEM_FILE_PATTERN "FilePattern" /* regexp(s) */ -#define GAIM_DESKTOP_ITEM_TRY_EXEC "TryExec" /* string */ -#define GAIM_DESKTOP_ITEM_NO_DISPLAY "NoDisplay" /* boolean */ -#define GAIM_DESKTOP_ITEM_COMMENT "Comment" /* localestring */ -#define GAIM_DESKTOP_ITEM_EXEC "Exec" /* string */ -#define GAIM_DESKTOP_ITEM_ACTIONS "Actions" /* strings */ -#define GAIM_DESKTOP_ITEM_ICON "Icon" /* string */ -#define GAIM_DESKTOP_ITEM_MINI_ICON "MiniIcon" /* string */ -#define GAIM_DESKTOP_ITEM_HIDDEN "Hidden" /* boolean */ -#define GAIM_DESKTOP_ITEM_PATH "Path" /* string */ -#define GAIM_DESKTOP_ITEM_TERMINAL "Terminal" /* boolean */ -#define GAIM_DESKTOP_ITEM_TERMINAL_OPTIONS "TerminalOptions" /* string */ -#define GAIM_DESKTOP_ITEM_SWALLOW_TITLE "SwallowTitle" /* string */ -#define GAIM_DESKTOP_ITEM_SWALLOW_EXEC "SwallowExec" /* string */ -#define GAIM_DESKTOP_ITEM_MIME_TYPE "MimeType" /* regexp(s) */ -#define GAIM_DESKTOP_ITEM_PATTERNS "Patterns" /* regexp(s) */ -#define GAIM_DESKTOP_ITEM_DEFAULT_APP "DefaultApp" /* string */ -#define GAIM_DESKTOP_ITEM_DEV "Dev" /* string */ -#define GAIM_DESKTOP_ITEM_FS_TYPE "FSType" /* string */ -#define GAIM_DESKTOP_ITEM_MOUNT_POINT "MountPoint" /* string */ -#define GAIM_DESKTOP_ITEM_READ_ONLY "ReadOnly" /* boolean */ -#define GAIM_DESKTOP_ITEM_UNMOUNT_ICON "UnmountIcon" /* string */ -#define GAIM_DESKTOP_ITEM_SORT_ORDER "SortOrder" /* strings */ -#define GAIM_DESKTOP_ITEM_URL "URL" /* string */ -#define GAIM_DESKTOP_ITEM_DOC_PATH "X-GNOME-DocPath" /* string */ - -#define gaim_desktop_item_new_from_file purple_desktop_item_new_from_file -#define gaim_desktop_item_get_entry_type purple_desktop_item_get_entry_type -#define gaim_desktop_item_get_string purple_desktop_item_get_string -#define gaim_desktop_item_copy purple_desktop_item_copy -#define gaim_desktop_item_unref purple_desktop_item_unref - -/* from dnsquery.h */ - -#define GaimDnsQueryData PurpleDnsQueryData -#define GaimDnsQueryConnectFunction PurpleDnsQueryConnectFunction - -#define gaim_dnsquery_a purple_dnsquery_a -#define gaim_dnsquery_destroy purple_dnsquery_destroy -#define gaim_dnsquery_init purple_dnsquery_init -#define gaim_dnsquery_uninit purple_dnsquery_uninit -#define gaim_dnsquery_set_ui_ops purple_dnsquery_set_ui_ops -#define gaim_dnsquery_get_host purple_dnsquery_get_host -#define gaim_dnsquery_get_port purple_dnsquery_get_port - -/* from dnssrv.h */ - -#define GaimSrvResponse PurpleSrvResponse -#define GaimSrvQueryData PurpleSrvTxtQueryData -#define GaimSrvCallback PurpleSrvCallback - -#define gaim_srv_resolve purple_srv_resolve -#define gaim_srv_cancel purple_srv_cancel - -/* from eventloop.h */ - -#define GAIM_INPUT_READ PURPLE_INPUT_READ -#define GAIM_INPUT_WRITE PURPLE_INPUT_WRITE - -#define GaimInputCondition PurpleInputCondition -#define GaimInputFunction PurpleInputFunction -#define GaimEventLoopUiOps PurpleEventLoopUiOps - -#define gaim_timeout_add purple_timeout_add -#define gaim_timeout_remove purple_timeout_remove -#define gaim_input_add purple_input_add -#define gaim_input_remove purple_input_remove - -#define gaim_eventloop_set_ui_ops purple_eventloop_set_ui_ops -#define gaim_eventloop_get_ui_ops purple_eventloop_get_ui_ops - -/* from ft.h */ - -#define GaimXfer PurpleXfer - -#define GAIM_XFER_UNKNOWN PURPLE_XFER_UNKNOWN -#define GAIM_XFER_SEND PURPLE_XFER_SEND -#define GAIM_XFER_RECEIVE PURPLE_XFER_RECEIVE - -#define GaimXferType PurpleXferType - -#define GAIM_XFER_STATUS_UNKNOWN PURPLE_XFER_STATUS_UNKNOWN -#define GAIM_XFER_STATUS_NOT_STARTED PURPLE_XFER_STATUS_NOT_STARTED -#define GAIM_XFER_STATUS_ACCEPTED PURPLE_XFER_STATUS_ACCEPTED -#define GAIM_XFER_STATUS_STARTED PURPLE_XFER_STATUS_STARTED -#define GAIM_XFER_STATUS_DONE PURPLE_XFER_STATUS_DONE -#define GAIM_XFER_STATUS_CANCEL_LOCAL PURPLE_XFER_STATUS_CANCEL_LOCAL -#define GAIM_XFER_STATUS_CANCEL_REMOTE PURPLE_XFER_STATUS_CANCEL_REMOTE - -#define GaimXferStatusType PurpleXferStatusType - -#define GaimXferUiOps PurpleXferUiOps - -#define gaim_xfer_new purple_xfer_new -#define gaim_xfer_ref purple_xfer_ref -#define gaim_xfer_unref purple_xfer_unref -#define gaim_xfer_request purple_xfer_request -#define gaim_xfer_request_accepted purple_xfer_request_accepted -#define gaim_xfer_request_denied purple_xfer_request_denied -#define gaim_xfer_get_type purple_xfer_get_type -#define gaim_xfer_get_account purple_xfer_get_account -#define gaim_xfer_get_status purple_xfer_get_status -#define gaim_xfer_is_canceled purple_xfer_is_canceled -#define gaim_xfer_is_completed purple_xfer_is_completed -#define gaim_xfer_get_filename purple_xfer_get_filename -#define gaim_xfer_get_local_filename purple_xfer_get_local_filename -#define gaim_xfer_get_bytes_sent purple_xfer_get_bytes_sent -#define gaim_xfer_get_bytes_remaining purple_xfer_get_bytes_remaining -#define gaim_xfer_get_size purple_xfer_get_size -#define gaim_xfer_get_progress purple_xfer_get_progress -#define gaim_xfer_get_local_port purple_xfer_get_local_port -#define gaim_xfer_get_remote_ip purple_xfer_get_remote_ip -#define gaim_xfer_get_remote_port purple_xfer_get_remote_port -#define gaim_xfer_set_completed purple_xfer_set_completed -#define gaim_xfer_set_message purple_xfer_set_message -#define gaim_xfer_set_filename purple_xfer_set_filename -#define gaim_xfer_set_local_filename purple_xfer_set_local_filename -#define gaim_xfer_set_size purple_xfer_set_size -#define gaim_xfer_set_bytes_sent purple_xfer_set_bytes_sent -#define gaim_xfer_get_ui_ops purple_xfer_get_ui_ops -#define gaim_xfer_set_read_fnc purple_xfer_set_read_fnc -#define gaim_xfer_set_write_fnc purple_xfer_set_write_fnc -#define gaim_xfer_set_ack_fnc purple_xfer_set_ack_fnc -#define gaim_xfer_set_request_denied_fnc purple_xfer_set_request_denied_fnc -#define gaim_xfer_set_init_fnc purple_xfer_set_init_fnc -#define gaim_xfer_set_start_fnc purple_xfer_set_start_fnc -#define gaim_xfer_set_end_fnc purple_xfer_set_end_fnc -#define gaim_xfer_set_cancel_send_fnc purple_xfer_set_cancel_send_fnc -#define gaim_xfer_set_cancel_recv_fnc purple_xfer_set_cancel_recv_fnc - -#define gaim_xfer_read purple_xfer_read -#define gaim_xfer_write purple_xfer_write -#define gaim_xfer_start purple_xfer_start -#define gaim_xfer_end purple_xfer_end -#define gaim_xfer_add purple_xfer_add -#define gaim_xfer_cancel_local purple_xfer_cancel_local -#define gaim_xfer_cancel_remote purple_xfer_cancel_remote -#define gaim_xfer_error purple_xfer_error -#define gaim_xfer_update_progress purple_xfer_update_progress -#define gaim_xfer_conversation_write purple_xfer_conversation_write - -#define gaim_xfers_get_handle purple_xfers_get_handle -#define gaim_xfers_init purple_xfers_init -#define gaim_xfers_uninit purple_xfers_uninit -#define gaim_xfers_set_ui_ops purple_xfers_set_ui_ops -#define gaim_xfers_get_ui_ops purple_xfers_get_ui_ops - -/* from gaim-client.h */ - -#define gaim_init purple_init - -/* from idle.h */ - -#define GaimIdleUiOps PurpleIdleUiOps - -#define gaim_idle_touch purple_idle_touch -#define gaim_idle_set purple_idle_set -#define gaim_idle_set_ui_ops purple_idle_set_ui_ops -#define gaim_idle_get_ui_ops purple_idle_get_ui_ops -#define gaim_idle_init purple_idle_init -#define gaim_idle_uninit purple_idle_uninit - -/* from imgstore.h */ - -#define GaimStoredImage PurpleStoredImage - -#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_by_id -#define gaim_imgstore_unref purple_imgstore_unref_by_id - - -/* from log.h */ - -#define GaimLog PurpleLog -#define GaimLogLogger PurpleLogLogger -#define GaimLogCommonLoggerData PurpleLogCommonLoggerData -#define GaimLogSet PurpleLogSet - -#define GAIM_LOG_IM PURPLE_LOG_IM -#define GAIM_LOG_CHAT PURPLE_LOG_CHAT -#define GAIM_LOG_SYSTEM PURPLE_LOG_SYSTEM - -#define GaimLogType PurpleLogType - -#define GAIM_LOG_READ_NO_NEWLINE PURPLE_LOG_READ_NO_NEWLINE - -#define GaimLogReadFlags PurpleLogReadFlags - -#define GaimLogSetCallback PurpleLogSetCallback - -#define gaim_log_new purple_log_new -#define gaim_log_free purple_log_free -#define gaim_log_write purple_log_write -#define gaim_log_read purple_log_read - -#define gaim_log_get_logs purple_log_get_logs -#define gaim_log_get_log_sets purple_log_get_log_sets -#define gaim_log_get_system_logs purple_log_get_system_logs -#define gaim_log_get_size purple_log_get_size -#define gaim_log_get_total_size purple_log_get_total_size -#define gaim_log_get_log_dir purple_log_get_log_dir -#define gaim_log_compare purple_log_compare -#define gaim_log_set_compare purple_log_set_compare -#define gaim_log_set_free purple_log_set_free - -#define gaim_log_common_writer purple_log_common_writer -#define gaim_log_common_lister purple_log_common_lister -#define gaim_log_common_total_sizer purple_log_common_total_sizer -#define gaim_log_common_sizer purple_log_common_sizer - -#define gaim_log_logger_new purple_log_logger_new -#define gaim_log_logger_free purple_log_logger_free -#define gaim_log_logger_add purple_log_logger_add -#define gaim_log_logger_remove purple_log_logger_remove -#define gaim_log_logger_set purple_log_logger_set -#define gaim_log_logger_get purple_log_logger_get - -#define gaim_log_logger_get_options purple_log_logger_get_options - -#define gaim_log_init purple_log_init -#define gaim_log_get_handle purple_log_get_handle -#define gaim_log_uninit purple_log_uninit - -/* from mime.h */ - -#define GaimMimeDocument PurpleMimeDocument -#define GaimMimePart PurpleMimePart - -#define gaim_mime_document_new purple_mime_document_new -#define gaim_mime_document_free purple_mime_document_free -#define gaim_mime_document_parse purple_mime_document_parse -#define gaim_mime_document_parsen purple_mime_document_parsen -#define gaim_mime_document_write purple_mime_document_write -#define gaim_mime_document_get_fields purple_mime_document_get_fields -#define gaim_mime_document_get_field purple_mime_document_get_field -#define gaim_mime_document_set_field purple_mime_document_set_field -#define gaim_mime_document_get_parts purple_mime_document_get_parts - -#define gaim_mime_part_new purple_mime_part_new -#define gaim_mime_part_get_fields purple_mime_part_get_fields -#define gaim_mime_part_get_field purple_mime_part_get_field -#define gaim_mime_part_get_field_decoded purple_mime_part_get_field_decoded -#define gaim_mime_part_set_field purple_mime_part_set_field -#define gaim_mime_part_get_data purple_mime_part_get_data -#define gaim_mime_part_get_data_decoded purple_mime_part_get_data_decoded -#define gaim_mime_part_get_length purple_mime_part_get_length -#define gaim_mime_part_set_data purple_mime_part_set_data - - -/* from network.h */ - -#define GaimNetworkListenData PurpleNetworkListenData - -#define GaimNetworkListenCallback PurpleNetworkListenCallback - -#define gaim_network_ip_atoi purple_network_ip_atoi -#define gaim_network_set_public_ip purple_network_set_public_ip -#define gaim_network_get_public_ip purple_network_get_public_ip -#define gaim_network_get_local_system_ip purple_network_get_local_system_ip -#define gaim_network_get_my_ip purple_network_get_my_ip - -#define gaim_network_listen purple_network_listen -#define gaim_network_listen_range purple_network_listen_range -#define gaim_network_listen_cancel purple_network_listen_cancel -#define gaim_network_get_port_from_fd purple_network_get_port_from_fd - -#define gaim_network_is_available purple_network_is_available - -#define gaim_network_init purple_network_init -#define gaim_network_uninit purple_network_uninit - -/* from notify.h */ - - -#define GaimNotifyUserInfoEntry PurpleNotifyUserInfoEntry -#define GaimNotifyUserInfo PurpleNotifyUserInfo - -#define GaimNotifyCloseCallback PurpleNotifyCloseCallback - -#define GAIM_NOTIFY_MESSAGE PURPLE_NOTIFY_MESSAGE -#define GAIM_NOTIFY_EMAIL PURPLE_NOTIFY_EMAIL -#define GAIM_NOTIFY_EMAILS PURPLE_NOTIFY_EMAILS -#define GAIM_NOTIFY_FORMATTED PURPLE_NOTIFY_FORMATTED -#define GAIM_NOTIFY_SEARCHRESULTS PURPLE_NOTIFY_SEARCHRESULTS -#define GAIM_NOTIFY_USERINFO PURPLE_NOTIFY_USERINFO -#define GAIM_NOTIFY_URI PURPLE_NOTIFY_URI - -#define GaimNotifyType PurpleNotifyType - -#define GAIM_NOTIFY_MSG_ERROR PURPLE_NOTIFY_MSG_ERROR -#define GAIM_NOTIFY_MSG_WARNING PURPLE_NOTIFY_MSG_WARNING -#define GAIM_NOTIFY_MSG_INFO PURPLE_NOTIFY_MSG_INFO - -#define GaimNotifyMsgType PurpleNotifyMsgType - -#define GAIM_NOTIFY_BUTTON_LABELED PURPLE_NOTIFY_BUTTON_LABELED -#define GAIM_NOTIFY_BUTTON_CONTINUE PURPLE_NOTIFY_BUTTON_CONTINUE -#define GAIM_NOTIFY_BUTTON_ADD PURPLE_NOTIFY_BUTTON_ADD -#define GAIM_NOTIFY_BUTTON_INFO PURPLE_NOTIFY_BUTTON_INFO -#define GAIM_NOTIFY_BUTTON_IM PURPLE_NOTIFY_BUTTON_IM -#define GAIM_NOTIFY_BUTTON_JOIN PURPLE_NOTIFY_BUTTON_JOIN -#define GAIM_NOTIFY_BUTTON_INVITE PURPLE_NOTIFY_BUTTON_INVITE - -#define GaimNotifySearchButtonType PurpleNotifySearchButtonType - -#define GaimNotifySearchResults PurpleNotifySearchResults - -#define GAIM_NOTIFY_USER_INFO_ENTRY_PAIR PURPLE_NOTIFY_USER_INFO_ENTRY_PAIR -#define GAIM_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK -#define GAIM_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER - -#define GaimNotifyUserInfoEntryType PurpleNotifyUserInfoEntryType - -#define GaimNotifySearchColumn PurpleNotifySearchColumn -#define GaimNotifySearchResultsCallback PurpleNotifySearchResultsCallback -#define GaimNotifySearchButton PurpleNotifySearchButton - -#define GaimNotifyUiOps PurpleNotifyUiOps - -#define gaim_notify_searchresults purple_notify_searchresults -#define gaim_notify_searchresults_free purple_notify_searchresults_free -#define gaim_notify_searchresults_new_rows purple_notify_searchresults_new_rows -#define gaim_notify_searchresults_button_add purple_notify_searchresults_button_add -#define gaim_notify_searchresults_button_add_labeled purple_notify_searchresults_button_add_labeled -#define gaim_notify_searchresults_new purple_notify_searchresults_new -#define gaim_notify_searchresults_column_new purple_notify_searchresults_column_new -#define gaim_notify_searchresults_column_add purple_notify_searchresults_column_add -#define gaim_notify_searchresults_row_add purple_notify_searchresults_row_add -#define gaim_notify_searchresults_get_rows_count purple_notify_searchresults_get_rows_count -#define gaim_notify_searchresults_get_columns_count purple_notify_searchresults_get_columns_count -#define gaim_notify_searchresults_row_get purple_notify_searchresults_row_get -#define gaim_notify_searchresults_column_get_title purple_notify_searchresults_column_get_title - -#define gaim_notify_message purple_notify_message -#define gaim_notify_email purple_notify_email -#define gaim_notify_emails purple_notify_emails -#define gaim_notify_formatted purple_notify_formatted -#define gaim_notify_userinfo purple_notify_userinfo - -#define gaim_notify_user_info_new purple_notify_user_info_new -#define gaim_notify_user_info_destroy purple_notify_user_info_destroy -#define gaim_notify_user_info_get_entries purple_notify_user_info_get_entries -#define gaim_notify_user_info_get_text_with_newline purple_notify_user_info_get_text_with_newline -#define gaim_notify_user_info_add_pair purple_notify_user_info_add_pair -#define gaim_notify_user_info_prepend_pair purple_notify_user_info_prepend_pair -#define gaim_notify_user_info_remove_entry purple_notify_user_info_remove_entry -#define gaim_notify_user_info_entry_new purple_notify_user_info_entry_new -#define gaim_notify_user_info_add_section_break purple_notify_user_info_add_section_break -#define gaim_notify_user_info_add_section_header purple_notify_user_info_add_section_header -#define gaim_notify_user_info_remove_last_item purple_notify_user_info_remove_last_item -#define gaim_notify_user_info_entry_get_label purple_notify_user_info_entry_get_label -#define gaim_notify_user_info_entry_set_label purple_notify_user_info_entry_set_label -#define gaim_notify_user_info_entry_get_value purple_notify_user_info_entry_get_value -#define gaim_notify_user_info_entry_set_value purple_notify_user_info_entry_set_value -#define gaim_notify_user_info_entry_get_type purple_notify_user_info_entry_get_type -#define gaim_notify_user_info_entry_set_type purple_notify_user_info_entry_set_type - -#define gaim_notify_uri purple_notify_uri -#define gaim_notify_close purple_notify_close -#define gaim_notify_close_with_handle purple_notify_close_with_handle - -#define gaim_notify_info purple_notify_info -#define gaim_notify_warning purple_notify_warning -#define gaim_notify_error purple_notify_error - -#define gaim_notify_set_ui_ops purple_notify_set_ui_ops -#define gaim_notify_get_ui_ops purple_notify_get_ui_ops - -#define gaim_notify_get_handle purple_notify_get_handle - -#define gaim_notify_init purple_notify_init -#define gaim_notify_uninit purple_notify_uninit - -/* from ntlm.h */ - -#define gaim_ntlm_gen_type1 purple_ntlm_gen_type1 -#define gaim_ntlm_parse_type2 purple_ntlm_parse_type2 -#define gaim_ntlm_gen_type3 purple_ntlm_gen_type3 - -/* from plugin.h */ - -#ifdef GAIM_PLUGINS -#ifndef PURPLE_PLUGINS -#define PURPLE_PLUGINS -#endif -#endif - -#define GaimPlugin PurplePlugin -#define GaimPluginInfo PurplePluginInfo -#define GaimPluginUiInfo PurplePluginUiInfo -#define GaimPluginLoaderInfo PurplePluginLoaderInfo -#define GaimPluginAction PurplePluginAction -#define GaimPluginPriority PurplePluginPriority - -#define GAIM_PLUGIN_UNKNOWN PURPLE_PLUGIN_UNKNOWN -#define GAIM_PLUGIN_STANDARD PURPLE_PLUGIN_STANDARD -#define GAIM_PLUGIN_LOADER PURPLE_PLUGIN_LOADER -#define GAIM_PLUGIN_PROTOCOL PURPLE_PLUGIN_PROTOCOL - -#define GaimPluginType PurplePluginType - -#define GAIM_PRIORITY_DEFAULT PURPLE_PRIORITY_DEFAULT -#define GAIM_PRIORITY_HIGHEST PURPLE_PRIORITY_HIGHEST -#define GAIM_PRIORITY_LOWEST PURPLE_PRIORITY_LOWEST - -#define GAIM_PLUGIN_FLAG_INVISIBLE PURPLE_PLUGIN_FLAG_INVISIBLE - -#define GAIM_PLUGIN_MAGIC PURPLE_PLUGIN_MAGIC - -#define GAIM_PLUGIN_LOADER_INFO PURPLE_PLUGIN_LOADER_INFO -#define GAIM_PLUGIN_HAS_PREF_FRAME PURPLE_PLUGIN_HAS_PREF_FRAME -#define GAIM_PLUGIN_UI_INFO PURPLE_PLUGIN_UI_INFO - -#define GAIM_PLUGIN_HAS_ACTIONS PURPLE_PLUGIN_HAS_ACTIONS -#define GAIM_PLUGIN_ACTIONS PURPLE_PLUGIN_ACTIONS - -#define GAIM_INIT_PLUGIN PURPLE_INIT_PLUGIN - -#define gaim_plugin_new purple_plugin_new -#define gaim_plugin_probe purple_plugin_probe -#define gaim_plugin_register purple_plugin_register -#define gaim_plugin_load purple_plugin_load -#define gaim_plugin_unload purple_plugin_unload -#define gaim_plugin_reload purple_plugin_reload -#define gaim_plugin_destroy purple_plugin_destroy -#define gaim_plugin_is_loaded purple_plugin_is_loaded -#define gaim_plugin_is_unloadable purple_plugin_is_unloadable -#define gaim_plugin_get_id purple_plugin_get_id -#define gaim_plugin_get_name purple_plugin_get_name -#define gaim_plugin_get_version purple_plugin_get_version -#define gaim_plugin_get_summary purple_plugin_get_summary -#define gaim_plugin_get_description purple_plugin_get_description -#define gaim_plugin_get_author purple_plugin_get_author -#define gaim_plugin_get_homepage purple_plugin_get_homepage - -#define gaim_plugin_ipc_register purple_plugin_ipc_register -#define gaim_plugin_ipc_unregister purple_plugin_ipc_unregister -#define gaim_plugin_ipc_unregister_all purple_plugin_ipc_unregister_all -#define gaim_plugin_ipc_get_params purple_plugin_ipc_get_params -#define gaim_plugin_ipc_call purple_plugin_ipc_call - -#define gaim_plugins_add_search_path purple_plugins_add_search_path -#define gaim_plugins_unload_all purple_plugins_unload_all -#define gaim_plugins_destroy_all purple_plugins_destroy_all -#define gaim_plugins_save_loaded purple_plugins_save_loaded -#define gaim_plugins_load_saved purple_plugins_load_saved -#define gaim_plugins_probe purple_plugins_probe -#define gaim_plugins_enabled purple_plugins_enabled - -#define gaim_plugins_register_probe_notify_cb purple_plugins_register_probe_notify_cb -#define gaim_plugins_unregister_probe_notify_cb purple_plugins_unregister_probe_notify_cb -#define gaim_plugins_register_load_notify_cb purple_plugins_register_load_notify_cb -#define gaim_plugins_unregister_load_notify_cb purple_plugins_unregister_load_notify_cb -#define gaim_plugins_register_unload_notify_cb purple_plugins_register_unload_notify_cb -#define gaim_plugins_unregister_unload_notify_cb purple_plugins_unregister_unload_notify_cb - -#define gaim_plugins_find_with_name purple_plugins_find_with_name -#define gaim_plugins_find_with_filename purple_plugins_find_with_filename -#define gaim_plugins_find_with_basename purple_plugins_find_with_basename -#define gaim_plugins_find_with_id purple_plugins_find_with_id - -#define gaim_plugins_get_loaded purple_plugins_get_loaded -#define gaim_plugins_get_protocols purple_plugins_get_protocols -#define gaim_plugins_get_all purple_plugins_get_all - -#define gaim_plugins_get_handle purple_plugins_get_handle -#define gaim_plugins_init purple_plugins_init -#define gaim_plugins_uninit purple_plugins_uninit - -#define gaim_plugin_action_new purple_plugin_action_new -#define gaim_plugin_action_free purple_plugin_action_free - -/* pluginpref.h */ - -#define GaimPluginPrefFrame PurplePluginPrefFrame -#define GaimPluginPref PurplePluginPref - -#define GAIM_STRING_FORMAT_TYPE_NONE PURPLE_STRING_FORMAT_TYPE_NONE -#define GAIM_STRING_FORMAT_TYPE_MULTILINE PURPLE_STRING_FORMAT_TYPE_MULTILINE -#define GAIM_STRING_FORMAT_TYPE_HTML PURPLE_STRING_FORMAT_TYPE_HTML - -#define GaimStringFormatType PurpleStringFormatType - -#define GAIM_PLUGIN_PREF_NONE PURPLE_PLUGIN_PREF_NONE -#define GAIM_PLUGIN_PREF_CHOICE PURPLE_PLUGIN_PREF_CHOICE -#define GAIM_PLUGIN_PREF_INFO PURPLE_PLUGIN_PREF_INFO -#define GAIM_PLUGIN_PREF_STRING_FORMAT PURPLE_PLUGIN_PREF_STRING_FORMAT - -#define GaimPluginPrefType PurplePluginPrefType - -#define gaim_plugin_pref_frame_new purple_plugin_pref_frame_new -#define gaim_plugin_pref_frame_destroy purple_plugin_pref_frame_destroy -#define gaim_plugin_pref_frame_add purple_plugin_pref_frame_add -#define gaim_plugin_pref_frame_get_prefs purple_plugin_pref_frame_get_prefs - -#define gaim_plugin_pref_new purple_plugin_pref_new -#define gaim_plugin_pref_new_with_name purple_plugin_pref_new_with_name -#define gaim_plugin_pref_new_with_label purple_plugin_pref_new_with_label -#define gaim_plugin_pref_new_with_name_and_label purple_plugin_pref_new_with_name_and_label -#define gaim_plugin_pref_destroy purple_plugin_pref_destroy -#define gaim_plugin_pref_set_name purple_plugin_pref_set_name -#define gaim_plugin_pref_get_name purple_plugin_pref_get_name -#define gaim_plugin_pref_set_label purple_plugin_pref_set_label -#define gaim_plugin_pref_get_label purple_plugin_pref_get_label -#define gaim_plugin_pref_set_bounds purple_plugin_pref_set_bounds -#define gaim_plugin_pref_get_bounds purple_plugin_pref_get_bounds -#define gaim_plugin_pref_set_type purple_plugin_pref_set_type -#define gaim_plugin_pref_get_type purple_plugin_pref_get_type -#define gaim_plugin_pref_add_choice purple_plugin_pref_add_choice -#define gaim_plugin_pref_get_choices purple_plugin_pref_get_choices -#define gaim_plugin_pref_set_max_length purple_plugin_pref_set_max_length -#define gaim_plugin_pref_get_max_length purple_plugin_pref_get_max_length -#define gaim_plugin_pref_set_masked purple_plugin_pref_set_masked -#define gaim_plugin_pref_get_masked purple_plugin_pref_get_masked -#define gaim_plugin_pref_set_format_type purple_plugin_pref_set_format_type -#define gaim_plugin_pref_get_format_type purple_plugin_pref_get_format_type - -/* from pounce.h */ - -#define GaimPounce PurplePounce - -#define GAIM_POUNCE_NONE PURPLE_POUNCE_NONE -#define GAIM_POUNCE_SIGNON PURPLE_POUNCE_SIGNON -#define GAIM_POUNCE_SIGNOFF PURPLE_POUNCE_SIGNOFF -#define GAIM_POUNCE_AWAY PURPLE_POUNCE_AWAY -#define GAIM_POUNCE_AWAY_RETURN PURPLE_POUNCE_AWAY_RETURN -#define GAIM_POUNCE_IDLE PURPLE_POUNCE_IDLE -#define GAIM_POUNCE_IDLE_RETURN PURPLE_POUNCE_IDLE_RETURN -#define GAIM_POUNCE_TYPING PURPLE_POUNCE_TYPING -#define GAIM_POUNCE_TYPED PURPLE_POUNCE_TYPED -#define GAIM_POUNCE_TYPING_STOPPED PURPLE_POUNCE_TYPING_STOPPED -#define GAIM_POUNCE_MESSAGE_RECEIVED PURPLE_POUNCE_MESSAGE_RECEIVED -#define GaimPounceEvent PurplePounceEvent - -#define GAIM_POUNCE_OPTION_NONE PURPLE_POUNCE_OPTION_NONE -#define GAIM_POUNCE_OPTION_AWAY PURPLE_POUNCE_OPTION_AWAY -#define GaimPounceOption PurplePounceOption - -#define GaimPounceCb PurplePounceCb - -#define gaim_pounce_new purple_pounce_new -#define gaim_pounce_destroy purple_pounce_destroy -#define gaim_pounce_destroy_all_by_account purple_pounce_destroy_all_by_account -#define gaim_pounce_set_events purple_pounce_set_events -#define gaim_pounce_set_options purple_pounce_set_options -#define gaim_pounce_set_pouncer purple_pounce_set_pouncer -#define gaim_pounce_set_pouncee purple_pounce_set_pouncee -#define gaim_pounce_set_save purple_pounce_set_save -#define gaim_pounce_action_register purple_pounce_action_register -#define gaim_pounce_action_set_enabled purple_pounce_action_set_enabled -#define gaim_pounce_action_set_attribute purple_pounce_action_set_attribute -#define gaim_pounce_set_data purple_pounce_set_data -#define gaim_pounce_get_events purple_pounce_get_events -#define gaim_pounce_get_options purple_pounce_get_options -#define gaim_pounce_get_pouncer purple_pounce_get_pouncer -#define gaim_pounce_get_pouncee purple_pounce_get_pouncee -#define gaim_pounce_get_save purple_pounce_get_save -#define gaim_pounce_action_is_enabled purple_pounce_action_is_enabled -#define gaim_pounce_action_get_attribute purple_pounce_action_get_attribute -#define gaim_pounce_get_data purple_pounce_get_data -#define gaim_pounce_execute purple_pounce_execute - -#define gaim_find_pounce purple_find_pounce -#define gaim_pounces_load purple_pounces_load -#define gaim_pounces_register_handler purple_pounces_register_handler -#define gaim_pounces_unregister_handler purple_pounces_unregister_handler -#define gaim_pounces_get_all purple_pounces_get_all -#define gaim_pounces_get_handle purple_pounces_get_handle -#define gaim_pounces_init purple_pounces_init -#define gaim_pounces_uninit purple_pounces_uninit - -/* from prefs.h */ - - -#define GAIM_PREF_NONE PURPLE_PREF_NONE -#define GAIM_PREF_BOOLEAN PURPLE_PREF_BOOLEAN -#define GAIM_PREF_INT PURPLE_PREF_INT -#define GAIM_PREF_STRING PURPLE_PREF_STRING -#define GAIM_PREF_STRING_LIST PURPLE_PREF_STRING_LIST -#define GAIM_PREF_PATH PURPLE_PREF_PATH -#define GAIM_PREF_PATH_LIST PURPLE_PREF_PATH_LIST -#define GaimPrefType PurplePrefType - -#define GaimPrefCallback PurplePrefCallback - -#define gaim_prefs_get_handle purple_prefs_get_handle -#define gaim_prefs_init purple_prefs_init -#define gaim_prefs_uninit purple_prefs_uninit -#define gaim_prefs_add_none purple_prefs_add_none -#define gaim_prefs_add_bool purple_prefs_add_bool -#define gaim_prefs_add_int purple_prefs_add_int -#define gaim_prefs_add_string purple_prefs_add_string -#define gaim_prefs_add_string_list purple_prefs_add_string_list -#define gaim_prefs_add_path purple_prefs_add_path -#define gaim_prefs_add_path_list purple_prefs_add_path_list -#define gaim_prefs_remove purple_prefs_remove -#define gaim_prefs_rename purple_prefs_rename -#define gaim_prefs_rename_boolean_toggle purple_prefs_rename_boolean_toggle -#define gaim_prefs_destroy purple_prefs_destroy -#define gaim_prefs_set_generic purple_prefs_set_generic -#define gaim_prefs_set_bool purple_prefs_set_bool -#define gaim_prefs_set_int purple_prefs_set_int -#define gaim_prefs_set_string purple_prefs_set_string -#define gaim_prefs_set_string_list purple_prefs_set_string_list -#define gaim_prefs_set_path purple_prefs_set_path -#define gaim_prefs_set_path_list purple_prefs_set_path_list -#define gaim_prefs_exists purple_prefs_exists -#define gaim_prefs_get_type purple_prefs_get_type -#define gaim_prefs_get_bool purple_prefs_get_bool -#define gaim_prefs_get_int purple_prefs_get_int -#define gaim_prefs_get_string purple_prefs_get_string -#define gaim_prefs_get_string_list purple_prefs_get_string_list -#define gaim_prefs_get_path purple_prefs_get_path -#define gaim_prefs_get_path_list purple_prefs_get_path_list -#define gaim_prefs_connect_callback purple_prefs_connect_callback -#define gaim_prefs_disconnect_callback purple_prefs_disconnect_callback -#define gaim_prefs_disconnect_by_handle purple_prefs_disconnect_by_handle -#define gaim_prefs_trigger_callback purple_prefs_trigger_callback -#define gaim_prefs_load purple_prefs_load -#define gaim_prefs_update_old purple_prefs_update_old - -/* from privacy.h */ - -#define GAIM_PRIVACY_ALLOW_ALL PURPLE_PRIVACY_ALLOW_ALL -#define GAIM_PRIVACY_DENY_ALL PURPLE_PRIVACY_DENY_ALL -#define GAIM_PRIVACY_ALLOW_USERS PURPLE_PRIVACY_ALLOW_USERS -#define GAIM_PRIVACY_DENY_USERS PURPLE_PRIVACY_DENY_USERS -#define GAIM_PRIVACY_ALLOW_BUDDYLIST PURPLE_PRIVACY_ALLOW_BUDDYLIST -#define GaimPrivacyType PurplePrivacyType - -#define GaimPrivacyUiOps PurplePrivacyUiOps - -#define gaim_privacy_permit_add purple_privacy_permit_add -#define gaim_privacy_permit_remove purple_privacy_permit_remove -#define gaim_privacy_deny_add purple_privacy_deny_add -#define gaim_privacy_deny_remove purple_privacy_deny_remove -#define gaim_privacy_allow purple_privacy_allow -#define gaim_privacy_deny purple_privacy_deny -#define gaim_privacy_check purple_privacy_check -#define gaim_privacy_set_ui_ops purple_privacy_set_ui_ops -#define gaim_privacy_get_ui_ops purple_privacy_get_ui_ops -#define gaim_privacy_init purple_privacy_init - -/* from proxy.h */ - -#define GAIM_PROXY_USE_GLOBAL PURPLE_PROXY_USE_GLOBAL -#define GAIM_PROXY_NONE PURPLE_PROXY_NONE -#define GAIM_PROXY_HTTP PURPLE_PROXY_HTTP -#define GAIM_PROXY_SOCKS4 PURPLE_PROXY_SOCKS4 -#define GAIM_PROXY_SOCKS5 PURPLE_PROXY_SOCKS5 -#define GAIM_PROXY_USE_ENVVAR PURPLE_PROXY_USE_ENVVAR -#define GaimProxyType PurpleProxyType - -#define GaimProxyInfo PurpleProxyInfo - -#define GaimProxyConnectData PurpleProxyConnectData -#define GaimProxyConnectFunction PurpleProxyConnectFunction - -#define gaim_proxy_info_new purple_proxy_info_new -#define gaim_proxy_info_destroy purple_proxy_info_destroy -#define gaim_proxy_info_set_type purple_proxy_info_set_type -#define gaim_proxy_info_set_host purple_proxy_info_set_host -#define gaim_proxy_info_set_port purple_proxy_info_set_port -#define gaim_proxy_info_set_username purple_proxy_info_set_username -#define gaim_proxy_info_set_password purple_proxy_info_set_password -#define gaim_proxy_info_get_type purple_proxy_info_get_type -#define gaim_proxy_info_get_host purple_proxy_info_get_host -#define gaim_proxy_info_get_port purple_proxy_info_get_port -#define gaim_proxy_info_get_username purple_proxy_info_get_username -#define gaim_proxy_info_get_password purple_proxy_info_get_password - -#define gaim_global_proxy_get_info purple_global_proxy_get_info -#define gaim_proxy_get_handle purple_proxy_get_handle -#define gaim_proxy_init purple_proxy_init -#define gaim_proxy_uninit purple_proxy_uninit -#define gaim_proxy_get_setup purple_proxy_get_setup - -#define gaim_proxy_connect purple_proxy_connect -#define gaim_proxy_connect_socks5 purple_proxy_connect_socks5 -#define gaim_proxy_connect_cancel purple_proxy_connect_cancel -#define gaim_proxy_connect_cancel_with_handle purple_proxy_connect_cancel_with_handle - -/* from prpl.h */ - -#define GaimPluginProtocolInfo PurplePluginProtocolInfo - -#define GAIM_ICON_SCALE_DISPLAY PURPLE_ICON_SCALE_DISPLAY -#define GAIM_ICON_SCALE_SEND PURPLE_ICON_SCALE_SEND -#define GaimIconScaleRules PurpleIconScaleRules - -#define GaimBuddyIconSpec PurpleBuddyIconSpec - -#define GaimProtocolOptions PurpleProtocolOptions - -#define GAIM_IS_PROTOCOL_PLUGIN PURPLE_IS_PROTOCOL_PLUGIN - -#define GAIM_PLUGIN_PROTOCOL_INFO PURPLE_PLUGIN_PROTOCOL_INFO - -#define gaim_prpl_got_account_idle purple_prpl_got_account_idle -#define gaim_prpl_got_account_login_time purple_prpl_got_account_login_time -#define gaim_prpl_got_account_status purple_prpl_got_account_status -#define gaim_prpl_got_user_idle purple_prpl_got_user_idle -#define gaim_prpl_got_user_login_time purple_prpl_got_user_login_time -#define gaim_prpl_got_user_status purple_prpl_got_user_status -#define gaim_prpl_change_account_status purple_prpl_change_account_status -#define gaim_prpl_get_statuses purple_prpl_get_statuses - -#define gaim_find_prpl purple_find_prpl - -/* from request.h */ - -#define GAIM_DEFAULT_ACTION_NONE PURPLE_DEFAULT_ACTION_NONE - -#define GAIM_REQUEST_INPUT PURPLE_REQUEST_INPUT -#define GAIM_REQUEST_CHOICE PURPLE_REQUEST_CHOICE -#define GAIM_REQUEST_ACTION PURPLE_REQUEST_ACTION -#define GAIM_REQUEST_FIELDS PURPLE_REQUEST_FIELDS -#define GAIM_REQUEST_FILE PURPLE_REQUEST_FILE -#define GAIM_REQUEST_FOLDER PURPLE_REQUEST_FOLDER -#define GaimRequestType PurpleRequestType - -#define GAIM_REQUEST_FIELD_NONE PURPLE_REQUEST_FIELD_NONE -#define GAIM_REQUEST_FIELD_STRING PURPLE_REQUEST_FIELD_STRING -#define GAIM_REQUEST_FIELD_INTEGER PURPLE_REQUEST_FIELD_INTEGER -#define GAIM_REQUEST_FIELD_BOOLEAN PURPLE_REQUEST_FIELD_BOOLEAN -#define GAIM_REQUEST_FIELD_CHOICE PURPLE_REQUEST_FIELD_CHOICE -#define GAIM_REQUEST_FIELD_LIST PURPLE_REQUEST_FIELD_LIST -#define GAIM_REQUEST_FIELD_LABEL PURPLE_REQUEST_FIELD_LABEL -#define GAIM_REQUEST_FIELD_IMAGE PURPLE_REQUEST_FIELD_IMAGE -#define GAIM_REQUEST_FIELD_ACCOUNT PURPLE_REQUEST_FIELD_ACCOUNT -#define GaimRequestFieldType PurpleRequestFieldType - -#define GaimRequestFields PurpleRequestFields - -#define GaimRequestFieldGroup PurpleRequestFieldGroup - -#define GaimRequestField PurpleRequestField - -#define GaimRequestUiOps PurpleRequestUiOps - -#define GaimRequestInputCb PurpleRequestInputCb -#define GaimRequestActionCb PurpleRequestActionCb -#define GaimRequestChoiceCb PurpleRequestChoiceCb -#define GaimRequestFieldsCb PurpleRequestFieldsCb -#define GaimRequestFileCb PurpleRequestFileCb - -#define gaim_request_fields_new purple_request_fields_new -#define gaim_request_fields_destroy purple_request_fields_destroy -#define gaim_request_fields_add_group purple_request_fields_add_group -#define gaim_request_fields_get_groups purple_request_fields_get_groups -#define gaim_request_fields_exists purple_request_fields_exists -#define gaim_request_fields_get_required purple_request_fields_get_required -#define gaim_request_fields_is_field_required purple_request_fields_is_field_required -#define gaim_request_fields_all_required_filled purple_request_fields_all_required_filled -#define gaim_request_fields_get_field purple_request_fields_get_field -#define gaim_request_fields_get_string purple_request_fields_get_string -#define gaim_request_fields_get_integer purple_request_fields_get_integer -#define gaim_request_fields_get_bool purple_request_fields_get_bool -#define gaim_request_fields_get_choice purple_request_fields_get_choice -#define gaim_request_fields_get_account purple_request_fields_get_account - -#define gaim_request_field_group_new purple_request_field_group_new -#define gaim_request_field_group_destroy purple_request_field_group_destroy -#define gaim_request_field_group_add_field purple_request_field_group_add_field -#define gaim_request_field_group_get_title purple_request_field_group_get_title -#define gaim_request_field_group_get_fields purple_request_field_group_get_fields - -#define gaim_request_field_new purple_request_field_new -#define gaim_request_field_destroy purple_request_field_destroy -#define gaim_request_field_set_label purple_request_field_set_label -#define gaim_request_field_set_visible purple_request_field_set_visible -#define gaim_request_field_set_type_hint purple_request_field_set_type_hint -#define gaim_request_field_set_required purple_request_field_set_required -#define gaim_request_field_get_type purple_request_field_get_type -#define gaim_request_field_get_id purple_request_field_get_id -#define gaim_request_field_get_label purple_request_field_get_label -#define gaim_request_field_is_visible purple_request_field_is_visible -#define gaim_request_field_get_type_hint purple_request_field_get_type_hint -#define gaim_request_field_is_required purple_request_field_is_required - -#define gaim_request_field_string_new purple_request_field_string_new -#define gaim_request_field_string_set_default_value \ - purple_request_field_string_set_default_value -#define gaim_request_field_string_set_value purple_request_field_string_set_value -#define gaim_request_field_string_set_masked purple_request_field_string_set_masked -#define gaim_request_field_string_set_editable purple_request_field_string_set_editable -#define gaim_request_field_string_get_default_value \ - purple_request_field_string_get_default_value -#define gaim_request_field_string_get_value purple_request_field_string_get_value -#define gaim_request_field_string_is_multiline purple_request_field_string_is_multiline -#define gaim_request_field_string_is_masked purple_request_field_string_is_masked -#define gaim_request_field_string_is_editable purple_request_field_string_is_editable - -#define gaim_request_field_int_new purple_request_field_int_new -#define gaim_request_field_int_set_default_value \ - purple_request_field_int_set_default_value -#define gaim_request_field_int_set_value purple_request_field_int_set_value -#define gaim_request_field_int_get_default_value \ - purple_request_field_int_get_default_value -#define gaim_request_field_int_get_value purple_request_field_int_get_value - -#define gaim_request_field_bool_new purple_request_field_bool_new -#define gaim_request_field_bool_set_default_value \ - purple_request_field_book_set_default_value -#define gaim_request_field_bool_set_value purple_request_field_bool_set_value -#define gaim_request_field_bool_get_default_value \ - purple_request_field_bool_get_default_value -#define gaim_request_field_bool_get_value purple_request_field_bool_get_value - -#define gaim_request_field_choice_new purple_request_field_choice_new -#define gaim_request_field_choice_add purple_request_field_choice_add -#define gaim_request_field_choice_set_default_value \ - purple_request_field_choice_set_default_value -#define gaim_request_field_choice_set_value purple_request_field_choice_set_value -#define gaim_request_field_choice_get_default_value \ - purple_request_field_choice_get_default_value -#define gaim_request_field_choice_get_value purple_request_field_choice_get_value -#define gaim_request_field_choice_get_labels purple_request_field_choice_get_labels - -#define gaim_request_field_list_new purple_request_field_list_new -#define gaim_request_field_list_set_multi_select purple_request_field_list_set_multi_select -#define gaim_request_field_list_get_multi_select purple_request_field_list_get_multi_select -#define gaim_request_field_list_get_data purple_request_field_list_get_data -#define gaim_request_field_list_add purple_request_field_list_add -#define gaim_request_field_list_add_selected purple_request_field_list_add_selected -#define gaim_request_field_list_clear_selected purple_request_field_list_clear_selected -#define gaim_request_field_list_set_selected purple_request_field_list_set_selected -#define gaim_request_field_list_is_selected purple_request_field_list_is_selected -#define gaim_request_field_list_get_selected purple_request_field_list_get_selected -#define gaim_request_field_list_get_items purple_request_field_list_get_items - -#define gaim_request_field_label_new purple_request_field_label_new - -#define gaim_request_field_image_new purple_request_field_image_new -#define gaim_request_field_image_set_scale purple_request_field_image_set_scale -#define gaim_request_field_image_get_buffer purple_request_field_image_get_buffer -#define gaim_request_field_image_get_size purple_request_field_image_get_size -#define gaim_request_field_image_get_scale_x purple_request_field_image_get_scale_x -#define gaim_request_field_image_get_scale_y purple_request_field_image_get_scale_y - -#define gaim_request_field_account_new purple_request_field_account_new -#define gaim_request_field_account_set_default_value purple_request_field_account_set_default_value -#define gaim_request_field_account_set_value purple_request_field_account_set_value -#define gaim_request_field_account_set_show_all purple_request_field_account_set_show_all -#define gaim_request_field_account_set_filter purple_request_field_account_set_filter -#define gaim_request_field_account_get_default_value purple_request_field_account_get_default_value -#define gaim_request_field_account_get_value purple_request_field_account_get_value -#define gaim_request_field_account_get_show_all purple_request_field_account_get_show_all -#define gaim_request_field_account_get_filter purple_request_field_account_get_filter - -#define gaim_request_input purple_request_input -#define gaim_request_choice purple_request_choice -#define gaim_request_choice_varg purple_request_choice_varg -#define gaim_request_action purple_request_action -#define gaim_request_action_varg purple_request_action_varg -#define gaim_request_fields(handle, title, primary, secondary, fields, ok_text, ok_cb, cancel_text, cancel_cb, user_data) purple_request_fields(handle, title, primary, secondary, fields, ok_text, ok_cb, cancel_text, cancel_cb, NULL, NULL, NULL, user_data) -#define gaim_request_close purple_request_close -#define gaim_request_close_with_handle purple_request_close_with_handle - -#define gaim_request_yes_no purple_request_yes_no -#define gaim_request_ok_cancel purple_request_ok_cancel -#define gaim_request_accept_cancel purple_request_accept_cancel - -#define gaim_request_file purple_request_file -#define gaim_request_folder purple_request_folder - -#define gaim_request_set_ui_ops purple_request_set_ui_ops -#define gaim_request_get_ui_ops purple_request_get_ui_ops - -/* from roomlist.h */ - -#define GaimRoomlist PurpleRoomlist -#define GaimRoomlistRoom PurpleRoomlistRoom -#define GaimRoomlistField PurpleRoomlistField -#define GaimRoomlistUiOps PurpleRoomlistUiOps - -#define GAIM_ROOMLIST_ROOMTYPE_CATEGORY PURPLE_ROOMLIST_ROOMTYPE_CATEGORY -#define GAIM_ROOMLIST_ROOMTYPE_ROOM PURPLE_ROOMLIST_ROOMTYPE_ROOM -#define GaimRoomlistRoomType PurpleRoomlistRoomType - -#define GAIM_ROOMLIST_FIELD_BOOL PURPLE_ROOMLIST_BOOL -#define GAIM_ROOMLIST_FIELD_INT PURPLE_ROOMLIST_INT -#define GAIM_ROOMLIST_FIELD_STRING PURPLE_ROOMLIST_STRING -#define GaimRoomlistFieldType PurpleRoomlistFieldType - -#define gaim_roomlist_show_with_account purple_roomlist_show_with_account -#define gaim_roomlist_new purple_roomlist_new -#define gaim_roomlist_ref purple_roomlist_ref -#define gaim_roomlist_unref purple_roomlist_unref -#define gaim_roomlist_set_fields purple_roomlist_set_fields -#define gaim_roomlist_set_in_progress purple_roomlist_set_in_progress -#define gaim_roomlist_get_in_progress purple_roomlist_get_in_progress -#define gaim_roomlist_room_add purple_roomlist_room_add - -#define gaim_roomlist_get_list purple_roomlist_get_list -#define gaim_roomlist_cancel_get_list purple_roomlist_cancel_get_list -#define gaim_roomlist_expand_category purple_roomlist_expand_category - -#define gaim_roomlist_room_new purple_roomlist_room_new -#define gaim_roomlist_room_add_field purple_roomlist_room_add_field -#define gaim_roomlist_room_join purple_roomlist_room_join -#define gaim_roomlist_field_new purple_roomlist_field_new - -#define gaim_roomlist_set_ui_ops purple_roomlist_set_ui_ops -#define gaim_roomlist_get_ui_ops purple_roomlist_get_ui_ops - -/* from savedstatuses.h */ - -#define GaimSavedStatus PurpleSavedStatus -#define GaimSavedStatusSub PurpleSavedStatusSub - -#define gaim_savedstatus_new purple_savedstatus_new -#define gaim_savedstatus_set_title purple_savedstatus_set_title -#define gaim_savedstatus_set_type purple_savedstatus_set_type -#define gaim_savedstatus_set_message purple_savedstatus_set_message -#define gaim_savedstatus_set_substatus purple_savedstatus_set_substatus -#define gaim_savedstatus_unset_substatus purple_savedstatus_unset_substatus -#define gaim_savedstatus_delete purple_savedstatus_delete - -#define gaim_savedstatuses_get_all purple_savedstatuses_get_all -#define gaim_savedstatuses_get_popular purple_savedstatuses_get_popular -#define gaim_savedstatus_get_current purple_savedstatus_get_current -#define gaim_savedstatus_get_default purple_savedstatus_get_default -#define gaim_savedstatus_get_idleaway purple_savedstatus_get_idleaway -#define gaim_savedstatus_is_idleaway purple_savedstatus_is_idleaway -#define gaim_savedstatus_set_idleaway purple_savedstatus_set_idleaway -#define gaim_savedstatus_get_startup purple_savedstatus_get_startup -#define gaim_savedstatus_find purple_savedstatus_find -#define gaim_savedstatus_find_by_creation_time purple_savedstatus_find_by_creation_time -#define gaim_savedstatus_find_transient_by_type_and_message \ - purple_savedstatus_find_transient_by_type_and_message - -#define gaim_savedstatus_is_transient purple_savedstatus_is_transient -#define gaim_savedstatus_get_title purple_savedstatus_get_title -#define gaim_savedstatus_get_type purple_savedstatus_get_type -#define gaim_savedstatus_get_message purple_savedstatus_get_message -#define gaim_savedstatus_get_creation_time purple_savedstatus_get_creation_time -#define gaim_savedstatus_has_substatuses purple_savedstatus_has_substatuses -#define gaim_savedstatus_get_substatus purple_savedstatus_get_substatus -#define gaim_savedstatus_substatus_get_type purple_savedstatus_substatus_get_type -#define gaim_savedstatus_substatus_get_message purple_savedstatus_substatus_get_message -#define gaim_savedstatus_activate purple_savedstatus_activate -#define gaim_savedstatus_activate_for_account purple_savedstatus_activate_for_account - -#define gaim_savedstatuses_get_handle purple_savedstatuses_get_handle -#define gaim_savedstatuses_init purple_savedstatuses_init -#define gaim_savedstatuses_uninit purple_savedstatuses_uninit - -/* from signals.h */ - -#define GAIM_CALLBACK PURPLE_CALLBACK - -#define GaimCallback PurpleCallback -#define GaimSignalMarshalFunc PurpleSignalMarshalFunc - -#define GAIM_SIGNAL_PRIORITY_DEFAULT PURPLE_SIGNAL_PRIORITY_DEFAULT -#define GAIM_SIGNAL_PRIORITY_HIGHEST PURPLE_SIGNAL_PRIORITY_HIGHEST -#define GAIM_SIGNAL_PRIORITY_LOWEST PURPLE_SIGNAL_PRIORITY_LOWEST - -#define gaim_signal_register purple_signal_register -#define gaim_signal_unregister purple_signal_unregister - -#define gaim_signals_unregister_by_instance purple_signals_unregister_by_instance - -#define gaim_signal_get_values purple_signal_get_values -#define gaim_signal_connect_priority purple_signal_connect_priority -#define gaim_signal_connect purple_signal_connect -#define gaim_signal_connect_priority_vargs purple_signal_connect_priority_vargs -#define gaim_signal_connect_vargs purple_signal_connect_vargs -#define gaim_signal_disconnect purple_signal_disconnect - -#define gaim_signals_disconnect_by_handle purple_signals_disconnect_by_handle - -#define gaim_signal_emit purple_signal_emit -#define gaim_signal_emit_vargs purple_signal_emit_vargs -#define gaim_signal_emit_return_1 purple_signal_emit_vargs -#define gaim_signal_emit_vargs_return_1 purple_signal_emit_vargs_return_1 - -#define gaim_signals_init purple_signals_init -#define gaim_signals_uninit purple_signals_uninit - -#define gaim_marshal_VOID \ - purple_marshal_VOID -#define gaim_marshal_VOID__INT \ - purple_marshal_VOID__INT -#define gaim_marshal_VOID__INT_INT \ - purple_marshal_VOID_INT_INT -#define gaim_marshal_VOID__POINTER \ - purple_marshal_VOID__POINTER -#define gaim_marshal_VOID__POINTER_UINT \ - purple_marshal_VOID__POINTER_UINT -#define gaim_marshal_VOID__POINTER_INT_INT \ - purple_marshal_VOID__POINTER_INT_INT -#define gaim_marshal_VOID__POINTER_POINTER \ - purple_marshal_VOID__POINTER_POINTER -#define gaim_marshal_VOID__POINTER_POINTER_UINT \ - purple_marshal_VOID__POINTER_POINTER_UINT -#define gaim_marshal_VOID__POINTER_POINTER_UINT_UINT \ - purple_marshal_VOID__POINTER_POINTER_UINT_UINT -#define gaim_marshal_VOID__POINTER_POINTER_POINTER \ - purple_marshal_VOID__POINTER_POINTER_POINTER -#define gaim_marshal_VOID__POINTER_POINTER_POINTER_POINTER \ - purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER -#define gaim_marshal_VOID__POINTER_POINTER_POINTER_POINTER_POINTER \ - purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_POINTER -#define gaim_marshal_VOID__POINTER_POINTER_POINTER_UINT \ - purple_marshal_VOID__POINTER_POINTER_POINTER_UINT -#define gaim_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT \ - purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT -#define gaim_marshal_VOID__POINTER_POINTER_POINTER_UINT_UINT \ - purple_marshal_VOID__POINTER_POINTER_POINTER_UINT_UINT - -#define gaim_marshal_INT__INT \ - purple_marshal_INT__INT -#define gaim_marshal_INT__INT_INT \ - purple_marshal_INT__INT_INT -#define gaim_marshal_INT__POINTER_POINTER_POINTER_POINTER_POINTER \ - purple_marshal_INT__POINTER_POINTER_POINTER_POINTER_POINTER - -#define gaim_marshal_BOOLEAN__POINTER \ - purple_marshal_BOOLEAN__POINTER -#define gaim_marshal_BOOLEAN__POINTER_POINTER \ - purple_marshal_BOOLEAN__POINTER_POINTER -#define gaim_marshal_BOOLEAN__POINTER_POINTER_POINTER \ - purple_marshal_BOOLEAN__POINTER_POINTER_POINTER -#define gaim_marshal_BOOLEAN__POINTER_POINTER_UINT \ - purple_marshal_BOOLEAN__POINTER_POINTER_UINT -#define gaim_marshal_BOOLEAN__POINTER_POINTER_POINTER_UINT \ - purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_UINT -#define gaim_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER \ - purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER -#define gaim_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER \ - purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER - -#define gaim_marshal_BOOLEAN__INT_POINTER \ - purple_marshal_BOOLEAN__INT_POINTER - -#define gaim_marshal_POINTER__POINTER_INT \ - purple_marshal_POINTER__POINTER_INT -#define gaim_marshal_POINTER__POINTER_INT64 \ - purple_marshal_POINTER__POINTER_INT64 -#define gaim_marshal_POINTER__POINTER_INT_BOOLEAN \ - purple_marshal_POINTER__POINTER_INT_BOOLEAN -#define gaim_marshal_POINTER__POINTER_INT64_BOOLEAN \ - purple_marshal_POINTER__POINTER_INT64_BOOLEAN -#define gaim_marshal_POINTER__POINTER_POINTER \ - purple_marshal_POINTER__POINTER_POINTER - -/* from sound.h */ - -#define GAIM_SOUND_BUDDY_ARRIVE PURPLE_SOUND_BUDDY_ARRIVE -#define GAIM_SOUND_BUDDY_LEAVE PURPLE_SOUND_BUDDY_LEAVE -#define GAIM_SOUND_RECEIVE PURPLE_SOUND_RECEIVE -#define GAIM_SOUND_FIRST_RECEIVE PURPLE_SOUND_FIRST_RECEIVE -#define GAIM_SOUND_SEND PURPLE_SOUND_SEND -#define GAIM_SOUND_CHAT_JOIN PURPLE_SOUND_CHAT_JOIN -#define GAIM_SOUND_CHAT_LEAVE PURPLE_SOUND_CHAT_LEAVE -#define GAIM_SOUND_CHAT_YOU_SAY PURPLE_SOUND_CHAT_YOU_SAY -#define GAIM_SOUND_CHAT_SAY PURPLE_SOUND_CHAT_SAY -#define GAIM_SOUND_POUNCE_DEFAULT PURPLE_SOUND_POUNCE_DEFAULT -#define GAIM_SOUND_CHAT_NICK PURPLE_SOUND_CHAT_NICK -#define GAIM_NUM_SOUNDS PURPLE_NUM_SOUNDS -#define GaimSoundEventID PurpleSoundEventID - -#define GaimSoundUiOps PurpleSoundUiOps - -#define gaim_sound_play_file purple_sound_play_file -#define gaim_sound_play_event purple_sound_play_event -#define gaim_sound_set_ui_ops purple_sound_set_ui_ops -#define gaim_sound_get_ui_ops purple_sound_get_ui_ops -#define gaim_sound_init purple_sound_init -#define gaim_sound_uninit purple_sound_uninit - -#define gaim_sounds_get_handle purple_sounds_get_handle - -/* from sslconn.h */ - -#define GAIM_SSL_DEFAULT_PORT PURPLE_SSL_DEFAULT_PORT - -#define GAIM_SSL_HANDSHAKE_FAILED PURPLE_SSL_HANDSHAKE_FAILED -#define GAIM_SSL_CONNECT_FAILED PURPLE_SSL_CONNECT_FAILED -#define GaimSslErrorType PurpleSslErrorType - -#define GaimSslConnection PurpleSslConnection - -#define GaimSslInputFunction PurpleSslInputFunction -#define GaimSslErrorFunction PurpleSslErrorFunction - -#define GaimSslOps PurpleSslOps - -#define gaim_ssl_is_supported purple_ssl_is_supported -#define gaim_ssl_connect purple_ssl_connect -#define gaim_ssl_connect_fd purple_ssl_connect_fd -#define gaim_ssl_input_add purple_ssl_input_add -#define gaim_ssl_close purple_ssl_close -#define gaim_ssl_read purple_ssl_read -#define gaim_ssl_write purple_ssl_write - -#define gaim_ssl_set_ops purple_ssl_set_ops -#define gaim_ssl_get_ops purple_ssl_get_ops -#define gaim_ssl_init purple_ssl_init -#define gaim_ssl_uninit purple_ssl_uninit - -/* from status.h */ - -#define GaimStatusType PurpleStatusType -#define GaimStatusAttr PurpleStatusAttr -#define GaimPresence PurplePresence -#define GaimStatus PurpleStatus - -#define GAIM_PRESENCE_CONTEXT_UNSET PURPLE_PRESENCE_CONTEXT_UNSET -#define GAIM_PRESENCE_CONTEXT_ACCOUNT PURPLE_PRESENCE_CONTEXT_ACCOUNT -#define GAIM_PRESENCE_CONTEXT_CONV PURPLE_PRESENCE_CONTEXT_CONV -#define GAIM_PRESENCE_CONTEXT_BUDDY PURPLE_PRESENCE_CONTEXT_BUDDY -#define GaimPresenceContext PurplePresenceContext - -#define GAIM_STATUS_UNSET PURPLE_STATUS_UNSET -#define GAIM_STATUS_OFFLINE PURPLE_STATUS_OFFLINE -#define GAIM_STATUS_AVAILABLE PURPLE_STATUS_AVAILABLE -#define GAIM_STATUS_UNAVAILABLE PURPLE_STATUS_UNAVAILABLE -#define GAIM_STATUS_INVISIBLE PURPLE_STATUS_INVISIBLE -#define GAIM_STATUS_AWAY PURPLE_STATUS_AWAY -#define GAIM_STATUS_EXTENDED_AWAY PURPLE_STATUS_EXTENDED_AWAY -#define GAIM_STATUS_MOBILE PURPLE_STATUS_MOBILE -#define GAIM_STATUS_NUM_PRIMITIVES PURPLE_STATUS_NUM_PRIMITIVES -#define GaimStatusPrimitive PurpleStatusPrimitive - -#define gaim_primitive_get_id_from_type purple_primitive_get_id_from_type -#define gaim_primitive_get_name_from_type purple_primitive_get_name_from_type -#define gaim_primitive_get_type_from_id purple_primitive_get_type_from_id - -#define gaim_status_type_new_full purple_status_type_new_full -#define gaim_status_type_new purple_status_type_new -#define gaim_status_type_new_with_attrs purple_status_type_new_with_attrs -#define gaim_status_type_destroy purple_status_type_destroy -#define gaim_status_type_set_primary_attr purple_status_type_set_primary_attr -#define gaim_status_type_add_attr purple_status_type_add_attr -#define gaim_status_type_add_attrs purple_status_type_add_attrs -#define gaim_status_type_add_attrs_vargs purple_status_type_add_attrs_vargs -#define gaim_status_type_get_primitive purple_status_type_get_primitive -#define gaim_status_type_get_id purple_status_type_get_id -#define gaim_status_type_get_name purple_status_type_get_name -#define gaim_status_type_is_saveable purple_status_type_is_saveable -#define gaim_status_type_is_user_settable purple_status_type_is_user_settable -#define gaim_status_type_is_independent purple_status_type_is_independent -#define gaim_status_type_is_exclusive purple_status_type_is_exclusive -#define gaim_status_type_is_available purple_status_type_is_available -#define gaim_status_type_get_primary_attr purple_status_type_get_primary_attr -#define gaim_status_type_get_attr purple_status_type_get_attr -#define gaim_status_type_get_attrs purple_status_type_get_attrs -#define gaim_status_type_find_with_id purple_status_type_find_with_id - -#define gaim_status_attr_new purple_status_attr_new -#define gaim_status_attr_destroy purple_status_attr_destroy -#define gaim_status_attr_get_id purple_status_attr_get_id -#define gaim_status_attr_get_name purple_status_attr_get_name -#define gaim_status_attr_get_value purple_status_attr_get_value - -#define gaim_status_new purple_status_new -#define gaim_status_destroy purple_status_destroy -#define gaim_status_set_active purple_status_set_active -#define gaim_status_set_active_with_attrs purple_status_set_active_with_attrs -#define gaim_status_set_active_with_attrs_list purple_status_set_active_with_attrs_list -#define gaim_status_set_attr_boolean purple_status_set_attr_boolean -#define gaim_status_set_attr_int purple_status_set_attr_int -#define gaim_status_set_attr_string purple_status_set_attr_string -#define gaim_status_get_type purple_status_get_type -#define gaim_status_get_presence purple_status_get_presence -#define gaim_status_get_id purple_status_get_id -#define gaim_status_get_name purple_status_get_name -#define gaim_status_is_independent purple_status_is_independent -#define gaim_status_is_exclusive purple_status_is_exclusive -#define gaim_status_is_available purple_status_is_available -#define gaim_status_is_active purple_status_is_active -#define gaim_status_is_online purple_status_is_online -#define gaim_status_get_attr_value purple_status_get_attr_value -#define gaim_status_get_attr_boolean purple_status_get_attr_boolean -#define gaim_status_get_attr_int purple_status_get_attr_int -#define gaim_status_get_attr_string purple_status_get_attr_string -#define gaim_status_compare purple_status_compare - -#define gaim_presence_new purple_presence_new -#define gaim_presence_new_for_account purple_presence_new_for_account -#define gaim_presence_new_for_conv purple_presence_new_for_conv -#define gaim_presence_new_for_buddy purple_presence_new_for_buddy -#define gaim_presence_destroy purple_presence_destroy -#define gaim_presence_add_status purple_presence_add_status -#define gaim_presence_add_list purple_presence_add_list -#define gaim_presence_set_status_active purple_presence_set_status_active -#define gaim_presence_switch_status purple_presence_switch_status -#define gaim_presence_set_idle purple_presence_set_idle -#define gaim_presence_set_login_time purple_presence_set_login_time -#define gaim_presence_get_context purple_presence_get_context -#define gaim_presence_get_account purple_presence_get_account -#define gaim_presence_get_conversation purple_presence_get_conversation -#define gaim_presence_get_chat_user purple_presence_get_chat_user -#define gaim_presence_get_statuses purple_presence_get_statuses -#define gaim_presence_get_status purple_presence_get_status -#define gaim_presence_get_active_status purple_presence_get_active_status -#define gaim_presence_is_available purple_presence_is_available -#define gaim_presence_is_online purple_presence_is_online -#define gaim_presence_is_status_active purple_presence_is_status_active -#define gaim_presence_is_status_primitive_active \ - purple_presence_is_status_primitive_active -#define gaim_presence_is_idle purple_presence_is_idle -#define gaim_presence_get_idle_time purple_presence_get_idle_time -#define gaim_presence_get_login_time purple_presence_get_login_time -#define gaim_presence_compare purple_presence_compare - -#define gaim_status_get_handle purple_status_get_handle -#define gaim_status_init purple_status_init -#define gaim_status_uninit purple_status_uninit - -/* from stringref.h */ - -#define GaimStringref PurpleStringref - -#define gaim_stringref_new purple_stringref_new -#define gaim_stringref_new_noref purple_stringref_new_noref -#define gaim_stringref_printf purple_stringref_printf -#define gaim_stringref_ref purple_stringref_ref -#define gaim_stringref_unref purple_stringref_unref -#define gaim_stringref_value purple_stringref_value -#define gaim_stringref_cmp purple_stringref_cmp -#define gaim_stringref_len purple_stringref_len - -/* from stun.h */ - -#define GaimStunNatDiscovery PurpleStunNatDiscovery - -#define GAIM_STUN_STATUS_UNDISCOVERED PURPLE_STUN_STATUS_UNDISCOVERED -#define GAIM_STUN_STATUS_UNKNOWN PURPLE_STUN_STATUS_UNKNOWN -#define GAIM_STUN_STATUS_DISCOVERING PURPLE_STUN_STATUS_DISCOVERING -#define GAIM_STUN_STATUS_DISCOVERED PURPLE_STUN_STATUS_DISCOVERED -#define GaimStunStatus PurpleStunStatus - -#define GAIM_STUN_NAT_TYPE_PUBLIC_IP PURPLE_STUN_NAT_TYPE_PUBLIC_IP -#define GAIM_STUN_NAT_TYPE_UNKNOWN_NAT PURPLE_STUN_NAT_TYPE_UNKNOWN_NAT -#define GAIM_STUN_NAT_TYPE_FULL_CONE PURPLE_STUN_NAT_TYPE_FULL_CONE -#define GAIM_STUN_NAT_TYPE_RESTRICTED_CONE PURPLE_STUN_NAT_TYPE_RESTRICTED_CONE -#define GAIM_STUN_NAT_TYPE_PORT_RESTRICTED_CONE PURPLE_STUN_NAT_TYPE_PORT_RESTRICTED_CONE -#define GAIM_STUN_NAT_TYPE_SYMMETRIC PURPLE_STUN_NAT_TYPE_SYMMETRIC -#define GaimStunNatType PurpleStunNatType - -/* why didn't this have a Gaim prefix before? */ -#define StunCallback PurpleStunCallback - -#define gaim_stun_discover purple_stun_discover -#define gaim_stun_init purple_stun_init - -/* from upnp.h */ - -/* suggested rename: PurpleUPnpMappingHandle */ -#define UPnPMappingAddRemove PurpleUPnPMappingAddRemove - -#define GaimUPnPCallback PurpleUPnPCallback - -#define gaim_upnp_discover purple_upnp_discover -#define gaim_upnp_get_public_ip purple_upnp_get_public_ip -#define gaim_upnp_cancel_port_mapping purple_upnp_cancel_port_mapping -#define gaim_upnp_set_port_mapping purple_upnp_set_port_mapping - -#define gaim_upnp_remove_port_mapping purple_upnp_remove_port_mapping - -/* from util.h */ - -#define GaimUtilFetchUrlData PurpleUtilFetchUrlData -#define GaimMenuAction PurpleMenuAction - -#define GaimInfoFieldFormatCallback PurpleIntoFieldFormatCallback - -#define GaimKeyValuePair PurpleKeyValuePair - -#define gaim_menu_action_new purple_menu_action_new -#define gaim_menu_action_free purple_menu_action_free - -#define gaim_base16_encode purple_base16_encode -#define gaim_base16_decode purple_base16_decode -#define gaim_base64_encode purple_base64_encode -#define gaim_base64_decode purple_base64_decode -#define gaim_quotedp_decode purple_quotedp_decode - -#define gaim_mime_decode_field purple_mime_deco_field - -#define gaim_utf8_strftime purple_utf8_strftime -#define gaim_date_format_short purple_date_format_short -#define gaim_date_format_long purple_date_format_long -#define gaim_date_format_full purple_date_format_full -#define gaim_time_format purple_time_format -#define gaim_time_build purple_time_build - -#define GAIM_NO_TZ_OFF PURPLE_NO_TZ_OFF - -#define gaim_str_to_time purple_str_to_time - -#define gaim_markup_find_tag purple_markup_find_tag -#define gaim_markup_extract_info_field purple_markup_extract_info_field -#define gaim_markup_html_to_xhtml purple_markup_html_to_xhtml -#define gaim_markup_strip_html purple_markup_strip_html -#define gaim_markup_linkify purple_markup_linkify -#define gaim_markup_slice purple_markup_slice -#define gaim_markup_get_tag_name purple_markup_get_tag_name -#define gaim_unescape_html purple_unescape_html - -#define gaim_home_dir purple_home_dir -#define gaim_user_dir purple_user_dir - -#define gaim_util_set_user_dir purple_util_set_user_dir - -#define gaim_build_dir purple_build_dir - -#define gaim_util_write_data_to_file purple_util_write_data_to_file - -#define gaim_util_read_xml_from_file purple_util_read_xml_from_file - -#define gaim_mkstemp purple_mkstemp - -#define gaim_program_is_valid purple_program_is_valid - -#define gaim_running_gnome purple_running_gnome -#define gaim_running_kde purple_running_kde -#define gaim_running_osx purple_running_osx - -#define gaim_fd_get_ip purple_fd_get_ip - -#define gaim_normalize purple_normalize -#define gaim_normalize_nocase purple_normalize_nocase - -#define gaim_strdup_withhtml purple_strdup_withhtml - -#define gaim_str_has_prefix purple_str_has_prefix -#define gaim_str_has_suffix purple_str_has_suffix -#define gaim_str_add_cr purple_str_add_cr -#define gaim_str_strip_char purple_str_strip_char - -#define gaim_util_chrreplace purple_util_chrreplace - -#define gaim_strreplace purple_strreplace - -#define gaim_utf8_ncr_encode purple_utf8_ncr_encode -#define gaim_utf8_ncr_decode purple_utf8_ncr_decode - -#define gaim_strcasereplace purple_strcasereplace -#define gaim_strcasestr purple_strcasestr - -#define gaim_str_size_to_units purple_str_size_to_units -#define gaim_str_seconds_to_string purple_str_seconds_to_string -#define gaim_str_binary_to_ascii purple_str_binary_to_ascii - - -#define gaim_got_protocol_handler_uri purple_got_protocol_handler_uri - -#define gaim_url_parse purple_url_parse - -#define GaimUtilFetchUrlCallback PurpleUtilFetchUrlCallback -#define gaim_util_fetch_url purple_util_fetch_url -#define gaim_util_fetch_url_request purple_util_fetch_url_request -#define gaim_util_fetch_url_cancel purple_util_fetch_url_cancel - -#define gaim_url_decode purple_url_decode -#define gaim_url_encode purple_url_encode - -#define gaim_email_is_valid purple_email_is_valid - -#define gaim_uri_list_extract_uris purple_uri_list_extract_uris -#define gaim_uri_list_extract_filenames purple_uri_list_extract_filenames - -#define gaim_utf8_try_convert purple_utf8_try_convert -#define gaim_utf8_salvage purple_utf8_salvage -#define gaim_utf8_strcasecmp purple_utf8_strcasecmp -#define gaim_utf8_has_word purple_utf8_has_word - -#define gaim_print_utf8_to_console purple_print_utf8_to_console - -#define gaim_message_meify purple_message_meify - -#define gaim_text_strip_mnemonic purple_text_strip_mnemonic - -#define gaim_unescape_filename purple_unescape_filename -#define gaim_escape_filename purple_escape_filename - -/* from value.h */ - -#define GAIM_TYPE_UNKNOWN PURPLE_TYPE_UNKNOWN -#define GAIM_TYPE_SUBTYPE PURPLE_TYPE_SUBTYPE -#define GAIM_TYPE_CHAR PURPLE_TYPE_CHAR -#define GAIM_TYPE_UCHAR PURPLE_TYPE_UCHAR -#define GAIM_TYPE_BOOLEAN PURPLE_TYPE_BOOLEAN -#define GAIM_TYPE_SHORT PURPLE_TYPE_SHORT -#define GAIM_TYPE_USHORT PURPLE_TYPE_USHORT -#define GAIM_TYPE_INT PURPLE_TYPE_INT -#define GAIM_TYPE_UINT PURPLE_TYPE_UINT -#define GAIM_TYPE_LONG PURPLE_TYPE_LONG -#define GAIM_TYPE_ULONG PURPLE_TYPE_ULONG -#define GAIM_TYPE_INT64 PURPLE_TYPE_INT64 -#define GAIM_TYPE_UINT64 PURPLE_TYPE_UINT64 -#define GAIM_TYPE_STRING PURPLE_TYPE_STRING -#define GAIM_TYPE_OBJECT PURPLE_TYPE_OBJECT -#define GAIM_TYPE_POINTER PURPLE_TYPE_POINTER -#define GAIM_TYPE_ENUM PURPLE_TYPE_ENUM -#define GAIM_TYPE_BOXED PURPLE_TYPE_BOXED -#define GaimType PurpleType - - -#define GAIM_SUBTYPE_UNKNOWN PURPLE_SUBTYPE_UNKNOWN -#define GAIM_SUBTYPE_ACCOUNT PURPLE_SUBTYPE_ACCOUNT -#define GAIM_SUBTYPE_BLIST PURPLE_SUBTYPE_BLIST -#define GAIM_SUBTYPE_BLIST_BUDDY PURPLE_SUBTYPE_BLIST_BUDDY -#define GAIM_SUBTYPE_BLIST_GROUP PURPLE_SUBTYPE_BLIST_GROUP -#define GAIM_SUBTYPE_BLIST_CHAT PURPLE_SUBTYPE_BLIST_CHAT -#define GAIM_SUBTYPE_BUDDY_ICON PURPLE_SUBTYPE_BUDDY_ICON -#define GAIM_SUBTYPE_CONNECTION PURPLE_SUBTYPE_CONNECTION -#define GAIM_SUBTYPE_CONVERSATION PURPLE_SUBTYPE_CONVERSATION -#define GAIM_SUBTYPE_PLUGIN PURPLE_SUBTYPE_PLUGIN -#define GAIM_SUBTYPE_BLIST_NODE PURPLE_SUBTYPE_BLIST_NODE -#define GAIM_SUBTYPE_CIPHER PURPLE_SUBTYPE_CIPHER -#define GAIM_SUBTYPE_STATUS PURPLE_SUBTYPE_STATUS -#define GAIM_SUBTYPE_LOG PURPLE_SUBTYPE_LOG -#define GAIM_SUBTYPE_XFER PURPLE_SUBTYPE_XFER -#define GAIM_SUBTYPE_SAVEDSTATUS PURPLE_SUBTYPE_SAVEDSTATUS -#define GAIM_SUBTYPE_XMLNODE PURPLE_SUBTYPE_XMLNODE -#define GAIM_SUBTYPE_USERINFO PURPLE_SUBTYPE_USERINFO -#define GaimSubType PurpleSubType - -#define GaimValue PurpleValue - -#define gaim_value_new purple_value_new -#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_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 -#define gaim_value_set_char purple_value_set_char -#define gaim_value_set_uchar purple_value_set_uchar -#define gaim_value_set_boolean purple_value_set_boolean -#define gaim_value_set_short purple_value_set_short -#define gaim_value_set_ushort purple_value_set_ushort -#define gaim_value_set_int purple_value_set_int -#define gaim_value_set_uint purple_value_set_uint -#define gaim_value_set_long purple_value_set_long -#define gaim_value_set_ulong purple_value_set_ulong -#define gaim_value_set_int64 purple_value_set_int64 -#define gaim_value_set_uint64 purple_value_set_uint64 -#define gaim_value_set_string purple_value_set_string -#define gaim_value_set_object purple_value_set_object -#define gaim_value_set_pointer purple_value_set_pointer -#define gaim_value_set_enum purple_value_set_enum -#define gaim_value_set_boxed purple_value_set_boxed -#define gaim_value_get_char purple_value_get_char -#define gaim_value_get_uchar purple_value_get_uchar -#define gaim_value_get_boolean purple_value_get_boolean -#define gaim_value_get_short purple_value_get_short -#define gaim_value_get_ushort purple_value_get_ushort -#define gaim_value_get_int purple_value_get_int -#define gaim_value_get_uint purple_value_get_uint -#define gaim_value_get_long purple_value_get_long -#define gaim_value_get_ulong purple_value_get_ulong -#define gaim_value_get_int64 purple_value_get_int64 -#define gaim_value_get_uint64 purple_value_get_uint64 -#define gaim_value_get_string purple_value_get_string -#define gaim_value_get_object purple_value_get_object -#define gaim_value_get_pointer purple_value_get_pointer -#define gaim_value_get_enum purple_value_get_enum -#define gaim_value_get_boxed purple_value_get_boxed - -/* from version.h */ - -#define GAIM_MAJOR_VERSION PURPLE_MAJOR_VERSION -#define GAIM_MINOR_VERSION PURPLE_MINOR_VERSION -#define GAIM_MICRO_VERSION PURPLE_MICRO_VERSION - -#define GAIM_VERSION_CHECK PURPLE_VERSION_CHECK - -/* from whiteboard.h */ - -#define GaimWhiteboardPrplOps PurpleWhiteboardPrplOps -#define GaimWhiteboard PurpleWhiteboard -#define GaimWhiteboardUiOps PurpleWhiteboardUiOps - -#define gaim_whiteboard_set_ui_ops purple_whiteboard_set_ui_ops -#define gaim_whiteboard_set_prpl_ops purple_whiteboard_set_prpl_ops - -#define gaim_whiteboard_create purple_whiteboard_create -#define gaim_whiteboard_destroy purple_whiteboard_destroy -#define gaim_whiteboard_start purple_whiteboard_start -#define gaim_whiteboard_get_session purple_whiteboard_get_session -#define gaim_whiteboard_draw_list_destroy purple_whiteboard_draw_list_destroy -#define gaim_whiteboard_get_dimensions purple_whiteboard_get_dimensions -#define gaim_whiteboard_set_dimensions purple_whiteboard_set_dimensions -#define gaim_whiteboard_draw_point purple_whiteboard_draw_point -#define gaim_whiteboard_send_draw_list purple_whiteboard_send_draw_list -#define gaim_whiteboard_draw_line purple_whiteboard_draw_line -#define gaim_whiteboard_clear purple_whiteboard_clear -#define gaim_whiteboard_send_clear purple_whiteboard_send_clear -#define gaim_whiteboard_send_brush purple_whiteboard_send_brush -#define gaim_whiteboard_get_brush purple_whiteboard_get_brush -#define gaim_whiteboard_set_brush purple_whiteboard_set_brush - -/* for static plugins */ -#define gaim_init_ssl_plugin purple_init_ssl_plugin -#define gaim_init_ssl_openssl_plugin purple_init_ssl_openssl_plugin -#define gaim_init_ssl_gnutls_plugin purple_init_ssl_gnutls_plugin -#define gaim_init_gg_plugin purple_init_gg_plugin -#define gaim_init_jabber_plugin purple_init_jabber_plugin -#define gaim_init_sametime_plugin purple_init_sametime_plugin -#define gaim_init_msn_plugin purple_init_msn_plugin -#define gaim_init_novell_plugin purple_init_novell_plugin -#define gaim_init_qq_plugin purple_init_qq_plugin -#define gaim_init_simple_plugin purple_init_simple_plugin -#define gaim_init_yahoo_plugin purple_init_yahoo_plugin -#define gaim_init_zephyr_plugin purple_init_zephyr_plugin -#define gaim_init_aim_plugin purple_init_aim_plugin -#define gaim_init_icq_plugin purple_init_icq_plugin - -#endif /* _GAIM_COMPAT_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/idle.h --- a/libpurple/idle.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/idle.h Fri Apr 06 04:30:00 2012 +0000 @@ -41,9 +41,7 @@ void (*_purple_reserved4)(void); } PurpleIdleUiOps; -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Idle API */ @@ -97,8 +95,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_IDLE_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/imgstore.h --- a/libpurple/imgstore.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/imgstore.h Fri Apr 06 04:30:00 2012 +0000 @@ -34,9 +34,7 @@ */ typedef struct _PurpleStoredImage PurpleStoredImage; -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /** * Add an image to the store. @@ -68,7 +66,6 @@ * @param path The path to the image. * * @return The stored image. - * @since 2.X.X */ PurpleStoredImage * purple_imgstore_new_from_file(const char *path); @@ -207,8 +204,6 @@ */ void purple_imgstore_uninit(void); -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_IMGSTORE_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/internal.h --- a/libpurple/internal.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/internal.h Fri Apr 06 04:30:00 2012 +0000 @@ -151,12 +151,6 @@ #include -/* Safer ways to work with static buffers. When using non-static - * buffers, either use g_strdup_* functions (preferred) or use - * g_strlcpy/g_strlcpy directly. */ -#define purple_strlcpy(dest, src) g_strlcpy(dest, src, sizeof(dest)) -#define purple_strlcat(dest, src) g_strlcat(dest, src, sizeof(dest)) - #define PURPLE_WEBSITE "http://pidgin.im/" #define PURPLE_DEVEL_WEBSITE "http://developer.pidgin.im/" @@ -176,12 +170,6 @@ 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); - /** * Creates a connection to the specified account and either connects * or attempts to register a new account. If you are logging in, diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/log.c --- a/libpurple/log.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/log.c Fri Apr 06 04:30:00 2012 +0000 @@ -1103,7 +1103,7 @@ /* Find the account for username in the list of accounts for protocol. */ username_unescaped = purple_unescape_filename(username); for (account_iter = g_list_first(accounts) ; account_iter != NULL ; account_iter = account_iter->next) { - if (purple_strequal(((PurpleAccount *)account_iter->data)->username, username_unescaped)) { + if (purple_strequal(purple_account_get_username((PurpleAccount *)account_iter->data), username_unescaped)) { account = account_iter->data; break; } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/log.h --- a/libpurple/log.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/log.h Fri Apr 06 04:30:00 2012 +0000 @@ -181,9 +181,7 @@ * IMPORTANT: Update that code if you add members here. */ }; -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /***************************************/ /** @name Log Functions */ @@ -301,8 +299,6 @@ * @param name The name of the log * @param account The account * @return The activity score - * - * @since 2.6.0 */ int purple_log_get_activity_score(PurpleLogType type, const char *name, PurpleAccount *account); @@ -576,8 +572,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_LOG_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/media-gst.h --- a/libpurple/media-gst.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/media-gst.h Fri Apr 06 04:30:00 2012 +0000 @@ -32,8 +32,6 @@ #include -G_BEGIN_DECLS - #define PURPLE_TYPE_MEDIA_ELEMENT_TYPE (purple_media_element_type_get_type()) #define PURPLE_TYPE_MEDIA_ELEMENT_INFO (purple_media_element_info_get_type()) #define PURPLE_MEDIA_ELEMENT_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_MEDIA_ELEMENT_INFO, PurpleMediaElementInfo)) @@ -73,16 +71,12 @@ PURPLE_MEDIA_ELEMENT_SINK = 1 << 10, /** can be set as an active sink */ } PurpleMediaElementType; -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /** * Gets the element type's GType. * * @return The element type's GType. - * - * @since 2.6.0 */ GType purple_media_element_type_get_type(void); @@ -90,8 +84,6 @@ * Gets the element info's GType. * * @return The element info's GType. - * - * @since 2.6.0 */ GType purple_media_element_info_get_type(void); @@ -102,8 +94,6 @@ * @param sess_id The session id of the session to get the source from. * * @return The source retrieved. - * - * @since 2.6.0 */ GstElement *purple_media_get_src(PurpleMedia *media, const gchar *sess_id); @@ -115,8 +105,6 @@ * @param participant Optionally, the participant of the stream to get the tee from. * * @return The GstTee element from the chosen session/stream. - * - * @since 2.6.0 */ GstElement *purple_media_get_tee(PurpleMedia *media, const gchar *session_id, const gchar *participant); @@ -128,8 +116,6 @@ * @param manager The media manager to get the pipeline from. * * @return The pipeline. - * - * @since 2.6.0 */ GstElement *purple_media_manager_get_pipeline(PurpleMediaManager *manager); @@ -141,8 +127,6 @@ * @param media The media call this element is requested for. * @param session_id The id of the session this element is requested for or NULL. * @param participant The remote user this element is requested for or NULL. - * - * @since 2.6.0 */ GstElement *purple_media_manager_get_element(PurpleMediaManager *manager, PurpleMediaSessionType type, PurpleMedia *media, @@ -167,8 +151,6 @@ * * @param manager The media manager to set the media formats. * @param caps Set of allowed media formats. - * - * @since 2.8.0 */ void purple_media_manager_set_video_caps(PurpleMediaManager *manager, GstCaps *caps); @@ -179,8 +161,6 @@ * @param manager The media manager to get the media formats from. * * @return @c GstCaps limiting the video source's formats. - * - * @since 2.8.0 */ GstCaps *purple_media_manager_get_video_caps(PurpleMediaManager *manager); @@ -192,10 +172,6 @@ PurpleMediaElementInfo *info, PurpleMedia *media, const gchar *session_id, const gchar *participant); -#ifdef __cplusplus -} -#endif - G_END_DECLS #endif /* _PURPLE_MEDIA_GST_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/media.h --- a/libpurple/media.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/media.h Fri Apr 06 04:30:00 2012 +0000 @@ -27,15 +27,13 @@ #ifndef _PURPLE_MEDIA_H_ #define _PURPLE_MEDIA_H_ +#include +#include + #include "media/candidate.h" #include "media/codec.h" #include "media/enum-types.h" -#include -#include - -G_BEGIN_DECLS - #define PURPLE_TYPE_MEDIA (purple_media_get_type()) #define PURPLE_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_MEDIA, PurpleMedia)) #define PURPLE_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_MEDIA, PurpleMediaClass)) @@ -49,16 +47,12 @@ #include "signals.h" #include "util.h" -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /** * Gets the media class's GType * * @return The media class's GType. - * - * @since 2.6.0 */ GType purple_media_get_type(void); @@ -68,8 +62,6 @@ * @param media The media session from which to retrieve session IDs. * * @return GList of session IDs. The caller must free the list. - * - * @since 2.6.0 */ GList *purple_media_get_session_ids(PurpleMedia *media); @@ -79,8 +71,6 @@ * @param media The media session to retrieve the account from. * * @return The account retrieved. - * - * @since 2.6.0 */ PurpleAccount *purple_media_get_account(PurpleMedia *media); @@ -90,8 +80,6 @@ * @param media The media session to retrieve the prpl data from. * * @return The prpl data retrieved. - * - * @since 2.6.0 */ gpointer purple_media_get_prpl_data(PurpleMedia *media); @@ -100,8 +88,6 @@ * * @param media The media session to set the prpl data on. * @param prpl_data The data to set on the media session. - * - * @since 2.6.0 */ void purple_media_set_prpl_data(PurpleMedia *media, gpointer prpl_data); @@ -111,8 +97,6 @@ * @param media The media object to set the state on. * @param error The format of the error message to send in the signal. * @param ... The arguments to plug into the format. - * - * @since 2.6.0 */ void purple_media_error(PurpleMedia *media, const gchar *error, ...); @@ -122,8 +106,6 @@ * @param media The media object with which to end streams. * @param session_id The session to end streams on. * @param participant The participant to end streams with. - * - * @since 2.6.0 */ void purple_media_end(PurpleMedia *media, const gchar *session_id, const gchar *participant); @@ -136,8 +118,6 @@ * @param session_id The id of the session of the stream being signaled. * @param participant The participant of the stream being signaled. * @param local TRUE if the info originated locally, FALSE if on the remote end. - * - * @since 2.6.0 */ void purple_media_stream_info(PurpleMedia *media, PurpleMediaInfoType type, const gchar *session_id, const gchar *participant, @@ -158,8 +138,6 @@ * @param media The media object to set the parameters on. * @param num_params The number of parameters to pass * @param params Array of @c GParameter to pass - * - * @since 2.8.0 */ void purple_media_set_params(PurpleMedia *media, guint num_params, GParameter *params); @@ -172,8 +150,6 @@ * @param media The media object * * @return NULL-terminated array of names of supported parameters. - * - * @since 2.8.0 */ const gchar **purple_media_get_available_params(PurpleMedia *media); @@ -184,8 +160,6 @@ * @param param name of parameter * * @return @c TRUE if backend recognizes the parameter, @c FALSE otherwise. - * - * @since 2.8.0 */ gboolean purple_media_param_is_supported(PurpleMedia *media, const gchar *param); @@ -205,8 +179,6 @@ * @param params The parameters to pass to Farsight. * * @return @c TRUE The stream was added successfully, @c FALSE otherwise. - * - * @since 2.6.0 */ gboolean purple_media_add_stream(PurpleMedia *media, const gchar *sess_id, const gchar *who, PurpleMediaSessionType type, @@ -220,8 +192,6 @@ * @param sess_id The session id of the session to get the type from. * * @return The retreived session type. - * - * @since 2.6.0 */ PurpleMediaSessionType purple_media_get_session_type(PurpleMedia *media, const gchar *sess_id); @@ -231,8 +201,6 @@ * @param media The media object to get the manager instance from. * * @return The PurpleMediaManager instance retrieved. - * - * @since 2.6.0 */ struct _PurpleMediaManager *purple_media_get_manager(PurpleMedia *media); @@ -243,8 +211,6 @@ * @param sess_id The session id of the session to get the codecs from. * * @return The retreieved codecs. - * - * @since 2.6.0 */ GList *purple_media_get_codecs(PurpleMedia *media, const gchar *sess_id); @@ -255,8 +221,6 @@ * @param sess_id The session id of the session find the stream in. * @param participant The name of the remote user to add the candidates for. * @param remote_candidates The remote candidates to add. - * - * @since 2.6.0 */ void purple_media_add_remote_candidates(PurpleMedia *media, const gchar *sess_id, @@ -269,8 +233,6 @@ * @param media The media object to find the session in. * @param sess_id The session id of the session to find the stream in. * @param participant The name of the remote user to get the candidates from. - * - * @since 2.6.0 */ GList *purple_media_get_local_candidates(PurpleMedia *media, const gchar *sess_id, @@ -285,8 +247,6 @@ * from. * * @return The active candidates retrieved. - * - * @since 2.8.0 */ GList *purple_media_get_active_local_candidates(PurpleMedia *media, const gchar *sess_id, const gchar *participant); @@ -300,8 +260,6 @@ * from. * * @return The remote candidates retrieved. - * - * @since 2.8.0 */ GList *purple_media_get_active_remote_candidates(PurpleMedia *media, const gchar *sess_id, const gchar *participant); @@ -315,8 +273,6 @@ * @param codecs The list of remote codecs to set. * * @return @c TRUE The codecs were set successfully, or @c FALSE otherwise. - * - * @since 2.6.0 */ gboolean purple_media_set_remote_codecs(PurpleMedia *media, const gchar *sess_id, const gchar *participant, GList *codecs); @@ -329,8 +285,6 @@ * @param participant The remote user to check for. * * @return @c TRUE All streams for the given session_id/participant combination have candidates prepared, @c FALSE otherwise. - * - * @since 2.6.0 */ gboolean purple_media_candidates_prepared(PurpleMedia *media, const gchar *session_id, const gchar *participant); @@ -343,8 +297,6 @@ * @param codec The codec to set the session to stream. * * @return @c TRUE The codec was successfully changed, or @c FALSE otherwise. - * - * @since 2.6.0 */ gboolean purple_media_set_send_codec(PurpleMedia *media, const gchar *sess_id, PurpleMediaCodec *codec); @@ -355,8 +307,6 @@ * @param sess_id The session id of the session to check. * * @return @c TRUE The codecs are ready, or @c FALSE otherwise. - * - * @since 2.6.0 */ gboolean purple_media_codecs_ready(PurpleMedia *media, const gchar *sess_id); @@ -368,8 +318,6 @@ * @param participant The participant of the stream to check. * * @return TRUE if the local user is the stream's initator, else FALSE. - * - * @since 2.6.0 */ gboolean purple_media_is_initiator(PurpleMedia *media, const gchar *sess_id, const gchar *participant); @@ -382,8 +330,6 @@ * @param participant The participant to check. * * @return @c TRUE The selected streams have been accepted, or @c FALSE otherwise. - * - * @since 2.6.0 */ gboolean purple_media_accepted(PurpleMedia *media, const gchar *sess_id, const gchar *participant); @@ -394,8 +340,6 @@ * @param media The media object the sessions are in. * @param session_id The session to select (if any). * @param level The level to set the volume to. - * - * @since 2.6.0 */ void purple_media_set_input_volume(PurpleMedia *media, const gchar *session_id, double level); @@ -406,8 +350,6 @@ * @param session_id The session to limit the streams to (if any). * @param participant The participant to limit the streams to (if any). * @param level The level to set the volume to. - * - * @since 2.6.0 */ void purple_media_set_output_volume(PurpleMedia *media, const gchar *session_id, const gchar *participant, double level); @@ -421,8 +363,6 @@ * @param window_id The window id use for embedding the video in. * * @return An id to reference the output window. - * - * @since 2.6.0 */ gulong purple_media_set_output_window(PurpleMedia *media, const gchar *session_id, const gchar *participant, @@ -432,15 +372,9 @@ * Removes all output windows from a given media session. * * @param media The instance to remove all output windows from. - * - * @since 2.6.0 */ void purple_media_remove_output_windows(PurpleMedia *media); -#ifdef __cplusplus -} -#endif - G_END_DECLS #endif /* _PURPLE_MEDIA_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/media/backend-fs2.h --- a/libpurple/media/backend-fs2.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/media/backend-fs2.h Fri Apr 06 04:30:00 2012 +0000 @@ -50,8 +50,6 @@ * Gets the type of the Farsight 2 media backend object. * * @return The Farsight 2 media backend's GType - * - * @since 2.7.0 */ GType purple_media_backend_fs2_get_type(void); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/media/backend-iface.h --- a/libpurple/media/backend-iface.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/media/backend-iface.h Fri Apr 06 04:30:00 2012 +0000 @@ -77,8 +77,6 @@ * Gets the media backend's GType. * * @return The media backend's GType. - * - * @since 2.7.0 */ GType purple_media_backend_get_type(void); @@ -95,8 +93,6 @@ * @param params The additional parameters to pass when creating the stream. * * @return True if the stream was successfully created, othewise False. - * - * @since 2.7.0 */ gboolean purple_media_backend_add_stream(PurpleMediaBackend *self, const gchar *sess_id, const gchar *who, @@ -111,8 +107,6 @@ * @param sess_id The session id associated with the stream. * @param participant The participant associated with the stream. * @param remote_candidates The list of remote candidates to add. - * - * @since 2.7.0 */ void purple_media_backend_add_remote_candidates(PurpleMediaBackend *self, const gchar *sess_id, const gchar *participant, @@ -128,8 +122,6 @@ * @param sess_id The session id of the session to check. * * @return True if the codecs are ready, otherwise False. - * - * @since 2.7.0 */ gboolean purple_media_backend_codecs_ready(PurpleMediaBackend *self, const gchar *sess_id); @@ -144,8 +136,6 @@ * @param sess_id The session id of the session to use. * * @return The codec intersection list. - * - * @since 2.7.0 */ GList *purple_media_backend_get_codecs(PurpleMediaBackend *self, const gchar *sess_id); @@ -158,8 +148,6 @@ * @param particilant The participant associated with the stream. * * @return The list of local candidates. - * - * @since 2.7.0 */ GList *purple_media_backend_get_local_candidates(PurpleMediaBackend *self, const gchar *sess_id, const gchar *participant); @@ -173,8 +161,6 @@ * @param codecs The list of remote codecs to set. * * @return True if the remote codecs were set successfully, otherwise False. - * - * @since 2.7.0 */ gboolean purple_media_backend_set_remote_codecs(PurpleMediaBackend *self, const gchar *sess_id, const gchar *participant, @@ -188,8 +174,6 @@ * @param codec The codec to set. * * @return True if set successfully, otherwise False. - * - * @since 2.7.0 */ gboolean purple_media_backend_set_send_codec(PurpleMediaBackend *self, const gchar *sess_id, PurpleMediaCodec *codec); @@ -200,8 +184,6 @@ * @param self The media backend to set the parameters on. * @param num_params The number of parameters to pass to backend * @param params Array of @c GParameter to pass to backend - * - * @since 2.8.0 */ void purple_media_backend_set_params(PurpleMediaBackend *self, guint num_params, GParameter *params); @@ -214,8 +196,6 @@ * @param self The media backend * * @return NULL-terminated array of names of supported parameters. - * - * @since 2.8.0 */ const gchar **purple_media_backend_get_available_params(PurpleMediaBackend *self); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/media/candidate.h --- a/libpurple/media/candidate.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/media/candidate.h Fri Apr 06 04:30:00 2012 +0000 @@ -47,8 +47,6 @@ * Gets the type of the media candidate structure. * * @return The media canditate's GType - * - * @since 2.6.0 */ GType purple_media_candidate_get_type(void); @@ -63,8 +61,6 @@ * @param port The network port. * * @return The newly created PurpleMediaCandidate instance. - * - * @since 2.6.0 */ PurpleMediaCandidate *purple_media_candidate_new( const gchar *foundation, guint component_id, @@ -78,8 +74,6 @@ * @param candidate The candidate to copy. * * @return The copy of the PurpleMediaCandidate. - * - * @since 2.7.0 */ PurpleMediaCandidate *purple_media_candidate_copy( PurpleMediaCandidate *candidate); @@ -90,8 +84,6 @@ * @param candidates The list of candidates to be copied. * * @return The copy of the GList. - * - * @since 2.6.0 */ GList *purple_media_candidate_list_copy(GList *candidates); @@ -99,8 +91,6 @@ * Frees a GList of PurpleMediaCandidate and its contents. * * @param candidates The list of candidates to be freed. - * - * @since 2.6.0 */ void purple_media_candidate_list_free(GList *candidates); @@ -110,8 +100,6 @@ * @param candidate The candidate to get the foundation from. * * @return The foundation. - * - * @since 2.6.0 */ gchar *purple_media_candidate_get_foundation(PurpleMediaCandidate *candidate); @@ -121,8 +109,6 @@ * @param candidate The candidate to get the compnent id from. * * @return The component id. - * - * @since 2.6.0 */ guint purple_media_candidate_get_component_id(PurpleMediaCandidate *candidate); @@ -132,8 +118,6 @@ * @param candidate The candidate to get the IP address from. * * @return The IP address. - * - * @since 2.6.0 */ gchar *purple_media_candidate_get_ip(PurpleMediaCandidate *candidate); @@ -143,8 +127,6 @@ * @param candidate The candidate to get the port from. * * @return The port. - * - * @since 2.6.0 */ guint16 purple_media_candidate_get_port(PurpleMediaCandidate *candidate); @@ -156,8 +138,6 @@ * @param candidate The candidate to get the base IP address from. * * @return The base IP address. - * - * @since 2.6.0 */ gchar *purple_media_candidate_get_base_ip(PurpleMediaCandidate *candidate); @@ -169,8 +149,6 @@ * @param candidate The candidate to get the base port. * * @return The base port. - * - * @since 2.6.0 */ guint16 purple_media_candidate_get_base_port(PurpleMediaCandidate *candidate); @@ -180,8 +158,6 @@ * @param candidate The candidate to get the protocol from. * * @return The protocol. - * - * @since 2.6.0 */ PurpleMediaNetworkProtocol purple_media_candidate_get_protocol( PurpleMediaCandidate *candidate); @@ -192,8 +168,6 @@ * @param candidate The candidate to get the priority from. * * @return The priority. - * - * @since 2.6.0 */ guint32 purple_media_candidate_get_priority(PurpleMediaCandidate *candidate); @@ -203,8 +177,6 @@ * @param candidate The candidate to get the candidate type from. * * @return The candidate type. - * - * @since 2.6.0 */ PurpleMediaCandidateType purple_media_candidate_get_candidate_type( PurpleMediaCandidate *candidate); @@ -217,8 +189,6 @@ * @param The candidate to get the username from. * * @return The username. - * - * @since 2.6.0 */ gchar *purple_media_candidate_get_username(PurpleMediaCandidate *candidate); @@ -230,8 +200,6 @@ * @param The candidate to get the password from. * * @return The password. - * - * @since 2.6.0 */ gchar *purple_media_candidate_get_password(PurpleMediaCandidate *candidate); @@ -241,8 +209,6 @@ * @param The candidate to get the TTL from. * * @return The TTL. - * - * @since 2.6.0 */ guint purple_media_candidate_get_ttl(PurpleMediaCandidate *candidate); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/media/codec.h --- a/libpurple/media/codec.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/media/codec.h Fri Apr 06 04:30:00 2012 +0000 @@ -50,8 +50,6 @@ * Gets the type of the media codec structure. * * @return The media codec's GType - * - * @since 2.6.0 */ GType purple_media_codec_get_type(void); @@ -64,8 +62,6 @@ * @param clock_rate The clock rate this codec encodes at, if applicable. * * @return The newly created PurpleMediaCodec. - * - * @since 2.6.0 */ PurpleMediaCodec *purple_media_codec_new(int id, const char *encoding_name, PurpleMediaSessionType media_type, guint clock_rate); @@ -76,8 +72,6 @@ * @param The codec to get the id from. * * @return The codec id. - * - * @since 2.6.0 */ guint purple_media_codec_get_id(PurpleMediaCodec *codec); @@ -87,8 +81,6 @@ * @param The codec to get the encoding name from. * * @return The encoding name. - * - * @since 2.6.0 */ gchar *purple_media_codec_get_encoding_name(PurpleMediaCodec *codec); @@ -98,8 +90,6 @@ * @param The codec to get the clock rate from. * * @return The clock rate. - * - * @since 2.6.0 */ guint purple_media_codec_get_clock_rate(PurpleMediaCodec *codec); @@ -109,8 +99,6 @@ * @param The codec to get the number of channels from. * * @return The number of channels. - * - * @since 2.6.0 */ guint purple_media_codec_get_channels(PurpleMediaCodec *codec); @@ -123,8 +111,6 @@ * * @return The list of optional parameters. The list is owned by the codec and * should not be freed. - * - * @since 2.6.0 */ GList *purple_media_codec_get_optional_parameters(PurpleMediaCodec *codec); @@ -134,8 +120,6 @@ * @param codec The codec to add the parameter to. * @param name The name of the parameter to add. * @param value The value of the parameter to add. - * - * @since 2.6.0 */ void purple_media_codec_add_optional_parameter(PurpleMediaCodec *codec, const gchar *name, const gchar *value); @@ -145,8 +129,6 @@ * * @param codec The codec to remove the parameter from. * @param param A pointer to the parameter to remove. - * - * @since 2.6.0 */ void purple_media_codec_remove_optional_parameter(PurpleMediaCodec *codec, PurpleKeyValuePair *param); @@ -159,8 +141,6 @@ * @param value The value to search for or NULL. * * @return The value found or NULL. - * - * @since 2.6.0 */ PurpleKeyValuePair *purple_media_codec_get_optional_parameter( PurpleMediaCodec *codec, const gchar *name, @@ -172,8 +152,6 @@ * @param codec The codec to copy. * * @return The copy of the codec. - * - * @since 2.7.0 */ PurpleMediaCodec *purple_media_codec_copy(PurpleMediaCodec *codec); @@ -183,8 +161,6 @@ * @param codecs The list of codecs to be copied. * * @return The copy of the GList. - * - * @since 2.6.0 */ GList *purple_media_codec_list_copy(GList *codecs); @@ -192,8 +168,6 @@ * Frees a GList of PurpleMediaCodec and its contents. * * @param codecs The list of codecs to be freed. - * - * @since 2.6.0 */ void purple_media_codec_list_free(GList *codecs); @@ -203,8 +177,6 @@ * @param codec The codec to create the string of. * * @return The new string representation. - * - * @since 2.6.0 */ gchar *purple_media_codec_to_string(const PurpleMediaCodec *codec); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/media/enum-types.h --- a/libpurple/media/enum-types.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/media/enum-types.h Fri Apr 06 04:30:00 2012 +0000 @@ -107,8 +107,6 @@ * Gets the media candidate type's GType * * @return The media candidate type's GType. - * - * @since 2.6.0 */ GType purple_media_candidate_type_get_type(void); @@ -116,8 +114,6 @@ * Gets the type of the media caps flags * * @return The media caps flags' GType - * - * @since 2.7.0 */ GType purple_media_caps_get_type(void); @@ -125,8 +121,6 @@ * Gets the type of the info type enum * * @return The info type enum's GType - * - * @since 2.6.0 */ GType purple_media_info_type_get_type(void); @@ -134,8 +128,6 @@ * Gets the media network protocol's GType * * @return The media network protocol's GType. - * - * @since 2.6.0 */ GType purple_media_network_protocol_get_type(void); @@ -143,8 +135,6 @@ * Gets the media session type's GType * * @return The media session type's GType. - * - * @since 2.6.0 */ GType purple_media_session_type_get_type(void); @@ -152,8 +142,6 @@ * Gets the type of the state-changed enum * * @return The state-changed enum's GType - * - * @since 2.6.0 */ GType purple_media_state_changed_get_type(void); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/mediamanager.h --- a/libpurple/mediamanager.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/mediamanager.h Fri Apr 06 04:30:00 2012 +0000 @@ -38,8 +38,6 @@ #include "account.h" #include "media.h" -G_BEGIN_DECLS - #define PURPLE_TYPE_MEDIA_MANAGER (purple_media_manager_get_type()) #define PURPLE_MEDIA_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_MEDIA_MANAGER, PurpleMediaManager)) #define PURPLE_MEDIA_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_MEDIA_MANAGER, PurpleMediaManagerClass)) @@ -47,9 +45,7 @@ #define PURPLE_IS_MEDIA_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_MEDIA_MANAGER)) #define PURPLE_MEDIA_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_MEDIA_MANAGER, PurpleMediaManagerClass)) -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Media Manager API */ @@ -60,8 +56,6 @@ * Gets the media manager's GType. * * @return The media manager's GType. - * - * @since 2.6.0 */ GType purple_media_manager_get_type(void); @@ -69,8 +63,6 @@ * Gets the "global" media manager object. It's created if it doesn't already exist. * * @return The "global" instance of the media manager object. - * - * @since 2.6.0 */ PurpleMediaManager *purple_media_manager_get(void); @@ -84,8 +76,6 @@ * @param initiator TRUE if the local user is the initiator of this media call, FALSE otherwise. * * @return A newly created media session. - * - * @since 2.6.0 */ PurpleMedia *purple_media_manager_create_media(PurpleMediaManager *manager, PurpleAccount *account, @@ -99,8 +89,6 @@ * @param manager The media manager to get all of the sessions from. * * @return A list of all the media sessions. - * - * @since 2.6.0 */ GList *purple_media_manager_get_media(PurpleMediaManager *manager); @@ -111,8 +99,6 @@ * @param account The account the sessions are on. * * @return A list of the media sessions on the given account. - * - * @since 2.6.0 */ GList *purple_media_manager_get_media_by_account( PurpleMediaManager *manager, PurpleAccount *account); @@ -122,8 +108,6 @@ * * @param manager The media manager to remove the media session from. * @param media The media session to remove. - * - * @since 2.6.0 */ void purple_media_manager_remove_media(PurpleMediaManager *manager, @@ -140,8 +124,6 @@ * @param participant The participant the output windows are registered with. * * @return TRUE if it succeeded, FALSE if it failed. - * - * @since 2.6.0 */ gboolean purple_media_manager_create_output_window( PurpleMediaManager *manager, PurpleMedia *media, @@ -157,8 +139,6 @@ * @param window_id The window ID to embed the video in. * * @return A unique ID to the registered output window, 0 if it failed. - * - * @since 2.6.0 */ gulong purple_media_manager_set_output_window(PurpleMediaManager *manager, PurpleMedia *media, const gchar *session_id, @@ -171,8 +151,6 @@ * @param output_window_id The ID of the output window. * * @return TRUE if it found the output window and was successful, else FALSE. - * - * @since 2.6.0 */ gboolean purple_media_manager_remove_output_window( PurpleMediaManager *manager, gulong output_window_id); @@ -184,8 +162,6 @@ * @param media The media instance the output windows were registered for. * @param session_id The session the output windows were registered for. * @param participant The participant the output windows were registered for. - * - * @since 2.6.0 */ void purple_media_manager_remove_output_windows( PurpleMediaManager *manager, PurpleMedia *media, @@ -196,8 +172,6 @@ * * @param manager The manager to set the caps on. * @param caps The caps to set. - * - * @since 2.6.0 */ void purple_media_manager_set_ui_caps(PurpleMediaManager *manager, PurpleMediaCaps caps); @@ -208,8 +182,6 @@ * @param manager The manager to get caps from. * * @return caps The caps retrieved. - * - * @since 2.6.0 */ PurpleMediaCaps purple_media_manager_get_ui_caps(PurpleMediaManager *manager); @@ -218,8 +190,6 @@ * * @param manager The manager to set the caps on. * @param backend_type The media backend type to use. - * - * @since 2.7.0 */ void purple_media_manager_set_backend_type(PurpleMediaManager *manager, GType backend_type); @@ -230,17 +200,11 @@ * @param manager The manager to get the media backend type from. * * @return The type of media backend type media objects will use. - * - * @since 2.7.0 */ GType purple_media_manager_get_backend_type(PurpleMediaManager *manager); /*}@*/ -#ifdef __cplusplus -} -#endif - G_END_DECLS #endif /* _PURPLE_MEDIA_MANAGER_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/mime.h --- a/libpurple/mime.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/mime.h Fri Apr 06 04:30:00 2012 +0000 @@ -26,10 +26,6 @@ #include -#ifdef __cplusplus -extern "C" { -#endif - /** * @file mime.h * @ingroup core @@ -48,6 +44,8 @@ */ typedef struct _PurpleMimePart PurpleMimePart; +G_BEGIN_DECLS + /** * Allocate an empty MIME document. */ @@ -211,8 +209,6 @@ void purple_mime_part_set_data(PurpleMimePart *part, const char *data); -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/nat-pmp.h --- a/libpurple/nat-pmp.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/nat-pmp.h Fri Apr 06 04:30:00 2012 +0000 @@ -41,6 +41,8 @@ PURPLE_PMP_TYPE_TCP } PurplePmpType; +G_BEGIN_DECLS + /** * Initialize nat-pmp */ @@ -54,24 +56,28 @@ /** * Remove the NAT-PMP mapping for a specified type on a specified port * - * @param type The PurplePmpType + * @param type The PurplePmpType * @param privateport The private port on which we are listening locally - * @param publicport The public port on which we are expecting a response - * @param lifetime The lifetime of the mapping. It is recommended that this be PURPLE_PMP_LIFETIME. + * @param publicport The public port on which we are expecting a response + * @param lifetime The lifetime of the mapping. It is recommended that this + * be PURPLE_PMP_LIFETIME. * - * @returns TRUE if succesful; FALSE if unsuccessful + * @returns TRUE if successful; FALSE if unsuccessful */ -gboolean purple_pmp_create_map(PurplePmpType type, unsigned short privateport, unsigned short publicport, int lifetime); +gboolean purple_pmp_create_map(PurplePmpType type, unsigned short privateport, + unsigned short publicport, int lifetime); /** * Remove the NAT-PMP mapping for a specified type on a specified port * - * @param type The PurplePmpType + * @param type The PurplePmpType * @param privateport The private port on which the mapping was previously made * - * @returns TRUE if succesful; FALSE if unsuccessful + * @returns TRUE if successful; FALSE if unsuccessful */ gboolean purple_pmp_destroy_map(PurplePmpType type, unsigned short privateport); +G_END_DECLS + #endif diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/network.c --- a/libpurple/network.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/network.c Fri Apr 06 04:30:00 2012 +0000 @@ -391,14 +391,9 @@ return FALSE; } -static gboolean listen_map_external = TRUE; -void purple_network_listen_map_external(gboolean map_external) -{ - listen_map_external = map_external; -} - static PurpleNetworkListenData * -purple_network_do_listen(unsigned short port, int socket_family, int socket_type, PurpleNetworkListenCallback cb, gpointer cb_data) +purple_network_do_listen(unsigned short port, int socket_family, int socket_type, gboolean map_external, + PurpleNetworkListenCallback cb, gpointer cb_data) { int listenfd = -1; int flags; @@ -503,7 +498,7 @@ listen_data->cb_data = cb_data; listen_data->socket_type = socket_type; - if (!purple_socket_speaks_ipv4(listenfd) || !listen_map_external || + if (!purple_socket_speaks_ipv4(listenfd) || !map_external || !purple_prefs_get_bool("/purple/network/map_ports")) { purple_debug_info("network", "Skipping external port mapping.\n"); @@ -531,27 +526,19 @@ } PurpleNetworkListenData * -purple_network_listen_family(unsigned short port, int socket_family, - int socket_type, PurpleNetworkListenCallback cb, +purple_network_listen(unsigned short port, int socket_family, int socket_type, + gboolean map_external, PurpleNetworkListenCallback cb, gpointer cb_data) { g_return_val_if_fail(port != 0, NULL); - return purple_network_do_listen(port, socket_family, socket_type, + return purple_network_do_listen(port, socket_family, socket_type, map_external, cb, cb_data); } PurpleNetworkListenData * -purple_network_listen(unsigned short port, int socket_type, - PurpleNetworkListenCallback cb, gpointer cb_data) -{ - return purple_network_listen_family(port, AF_UNSPEC, socket_type, - cb, cb_data); -} - -PurpleNetworkListenData * -purple_network_listen_range_family(unsigned short start, unsigned short end, - int socket_family, int socket_type, +purple_network_listen_range(unsigned short start, unsigned short end, + int socket_family, int socket_type, gboolean map_external, PurpleNetworkListenCallback cb, gpointer cb_data) { @@ -566,7 +553,7 @@ } for (; start <= end; start++) { - ret = purple_network_do_listen(start, AF_UNSPEC, socket_type, cb, cb_data); + ret = purple_network_do_listen(start, AF_UNSPEC, socket_type, map_external, cb, cb_data); if (ret != NULL) break; } @@ -574,15 +561,6 @@ return ret; } -PurpleNetworkListenData * -purple_network_listen_range(unsigned short start, unsigned short end, - int socket_type, PurpleNetworkListenCallback cb, - gpointer cb_data) -{ - return purple_network_listen_range_family(start, end, AF_UNSPEC, - socket_type, cb, cb_data); -} - void purple_network_listen_cancel(PurpleNetworkListenData *listen_data) { if (listen_data->mapping_data != NULL) @@ -1003,7 +981,7 @@ if (stun_server && stun_server[0] != '\0') { if (purple_network_is_available()) { purple_debug_info("network", "running DNS query for STUN server\n"); - purple_dnsquery_a_account(NULL, stun_server, 3478, purple_network_ip_lookup_cb, + purple_dnsquery_a(NULL, stun_server, 3478, purple_network_ip_lookup_cb, &stun_ip); } else { purple_debug_info("network", @@ -1021,7 +999,7 @@ if (turn_server && turn_server[0] != '\0') { if (purple_network_is_available()) { purple_debug_info("network", "running DNS query for TURN server\n"); - purple_dnsquery_a_account(NULL, turn_server, + purple_dnsquery_a(NULL, turn_server, purple_prefs_get_int("/purple/network/turn_port"), purple_network_ip_lookup_cb, &turn_ip); } else { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/network.h --- a/libpurple/network.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/network.h Fri Apr 06 04:30:00 2012 +0000 @@ -26,9 +26,9 @@ #ifndef _PURPLE_NETWORK_H_ #define _PURPLE_NETWORK_H_ -#ifdef __cplusplus -extern "C" { -#endif +#include + +G_BEGIN_DECLS /**************************************************************************/ /** @name Network API */ @@ -92,7 +92,6 @@ * * @note The caller must free this list. If libpurple was built with * support for it, this function also enumerates IPv6 addresses. - * @since 2.7.0 * * @return A list of local IP addresses. */ @@ -118,18 +117,6 @@ const char *purple_network_get_my_ip(int fd); /** - * Should calls to purple_network_listen() and purple_network_listen_range() - * map the port externally using NAT-PMP or UPnP? - * The default value is TRUE - * - * @param map_external Should the open port be mapped externally? - * @deprecated In 3.0.0 a boolean will be added to the functions mentioned - * above to perform the same function. - * @since 2.3.0 - */ -void purple_network_listen_map_external(gboolean map_external); - -/** * Attempts to open a listening port ONLY on the specified port number. * You probably want to use purple_network_listen_range() instead of this. * This function is useful, for example, if you wanted to write a telnet @@ -142,9 +129,22 @@ * close the listening socket, and add a new watcher on the new socket accept * returned. * + * Libpurple does not currently do any port mapping (stateful firewall hole + * poking) for IPv6-only listeners (if an IPv6 socket supports v4-mapped + * addresses, a mapping is done). + * * @param port The port number to bind to. Must be greater than 0. + * @param socket_family The protocol family of the socket. This should be + * AF_INET for IPv4 or AF_INET6 for IPv6. IPv6 sockets + * may or may not be able to accept IPv4 connections + * based on the system configuration (use + * purple_socket_speaks_ipv4 to check). If an IPv6 + * socket doesn't accept V4-mapped addresses, you will + * need a second listener to support both v4 and v6. * @param socket_type The type of socket to open for listening. * This will be either SOCK_STREAM for TCP or SOCK_DGRAM for UDP. + * @param map_external Should the open port be mapped externally using + * NAT-PNP or UPnP? (default should be TRUE) * @param cb The callback to be invoked when the port to listen on is available. * The file descriptor of the listening socket will be specified in * this callback, or -1 if no socket could be established. @@ -155,28 +155,8 @@ * socket to listen on. */ PurpleNetworkListenData *purple_network_listen(unsigned short port, - int socket_type, PurpleNetworkListenCallback cb, gpointer cb_data); - -/** - * \copydoc purple_network_listen - * - * Libpurple does not currently do any port mapping (stateful firewall hole - * poking) for IPv6-only listeners (if an IPv6 socket supports v4-mapped - * addresses, a mapping is done). - * - * @param socket_family The protocol family of the socket. This should be - * AF_INET for IPv4 or AF_INET6 for IPv6. IPv6 sockets - * may or may not be able to accept IPv4 connections - * based on the system configuration (use - * purple_socket_speaks_ipv4 to check). If an IPv6 - * socket doesn't accept V4-mapped addresses, you will - * need a second listener to support both v4 and v6. - * @since 2.7.0 - * @deprecated This function will be renamed to purple_network_listen in 3.0.0. - */ -PurpleNetworkListenData *purple_network_listen_family(unsigned short port, - int socket_family, int socket_type, PurpleNetworkListenCallback cb, - gpointer cb_data); + int socket_family, int socket_type, gboolean map_external, + PurpleNetworkListenCallback cb, gpointer cb_data); /** * Opens a listening port selected from a range of ports. The range of @@ -192,13 +172,26 @@ * the listening socket, and add a new watcher on the new socket accept * returned. * + * Libpurple does not currently do any port mapping (stateful firewall hole + * poking) for IPv6-only listeners (if an IPv6 socket supports v4-mapped + * addresses, a mapping is done). + * * @param start The port number to bind to, or 0 to pick a random port. * Users are allowed to override this arg in prefs. * @param end The highest possible port in the range of ports to listen on, * or 0 to pick a random port. Users are allowed to override this * arg in prefs. + * @param socket_family The protocol family of the socket. This should be + * AF_INET for IPv4 or AF_INET6 for IPv6. IPv6 sockets + * may or may not be able to accept IPv4 connections + * based on the system configuration (use + * purple_socket_speaks_ipv4 to check). If an IPv6 + * socket doesn't accept V4-mapped addresses, you will + * need a second listener to support both v4 and v6. * @param socket_type The type of socket to open for listening. * This will be either SOCK_STREAM for TCP or SOCK_DGRAM for UDP. + * @param map_external Should the open port be mapped externally using + * NAT-PNP or UPnP? (default should be TRUE) * @param cb The callback to be invoked when the port to listen on is available. * The file descriptor of the listening socket will be specified in * this callback, or -1 if no socket could be established. @@ -208,31 +201,10 @@ * the pending listener, or NULL if unable to obtain a local * socket to listen on. */ -PurpleNetworkListenData *purple_network_listen_range(unsigned short start, - unsigned short end, int socket_type, - PurpleNetworkListenCallback cb, gpointer cb_data); - -/** - * \copydoc purple_network_listen_range - * - * Libpurple does not currently do any port mapping (stateful firewall hole - * poking) for IPv6-only listeners (if an IPv6 socket supports v4-mapped - * addresses, a mapping is done). - * - * @param socket_family The protocol family of the socket. This should be - * AF_INET for IPv4 or AF_INET6 for IPv6. IPv6 sockets - * may or may not be able to accept IPv4 connections - * based on the system configuration (use - * purple_socket_speaks_ipv4 to check). If an IPv6 - * socket doesn't accept V4-mapped addresses, you will - * need a second listener to support both v4 and v6. - * @since 2.7.0 - * @deprecated This function will be renamed to purple_network_listen_range - * in 3.0.0. - */ -PurpleNetworkListenData *purple_network_listen_range_family( +PurpleNetworkListenData *purple_network_listen_range( unsigned short start, unsigned short end, int socket_family, - int socket_type, PurpleNetworkListenCallback cb, gpointer cb_data); + int socket_type, gboolean map_external, + PurpleNetworkListenCallback cb, gpointer cb_data); /** * This can be used to cancel any in-progress listener connection @@ -267,8 +239,6 @@ * This is what backs the --force-online command line argument in Pidgin, * for example. This is useful for offline testing, especially when * combined with nullprpl. - * - * @since 2.6.0 */ void purple_network_force_online(void); @@ -284,7 +254,6 @@ * Will result in a DNS query being executed asynchronous * * @param stun_server The host name of the STUN server to set - * @since 2.6.0 */ void purple_network_set_stun_server(const gchar *stun_server); @@ -292,7 +261,6 @@ * Get the IP address of the STUN server as a string representation * * @return the IP address - * @since 2.6.0 */ const gchar *purple_network_get_stun_ip(void); @@ -301,7 +269,6 @@ * Will result in a DNS query being executed asynchronous * * @param turn_server The host name of the TURN server to set - * @since 2.6.0 */ void purple_network_set_turn_server(const gchar *turn_server); @@ -309,7 +276,6 @@ * Get the IP address of the TURN server as a string representation * * @return the IP address - * @since 2.6.0 */ const gchar *purple_network_get_turn_ip(void); @@ -317,7 +283,6 @@ * Remove a port mapping (UPnP or NAT-PMP) associated with listening socket * * @param fd Socket to remove the port mapping for - * @since 2.6.0 */ void purple_network_remove_port_mapping(gint fd); @@ -336,7 +301,6 @@ * The caller is responsible for freeing this. * @returns 0 on success, -1 if the out is NULL, or an error code * that currently corresponds to the Idna_rc enum in libidn. - * @since 2.6.0 */ int purple_network_convert_idn_to_ascii(const gchar *in, gchar **out); @@ -352,8 +316,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_NETWORK_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/notify.c --- a/libpurple/notify.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/notify.c Fri Apr 06 04:30:00 2012 +0000 @@ -53,7 +53,17 @@ struct _PurpleNotifyUserInfo { - GList *user_info_entries; + GQueue entries; +}; + +/** + * Single column of a search result. + */ +struct _PurpleNotifySearchColumn +{ + char *title; /**< Title of the column. */ + gboolean visible; /**< Should the column be visible to the user. Defaults to TRUE. */ + }; void * @@ -363,42 +373,31 @@ sc = g_new0(PurpleNotifySearchColumn, 1); sc->title = g_strdup(title); + sc->visible = TRUE; return sc; } -guint -purple_notify_searchresults_get_columns_count(PurpleNotifySearchResults *results) +const char *purple_notify_searchresult_column_get_title(const PurpleNotifySearchColumn *column) { - g_return_val_if_fail(results != NULL, 0); - - return g_list_length(results->columns); -} - -guint -purple_notify_searchresults_get_rows_count(PurpleNotifySearchResults *results) -{ - g_return_val_if_fail(results != NULL, 0); - - return g_list_length(results->rows); + g_return_val_if_fail(column != NULL, NULL); + + return column->title; } -char * -purple_notify_searchresults_column_get_title(PurpleNotifySearchResults *results, - unsigned int column_id) +void purple_notify_searchresult_column_set_visible(PurpleNotifySearchColumn *column, gboolean visible) { - g_return_val_if_fail(results != NULL, NULL); + g_return_if_fail(column != NULL); - return ((PurpleNotifySearchColumn *)g_list_nth_data(results->columns, column_id))->title; + column->visible = visible; } -GList * -purple_notify_searchresults_row_get(PurpleNotifySearchResults *results, - unsigned int row_id) +gboolean +purple_notify_searchresult_column_is_visible(const PurpleNotifySearchColumn *column) { - g_return_val_if_fail(results != NULL, NULL); + g_return_val_if_fail(column != NULL, FALSE); - return g_list_nth_data(results->rows, row_id); + return column->visible; } void * @@ -472,7 +471,7 @@ user_info = g_new0(PurpleNotifyUserInfo, 1); PURPLE_DBUS_REGISTER_POINTER(user_info, PurpleNotifyUserInfo); - user_info->user_info_entries = NULL; + g_queue_init(&user_info->entries); return user_info; } @@ -482,23 +481,23 @@ { GList *l; - for (l = user_info->user_info_entries; l != NULL; l = l->next) { + for (l = user_info->entries.head; l != NULL; l = l->next) { PurpleNotifyUserInfoEntry *user_info_entry = l->data; purple_notify_user_info_entry_destroy(user_info_entry); } - g_list_free(user_info->user_info_entries); + g_queue_clear(&user_info->entries); PURPLE_DBUS_UNREGISTER_POINTER(user_info); g_free(user_info); } -GList * +GQueue * purple_notify_user_info_get_entries(PurpleNotifyUserInfo *user_info) { g_return_val_if_fail(user_info != NULL, NULL); - return user_info->user_info_entries; + return &user_info->entries; } char * @@ -509,7 +508,7 @@ text = g_string_new(""); - for (l = user_info->user_info_entries; l != NULL; l = l->next) { + for (l = user_info->entries.head; l != NULL; l = l->next) { PurpleNotifyUserInfoEntry *user_info_entry = l->data; /* Add a newline before a section header */ if (user_info_entry->type == PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER) @@ -593,33 +592,41 @@ } void -purple_notify_user_info_add_pair(PurpleNotifyUserInfo *user_info, const char *label, const char *value) +purple_notify_user_info_add_pair_html(PurpleNotifyUserInfo *user_info, const char *label, const char *value) { PurpleNotifyUserInfoEntry *entry; entry = purple_notify_user_info_entry_new(label, value); - user_info->user_info_entries = g_list_append(user_info->user_info_entries, entry); + g_queue_push_tail(&user_info->entries, entry); } void purple_notify_user_info_add_pair_plaintext(PurpleNotifyUserInfo *user_info, const char *label, const char *value) { gchar *escaped; - PurpleNotifyUserInfoEntry *entry; escaped = g_markup_escape_text(value, -1); - entry = purple_notify_user_info_entry_new(label, escaped); + purple_notify_user_info_add_pair_html(user_info, label, escaped); g_free(escaped); - user_info->user_info_entries = g_list_append(user_info->user_info_entries, entry); } void -purple_notify_user_info_prepend_pair(PurpleNotifyUserInfo *user_info, const char *label, const char *value) +purple_notify_user_info_prepend_pair_html(PurpleNotifyUserInfo *user_info, const char *label, const char *value) { PurpleNotifyUserInfoEntry *entry; entry = purple_notify_user_info_entry_new(label, value); - user_info->user_info_entries = g_list_prepend(user_info->user_info_entries, entry); + g_queue_push_head(&user_info->entries, entry); +} + +void +purple_notify_user_info_prepend_pair_plaintext(PurpleNotifyUserInfo *user_info, const char *label, const char *value) +{ + gchar *escaped; + + escaped = g_markup_escape_text(value, -1); + purple_notify_user_info_prepend_pair_html(user_info, label, escaped); + g_free(escaped); } void @@ -628,7 +635,7 @@ g_return_if_fail(user_info != NULL); g_return_if_fail(entry != NULL); - user_info->user_info_entries = g_list_remove(user_info->user_info_entries, entry); + g_queue_remove(&user_info->entries, entry); } void @@ -639,7 +646,7 @@ entry = purple_notify_user_info_entry_new(label, NULL); entry->type = PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER; - user_info->user_info_entries = g_list_append(user_info->user_info_entries, entry); + g_queue_push_tail(&user_info->entries, entry); } void @@ -650,7 +657,7 @@ entry = purple_notify_user_info_entry_new(label, NULL); entry->type = PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER; - user_info->user_info_entries = g_list_prepend(user_info->user_info_entries, entry); + g_queue_push_head(&user_info->entries, entry); } void @@ -661,7 +668,7 @@ entry = purple_notify_user_info_entry_new(NULL, NULL); entry->type = PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK; - user_info->user_info_entries = g_list_append(user_info->user_info_entries, entry); + g_queue_push_tail(&user_info->entries, entry); } void @@ -672,17 +679,17 @@ entry = purple_notify_user_info_entry_new(NULL, NULL); entry->type = PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_BREAK; - user_info->user_info_entries = g_list_prepend(user_info->user_info_entries, entry); + g_queue_push_head(&user_info->entries, entry); } void purple_notify_user_info_remove_last_item(PurpleNotifyUserInfo *user_info) { - GList *last = g_list_last(user_info->user_info_entries); - if (last) { - purple_notify_user_info_entry_destroy(last->data); - user_info->user_info_entries = g_list_delete_link(user_info->user_info_entries, last); - } + PurpleNotifyUserInfoEntry *entry; + + entry = g_queue_pop_tail(&user_info->entries); + if (entry) + purple_notify_user_info_entry_destroy(entry); } void * diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/notify.h --- a/libpurple/notify.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/notify.h Fri Apr 06 04:30:00 2012 +0000 @@ -32,10 +32,13 @@ #include typedef struct _PurpleNotifyUserInfoEntry PurpleNotifyUserInfoEntry; -typedef struct _PurpleNotifyUserInfo PurpleNotifyUserInfo; +typedef struct _PurpleNotifyUserInfo PurpleNotifyUserInfo; +/** @copydoc _PurpleNotifySearchColumn */ +typedef struct _PurpleNotifySearchColumn PurpleNotifySearchColumn; #include "connection.h" + /** * Notification close callbacks. */ @@ -106,14 +109,6 @@ PURPLE_NOTIFY_USER_INFO_ENTRY_SECTION_HEADER } PurpleNotifyUserInfoEntryType; -/** - * Single column of a search result. - */ -typedef struct -{ - char *title; /**< Title of the column. */ - -} PurpleNotifySearchColumn; /** @@ -180,9 +175,7 @@ } PurpleNotifyUiOps; -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ @@ -266,7 +259,8 @@ PurpleNotifySearchResults *purple_notify_searchresults_new(void); /** - * Returns a newly created search result column object. + * Returns a newly created search result column object. The column defaults + * to being visible. * * @param title Title of the column. NOTE: Title will get g_strdup()ed. * @@ -275,6 +269,32 @@ PurpleNotifySearchColumn *purple_notify_searchresults_column_new(const char *title); /** + * Returns the title of the column + * + * @param column The search column object. + * + * @return The title of the column + */ +const char *purple_notify_searchresult_column_get_title(const PurpleNotifySearchColumn *column); + +/** + * Sets whether or not a search result column is visible. + * + * @param column The search column object. + * @param visible TRUE if visible, or FALSE if not. + */ +void purple_notify_searchresult_column_set_visible(PurpleNotifySearchColumn *column, gboolean visible); + +/** + * Returns whether or not a search result column is visible. + * + * @param column The search column object. + * + * @return TRUE if the search result column is visible. FALSE otherwise. + */ +gboolean purple_notify_searchresult_column_is_visible(const PurpleNotifySearchColumn *column); + +/** * Adds a new column to the search result object. * * @param results The result object to which the column will be added. @@ -292,92 +312,6 @@ void purple_notify_searchresults_row_add(PurpleNotifySearchResults *results, GList *row); -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_NOTIFY_C_) -/** - * Returns a number of the rows in the search results object. - * - * @deprecated This function will be removed in Pidgin 3.0.0 unless - * there is sufficient demand to keep it. Using this - * function encourages looping through the results - * inefficiently. Instead of using this function you - * should iterate through the results using a loop - * similar to this: - * for (l = results->rows; l != NULL; l = l->next) - * If you really need to get the number of rows you - * can use g_list_length(results->rows). - * - * @param results The search results object. - * - * @return Number of the result rows. - */ -guint purple_notify_searchresults_get_rows_count(PurpleNotifySearchResults *results); -#endif - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_NOTIFY_C_) -/** - * Returns a number of the columns in the search results object. - * - * @deprecated This function will be removed in Pidgin 3.0.0 unless - * there is sufficient demand to keep it. Using this - * function encourages looping through the columns - * inefficiently. Instead of using this function you - * should iterate through the columns using a loop - * similar to this: - * for (l = results->columns; l != NULL; l = l->next) - * If you really need to get the number of columns you - * can use g_list_length(results->columns). - * - * @param results The search results object. - * - * @return Number of the columns. - */ -guint purple_notify_searchresults_get_columns_count(PurpleNotifySearchResults *results); -#endif - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_NOTIFY_C_) -/** - * Returns a row of the results from the search results object. - * - * @deprecated This function will be removed in Pidgin 3.0.0 unless - * there is sufficient demand to keep it. Using this - * function encourages looping through the results - * inefficiently. Instead of using this function you - * should iterate through the results using a loop - * similar to this: - * for (l = results->rows; l != NULL; l = l->next) - * If you really need to get the data for a particular - * row you can use g_list_nth_data(results->rows, row_id). - * - * @param results The search results object. - * @param row_id Index of the row to be returned. - * - * @return Row of the results. - */ -GList *purple_notify_searchresults_row_get(PurpleNotifySearchResults *results, - unsigned int row_id); -#endif - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_NOTIFY_C_) -/** - * Returns a title of the search results object's column. - * - * @deprecated This function will be removed in Pidgin 3.0.0 unless - * there is sufficient demand to keep it. Using this - * function encourages looping through the columns - * inefficiently. Instead of using this function you - * should iterate through the name of a particular - * column you can use - * g_list_nth_data(results->columns, row_id). - * - * @param results The search results object. - * @param column_id Index of the column. - * - * @return Title of the column. - */ -char *purple_notify_searchresults_column_get_title(PurpleNotifySearchResults *results, - unsigned int column_id); -#endif - /*@}*/ /**************************************************************************/ @@ -506,20 +440,20 @@ * Retrieve the array of PurpleNotifyUserInfoEntry objects from a * PurpleNotifyUserInfo * - * This GList may be manipulated directly with normal GList functions such - * as g_list_insert(). Only PurpleNotifyUserInfoEntry are allowed in the - * list. If a PurpleNotifyUserInfoEntry item is added to the list, it - * should not be g_free()'d by the caller; PurpleNotifyUserInfo will g_free - * it when destroyed. + * This GQueue may be manipulated directly with normal GQueue functions such + * as g_queue_push_tail(). Only PurpleNotifyUserInfoEntry are allowed in the + * queue. If a PurpleNotifyUserInfoEntry item is added to the queue, it + * should not be freed by the caller; PurpleNotifyUserInfo will free it when + * destroyed. * * To remove a PurpleNotifyUserInfoEntry, use - * purple_notify_user_info_remove_entry(). Do not use the GList directly. + * purple_notify_user_info_remove_entry(). Do not use the GQueue directly. * * @param user_info The PurpleNotifyUserInfo * - * @constreturn A GList of PurpleNotifyUserInfoEntry objects + * @constreturn A GQueue of PurpleNotifyUserInfoEntry objects. */ -GList *purple_notify_user_info_get_entries(PurpleNotifyUserInfo *user_info); +GQueue *purple_notify_user_info_get_entries(PurpleNotifyUserInfo *user_info); /** * Create a textual representation of a PurpleNotifyUserInfo, separating @@ -547,34 +481,25 @@ * the UI should treat label as independent and not * include a colon if it would otherwise. */ -/* - * TODO: In 3.0.0 this function should be renamed to - * purple_notify_user_info_add_pair_html(). And optionally - * purple_notify_user_info_add_pair_plaintext() could be renamed to - * purple_notify_user_info_add_pair(). - */ -void purple_notify_user_info_add_pair(PurpleNotifyUserInfo *user_info, const char *label, const char *value); +void purple_notify_user_info_add_pair_html(PurpleNotifyUserInfo *user_info, const char *label, const char *value); /** - * Like purple_notify_user_info_add_pair, but value should be plaintext + * Like purple_notify_user_info_add_pair_html, but value should be plaintext * and will be escaped using g_markup_escape_text(). */ void purple_notify_user_info_add_pair_plaintext(PurpleNotifyUserInfo *user_info, const char *label, const char *value); /** - * Prepend a label/value pair to a PurpleNotifyUserInfo object - * - * @param user_info The PurpleNotifyUserInfo - * @param label A label, which for example might be displayed by a - * UI with a colon after it ("Status:"). Do not include - * a colon. If NULL, value will be displayed without a - * label. - * @param value The value, which might be displayed by a UI after - * the label. If NULL, label will still be displayed; - * the UI should then treat label as independent and not - * include a colon if it would otherwise. + * Like purple_notify_user_info_add_pair_html, but the pair is inserted + * at the beginning of the list. */ -void purple_notify_user_info_prepend_pair(PurpleNotifyUserInfo *user_info, const char *label, const char *value); +void purple_notify_user_info_prepend_pair_html(PurpleNotifyUserInfo *user_info, const char *label, const char *value); + +/** + * Like purple_notify_user_info_prepend_pair_html, but value should be plaintext + * and will be escaped using g_markup_escape_text(). + */ +void purple_notify_user_info_prepend_pair_plaintext(PurpleNotifyUserInfo *user_info, const char *label, const char *value); #if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_NOTIFY_C_) /** @@ -597,9 +522,11 @@ * * If added to a PurpleNotifyUserInfo object, this should not be free()'d, * as PurpleNotifyUserInfo will do so when destroyed. - * purple_notify_user_info_add_pair() and - * purple_notify_user_info_prepend_pair() are convenience methods for - * creating entries and adding them to a PurpleNotifyUserInfo. + * purple_notify_user_info_add_pair_html(), + * purple_notify_user_info_add_pair_plaintext(), + * purple_notify_user_info_prepend_pair_html() and + * purple_notify_user_info_prepend_pair_plaintext() are convenience + * methods for creating entries and adding them to a PurpleNotifyUserInfo. * * @param label A label, which for example might be displayed by a UI * with a colon after it ("Status:"). Do not include a @@ -624,7 +551,6 @@ * Prepend a section break. A UI might display this as a horizontal line. * * @param user_info The PurpleNotifyUserInfo - * @since 2.5.0 */ void purple_notify_user_info_prepend_section_break(PurpleNotifyUserInfo *user_info); @@ -643,7 +569,6 @@ * * @param user_info The PurpleNotifyUserInfo * @param label The name of the section - * @since 2.5.0 */ void purple_notify_user_info_prepend_section_header(PurpleNotifyUserInfo *user_info, const char *label); @@ -807,8 +732,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_NOTIFY_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/ntlm.h --- a/libpurple/ntlm.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/ntlm.h Fri Apr 06 04:30:00 2012 +0000 @@ -27,9 +27,7 @@ #ifndef _PURPLE_NTLM_H #define _PURPLE_NTLM_H -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /** * Generates the base64 encoded type 1 message needed for NTLM authentication @@ -66,8 +64,6 @@ */ gchar *purple_ntlm_gen_type3(const gchar *username, const gchar *passw, const gchar *hostname, const gchar *domain, const guint8 *nonce, guint32 *flags); -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_NTLM_H */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugin.c --- a/libpurple/plugin.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugin.c Fri Apr 06 04:30:00 2012 +0000 @@ -64,13 +64,6 @@ static GList *plugins_to_disable = NULL; #endif -static void (*probe_cb)(void *) = NULL; -static void *probe_cb_data = NULL; -static void (*load_cb)(PurplePlugin *, void *) = NULL; -static void *load_cb_data = NULL; -static void (*unload_cb)(PurplePlugin *, void *) = NULL; -static void *unload_cb_data = NULL; - #ifdef PURPLE_PLUGINS static gboolean @@ -615,9 +608,6 @@ plugin->loaded = TRUE; - if (load_cb != NULL) - load_cb(plugin, load_cb_data); - purple_signal_emit(purple_plugins_get_handle(), "plugin-load", plugin); return TRUE; @@ -745,9 +735,6 @@ g_free(plugin->error); plugin->error = NULL; - if (unload_cb != NULL) - unload_cb(plugin, unload_cb_data); - purple_signal_emit(purple_plugins_get_handle(), "plugin-unload", plugin); purple_prefs_disconnect_by_handle(plugin); @@ -1439,10 +1426,6 @@ (GCompareFunc)compare_prpl); } } - - if (probe_cb != NULL) - probe_cb(probe_cb_data); - #endif /* PURPLE_PLUGINS */ } @@ -1513,50 +1496,6 @@ #endif } -void -purple_plugins_register_probe_notify_cb(void (*func)(void *), void *data) -{ - probe_cb = func; - probe_cb_data = data; -} - -void -purple_plugins_unregister_probe_notify_cb(void (*func)(void *)) -{ - probe_cb = NULL; - probe_cb_data = NULL; -} - -void -purple_plugins_register_load_notify_cb(void (*func)(PurplePlugin *, void *), - void *data) -{ - load_cb = func; - load_cb_data = data; -} - -void -purple_plugins_unregister_load_notify_cb(void (*func)(PurplePlugin *, void *)) -{ - load_cb = NULL; - load_cb_data = NULL; -} - -void -purple_plugins_register_unload_notify_cb(void (*func)(PurplePlugin *, void *), - void *data) -{ - unload_cb = func; - unload_cb_data = data; -} - -void -purple_plugins_unregister_unload_notify_cb(void (*func)(PurplePlugin *, void *)) -{ - unload_cb = NULL; - unload_cb_data = NULL; -} - PurplePlugin * purple_plugins_find_with_name(const char *name) { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugin.h --- a/libpurple/plugin.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugin.h Fri Apr 06 04:30:00 2012 +0000 @@ -239,9 +239,7 @@ #endif -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Plugin API */ @@ -317,8 +315,6 @@ * startup" by excluding said plugins from the list of plugins to save. The * UI needs to call purple_plugins_save_loaded() after calling this for it * to have any effect. - * - * @since 2.3.0 */ void purple_plugin_disable(PurplePlugin *plugin); @@ -515,8 +511,6 @@ * Returns a list of plugin search paths. * * @constreturn A list of searched paths. - * - * @since 2.6.0 */ GList *purple_plugins_get_search_paths(void); @@ -566,72 +560,6 @@ */ gboolean purple_plugins_enabled(void); -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_PLUGIN_C_) -/** - * Registers a function that will be called when probing is finished. - * - * @param func The callback function. - * @param data Data to pass to the callback. - * @deprecated If you need this, ask for a plugin-probe signal to be added. - */ -void purple_plugins_register_probe_notify_cb(void (*func)(void *), void *data); -#endif - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_PLUGIN_C_) -/** - * Unregisters a function that would be called when probing is finished. - * - * @param func The callback function. - * @deprecated If you need this, ask for a plugin-probe signal to be added. - */ -void purple_plugins_unregister_probe_notify_cb(void (*func)(void *)); -#endif - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_PLUGIN_C_) -/** - * Registers a function that will be called when a plugin is loaded. - * - * @param func The callback function. - * @param data Data to pass to the callback. - * @deprecated Use the plugin-load signal instead. - */ -void purple_plugins_register_load_notify_cb(void (*func)(PurplePlugin *, void *), - void *data); -#endif - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_PLUGIN_C_) -/** - * Unregisters a function that would be called when a plugin is loaded. - * - * @param func The callback function. - * @deprecated Use the plugin-load signal instead. - */ -void purple_plugins_unregister_load_notify_cb(void (*func)(PurplePlugin *, void *)); -#endif - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_PLUGIN_C_) -/** - * Registers a function that will be called when a plugin is unloaded. - * - * @param func The callback function. - * @param data Data to pass to the callback. - * @deprecated Use the plugin-unload signal instead. - */ -void purple_plugins_register_unload_notify_cb(void (*func)(PurplePlugin *, void *), - void *data); -#endif - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_PLUGIN_C_) -/** - * Unregisters a function that would be called when a plugin is unloaded. - * - * @param func The callback function. - * @deprecated Use the plugin-unload signal instead. - */ -void purple_plugins_unregister_unload_notify_cb(void (*func)(PurplePlugin *, - void *)); -#endif - /** * Finds a plugin with the specified name. * @@ -733,8 +661,6 @@ */ void purple_plugin_action_free(PurplePluginAction *action); -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_PLUGIN_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/pluginpref.h --- a/libpurple/pluginpref.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/pluginpref.h Fri Apr 06 04:30:00 2012 +0000 @@ -50,9 +50,7 @@ #include #include "prefs.h" -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Plugin Preference API */ @@ -262,8 +260,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_PLUGINPREF_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/autoaccept.c --- a/libpurple/plugins/autoaccept.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/autoaccept.c Fri Apr 06 04:30:00 2012 +0000 @@ -73,10 +73,10 @@ auto_accept_complete_cb(PurpleXfer *xfer, PurpleXfer *my) { if (xfer == my && purple_prefs_get_bool(PREF_NOTIFY) && - !purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, xfer->who, xfer->account)) + !purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_xfer_get_remote_user(xfer), purple_xfer_get_account(xfer))) { char *message = g_strdup_printf(_("Autoaccepted file transfer of \"%s\" from \"%s\" completed."), - xfer->filename, xfer->who); + purple_xfer_get_filename(xfer), purple_xfer_get_remote_user(xfer)); purple_notify_info(NULL, _("Autoaccept complete"), message, NULL); g_free(message); } @@ -93,8 +93,8 @@ int accept_setting; - account = xfer->account; - node = PURPLE_BLIST_NODE(purple_find_buddy(account, xfer->who)); + account = purple_xfer_get_account(xfer); + node = PURPLE_BLIST_NODE(purple_find_buddy(account, purple_xfer_get_remote_user(xfer))); /* If person is on buddy list, use the buddy setting; otherwise, use the stranger setting. */ @@ -121,7 +121,7 @@ gchar *ext; if (purple_prefs_get_bool(PREF_NEWDIR)) - dirname = g_build_filename(pref, purple_normalize(account, xfer->who), NULL); + dirname = g_build_filename(pref, purple_normalize(account, purple_xfer_get_remote_user(xfer)), NULL); else dirname = g_build_filename(pref, NULL); @@ -133,9 +133,9 @@ /* Escape filename (if escaping is turned on) */ if (purple_prefs_get_bool(PREF_ESCAPE)) { - escape = purple_escape_filename(xfer->filename); + escape = purple_escape_filename(purple_xfer_get_filename(xfer)); } else { - escape = xfer->filename; + escape = purple_xfer_get_filename(xfer); } filename = g_build_filename(dirname, escape, NULL); @@ -174,7 +174,7 @@ PURPLE_CALLBACK(auto_accept_complete_cb), xfer); break; case FT_REJECT: - xfer->status = PURPLE_XFER_STATUS_CANCEL_LOCAL; + purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_LOCAL); break; } } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/log_reader.c --- a/libpurple/plugins/log_reader.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/log_reader.c Fri Apr 06 04:30:00 2012 +0000 @@ -92,7 +92,7 @@ prpl_name = g_ascii_strup(prpl_info->list_icon(account, NULL), -1); - temp = g_strdup_printf("%s.%s", prpl_name, account->username); + temp = g_strdup_printf("%s.%s", prpl_name, purple_account_get_username(account)); path = g_build_filename(logdir, temp, sn, NULL); g_free(temp); @@ -635,7 +635,7 @@ g_return_val_if_fail(sn != NULL, NULL); g_return_val_if_fail(account != NULL, NULL); - if (strcmp(account->protocol_id, "prpl-msn")) + if (strcmp(purple_account_get_protocol_id(account), "prpl-msn")) return NULL; logdir = purple_prefs_get_string("/plugins/core/log_reader/msn/log_directory"); @@ -658,7 +658,7 @@ return list; } } else { - username = g_strdup(purple_normalize(account, account->username)); + username = g_strdup(purple_normalize(account, purple_account_get_username(account))); } if (buddy) { @@ -974,7 +974,7 @@ their_name = from_name; if (from_name && purple_prefs_get_bool("/plugins/core/log_reader/use_name_heuristics")) { - const char *friendly_name = purple_connection_get_display_name(log->account->gc); + const char *friendly_name = purple_connection_get_display_name(purple_account_get_connection(log->account)); if (friendly_name != NULL) { int friendly_name_length = strlen(friendly_name); @@ -987,13 +987,10 @@ if (buddy) their_name = purple_buddy_get_alias(buddy); - if (log->account->alias) - { - alias = log->account->alias; + alias = purple_account_get_alias(log->account); + if (alias) { alias_length = strlen(alias); - } - else - { + } else { alias = ""; alias_length = 0; } @@ -1115,10 +1112,10 @@ text = g_string_append(text, ""); if (name_guessed == NAME_GUESS_ME) { - if (log->account->alias) - text = g_string_append(text, log->account->alias); + if (purple_account_get_alias(log->account)) + text = g_string_append(text, purple_account_get_alias(log->account)); else - text = g_string_append(text, log->account->username); + text = g_string_append(text, purple_account_get_username(log->account)); } else if (name_guessed == NAME_GUESS_THEM) text = g_string_append(text, their_name); @@ -1781,7 +1778,7 @@ g_return_val_if_fail(account != NULL, NULL); /* QIP only supports ICQ. */ - if (strcmp(account->protocol_id, "prpl-icq")) + if (strcmp(purple_account_get_protocol_id(account), "prpl-icq")) return NULL; logdir = purple_prefs_get_string("/plugins/core/log_reader/qip/log_directory"); @@ -1798,7 +1795,7 @@ if (!prpl_info->list_icon) return NULL; - username = g_strdup(purple_normalize(account, account->username)); + username = g_strdup(purple_normalize(account, purple_account_get_username(account))); filename = g_strdup_printf("%s.txt", purple_normalize(account, sn)); path = g_build_filename(logdir, username, "History", filename, NULL); g_free(username); @@ -2206,7 +2203,6 @@ log->logger = amsn_logger; log->logger_data = data; list = g_list_prepend(list, log); - found_start = FALSE; purple_debug_info("aMSN logger", "Found log for %s:" @@ -2241,10 +2237,10 @@ return NULL; /* aMSN only works with MSN/WLM */ - if (strcmp(account->protocol_id, "prpl-msn")) + if (strcmp(purple_account_get_protocol_id(account), "prpl-msn")) return NULL; - username = g_strdup(purple_normalize(account, account->username)); + username = g_strdup(purple_normalize(account, purple_account_get_username(account))); buddy_log = g_strdup_printf("%s.log", purple_normalize(account, sn)); log_path = g_build_filename(logdir, username, "logs", NULL); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/offlinemsg.c --- a/libpurple/plugins/offlinemsg.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/offlinemsg.c Fri Apr 06 04:30:00 2012 +0000 @@ -80,6 +80,7 @@ PurplePounceEvent event; PurplePounceOption option; PurpleConversation *conv; + char *temp; event = PURPLE_POUNCE_SIGNON; option = PURPLE_POUNCE_OPTION_NONE; @@ -88,7 +89,12 @@ event, option); purple_pounce_action_set_enabled(pounce, "send-message", TRUE); - purple_pounce_action_set_attribute(pounce, "send-message", "message", offline->message); + + temp = g_strdup_printf("(%s) %s", _("Offline message"), + offline->message); + purple_pounce_action_set_attribute(pounce, "send-message", "message", + temp); + g_free(temp); conv = offline->conv; if (!purple_conversation_get_data(conv, "plugin_pack:offlinemsg")) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/perl/common/Account.xs --- a/libpurple/plugins/perl/common/Account.xs Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/perl/common/Account.xs Fri Apr 06 04:30:00 2012 +0000 @@ -199,9 +199,10 @@ Purple::Account account void -purple_account_add_buddies(account, list) +purple_account_add_buddies(account, list, message) Purple::Account account SV * list + const char *message PREINIT: GList *t_GL; int i, t_len; @@ -212,13 +213,14 @@ for (i = 0; i <= t_len; i++) t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(list), i, 0))); - purple_account_add_buddies(account, t_GL); + purple_account_add_buddies(account, t_GL, message); g_list_free(t_GL); void -purple_account_add_buddy(account, buddy) - Purple::Account account - Purple::BuddyList::Buddy buddy +purple_account_add_buddy(account, buddy, message) + Purple::Account account + Purple::BuddyList::Buddy buddy + const char * message void purple_account_change_password(account, a, b) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/perl/common/BuddyList.xs --- a/libpurple/plugins/perl/common/BuddyList.xs Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/perl/common/BuddyList.xs Fri Apr 06 04:30:00 2012 +0000 @@ -82,11 +82,6 @@ purple_contact_get_priority_buddy(contact) Purple::BuddyList::Contact contact -void -purple_contact_set_alias(contact, alias) - Purple::BuddyList::Contact contact - const char * alias - const char * purple_contact_get_alias(contact) Purple::BuddyList::Contact contact @@ -200,10 +195,6 @@ Purple::Status old_status void -purple_blist_update_buddy_icon(buddy) - Purple::BuddyList::Buddy buddy - -void purple_blist_rename_buddy(buddy, name) Purple::BuddyList::Buddy buddy const char * name @@ -430,9 +421,5 @@ Purple::BuddyList::Buddy buddy const char * -purple_buddy_get_local_alias(buddy) - Purple::BuddyList::Buddy buddy - -const char * purple_buddy_get_alias(buddy) Purple::BuddyList::Buddy buddy diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/perl/common/Certificate.xs --- a/libpurple/plugins/perl/common/Certificate.xs Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/perl/common/Certificate.xs Fri Apr 06 04:30:00 2012 +0000 @@ -68,10 +68,6 @@ purple_certificate_destroy(crt) Purple::Certificate crt -void -purple_certificate_display_x509(crt) - Purple::Certificate crt - ## changed order of arguments, so that $cert->export($file) could be used gboolean purple_certificate_export(crt, filename) @@ -202,7 +198,7 @@ l = g_list_prepend(l, purple_perl_ref_object(ST(i))); } l = g_list_reverse(l); - ret = purple_certificate_check_signature_chain(l); + ret = purple_certificate_check_signature_chain(l, NULL); g_list_free(l); if(ret) XSRETURN_YES; XSRETURN_NO; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/perl/common/Connection.xs --- a/libpurple/plugins/perl/common/Connection.xs Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/perl/common/Connection.xs Fri Apr 06 04:30:00 2012 +0000 @@ -36,15 +36,6 @@ const char *text void -purple_connection_error(gc, reason) - Purple::Connection gc - const char *reason - -void -purple_connection_destroy(gc) - Purple::Connection gc - -void purple_connection_set_state(gc, state) Purple::Connection gc Purple::ConnectionState state diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/perl/common/Conversation.xs --- a/libpurple/plugins/perl/common/Conversation.xs Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/perl/common/Conversation.xs Fri Apr 06 04:30:00 2012 +0000 @@ -146,7 +146,7 @@ Purple::Conversation conv Purple::Connection -purple_conversation_get_gc(conv) +purple_conversation_get_connection(conv) Purple::Conversation conv void @@ -338,24 +338,6 @@ Purple::Conversation::Chat chat void -purple_conv_chat_set_users(chat, users) - Purple::Conversation::Chat chat - SV * users -PREINIT: - GList *l, *t_GL; - int i, t_len; -PPCODE: - t_GL = NULL; - t_len = av_len((AV *)SvRV(users)); - - for (i = 0; i <= t_len; i++) - t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(users), i, 0))); - - for (l = purple_conv_chat_set_users(chat, t_GL); l != NULL; l = l->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListEntry"))); - } - -void purple_conv_chat_get_users(chat) Purple::Conversation::Chat chat PREINIT: diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/perl/common/FT.xs --- a/libpurple/plugins/perl/common/FT.xs Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/perl/common/FT.xs Fri Apr 06 04:30:00 2012 +0000 @@ -113,7 +113,7 @@ Purple::Xfer xfer gboolean -purple_xfer_is_canceled(xfer) +purple_xfer_is_cancelled(xfer) Purple::Xfer xfer gboolean diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/perl/common/Network.xs --- a/libpurple/plugins/perl/common/Network.xs Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/perl/common/Network.xs Fri Apr 06 04:30:00 2012 +0000 @@ -23,17 +23,21 @@ const char *ip Purple::NetworkListenData -purple_network_listen(port, socket_type, cb, cb_data) +purple_network_listen(port, socket_family, socket_type, map_external, cb, cb_data) unsigned short port + int socket_family int socket_type + gboolean map_external Purple::NetworkListenCallback cb gpointer cb_data Purple::NetworkListenData -purple_network_listen_range(start, end, socket_type, cb, cb_data) +purple_network_listen_range(start, end, socket_family, socket_type, map_external, cb, cb_data) unsigned short start unsigned short end + int socket_family int socket_type + gboolean map_external Purple::NetworkListenCallback cb gpointer cb_data diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/perl/common/Notify.xs --- a/libpurple/plugins/perl/common/Notify.xs Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/perl/common/Notify.xs Fri Apr 06 04:30:00 2012 +0000 @@ -135,7 +135,7 @@ PREINIT: GList *l; PPCODE: - l = purple_notify_user_info_get_entries(user_info); + l = purple_notify_user_info_get_entries(user_info)->head; for (; l != NULL; l = l->next) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::NotifyUserInfoEntry"))); } @@ -145,12 +145,12 @@ Purple::NotifyUserInfo user_info const char *newline -void purple_notify_user_info_add_pair(user_info, label, value) +void purple_notify_user_info_add_pair_html(user_info, label, value) Purple::NotifyUserInfo user_info const char *label const char *value -void purple_notify_user_info_prepend_pair(user_info, label, value) +void purple_notify_user_info_prepend_pair_html(user_info, label, value) Purple::NotifyUserInfo user_info const char *label const char *value diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/perl/common/Request.xs --- a/libpurple/plugins/perl/common/Request.xs Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/perl/common/Request.xs Fri Apr 06 04:30:00 2012 +0000 @@ -374,12 +374,6 @@ C_ARGS: id, text void -purple_request_field_list_add(field, item, data) - Purple::Request::Field field - const char *item - void * data - -void purple_request_field_list_add_icon(field, item, icon_path, data) Purple::Request::Field field const char *item diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/perl/common/SSLConn.xs --- a/libpurple/plugins/perl/common/SSLConn.xs Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/perl/common/SSLConn.xs Fri Apr 06 04:30:00 2012 +0000 @@ -16,13 +16,6 @@ Purple::Ssl::Connection gsc Purple::SslInputFunction func -Purple::Ssl::Connection -purple_ssl_connect_fd(account, fd, func, error_func, data) - Purple::Account account - int fd - PurpleSslInputFunction func - PurpleSslErrorFunction error_func - */ MODULE = Purple::SSL PACKAGE = Purple::SSL PREFIX = purple_ssl_ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/perl/common/Status.xs --- a/libpurple/plugins/perl/common/Status.xs Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/perl/common/Status.xs Fri Apr 06 04:30:00 2012 +0000 @@ -74,28 +74,6 @@ newCONSTSUB(primitive_stash, (char *)civ->name, newSViv(civ->iv)); } -void -purple_presence_add_list(presence, source_list) - Purple::Presence presence - SV *source_list -PREINIT: - GList *t_GL; - int i, t_len; -PPCODE: - t_GL = NULL; - t_len = av_len((AV *)SvRV(source_list)); - - for (i = 0; i <= t_len; i++) { - t_GL = g_list_append(t_GL, SvPVutf8_nolen(*av_fetch((AV *)SvRV(source_list), i, 0))); - } - purple_presence_add_list(presence, t_GL); - g_list_free(t_GL); - -void -purple_presence_add_status(presence, status) - Purple::Presence presence - Purple::Status status - gint purple_presence_compare(presence1, presence2) Purple::Presence presence1 @@ -329,29 +307,10 @@ Purple::Status status gboolean active -void -purple_status_set_attr_boolean(status, id, value) - Purple::Status status - const char *id - gboolean value - -void -purple_status_set_attr_string(status, id, value) - Purple::Status status - const char *id - const char *value - MODULE = Purple::Status PACKAGE = Purple::StatusType PREFIX = purple_status_type_ PROTOTYPES: ENABLE void -purple_status_type_add_attr(status_type, id, name, value) - Purple::StatusType status_type - const char *id - const char *name - Purple::Value value - -void purple_status_type_destroy(status_type) Purple::StatusType status_type @@ -397,10 +356,6 @@ purple_status_type_get_name(status_type) Purple::StatusType status_type -const char * -purple_status_type_get_primary_attr(status_type) - Purple::StatusType status_type - Purple::StatusPrimitive purple_status_type_get_primitive(status_type) Purple::StatusType status_type @@ -440,8 +395,3 @@ gboolean saveable gboolean user_settable gboolean independent - -void -purple_status_type_set_primary_attr(status_type, attr_id) - Purple::StatusType status_type - const char *attr_id diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/perl/common/Util.xs --- a/libpurple/plugins/perl/common/Util.xs Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/perl/common/Util.xs Fri Apr 06 04:30:00 2012 +0000 @@ -202,6 +202,14 @@ purple_ip_address_is_valid(ip) const char* ip +gboolean +purple_ipv4_address_is_valid(ip) + const char* ip + +gboolean +purple_ipv6_address_is_valid(ip) + const char* ip + const char* purple_normalize_nocase(account, str) Purple::Account account @@ -454,12 +462,13 @@ #XXX: expand... void -purple_util_fetch_url(plugin, url, full, user_agent, http11, cb) +purple_util_fetch_url(plugin, url, full, user_agent, http11, max_len, cb) Purple::Plugin plugin const char *url gboolean full const char *user_agent gboolean http11 + gssize max_len SV * cb PREINIT: PurpleUtilFetchUrlData *data; @@ -468,7 +477,7 @@ SV *sv = purple_perl_sv_from_fun(plugin, cb); if (sv != NULL) { - data = purple_util_fetch_url(url, full, user_agent, http11, + data = purple_util_fetch_url(url, full, user_agent, http11, max_len, purple_perl_util_url_cb, sv); XPUSHs(sv_2mortal(purple_perl_bless_object(data, "Purple::Util::FetchUrlData"))); } else { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/ssl/Makefile.am --- a/libpurple/plugins/ssl/Makefile.am Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/ssl/Makefile.am Fri Apr 06 04:30:00 2012 +0000 @@ -9,30 +9,15 @@ if PLUGINS -# I'm sorry to report that Automake Conditionals don't support -# if USE_GNUTLS && USE_NSS -# but only support testing a single variable. Hence: - +plugin_LTLIBRARIES = \ + ssl.la if USE_GNUTLS -if USE_NSS -plugin_LTLIBRARIES = \ - ssl.la \ - ssl-gnutls.la \ - ssl-nss.la -else -plugin_LTLIBRARIES = \ - ssl.la \ +plugin_LTLIBRARIES += \ ssl-gnutls.la endif -else if USE_NSS -plugin_LTLIBRARIES = \ - ssl.la \ +plugin_LTLIBRARIES += \ ssl-nss.la -else -plugin_LTLIBRARIES = \ - ssl.la -endif endif ssl_la_SOURCES = ssl.c @@ -56,3 +41,4 @@ ssl_gnutls_la_CFLAGS = $(AM_CPPFLAGS) $(GNUTLS_CFLAGS) ssl_nss_la_CFLAGS = $(AM_CPPFLAGS) $(NSS_CFLAGS) + diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/ssl/ssl-gnutls.c --- a/libpurple/plugins/ssl/ssl-gnutls.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/ssl/ssl-gnutls.c Fri Apr 06 04:30:00 2012 +0000 @@ -1142,6 +1142,86 @@ return success; } +static GByteArray * +x509_get_der_data(PurpleCertificate *crt) +{ + gnutls_x509_crt crt_dat; + GByteArray *data; + size_t len; + int ret; + + crt_dat = X509_GET_GNUTLS_DATA(crt); + g_return_val_if_fail(crt_dat, NULL); + + /* Obtain the output size required */ + len = 0; + ret = gnutls_x509_crt_export(crt_dat, GNUTLS_X509_FMT_DER, NULL, &len); + g_return_val_if_fail(ret == GNUTLS_E_SHORT_MEMORY_BUFFER, NULL); + + /* Now allocate a buffer and *really* export it */ + data = g_byte_array_sized_new(len); + data->len = len; + ret = gnutls_x509_crt_export(crt_dat, GNUTLS_X509_FMT_DER, data->data, &len); + if (ret != 0) { + purple_debug_error("gnutls/x509", + "Failed to export cert to buffer with code %d\n", + ret); + g_byte_array_free(data, TRUE); + return NULL; + } + + return data; +} + +static gchar * +x509_display_string(PurpleCertificate *crt) +{ + gchar *sha_asc; + GByteArray *sha_bin; + gchar *cn; + time_t activation, expiration; + gchar *activ_str, *expir_str; + gchar *text; + + /* Pull out the SHA1 checksum */ + sha_bin = x509_sha1sum(crt); + sha_asc = purple_base16_encode_chunked(sha_bin->data, sha_bin->len); + + /* Get the cert Common Name */ + /* TODO: Will break on CA certs */ + cn = x509_common_name(crt); + + /* Get the certificate times */ + /* TODO: Check the times against localtime */ + /* TODO: errorcheck? */ + if (!x509_times(crt, &activation, &expiration)) { + purple_debug_error("certificate", + "Failed to get certificate times!\n"); + activation = expiration = 0; + } + activ_str = g_strdup(ctime(&activation)); + expir_str = g_strdup(ctime(&expiration)); + + /* Make messages */ + text = g_strdup_printf(_("Common name: %s\n\n" + "Fingerprint (SHA1): %s\n\n" + "Activation date: %s\n" + "Expiration date: %s\n"), + cn ? cn : "(null)", + sha_asc ? sha_asc : "(null)", + activ_str ? activ_str : "(null)", + expir_str ? expir_str : "(null)"); + + /* Cleanup */ + g_free(cn); + g_free(sha_asc); + g_free(activ_str); + g_free(expir_str); + g_byte_array_free(sha_bin, TRUE); + + return text; +} + /* X.509 certificate operations provided by this plugin */ static PurpleCertificateScheme x509_gnutls = { "x509", /* Scheme name */ @@ -1158,9 +1238,9 @@ x509_check_name, /* Check subject name */ x509_times, /* Activation/Expiration time */ x509_importcerts_from_file, /* Multiple certificates import function */ + x509_get_der_data, /* Binary DER data */ + x509_display_string, /* Display representation */ - NULL, - NULL, NULL }; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/ssl/ssl-nss.c --- a/libpurple/plugins/ssl/ssl-nss.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/ssl/ssl-nss.c Fri Apr 06 04:30:00 2012 +0000 @@ -930,6 +930,78 @@ return TRUE; } +static GByteArray * +x509_get_der_data(PurpleCertificate *crt) +{ + CERTCertificate *crt_dat; + SECItem *dercrt; + GByteArray *data; + + crt_dat = X509_NSS_DATA(crt); + g_return_val_if_fail(crt_dat, NULL); + + dercrt = SEC_ASN1EncodeItem(NULL, NULL, crt_dat, + SEC_ASN1_GET(SEC_SignedCertificateTemplate)); + g_return_val_if_fail(dercrt != NULL, FALSE); + + data = g_byte_array_sized_new(dercrt->len); + memcpy(data->data, dercrt->data, dercrt->len); + data->len = dercrt->len; + + SECITEM_FreeItem(dercrt, PR_TRUE); + + return data; +} + +static gchar * +x509_display_string(PurpleCertificate *crt) +{ + gchar *sha_asc; + GByteArray *sha_bin; + gchar *cn; + time_t activation, expiration; + gchar *activ_str, *expir_str; + gchar *text; + + /* Pull out the SHA1 checksum */ + sha_bin = x509_sha1sum(crt); + sha_asc = purple_base16_encode_chunked(sha_bin->data, sha_bin->len); + + /* Get the cert Common Name */ + /* TODO: Will break on CA certs */ + cn = x509_common_name(crt); + + /* Get the certificate times */ + /* TODO: Check the times against localtime */ + /* TODO: errorcheck? */ + if (!x509_times(crt, &activation, &expiration)) { + purple_debug_error("certificate", + "Failed to get certificate times!\n"); + activation = expiration = 0; + } + activ_str = g_strdup(ctime(&activation)); + expir_str = g_strdup(ctime(&expiration)); + + /* Make messages */ + text = g_strdup_printf(_("Common name: %s\n\n" + "Fingerprint (SHA1): %s\n\n" + "Activation date: %s\n" + "Expiration date: %s\n"), + cn ? cn : "(null)", + sha_asc ? sha_asc : "(null)", + activ_str ? activ_str : "(null)", + expir_str ? expir_str : "(null)"); + + /* Cleanup */ + g_free(cn); + g_free(sha_asc); + g_free(activ_str); + g_free(expir_str); + g_byte_array_free(sha_bin, TRUE); + + return text; +} + static PurpleCertificateScheme x509_nss = { "x509", /* Scheme name */ N_("X.509 Certificates"), /* User-visible scheme name */ @@ -945,9 +1017,9 @@ x509_check_name, /* Check subject name */ x509_times, /* Activation/Expiration time */ x509_importcerts_from_file, /* Multiple certificate import function */ + x509_get_der_data, /* Binary DER data */ + x509_display_string, /* Display representation */ - NULL, - NULL, NULL }; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/statenotify.c --- a/libpurple/plugins/statenotify.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/statenotify.c Fri Apr 06 04:30:00 2012 +0000 @@ -30,7 +30,7 @@ if (conv == NULL) return; - g_return_if_fail(conv->type == PURPLE_CONV_TYPE_IM); + g_return_if_fail(purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM); /* Prevent duplicate notifications for buddies in multiple groups */ if (buddy != purple_find_buddy(account, buddy_name)) @@ -42,7 +42,7 @@ g_snprintf(buf, sizeof(buf), message, escaped); g_free(escaped); - purple_conv_im_write(conv->u.im, NULL, buf, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_ACTIVE_ONLY | PURPLE_MESSAGE_NO_LINKIFY, time(NULL)); + purple_conv_im_write(PURPLE_CONV_IM(conv), NULL, buf, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_ACTIVE_ONLY | PURPLE_MESSAGE_NO_LINKIFY, time(NULL)); } static void diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/plugins/tcl/tcl_cmds.c --- a/libpurple/plugins/tcl/tcl_cmds.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/plugins/tcl/tcl_cmds.c Fri Apr 06 04:30:00 2012 +0000 @@ -1640,13 +1640,13 @@ int tcl_cmd_status_type(ClientData unused, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { const char *cmds[] = { "attr", "attrs", "available", "exclusive", "id", - "independent", "name", "primary_attr", + "independent", "name", "primitive", "saveable", "user_settable", NULL }; enum { CMD_STATUS_TYPE_ATTR, CMD_STATUS_TYPE_ATTRS, CMD_STATUS_TYPE_AVAILABLE, CMD_STATUS_TYPE_EXCLUSIVE, CMD_STATUS_TYPE_ID, CMD_STATUS_TYPE_INDEPENDENT, - CMD_STATUS_TYPE_NAME, CMD_STATUS_TYPE_PRIMARY_ATTR, + CMD_STATUS_TYPE_NAME, CMD_STATUS_TYPE_PRIMITIVE, CMD_STATUS_TYPE_SAVEABLE, CMD_STATUS_TYPE_USER_SETTABLE } cmd; PurpleStatusType *status_type; @@ -1751,18 +1751,6 @@ Tcl_NewStringObj(purple_primitive_get_id_from_type (purple_status_type_get_primitive(status_type)), -1)); break; - case CMD_STATUS_TYPE_PRIMARY_ATTR: -#if !(defined PURPLE_DISABLE_DEPRECATED) - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "statustype"); - return TCL_ERROR; - } - if ((status_type = purple_tcl_ref_get(interp, objv[2], PurpleTclRefStatusType)) == NULL) - return TCL_ERROR; - Tcl_SetObjResult(interp, - Tcl_NewStringObj(purple_status_type_get_primary_attr(status_type), -1)); -#endif - break; case CMD_STATUS_TYPE_SAVEABLE: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "statustype"); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/pounce.c --- a/libpurple/pounce.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/pounce.c Fri Apr 06 04:30:00 2012 +0000 @@ -32,6 +32,31 @@ #include "pounce.h" #include "util.h" +/** + * A buddy pounce structure. + * + * Buddy pounces are actions triggered by a buddy-related event. For + * example, a sound can be played or an IM window opened when a buddy + * signs on or returns from away. Such responses are handled in the + * UI. The events themselves are done in the core. + */ +struct _PurplePounce +{ + char *ui_type; /**< The type of UI. */ + + PurplePounceEvent events; /**< The event(s) to pounce on. */ + PurplePounceOption options; /**< The pounce options */ + PurpleAccount *pouncer; /**< The user who is pouncing. */ + + char *pouncee; /**< The buddy to pounce on. */ + + GHashTable *actions; /**< The registered actions. */ + + gboolean save; /**< Whether or not the pounce should + be saved after activation. */ + void *data; /**< Pounce-specific data. */ +}; + typedef struct { GString *buffer; @@ -180,7 +205,7 @@ xmlnode_set_attrib(node, "ui", pounce->ui_type); child = xmlnode_new_child(node, "account"); - xmlnode_set_attrib(child, "protocol", pouncer->protocol_id); + xmlnode_set_attrib(child, "protocol", purple_account_get_protocol_id(pouncer)); xmlnode_insert_data(child, purple_normalize(pouncer, purple_account_get_username(pouncer)), -1); @@ -405,12 +430,8 @@ } if (purple_strequal(element_name, "account")) { - char *tmp; g_free(data->account_name); data->account_name = g_strdup(buffer); - tmp = data->protocol_id; - data->protocol_id = g_strdup(_purple_oscar_convert(buffer, tmp)); - g_free(tmp); } else if (purple_strequal(element_name, "pouncee")) { g_free(data->pouncee); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/pounce.h --- a/libpurple/pounce.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/pounce.h Fri Apr 06 04:30:00 2012 +0000 @@ -59,34 +59,7 @@ /** A pounce callback. */ typedef void (*PurplePounceCb)(PurplePounce *, PurplePounceEvent, void *); -/** - * A buddy pounce structure. - * - * Buddy pounces are actions triggered by a buddy-related event. For - * example, a sound can be played or an IM window opened when a buddy - * signs on or returns from away. Such responses are handled in the - * UI. The events themselves are done in the core. - */ -struct _PurplePounce -{ - char *ui_type; /**< The type of UI. */ - - PurplePounceEvent events; /**< The event(s) to pounce on. */ - PurplePounceOption options; /**< The pounce options */ - PurpleAccount *pouncer; /**< The user who is pouncing. */ - - char *pouncee; /**< The buddy to pounce on. */ - - GHashTable *actions; /**< The registered actions. */ - - gboolean save; /**< Whether or not the pounce should - be saved after activation. */ - void *data; /**< Pounce-specific data. */ -}; - -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Buddy Pounce API */ @@ -126,8 +99,6 @@ * Destroys all buddy pounces for a buddy * * @param buddy The buddy whose pounces are to be removed - * - * @since 2.8.0 */ void purple_pounce_destroy_all_by_buddy(PurpleBuddy *buddy); @@ -359,7 +330,6 @@ * * @return The list of buddy pounces. The list should be freed by * the caller when it's no longer used. - * @since 2.1.0 */ GList *purple_pounces_get_all_for_ui(const char *ui); @@ -382,8 +352,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_POUNCE_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/prefs.c --- a/libpurple/prefs.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/prefs.c Fri Apr 06 04:30:00 2012 +0000 @@ -1357,6 +1357,7 @@ purple_prefs_remove("/purple/conversations/chat/show_leave"); purple_prefs_remove("/purple/conversations/combine_chat_im"); purple_prefs_remove("/purple/conversations/use_alias_for_title"); + purple_prefs_remove("/purple/debug/timestamps"); purple_prefs_remove("/purple/logging/log_signon_signoff"); purple_prefs_remove("/purple/logging/log_idle_state"); purple_prefs_remove("/purple/logging/log_away_state"); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/prefs.h --- a/libpurple/prefs.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/prefs.h Fri Apr 06 04:30:00 2012 +0000 @@ -32,7 +32,7 @@ /** * Preference data types. */ -typedef enum _PurplePrefType +typedef enum { PURPLE_PREF_NONE, /**< No type. */ PURPLE_PREF_BOOLEAN, /**< Boolean. */ @@ -62,9 +62,7 @@ typedef void (*PurplePrefCallback) (const char *name, PurplePrefType type, gconstpointer val, gpointer data); -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Prefs API @@ -317,8 +315,6 @@ * @return A list of newly allocated strings denoting the names of the children. * Returns @c NULL if there are no children or if pref doesn't exist. * The caller must free all the strings and the list. - * - * @since 2.1.0 */ GList *purple_prefs_get_children_names(const char *name); @@ -364,8 +360,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_PREFS_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/privacy.c --- a/libpurple/privacy.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/privacy.c Fri Apr 06 04:30:00 2012 +0000 @@ -264,9 +264,9 @@ gboolean restore) { GSList *list; - PurplePrivacyType type = account->perm_deny; + PurplePrivacyType type = purple_account_get_privacy_type(account); - switch (account->perm_deny) { + switch (type) { case PURPLE_PRIVACY_ALLOW_ALL: return; case PURPLE_PRIVACY_ALLOW_USERS: @@ -287,13 +287,13 @@ } } purple_privacy_permit_add(account, who, local); - account->perm_deny = PURPLE_PRIVACY_ALLOW_USERS; + purple_account_set_privacy_type(account, PURPLE_PRIVACY_ALLOW_USERS); break; case PURPLE_PRIVACY_ALLOW_BUDDYLIST: if (!purple_find_buddy(account, who)) { add_all_buddies_to_permit_list(account, local); purple_privacy_permit_add(account, who, local); - account->perm_deny = PURPLE_PRIVACY_ALLOW_USERS; + purple_account_set_privacy_type(account, PURPLE_PRIVACY_ALLOW_USERS); } break; default: @@ -301,7 +301,7 @@ } /* Notify the server if the privacy setting was changed */ - if (type != account->perm_deny && purple_account_is_connected(account)) + if (type != purple_account_get_privacy_type(account) && purple_account_is_connected(account)) serv_set_permit_deny(purple_account_get_connection(account)); } @@ -316,9 +316,9 @@ gboolean restore) { GSList *list; - PurplePrivacyType type = account->perm_deny; + PurplePrivacyType type = purple_account_get_privacy_type(account); - switch (account->perm_deny) { + switch (type) { case PURPLE_PRIVACY_ALLOW_ALL: if (!restore) { /* Empty the deny-list. */ @@ -331,7 +331,7 @@ } } purple_privacy_deny_add(account, who, local); - account->perm_deny = PURPLE_PRIVACY_DENY_USERS; + purple_account_set_privacy_type(account, PURPLE_PRIVACY_DENY_USERS); break; case PURPLE_PRIVACY_ALLOW_USERS: purple_privacy_permit_remove(account, who, local); @@ -345,7 +345,7 @@ if (purple_find_buddy(account, who)) { add_all_buddies_to_permit_list(account, local); purple_privacy_permit_remove(account, who, local); - account->perm_deny = PURPLE_PRIVACY_ALLOW_USERS; + purple_account_set_privacy_type(account, PURPLE_PRIVACY_ALLOW_USERS); } break; default: @@ -353,7 +353,7 @@ } /* Notify the server if the privacy setting was changed */ - if (type != account->perm_deny && purple_account_is_connected(account)) + if (type != purple_account_get_privacy_type(account) && purple_account_is_connected(account)) serv_set_permit_deny(purple_account_get_connection(account)); } @@ -362,7 +362,7 @@ { GSList *list; - switch (account->perm_deny) { + switch (purple_account_get_privacy_type(account)) { case PURPLE_PRIVACY_ALLOW_ALL: return TRUE; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/privacy.h --- a/libpurple/privacy.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/privacy.h Fri Apr 06 04:30:00 2012 +0000 @@ -29,7 +29,7 @@ /** * Privacy data types. */ -typedef enum _PurplePrivacyType +typedef enum { PURPLE_PRIVACY_ALLOW_ALL = 1, PURPLE_PRIVACY_DENY_ALL, @@ -40,10 +40,6 @@ #include "account.h" -#ifdef __cplusplus -extern "C" { -#endif - /** * Privacy core/UI operations. */ @@ -60,6 +56,8 @@ void (*_purple_reserved4)(void); } PurplePrivacyUiOps; +G_BEGIN_DECLS + /** * Adds a user to the account's permit list. * @@ -187,8 +185,6 @@ */ void purple_privacy_init(void); -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_PRIVACY_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/Makefile.am --- a/libpurple/protocols/Makefile.am Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/Makefile.am Fri Apr 06 04:30:00 2012 +0000 @@ -1,5 +1,5 @@ EXTRA_DIST = Makefile.mingw -DIST_SUBDIRS = bonjour gg irc jabber msn myspace mxit novell null oscar sametime silc silc10 simple yahoo zephyr +DIST_SUBDIRS = bonjour gg irc jabber msn mxit myspace novell null oscar sametime silc simple yahoo zephyr SUBDIRS = $(DYNAMIC_PRPLS) $(STATIC_PRPLS) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/bonjour/bonjour.c --- a/libpurple/protocols/bonjour/bonjour.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/bonjour/bonjour.c Fri Apr 06 04:30:00 2012 +0000 @@ -51,7 +51,7 @@ bonjour_get_jid(PurpleAccount *account) { PurpleConnection *conn = purple_account_get_connection(account); - BonjourData *bd = conn->proto_data; + BonjourData *bd = purple_connection_get_protocol_data(conn); return bd->jid; } @@ -94,7 +94,7 @@ #ifdef _WIN32 if (!dns_sd_available()) { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Unable to find Apple's \"Bonjour for Windows\" toolkit, see " "http://d.pidgin.im/BonjourWindows for more information.")); @@ -102,8 +102,9 @@ } #endif /* _WIN32 */ - gc->flags |= PURPLE_CONNECTION_HTML; - gc->proto_data = bd = g_new0(BonjourData, 1); + purple_connection_set_flags(gc, PURPLE_CONNECTION_HTML); + bd = g_new0(BonjourData, 1); + purple_connection_set_protocol_data(gc, bd); /* Start waiting for jabber connections (iChat style) */ bd->jabber_data = g_new0(BonjourJabber, 1); @@ -114,7 +115,7 @@ if (bonjour_jabber_start(bd->jabber_data) == -1) { /* Send a message about the connection error */ - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to listen for incoming IM connections")); return; @@ -141,7 +142,7 @@ bd->dns_sd_data->account = account; if (!bonjour_dns_sd_start(bd->dns_sd_data)) { - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to establish connection with the local mDNS server. Is it running?")); return; @@ -157,7 +158,7 @@ bonjour_close(PurpleConnection *connection) { PurpleGroup *bonjour_group; - BonjourData *bd = connection->proto_data; + BonjourData *bd = purple_connection_get_protocol_data(connection); bonjour_group = purple_find_group(BONJOUR_GROUP_NAME); @@ -192,7 +193,7 @@ if (bd != NULL) g_free(bd->jid); g_free(bd); - connection->proto_data = NULL; + purple_connection_set_protocol_data(connection, NULL); } static const char * @@ -204,10 +205,12 @@ static int bonjour_send_im(PurpleConnection *connection, const char *to, const char *msg, PurpleMessageFlags flags) { + BonjourData *bd = purple_connection_get_protocol_data(connection); + if(!to || !msg) return 0; - return bonjour_jabber_send_message(((BonjourData*)(connection->proto_data))->jabber_data, to, msg); + return bonjour_jabber_send_message(bd->jabber_data, to, msg); } static void @@ -220,7 +223,7 @@ gchar *stripped; gc = purple_account_get_connection(account); - bd = gc->proto_data; + bd = purple_connection_get_protocol_data(gc); presence = purple_account_get_presence(account); message = purple_status_get_attr_string(status, "message"); @@ -253,7 +256,7 @@ * if there is no add_buddy callback. */ static void -bonjour_fake_add_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group) { +bonjour_fake_add_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group, const char *message) { purple_debug_error("bonjour", "Buddy '%s' manually added; removing. " "Bonjour buddies must be discovered and not manually added.\n", purple_buddy_get_name(buddy)); @@ -306,7 +309,7 @@ static void bonjour_convo_closed(PurpleConnection *connection, const char *who) { - PurpleBuddy *buddy = purple_find_buddy(connection->account, who); + PurpleBuddy *buddy = purple_find_buddy(purple_connection_get_account(connection), who); BonjourBuddy *bb; if (buddy == NULL || (bb = purple_buddy_get_protocol_data(buddy)) == NULL) @@ -325,7 +328,7 @@ static void bonjour_set_buddy_icon(PurpleConnection *conn, PurpleStoredImage *img) { - BonjourData *bd = conn->proto_data; + BonjourData *bd = purple_connection_get_protocol_data(conn); bonjour_dns_sd_update_buddy_icon(bd->dns_sd_data); } @@ -371,9 +374,12 @@ else status_description = purple_status_get_name(status); - purple_notify_user_info_add_pair(user_info, _("Status"), status_description); - if (message != NULL) - purple_notify_user_info_add_pair(user_info, _("Message"), message); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), status_description); + if (message != NULL) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Message"), message); + } if (bb == NULL) { purple_debug_error("bonjour", "Got tooltip request for a buddy without protocol data.\n"); @@ -382,20 +388,35 @@ /* Only show first/last name if there is a nickname set (to avoid duplication) */ if (bb->nick != NULL && *bb->nick != '\0') { - if (bb->first != NULL && *bb->first != '\0') - purple_notify_user_info_add_pair(user_info, _("First name"), bb->first); - if (bb->last != NULL && *bb->last != '\0') - purple_notify_user_info_add_pair(user_info, _("Last name"), bb->last); + if (bb->first != NULL && *bb->first != '\0') { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("First name"), bb->first); + } + if (bb->last != NULL && *bb->last != '\0') { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Last name"), bb->last); + } } - if (bb->email != NULL && *bb->email != '\0') - purple_notify_user_info_add_pair(user_info, _("Email"), bb->email); + if (bb->email != NULL && *bb->email != '\0') { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Email"), bb->email); + } - if (bb->AIM != NULL && *bb->AIM != '\0') - purple_notify_user_info_add_pair(user_info, _("AIM Account"), bb->AIM); + if (bb->AIM != NULL && *bb->AIM != '\0') { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("AIM Account"), bb->AIM); + } - if (bb->jid != NULL && *bb->jid != '\0') - purple_notify_user_info_add_pair(user_info, _("XMPP Account"), bb->jid); + if (bb->jid != NULL && *bb->jid != '\0') { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("XMPP Account"), bb->jid); + } } static void @@ -418,7 +439,7 @@ static void bonjour_group_buddy(PurpleConnection *connection, const char *who, const char *old_group, const char *new_group) { - PurpleBuddy *buddy = purple_find_buddy(connection->account, who); + PurpleBuddy *buddy = purple_find_buddy(purple_connection_get_account(connection), who); bonjour_do_group_change(buddy, new_group); @@ -443,7 +464,7 @@ static gboolean bonjour_can_receive_file(PurpleConnection *connection, const char *who) { - PurpleBuddy *buddy = purple_find_buddy(connection->account, who); + PurpleBuddy *buddy = purple_find_buddy(purple_connection_get_account(connection), who); return (buddy != NULL && purple_buddy_get_protocol_data(buddy) != NULL); } @@ -463,6 +484,7 @@ static PurplePluginProtocolInfo prpl_info = { + sizeof(PurplePluginProtocolInfo), /* struct_size */ OPT_PROTO_NO_PASSWORD, NULL, /* user_splits */ NULL, /* protocol_options */ @@ -503,7 +525,6 @@ NULL, /* keepalive */ NULL, /* register_user */ NULL, /* get_cb_info */ - NULL, /* get_cb_away */ NULL, /* alias_buddy */ bonjour_group_buddy, /* group_buddy */ bonjour_rename_group, /* rename_group */ @@ -528,15 +549,12 @@ NULL, /* unregister_user */ NULL, /* send_attention */ NULL, /* get_attention_types */ - sizeof(PurplePluginProtocolInfo), /* struct_size */ NULL, /* get_account_text_table */ NULL, /* initiate_media */ NULL, /* get_media_caps */ NULL, /* get_moods */ NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - NULL, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ + NULL /* get_public_alias */ }; static PurplePluginInfo info = diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/bonjour/bonjour_ft.c --- a/libpurple/protocols/bonjour/bonjour_ft.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/bonjour/bonjour_ft.c Fri Apr 06 04:30:00 2012 +0000 @@ -38,7 +38,7 @@ bonjour_xfer_init(PurpleXfer *xfer); static void bonjour_xfer_receive(PurpleConnection *pc, const char *id, const char *sid, const char *from, - const int filesize, const char *filename, int option); + const goffset filesize, const char *filename, int option); static void bonjour_free_xfer(PurpleXfer *xfer); /* Look for specific xfer handle */ @@ -90,12 +90,12 @@ static void bonjour_xfer_request_denied(PurpleXfer *xfer) { - XepXfer *xf = xfer->data; + XepXfer *xf = purple_xfer_get_protocol_data(xfer); purple_debug_info("bonjour", "Bonjour-xfer-request-denied.\n"); if(xf) - xep_ft_si_reject(xf->data, xf->sid, xfer->who, "403", "cancel"); + xep_ft_si_reject(xf->data, xf->sid, purple_xfer_get_remote_user(xfer), "403", "cancel"); bonjour_free_xfer(xfer); } @@ -136,8 +136,8 @@ * otherwise there is a RST resulting in an error on the client side */ if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && purple_xfer_is_completed(xfer)) { struct socket_cleanup *sc = g_new0(struct socket_cleanup, 1); - sc->fd = xfer->fd; - xfer->fd = -1; + sc->fd = purple_xfer_get_fd(xfer); + purple_xfer_set_fd(xfer, -1); sc->handle = purple_input_add(sc->fd, PURPLE_INPUT_READ, _wait_for_socket_close, sc); } @@ -162,11 +162,11 @@ xfer = xfers->data; if(xfer == NULL) break; - xf = xfer->data; + xf = purple_xfer_get_protocol_data(xfer); if(xf == NULL) break; - if(xf->sid && xfer->who && !strcmp(xf->sid, sid) && - !strcmp(xfer->who, from)) + if(xf->sid && purple_xfer_get_remote_user(xfer) && !strcmp(xf->sid, sid) && + !strcmp(purple_xfer_get_remote_user(xfer), from)) return xfer; } @@ -180,7 +180,7 @@ { xmlnode *si_node, *feature, *field, *file, *x; XepIq *iq; - XepXfer *xf = xfer->data; + XepXfer *xf = purple_xfer_get_protocol_data(xfer); BonjourData *bd = NULL; char buf[32]; @@ -210,8 +210,8 @@ file = xmlnode_new_child(si_node, "file"); xmlnode_set_namespace(file, "http://jabber.org/protocol/si/profile/file-transfer"); - xmlnode_set_attrib(file, "name", xfer->filename); - g_snprintf(buf, sizeof(buf), "%" G_GSIZE_FORMAT, xfer->size); + xmlnode_set_attrib(file, "name", purple_xfer_get_filename(xfer)); + g_snprintf(buf, sizeof(buf), "%" G_GOFFSET_FORMAT, purple_xfer_get_size(xfer)); xmlnode_set_attrib(file, "size", buf); feature = xmlnode_new_child(si_node, "feature"); @@ -240,7 +240,7 @@ } static void -xep_ft_si_result(PurpleXfer *xfer, char *to) +xep_ft_si_result(PurpleXfer *xfer, const char *to) { xmlnode *si_node, *feature, *field, *value, *x; XepIq *iq; @@ -249,7 +249,7 @@ if(!to || !xfer) return; - xf = xfer->data; + xf = purple_xfer_get_protocol_data(xfer); if(!xf) return; @@ -290,14 +290,14 @@ return; } - purple_debug_info("bonjour", "bonjour-free-xfer-%p.\n", xfer); + purple_debug_misc("bonjour", "bonjour-free-xfer-%p.\n", xfer); - xf = (XepXfer*)xfer->data; + xf = purple_xfer_get_protocol_data(xfer); if(xf != NULL) { BonjourData *bd = (BonjourData*)xf->data; if(bd != NULL) { bd->xfer_lists = g_slist_remove(bd->xfer_lists, xfer); - purple_debug_info("bonjour", "B free xfer from lists(%p).\n", bd->xfer_lists); + purple_debug_misc("bonjour", "B free xfer from lists(%p).\n", bd->xfer_lists); } if (xf->proxy_connection != NULL) purple_proxy_connect_cancel(xf->proxy_connection); @@ -311,10 +311,10 @@ g_free(xf->buddy_ip); g_free(xf->sid); g_free(xf); - xfer->data = NULL; + purple_xfer_set_protocol_data(xfer, NULL); } - purple_debug_info("bonjour", "Need close socket=%d.\n", xfer->fd); + purple_debug_misc("bonjour", "Need close socket.\n"); } PurpleXfer * @@ -328,13 +328,14 @@ return NULL; purple_debug_info("bonjour", "Bonjour-new-xfer to %s.\n", who); - bd = (BonjourData*) gc->proto_data; + bd = purple_connection_get_protocol_data(gc); if(bd == NULL) return NULL; /* Build the file transfer handle */ - xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who); - xfer->data = xep_xfer = g_new0(XepXfer, 1); + xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_SEND, who); + xep_xfer = g_new0(XepXfer, 1); + purple_xfer_set_protocol_data(xfer, xep_xfer); xep_xfer->data = bd; purple_debug_info("bonjour", "Bonjour-new-xfer bd=%p data=%p.\n", bd, xep_xfer->data); @@ -379,13 +380,13 @@ BonjourBuddy *bb; XepXfer *xf; - xf = (XepXfer*)xfer->data; + xf = purple_xfer_get_protocol_data(xfer); if(xf == NULL) return; purple_debug_info("bonjour", "Bonjour-xfer-init.\n"); - buddy = purple_find_buddy(xfer->account, xfer->who); + buddy = purple_find_buddy(purple_xfer_get_account(xfer), purple_xfer_get_remote_user(xfer)); /* this buddy is offline. */ if (buddy == NULL || (bb = purple_buddy_get_protocol_data(buddy)) == NULL) return; @@ -396,10 +397,10 @@ if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) { /* initiate file transfer, send SI offer. */ purple_debug_info("bonjour", "Bonjour xfer type is PURPLE_XFER_SEND.\n"); - xep_ft_si_offer(xfer, xfer->who); + xep_ft_si_offer(xfer, purple_xfer_get_remote_user(xfer)); } else { /* accept file transfer request, send SI result. */ - xep_ft_si_result(xfer, xfer->who); + xep_ft_si_result(xfer, purple_xfer_get_remote_user(xfer)); purple_debug_info("bonjour", "Bonjour xfer type is PURPLE_XFER_RECEIVE.\n"); } } @@ -416,7 +417,7 @@ g_return_if_fail(packet != NULL); g_return_if_fail(pb != NULL); - bd = (BonjourData*) pc->proto_data; + bd = purple_connection_get_protocol_data(pc); if(bd == NULL) return; @@ -553,9 +554,8 @@ const char *jid, *host, *port; int portnum; xmlnode *streamhost; - XepXfer *xf = NULL; + XepXfer *xf = purple_xfer_get_protocol_data(xfer); - xf = (XepXfer*)xfer->data; for(streamhost = xmlnode_get_child(query, "streamhost"); streamhost; streamhost = xmlnode_get_next_twin(streamhost)) { @@ -598,7 +598,7 @@ g_return_if_fail(packet != NULL); g_return_if_fail(pb != NULL); - bd = (BonjourData*) pc->proto_data; + bd = purple_connection_get_protocol_data(pc); if(bd == NULL) return; @@ -632,7 +632,7 @@ static void bonjour_xfer_receive(PurpleConnection *pc, const char *id, const char *sid, const char *from, - const int filesize, const char *filename, int option) + const goffset filesize, const char *filename, int option) { PurpleXfer *xfer; XepXfer *xf; @@ -641,15 +641,16 @@ if(pc == NULL || id == NULL || from == NULL) return; - bd = (BonjourData*) pc->proto_data; + bd = purple_connection_get_protocol_data(pc); if(bd == NULL) return; purple_debug_info("bonjour", "bonjour-xfer-receive.\n"); /* Build the file transfer handle */ - xfer = purple_xfer_new(pc->account, PURPLE_XFER_RECEIVE, from); - xfer->data = xf = g_new0(XepXfer, 1); + xfer = purple_xfer_new(purple_connection_get_account(pc), PURPLE_XFER_RECEIVE, from); + xf = g_new0(XepXfer, 1); + purple_xfer_set_protocol_data(xfer, xf); xf->data = bd; purple_xfer_set_filename(xfer, filename); xf->iq_id = g_strdup(id); @@ -671,7 +672,7 @@ bonjour_sock5_request_cb(gpointer data, gint source, PurpleInputCondition cond) { PurpleXfer *xfer = data; - XepXfer *xf = xfer->data; + XepXfer *xf = purple_xfer_get_protocol_data(xfer); int acceptfd; int len = 0; @@ -689,8 +690,6 @@ /* This should cancel the ft */ purple_debug_error("bonjour", "Error accepting incoming SOCKS5 connection. (%d)\n", errno); - purple_input_remove(xfer->watcher); - xfer->watcher = 0; close(source); purple_xfer_cancel_remote(xfer); return; @@ -705,29 +704,26 @@ fcntl(acceptfd, F_SETFD, FD_CLOEXEC); #endif - purple_input_remove(xfer->watcher); + purple_input_remove(purple_xfer_get_watcher(xfer)); close(source); - xfer->watcher = purple_input_add(acceptfd, PURPLE_INPUT_READ, - bonjour_sock5_request_cb, xfer); + purple_xfer_set_watcher(xfer, purple_input_add(acceptfd, PURPLE_INPUT_READ, + bonjour_sock5_request_cb, xfer)); xf->sock5_req_state++; xf->rxlen = 0; } break; case 0x01: - xfer->fd = source; + purple_xfer_set_fd(xfer, source); len = read(source, xf->rx_buf + xf->rxlen, 3); if(len < 0 && errno == EAGAIN) return; else if(len <= 0){ - purple_input_remove(xfer->watcher); - xfer->watcher = 0; - close(source); purple_xfer_cancel_remote(xfer); return; } else { - purple_input_remove(xfer->watcher); - xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE, - bonjour_sock5_request_cb, xfer); + purple_input_remove(purple_xfer_get_watcher(xfer)); + purple_xfer_set_watcher(xfer, purple_input_add(source, PURPLE_INPUT_WRITE, + bonjour_sock5_request_cb, xfer)); xf->sock5_req_state++; xf->rxlen = 0; bonjour_sock5_request_cb(xfer, source, PURPLE_INPUT_WRITE); @@ -740,15 +736,13 @@ if (len < 0 && errno == EAGAIN) return; else if (len < 0) { - purple_input_remove(xfer->watcher); - xfer->watcher = 0; close(source); purple_xfer_cancel_remote(xfer); return; } else { - purple_input_remove(xfer->watcher); - xfer->watcher = purple_input_add(source, PURPLE_INPUT_READ, - bonjour_sock5_request_cb, xfer); + purple_input_remove(purple_xfer_get_watcher(xfer)); + purple_xfer_set_watcher(xfer, purple_input_add(source, PURPLE_INPUT_READ, + bonjour_sock5_request_cb, xfer)); xf->sock5_req_state++; xf->rxlen = 0; } @@ -757,9 +751,9 @@ len = read(source, xf->rx_buf + xf->rxlen, 20); if(len<=0){ } else { - purple_input_remove(xfer->watcher); - xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE, - bonjour_sock5_request_cb, xfer); + purple_input_remove(purple_xfer_get_watcher(xfer)); + purple_xfer_set_watcher(xfer, purple_input_add(source, PURPLE_INPUT_WRITE, + bonjour_sock5_request_cb, xfer)); xf->sock5_req_state++; xf->rxlen = 0; bonjour_sock5_request_cb(xfer, source, PURPLE_INPUT_WRITE); @@ -778,14 +772,12 @@ if (len < 0 && errno == EAGAIN) { return; } else if (len < 0) { - purple_input_remove(xfer->watcher); - xfer->watcher = 0; close(source); purple_xfer_cancel_remote(xfer); return; } else { - purple_input_remove(xfer->watcher); - xfer->watcher = 0; + purple_input_remove(purple_xfer_get_watcher(xfer)); + purple_xfer_set_watcher(xfer, 0); xf->rxlen = 0; /*close(source);*/ purple_xfer_start(xfer, source, NULL, -1); @@ -814,25 +806,25 @@ return; } - xfer->watcher = purple_input_add(sock, PURPLE_INPUT_READ, - bonjour_sock5_request_cb, xfer); - xf = (XepXfer*)xfer->data; + purple_xfer_set_watcher(xfer, purple_input_add(sock, PURPLE_INPUT_READ, + bonjour_sock5_request_cb, xfer)); + xf = purple_xfer_get_protocol_data(xfer); xf->listen_data = NULL; bd = xf->data; - iq = xep_iq_new(bd, XEP_IQ_SET, xfer->who, bonjour_get_jid(bd->jabber_data->account), xf->sid); + iq = xep_iq_new(bd, XEP_IQ_SET, purple_xfer_get_remote_user(xfer), bonjour_get_jid(bd->jabber_data->account), xf->sid); query = xmlnode_new_child(iq->node, "query"); xmlnode_set_namespace(query, "http://jabber.org/protocol/bytestreams"); xmlnode_set_attrib(query, "sid", xf->sid); xmlnode_set_attrib(query, "mode", "tcp"); - xfer->local_port = purple_network_get_port_from_fd(sock); + purple_xfer_set_local_port(xfer, purple_network_get_port_from_fd(sock)); local_ips = bonjour_jabber_get_local_ips(sock); - port = g_strdup_printf("%hu", xfer->local_port); + port = g_strdup_printf("%hu", purple_xfer_get_local_port(xfer)); while(local_ips) { streamhost = xmlnode_new_child(query, "streamhost"); xmlnode_set_attrib(streamhost, "jid", xf->sid); @@ -854,12 +846,10 @@ return; purple_debug_info("bonjour", "Bonjour-bytestreams-init.\n"); - xf = xfer->data; + xf = purple_xfer_get_protocol_data(xfer); - purple_network_listen_map_external(FALSE); - xf->listen_data = purple_network_listen_range(0, 0, SOCK_STREAM, + xf->listen_data = purple_network_listen_range(0, 0, AF_UNSPEC, SOCK_STREAM, FALSE, bonjour_bytestreams_listen, xfer); - purple_network_listen_map_external(TRUE); if (xf->listen_data == NULL) purple_xfer_cancel_local(xfer); @@ -870,7 +860,7 @@ bonjour_bytestreams_connect_cb(gpointer data, gint source, const gchar *error_message) { PurpleXfer *xfer = data; - XepXfer *xf = xfer->data; + XepXfer *xf = purple_xfer_get_protocol_data(xfer); XepIq *iq; xmlnode *q_node, *tmp_node; BonjourData *bd; @@ -880,7 +870,7 @@ if(source < 0) { purple_debug_error("bonjour", "Error connecting via SOCKS5 - %s\n", error_message ? error_message : "(null)"); - xep_ft_si_reject(xf->data, xf->iq_id, xfer->who, "404", "cancel"); + xep_ft_si_reject(xf->data, xf->iq_id, purple_xfer_get_remote_user(xfer), "404", "cancel"); /* Cancel the connection */ purple_xfer_cancel_local(xfer); return; @@ -893,7 +883,7 @@ /* Here, start the file transfer.*/ /* Notify Initiator of Connection */ - iq = xep_iq_new(bd, XEP_IQ_RESULT, xfer->who, bonjour_get_jid(bd->jabber_data->account), xf->iq_id); + iq = xep_iq_new(bd, XEP_IQ_RESULT, purple_xfer_get_remote_user(xfer), bonjour_get_jid(bd->jabber_data->account), xf->iq_id); q_node = xmlnode_new_child(iq->node, "query"); xmlnode_set_namespace(q_node, "http://jabber.org/protocol/bytestreams"); tmp_node = xmlnode_new_child(q_node, "streamhost-used"); @@ -919,7 +909,7 @@ purple_debug_info("bonjour", "bonjour-bytestreams-connect.\n"); - xf = (XepXfer*)xfer->data; + xf = purple_xfer_get_protocol_data(xfer); if(!xf) return; @@ -948,7 +938,7 @@ bonjour_bytestreams_connect_cb, xfer); if(xf->proxy_connection == NULL) { - xep_ft_si_reject(xf->data, xf->iq_id, xfer->who, "404", "cancel"); + xep_ft_si_reject(xf->data, xf->iq_id, purple_xfer_get_remote_user(xfer), "404", "cancel"); /* Cancel the connection */ purple_xfer_cancel_local(xfer); } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/bonjour/jabber.c --- a/libpurple/protocols/bonjour/jabber.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/bonjour/jabber.c Fri Apr 06 04:30:00 2012 +0000 @@ -206,7 +206,9 @@ g_string_append_printf(str, " face='%s'", font_face); if (font_size) g_string_append_printf(str, " size='%s'", font_size); - if (ichat_text_color) + if (font_color) + g_string_append_printf(str, " color='%s'", font_color); + else if (ichat_text_color) g_string_append_printf(str, " color='%s'", ichat_text_color); if (ichat_balloon_color) g_string_append_printf(str, " back='%s'", ichat_balloon_color); @@ -748,7 +750,7 @@ #if 0 /* TODO: Why isn't this being used? */ - data->socket = purple_network_listen(jdata->port, SOCK_STREAM); + data->socket = purple_network_listen(jdata->port, AF_UNSPEC, SOCK_STREAM, TRUE); if (jdata->socket == -1) { @@ -933,7 +935,9 @@ while(tmp) { ip = tmp->data; if (ip != NULL && g_ascii_strcasecmp(ip, bconv->ip) == 0) { - BonjourJabber *jdata = ((BonjourData*) bconv->account->gc->proto_data)->jabber_data; + PurpleConnection *pc = purple_account_get_connection(bconv->account); + BonjourData *bd = purple_connection_get_protocol_data(pc); + BonjourJabber *jdata = bd->jabber_data; purple_debug_info("bonjour", "Matched buddy %s to incoming conversation \"from\" attrib and IP (%s)\n", purple_buddy_get_name(pb), bconv->ip); @@ -966,7 +970,9 @@ void bonjour_jabber_conv_match_by_ip(BonjourJabberConversation *bconv) { - BonjourJabber *jdata = ((BonjourData*) bconv->account->gc->proto_data)->jabber_data; + PurpleConnection *pc = purple_account_get_connection(bconv->account); + BonjourData *bd = purple_connection_get_protocol_data(pc); + BonjourJabber *jdata = bd->jabber_data; struct _match_buddies_by_address_t *mbba; GSList *buddies; @@ -1126,7 +1132,9 @@ void async_bonjour_jabber_close_conversation(BonjourJabberConversation *bconv) { - BonjourJabber *jdata = ((BonjourData*) bconv->account->gc->proto_data)->jabber_data; + PurpleConnection *pc = purple_account_get_connection(bconv->account); + BonjourData *bd = purple_connection_get_protocol_data(pc); + BonjourJabber *jdata = bd->jabber_data; jdata->pending_conversations = g_slist_remove(jdata->pending_conversations, bconv); @@ -1146,8 +1154,9 @@ if (bconv != NULL) { BonjourData *bd = NULL; - if(PURPLE_CONNECTION_IS_VALID(bconv->account->gc)) { - bd = bconv->account->gc->proto_data; + PurpleConnection *pc = purple_account_get_connection(bconv->account); + if (PURPLE_CONNECTION_IS_VALID(pc)) { + bd = purple_connection_get_protocol_data(pc); bd->jabber_data->pending_conversations = g_slist_remove(bd->jabber_data->pending_conversations, bconv); } @@ -1161,7 +1170,7 @@ tmp_next = xfers->next; /* We only need to cancel this if it hasn't actually started transferring. */ /* This will change if we ever support IBB transfers. */ - if (strcmp(xfer->who, purple_buddy_get_name(bconv->pb)) == 0 + if (strcmp(purple_xfer_get_remote_user(xfer), purple_buddy_get_name(bconv->pb)) == 0 && (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_NOT_STARTED || purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_UNKNOWN)) { purple_xfer_cancel_remote(xfer); @@ -1219,7 +1228,7 @@ purple_input_remove(jdata->watcher_id6); /* Close all the conversation sockets and remove all the watchers after sending end streams */ - if (jdata->account->gc != NULL) { + if (!purple_account_is_disconnected(jdata->account)) { GSList *buddies, *l; buddies = purple_find_buddies(jdata->account, NULL); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/bonjour/mdns_avahi.c --- a/libpurple/protocols/bonjour/mdns_avahi.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/bonjour/mdns_avahi.c Fri Apr 06 04:30:00 2012 +0000 @@ -618,7 +618,7 @@ void _mdns_retrieve_buddy_icon(BonjourBuddy* buddy) { PurpleConnection *conn = purple_account_get_connection(buddy->account); - BonjourData *bd = conn->proto_data; + BonjourData *bd = purple_connection_get_protocol_data(conn); AvahiSessionImplData *session_idata = bd->dns_sd_data->mdns_impl_data; AvahiBuddyImplData *idata = buddy->mdns_impl_data; gchar *name; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/bonjour/mdns_common.c --- a/libpurple/protocols/bonjour/mdns_common.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/bonjour/mdns_common.c Fri Apr 06 04:30:00 2012 +0000 @@ -257,7 +257,7 @@ bonjour_dns_sd_set_jid(PurpleAccount *account, const char *hostname) { PurpleConnection *conn = purple_account_get_connection(account); - BonjourData *bd = conn->proto_data; + BonjourData *bd = purple_connection_get_protocol_data(conn); const char *tmp, *account_name = purple_account_get_username(account); /* Previously we allowed the hostname part of the jid to be set diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/bonjour/mdns_types.h --- a/libpurple/protocols/bonjour/mdns_types.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/bonjour/mdns_types.h Fri Apr 06 04:30:00 2012 +0000 @@ -37,7 +37,7 @@ gchar *msg; } BonjourDnsSd; -typedef enum _PublishType { +typedef enum { PUBLISH_START, PUBLISH_UPDATE } PublishType; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/bonjour/mdns_win32.c --- a/libpurple/protocols/bonjour/mdns_win32.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/bonjour/mdns_win32.c Fri Apr 06 04:30:00 2012 +0000 @@ -105,7 +105,7 @@ purple_debug_error("bonjour", "Error (%d) handling mDNS response.\n", errorCode); /* This happens when the mDNSResponder goes down, I haven't seen it happen any other time (in my limited testing) */ if (errorCode == kDNSServiceErr_Unknown) { - purple_connection_error_reason(srh->account->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(srh->account->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Error communicating with local mDNSResponder.")); } } @@ -177,7 +177,7 @@ args->resolver_query = NULL; if ((pb = purple_find_buddy(args->account, args->res_data->name))) { - if (pb->proto_data != args->bb) { + if (purple_buddy_get_protocol_data(pb) != args->bb) { purple_debug_error("bonjour", "Found purple buddy for %s not matching bonjour buddy record.", args->res_data->name); goto cleanup; @@ -348,7 +348,7 @@ /* Is there an existing buddy? */ if ((pb = purple_find_buddy(account, serviceName))) - bb = pb->proto_data; + bb = purple_buddy_get_protocol_data(pb); /* Is there a pending buddy? */ else { while (tmp) { @@ -368,7 +368,7 @@ if (pb == NULL) pending_buddies = g_slist_prepend(pending_buddies, bb); else - pb->proto_data = bb; + purple_buddy_set_protocol_data(pb, bb); } rd = g_new0(Win32SvcResolverData, 1); @@ -408,7 +408,7 @@ GSList *l; /* There may be multiple presences, we should only get rid of this one */ Win32SvcResolverData *rd_search; - BonjourBuddy *bb = pb->proto_data; + BonjourBuddy *bb = purple_buddy_get_protocol_data(pb); Win32BuddyImplData *idata; g_return_if_fail(bb != NULL); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/Makefile.am --- a/libpurple/protocols/gg/Makefile.am Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/Makefile.am Fri Apr 06 04:30:00 2012 +0000 @@ -1,5 +1,7 @@ EXTRA_DIST = \ Makefile.mingw \ + win32-resolver.c \ + win32-resolver.h \ lib/common.c \ lib/compat.h \ lib/COPYING \ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/Makefile.mingw --- a/libpurple/protocols/gg/Makefile.mingw Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/Makefile.mingw Fri Apr 06 04:30:00 2012 +0000 @@ -60,7 +60,8 @@ confer.c \ gg.c \ search.c \ - gg-utils.c + gg-utils.c \ + win32-resolver.c OBJECTS = $(C_SRC:%.c=%.o) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/buddylist.c --- a/libpurple/protocols/gg/buddylist.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/buddylist.c Fri Apr 06 04:30:00 2012 +0000 @@ -38,7 +38,7 @@ /* void ggp_buddylist_send(PurpleConnection *gc) {{{ */ void ggp_buddylist_send(PurpleConnection *gc) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); PurpleAccount *account = purple_connection_get_account(gc); GSList *buddies; uin_t *userlist; @@ -90,7 +90,7 @@ gchar **data_tbl; gchar *name, *show, *g; - if (strlen(users_tbl[i]) == 0) + if (!*users_tbl[i]) continue; data_tbl = g_strsplit(users_tbl[i], ";", 8); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/confer.c --- a/libpurple/protocols/gg/confer.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/confer.c Fri Apr 06 04:30:00 2012 +0000 @@ -42,7 +42,7 @@ const uin_t uin) { PurpleConversation *conv; - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); GGPChat *chat; GList *l; gchar *str_uin; @@ -73,7 +73,7 @@ void ggp_confer_participants_add(PurpleConnection *gc, const gchar *chat_name, const uin_t *recipients, int count) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); GList *l; gchar *str_uin; @@ -111,7 +111,7 @@ const char *ggp_confer_find_by_participants(PurpleConnection *gc, const uin_t *recipients, int count) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); GGPChat *chat = NULL; GList *l; int matches; @@ -149,7 +149,7 @@ /* const char *ggp_confer_add_new(PurpleConnection *gc, const char *name) {{{ */ const char *ggp_confer_add_new(PurpleConnection *gc, const char *name) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); GGPChat *chat; chat = g_new0(GGPChat, 1); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/gg-utils.c --- a/libpurple/protocols/gg/gg-utils.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/gg-utils.c Fri Apr 06 04:30:00 2012 +0000 @@ -143,5 +143,18 @@ msg ? "message" : NULL, msg, NULL); } +guint ggp_http_input_add(struct gg_http *http_req, PurpleInputFunction func, + gpointer user_data) +{ + PurpleInputCondition cond = 0; + int check = http_req->check; + + if (check & GG_CHECK_READ) + cond |= PURPLE_INPUT_READ; + if (check & GG_CHECK_WRITE) + cond |= PURPLE_INPUT_WRITE; + + return purple_input_add(http_req->fd, cond, func, user_data); +} /* vim: set ts=8 sts=0 sw=8 noet: */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/gg-utils.h --- a/libpurple/protocols/gg/gg-utils.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/gg-utils.h Fri Apr 06 04:30:00 2012 +0000 @@ -101,6 +101,21 @@ ggp_status_fake_to_self(PurpleAccount *account); +/** + * Adds an input handler in purple event loop for http request. + * + * @see purple_input_add + * + * @param http_req Http connection to watch. + * @param func The callback function for data. + * @param user_data User-specified data. + * + * @return The resulting handle (will be greater than 0). + */ +guint +ggp_http_input_add(struct gg_http *http_req, PurpleInputFunction func, + gpointer user_data); + #endif /* _PURPLE_GG_UTILS_H */ /* vim: set ts=8 sts=0 sw=8 noet: */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/gg.c --- a/libpurple/protocols/gg/gg.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/gg.c Fri Apr 06 04:30:00 2012 +0000 @@ -39,14 +39,16 @@ #include "request.h" #include "xmlnode.h" -#include - #include "gg.h" #include "confer.h" #include "search.h" #include "buddylist.h" #include "gg-utils.h" +#ifdef _WIN32 +# include "win32-resolver.h" +#endif + static PurplePlugin *my_protocol = NULL; /* Prototypes */ @@ -97,7 +99,7 @@ static void ggp_async_token_handler(gpointer _gc, gint fd, PurpleInputCondition cond) { PurpleConnection *gc = _gc; - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); GGPToken *token = info->token; GGPTokenCallback cb; @@ -170,7 +172,7 @@ if (ggp_setup_proxy(account) == -1) return; - info = gc->proto_data; + info = purple_connection_get_protocol_data(gc); if ((req = gg_token(1)) == NULL) { purple_notify_error(account, @@ -199,7 +201,7 @@ static void ggp_action_buddylist_get(PurplePluginAction *action) { PurpleConnection *gc = (PurpleConnection *)action->context; - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); purple_debug_info("gg", "Downloading...\n"); @@ -214,7 +216,7 @@ static void ggp_action_buddylist_put(PurplePluginAction *action) { PurpleConnection *gc = (PurpleConnection *)action->context; - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); char *buddylist = ggp_buddylist_dump(purple_connection_get_account(gc)); @@ -235,7 +237,7 @@ static void ggp_action_buddylist_delete(PurplePluginAction *action) { PurpleConnection *gc = (PurpleConnection *)action->context; - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); purple_debug_info("gg", "Deleting...\n"); @@ -334,7 +336,7 @@ PurpleRequestFields *fields) { PurpleAccount *account; - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); struct gg_http *h = NULL; struct gg_pubdir *s; uin_t uin; @@ -354,14 +356,14 @@ if (email == NULL || p1 == NULL || p2 == NULL || t == NULL || *email == '\0' || *p1 == '\0' || *p2 == '\0' || *t == '\0') { - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("You must fill in all registration fields")); goto exit_err; } if (g_utf8_collate(p1, p2) != 0) { - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Passwords do not match")); goto exit_err; @@ -371,7 +373,7 @@ token->id, t); h = gg_register3(email, p1, token->id, t, 0); if (h == NULL || !(s = h->data) || !s->success) { - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Unable to register new account. An unknown error occurred.")); goto exit_err; @@ -389,8 +391,8 @@ purple_notify_info(NULL, _("New Gadu-Gadu Account Registered"), _("Registration completed successfully!"), NULL); - if(account->registration_cb) - (account->registration_cb)(account, TRUE, account->registration_cb_user_data); + purple_account_register_completed(account, TRUE); + /* TODO: the currently open Accounts Window will not be updated withthe * new username and etc, we need to somehow have it refresh at this * point @@ -400,8 +402,7 @@ purple_account_disconnect(account); exit_err: - if(account->registration_cb) - (account->registration_cb)(account, FALSE, account->registration_cb_user_data); + purple_account_register_completed(account, FALSE); gg_register_free(h); g_free(email); @@ -415,10 +416,10 @@ static void ggp_callback_register_account_cancel(PurpleConnection *gc, PurpleRequestFields *fields) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); GGPToken *token = info->token; - purple_account_disconnect(gc->account); + purple_account_disconnect(purple_connection_get_account(gc)); g_free(token->id); g_free(token->data); @@ -433,7 +434,7 @@ PurpleRequestFieldGroup *group; PurpleRequestField *field; - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); GGPToken *token = info->token; @@ -483,7 +484,7 @@ static void ggp_callback_show_next(PurpleConnection *gc, GList *row, gpointer user_data) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); GGPSearchForm *form = user_data; guint32 seq; @@ -520,7 +521,7 @@ static void ggp_callback_find_buddies(PurpleConnection *gc, PurpleRequestFields *fields) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); GGPSearchForm *form; guint32 seq; @@ -616,75 +617,137 @@ gc); } -/* ----- CHANGE PASSWORD ------------------------------------------------ */ - -static void ggp_callback_change_passwd_ok(PurpleConnection *gc, PurpleRequestFields *fields) +/* ----- CHANGE PASSWORD ---------------------------------------------------- */ + +typedef struct +{ + guint inpa; + struct gg_http *http_req; + gchar *new_password; + PurpleAccount *account; +} ggp_change_passwd_request; + +static void ggp_callback_change_passwd_handler(gpointer _req, gint fd, + PurpleInputCondition cond) +{ + ggp_change_passwd_request *req = _req; + const char *messagesTitle = + _("Change password for the Gadu-Gadu account"); + + purple_input_remove(req->inpa); + + if (gg_change_passwd_watch_fd(req->http_req) == -1 || + req->http_req->state == GG_STATE_ERROR) + goto exit_error; + + if (req->http_req->state != GG_STATE_DONE) + { + req->inpa = ggp_http_input_add(req->http_req, + ggp_callback_change_passwd_handler, req); + return; + } + + if (req->http_req->data != NULL && + ((struct gg_pubdir*)req->http_req->data)->success == 1) + { + purple_account_set_password(req->account, req->new_password); + purple_notify_info(req->account, messagesTitle, + _("Password was changed successfully!"), NULL); + goto exit_cleanup; + } + +exit_error: + purple_notify_error(req->account, messagesTitle, + _("Unable to change password. Error occurred.\n"), NULL); + +exit_cleanup: + gg_change_passwd_free(req->http_req); + g_free(req->new_password); + g_free(req); +} + +static void ggp_callback_change_passwd_ok(PurpleConnection *gc, + PurpleRequestFields *fields) { PurpleAccount *account; - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); struct gg_http *h; - gchar *cur, *p1, *p2, *t; - - cur = charset_convert( - purple_request_fields_get_string(fields, "password_cur"), - "UTF-8", "CP1250"); - p1 = charset_convert( - purple_request_fields_get_string(fields, "password1"), - "UTF-8", "CP1250"); - p2 = charset_convert( - purple_request_fields_get_string(fields, "password2"), - "UTF-8", "CP1250"); - t = charset_convert( - purple_request_fields_get_string(fields, "token"), - "UTF-8", "CP1250"); + gchar *cur, *p1, *p2, *t, *mail; + const char *messagesTitle = + _("Change password for the Gadu-Gadu account"); + + cur = g_strdup(purple_request_fields_get_string(fields, + "password_cur")); + p1 = g_strdup(purple_request_fields_get_string(fields, "password1")); + p2 = g_strdup(purple_request_fields_get_string(fields, "password2")); + t = g_strdup(purple_request_fields_get_string(fields, "token")); + mail = g_strdup(purple_request_fields_get_string(fields, "email")); account = purple_connection_get_account(gc); if (cur == NULL || p1 == NULL || p2 == NULL || t == NULL || - *cur == '\0' || *p1 == '\0' || *p2 == '\0' || *t == '\0') { - purple_notify_error(account, NULL, _("Fill in the fields."), NULL); + mail == NULL || *cur == '\0' || *p1 == '\0' || *p2 == '\0' || + *t == '\0' || *mail == '\0') { + purple_notify_error(account, messagesTitle, + _("Fill in the fields."), NULL); goto exit_err; } if (g_utf8_collate(p1, p2) != 0) { - purple_notify_error(account, NULL, - _("New passwords do not match."), NULL); + purple_notify_error(account, messagesTitle, + _("New passwords do not match."), NULL); + goto exit_err; + } + + if (strlen(p1) > 15) { + purple_notify_error(account, messagesTitle, + _("New password should be at most 15 characters long."), + NULL); goto exit_err; } if (g_utf8_collate(cur, purple_account_get_password(account)) != 0) { - purple_notify_error(account, NULL, - _("Your current password is different from the one that you specified."), - NULL); + purple_notify_error(account, messagesTitle, + _("Your current password is different from the one that" + " you specified."), NULL); + goto exit_err; + } + + if (!purple_email_is_valid(mail)) { + purple_notify_error(account, messagesTitle, + _("Invalid email address"), NULL); goto exit_err; } - purple_debug_info("gg", "Changing password\n"); - - /* XXX: this email should be a pref... */ - h = gg_change_passwd4(ggp_get_uin(account), - "user@example.net", purple_account_get_password(account), - p1, info->token->id, t, 0); - - if (h == NULL) { - purple_notify_error(account, NULL, + purple_debug_info("gg", "Changing password with email \"%s\"...\n", + mail); + + h = gg_change_passwd4(ggp_get_uin(account), mail, + purple_account_get_password(account), p1, info->token->id, t, + 1); + + if (h == NULL) + purple_notify_error(account, messagesTitle, _("Unable to change password. Error occurred.\n"), NULL); - goto exit_err; + else + { + ggp_change_passwd_request *req = + g_new(ggp_change_passwd_request, 1); + req->http_req = h; + req->new_password = g_strdup(p1); + req->account = account; + + req->inpa = ggp_http_input_add(h, + ggp_callback_change_passwd_handler, req); } - - purple_account_set_password(account, p1); - - gg_change_passwd_free(h); - - purple_notify_info(account, _("Change password for the Gadu-Gadu account"), - _("Password was changed successfully!"), NULL); - + exit_err: g_free(cur); g_free(p1); g_free(p2); g_free(t); + g_free(mail); g_free(info->token->id); g_free(info->token->data); g_free(info->token); @@ -696,12 +759,11 @@ PurpleRequestFieldGroup *group; PurpleRequestField *field; - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); GGPToken *token = info->token; char *msg; - fields = purple_request_fields_new(); group = purple_request_field_group_new(NULL); purple_request_fields_add_group(fields, group); @@ -721,6 +783,11 @@ purple_request_field_string_set_masked(field, TRUE); purple_request_field_group_add_field(group, field); + field = purple_request_field_string_new("email", + _("Email Address"), "", FALSE); + purple_request_field_string_set_masked(field, FALSE); + purple_request_field_group_add_field(group, field); + field = purple_request_field_string_new("token", _("Enter current token"), "", FALSE); purple_request_field_string_set_masked(field, FALSE); @@ -732,8 +799,8 @@ purple_request_field_group_add_field(group, field); msg = g_strdup_printf("%s %d", - _("Please, enter your current password and your new password for UIN: "), - ggp_get_uin(purple_connection_get_account(gc))); + _("Please, enter your current password and your new password " + "for UIN: "), ggp_get_uin(purple_connection_get_account(gc))); purple_request_fields(gc, _("Change Gadu-Gadu Password"), @@ -758,7 +825,7 @@ static void ggp_action_change_status_broadcasting_ok(PurpleConnection *gc, PurpleRequestFields *fields) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); int selected_field; PurpleAccount *account = purple_connection_get_account(gc); PurpleStatus *status; @@ -778,7 +845,7 @@ static void ggp_action_change_status_broadcasting(PurplePluginAction *action) { PurpleConnection *gc = (PurpleConnection *)action->context; - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); PurpleRequestFields *fields; PurpleRequestFieldGroup *group; @@ -848,7 +915,7 @@ buddy = (PurpleBuddy *)node; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); - info = gc->proto_data; + info = purple_connection_get_protocol_data(gc); fields = purple_request_fields_new(); group = purple_request_field_group_new(NULL); @@ -857,7 +924,7 @@ field = purple_request_field_list_new("name", "Chat name"); for (l = info->chats; l != NULL; l = l->next) { GGPChat *chat = l->data; - purple_request_field_list_add(field, chat->name, chat->name); + purple_request_field_list_add_icon(field, chat->name, NULL, chat->name); } purple_request_field_group_add_field(group, field); @@ -879,7 +946,7 @@ static void ggp_add_deny(PurpleConnection *gc, const char *who) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); uin_t uin = ggp_str_to_uin(who); purple_debug_info("gg", "ggp_add_deny: %u\n", uin); @@ -890,7 +957,7 @@ static void ggp_rem_deny(PurpleConnection *gc, const char *who) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); uin_t uin = ggp_str_to_uin(who); purple_debug_info("gg", "ggp_rem_deny: %u\n", uin); @@ -1024,7 +1091,8 @@ purple_debug_info("gg", "gg_get_avatar_url_cb: " "requesting avatar for %s\n", uin); - url_data = purple_util_fetch_url_request_len_with_account(account, + /* FIXME: This should be cancelled somewhere if not needed. */ + url_data = purple_util_fetch_url_request(account, bigavatar, TRUE, "Mozilla/4.0 (compatible; MSIE 5.0)", FALSE, NULL, FALSE, -1, gg_fetch_avatar_cb, data); } @@ -1052,7 +1120,8 @@ avatarurl = g_strdup_printf("http://api.gadu-gadu.pl/avatars/%u/0.xml", uin); - url_data = purple_util_fetch_url_request_len_with_account( + /* FIXME: This should be cancelled somewhere if not needed. */ + url_data = purple_util_fetch_url_request( purple_connection_get_account(gc), avatarurl, TRUE, "Mozilla/4.0 (compatible; MSIE 5.5)", FALSE, NULL, FALSE, -1, gg_get_avatar_url_cb, gc); @@ -1086,7 +1155,7 @@ break; case GG_STATUS_FFC: case GG_STATUS_FFC_DESCR: - st = purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE); + st = "freeforchat"; break; case GG_STATUS_AVAIL: case GG_STATUS_AVAIL_DESCR: @@ -1096,6 +1165,10 @@ case GG_STATUS_BUSY_DESCR: st = purple_primitive_get_id_from_type(PURPLE_STATUS_AWAY); break; + case GG_STATUS_INVISIBLE: + case GG_STATUS_INVISIBLE_DESCR: + st = purple_primitive_get_id_from_type(PURPLE_STATUS_INVISIBLE); + break; case GG_STATUS_DND: case GG_STATUS_DND_DESCR: st = purple_primitive_get_id_from_type(PURPLE_STATUS_UNAVAILABLE); @@ -1194,27 +1267,37 @@ val = ggp_search_get_result(req, 0, GG_PUBDIR50_STATUS); /* XXX: Use of ggp_str_to_uin() is an ugly hack! */ - purple_notify_user_info_add_pair(user_info, _("Status"), ggp_status_by_id(ggp_str_to_uin(val))); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), ggp_status_by_id(ggp_str_to_uin(val))); g_free(val); who = ggp_search_get_result(req, 0, GG_PUBDIR50_UIN); - purple_notify_user_info_add_pair(user_info, _("UIN"), who); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("UIN"), who); val = ggp_search_get_result(req, 0, GG_PUBDIR50_FIRSTNAME); - purple_notify_user_info_add_pair(user_info, _("First Name"), val); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("First Name"), val); g_free(val); val = ggp_search_get_result(req, 0, GG_PUBDIR50_NICKNAME); - purple_notify_user_info_add_pair(user_info, _("Nickname"), val); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Nickname"), val); g_free(val); val = ggp_search_get_result(req, 0, GG_PUBDIR50_CITY); - purple_notify_user_info_add_pair(user_info, _("City"), val); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("City"), val); g_free(val); val = ggp_search_get_result(req, 0, GG_PUBDIR50_BIRTHYEAR); if (strncmp(val, "0", 1)) { - purple_notify_user_info_add_pair(user_info, _("Birth Year"), val); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Birth Year"), val); } g_free(val); @@ -1225,15 +1308,12 @@ if (NULL != buddy) { PurpleStatus *status; const char *msg; - char *text; status = purple_presence_get_active_status(purple_buddy_get_presence(buddy)); msg = purple_status_get_attr_string(status, "message"); if (msg != NULL) { - text = g_markup_escape_text(msg, -1); - purple_notify_user_info_add_pair(user_info, _("Message"), text); - g_free(text); + purple_notify_user_info_add_pair_plaintext(user_info, _("Message"), msg); } } @@ -1342,7 +1422,7 @@ static void ggp_pubdir_reply_handler(PurpleConnection *gc, gg_pubdir50_t req) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); GGPSearchForm *form; int res_count; guint32 seq; @@ -1384,7 +1464,7 @@ static void ggp_recv_image_handler(PurpleConnection *gc, const struct gg_event *ev) { gint imgid = 0; - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); GList *entry = g_list_first(info->pending_richtext_messages); gchar *handlerid = g_strdup_printf("IMGID_HANDLER-%i", ev->event.image_reply.crc32); @@ -1432,11 +1512,12 @@ */ static void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event *ev) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); PurpleConversation *conv; gchar *from; gchar *msg; gchar *tmp; + time_t mtime; if (ev->event.msg.message == NULL) { @@ -1565,8 +1646,13 @@ from, msg, ev->event.msg.msgclass, ev->event.msg.recipients_count); + if (ev->event.msg.msgclass & GG_CLASS_QUEUED) + mtime = ev->event.msg.time; + else + mtime = time(NULL); + if (ev->event.msg.recipients_count == 0) { - serv_got_im(gc, from, msg, 0, ev->event.msg.time); + serv_got_im(gc, from, msg, 0, mtime); } else { const char *chat_name; int chat_id; @@ -1592,7 +1678,7 @@ buddy_name = ggp_buddy_get_name(gc, ev->event.msg.sender); serv_got_chat_in(gc, chat_id, buddy_name, - PURPLE_MESSAGE_RECV, msg, ev->event.msg.time); + PURPLE_MESSAGE_RECV, msg, mtime); g_free(buddy_name); } g_free(msg); @@ -1601,7 +1687,7 @@ static void ggp_send_image_handler(PurpleConnection *gc, const struct gg_event *ev) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); PurpleStoredImage *image; gint imgid = GPOINTER_TO_INT(g_hash_table_lookup(info->pending_images, GINT_TO_POINTER(ev->event.image_request.crc32))); @@ -1707,14 +1793,14 @@ static void ggp_callback_recv(gpointer _gc, gint fd, PurpleInputCondition cond) { PurpleConnection *gc = _gc; - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); struct gg_event *ev; int i; if (!(ev = gg_watch_fd(info->session))) { purple_debug_error("gg", "ggp_callback_recv: gg_watch_fd failed -- CRITICAL!\n"); - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to read from socket")); return; @@ -1842,7 +1928,7 @@ g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc)); - info = gc->proto_data; + info = purple_connection_get_protocol_data(gc); purple_debug_info("gg", "login_handler: session: check = %d; state = %d;\n", info->session->check, info->session->state); @@ -1880,7 +1966,7 @@ if (!(ev = gg_watch_fd(info->session))) { purple_debug_error("gg", "login_handler: gg_watch_fd failed!\n"); - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to read from socket")); return; @@ -1889,11 +1975,12 @@ purple_debug_info("gg", "login_handler: session: check = %d; state = %d;\n", info->session->check, info->session->state); - purple_input_remove(gc->inpa); + purple_input_remove(info->inpa); + info->inpa = 0; /** XXX I think that this shouldn't be done if ev->type is GG_EVENT_CONN_FAILED or GG_EVENT_CONN_SUCCESS -datallah */ if (info->session->fd >= 0) - gc->inpa = purple_input_add(info->session->fd, + info->inpa = purple_input_add(info->session->fd, (info->session->check == 1) ? PURPLE_INPUT_WRITE : PURPLE_INPUT_READ, ggp_async_login_handler, gc); @@ -1906,8 +1993,8 @@ case GG_EVENT_CONN_SUCCESS: { purple_debug_info("gg", "GG_EVENT_CONN_SUCCESS\n"); - purple_input_remove(gc->inpa); - gc->inpa = purple_input_add(info->session->fd, + purple_input_remove(info->inpa); + info->inpa = purple_input_add(info->session->fd, PURPLE_INPUT_READ, ggp_callback_recv, gc); @@ -1917,17 +2004,69 @@ } break; case GG_EVENT_CONN_FAILED: - purple_input_remove(gc->inpa); - gc->inpa = 0; - purple_connection_error_reason (gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Connection failed")); + purple_input_remove(info->inpa); + info->inpa = 0; + purple_debug_info("gg", "Connection failure: %d\n", + ev->event.failure); + switch (ev->event.failure) { + case GG_FAILURE_RESOLVING: + purple_connection_error(gc, + PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("Unable to resolve " + "hostname")); + break; + case GG_FAILURE_PASSWORD: + purple_connection_error(gc, + PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, + _("Incorrect password")); + break; + case GG_FAILURE_TLS: + purple_connection_error(gc, + PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, + _("SSL Connection Failed")); + break; + case GG_FAILURE_INTRUDER: + purple_connection_error(gc, + PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, + _("Your account has been " + "disabled because too many " + "incorrect passwords were " + "entered")); + break; + case GG_FAILURE_UNAVAILABLE: + purple_connection_error(gc, + PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("Service temporarily " + "unavailable")); + break; + case GG_FAILURE_PROXY: + purple_connection_error(gc, + PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("Error connecting to proxy " + "server")); + break; + case GG_FAILURE_HUB: + purple_connection_error(gc, + PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("Error connecting to master " + "server")); + break; + default: + purple_connection_error(gc, + PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("Connection failed")); + } break; case GG_EVENT_MSG: if (ev->event.msg.sender == 0) + { + if (ev->event.msg.message == NULL) + break; + /* system messages are mostly ads */ purple_debug_info("gg", "System message:\n%s\n", ev->event.msg.message); + } else purple_debug_warning("gg", "GG_EVENT_MSG: message from user %u " "unexpected while connecting:\n%s\n", @@ -1951,6 +2090,19 @@ return "gadu-gadu"; } +static const char *ggp_normalize(const PurpleAccount *account, const char *who) +{ + static char normalized[21]; /* maximum unsigned long long int size */ + + uin_t uin = ggp_str_to_uin(who); + if (uin <= 0) + return NULL; + + g_snprintf(normalized, sizeof(normalized), "%u", uin); + + return normalized; +} + static char *ggp_status_text(PurpleBuddy *b) { PurpleStatus *status; @@ -1975,7 +2127,7 @@ static void ggp_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) { PurpleStatus *status; - char *text, *tmp; + char *tmp; const char *msg, *name, *alias; g_return_if_fail(b != NULL); @@ -1985,21 +2137,19 @@ name = purple_status_get_name(status); alias = purple_buddy_get_alias(b); - purple_notify_user_info_add_pair (user_info, _("Alias"), alias); + purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), alias); if (msg != NULL) { - text = g_markup_escape_text(msg, -1); if (PURPLE_BUDDY_IS_ONLINE(b)) { - tmp = g_strdup_printf("%s: %s", name, text); - purple_notify_user_info_add_pair(user_info, _("Status"), tmp); + tmp = g_strdup_printf("%s: %s", name, msg); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), tmp); g_free(tmp); } else { - purple_notify_user_info_add_pair(user_info, _("Message"), text); + purple_notify_user_info_add_pair_plaintext(user_info, _("Message"), msg); } - g_free(text); /* We don't want to duplicate 'Status: Offline'. */ } else if (PURPLE_BUDDY_IS_ONLINE(b)) { - purple_notify_user_info_add_pair(user_info, _("Status"), name); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), name); } } @@ -2008,50 +2158,60 @@ PurpleStatusType *type; GList *types = NULL; - type = purple_status_type_new_with_attrs( - PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), - NULL); + type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, + NULL, NULL, TRUE, TRUE, FALSE, + "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + NULL); types = g_list_append(types, type); /* - * Without this selecting Invisible as own status doesn't - * work. It's not used and not needed to show status of buddies. + * New status for GG 8.0: PoGGadaj ze mna (chatty). + * NOTE: at this time, this is used only to set our own status. */ - type = purple_status_type_new_with_attrs( - PURPLE_STATUS_INVISIBLE, NULL, NULL, TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), - NULL); + type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, + "freeforchat", _("Chatty"), TRUE, TRUE, FALSE, + "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + NULL); + types = g_list_append(types, type); + + type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY, + NULL, NULL, TRUE, TRUE, FALSE, + "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + NULL); types = g_list_append(types, type); - type = purple_status_type_new_with_attrs( - PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), - NULL); + /* + * New status for GG 8.0: Nie przeszkadzac (do not disturb). + */ + type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE, + NULL, NULL, TRUE, TRUE, FALSE, + "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + NULL); types = g_list_append(types, type); - /* - * New statuses for GG 8.0 like PoGGadaj ze mna (not yet because - * libpurple can't support Chatty status) and Nie przeszkadzac + /* + * It's used on buddy list if and only if it's showing our own + * (invisible) status. */ - type = purple_status_type_new_with_attrs( - PURPLE_STATUS_UNAVAILABLE, NULL, NULL, TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), - NULL); + type = purple_status_type_new_with_attrs(PURPLE_STATUS_INVISIBLE, + NULL, NULL, TRUE, TRUE, FALSE, + "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + NULL); types = g_list_append(types, type); /* * This status is necessary to display guys who are blocking *us*. */ - type = purple_status_type_new_with_attrs( - PURPLE_STATUS_INVISIBLE, "blocked", _("Blocked"), TRUE, FALSE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), NULL); + type = purple_status_type_new_with_attrs(PURPLE_STATUS_INVISIBLE, + "blocked", _("Blocked"), TRUE, FALSE, FALSE, + "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + NULL); types = g_list_append(types, type); - type = purple_status_type_new_with_attrs( - PURPLE_STATUS_OFFLINE, NULL, NULL, TRUE, TRUE, FALSE, - "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), - NULL); + type = purple_status_type_new_with_attrs(PURPLE_STATUS_OFFLINE, + NULL, NULL, TRUE, TRUE, FALSE, + "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), + NULL); types = g_list_append(types, type); return types; @@ -2062,13 +2222,15 @@ PurpleMenuAction *act; GList *m = NULL; PurpleAccount *account; + PurpleConnection *gc; GGPInfo *info; if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) return NULL; account = purple_buddy_get_account((PurpleBuddy *) node); - info = purple_account_get_connection(account)->proto_data; + gc = purple_account_get_connection(account); + info = purple_connection_get_protocol_data(gc); if (info->chats) { act = purple_menu_action_new(_("Add to chat"), PURPLE_CALLBACK(ggp_bmenu_add_to_chat), @@ -2120,11 +2282,25 @@ info->pending_images = g_hash_table_new(g_direct_hash, g_direct_equal); info->status_broadcasting = purple_account_get_bool(account, "status_broadcasting", TRUE); - gc->proto_data = info; + purple_connection_set_protocol_data(gc, info); glp->uin = ggp_get_uin(account); - glp->password = (char *)purple_account_get_password(account); + glp->password = charset_convert(purple_account_get_password(account), + "UTF-8", "CP1250"); + + if (glp->uin == 0) { + purple_connection_error(gc, + PURPLE_CONNECTION_ERROR_INVALID_USERNAME, + _("The username specified is invalid.")); + g_free(glp); + return; + } + glp->image_size = 255; + glp->status_flags = GG_STATUS_FLAG_UNKNOWN; + + if (purple_account_get_bool(account, "show_links_from_strangers", 1)) + glp->status_flags |= GG_STATUS_FLAG_SPAM; presence = purple_account_get_presence(account); status = purple_presence_get_active_status(presence); @@ -2136,13 +2312,26 @@ glp->async = 1; glp->status = ggp_to_gg_status(status, &glp->status_descr); - encryption_type = purple_account_get_string(account, "encryption", "none"); - purple_debug_info("gg", "Requested encryption type: %s\n", encryption_type); + encryption_type = purple_account_get_string(account, "encryption", + "opportunistic_tls"); + purple_debug_info("gg", "Requested encryption type: %s\n", + encryption_type); if (strcmp(encryption_type, "opportunistic_tls") == 0) - glp->tls = 1; - else - glp->tls = 0; - purple_debug_info("gg", "TLS enabled: %d\n", glp->tls); + glp->tls = GG_SSL_ENABLED; + else if (strcmp(encryption_type, "require_tls") == 0) { + if (gg_libgadu_check_feature(GG_LIBGADU_FEATURE_SSL)) + glp->tls = GG_SSL_REQUIRED; + else { + purple_connection_error(gc, + PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, + _("SSL support unavailable")); + g_free(glp); + return; + } + } + else /* encryption_type == "none" */ + glp->tls = GG_SSL_DISABLED; + purple_debug_info("gg", "TLS mode: %d\n", glp->tls); if (!info->status_broadcasting) glp->status = glp->status|GG_STATUS_FRIENDS_MASK; @@ -2157,7 +2346,7 @@ if (addr == NULL) { gchar *tmp = g_strdup_printf(_("Unable to resolve hostname '%s': %s"), address, g_strerror(errno)); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, /* should this be a settings error? */ tmp); g_free(tmp); @@ -2172,30 +2361,31 @@ info->session = gg_login(glp); purple_connection_update_progress(gc, _("Connecting"), 0, 2); if (info->session == NULL) { - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Connection failed")); g_free(glp); return; } - gc->inpa = purple_input_add(info->session->fd, PURPLE_INPUT_READ, + info->inpa = purple_input_add(info->session->fd, PURPLE_INPUT_READ, ggp_async_login_handler, gc); } static void ggp_close(PurpleConnection *gc) { + PurpleAccount *account; + GGPInfo *info;; if (gc == NULL) { purple_debug_info("gg", "gc == NULL\n"); return; } - if (gc->proto_data) { - PurpleAccount *account = purple_connection_get_account(gc); - PurpleStatus *status; - GGPInfo *info = gc->proto_data; - - status = purple_account_get_active_status(account); + account = purple_connection_get_account(gc); + info = purple_connection_get_protocol_data(gc); + + if (info) { + PurpleStatus *status = purple_account_get_active_status(account); if (info->session != NULL) { ggp_set_status(account, status); @@ -2213,20 +2403,21 @@ ggp_search_destroy(info->searches); g_list_free(info->pending_richtext_messages); g_hash_table_destroy(info->pending_images); + + if (info->inpa > 0) + purple_input_remove(info->inpa); + + purple_connection_set_protocol_data(gc, NULL); g_free(info); - gc->proto_data = NULL; } - if (gc->inpa > 0) - purple_input_remove(gc->inpa); - purple_debug_info("gg", "Connection closed.\n"); } static int ggp_send_im(PurpleConnection *gc, const char *who, const char *msg, PurpleMessageFlags flags) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); char *tmp, *plain; int ret = 1; unsigned char format[1024]; @@ -2344,6 +2535,7 @@ static unsigned int ggp_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState state) { + GGPInfo *info = purple_connection_get_protocol_data(gc); int dummy_length; // we don't send real length of typed message if (state == PURPLE_TYPED) // not supported @@ -2355,7 +2547,7 @@ dummy_length = 0; gg_typing_notification( - ((GGPInfo*)gc->proto_data)->session, + info->session, ggp_str_to_uin(name), dummy_length); @@ -2364,7 +2556,7 @@ static void ggp_get_info(PurpleConnection *gc, const char *name) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); GGPSearchForm *form; guint32 seq; @@ -2392,6 +2584,9 @@ if (strcmp(status_id, "available") == 0) { new_status = GG_STATUS_AVAIL; new_status_descr = GG_STATUS_AVAIL_DESCR; + } else if (strcmp(status_id, "freeforchat") == 0) { + new_status = GG_STATUS_FFC; + new_status_descr = GG_STATUS_FFC_DESCR; } else if (strcmp(status_id, "away") == 0) { new_status = GG_STATUS_BUSY; new_status_descr = GG_STATUS_BUSY_DESCR; @@ -2440,7 +2635,7 @@ return; gc = purple_account_get_connection(account); - info = gc->proto_data; + info = purple_connection_get_protocol_data(gc); new_status = ggp_to_gg_status(status, &new_msg); @@ -2458,10 +2653,10 @@ } -static void ggp_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) +static void ggp_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message) { PurpleAccount *account; - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); const gchar *name = purple_buddy_get_name(buddy); gg_add_notify(info->session, ggp_str_to_uin(name)); @@ -2475,14 +2670,14 @@ static void ggp_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); gg_remove_notify(info->session, ggp_str_to_uin(purple_buddy_get_name(buddy))); } static void ggp_join_chat(PurpleConnection *gc, GHashTable *data) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); GGPChat *chat; char *chat_name; GList *l; @@ -2520,7 +2715,7 @@ static int ggp_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags) { PurpleConversation *conv; - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); GGPChat *chat = NULL; GList *l; /* char *msg, *plain; */ @@ -2534,7 +2729,7 @@ for (l = info->chats; l != NULL; l = l->next) { chat = l->data; - if (g_utf8_collate(chat->name, conv->name) == 0) { + if (g_utf8_collate(chat->name, purple_conversation_get_name(conv)) == 0) { break; } @@ -2575,14 +2770,14 @@ static void ggp_keepalive(PurpleConnection *gc) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); /* purple_debug_info("gg", "Keeping connection alive....\n"); */ if (gg_ping(info->session) < 0) { purple_debug_info("gg", "Not connected to the server " "or gg_session is not correct\n"); - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Not connected to the server")); } @@ -2600,14 +2795,16 @@ GList *m = NULL; PurplePluginAction *act; + act = purple_plugin_action_new(_("Change password..."), + ggp_change_passwd); + m = g_list_append(m, act); + act = purple_plugin_action_new(_("Find buddies..."), ggp_find_buddies); m = g_list_append(m, act); - m = g_list_append(m, NULL); - - act = purple_plugin_action_new(_("Change password..."), - ggp_change_passwd); + act = purple_plugin_action_new(_("Change status broadcasting"), + ggp_action_change_status_broadcasting); m = g_list_append(m, act); m = g_list_append(m, NULL); @@ -2632,10 +2829,6 @@ ggp_action_buddylist_load); m = g_list_append(m, act); - act = purple_plugin_action_new(_("Change status broadcasting"), - ggp_action_change_status_broadcasting); - m = g_list_append(m, act); - return m; } @@ -2646,6 +2839,7 @@ static PurplePluginProtocolInfo prpl_info = { + sizeof(PurplePluginProtocolInfo), /* struct_size */ OPT_PROTO_REGISTER_NOSCREENNAME | OPT_PROTO_IM_IMAGE, NULL, /* user_splits */ NULL, /* protocol_options */ @@ -2686,13 +2880,12 @@ ggp_keepalive, /* keepalive */ ggp_register_user, /* register_user */ NULL, /* get_cb_info */ - NULL, /* get_cb_away */ NULL, /* alias_buddy */ NULL, /* group_buddy */ NULL, /* rename_group */ NULL, /* buddy_free */ NULL, /* convo_closed */ - NULL, /* normalize */ + ggp_normalize, /* normalize */ NULL, /* set_buddy_icon */ NULL, /* remove_group */ NULL, /* get_cb_real_name */ @@ -2711,15 +2904,12 @@ NULL, /* unregister_user */ NULL, /* send_attention */ NULL, /* get_attention_types */ - sizeof(PurplePluginProtocolInfo), /* struct_size */ NULL, /* get_account_text_table */ NULL, /* initiate_media */ NULL, /* can_do_media */ NULL, /* get_moods */ NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - NULL, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ + NULL /* get_public_alias */ }; static PurplePluginInfo info = { @@ -2785,11 +2975,6 @@ PurpleAccountOption *option; GList *encryption_options = NULL; - option = purple_account_option_string_new(_("Nickname"), - "nick", _("Gadu-Gadu User")); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, - option); - option = purple_account_option_string_new(_("GG server"), "gg_server", ""); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, @@ -2802,22 +2987,29 @@ list = g_list_append(list, kvp); \ } - ADD_VALUE(encryption_options, _("Don't use encryption"), "none"); ADD_VALUE(encryption_options, _("Use encryption if available"), "opportunistic_tls"); -#if 0 - /* TODO */ ADD_VALUE(encryption_options, _("Require encryption"), "require_tls"); -#endif + ADD_VALUE(encryption_options, _("Don't use encryption"), "none"); option = purple_account_option_list_new(_("Connection security"), "encryption", encryption_options); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + option = purple_account_option_bool_new(_("Show links from strangers"), + "show_links_from_strangers", 1); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + option); + my_protocol = plugin; gg_debug_handler = purple_gg_debug_handler; + +#ifdef _WIN32 + gg_global_set_custom_resolver(ggp_resolver_win32thread_start, + ggp_resolver_win32thread_cleanup); +#endif } PURPLE_INIT_PLUGIN(gg, init_plugin, info); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/gg.h --- a/libpurple/protocols/gg/gg.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/gg.h Fri Apr 06 04:30:00 2012 +0000 @@ -24,6 +24,7 @@ #ifndef _PURPLE_GG_H #define _PURPLE_GG_H +#undef printf #include #include "internal.h" #include "search.h" @@ -58,6 +59,7 @@ typedef struct { struct gg_session *session; + guint inpa; GGPToken *token; GList *chats; GGPSearches *searches; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/lib/common.c --- a/libpurple/protocols/gg/lib/common.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/lib/common.c Fri Apr 06 04:30:00 2012 +0000 @@ -24,22 +24,14 @@ * * \brief Funkcje wykorzystywane przez różne moduły biblioteki */ -#ifndef _WIN32 -# include -# include -# include -# include -# include -# ifdef sun -# include -# endif +#include "compat.h" +#include +#ifdef sun +# include #endif #include #include -#ifndef _WIN32 -# include -#endif #include #include #include @@ -92,7 +84,7 @@ } buf = tmp; res = vsnprintf(buf, size, format, ap); - } while (res == size - 1 || res == -1); + } while (res >= size - 1 || res == -1); } #else { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/lib/compat.h --- a/libpurple/protocols/gg/lib/compat.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/lib/compat.h Fri Apr 06 04:30:00 2012 +0000 @@ -28,6 +28,21 @@ #ifndef __COMPAT_H #define __COMPAT_H +#ifdef _WIN32 +# include +# include +# define EINPROGRESS WSAEINPROGRESS +# define ETIMEDOUT WSAETIMEDOUT +# define ENOTCONN WSAENOTCONN +# define ECONNRESET WSAECONNRESET +#else +# include +# include +# include +# include +# include +#endif + #ifdef sun # define INADDR_NONE ((in_addr_t) 0xffffffff) #endif diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/lib/dcc.c --- a/libpurple/protocols/gg/lib/dcc.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/lib/dcc.c Fri Apr 06 04:30:00 2012 +0000 @@ -26,16 +26,11 @@ * \brief Obsługa połączeń bezpośrednich do wersji Gadu-Gadu 6.x */ +#include "compat.h" #include #include -#ifndef _WIN32 -# include -# include -# include -# include -# ifdef sun -# include -# endif +#ifdef sun +# include #endif #include @@ -601,7 +596,7 @@ struct sockaddr_in sin; struct gg_dcc *c; int fd, one = 1; - unsigned int sin_len = sizeof(sin); + socklen_t sin_len = sizeof(sin); if ((fd = accept(h->fd, (struct sockaddr*) &sin, &sin_len)) == -1) { gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() can't accept() new connection (errno=%d, %s)\n", errno, strerror(errno)); @@ -648,7 +643,8 @@ struct gg_dcc_small_packet small; struct gg_dcc_big_packet big; int size, tmp, res; - unsigned int utmp, res_size = sizeof(res); + unsigned int utmp; + socklen_t res_size = sizeof(res); char buf[1024], ack[] = "UDAG"; struct gg_dcc_file_info_packet { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/lib/dcc7.c --- a/libpurple/protocols/gg/lib/dcc7.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/lib/dcc7.c Fri Apr 06 04:30:00 2012 +0000 @@ -31,14 +31,8 @@ #include #include -#ifndef _WIN32 -# include -# include -# include -# include -# ifdef sun -# include -# endif +#ifdef sun +# include #endif #include @@ -1095,7 +1089,7 @@ case GG_STATE_CONNECTING: { int res = 0, error = 0; - unsigned int error_size = sizeof(error); + socklen_t error_size = sizeof(error); gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_CONNECTING\n"); @@ -1384,7 +1378,7 @@ case GG_STATE_CONNECTING_RELAY: { int res; - unsigned int res_size = sizeof(res); + socklen_t res_size = sizeof(res); struct gg_dcc7_relay_req pkt; gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_CONNECTING_RELAY\n"); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/lib/events.c --- a/libpurple/protocols/gg/lib/events.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/lib/events.c Fri Apr 06 04:30:00 2012 +0000 @@ -28,17 +28,10 @@ */ #include -#ifndef _WIN32 -# include -# include -# include -# include -#endif #include #include "compat.h" #include "libgadu.h" -#include "libgadu-config.h" #include "protocol.h" #include "libgadu-internal.h" #include "encoding.h" diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/lib/handlers.c --- a/libpurple/protocols/gg/lib/handlers.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/lib/handlers.c Fri Apr 06 04:30:00 2012 +0000 @@ -27,21 +27,13 @@ */ #include -#ifndef _WIN32 -# include -# include -# include -#endif #include -#ifndef _WIN32 -# ifdef sun -# include -# endif +#ifdef sun +# include #endif #include "compat.h" #include "libgadu.h" -#include "libgadu-config.h" #include "resolver.h" #include "session.h" #include "protocol.h" @@ -51,9 +43,6 @@ #include "deflate.h" #include -#ifndef _WIN32 -# include -#endif #include #include #include @@ -92,7 +81,7 @@ uint8_t hash_buf[64]; uint32_t local_ip; struct sockaddr_in sin; - unsigned int sin_len = sizeof(sin); + socklen_t sin_len = sizeof(sin); if (len < sizeof(struct gg_welcome)) { ge->type = GG_EVENT_CONN_FAILED; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/lib/http.c --- a/libpurple/protocols/gg/lib/http.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/lib/http.c Fri Apr 06 04:30:00 2012 +0000 @@ -25,11 +25,6 @@ */ #include -#ifndef _WIN32 -# include -# include -# include -#endif #include "compat.h" #include "libgadu.h" @@ -37,9 +32,6 @@ #include #include -#ifndef _WIN32 -# include -#endif #include #include #include @@ -258,7 +250,7 @@ } if (h->state == GG_STATE_SENDING_QUERY) { - size_t res; + ssize_t res; if ((res = write(h->fd, h->query, strlen(h->query))) < 1) { gg_debug(GG_DEBUG_MISC, "=> http, write() failed (len=%d, res=%d, errno=%d)\n", strlen(h->query), res, errno); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/lib/libgadu-config.h --- a/libpurple/protocols/gg/lib/libgadu-config.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/lib/libgadu-config.h Fri Apr 06 04:30:00 2012 +0000 @@ -8,8 +8,30 @@ /* Defined if libgadu was compiled for bigendian machine. */ #undef __GG_LIBGADU_BIGENDIAN #ifdef WORDS_BIGENDIAN -#define __GG_LIBGADU_BIGENDIAN -#endif /* WORDS_BIGENDIAN */ +# define __GG_LIBGADU_BIGENDIAN +#endif + +/* Defined if this machine has gethostbyname_r(). */ +#undef GG_CONFIG_HAVE_GETHOSTBYNAME_R + +/* Defined if this machine has _exit(). */ +#define GG_CONFIG_HAVE__EXIT + +/* Defined if libgadu was compiled and linked with fork support. */ +#undef GG_CONFIG_HAVE_FORK +#ifndef _WIN32 +# define GG_CONFIG_HAVE_FORK +#endif + +/* Defined if libgadu was compiled and linked with pthread support. */ +/* We don't like pthreads. */ +#undef __GG_LIBGADU_HAVE_PTHREAD + +/* Defined if this machine has C99-compiliant vsnprintf(). */ +#undef __GG_LIBGADU_HAVE_C99_VSNPRINTF +#ifndef _WIN32 +# define __GG_LIBGADU_HAVE_C99_VSNPRINTF +#endif /* Defined if this machine has va_copy(). */ #define __GG_LIBGADU_HAVE_VA_COPY @@ -20,40 +42,29 @@ /* Defined if this machine supports long long. */ #undef __GG_LIBGADU_HAVE_LONG_LONG #ifdef HAVE_LONG_LONG -#define __GG_LIBGADU_HAVE_LONG_LONG -#endif /* HAVE_LONG_LONG */ +# define __GG_LIBGADU_HAVE_LONG_LONG +#endif -/* Defined if libgadu was compiled and linked with pthread support. */ -/* We don't like pthreads. */ -#undef __GG_LIBGADU_HAVE_PTHREAD - -/* Defined if libgadu was compiled and linked with GnuTLS encryption support. */ +/* Defined if libgadu was compiled and linked with GnuTLS support. */ +#undef GG_CONFIG_HAVE_GNUTLS #ifdef HAVE_GNUTLS # define GG_CONFIG_HAVE_GNUTLS -#else -# undef GG_CONFIG_HAVE_GNUTLS #endif -/* Defined if libgadu was compiled and linked with TLS support. */ +/* Defined if libgadu was compiled and linked with OpenSSL support. */ /* Always undefined in Purple. */ #undef __GG_LIBGADU_HAVE_OPENSSL -/* Include file containing uintXX_t declarations. */ +/* Defined if libgadu was compiled and linked with zlib support. */ +#undef GG_CONFIG_HAVE_ZLIB + +/* Defined if uintX_t types are defined in . */ +#undef GG_CONFIG_HAVE_STDINT_H #if HAVE_STDINT_H -#include +# define GG_CONFIG_HAVE_STDINT_H #endif -/* Defined if this machine has C99-compiliant vsnprintf(). */ -#ifndef _WIN32 -#define __GG_LIBGADU_HAVE_C99_VSNPRINTF -#else -#undef __GG_LIBGADU_HAVE_C99_VSNPRINTF -#endif #define vnsprintf g_vnsprintf -#ifdef _WIN32 -#define random (long) rand #endif - -#endif /* __GG_LIBGADU_CONFIG_H */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/lib/libgadu.c --- a/libpurple/protocols/gg/lib/libgadu.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/lib/libgadu.c Fri Apr 06 04:30:00 2012 +0000 @@ -29,23 +29,12 @@ */ #include -#ifdef _WIN32 -# include -# include -# include -# define SHUT_RDWR SD_BOTH -#else -# include -# include -# include -# ifdef sun -# include -# endif +#ifdef sun +# include #endif #include "compat.h" #include "libgadu.h" -#include "libgadu-config.h" #include "protocol.h" #include "resolver.h" #include "libgadu-internal.h" @@ -55,10 +44,7 @@ #include "message.h" #include "deflate.h" -#ifndef _WIN32 -# include /* on Win32 this is included above */ -# include -#endif +#include #include #include #include @@ -1122,7 +1108,6 @@ sess->resolver_cleanup(&sess->resolver, 1); if (sess->fd != -1) { - shutdown(sess->fd, SHUT_RDWR); close(sess->fd); sess->fd = -1; } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/lib/libgadu.h --- a/libpurple/protocols/gg/lib/libgadu.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/lib/libgadu.h Fri Apr 06 04:30:00 2012 +0000 @@ -33,7 +33,7 @@ #ifndef __GG_LIBGADU_H #define __GG_LIBGADU_H -#ifdef _WIN32 +#if defined(__cplusplus) || defined(_WIN32) #pragma pack(push, 1) #endif @@ -53,6 +53,12 @@ /* Defined if this machine has gethostbyname_r(). */ #undef GG_CONFIG_HAVE_GETHOSTBYNAME_R +/* Defined if this machine has _exit(). */ +#undef GG_CONFIG_HAVE__EXIT + +/* Defined if libgadu was compiled and linked with fork support. */ +#undef GG_CONFIG_HAVE_FORK + /* Defined if libgadu was compiled and linked with pthread support. */ #undef GG_CONFIG_HAVE_PTHREAD @@ -95,6 +101,8 @@ /* Defined if uintX_t types are defined in . */ #undef GG_CONFIG_HAVE_SYS_TYPES_H +#include "libgadu-config.h" + #ifdef GG_CONFIG_HAVE_OPENSSL #include #endif @@ -115,24 +123,12 @@ # include # else -#ifndef __AC_STDINT_H -#define __AC_STDINT_H - /* ISO C 9X: 7.18 Integer types */ typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; -#if !defined(__CYGWIN__) && !defined(__SunOS) && !defined(_INCLUDE_HPUX_SOURCE) -#define __int8_t_defined -typedef signed char int8_t; -typedef signed short int16_t; -typedef signed int int32_t; -#endif - -#endif /* __AC_STDINT_H */ - # endif # endif # endif @@ -195,7 +191,6 @@ GG_RESOLVER_DEFAULT = 0, /**< Domyślny sposób rozwiązywania nazw (jeden z poniższych) */ GG_RESOLVER_FORK, /**< Rozwiązywanie nazw bazujące na procesach */ GG_RESOLVER_PTHREAD, /**< Rozwiązywanie nazw bazujące na wątkach */ - GG_RESOLVER_WIN32, GG_RESOLVER_CUSTOM, /**< Funkcje rozwiązywania nazw dostarczone przed aplikację */ GG_RESOLVER_INVALID = -1 /**< Nieprawidłowy sposób rozwiązywania nazw (wynik \c gg_session_get_resolver) */ } gg_resolver_t; @@ -1442,7 +1437,6 @@ int gg_file_hash_sha1(int fd, uint8_t *result) GG_DEPRECATED; -#undef printf #ifdef __GNUC__ char *gg_saprintf(const char *format, ...) __attribute__ ((format (printf, 1, 2))) GG_DEPRECATED; #else @@ -2298,12 +2292,12 @@ #define GG_DCC7_TIMEOUT_FILE_ACK 300 /* 5 minut */ #define GG_DCC7_TIMEOUT_VOICE_ACK 300 /* 5 minut */ -#ifdef _WIN32 -#pragma pack(pop) +#ifdef __cplusplus +} #endif -#ifdef __cplusplus -} +#if defined(__cplusplus) || defined(_WIN32) +#pragma pack(pop) #endif #endif /* __GG_LIBGADU_H */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/lib/pubdir.c --- a/libpurple/protocols/gg/lib/pubdir.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/lib/pubdir.c Fri Apr 06 04:30:00 2012 +0000 @@ -35,7 +35,6 @@ #include #include "libgadu.h" -#include "libgadu-config.h" /** * Rejestruje nowego użytkownika. @@ -194,7 +193,7 @@ return NULL; } - __pwd = gg_saprintf("%ld", random()); + __pwd = gg_saprintf("%d", rand()); __fmpwd = gg_urlencode(password); __tokenid = gg_urlencode(tokenid); __tokenval = gg_urlencode(tokenval); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/lib/pubdir50.c --- a/libpurple/protocols/gg/lib/pubdir50.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/lib/pubdir50.c Fri Apr 06 04:30:00 2012 +0000 @@ -31,7 +31,6 @@ #include #include "libgadu.h" -#include "libgadu-config.h" #include "libgadu-internal.h" #include "encoding.h" diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/lib/resolver.c --- a/libpurple/protocols/gg/lib/resolver.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/lib/resolver.c Fri Apr 06 04:30:00 2012 +0000 @@ -26,26 +26,21 @@ * \brief Funkcje rozwiązywania nazw */ -#ifndef _WIN32 -# include -# include -#endif #include #include #include #include -#ifndef _WIN32 -# include -# include -# include -#endif #include "libgadu.h" -#include "libgadu-config.h" #include "resolver.h" #include "compat.h" #include "session.h" +#ifdef GG_CONFIG_HAVE_FORK +#include +#include +#endif + /** Sposób rozwiązywania nazw serwerów */ static gg_resolver_t gg_global_resolver_type = GG_RESOLVER_DEFAULT; @@ -249,7 +244,8 @@ #endif /* GG_CONFIG_HAVE_GETHOSTBYNAME_R */ } -#if defined(GG_CONFIG_HAVE_PTHREAD) || !defined(_WIN32) +#if defined(GG_CONFIG_HAVE_PTHREAD) || defined(GG_CONFIG_HAVE_FORK) + /** * \internal Rozwiązuje nazwę i zapisuje wynik do podanego desktyptora. * @@ -287,7 +283,8 @@ return res; } -#endif + +#endif /* GG_CONFIG_HAVE_PTHREAD || GG_CONFIG_HAVE_FORK */ /** * \internal Odpowiednik \c gethostbyname zapewniający współbieżność. @@ -312,6 +309,8 @@ return result; } +#ifdef GG_CONFIG_HAVE_FORK + /** * \internal Struktura przekazywana do wątku rozwiązującego nazwę. */ @@ -319,280 +318,6 @@ int pid; /*< Identyfikator procesu */ }; -#ifdef _WIN32 -/** - * Deal with the fact that you can't select() on a win32 file fd. - * This makes it practically impossible to tie into purple's event loop. - * - * -This is thanks to Tor Lillqvist. - * XXX - Move this to where the rest of the the win32 compatiblity stuff goes when we push the changes back to libgadu. - */ -static int -socket_pipe (int *fds) -{ - SOCKET temp, socket1 = -1, socket2 = -1; - struct sockaddr_in saddr; - int len; - u_long arg; - fd_set read_set, write_set; - struct timeval tv; - - temp = socket(AF_INET, SOCK_STREAM, 0); - - if (temp == INVALID_SOCKET) { - goto out0; - } - - arg = 1; - if (ioctlsocket(temp, FIONBIO, &arg) == SOCKET_ERROR) { - goto out0; - } - - memset(&saddr, 0, sizeof(saddr)); - saddr.sin_family = AF_INET; - saddr.sin_port = 0; - saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - if (bind(temp, (struct sockaddr *)&saddr, sizeof (saddr))) { - goto out0; - } - - if (listen(temp, 1) == SOCKET_ERROR) { - goto out0; - } - - len = sizeof(saddr); - if (getsockname(temp, (struct sockaddr *)&saddr, &len)) { - goto out0; - } - - socket1 = socket(AF_INET, SOCK_STREAM, 0); - - if (socket1 == INVALID_SOCKET) { - goto out0; - } - - arg = 1; - if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) { - goto out1; - } - - if (connect(socket1, (struct sockaddr *)&saddr, len) != SOCKET_ERROR || - WSAGetLastError() != WSAEWOULDBLOCK) { - goto out1; - } - - FD_ZERO(&read_set); - FD_SET(temp, &read_set); - - tv.tv_sec = 0; - tv.tv_usec = 0; - - if (select(0, &read_set, NULL, NULL, NULL) == SOCKET_ERROR) { - goto out1; - } - - if (!FD_ISSET(temp, &read_set)) { - goto out1; - } - - socket2 = accept(temp, (struct sockaddr *) &saddr, &len); - if (socket2 == INVALID_SOCKET) { - goto out1; - } - - FD_ZERO(&write_set); - FD_SET(socket1, &write_set); - - tv.tv_sec = 0; - tv.tv_usec = 0; - - if (select(0, NULL, &write_set, NULL, NULL) == SOCKET_ERROR) { - goto out2; - } - - if (!FD_ISSET(socket1, &write_set)) { - goto out2; - } - - arg = 0; - if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) { - goto out2; - } - - arg = 0; - if (ioctlsocket(socket2, FIONBIO, &arg) == SOCKET_ERROR) { - goto out2; - } - - fds[0] = socket1; - fds[1] = socket2; - - closesocket (temp); - - return 0; - -out2: - closesocket (socket2); -out1: - closesocket (socket1); -out0: - closesocket (temp); - errno = EIO; /* XXX */ - - return -1; -} -#endif - - - -#ifdef _WIN32 -struct gg_resolve_win32thread_data { - char *hostname; - int fd; -}; - -static DWORD WINAPI gg_resolve_win32thread_thread(LPVOID arg) -{ - struct gg_resolve_win32thread_data *d = arg; - struct in_addr addr_ip[2], *addr_list; - int addr_count; - - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_thread() host: %s, fd: %i called\n", d->hostname, d->fd); - - if ((addr_ip[0].s_addr = inet_addr(d->hostname)) == INADDR_NONE) { - /* W przypadku błędu gg_gethostbyname_real() zwróci -1 - * i nie zmieni &addr. Tam jest już INADDR_NONE, - * więc nie musimy robić nic więcej. */ - if (gg_gethostbyname_real(d->hostname, &addr_list, &addr_count, 0) == -1) - { - addr_list = addr_ip; - } - } else { - addr_list = addr_ip; - addr_ip[1].s_addr = INADDR_NONE; - addr_count = 1; - } - - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_thread() count = %d\n", addr_count); - - write(d->fd, addr_list, (addr_count+1) * sizeof(struct in_addr)); - close(d->fd); - - free(d->hostname); - d->hostname = NULL; - - free(d); - - if (addr_list != addr_ip) - free(addr_list); - - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_thread() done\n"); - - return 0; -} - - -static int gg_resolve_win32thread(int *fd, void **resolver, const char *hostname) -{ - struct gg_resolve_win32thread_data *d = NULL; - HANDLE h; - DWORD dwTId; - int pipes[2], new_errno; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve_win32thread(%p, %p, \"%s\");\n", fd, resolver, hostname); - - if (!resolver || !fd || !hostname) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() invalid arguments\n"); - errno = EFAULT; - return -1; - } - - if (socket_pipe(pipes) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno)); - return -1; - } - - if (!(d = malloc(sizeof(*d)))) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() out of memory\n"); - new_errno = errno; - goto cleanup; - } - - d->hostname = NULL; - - if (!(d->hostname = strdup(hostname))) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() out of memory\n"); - new_errno = errno; - goto cleanup; - } - - d->fd = pipes[1]; - - h = CreateThread(NULL, 0, gg_resolve_win32thread_thread, - d, 0, &dwTId); - - if (h == NULL) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() unable to create thread\n"); - new_errno = errno; - goto cleanup; - } - - *resolver = h; - *fd = pipes[0]; - - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() done\n"); - - return 0; - -cleanup: - if (d) { - free(d->hostname); - free(d); - } - - close(pipes[0]); - close(pipes[1]); - - errno = new_errno; - - return -1; - -} - -static void gg_resolve_win32thread_cleanup(void **priv_data, int force) -{ - struct gg_resolve_win32thread_data *data; - - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() force: %i called\n", force); - - if (priv_data == NULL || *priv_data == NULL) - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() priv_data: NULL\n"); - return; - - data = (struct gg_resolve_win32thread_data*) *priv_data; - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() data: %s called\n", data->hostname); - *priv_data = NULL; - - if (force) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() force called\n", force); - //pthread_cancel(data->thread); - //pthread_join(data->thread, NULL); - } - - free(data->hostname); - data->hostname = NULL; - - if (data->fd != -1) { - close(data->fd); - data->fd = -1; - } - gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() done\n"); - free(data); -} -#endif - -#ifndef _WIN32 /** * \internal Rozwiązuje nazwę serwera w osobnym procesie. * @@ -644,12 +369,17 @@ } if (data->pid == 0) { + int status; + close(pipes[0]); - if (gg_resolver_run(pipes[1], hostname) == -1) - _exit(1); - else - _exit(0); + status = (gg_resolver_run(pipes[1], hostname) == -1) ? 1 : 0; + +#ifdef GG_CONFIG_HAVE__EXIT + _exit(status); +#else + exit(status); +#endif } close(pipes[1]); @@ -698,7 +428,8 @@ free(data); } -#endif + +#endif /* GG_CONFIG_HAVE_FORK */ #ifdef GG_CONFIG_HAVE_PTHREAD @@ -868,25 +599,15 @@ return 0; } -#if !defined(GG_CONFIG_HAVE_PTHREAD) || !defined(GG_CONFIG_PTHREAD_DEFAULT) -# ifdef _WIN32 - type = GG_RESOLVER_WIN32; -# else +#if defined(GG_CONFIG_HAVE_PTHREAD) && defined(GG_CONFIG_PTHREAD_DEFAULT) + type = GG_RESOLVER_PTHREAD; +#elif defined(GG_CONFIG_HAVE_FORK) type = GG_RESOLVER_FORK; -# endif -#else - type = GG_RESOLVER_PTHREAD; #endif } switch (type) { -#ifdef _WIN32 - case GG_RESOLVER_WIN32: - gs->resolver_type = type; - gs->resolver_start = gg_resolve_win32thread; - gs->resolver_cleanup = gg_resolve_win32thread_cleanup; - return 0; -#else +#ifdef GG_CONFIG_HAVE_FORK case GG_RESOLVER_FORK: gs->resolver_type = type; gs->resolver_start = gg_resolver_fork_start; @@ -989,25 +710,15 @@ return 0; } -#if !defined(GG_CONFIG_HAVE_PTHREAD) || !defined(GG_CONFIG_PTHREAD_DEFAULT) -# ifdef _WIN32 - type = GG_RESOLVER_WIN32; -# else +#if defined(GG_CONFIG_HAVE_PTHREAD) && defined(GG_CONFIG_PTHREAD_DEFAULT) + type = GG_RESOLVER_PTHREAD; +#elif defined(GG_CONFIG_HAVE_FORK) type = GG_RESOLVER_FORK; -# endif -#else - type = GG_RESOLVER_PTHREAD; #endif } switch (type) { -#ifdef _WIN32 - case GG_RESOLVER_WIN32: - gh->resolver_type = type; - gh->resolver_start = gg_resolve_win32thread; - gh->resolver_cleanup = gg_resolve_win32thread_cleanup; - return 0; -#else +#ifdef GG_CONFIG_HAVE_FORK case GG_RESOLVER_FORK: gh->resolver_type = type; gh->resolver_start = gg_resolver_fork_start; @@ -1085,13 +796,7 @@ gg_global_resolver_cleanup = NULL; return 0; -#ifdef _WIN32 - case GG_RESOLVER_WIN32: - gg_global_resolver_type = type; - gg_global_resolver_start = gg_resolve_win32thread; - gg_global_resolver_cleanup = gg_resolve_win32thread_cleanup; - return 0; -#else +#ifdef GG_CONFIG_HAVE_FORK case GG_RESOLVER_FORK: gg_global_resolver_type = type; gg_global_resolver_start = gg_resolver_fork_start; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/lib/resolver.h --- a/libpurple/protocols/gg/lib/resolver.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/lib/resolver.h Fri Apr 06 04:30:00 2012 +0000 @@ -19,9 +19,7 @@ #ifndef LIBGADU_RESOLVER_H #define LIBGADU_RESOLVER_H -#ifndef _WIN32 -# include -#endif +#include "compat.h" int gg_gethostbyname_real(const char *hostname, struct in_addr **result, int *count, int pthread); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/search.c --- a/libpurple/protocols/gg/search.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/gg/search.c Fri Apr 06 04:30:00 2012 +0000 @@ -135,7 +135,7 @@ /* guint32 ggp_search_start(PurpleConnection *gc, GGPSearchForm *form) {{{ */ guint32 ggp_search_start(PurpleConnection *gc, GGPSearchForm *form) { - GGPInfo *info = gc->proto_data; + GGPInfo *info = purple_connection_get_protocol_data(gc); gg_pubdir50_t req; guint seq, offset; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/win32-resolver.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/gg/win32-resolver.c Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,322 @@ +/** + * @file win32-resolver.c + * + * purple + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "win32-resolver.h" + +#include +#include +#include "debug.h" + +#ifndef _WIN32 +#error "win32thread resolver is not supported on current platform" +#endif + +/** + * Deal with the fact that you can't select() on a win32 file fd. + * This makes it practically impossible to tie into purple's event loop. + * + * -This is thanks to Tor Lillqvist. + */ +static int ggp_resolver_win32thread_socket_pipe(int *fds) +{ + SOCKET temp, socket1 = -1, socket2 = -1; + struct sockaddr_in saddr; + int len; + u_long arg; + fd_set read_set, write_set; + struct timeval tv; + + purple_debug_misc("gg", "ggp_resolver_win32thread_socket_pipe(&%d)\n", + *fds); + + temp = socket(AF_INET, SOCK_STREAM, 0); + + if (temp == INVALID_SOCKET) { + goto out0; + } + + arg = 1; + if (ioctlsocket(temp, FIONBIO, &arg) == SOCKET_ERROR) { + goto out0; + } + + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_port = 0; + saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + if (bind(temp, (struct sockaddr *)&saddr, sizeof (saddr))) { + goto out0; + } + + if (listen(temp, 1) == SOCKET_ERROR) { + goto out0; + } + + len = sizeof(saddr); + if (getsockname(temp, (struct sockaddr *)&saddr, &len)) { + goto out0; + } + + socket1 = socket(AF_INET, SOCK_STREAM, 0); + + if (socket1 == INVALID_SOCKET) { + goto out0; + } + + arg = 1; + if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) { + goto out1; + } + + if (connect(socket1, (struct sockaddr *)&saddr, len) != SOCKET_ERROR || + WSAGetLastError() != WSAEWOULDBLOCK) { + goto out1; + } + + FD_ZERO(&read_set); + FD_SET(temp, &read_set); + + tv.tv_sec = 0; + tv.tv_usec = 0; + + if (select(0, &read_set, NULL, NULL, NULL) == SOCKET_ERROR) { + goto out1; + } + + if (!FD_ISSET(temp, &read_set)) { + goto out1; + } + + socket2 = accept(temp, (struct sockaddr *) &saddr, &len); + if (socket2 == INVALID_SOCKET) { + goto out1; + } + + FD_ZERO(&write_set); + FD_SET(socket1, &write_set); + + tv.tv_sec = 0; + tv.tv_usec = 0; + + if (select(0, NULL, &write_set, NULL, NULL) == SOCKET_ERROR) { + goto out2; + } + + if (!FD_ISSET(socket1, &write_set)) { + goto out2; + } + + arg = 0; + if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) { + goto out2; + } + + arg = 0; + if (ioctlsocket(socket2, FIONBIO, &arg) == SOCKET_ERROR) { + goto out2; + } + + fds[0] = socket1; + fds[1] = socket2; + + closesocket (temp); + + return 0; + +out2: + closesocket (socket2); +out1: + closesocket (socket1); +out0: + closesocket (temp); + errno = EIO; /* XXX */ + + return -1; +} + +struct ggp_resolver_win32thread_data { + char *hostname; + int fd; +}; + +/** + * Copy-paste from gg_resolver_run(). + */ +static DWORD WINAPI ggp_resolver_win32thread_thread(LPVOID arg) +{ + struct ggp_resolver_win32thread_data *data = arg; + struct in_addr addr_ip[2], *addr_list; + int addr_count; + + purple_debug_info("gg", "ggp_resolver_win32thread_thread() host: %s, " + "fd: %i called\n", data->hostname, data->fd); + + if ((addr_ip[0].s_addr = inet_addr(data->hostname)) == INADDR_NONE) { + if (gg_gethostbyname_real(data->hostname, &addr_list, + &addr_count, 0) == -1) { + addr_list = addr_ip; + /* addr_ip[0] już zawiera INADDR_NONE */ + } + } else { + addr_list = addr_ip; + addr_ip[1].s_addr = INADDR_NONE; + addr_count = 1; + } + + purple_debug_misc("gg", "ggp_resolver_win32thread_thread() " + "count = %d\n", addr_count); + + write(data->fd, addr_list, (addr_count + 1) * sizeof(struct in_addr)); + close(data->fd); + + free(data->hostname); + data->hostname = NULL; + + free(data); + + if (addr_list != addr_ip) + free(addr_list); + + purple_debug_misc("gg", "ggp_resolver_win32thread_thread() done\n"); + + return 0; +} + + +int ggp_resolver_win32thread_start(int *fd, void **private_data, + const char *hostname) +{ + struct ggp_resolver_win32thread_data *data = NULL; + HANDLE h; + DWORD dwTId; + int pipes[2], new_errno; + + purple_debug_info("gg", "ggp_resolver_win32thread_start(%p, %p, " + "\"%s\");\n", fd, private_data, hostname); + + if (!private_data || !fd || !hostname) { + purple_debug_error("gg", "ggp_resolver_win32thread_start() " + "invalid arguments\n"); + errno = EFAULT; + return -1; + } + + purple_debug_misc("gg", "ggp_resolver_win32thread_start() creating " + "pipes...\n"); + + if (ggp_resolver_win32thread_socket_pipe(pipes) == -1) { + purple_debug_error("gg", "ggp_resolver_win32thread_start() " + "unable to create pipes (errno=%d, %s)\n", + errno, strerror(errno)); + return -1; + } + + if (!(data = malloc(sizeof(*data)))) { + purple_debug_error("gg", "ggp_resolver_win32thread_start() out " + "of memory\n"); + new_errno = errno; + goto cleanup; + } + + data->hostname = NULL; + + if (!(data->hostname = strdup(hostname))) { + purple_debug_error("gg", "ggp_resolver_win32thread_start() out " + "of memory\n"); + new_errno = errno; + goto cleanup; + } + + data->fd = pipes[1]; + + purple_debug_misc("gg", "ggp_resolver_win32thread_start() creating " + "thread...\n"); + + h = CreateThread(NULL, 0, ggp_resolver_win32thread_thread, data, 0, + &dwTId); + + if (h == NULL) { + purple_debug_error("gg", "ggp_resolver_win32thread_start() " + "unable to create thread\n"); + new_errno = errno; + goto cleanup; + } + + *private_data = h; + *fd = pipes[0]; + + purple_debug_misc("gg", "ggp_resolver_win32thread_start() done\n"); + + return 0; + +cleanup: + if (data) { + free(data->hostname); + free(data); + } + + close(pipes[0]); + close(pipes[1]); + + errno = new_errno; + + return -1; + +} + +void ggp_resolver_win32thread_cleanup(void **private_data, int force) +{ + struct ggp_resolver_win32thread_data *data; + + purple_debug_info("gg", "ggp_resolver_win32thread_cleanup() force: %i " + "called\n", force); + + if (private_data == NULL || *private_data == NULL) { + purple_debug_error("gg", "ggp_resolver_win32thread_cleanup() " + "private_data: NULL\n"); + return; + } + return; /* XXX */ + + data = (struct ggp_resolver_win32thread_data*) *private_data; + purple_debug_misc("gg", "ggp_resolver_win32thread_cleanup() data: " + "%s called\n", data->hostname); + *private_data = NULL; + + if (force) { + purple_debug_misc("gg", "ggp_resolver_win32thread_cleanup() " + "force called\n"); + //pthread_cancel(data->thread); + //pthread_join(data->thread, NULL); + } + + free(data->hostname); + data->hostname = NULL; + + if (data->fd != -1) { + close(data->fd); + data->fd = -1; + } + purple_debug_info("gg", "ggp_resolver_win32thread_cleanup() done\n"); + free(data); +} + +/* vim: set ts=8 sts=0 sw=8 noet: */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/gg/win32-resolver.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/gg/win32-resolver.h Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,46 @@ +/** + * @file win32-resolver.h + * + * purple + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#ifndef _PURPLE_GG_WIN32_RESOLVER +#define _PURPLE_GG_WIN32_RESOLVER + +/** + * Starts hostname resolving in new win32 thread. + * + * @param fd Pointer to variable, where pipe descriptor will be saved. + * @param private_data Pointer to variable, where pointer to private data will + * be saved. + * @param hostname Hostname to resolve. + */ +int ggp_resolver_win32thread_start(int *fd, void **private_data, + const char *hostname); + +/** + * Cleans up resources after hostname resolving. + * + * @param private_data Pointer to variable storing pointer to private data. + * @param force TRUE, if resources should be cleaned up even, if + * resolving process didn't finished. + */ +void ggp_resolver_win32thread_cleanup(void **private_data, int force); + +#endif /* _PURPLE_GG_WIN32_RESOLVER */ + +/* vim: set ts=8 sts=0 sw=8 noet: */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/irc/cmds.c --- a/libpurple/protocols/irc/cmds.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/irc/cmds.c Fri Apr 06 04:30:00 2012 +0000 @@ -423,7 +423,7 @@ irc->quitting = TRUE; - if (!irc->account->disconnecting) + if (!purple_account_is_disconnecting(irc->account)) purple_account_set_status(irc->account, "offline", TRUE, NULL); } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/irc/dcc_send.c --- a/libpurple/protocols/irc/dcc_send.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/irc/dcc_send.c Fri Apr 06 04:30:00 2012 +0000 @@ -34,11 +34,12 @@ struct irc_xfer_rx_data { gchar *ip; + unsigned int remote_port; }; static void irc_dccsend_recv_destroy(PurpleXfer *xfer) { - struct irc_xfer_rx_data *xd = xfer->data; + struct irc_xfer_rx_data *xd = purple_xfer_get_protocol_data(xfer); g_free(xd->ip); g_free(xd); @@ -51,10 +52,10 @@ */ static void irc_dccsend_recv_ack(PurpleXfer *xfer, const guchar *data, size_t size) { guint32 l; - size_t result; + gssize result; - l = htonl(xfer->bytes_sent); - result = write(xfer->fd, &l, sizeof(l)); + l = htonl(purple_xfer_get_bytes_sent(xfer)); + result = purple_xfer_write(xfer, (guchar *)&l, sizeof(l)); if (result != sizeof(l)) { purple_debug_error("irc", "unable to send acknowledgement: %s\n", g_strerror(errno)); /* TODO: We should probably close the connection here or something. */ @@ -62,9 +63,9 @@ } static void irc_dccsend_recv_init(PurpleXfer *xfer) { - struct irc_xfer_rx_data *xd = xfer->data; + struct irc_xfer_rx_data *xd = purple_xfer_get_protocol_data(xfer); - purple_xfer_start(xfer, -1, xd->ip, xfer->remote_port); + purple_xfer_start(xfer, -1, xd->ip, xd->remote_port); g_free(xd->ip); xd->ip = NULL; } @@ -114,10 +115,10 @@ if (xfer) { xd = g_new0(struct irc_xfer_rx_data, 1); - xfer->data = xd; + purple_xfer_set_protocol_data(xfer, xd); purple_xfer_set_filename(xfer, filename->str); - xfer->remote_port = atoi(token[i+1]); + xd->remote_port = atoi(token[i+1]); nip = strtoul(token[i], NULL, 10); if (nip) { @@ -157,7 +158,7 @@ static void irc_dccsend_send_destroy(PurpleXfer *xfer) { - struct irc_xfer_send_data *xd = xfer->data; + struct irc_xfer_send_data *xd = purple_xfer_get_protocol_data(xfer); if (xd == NULL) return; @@ -178,7 +179,7 @@ static void irc_dccsend_send_read(gpointer data, int source, PurpleInputCondition cond) { PurpleXfer *xfer = data; - struct irc_xfer_send_data *xd = xfer->data; + struct irc_xfer_send_data *xd = purple_xfer_get_protocol_data(xfer); char buffer[64]; int len; @@ -228,13 +229,13 @@ static gssize irc_dccsend_send_write(const guchar *buffer, size_t size, PurpleXfer *xfer) { gssize s; - int ret; + gssize ret; s = MIN(purple_xfer_get_bytes_remaining(xfer), size); if (!s) return 0; - ret = write(xfer->fd, buffer, s); + ret = purple_xfer_write(xfer, buffer, s); if (ret < 0 && errno == EAGAIN) ret = 0; @@ -244,7 +245,7 @@ static void irc_dccsend_send_connected(gpointer data, int source, PurpleInputCondition cond) { PurpleXfer *xfer = (PurpleXfer *) data; - struct irc_xfer_send_data *xd = xfer->data; + struct irc_xfer_send_data *xd = purple_xfer_get_protocol_data(xfer); int conn, flags; conn = accept(xd->fd, NULL, 0); @@ -257,8 +258,8 @@ return; } - purple_input_remove(xfer->watcher); - xfer->watcher = 0; + purple_input_remove(purple_xfer_get_watcher(xfer)); + purple_xfer_set_watcher(xfer, 0); close(xd->fd); xd->fd = -1; @@ -285,7 +286,7 @@ struct in_addr addr; unsigned short int port; - xd = xfer->data; + xd = purple_xfer_get_protocol_data(xfer); xd->listen_data = NULL; if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL @@ -294,9 +295,9 @@ return; } - xd = xfer->data; + xd = purple_xfer_get_protocol_data(xfer); gc = purple_account_get_connection(purple_xfer_get_account(xfer)); - irc = gc->proto_data; + irc = purple_connection_get_protocol_data(gc); purple_xfer_unref(xfer); @@ -312,17 +313,17 @@ port = purple_network_get_port_from_fd(sock); purple_debug_misc("irc", "port is %hu\n", port); /* Monitor the listening socket */ - xfer->watcher = purple_input_add(sock, PURPLE_INPUT_READ, - irc_dccsend_send_connected, xfer); + purple_xfer_set_watcher(xfer, purple_input_add(sock, PURPLE_INPUT_READ, + irc_dccsend_send_connected, xfer)); /* Send the intended recipient the DCC request */ - arg[0] = xfer->who; + arg[0] = purple_xfer_get_remote_user(xfer); inet_aton(purple_network_get_my_ip(irc->fd), &addr); - arg[1] = tmp = g_strdup_printf("\001DCC SEND \"%s\" %u %hu %" G_GSIZE_FORMAT "\001", - xfer->filename, ntohl(addr.s_addr), - port, xfer->size); + arg[1] = tmp = g_strdup_printf("\001DCC SEND \"%s\" %u %hu %" G_GOFFSET_FORMAT "\001", + purple_xfer_get_filename(xfer), ntohl(addr.s_addr), + port, purple_xfer_get_size(xfer)); - irc_cmd_privmsg(gc->proto_data, "msg", NULL, arg); + irc_cmd_privmsg(purple_connection_get_protocol_data(gc), "msg", NULL, arg); g_free(tmp); } @@ -331,14 +332,14 @@ */ static void irc_dccsend_send_init(PurpleXfer *xfer) { PurpleConnection *gc = purple_account_get_connection(purple_xfer_get_account(xfer)); - struct irc_xfer_send_data *xd = xfer->data; + struct irc_xfer_send_data *xd = purple_xfer_get_protocol_data(xfer); - xfer->filename = g_path_get_basename(xfer->local_filename); + purple_xfer_set_filename(xfer, g_path_get_basename(purple_xfer_get_local_filename(xfer))); purple_xfer_ref(xfer); /* Create a listening socket */ - xd->listen_data = purple_network_listen_range(0, 0, SOCK_STREAM, + xd->listen_data = purple_network_listen_range(0, 0, AF_UNSPEC, SOCK_STREAM, TRUE, irc_dccsend_network_listen_cb, xfer); if (xd->listen_data == NULL) { purple_xfer_unref(xfer); @@ -359,7 +360,7 @@ { xd = g_new0(struct irc_xfer_send_data, 1); xd->fd = -1; - xfer->data = xd; + purple_xfer_set_protocol_data(xfer, xd); /* Setup our I/O op functions */ purple_xfer_set_init_fnc(xfer, irc_dccsend_send_init); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/irc/irc.c --- a/libpurple/protocols/irc/irc.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/irc/irc.c Fri Apr 06 04:30:00 2012 +0000 @@ -70,11 +70,11 @@ struct irc_conn *irc; char *title; - if (gc == NULL || gc->proto_data == NULL) { + if (gc == NULL || purple_connection_get_protocol_data(gc) == NULL) { purple_debug(PURPLE_DEBUG_ERROR, "irc", "got MOTD request for NULL gc\n"); return; } - irc = gc->proto_data; + irc = purple_connection_get_protocol_data(gc); if (irc->motd == NULL) { purple_notify_error(gc, _("Error displaying MOTD"), _("No MOTD available"), _("There is no MOTD associated with this connection.")); @@ -100,7 +100,7 @@ static int irc_send_raw(PurpleConnection *gc, const char *buf, int len) { - struct irc_conn *irc = (struct irc_conn*)gc->proto_data; + struct irc_conn *irc = purple_connection_get_protocol_data(gc); if (len == -1) { len = strlen(buf); } @@ -130,7 +130,7 @@ PurpleConnection *gc = purple_account_get_connection(irc->account); gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; @@ -174,7 +174,7 @@ PurpleConnection *gc = purple_account_get_connection(irc->account); gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); } else if (ret < buflen) { @@ -356,16 +356,17 @@ const char *username = purple_account_get_username(account); gc = purple_account_get_connection(account); - gc->flags |= PURPLE_CONNECTION_NO_NEWLINES; + purple_connection_set_flags(gc, PURPLE_CONNECTION_NO_NEWLINES); if (strpbrk(username, " \t\v\r\n") != NULL) { - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, _("IRC nick and server may not contain whitespace")); return; } - gc->proto_data = irc = g_new0(struct irc_conn, 1); + irc = g_new0(struct irc_conn, 1); + purple_connection_set_protocol_data(gc, irc); irc->fd = -1; irc->account = account; irc->outbuf = purple_circ_buffer_new(512); @@ -390,7 +391,7 @@ purple_account_get_int(account, "port", IRC_DEFAULT_SSL_PORT), irc_login_cb_ssl, irc_ssl_connect_failure, gc); } else { - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("SSL support unavailable")); return; @@ -403,7 +404,7 @@ purple_account_get_int(account, "port", IRC_DEFAULT_PORT), irc_login_cb, gc) == NULL) { - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); return; @@ -415,7 +416,7 @@ char *buf, *tmp = NULL; char *server; const char *username, *realname; - struct irc_conn *irc = gc->proto_data; + struct irc_conn *irc = purple_connection_get_protocol_data(gc); const char *pass = purple_connection_get_password(gc); if (pass && *pass) { @@ -485,12 +486,12 @@ static void irc_login_cb(gpointer data, gint source, const gchar *error_message) { PurpleConnection *gc = data; - struct irc_conn *irc = gc->proto_data; + struct irc_conn *irc = purple_connection_get_protocol_data(gc); if (source < 0) { gchar *tmp = g_strdup_printf(_("Unable to connect: %s"), error_message); - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; @@ -499,7 +500,7 @@ irc->fd = source; if (do_login(gc)) { - gc->inpa = purple_input_add(irc->fd, PURPLE_INPUT_READ, irc_input_cb, gc); + irc->inpa = purple_input_add(irc->fd, PURPLE_INPUT_READ, irc_input_cb, gc); } } @@ -508,7 +509,7 @@ gpointer data) { PurpleConnection *gc = data; - struct irc_conn *irc = gc->proto_data; + struct irc_conn *irc = purple_connection_get_protocol_data(gc); irc->gsc = NULL; @@ -517,7 +518,7 @@ static void irc_close(PurpleConnection *gc) { - struct irc_conn *irc = gc->proto_data; + struct irc_conn *irc = purple_connection_get_protocol_data(gc); if (irc == NULL) return; @@ -525,8 +526,10 @@ if (irc->gsc || (irc->fd >= 0)) irc_cmd_quit(irc, "quit", NULL, NULL); - if (gc->inpa) - purple_input_remove(gc->inpa); + if (irc->inpa) { + purple_input_remove(irc->inpa); + irc->inpa = 0; + } g_free(irc->inbuf); if (irc->gsc) { @@ -558,7 +561,7 @@ static int irc_im_send(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags) { - struct irc_conn *irc = gc->proto_data; + struct irc_conn *irc = purple_connection_get_protocol_data(gc); char *plain; const char *args[2]; @@ -574,7 +577,7 @@ static void irc_get_info(PurpleConnection *gc, const char *who) { - struct irc_conn *irc = gc->proto_data; + struct irc_conn *irc = purple_connection_get_protocol_data(gc); const char *args[2]; args[0] = who; args[1] = NULL; @@ -589,7 +592,7 @@ const char *status_id = purple_status_get_id(status); g_return_if_fail(gc != NULL); - irc = gc->proto_data; + irc = purple_connection_get_protocol_data(gc); if (!purple_status_is_active(status)) return; @@ -606,9 +609,9 @@ } } -static void irc_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) +static void irc_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message) { - struct irc_conn *irc = (struct irc_conn *)gc->proto_data; + struct irc_conn *irc = purple_connection_get_protocol_data(gc); struct irc_buddy *ib; const char *bname = purple_buddy_get_name(buddy); @@ -633,7 +636,7 @@ static void irc_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { - struct irc_conn *irc = (struct irc_conn *)gc->proto_data; + struct irc_conn *irc = purple_connection_get_protocol_data(gc); struct irc_buddy *ib; ib = g_hash_table_lookup(irc->buddies, purple_buddy_get_name(buddy)); @@ -644,9 +647,10 @@ static void read_input(struct irc_conn *irc, int len) { + PurpleConnection *connection = purple_account_get_connection(irc->account); char *cur, *end; - irc->account->gc->last_received = time(NULL); + purple_connection_update_last_received(connection); irc->inbufused += len; irc->inbuf[irc->inbufused] = '\0'; @@ -678,7 +682,7 @@ { PurpleConnection *gc = data; - struct irc_conn *irc = gc->proto_data; + struct irc_conn *irc = purple_connection_get_protocol_data(gc); int len; if(!g_list_find(purple_connections_get_all(), gc)) { @@ -699,12 +703,12 @@ } else if (len < 0) { gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; } else if (len == 0) { - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Server closed the connection")); return; @@ -716,7 +720,7 @@ static void irc_input_cb(gpointer data, gint source, PurpleInputCondition cond) { PurpleConnection *gc = data; - struct irc_conn *irc = gc->proto_data; + struct irc_conn *irc = purple_connection_get_protocol_data(gc); int len; if (irc->inbuflen < irc->inbufused + IRC_INITIAL_BUFSIZE) { @@ -730,12 +734,12 @@ } else if (len < 0) { gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; } else if (len == 0) { - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Server closed the connection")); return; @@ -746,7 +750,7 @@ static void irc_chat_join (PurpleConnection *gc, GHashTable *data) { - struct irc_conn *irc = gc->proto_data; + struct irc_conn *irc = purple_connection_get_protocol_data(gc); const char *args[2]; args[0] = g_hash_table_lookup(data, "channel"); @@ -760,7 +764,7 @@ static void irc_chat_invite(PurpleConnection *gc, int id, const char *message, const char *name) { - struct irc_conn *irc = gc->proto_data; + struct irc_conn *irc = purple_connection_get_protocol_data(gc); PurpleConversation *convo = purple_find_chat(gc, id); const char *args[2]; @@ -776,7 +780,7 @@ static void irc_chat_leave (PurpleConnection *gc, int id) { - struct irc_conn *irc = gc->proto_data; + struct irc_conn *irc = purple_connection_get_protocol_data(gc); PurpleConversation *convo = purple_find_chat(gc, id); const char *args[2]; @@ -791,7 +795,7 @@ static int irc_chat_send(PurpleConnection *gc, int id, const char *what, PurpleMessageFlags flags) { - struct irc_conn *irc = gc->proto_data; + struct irc_conn *irc = purple_connection_get_protocol_data(gc); PurpleConversation *convo = purple_find_chat(gc, id); const char *args[2]; char *tmp; @@ -806,7 +810,7 @@ } #endif purple_markup_html_to_xhtml(what, NULL, &tmp); - args[0] = convo->name; + args[0] = purple_conversation_get_name(convo); args[1] = tmp; irc_cmd_privmsg(irc, "msg", NULL, args); @@ -845,7 +849,7 @@ const char *name = NULL; struct irc_conn *irc; - irc = gc->proto_data; + irc = purple_connection_get_protocol_data(gc); name = purple_conversation_get_name(purple_find_chat(gc, id)); if (name == NULL) @@ -863,7 +867,7 @@ PurpleRoomlistField *f; char *buf; - irc = gc->proto_data; + irc = purple_connection_get_protocol_data(gc); if (irc->roomlist) purple_roomlist_unref(irc->roomlist); @@ -890,13 +894,14 @@ static void irc_roomlist_cancel(PurpleRoomlist *list) { - PurpleConnection *gc = purple_account_get_connection(list->account); + PurpleAccount *account = purple_roomlist_get_account(list); + PurpleConnection *gc = purple_account_get_connection(account); struct irc_conn *irc; if (gc == NULL) return; - irc = gc->proto_data; + irc = purple_connection_get_protocol_data(gc); purple_roomlist_set_in_progress(list, FALSE); @@ -908,13 +913,14 @@ static void irc_keepalive(PurpleConnection *gc) { - struct irc_conn *irc = gc->proto_data; + struct irc_conn *irc = purple_connection_get_protocol_data(gc); if ((time(NULL) - irc->recv_time) > PING_TIMEOUT) irc_cmd_ping(irc, NULL, NULL, NULL); } static PurplePluginProtocolInfo prpl_info = { + sizeof(PurplePluginProtocolInfo), /* struct_size */ OPT_PROTO_CHAT_TOPIC | OPT_PROTO_PASSWORD_OPTIONAL | OPT_PROTO_SLASH_COMMANDS_NATIVE, NULL, /* user_splits */ @@ -956,7 +962,6 @@ irc_keepalive, /* keepalive */ NULL, /* register_user */ NULL, /* get_cb_info */ - NULL, /* get_cb_away */ NULL, /* alias_buddy */ NULL, /* group_buddy */ NULL, /* rename_group */ @@ -981,15 +986,12 @@ NULL, /* unregister_user */ NULL, /* send_attention */ NULL, /* get_attention_types */ - sizeof(PurplePluginProtocolInfo), /* struct_size */ NULL, /* get_account_text_table */ NULL, /* initiate_media */ NULL, /* get_media_caps */ NULL, /* get_moods */ NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - NULL, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ + NULL /* get_public_alias */ }; static gboolean load_plugin (PurplePlugin *plugin) { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/irc/irc.h --- a/libpurple/protocols/irc/irc.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/irc/irc.h Fri Apr 06 04:30:00 2012 +0000 @@ -54,6 +54,7 @@ GHashTable *cmds; char *server; int fd; + guint inpa; guint timer; guint who_channel_timer; GHashTable *buddies; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/irc/msgs.c --- a/libpurple/protocols/irc/msgs.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/irc/msgs.c Fri Apr 06 04:30:00 2012 +0000 @@ -92,7 +92,7 @@ /* If we're away then set our away message */ status = purple_account_get_active_status(irc->account); if (!purple_status_get_type(status) != PURPLE_STATUS_AVAILABLE) { - PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); prpl_info->set_status(irc->account, status); } @@ -352,44 +352,40 @@ tmp = g_strdup_printf("%s%s%s", tmp2, (irc->whois.ircop ? _(" (ircop)") : ""), (irc->whois.identified ? _(" (identified)") : "")); - purple_notify_user_info_add_pair(user_info, _("Nick"), tmp); + purple_notify_user_info_add_pair_html(user_info, _("Nick"), tmp); g_free(tmp2); g_free(tmp); if (irc->whois.away) { - tmp = g_markup_escape_text(irc->whois.away, strlen(irc->whois.away)); + purple_notify_user_info_add_pair_plaintext(user_info, _("Away"), irc->whois.away); g_free(irc->whois.away); - purple_notify_user_info_add_pair(user_info, _("Away"), tmp); - g_free(tmp); } if (irc->whois.userhost) { - tmp = g_markup_escape_text(irc->whois.name, strlen(irc->whois.name)); + purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), irc->whois.userhost); + purple_notify_user_info_add_pair_plaintext(user_info, _("Real name"), irc->whois.name); + g_free(irc->whois.userhost); g_free(irc->whois.name); - purple_notify_user_info_add_pair(user_info, _("Username"), irc->whois.userhost); - purple_notify_user_info_add_pair(user_info, _("Real name"), tmp); - g_free(irc->whois.userhost); - g_free(tmp); } if (irc->whois.server) { tmp = g_strdup_printf("%s (%s)", irc->whois.server, irc->whois.serverinfo); - purple_notify_user_info_add_pair(user_info, _("Server"), tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Server"), tmp); g_free(tmp); g_free(irc->whois.server); g_free(irc->whois.serverinfo); } if (irc->whois.channels) { - purple_notify_user_info_add_pair(user_info, _("Currently on"), irc->whois.channels->str); + purple_notify_user_info_add_pair_plaintext(user_info, _("Currently on"), irc->whois.channels->str); g_string_free(irc->whois.channels, TRUE); } if (irc->whois.idle) { gchar *timex = purple_str_seconds_to_string(irc->whois.idle); - purple_notify_user_info_add_pair(user_info, _("Idle for"), timex); + purple_notify_user_info_add_pair_plaintext(user_info, _("Idle for"), timex); g_free(timex); - purple_notify_user_info_add_pair(user_info, + purple_notify_user_info_add_pair_plaintext(user_info, _("Online since"), purple_date_format_full(localtime(&irc->whois.signon))); } - if (!strcmp(irc->whois.nick, "Paco-Paco")) { - purple_notify_user_info_add_pair(user_info, + if (!strcmp(irc->whois.nick, "elb")) { + purple_notify_user_info_add_pair_plaintext(user_info, _("Defining adjective:"), _("Glorious")); } @@ -461,12 +457,12 @@ g_free(userhost); g_free(realname); - flags = cb->flags; + flags = purple_conv_chat_cb_get_flags(cb); if (args[6][0] == 'G' && !(flags & PURPLE_CBFLAGS_AWAY)) { - purple_conv_chat_user_set_flags(chat, cb->name, flags | PURPLE_CBFLAGS_AWAY); + purple_conv_chat_user_set_flags(chat, purple_conv_chat_cb_get_name(cb), flags | PURPLE_CBFLAGS_AWAY); } else if(args[6][0] == 'H' && (flags & PURPLE_CBFLAGS_AWAY)) { - purple_conv_chat_user_set_flags(chat, cb->name, flags & ~PURPLE_CBFLAGS_AWAY); + purple_conv_chat_user_set_flags(chat, purple_conv_chat_cb_get_name(cb), flags & ~PURPLE_CBFLAGS_AWAY); } } } @@ -1075,7 +1071,7 @@ _("Your selected nickname was rejected by the server. It probably contains invalid characters.")); } else { - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, _("Your selected account name was rejected by the server. It probably contains invalid characters.")); } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/irc/parse.c --- a/libpurple/protocols/irc/parse.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/irc/parse.c Fri Apr 06 04:30:00 2012 +0000 @@ -171,11 +171,11 @@ struct irc_conn *irc; struct _irc_user_cmd *cmdent; - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); if (!gc) return PURPLE_CMD_RET_FAILED; - irc = gc->proto_data; + irc = purple_connection_get_protocol_data(gc); if ((cmdent = g_hash_table_lookup(irc->cmds, cmd)) == NULL) return PURPLE_CMD_RET_FAILED; @@ -670,11 +670,11 @@ } else if (!strncmp(input, "ERROR ", 6)) { if (g_utf8_validate(input, -1, NULL)) { char *tmp = g_strdup_printf("%s\n%s", _("Disconnected."), input); - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); } else - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Disconnected.")); return; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/Makefile.am --- a/libpurple/protocols/jabber/Makefile.am Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/Makefile.am Fri Apr 06 04:30:00 2012 +0000 @@ -103,19 +103,25 @@ st = -DPURPLE_STATIC_PRPL noinst_LTLIBRARIES = libjabber.la -libjabber_la_SOURCES = $(JABBERSOURCES) libxmpp.c +libjabber_la_SOURCES = $(JABBERSOURCES) libfacebook.c libgtalk.c libxmpp.c libjabber_la_CFLAGS = $(AM_CFLAGS) else st = -pkg_LTLIBRARIES = libjabber.la libxmpp.la +pkg_LTLIBRARIES = libjabber.la libfacebook.la libgtalk.la libxmpp.la libjabber_la_SOURCES = $(JABBERSOURCES) libjabber_la_LIBADD = $(GLIB_LIBS) $(SASL_LIBS) $(LIBXML_LIBS) $(IDN_LIBS)\ $(FARSIGHT_LIBS) \ $(GSTREAMER_LIBS) \ $(GSTINTERFACES_LIBS) +libfacebook_la_SOURCES = libfacebook.c +libfacebook_la_LIBADD = libjabber.la + +libgtalk_la_SOURCES = libgtalk.c +libgtalk_la_LIBADD = libjabber.la + libxmpp_la_SOURCES = libxmpp.c libxmpp_la_LIBADD = libjabber.la diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/Makefile.mingw --- a/libpurple/protocols/jabber/Makefile.mingw Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/Makefile.mingw Fri Apr 06 04:30:00 2012 +0000 @@ -8,6 +8,8 @@ include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak TARGET = libjabber +FACEBOOK_TARGET = libfacebook +GTALK_TARGET = libgtalk XMPP_TARGET = libxmpp TYPE = PLUGIN @@ -90,6 +92,12 @@ OBJECTS = $(C_SRC:%.c=%.o) +FACEBOOK_C_SRC = libfacebook.c +FACEBOOK_OBJECTS = $(FACEBOOK_C_SRC:%.c=%.o) + +GTALK_C_SRC = libgtalk.c +GTALK_OBJECTS = $(GTALK_C_SRC:%.c=%.o) + XMPP_C_SRC = libxmpp.c XMPP_OBJECTS = $(XMPP_C_SRC:%.c=%.o) @@ -129,9 +137,11 @@ ## .PHONY: all install clean -all: $(TARGET).dll $(XMPP_TARGET).dll +all: $(TARGET).dll $(FACEBOOK_TARGET).dll $(GTALK_TARGET).dll $(XMPP_TARGET).dll install: all $(DLL_INSTALL_DIR) + cp $(FACEBOOK_TARGET).dll $(DLL_INSTALL_DIR) + cp $(GTALK_TARGET).dll $(DLL_INSTALL_DIR) cp $(XMPP_TARGET).dll $(DLL_INSTALL_DIR) cp $(TARGET).dll $(PURPLE_INSTALL_DIR) ifeq ($(CYRUS_SASL), 1) @@ -145,6 +155,12 @@ $(TARGET).dll $(TARGET).dll.a: $(PURPLE_DLL).a $(OBJECTS) $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--out-implib,$(TARGET).dll.a -o $(TARGET).dll +$(FACEBOOK_TARGET).dll: $(TARGET).dll.a $(FACEBOOK_OBJECTS) + $(CC) -shared $(FACEBOOK_OBJECTS) $(LIB_PATHS) $(LIBS) -ljabber $(DLL_LD_FLAGS) -o $(FACEBOOK_TARGET).dll + +$(GTALK_TARGET).dll: $(TARGET).dll.a $(GTALK_OBJECTS) + $(CC) -shared $(GTALK_OBJECTS) $(LIB_PATHS) $(LIBS) -ljabber $(DLL_LD_FLAGS) -o $(GTALK_TARGET).dll + $(XMPP_TARGET).dll: $(TARGET).dll.a $(XMPP_OBJECTS) $(CC) -shared $(XMPP_OBJECTS) $(LIB_PATHS) $(LIBS) -ljabber $(DLL_LD_FLAGS) -o $(XMPP_TARGET).dll @@ -153,6 +169,8 @@ ## clean: rm -f $(OBJECTS) $(TARGET).dll $(TARGET).dll.a + rm -f $(FACEBOOK_OBJECTS) $(FACEBOOK_TARGET).dll + rm -f $(GTALK_OBJECTS) $(GTALK_TARGET).dll rm -f $(XMPP_OBJECTS) $(XMPP_TARGET).dll include $(PIDGIN_COMMON_TARGETS) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/adhoccommands.c --- a/libpurple/protocols/jabber/adhoccommands.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/adhoccommands.c Fri Apr 06 04:30:00 2012 +0000 @@ -228,7 +228,8 @@ JabberAdHocCommands *cmd = data; PurpleBuddy *buddy = (PurpleBuddy *) node; PurpleAccount *account = purple_buddy_get_account(buddy); - JabberStream *js = purple_account_get_connection(account)->proto_data; + PurpleConnection *gc = purple_account_get_connection(account); + JabberStream *js = purple_connection_get_protocol_data(gc); jabber_adhoc_execute(js, cmd); } @@ -321,7 +322,7 @@ JabberAdHocCommands *cmd = action->user_data; if(cmd) { PurpleConnection *gc = (PurpleConnection *) action->context; - JabberStream *js = gc->proto_data; + JabberStream *js = purple_connection_get_protocol_data(gc); jabber_adhoc_execute(js, cmd); } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/auth.c --- a/libpurple/protocols/jabber/auth.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/auth.c Fri Apr 06 04:30:00 2012 +0000 @@ -77,7 +77,7 @@ static void disallow_plaintext_auth(PurpleAccount *account) { - purple_connection_error_reason(purple_account_get_connection(account), + purple_connection_error(purple_account_get_connection(account), PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, _("Server requires plaintext authentication over an unencrypted stream")); } @@ -145,7 +145,7 @@ mechs = xmlnode_get_child(packet, "mechanisms"); if(!mechs) { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Invalid response from server")); return; @@ -186,7 +186,7 @@ if (js->auth_mech == NULL) { /* Found no good mechanisms... */ - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, _("Server does not use any supported authentication method")); return; @@ -194,7 +194,7 @@ state = js->auth_mech->start(js, mechs, &response, &msg); if (state == JABBER_SASL_STATE_FAIL) { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, msg ? msg : _("Unknown Error")); } else if (response) { @@ -231,7 +231,7 @@ purple_account_set_password(account, NULL); } - purple_connection_error_reason(js->gc, reason, msg); + purple_connection_error(js->gc, reason, msg); g_free(msg); } } @@ -247,7 +247,7 @@ if (type == JABBER_IQ_ERROR) { PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; char *msg = jabber_parse_error(js, packet, &reason); - purple_connection_error_reason(js->gc, reason, msg); + purple_connection_error(js->gc, reason, msg); g_free(msg); } else if (type == JABBER_IQ_RESULT) { query = xmlnode_get_child(packet, "query"); @@ -321,7 +321,7 @@ } finish_plaintext_authentication(js); } else { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, _("Server does not use any supported authentication method")); return; @@ -345,7 +345,7 @@ if (!jabber_stream_is_ssl(js) && g_str_equal("require_tls", purple_account_get_string(account, "connection_security", JABBER_DEFAULT_REQUIRE_TLS))) { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, _("You require encryption, but it is not available on this server.")); return; @@ -394,7 +394,7 @@ const char *ns = xmlnode_get_namespace(packet); if (!purple_strequal(ns, NS_XMPP_SASL)) { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Invalid response from server")); return; @@ -405,7 +405,7 @@ char *msg = NULL; JabberSaslState state = js->auth_mech->handle_challenge(js, packet, &response, &msg); if (state == JABBER_SASL_STATE_FAIL) { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, msg ? msg : _("Invalid challenge from server")); } else if (response) { @@ -423,7 +423,7 @@ const char *ns = xmlnode_get_namespace(packet); if (!purple_strequal(ns, NS_XMPP_SASL)) { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Invalid response from server")); return; @@ -434,12 +434,12 @@ JabberSaslState state = js->auth_mech->handle_success(js, packet, &msg); if (state == JABBER_SASL_STATE_FAIL) { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, msg ? msg : _("Invalid response from server")); return; } else if (state == JABBER_SASL_STATE_CONTINUE) { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, msg ? msg : _("Server thinks authentication is complete, but client does not")); return; @@ -479,11 +479,11 @@ msg = jabber_parse_error(js, packet, &reason); if (!msg) { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Invalid response from server")); } else { - purple_connection_error_reason(js->gc, reason, msg); + purple_connection_error(js->gc, reason, msg); g_free(msg); } } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/auth_cyrus.c --- a/libpurple/protocols/jabber/auth_cyrus.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/auth_cyrus.c Fri Apr 06 04:30:00 2012 +0000 @@ -34,7 +34,7 @@ static void disallow_plaintext_auth(PurpleAccount *account) { - purple_connection_error_reason(purple_account_get_connection(account), + purple_connection_error(purple_account_get_connection(account), PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, _("Server may require plaintext authentication over an unencrypted stream")); } @@ -46,7 +46,7 @@ JabberSaslState state = jabber_auth_start_cyrus(js, &response, &error); if (state == JABBER_SASL_STATE_FAIL) { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, error); g_free(error); @@ -167,7 +167,6 @@ auth_no_pass_cb(PurpleConnection *gc, PurpleRequestFields *fields) { PurpleAccount *account; - JabberStream *js; /* The password prompt dialog doesn't get disposed if the account disconnects */ if (!PURPLE_CONNECTION_IS_VALID(gc)) @@ -361,30 +360,30 @@ id = 0; js->sasl_cb[id].id = SASL_CB_GETREALM; - js->sasl_cb[id].proc = jabber_sasl_cb_realm; + js->sasl_cb[id].proc = (void *)jabber_sasl_cb_realm; js->sasl_cb[id].context = (void *)js; id++; js->sasl_cb[id].id = SASL_CB_AUTHNAME; - js->sasl_cb[id].proc = jabber_sasl_cb_simple; + js->sasl_cb[id].proc = (void *)jabber_sasl_cb_simple; js->sasl_cb[id].context = (void *)js; id++; js->sasl_cb[id].id = SASL_CB_USER; - js->sasl_cb[id].proc = jabber_sasl_cb_simple; + js->sasl_cb[id].proc = (void *)jabber_sasl_cb_simple; js->sasl_cb[id].context = (void *)js; id++; account = purple_connection_get_account(js->gc); if (purple_account_get_password(account) != NULL ) { js->sasl_cb[id].id = SASL_CB_PASS; - js->sasl_cb[id].proc = jabber_sasl_cb_secret; + js->sasl_cb[id].proc = (void *)jabber_sasl_cb_secret; js->sasl_cb[id].context = (void *)js; id++; } js->sasl_cb[id].id = SASL_CB_LOG; - js->sasl_cb[id].proc = jabber_sasl_cb_log; + js->sasl_cb[id].proc = (void *)jabber_sasl_cb_log; js->sasl_cb[id].context = (void*)js; id++; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/auth_plain.c --- a/libpurple/protocols/jabber/auth_plain.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/auth_plain.c Fri Apr 06 04:30:00 2012 +0000 @@ -75,7 +75,7 @@ static void disallow_plaintext_auth(PurpleAccount *account) { - purple_connection_error_reason(purple_account_get_connection(account), + purple_connection_error(purple_account_get_connection(account), PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, _("Server requires plaintext authentication over an unencrypted stream")); } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/bosh.c --- a/libpurple/protocols/jabber/bosh.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/bosh.c Fri Apr 06 04:30:00 2012 +0000 @@ -436,7 +436,7 @@ if (type != NULL && !strcmp(type, "terminate")) { conn->state = BOSH_CONN_OFFLINE; - purple_connection_error_reason(conn->js->gc, + purple_connection_error(conn->js->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("The BOSH connection manager terminated your session.")); return TRUE; @@ -539,7 +539,7 @@ if (sid) { conn->sid = g_strdup(sid); } else { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("No session ID given")); return; @@ -556,7 +556,7 @@ minor = atoi(dot + 1); if (major != 1 || minor < 6) { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unsupported version of BOSH protocol")); return; @@ -733,7 +733,7 @@ return; if (++conn->bosh->failed_connections == MAX_FAILED_CONNECTIONS) { - purple_connection_error_reason(conn->bosh->js->gc, + purple_connection_error(conn->bosh->js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to establish a connection with the server")); } else { @@ -939,7 +939,7 @@ gchar *tmp; tmp = g_strdup_printf(_("Unable to establish a connection with the server: %s"), error); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; } @@ -965,18 +965,18 @@ ssl_connection_error_cb, conn); if (!conn->psc) { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("Unable to establish SSL connection")); } } else { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("SSL support unavailable")); } } else if (purple_proxy_connect(conn, account, bosh->host, bosh->port, connection_established_cb, conn) == NULL) { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); } @@ -1023,7 +1023,7 @@ */ gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); - purple_connection_error_reason(conn->bosh->js->gc, + purple_connection_error(conn->bosh->js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); @@ -1079,7 +1079,7 @@ */ gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); - purple_connection_error_reason(conn->bosh->js->gc, + purple_connection_error(conn->bosh->js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/buddy.c --- a/libpurple/protocols/jabber/buddy.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/buddy.c Fri Apr 06 04:30:00 2012 +0000 @@ -465,10 +465,22 @@ xmlnode *vc_node; const struct tag_attr *tag_attr; - /* if we have't grabbed the remote vcard yet, we can't + /* if we haven't grabbed the remote vcard yet, we can't * assume that what we have here is correct */ - if(!js->vcard_fetched) + if(!js->vcard_fetched) { + PurpleStoredImage *image; + g_free(js->initial_avatar_hash); + image = purple_buddy_icons_find_account_icon(purple_connection_get_account(gc)); + if (image != NULL) { + js->initial_avatar_hash = + jabber_calculate_data_hash(purple_imgstore_get_data(image), + purple_imgstore_get_size(image), "sha1"); + purple_imgstore_unref(image); + } else { + js->initial_avatar_hash = NULL; + } return; + } if (js->vcard_timer) { purple_timeout_remove(js->vcard_timer); @@ -489,7 +501,7 @@ vc_node = NULL; } - if ((img = purple_buddy_icons_find_account_icon(gc->account))) { + if ((img = purple_buddy_icons_find_account_icon(purple_connection_get_account(gc)))) { gconstpointer avatar_data; gsize avatar_len; xmlnode *photo, *binval, *type; @@ -545,7 +557,7 @@ PurpleAccount *account = purple_connection_get_account(gc); /* Publish the avatar as specified in XEP-0084 */ - jabber_avatar_set(gc->proto_data, img); + jabber_avatar_set(purple_connection_get_protocol_data(gc), img); /* Set the image in our vCard */ jabber_set_info(gc, purple_account_get_user_info(account)); @@ -630,7 +642,7 @@ /* * Get existing, XML-formatted, user info */ - if((user_info = purple_account_get_user_info(gc->account)) != NULL) + if((user_info = purple_account_get_user_info(purple_connection_get_account(gc))) != NULL) x_vc_data = xmlnode_from_str(user_info, -1); /* @@ -719,11 +731,16 @@ g_strdup_printf("%s%s%s", jbr->client.name, (jbr->client.version ? " " : ""), (jbr->client.version ? jbr->client.version : "")); - purple_notify_user_info_prepend_pair(user_info, _("Client"), tmp); + /* TODO: Check whether it's correct to call prepend_pair_html, + or if we should be using prepend_pair_plaintext */ + purple_notify_user_info_prepend_pair_html(user_info, _("Client"), tmp); g_free(tmp); - if (jbr->client.os) - purple_notify_user_info_prepend_pair(user_info, _("Operating System"), jbr->client.os); + if (jbr->client.os) { + /* TODO: Check whether it's correct to call prepend_pair_html, + or if we should be using prepend_pair_plaintext */ + purple_notify_user_info_prepend_pair_html(user_info, _("Operating System"), jbr->client.os); + } } if (jbr && jbr->tz_off != PURPLE_NO_TZ_OFF) { @@ -739,13 +756,13 @@ jbr->tz_off < 0 ? '-' : '+', abs(jbr->tz_off / (60*60)), abs((jbr->tz_off % (60*60)) / 60)); - purple_notify_user_info_prepend_pair(user_info, _("Local Time"), timestamp); + purple_notify_user_info_prepend_pair_plaintext(user_info, _("Local Time"), timestamp); g_free(timestamp); } if (jbir && jbir->idle_seconds > 0) { char *idle = purple_str_seconds_to_string(jbir->idle_seconds); - purple_notify_user_info_prepend_pair(user_info, _("Idle"), idle); + purple_notify_user_info_prepend_pair_plaintext(user_info, _("Idle"), idle); g_free(idle); } @@ -767,15 +784,15 @@ tmp = g_strdup_printf("%s%s%s", (status_name ? status_name : ""), ((status_name && purdy) ? ": " : ""), (purdy ? purdy : "")); - purple_notify_user_info_prepend_pair(user_info, _("Status"), tmp); + purple_notify_user_info_prepend_pair_html(user_info, _("Status"), tmp); g_snprintf(priority, sizeof(priority), "%d", jbr->priority); - purple_notify_user_info_prepend_pair(user_info, _("Priority"), priority); + purple_notify_user_info_prepend_pair_plaintext(user_info, _("Priority"), priority); g_free(tmp); g_free(purdy); } else { - purple_notify_user_info_prepend_pair(user_info, _("Status"), _("Unknown")); + purple_notify_user_info_prepend_pair_plaintext(user_info, _("Status"), _("Unknown")); } } @@ -794,7 +811,7 @@ resource_name = jabber_get_resource(jbi->jid); /* If we have one or more pairs from the vcard, put a section break above it */ - if (purple_notify_user_info_get_entries(user_info)) + if (g_queue_get_length(purple_notify_user_info_get_entries(user_info))) purple_notify_user_info_prepend_section_break(user_info); /* Add the information about the user's resource(s) */ @@ -815,8 +832,11 @@ add_jbr_info(jbi, jbr->name, jbr); - if (jbr->name) - purple_notify_user_info_prepend_pair(user_info, _("Resource"), jbr->name); + if (jbr->name) { + /* TODO: Check whether it's correct to call prepend_pair_html, + or if we should be using prepend_pair_plaintext */ + purple_notify_user_info_prepend_pair_html(user_info, _("Resource"), jbr->name); + } } } @@ -836,7 +856,7 @@ title = _("Logged Off"); message = g_strdup_printf(_("%s ago"), last); } - purple_notify_user_info_prepend_pair(user_info, title, message); + purple_notify_user_info_prepend_pair_plaintext(user_info, title, message); g_free(last); g_free(message); } @@ -846,7 +866,9 @@ g_strdup_printf("%s%s%s", _("Offline"), jbi->last_message ? ": " : "", jbi->last_message ? jbi->last_message : ""); - purple_notify_user_info_prepend_pair(user_info, _("Status"), status); + /* TODO: Check whether it's correct to call prepend_pair_html, + or if we should be using prepend_pair_plaintext */ + purple_notify_user_info_prepend_pair_html(user_info, _("Status"), status); g_free(status); } } @@ -1124,7 +1146,7 @@ char *mailto; escaped = g_markup_escape_text(userid, -1); mailto = g_strdup_printf("%s", escaped, escaped); - purple_notify_user_info_add_pair(user_info, _("Email"), mailto); + purple_notify_user_info_add_pair_html(user_info, _("Email"), mailto); g_free(mailto); g_free(escaped); @@ -1137,7 +1159,7 @@ escaped = g_markup_escape_text(userid, -1); mailto = g_strdup_printf("%s", escaped, escaped); - purple_notify_user_info_add_pair(user_info, _("Email"), mailto); + purple_notify_user_info_add_pair_html(user_info, _("Email"), mailto); g_free(mailto); g_free(escaped); @@ -1184,7 +1206,7 @@ jbi->vcard_imgids = g_slist_prepend(jbi->vcard_imgids, GINT_TO_POINTER(purple_imgstore_add_with_id(g_memdup(data, size), size, "logo.png"))); img_text = g_strdup_printf("", GPOINTER_TO_INT(jbi->vcard_imgids->data)); - purple_notify_user_info_add_pair(user_info, (photo ? _("Photo") : _("Logo")), img_text); + purple_notify_user_info_add_pair_html(user_info, (photo ? _("Photo") : _("Logo")), img_text); hash = jabber_calculate_data_hash(data, size, "sha1"); purple_buddy_icons_set_for_user(account, bare_jid, data, size, hash); @@ -1338,7 +1360,7 @@ if (jbr == jabber_buddy_find_resource(jb, NULL)) { - purple_prpl_got_user_idle(js->gc->account, + purple_prpl_got_user_idle(purple_connection_get_account(js->gc), buddy_name, jbr->idle, jbr->idle); } } @@ -2233,10 +2255,10 @@ make sure we aren't persisting an old value */ if(js->user_directories && js->user_directories->data && !strcmp(directory, js->user_directories->data)) { - purple_account_set_string(js->gc->account, "user_directory", ""); + purple_account_set_string(purple_connection_get_account(js->gc), "user_directory", ""); } else { - purple_account_set_string(js->gc->account, "user_directory", directory); + purple_account_set_string(purple_connection_get_account(js->gc), "user_directory", directory); } iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:search"); @@ -2251,7 +2273,7 @@ { PurpleConnection *gc = (PurpleConnection *) action->context; JabberStream *js = purple_connection_get_protocol_data(gc); - const char *def_val = purple_account_get_string(js->gc->account, "user_directory", ""); + const char *def_val = purple_account_get_string(purple_connection_get_account(js->gc), "user_directory", ""); if(!*def_val && js->user_directories) def_val = js->user_directories->data; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/caps.c --- a/libpurple/protocols/jabber/caps.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/caps.c Fri Apr 06 04:30:00 2012 +0000 @@ -794,11 +794,11 @@ for (value = xmlnode_get_child(field, "value"); value; value = xmlnode_get_next_twin(value)) { gchar *val = xmlnode_get_data(value); - xdatafield->values = g_list_append(xdatafield->values, val); + xdatafield->values = g_list_prepend(xdatafield->values, val); } xdatafield->values = g_list_sort(xdatafield->values, (GCompareFunc)strcmp); - fields = g_list_append(fields, xdatafield); + fields = g_list_prepend(fields, xdatafield); } fields = g_list_sort(fields, jabber_caps_xdata_field_compare); @@ -875,21 +875,25 @@ g_free(formtype); while (fields) { - GList *value; JabberDataFormField *field = (JabberDataFormField*)fields->data; if (!g_str_equal(field->var, "FORM_TYPE")) { /* Append the "var" attribute */ append_escaped_string(context, field->var); /* Append elements' cdata */ - for (value = field->values; value; value = value->next) { - append_escaped_string(context, value->data); - g_free(value->data); + while (field->values) { + append_escaped_string(context, field->values->data); + g_free(field->values->data); + field->values = g_list_delete_link(field->values, + field->values); } + } else { + g_list_foreach(field->values, (GFunc) g_free, NULL); + g_list_free(field->values); } g_free(field->var); - g_list_free(field->values); + g_free(field); fields = g_list_delete_link(fields, fields); } @@ -958,7 +962,7 @@ const char *prpl_id = purple_account_get_protocol_id(account); if (g_str_equal("prpl-jabber", prpl_id) && purple_account_is_connected(account)) { PurpleConnection *gc = purple_account_get_connection(account); - jabber_presence_send(gc->proto_data, TRUE); + jabber_presence_send(purple_connection_get_protocol_data(gc), TRUE); } } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/chat.c --- a/libpurple/protocols/jabber/chat.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/chat.c Fri Apr 06 04:30:00 2012 +0000 @@ -70,7 +70,7 @@ GHashTable *jabber_chat_info_defaults(PurpleConnection *gc, const char *chat_name) { GHashTable *defaults; - JabberStream *js = gc->proto_data; + JabberStream *js = purple_connection_get_protocol_data(gc); defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); @@ -146,7 +146,7 @@ int id; if (!gc) return NULL; - js = gc->proto_data; + js = purple_connection_get_protocol_data(gc); id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)); return jabber_chat_find_by_id(js, id); } @@ -154,7 +154,7 @@ void jabber_chat_invite(PurpleConnection *gc, int id, const char *msg, const char *name) { - JabberStream *js = gc->proto_data; + JabberStream *js = purple_connection_get_protocol_data(gc); JabberChat *chat; xmlnode *message, *body, *x, *invite; char *room_jid; @@ -360,7 +360,7 @@ { char *room, *server, *handle, *passwd; JabberID *jid; - JabberStream *js = gc->proto_data; + JabberStream *js = purple_connection_get_protocol_data(gc); char *tmp; room = g_hash_table_lookup(data, "room"); @@ -418,10 +418,9 @@ void jabber_chat_leave(PurpleConnection *gc, int id) { - JabberStream *js = gc->proto_data; + JabberStream *js = purple_connection_get_protocol_data(gc); JabberChat *chat = jabber_chat_find_by_id(js, id); - if(!chat) return; @@ -459,7 +458,7 @@ char *jabber_chat_buddy_real_name(PurpleConnection *gc, int id, const char *who) { - JabberStream *js = gc->proto_data; + JabberStream *js = purple_connection_get_protocol_data(gc); JabberChat *chat; JabberChatMember *jcm; @@ -887,13 +886,13 @@ char *jabber_roomlist_room_serialize(PurpleRoomlistRoom *room) { - - return g_strdup_printf("%s@%s", (char*)room->fields->data, (char*)room->fields->next->data); + GList *fields = purple_roomlist_room_get_fields(room); + return g_strdup_printf("%s@%s", (char*)fields->data, (char*)fields->next->data); } PurpleRoomlist *jabber_roomlist_get_list(PurpleConnection *gc) { - JabberStream *js = gc->proto_data; + JabberStream *js = purple_connection_get_protocol_data(gc); GList *fields = NULL; PurpleRoomlistField *f; @@ -928,11 +927,13 @@ void jabber_roomlist_cancel(PurpleRoomlist *list) { + PurpleAccount *account; PurpleConnection *gc; JabberStream *js; - gc = purple_account_get_connection(list->account); - js = gc->proto_data; + account = purple_roomlist_get_account(list); + gc = purple_account_get_connection(account); + js = purple_connection_get_protocol_data(gc); purple_roomlist_set_in_progress(list, FALSE); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/disco.c --- a/libpurple/protocols/jabber/disco.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/disco.c Fri Apr 06 04:30:00 2012 +0000 @@ -387,7 +387,7 @@ } /* If there are manually specified bytestream proxies, query them */ - ft_proxies = purple_account_get_string(js->gc->account, "ft_proxies", NULL); + ft_proxies = purple_account_get_string(purple_connection_get_account(js->gc), "ft_proxies", NULL); if (ft_proxies) { JabberIq *iq; JabberBytestreamsStreamhost *sh; @@ -485,7 +485,7 @@ resp[0].hostname, resp[0].port); account = purple_connection_get_account(js->gc); js->stun_query = - purple_dnsquery_a_account(account, resp[0].hostname, resp[0].port, + purple_dnsquery_a(account, resp[0].hostname, resp[0].port, jabber_disco_stun_lookup_cb, js); } } @@ -524,8 +524,10 @@ if(category && type && !strcmp(category, "pubsub") && !strcmp(type,"pep")) { PurpleConnection *gc = js->gc; js->pep = TRUE; - gc->flags |= PURPLE_CONNECTION_SUPPORT_MOODS | - PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES; + purple_connection_set_flags(gc, + purple_connection_get_flags(gc) + | PURPLE_CONNECTION_SUPPORT_MOODS + | PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES); } if (!category || strcmp(category, "server")) continue; @@ -550,7 +552,7 @@ } else if (purple_network_get_stun_ip() == NULL || purple_strequal(purple_network_get_stun_ip(), "")) { js->srv_query_data = - purple_srv_resolve_account( + purple_srv_resolve( purple_connection_get_account(js->gc), "stun", "udp", js->user->domain, jabber_disco_stun_srv_resolve_cb, js); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/google/gmail.c --- a/libpurple/protocols/jabber/google/gmail.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/google/gmail.c Fri Apr 06 04:30:00 2012 +0000 @@ -150,7 +150,7 @@ JabberIq *iq; /* bail if the user isn't interested */ - if (!purple_account_get_check_mail(js->gc->account)) + if (!purple_account_get_check_mail(purple_connection_get_account(js->gc))) return; /* Is this an initial incoming mail notification? If so, send a request for more info */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/google/google_presence.c --- a/libpurple/protocols/jabber/google/google_presence.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/google/google_presence.c Fri Apr 06 04:30:00 2012 +0000 @@ -27,12 +27,12 @@ if (!js->googletalk) return; if (jbr->status && purple_str_has_prefix(jbr->status, "♫ ")) { - purple_prpl_got_user_status(js->gc->account, user, "tune", + purple_prpl_got_user_status(purple_connection_get_account(js->gc), user, "tune", PURPLE_TUNE_TITLE, jbr->status + strlen("♫ "), NULL); g_free(jbr->status); jbr->status = NULL; } else { - purple_prpl_got_user_status_deactive(js->gc->account, user, "tune"); + purple_prpl_got_user_status_deactive(purple_connection_get_account(js->gc), user, "tune"); } } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/google/jingleinfo.c --- a/libpurple/protocols/jabber/google/jingleinfo.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/google/jingleinfo.c Fri Apr 06 04:30:00 2012 +0000 @@ -117,7 +117,7 @@ purple_dnsquery_destroy(js->stun_query); account = purple_connection_get_account(js->gc); - js->stun_query = purple_dnsquery_a_account(account, host, port, + js->stun_query = purple_dnsquery_a(account, host, port, jabber_google_stun_lookup_cb, js); } } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/google/relay.c --- a/libpurple/protocols/jabber/google/relay.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/google/relay.c Fri Apr 06 04:30:00 2012 +0000 @@ -137,7 +137,7 @@ purple_debug_info("jabber", "sending Google relay request %s to %s\n", request, url); url_data = - purple_util_fetch_url_request(url, FALSE, NULL, FALSE, request, FALSE, + purple_util_fetch_url_request(NULL, url, FALSE, NULL, FALSE, request, FALSE, -1, jabber_google_relay_fetch_cb, data); if (url_data) { js->google_relay_requests = diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/jabber.c Fri Apr 06 04:30:00 2012 +0000 @@ -119,7 +119,7 @@ if(js->unregistration) jabber_unregister_account_cb(js); } else { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, ("Error initializing session")); } @@ -153,7 +153,7 @@ js->user = jabber_id_new(full_jid); if (js->user == NULL) { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Invalid response from server")); g_free(full_jid); @@ -170,7 +170,7 @@ } else { PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; char *msg = jabber_parse_error(js, packet, &reason); - purple_connection_error_reason(js->gc, reason, msg); + purple_connection_error(js->gc, reason, msg); g_free(msg); return; @@ -247,14 +247,14 @@ starttls = xmlnode_get_child(packet, "starttls"); if(xmlnode_get_child(starttls, "required")) { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("Server requires TLS/SSL, but no TLS/SSL support was found.")); return TRUE; } if (g_str_equal("require_tls", purple_account_get_string(account, "connection_security", JABBER_DEFAULT_REQUIRE_TLS))) { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("You require encryption, but no TLS/SSL support was found.")); return TRUE; @@ -275,7 +275,7 @@ return; } } else if (g_str_equal(connection_security, "require_tls") && !jabber_stream_is_ssl(js)) { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, _("You require encryption, but it is not available on this server.")); return; @@ -320,7 +320,7 @@ PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; char *msg = jabber_parse_error(js, packet, &reason); - purple_connection_error_reason(js->gc, reason, msg); + purple_connection_error(js->gc, reason, msg); g_free(msg); } @@ -407,7 +407,7 @@ else if (ret <= 0) { gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; @@ -440,10 +440,10 @@ * we're disconnecting, don't generate (possibly another) error that * (for some UIs) would mask the first. */ - if (!account->disconnecting) { + if (!purple_account_is_disconnecting(account)) { gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); } @@ -544,7 +544,7 @@ purple_debug_error("jabber", "sasl_encode error %d: %s\n", rc, sasl_errdetail(js->sasl)); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error); g_free(error); @@ -616,8 +616,8 @@ static gboolean jabber_keepalive_timeout(PurpleConnection *gc) { - JabberStream *js = gc->proto_data; - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + JabberStream *js = purple_connection_get_protocol_data(gc); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Ping timed out")); js->keepalive_timeout = 0; return FALSE; @@ -642,7 +642,7 @@ PurpleInputCondition cond) { PurpleConnection *gc = data; - JabberStream *js = gc->proto_data; + JabberStream *js = purple_connection_get_protocol_data(gc); int len; static char buf[4096]; @@ -653,7 +653,7 @@ } while((len = purple_ssl_read(gsc, buf, sizeof(buf) - 1)) > 0) { - gc->last_received = time(NULL); + purple_connection_update_last_received(gc); buf[len] = '\0'; purple_debug_info("jabber", "Recv (ssl)(%d): %s\n", len, buf); jabber_parser_process(js, buf, len); @@ -670,7 +670,7 @@ else tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); } @@ -687,7 +687,7 @@ g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc)); if((len = read(js->fd, buf, sizeof(buf) - 1)) > 0) { - gc->last_received = time(NULL); + purple_connection_update_last_received(gc); #ifdef HAVE_CYRUS_SASL if (js->sasl_maxbuf > 0) { const char *out; @@ -702,7 +702,7 @@ purple_debug_error("jabber", "sasl_decode_error %d: %s\n", rc, sasl_errdetail(js->sasl)); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error); } else if (olen > 0) { @@ -728,7 +728,7 @@ else tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); } @@ -747,7 +747,7 @@ g_return_if_reached(); } - js = gc->proto_data; + js = purple_connection_get_protocol_data(gc); if(js->state == JABBER_STREAM_CONNECTING) jabber_send_raw(js, "", -1); @@ -789,7 +789,7 @@ if (!found) { purple_debug_warning("jabber", "Unable to find alternative XMPP connection " "methods after failing to connect directly.\n"); - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); return; @@ -813,7 +813,7 @@ try_srv_connect(js); } else { purple_debug_info("jabber","Couldn't connect directly to %s. Trying to find alternative connection methods, like BOSH.\n", js->user->domain); - js->srv_query_data = purple_txt_resolve_account( + js->srv_query_data = purple_txt_resolve( purple_connection_get_account(gc), "_xmppconnect", js->user->domain, txt_resolved_cb, js); } @@ -829,7 +829,7 @@ jabber_send_raw(js, "", -1); jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING); - gc->inpa = purple_input_add(js->fd, PURPLE_INPUT_READ, jabber_recv_cb, gc); + js->inpa = purple_input_add(js->fd, PURPLE_INPUT_READ, jabber_recv_cb, gc); } static void @@ -842,7 +842,7 @@ /* If the connection is already disconnected, we don't need to do anything else */ g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc)); - js = gc->proto_data; + js = purple_connection_get_protocol_data(gc); js->gsc = NULL; purple_connection_ssl_error (gc, error); @@ -850,9 +850,9 @@ static void tls_init(JabberStream *js) { - purple_input_remove(js->gc->inpa); - js->gc->inpa = 0; - js->gsc = purple_ssl_connect_with_host_fd(js->gc->account, js->fd, + purple_input_remove(js->inpa); + js->inpa = 0; + js->gsc = purple_ssl_connect_with_host_fd(purple_connection_get_account(js->gc), js->fd, jabber_login_callback_ssl, jabber_ssl_connect_failure, js->certificate_CN, js->gc); /* The fd is no longer our concern */ js->fd = -1; @@ -874,7 +874,7 @@ if (purple_proxy_connect(js->gc, purple_connection_get_account(js->gc), host, port, jabber_login_callback, js->gc) == NULL) { if (fatal_failure) { - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); } @@ -928,7 +928,8 @@ gchar *user; gchar *slash; - js = gc->proto_data = g_new0(JabberStream, 1); + js = g_new0(JabberStream, 1); + purple_connection_set_protocol_data(gc, js); js->gc = gc; js->fd = -1; @@ -940,7 +941,7 @@ js->user = jabber_id_new(user); if (!js->user) { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, _("Invalid XMPP ID")); g_free(user); @@ -949,7 +950,7 @@ } if (!js->user->node || *(js->user->node) == '\0') { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, _("Invalid XMPP ID. Username portion must be set.")); g_free(user); @@ -958,7 +959,7 @@ } if (!js->user->domain || *(js->user->domain) == '\0') { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, _("Invalid XMPP ID. Domain must be set.")); g_free(user); @@ -978,7 +979,7 @@ g_free(user); if (!js->user_jb) { /* This basically *can't* fail, but for good measure... */ - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, _("Invalid XMPP ID")); /* Destroying the connection will free the JabberStream */ @@ -1037,7 +1038,7 @@ if (js->bosh) jabber_bosh_connection_connect(js->bosh); else { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, _("Malformed BOSH URL")); } @@ -1054,12 +1055,12 @@ purple_account_get_int(account, "port", 5223), jabber_login_callback_ssl, jabber_ssl_connect_failure, gc); if (!js->gsc) { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("Unable to establish SSL connection")); } } else { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("SSL support unavailable")); } @@ -1073,7 +1074,7 @@ jabber_login_connect(js, js->user->domain, connect_server, purple_account_get_int(account, "port", 5222), TRUE); } else { - js->srv_query_data = purple_srv_resolve_account(account, "xmpp-client", + js->srv_query_data = purple_srv_resolve(account, "xmpp-client", "tcp", js->user->domain, srv_resolved_cb, js); } } @@ -1085,8 +1086,7 @@ JabberStream *js; PurpleStoredImage *image; - gc->flags |= PURPLE_CONNECTION_HTML | - PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY; + purple_connection_set_flags(gc, PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY); js = jabber_stream_new(account); if (js == NULL) return; @@ -1144,8 +1144,7 @@ if(js->registration) { buf = g_strdup_printf(_("Registration of %s@%s successful"), js->user->node, js->user->domain); - if(account->registration_cb) - (account->registration_cb)(account, TRUE, account->registration_cb_user_data); + purple_account_register_completed(account, TRUE); } else { g_return_if_fail(to != NULL); buf = g_strdup_printf(_("Registration to %s successful"), @@ -1163,8 +1162,7 @@ purple_notify_error(NULL, _("Registration Failed"), _("Registration Failed"), msg); g_free(msg); - if(account->registration_cb) - (account->registration_cb)(account, FALSE, account->registration_cb_user_data); + purple_account_register_completed(account, FALSE); } g_free(to); if(js->registration) @@ -1264,7 +1262,7 @@ cbdata->js->user->node = g_strdup(value); } if(cbdata->js->registration && !strcmp(id, "password")) - purple_account_set_password(cbdata->js->gc->account, value); + purple_account_set_password(purple_connection_get_account(cbdata->js->gc), value); } } } @@ -1273,7 +1271,7 @@ username = g_strdup_printf("%s@%s%s%s", cbdata->js->user->node, cbdata->js->user->domain, cbdata->js->user->resource ? "/" : "", cbdata->js->user->resource ? cbdata->js->user->resource : ""); - purple_account_set_username(cbdata->js->gc->account, username); + purple_account_set_username(purple_connection_get_account(cbdata->js->gc), username); g_free(username); } @@ -1288,8 +1286,7 @@ { PurpleAccount *account = purple_connection_get_account(cbdata->js->gc); if(account && cbdata->js->registration) { - if(account->registration_cb) - (account->registration_cb)(account, FALSE, account->registration_cb_user_data); + purple_account_register_completed(account, FALSE); jabber_connection_schedule_close(cbdata->js); } g_free(cbdata->who); @@ -1358,8 +1355,7 @@ if(js->registration) { purple_notify_error(NULL, _("Already Registered"), _("Already Registered"), NULL); - if(account->registration_cb) - (account->registration_cb)(account, FALSE, account->registration_cb_user_data); + purple_account_register_completed(account, FALSE); jabber_connection_schedule_close(js); return; } @@ -1380,8 +1376,8 @@ if(js->registration) { js->gc->wants_to_die = TRUE; - if(account->registration_cb) /* succeeded, but we have no login info */ - (account->registration_cb)(account, TRUE, account->registration_cb_user_data); + /* succeeded, but we have no login info */ + purple_account_register_completed(account, TRUE); jabber_connection_schedule_close(js); } return; @@ -1422,7 +1418,7 @@ if((node = xmlnode_get_child(query, "name"))) { if(js->registration) field = purple_request_field_string_new("name", _("Name"), - purple_account_get_alias(js->gc->account), FALSE); + purple_account_get_alias(purple_connection_get_account(js->gc)), FALSE); else { char *data = xmlnode_get_data(node); field = purple_request_field_string_new("name", _("Name"), data, FALSE); @@ -1556,17 +1552,17 @@ PurpleConnection *gc = purple_account_get_connection(account); JabberStream *js; - if(gc->state != PURPLE_CONNECTED) { - if(gc->state != PURPLE_CONNECTING) + if (purple_connection_get_state(gc) != PURPLE_CONNECTED) { + if (purple_connection_get_state(gc) != PURPLE_CONNECTING) jabber_login(account); - js = gc->proto_data; + js = purple_connection_get_protocol_data(gc); js->unregistration = TRUE; js->unregistration_cb = cb; js->unregistration_user_data = user_data; return; } - js = gc->proto_data; + js = purple_connection_get_protocol_data(gc); if (js->unregistration) { purple_debug_error("jabber", "Unregistration in process; ignoring duplicate request.\n"); @@ -1598,13 +1594,15 @@ jabber_send_raw(js, "", -1); if (js->srv_query_data) - purple_srv_cancel(js->srv_query_data); + purple_srv_txt_query_destroy(js->srv_query_data); if(js->gsc) { purple_ssl_close(js->gsc); } else if (js->fd > 0) { - if(js->gc->inpa) - purple_input_remove(js->gc->inpa); + if(js->inpa) { + purple_input_remove(js->inpa); + js->inpa = 0; + } close(js->fd); } @@ -1726,7 +1724,7 @@ g_free(js); - gc->proto_data = NULL; + purple_connection_set_protocol_data(gc, NULL); } void jabber_stream_set_state(JabberStream *js, JabberStreamState state) @@ -1780,7 +1778,7 @@ void jabber_idle_set(PurpleConnection *gc, int idle) { - JabberStream *js = gc->proto_data; + JabberStream *js = purple_connection_get_protocol_data(gc); js->idle = idle ? time(NULL) - idle : idle; @@ -1871,8 +1869,7 @@ return; /* This is the only privacy method supported by XEP-0191 */ - if (account->perm_deny != PURPLE_PRIVACY_DENY_USERS) - account->perm_deny = PURPLE_PRIVACY_DENY_USERS; + purple_account_set_privacy_type(account, PURPLE_PRIVACY_DENY_USERS); /* * TODO: When account->deny is something more than a hash table, this can @@ -2133,7 +2130,7 @@ if(!gc) return NULL; - js = gc->proto_data; + js = purple_connection_get_protocol_data(gc); if(js) jb = jabber_buddy_find(js, purple_buddy_get_name(b), FALSE); @@ -2174,8 +2171,8 @@ PurpleAccount *account = purple_buddy_get_account(b); PurpleConnection *gc = purple_account_get_connection(account); - if (gc && gc->proto_data) - jb = jabber_buddy_find(gc->proto_data, purple_buddy_get_name(b), FALSE); + if (gc && purple_connection_get_protocol_data(gc)) + jb = jabber_buddy_find(purple_connection_get_protocol_data(gc), purple_buddy_get_name(b), FALSE); if(jb && !PURPLE_BUDDY_IS_ONLINE(b) && (jb->subscription & JABBER_SUB_PENDING || !(jb->subscription & JABBER_SUB_TO))) { ret = g_strdup(_("Not Authorized")); @@ -2225,7 +2222,7 @@ label = g_strdup_printf("%s%s", _("Status"), (res ? res : "")); value = g_strdup_printf("%s%s%s", state, (text ? ": " : ""), (text ? text : "")); - purple_notify_user_info_add_pair(user_info, label, value); + purple_notify_user_info_add_pair_html(user_info, label, value); g_free(label); g_free(value); g_free(text); @@ -2238,7 +2235,7 @@ gchar *idle_str = purple_str_seconds_to_string(time(NULL) - jbr->idle); label = g_strdup_printf("%s%s", _("Idle"), (res ? res : "")); - purple_notify_user_info_add_pair(user_info, label, idle_str); + purple_notify_user_info_add_pair_plaintext(user_info, label, idle_str); g_free(idle_str); g_free(label); } @@ -2250,6 +2247,7 @@ JabberBuddy *jb; PurpleAccount *account; PurpleConnection *gc; + JabberStream *js; g_return_if_fail(b != NULL); @@ -2258,9 +2256,11 @@ gc = purple_account_get_connection(account); g_return_if_fail(gc != NULL); - g_return_if_fail(gc->proto_data != NULL); - - jb = jabber_buddy_find(gc->proto_data, purple_buddy_get_name(b), FALSE); + + js = purple_connection_get_protocol_data(gc); + g_return_if_fail(js != NULL); + + jb = jabber_buddy_find(js, purple_buddy_get_name(b), FALSE); if(jb) { JabberBuddyResource *jbr = NULL; @@ -2310,10 +2310,10 @@ char *moodplustext = g_strdup_printf("%s (%s)", description ? _(description) : mood, moodtext); - purple_notify_user_info_add_pair(user_info, _("Mood"), moodplustext); + purple_notify_user_info_add_pair_html(user_info, _("Mood"), moodplustext); g_free(moodplustext); } else - purple_notify_user_info_add_pair(user_info, _("Mood"), + purple_notify_user_info_add_pair_html(user_info, _("Mood"), description ? _(description) : mood); } if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) { @@ -2323,7 +2323,7 @@ const char *album = purple_status_get_attr_string(tune, PURPLE_TUNE_ALBUM); char *playing = purple_util_format_song_info(title, artist, album, NULL); if (playing) { - purple_notify_user_info_add_pair(user_info, _("Now Listening"), playing); + purple_notify_user_info_add_pair_html(user_info, _("Now Listening"), playing); g_free(playing); } } @@ -2344,12 +2344,12 @@ sub = _("None"); } - purple_notify_user_info_add_pair(user_info, _("Subscription"), sub); + purple_notify_user_info_add_pair_html(user_info, _("Subscription"), sub); } if(!PURPLE_BUDDY_IS_ONLINE(b) && jb->error_msg) { - purple_notify_user_info_add_pair(user_info, _("Error"), jb->error_msg); + purple_notify_user_info_add_pair_html(user_info, _("Error"), jb->error_msg); } } } @@ -2484,7 +2484,7 @@ purple_notify_info(js->gc, _("Password Changed"), _("Password Changed"), _("Your password has been changed.")); - purple_account_set_password(js->gc->account, (char *)data); + purple_account_set_password(purple_connection_get_account(js->gc), (char *)data); } else { char *msg = jabber_parse_error(js, packet, NULL); @@ -2531,7 +2531,7 @@ { PurpleConnection *gc = (PurpleConnection *) action->context; - JabberStream *js = gc->proto_data; + JabberStream *js = purple_connection_get_protocol_data(gc); PurpleRequestFields *fields; PurpleRequestFieldGroup *group; PurpleRequestField *field; @@ -2563,7 +2563,7 @@ GList *jabber_actions(PurplePlugin *plugin, gpointer context) { PurpleConnection *gc = (PurpleConnection *) context; - JabberStream *js = gc->proto_data; + JabberStream *js = purple_connection_get_protocol_data(gc); GList *m = NULL; PurplePluginAction *act; @@ -2634,7 +2634,7 @@ void jabber_convo_closed(PurpleConnection *gc, const char *who) { - JabberStream *js = gc->proto_data; + JabberStream *js = purple_connection_get_protocol_data(gc); JabberID *jid; JabberBuddy *jb; JabberBuddyResource *jbr; @@ -2739,8 +2739,8 @@ } else if(xmlnode_get_child(packet, "not-authorized")) { SET_REASON(PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED); /* Clear the pasword if it isn't being saved */ - if (!purple_account_get_remember_password(js->gc->account)) - purple_account_set_password(js->gc->account, NULL); + if (!purple_account_get_remember_password(purple_connection_get_account(js->gc))) + purple_account_set_password(purple_connection_get_account(js->gc), NULL); text = _("Not Authorized"); } else if(xmlnode_get_child(packet, "temporary-auth-failure")) { text = _("Temporary Authentication Failure"); @@ -2997,7 +2997,7 @@ if(!args || !args[0]) return PURPLE_CMD_RET_FAILED; - jabber_chat_invite(purple_conversation_get_gc(conv), + jabber_chat_invite(purple_conversation_get_connection(conv), purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), args[1] ? args[1] : "", args[0]); @@ -3044,7 +3044,7 @@ if (args[1]) g_hash_table_insert(components, "password", args[1]); - jabber_chat_join(purple_conversation_get_gc(conv), components); + jabber_chat_join(purple_conversation_get_connection(conv), components); g_hash_table_destroy(components); jabber_id_free(jid); @@ -3078,7 +3078,7 @@ who = g_strdup_printf("%s@%s/%s", chat->room, chat->server, args[0]); - jabber_message_send_im(purple_conversation_get_gc(conv), who, args[1], 0); + jabber_message_send_im(purple_conversation_get_connection(conv), who, args[1], 0); g_free(who); return PURPLE_CMD_RET_OK; @@ -3159,13 +3159,14 @@ static PurpleCmdRet jabber_cmd_buzz(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { - JabberStream *js = conv->account->gc->proto_data; + PurpleAccount *account = purple_conversation_get_account(conv); + JabberStream *js = purple_connection_get_protocol_data(purple_account_get_connection(account)); const gchar *who; gchar *description; PurpleBuddy *buddy; const char *alias; PurpleAttentionType *attn = - purple_get_attention_type_from_code(conv->account, 0); + purple_get_attention_type_from_code(account, 0); if (!args || !args[0]) { /* use the buddy from conversation, if it's a one-to-one conversation */ @@ -3178,7 +3179,7 @@ who = args[0]; } - buddy = purple_find_buddy(conv->account, who); + buddy = purple_find_buddy(account, who); if (buddy != NULL) alias = purple_buddy_get_contact_alias(buddy); else @@ -3206,7 +3207,7 @@ gboolean jabber_send_attention(PurpleConnection *gc, const char *username, guint code) { - JabberStream *js = gc->proto_data; + JabberStream *js = purple_connection_get_protocol_data(gc); gchar *error = NULL; if (!_jabber_send_buzz(js, username, &error)) { @@ -3289,8 +3290,8 @@ PurpleMediaSessionType type) { #ifdef USE_VV - JabberStream *js = (JabberStream *) - purple_account_get_connection(account)->proto_data; + PurpleConnection *gc = purple_account_get_connection(account); + JabberStream *js = purple_connection_get_protocol_data(gc); JabberBuddy *jb; JabberBuddyResource *jbr = NULL; char *resource; @@ -3301,7 +3302,6 @@ return FALSE; } - if((resource = jabber_get_resource(who)) != NULL) { /* they've specified a resource, no need to ask or * default or anything, just do it */ @@ -3432,8 +3432,8 @@ PurpleMediaCaps jabber_get_media_caps(PurpleAccount *account, const char *who) { #ifdef USE_VV - JabberStream *js = (JabberStream *) - purple_account_get_connection(account)->proto_data; + PurpleConnection *gc = purple_account_get_connection(account); + JabberStream *js = purple_connection_get_protocol_data(gc); JabberBuddy *jb; JabberBuddyResource *jbr; PurpleMediaCaps total = PURPLE_MEDIA_CAPS_NONE; @@ -3521,7 +3521,7 @@ gboolean jabber_can_receive_file(PurpleConnection *gc, const char *who) { - JabberStream *js = gc->proto_data; + JabberStream *js = purple_connection_get_protocol_data(gc); if (js) { JabberBuddy *jb = jabber_buddy_find(js, who, FALSE); @@ -3571,7 +3571,8 @@ jabber_cmd_mood(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { - JabberStream *js = conv->account->gc->proto_data; + PurpleAccount *account = purple_conversation_get_account(conv); + JabberStream *js = purple_connection_get_protocol_data(purple_account_get_connection(account)); if (js->pep) { /* if no argument was given, unset mood */ @@ -3755,7 +3756,7 @@ if (!purple_account_is_connected(account)) return FALSE; - js = gc->proto_data; + js = purple_connection_get_protocol_data(gc); if (!(resource = jabber_get_resource(jid)) || !(jb = jabber_buddy_find(js, jid, FALSE)) || diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/jabber.h --- a/libpurple/protocols/jabber/jabber.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/jabber.h Fri Apr 06 04:30:00 2012 +0000 @@ -99,6 +99,7 @@ struct _JabberStream { int fd; + guint inpa; PurpleSrvTxtQueryData *srv_query_data; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/jutil.c --- a/libpurple/protocols/jabber/jutil.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/jutil.c Fri Apr 06 04:30:00 2012 +0000 @@ -583,11 +583,16 @@ const char *jabber_normalize(const PurpleAccount *account, const char *in) { - PurpleConnection *gc = account ? account->gc : NULL; - JabberStream *js = gc ? gc->proto_data : NULL; + PurpleConnection *gc = NULL; + JabberStream *js = NULL; static char buf[3072]; /* maximum legal length of a jabber jid */ JabberID *jid; + if (account) + gc = purple_account_get_connection(account); + if (gc) + js = purple_connection_get_protocol_data(gc); + jid = jabber_id_new_internal(in, TRUE); if(!jid) return NULL; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/libfacebook.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/jabber/libfacebook.c Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,326 @@ +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + */ + +/* libfacebook is the Facebook XMPP protocol plugin. It is linked against + * libjabbercommon, which may be used to support other protocols (Bonjour) + * which may need to share code. + */ + +#include "internal.h" + +#include "accountopt.h" +#include "core.h" +#include "debug.h" +#include "version.h" + +#include "iq.h" +#include "jabber.h" +#include "chat.h" +#include "disco.h" +#include "message.h" +#include "roster.h" +#include "si.h" +#include "message.h" +#include "presence.h" +#include "google/google.h" +#include "pep.h" +#include "usermood.h" +#include "usertune.h" +#include "caps.h" +#include "data.h" +#include "ibb.h" + +static const char * +facebook_list_icon(PurpleAccount *a, PurpleBuddy *b) +{ + return "facebook"; +} + +static PurplePlugin *my_protocol = NULL; + +static PurplePluginProtocolInfo prpl_info = +{ + sizeof(PurplePluginProtocolInfo), /* struct_size */ + OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_MAIL_CHECK | +#ifdef HAVE_CYRUS_SASL + OPT_PROTO_PASSWORD_OPTIONAL | +#endif + OPT_PROTO_SLASH_COMMANDS_NATIVE, + NULL, /* user_splits */ + NULL, /* protocol_options */ + {"png", 32, 32, 96, 96, 0, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ + facebook_list_icon, /* list_icon */ + jabber_list_emblem, /* list_emblems */ + jabber_status_text, /* status_text */ + jabber_tooltip_text, /* tooltip_text */ + jabber_status_types, /* status_types */ + jabber_blist_node_menu, /* blist_node_menu */ + jabber_chat_info, /* chat_info */ + jabber_chat_info_defaults, /* chat_info_defaults */ + jabber_login, /* login */ + jabber_close, /* close */ + jabber_message_send_im, /* send_im */ + jabber_set_info, /* set_info */ + jabber_send_typing, /* send_typing */ + jabber_buddy_get_info, /* get_info */ + jabber_set_status, /* set_status */ + jabber_idle_set, /* set_idle */ + NULL, /* change_passwd */ + NULL, /* add_buddy */ + NULL, /* add_buddies */ + NULL, /* remove_buddy */ + NULL, /* remove_buddies */ + NULL, /* add_permit */ + NULL, /* add_deny */ + NULL, /* rem_permit */ + NULL, /* rem_deny */ + NULL, /* set_permit_deny */ + jabber_chat_join, /* join_chat */ + NULL, /* reject_chat */ + jabber_get_chat_name, /* get_chat_name */ + jabber_chat_invite, /* chat_invite */ + jabber_chat_leave, /* chat_leave */ + NULL, /* chat_whisper */ + jabber_message_send_chat, /* chat_send */ + jabber_keepalive, /* keepalive */ + NULL, /* register_user */ + NULL, /* get_cb_info */ + NULL, /* alias_buddy */ + NULL, /* group_buddy */ + NULL, /* rename_group */ + NULL, /* buddy_free */ + jabber_convo_closed, /* convo_closed */ + jabber_normalize, /* normalize */ + jabber_set_buddy_icon, /* set_buddy_icon */ + NULL, /* remove_group */ + jabber_chat_buddy_real_name, /* get_cb_real_name */ + jabber_chat_set_topic, /* set_chat_topic */ + jabber_find_blist_chat, /* find_blist_chat */ + jabber_roomlist_get_list, /* roomlist_get_list */ + jabber_roomlist_cancel, /* roomlist_cancel */ + NULL, /* roomlist_expand_category */ + NULL, /* can_receive_file */ + NULL, /* send_file */ + NULL, /* new_xfer */ + jabber_offline_message, /* offline_message */ + NULL, /* whiteboard_prpl_ops */ + jabber_prpl_send_raw, /* send_raw */ + jabber_roomlist_room_serialize, /* roomlist_room_serialize */ + NULL, /* unregister_user */ + NULL, /* send_attention */ + NULL, /* attention_types */ + NULL, /* get_account_text_table */ + NULL, /* initiate_media */ + NULL, /* get_media_caps */ + NULL, /* get_moods */ + NULL, /* set_public_alias */ + NULL /* get_public_alias */ +}; + +static gboolean load_plugin(PurplePlugin *plugin) +{ + jabber_plugin_init(plugin); + + return TRUE; +} + +static gboolean unload_plugin(PurplePlugin *plugin) +{ + jabber_plugin_uninit(plugin); + + return TRUE; +} + +static PurplePluginInfo info = +{ + PURPLE_PLUGIN_MAGIC, + PURPLE_MAJOR_VERSION, + PURPLE_MINOR_VERSION, + PURPLE_PLUGIN_PROTOCOL, /**< type */ + NULL, /**< ui_requirement */ + 0, /**< flags */ + NULL, /**< dependencies */ + PURPLE_PRIORITY_DEFAULT, /**< priority */ + + "prpl-facebook-xmpp", /**< id */ + "Facebook (XMPP)", /**< name */ + DISPLAY_VERSION, /**< version */ + /** summary */ + N_("Facebook XMPP Protocol Plugin"), + /** description */ + N_("Facebook XMPP Protocol Plugin"), + NULL, /**< author */ + PURPLE_WEBSITE, /**< homepage */ + + load_plugin, /**< load */ + unload_plugin, /**< unload */ + NULL, /**< destroy */ + + NULL, /**< ui_info */ + &prpl_info, /**< extra_info */ + NULL, /**< prefs_info */ + jabber_actions, + + /* padding */ + NULL, + NULL, + NULL, + NULL +}; + +static PurpleAccount *find_acct(const char *prpl, const char *acct_id) +{ + PurpleAccount *acct = NULL; + + /* If we have a specific acct, use it */ + if (acct_id) { + acct = purple_accounts_find(acct_id, prpl); + if (acct && !purple_account_is_connected(acct)) + acct = NULL; + } else { /* Otherwise find an active account for the protocol */ + GList *l = purple_accounts_get_all(); + while (l) { + if (!strcmp(prpl, purple_account_get_protocol_id(l->data)) + && purple_account_is_connected(l->data)) { + acct = l->data; + break; + } + l = l->next; + } + } + + return acct; +} + +static gboolean xmpp_uri_handler(const char *proto, const char *user, GHashTable *params) +{ + char *acct_id = params ? g_hash_table_lookup(params, "account") : NULL; + PurpleAccount *acct; + + if (g_ascii_strcasecmp(proto, "xmpp")) + return FALSE; + + acct = find_acct(purple_plugin_get_id(my_protocol), acct_id); + + if (!acct) + return FALSE; + + /* xmpp:romeo@montague.net?message;subject=Test%20Message;body=Here%27s%20a%20test%20message */ + /* params is NULL if the URI has no '?' (or anything after it) */ + if (!params || g_hash_table_lookup_extended(params, "message", NULL, NULL)) { + char *body = g_hash_table_lookup(params, "body"); + if (user && *user) { + PurpleConversation *conv = + purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, user); + purple_conversation_present(conv); + if (body && *body) + purple_conv_send_confirm(conv, body); + } + } else if (g_hash_table_lookup_extended(params, "roster", NULL, NULL)) { + char *name = g_hash_table_lookup(params, "name"); + if (user && *user) + purple_blist_request_add_buddy(acct, user, NULL, name); + } else if (g_hash_table_lookup_extended(params, "join", NULL, NULL)) { + PurpleConnection *gc = purple_account_get_connection(acct); + if (user && *user) { + GHashTable *params = jabber_chat_info_defaults(gc, user); + jabber_chat_join(gc, params); + } + return TRUE; + } + + return FALSE; +} + + +static void +init_plugin(PurplePlugin *plugin) +{ + PurpleAccountUserSplit *split; + PurpleAccountOption *option; + GList *encryption_values = NULL; + + /* Translators: 'domain' is used here in the context of Internet domains, e.g. pidgin.im */ + split = purple_account_user_split_new(_("Domain"), "chat.facebook.com", '@'); + purple_account_user_split_set_reverse(split, FALSE); + prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); + + split = purple_account_user_split_new(_("Resource"), "", '/'); + purple_account_user_split_set_reverse(split, FALSE); + prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); + +#define ADD_VALUE(list, desc, v) { \ + PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1); \ + kvp->key = g_strdup((desc)); \ + kvp->value = g_strdup((v)); \ + list = g_list_prepend(list, kvp); \ +} + + ADD_VALUE(encryption_values, _("Use encryption if available"), "opportunistic_tls"); + ADD_VALUE(encryption_values, _("Require encryption"), "require_tls"); + ADD_VALUE(encryption_values, _("Use old-style SSL"), "old_ssl"); +#if 0 + ADD_VALUE(encryption_values, "None", "none"); +#endif + encryption_values = g_list_reverse(encryption_values); + +#undef ADD_VALUE + + option = purple_account_option_list_new(_("Connection security"), "connection_security", encryption_values); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + option); + + option = purple_account_option_bool_new( + _("Allow plaintext auth over unencrypted streams"), + "auth_plain_in_clear", FALSE); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + option); + + option = purple_account_option_int_new(_("Connect port"), "port", 5222); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + option); + + option = purple_account_option_string_new(_("Connect server"), + "connect_server", NULL); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + option); + + option = purple_account_option_string_new(_("BOSH URL"), + "bosh_url", NULL); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + option); + + /* this should probably be part of global smiley theme settings later on, + shared with MSN */ + option = purple_account_option_bool_new(_("Show Custom Smileys"), + "custom_smileys", TRUE); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + option); + + my_protocol = plugin; + + purple_signal_connect(purple_get_core(), "uri-handler", plugin, + PURPLE_CALLBACK(xmpp_uri_handler), NULL); +} + +PURPLE_INIT_PLUGIN(facebookxmpp, init_plugin, info); + diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/libgtalk.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/jabber/libgtalk.c Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,334 @@ +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + */ + +/* libgtalk is the Google Talk XMPP protocol plugin. It is linked against + * libjabbercommon, which may be used to support other protocols (Bonjour) which + * may need to share code. + */ + +#include "internal.h" + +#include "accountopt.h" +#include "core.h" +#include "debug.h" +#include "version.h" + +#include "iq.h" +#include "jabber.h" +#include "chat.h" +#include "disco.h" +#include "message.h" +#include "roster.h" +#include "si.h" +#include "message.h" +#include "presence.h" +#include "google/google.h" +#include "pep.h" +#include "usermood.h" +#include "usertune.h" +#include "caps.h" +#include "data.h" +#include "ibb.h" + +static const char * +gtalk_list_icon(PurpleAccount *a, PurpleBuddy *b) +{ + return "google-talk"; +} + +static PurplePlugin *my_protocol = NULL; + +static PurplePluginProtocolInfo prpl_info = +{ + sizeof(PurplePluginProtocolInfo), /* struct_size */ + OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_MAIL_CHECK | +#ifdef HAVE_CYRUS_SASL + OPT_PROTO_PASSWORD_OPTIONAL | +#endif + OPT_PROTO_SLASH_COMMANDS_NATIVE, + NULL, /* user_splits */ + NULL, /* protocol_options */ + {"png", 32, 32, 96, 96, 0, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ + gtalk_list_icon, /* list_icon */ + jabber_list_emblem, /* list_emblems */ + jabber_status_text, /* status_text */ + jabber_tooltip_text, /* tooltip_text */ + jabber_status_types, /* status_types */ + jabber_blist_node_menu, /* blist_node_menu */ + jabber_chat_info, /* chat_info */ + jabber_chat_info_defaults, /* chat_info_defaults */ + jabber_login, /* login */ + jabber_close, /* close */ + jabber_message_send_im, /* send_im */ + jabber_set_info, /* set_info */ + jabber_send_typing, /* send_typing */ + jabber_buddy_get_info, /* get_info */ + jabber_set_status, /* set_status */ + jabber_idle_set, /* set_idle */ + NULL, /* change_passwd */ + jabber_roster_add_buddy, /* add_buddy */ + NULL, /* add_buddies */ + jabber_roster_remove_buddy, /* remove_buddy */ + NULL, /* remove_buddies */ + NULL, /* add_permit */ + jabber_add_deny, /* add_deny */ + NULL, /* rem_permit */ + jabber_rem_deny, /* rem_deny */ + NULL, /* set_permit_deny */ + jabber_chat_join, /* join_chat */ + NULL, /* reject_chat */ + jabber_get_chat_name, /* get_chat_name */ + jabber_chat_invite, /* chat_invite */ + jabber_chat_leave, /* chat_leave */ + NULL, /* chat_whisper */ + jabber_message_send_chat, /* chat_send */ + jabber_keepalive, /* keepalive */ + NULL, /* register_user */ + NULL, /* get_cb_info */ + jabber_roster_alias_change, /* alias_buddy */ + jabber_roster_group_change, /* group_buddy */ + jabber_roster_group_rename, /* rename_group */ + NULL, /* buddy_free */ + jabber_convo_closed, /* convo_closed */ + jabber_normalize, /* normalize */ + jabber_set_buddy_icon, /* set_buddy_icon */ + NULL, /* remove_group */ + jabber_chat_buddy_real_name, /* get_cb_real_name */ + jabber_chat_set_topic, /* set_chat_topic */ + jabber_find_blist_chat, /* find_blist_chat */ + jabber_roomlist_get_list, /* roomlist_get_list */ + jabber_roomlist_cancel, /* roomlist_cancel */ + NULL, /* roomlist_expand_category */ + jabber_can_receive_file, /* can_receive_file */ + jabber_si_xfer_send, /* send_file */ + jabber_si_new_xfer, /* new_xfer */ + jabber_offline_message, /* offline_message */ + NULL, /* whiteboard_prpl_ops */ + jabber_prpl_send_raw, /* send_raw */ + jabber_roomlist_room_serialize, /* roomlist_room_serialize */ + NULL, /* unregister_user */ + jabber_send_attention, /* send_attention */ + jabber_attention_types, /* attention_types */ + NULL, /* get_account_text_table */ + jabber_initiate_media, /* initiate_media */ + jabber_get_media_caps, /* get_media_caps */ + jabber_get_moods, /* get_moods */ + NULL, /* set_public_alias */ + NULL /* get_public_alias */ +}; + +static gboolean load_plugin(PurplePlugin *plugin) +{ + jabber_plugin_init(plugin); + + return TRUE; +} + +static gboolean unload_plugin(PurplePlugin *plugin) +{ + jabber_plugin_uninit(plugin); + + return TRUE; +} + +static PurplePluginInfo info = +{ + PURPLE_PLUGIN_MAGIC, + PURPLE_MAJOR_VERSION, + PURPLE_MINOR_VERSION, + PURPLE_PLUGIN_PROTOCOL, /**< type */ + NULL, /**< ui_requirement */ + 0, /**< flags */ + NULL, /**< dependencies */ + PURPLE_PRIORITY_DEFAULT, /**< priority */ + + "prpl-gtalk", /**< id */ + "Google Talk (XMPP)", /**< name */ + DISPLAY_VERSION, /**< version */ + /** summary */ + N_("Google Talk Protocol Plugin"), + /** description */ + N_("Google Talk Protocol Plugin"), + NULL, /**< author */ + PURPLE_WEBSITE, /**< homepage */ + + load_plugin, /**< load */ + unload_plugin, /**< unload */ + NULL, /**< destroy */ + + NULL, /**< ui_info */ + &prpl_info, /**< extra_info */ + NULL, /**< prefs_info */ + jabber_actions, + + /* padding */ + NULL, + NULL, + NULL, + NULL +}; + +static PurpleAccount *find_acct(const char *prpl, const char *acct_id) +{ + PurpleAccount *acct = NULL; + + /* If we have a specific acct, use it */ + if (acct_id) { + acct = purple_accounts_find(acct_id, prpl); + if (acct && !purple_account_is_connected(acct)) + acct = NULL; + } else { /* Otherwise find an active account for the protocol */ + GList *l = purple_accounts_get_all(); + while (l) { + if (!strcmp(prpl, purple_account_get_protocol_id(l->data)) + && purple_account_is_connected(l->data)) { + acct = l->data; + break; + } + l = l->next; + } + } + + return acct; +} + +static gboolean xmpp_uri_handler(const char *proto, const char *user, GHashTable *params) +{ + char *acct_id = params ? g_hash_table_lookup(params, "account") : NULL; + PurpleAccount *acct; + + if (g_ascii_strcasecmp(proto, "xmpp")) + return FALSE; + + acct = find_acct(purple_plugin_get_id(my_protocol), acct_id); + + if (!acct) + return FALSE; + + /* xmpp:romeo@montague.net?message;subject=Test%20Message;body=Here%27s%20a%20test%20message */ + /* params is NULL if the URI has no '?' (or anything after it) */ + if (!params || g_hash_table_lookup_extended(params, "message", NULL, NULL)) { + char *body = g_hash_table_lookup(params, "body"); + if (user && *user) { + PurpleConversation *conv = + purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, user); + purple_conversation_present(conv); + if (body && *body) + purple_conv_send_confirm(conv, body); + } + } else if (g_hash_table_lookup_extended(params, "roster", NULL, NULL)) { + char *name = g_hash_table_lookup(params, "name"); + if (user && *user) + purple_blist_request_add_buddy(acct, user, NULL, name); + } else if (g_hash_table_lookup_extended(params, "join", NULL, NULL)) { + PurpleConnection *gc = purple_account_get_connection(acct); + if (user && *user) { + GHashTable *params = jabber_chat_info_defaults(gc, user); + jabber_chat_join(gc, params); + } + return TRUE; + } + + return FALSE; +} + + +static void +init_plugin(PurplePlugin *plugin) +{ + PurpleAccountUserSplit *split; + PurpleAccountOption *option; + GList *encryption_values = NULL; + + /* Translators: 'domain' is used here in the context of Internet domains, e.g. pidgin.im */ + split = purple_account_user_split_new(_("Domain"), "gmail.com", '@'); + purple_account_user_split_set_reverse(split, FALSE); + prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); + + split = purple_account_user_split_new(_("Resource"), "", '/'); + purple_account_user_split_set_reverse(split, FALSE); + prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); + +#define ADD_VALUE(list, desc, v) { \ + PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1); \ + kvp->key = g_strdup((desc)); \ + kvp->value = g_strdup((v)); \ + list = g_list_prepend(list, kvp); \ +} + + ADD_VALUE(encryption_values, _("Require encryption"), "require_tls"); + ADD_VALUE(encryption_values, _("Use encryption if available"), "opportunistic_tls"); + ADD_VALUE(encryption_values, _("Use old-style SSL"), "old_ssl"); +#if 0 + ADD_VALUE(encryption_values, "None", "none"); +#endif + encryption_values = g_list_reverse(encryption_values); + +#undef ADD_VALUE + + option = purple_account_option_list_new(_("Connection security"), "connection_security", encryption_values); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + option); + + option = purple_account_option_bool_new( + _("Allow plaintext auth over unencrypted streams"), + "auth_plain_in_clear", FALSE); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + option); + + option = purple_account_option_int_new(_("Connect port"), "port", 5222); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + option); + + option = purple_account_option_string_new(_("Connect server"), + "connect_server", NULL); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + option); + + option = purple_account_option_string_new(_("File transfer proxies"), + "ft_proxies", + /* TODO: Is this an acceptable default? + * Also, keep this in sync as they add more servers */ + JABBER_DEFAULT_FT_PROXIES); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + option); + + option = purple_account_option_string_new(_("BOSH URL"), + "bosh_url", NULL); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + option); + + /* this should probably be part of global smiley theme settings later on, + shared with MSN */ + option = purple_account_option_bool_new(_("Show Custom Smileys"), + "custom_smileys", TRUE); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + option); + + my_protocol = plugin; + + purple_signal_connect(purple_get_core(), "uri-handler", plugin, + PURPLE_CALLBACK(xmpp_uri_handler), NULL); +} + +PURPLE_INIT_PLUGIN(gtalk, init_plugin, info); + diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/libxmpp.c --- a/libpurple/protocols/jabber/libxmpp.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/libxmpp.c Fri Apr 06 04:30:00 2012 +0000 @@ -53,6 +53,7 @@ static PurplePluginProtocolInfo prpl_info = { + sizeof(PurplePluginProtocolInfo), /* struct_size */ OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_MAIL_CHECK | #ifdef HAVE_CYRUS_SASL OPT_PROTO_PASSWORD_OPTIONAL | @@ -97,7 +98,6 @@ jabber_keepalive, /* keepalive */ jabber_register_account, /* register_user */ NULL, /* get_cb_info */ - NULL, /* get_cb_away */ jabber_roster_alias_change, /* alias_buddy */ jabber_roster_group_change, /* group_buddy */ jabber_roster_group_rename, /* rename_group */ @@ -122,16 +122,12 @@ jabber_unregister_account, /* unregister_user */ jabber_send_attention, /* send_attention */ jabber_attention_types, /* attention_types */ - - sizeof(PurplePluginProtocolInfo), /* struct_size */ NULL, /* get_account_text_table */ jabber_initiate_media, /* initiate_media */ jabber_get_media_caps, /* get_media_caps */ jabber_get_moods, /* get_moods */ NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - NULL, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ + NULL /* get_public_alias */ }; static gboolean load_plugin(PurplePlugin *plugin) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/message.c --- a/libpurple/protocols/jabber/message.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/message.c Fri Apr 06 04:30:00 2012 +0000 @@ -638,6 +638,8 @@ jabber_message_add_remote_smileys(js, to, packet); } + xmlnode_strip_prefixes(child); + /* reformat xhtml so that img tags with a "cid:" src gets translated to the bare text of the emoticon (the "alt" attrib) */ /* this is done also when custom smiley retrieval is turned off, @@ -1148,13 +1150,13 @@ resource = jabber_get_resource(who); - jb = jabber_buddy_find(gc->proto_data, who, TRUE); + jb = jabber_buddy_find(purple_connection_get_protocol_data(gc), who, TRUE); jbr = jabber_buddy_find_resource(jb, resource); g_free(resource); jm = g_new0(JabberMessage, 1); - jm->js = gc->proto_data; + jm->js = purple_connection_get_protocol_data(gc); jm->type = JABBER_MESSAGE_CHAT; jm->chat_state = JM_STATE_ACTIVE; jm->to = g_strdup(who); @@ -1211,14 +1213,14 @@ if(!msg || !gc) return 0; - js = gc->proto_data; + js = purple_connection_get_protocol_data(gc); chat = jabber_chat_find_by_id(js, id); if(!chat) return 0; jm = g_new0(JabberMessage, 1); - jm->js = gc->proto_data; + jm->js = purple_connection_get_protocol_data(gc); jm->type = JABBER_MESSAGE_GROUPCHAT; jm->to = g_strdup_printf("%s@%s", chat->room, chat->server); jm->id = jabber_get_next_id(jm->js); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/oob.c --- a/libpurple/protocols/jabber/oob.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/oob.c Fri Apr 06 04:30:00 2012 +0000 @@ -48,13 +48,13 @@ static void jabber_oob_xfer_init(PurpleXfer *xfer) { - JabberOOBXfer *jox = xfer->data; + JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer); purple_xfer_start(xfer, -1, jox->address, jox->port); } static void jabber_oob_xfer_free(PurpleXfer *xfer) { - JabberOOBXfer *jox = xfer->data; + JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer); jox->js->oob_file_transfers = g_list_remove(jox->js->oob_file_transfers, xfer); @@ -67,16 +67,16 @@ purple_input_remove(jox->writeh); g_free(jox); - xfer->data = NULL; + purple_xfer_set_protocol_data(xfer, NULL); } static void jabber_oob_xfer_end(PurpleXfer *xfer) { - JabberOOBXfer *jox = xfer->data; + JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer); JabberIq *iq; iq = jabber_iq_new(jox->js, JABBER_IQ_RESULT); - xmlnode_set_attrib(iq->node, "to", xfer->who); + xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer)); jabber_iq_set_id(iq, jox->iq_id); jabber_iq_send(iq); @@ -86,10 +86,10 @@ static void jabber_oob_xfer_request_send(gpointer data, gint source, PurpleInputCondition cond) { PurpleXfer *xfer = data; - JabberOOBXfer *jox = xfer->data; + JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer); int len, total_len = strlen(jox->write_buffer); - len = write(xfer->fd, jox->write_buffer + jox->written_len, + len = purple_xfer_write(xfer, (guchar*) jox->write_buffer + jox->written_len, total_len - jox->written_len); if(len < 0 && errno == EAGAIN) @@ -110,7 +110,7 @@ static void jabber_oob_xfer_start(PurpleXfer *xfer) { - JabberOOBXfer *jox = xfer->data; + JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer); if(jox->write_buffer == NULL) { jox->write_buffer = g_strdup_printf( @@ -119,26 +119,26 @@ jox->written_len = 0; } - jox->writeh = purple_input_add(xfer->fd, PURPLE_INPUT_WRITE, + jox->writeh = purple_input_add(purple_xfer_get_fd(xfer), PURPLE_INPUT_WRITE, jabber_oob_xfer_request_send, xfer); - jabber_oob_xfer_request_send(xfer, xfer->fd, PURPLE_INPUT_WRITE); + jabber_oob_xfer_request_send(xfer, purple_xfer_get_fd(xfer), PURPLE_INPUT_WRITE); } static gssize jabber_oob_xfer_read(guchar **buffer, PurpleXfer *xfer) { - JabberOOBXfer *jox = xfer->data; + JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer); char test[2048]; char *tmp, *lenstr; int len; - if((len = read(xfer->fd, test, sizeof(test))) > 0) { + if((len = read(purple_xfer_get_fd(xfer), test, sizeof(test))) > 0) { jox->headers = g_string_append_len(jox->headers, test, len); if((tmp = strstr(jox->headers->str, "\r\n\r\n"))) { *tmp = '\0'; lenstr = strstr(jox->headers->str, "Content-Length: "); if(lenstr) { - int size; - sscanf(lenstr, "Content-Length: %d", &size); + goffset size; + sscanf(lenstr, "Content-Length: %" G_GOFFSET_FORMAT, &size); purple_xfer_set_size(xfer, size); } purple_xfer_set_read_fnc(xfer, NULL); @@ -158,12 +158,12 @@ } static void jabber_oob_xfer_recv_error(PurpleXfer *xfer, const char *code) { - JabberOOBXfer *jox = xfer->data; + JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer); JabberIq *iq; xmlnode *y, *z; iq = jabber_iq_new(jox->js, JABBER_IQ_ERROR); - xmlnode_set_attrib(iq->node, "to", xfer->who); + xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer)); jabber_iq_set_id(iq, jox->iq_id); y = xmlnode_new_child(iq->node, "error"); xmlnode_set_attrib(y, "code", code); @@ -218,10 +218,10 @@ jox->headers = g_string_new(""); jox->iq_id = g_strdup(id); - xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE, from); + xfer = purple_xfer_new(purple_connection_get_account(js->gc), PURPLE_XFER_RECEIVE, from); if (xfer) { - xfer->data = jox; + purple_xfer_set_protocol_data(xfer, jox); if(!(filename = g_strdup(g_strrstr(jox->page, "/")))) filename = g_strdup(jox->page); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/parser.c --- a/libpurple/protocols/jabber/parser.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/parser.c Fri Apr 06 04:30:00 2012 +0000 @@ -52,7 +52,7 @@ */ purple_debug_error("jabber", "Expecting stream header, got %s with " "xmlns %s\n", element_name, namespace); - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, _("XMPP stream header missing")); return; @@ -73,7 +73,7 @@ if (js->protocol_version.major > 1) { /* TODO: Send error */ - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, _("XMPP Version Mismatch")); g_free(attrib); @@ -98,7 +98,7 @@ /* This was underspecified in rfc3920 as only being a SHOULD, so * we cannot rely on it. See #12331 and Oracle's server. */ - purple_connection_error_reason(js->gc, + purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, _("XMPP stream missing ID")); #else @@ -300,7 +300,7 @@ break; case XML_ERR_FATAL: purple_debug_error("jabber", "xmlParseChunk returned fatal %i\n", ret); - purple_connection_error_reason (js->gc, + purple_connection_error (js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("XML Parse error")); break; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/presence.c --- a/libpurple/protocols/jabber/presence.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/presence.c Fri Apr 06 04:30:00 2012 +0000 @@ -299,11 +299,6 @@ jabber_presence_fake_to_self(js, status); } -xmlnode *jabber_presence_create(JabberBuddyState state, const char *msg, int priority) -{ - return jabber_presence_create_js(NULL, state, msg, priority); -} - xmlnode *jabber_presence_create_js(JabberStream *js, JabberBuddyState state, const char *msg, int priority) { xmlnode *show, *status, *presence, *pri, *c; @@ -393,7 +388,7 @@ { struct _jabber_add_permit *jap = data; if(PURPLE_CONNECTION_IS_VALID(jap->gc)) - jabber_presence_subscription_set(jap->gc->proto_data, + jabber_presence_subscription_set(purple_connection_get_protocol_data(jap->gc), jap->who, "subscribed"); g_free(jap->who); g_free(jap); @@ -403,7 +398,7 @@ { struct _jabber_add_permit *jap = data; if(PURPLE_CONNECTION_IS_VALID(jap->gc)) - jabber_presence_subscription_set(jap->gc->proto_data, + jabber_presence_subscription_set(purple_connection_get_protocol_data(jap->gc), jap->who, "unsubscribed"); g_free(jap->who); g_free(jap); @@ -464,7 +459,7 @@ hash = jabber_calculate_data_hash(data, size, "sha1"); } - purple_buddy_icons_set_for_user(js->gc->account, from, data, size, hash); + purple_buddy_icons_set_for_user(purple_connection_get_account(js->gc), from, data, size, hash); g_free(hash); } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/presence.h --- a/libpurple/protocols/jabber/presence.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/presence.h Fri Apr 06 04:30:00 2012 +0000 @@ -92,7 +92,6 @@ */ void jabber_presence_send(JabberStream *js, gboolean force); -xmlnode *jabber_presence_create(JabberBuddyState state, const char *msg, int priority); /* DEPRECATED */ xmlnode *jabber_presence_create_js(JabberStream *js, JabberBuddyState state, const char *msg, int priority); void jabber_presence_parse(JabberStream *js, xmlnode *packet); void jabber_presence_subscription_set(JabberStream *js, const char *who, diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/roster.c --- a/libpurple/protocols/jabber/roster.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/roster.c Fri Apr 06 04:30:00 2012 +0000 @@ -96,7 +96,7 @@ { GSList *buddies, *l; - buddies = purple_find_buddies(js->gc->account, jid); + buddies = purple_find_buddies(purple_connection_get_account(js->gc), jid); for(l = buddies; l; l = l->next) purple_blist_remove_buddy(l->data); @@ -110,7 +110,7 @@ GSList *buddies, *l; PurpleAccount *account = purple_connection_get_account(js->gc); - buddies = purple_find_buddies(js->gc->account, jid); + buddies = purple_find_buddies(purple_connection_get_account(js->gc), jid); if(!groups) { if(!buddies) @@ -304,7 +304,7 @@ if (js->currently_parsing_roster_push) return; - if(!(b = purple_find_buddy(js->gc->account, name))) + if(!(b = purple_find_buddy(purple_connection_get_account(js->gc), name))) return; if (groups) { @@ -314,7 +314,7 @@ "groups]: groups: %s\n", name, tmp); g_free(tmp); } else { - GSList *buddies = purple_find_buddies(js->gc->account, name); + GSList *buddies = purple_find_buddies(purple_connection_get_account(js->gc), name); char *tmp; if(!buddies) @@ -358,9 +358,9 @@ } void jabber_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, - PurpleGroup *group) + PurpleGroup *group, const char *message) { - JabberStream *js = gc->proto_data; + JabberStream *js = purple_connection_get_protocol_data(gc); char *who; JabberID *jid; JabberBuddy *jb; @@ -413,7 +413,7 @@ } else if(!jb || !(jb->subscription & JABBER_SUB_TO)) { jabber_presence_subscription_set(js, who, "subscribe"); } else if((jbr =jabber_buddy_find_resource(jb, NULL))) { - purple_prpl_got_user_status(gc->account, who, + purple_prpl_got_user_status(purple_connection_get_account(gc), who, jabber_buddy_state_get_status_id(jbr->state), "priority", jbr->priority, jbr->status ? "message" : NULL, jbr->status, NULL); } @@ -423,7 +423,7 @@ void jabber_roster_alias_change(PurpleConnection *gc, const char *name, const char *alias) { - PurpleBuddy *b = purple_find_buddy(gc->account, name); + PurpleBuddy *b = purple_find_buddy(purple_connection_get_account(gc), name); if(b != NULL) { purple_blist_alias_buddy(b, alias); @@ -431,7 +431,7 @@ purple_debug_info("jabber", "jabber_roster_alias_change(): Aliased %s to %s\n", name, alias ? alias : "(null)"); - jabber_roster_update(gc->proto_data, name, NULL); + jabber_roster_update(purple_connection_get_protocol_data(gc), name, NULL); } } @@ -446,7 +446,7 @@ if(!old_group || !new_group || !strcmp(old_group, new_group)) return; - buddies = purple_find_buddies(gc->account, name); + buddies = purple_find_buddies(purple_connection_get_account(gc), name); while(buddies) { b = buddies->data; g = purple_buddy_get_group(b); @@ -461,7 +461,7 @@ purple_debug_info("jabber", "jabber_roster_group_change(): Moving %s from %s to %s\n", name, old_group, new_group); - jabber_roster_update(gc->proto_data, name, groups); + jabber_roster_update(purple_connection_get_protocol_data(gc), name, groups); } void jabber_roster_group_rename(PurpleConnection *gc, const char *old_name, @@ -496,9 +496,9 @@ purple_debug_info("jabber", "jabber_roster_remove_buddy(): Removing %s from %s\n", purple_buddy_get_name(buddy), purple_group_get_name(group)); - jabber_roster_update(gc->proto_data, name, groups); + jabber_roster_update(purple_connection_get_protocol_data(gc), name, groups); } else { - JabberIq *iq = jabber_iq_new_query(gc->proto_data, JABBER_IQ_SET, + JabberIq *iq = jabber_iq_new_query(purple_connection_get_protocol_data(gc), JABBER_IQ_SET, "jabber:iq:roster"); xmlnode *query = xmlnode_get_child(iq->node, "query"); xmlnode *item = xmlnode_new_child(query, "item"); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/roster.h --- a/libpurple/protocols/jabber/roster.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/roster.h Fri Apr 06 04:30:00 2012 +0000 @@ -32,7 +32,7 @@ JabberIqType type, const char *id, xmlnode *query); void jabber_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, - PurpleGroup *group); + PurpleGroup *group, const char *message); void jabber_roster_alias_change(PurpleConnection *gc, const char *name, const char *alias); void jabber_roster_group_change(PurpleConnection *gc, const char *name, diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/si.c --- a/libpurple/protocols/jabber/si.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/si.c Fri Apr 06 04:30:00 2012 +0000 @@ -87,9 +87,9 @@ for(xfers = js->file_transfers; xfers; xfers = xfers->next) { PurpleXfer *xfer = xfers->data; - JabberSIXfer *jsx = xfer->data; - if(jsx->stream_id && xfer->who && - !strcmp(jsx->stream_id, sid) && !strcmp(xfer->who, from)) + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); + if(jsx->stream_id && purple_xfer_get_remote_user(xfer) && + !strcmp(jsx->stream_id, sid) && !strcmp(purple_xfer_get_remote_user(xfer), from)) return xfer; } @@ -118,7 +118,7 @@ jabber_si_bytestreams_connect_cb(gpointer data, gint source, const gchar *error_message) { PurpleXfer *xfer = data; - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); JabberIq *iq; xmlnode *query, *su; JabberBytestreamsStreamhost *streamhost = jsx->streamhosts->data; @@ -143,7 +143,7 @@ } /* unknown file transfer type is assumed to be RECEIVE */ - if(xfer->type == PURPLE_XFER_SEND) + if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) { xmlnode *activate; iq = jabber_iq_new_query(jsx->js, JABBER_IQ_SET, NS_BYTESTREAMS); @@ -151,14 +151,14 @@ query = xmlnode_get_child(iq->node, "query"); xmlnode_set_attrib(query, "sid", jsx->stream_id); activate = xmlnode_new_child(query, "activate"); - xmlnode_insert_data(activate, xfer->who, -1); + xmlnode_insert_data(activate, purple_xfer_get_remote_user(xfer), -1); /* TODO: We need to wait for an activation result before starting */ } else { iq = jabber_iq_new_query(jsx->js, JABBER_IQ_RESULT, NS_BYTESTREAMS); - xmlnode_set_attrib(iq->node, "to", xfer->who); + xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer)); jabber_iq_set_id(iq, jsx->iq_id); query = xmlnode_get_child(iq->node, "query"); su = xmlnode_new_child(query, "streamhost-used"); @@ -174,7 +174,7 @@ connect_timeout_cb(gpointer data) { PurpleXfer *xfer = data; - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); purple_debug_info("jabber", "Streamhost connection timeout of %d seconds exceeded.\n", STREAMHOST_CONNECT_TIMEOUT); @@ -203,7 +203,7 @@ jabber_si_bytestreams_ibb_timeout_cb(gpointer data) { PurpleXfer *xfer = (PurpleXfer *) data; - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); if (jsx && !jsx->ibb_session) { purple_debug_info("jabber", @@ -218,7 +218,7 @@ static void jabber_si_bytestreams_attempt_connect(PurpleXfer *xfer) { - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); JabberBytestreamsStreamhost *streamhost; JabberID *dstjid; @@ -229,7 +229,7 @@ if(jsx->iq_id) jabber_iq_set_id(iq, jsx->iq_id); - xmlnode_set_attrib(iq->node, "to", xfer->who); + xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer)); error = xmlnode_new_child(iq->node, "error"); xmlnode_set_attrib(error, "code", "404"); xmlnode_set_attrib(error, "type", "cancel"); @@ -271,7 +271,7 @@ purple_proxy_info_destroy(jsx->gpi); jsx->gpi = NULL; - dstjid = jabber_id_new(xfer->who); + dstjid = jabber_id_new(purple_xfer_get_remote_user(xfer)); /* TODO: Deal with zeroconf */ @@ -284,7 +284,7 @@ purple_proxy_info_set_port(jsx->gpi, streamhost->port); /* unknown file transfer type is assumed to be RECEIVE */ - if(xfer->type == PURPLE_XFER_SEND) + if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) dstaddr = g_strdup_printf("%s%s@%s/%s%s@%s/%s", jsx->stream_id, jsx->js->user->node, jsx->js->user->domain, jsx->js->user->resource, dstjid->node, dstjid->domain, dstjid->resource); else @@ -302,7 +302,7 @@ g_free(dstaddr); /* When selecting a streamhost, timeout after STREAMHOST_CONNECT_TIMEOUT seconds, otherwise it takes forever */ - if (xfer->type != PURPLE_XFER_SEND && jsx->connect_data != NULL) + if (purple_xfer_get_type(xfer) != PURPLE_XFER_SEND && jsx->connect_data != NULL) jsx->connect_timeout = purple_timeout_add_seconds( STREAMHOST_CONNECT_TIMEOUT, connect_timeout_cb, xfer); @@ -337,7 +337,7 @@ if(!(xfer = jabber_si_xfer_find(js, sid, from))) return; - jsx = xfer->data; + jsx = purple_xfer_get_protocol_data(xfer); if(!jsx->accepted) return; @@ -375,15 +375,13 @@ PurpleInputCondition cond) { PurpleXfer *xfer = data; - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); int len; len = write(source, jsx->rxqueue + jsx->rxlen, jsx->rxmaxlen - jsx->rxlen); if (len < 0 && errno == EAGAIN) return; else if (len < 0) { - purple_input_remove(xfer->watcher); - xfer->watcher = 0; g_free(jsx->rxqueue); jsx->rxqueue = NULL; close(source); @@ -395,8 +393,8 @@ if (jsx->rxlen < jsx->rxmaxlen) return; - purple_input_remove(xfer->watcher); - xfer->watcher = 0; + purple_input_remove(purple_xfer_get_watcher(xfer)); + purple_xfer_set_watcher(xfer, 0); g_free(jsx->rxqueue); jsx->rxqueue = NULL; @@ -412,7 +410,7 @@ PurpleInputCondition cond) { PurpleXfer *xfer = data; - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); char buffer[42]; /* 40 for DST.ADDR + 2 bytes for port number*/ int len; char *dstaddr, *hash; @@ -426,8 +424,6 @@ if(len < 0 && errno == EAGAIN) return; else if(len <= 0) { - purple_input_remove(xfer->watcher); - xfer->watcher = 0; close(source); purple_xfer_cancel_remote(xfer); return; @@ -441,8 +437,6 @@ purple_debug_info("jabber", "Invalid socks5 conn req. header[0x%x,0x%x,0x%x,0x%x,0x%x]\n", jsx->rxqueue[0], jsx->rxqueue[1], jsx->rxqueue[2], jsx->rxqueue[3], jsx->rxqueue[4]); - purple_input_remove(xfer->watcher); - xfer->watcher = 0; close(source); purple_xfer_cancel_remote(xfer); return; @@ -455,8 +449,6 @@ if(len < 0 && errno == EAGAIN) return; else if(len <= 0) { - purple_input_remove(xfer->watcher); - xfer->watcher = 0; close(source); purple_xfer_cancel_remote(xfer); return; @@ -470,12 +462,12 @@ if(jsx->rxlen - 5 < jsx->rxqueue[4] + 2) return; - purple_input_remove(xfer->watcher); - xfer->watcher = 0; + purple_input_remove(purple_xfer_get_watcher(xfer)); + purple_xfer_set_watcher(xfer, 0); dstaddr = g_strdup_printf("%s%s@%s/%s%s", jsx->stream_id, jsx->js->user->node, jsx->js->user->domain, - jsx->js->user->resource, xfer->who); + jsx->js->user->resource, purple_xfer_get_remote_user(xfer)); /* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */ hash = jabber_calculate_data_hash(dstaddr, strlen(dstaddr), "sha1"); @@ -516,8 +508,8 @@ jsx->rxqueue[5+strlen(host)] = 0x00; jsx->rxqueue[6+strlen(host)] = 0x00; - xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE, - jabber_si_xfer_bytestreams_send_read_again_resp_cb, xfer); + purple_xfer_set_watcher(xfer, purple_input_add(source, PURPLE_INPUT_WRITE, + jabber_si_xfer_bytestreams_send_read_again_resp_cb, xfer)); jabber_si_xfer_bytestreams_send_read_again_resp_cb(xfer, source, PURPLE_INPUT_WRITE); } @@ -527,15 +519,13 @@ PurpleInputCondition cond) { PurpleXfer *xfer = data; - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); int len; len = write(source, jsx->rxqueue + jsx->rxlen, jsx->rxmaxlen - jsx->rxlen); if (len < 0 && errno == EAGAIN) return; else if (len < 0) { - purple_input_remove(xfer->watcher); - xfer->watcher = 0; g_free(jsx->rxqueue); jsx->rxqueue = NULL; close(source); @@ -547,13 +537,11 @@ if (jsx->rxlen < jsx->rxmaxlen) return; - purple_input_remove(xfer->watcher); - xfer->watcher = 0; - /* If we sent a "Success", wait for a response, otherwise give up and cancel */ if (jsx->rxqueue[1] == 0x00) { - xfer->watcher = purple_input_add(source, PURPLE_INPUT_READ, - jabber_si_xfer_bytestreams_send_read_again_cb, xfer); + purple_input_remove(purple_xfer_get_watcher(xfer)); + purple_xfer_set_watcher(xfer, purple_input_add(source, PURPLE_INPUT_READ, + jabber_si_xfer_bytestreams_send_read_again_cb, xfer)); g_free(jsx->rxqueue); jsx->rxqueue = NULL; jsx->rxlen = 0; @@ -568,14 +556,14 @@ PurpleInputCondition cond) { PurpleXfer *xfer = data; - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); int i; int len; char buffer[256]; purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_read_cb\n"); - xfer->fd = source; + purple_xfer_set_fd(xfer, source); /** Try to read the SOCKS5 header */ if(jsx->rxlen < 2) { @@ -584,9 +572,6 @@ if(len < 0 && errno == EAGAIN) return; else if(len <= 0) { - purple_input_remove(xfer->watcher); - xfer->watcher = 0; - close(source); purple_xfer_cancel_remote(xfer); return; } @@ -603,9 +588,6 @@ if(len < 0 && errno == EAGAIN) return; else if(len <= 0) { - purple_input_remove(xfer->watcher); - xfer->watcher = 0; - close(source); purple_xfer_cancel_remote(xfer); return; } @@ -618,13 +600,9 @@ if(jsx->rxlen -2 < jsx->rxqueue[1]) return; - purple_input_remove(xfer->watcher); - xfer->watcher = 0; - purple_debug_info("jabber", "checking to make sure we're socks FIVE\n"); if(jsx->rxqueue[0] != 0x05) { - close(source); purple_xfer_cancel_remote(xfer); return; } @@ -641,9 +619,10 @@ jsx->rxqueue = g_malloc(jsx->rxmaxlen); jsx->rxqueue[0] = 0x05; jsx->rxqueue[1] = 0x00; - xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE, + purple_input_remove(purple_xfer_get_watcher(xfer)); + purple_xfer_set_watcher(xfer, purple_input_add(source, PURPLE_INPUT_WRITE, jabber_si_xfer_bytestreams_send_read_response_cb, - xfer); + xfer)); jabber_si_xfer_bytestreams_send_read_response_cb(xfer, source, PURPLE_INPUT_WRITE); jsx->rxqueue = NULL; @@ -658,8 +637,9 @@ jsx->rxqueue = g_malloc(jsx->rxmaxlen); jsx->rxqueue[0] = 0x05; jsx->rxqueue[1] = 0xFF; - xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE, - jabber_si_xfer_bytestreams_send_read_response_cb, xfer); + purple_input_remove(purple_xfer_get_watcher(xfer)); + purple_xfer_set_watcher(xfer, purple_input_add(source, PURPLE_INPUT_WRITE, + jabber_si_xfer_bytestreams_send_read_response_cb, xfer)); jabber_si_xfer_bytestreams_send_read_response_cb(xfer, source, PURPLE_INPUT_WRITE); } @@ -680,7 +660,7 @@ PurpleInputCondition cond) { PurpleXfer *xfer = data; - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); int acceptfd, flags; purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_connected_cb\n"); @@ -694,7 +674,7 @@ return; } - purple_input_remove(xfer->watcher); + purple_input_remove(purple_xfer_get_watcher(xfer)); close(source); jsx->local_streamhost_fd = -1; @@ -704,8 +684,8 @@ fcntl(acceptfd, F_SETFD, FD_CLOEXEC); #endif - xfer->watcher = purple_input_add(acceptfd, PURPLE_INPUT_READ, - jabber_si_xfer_bytestreams_send_read_cb, xfer); + purple_xfer_set_watcher(xfer, purple_input_add(acceptfd, PURPLE_INPUT_READ, + jabber_si_xfer_bytestreams_send_read_cb, xfer)); } static void @@ -727,12 +707,12 @@ return; } + jsx = purple_xfer_get_protocol_data(xfer); + /* In the case of a direct file transfer, this is expected to return */ - if(!xfer->data) + if(!jsx) return; - jsx = xfer->data; - if(type != JABBER_IQ_RESULT) { purple_debug_info("jabber", "jabber_si_xfer_connect_proxy_cb: type = error\n"); @@ -781,7 +761,7 @@ jsx->js->user->domain, jsx->js->user->resource); if (!strcmp(jid, my_jid)) { purple_debug_info("jabber", "Got local SOCKS5 streamhost-used.\n"); - purple_xfer_start(xfer, xfer->fd, NULL, -1); + purple_xfer_start(xfer, purple_xfer_get_fd(xfer), NULL, -1); } else { /* if available, try to revert to IBB... */ if (jsx->stream_method & STREAM_METHOD_IBB) { @@ -805,9 +785,9 @@ } /* Clean up the local streamhost - it isn't going to be used.*/ - if (xfer->watcher > 0) { - purple_input_remove(xfer->watcher); - xfer->watcher = 0; + if (purple_xfer_get_watcher(xfer) > 0) { + purple_input_remove(purple_xfer_get_watcher(xfer)); + purple_xfer_set_watcher(xfer, 0); } if (jsx->local_streamhost_fd >= 0) { close(jsx->local_streamhost_fd); @@ -835,7 +815,7 @@ JabberBytestreamsStreamhost *sh, *sh2; int streamhost_count = 0; - jsx = xfer->data; + jsx = purple_xfer_get_protocol_data(xfer); jsx->listen_data = NULL; /* I'm not sure under which conditions this can happen @@ -848,7 +828,7 @@ purple_xfer_unref(xfer); iq = jabber_iq_new_query(jsx->js, JABBER_IQ_SET, NS_BYTESTREAMS); - xmlnode_set_attrib(iq->node, "to", xfer->who); + xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer)); query = xmlnode_get_child(iq->node, "query"); xmlnode_set_attrib(query, "sid", jsx->stream_id); @@ -865,8 +845,8 @@ jid = g_strdup_printf("%s@%s/%s", jsx->js->user->node, jsx->js->user->domain, jsx->js->user->resource); - xfer->local_port = purple_network_get_port_from_fd(sock); - g_snprintf(port, sizeof(port), "%hu", xfer->local_port); + purple_xfer_set_local_port(xfer, purple_network_get_port_from_fd(sock)); + g_snprintf(port, sizeof(port), "%hu", purple_xfer_get_local_port(xfer)); public_ip = purple_network_get_my_ip(jsx->js->fd); @@ -896,8 +876,8 @@ g_free(jid); /* The listener for the local proxy */ - xfer->watcher = purple_input_add(sock, PURPLE_INPUT_READ, - jabber_si_xfer_bytestreams_send_connected_cb, xfer); + purple_xfer_set_watcher(xfer, purple_input_add(sock, PURPLE_INPUT_READ, + jabber_si_xfer_bytestreams_send_connected_cb, xfer)); } for (tmp = jsx->js->bs_proxies; tmp; tmp = tmp->next) { @@ -969,7 +949,7 @@ purple_xfer_ref(xfer); - jsx = xfer->data; + jsx = purple_xfer_get_protocol_data(xfer); /* TODO: This should probably be done with an account option instead of * piggy-backing on the TOR proxy type. */ @@ -979,7 +959,7 @@ purple_debug_info("jabber", "Skipping attempting local streamhost.\n"); jsx->listen_data = NULL; } else - jsx->listen_data = purple_network_listen_range(0, 0, SOCK_STREAM, + jsx->listen_data = purple_network_listen_range(0, 0, AF_UNSPEC, SOCK_STREAM, TRUE, jabber_si_xfer_bytestreams_listen_cb, xfer); if (jsx->listen_data == NULL) { @@ -1017,7 +997,7 @@ gsize size) { PurpleXfer *xfer = (PurpleXfer *) jabber_ibb_session_get_user_data(sess); - JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); if (size <= purple_xfer_get_bytes_remaining(xfer)) { purple_debug_info("jabber", "about to write %" G_GSIZE_FORMAT " bytes from IBB stream\n", @@ -1037,7 +1017,7 @@ static gssize jabber_si_xfer_ibb_read(guchar **out_buffer, PurpleXfer *xfer) { - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); guchar *buffer; gsize size; gsize tmp; @@ -1060,7 +1040,7 @@ const gchar *sid = xmlnode_get_attrib(open, "sid"); PurpleXfer *xfer = jabber_si_xfer_find(js, sid, who); if (xfer) { - JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); JabberIBBSession *sess = jabber_ibb_session_create_from_xmlnode(js, who, id, open, xfer); @@ -1105,7 +1085,7 @@ static gssize jabber_si_xfer_ibb_write(const guchar *buffer, size_t len, PurpleXfer *xfer) { - JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); JabberIBBSession *sess = jsx->ibb_session; gsize packet_size = len < jabber_ibb_session_get_max_data_size(sess) ? len : jabber_ibb_session_get_max_data_size(sess); @@ -1119,7 +1099,7 @@ jabber_si_xfer_ibb_sent_cb(JabberIBBSession *sess) { PurpleXfer *xfer = (PurpleXfer *) jabber_ibb_session_get_user_data(sess); - gsize remaining = purple_xfer_get_bytes_remaining(xfer); + goffset remaining = purple_xfer_get_bytes_remaining(xfer); if (remaining == 0) { /* close the session */ @@ -1149,7 +1129,7 @@ static void jabber_si_xfer_ibb_send_init(JabberStream *js, PurpleXfer *xfer) { - JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); jsx->ibb_session = jabber_ibb_session_create(js, jsx->stream_id, purple_xfer_get_remote_user(xfer), xfer); @@ -1206,7 +1186,7 @@ for(field = xmlnode_get_child(x, "field"); field; field = xmlnode_get_next_twin(field)) { const char *var = xmlnode_get_attrib(field, "var"); - JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); if(var && !strcmp(var, "stream-method")) { if((value = xmlnode_get_child(field, "value"))) { @@ -1237,7 +1217,7 @@ static void jabber_si_xfer_send_request(PurpleXfer *xfer) { - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); JabberIq *iq; xmlnode *si, *file, *feature, *x, *field, *option, *value; char buf[32]; @@ -1247,10 +1227,10 @@ purple_xfer_prepare_thumbnail(xfer, "jpeg,png"); #endif - xfer->filename = g_path_get_basename(xfer->local_filename); + purple_xfer_set_filename(xfer, g_path_get_basename(purple_xfer_get_local_filename(xfer))); iq = jabber_iq_new(jsx->js, JABBER_IQ_SET); - xmlnode_set_attrib(iq->node, "to", xfer->who); + xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer)); si = xmlnode_new_child(iq->node, "si"); xmlnode_set_namespace(si, "http://jabber.org/protocol/si"); jsx->stream_id = jabber_get_next_id(jsx->js); @@ -1259,8 +1239,8 @@ file = xmlnode_new_child(si, "file"); xmlnode_set_namespace(file, NS_SI_FILE_TRANSFER); - xmlnode_set_attrib(file, "name", xfer->filename); - g_snprintf(buf, sizeof(buf), "%" G_GSIZE_FORMAT, xfer->size); + xmlnode_set_attrib(file, "name", purple_xfer_get_filename(xfer)); + g_snprintf(buf, sizeof(buf), "%" G_GOFFSET_FORMAT, purple_xfer_get_size(xfer)); xmlnode_set_attrib(file, "size", buf); /* maybe later we'll do hash and date attribs */ @@ -1309,7 +1289,7 @@ static void jabber_si_xfer_free(PurpleXfer *xfer) { - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); if (jsx) { JabberStream *js = jsx->js; @@ -1324,10 +1304,9 @@ jabber_iq_remove_callback_by_id(js, jsx->iq_id); if (jsx->local_streamhost_fd >= 0) close(jsx->local_streamhost_fd); - if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && - xfer->fd >= 0) { + if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && purple_xfer_get_fd(xfer) >= 0) { purple_debug_info("jabber", "remove port mapping\n"); - purple_network_remove_port_mapping(xfer->fd); + purple_network_remove_port_mapping(purple_xfer_get_fd(xfer)); } if (jsx->connect_timeout > 0) purple_timeout_remove(jsx->connect_timeout); @@ -1356,7 +1335,7 @@ /* XXX: free other stuff */ g_free(jsx->rxqueue); g_free(jsx); - xfer->data = NULL; + purple_xfer_set_protocol_data(xfer, NULL); } } @@ -1367,7 +1346,7 @@ */ static void jabber_si_xfer_cancel_send(PurpleXfer *xfer) { - JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); /* if there is an IBB session active, send close on that */ if (jsx->ibb_session) { @@ -1380,7 +1359,7 @@ static void jabber_si_xfer_request_denied(PurpleXfer *xfer) { - JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); JabberStream *js = jsx->js; /* @@ -1391,7 +1370,7 @@ JabberIq *iq; xmlnode *error, *child; iq = jabber_iq_new(js, JABBER_IQ_ERROR); - xmlnode_set_attrib(iq->node, "to", xfer->who); + xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer)); jabber_iq_set_id(iq, jsx->iq_id); error = xmlnode_new_child(iq->node, "error"); @@ -1412,7 +1391,7 @@ static void jabber_si_xfer_cancel_recv(PurpleXfer *xfer) { - JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); /* if there is an IBB session active, send close */ if (jsx->ibb_session) { jabber_ibb_session_close(jsx->ibb_session); @@ -1432,7 +1411,7 @@ JabberCapabilities capabilities, gpointer data) { PurpleXfer *xfer = (PurpleXfer *) data; - JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); if (capabilities & JABBER_CAP_IBB) { purple_debug_info("jabber", @@ -1458,8 +1437,8 @@ static void do_transfer_send(PurpleXfer *xfer, const char *resource) { - JabberSIXfer *jsx = xfer->data; - char **who_v = g_strsplit(xfer->who, "/", 2); + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); + char **who_v = g_strsplit(purple_xfer_get_remote_user(xfer), "/", 2); char *who; JabberBuddy *jb; JabberBuddyResource *jbr = NULL; @@ -1508,7 +1487,7 @@ static void jabber_si_xfer_init(PurpleXfer *xfer) { - JabberSIXfer *jsx = xfer->data; + JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer); JabberIq *iq; if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) { JabberBuddy *jb; @@ -1516,7 +1495,7 @@ char *resource; GList *resources = NULL; - if(NULL != (resource = jabber_get_resource(xfer->who))) { + if(NULL != (resource = jabber_get_resource(purple_xfer_get_remote_user(xfer)))) { /* they've specified a resource, no need to ask or * default or anything, just do it */ @@ -1525,7 +1504,7 @@ return; } - jb = jabber_buddy_find(jsx->js, xfer->who, TRUE); + jb = jabber_buddy_find(jsx->js, purple_xfer_get_remote_user(xfer), TRUE); if (jb) { GList *l; @@ -1549,11 +1528,11 @@ char *msg; if(!jb) { - msg = g_strdup_printf(_("Unable to send file to %s, invalid JID"), xfer->who); + msg = g_strdup_printf(_("Unable to send file to %s, invalid JID"), purple_xfer_get_remote_user(xfer)); } else if(jb->subscription & JABBER_SUB_TO) { - msg = g_strdup_printf(_("Unable to send file to %s, user is not online"), xfer->who); + msg = g_strdup_printf(_("Unable to send file to %s, user is not online"), purple_xfer_get_remote_user(xfer)); } else { - msg = g_strdup_printf(_("Unable to send file to %s, not subscribed to user presence"), xfer->who); + msg = g_strdup_printf(_("Unable to send file to %s, not subscribed to user presence"), purple_xfer_get_remote_user(xfer)); } purple_notify_error(jsx->js->gc, _("File Send Failed"), _("File Send Failed"), msg); @@ -1566,7 +1545,7 @@ } else { /* we've got multiple resources, we need to pick one to send to */ GList *l; - char *msg = g_strdup_printf(_("Please select the resource of %s to which you would like to send a file"), xfer->who); + char *msg = g_strdup_printf(_("Please select the resource of %s to which you would like to send a file"), purple_xfer_get_remote_user(xfer)); PurpleRequestFields *fields = purple_request_fields_new(); PurpleRequestField *field = purple_request_field_choice_new("resource", _("Resource"), 0); PurpleRequestFieldGroup *group = purple_request_field_group_new(NULL); @@ -1582,7 +1561,7 @@ purple_request_fields(jsx->js->gc, _("Select a Resource"), msg, NULL, fields, _("Send File"), G_CALLBACK(resource_select_ok_cb), _("Cancel"), G_CALLBACK(resource_select_cancel_cb), - jsx->js->gc->account, xfer->who, NULL, xfer); + purple_connection_get_account(jsx->js->gc), purple_xfer_get_remote_user(xfer), NULL, xfer); g_free(msg); } @@ -1592,7 +1571,7 @@ xmlnode *si, *feature, *x, *field, *value; iq = jabber_iq_new(jsx->js, JABBER_IQ_RESULT); - xmlnode_set_attrib(iq->node, "to", xfer->who); + xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer)); if(jsx->iq_id) jabber_iq_set_id(iq, jsx->iq_id); else @@ -1636,12 +1615,13 @@ PurpleXfer *xfer; JabberSIXfer *jsx; - js = gc->proto_data; + js = purple_connection_get_protocol_data(gc); - xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who); + xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_SEND, who); if (xfer) { - xfer->data = jsx = g_new0(JabberSIXfer, 1); + jsx = g_new0(JabberSIXfer, 1); + purple_xfer_set_protocol_data(xfer, jsx); jsx->js = js; jsx->local_streamhost_fd = -1; @@ -1696,8 +1676,7 @@ xmlnode *thumbnail; #endif const char *stream_id, *filename, *filesize_c, *profile; - guint64 filesize_64 = 0; - size_t filesize = 0; + goffset filesize = 0; if(!(profile = xmlnode_get_attrib(si, "profile")) || strcmp(profile, NS_SI_FILE_TRANSFER)) @@ -1713,17 +1692,7 @@ return; if((filesize_c = xmlnode_get_attrib(file, "size"))) - filesize_64 = g_ascii_strtoull(filesize_c, NULL, 10); - /* TODO 3.0.0: When the core uses a guint64, this is redundant. - * See #8477. - */ - if (filesize_64 > G_MAXSIZE) { - /* Should this pop up a warning? */ - purple_debug_warning("jabber", "Unable to transfer file (too large)" - " -- see #8477 for more details."); - return; - } - filesize = filesize_64; + filesize = g_ascii_strtoull(filesize_c, NULL, 10); if(!(feature = xmlnode_get_child(si, "feature"))) return; @@ -1774,10 +1743,10 @@ jsx->stream_id = g_strdup(stream_id); jsx->iq_id = g_strdup(id); - xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE, from); + xfer = purple_xfer_new(purple_connection_get_account(js->gc), PURPLE_XFER_RECEIVE, from); g_return_if_fail(xfer != NULL); - xfer->data = jsx; + purple_xfer_set_protocol_data(xfer, jsx); purple_xfer_set_filename(xfer, filename); if(filesize > 0) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/useravatar.c --- a/libpurple/protocols/jabber/useravatar.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/useravatar.c Fri Apr 06 04:30:00 2012 +0000 @@ -377,7 +377,7 @@ JabberBuddyAvatarUpdateURLInfo *info = g_new0(JabberBuddyAvatarUpdateURLInfo, 1); info->js = js; - url_data = purple_util_fetch_url_len(url, TRUE, NULL, TRUE, + url_data = purple_util_fetch_url(url, TRUE, NULL, TRUE, MAX_HTTP_BUDDYICON_BYTES, do_buddy_avatar_update_fromurl, info); if (url_data) { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/usermood.c --- a/libpurple/protocols/jabber/usermood.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/usermood.c Fri Apr 06 04:30:00 2012 +0000 @@ -155,12 +155,12 @@ break; } if (newmood != NULL) { - purple_prpl_got_user_status(js->gc->account, from, "mood", + purple_prpl_got_user_status(purple_connection_get_account(js->gc), from, "mood", PURPLE_MOOD_NAME, newmood, PURPLE_MOOD_COMMENT, moodtext, NULL); } else { - purple_prpl_got_user_status_deactive(js->gc->account, from, "mood"); + purple_prpl_got_user_status_deactive(purple_connection_get_account(js->gc), from, "mood"); } g_free(moodtext); } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/jabber/usertune.c --- a/libpurple/protocols/jabber/usertune.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/jabber/usertune.c Fri Apr 06 04:30:00 2012 +0000 @@ -92,7 +92,7 @@ } if (valid) { - purple_prpl_got_user_status(js->gc->account, from, "tune", + purple_prpl_got_user_status(purple_connection_get_account(js->gc), from, "tune", PURPLE_TUNE_ARTIST, tuneinfodata.artist, PURPLE_TUNE_TITLE, tuneinfodata.title, PURPLE_TUNE_ALBUM, tuneinfodata.album, @@ -100,7 +100,7 @@ PURPLE_TUNE_TIME, tuneinfodata.time, PURPLE_TUNE_URL, tuneinfodata.url, NULL); } else { - purple_prpl_got_user_status_deactive(js->gc->account, from, "tune"); + purple_prpl_got_user_status_deactive(purple_connection_get_account(js->gc), from, "tune"); } g_free(tuneinfodata.artist); @@ -117,7 +117,7 @@ void jabber_tune_set(PurpleConnection *gc, const PurpleJabberTuneInfo *tuneinfo) { xmlnode *publish, *tunenode; - JabberStream *js = gc->proto_data; + JabberStream *js = purple_connection_get_protocol_data(gc); publish = xmlnode_new("publish"); xmlnode_set_attrib(publish,"node","http://jabber.org/protocol/tune"); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/contact.c --- a/libpurple/protocols/msn/contact.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/contact.c Fri Apr 06 04:30:00 2012 +0000 @@ -740,6 +740,20 @@ } passportName = xmlnode_get_child(contactInfo, "passportName"); + if (passportName != NULL) { + xmlnode *messenger_user; + /* ignore non-messenger contacts */ + if ((messenger_user = xmlnode_get_child(contactInfo, "isMessengerUser"))) { + char *is_messenger_user = xmlnode_get_data(messenger_user); + + if (is_messenger_user && !strcmp(is_messenger_user, "false")) { + passportName = NULL; + } + + g_free(is_messenger_user); + } + } + if (passportName == NULL) { xmlnode *emailsNode, *contactEmailNode, *emailNode; xmlnode *messengerEnabledNode; @@ -773,19 +787,6 @@ } } } else { - xmlnode *messenger_user; - /* ignore non-messenger contacts */ - if ((messenger_user = xmlnode_get_child(contactInfo, "isMessengerUser"))) { - char *is_messenger_user = xmlnode_get_data(messenger_user); - - if (is_messenger_user && !strcmp(is_messenger_user, "false")) { - g_free(is_messenger_user); - continue; - } - - g_free(is_messenger_user); - } - passport = xmlnode_get_data(passportName); } @@ -989,7 +990,7 @@ purple_debug_misc("msn", "Got the Address Book!\n"); if (msn_parse_addressbook(session, resp->xml)) { - msn_send_privacy(session->account->gc); + msn_send_privacy(purple_account_get_connection(session->account)); msn_notification_dump_contact(session); } else { /* This is making us loop infinitely when we fail to parse the @@ -1272,7 +1273,7 @@ body = g_markup_escape_text(user->invite_message, -1); /* Ignore the cast, we treat it as const anyway. */ - tmp = (char *)purple_connection_get_display_name(session->account->gc); + tmp = (char *)purple_connection_get_display_name(purple_account_get_connection(session->account)); tmp = tmp ? g_markup_escape_text(tmp, -1) : g_strdup(""); invite = g_strdup_printf(MSN_CONTACT_INVITE_MESSAGE_XML, body, tmp); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/error.c --- a/libpurple/protocols/msn/error.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/error.c Fri Apr 06 04:30:00 2012 +0000 @@ -274,7 +274,7 @@ if (debug) purple_debug_warning("msn", "error %d: %s\n", type, buf); else - purple_notify_error(session->account->gc, NULL, buf, NULL); + purple_notify_error(purple_account_get_connection(session->account), NULL, buf, NULL); g_free(buf); } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/httpconn.c --- a/libpurple/protocols/msn/httpconn.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/httpconn.c Fri Apr 06 04:30:00 2012 +0000 @@ -285,8 +285,10 @@ httpconn = data; servconn = httpconn->servconn; - if (servconn->type == MSN_SERVCONN_NS) - servconn->session->account->gc->last_received = time(NULL); + if (servconn->type == MSN_SERVCONN_NS) { + PurpleConnection *gc = purple_account_get_connection(servconn->session->account); + purple_connection_update_last_received(gc); + } len = read(httpconn->fd, buf, sizeof(buf) - 1); if (len < 0 && errno == EAGAIN) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/msg.c --- a/libpurple/protocols/msn/msg.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/msg.c Fri Apr 06 04:30:00 2012 +0000 @@ -627,7 +627,7 @@ const char *passport; const char *value; - gc = cmdproc->session->account->gc; + gc = purple_account_get_connection(cmdproc->session->account); body = msn_message_get_bin_data(msg, &body_len); body_enc = g_markup_escape_text(body, body_len); @@ -688,7 +688,7 @@ swboard->flag |= MSN_SB_FLAG_IM; } } - else if (!g_str_equal(passport, purple_account_get_username(gc->account))) + else if (!g_str_equal(passport, purple_account_get_username(purple_connection_get_account(gc)))) { /* Don't im ourselves ... */ serv_got_im(gc, passport, body_final, 0, time(NULL)); @@ -713,7 +713,7 @@ PurpleConnection *gc; char *passport; - gc = cmdproc->session->account->gc; + gc = purple_account_get_connection(cmdproc->session->account); passport = msg->remote_user; if (msn_message_get_header_value(msg, "TypingUser") == NULL) @@ -762,7 +762,7 @@ if (swboard->conv == NULL) { if (chat) - swboard->conv = purple_find_chat(account->gc, swboard->chat_id); + swboard->conv = purple_find_chat(purple_account_get_connection(account), swboard->chat_id); else { swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, account); @@ -970,7 +970,7 @@ msn_slplink_request_object(slplink, smile, got_emoticon, NULL, obj); } - msn_object_destroy(obj); + msn_object_destroy(obj, FALSE); obj = NULL; who = NULL; sha1 = NULL; @@ -991,21 +991,23 @@ /* Nudge */ PurpleAccount *account; const char *user; + PurpleConnection *gc; account = cmdproc->session->account; user = msg->remote_user; + gc = purple_account_get_connection(account); if (cmdproc->servconn->type == MSN_SERVCONN_SB) { MsnSwitchBoard *swboard = cmdproc->data; if (swboard->current_users > 1 || ((swboard->conv != NULL) && purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT)) - purple_prpl_got_attention_in_chat(account->gc, swboard->chat_id, user, MSN_NUDGE); + purple_prpl_got_attention_in_chat(gc, swboard->chat_id, user, MSN_NUDGE); else - purple_prpl_got_attention(account->gc, user, MSN_NUDGE); + purple_prpl_got_attention(gc, user, MSN_NUDGE); } else { - purple_prpl_got_attention(account->gc, user, MSN_NUDGE); + purple_prpl_got_attention(gc, user, MSN_NUDGE); } } else if (!strcmp(id, "2")) { @@ -1025,7 +1027,7 @@ slplink = msn_session_get_slplink(session, who); msn_slplink_request_object(slplink, data, got_wink_cb, NULL, obj); - msn_object_destroy(obj); + msn_object_destroy(obj, FALSE); } else if (!strcmp(id, "3")) { @@ -1045,7 +1047,7 @@ slplink = msn_session_get_slplink(session, who); msn_slplink_request_object(slplink, data, got_voiceclip_cb, NULL, obj); - msn_object_destroy(obj); + msn_object_destroy(obj, FALSE); } else if (!strcmp(id, "4")) { /* Action */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/msn.c --- a/libpurple/protocols/msn/msn.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/msn.c Fri Apr 06 04:30:00 2012 +0000 @@ -119,7 +119,7 @@ MsnSwitchBoard *swboard; msg = msn_message_new_nudge(); - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); swboard = msn_session_get_swboard(session, username, MSN_SB_FLAG_IM); msn_switchboard_send_msg(swboard, msg, TRUE); @@ -326,7 +326,7 @@ MsnSession *session; MsnTransaction *trans; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); cmdproc = session->notification->cmdproc; if (entry == NULL || *entry == '\0') @@ -384,7 +384,7 @@ const char *mobile_number = NULL; gsize payload_len; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); cmdproc = session->notification->cmdproc; page = msn_page_new(); @@ -647,7 +647,7 @@ MsnSession *session; gc = (PurpleConnection *) action->context; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); purple_request_input(gc, NULL, _("Set your home phone number."), NULL, msn_user_get_home_phone(session->user), FALSE, FALSE, NULL, @@ -664,7 +664,7 @@ MsnSession *session; gc = (PurpleConnection *) action->context; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); purple_request_input(gc, NULL, _("Set your work phone number."), NULL, msn_user_get_work_phone(session->user), FALSE, FALSE, NULL, @@ -681,7 +681,7 @@ MsnSession *session; gc = (PurpleConnection *) action->context; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); purple_request_input(gc, NULL, _("Set your mobile phone number."), NULL, msn_user_get_mobile_phone(session->user), FALSE, FALSE, NULL, @@ -719,7 +719,7 @@ MsnSession *session; char *title; - session = pc->proto_data; + session = purple_connection_get_protocol_data(pc); title = g_strdup_printf(_("Blocked Text for %s"), session->account->username); if (session->blocked_text == NULL) { @@ -743,7 +743,7 @@ MsnSession *session; gc = (PurpleConnection *) action->context; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); if (!session->passport_info.email_enabled) { purple_notify_error(gc, NULL, @@ -810,11 +810,11 @@ MsnTransaction *trans; account = purple_connection_get_account(gc); - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); cmdproc = session->notification->cmdproc; - if (account->perm_deny == PURPLE_PRIVACY_ALLOW_ALL || - account->perm_deny == PURPLE_PRIVACY_DENY_USERS) + if (purple_account_get_privacy_type(account) == PURPLE_PRIVACY_ALLOW_ALL || + purple_account_get_privacy_type(account) == PURPLE_PRIVACY_DENY_USERS) trans = msn_transaction_new(cmdproc, "BLP", "%s", "AL"); else trans = msn_transaction_new(cmdproc, "BLP", "%s", "BL"); @@ -840,7 +840,7 @@ account = purple_buddy_get_account(buddy); gc = purple_account_get_connection(account); - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); swboard = msn_switchboard_new(session); msn_switchboard_request(swboard); @@ -869,7 +869,7 @@ static void t_msn_xfer_cancel_send(PurpleXfer *xfer) { - MsnSlpLink *slplink = xfer->data; + MsnSlpLink *slplink = purple_xfer_get_protocol_data(xfer); msn_slplink_unref(slplink); } @@ -879,13 +879,13 @@ MsnSession *session; PurpleXfer *xfer; - session = gc->proto_data; - - xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who); + session = purple_connection_get_protocol_data(gc); + + xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_SEND, who); g_return_val_if_fail(xfer != NULL, NULL); - xfer->data = msn_slplink_ref(msn_session_get_slplink(session, who)); + purple_xfer_set_protocol_data(xfer, msn_slplink_ref(msn_session_get_slplink(session, who))); purple_xfer_set_init_fnc(xfer, t_msn_xfer_init); purple_xfer_set_cancel_send_fnc(xfer, t_msn_xfer_cancel_send); @@ -918,7 +918,7 @@ g_free(normal); if (ret) { - MsnSession *session = gc->proto_data; + MsnSession *session = purple_connection_get_protocol_data(gc); if (session) { MsnUser *user = msn_userlist_find_user(session->userlist, who); if (user) { @@ -1078,7 +1078,7 @@ if (psm != NULL && *psm) { purple_notify_user_info_add_pair_plaintext(user_info, tmp2, psm); } else { - purple_notify_user_info_add_pair(user_info, _("Status"), tmp2); + purple_notify_user_info_add_pair_html(user_info, _("Status"), tmp2); } g_free(tmp2); @@ -1091,17 +1091,17 @@ } } else { if (purple_presence_is_idle(presence)) { - purple_notify_user_info_add_pair(user_info, _("Status"), - _("Idle")); + purple_notify_user_info_add_pair_plaintext(user_info, + _("Status"), _("Idle")); } else { - purple_notify_user_info_add_pair(user_info, _("Status"), - purple_status_get_name(status)); + purple_notify_user_info_add_pair_plaintext(user_info, + _("Status"), purple_status_get_name(status)); } } } if (currentmedia) { - purple_notify_user_info_add_pair(user_info, mediatype, currentmedia); + purple_notify_user_info_add_pair_html(user_info, mediatype, currentmedia); g_free(currentmedia); } } @@ -1119,23 +1119,26 @@ { const char *phone; - purple_notify_user_info_add_pair(user_info, _("Has you"), + purple_notify_user_info_add_pair_plaintext(user_info, _("Has you"), ((user->list_op & (1 << MSN_LIST_RL)) ? _("Yes") : _("No"))); - purple_notify_user_info_add_pair(user_info, _("Blocked"), + purple_notify_user_info_add_pair_plaintext(user_info, _("Blocked"), ((user->list_op & (1 << MSN_LIST_BL)) ? _("Yes") : _("No"))); phone = msn_user_get_home_phone(user); - if (phone != NULL) - purple_notify_user_info_add_pair(user_info, _("Home Phone Number"), phone); + if (phone != NULL) { + purple_notify_user_info_add_pair_plaintext(user_info, _("Home Phone Number"), phone); + } phone = msn_user_get_work_phone(user); - if (phone != NULL) - purple_notify_user_info_add_pair(user_info, _("Work Phone Number"), phone); + if (phone != NULL) { + purple_notify_user_info_add_pair_plaintext(user_info, _("Work Phone Number"), phone); + } phone = msn_user_get_mobile_phone(user); - if (phone != NULL) - purple_notify_user_info_add_pair(user_info, _("Mobile Phone Number"), phone); + if (phone != NULL) { + purple_notify_user_info_add_pair_plaintext(user_info, _("Mobile Phone Number"), phone); + } } } @@ -1213,7 +1216,7 @@ PurplePluginAction *act; gc = (PurpleConnection *) context; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); act = purple_plugin_action_new(_("Set Friendly Name..."), msn_show_set_friendly_name); @@ -1333,7 +1336,7 @@ if (!purple_ssl_is_supported()) { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("SSL support is needed for MSN. Please install a supported " "SSL library.")); @@ -1350,9 +1353,10 @@ session = msn_session_new(account); - gc->proto_data = session; - gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_FORMATTING_WBFO | PURPLE_CONNECTION_NO_BGCOLOR | - PURPLE_CONNECTION_NO_FONTSIZE | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY; + purple_connection_set_protocol_data(gc, session); + purple_connection_set_flags(gc, + PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_FORMATTING_WBFO | PURPLE_CONNECTION_NO_BGCOLOR | + PURPLE_CONNECTION_NO_FONTSIZE | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY); msn_session_set_login_step(session, MSN_LOGIN_STEP_START); @@ -1374,7 +1378,7 @@ } if (!msn_session_connect(session, host, port, http_method)) - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); } @@ -1384,13 +1388,13 @@ { MsnSession *session; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); g_return_if_fail(session != NULL); msn_session_destroy(session); - gc->proto_data = NULL; + purple_connection_set_protocol_data(gc, NULL); } static gboolean @@ -1450,7 +1454,7 @@ static void msn_emoticon_destroy(MsnEmoticon *emoticon) { if (emoticon->obj) - msn_object_destroy(emoticon->obj); + msn_object_destroy(emoticon->obj, FALSE); g_free(emoticon->smile); g_free(emoticon); } @@ -1523,7 +1527,7 @@ PurpleMessageFlags flags) { PurpleAccount *account; - PurpleBuddy *buddy = purple_find_buddy(gc->account, who); + PurpleBuddy *buddy = purple_find_buddy(purple_connection_get_account(gc), who); MsnSession *session; MsnSwitchBoard *swboard; MsnMessage *msg; @@ -1536,7 +1540,7 @@ account = purple_connection_get_account(gc); username = purple_account_get_username(account); - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); swboard = msn_session_find_swboard(session, who); if (!strncmp("tel:+", who, 5)) { @@ -1642,7 +1646,7 @@ MsnMessage *msg; account = purple_connection_get_account(gc); - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); /* * TODO: I feel like this should be "if (state != PURPLE_TYPING)" @@ -1691,7 +1695,7 @@ if (gc != NULL) { - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); msn_change_status(session); } } @@ -1701,7 +1705,7 @@ { MsnSession *session; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); msn_change_status(session); } @@ -1831,7 +1835,7 @@ MsnSession *session; MsnUserList *userlist; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); userlist = session->userlist; if (!session->logged_in) @@ -1848,7 +1852,7 @@ MsnUserList *userlist; MsnUser *user; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); userlist = session->userlist; user = msn_userlist_find_user(userlist, who); @@ -1876,7 +1880,7 @@ MsnUserList *userlist; MsnUser *user; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); userlist = session->userlist; user = msn_userlist_find_user(userlist, who); @@ -1903,7 +1907,7 @@ MsnUserList *userlist; MsnUser *user; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); userlist = session->userlist; if (!session->logged_in) @@ -1926,7 +1930,7 @@ MsnUserList *userlist; MsnUser *user; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); userlist = session->userlist; if (!session->logged_in) @@ -1955,7 +1959,7 @@ MsnSession *session; MsnSwitchBoard *swboard; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); swboard = msn_session_find_swboard_with_id(session, id); @@ -1980,7 +1984,7 @@ MsnSwitchBoard *swboard; PurpleConversation *conv; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); swboard = msn_session_find_swboard_with_id(session, id); @@ -2017,7 +2021,7 @@ GString *emoticons = NULL; account = purple_connection_get_account(gc); - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); username = purple_account_get_username(account); swboard = msn_session_find_swboard_with_id(session, id); @@ -2083,7 +2087,7 @@ MsnSession *session; MsnTransaction *trans; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); if (!session->http_method) { @@ -2101,7 +2105,7 @@ { MsnSession *session; - session = pc->proto_data; + session = purple_connection_get_protocol_data(pc); msn_update_contact(session, name, MSN_UPDATE_ALIAS, alias); } @@ -2113,7 +2117,7 @@ MsnSession *session; MsnUserList *userlist; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); userlist = session->userlist; msn_userlist_move_buddy(userlist, who, old_group_name, new_group_name); @@ -2126,7 +2130,7 @@ MsnSession *session; const char *gname; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); g_return_if_fail(session != NULL); g_return_if_fail(session->userlist != NULL); @@ -2150,7 +2154,7 @@ MsnSwitchBoard *swboard; PurpleConversation *conv; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); swboard = msn_session_find_swboard(session, who); @@ -2186,7 +2190,7 @@ MsnSession *session; MsnUser *user; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); user = session->user; msn_user_set_buddy_icon(user, img); @@ -2200,7 +2204,7 @@ MsnSession *session; const char *gname; - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); gname = purple_group_get_name(group); purple_debug_info("msn", "Remove group %s\n", gname); @@ -2241,7 +2245,7 @@ { char *nicktext = g_markup_escape_text(alias, -1); tmp = g_strdup_printf("%s", nicktext); - purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp); + purple_notify_user_info_add_pair_html(user_info, _("Nickname"), tmp); g_free(tmp); g_free(nicktext); } @@ -2340,7 +2344,7 @@ if (error_message != NULL || url_text == NULL || strcmp(url_text, "") == 0) { - purple_notify_user_info_add_pair(user_info, + purple_notify_user_info_add_pair_html(user_info, _("Error retrieving profile"), NULL); purple_notify_userinfo(info_data->gc, info_data->name, user_info, NULL, NULL); @@ -2659,7 +2663,7 @@ if (user_url != NULL) { tmp = g_strdup_printf("%s", user_url, user_url); - purple_notify_user_info_add_pair(user_info, _("Homepage"), tmp); + purple_notify_user_info_add_pair_html(user_info, _("Homepage"), tmp); g_free(tmp); g_free(user_url); @@ -2682,9 +2686,9 @@ char *p = strstr(url_buffer, "
gc), info_data->name); - purple_notify_user_info_add_pair(user_info, + purple_notify_user_info_add_pair_html(user_info, _("Error retrieving profile"), NULL); - purple_notify_user_info_add_pair(user_info, NULL, + purple_notify_user_info_add_pair_plaintext(user_info, NULL, ((p && b) ? _("The user has not created a public profile.") : (p ? _("MSN reported not being able to find the user's profile. " "This either means that the user does not exist, " @@ -2699,7 +2703,7 @@ purple_notify_user_info_add_section_break(user_info); tmp = g_strdup_printf("%s", PROFILE_URL, info_data->name, _("View web profile")); - purple_notify_user_info_add_pair(user_info, NULL, tmp); + purple_notify_user_info_add_pair_html(user_info, NULL, tmp); g_free(tmp); #if PHOTO_SUPPORT @@ -2718,7 +2722,7 @@ /* Try to put the photo in there too, if there's one */ if (photo_url_text) { - url_data = purple_util_fetch_url_len(photo_url_text, FALSE, NULL, FALSE, + url_data = purple_util_fetch_url(photo_url_text, FALSE, NULL, FALSE, MAX_HTTP_BUDDYICON_BYTES, msn_got_photo, info2_data); session->url_datas = g_slist_prepend(session->url_datas, url_data); @@ -2780,7 +2784,7 @@ purple_debug_info("msn", "%s is %" G_GSIZE_FORMAT " bytes\n", photo_url_text, len); id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL); g_snprintf(buf, sizeof(buf), "
", id); - purple_notify_user_info_prepend_pair(user_info, NULL, buf); + purple_notify_user_info_prepend_pair_html(user_info, NULL, buf); } } @@ -2817,7 +2821,7 @@ url_data = purple_util_fetch_url(url, FALSE, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)", - TRUE, msn_got_info, data); + TRUE, -1, msn_got_info, data); session->url_datas = g_slist_prepend(session->url_datas, url_data); g_free(url); @@ -2906,6 +2910,7 @@ static PurplePluginProtocolInfo prpl_info = { + sizeof(PurplePluginProtocolInfo), /* struct_size */ OPT_PROTO_MAIL_CHECK|OPT_PROTO_INVITE_MESSAGE, NULL, /* user_splits */ NULL, /* protocol_options */ @@ -2927,7 +2932,7 @@ msn_set_status, /* set_away */ msn_set_idle, /* set_idle */ NULL, /* change_passwd */ - NULL, /* add_buddy */ + msn_add_buddy, /* add_buddy */ NULL, /* add_buddies */ msn_rem_buddy, /* remove_buddy */ NULL, /* remove_buddies */ @@ -2946,7 +2951,6 @@ msn_keepalive, /* keepalive */ NULL, /* register_user */ NULL, /* get_cb_info */ - NULL, /* get_cb_away */ msn_alias_buddy, /* alias_buddy */ msn_group_buddy, /* group_buddy */ msn_rename_group, /* rename_group */ @@ -2971,15 +2975,12 @@ NULL, /* unregister_user */ msn_send_attention, /* send_attention */ msn_attention_types, /* attention_types */ - sizeof(PurplePluginProtocolInfo), /* struct_size */ msn_get_account_text_table, /* get_account_text_table */ NULL, /* initiate_media */ NULL, /* get_media_caps */ NULL, /* get_moods */ msn_set_public_alias, /* set_public_alias */ - msn_get_public_alias, /* get_public_alias */ - msn_add_buddy, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ + msn_get_public_alias /* get_public_alias */ }; static PurplePluginInfo info = diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/nexus.c --- a/libpurple/protocols/msn/nexus.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/nexus.c Fri Apr 06 04:30:00 2012 +0000 @@ -389,7 +389,7 @@ msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE); username = purple_account_get_username(session->account); - password = purple_connection_get_password(session->account->gc); + password = purple_connection_get_password(purple_account_get_connection(session->account)); if (g_utf8_strlen(password, -1) > 16) { /* max byte size for 16 utf8 characters is 64 + 1 for the null */ gchar truncated[65]; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/notification.c --- a/libpurple/protocols/msn/notification.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/notification.c Fri Apr 06 04:30:00 2012 +0000 @@ -1203,7 +1203,7 @@ if (id && strcmp(id, "1")) { PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, - who, gc->account); + who, purple_connection_get_account(gc)); if (conv != NULL) { const char *error; if (!strcmp(id, "407")) @@ -1402,7 +1402,7 @@ session = cmdproc->session; account = session->account; - gc = account->gc; + gc = purple_account_get_connection(account); rru = cmd->params[1]; url = cmd->params[2]; @@ -2041,7 +2041,7 @@ const char *unread; session = cmdproc->session; - gc = session->account->gc; + gc = purple_account_get_connection(session->account); if (strcmp(msg->remote_user, "Hotmail")) /* This isn't an official message. */ @@ -2092,7 +2092,7 @@ const char *mdata, *unread; session = cmdproc->session; - gc = session->account->gc; + gc = purple_account_get_connection(session->account); if (strcmp(msg->remote_user, "Hotmail")) /* This isn't an official message. */ @@ -2164,7 +2164,7 @@ char *from, *subject, *tmp; session = cmdproc->session; - gc = session->account->gc; + gc = purple_account_get_connection(session->account); if (strcmp(msg->remote_user, "Hotmail")) /* This isn't an official message. */ @@ -2249,7 +2249,7 @@ } if (*buf != '\0') - purple_notify_info(cmdproc->session->account->gc, NULL, buf, NULL); + purple_notify_info(purple_account_get_connection(cmdproc->session->account), NULL, buf, NULL); } g_hash_table_destroy(table); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/object.c --- a/libpurple/protocols/msn/object.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/object.c Fri Apr 06 04:30:00 2012 +0000 @@ -103,7 +103,7 @@ if (obj->creator == NULL || obj->size == 0 || obj->type == 0 || obj->sha1d == NULL) { purple_debug_error("msn", "Discarding invalid msnobj: '%s'\n", str); - msn_object_destroy(obj); + msn_object_destroy(obj, FALSE); return NULL; } @@ -111,12 +111,12 @@ /* Location/friendly are required for non-buddyicon objects */ if (obj->type != MSN_OBJECT_USERTILE) { purple_debug_error("msn", "Discarding invalid msnobj: '%s'\n", str); - msn_object_destroy(obj); + msn_object_destroy(obj, FALSE); return NULL; /* Buddy icon object can contain Url/Url1 instead */ } else if (obj->url == NULL || obj->url1 == NULL) { purple_debug_error("msn", "Discarding invalid msnobj: '%s'\n", str); - msn_object_destroy(obj); + msn_object_destroy(obj, FALSE); return NULL; } } @@ -193,10 +193,13 @@ } void -msn_object_destroy(MsnObject *obj) +msn_object_destroy(MsnObject *obj, gboolean only_remote) { g_return_if_fail(obj != NULL); + if (only_remote && obj->local) + return; + g_free(obj->creator); g_free(obj->location); g_free(obj->friendly); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/object.h --- a/libpurple/protocols/msn/object.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/object.h Fri Apr 06 04:30:00 2012 +0000 @@ -86,9 +86,10 @@ /** * Destroys an MsnObject structure. * - * @param obj The object structure. + * @param obj The object structure. + * @param only_remote Only destroy non-local objects. */ -void msn_object_destroy(MsnObject *obj); +void msn_object_destroy(MsnObject *obj, gboolean only_remote); /** * Outputs a string representation of an MsnObject. diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/oim.c --- a/libpurple/protocols/msn/oim.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/oim.c Fri Apr 06 04:30:00 2012 +0000 @@ -828,7 +828,7 @@ /* XXX/khc: pretty sure this is wrong */ if (count > 0) - purple_notify_emails(session->account->gc, count, FALSE, NULL, + purple_notify_emails(purple_account_get_connection(session->account), count, FALSE, NULL, NULL, passports, urls, NULL, NULL); g_free(unread); } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/sbconn.c --- a/libpurple/protocols/msn/sbconn.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/sbconn.c Fri Apr 06 04:30:00 2012 +0000 @@ -121,6 +121,8 @@ } #endif } + } else { + msn_transaction_set_saveable(trans, FALSE); } trans->payload = payload; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/servconn.c --- a/libpurple/protocols/msn/servconn.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/servconn.c Fri Apr 06 04:30:00 2012 +0000 @@ -421,8 +421,10 @@ servconn = data; - if (servconn->type == MSN_SERVCONN_NS) - servconn->session->account->gc->last_received = time(NULL); + if (servconn->type == MSN_SERVCONN_NS) { + PurpleConnection *gc = purple_account_get_connection(servconn->session->account); + purple_connection_update_last_received(gc); + } len = read(servconn->fd, buf, sizeof(buf) - 1); if (len < 0 && errno == EAGAIN) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/session.c --- a/libpurple/protocols/msn/session.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/session.c Fri Apr 06 04:30:00 2012 +0000 @@ -420,7 +420,7 @@ msn_session_disconnect(session); - purple_connection_error_reason(gc, reason, msg); + purple_connection_error(gc, reason, msg); g_free(msg); } @@ -459,7 +459,7 @@ if (session->logged_in) return; - gc = session->account->gc; + gc = purple_account_get_connection(session->account); session->login_step = step; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/slp.c --- a/libpurple/protocols/msn/slp.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/slp.c Fri Apr 06 04:30:00 2012 +0000 @@ -253,7 +253,7 @@ data->session = session; data->remote_user = user->passport; data->sha1 = info; - url_data = purple_util_fetch_url_len(url, TRUE, NULL, TRUE, 200*1024, + url_data = purple_util_fetch_url(url, TRUE, NULL, TRUE, 200*1024, fetched_user_display, data); session->url_datas = g_slist_prepend(session->url_datas, url_data); } else { @@ -291,7 +291,7 @@ static gchar * gen_context(PurpleXfer *xfer, const char *file_name, const char *file_path) { - gsize size = 0; + goffset size = 0; MsnFileContext context; gchar *u8 = NULL; gchar *ret; @@ -322,7 +322,7 @@ preview = purple_xfer_get_thumbnail(xfer, &preview_len); - context.length = MSN_FILE_CONTEXT_SIZE; + context.length = MSN_FILE_CONTEXT_SIZE_V2; context.version = 2; /* V.3 contains additional unnecessary data */ context.file_size = size; if (preview) @@ -336,15 +336,17 @@ } memset(&context.file_name[currentChar], 0x00, (MAX_FILE_NAME_LEN - currentChar) * 2); +#if 0 memset(&context.unknown1, 0, sizeof(context.unknown1)); context.unknown2 = 0xffffffff; +#endif /* Mind the cast, as in, don't free it after! */ context.preview = (char *)preview; context.preview_len = preview_len; u8 = msn_file_context_to_wire(&context); - ret = purple_base64_encode((const guchar *)u8, MSN_FILE_CONTEXT_SIZE + preview_len); + ret = purple_base64_encode((const guchar *)u8, MSN_FILE_CONTEXT_SIZE_V2 + preview_len); g_free(uni); g_free(u8); @@ -364,7 +366,7 @@ fn = purple_xfer_get_filename(xfer); fp = purple_xfer_get_local_filename(xfer); - slplink = xfer->data; + slplink = purple_xfer_get_protocol_data(xfer); g_return_if_fail(slplink != NULL); g_return_if_fail(fp != NULL); @@ -384,7 +386,7 @@ purple_xfer_set_read_fnc(xfer, msn_xfer_read); purple_xfer_set_write_fnc(xfer, msn_xfer_write); - xfer->data = slpcall; + purple_xfer_set_protocol_data(xfer, slpcall); context = gen_context(xfer, fn, fp); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/slpcall.c --- a/libpurple/protocols/msn/slpcall.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/slpcall.c Fri Apr 06 04:30:00 2012 +0000 @@ -113,7 +113,7 @@ if (slpcall->xfer != NULL) { if (purple_xfer_get_type(slpcall->xfer) == PURPLE_XFER_RECEIVE) g_byte_array_free(slpcall->u.incoming_data, TRUE); - slpcall->xfer->data = NULL; + purple_xfer_set_protocol_data(slpcall->xfer, NULL); purple_xfer_unref(slpcall->xfer); } @@ -485,7 +485,7 @@ if (img) purple_imgstore_ref(img); } - msn_object_destroy(obj); + msn_object_destroy(obj, FALSE); if (img != NULL) { /* DATA PREP */ @@ -512,7 +512,6 @@ MsnFileContext *file_context; char *buf; gsize bin_len; - guint32 file_size; char *file_name; account = slpcall->slplink->session->account; @@ -529,8 +528,6 @@ file_context = msn_file_context_from_wire(buf, bin_len); if (file_context != NULL) { - file_size = file_context->file_size; - file_name = g_convert((const gchar *)&file_context->file_name, MAX_FILE_NAME_LEN * 2, "UTF-8", "UTF-16LE", @@ -538,7 +535,7 @@ purple_xfer_set_filename(xfer, file_name ? file_name : ""); g_free(file_name); - purple_xfer_set_size(xfer, file_size); + purple_xfer_set_size(xfer, file_context->file_size); purple_xfer_set_init_fnc(xfer, msn_xfer_init); purple_xfer_set_request_denied_fnc(xfer, msn_xfer_cancel); purple_xfer_set_cancel_recv_fnc(xfer, msn_xfer_cancel); @@ -550,7 +547,7 @@ slpcall->xfer = xfer; purple_xfer_ref(slpcall->xfer); - xfer->data = slpcall; + purple_xfer_set_protocol_data(xfer, slpcall); if (file_context->preview) { purple_xfer_set_thumbnail(xfer, file_context->preview, @@ -731,7 +728,9 @@ dc->listen_data = purple_network_listen_range( 0, 0, + AF_UNSPEC, SOCK_STREAM, + TRUE, msn_dc_listen_socket_created_cb, dc ); @@ -832,7 +831,9 @@ dc->listen_data = purple_network_listen_range( 0, 0, + AF_UNSPEC, SOCK_STREAM, + TRUE, msn_dc_listen_socket_created_cb, dc ); @@ -1141,8 +1142,6 @@ if (slpcall->cb) slpcall->cb(slpcall, body, body_len); - - slpcall->wasted = TRUE; } } else if (msn_p2p_info_is_ack(slpmsg->p2p_info)) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/slplink.c --- a/libpurple/protocols/msn/slplink.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/slplink.c Fri Apr 06 04:30:00 2012 +0000 @@ -465,7 +465,7 @@ purple_xfer_ref(xfer); purple_xfer_start(xfer, -1, NULL, 0); - if (xfer->data == NULL) { + if (purple_xfer_get_protocol_data(xfer) == NULL) { purple_xfer_unref(xfer); msn_slpmsg_destroy(slpmsg); g_return_val_if_reached(NULL); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/slpmsg.c --- a/libpurple/protocols/msn/slpmsg.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/slpmsg.c Fri Apr 06 04:30:00 2012 +0000 @@ -239,7 +239,7 @@ } -MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, size_t size) +MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, goffset size) { MsnSlpMessage *slpmsg; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/slpmsg.h --- a/libpurple/protocols/msn/slpmsg.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/slpmsg.h Fri Apr 06 04:30:00 2012 +0000 @@ -133,7 +133,7 @@ * * @return A new SlpMessage with the file transfer info. */ -MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, size_t size); +MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, goffset size); /** * Serialize the MsnSlpMessage in a way it can be used to be transmited diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/switchboard.c --- a/libpurple/protocols/msn/switchboard.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/switchboard.c Fri Apr 06 04:30:00 2012 +0000 @@ -312,7 +312,7 @@ swboard->chat_id = msn_switchboard_get_chat_id(); swboard->flag |= MSN_SB_FLAG_IM; - swboard->conv = serv_got_joined_chat(account->gc, + swboard->conv = serv_got_joined_chat(purple_account_get_connection(account), swboard->chat_id, "MSN Chat"); @@ -747,7 +747,7 @@ PurpleConnection *gc; MsnSwitchBoard *swboard; - gc = cmdproc->session->account->gc; + gc = purple_account_get_connection(cmdproc->session->account); swboard = cmdproc->data; if (swboard->current_users > 1) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/user.c --- a/libpurple/protocols/msn/user.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/user.c Fri Apr 06 04:30:00 2012 +0000 @@ -76,7 +76,7 @@ } if (user->msnobj != NULL) - msn_object_destroy(user->msnobj); + msn_object_destroy(user->msnobj, FALSE); g_free(user->passport); g_free(user->friendly_name); @@ -406,7 +406,7 @@ gc = purple_account_get_connection(account); if (gc != NULL) - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); if ((session != NULL) && (user = msn_userlist_find_user(session->userlist, name)) != NULL) { @@ -566,7 +566,7 @@ return; } - if (!buddy_icon_cached(account->gc, obj)) { + if (!buddy_icon_cached(purple_account_get_connection(account), obj)) { MsnUserList *userlist; userlist = user->userlist; @@ -588,8 +588,8 @@ { g_return_if_fail(user != NULL); - if (user->msnobj != NULL && !msn_object_find_local(msn_object_get_sha1(obj))) - msn_object_destroy(user->msnobj); + if (user->msnobj != NULL) + msn_object_destroy(user->msnobj, TRUE); user->msnobj = obj; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/userlist.c --- a/libpurple/protocols/msn/userlist.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/userlist.c Fri Apr 06 04:30:00 2012 +0000 @@ -54,7 +54,7 @@ if (PURPLE_CONNECTION_IS_VALID(pa->gc)) { - MsnSession *session = pa->gc->proto_data; + MsnSession *session = purple_connection_get_protocol_data(pa->gc); MsnUserList *userlist = session->userlist; PurpleAccount *account = purple_connection_get_account(pa->gc); @@ -79,7 +79,7 @@ if (PURPLE_CONNECTION_IS_VALID(pa->gc)) { - MsnSession *session = pa->gc->proto_data; + MsnSession *session = purple_connection_get_protocol_data(pa->gc); MsnUserList *userlist = session->userlist; MsnCallbackState *state = msn_callback_state_new(session); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/xfer.c --- a/libpurple/protocols/msn/xfer.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/xfer.c Fri Apr 06 04:30:00 2012 +0000 @@ -42,7 +42,7 @@ purple_debug_info("msn", "xfer_init\n"); - slpcall = xfer->data; + slpcall = purple_xfer_get_protocol_data(xfer); /* Send Ok */ content = g_strdup_printf("SessionID: %lu\r\n\r\n", @@ -62,9 +62,9 @@ char *content; g_return_if_fail(xfer != NULL); - g_return_if_fail(xfer->data != NULL); - slpcall = xfer->data; + slpcall = purple_xfer_get_protocol_data(xfer); + g_return_if_fail(slpcall != NULL); if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL) { @@ -102,7 +102,7 @@ g_return_val_if_fail(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND, -1); - slpcall = xfer->data; + slpcall = purple_xfer_get_protocol_data(xfer); /* Not sure I trust it'll be there */ g_return_val_if_fail(slpcall != NULL, -1); @@ -126,7 +126,7 @@ g_return_val_if_fail(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE, -1); - slpcall = xfer->data; + slpcall = purple_xfer_get_protocol_data(xfer); /* Not sure I trust it'll be there */ g_return_val_if_fail(slpcall != NULL, -1); @@ -166,7 +166,7 @@ { gchar *ret, *tmp; - tmp = ret = g_new(gchar, MSN_FILE_CONTEXT_SIZE + context->preview_len + 1); + tmp = ret = g_new(gchar, MSN_FILE_CONTEXT_SIZE_V2 + context->preview_len + 1); msn_push32le(tmp, context->length); msn_push32le(tmp, context->version); @@ -174,9 +174,15 @@ msn_push32le(tmp, context->type); memcpy(tmp, context->file_name, MAX_FILE_NAME_LEN * 2); tmp += MAX_FILE_NAME_LEN * 2; +#if 0 memcpy(tmp, context->unknown1, sizeof(context->unknown1)); tmp += sizeof(context->unknown1); msn_push32le(tmp, context->unknown2); +#else + memset(tmp, 0, sizeof(gchar[30])); + tmp += sizeof(gchar[30]); + msn_push32le(tmp, 0xffffffff); +#endif if (context->preview) { memcpy(tmp, context->preview, context->preview_len); } @@ -190,21 +196,30 @@ { MsnFileContext *context; - if (!buf || len < MSN_FILE_CONTEXT_SIZE) + if (!buf || len < MSN_FILE_CONTEXT_SIZE_V0) return NULL; context = g_new(MsnFileContext, 1); context->length = msn_pop32le(buf); context->version = msn_pop32le(buf); - if (context->version == 2) { - /* The length field is broken for this version. No check. */ - context->length = MSN_FILE_CONTEXT_SIZE; - } else if (context->version == 3) { - if (context->length != MSN_FILE_CONTEXT_SIZE + 63) { + if (context->version == 0) { + if (context->length != MSN_FILE_CONTEXT_SIZE_V0) { g_free(context); return NULL; - } else if (len < MSN_FILE_CONTEXT_SIZE + 63) { + } + } else if (context->version == 2) { + /* The length field is broken for this version. No check. */ + context->length = MSN_FILE_CONTEXT_SIZE_V2; + if (len < MSN_FILE_CONTEXT_SIZE_V2) { + g_free(context); + return NULL; + } + } else if (context->version == 3) { + if (context->length != MSN_FILE_CONTEXT_SIZE_V3) { + g_free(context); + return NULL; + } else if (len < MSN_FILE_CONTEXT_SIZE_V3) { g_free(context); return NULL; } @@ -218,9 +233,15 @@ context->type = msn_pop32le(buf); memcpy(context->file_name, buf, MAX_FILE_NAME_LEN * 2); buf += MAX_FILE_NAME_LEN * 2; - memcpy(context->unknown1, buf, sizeof(context->unknown1)); - buf += sizeof(context->unknown1); - context->unknown2 = msn_pop32le(buf); + if (context->version > 0) { +#if 0 + memcpy(context->unknown1, buf, sizeof(context->unknown1)); + buf += sizeof(context->unknown1); + context->unknown2 = msn_pop32le(buf); +#else + buf += sizeof(gchar[30]) + sizeof(guint32); +#endif + } if (context->type == 0 && len > context->length) { context->preview_len = len - context->length; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/msn/xfer.h --- a/libpurple/protocols/msn/xfer.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/msn/xfer.h Fri Apr 06 04:30:00 2012 +0000 @@ -39,13 +39,17 @@ guint64 file_size; /*< Size of file */ guint32 type; /*< Transfer type */ gunichar2 file_name[MAX_FILE_NAME_LEN]; /*< Self-explanatory */ +#if 0 gchar unknown1[30]; /*< Used somehow for background sharing */ guint32 unknown2; /*< Possibly for background sharing as well */ +#endif gchar *preview; /*< File preview data, 96x96 PNG */ gsize preview_len; } MsnFileContext; -#define MSN_FILE_CONTEXT_SIZE (4*4 + 1*8 + 2*MAX_FILE_NAME_LEN + 30) +#define MSN_FILE_CONTEXT_SIZE_V0 (4*3 + 1*8 + 2*MAX_FILE_NAME_LEN) +#define MSN_FILE_CONTEXT_SIZE_V2 (MSN_FILE_CONTEXT_SIZE_V0 + 4*1 + 30) +#define MSN_FILE_CONTEXT_SIZE_V3 (MSN_FILE_CONTEXT_SIZE_V2 + 63) void msn_xfer_init(PurpleXfer *xfer); void msn_xfer_cancel(PurpleXfer *xfer); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/actions.c --- a/libpurple/protocols/mxit/actions.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/actions.c Fri Apr 06 04:30:00 2012 +0000 @@ -43,7 +43,7 @@ */ static void mxit_profile_cb( PurpleConnection* gc, PurpleRequestFields* fields ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ) ; PurpleRequestField* field = NULL; const char* name = NULL; const char* bday = NULL; @@ -84,13 +84,6 @@ g_string_append( attributes, attrib ); acount++; - /* force hidden if disabled */ - if ( profile->hidden == FALSE ) { - g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_HIDENUMBER, CP_PROFILE_TYPE_BOOL, "1" ); - g_string_append( attributes, attrib ); - acount++; - } - /* update birthday */ g_strlcpy( profile->birthday, bday, sizeof( profile->birthday ) ); g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_BIRTHDATE, CP_PROFILE_TYPE_UTF8, profile->birthday ); @@ -165,7 +158,7 @@ /* update where am i */ name = purple_request_fields_get_string( fields, "whereami" ); - if ( !name) + if ( !name ) profile->whereami[0] = '\0'; else g_strlcpy( profile->whereami, name, sizeof( profile->whereami ) ); @@ -207,7 +200,7 @@ static void mxit_profile_action( PurplePluginAction* action ) { PurpleConnection* gc = (PurpleConnection*) action->context; - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); struct MXitProfile* profile = session->profile; PurpleRequestFields* fields = NULL; @@ -304,7 +297,7 @@ */ static void mxit_change_pin_cb( PurpleConnection* gc, PurpleRequestFields* fields ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); const char* pin = NULL; const char* pin2 = NULL; const char* err = NULL; @@ -366,7 +359,7 @@ static void mxit_change_pin_action( PurplePluginAction* action ) { PurpleConnection* gc = (PurpleConnection*) action->context; - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); PurpleRequestFields* fields = NULL; PurpleRequestFieldGroup* group = NULL; @@ -375,16 +368,16 @@ purple_debug_info( MXIT_PLUGIN_ID, "mxit_change_pin_action\n" ); fields = purple_request_fields_new(); - group = purple_request_field_group_new(NULL); - purple_request_fields_add_group(fields, group); + group = purple_request_field_group_new( NULL ); + purple_request_fields_add_group( fields, group ); /* pin */ - field = purple_request_field_string_new( "pin", _( "PIN" ), session->acc->password, FALSE ); + field = purple_request_field_string_new( "pin", _( "PIN" ), purple_account_get_password( session->acc ), FALSE ); purple_request_field_string_set_masked( field, TRUE ); purple_request_field_group_add_field( group, field ); /* verify pin */ - field = purple_request_field_string_new( "pin2", _( "Verify PIN" ), session->acc->password, FALSE ); + field = purple_request_field_string_new( "pin2", _( "Verify PIN" ), purple_account_get_password( session->acc ), FALSE ); purple_request_field_string_set_masked( field, TRUE ); purple_request_field_group_add_field( group, field ); @@ -402,7 +395,7 @@ static void mxit_splash_action( PurplePluginAction* action ) { PurpleConnection* gc = (PurpleConnection*) action->context; - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); if ( splash_current( session ) != NULL ) splash_display( session ); @@ -439,7 +432,7 @@ static void mxit_suggested_friends_action( PurplePluginAction* action ) { PurpleConnection* gc = (PurpleConnection*) action->context; - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); const char* profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_STATUS, CP_PROFILE_AVATAR, @@ -456,7 +449,7 @@ */ static void mxit_user_search_cb( PurpleConnection *gc, const char *input ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); const char* profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_STATUS, CP_PROFILE_AVATAR, @@ -479,10 +472,10 @@ _( "Search for a MXit contact" ), _( "Type search information" ), NULL, FALSE, FALSE, NULL, - _("_Search"), G_CALLBACK( mxit_user_search_cb ), - _("_Cancel"), NULL, + _( "_Search" ), G_CALLBACK( mxit_user_search_cb ), + _( "_Cancel" ), NULL, purple_connection_get_account( gc ), NULL, NULL, - gc); + gc ); } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/cipher.c --- a/libpurple/protocols/mxit/cipher.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/cipher.c Fri Apr 06 04:30:00 2012 +0000 @@ -1,7 +1,7 @@ /* * MXit Protocol libPurple Plugin * - * -- user password encryption -- + * -- encryption -- * * Pieter Loubser * @@ -31,30 +31,70 @@ #include "aes.h" -/* password encryption */ +/* encryption */ #define INITIAL_KEY "6170383452343567" #define SECRET_HEADER "" +#define ENCRYPT_HEADER "" + + +/*------------------------------------------------------------------------ + * Add ISO10126 Padding to the data. + * + * @param data The data to pad. + */ +static void padding_add( GString* data ) +{ + unsigned int blocks = ( data->len / 16 ) + 1; + unsigned int padding = ( blocks * 16 ) - data->len; + + g_string_set_size( data, blocks * 16 ); + data->str[data->len - 1] = padding; +} /*------------------------------------------------------------------------ - * Pad the secret data using ISO10126 Padding. + * Remove ISO10126 Padding from the data. * - * @param secret The data to pad (caller must ensure buffer has enough space for padding) - * @return The total number of 128-bit blocks used + * @param data The data from which to remove padding. */ -static int pad_secret_data( char* secret ) +static void padding_remove( GString* data ) { - int blocks = 0; - int passlen; - int padding; + unsigned int padding; + + if ( data->len == 0 ) + return; + + padding = data->str[data->len - 1]; + g_string_truncate( data, data->len - padding ); +} + - passlen = strlen( secret ); - blocks = ( passlen / 16 ) + 1; - padding = ( blocks * 16 ) - passlen; - secret[passlen] = 0x50; - secret[(blocks * 16) - 1] = padding; +/*------------------------------------------------------------------------ + * Generate the Transport-Layer crypto key. + * (Note: this function is not-thread safe) + * + * @param session The MXit Session object + * @return The transport-layer crypto key. + */ +static char* transport_layer_key( struct MXitSession* session ) +{ + static char key[16 + 1]; + const char* password = purple_account_get_password( session->acc ); + int passlen = strlen( password ); - return blocks; + /* initialize with initial key */ + g_strlcpy( key, INITIAL_KEY, sizeof( key ) ); + + /* client key (8 bytes) */ + memcpy( key, session->clientkey, strlen( session->clientkey ) ); + + /* add last 8 characters of the PIN (no padding if less characters) */ + if ( passlen <= 8 ) + memcpy( key + 8, password, passlen ); + else + memcpy( key + 8, password + ( passlen - 8 ), 8 ); + + return key; } @@ -67,42 +107,131 @@ */ char* mxit_encrypt_password( struct MXitSession* session ) { - char key[64]; + char key[16 + 1]; char exkey[512]; - char pass[64]; + GString* pass = NULL; char encrypted[64]; char* base64; - int blocks; - int size; int i; purple_debug_info( MXIT_PLUGIN_ID, "mxit_encrypt_password\n" ); memset( encrypted, 0x00, sizeof( encrypted ) ); - memset( exkey, 0x00, sizeof( exkey ) ); - memset( pass, 0x58, sizeof( pass ) ); - pass[sizeof( pass ) - 1] = '\0'; - /* build the custom AES encryption key */ + /* build the AES encryption key */ g_strlcpy( key, INITIAL_KEY, sizeof( key ) ); memcpy( key, session->clientkey, strlen( session->clientkey ) ); ExpandKey( (unsigned char*) key, (unsigned char*) exkey ); - /* build the custom data to be encrypted */ - g_strlcpy( pass, SECRET_HEADER, sizeof( pass ) ); - strcat( pass, session->acc->password ); + /* build the secret data to be encrypted: SECRET_HEADER + password */ + pass = g_string_new( SECRET_HEADER ); + g_string_append( pass, purple_account_get_password( session->acc) ); + padding_add( pass ); /* add ISO10126 padding */ - /* pad the secret data */ - blocks = pad_secret_data( pass ); - size = blocks * 16; - - /* now encrypt the password. we encrypt each block separately (ECB mode) */ - for ( i = 0; i < size; i += 16 ) - Encrypt( (unsigned char*) pass + i, (unsigned char*) exkey, (unsigned char*) encrypted + i ); + /* now encrypt the secret. we encrypt each block separately (ECB mode) */ + for ( i = 0; i < pass->len; i += 16 ) + Encrypt( (unsigned char*) pass->str + i, (unsigned char*) exkey, (unsigned char*) encrypted + i ); /* now base64 encode the encrypted password */ - base64 = purple_base64_encode( (unsigned char*) encrypted, size ); + base64 = purple_base64_encode( (unsigned char*) encrypted, pass->len ); + + g_string_free( pass, TRUE ); return base64; } + +/*------------------------------------------------------------------------ + * Decrypt a message using transport-layer encryption. + * + * @param session The MXit session object + * @param message The encrypted message data (is base64-encoded). + * @return The decrypted message. Must be g_free'd when no longer needed. + */ +char* mxit_decrypt_message( struct MXitSession* session, char* message ) +{ + guchar* raw_message; + gsize raw_len; + char exkey[512]; + GString* decoded = NULL; + int i; + + /* remove optional header: */ + if ( strncmp( message, ENCRYPT_HEADER, strlen( ENCRYPT_HEADER ) ) == 0 ) + message += strlen( ENCRYPT_HEADER ); + + /* base64 decode the message */ + raw_message = purple_base64_decode( message, &raw_len ); + + /* build the AES key */ + ExpandKey( (unsigned char*) transport_layer_key( session ), (unsigned char*) exkey ); + + /* AES decrypt each block */ + decoded = g_string_sized_new( raw_len ); + for ( i = 0; i < raw_len; i += 16 ) { + char block[16]; + + Decrypt( (unsigned char*) raw_message + i, (unsigned char*) exkey, (unsigned char*) block ); + g_string_append_len( decoded, block, 16 ); + } + g_free( raw_message ); + + /* check that the decrypted message starts with header: */ + if ( strncmp( decoded->str, SECRET_HEADER, strlen( SECRET_HEADER ) != 0 ) ) { + g_string_free( decoded, TRUE ); + return NULL; /* message could not be decrypted */ + } + + /* remove ISO10126 padding */ + padding_remove( decoded ); + + /* remove encryption header */ + g_string_erase( decoded, 0, strlen( SECRET_HEADER ) ); + + return g_string_free( decoded, FALSE ); +} + + +/*------------------------------------------------------------------------ + * Encrypt a message using transport-layer encryption. + * + * @param session The MXit session object + * @param message The message data. + * @return The encrypted message. Must be g_free'd when no longer needed. + */ +char* mxit_encrypt_message( struct MXitSession* session, char* message ) +{ + GString* raw_message = NULL; + char exkey[512]; + GString* encoded = NULL; + gchar* base64; + int i; + + purple_debug_info( MXIT_PLUGIN_ID, "encrypt message: '%s'\n", message ); + + /* append encryption header to message data */ + raw_message = g_string_new( SECRET_HEADER ); + g_string_append( raw_message, message ); + padding_add( raw_message ); /* add ISO10126 padding */ + + /* build the AES key */ + ExpandKey( (unsigned char*) transport_layer_key( session ), (unsigned char*) exkey ); + + /* AES encrypt each block */ + encoded = g_string_sized_new( raw_message->len ); + for ( i = 0; i < raw_message->len; i += 16 ) { + char block[16]; + + Encrypt( (unsigned char*) raw_message->str + i, (unsigned char*) exkey, (unsigned char*) block ); + g_string_append_len( encoded, block, 16 ); + } + g_string_free( raw_message, TRUE ); + + /* base64 encode the encrypted message */ + base64 = purple_base64_encode( (unsigned char *) encoded->str, encoded->len ); + g_string_free( encoded, TRUE ); + + purple_debug_info( MXIT_PLUGIN_ID, "encrypted message: '%s'\n", base64 ); + + return base64; +} diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/cipher.h --- a/libpurple/protocols/mxit/cipher.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/cipher.h Fri Apr 06 04:30:00 2012 +0000 @@ -1,7 +1,7 @@ /* * MXit Protocol libPurple Plugin * - * -- user password encryption -- + * -- encryption -- * * Pieter Loubser * @@ -32,5 +32,7 @@ char* mxit_encrypt_password( struct MXitSession* session ); +char* mxit_decrypt_message( struct MXitSession* session, char* message ); +char* mxit_encrypt_message( struct MXitSession* session, char* message ); #endif /* _MXIT_CIPHER_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/filexfer.c --- a/libpurple/protocols/mxit/filexfer.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/filexfer.c Fri Apr 06 04:30:00 2012 +0000 @@ -97,11 +97,11 @@ */ static void mxit_xfer_free( PurpleXfer* xfer ) { - struct mxitxfer* mx = (struct mxitxfer*) xfer->data;; + struct mxitxfer* mx = purple_xfer_get_protocol_data( xfer ); if ( mx ) { + purple_xfer_set_protocol_data( xfer, NULL ); g_free( mx ); - xfer->data = NULL; } } @@ -117,16 +117,16 @@ */ static void mxit_xfer_init( PurpleXfer* xfer ) { - struct mxitxfer* mx = (struct mxitxfer*) xfer->data; + struct mxitxfer* mx = purple_xfer_get_protocol_data( xfer ); purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_init\n" ); if ( purple_xfer_get_type( xfer ) == PURPLE_XFER_SEND ) { /* we are trying to send a file to MXit */ - if ( purple_xfer_get_size( xfer ) > CP_MAX_FILESIZE ) { + if ( purple_xfer_get_size( xfer ) > ( CP_MAX_PACKET - 1000 ) ) { /* need to reserve some space for packet headers */ /* the file is too big */ - purple_xfer_error( xfer->type, xfer->account, xfer->who, _( "The file you are trying to send is too large!" ) ); + purple_xfer_error( purple_xfer_get_type( xfer ), purple_xfer_get_account( xfer ), purple_xfer_get_remote_user( xfer ), _( "The file you are trying to send is too large!" ) ); purple_xfer_cancel_local( xfer ); return; } @@ -139,7 +139,7 @@ * we have just accepted a file transfer request from MXit. send a confirmation * to the MXit server so that can send us the file */ - mxit_send_file_accept( mx->session, mx->fileid, purple_xfer_get_size( xfer ), 0 ); + mxit_send_file_accept( mx->session, mx->fileid, (int) purple_xfer_get_size( xfer ), 0 ); } } @@ -151,6 +151,7 @@ */ static void mxit_xfer_start( PurpleXfer* xfer ) { + goffset filesize; unsigned char* buffer; int size; int wrote; @@ -163,10 +164,12 @@ * a buffer and copy the file data into memory and then we can send it to * the contact. we will send the whole file with one go. */ - buffer = g_malloc( xfer->bytes_remaining ); - size = fread( buffer, xfer->bytes_remaining, 1, xfer->dest_fp ); + filesize = purple_xfer_get_bytes_remaining( xfer ); + buffer = g_malloc( filesize ); + size = fread( buffer, filesize, 1, xfer->dest_fp ); + // TODO: If (size != 1) -> file read error - wrote = purple_xfer_write( xfer, buffer, xfer->bytes_remaining ); + wrote = purple_xfer_write( xfer, buffer, filesize ); if ( wrote > 0 ) purple_xfer_set_bytes_sent( xfer, wrote ); @@ -215,7 +218,7 @@ */ static gssize mxit_xfer_write( const guchar* buffer, size_t size, PurpleXfer* xfer ) { - struct mxitxfer* mx = (struct mxitxfer*) xfer->data; + struct mxitxfer* mx = purple_xfer_get_protocol_data( xfer ); purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_write\n" ); @@ -245,7 +248,7 @@ */ static void mxit_xfer_request_denied( PurpleXfer* xfer ) { - struct mxitxfer* mx = (struct mxitxfer*) xfer->data; + struct mxitxfer* mx = purple_xfer_get_protocol_data( xfer ); purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_request_denied\n" ); @@ -295,7 +298,7 @@ */ PurpleXfer* mxit_xfer_new( PurpleConnection* gc, const char* who ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); PurpleXfer* xfer = NULL; struct mxitxfer* mx = NULL; @@ -305,7 +308,7 @@ /* create file info and attach it to the file transfer */ mx = g_new0( struct mxitxfer, 1 ); mx->session = session; - xfer->data = mx; + purple_xfer_set_protocol_data( xfer, mx ); /* configure callbacks (reference: "libpurple/ft.h") */ purple_xfer_set_init_fnc( xfer, mxit_xfer_init ); @@ -362,7 +365,7 @@ mx = g_new0( struct mxitxfer, 1 ); mx->session = session; memcpy( mx->fileid, fileid, MXIT_CHUNK_FILEID_LEN ); - xfer->data = mx; + purple_xfer_set_protocol_data( xfer, mx ); purple_xfer_set_filename( xfer, filename ); if( filesize > 0 ) @@ -395,9 +398,9 @@ while ( item ) { xfer = item->data; - if ( xfer->account == session->acc ) { + if ( purple_xfer_get_account( xfer ) == session->acc ) { /* transfer is associated with this MXit account */ - struct mxitxfer* mx = xfer->data; + struct mxitxfer* mx = purple_xfer_get_protocol_data( xfer ); /* does the fileid match? */ if ( ( mx ) && ( memcmp( mx->fileid, fileid, MXIT_CHUNK_FILEID_LEN ) == 0 ) ) @@ -424,19 +427,17 @@ void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, int datalen ) { PurpleXfer* xfer = NULL; - struct mxitxfer* mx = NULL; purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_rx_file: (size=%i)\n", datalen ); /* find the file-transfer object */ xfer = find_mxit_xfer( session, fileid ); if ( xfer ) { - mx = xfer->data; - /* this is the transfer we have been looking for */ purple_xfer_ref( xfer ); purple_xfer_start( xfer, -1, NULL, 0 ); fwrite( data, datalen, 1, xfer->dest_fp ); + // TODO: Handle error from fwrite() purple_xfer_unref( xfer ); purple_xfer_set_completed( xfer, TRUE ); purple_xfer_end( xfer ); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/formcmds.c --- a/libpurple/protocols/mxit/formcmds.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/formcmds.c Fri Apr 06 04:30:00 2012 +0000 @@ -86,7 +86,6 @@ static void mxit_cb_ii_returned(PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message) { struct ii_url_request* iireq = (struct ii_url_request*) user_data; - char* ii_data; int* intptr = NULL; int id; @@ -106,12 +105,8 @@ goto done; } - /* make a copy of the data */ - ii_data = g_malloc(len); - memcpy(ii_data, (const char*) url_text, len); - - /* we now have the inline image, store it in the imagestore */ - id = purple_imgstore_add_with_id(ii_data, len, NULL); + /* we now have the inline image, store a copy in the imagestore */ + id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL); /* map the inline image id to purple image id */ intptr = g_malloc(sizeof(int)); @@ -253,8 +248,8 @@ /*------------------------------------------------------------------------ * Process a Reply MXit command. - * [::op=cmd|type=reply|replymsg=back|selmsg=b) Back|id=12345:] - * [::op=cmd|nm=rep|type=reply|replymsg=back|selmsg=b) Back|id=12345:] + * [::op=cmd|type=reply|replymsg=back|selmsg=b) Back|displaymsg=Processing|id=12345:] + * [::op=cmd|nm=rep|type=reply|replymsg=back|selmsg=b) Back|displaymsg=Processing|id=12345:] * * @param mx The received message data object * @param hash The MXit command map @@ -265,22 +260,26 @@ char* selmsg; char* nm; - selmsg = g_hash_table_lookup(hash, "selmsg"); /* find the selection message */ - replymsg = g_hash_table_lookup(hash, "replymsg"); /* find the reply message */ + selmsg = g_hash_table_lookup(hash, "selmsg"); /* selection message */ + replymsg = g_hash_table_lookup(hash, "replymsg"); /* reply message */ nm = g_hash_table_lookup(hash, "nm"); /* name parameter */ - if ((selmsg) && (replymsg) && (nm)) { + + if ((selmsg == NULL) || (replymsg == NULL)) + return; /* these parameters are required */ + + if (nm) { /* indicates response must be a structured response */ gchar* seltext = g_markup_escape_text(purple_url_decode(selmsg), -1); - gchar* replycmd = g_strdup_printf("::type=reply|nm=%s|res=%s|err=0:", nm, replymsg); + gchar* replycmd = g_strdup_printf("type=reply|nm=%s|res=%s|err=0", nm, replymsg); - mxit_add_html_link( mx, replycmd, seltext ); + mxit_add_html_link( mx, replycmd, TRUE, seltext ); g_free(seltext); g_free(replycmd); } - else if ((selmsg) && (replymsg)) { + else { gchar* seltext = g_markup_escape_text(purple_url_decode(selmsg), -1); - mxit_add_html_link( mx, purple_url_decode(replymsg), seltext ); + mxit_add_html_link( mx, purple_url_decode(replymsg), FALSE, seltext ); g_free(seltext); } @@ -317,6 +316,7 @@ /*------------------------------------------------------------------------ * Process an inline image MXit command. + * [::op=img|dat=ASDF23408asdflkj2309flkjsadf%3d%3d|algn=1|w=120|h=12|t=100|replymsg=text:] * * @param mx The received message data object * @param hash The MXit command map @@ -362,7 +362,7 @@ purple_debug_info(MXIT_PLUGIN_ID, "sending request for inline image '%s'\n", iireq->url); /* request the image (reference: "libpurple/util.h") */ - purple_util_fetch_url_request(iireq->url, TRUE, NULL, TRUE, NULL, FALSE, mxit_cb_ii_returned, iireq); + purple_util_fetch_url(iireq->url, TRUE, NULL, TRUE, -1, mxit_cb_ii_returned, iireq); mx->img_count++; } } @@ -372,7 +372,7 @@ reply = g_hash_table_lookup(hash, "replymsg"); if (reply) { g_string_append_printf(msg, "\n"); - mxit_add_html_link(mx, reply, _( "click here" )); + mxit_add_html_link(mx, reply, FALSE, _( "click here" )); } } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/http.c --- a/libpurple/protocols/mxit/http.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/http.c Fri Apr 06 04:30:00 2012 +0000 @@ -273,7 +273,7 @@ /* source is the file descriptor of the new connection */ if ( source < 0 ) { purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_http_connect failed: %s\n", error_message ); - purple_connection_error( req->session->con, _( "Unable to connect to the MXit HTTP server. Please check your server settings." ) ); + purple_connection_error( req->session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Unable to connect to the MXit HTTP server. Please check your server settings." ) ); return; } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/login.c --- a/libpurple/protocols/mxit/login.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/login.c Fri Apr 06 04:30:00 2012 +0000 @@ -49,29 +49,32 @@ */ static struct MXitSession* mxit_create_object( PurpleAccount* account ) { + PurpleConnection* con = purple_account_get_connection( account ); struct MXitSession* session = NULL; - PurpleConnection* con = NULL; /* currently the wapsite does not handle a '+' in front of the username (mxitid) so we just strip it */ - if ( account->username[0] == '+' ) { - char* fixed; + { + const char* username = purple_account_get_username( account ); - /* cut off the '+' */ - fixed = g_strdup( &account->username[1] ); - purple_account_set_username( account, fixed ); - g_free( fixed ); + if ( username[0] == '+' ) { + char* fixed = g_strdup( &username[1] ); + purple_account_set_username( account, fixed ); + g_free( fixed ); + } } session = g_new0( struct MXitSession, 1 ); + session->con = con; + session->acc = account; /* configure the connection (reference: "libpurple/connection.h") */ - con = purple_account_get_connection( account ); - con->proto_data = session; - con->flags |= PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_SUPPORT_MOODS; - session->con = con; - - /* add account */ - session->acc = account; + purple_connection_set_protocol_data( con, session ); + purple_connection_set_flags( con, + PURPLE_CONNECTION_NO_BGCOLOR + | PURPLE_CONNECTION_NO_URLDESC + | PURPLE_CONNECTION_HTML + | PURPLE_CONNECTION_SUPPORT_MOODS + ); /* configure the session (reference: "libpurple/account.h") */ g_strlcpy( session->server, purple_account_get_string( account, MXIT_CONFIG_SERVER_ADDR, DEFAULT_SERVER ), sizeof( session->server ) ); @@ -165,7 +168,7 @@ /* source is the file descriptor of the new connection */ if ( source < 0 ) { purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_connect failed: %s\n", error_message ); - purple_connection_error( session->con, _( "Unable to connect to the MXit server. Please check your server settings." ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Unable to connect to the MXit server. Please check your server settings." ) ); return; } @@ -173,7 +176,7 @@ session->fd = source; /* start listening on the open connection for messages from the server (reference: "libpurple/eventloop.h") */ - session->con->inpa = purple_input_add( session->fd, PURPLE_INPUT_READ, mxit_cb_rx, session ); + session->inpa = purple_input_add( session->fd, PURPLE_INPUT_READ, mxit_cb_rx, session ); mxit_connected( session ); } @@ -202,7 +205,7 @@ /* socket connection */ data = purple_proxy_connect( session->con, session->acc, session->server, session->port, mxit_cb_connect, session ); if ( !data ) { - purple_connection_error( session->con, _( "Unable to connect to the MXit server. Please check your server settings." ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Unable to connect to the MXit server. Please check your server settings." ) ); return; } } @@ -221,7 +224,7 @@ */ static void mxit_cb_register_ok( PurpleConnection *gc, PurpleRequestFields *fields ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); struct MXitProfile* profile = session->profile; const char* str; const char* pin; @@ -303,7 +306,7 @@ purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_register_cancel\n" ); /* disconnect */ - purple_account_disconnect( gc->account ); + purple_account_disconnect( purple_connection_get_account( gc ) ); } @@ -391,7 +394,7 @@ if ( !url_text ) { /* no reply from the WAP site */ - purple_connection_error( session->con, _( "Error contacting the MXit WAP site. Please try again later." ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Error contacting the MXit WAP site. Please try again later." ) ); return; } @@ -400,7 +403,7 @@ if ( !parts ) { /* wapserver error */ - purple_connection_error( session->con, _( "MXit is currently unable to process the request. Please try again later." ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "MXit is currently unable to process the request. Please try again later." ) ); return; } @@ -410,26 +413,26 @@ /* valid reply! */ break; case '1' : - purple_connection_error( session->con, _( "Wrong security code entered. Please try again later." ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Wrong security code entered. Please try again later." ) ); return; case '2' : - purple_connection_error( session->con, _( "Your session has expired. Please try again later." ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Your session has expired. Please try again later." ) ); return; case '5' : - purple_connection_error( session->con, _( "Invalid country selected. Please try again." ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Invalid country selected. Please try again." ) ); return; case '6' : - purple_connection_error( session->con, _( "The MXit ID you entered is not registered. Please register first." ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "The MXit ID you entered is not registered. Please register first." ) ); return; case '7' : - purple_connection_error( session->con, _( "The MXit ID you entered is already registered. Please choose another." ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "The MXit ID you entered is already registered. Please choose another." ) ); /* this user's account already exists, so we need to change the registration login flag to be login */ purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN ); return; case '3' : case '4' : default : - purple_connection_error( session->con, _( "Internal error. Please try again later." ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Internal error. Please try again later." ) ); return; } @@ -507,7 +510,7 @@ */ static void mxit_cb_captcha_ok( PurpleConnection* gc, PurpleRequestFields* fields ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); PurpleUtilFetchUrlData* url_data; PurpleRequestField* field; const char* captcha_resp; @@ -548,10 +551,24 @@ state = purple_account_get_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN ); url = g_strdup_printf( "%s?type=getpid&sessionid=%s&login=%s&ver=%i.%i.%i&clientid=%s&cat=%s&chalresp=%s&cc=%s&loc=%s&path=%i&brand=%s&model=%s&h=%i&w=%i&ts=%li", - session->logindata->wapserver, session->logindata->sessionid, purple_url_encode( session->acc->username ), PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CLIENT_ID, MXIT_CP_ARCH, - captcha_resp, session->logindata->cc, session->logindata->locale, ( state == MXIT_STATE_REGISTER1 ) ? 0 : 1, MXIT_CP_PLATFORM, MXIT_CP_OS, - MXIT_CAPTCHA_HEIGHT, MXIT_CAPTCHA_WIDTH, time( NULL ) ); - url_data = purple_util_fetch_url_request( url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, mxit_cb_clientinfo2, session ); + session->logindata->wapserver, + session->logindata->sessionid, + purple_url_encode( purple_account_get_username( session->acc ) ), + PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, + MXIT_CLIENT_ID, + MXIT_CP_ARCH, + captcha_resp, + session->logindata->cc, + session->logindata->locale, + ( state == MXIT_STATE_REGISTER1 ) ? 0 : 1, + MXIT_CP_PLATFORM, + MXIT_CP_OS, + MXIT_CAPTCHA_HEIGHT, + MXIT_CAPTCHA_WIDTH, + time( NULL ) + ); + /* FIXME: This should be cancelled somewhere if not needed. */ + url_data = purple_util_fetch_url_request( session->acc, url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, -1, mxit_cb_clientinfo2, session ); #ifdef DEBUG_PROTOCOL purple_debug_info( MXIT_PLUGIN_ID, "HTTP REQUEST: '%s'\n", url ); @@ -571,7 +588,7 @@ */ static void mxit_cb_captcha_cancel( PurpleConnection* gc, PurpleRequestFields* fields ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); /* free up the login resources */ free_logindata( session->logindata ); @@ -611,7 +628,7 @@ if ( !url_text ) { /* no reply from the WAP site */ - purple_connection_error( session->con, _( "Error contacting the MXit WAP site. Please try again later." ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Error contacting the MXit WAP site. Please try again later." ) ); return; } @@ -620,7 +637,7 @@ if ( ( !parts ) || ( parts[0][0] != '0' ) ) { /* server could not find the user */ - purple_connection_error( session->con, _( "MXit is currently unable to process the request. Please try again later." ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "MXit is currently unable to process the request. Please try again later." ) ); return; } @@ -658,7 +675,7 @@ /* oops, this is not good, time to bail */ break; } - purple_request_field_list_add( field, country[1], g_strdup( country[0] ) ); + purple_request_field_list_add_icon( field, country[1], NULL, g_strdup( country[0] ) ); if ( strcmp( country[1], parts[6] ) == 0 ) { /* based on the user's IP, this is his current country code, so we default to it */ purple_request_field_list_add_selected( field, country[1] ); @@ -679,7 +696,7 @@ /* oops, this is not good, time to bail */ break; } - purple_request_field_list_add( field, locale[1], g_strdup( locale[0] ) ); + purple_request_field_list_add_icon( field, locale[1], NULL, g_strdup( locale[0] ) ); g_strfreev( locale ); } purple_request_field_list_add_selected( field, "English" ); @@ -715,7 +732,8 @@ /* reference: "libpurple/util.h" */ url = g_strdup_printf( "%s/res/?type=challenge&getcountries=true&getlanguage=true&getimage=true&h=%i&w=%i&ts=%li", wapserver, MXIT_CAPTCHA_HEIGHT, MXIT_CAPTCHA_WIDTH, time( NULL ) ); - url_data = purple_util_fetch_url_request( url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, mxit_cb_clientinfo1, session ); + /* FIXME: This should be cancelled somewhere if not needed. */ + url_data = purple_util_fetch_url_request( session->acc, url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, -1, mxit_cb_clientinfo1, session ); #ifdef DEBUG_PROTOCOL purple_debug_info( MXIT_PLUGIN_ID, "HTTP REQUEST: '%s'\n", url ); @@ -743,7 +761,7 @@ * if we don't have any info saved from a previous login, we need to get it from the MXit WAP site. * we do cache it, so this step is only done on the very first login for each account. */ - if ( ( session->distcode == NULL ) || ( strlen( session->distcode ) == 0 ) ) { + if ( ( session->distcode == NULL ) || ( !*session->distcode ) ) { /* this must be the very first login, so we need to retrieve the user information */ get_clientinfo( session ); } @@ -764,9 +782,9 @@ purple_debug_info( MXIT_PLUGIN_ID, "mxit_reconnect\n" ); /* remove the input cb function */ - if ( session->con->inpa ) { - purple_input_remove( session->con->inpa ); - session->con->inpa = 0; + if ( session->inpa ) { + purple_input_remove( session->inpa ); + session->inpa = 0; } /* close existing connection */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/markup.c --- a/libpurple/protocols/mxit/markup.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/markup.c Fri Apr 06 04:30:00 2012 +0000 @@ -124,10 +124,11 @@ * Adds a link to a message * * @param mx The Markup message object - * @param linkname This is the what will be returned when the link gets clicked - * @param displayname This is the name for the link which will be displayed in the UI + * @param replydata This is the what will be returned when the link gets clicked + * @param isStructured Indicates that the reply is a structured reply + * @param displaytext This is the text for the link which will be displayed in the UI */ -void mxit_add_html_link( struct RXMsgData* mx, const char* linkname, const char* displayname ) +void mxit_add_html_link( struct RXMsgData* mx, const char* replydata, gboolean isStructured, const char* displaytext ) { #ifdef MXIT_LINK_CLICK char retstr[256]; @@ -135,15 +136,24 @@ char link[256]; int len; - len = g_snprintf( retstr, sizeof( retstr ), "%s|%s|%s|%s|%s", MXIT_LINK_KEY, purple_account_get_username( mx->session->acc ), - purple_account_get_protocol_id( mx->session->acc ), mx->from, linkname ); + /* + * The link content is encoded as follows: + * MXIT_LINK_KEY | ACCOUNT_USER | ACCOUNT_PROTO | REPLY_TO | REPLY_FORMAT | REPLY_DATA + */ + len = g_snprintf( retstr, sizeof( retstr ), "%s|%s|%s|%s|%i|%s", + MXIT_LINK_KEY, + purple_account_get_username( mx->session->acc ), + purple_account_get_protocol_id( mx->session->acc ), + mx->from, + isStructured ? 1 : 0, + replydata ); retstr64 = purple_base64_encode( (const unsigned char*) retstr, len ); g_snprintf( link, sizeof( link ), "%s%s", MXIT_LINK_PREFIX, retstr64 ); g_free( retstr64 ); - g_string_append_printf( mx->msg, "%s", link, displayname ); + g_string_append_printf( mx->msg, "%s", link, displaytext ); #else - g_string_append_printf( mx->msg, "%s", linkname ); + g_string_append_printf( mx->msg, "%s", replydata ); #endif } @@ -618,7 +628,8 @@ /* reference: "libpurple/util.h" */ url = g_strdup_printf( "%s/res/?type=emo&mlh=%i&sc=%s&ts=%li", wapserver, MXIT_EMOTICON_SIZE, id, time( NULL ) ); - url_data = purple_util_fetch_url_request( url, TRUE, NULL, TRUE, NULL, FALSE, emoticon_returned, mx ); + /* FIXME: This should be cancelled somewhere if not needed. */ + url_data = purple_util_fetch_url( url, TRUE, NULL, TRUE, -1, emoticon_returned, mx ); g_free( url ); } @@ -735,6 +746,7 @@ gboolean tag_bold = FALSE; gboolean tag_under = FALSE; gboolean tag_italic = FALSE; + int font_size = 0; #ifdef MXIT_DEBUG_MARKUP purple_debug_info( MXIT_PLUGIN_ID, "Markup RX (original): '%s'\n", message ); @@ -823,7 +835,7 @@ if ( ch ) { /* end found */ *ch = '\0'; - mxit_add_html_link( mx, &message[i + 1], &message[i + 1] ); + mxit_add_html_link( mx, &message[i + 1], FALSE, &message[i + 1] ); *ch = '$'; i += ( ch - &message[i + 1] ) + 1; } @@ -862,59 +874,54 @@ } break; case '.' : - if ( !( msgflags & CP_MSG_EMOTICON ) ) { - g_string_append_c( mx->msg, message[i] ); - break; - } - else if ( i + 1 >= len ) { + if ( i + 1 >= len ) { /* message too short */ g_string_append_c( mx->msg, '.' ); break; } - switch ( message[i+1] ) { - case '+' : - /* increment text size */ - g_string_append( mx->msg, "" ); - i++; - break; - case '-' : - /* decrement text size */ - g_string_append( mx->msg, "" ); - i++; - break; - case '{' : - /* custom emoticon */ - if ( i + 2 >= len ) { - /* message too short */ - g_string_append_c( mx->msg, '.' ); - break; - } + if ( ( msgflags & CP_MSG_EMOTICON ) && ( message[i+1] == '{' ) ) { + /* custom emoticon */ + if ( i + 2 >= len ) { + /* message too short */ + g_string_append_c( mx->msg, '.' ); + break; + } + + parse_emoticon_str( &message[i+2], tmpstr1 ); + if ( tmpstr1[0] != '\0' ) { + mx->got_img = TRUE; + + if ( g_hash_table_lookup( mx->session->iimages, tmpstr1 ) ) { + /* emoticon found in the cache, so we do not have to request it from the WAPsite */ + } + else { + /* request emoticon from the WAPsite */ + mx->img_count++; + emoticon_request( mx, tmpstr1 ); + } - parse_emoticon_str( &message[i+2], tmpstr1 ); - if ( tmpstr1[0] != '\0' ) { - mx->got_img = TRUE; + g_string_append_printf( mx->msg, MXIT_II_TAG"%s>", tmpstr1 ); + i += strlen( tmpstr1 ) + 2; + } + else + g_string_append_c( mx->msg, '.' ); + } + else if ( ( msgflags & CP_MSG_MARKUP ) && ( message[i+1] == '+' ) ) { + /* increment text size */ + font_size++; + g_string_append_printf( mx->msg, "", font_size ); + i++; + } + else if ( ( msgflags & CP_MSG_MARKUP ) && ( message[i+1] == '-' ) ) { + /* decrement text size */ + font_size--; + g_string_append_printf( mx->msg, "", font_size ); + i++; + } + else + g_string_append_c( mx->msg, '.' ); - if ( g_hash_table_lookup( mx->session->iimages, tmpstr1 ) ) { - /* emoticon found in the cache, so we do not have to request it from the WAPsite */ - } - else { - /* request emoticon from the WAPsite */ - mx->img_count++; - emoticon_request( mx, tmpstr1 ); - } - - g_string_append_printf( mx->msg, MXIT_II_TAG"%s>", tmpstr1 ); - i += strlen( tmpstr1 ) + 2; - } - else - g_string_append_c( mx->msg, '.' ); - - break; - default : - g_string_append_c( mx->msg, '.' ); - break; - } break; case '\\' : if ( i + 1 >= len ) { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/markup.h --- a/libpurple/protocols/mxit/markup.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/markup.h Fri Apr 06 04:30:00 2012 +0000 @@ -31,7 +31,7 @@ void mxit_parse_markup( struct RXMsgData* mx, char* message, int len, short msgtype, int msgflags ); char* mxit_convert_markup_tx( const char* message, int* msgtype ); -void mxit_add_html_link( struct RXMsgData* mx, const char* linkname, const char* displayname ); +void mxit_add_html_link( struct RXMsgData* mx, const char* replydata, gboolean isStructured, const char* displaytext ); void mxit_show_message( struct RXMsgData* mx ); void mxit_free_emoticon_cache( struct MXitSession* session ); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/multimx.c --- a/libpurple/protocols/mxit/multimx.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/multimx.c Fri Apr 06 04:30:00 2012 +0000 @@ -277,7 +277,11 @@ GHashTable *components; struct multimx* multimx = NULL; - purple_debug_info(MXIT_PLUGIN_ID, "Groupchat invite to '%s' by '%s'\n", contact->alias, creator); + purple_debug_info(MXIT_PLUGIN_ID, "Groupchat invite to '%s' (roomid='%s') by '%s'\n", contact->alias, contact->username, creator); + + /* Check if the room already exists (ie, already joined or invite pending) */ + if (find_room_by_username(session, contact->username) != NULL) + return; /* Create a new room */ multimx = room_create(session, contact->username, contact->alias, STATE_INVITED); @@ -307,7 +311,7 @@ multimx = find_room_by_username(session, contact->username); if (multimx == NULL) { multimx = room_create(session, contact->username, contact->alias, TRUE); - } + } else if (multimx->state == STATE_INVITED) { /* After successfully accepting an invitation */ multimx->state = STATE_JOINED; @@ -454,7 +458,7 @@ */ void mxit_chat_join(PurpleConnection *gc, GHashTable *components) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data(gc); const char* roomname = NULL; struct multimx* multimx = NULL; @@ -496,7 +500,7 @@ */ void mxit_chat_reject(PurpleConnection *gc, GHashTable* components) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data(gc); const char* roomname = NULL; struct multimx* multimx = NULL; @@ -539,7 +543,7 @@ */ void mxit_chat_invite(PurpleConnection *gc, int id, const char *msg, const char *username) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data(gc); struct multimx* multimx = NULL; PurpleBuddy* buddy; PurpleConversation *convo; @@ -585,7 +589,7 @@ */ void mxit_chat_leave(PurpleConnection *gc, int id) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data(gc); struct multimx* multimx = NULL; purple_debug_info(MXIT_PLUGIN_ID, "Groupchat %i leave\n", id); @@ -616,7 +620,7 @@ */ int mxit_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data(gc); struct multimx* multimx = NULL; const char* nickname; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/mxit.c --- a/libpurple/protocols/mxit/mxit.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/mxit.c Fri Apr 06 04:30:00 2012 +0000 @@ -58,7 +58,7 @@ static void* mxit_link_click( const char* link64 ) { PurpleAccount* account; - PurpleConnection* con; + PurpleConnection* gc; gchar** parts = NULL; gchar* link = NULL; gsize len; @@ -75,10 +75,10 @@ link = (gchar*) purple_base64_decode( link64 + strlen( MXIT_LINK_PREFIX ), &len ); purple_debug_info( MXIT_PLUGIN_ID, "Clicked Link: '%s'\n", link ); - parts = g_strsplit( link, "|", 5 ); + parts = g_strsplit( link, "|", 6 ); /* check if this is a valid mxit link */ - if ( ( !parts ) || ( !parts[0] ) || ( !parts[1] ) || ( !parts[2] ) || ( !parts[3] ) || ( !parts[4] ) ) { + if ( ( !parts ) || ( !parts[0] ) || ( !parts[1] ) || ( !parts[2] ) || ( !parts[3] ) || ( !parts[4] ) || ( !parts[5] ) ) { /* this is not for us */ goto skip; } @@ -91,15 +91,15 @@ account = purple_accounts_find( parts[1], parts[2] ); if ( !account ) goto skip; - con = purple_account_get_connection( account ); - if ( !con ) + gc = purple_account_get_connection( account ); + if ( !gc ) goto skip; /* determine if it's a command-response to send */ - is_command = g_str_has_prefix( parts[4], "::type=reply|" ); + is_command = ( atoi( parts[4] ) == 1 ); /* send click message back to MXit */ - mxit_send_message( con->proto_data, parts[3], parts[4], FALSE, is_command ); + mxit_send_message( purple_connection_get_protocol_data( gc ), parts[3], parts[5], FALSE, is_command ); g_free( link ); link = NULL; @@ -129,7 +129,7 @@ /*------------------------------------------------------------------------ * Register MXit to receive URI click notifications from the UI */ -void mxit_register_uri_handler(void) +void mxit_register_uri_handler( void ) { not_link_ref_count++; if ( not_link_ref_count == 1 ) { @@ -176,7 +176,7 @@ const char* who; char* tmp; - gc = purple_conversation_get_gc( conv ); + gc = purple_conversation_get_connection( conv ); if ( session->con != gc ) { /* not our conversation */ return; @@ -198,7 +198,7 @@ if ( !buddy ) return; - contact = purple_buddy_get_protocol_data(buddy); + contact = purple_buddy_get_protocol_data( buddy ); if ( !contact ) return; @@ -214,7 +214,7 @@ case MXIT_TYPE_INFO : tmp = g_strdup_printf("%s\n", _( "Loading menu..." )); serv_got_im( session->con, who, tmp, PURPLE_MESSAGE_NOTIFY, time( NULL ) ); - g_free(tmp); + g_free( tmp ); mxit_send_message( session, who, " ", FALSE, FALSE ); default : break; @@ -268,7 +268,7 @@ */ static const char* mxit_list_emblem( PurpleBuddy* buddy ) { - struct contact* contact = purple_buddy_get_protocol_data(buddy); + struct contact* contact = purple_buddy_get_protocol_data( buddy ); if ( !contact ) return NULL; @@ -309,19 +309,18 @@ */ char* mxit_status_text( PurpleBuddy* buddy ) { - struct contact* contact = purple_buddy_get_protocol_data(buddy); + char* text = NULL; + struct contact* contact = purple_buddy_get_protocol_data( buddy ); if ( !contact ) return NULL; - if ( contact->statusMsg ) { - /* status message */ - return g_strdup( contact-> statusMsg ); - } - else { - /* mood */ - return g_strdup( mxit_convert_mood_to_name( contact->mood ) ); - } + if ( contact->statusMsg ) /* status message */ + text = g_strdup( contact-> statusMsg ); + else if ( contact->mood != MXIT_MOOD_NONE ) /* mood */ + text = g_strdup( mxit_convert_mood_to_name( contact->mood ) ); + + return text; } @@ -334,34 +333,33 @@ */ static void mxit_tooltip( PurpleBuddy* buddy, PurpleNotifyUserInfo* info, gboolean full ) { - struct contact* contact = purple_buddy_get_protocol_data(buddy); + struct contact* contact = purple_buddy_get_protocol_data( buddy ); if ( !contact ) return; /* status (reference: "libpurple/notify.h") */ if ( contact->presence != MXIT_PRESENCE_OFFLINE ) - purple_notify_user_info_add_pair( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) ); /* status message */ - if ( contact->statusMsg ) - purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg ); + if ( contact->statusMsg ) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html( info, _( "Status Message" ), contact->statusMsg ); + } /* mood */ if ( contact->mood != MXIT_MOOD_NONE ) - purple_notify_user_info_add_pair( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) ); /* subscription type */ if ( contact->subtype != 0 ) - purple_notify_user_info_add_pair( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) ); /* rejection message */ if ( ( contact->subtype == MXIT_SUBTYPE_REJECTED ) && ( contact->msg != NULL ) ) - purple_notify_user_info_add_pair( info, _( "Rejection Message" ), contact->msg ); - - /* hidden number */ - if ( contact->flags & MXIT_CFLAG_HIDDEN ) - purple_notify_user_info_add_pair( info, _( "Hidden Number" ), _( "Yes" ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Rejection Message" ), contact->msg ); } @@ -372,7 +370,7 @@ */ static void mxit_close( PurpleConnection* gc ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); /* disable signals */ mxit_disable_signals( session ); @@ -408,7 +406,7 @@ { purple_debug_info( MXIT_PLUGIN_ID, "Sending message '%s' to buddy '%s'\n", message, who ); - mxit_send_message( gc->proto_data, who, message, TRUE, FALSE ); + mxit_send_message( purple_connection_get_protocol_data( gc ), who, message, TRUE, FALSE ); return 1; /* echo to conversation window */ } @@ -422,14 +420,14 @@ */ static void mxit_set_status( PurpleAccount* account, PurpleStatus* status ) { - struct MXitSession* session = purple_account_get_connection( account )->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( purple_account_get_connection( account ) ); const char* statusid; int presence; char* statusmsg1; char* statusmsg2; /* Handle mood changes */ - if (purple_status_type_get_primitive(purple_status_get_type(status)) == PURPLE_STATUS_MOOD) { + if ( purple_status_type_get_primitive(purple_status_get_type( status ) ) == PURPLE_STATUS_MOOD ) { const char* moodid = purple_status_get_attr_string( status, PURPLE_MOOD_NAME ); int mood; @@ -492,7 +490,7 @@ purple_debug_info( MXIT_PLUGIN_ID, "mxit_free_buddy\n" ); - contact = purple_buddy_get_protocol_data(buddy); + contact = purple_buddy_get_protocol_data( buddy ); if ( contact ) { if ( contact->statusMsg ) g_free( contact->statusMsg ); @@ -503,7 +501,7 @@ g_free( contact ); } - purple_buddy_set_protocol_data(buddy, NULL); + purple_buddy_set_protocol_data( buddy, NULL ); } @@ -515,7 +513,7 @@ */ static void mxit_keepalive( PurpleConnection *gc ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); /* if not logged in, there is nothing to do */ if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) @@ -543,7 +541,7 @@ */ static void mxit_set_buddy_icon( PurpleConnection *gc, PurpleStoredImage *img ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); if ( img == NULL ) mxit_set_avatar( session, NULL, 0 ); @@ -562,7 +560,7 @@ { PurpleBuddy* buddy; struct contact* contact; - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); const char* profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_LASTSEEN, CP_PROFILE_STATUS, CP_PROFILE_AVATAR, CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME }; @@ -612,14 +610,10 @@ */ static void mxit_reinvite( PurpleBlistNode *node, gpointer ignored ) { - PurpleBuddy* buddy; + PurpleBuddy* buddy = (PurpleBuddy *) node; + PurpleConnection* gc = purple_account_get_connection( purple_buddy_get_account( buddy ) ); + struct MXitSession* session = purple_connection_get_protocol_data( gc ); struct contact* contact; - PurpleConnection* gc; - struct MXitSession* session; - - buddy = (PurpleBuddy *)node; - gc = purple_account_get_connection( purple_buddy_get_account( buddy ) ); - session = gc->proto_data; contact = purple_buddy_get_protocol_data( (PurpleBuddy*) node ); if ( !contact ) @@ -653,15 +647,28 @@ if ( ( contact->subtype == MXIT_SUBTYPE_DELETED ) || ( contact->subtype == MXIT_SUBTYPE_REJECTED ) || ( contact->subtype == MXIT_SUBTYPE_NONE ) ) { /* contact is in Deleted, Rejected or None state */ act = purple_menu_action_new( _( "Re-Invite" ), PURPLE_CALLBACK( mxit_reinvite ), NULL, NULL ); - m = g_list_append(m, act); + m = g_list_append( m, act ); } return m; } + +/*------------------------------------------------------------------------ + * Return Chat-room default settings. + * + * @return Chat defaults list + */ +static GHashTable *mxit_chat_info_defaults( PurpleConnection *gc, const char *chat_name ) +{ + return g_hash_table_new_full( g_str_hash, g_str_equal, NULL, g_free ); +} + + /*========================================================================================================================*/ static PurplePluginProtocolInfo proto_info = { + sizeof( PurplePluginProtocolInfo ), /* struct_size */ OPT_PROTO_REGISTER_NOSCREENNAME | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE, /* options */ NULL, /* user_splits */ NULL, /* protocol_options */ @@ -680,7 +687,7 @@ mxit_status_types, /* status types [roster.c] */ mxit_blist_menu, /* blist_node_menu */ mxit_chat_info, /* chat_info [multimx.c] */ - NULL, /* chat_info_defaults */ + mxit_chat_info_defaults,/* chat_info_defaults */ mxit_login, /* login [login.c] */ mxit_close, /* close */ mxit_send_im, /* send_im */ @@ -690,7 +697,7 @@ mxit_set_status, /* set_status */ NULL, /* set_idle */ NULL, /* change_passwd */ - NULL, /* add_buddy [roster.c] */ + mxit_add_buddy, /* add_buddy [roster.c] */ NULL, /* add_buddies */ mxit_remove_buddy, /* remove_buddy [roster.c] */ NULL, /* remove_buddies */ @@ -709,7 +716,6 @@ mxit_keepalive, /* keepalive */ mxit_register, /* register_user */ NULL, /* get_cb_info */ - NULL, /* get_cb_away */ mxit_buddy_alias, /* alias_buddy [roster.c] */ mxit_buddy_group, /* group_buddy [roster.c] */ mxit_rename_group, /* rename_group [roster.c] */ @@ -734,15 +740,12 @@ NULL, /* unregister_user */ NULL, /* send_attention */ NULL, /* attention_types */ - sizeof( PurplePluginProtocolInfo ), /* struct_size */ mxit_get_text_table, /* get_account_text_table */ mxit_media_initiate, /* initiate_media */ mxit_media_caps, /* get_media_caps */ mxit_get_moods, /* get_moods */ NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - mxit_add_buddy, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ + NULL /* get_public_alias */ }; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/mxit.h --- a/libpurple/protocols/mxit/mxit.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/mxit.h Fri Apr 06 04:30:00 2012 +0000 @@ -161,6 +161,7 @@ /* libpurple */ PurpleAccount* acc; /* pointer to the libpurple internal account struct */ PurpleConnection* con; /* pointer to the libpurple internal connection struct */ + guint inpa; /* the input watcher */ /* transmit */ struct tx_queue queue; /* transmit packet queue (FIFO mode) */ @@ -191,7 +192,7 @@ void mxit_enable_signals( struct MXitSession* session ); #ifdef MXIT_LINK_CLICK -void mxit_register_uri_handler(void); +void mxit_register_uri_handler( void ); #endif diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/profile.c --- a/libpurple/protocols/mxit/profile.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/profile.c Fri Apr 06 04:30:00 2012 +0000 @@ -115,16 +115,16 @@ struct tm now, bdate; int age; - if ( ( !date ) || ( strlen( date ) == 0 ) ) + if ( ( !date ) || ( !*date ) ) return 0; /* current time */ - t = time(NULL); + t = time( NULL ); localtime_r( &t, &now ); /* decode hdate */ memset( &bdate, 0, sizeof( struct tm ) ); - purple_str_to_time(date, FALSE, &bdate, NULL, NULL); + purple_str_to_time( date, FALSE, &bdate, NULL, NULL ); /* calculate difference */ age = now.tm_year - bdate.tm_year; @@ -170,54 +170,56 @@ buddy = purple_find_buddy( session->acc, username ); if ( buddy ) { - purple_notify_user_info_add_pair( info, _( "Alias" ), purple_buddy_get_alias( buddy ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Alias" ), purple_buddy_get_alias( buddy ) ); purple_notify_user_info_add_section_break( info ); - contact = purple_buddy_get_protocol_data(buddy); + contact = purple_buddy_get_protocol_data( buddy ); } - purple_notify_user_info_add_pair( info, _( "Display Name" ), profile->nickname ); + purple_notify_user_info_add_pair_plaintext( info, _( "Display Name" ), profile->nickname ); tmp = g_strdup_printf("%s (%i)", profile->birthday, calculateAge( profile->birthday ) ); - purple_notify_user_info_add_pair( info, _( "Birthday" ), tmp ); + purple_notify_user_info_add_pair_plaintext( info, _( "Birthday" ), tmp ); g_free( tmp ); - purple_notify_user_info_add_pair( info, _( "Gender" ), profile->male ? _( "Male" ) : _( "Female" ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Gender" ), profile->male ? _( "Male" ) : _( "Female" ) ); /* optional information */ - purple_notify_user_info_add_pair( info, _( "First Name" ), profile->firstname ); - purple_notify_user_info_add_pair( info, _( "Last Name" ), profile->lastname ); - purple_notify_user_info_add_pair( info, _( "Country" ), profile->regcountry ); + purple_notify_user_info_add_pair_plaintext( info, _( "First Name" ), profile->firstname ); + purple_notify_user_info_add_pair_plaintext( info, _( "Last Name" ), profile->lastname ); + + purple_notify_user_info_add_pair_plaintext( info, _( "Country" ), profile->regcountry ); - if ( strlen( profile->aboutme ) > 0 ) - purple_notify_user_info_add_pair( info, _( "About Me" ), profile->aboutme ); - if ( strlen( profile->whereami ) > 0 ) - purple_notify_user_info_add_pair( info, _( "Where I Live" ), profile->whereami ); + if ( *profile->aboutme ) + purple_notify_user_info_add_pair_plaintext( info, _( "About Me" ), profile->aboutme ); + + if ( *profile->whereami ) + purple_notify_user_info_add_pair_plaintext( info, _( "Where I Live" ), profile->whereami ); purple_notify_user_info_add_section_break( info ); if ( contact ) { /* presence */ - purple_notify_user_info_add_pair( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) ); /* last online */ if ( contact->presence == MXIT_PRESENCE_OFFLINE ) - purple_notify_user_info_add_pair( info, _( "Last Online" ), ( profile->lastonline == 0 ) ? _( "Unknown" ) : datetime( profile->lastonline ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Last Online" ), ( profile->lastonline == 0 ) ? _( "Unknown" ) : datetime( profile->lastonline ) ); /* mood */ if ( contact->mood != MXIT_MOOD_NONE ) - purple_notify_user_info_add_pair( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) ); else - purple_notify_user_info_add_pair( info, _( "Mood" ), _( "None" ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Mood" ), _( "None" ) ); /* status message */ - if ( contact->statusMsg ) - purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg ); + if ( contact->statusMsg ) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html( info, _( "Status Message" ), contact->statusMsg ); + } /* subscription type */ - purple_notify_user_info_add_pair( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) ); - - /* hidden number */ - purple_notify_user_info_add_pair( info, _( "Hidden Number" ), ( contact->flags & MXIT_CFLAG_HIDDEN ) ? _( "Yes" ) : _( "No" ) ); + purple_notify_user_info_add_pair_plaintext( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) ); } else { /* this is an invite */ @@ -226,17 +228,21 @@ /* invite found */ if ( contact->msg ) - purple_notify_user_info_add_pair( info, _( "Invite Message" ), contact->msg ); + purple_notify_user_info_add_pair_plaintext( info, _( "Invite Message" ), contact->msg ); if ( contact->imgid ) { /* this invite has a avatar */ char* img_text; img_text = g_strdup_printf( "", contact->imgid ); - purple_notify_user_info_add_pair( info, _( "Photo" ), img_text ); + purple_notify_user_info_add_pair_html( info, _( "Photo" ), img_text ); + g_free(img_text); } - if ( contact->statusMsg ) - purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg ); + if ( contact->statusMsg ) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html( info, _( "Status Message" ), contact->statusMsg ); + } } } @@ -284,6 +290,7 @@ /* define columns */ column = purple_notify_searchresults_column_new( _( "UserId" ) ); + purple_notify_searchresult_column_set_visible( column, FALSE ); purple_notify_searchresults_column_add( results, column ); column = purple_notify_searchresults_column_new( _( "Display Name" ) ); purple_notify_searchresults_column_add( results, column ); @@ -298,7 +305,7 @@ column = purple_notify_searchresults_column_new( _( "Where I live" ) ); purple_notify_searchresults_column_add( results, column ); - while (entries != NULL) { + while ( entries != NULL ) { struct MXitProfile* profile = ( struct MXitProfile *) entries->data; GList* row; gchar* tmp = purple_base64_encode( (unsigned char *) profile->userid, strlen( profile->userid ) ); @@ -328,5 +335,5 @@ purple_notify_searchresults( session->con, NULL, text, NULL, results, NULL, NULL ); - g_free( text); + g_free( text ); } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/profile.h --- a/libpurple/protocols/mxit/profile.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/profile.h Fri Apr 06 04:30:00 2012 +0000 @@ -50,7 +50,6 @@ int flags; /* user's profile flags */ gint64 lastonline; /* user's last-online timestamp */ - gboolean hidden; /* set if the user's mxitid should remain hidden */ }; struct MXitSession; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/protocol.c --- a/libpurple/protocols/mxit/protocol.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/protocol.c Fri Apr 06 04:30:00 2012 +0000 @@ -86,7 +86,7 @@ void mxit_strip_domain( char* username ) { if ( g_str_has_suffix( username, "@m" ) ) - username[ strlen(username) - 2 ] = '\0'; + username[ strlen( username ) - 2 ] = '\0'; } @@ -311,7 +311,7 @@ #endif /* send the HTTP request */ - session->http_out_req = purple_util_fetch_url_request( url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, mxit_cb_http_rx, session ); + session->http_out_req = purple_util_fetch_url_request( session->acc, url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, -1, mxit_cb_http_rx, session ); g_free( url ); if ( part ) @@ -408,7 +408,7 @@ res = mxit_write_sock_packet( session->fd, data, datalen ); if ( res < 0 ) { /* we must have lost the connection, so terminate it so that we can reconnect */ - purple_connection_error( session->con, _( "We have lost the connection to MXit. Please reconnect." ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "We have lost the connection to MXit. Please reconnect." ) ); } } else { @@ -458,7 +458,7 @@ packet->headerlen = 0; /* create generic packet header */ - hlen = snprintf( header, sizeof( header ), "id=%s%c", session->acc->username, CP_REC_TERM ); /* client msisdn */ + hlen = snprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc), CP_REC_TERM ); /* client msisdn */ if ( session->http ) { /* http connection only */ @@ -530,7 +530,7 @@ if ( session->last_tx <= mxit_now_milli() - ( MXIT_ACK_TIMEOUT * 1000 ) ) { /* ack timeout! so we close the connection here */ purple_debug_info( MXIT_PLUGIN_ID, "mxit_manage_queue: Timeout awaiting ACK for command '%i'\n", session->outack ); - purple_connection_error( session->con, _( "Timeout while waiting for a response from the MXit server." ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Timeout while waiting for a response from the MXit server." ) ); } return; } @@ -704,9 +704,9 @@ locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE ); /* Voice and Video supported */ - if (mxit_audio_enabled() && mxit_video_enabled()) - features |= (MXIT_CF_VOICE | MXIT_CF_VIDEO); - else if (mxit_audio_enabled()) + if ( mxit_audio_enabled() && mxit_video_enabled() ) + features |= ( MXIT_CF_VOICE | MXIT_CF_VIDEO ); + else if ( mxit_audio_enabled() ) features |= MXIT_CF_VOICE; /* generate client version string (eg, P-2.7.10-Y-PURPLE) */ @@ -718,7 +718,7 @@ "%s%c%i%c%s%c%s%c" /* dateOfBirth\1gender\1location\1capabilities\1 */ "%s%c%i%c%s%c%s" /* dc\1features\1dialingcode\1locale */ "%c%i%c%i", /* \1protocolVer\1lastRosterUpdate */ - session->encpwd, CP_FLD_TERM, clientVersion, CP_FLD_TERM, CP_MAX_FILESIZE, CP_FLD_TERM, profile->nickname, CP_FLD_TERM, + session->encpwd, CP_FLD_TERM, clientVersion, CP_FLD_TERM, CP_MAX_PACKET, CP_FLD_TERM, profile->nickname, CP_FLD_TERM, profile->birthday, CP_FLD_TERM, ( profile->male ) ? 1 : 0, CP_FLD_TERM, MXIT_DEFAULT_LOC, CP_FLD_TERM, MXIT_CP_CAP, CP_FLD_TERM, session->distcode, CP_FLD_TERM, features, CP_FLD_TERM, session->dialcode, CP_FLD_TERM, locale, CP_FLD_TERM, MXIT_CP_PROTO_VESION, CP_FLD_TERM, 0 @@ -748,9 +748,9 @@ locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE ); /* Voice and Video supported */ - if (mxit_audio_enabled() && mxit_video_enabled()) - features |= (MXIT_CF_VOICE | MXIT_CF_VIDEO); - else if (mxit_audio_enabled()) + if ( mxit_audio_enabled() && mxit_video_enabled() ) + features |= ( MXIT_CF_VOICE | MXIT_CF_VIDEO ); + else if ( mxit_audio_enabled() ) features |= MXIT_CF_VOICE; /* generate client version string (eg, P-2.7.10-Y-PURPLE) */ @@ -765,7 +765,7 @@ session->encpwd, CP_FLD_TERM, clientVersion, CP_FLD_TERM, 1, CP_FLD_TERM, MXIT_CP_CAP, CP_FLD_TERM, session->distcode, CP_FLD_TERM, features, CP_FLD_TERM, session->dialcode, CP_FLD_TERM, locale, CP_FLD_TERM, - CP_MAX_FILESIZE, CP_FLD_TERM, MXIT_CP_PROTO_VESION, CP_FLD_TERM, 0 + CP_MAX_PACKET, CP_FLD_TERM, MXIT_CP_PROTO_VESION, CP_FLD_TERM, 0 ); /* include "custom resource" information */ @@ -835,7 +835,7 @@ /* add attributes */ for ( i = 0; i < nr_attrib; i++ ) - datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] ); + datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] ); /* queue packet for transmission */ mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_GET ); @@ -868,7 +868,7 @@ /* add attributes */ for ( i = 1; i < nr_attrib * 3; i+=3 ) - datalen += sprintf( data + datalen, "%c%s%c%s%c%s", /* \1name\1type\1value */ + datalen += sprintf( data + datalen, "%c%s%c%s%c%s", /* \1name\1type\1value */ CP_FLD_TERM, parts[i], CP_FLD_TERM, parts[i + 1], CP_FLD_TERM, parts[i + 2] ); /* queue packet for transmission */ @@ -900,7 +900,7 @@ /* add attributes */ for ( i = 0; i < nr_attrib; i++ ) - datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] ); + datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] ); /* queue packet for transmission */ mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS ); @@ -929,7 +929,7 @@ /* add attributes */ for ( i = 0; i < nr_attrib; i++ ) - datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] ); + datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] ); /* queue packet for transmission */ mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS ); @@ -1175,7 +1175,7 @@ /* add usernames */ for ( i = 0; i < nr_usernames; i++ ) - datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, usernames[i] ); + datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, usernames[i] ); /* queue packet for transmission */ mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_CREATE ); @@ -1204,7 +1204,7 @@ /* add usernames */ for ( i = 0; i < nr_usernames; i++ ) - datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, usernames[i] ); + datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, usernames[i] ); /* queue packet for transmission */ mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_INVITE ); @@ -1448,7 +1448,7 @@ PurpleStatus* status; int presence; const char* statusmsg; - const char* profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_HIDENUMBER, CP_PROFILE_FULLNAME, + const char* profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_TITLE, CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_EMAIL, CP_PROFILE_MOBILENR, CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME, CP_PROFILE_FLAGS }; @@ -1516,6 +1516,7 @@ { struct RXMsgData* mx = NULL; char* message = NULL; + char* sender = NULL; int msglen = 0; int msgflags = 0; int msgtype = 0; @@ -1529,10 +1530,11 @@ msglen = strlen( message ); /* strip off dummy domain */ - mxit_strip_domain( records[0]->fields[0]->data ); + sender = records[0]->fields[0]->data; + mxit_strip_domain( sender ); #ifdef DEBUG_PROTOCOL - purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", records[0]->fields[0]->data ); + purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", sender ); #endif /* decode message flags (if any) */ @@ -1540,33 +1542,42 @@ msgflags = atoi( records[0]->fields[4]->data ); msgtype = atoi( records[0]->fields[2]->data ); - if ( msgflags & CP_MSG_ENCRYPTED ) { - /* this is an encrypted message. we do not currently support those so ignore it */ + if ( msgflags & CP_MSG_PWD_ENCRYPTED ) { + /* this is a password encrypted message. we do not currently support those so ignore it */ PurpleBuddy* buddy; const char* name; char msg[128]; - buddy = purple_find_buddy( session->acc, records[0]->fields[0]->data ); + buddy = purple_find_buddy( session->acc, sender ); if ( buddy ) name = purple_buddy_get_alias( buddy ); else - name = records[0]->fields[0]->data; + name = sender; g_snprintf( msg, sizeof( msg ), _( "%s sent you an encrypted message, but it is not supported on this client." ), name ); mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), msg ); return; } + else if ( msgflags & CP_MSG_TL_ENCRYPTED ) { + /* this is a transport-layer encrypted message. */ + message = mxit_decrypt_message( session, message ); + if ( !message ) { + /* could not be decrypted */ + serv_got_im( session->con, sender, _( "An encrypted message was received which could not be decrypted." ), PURPLE_MESSAGE_ERROR, time( NULL ) ); + return; + } + } if ( msgflags & CP_MSG_NOTIFY_DELIVERY ) { /* delivery notification is requested */ if ( records[0]->fcount >= 4 ) - mxit_send_msgevent( session, records[0]->fields[0]->data, records[0]->fields[3]->data, CP_MSGEVENT_DELIVERED ); + mxit_send_msgevent( session, sender, records[0]->fields[3]->data, CP_MSGEVENT_DELIVERED ); } /* create and initialise new markup struct */ mx = g_new0( struct RXMsgData, 1 ); mx->msg = g_string_sized_new( msglen ); mx->session = session; - mx->from = g_strdup( records[0]->fields[0]->data ); + mx->from = g_strdup( sender ); mx->timestamp = atoi( records[0]->fields[1]->data ); mx->got_img = FALSE; mx->chatid = -1; @@ -1597,6 +1608,10 @@ * so the image received callback function will eventually display * the message. */ } + + /* cleanup */ + if ( msgflags & CP_MSG_TL_ENCRYPTED ) + g_free( message ); } @@ -1633,7 +1648,7 @@ if ( rec->fcount >= 5 ) { /* there is a personal invite message attached */ - if ( ( rec->fields[4]->data ) && ( strlen( rec->fields[4]->data ) > 0 ) ) + if ( ( rec->fields[4]->data ) && ( *rec->fields[4]->data ) ) contact->msg = strdup( rec->fields[4]->data ); } @@ -1810,10 +1825,6 @@ /* gender */ profile->male = ( fvalue[0] == '1' ); } - else if ( strcmp( CP_PROFILE_HIDENUMBER, fname ) == 0 ) { - /* hide number */ - profile->hidden = ( fvalue[0] == '1' ); - } else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) { /* nickname */ g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) ); @@ -1879,7 +1890,7 @@ contact = get_mxit_invite_contact( session, mxitId ); if ( contact ) { /* this is an invite, so update its profile info */ - if ( ( statusMsg ) && ( strlen( statusMsg ) > 0 ) ) { + if ( ( statusMsg ) && ( *statusMsg ) ) { /* update the status message */ if ( contact->statusMsg ) g_free( contact->statusMsg ); @@ -1890,7 +1901,7 @@ if ( contact->profile ) g_free( contact->profile ); contact->profile = profile; - if ( ( avatarId ) && ( strlen( avatarId ) > 0 ) ) { + if ( ( avatarId ) && ( *avatarId ) ) { /* avatar must be requested for this invite before we can display it */ mxit_get_avatar( session, mxitId, avatarId ); if ( contact->avatarId ) @@ -1908,7 +1919,7 @@ if ( avatarId ) mxit_update_buddy_avatar( session, mxitId, avatarId ); - if ( ( statusMsg ) && ( strlen( statusMsg ) > 0 ) ) { + if ( ( statusMsg ) && ( *statusMsg ) ) { /* update the status message */ PurpleBuddy* buddy = NULL; @@ -2125,13 +2136,13 @@ contact = get_mxit_invite_contact( session, chunk.mxitid ); if ( contact ) { /* this is an invite (add image to the internal image store) */ - contact->imgid = purple_imgstore_add_with_id( chunk.data, chunk.length, NULL ); + contact->imgid = purple_imgstore_add_with_id( g_memdup( chunk.data, chunk.length ), chunk.length, NULL ); /* show the profile */ mxit_show_profile( session, chunk.mxitid, contact->profile ); } else { /* this is a contact's avatar, so update it */ - purple_buddy_icons_set_for_user( session->acc, chunk.mxitid, g_memdup( chunk.data, chunk.length), chunk.length, chunk.avatarid ); + purple_buddy_icons_set_for_user( session->acc, chunk.mxitid, g_memdup( chunk.data, chunk.length ), chunk.length, chunk.avatarid ); } } } @@ -2192,7 +2203,7 @@ session->port = atoi( host[2] ); } else { - purple_connection_error( session->con, _( "Cannot perform redirect using the specified protocol" ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Cannot perform redirect using the specified protocol" ) ); goto redirect_fail; } @@ -2270,7 +2281,7 @@ case CP_CMD_PRESENCE : /* presence update */ - mxit_parse_cmd_presence(session, &packet->records[2], packet->rcount - 3 ); + mxit_parse_cmd_presence( session, &packet->records[2], packet->rcount - 3 ); break; case CP_CMD_RX_MSG : @@ -2361,7 +2372,7 @@ if ( packet->errcode == MXIT_ERRCODE_LOGGEDOUT ) { /* we are not currently logged in, so we need to reconnect */ - purple_connection_error( session->con, _( errdesc ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( errdesc ) ); } /* packet command */ @@ -2375,12 +2386,12 @@ } else { snprintf( errmsg, sizeof( errmsg ), _( "Login error: %s (%i)" ), errdesc, packet->errcode ); - purple_connection_error( session->con, errmsg ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, errmsg ); return -1; } case CP_CMD_LOGOUT : snprintf( errmsg, sizeof( errmsg ), _( "Logout error: %s (%i)" ), errdesc, packet->errcode ); - purple_connection_error_reason( session->con, PURPLE_CONNECTION_ERROR_NAME_IN_USE, _( errmsg ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NAME_IN_USE, _( errmsg ) ); return -1; case CP_CMD_CONTACT : mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Error" ), _( errdesc ) ); @@ -2643,7 +2654,7 @@ if ( packet.rcount < 2 ) { /* bad packet */ - purple_connection_error( session->con, _( "Invalid packet received from MXit." ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Invalid packet received from MXit." ) ); free_rx_packet( &packet ); continue; } @@ -2708,12 +2719,12 @@ len = read( session->fd, &ch, 1 ); if ( len < 0 ) { /* connection error */ - purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x01)" ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x01)" ) ); return; } else if ( len == 0 ) { /* connection closed */ - purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x02)" ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x02)" ) ); return; } else { @@ -2723,7 +2734,7 @@ session->rx_lbuf[session->rx_i] = '\0'; session->rx_res = atoi( &session->rx_lbuf[3] ); if ( session->rx_res > CP_MAX_PACKET ) { - purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x03)" ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x03)" ) ); } session->rx_state = RX_STATE_DATA; session->rx_i = 0; @@ -2734,7 +2745,7 @@ session->rx_i++; if ( session->rx_i >= sizeof( session->rx_lbuf ) ) { /* malformed packet length record (too long) */ - purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x04)" ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x04)" ) ); return; } } @@ -2745,12 +2756,12 @@ len = read( session->fd, &session->rx_dbuf[session->rx_i], session->rx_res ); if ( len < 0 ) { /* connection error */ - purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x05)" ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x05)" ) ); return; } else if ( len == 0 ) { /* connection closed */ - purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x06)" ) ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x06)" ) ); return; } else { @@ -2808,9 +2819,9 @@ } /* remove the input cb function */ - if ( session->con->inpa ) { - purple_input_remove( session->con->inpa ); - session->con->inpa = 0; + if ( session->inpa ) { + purple_input_remove( session->inpa ); + session->inpa = 0; } /* remove HTTP poll timer */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/protocol.h --- a/libpurple/protocols/mxit/protocol.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/protocol.h Fri Apr 06 04:30:00 2012 +0000 @@ -34,8 +34,7 @@ #define CP_PKT_TERM '\x02' /* packet terminator */ -#define CP_MAX_PACKET ( 1024 * 1024 ) /* maximum client protocol packet size (1 MiB) */ -#define CP_MAX_FILESIZE ( 150 * 1000 ) /* maximum client protocol file transfer size (150 KB) */ +#define CP_MAX_PACKET ( 1 * 1000 * 1000 ) /* maximum client protocol packet size (1 MB) */ #define MXIT_EMOTICON_SIZE 18 /* icon size for custom emoticons */ #define CP_MAX_STATUS_MSG 250 /* maximum status message length (in characters) */ @@ -77,6 +76,7 @@ #define MXIT_CF_GAMING_UPDATE 0x800000 #define MXIT_CF_VOICE 0x1000000 #define MXIT_CF_VIDEO 0x2000000 +#define MXIT_CF_TOUCHSCREEN 0x4000000 /* Client features supported by this implementation */ #define MXIT_CP_FEATURES ( MXIT_CF_FILE_TRANSFER | MXIT_CF_FILE_ACCESS | MXIT_CF_AUDIO | MXIT_CF_MARKUP | MXIT_CF_EXT_MARKUP | MXIT_CF_NO_GATEWAYS | MXIT_CF_IMAGES | MXIT_CF_COMMANDS | MXIT_CF_VIBES | MXIT_CF_MIDP2 ) @@ -155,7 +155,10 @@ /* message flags */ #define CP_MSG_NOTIFY_DELIVERY 0x0002 /* request delivery notification */ #define CP_MSG_NOTIFY_READ 0x0004 /* request read notification */ -#define CP_MSG_ENCRYPTED 0x0010 /* message is encrypted */ +#define CP_MSG_PWD_ENCRYPTED 0x0010 /* message is password encrypted */ +#define CP_MSG_TL_ENCRYPTED 0x0020 /* message is transport encrypted */ +#define CP_MSG_RPLY_PWD_ENCRYPT 0x0040 /* reply should be password encrypted */ +#define CP_MSG_RPLY_TL_ENCRYPT 0x0080 /* reply should be transport encrypted */ #define CP_MSG_MARKUP 0x0200 /* message may contain markup */ #define CP_MSG_EMOTICON 0x0400 /* message may contain custom emoticons */ @@ -179,7 +182,7 @@ /* extended profile attribute fields */ #define CP_PROFILE_BIRTHDATE "birthdate" /* Birthdate (String - ISO 8601 format) */ #define CP_PROFILE_GENDER "gender" /* Gender (Boolean - 0=female, 1=male) */ -#define CP_PROFILE_HIDENUMBER "hidenumber" /* Hide Number (Boolean - 0=false, 1=true) */ +// #define CP_PROFILE_HIDENUMBER "hidenumber" /* Hide Number (Boolean - 0=false, 1=true) (DEPRECATED) */ #define CP_PROFILE_FULLNAME "fullname" /* Fullname (UTF8 String) */ #define CP_PROFILE_STATUS "statusmsg" /* Status Message (UTF8 String) */ #define CP_PROFILE_PREVSTATUS "prevstatusmsgs" /* Previous Status Messages (UTF8 String) */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/roster.c --- a/libpurple/protocols/mxit/roster.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/roster.c Fri Apr 06 04:30:00 2012 +0000 @@ -82,9 +82,9 @@ } /* add Mood option */ - type = purple_status_type_new_with_attrs(PURPLE_STATUS_MOOD, "mood", NULL, FALSE, TRUE, TRUE, + type = purple_status_type_new_with_attrs( PURPLE_STATUS_MOOD, "mood", NULL, FALSE, TRUE, TRUE, PURPLE_MOOD_NAME, _("Mood Name"), purple_value_new( PURPLE_TYPE_STRING ), - NULL); + NULL ); statuslist = g_list_append( statuslist, type ); return statuslist; @@ -135,21 +135,21 @@ /* moods (reference: libpurple/status.h) */ static PurpleMood mxit_moods[] = { - {"angry", N_("Angry"), NULL}, - {"excited", N_("Excited"), NULL}, - {"grumpy", N_("Grumpy"), NULL}, - {"happy", N_("Happy"), NULL}, - {"in_love", N_("In love"), NULL}, - {"invincible", N_("Invincible"), NULL}, - {"sad", N_("Sad"), NULL}, - {"hot", N_("Hot"), NULL}, - {"sick", N_("Sick"), NULL}, - {"sleepy", N_("Sleepy"), NULL}, - {"bored", N_("Bored"), NULL}, - {"cold", N_("Cold"), NULL}, - {"confused", N_("Confused"), NULL}, - {"hungry", N_("Hungry"), NULL}, - {"stressed", N_("Stressed"), NULL}, + { "angry", N_( "Angry" ), NULL }, + { "excited", N_( "Excited" ), NULL }, + { "grumpy", N_( "Grumpy" ), NULL }, + { "happy", N_( "Happy" ), NULL }, + { "in_love", N_( "In love" ), NULL }, + { "invincible", N_( "Invincible" ), NULL }, + { "sad", N_( "Sad" ), NULL }, + { "hot", N_( "Hot" ), NULL }, + { "sick", N_( "Sick" ), NULL }, + { "sleepy", N_( "Sleepy" ), NULL }, + { "bored", N_( "Bored" ), NULL }, + { "cold", N_( "Cold" ), NULL }, + { "confused", N_( "Confused" ), NULL }, + { "hungry", N_( "Hungry" ), NULL }, + { "stressed", N_( "Stressed" ), NULL }, /* Mark the last record. */ { NULL, NULL, NULL } }; @@ -293,14 +293,15 @@ */ static PurpleBuddy* mxit_update_buddy_group( struct MXitSession* session, PurpleBuddy* buddy, PurpleGroup* group ) { - struct contact* contact = NULL; PurpleGroup* current_group = purple_buddy_get_group( buddy ); - PurpleBuddy* newbuddy = NULL; /* make sure the groups actually differs */ if ( strcmp( current_group->name, group->name ) != 0 ) { /* groupnames does not match, so we need to make the update */ + struct contact* contact = purple_buddy_get_protocol_data( buddy ); + PurpleBuddy* newbuddy = NULL; + purple_debug_info( MXIT_PLUGIN_ID, "Moving '%s' from group '%s' to '%s'\n", buddy->alias, current_group->name, group->name ); /* @@ -310,10 +311,10 @@ * again. This is really not ideal and very irritating, but how else then? */ - /* create new buddy */ + /* create new buddy, and transfer 'contact' data */ newbuddy = purple_buddy_new( session->acc, buddy->name, buddy->alias ); - newbuddy->proto_data = buddy->proto_data; - buddy->proto_data = NULL; + purple_buddy_set_protocol_data( newbuddy, contact ); + purple_buddy_set_protocol_data( buddy, NULL ); /* remove the buddy */ purple_blist_remove_buddy( buddy ); @@ -322,7 +323,6 @@ purple_blist_add_buddy( newbuddy, NULL, group, NULL ); /* now re-instate his presence again */ - contact = newbuddy->proto_data; if ( contact ) { /* update the buddy's status (reference: "libpurple/prpl.h") */ @@ -396,7 +396,7 @@ /* create new buddy */ buddy = purple_buddy_new( session->acc, contact->username, contact->alias ); - purple_buddy_set_protocol_data(buddy, contact); + purple_buddy_set_protocol_data( buddy, contact ); /* add new buddy to list */ purple_blist_add_buddy( buddy, NULL, group, NULL ); @@ -728,7 +728,7 @@ */ void mxit_add_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group, const char* message ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); GSList* list = NULL; PurpleBuddy* mxbuddy = NULL; unsigned int i; @@ -804,7 +804,7 @@ */ void mxit_remove_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); const gchar * buddy_name = purple_buddy_get_name( buddy ); purple_debug_info( MXIT_PLUGIN_ID, "mxit_remove_buddy '%s'\n", buddy_name ); @@ -822,7 +822,7 @@ */ void mxit_buddy_alias( PurpleConnection* gc, const char* who, const char* alias ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); PurpleBuddy* buddy = NULL; PurpleGroup* group = NULL; @@ -856,7 +856,7 @@ */ void mxit_buddy_group( PurpleConnection* gc, const char* who, const char* old_group, const char* new_group ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); PurpleBuddy* buddy = NULL; purple_debug_info( MXIT_PLUGIN_ID, "mxit_buddy_group from '%s' to '%s'\n", old_group, new_group ); @@ -883,7 +883,7 @@ */ void mxit_rename_group( PurpleConnection* gc, const char* old_name, PurpleGroup* group, GList* moved_buddies ) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data( gc ); PurpleBuddy* buddy = NULL; GList* item = NULL; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/roster.h --- a/libpurple/protocols/mxit/roster.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/roster.h Fri Apr 06 04:30:00 2012 +0000 @@ -74,7 +74,7 @@ /* MXit contact flags */ -#define MXIT_CFLAG_HIDDEN 0x02 +//#define MXIT_CFLAG_HIDDEN 0x02 /* (DEPRECATED) */ #define MXIT_CFLAG_GATEWAY 0x04 #define MXIT_CFLAG_FOCUS_SEND_BLANK 0x20000 @@ -96,7 +96,7 @@ /* client protocol constants */ #define MXIT_CP_MAX_JID_LEN 64 #define MXIT_CP_MAX_GROUP_LEN 32 -#define MXIT_CP_MAX_ALIAS_LEN 48 +#define MXIT_CP_MAX_ALIAS_LEN 100 #define MXIT_DEFAULT_GROUP "MXit" @@ -106,8 +106,8 @@ */ struct contact { char username[MXIT_CP_MAX_JID_LEN+1]; /* unique contact name (with domain) */ - char alias[MXIT_CP_MAX_GROUP_LEN+1]; /* contact alias (what will be seen) */ - char groupname[MXIT_CP_MAX_ALIAS_LEN+1]; /* contact group name */ + char alias[MXIT_CP_MAX_ALIAS_LEN+1]; /* contact alias (what will be seen) */ + char groupname[MXIT_CP_MAX_GROUP_LEN+1]; /* contact group name */ short type; /* contact type */ short mood; /* contact current mood */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/splashscreen.c --- a/libpurple/protocols/mxit/splashscreen.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/splashscreen.c Fri Apr 06 04:30:00 2012 +0000 @@ -144,7 +144,7 @@ */ static void splash_click_ok(PurpleConnection* gc, PurpleRequestFields* fields) { - struct MXitSession* session = (struct MXitSession*) gc->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data(gc); const char* splashId; /* Get current splash ID */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/mxit/voicevideo.c --- a/libpurple/protocols/mxit/voicevideo.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/mxit/voicevideo.c Fri Apr 06 04:30:00 2012 +0000 @@ -63,7 +63,7 @@ */ PurpleMediaCaps mxit_media_caps(PurpleAccount *account, const char *who) { - struct MXitSession* session = purple_account_get_connection(account)->proto_data; + struct MXitSession* session = purple_connection_get_protocol_data(purple_account_get_connection(account)); PurpleBuddy* buddy; struct contact* contact; PurpleMediaCaps capa = PURPLE_MEDIA_CAPS_NONE; @@ -71,7 +71,7 @@ purple_debug_info(MXIT_PLUGIN_ID, "mxit_media_caps: buddy '%s'\n", who); /* We need to have a voice/video server */ - if (strlen(session->voip_server) == 0) + if (!*session->voip_server) return PURPLE_MEDIA_CAPS_NONE; /* find the buddy information for this contact (reference: "libpurple/blist.h") */ @@ -95,7 +95,7 @@ /* and only when they're online */ if (contact->presence == MXIT_PRESENCE_OFFLINE) - return MXIT_PRESENCE_OFFLINE; + return PURPLE_MEDIA_CAPS_NONE; /* they support voice-only */ if (contact->capabilities & MXIT_PFLAG_VOICE) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/myspace/myspace.c --- a/libpurple/protocols/myspace/myspace.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/myspace/myspace.c Fri Apr 06 04:30:00 2012 +0000 @@ -254,7 +254,7 @@ g_return_val_if_fail(who != NULL, FALSE); g_return_val_if_fail(text != NULL, FALSE); - from_username = session->account->username; + from_username = purple_account_get_username(session->account); g_return_val_if_fail(from_username != NULL, FALSE); @@ -429,11 +429,9 @@ user = msim_get_user_from_buddy(buddy, TRUE); if (PURPLE_BUDDY_IS_ONLINE(buddy)) { - MsimSession *session; PurpleAccount *account = purple_buddy_get_account(buddy); PurpleConnection *gc = purple_account_get_connection(account); - - session = (MsimSession *)gc->proto_data; + MsimSession *session = purple_connection_get_protocol_data(gc); /* TODO: if (full), do something different? */ @@ -698,7 +696,7 @@ if (nc_len != MSIM_AUTH_CHALLENGE_LENGTH) { purple_debug_info("msim", "bad nc length: %" G_GSIZE_MODIFIER "x != 0x%x\n", nc_len, MSIM_AUTH_CHALLENGE_LENGTH); - purple_connection_error_reason (session->gc, + purple_connection_error (session->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unexpected challenge length from server")); return FALSE; @@ -707,14 +705,14 @@ purple_connection_update_progress(session->gc, _("Logging in"), 2, 4); response_len = 0; - response = msim_compute_login_response(nc, account->username, account->password, &response_len); + response = msim_compute_login_response(nc, purple_account_get_username(account), purple_account_get_password(account), &response_len); g_free(nc); ret = msim_send(session, "login2", MSIM_TYPE_INTEGER, MSIM_AUTH_ALGORITHM, /* This is actually user's email address. */ - "username", MSIM_TYPE_STRING, g_strdup(account->username), + "username", MSIM_TYPE_STRING, g_strdup(purple_account_get_username(account)), /* GString will be freed in msim_msg_free() in msim_send(). */ "response", MSIM_TYPE_BINARY, g_string_new_len(response, response_len), "clientver", MSIM_TYPE_INTEGER, MSIM_CLIENT_VERSION, @@ -754,8 +752,8 @@ */ purple_debug_info("msim", "Unrecognized data on account for %s\n", - (session && session->account && session->account->username) ? - session->account->username : "(NULL)"); + (session && session->account && purple_account_get_username(session->account)) ? + purple_account_get_username(session->account) : "(NULL)"); if (note) { purple_debug_info("msim", "(Note: %s)\n", note); } @@ -835,7 +833,7 @@ purple_debug_info("msim", "msim_check_alive: %zu > interval of %d, presumed dead\n", delta, MSIM_KEEPALIVE_INTERVAL); - purple_connection_error_reason(session->gc, + purple_connection_error(session->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Lost connection with server")); @@ -1840,7 +1838,7 @@ if (!purple_account_get_remember_password(session->account)) purple_account_set_password(session->account, NULL); #ifdef MSIM_MAX_PASSWORD_LENGTH - if (session->account->password && (strlen(session->account->password) > MSIM_MAX_PASSWORD_LENGTH)) { + if (purple_account_get_password(session->account) && (strlen(purple_account_get_password(session->account)) > MSIM_MAX_PASSWORD_LENGTH)) { gchar *suggestion; suggestion = g_strdup_printf(_("%s Your password is " @@ -1848,7 +1846,7 @@ "maximum length of %d. Please shorten your " "password at http://profileedit.myspace.com/index.cfm?fuseaction=accountSettings.changePassword and try again."), full_errmsg, - strlen(session->account->password), + strlen(purple_account_get_password(session->account)), MSIM_MAX_PASSWORD_LENGTH); /* Replace full_errmsg. */ @@ -1866,7 +1864,7 @@ purple_account_set_password(session->account, NULL); break; } - purple_connection_error_reason(session->gc, reason, full_errmsg); + purple_connection_error(session->gc, reason, full_errmsg); } else { purple_notify_error(session->account, _("MySpaceIM Error"), full_errmsg, NULL); } @@ -2022,12 +2020,12 @@ g_return_if_fail(source >= 0); /* Note: 0 is a valid fd */ gc = (PurpleConnection *)(gc_uncasted); - session = gc->proto_data; + session = purple_connection_get_protocol_data(gc); /* libpurple/eventloop.h only defines these two */ if (cond != PURPLE_INPUT_READ && cond != PURPLE_INPUT_WRITE) { purple_debug_info("msim_input_cb", "unknown condition=%d\n", cond); - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Invalid input condition")); return; @@ -2069,12 +2067,12 @@ tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; } else if (n == 0) { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Server closed the connection")); return; @@ -2092,7 +2090,7 @@ purple_debug_info("msim", "msim_input_cb: strlen=%d, but read %d bytes" "--null byte encountered?\n", strlen(session->rxbuf + session->rxoff), n); - /*purple_connection_error_reason (gc, + /*purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, "Invalid message - null byte on input"); */ return; @@ -2117,7 +2115,7 @@ msg = msim_parse(session->rxbuf); if (!msg) { purple_debug_info("msim", "msim_input_cb: couldn't parse rxbuf\n"); - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to parse message")); break; @@ -2157,20 +2155,19 @@ g_return_if_fail(data != NULL); gc = (PurpleConnection *)data; - session = (MsimSession *)gc->proto_data; + session = purple_connection_get_protocol_data(gc); if (source < 0) { gchar *tmp = g_strdup_printf(_("Unable to connect: %s"), error_message); - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; } session->fd = source; - - gc->inpa = purple_input_add(source, PURPLE_INPUT_READ, msim_input_cb, gc); + session->inpa = purple_input_add(source, PURPLE_INPUT_READ, msim_input_cb, gc); } /** @@ -2186,13 +2183,13 @@ int port; g_return_if_fail(acct != NULL); - g_return_if_fail(acct->username != NULL); - - purple_debug_info("msim", "logging in %s\n", acct->username); + g_return_if_fail(purple_account_get_username(acct) != NULL); + + purple_debug_info("msim", "logging in %s\n", purple_account_get_username(acct)); gc = purple_account_get_connection(acct); - gc->proto_data = msim_session_new(acct); - gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_URLDESC; + purple_connection_set_protocol_data(gc, msim_session_new(acct)); + purple_connection_set_flags(gc, PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_URLDESC); /* * Lets wipe out our local list of blocked buddies. We'll get a @@ -2219,7 +2216,7 @@ if (!purple_proxy_connect(gc, acct, host, port, msim_connect_cb, gc)) { /* TODO: try other ports if in auto mode, then save * working port and try that first next time. */ - purple_connection_error_reason (gc, + purple_connection_error (gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); return; @@ -2259,14 +2256,15 @@ buddies = g_slist_delete_link(buddies, buddies); } - session = (MsimSession *)gc->proto_data; + session = purple_connection_get_protocol_data(gc); if (session == NULL) return; - gc->proto_data = NULL; - - if (session->gc->inpa) { - purple_input_remove(session->gc->inpa); + purple_connection_set_protocol_data(gc, NULL); + + if (session->inpa) { + purple_input_remove(session->inpa); + session->inpa = 0; } if (session->fd >= 0) { close(session->fd); @@ -2304,7 +2302,7 @@ /* 'flags' has many options, not used here. */ - session = (MsimSession *)gc->proto_data; + session = purple_connection_get_protocol_data(gc); message_msim = html_to_msim_markup(session, message); @@ -2344,7 +2342,7 @@ g_return_val_if_fail(gc != NULL, 0); g_return_val_if_fail(name != NULL, 0); - session = (MsimSession *)gc->proto_data; + session = purple_connection_get_protocol_data(gc); switch (state) { case PURPLE_TYPING: @@ -2430,7 +2428,7 @@ g_return_if_fail(gc != NULL); g_return_if_fail(username != NULL); - session = (MsimSession *)gc->proto_data; + session = purple_connection_get_protocol_data(gc); /* Obtain uid of buddy. */ user = msim_find_user(session, username); @@ -2487,6 +2485,7 @@ static void msim_set_status(PurpleAccount *account, PurpleStatus *status) { + PurpleConnection *gc = purple_account_get_connection(account); PurpleStatusType *type; PurplePresence *pres; MsimSession *session; @@ -2495,7 +2494,7 @@ gchar *stripped; gchar *unrecognized_msg; - session = (MsimSession *)account->gc->proto_data; + session = purple_connection_get_protocol_data(gc); type = purple_status_get_type(status); pres = purple_status_get_presence(status); @@ -2544,7 +2543,7 @@ /* If we should be idle, set that status. Time is irrelevant here. */ if (purple_presence_is_idle(pres) && status_code != MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN) - msim_set_idle(account->gc, 1); + msim_set_idle(purple_account_get_connection(account), 1); } /** @@ -2558,7 +2557,7 @@ g_return_if_fail(gc != NULL); - session = (MsimSession *)gc->proto_data; + session = purple_connection_get_protocol_data(gc); status = purple_account_get_active_status(session->account); @@ -2628,7 +2627,7 @@ * Add a buddy to user's buddy list. */ static void -msim_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) +msim_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message) { MsimSession *session; MsimMessage *msg; @@ -2636,7 +2635,7 @@ MsimMessage *body; const char *name, *gname; - session = (MsimSession *)gc->proto_data; + session = purple_connection_get_protocol_data(gc); name = purple_buddy_get_name(buddy); gname = group ? purple_group_get_name(group) : NULL; @@ -2709,7 +2708,7 @@ MsimMessage *persist_msg; const char *name; - session = (MsimSession *)gc->proto_data; + session = purple_connection_get_protocol_data(gc); name = purple_buddy_get_name(buddy); delbuddy_msg = msim_msg_new( @@ -2766,7 +2765,7 @@ MsimSession *session; MsimMessage *msg, *body; - session = (MsimSession *)gc->proto_data; + session = purple_connection_get_protocol_data(gc); /* Remove from buddy list */ msg = msim_msg_new( @@ -2818,7 +2817,7 @@ MsimSession *session; MsimMessage *msg, *body; - session = (MsimSession *)gc->proto_data; + session = purple_connection_get_protocol_data(gc); /* * Remove from our list of blocked contacts, so we know they @@ -2865,7 +2864,7 @@ const char *username; /* If the account does not exist, we can't look up the user. */ - if (!account || !account->gc) + if (!account || !purple_account_get_connection(account)) return str; id = atol(str); @@ -2948,7 +2947,7 @@ g_return_val_if_fail(buf != NULL, -1); g_return_val_if_fail(total_bytes >= 0, -1); - session = (MsimSession *)gc->proto_data; + session = purple_connection_get_protocol_data(gc); /* Loop until all data is sent, or a failure occurs. */ total_bytes_sent = 0; @@ -3008,6 +3007,7 @@ * Callbacks called by Purple, to access this plugin. */ static PurplePluginProtocolInfo prpl_info = { + sizeof(PurplePluginProtocolInfo), /* struct_size */ /* options */ OPT_PROTO_USE_POINTSIZE /* specify font size in sane point size */ | OPT_PROTO_MAIL_CHECK, @@ -3052,7 +3052,6 @@ NULL, /* keepalive */ NULL, /* register_user */ NULL, /* get_cb_info */ - NULL, /* get_cb_away */ NULL, /* alias_buddy */ NULL, /* group_buddy */ NULL, /* rename_group */ @@ -3077,15 +3076,12 @@ NULL, /* unregister_user */ msim_send_attention, /* send_attention */ msim_attention_types, /* attention_types */ - sizeof(PurplePluginProtocolInfo), /* struct_size */ msim_get_account_text_table, /* get_account_text_table */ NULL, /* initiate_media */ NULL, /* get_media_caps */ NULL, /* get_moods */ NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - NULL, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ + NULL /* get_public_alias */ }; /** @@ -3151,7 +3147,7 @@ gchar *group_name; gc = (PurpleConnection *)action->context; - session = (MsimSession *)gc->proto_data; + session = purple_connection_get_protocol_data(gc); group_name = "MySpace Friends"; @@ -3530,6 +3526,7 @@ msim_uri_handler(const gchar *proto, const gchar *cmd, GHashTable *params) { PurpleAccount *account; + PurpleConnection *gc; MsimSession *session; GList *l; gchar *uid_str, *cid_str; @@ -3578,7 +3575,8 @@ return FALSE; } - session = (MsimSession *)account->gc->proto_data; + gc = purple_account_get_connection(account); + session = purple_connection_get_protocol_data(gc); g_return_val_if_fail(session != NULL, FALSE); /* Lookup userid to username. TODO: push this down, to IM sending/contact diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/myspace/session.h --- a/libpurple/protocols/myspace/session.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/myspace/session.h Fri Apr 06 04:30:00 2012 +0000 @@ -38,6 +38,7 @@ int privacy_mode; /**< This is a bitmask */ int offline_message_mode; gint fd; /**< File descriptor to/from server */ + guint inpa; /**< The input watcher */ /* TODO: Remove. */ GHashTable *user_lookup_cb; /**< Username -> userid lookup callback */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/myspace/user.c --- a/libpurple/protocols/myspace/user.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/myspace/user.c Fri Apr 06 04:30:00 2012 +0000 @@ -117,27 +117,33 @@ /* Useful to identify the account the tooltip refers to. * Other prpls show this. */ if (user->username) { - purple_notify_user_info_add_pair(user_info, _("User"), user->username); + purple_notify_user_info_add_pair_plaintext(user_info, _("User"), user->username); } /* a/s/l...the vitals */ if (user->age) { char age[16]; g_snprintf(age, sizeof(age), "%d", user->age); - purple_notify_user_info_add_pair(user_info, _("Age"), age); + purple_notify_user_info_add_pair_plaintext(user_info, _("Age"), age); } if (user->gender && *user->gender) { - purple_notify_user_info_add_pair(user_info, _("Gender"), user->gender); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_plaintext(user_info, _("Gender"), user->gender); } if (user->location && *user->location) { - purple_notify_user_info_add_pair(user_info, _("Location"), user->location); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_plaintext(user_info, _("Location"), user->location); } /* Other information */ if (user->headline && *user->headline) { - purple_notify_user_info_add_pair(user_info, _("Headline"), user->headline); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_plaintext(user_info, _("Headline"), user->headline); } if (user->buddy != NULL) { @@ -153,7 +159,9 @@ str = msim_format_now_playing(artist, title); if (str && *str) { - purple_notify_user_info_add_pair(user_info, _("Song"), str); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_plaintext(user_info, _("Song"), str); } g_free(str); } @@ -163,7 +171,7 @@ if (user->total_friends) { char friends[16]; g_snprintf(friends, sizeof(friends), "%d", user->total_friends); - purple_notify_user_info_add_pair(user_info, _("Total Friends"), friends); + purple_notify_user_info_add_pair_plaintext(user_info, _("Total Friends"), friends); } if (full) { @@ -180,8 +188,11 @@ } else if (cv) { client = g_strdup_printf("Build %d", cv); } - if (client && *client) - purple_notify_user_info_add_pair(user_info, _("Client Version"), client); + if (client && *client) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_plaintext(user_info, _("Client Version"), client); + } g_free(client); } @@ -195,7 +206,7 @@ else profile = g_strdup_printf("%s", user->id, _("View web profile")); - purple_notify_user_info_add_pair(user_info, NULL, profile); + purple_notify_user_info_add_pair_html(user_info, NULL, profile); g_free(profile); } } @@ -373,7 +384,7 @@ if (!previous_url || !g_str_equal(previous_url, user->image_url)) { if (user->url_data != NULL) purple_util_fetch_url_cancel(user->url_data); - user->url_data = purple_util_fetch_url(user->image_url, TRUE, NULL, TRUE, msim_downloaded_buddy_icon, (gpointer)user); + user->url_data = purple_util_fetch_url(user->image_url, TRUE, NULL, TRUE, -1, msim_downloaded_buddy_icon, (gpointer)user); } } else if (g_str_equal(key_str, "LastImageUpdated")) { /* TODO: use somewhere */ @@ -401,7 +412,7 @@ * * @param session * @param msg The user information reply, with any amount of information. - * @param user The structure to save to, or NULL to save in PurpleBuddy->proto_data. + * @param user The structure to save to, or NULL to save in PurpleBuddy's protocol_data. * * Variable information is saved to the passed MsimUser structure. Permanent * information (UserID) is stored in the blist node of the buddy list (and @@ -636,7 +647,7 @@ if (!body) { purple_debug_info("msim_username_is_set_cb", "No body"); /* Error: No body! */ - purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg); + purple_connection_error(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg); } username = msim_msg_get_string(body, "UserName"); code = msim_msg_get_integer(body,"Code"); @@ -678,13 +689,13 @@ NULL)) { /* Error! */ /* Can't set... Disconnect */ - purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg); + purple_connection_error(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg); } } else { /* Error! */ purple_debug_info("msim","username_is_set Error: Invalid cmd/dsn/lid combination"); - purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg); + purple_connection_error(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg); } } @@ -747,7 +758,7 @@ g_return_if_fail(gc != NULL); - session = (MsimSession *)gc->proto_data; + session = purple_connection_get_protocol_data(gc); user_msg = msim_msg_new( "user", MSIM_TYPE_STRING, g_strdup(msim_username_to_set), @@ -782,7 +793,7 @@ if (!body) { purple_debug_info("msim_username_is_available_cb", "No body for %s?!\n", username); - purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, + purple_connection_error(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("An error occurred while trying to set the username. " "Please try again, or visit http://editprofile.myspace.com/index.cfm?" "fuseaction=profile.username to set your username.")); @@ -840,7 +851,7 @@ g_return_if_fail(gc != NULL); - session = (MsimSession *)gc->proto_data; + session = purple_connection_get_protocol_data(gc); purple_debug_info("msim_check_username_availability_cb", "Checking username: %s\n", username_to_check); @@ -867,7 +878,7 @@ purple_debug_info("msim", "Don't set username"); /* Protocol won't log in now without a username set.. Disconnect */ - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("No username set")); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("No username set")); } /** diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/myspace/zap.c --- a/libpurple/protocols/myspace/zap.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/myspace/zap.c Fri Apr 06 04:30:00 2012 +0000 @@ -132,10 +132,10 @@ PurpleAttentionType *attn; PurpleBuddy *buddy; - session = (MsimSession *)gc->proto_data; + session = purple_connection_get_protocol_data(gc); /* Look for this attention type, by the code index given. */ - types = msim_attention_types(gc->account); + types = msim_attention_types(purple_connection_get_account(gc)); attn = (PurpleAttentionType *)g_list_nth_data(types, code); if (!attn) { @@ -175,7 +175,7 @@ /* Find the session */ account = purple_buddy_get_account(buddy); gc = purple_account_get_connection(account); - session = (MsimSession *)gc->proto_data; + session = purple_connection_get_protocol_data(gc); zap = GPOINTER_TO_INT(zap_num_ptr); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/novell/novell.c --- a/libpurple/protocols/novell/novell.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/novell/novell.c Fri Apr 06 04:30:00 2012 +0000 @@ -131,8 +131,8 @@ /* Don't attempt to auto-reconnect if our * password was invalid. */ - if (!purple_account_get_remember_password(gc->account)) - purple_account_set_password(gc->account, NULL); + if (!purple_account_get_remember_password(purple_connection_get_account(gc))) + purple_account_set_password(purple_connection_get_account(gc), NULL); reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; break; default: @@ -140,7 +140,7 @@ reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; } - purple_connection_error_reason(gc, reason, err); + purple_connection_error(gc, reason, err); g_free(err); } } @@ -741,16 +741,16 @@ if (allowed) { - if (!g_slist_find_custom(gc->account->permit, + if (!g_slist_find_custom(purple_connection_get_account(gc)->permit, display_id, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_permit_add(gc->account, display_id, TRUE); + purple_privacy_permit_add(purple_connection_get_account(gc), display_id, TRUE); } } else { - if (!g_slist_find_custom(gc->account->permit, + if (!g_slist_find_custom(purple_connection_get_account(gc)->permit, display_id, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_deny_add(gc->account, display_id, TRUE); + purple_privacy_deny_add(purple_connection_get_account(gc), display_id, TRUE); } } @@ -789,10 +789,10 @@ if (display_id) { - if (!g_slist_find_custom(gc->account->deny, + if (!g_slist_find_custom(purple_connection_get_account(gc)->deny, display_id, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_deny_add(gc->account, display_id, TRUE); + purple_privacy_deny_add(purple_connection_get_account(gc), display_id, TRUE); } } else { @@ -840,11 +840,11 @@ if (display_id) { - if (!g_slist_find_custom(gc->account->permit, + if (!g_slist_find_custom(purple_connection_get_account(gc)->permit, display_id, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_permit_add(gc->account, display_id, TRUE); + purple_privacy_permit_add(purple_connection_get_account(gc), display_id, TRUE); } } else { @@ -1126,7 +1126,7 @@ if (_is_disconnect_error(err)) { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Error communicating with server. Closing connection.")); return TRUE; @@ -1177,7 +1177,6 @@ const char *dn; const char *name; int idle = 0; - gboolean loggedin = TRUE; account = purple_buddy_get_account(buddy); name = purple_buddy_get_name(buddy); @@ -1194,7 +1193,6 @@ break; case NM_STATUS_OFFLINE: status_id = NOVELL_STATUS_TYPE_OFFLINE; - loggedin = FALSE; break; case NM_STATUS_AWAY_IDLE: status_id = NOVELL_STATUS_TYPE_AWAY; @@ -1202,7 +1200,6 @@ break; default: status_id = NOVELL_STATUS_TYPE_OFFLINE; - loggedin = FALSE; break; } @@ -1404,15 +1401,15 @@ /* Set the Purple privacy setting */ if (user->default_deny) { if (user->allow_list == NULL) { - gc->account->perm_deny = PURPLE_PRIVACY_DENY_ALL; + purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_DENY_ALL); } else { - gc->account->perm_deny = PURPLE_PRIVACY_ALLOW_USERS; + purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_ALLOW_USERS); } } else { if (user->deny_list == NULL) { - gc->account->perm_deny = PURPLE_PRIVACY_ALLOW_ALL; + purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_ALLOW_ALL); } else { - gc->account->perm_deny = PURPLE_PRIVACY_DENY_USERS; + purple_account_set_privacy_type(purple_connection_get_account(gc), PURPLE_PRIVACY_DENY_USERS); } } @@ -1424,9 +1421,9 @@ else name =(char *)node->data; - if (!g_slist_find_custom(gc->account->permit, + if (!g_slist_find_custom(purple_connection_get_account(gc)->permit, name, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_permit_add(gc->account, name , TRUE); + purple_privacy_permit_add(purple_connection_get_account(gc), name , TRUE); } } @@ -1437,15 +1434,15 @@ else name =(char *)node->data; - if (!g_slist_find_custom(gc->account->deny, + if (!g_slist_find_custom(purple_connection_get_account(gc)->deny, name, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_deny_add(gc->account, name, TRUE); + purple_privacy_deny_add(purple_connection_get_account(gc), name, TRUE); } } /* Remove stuff */ - for (node = gc->account->permit; node; node = node->next) { + for (node = purple_connection_get_account(gc)->permit; node; node = node->next) { dn = nm_lookup_dn(user, (char *)node->data); if (dn != NULL && !g_slist_find_custom(user->allow_list, @@ -1456,13 +1453,13 @@ if (rem_list) { for (node = rem_list; node; node = node->next) { - purple_privacy_permit_remove(gc->account, (char *)node->data, TRUE); + purple_privacy_permit_remove(purple_connection_get_account(gc), (char *)node->data, TRUE); } g_slist_free(rem_list); rem_list = NULL; } - for (node = gc->account->deny; node; node = node->next) { + for (node = purple_connection_get_account(gc)->deny; node; node = node->next) { dn = nm_lookup_dn(user, (char *)node->data); if (dn != NULL && !g_slist_find_custom(user->deny_list, @@ -1473,7 +1470,7 @@ if (rem_list) { for (node = rem_list; node; node = node->next) { - purple_privacy_deny_remove(gc->account, (char *)node->data, TRUE); + purple_privacy_deny_remove(purple_connection_get_account(gc), (char *)node->data, TRUE); } g_slist_free(rem_list); } @@ -1515,20 +1512,27 @@ tag = _("User ID"); value = nm_user_record_get_userid(user_record); if (value) { - purple_notify_user_info_add_pair(user_info, tag, value); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, tag, value); } -/* tag = _("DN"); +#if 0 + tag = _("DN"); value = nm_user_record_get_dn(user_record); if (value) { - purple_notify_user_info_add_pair(user_info, tag, value); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, tag, value); } -*/ +#endif /* if 0 */ tag = _("Full name"); value = nm_user_record_get_full_name(user_record); if (value) { - purple_notify_user_info_add_pair(user_info, tag, value); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, tag, value); } count = nm_user_record_get_property_count(user_record); @@ -1538,7 +1542,9 @@ tag = _map_property_tag(nm_property_get_tag(property)); value = nm_property_get_value(property); if (tag && value) { - purple_notify_user_info_add_pair(user_info, tag, value); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, tag, value); } nm_release_property(property); } @@ -1620,7 +1626,7 @@ buddy = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user == NULL) return; @@ -1676,7 +1682,7 @@ NMUser *user; gc = data; - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); user->conn->ssl_conn->data = NULL; purple_connection_ssl_error (gc, error); @@ -1693,7 +1699,7 @@ if (gc == NULL) return; - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user == NULL) return; @@ -1702,7 +1708,7 @@ if (_is_disconnect_error(rc)) { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Error communicating with server. Closing connection.")); } else { @@ -1727,7 +1733,7 @@ if (gc == NULL || gsc == NULL) return; - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if ((user == NULL) || (conn = user->conn) == NULL) return; @@ -1743,7 +1749,7 @@ conn->connected = TRUE; purple_ssl_input_add(gsc, novell_ssl_recv_cb, gc); } else { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); } @@ -2028,7 +2034,7 @@ { if (!purple_account_get_remember_password(account)) purple_account_set_password(account, NULL); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NAME_IN_USE, _("You have signed on from another location")); } @@ -2184,7 +2190,7 @@ */ /* ...but for now just error out with a nice message. */ - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, _("Unable to connect to server. Please enter the " "address of the server to which you wish to connect.")); @@ -2197,7 +2203,7 @@ user = nm_initialize_user(name, server, port, account, _event_callback); if (user && user->conn) { /* save user */ - gc->proto_data = user; + purple_connection_set_protocol_data(gc, user); /* connect to the server */ purple_connection_update_progress(gc, _("Connecting"), @@ -2213,7 +2219,7 @@ user->conn->addr, user->conn->port, novell_ssl_connected_cb, novell_ssl_connect_error, gc); if (user->conn->ssl_conn->data == NULL) { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("SSL support unavailable")); } @@ -2229,7 +2235,7 @@ if (gc == NULL) return; - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user) { conn = user->conn; if (conn && conn->ssl_conn) { @@ -2237,7 +2243,7 @@ } nm_deinitialize_user(user); } - gc->proto_data = NULL; + purple_connection_set_protocol_data(gc, NULL); } static int @@ -2257,7 +2263,7 @@ message_body == NULL || *message_body == '\0') return 0; - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user == NULL) return 0; @@ -2343,7 +2349,7 @@ if (gc == NULL || name == NULL) return 0; - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user == NULL) return 0; @@ -2377,7 +2383,7 @@ if (gc == NULL || who == NULL) return; - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user && (dn = nm_lookup_dn(user, who))) { conf = nm_find_conversation(user, dn); if (conf) { @@ -2399,7 +2405,7 @@ if (gc == NULL) return; - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user == NULL) return; @@ -2431,7 +2437,7 @@ if (gc == NULL) return; - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user == NULL) return; @@ -2470,7 +2476,7 @@ if (gc == NULL || text == NULL) return -1; - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user == NULL) return -1; @@ -2536,7 +2542,7 @@ } static void -novell_add_buddy(PurpleConnection * gc, PurpleBuddy *buddy, PurpleGroup * group) +novell_add_buddy(PurpleConnection * gc, PurpleBuddy *buddy, PurpleGroup * group, const char *message) { NMFolder *folder = NULL; NMContact *contact; @@ -2610,7 +2616,7 @@ if (gc == NULL || buddy == NULL || group == NULL) return; - user = (NMUser *) gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user && (dn = nm_lookup_dn(user, purple_buddy_get_name(buddy)))) { gname = purple_group_get_name(group); if (strcmp(gname, NM_ROOT_FOLDER_NAME) == 0) { @@ -2642,7 +2648,7 @@ if (gc == NULL || group == NULL) return; - user = (NMUser *) gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user) { NMFolder *folder = nm_find_folder(user, purple_group_get_name(group)); @@ -2667,7 +2673,7 @@ if (gc == NULL || name == NULL || alias == NULL) return; - user = (NMUser *) gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user && (dn = nm_lookup_dn(user, name))) { /* Alias all of instances of the contact */ @@ -2726,7 +2732,7 @@ old_group_name == NULL || new_group_name == NULL) return; - user = (NMUser *) gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user && (dn = nm_lookup_dn(user, name))) { /* Find the old folder */ @@ -2784,7 +2790,7 @@ return; } - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user) { const char *gname = purple_group_get_name(group); /* Does new folder exist already? */ @@ -2830,7 +2836,7 @@ return; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); - if (gc == NULL || (user = gc->proto_data) == NULL) + if (gc == NULL || (user = purple_connection_get_protocol_data(gc)) == NULL) return; if (PURPLE_BUDDY_IS_ONLINE(buddy)) { @@ -2860,10 +2866,13 @@ break; } - purple_notify_user_info_add_pair(user_info, _("Status"), status_str); - - if (text) - purple_notify_user_info_add_pair(user_info, _("Message"), text); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), status_str); + + if (text) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Message"), text); + } } } } @@ -2879,7 +2888,7 @@ if (gc == NULL) return; - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user == NULL) return; @@ -2908,7 +2917,7 @@ if (gc == NULL || name == NULL) return; - user = (NMUser *) gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user) { user_record = nm_find_user_record(user, name); @@ -2937,17 +2946,19 @@ if (buddy && account) { PurpleConnection *gc = purple_account_get_connection(account); - if (gc && gc->proto_data) { - NMUser *user = gc->proto_data; - - dn = nm_lookup_dn(user, purple_buddy_get_name(buddy)); - if (dn) { - NMUserRecord *user_record = nm_find_user_record(user, dn); - - if (user_record) { - text = nm_user_record_get_status_text(user_record); - if (text) - return g_strdup(text); + if (gc) { + NMUser *user = purple_connection_get_protocol_data(gc); + + if (user) { + dn = nm_lookup_dn(user, purple_buddy_get_name(buddy)); + if (dn) { + NMUserRecord *user_record = nm_find_user_record(user, dn); + + if (user_record) { + text = nm_user_record_get_status_text(user_record); + if (text) + return g_strdup(text); + } } } } @@ -3023,7 +3034,7 @@ return; gc = purple_account_get_connection(account); - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user == NULL) return; @@ -3070,14 +3081,14 @@ if (gc == NULL || who == NULL) return; - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user == NULL) return; /* Remove first -- we will add it back in when we get * the okay from the server */ - purple_privacy_permit_remove(gc->account, who, TRUE); + purple_privacy_permit_remove(purple_connection_get_account(gc), who, TRUE); if (nm_user_is_privacy_locked(user)) { _show_privacy_locked_error(gc, user); @@ -3114,14 +3125,14 @@ if (gc == NULL || who == NULL) return; - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user == NULL) return; /* Remove first -- we will add it back in when we get * the okay from the server */ - purple_privacy_deny_remove(gc->account, who, TRUE); + purple_privacy_deny_remove(purple_connection_get_account(gc), who, TRUE); if (nm_user_is_privacy_locked(user)) { _show_privacy_locked_error(gc, user); @@ -3158,7 +3169,7 @@ if (gc == NULL || who == NULL) return; - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user == NULL) return; @@ -3188,7 +3199,7 @@ if (gc == NULL || who == NULL) return; - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user == NULL) return; @@ -3223,7 +3234,7 @@ if (gc == NULL) return; - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user == NULL) return; @@ -3239,7 +3250,7 @@ return; } - switch (gc->account->perm_deny) { + switch (purple_account_get_privacy_type(purple_connection_get_account(gc))) { case PURPLE_PRIVACY_ALLOW_ALL: rc = nm_send_set_privacy_default(user, FALSE, @@ -3295,14 +3306,14 @@ if (user_record) { name = nm_user_record_get_display_id(user_record); - if (!g_slist_find_custom(gc->account->permit, + if (!g_slist_find_custom(purple_connection_get_account(gc)->permit, name, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_permit_add(gc->account, name , TRUE); + purple_privacy_permit_add(purple_connection_get_account(gc), name , TRUE); } } } - for (node = gc->account->permit; node; node = node->next) { + for (node = purple_connection_get_account(gc)->permit; node; node = node->next) { name = NULL; dn = nm_lookup_dn(user, (char *)node->data); if (dn) { @@ -3316,7 +3327,7 @@ g_strdup(dn)); } } else { - purple_privacy_permit_remove(gc->account, (char *)node->data, TRUE); + purple_privacy_permit_remove(purple_connection_get_account(gc), (char *)node->data, TRUE); } } } @@ -3337,14 +3348,14 @@ if (user_record) { name = nm_user_record_get_display_id(user_record); - if (!g_slist_find_custom(gc->account->deny, + if (!g_slist_find_custom(purple_connection_get_account(gc)->deny, name, (GCompareFunc)purple_utf8_strcasecmp)) { - purple_privacy_deny_add(gc->account, name , TRUE); + purple_privacy_deny_add(purple_connection_get_account(gc), name , TRUE); } } } - for (node = gc->account->deny; node; node = node->next) { + for (node = purple_connection_get_account(gc)->deny; node; node = node->next) { name = NULL; dn = nm_lookup_dn(user, (char *)node->data); @@ -3359,7 +3370,7 @@ g_strdup(name)); } } else { - purple_privacy_deny_remove(gc->account, (char *)node->data, TRUE); + purple_privacy_deny_remove(purple_connection_get_account(gc), (char *)node->data, TRUE); } } @@ -3451,7 +3462,7 @@ if (gc == NULL) return; - user = gc->proto_data; + user = purple_connection_get_protocol_data(gc); if (user == NULL) return; @@ -3460,6 +3471,7 @@ } static PurplePluginProtocolInfo prpl_info = { + sizeof(PurplePluginProtocolInfo), /* struct_size */ 0, NULL, /* user_splits */ NULL, /* protocol_options */ @@ -3500,7 +3512,6 @@ novell_keepalive, /* keepalive */ NULL, /* register_user */ NULL, /* get_cb_info */ - NULL, /* get_cb_away */ novell_alias_buddy, /* alias_buddy */ novell_group_buddy, /* group_buddy */ novell_rename_group, /* rename_group */ @@ -3525,15 +3536,12 @@ NULL, /* unregister_user */ NULL, /* send_attention */ NULL, /* get_attention_types */ - sizeof(PurplePluginProtocolInfo), /* struct_size */ NULL, /* get_account_text_table */ NULL, /* initiate_media */ NULL, /* get_media_caps */ NULL, /* get_moods */ NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - NULL, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ + NULL /* get_public_alias */ }; static PurplePluginInfo info = { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/null/nullprpl.c --- a/libpurple/protocols/null/nullprpl.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/null/nullprpl.c Fri Apr 06 04:30:00 2012 +0000 @@ -113,7 +113,7 @@ PurpleConnection *gc = (PurpleConnection *)(data); GcFuncData *gcfdata = (GcFuncData *)userdata; - if (!strcmp(gc->account->protocol_id, NULLPRPL_ID)) + if (!strcmp(purple_account_get_protocol_id(purple_connection_get_account(gc)), NULLPRPL_ID)) gcfdata->fn(gcfdata->from, gc, gcfdata->userdata); } @@ -138,11 +138,11 @@ PurpleConnection *to = (PurpleConnection *)data; ChatFuncData *cfdata = (ChatFuncData *)userdata; - int id = cfdata->from_chat->id; + int id = purple_conv_chat_get_id(cfdata->from_chat); PurpleConversation *conv = purple_find_chat(to, id); if (conv) { PurpleConvChat *chat = purple_conversation_get_chat_data(conv); - cfdata->fn(cfdata->from_chat, chat, id, conv->name, cfdata->userdata); + cfdata->fn(cfdata->from_chat, chat, id, purple_conversation_get_name(conv), cfdata->userdata); } } @@ -160,11 +160,11 @@ static void discover_status(PurpleConnection *from, PurpleConnection *to, gpointer userdata) { - const char *from_username = from->account->username; - const char *to_username = to->account->username; + const char *from_username = purple_account_get_username(purple_connection_get_account(from)); + const char *to_username = purple_account_get_username(purple_connection_get_account(to)); - if (purple_find_buddy(from->account, to_username)) { - PurpleStatus *status = purple_account_get_active_status(to->account); + if (purple_find_buddy(purple_connection_get_account(from), to_username)) { + PurpleStatus *status = purple_account_get_active_status(purple_connection_get_account(to)); const char *status_id = purple_status_get_id(status); const char *message = purple_status_get_attr_string(status, "message"); @@ -173,7 +173,7 @@ !strcmp(status_id, NULL_STATUS_OFFLINE)) { purple_debug_info("nullprpl", "%s sees that %s is %s: %s\n", from_username, to_username, status_id, message); - purple_prpl_got_user_status(from->account, to_username, status_id, + purple_prpl_got_user_status(purple_connection_get_account(from), to_username, status_id, (message) ? "message" : NULL, message, NULL); } else { purple_debug_error("nullprpl", @@ -186,7 +186,7 @@ static void report_status_change(PurpleConnection *from, PurpleConnection *to, gpointer userdata) { purple_debug_info("nullprpl", "notifying %s that %s changed status\n", - to->account->username, from->account->username); + purple_account_get_username(purple_connection_get_account(to)), purple_account_get_username(purple_connection_get_account(from))); discover_status(to, from, NULL); } @@ -199,7 +199,7 @@ PurpleConnection *gc = (PurpleConnection *)action->context; PurpleAccount *acct = purple_connection_get_account(gc); purple_debug_info("nullprpl", "showing 'Set User Info' dialog for %s\n", - acct->username); + purple_account_get_username(acct)); purple_account_request_change_user_info(acct); } @@ -225,7 +225,7 @@ static char *nullprpl_status_text(PurpleBuddy *buddy) { purple_debug_info("nullprpl", "getting %s's status text for %s\n", - buddy->name, buddy->account->username); + buddy->name, purple_account_get_username(buddy->account)); if (purple_find_buddy(buddy->account, buddy->name)) { PurplePresence *presence = purple_buddy_get_presence(buddy); @@ -234,7 +234,7 @@ const char *message = purple_status_get_attr_string(status, "message"); char *text; - if (message && strlen(message) > 0) + if (message && *message) text = g_strdup_printf("%s: %s", name, message); else text = g_strdup(name); @@ -258,19 +258,23 @@ PurplePresence *presence = purple_buddy_get_presence(buddy); PurpleStatus *status = purple_presence_get_active_status(presence); char *msg = nullprpl_status_text(buddy); - purple_notify_user_info_add_pair(info, purple_status_get_name(status), + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(info, purple_status_get_name(status), msg); g_free(msg); if (full) { - const char *user_info = purple_account_get_user_info(gc->account); + const char *user_info = purple_account_get_user_info(purple_connection_get_account(gc)); if (user_info) - purple_notify_user_info_add_pair(info, _("User info"), user_info); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(info, _("User info"), user_info); } } else { /* they're not logged in */ - purple_notify_user_info_add_pair(info, _("User info"), _("not logged in")); + purple_notify_user_info_add_pair_plaintext(info, _("User info"), _("not logged in")); } purple_debug_info("nullprpl", "showing %s tooltip for %s\n", @@ -283,7 +287,7 @@ PurpleStatusType *type; purple_debug_info("nullprpl", "returning status types for %s: %s, %s, %s\n", - acct->username, + purple_account_get_username(acct), NULL_STATUS_ONLINE, NULL_STATUS_AWAY, NULL_STATUS_OFFLINE); type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, @@ -362,7 +366,7 @@ PurpleConnection *gc = purple_account_get_connection(acct); GList *offline_messages; - purple_debug_info("nullprpl", "logging in %s\n", acct->username); + purple_debug_info("nullprpl", "logging in %s\n", purple_account_get_username(acct)); purple_connection_update_progress(gc, _("Connecting"), 0, /* which connection step this is */ @@ -381,12 +385,12 @@ /* fetch stored offline messages */ purple_debug_info("nullprpl", "checking for offline messages for %s\n", - acct->username); - offline_messages = g_hash_table_lookup(goffline_messages, acct->username); + purple_account_get_username(acct)); + offline_messages = g_hash_table_lookup(goffline_messages, purple_account_get_username(acct)); while (offline_messages) { GOfflineMessage *message = (GOfflineMessage *)offline_messages->data; purple_debug_info("nullprpl", "delivering offline message to %s: %s\n", - acct->username, message->message); + purple_account_get_username(acct), message->message); serv_got_im(gc, message->from, message->message, message->flags, message->mtime); offline_messages = g_list_next(offline_messages); @@ -397,7 +401,7 @@ } g_list_free(offline_messages); - g_hash_table_remove(goffline_messages, &acct->username); + g_hash_table_remove(goffline_messages, purple_account_get_username(acct)); } static void nullprpl_close(PurpleConnection *gc) @@ -409,7 +413,7 @@ static int nullprpl_send_im(PurpleConnection *gc, const char *who, const char *message, PurpleMessageFlags flags) { - const char *from_username = gc->account->username; + const char *from_username = purple_account_get_username(purple_connection_get_account(gc)); PurpleMessageFlags receive_flags = ((flags & ~PURPLE_MESSAGE_SEND) | PURPLE_MESSAGE_RECV); PurpleAccount *to_acct = purple_accounts_find(who, NULLPRPL_ID); @@ -419,13 +423,13 @@ from_username, who, message); /* is the sender blocked by the recipient's privacy settings? */ - if (to_acct && !purple_privacy_check(to_acct, gc->account->username)) { + if (to_acct && !purple_privacy_check(to_acct, purple_account_get_username(purple_connection_get_account(gc)))) { char *msg = g_strdup_printf( _("Your message was blocked by %s's privacy settings."), who); purple_debug_info("nullprpl", "discarding; %s is blocked by %s's privacy settings\n", from_username, who); - purple_conv_present_error(who, gc->account, msg); + purple_conv_present_error(who, purple_connection_get_account(gc), msg); g_free(msg); return 0; } @@ -457,7 +461,7 @@ static void nullprpl_set_info(PurpleConnection *gc, const char *info) { purple_debug_info("nullprpl", "setting %s's user info to %s\n", - gc->account->username, info); + purple_account_get_username(purple_connection_get_account(gc)), info); } static const char *typing_state_to_string(PurpleTypingState typing) { @@ -471,10 +475,10 @@ static void notify_typing(PurpleConnection *from, PurpleConnection *to, gpointer typing) { - const char *from_username = from->account->username; + const char *from_username = purple_account_get_username(purple_connection_get_account(from)); const char *action = typing_state_to_string((PurpleTypingState)typing); purple_debug_info("nullprpl", "notifying %s that %s %s\n", - to->account->username, from_username, action); + purple_account_get_username(purple_connection_get_account(to)), from_username, action); serv_got_typing(to, from_username, @@ -485,7 +489,7 @@ static unsigned int nullprpl_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState typing) { - purple_debug_info("nullprpl", "%s %s\n", gc->account->username, + purple_debug_info("nullprpl", "%s %s\n", purple_account_get_username(purple_connection_get_account(gc)), typing_state_to_string(typing)); foreach_nullprpl_gc(notify_typing, gc, (gpointer)typing); return 0; @@ -497,7 +501,7 @@ PurpleAccount *acct; purple_debug_info("nullprpl", "Fetching %s's user info for %s\n", username, - gc->account->username); + purple_account_get_username(purple_connection_get_account(gc))); if (!get_nullprpl_gc(username)) { char *msg = g_strdup_printf(_("%s is not logged in."), username); @@ -510,7 +514,9 @@ body = purple_account_get_user_info(acct); else body = _("No user info."); - purple_notify_user_info_add_pair(info, "Info", body); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(info, "Info", body); /* show a buddy's user info in a nice dialog box */ purple_notify_userinfo(gc, /* connection the buddy info came through */ @@ -523,35 +529,35 @@ static void nullprpl_set_status(PurpleAccount *acct, PurpleStatus *status) { const char *msg = purple_status_get_attr_string(status, "message"); purple_debug_info("nullprpl", "setting %s's status to %s: %s\n", - acct->username, purple_status_get_name(status), msg); + purple_account_get_username(acct), purple_status_get_name(status), msg); - foreach_nullprpl_gc(report_status_change, get_nullprpl_gc(acct->username), + foreach_nullprpl_gc(report_status_change, get_nullprpl_gc(purple_account_get_username(acct)), NULL); } static void nullprpl_set_idle(PurpleConnection *gc, int idletime) { purple_debug_info("nullprpl", "purple reports that %s has been idle for %d seconds\n", - gc->account->username, idletime); + purple_account_get_username(purple_connection_get_account(gc)), idletime); } static void nullprpl_change_passwd(PurpleConnection *gc, const char *old_pass, const char *new_pass) { purple_debug_info("nullprpl", "%s wants to change their password\n", - gc->account->username); + purple_account_get_username(purple_connection_get_account(gc))); } static void nullprpl_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, - PurpleGroup *group) + PurpleGroup *group, const char *message) { - const char *username = gc->account->username; + const char *username = purple_account_get_username(purple_connection_get_account(gc)); PurpleConnection *buddy_gc = get_nullprpl_gc(buddy->name); purple_debug_info("nullprpl", "adding %s to %s's buddy list\n", buddy->name, username); if (buddy_gc) { - PurpleAccount *buddy_acct = buddy_gc->account; + PurpleAccount *buddy_acct = purple_connection_get_account(buddy_gc); discover_status(gc, buddy_gc, NULL); @@ -565,20 +571,20 @@ username, NULL, /* local account id (rarely used) */ NULL, /* alias */ - NULL); /* message */ + message); /* message */ } } } static void nullprpl_add_buddies(PurpleConnection *gc, GList *buddies, - GList *groups) { + GList *groups, const char *message) { GList *buddy = buddies; GList *group = groups; purple_debug_info("nullprpl", "adding multiple buddies\n"); while (buddy && group) { - nullprpl_add_buddy(gc, (PurpleBuddy *)buddy->data, (PurpleGroup *)group->data); + nullprpl_add_buddy(gc, (PurpleBuddy *)buddy->data, (PurpleGroup *)group->data, message); buddy = g_list_next(buddy); group = g_list_next(group); } @@ -588,7 +594,7 @@ PurpleGroup *group) { purple_debug_info("nullprpl", "removing %s from %s's buddy list\n", - buddy->name, gc->account->username); + buddy->name, purple_account_get_username(purple_connection_get_account(gc))); } static void nullprpl_remove_buddies(PurpleConnection *gc, GList *buddies, @@ -614,22 +620,22 @@ */ static void nullprpl_add_permit(PurpleConnection *gc, const char *name) { purple_debug_info("nullprpl", "%s adds %s to their allowed list\n", - gc->account->username, name); + purple_account_get_username(purple_connection_get_account(gc)), name); } static void nullprpl_add_deny(PurpleConnection *gc, const char *name) { purple_debug_info("nullprpl", "%s adds %s to their blocked list\n", - gc->account->username, name); + purple_account_get_username(purple_connection_get_account(gc)), name); } static void nullprpl_rem_permit(PurpleConnection *gc, const char *name) { purple_debug_info("nullprpl", "%s removes %s from their allowed list\n", - gc->account->username, name); + purple_account_get_username(purple_connection_get_account(gc)), name); } static void nullprpl_rem_deny(PurpleConnection *gc, const char *name) { purple_debug_info("nullprpl", "%s removes %s from their blocked list\n", - gc->account->username, name); + purple_account_get_username(purple_connection_get_account(gc)), name); } static void nullprpl_set_permit_deny(PurpleConnection *gc) { @@ -642,9 +648,9 @@ int id, const char *room, gpointer userdata) { /* tell their chat window that we joined */ purple_debug_info("nullprpl", "%s sees that %s joined chat room %s\n", - to->nick, from->nick, room); + purple_conv_chat_get_nick(to), purple_conv_chat_get_nick(from), room); purple_conv_chat_add_user(to, - from->nick, + purple_conv_chat_get_nick(from), NULL, /* user-provided join message, IRC style */ PURPLE_CBFLAGS_NONE, TRUE); /* show a join message */ @@ -652,9 +658,9 @@ if (from != to) { /* add them to our chat window */ purple_debug_info("nullprpl", "%s sees that %s is in chat room %s\n", - from->nick, to->nick, room); + purple_conv_chat_get_nick(from), purple_conv_chat_get_nick(to), room); purple_conv_chat_add_user(from, - to->nick, + purple_conv_chat_get_nick(to), NULL, /* user-provided join message, IRC style */ PURPLE_CBFLAGS_NONE, FALSE); /* show a join message */ @@ -662,7 +668,7 @@ } static void nullprpl_join_chat(PurpleConnection *gc, GHashTable *components) { - const char *username = gc->account->username; + const char *username = purple_account_get_username(purple_connection_get_account(gc)); const char *room = g_hash_table_lookup(components, "room"); int chat_id = g_str_hash(room); purple_debug_info("nullprpl", "%s is joining chat room %s\n", username, room); @@ -686,7 +692,7 @@ static void nullprpl_reject_chat(PurpleConnection *gc, GHashTable *components) { const char *invited_by = g_hash_table_lookup(components, "invited_by"); const char *room = g_hash_table_lookup(components, "room"); - const char *username = gc->account->username; + const char *username = purple_account_get_username(purple_connection_get_account(gc)); PurpleConnection *invited_by_gc = get_nullprpl_gc(invited_by); char *message = g_strdup_printf( "%s %s %s.", @@ -713,9 +719,9 @@ static void nullprpl_chat_invite(PurpleConnection *gc, int id, const char *message, const char *who) { - const char *username = gc->account->username; + const char *username = purple_account_get_username(purple_connection_get_account(gc)); PurpleConversation *conv = purple_find_chat(gc, id); - const char *room = conv->name; + const char *room = purple_conversation_get_name(conv); PurpleAccount *to_acct = purple_accounts_find(who, NULLPRPL_ID); purple_debug_info("nullprpl", "%s is inviting %s to join chat room %s\n", @@ -746,9 +752,9 @@ if (from != to) { /* tell their chat window that we left */ purple_debug_info("nullprpl", "%s sees that %s left chat room %s\n", - to->nick, from->nick, room); + purple_conv_chat_get_nick(to), purple_conv_chat_get_nick(from), room); purple_conv_chat_remove_user(to, - from->nick, + purple_conv_chat_get_nick(from), NULL); /* user-provided message, IRC style */ } } @@ -756,7 +762,7 @@ static void nullprpl_chat_leave(PurpleConnection *gc, int id) { PurpleConversation *conv = purple_find_chat(gc, id); purple_debug_info("nullprpl", "%s is leaving chat room %s\n", - gc->account->username, conv->name); + purple_account_get_username(purple_connection_get_account(gc)), purple_conversation_get_name(conv)); /* tell everyone that we left */ foreach_gc_in_chat(left_chat_room, gc, id, NULL); @@ -775,17 +781,17 @@ to_username = args[0]; message = args[1]; - if (!to_username || strlen(to_username) == 0) { + if (!to_username || !*to_username) { *error = g_strdup(_("Whisper is missing recipient.")); return PURPLE_CMD_RET_FAILED; - } else if (!message || strlen(message) == 0) { + } else if (!message || !*message) { *error = g_strdup(_("Whisper is missing message.")); return PURPLE_CMD_RET_FAILED; } - from_username = conv->account->username; + from_username = purple_account_get_username(purple_conversation_get_account(conv)); purple_debug_info("nullprpl", "%s whispers to %s in chat room %s: %s\n", - from_username, to_username, conv->name, message); + from_username, to_username, purple_conversation_get_name(conv), message); chat = purple_conversation_get_chat_data(conv); chat_buddy = purple_conv_chat_cb_find(chat, to_username); @@ -807,7 +813,7 @@ g_free(message_to); /* send the whisper */ - serv_chat_whisper(to, chat->id, from_username, message); + serv_chat_whisper(to, purple_conv_chat_get_id(chat), from_username, message); return PURPLE_CMD_RET_OK; } @@ -815,11 +821,11 @@ static void nullprpl_chat_whisper(PurpleConnection *gc, int id, const char *who, const char *message) { - const char *username = gc->account->username; + const char *username = purple_account_get_username(purple_connection_get_account(gc)); PurpleConversation *conv = purple_find_chat(gc, id); purple_debug_info("nullprpl", "%s receives whisper from %s in chat room %s: %s\n", - username, who, conv->name, message); + username, who, purple_conversation_get_name(conv), message); /* receive whisper on recipient's account */ serv_got_chat_in(gc, id, who, PURPLE_MESSAGE_RECV | PURPLE_MESSAGE_WHISPER, @@ -829,24 +835,24 @@ static void receive_chat_message(PurpleConvChat *from, PurpleConvChat *to, int id, const char *room, gpointer userdata) { const char *message = (const char *)userdata; - PurpleConnection *to_gc = get_nullprpl_gc(to->nick); + PurpleConnection *to_gc = get_nullprpl_gc(purple_conv_chat_get_nick(to)); purple_debug_info("nullprpl", "%s receives message from %s in chat room %s: %s\n", - to->nick, from->nick, room, message); - serv_got_chat_in(to_gc, id, from->nick, PURPLE_MESSAGE_RECV, message, + purple_conv_chat_get_nick(to), purple_conv_chat_get_nick(from), room, message); + serv_got_chat_in(to_gc, id, purple_conv_chat_get_nick(from), PURPLE_MESSAGE_RECV, message, time(NULL)); } static int nullprpl_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags) { - const char *username = gc->account->username; + const char *username = purple_account_get_username(purple_connection_get_account(gc)); PurpleConversation *conv = purple_find_chat(gc, id); if (conv) { purple_debug_info("nullprpl", "%s is sending message to chat room %s: %s\n", username, - conv->name, message); + purple_conversation_get_name(conv), message); /* send message to everyone in the chat room */ foreach_gc_in_chat(receive_chat_message, gc, id, (gpointer)message); @@ -862,14 +868,14 @@ static void nullprpl_register_user(PurpleAccount *acct) { purple_debug_info("nullprpl", "registering account for %s\n", - acct->username); + purple_account_get_username(acct)); } static void nullprpl_get_cb_info(PurpleConnection *gc, int id, const char *who) { PurpleConversation *conv = purple_find_chat(gc, id); purple_debug_info("nullprpl", "retrieving %s's info for %s in chat room %s\n", who, - gc->account->username, conv->name); + purple_account_get_username(purple_connection_get_account(gc)), purple_conversation_get_name(conv)); nullprpl_get_info(gc, who); } @@ -877,25 +883,25 @@ static void nullprpl_alias_buddy(PurpleConnection *gc, const char *who, const char *alias) { purple_debug_info("nullprpl", "%s sets %s's alias to %s\n", - gc->account->username, who, alias); + purple_account_get_username(purple_connection_get_account(gc)), who, alias); } static void nullprpl_group_buddy(PurpleConnection *gc, const char *who, const char *old_group, const char *new_group) { purple_debug_info("nullprpl", "%s has moved %s from group %s to group %s\n", - gc->account->username, who, old_group, new_group); + purple_account_get_username(purple_connection_get_account(gc)), who, old_group, new_group); } static void nullprpl_rename_group(PurpleConnection *gc, const char *old_name, PurpleGroup *group, GList *moved_buddies) { purple_debug_info("nullprpl", "%s has renamed group %s to %s\n", - gc->account->username, old_name, group->name); + purple_account_get_username(purple_connection_get_account(gc)), old_name, group->name); } static void nullprpl_convo_closed(PurpleConnection *gc, const char *who) { purple_debug_info("nullprpl", "%s's conversation with %s was closed\n", - gc->account->username, who); + purple_account_get_username(purple_connection_get_account(gc)), who); } /* normalize a username (e.g. remove whitespace, add default domain, etc.) @@ -909,25 +915,25 @@ static void nullprpl_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img) { purple_debug_info("nullprpl", "setting %s's buddy icon to %s\n", - gc->account->username, + purple_account_get_username(purple_connection_get_account(gc)), img ? purple_imgstore_get_filename(img) : "(null)"); } static void nullprpl_remove_group(PurpleConnection *gc, PurpleGroup *group) { purple_debug_info("nullprpl", "%s has removed group %s\n", - gc->account->username, group->name); + purple_account_get_username(purple_connection_get_account(gc)), group->name); } static void set_chat_topic_fn(PurpleConvChat *from, PurpleConvChat *to, int id, const char *room, gpointer userdata) { const char *topic = (const char *)userdata; - const char *username = from->conv->account->username; + const char *username = purple_account_get_username(purple_conversation_get_account(purple_conv_chat_get_conversation(from))); char *msg; purple_conv_chat_set_topic(to, username, topic); - if (topic && strlen(topic) > 0) + if (topic && *topic) msg = g_strdup_printf(_("%s sets topic to: %s"), username, topic); else msg = g_strdup_printf(_("%s clears topic"), username); @@ -948,7 +954,7 @@ return; purple_debug_info("nullprpl", "%s sets topic of chat room '%s' to '%s'\n", - gc->account->username, conv->name, topic); + purple_account_get_username(purple_connection_get_account(gc)), purple_conversation_get_name(conv), topic); last_topic = purple_conv_chat_get_topic(chat); if ((!topic && !last_topic) || @@ -964,8 +970,8 @@ } static PurpleRoomlist *nullprpl_roomlist_get_list(PurpleConnection *gc) { - const char *username = gc->account->username; - PurpleRoomlist *roomlist = purple_roomlist_new(gc->account); + const char *username = purple_account_get_username(purple_connection_get_account(gc)); + PurpleRoomlist *roomlist = purple_roomlist_new(purple_connection_get_account(gc)); GList *fields = NULL; PurpleRoomlistField *field; GList *chats; @@ -988,8 +994,8 @@ for (chats = purple_get_chats(); chats; chats = g_list_next(chats)) { PurpleConversation *conv = (PurpleConversation *)chats->data; PurpleRoomlistRoom *room; - const char *name = conv->name; - int id = purple_conversation_get_chat_data(conv)->id; + const char *name = purple_conversation_get_name(conv); + int id = purple_conv_chat_get_id(purple_conversation_get_chat_data(conv)); /* have we already added this room? */ if (g_list_find_custom(seen_ids, name, (GCompareFunc)strcmp)) @@ -1013,14 +1019,17 @@ } static void nullprpl_roomlist_cancel(PurpleRoomlist *list) { + PurpleAccount *account = purple_roomlist_get_account(list); purple_debug_info("nullprpl", "%s asked to cancel room list request\n", - list->account->username); + purple_account_get_username(account)); } static void nullprpl_roomlist_expand_category(PurpleRoomlist *list, PurpleRoomlistRoom *category) { + PurpleAccount *account = purple_roomlist_get_account(list); purple_debug_info("nullprpl", "%s asked to expand room list category %s\n", - list->account->username, category->name); + purple_account_get_username(account), + purple_roomlist_room_get_name(category)); } /* nullprpl doesn't support file transfer...yet... */ @@ -1043,6 +1052,7 @@ static PurplePluginProtocolInfo prpl_info = { + sizeof(PurplePluginProtocolInfo), /* struct_size */ OPT_PROTO_NO_PASSWORD | OPT_PROTO_CHAT_TOPIC, /* options */ NULL, /* user_splits, initialized in nullprpl_init() */ NULL, /* protocol_options, initialized in nullprpl_init() */ @@ -1091,7 +1101,6 @@ NULL, /* keepalive */ nullprpl_register_user, /* register_user */ nullprpl_get_cb_info, /* get_cb_info */ - NULL, /* get_cb_away */ nullprpl_alias_buddy, /* alias_buddy */ nullprpl_group_buddy, /* group_buddy */ nullprpl_rename_group, /* rename_group */ @@ -1116,15 +1125,12 @@ NULL, /* unregister_user */ NULL, /* send_attention */ NULL, /* get_attention_types */ - sizeof(PurplePluginProtocolInfo), /* struct_size */ NULL, /* get_account_text_table */ NULL, /* initiate_media */ NULL, /* get_media_caps */ NULL, /* get_moods */ NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - NULL, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ + NULL /* get_public_alias */ }; static void nullprpl_init(PurplePlugin *plugin) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/oscar/authorization.c --- a/libpurple/protocols/oscar/authorization.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/oscar/authorization.c Fri Apr 06 04:30:00 2012 +0000 @@ -49,7 +49,7 @@ purple_debug_info("oscar", "ssi: adding buddy %s to group %s\n", bname, gname); aim_ssi_sendauthrequest(od, bname, msg ? msg : _("Please authorize me so I can add you to my buddy list.")); - if (!aim_ssi_itemlist_finditem(od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY)) + if (!aim_ssi_itemlist_finditem(&od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY)) { aim_ssi_addbuddy(od, bname, gname, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, TRUE); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/oscar/clientlogin.c --- a/libpurple/protocols/oscar/clientlogin.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/oscar/clientlogin.c Fri Apr 06 04:30:00 2012 +0000 @@ -182,7 +182,7 @@ /* Note to translators: %s in this string is a URL */ msg = generate_error_message(response_node, get_start_oscar_session_url(od)); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); g_free(msg); return FALSE; @@ -204,7 +204,7 @@ "missing statusCode: %s\n", response); msg = generate_error_message(response_node, get_start_oscar_session_url(od)); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); g_free(msg); xmlnode_free(response_node); @@ -232,7 +232,7 @@ "was %s: %s\n", tmp, response); if ((code == 401 && status_detail != 1014) || code == 607) - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("You have been connecting and disconnecting too " "frequently. Wait ten minutes and try again. If " @@ -242,7 +242,7 @@ char *msg; msg = generate_error_message(response_node, get_start_oscar_session_url(od)); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg); g_free(msg); } @@ -261,7 +261,7 @@ "something: %s\n", response); msg = generate_error_message(response_node, get_start_oscar_session_url(od)); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); g_free(msg); xmlnode_free(response_node); @@ -277,7 +277,7 @@ purple_debug_warning("oscar", "We haven't received a tlsCertName to use. We will not do SSL to BOS.\n"); } else { purple_debug_error("oscar", "startOSCARSession was missing tlsCertName: %s\n", response); - purple_connection_error_reason( + purple_connection_error( gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("You required encryption in your account settings, but one of the servers doesn't support it.")); @@ -299,7 +299,7 @@ "something: %s\n", response); msg = generate_error_message(response_node, get_start_oscar_session_url(od)); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); g_free(msg); g_free(*host); @@ -337,7 +337,7 @@ tmp = g_strdup_printf(_("Error requesting %s: %s"), get_start_oscar_session_url(od), error_message ? error_message : _("The server returned an empty response")); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; @@ -384,7 +384,7 @@ g_free(signature); /* Make the request */ - od->url_data = purple_util_fetch_url_request_len_with_account(account, + od->url_data = purple_util_fetch_url_request(account, url, TRUE, NULL, FALSE, NULL, FALSE, -1, start_oscar_session_cb, od); g_free(url); @@ -395,7 +395,7 @@ * and extracts the useful information. * * @param gc The PurpleConnection. If the response data does - * not indicate then purple_connection_error_reason() + * not indicate then purple_connection_error() * will be called to close this connection. * @param response The response data from the clientLogin request. * @param response_len The length of the above response, or -1 if @@ -431,7 +431,7 @@ "response as XML: %s\n", response); msg = generate_error_message(response_node, get_client_login_url(od)); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); g_free(msg); return FALSE; @@ -455,7 +455,7 @@ "missing statusCode: %s\n", response); msg = generate_error_message(response_node, get_client_login_url(od)); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); g_free(msg); xmlnode_free(response_node); @@ -482,23 +482,23 @@ PurpleAccount *account = purple_connection_get_account(gc); if (!purple_account_get_remember_password(account)) purple_account_set_password(account, NULL); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Incorrect password")); } else if (status_code == 330 && status_detail_code == 3015) { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Server requested that you fill out a CAPTCHA in order to " "sign in, but this client does not currently support CAPTCHAs.")); } else if (status_code == 401 && status_detail_code == 3019) { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("AOL does not allow your screen name to authenticate here")); } else { char *msg; msg = generate_error_message(response_node, get_client_login_url(od)); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg); g_free(msg); } @@ -517,7 +517,7 @@ "something: %s\n", response); msg = generate_error_message(response_node, get_client_login_url(od)); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); g_free(msg); xmlnode_free(response_node); @@ -535,7 +535,7 @@ "something: %s\n", response); msg = generate_error_message(response_node, get_client_login_url(od)); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); g_free(msg); g_free(*token); @@ -572,7 +572,7 @@ tmp = g_strdup_printf(_("Error requesting %s: %s"), get_client_login_url(od), error_message ? error_message : _("The server returned an empty response")); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; @@ -646,7 +646,7 @@ g_string_free(body, TRUE); /* Send the POST request */ - od->url_data = purple_util_fetch_url_request_len_with_account( + od->url_data = purple_util_fetch_url_request( purple_connection_get_account(gc), get_client_login_url(od), TRUE, NULL, FALSE, request->str, FALSE, -1, client_login_cb, od); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/oscar/family_feedbag.c --- a/libpurple/protocols/oscar/family_feedbag.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/oscar/family_feedbag.c Fri Apr 06 04:30:00 2012 +0000 @@ -21,9 +21,9 @@ /* * Family 0x0013 - Server-Side/Stored Information. * - * Relatively new facility that allows certain types of information, such as - * a user's buddy list, permit/deny list, and permit/deny preferences, to be - * stored on the server, so that they can be accessed from any client. + * Deals with storing certain types of information, such as a user's buddy + * list, permit/deny list, and permit/deny preferences, on the server, so + * that they can be accessed from any client. * * We keep 2 copies of SSI data: * 1) An exact copy of what is stored on the AIM servers. @@ -40,14 +40,41 @@ * * This is entirely too complicated. * You don't know the half of it. - * */ #include "oscar.h" +#include "oscarcommon.h" #include "debug.h" static int aim_ssi_addmoddel(OscarData *od); +static void aim_ssi_item_free(struct aim_ssi_item *item) +{ + g_free(item->name); + aim_tlvlist_free(item->data); + g_free(item); +} + +static void aim_ssi_item_set_name(struct aim_ssi_itemlist *list, struct aim_ssi_item *item, const char *name) +{ + gchar key[3000]; + + if (item->name) { + /* Remove old name from hash table */ + snprintf(key, sizeof(key), "%hx%s", item->type, oscar_normalize(NULL, item->name)); + g_hash_table_remove(list->idx_all_named_items, key); + } + + g_free(item->name); + item->name = g_strdup(name); + + if (name) { + /* Add new name to hash table */ + snprintf(key, sizeof(key), "%hx%s", item->type, oscar_normalize(NULL, item->name)); + g_hash_table_insert(list->idx_all_named_items, g_strdup(key), item); + } +} + /** * List types based on http://dev.aol.com/aim/oscar/#FEEDBAG (archive.org) * and http://iserverd.khstu.ru/oscar/ssi_item.html @@ -113,7 +140,7 @@ * @return Return a pointer to the modified item. */ static void -aim_ssi_itemlist_rebuildgroup(struct aim_ssi_item *list, const char *name) +aim_ssi_itemlist_rebuildgroup(struct aim_ssi_itemlist *list, const char *name) { int newlen; struct aim_ssi_item *cur, *group; @@ -125,11 +152,11 @@ /* Find the length for the new additional data */ newlen = 0; if (group->gid == 0x0000) { - for (cur=list; cur; cur=cur->next) + for (cur=list->data; cur; cur=cur->next) if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000)) newlen += 2; } else { - for (cur=list; cur; cur=cur->next) + for (cur=list->data; cur; cur=cur->next) if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY)) newlen += 2; } @@ -138,14 +165,14 @@ if (newlen > 0) { guint8 *newdata; - newdata = (guint8 *)g_malloc((newlen)*sizeof(guint8)); + newdata = g_new(guint8, newlen); newlen = 0; if (group->gid == 0x0000) { - for (cur=list; cur; cur=cur->next) + for (cur=list->data; cur; cur=cur->next) if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000)) newlen += aimutil_put16(newdata+newlen, cur->gid); } else { - for (cur=list; cur; cur=cur->next) + for (cur=list->data; cur; cur=cur->next) if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY)) newlen += aimutil_put16(newdata+newlen, cur->bid); } @@ -167,15 +194,12 @@ * @param data The additional data for the new item. * @return A pointer to the newly created item. */ -static struct aim_ssi_item *aim_ssi_itemlist_add(struct aim_ssi_item **list, const char *name, guint16 gid, guint16 bid, guint16 type, GSList *data) +static struct aim_ssi_item *aim_ssi_itemlist_add(struct aim_ssi_itemlist *list, const char *name, guint16 gid, guint16 bid, guint16 type, GSList *data) { gboolean exists; struct aim_ssi_item *cur, *new; - new = g_new(struct aim_ssi_item, 1); - - /* Set the name */ - new->name = g_strdup(name); + new = g_new0(struct aim_ssi_item, 1); /* Set the group ID# and buddy ID# */ new->gid = gid; @@ -185,7 +209,7 @@ do { new->gid += 0x0001; exists = FALSE; - for (cur = *list; cur != NULL; cur = cur->next) + for (cur = list->data; cur != NULL; cur = cur->next) if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid == new->gid)) { exists = TRUE; break; @@ -202,7 +226,7 @@ do { new->bid += 0x0001; exists = FALSE; - for (cur = *list; cur != NULL; cur = cur->next) + for (cur = list->data; cur != NULL; cur = cur->next) if (cur->bid == new->bid || cur->gid == new->bid) { exists = TRUE; break; @@ -214,7 +238,7 @@ do { new->bid += 0x0001; exists = FALSE; - for (cur = *list; cur != NULL; cur = cur->next) + for (cur = list->data; cur != NULL; cur = cur->next) if (cur->bid == new->bid && cur->gid == new->gid) { exists = TRUE; break; @@ -226,23 +250,29 @@ /* Set the type */ new->type = type; + /* Add it to the gid+bid hashtable */ + g_hash_table_insert(list->idx_gid_bid, GINT_TO_POINTER((new->gid << 16) + new->bid), new); + + /* Set the name - do this *AFTER* setting the type because type is used for the key */ + aim_ssi_item_set_name(list, new, name); + /* Set the TLV list */ new->data = aim_tlvlist_copy(data); /* Add the item to the list in the correct numerical position. Fancy, eh? */ - if (*list) { - if ((new->gid < (*list)->gid) || ((new->gid == (*list)->gid) && (new->bid < (*list)->bid))) { - new->next = *list; - *list = new; + if (list->data) { + if ((new->gid < list->data->gid) || ((new->gid == list->data->gid) && (new->bid < list->data->bid))) { + new->next = list->data; + list->data = new; } else { struct aim_ssi_item *prev; - for ((prev=*list, cur=(*list)->next); (cur && ((new->gid > cur->gid) || ((new->gid == cur->gid) && (new->bid > cur->bid)))); prev=cur, cur=cur->next); + for ((prev=list->data, cur=list->data->next); (cur && ((new->gid > cur->gid) || ((new->gid == cur->gid) && (new->bid > cur->bid)))); prev=cur, cur=cur->next); new->next = prev->next; prev->next = new; } } else { - new->next = *list; - *list = new; + new->next = list->data; + list->data = new; } return new; @@ -255,25 +285,31 @@ * @param del A pointer to the item you want to remove from the list. * @return Return 0 if no errors, otherwise return the error number. */ -static int aim_ssi_itemlist_del(struct aim_ssi_item **list, struct aim_ssi_item *del) +static int aim_ssi_itemlist_del(struct aim_ssi_itemlist *list, struct aim_ssi_item *del) { - if (!(*list) || !del) + gchar key[3000]; + + if (!(list->data) || !del) return -EINVAL; /* Remove the item from the list */ - if (*list == del) { - *list = (*list)->next; + if (list->data == del) { + list->data = list->data->next; } else { struct aim_ssi_item *cur; - for (cur=*list; (cur->next && (cur->next!=del)); cur=cur->next); + for (cur=list->data; (cur->next && (cur->next!=del)); cur=cur->next); if (cur->next) cur->next = del->next; } + /* Remove from the hashtables */ + g_hash_table_remove(list->idx_gid_bid, GINT_TO_POINTER((del->gid << 16) + del->bid)); + + snprintf(key, sizeof(key), "%hx%s", del->type, oscar_normalize(NULL, del->name)); + g_hash_table_remove(list->idx_all_named_items, key); + /* Free the removed item */ - g_free(del->name); - aim_tlvlist_free(del->data); - g_free(del); + aim_ssi_item_free(del); return 0; } @@ -320,10 +356,10 @@ return 0; } -static gboolean aim_ssi_itemlist_valid(struct aim_ssi_item *list, struct aim_ssi_item *item) +static gboolean aim_ssi_itemlist_valid(struct aim_ssi_itemlist *list, struct aim_ssi_item *item) { struct aim_ssi_item *cur; - for (cur=list; cur; cur=cur->next) + for (cur=list->data; cur; cur=cur->next) if (cur == item) return TRUE; return FALSE; @@ -337,13 +373,10 @@ * @param bid The buddy ID# of the desired item. * @return Return a pointer to the item if found, else return NULL; */ -struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gid, guint16 bid) +struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_itemlist *list, guint16 gid, guint16 bid) { - struct aim_ssi_item *cur; - for (cur=list; cur; cur=cur->next) - if ((cur->gid == gid) && (cur->bid == bid)) - return cur; - return NULL; + guint32 id_key = (gid << 16) + bid; + return g_hash_table_lookup(list->idx_gid_bid, GINT_TO_POINTER(id_key)); } /** @@ -356,37 +389,30 @@ * @param type The type of the desired item. * @return Return a pointer to the item if found, else return NULL. */ -struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *bn, guint16 type) +struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_itemlist *list, const char *gn, const char *bn, guint16 type) { struct aim_ssi_item *cur; - if (!list) + gchar key[3000]; + + if (!list->data) return NULL; if (gn && bn) { /* For finding buddies in groups */ - for (cur=list; cur; cur=cur->next) + g_return_val_if_fail(type == AIM_SSI_TYPE_BUDDY, NULL); + for (cur=list->data; cur; cur=cur->next) if ((cur->type == type) && (cur->name) && !(oscar_util_name_compare(cur->name, bn))) { struct aim_ssi_item *curg; - for (curg=list; curg; curg=curg->next) + for (curg=list->data; curg; curg=curg->next) if ((curg->type == AIM_SSI_TYPE_GROUP) && (curg->gid == cur->gid) && (curg->name) && !(oscar_util_name_compare(curg->name, gn))) return cur; } - } else if (gn) { /* For finding groups */ - for (cur=list; cur; cur=cur->next) { - if ((cur->type == type) && (cur->bid == 0x0000) && (cur->name) && !(oscar_util_name_compare(cur->name, gn))) { - return cur; - } - } - - } else if (bn) { /* For finding permits, denies, and ignores */ - for (cur=list; cur; cur=cur->next) { - if ((cur->type == type) && (cur->name) && !(oscar_util_name_compare(cur->name, bn))) { - return cur; - } - } + } else if (gn || bn) { /* For finding groups, permits, denies and ignores */ + snprintf(key, sizeof(key), "%hx%s", type, oscar_normalize(NULL, gn ? gn : bn)); + return g_hash_table_lookup(list->idx_all_named_items, key); /* For stuff without names--permit deny setting, visibility mask, etc. */ - } else for (cur=list; cur; cur=cur->next) { + } else for (cur=list->data; cur; cur=cur->next) { if ((cur->type == type) && (!cur->name)) return cur; } @@ -401,7 +427,7 @@ * @param bn The group name of the desired item. * @return Return a pointer to the name of the item if found, else return NULL; */ -struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *bn) +struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_itemlist *list, const char *bn) { if (!bn) return NULL; @@ -415,10 +441,10 @@ * @param bn The buddy name of the desired item. * @return Return a pointer to the name of the item if found, else return NULL; */ -char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *bn) +char *aim_ssi_itemlist_findparentname(struct aim_ssi_itemlist *list, const char *bn) { struct aim_ssi_item *cur, *curg; - if (!list || !bn) + if (!list->data || !bn) return NULL; if (!(cur = aim_ssi_itemlist_exists(list, bn))) return NULL; @@ -433,7 +459,7 @@ * @param list A pointer to the current list of items. * @return Return the current SSI permit deny setting, or 0 if no setting was found. */ -int aim_ssi_getpermdeny(struct aim_ssi_item *list) +int aim_ssi_getpermdeny(struct aim_ssi_itemlist *list) { struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PDINFO); if (cur) { @@ -451,7 +477,7 @@ * @param list A pointer to the current list of items. * @return Return the current set of preferences. */ -guint32 aim_ssi_getpresence(struct aim_ssi_item *list) +guint32 aim_ssi_getpresence(struct aim_ssi_itemlist *list) { struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS); if (cur) { @@ -472,17 +498,23 @@ * alias, or NULL if the buddy has no alias. You should free * this returned value! */ -char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *bn) +char *aim_ssi_getalias(struct aim_ssi_itemlist *list, const char *gn, const char *bn) { - struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, bn, AIM_SSI_TYPE_BUDDY); - if (cur) { - aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x0131, 1); - if (tlv && tlv->length) - return g_strndup((const gchar *)tlv->value, tlv->length); + struct aim_ssi_item *item = aim_ssi_itemlist_finditem(list, gn, bn, AIM_SSI_TYPE_BUDDY); + if (item) { + return aim_ssi_getalias_from_item(item); } return NULL; } +char *aim_ssi_getalias_from_item(struct aim_ssi_item *item) +{ + aim_tlv_t *tlv = aim_tlv_gettlv(item->data, 0x0131, 1); + if (tlv && tlv->length) + return g_strndup((const gchar *)tlv->value, tlv->length); + return NULL; +} + /** * Locally find the comment of the given buddy. * @@ -493,7 +525,7 @@ * comment, or NULL if the buddy has no comment. You should free * this returned value! */ -char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *bn) +char *aim_ssi_getcomment(struct aim_ssi_itemlist *list, const char *gn, const char *bn) { struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, bn, AIM_SSI_TYPE_BUDDY); if (cur) { @@ -513,7 +545,7 @@ * @param bn The name of the buddy. * @return 1 if you are waiting for authorization; 0 if you are not */ -gboolean aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *bn) +gboolean aim_ssi_waitingforauth(struct aim_ssi_itemlist *list, const char *gn, const char *bn) { struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, bn, AIM_SSI_TYPE_BUDDY); if (cur) { @@ -561,8 +593,8 @@ /* Deletions */ if (!od->ssi.pending) { - for (cur1=od->ssi.official; cur1 && (n < 15); cur1=cur1->next) { - if (!aim_ssi_itemlist_find(od->ssi.local, cur1->gid, cur1->bid)) { + for (cur1=od->ssi.official.data; cur1 && (n < 15); cur1=cur1->next) { + if (!aim_ssi_itemlist_find(&od->ssi.local, cur1->gid, cur1->bid)) { n++; new = g_new(struct aim_ssi_tmp, 1); new->action = SNAC_SUBTYPE_FEEDBAG_DEL; @@ -575,15 +607,15 @@ cur->next = new; } else od->ssi.pending = new; - aim_ssi_item_debug_append(debugstr, "Deleting item ", cur1); + aim_ssi_item_debug_append(debugstr, "Deleting item ", cur1); } } } /* Additions */ if (!od->ssi.pending) { - for (cur1=od->ssi.local; cur1 && (n < 15); cur1=cur1->next) { - if (!aim_ssi_itemlist_find(od->ssi.official, cur1->gid, cur1->bid)) { + for (cur1=od->ssi.local.data; cur1 && (n < 15); cur1=cur1->next) { + if (!aim_ssi_itemlist_find(&od->ssi.official, cur1->gid, cur1->bid)) { n++; new = g_new(struct aim_ssi_tmp, 1); new->action = SNAC_SUBTYPE_FEEDBAG_ADD; @@ -596,15 +628,15 @@ cur->next = new; } else od->ssi.pending = new; - aim_ssi_item_debug_append(debugstr, "Adding item ", cur1); + aim_ssi_item_debug_append(debugstr, "Adding item ", cur1); } } } /* Modifications */ if (!od->ssi.pending) { - for (cur1=od->ssi.local; cur1 && (n < 15); cur1=cur1->next) { - cur2 = aim_ssi_itemlist_find(od->ssi.official, cur1->gid, cur1->bid); + for (cur1=od->ssi.local.data; cur1 && (n < 15); cur1=cur1->next) { + cur2 = aim_ssi_itemlist_find(&od->ssi.official, cur1->gid, cur1->bid); if (cur2 && (aim_ssi_itemlist_cmp(cur1, cur2))) { n++; new = g_new(struct aim_ssi_tmp, 1); @@ -618,18 +650,18 @@ cur->next = new; } else od->ssi.pending = new; - aim_ssi_item_debug_append(debugstr, "Modifying item ", cur1); + aim_ssi_item_debug_append(debugstr, "Modifying item ", cur1); } } } if (debugstr->len > 0) { purple_debug_info("oscar", "%s", debugstr->str); if (purple_debug_is_verbose()) { - g_string_truncate(debugstr, 0); - for (cur1 = od->ssi.local; cur1; cur1 = cur1->next) + g_string_truncate(debugstr, 0); + for (cur1 = od->ssi.local.data; cur1; cur1 = cur1->next) aim_ssi_item_debug_append(debugstr, "\t", cur1); purple_debug_misc("oscar", "Dumping item list of account %s:\n%s", - purple_connection_get_account(od->gc)->username, debugstr->str); + purple_account_get_username(purple_connection_get_account(od->gc)), debugstr->str); } } g_string_free(debugstr, TRUE); @@ -673,22 +705,18 @@ struct aim_ssi_item *cur, *del; struct aim_ssi_tmp *curtmp, *deltmp; - cur = od->ssi.official; + cur = od->ssi.official.data; while (cur) { del = cur; cur = cur->next; - g_free(del->name); - aim_tlvlist_free(del->data); - g_free(del); + aim_ssi_item_free(del); } - cur = od->ssi.local; + cur = od->ssi.local.data; while (cur) { del = cur; cur = cur->next; - g_free(del->name); - aim_tlvlist_free(del->data); - g_free(del); + aim_ssi_item_free(del); } curtmp = od->ssi.pending; @@ -699,22 +727,49 @@ } od->ssi.numitems = 0; - od->ssi.official = NULL; - od->ssi.local = NULL; + od->ssi.official.data = NULL; + od->ssi.local.data = NULL; od->ssi.pending = NULL; od->ssi.timestamp = (time_t)0; } /** - * This "cleans" the ssi list. It does the following: - * 1) Makes sure all buddies, permits, and denies have names. - * 2) Makes sure that all buddies are in a group that exist. - * 3) Deletes any empty groups + * Look up the given TLV type in the item's data. If the value of + * the TLV is not a valid UTF-8 string then use purple_utf8_salvage() + * to replace invalid bytes with question marks. + */ +static void cleanlist_ensure_utf8_data(struct aim_ssi_item *item, guint16 tlvtype) +{ + aim_tlv_t *tlv; + gchar *value, *salvaged; + + tlv = aim_tlv_gettlv(item->data, tlvtype, 1); + if (tlv && tlv->length && !g_utf8_validate((const gchar *)tlv->value, tlv->length, NULL)) { + purple_debug_warning("oscar", "cleanlist found invalid UTF-8 " + "for 0x%04hx field of 0x%04hx item with name %s. " + "Attempting to repair.\n", + tlvtype, item->type, item->name ? item->name : "(null)"); + value = g_strndup((const gchar *)tlv->value, tlv->length); + salvaged = purple_utf8_salvage(value); + g_free(value); + if (*salvaged) + aim_tlvlist_replace_str(&item->data, tlvtype, salvaged); + else + aim_tlvlist_remove(&item->data, tlvtype); + g_free(salvaged); + } +} + +/** + * This "cleans" the ssi list. It does things like: + * - Makes sure all buddies, permits, and denies have names + * - Makes sure all buddies are in a group that exist + * - Makes sure strings are valid UTF-8 * * @param od The oscar odion. * @return Return 0 if no errors, otherwise return the error number. */ -int aim_ssi_cleanlist(OscarData *od) +static int aim_ssi_cleanlist(OscarData *od) { struct aim_ssi_item *cur, *next; @@ -726,7 +781,7 @@ /* DESTROY any buddies that are directly in the master group. */ /* Do the same for buddies that are in a non-existant group. */ /* This will kind of mess up if you hit the item limit, but this function isn't too critical */ - cur = od->ssi.local; + cur = od->ssi.local.data; while (cur) { next = cur->next; if (!cur->name) { @@ -734,29 +789,42 @@ aim_ssi_delbuddy(od, NULL, NULL); else if (cur->type == AIM_SSI_TYPE_PERMIT || cur->type == AIM_SSI_TYPE_DENY || cur->type == AIM_SSI_TYPE_ICQDENY) aim_ssi_del_from_private_list(od, NULL, cur->type); - } else if ((cur->type == AIM_SSI_TYPE_BUDDY) && ((cur->gid == 0x0000) || (!aim_ssi_itemlist_find(od->ssi.local, cur->gid, 0x0000)))) { - char *alias = aim_ssi_getalias(od->ssi.local, NULL, cur->name); - aim_ssi_addbuddy(od, cur->name, "orphans", NULL, alias, NULL, NULL, FALSE); + } else if ((cur->type == AIM_SSI_TYPE_BUDDY) && ((cur->gid == 0x0000) || (!aim_ssi_itemlist_find(&od->ssi.local, cur->gid, 0x0000)))) { + char *alias = aim_ssi_getalias(&od->ssi.local, NULL, cur->name); + aim_ssi_addbuddy(od, cur->name, _("Buddies"), NULL, alias, NULL, NULL, FALSE); aim_ssi_delbuddy(od, cur->name, NULL); g_free(alias); } cur = next; } - /* Make sure there aren't any duplicate buddies in a group, or duplicate permits or denies */ - cur = od->ssi.local; + cur = od->ssi.local.data; while (cur) { if ((cur->type == AIM_SSI_TYPE_BUDDY) || (cur->type == AIM_SSI_TYPE_PERMIT) || (cur->type == AIM_SSI_TYPE_DENY)) { struct aim_ssi_item *cur2, *next2; + + /* Make sure there aren't any duplicate permits or denies, or + duplicate buddies within a group */ cur2 = cur->next; while (cur2) { next2 = cur2->next; - if ((cur->type == cur2->type) && (cur->gid == cur2->gid) && (cur->name != NULL) && (cur2->name != NULL) && (!oscar_util_name_compare(cur->name, cur2->name))) { + if (cur->type == cur2->type + && cur->gid == cur2->gid + && cur->name + && cur2->name + && !oscar_util_name_compare(cur->name, cur2->name)) + { aim_ssi_itemlist_del(&od->ssi.local, cur2); } cur2 = next2; } + + /* Make sure alias is valid UTF-8 */ + cleanlist_ensure_utf8_data(cur, 0x0131); + + /* Make sure comment is valid UTF-8 */ + cleanlist_ensure_utf8_data(cur, 0x013c); } cur = cur->next; } @@ -785,16 +853,16 @@ return -EINVAL; /* Find the parent */ - if (!(parent = aim_ssi_itemlist_finditem(od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP))) { + if (!(parent = aim_ssi_itemlist_finditem(&od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP))) { /* Find the parent's parent (the master group) */ - if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL) + if (aim_ssi_itemlist_find(&od->ssi.local, 0x0000, 0x0000) == NULL) aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL); /* Add the parent */ parent = aim_ssi_itemlist_add(&od->ssi.local, group, 0xFFFF, 0x0000, AIM_SSI_TYPE_GROUP, NULL); /* Modify the parent's parent (the master group) */ - aim_ssi_itemlist_rebuildgroup(od->ssi.local, NULL); + aim_ssi_itemlist_rebuildgroup(&od->ssi.local, NULL); } /* Create a TLV list for the new buddy */ @@ -812,7 +880,7 @@ aim_tlvlist_free(data); /* Modify the parent group */ - aim_ssi_itemlist_rebuildgroup(od->ssi.local, group); + aim_ssi_itemlist_rebuildgroup(&od->ssi.local, group); /* Sync our local list with the server list */ return aim_ssi_sync(od); @@ -824,7 +892,7 @@ if (!od || !name || !od->ssi.received_data) return -EINVAL; - if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL) + if (aim_ssi_itemlist_find(&od->ssi.local, 0x0000, 0x0000) == NULL) aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL); aim_ssi_itemlist_add(&od->ssi.local, name, 0x0000, 0xFFFF, list_type, NULL); @@ -839,7 +907,7 @@ if (!od) return -EINVAL; - if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, NULL, name, list_type))) + if (!(del = aim_ssi_itemlist_finditem(&od->ssi.local, NULL, name, list_type))) return -EINVAL; aim_ssi_itemlist_del(&od->ssi.local, del); @@ -862,14 +930,14 @@ return -EINVAL; /* Find the buddy */ - if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, group, name, AIM_SSI_TYPE_BUDDY))) + if (!(del = aim_ssi_itemlist_finditem(&od->ssi.local, group, name, AIM_SSI_TYPE_BUDDY))) return -EINVAL; /* Remove the item from the list */ aim_ssi_itemlist_del(&od->ssi.local, del); /* Modify the parent group */ - aim_ssi_itemlist_rebuildgroup(od->ssi.local, group); + aim_ssi_itemlist_rebuildgroup(&od->ssi.local, group); /* Sync our local list with the server list */ return aim_ssi_sync(od); @@ -891,7 +959,7 @@ return -EINVAL; /* Find the group */ - if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP))) + if (!(del = aim_ssi_itemlist_finditem(&od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP))) return -EINVAL; /* Don't delete the group if it's not empty */ @@ -903,7 +971,7 @@ aim_ssi_itemlist_del(&od->ssi.local, del); /* Modify the parent group */ - aim_ssi_itemlist_rebuildgroup(od->ssi.local, group); + aim_ssi_itemlist_rebuildgroup(&od->ssi.local, NULL); /* Sync our local list with the server list */ return aim_ssi_sync(od); @@ -925,7 +993,7 @@ GSList *data; /* Find the buddy */ - buddy = aim_ssi_itemlist_finditem(od->ssi.local, oldgn, bn, AIM_SSI_TYPE_BUDDY); + buddy = aim_ssi_itemlist_finditem(&od->ssi.local, oldgn, bn, AIM_SSI_TYPE_BUDDY); if (buddy == NULL) return -EINVAL; @@ -958,11 +1026,11 @@ if (!od || !gn || !bn) return -EINVAL; - if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, gn, bn, AIM_SSI_TYPE_BUDDY))) + if (!(tmp = aim_ssi_itemlist_finditem(&od->ssi.local, gn, bn, AIM_SSI_TYPE_BUDDY))) return -EINVAL; /* Either add or remove the 0x0131 TLV from the TLV chain */ - if ((alias != NULL) && (strlen(alias) > 0)) + if (alias && *alias) aim_tlvlist_replace_str(&tmp->data, 0x0131, alias); else aim_tlvlist_remove(&tmp->data, 0x0131); @@ -988,11 +1056,11 @@ if (!od || !gn || !bn) return -EINVAL; - if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, gn, bn, AIM_SSI_TYPE_BUDDY))) + if (!(tmp = aim_ssi_itemlist_finditem(&od->ssi.local, gn, bn, AIM_SSI_TYPE_BUDDY))) return -EINVAL; /* Either add or remove the 0x0131 TLV from the TLV chain */ - if ((comment != NULL) && (strlen(comment) > 0)) + if (comment && *comment) aim_tlvlist_replace_str(&tmp->data, 0x013c, comment); else aim_tlvlist_remove(&tmp->data, 0x013c); @@ -1016,11 +1084,10 @@ if (!od || !oldgn || !newgn) return -EINVAL; - if (!(group = aim_ssi_itemlist_finditem(od->ssi.local, oldgn, NULL, AIM_SSI_TYPE_GROUP))) + if (!(group = aim_ssi_itemlist_finditem(&od->ssi.local, oldgn, NULL, AIM_SSI_TYPE_GROUP))) return -EINVAL; - g_free(group->name); - group->name = g_strdup(newgn); + aim_ssi_item_set_name(&od->ssi.local, group, newgn); /* Sync our local list with the server list */ return aim_ssi_sync(od); @@ -1047,9 +1114,9 @@ return -EINVAL; /* Find the PDINFO item, or add it if it does not exist */ - if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, NULL, AIM_SSI_TYPE_PDINFO))) { + if (!(tmp = aim_ssi_itemlist_finditem(&od->ssi.local, NULL, NULL, AIM_SSI_TYPE_PDINFO))) { /* Make sure the master group exists */ - if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL) + if (aim_ssi_itemlist_find(&od->ssi.local, 0x0000, 0x0000) == NULL) aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL); tmp = aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PDINFO, NULL); @@ -1079,9 +1146,9 @@ return -EINVAL; /* Find the ICONINFO item, or add it if it does not exist */ - if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) { + if (!(tmp = aim_ssi_itemlist_finditem(&od->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) { /* Make sure the master group exists */ - if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL) + if (aim_ssi_itemlist_find(&od->ssi.local, 0x0000, 0x0000) == NULL) aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL); tmp = aim_ssi_itemlist_add(&od->ssi.local, "1", 0x0000, 0xFFFF, AIM_SSI_TYPE_ICONINFO, NULL); @@ -1139,9 +1206,9 @@ return -EINVAL; /* Find the PRESENCEPREFS item, or add it if it does not exist */ - if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS))) { + if (!(tmp = aim_ssi_itemlist_finditem(&od->ssi.local, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS))) { /* Make sure the master group exists */ - if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL) + if (aim_ssi_itemlist_find(&od->ssi.local, 0x0000, 0x0000) == NULL) aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL); tmp = aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PRESENCEPREFS, NULL); @@ -1257,7 +1324,7 @@ aim_tlvlist_free(data); } purple_debug_misc("oscar", "Reading items from tlvlist for account %s:\n%s", - purple_connection_get_account(od->gc)->username, debugstr->str); + purple_account_get_username(purple_connection_get_account(od->gc)), debugstr->str); g_string_free(debugstr, TRUE); /* Read in the timestamp */ @@ -1266,9 +1333,12 @@ if (!(snac->flags & 0x0001)) { /* Make a copy of the list */ struct aim_ssi_item *cur; - for (cur=od->ssi.official; cur; cur=cur->next) + for (cur=od->ssi.official.data; cur; cur=cur->next) aim_ssi_itemlist_add(&od->ssi.local, cur->name, cur->gid, cur->bid, cur->type, cur->data); + /* Clean the buddy list */ + aim_ssi_cleanlist(od); + od->ssi.received_data = TRUE; if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) @@ -1416,18 +1486,16 @@ data = NULL; /* Replace the 2 local items with the given one */ - if ((item = aim_ssi_itemlist_find(od->ssi.local, gid, bid))) { + if ((item = aim_ssi_itemlist_find(&od->ssi.local, gid, bid))) { item->type = type; - g_free(item->name); - item->name = g_strdup(name); + aim_ssi_item_set_name(&od->ssi.local, item, name); aim_tlvlist_free(item->data); item->data = aim_tlvlist_copy(data); } - if ((item = aim_ssi_itemlist_find(od->ssi.official, gid, bid))) { + if ((item = aim_ssi_itemlist_find(&od->ssi.official, gid, bid))) { item->type = type; - g_free(item->name); - item->name = g_strdup(name); + aim_ssi_item_set_name(&od->ssi.official, item, name); aim_tlvlist_free(item->data); item->data = aim_tlvlist_copy(data); } @@ -1461,9 +1529,9 @@ byte_stream_get16(bs); byte_stream_advance(bs, byte_stream_get16(bs)); - if ((del = aim_ssi_itemlist_find(od->ssi.local, gid, bid))) + if ((del = aim_ssi_itemlist_find(&od->ssi.local, gid, bid))) aim_ssi_itemlist_del(&od->ssi.local, del); - if ((del = aim_ssi_itemlist_find(od->ssi.official, gid, bid))) + if ((del = aim_ssi_itemlist_find(&od->ssi.official, gid, bid))) aim_ssi_itemlist_del(&od->ssi.official, del); if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) @@ -1504,7 +1572,8 @@ if (cur->action == SNAC_SUBTYPE_FEEDBAG_ADD) { /* Remove the item from the local list */ /* Make sure cur->item is still valid memory */ - if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) { + /* TODO: "Still valid memory"? That's bad form. */ + if (aim_ssi_itemlist_valid(&od->ssi.local, cur->item)) { cur->name = g_strdup(cur->item->name); aim_ssi_itemlist_del(&od->ssi.local, cur->item); } @@ -1512,11 +1581,10 @@ } else if (cur->action == SNAC_SUBTYPE_FEEDBAG_MOD) { /* Replace the local item with the item from the official list */ - if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) { + if (aim_ssi_itemlist_valid(&od->ssi.local, cur->item)) { struct aim_ssi_item *cur1; - if ((cur1 = aim_ssi_itemlist_find(od->ssi.official, cur->item->gid, cur->item->bid))) { - g_free(cur->item->name); - cur->item->name = g_strdup(cur1->name); + if ((cur1 = aim_ssi_itemlist_find(&od->ssi.official, cur->item->gid, cur->item->bid))) { + aim_ssi_item_set_name(&od->ssi.official, cur->item, cur1->name); aim_tlvlist_free(cur->item->data); cur->item->data = aim_tlvlist_copy(cur1->data); } @@ -1525,7 +1593,7 @@ } else if (cur->action == SNAC_SUBTYPE_FEEDBAG_DEL) { /* Add the item back into the local list */ - if (aim_ssi_itemlist_valid(od->ssi.official, cur->item)) { + if (aim_ssi_itemlist_valid(&od->ssi.official, cur->item)) { aim_ssi_itemlist_add(&od->ssi.local, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data); } else cur->item = NULL; @@ -1535,18 +1603,17 @@ /* Do the exact opposite */ if (cur->action == SNAC_SUBTYPE_FEEDBAG_ADD) { /* Add the local item to the official list */ - if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) { + if (aim_ssi_itemlist_valid(&od->ssi.local, cur->item)) { aim_ssi_itemlist_add(&od->ssi.official, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data); } else cur->item = NULL; } else if (cur->action == SNAC_SUBTYPE_FEEDBAG_MOD) { /* Replace the official item with the item from the local list */ - if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) { + if (aim_ssi_itemlist_valid(&od->ssi.local, cur->item)) { struct aim_ssi_item *cur1; - if ((cur1 = aim_ssi_itemlist_find(od->ssi.official, cur->item->gid, cur->item->bid))) { - g_free(cur1->name); - cur1->name = g_strdup(cur->item->name); + if ((cur1 = aim_ssi_itemlist_find(&od->ssi.official, cur->item->gid, cur->item->bid))) { + aim_ssi_item_set_name(&od->ssi.official, cur1, cur->item->name); aim_tlvlist_free(cur1->data); cur1->data = aim_tlvlist_copy(cur->item->data); } @@ -1555,7 +1622,7 @@ } else if (cur->action == SNAC_SUBTYPE_FEEDBAG_DEL) { /* Remove the item from the official list */ - if (aim_ssi_itemlist_valid(od->ssi.official, cur->item)) + if (aim_ssi_itemlist_valid(&od->ssi.official, cur->item)) aim_ssi_itemlist_del(&od->ssi.official, cur->item); cur->item = NULL; } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/oscar/family_icbm.c --- a/libpurple/protocols/oscar/family_icbm.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/oscar/family_icbm.c Fri Apr 06 04:30:00 2012 +0000 @@ -650,6 +650,9 @@ GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL; ByteStream hdrbs; + g_return_if_fail(bn != NULL); + g_return_if_fail(ip != NULL); + conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM); if (conn == NULL) return; @@ -1941,7 +1944,7 @@ account = purple_connection_get_account(od->gc); - statxml = g_strdup_printf(fmt, account->username); + statxml = g_strdup_printf(fmt, purple_account_get_username(account)); xmllen = strlen(statxml); aim_icbm_makecookie(cookie); @@ -2035,7 +2038,7 @@ /* if (!strcmp(account->username, sn)) icq_im_xstatus_request(od, sn); */ - status = purple_presence_get_active_status(account->presence); + status = purple_presence_get_active_status(purple_account_get_presence(account)); if (!status) return -EINVAL; @@ -2051,7 +2054,7 @@ if (!msg) return -EINVAL; - statxml = g_strdup_printf(fmt, account->username, title, msg); + statxml = g_strdup_printf(fmt, purple_account_get_username(account), title, msg); len = strlen(statxml); purple_debug_misc("oscar", "X-Status AutoReply: %s, %s\n", formatted_msg, msg); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/oscar/flap_connection.c --- a/libpurple/protocols/oscar/flap_connection.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/oscar/flap_connection.c Fri Apr 06 04:30:00 2012 +0000 @@ -456,7 +456,7 @@ * TODO: If we don't have a SNAC_FAMILY_LOCATE connection then * we should try to request one instead of disconnecting. */ - if (!account->disconnecting && ((od->oscar_connections == NULL) + if (!purple_account_is_disconnecting(account) && ((od->oscar_connections == NULL) || (!flap_connection_getbytype(od, SNAC_FAMILY_LOCATE)))) { /* No more FLAP connections! Sign off this PurpleConnection! */ @@ -487,7 +487,7 @@ if (tmp != NULL) { - purple_connection_error_reason(od->gc, reason, tmp); + purple_connection_error(od->gc, reason, tmp); g_free(tmp); } } @@ -921,7 +921,7 @@ OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno)); break; } - conn->od->gc->last_received = time(NULL); + purple_connection_update_last_received(conn->od->gc); /* If we don't even have a complete FLAP header then do nothing */ conn->header_received += read; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/oscar/libaim.c --- a/libpurple/protocols/oscar/libaim.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/oscar/libaim.c Fri Apr 06 04:30:00 2012 +0000 @@ -29,6 +29,7 @@ static PurplePluginProtocolInfo prpl_info = { + sizeof(PurplePluginProtocolInfo), /* struct_size */ OPT_PROTO_MAIL_CHECK | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE, NULL, /* user_splits */ NULL, /* protocol_options */ @@ -50,7 +51,7 @@ oscar_set_status, /* set_status */ oscar_set_idle, /* set_idle */ oscar_change_passwd, /* change_passwd */ - NULL, /* add_buddy */ + oscar_add_buddy, /* add_buddy */ NULL, /* add_buddies */ oscar_remove_buddy, /* remove_buddy */ NULL, /* remove_buddies */ @@ -69,7 +70,6 @@ oscar_keepalive, /* keepalive */ NULL, /* register_user */ NULL, /* get_cb_info */ - NULL, /* get_cb_away */ oscar_alias_buddy, /* alias_buddy */ oscar_move_buddy, /* group_buddy */ oscar_rename_group, /* rename_group */ @@ -94,15 +94,12 @@ NULL, /* unregister_user */ NULL, /* send_attention */ NULL, /* get_attention_types */ - sizeof(PurplePluginProtocolInfo), /* struct_size */ NULL, /* get_account_text_table */ NULL, /* initiate_media */ NULL, /* get_media_caps */ NULL, /* get_moods */ NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - oscar_add_buddy, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ + NULL /* get_public_alias */ }; static PurplePluginInfo info = diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/oscar/libicq.c --- a/libpurple/protocols/oscar/libicq.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/oscar/libicq.c Fri Apr 06 04:30:00 2012 +0000 @@ -38,6 +38,7 @@ static PurplePluginProtocolInfo prpl_info = { + sizeof(PurplePluginProtocolInfo), /* struct_size */ OPT_PROTO_MAIL_CHECK | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE, NULL, /* user_splits */ NULL, /* protocol_options */ @@ -59,7 +60,7 @@ oscar_set_status, /* set_status */ oscar_set_idle, /* set_idle */ oscar_change_passwd, /* change_passwd */ - NULL, /* add_buddy */ + oscar_add_buddy, /* add_buddy */ NULL, /* add_buddies */ oscar_remove_buddy, /* remove_buddy */ NULL, /* remove_buddies */ @@ -78,7 +79,6 @@ oscar_keepalive, /* keepalive */ NULL, /* register_user */ NULL, /* get_cb_info */ - NULL, /* get_cb_away */ oscar_alias_buddy, /* alias_buddy */ oscar_move_buddy, /* group_buddy */ oscar_rename_group, /* rename_group */ @@ -103,16 +103,12 @@ NULL, /* unregister_user */ NULL, /* send_attention */ NULL, /* get_attention_types */ - - sizeof(PurplePluginProtocolInfo), /* struct_size */ icq_get_account_text_table, /* get_account_text_table */ NULL, /* initiate_media */ NULL, /* can_do_media */ oscar_get_purple_moods, /* get_moods */ NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - oscar_add_buddy, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ + NULL /* get_public_alias */ }; static PurplePluginInfo info = diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/oscar/oft.c --- a/libpurple/protocols/oscar/oft.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/oscar/oft.c Fri Apr 06 04:30:00 2012 +0000 @@ -362,10 +362,10 @@ if (purple_circ_buffer_get_max_read(conn->buffer_outgoing) == 0) { + int fd = conn->fd; conn->sending_data_timer = 0; - conn->xfer->fd = conn->fd; conn->fd = -1; - purple_xfer_start(conn->xfer, conn->xfer->fd, NULL, 0); + purple_xfer_start(conn->xfer, fd, NULL, 0); return FALSE; } @@ -508,7 +508,7 @@ purple_input_remove(conn->watcher_incoming); conn->watcher_incoming = 0; - conn->xfer->fd = conn->fd; + purple_xfer_set_fd(conn->xfer, conn->fd); conn->fd = -1; conn->disconnect_reason = OSCAR_DISCONNECT_DONE; peer_connection_schedule_destroy(conn, conn->disconnect_reason, NULL); @@ -589,7 +589,7 @@ { PeerConnection *conn; - conn = xfer->data; + conn = purple_xfer_get_protocol_data(xfer); conn->flags |= PEER_CONNECTION_FLAG_APPROVED; peer_connection_trynext(conn); } @@ -599,11 +599,11 @@ { PeerConnection *conn; - conn = xfer->data; + conn = purple_xfer_get_protocol_data(xfer); /* Tell the other person that we've received everything */ - conn->fd = conn->xfer->fd; - conn->xfer->fd = -1; + conn->fd = purple_xfer_get_fd(conn->xfer); + purple_xfer_set_fd(conn->xfer, -1); peer_oft_send_done(conn); conn->disconnect_reason = OSCAR_DISCONNECT_DONE; @@ -617,7 +617,7 @@ PeerConnection *conn; /* Update our rolling checksum. Like Walmart, yo. */ - conn = xfer->data; + conn = purple_xfer_get_protocol_data(xfer); conn->xferdata.recvcsum = peer_oft_checksum_chunk(buffer, size, conn->xferdata.recvcsum, purple_xfer_get_bytes_sent(xfer) & 1); } @@ -651,9 +651,9 @@ peer_oft_sendcb_init(PurpleXfer *xfer) { PeerConnection *conn; - size_t size; + goffset size; - conn = xfer->data; + conn = purple_xfer_get_protocol_data(xfer); conn->flags |= PEER_CONNECTION_FLAG_APPROVED; /* Make sure the file size can be represented in 32 bits */ @@ -665,9 +665,9 @@ size2 = purple_str_size_to_units(G_MAXUINT32); tmp = g_strdup_printf(_("File %s is %s, which is larger than " "the maximum size of %s."), - xfer->local_filename, size1, size2); + purple_xfer_get_local_filename(xfer), size1, size2); purple_xfer_error(purple_xfer_get_type(xfer), - purple_xfer_get_account(xfer), xfer->who, tmp); + purple_xfer_get_account(xfer), purple_xfer_get_remote_user(xfer), tmp); g_free(size1); g_free(size2); g_free(tmp); @@ -689,9 +689,9 @@ strncpy((gchar *)conn->xferdata.idstring, "Cool FileXfer", 31); conn->xferdata.modtime = 0; conn->xferdata.cretime = 0; - xfer->filename = g_path_get_basename(xfer->local_filename); - conn->xferdata.name_length = MAX(64, strlen(xfer->filename) + 1); - conn->xferdata.name = (guchar *)g_strndup(xfer->filename, conn->xferdata.name_length - 1); + purple_xfer_set_filename(xfer, g_path_get_basename(purple_xfer_get_local_filename(xfer))); + conn->xferdata.name_length = MAX(64, strlen(purple_xfer_get_filename(xfer)) + 1); + conn->xferdata.name = (guchar *)g_strndup(purple_xfer_get_filename(xfer), conn->xferdata.name_length - 1); peer_oft_checksum_file(conn, xfer, peer_oft_checksum_calculated_cb, G_MAXUINT32); @@ -713,7 +713,7 @@ { PeerConnection *conn; - conn = xfer->data; + conn = purple_xfer_get_protocol_data(xfer); /* * If we're done sending, intercept the socket from the core ft code @@ -721,9 +721,9 @@ */ if (purple_xfer_get_bytes_remaining(xfer) <= 0) { - purple_input_remove(xfer->watcher); - conn->fd = xfer->fd; - xfer->fd = -1; + purple_input_remove(purple_xfer_get_watcher(xfer)); + conn->fd = purple_xfer_get_fd(xfer); + purple_xfer_set_fd(xfer, -1); conn->watcher_incoming = purple_input_add(conn->fd, PURPLE_INPUT_READ, peer_connection_recv_cb, conn); } @@ -742,7 +742,7 @@ { PeerConnection *conn; - conn = xfer->data; + conn = purple_xfer_get_protocol_data(xfer); if (conn == NULL) return; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/oscar/oscar.c --- a/libpurple/protocols/oscar/oscar.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/oscar/oscar.c Fri Apr 06 04:30:00 2012 +0000 @@ -308,7 +308,7 @@ gchar *msg; msg = g_strdup_printf(_("Unable to connect to authentication server: %s"), error_message); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); g_free(msg); } else if (conn->type == SNAC_FAMILY_LOCATE) @@ -316,7 +316,7 @@ gchar *msg; msg = g_strdup_printf(_("Unable to connect to BOS server: %s"), error_message); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); g_free(msg); } else @@ -578,7 +578,7 @@ gc = data; od = purple_connection_get_protocol_data(gc); report_idle = strcmp((const char *)value, "none") != 0; - presence = aim_ssi_getpresence(od->ssi.local); + presence = aim_ssi_getpresence(&od->ssi.local); if (report_idle) aim_ssi_setpresence(od, presence | AIM_SSI_PRESENCE_FLAG_SHOWIDLE); @@ -600,7 +600,7 @@ gc = data; od = purple_connection_get_protocol_data(gc); - presence = aim_ssi_getpresence(od->ssi.local); + presence = aim_ssi_getpresence(&od->ssi.local); if (value) aim_ssi_setpresence(od, presence & ~AIM_SSI_PRESENCE_FLAG_NORECENTBUDDIES); @@ -655,6 +655,7 @@ GList *sorted_handlers; GList *cur; GString *msg = g_string_new(""); + PurpleConnectionFlags flags; gc = purple_account_get_connection(account); od = oscar_data_new(); @@ -735,28 +736,30 @@ if (!oscar_util_valid_name(purple_account_get_username(account))) { gchar *buf; buf = g_strdup_printf(_("Unable to sign on as %s because the username is invalid. Usernames must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), purple_account_get_username(account)); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, buf); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, buf); g_free(buf); return; } - gc->flags |= PURPLE_CONNECTION_HTML; + flags = PURPLE_CONNECTION_HTML; if (g_str_equal(purple_account_get_protocol_id(account), "prpl-icq")) { od->icq = TRUE; } else { - gc->flags |= PURPLE_CONNECTION_AUTO_RESP; + flags |= PURPLE_CONNECTION_AUTO_RESP; } /* Set this flag based on the protocol_id rather than the username, because that is what's tied to the get_moods prpl callback. */ if (g_str_equal(purple_account_get_protocol_id(account), "prpl-icq")) - gc->flags |= PURPLE_CONNECTION_SUPPORT_MOODS; + flags |= PURPLE_CONNECTION_SUPPORT_MOODS; + + purple_connection_set_flags(gc, flags); od->default_port = purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT); encryption_type = purple_account_get_string(account, "encryption", OSCAR_DEFAULT_ENCRYPTION); if (!purple_ssl_is_supported() && strcmp(encryption_type, OSCAR_REQUIRE_ENCRYPTION) == 0) { - purple_connection_error_reason( + purple_connection_error( gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("You required encryption in your account settings, but encryption is not supported by your system.")); @@ -825,7 +828,7 @@ } if (newconn->gsc == NULL && newconn->connect_data == NULL) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); return; } @@ -1000,7 +1003,7 @@ pos->len = len; pos->modname = g_strdup(modname); - if (purple_proxy_connect(pos->gc, pos->gc->account, "pidgin.im", 80, + if (purple_proxy_connect(pos->gc, purple_connection_get_account(pos->gc), "pidgin.im", 80, straight_to_hell, pos) == NULL) { char buf[256]; @@ -1048,7 +1051,7 @@ if (conn->gsc == NULL && conn->connect_data == NULL) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); return 0; } @@ -1087,41 +1090,41 @@ switch (info->errorcode) { case 0x01: /* Unregistered username */ - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_USERNAME, _("Username does not exist")); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_INVALID_USERNAME, _("Username does not exist")); break; case 0x05: /* Incorrect password */ if (!purple_account_get_remember_password(account)) purple_account_set_password(account, NULL); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Incorrect password")); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Incorrect password")); break; case 0x11: /* Suspended account */ - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Your account is currently suspended")); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Your account is currently suspended")); break; case 0x02: case 0x14: /* service temporarily unavailable */ - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("The AOL Instant Messenger service is temporarily unavailable.")); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("The AOL Instant Messenger service is temporarily unavailable.")); break; case 0x18: /* username connecting too frequently */ - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Your username has been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer.")); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Your username has been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer.")); break; case 0x1c: { /* client too old */ g_snprintf(buf, sizeof(buf), _("The client version you are using is too old. Please upgrade at %s"), oscar_get_ui_info_string("website", PURPLE_WEBSITE)); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, buf); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, buf); break; } case 0x1d: /* IP address connecting too frequently */ - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Your IP address has been connecting and disconnecting too frequently. Wait a minute and try again. If you continue to try, you will need to wait even longer.")); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Your IP address has been connecting and disconnecting too frequently. Wait a minute and try again. If you continue to try, you will need to wait even longer.")); break; default: - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Unknown reason")); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Unknown reason")); break; } purple_debug_info("oscar", "Login Error Code 0x%04hx\n", info->errorcode); @@ -1169,7 +1172,7 @@ g_free(host); if (newconn->gsc == NULL && newconn->connect_data == NULL) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); return 0; } @@ -1199,7 +1202,7 @@ PurpleConnection *gc = user_data; /* Disconnect */ - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("The SecurID key entered is invalid")); } @@ -1292,7 +1295,7 @@ purple_debug_warning("oscar", "We won't use SSL for FLAP type 0x%04hx.\n", redir->group); } else if (strcmp(encryption_type, OSCAR_REQUIRE_ENCRYPTION) == 0) { purple_debug_error("oscar", "FLAP server %s:%d of type 0x%04hx doesn't support encryption.", host, port, redir->group); - purple_connection_error_reason( + purple_connection_error( gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("You required encryption in your account settings, but one of the servers doesn't support it.")); @@ -1547,7 +1550,7 @@ purple_prpl_got_user_status(account, info->bn, OSCAR_STATUS_ID_OFFLINE, NULL); purple_prpl_got_user_status_deactive(account, info->bn, OSCAR_STATUS_ID_MOBILE); - g_hash_table_remove(od->buddyinfo, purple_normalize(gc->account, info->bn)); + g_hash_table_remove(od->buddyinfo, purple_normalize(purple_connection_get_account(gc), info->bn)); return 1; } @@ -2278,7 +2281,7 @@ return 0; } -static int purple_parse_clientauto_ch4(OscarData *od, char *who, guint16 reason, guint32 state, char *msg) { +static int purple_parse_clientauto_ch4(OscarData *od, const char *who, guint16 reason, guint32 state, char *msg) { PurpleConnection *gc = od->gc; switch(reason) { @@ -2286,16 +2289,20 @@ char *statusmsg, **splitmsg; PurpleNotifyUserInfo *user_info; + statusmsg = oscar_icqstatus(state); + /* Split at (carriage return/newline)'s, then rejoin later with BRs between. */ - statusmsg = oscar_icqstatus(state); + /* TODO: Don't we need to escape each piece? */ splitmsg = g_strsplit(msg, "\r\n", 0); user_info = purple_notify_user_info_new(); - purple_notify_user_info_add_pair(user_info, _("UIN"), who); - purple_notify_user_info_add_pair(user_info, _("Status"), statusmsg); + purple_notify_user_info_add_pair_plaintext(user_info, _("UIN"), who); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Status"), statusmsg); purple_notify_user_info_add_section_break(user_info); - purple_notify_user_info_add_pair(user_info, NULL, g_strjoinv("
", splitmsg)); + purple_notify_user_info_add_pair_html(user_info, NULL, g_strjoinv("
", splitmsg)); g_free(statusmsg); g_strfreev(splitmsg); @@ -2309,16 +2316,20 @@ char *statusmsg, **splitmsg; PurpleNotifyUserInfo *user_info; + statusmsg = oscar_icqstatus(state); + /* Split at (carriage return/newline)'s, then rejoin later with BRs between. */ - statusmsg = oscar_icqstatus(state); + /* TODO: Don't we need to escape each piece? */ splitmsg = g_strsplit(msg, "\r\n", 0); user_info = purple_notify_user_info_new(); - purple_notify_user_info_add_pair(user_info, _("UIN"), who); - purple_notify_user_info_add_pair(user_info, _("Status"), statusmsg); + purple_notify_user_info_add_pair_plaintext(user_info, _("UIN"), who); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Status"), statusmsg); purple_notify_user_info_add_section_break(user_info); - purple_notify_user_info_add_pair(user_info, NULL, g_strjoinv("
", splitmsg)); + purple_notify_user_info_add_pair_html(user_info, NULL, g_strjoinv("
", splitmsg)); g_free(statusmsg); g_strfreev(splitmsg); @@ -2808,7 +2819,7 @@ od->rights.maxsiglen = od->rights.maxawaymsglen = (guint)maxsiglen; aim_locate_setcaps(od, purple_caps); - oscar_set_info_and_status(account, TRUE, account->user_info, TRUE, + oscar_set_info_and_status(account, TRUE, purple_account_get_user_info(account), TRUE, purple_account_get_active_status(account)); return 1; @@ -3168,9 +3179,9 @@ else { /* Don't send if this turkey is in our deny list */ GSList *list; - for (list=gc->account->deny; (list && oscar_util_name_compare(name, list->data)); list=list->next); + for (list=purple_connection_get_account(gc)->deny; (list && oscar_util_name_compare(name, list->data)); list=list->next); if (!list) { - struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(gc->account, name)); + struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(purple_connection_get_account(gc), name)); if (bi && bi->typingnot) { if (state == PURPLE_TYPING) aim_im_sendmtn(od, 0x0001, name, 0x0002); @@ -3470,13 +3481,11 @@ static guint32 oscar_get_extended_status(PurpleConnection *gc) { - OscarData *od; PurpleAccount *account; PurpleStatus *status; const gchar *status_id; guint32 data = 0x00000000; - od = purple_connection_get_protocol_data(gc); account = purple_connection_get_account(gc); status = purple_account_get_active_status(account); status_id = purple_status_get_id(status); @@ -3716,7 +3725,7 @@ } if (od->ssi.received_data) { - if (!aim_ssi_itemlist_finditem(od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY)) { + if (!aim_ssi_itemlist_finditem(&od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY)) { purple_debug_info("oscar", "ssi: adding buddy %s to group %s\n", bname, gname); aim_ssi_addbuddy(od, bname, gname, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, 0); @@ -3728,8 +3737,8 @@ purple_prpl_got_user_status(account, bname, OSCAR_STATUS_ID_MOBILE, NULL); } - } else if (aim_ssi_waitingforauth(od->ssi.local, - aim_ssi_itemlist_findparentname(od->ssi.local, bname), + } else if (aim_ssi_waitingforauth(&od->ssi.local, + aim_ssi_itemlist_findparentname(&od->ssi.local, bname), bname)) { /* Not authorized -- Re-request authorization */ oscar_auth_sendrequest(gc, bname, msg); @@ -3767,7 +3776,7 @@ OscarData *od = purple_connection_get_protocol_data(gc); if (od->ssi.received_data) { - char *gname = aim_ssi_itemlist_findparentname(od->ssi.local, name); + char *gname = aim_ssi_itemlist_findparentname(&od->ssi.local, name); if (gname) { purple_debug_info("oscar", "ssi: changing the alias for buddy %s to %s\n", name, alias ? alias : "(none)"); @@ -3784,7 +3793,7 @@ if (od->ssi.received_data) { const char *gname = purple_group_get_name(group); - if (aim_ssi_itemlist_finditem(od->ssi.local, gname, NULL, AIM_SSI_TYPE_GROUP)) { + if (aim_ssi_itemlist_finditem(&od->ssi.local, gname, NULL, AIM_SSI_TYPE_GROUP)) { GList *cur, *groups = NULL; PurpleAccount *account = purple_connection_get_account(gc); @@ -3798,7 +3807,7 @@ } purple_account_remove_buddies(account, moved_buddies, groups); - purple_account_add_buddies(account, moved_buddies); + purple_account_add_buddies(account, moved_buddies, NULL); g_list_free(groups); purple_debug_info("oscar", "ssi: moved all buddies from group %s to %s\n", old_name, gname); @@ -3915,9 +3924,6 @@ purple_debug_info("oscar", "ssi: syncing local list and server list\n"); - /* Clean the buddy list */ - aim_ssi_cleanlist(od); - /*** Begin code for pruning buddies from local list if they're not in server list ***/ /* Buddies */ @@ -3935,7 +3941,7 @@ gname = purple_group_get_name(g); bname = purple_buddy_get_name(b); - if (aim_ssi_itemlist_exists(od->ssi.local, bname)) { + if (aim_ssi_itemlist_exists(&od->ssi.local, bname)) { /* If the buddy is an ICQ user then load his nickname */ const char *servernick = purple_blist_node_get_string((PurpleBlistNode*)b, "servernick"); char *alias; @@ -3944,7 +3950,7 @@ serv_got_alias(gc, bname, servernick); /* Store local alias on server */ - alias = aim_ssi_getalias(od->ssi.local, gname, bname); + alias = aim_ssi_getalias(&od->ssi.local, gname, bname); balias = purple_buddy_get_local_buddy_alias(b); if (!alias && balias && *balias) aim_ssi_aliasbuddy(od, gname, bname, balias); @@ -3967,7 +3973,7 @@ while (next != NULL) { cur = next; next = next->next; - if (!aim_ssi_itemlist_finditem(od->ssi.local, NULL, cur->data, AIM_SSI_TYPE_PERMIT)) { + if (!aim_ssi_itemlist_finditem(&od->ssi.local, NULL, cur->data, AIM_SSI_TYPE_PERMIT)) { purple_debug_info("oscar", "ssi: removing permit %s from local list\n", (const char *)cur->data); purple_privacy_permit_remove(account, cur->data, TRUE); @@ -3980,7 +3986,7 @@ while (next != NULL) { cur = next; next = next->next; - if (!aim_ssi_itemlist_finditem(od->ssi.local, NULL, cur->data, deny_entry_type)) { + if (!aim_ssi_itemlist_finditem(&od->ssi.local, NULL, cur->data, deny_entry_type)) { purple_debug_info("oscar", "ssi: removing deny %s from local list\n", (const char *)cur->data); purple_privacy_deny_remove(account, cur->data, TRUE); @@ -3988,7 +3994,7 @@ } /* Presence settings (idle time visibility) */ - tmp = aim_ssi_getpresence(od->ssi.local); + tmp = aim_ssi_getpresence(&od->ssi.local); if (tmp != 0xFFFFFFFF) { const char *idle_reporting_pref; gboolean report_idle; @@ -4006,7 +4012,7 @@ /*** Begin code for adding from server list to local list ***/ - for (curitem=od->ssi.local; curitem; curitem=curitem->next) { + for (curitem=od->ssi.local.data; curitem; curitem=curitem->next) { if (curitem->name && !g_utf8_validate(curitem->name, -1, NULL)) { /* Got node with invalid UTF-8 in the name. Skip it. */ purple_debug_warning("oscar", "ssi: server list contains item of " @@ -4020,17 +4026,17 @@ struct aim_ssi_item *groupitem; char *gname, *gname_utf8, *alias, *alias_utf8; - groupitem = aim_ssi_itemlist_find(od->ssi.local, curitem->gid, 0x0000); + groupitem = aim_ssi_itemlist_find(&od->ssi.local, curitem->gid, 0x0000); gname = groupitem ? groupitem->name : NULL; gname_utf8 = oscar_utf8_try_convert(account, od, gname); - g = purple_find_group(gname_utf8 ? gname_utf8 : _("Orphans")); + g = purple_find_group(gname_utf8 ? gname_utf8 : _("Buddies")); if (g == NULL) { - g = purple_group_new(gname_utf8 ? gname_utf8 : _("Orphans")); + g = purple_group_new(gname_utf8 ? gname_utf8 : _("Buddies")); purple_blist_add_group(g, NULL); } - alias = aim_ssi_getalias(od->ssi.local, gname, curitem->name); + alias = aim_ssi_getalias_from_item(curitem); alias_utf8 = oscar_utf8_try_convert(account, od, alias); b = purple_find_buddy_in_group(account, curitem->name, g); @@ -4099,12 +4105,12 @@ * a part of your status and not really related to blocking. */ if (!od->icq && curitem->data) { - guint8 perm_deny = aim_ssi_getpermdeny(od->ssi.local); - if (perm_deny != 0 && perm_deny != account->perm_deny) + guint8 perm_deny = aim_ssi_getpermdeny(&od->ssi.local); + if (perm_deny != 0 && perm_deny != purple_account_get_privacy_type(account)) { purple_debug_info("oscar", - "ssi: changing permdeny from %d to %hhu\n", account->perm_deny, perm_deny); - account->perm_deny = perm_deny; + "ssi: changing permdeny from %d to %hhu\n", purple_account_get_privacy_type(account), perm_deny); + purple_account_set_privacy_type(account, perm_deny); } } } break; @@ -4228,10 +4234,10 @@ if ((type != 0x0000) || (name == NULL)) return 1; - gname = aim_ssi_itemlist_findparentname(od->ssi.local, name); + gname = aim_ssi_itemlist_findparentname(&od->ssi.local, name); gname_utf8 = gname ? oscar_utf8_try_convert(account, od, gname) : NULL; - alias = aim_ssi_getalias(od->ssi.local, gname, name); + alias = aim_ssi_getalias(&od->ssi.local, gname, name); alias_utf8 = oscar_utf8_try_convert(account, od, alias); g_free(alias); @@ -4250,13 +4256,13 @@ */ b = purple_buddy_new(account, name, alias_utf8); - if (!(g = purple_find_group(gname_utf8 ? gname_utf8 : _("Orphans")))) { - g = purple_group_new(gname_utf8 ? gname_utf8 : _("Orphans")); + if (!(g = purple_find_group(gname_utf8 ? gname_utf8 : _("Buddies")))) { + g = purple_group_new(gname_utf8 ? gname_utf8 : _("Buddies")); purple_blist_add_group(g, NULL); } purple_debug_info("oscar", - "ssi: adding buddy %s to group %s to local list\n", name, gname_utf8 ? gname_utf8 : _("Orphans")); + "ssi: adding buddy %s to group %s to local list\n", name, gname_utf8 ? gname_utf8 : _("Buddies")); purple_blist_add_buddy(b, NULL, g, NULL); /* Mobile users should always be online */ @@ -4269,7 +4275,7 @@ } - ssi_item = aim_ssi_itemlist_finditem(od->ssi.local, + ssi_item = aim_ssi_itemlist_finditem(&od->ssi.local, gname, name, AIM_SSI_TYPE_BUDDY); if (ssi_item == NULL) { @@ -4608,7 +4614,6 @@ PurpleAccount *account = NULL; PurplePresence *presence; PurpleStatus *status; - const char *status_id; aim_userinfo_t *userinfo = NULL; const char *name; @@ -4623,13 +4628,12 @@ presence = purple_buddy_get_presence(b); status = purple_presence_get_active_status(presence); - status_id = purple_status_get_id(status); if (purple_presence_is_online(presence) == FALSE) { char *gname; if ((name) && (od) && (od->ssi.received_data) && - (gname = aim_ssi_itemlist_findparentname(od->ssi.local, name)) && - (aim_ssi_waitingforauth(od->ssi.local, gname, name))) { + (gname = aim_ssi_itemlist_findparentname(&od->ssi.local, name)) && + (aim_ssi_waitingforauth(&od->ssi.local, gname, name))) { return "not-authorized"; } } @@ -4682,7 +4686,6 @@ OscarData *od; const PurplePresence *presence; const PurpleStatus *status; - const char *id; const char *message; gchar *ret = NULL; @@ -4691,13 +4694,12 @@ od = purple_connection_get_protocol_data(gc); presence = purple_buddy_get_presence(b); status = purple_presence_get_active_status(presence); - id = purple_status_get_id(status); if ((od != NULL) && !purple_presence_is_online(presence)) { const char *name = purple_buddy_get_name(b); - char *gname = aim_ssi_itemlist_findparentname(od->ssi.local, name); - if (aim_ssi_waitingforauth(od->ssi.local, gname, name)) + char *gname = aim_ssi_itemlist_findparentname(&od->ssi.local, name); + if (aim_ssi_waitingforauth(&od->ssi.local, gname, name)) ret = g_strdup(_("Not Authorized")); else ret = g_strdup(_("Offline")); @@ -4733,7 +4735,7 @@ * values of libpurple's PurplePrivacyType and the values used * by the oscar protocol. */ - aim_ssi_setpermdeny(od, account->perm_deny); + aim_ssi_setpermdeny(od, purple_account_get_privacy_type(account)); } void oscar_add_permit(PurpleConnection *gc, const char *who) { @@ -4940,7 +4942,7 @@ data = g_new(struct name_data, 1); - comment = aim_ssi_getcomment(od->ssi.local, purple_group_get_name(g), name); + comment = aim_ssi_getcomment(&od->ssi.local, purple_group_get_name(g), name); comment_utf8 = comment ? oscar_utf8_try_convert(account, od, comment) : NULL; data->gc = gc; @@ -5032,7 +5034,7 @@ name = purple_buddy_get_name(buddy); account = purple_buddy_get_account(buddy); gc = purple_account_get_connection(account); - od = gc->proto_data; + od = purple_connection_get_protocol_data(gc); conn = peer_connection_find_by_type(od, name, OSCAR_CAPABILITY_DIRECTIM); if (conn != NULL) @@ -5161,8 +5163,8 @@ * waiting for authorization. */ char *gname; - gname = aim_ssi_itemlist_findparentname(od->ssi.local, bname); - if (gname && aim_ssi_waitingforauth(od->ssi.local, gname, bname)) + gname = aim_ssi_itemlist_findparentname(&od->ssi.local, bname); + if (gname && aim_ssi_waitingforauth(&od->ssi.local, gname, bname)) { act = purple_menu_action_new(_("Re-request Authorization"), PURPLE_CALLBACK(oscar_auth_sendrequest_menu), @@ -5313,7 +5315,7 @@ buddy = cur->data; bname = purple_buddy_get_name(buddy); gname = purple_group_get_name(purple_buddy_get_group(buddy)); - if (aim_ssi_waitingforauth(od->ssi.local, gname, bname)) { + if (aim_ssi_waitingforauth(&od->ssi.local, gname, bname)) { filtered_buddies = g_slist_prepend(filtered_buddies, buddy); } } @@ -5468,7 +5470,7 @@ conn->flags |= PEER_CONNECTION_FLAG_APPROVED; aim_icbm_makecookie(conn->cookie); conn->xfer = xfer; - xfer->data = conn; + purple_xfer_set_protocol_data(xfer, conn); } return xfer; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/oscar/oscar.h --- a/libpurple/protocols/oscar/oscar.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/oscar/oscar.h Fri Apr 06 04:30:00 2012 +0000 @@ -308,9 +308,14 @@ #include "peer.h" -/* - * AIM Session: The main client-data interface. - * +struct aim_ssi_itemlist { + struct aim_ssi_item *data; + GHashTable *idx_gid_bid; + GHashTable *idx_all_named_items; +}; + +/** + * The main client-data interface. */ struct _OscarData { @@ -387,8 +392,8 @@ struct { gboolean received_data; guint16 numitems; - struct aim_ssi_item *official; - struct aim_ssi_item *local; + struct aim_ssi_itemlist official; + struct aim_ssi_itemlist local; struct aim_ssi_tmp *pending; time_t timestamp; gboolean waiting_for_ack; @@ -916,15 +921,16 @@ /* 0x001a */ int aim_ssi_sendauthreply(OscarData *od, const char *bn, guint8 reply, const char *msg); /* Client functions for retrieving SSI data */ -struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gid, guint16 bid); -struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *bn, guint16 type); -struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *bn); -char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *bn); -int aim_ssi_getpermdeny(struct aim_ssi_item *list); -guint32 aim_ssi_getpresence(struct aim_ssi_item *list); -char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *bn); -char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *bn); -gboolean aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *bn); +struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_itemlist *list, guint16 gid, guint16 bid); +struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_itemlist *list, const char *gn, const char *bn, guint16 type); +struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_itemlist *list, const char *bn); +char *aim_ssi_itemlist_findparentname(struct aim_ssi_itemlist *list, const char *bn); +int aim_ssi_getpermdeny(struct aim_ssi_itemlist *list); +guint32 aim_ssi_getpresence(struct aim_ssi_itemlist *list); +char *aim_ssi_getalias(struct aim_ssi_itemlist *list, const char *gn, const char *bn); +char *aim_ssi_getalias_from_item(struct aim_ssi_item *item); +char *aim_ssi_getcomment(struct aim_ssi_itemlist *list, const char *gn, const char *bn); +gboolean aim_ssi_waitingforauth(struct aim_ssi_itemlist *list, const char *gn, const char *bn); /* Client functions for changing SSI data */ int aim_ssi_addbuddy(OscarData *od, const char *name, const char *group, GSList *tlvlist, const char *alias, const char *comment, const char *smsnum, gboolean needauth); @@ -934,7 +940,6 @@ int aim_ssi_aliasbuddy(OscarData *od, const char *gn, const char *bn, const char *alias); int aim_ssi_editcomment(OscarData *od, const char *gn, const char *bn, const char *alias); int aim_ssi_rename_group(OscarData *od, const char *oldgn, const char *newgn); -int aim_ssi_cleanlist(OscarData *od); int aim_ssi_deletelist(OscarData *od); int aim_ssi_setpermdeny(OscarData *od, guint8 permdeny); int aim_ssi_setpresence(OscarData *od, guint32 presence); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/oscar/oscar_data.c --- a/libpurple/protocols/oscar/oscar_data.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/oscar/oscar_data.c Fri Apr 06 04:30:00 2012 +0000 @@ -47,6 +47,12 @@ od->buddyinfo = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); od->handlerlist = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free); + od->ssi.local.idx_gid_bid = g_hash_table_new(g_direct_hash, g_direct_equal); + od->ssi.local.idx_all_named_items = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + + od->ssi.official.idx_gid_bid = g_hash_table_new(g_direct_hash, g_direct_equal); + od->ssi.official.idx_all_named_items = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + /* * Register all the modules for this session... */ @@ -126,6 +132,12 @@ g_hash_table_destroy(od->buddyinfo); g_hash_table_destroy(od->handlerlist); + g_hash_table_destroy(od->ssi.local.idx_gid_bid); + g_hash_table_destroy(od->ssi.local.idx_all_named_items); + + g_hash_table_destroy(od->ssi.official.idx_gid_bid); + g_hash_table_destroy(od->ssi.official.idx_all_named_items); + g_free(od); } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/oscar/peer.c --- a/libpurple/protocols/oscar/peer.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/oscar/peer.c Fri Apr 06 04:30:00 2012 +0000 @@ -212,7 +212,7 @@ if (conn->xfer != NULL) { PurpleXferStatusType status; - conn->xfer->data = NULL; + purple_xfer_set_protocol_data(conn->xfer, NULL); status = purple_xfer_get_status(conn->xfer); if ((status != PURPLE_XFER_STATUS_DONE) && (status != PURPLE_XFER_STATUS_CANCEL_LOCAL) && @@ -603,15 +603,11 @@ peer_connection_listen_cb(gpointer data, gint source, PurpleInputCondition cond) { PeerConnection *conn; - OscarData *od; - PurpleConnection *gc; struct sockaddr addr; socklen_t addrlen = sizeof(addr); int flags; conn = data; - od = conn->od; - gc = od->gc; purple_debug_info("oscar", "Accepting connection on listener socket.\n"); @@ -851,7 +847,7 @@ */ conn->flags |= PEER_CONNECTION_FLAG_IS_INCOMING; - conn->listen_data = purple_network_listen_range(5190, 5290, SOCK_STREAM, + conn->listen_data = purple_network_listen_range(5190, 5290, AF_UNSPEC, SOCK_STREAM, TRUE, peer_connection_establish_listener_cb, conn); if (conn->listen_data != NULL) { @@ -1081,7 +1077,7 @@ conn->xfer = purple_xfer_new(account, PURPLE_XFER_RECEIVE, bn); if (conn->xfer) { - conn->xfer->data = conn; + purple_xfer_set_protocol_data(conn->xfer, conn); purple_xfer_ref(conn->xfer); purple_xfer_set_size(conn->xfer, args->info.sendfile.totsize); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/oscar/userinfo.c --- a/libpurple/protocols/oscar/userinfo.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/oscar/userinfo.c Fri Apr 06 04:30:00 2012 +0000 @@ -131,21 +131,16 @@ } static void -oscar_user_info_add_pair(PurpleNotifyUserInfo *user_info, const char *name, const char *value) -{ - if (value && value[0]) { - purple_notify_user_info_add_pair(user_info, name, value); - } -} - -static void oscar_user_info_convert_and_add(PurpleAccount *account, OscarData *od, PurpleNotifyUserInfo *user_info, const char *name, const char *value) { gchar *utf8; if (value && value[0] && (utf8 = oscar_utf8_try_convert(account, od, value))) { - purple_notify_user_info_add_pair(user_info, name, utf8); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext. Will + need to check callers of this function. */ + purple_notify_user_info_add_pair_html(user_info, name, utf8); g_free(utf8); } } @@ -158,7 +153,10 @@ if (value && value[0] && (utf8 = oscar_utf8_try_convert(account, od, value))) { gchar *tmp = g_strdup_printf("%s", url_prefix, utf8, utf8); - purple_notify_user_info_add_pair(user_info, name, tmp); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext. Will + need to check callers of this function. */ + purple_notify_user_info_add_pair_html(user_info, name, tmp); g_free(utf8); g_free(tmp); } @@ -263,8 +261,8 @@ message = tmp; } - } else if (aim_ssi_waitingforauth(od->ssi.local, - aim_ssi_itemlist_findparentname(od->ssi.local, purple_buddy_get_name(b)), + } else if (aim_ssi_waitingforauth(&od->ssi.local, + aim_ssi_itemlist_findparentname(&od->ssi.local, purple_buddy_get_name(b)), purple_buddy_get_name(b))) { /* Note if an offline buddy is not authorized */ @@ -295,12 +293,12 @@ } else { description = g_strdup(_(mood)); } - purple_notify_user_info_add_pair(user_info, _("Mood"), description); + purple_notify_user_info_add_pair_html(user_info, _("Mood"), description); g_free(description); } } - purple_notify_user_info_add_pair(user_info, _("Status"), message); + purple_notify_user_info_add_pair_html(user_info, _("Status"), message); g_free(message); } @@ -309,8 +307,6 @@ { OscarData *od; PurpleAccount *account; - PurplePresence *presence = NULL; - PurpleStatus *status = NULL; PurpleGroup *g = NULL; struct buddyinfo *bi = NULL; char *tmp; @@ -332,31 +328,29 @@ bname = purple_buddy_get_name(b); g = purple_buddy_get_group(b); gname = purple_group_get_name(g); - presence = purple_buddy_get_presence(b); - status = purple_presence_get_active_status(presence); } if (userinfo != NULL) bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, userinfo->bn)); if ((bi != NULL) && (bi->ipaddr != 0)) { - tmp = g_strdup_printf("%hhu.%hhu.%hhu.%hhu", - (bi->ipaddr & 0xff000000) >> 24, - (bi->ipaddr & 0x00ff0000) >> 16, - (bi->ipaddr & 0x0000ff00) >> 8, - (bi->ipaddr & 0x000000ff)); - oscar_user_info_add_pair(user_info, _("IP Address"), tmp); - g_free(tmp); + char tmp2[40]; + sprintf(tmp2, "%hhu.%hhu.%hhu.%hhu", + (bi->ipaddr & 0xff000000) >> 24, + (bi->ipaddr & 0x00ff0000) >> 16, + (bi->ipaddr & 0x0000ff00) >> 8, + (bi->ipaddr & 0x000000ff)); + purple_notify_user_info_add_pair_plaintext(user_info, _("IP Address"), tmp2); } if ((userinfo != NULL) && (userinfo->warnlevel != 0)) { - tmp = g_strdup_printf("%d", (int)(userinfo->warnlevel/10.0 + .5)); - oscar_user_info_add_pair(user_info, _("Warning Level"), tmp); - g_free(tmp); + char tmp2[12]; + sprintf(tmp2, "%d", (int)(userinfo->warnlevel/10.0 + .5)); + purple_notify_user_info_add_pair_plaintext(user_info, _("Warning Level"), tmp2); } if ((b != NULL) && (bname != NULL) && (g != NULL) && (gname != NULL)) { - tmp = aim_ssi_getcomment(od->ssi.local, gname, bname); + tmp = aim_ssi_getcomment(&od->ssi.local, gname, bname); if (tmp != NULL) { char *tmp2 = g_markup_escape_text(tmp, strlen(tmp)); g_free(tmp); @@ -372,7 +366,7 @@ { PurpleNotifyUserInfo *user_info = purple_notify_user_info_new(); gchar *buf = g_strdup_printf(_("User information not available: %s"), oscar_get_msgerr_reason(error_reason)); - purple_notify_user_info_add_pair(user_info, NULL, buf); + purple_notify_user_info_add_pair_plaintext(user_info, NULL, buf); purple_notify_userinfo(od->gc, buddy, user_info, NULL, NULL); purple_notify_user_info_destroy(user_info); purple_conv_present_error(buddy, purple_connection_get_account(od->gc), buf); @@ -402,16 +396,16 @@ else bi = NULL; - purple_notify_user_info_add_pair(user_info, _("UIN"), who); + purple_notify_user_info_add_pair_plaintext(user_info, _("UIN"), who); oscar_user_info_convert_and_add(account, od, user_info, _("Nick"), info->nick); if ((bi != NULL) && (bi->ipaddr != 0)) { - char *tstr = g_strdup_printf("%hhu.%hhu.%hhu.%hhu", - (bi->ipaddr & 0xff000000) >> 24, - (bi->ipaddr & 0x00ff0000) >> 16, - (bi->ipaddr & 0x0000ff00) >> 8, - (bi->ipaddr & 0x000000ff)); - purple_notify_user_info_add_pair(user_info, _("IP Address"), tstr); - g_free(tstr); + char tstr[40]; + sprintf(tstr, "%hhu.%hhu.%hhu.%hhu", + (bi->ipaddr & 0xff000000) >> 24, + (bi->ipaddr & 0x00ff0000) >> 16, + (bi->ipaddr & 0x0000ff00) >> 8, + (bi->ipaddr & 0x000000ff)); + purple_notify_user_info_add_pair_plaintext(user_info, _("IP Address"), tstr); } oscar_user_info_convert_and_add(account, od, user_info, _("First Name"), info->first); oscar_user_info_convert_and_add(account, od, user_info, _("Last Name"), info->last); @@ -425,7 +419,7 @@ oscar_user_info_convert_and_add(account, od, user_info, _("Mobile Phone"), info->mobile); if (info->gender != 0) - purple_notify_user_info_add_pair(user_info, _("Gender"), (info->gender == 1 ? _("Female") : _("Male"))); + purple_notify_user_info_add_pair_plaintext(user_info, _("Gender"), (info->gender == 1 ? _("Female") : _("Male"))); if ((info->birthyear > 1900) && (info->birthmonth > 0) && (info->birthday > 0)) { /* Initialize the struct properly or strftime() will crash @@ -437,7 +431,7 @@ tm->tm_mon = (int)info->birthmonth - 1; tm->tm_year = (int)info->birthyear - 1900; - /* Ignore dst setting of today to avoid timezone shift between + /* Ignore dst setting of today to avoid timezone shift between * dates in summer and winter time. */ tm->tm_isdst = -1; @@ -451,8 +445,9 @@ if ((info->age > 0) && (info->age < 255)) { char age[5]; snprintf(age, sizeof(age), "%hhd", info->age); - purple_notify_user_info_add_pair(user_info, _("Age"), age); + purple_notify_user_info_add_pair_plaintext(user_info, _("Age"), age); } + /* TODO: Is it correct to pass info->email here...? */ oscar_user_info_convert_and_add_hyperlink(account, od, user_info, _("Personal Web Page"), info->email, ""); if (buddy != NULL) oscar_user_info_append_status(gc, user_info, buddy, /* aim_userinfo_t */ NULL, /* use_html_status */ TRUE); @@ -482,6 +477,7 @@ oscar_user_info_convert_and_add(account, od, user_info, _("Company"), info->workcompany); oscar_user_info_convert_and_add(account, od, user_info, _("Division"), info->workdivision); oscar_user_info_convert_and_add(account, od, user_info, _("Position"), info->workposition); + /* TODO: Is it correct to pass info->email here...? */ oscar_user_info_convert_and_add_hyperlink(account, od, user_info, _("Web Page"), info->email, ""); } @@ -505,7 +501,7 @@ if ((userinfo->present & AIM_USERINFO_PRESENT_IDLE) && userinfo->idletime != 0) { tmp = purple_str_seconds_to_string(userinfo->idletime*60); - oscar_user_info_add_pair(user_info, _("Idle"), tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Idle"), tmp); g_free(tmp); } @@ -514,17 +510,18 @@ if ((userinfo->present & AIM_USERINFO_PRESENT_ONLINESINCE) && !oscar_util_valid_name_sms(userinfo->bn)) { /* An SMS contact is always online; its Online Since value is not useful */ time_t t = userinfo->onlinesince; - oscar_user_info_add_pair(user_info, _("Online Since"), purple_date_format_full(localtime(&t))); + purple_notify_user_info_add_pair_plaintext(user_info, _("Online Since"), purple_date_format_full(localtime(&t))); } if (userinfo->present & AIM_USERINFO_PRESENT_MEMBERSINCE) { time_t t = userinfo->membersince; - oscar_user_info_add_pair(user_info, _("Member Since"), purple_date_format_full(localtime(&t))); + purple_notify_user_info_add_pair_plaintext(user_info, _("Member Since"), purple_date_format_full(localtime(&t))); } if (userinfo->capabilities != 0) { tmp = oscar_caps_to_string(userinfo->capabilities); - oscar_user_info_add_pair(user_info, _("Capabilities"), tmp); + if (tmp && *tmp) + purple_notify_user_info_add_pair_plaintext(user_info, _("Capabilities"), tmp); g_free(tmp); } @@ -533,7 +530,11 @@ info_utf8 = oscar_encoding_to_utf8(userinfo->info_encoding, userinfo->info, userinfo->info_len); tmp = oscar_util_format_string(info_utf8, purple_account_get_username(account)); purple_notify_user_info_add_section_break(user_info); - oscar_user_info_add_pair(user_info, _("Profile"), tmp); + if (tmp && *tmp) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Profile"), tmp); + } g_free(tmp); g_free(info_utf8); } @@ -542,9 +543,9 @@ base_profile_url = oscar_util_valid_name_icq(userinfo->bn) ? "http://www.icq.com/people" : "http://profiles.aim.com"; tmp = g_strdup_printf("%s", base_profile_url, purple_normalize(account, userinfo->bn), _("View web profile")); - purple_notify_user_info_add_pair(user_info, NULL, tmp); + purple_notify_user_info_add_pair_html(user_info, NULL, tmp); g_free(tmp); purple_notify_userinfo(gc, userinfo->bn, user_info, NULL, NULL); purple_notify_user_info_destroy(user_info); -} \ No newline at end of file +} diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/oscar/visibility.c --- a/libpurple/protocols/oscar/visibility.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/oscar/visibility.c Fri Apr 06 04:30:00 2012 +0000 @@ -51,7 +51,7 @@ static gboolean is_buddy_on_list(OscarData *od, const char *bname) { - return aim_ssi_itemlist_finditem(od->ssi.local, NULL, bname, get_buddy_list_type(od)) != NULL; + return aim_ssi_itemlist_finditem(&od->ssi.local, NULL, bname, get_buddy_list_type(od)) != NULL; } static void @@ -102,7 +102,7 @@ buddy = cur->data; bname = purple_buddy_get_name(buddy); - if (aim_ssi_itemlist_finditem(od->ssi.local, NULL, bname, list_type)) { + if (aim_ssi_itemlist_finditem(&od->ssi.local, NULL, bname, list_type)) { filtered_buddies = g_slist_prepend(filtered_buddies, buddy); } } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/sametime/sametime.c --- a/libpurple/protocols/sametime/sametime.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/sametime/sametime.c Fri Apr 06 04:30:00 2012 +0000 @@ -197,7 +197,7 @@ /** the purple plugin data. - available as gc->proto_data and mwSession_getClientData */ + available as purple_connection_get_protocol_data(gc) and mwSession_getClientData */ struct mwPurplePluginData { struct mwSession *session; @@ -217,6 +217,7 @@ /** socket fd */ int socket; + guint inpa; /* input watcher */ gint outpa; /* like inpa, but the other way */ /** circular buffer for outgoing data */ @@ -320,7 +321,7 @@ g_return_val_if_fail(gc != NULL, NULL); - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); g_return_val_if_fail(pd != NULL, NULL); return pd->session; @@ -413,7 +414,7 @@ g_strerror(errno)); DEBUG_ERROR("write returned %" G_GSSIZE_FORMAT ", %" G_GSIZE_FORMAT " bytes left unwritten\n", ret, len); - purple_connection_error_reason(pd->gc, + purple_connection_error(pd->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); @@ -449,9 +450,9 @@ pd->socket = 0; } - if(gc->inpa) { - purple_input_remove(gc->inpa); - gc->inpa = 0; + if(pd->inpa) { + purple_input_remove(pd->inpa); + pd->inpa = 0; } } @@ -499,7 +500,7 @@ gc = mwAwareList_getClientData(list); acct = purple_connection_get_account(gc); - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); idle = aware->status.time; stat = aware->status.status; id = aware->id.user; @@ -851,7 +852,7 @@ static PurpleBuddy *buddy_ensure(PurpleConnection *gc, PurpleGroup *group, struct mwSametimeUser *stuser) { - struct mwPurplePluginData *pd = gc->proto_data; + struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc); PurpleBuddy *buddy; PurpleAccount *acct = purple_connection_get_account(gc); @@ -861,7 +862,7 @@ enum mwSametimeUserType type = mwSametimeUser_getType(stuser); g_return_val_if_fail(id != NULL, NULL); - g_return_val_if_fail(strlen(id) > 0, NULL); + g_return_val_if_fail(*id, NULL); buddy = purple_find_buddy_in_group(acct, id, group); if(! buddy) { @@ -973,7 +974,7 @@ if(type == mwSametimeGroup_DYNAMIC) { purple_blist_node_set_string(gn, GROUP_KEY_OWNER, owner); - group_add(gc->proto_data, group); + group_add(purple_connection_get_protocol_data(gc), group); } return group; @@ -1279,7 +1280,7 @@ struct mwIdBlock who = { 0, 0 }; struct mwConversation *conv; - gc = purple_conversation_get_gc(g_conv); + gc = purple_conversation_get_connection(g_conv); if(pd->gc != gc) return; /* not ours */ @@ -1403,7 +1404,7 @@ } if(add_buds) { - purple_account_add_buddies(acct, add_buds); + purple_account_add_buddies(acct, add_buds, NULL); g_list_free(add_buds); } } @@ -1618,7 +1619,7 @@ default: reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR; } - purple_connection_error_reason(gc, reason, err); + purple_connection_error(gc, reason, err); g_free(err); } break; @@ -1760,14 +1761,14 @@ pd->socket = 0; } - if(pd->gc->inpa) { - purple_input_remove(pd->gc->inpa); - pd->gc->inpa = 0; + if(pd->inpa) { + purple_input_remove(pd->inpa); + pd->inpa = 0; } if(! ret) { DEBUG_INFO("connection reset\n"); - purple_connection_error_reason(pd->gc, + purple_connection_error(pd->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Server closed the connection")); @@ -1778,7 +1779,7 @@ DEBUG_INFO("error in read callback: %s\n", err_str); msg = g_strdup_printf(_("Lost connection with server: %s"), err_str); - purple_connection_error_reason(pd->gc, + purple_connection_error(pd->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg); g_free(msg); @@ -1791,7 +1792,6 @@ static void connect_cb(gpointer data, gint source, const gchar *error_message) { struct mwPurplePluginData *pd = data; - PurpleConnection *gc = pd->gc; if(source < 0) { /* connection failed */ @@ -1804,7 +1804,7 @@ /* this is a regular connect, error out */ gchar *tmp = g_strdup_printf(_("Unable to connect: %s"), error_message); - purple_connection_error_reason(pd->gc, + purple_connection_error(pd->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); @@ -1819,7 +1819,7 @@ } pd->socket = source; - gc->inpa = purple_input_add(source, PURPLE_INPUT_READ, + pd->inpa = purple_input_add(source, PURPLE_INPUT_READ, read_cb, pd); mwSession_start(pd->session); @@ -2144,7 +2144,7 @@ static void ft_incoming_cancel(PurpleXfer *xfer) { /* incoming transfer rejected or cancelled in-progress */ - struct mwFileTransfer *ft = xfer->data; + struct mwFileTransfer *ft = purple_xfer_get_protocol_data(xfer); if(ft) mwFileTransfer_reject(ft); } @@ -2160,9 +2160,9 @@ struct mwFileTransfer *ft; FILE *fp; - ft = xfer->data; - - fp = g_fopen(xfer->local_filename, "wb"); + ft = purple_xfer_get_protocol_data(xfer); + + fp = g_fopen(purple_xfer_get_local_filename(xfer), "wb"); if(! fp) { mwFileTransfer_cancel(ft); return; @@ -2207,7 +2207,7 @@ { purple_xfer_ref(xfer); mwFileTransfer_setClientData(ft, xfer, (GDestroyNotify) purple_xfer_unref); - xfer->data = ft; + purple_xfer_set_protocol_data(xfer, ft); purple_xfer_set_init_fnc(xfer, ft_incoming_init); purple_xfer_set_cancel_recv_fnc(xfer, ft_incoming_cancel); @@ -2236,8 +2236,7 @@ if(fread(buf, (size_t) o.len, 1, fp)) { /* calculate progress and display it */ - xfer->bytes_sent += o.len; - xfer->bytes_remaining -= o.len; + purple_xfer_set_bytes_sent(xfer, purple_xfer_get_bytes_sent(xfer) + o.len); purple_xfer_update_progress(xfer); mwFileTransfer_send(ft, &o); @@ -2269,7 +2268,7 @@ } if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) { - xfer->dest_fp = g_fopen(xfer->local_filename, "rb"); + xfer->dest_fp = g_fopen(purple_xfer_get_local_filename(xfer), "rb"); ft_send(ft, xfer->dest_fp); } } @@ -2286,7 +2285,7 @@ xfer = mwFileTransfer_getClientData(ft); if(xfer) { - xfer->data = NULL; + purple_xfer_set_protocol_data(xfer, NULL); if(! mwFileTransfer_getRemaining(ft)) { purple_xfer_set_completed(xfer, TRUE); @@ -2339,8 +2338,7 @@ } /* update the progress */ - xfer->bytes_sent += data->len; - xfer->bytes_remaining -= data->len; + purple_xfer_set_bytes_sent(xfer, purple_xfer_get_bytes_sent(xfer) + data->len); purple_xfer_update_progress(xfer); /* let the other side know we got it, and to send some more */ @@ -2353,7 +2351,7 @@ xfer = mwFileTransfer_getClientData(ft); g_return_if_fail(xfer != NULL); - g_return_if_fail(xfer->watcher == 0); + g_return_if_fail(purple_xfer_get_watcher(xfer) == 0); if(! mwFileTransfer_getRemaining(ft)) { purple_xfer_set_completed(xfer, TRUE); @@ -2487,12 +2485,12 @@ text = g_strconcat(_("Unable to send message: "), tmp, NULL); gconv = convo_get_gconv(conv); - if(gconv && !purple_conv_present_error(idb->user, gconv->account, text)) { + if(gconv && !purple_conv_present_error(idb->user, purple_conversation_get_account(gconv), text)) { g_free(text); text = g_strdup_printf(_("Unable to send message to %s:"), (idb->user)? idb->user: "(unknown)"); - purple_notify_error(purple_account_get_connection(gconv->account), + purple_notify_error(purple_account_get_connection(purple_conversation_get_account(gconv)), NULL, text, tmp); } @@ -2530,10 +2528,10 @@ gconv = convo_get_gconv(conv); if(! gconv) return; - gc = purple_conversation_get_gc(gconv); + gc = purple_conversation_get_connection(gconv); if(! gc) return; - purple_conversation_set_features(gconv, gc->flags); + purple_conversation_set_features(gconv, purple_connection_get_flags(gc)); } @@ -3199,7 +3197,7 @@ mwSession_addCipher(pd->session, mwCipher_new_RC2_128(pd->session)); mwSession_setClientData(pd->session, pd, NULL); - gc->proto_data = pd; + purple_connection_set_protocol_data(gc, pd); return pd; } @@ -3208,7 +3206,7 @@ static void mwPurplePluginData_free(struct mwPurplePluginData *pd) { g_return_if_fail(pd != NULL); - pd->gc->proto_data = NULL; + purple_connection_set_protocol_data(pd->gc, NULL); mwSession_removeService(pd->session, mwService_AWARE); mwSession_removeService(pd->session, mwService_CONFERENCE); @@ -3270,7 +3268,7 @@ const char *ret = NULL; if ((gc = purple_account_get_connection(purple_buddy_get_account(b))) - && (pd = gc->proto_data)) + && (pd = purple_connection_get_protocol_data(gc))) ret = mwServiceAware_getText(pd->srvc_aware, &t); return (ret && g_utf8_validate(ret, -1, NULL)) ? g_markup_escape_text(ret, -1): NULL; @@ -3333,29 +3331,27 @@ char *tmp; if ((gc = purple_account_get_connection(purple_buddy_get_account(b))) - && (pd = gc->proto_data)) + && (pd = purple_connection_get_protocol_data(gc))) message = mwServiceAware_getText(pd->srvc_aware, &idb); status = status_text(b); if(message != NULL && g_utf8_validate(message, -1, NULL) && purple_utf8_strcasecmp(status, message)) { - tmp = g_markup_escape_text(message, -1); - purple_notify_user_info_add_pair(user_info, status, tmp); - g_free(tmp); + purple_notify_user_info_add_pair_plaintext(user_info, status, message); } else { - purple_notify_user_info_add_pair(user_info, _("Status"), status); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), status); } if(full && pd != NULL) { tmp = user_supports_text(pd->srvc_aware, purple_buddy_get_name(b)); if(tmp) { - purple_notify_user_info_add_pair(user_info, _("Supports"), tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Supports"), tmp); g_free(tmp); } if(buddy_is_external(b)) { - purple_notify_user_info_add_pair(user_info, NULL, _("External User")); + purple_notify_user_info_add_pair_plaintext(user_info, NULL, _("External User")); } } } @@ -3412,7 +3408,7 @@ acct = purple_buddy_get_account(buddy); gc = purple_account_get_connection(acct); - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); srvc = pd->srvc_conf; f = purple_request_fields_get_field(fields, CHAT_KEY_TOPIC); @@ -3578,7 +3574,7 @@ gc = purple_account_get_connection(acct); g_return_if_fail(gc != NULL); - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); g_return_if_fail(pd != NULL); /* @@ -3617,7 +3613,7 @@ gc = purple_account_get_connection(acct); g_return_if_fail(gc != NULL); - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); g_return_if_fail(pd != NULL); rcpt_name = g_strdup_printf("@U %s", buddy->name); @@ -3705,7 +3701,7 @@ pd = mwPurplePluginData_new(gc); /* while we do support images, the default is to not offer it */ - gc->flags |= PURPLE_CONNECTION_NO_IMAGES; + purple_connection_set_flags(gc, PURPLE_CONNECTION_NO_IMAGES); user = g_strdup(purple_account_get_username(account)); @@ -3725,7 +3721,7 @@ /* somehow, we don't have a host to connect to. Well, we need one to actually continue, so let's ask the user directly. */ g_free(user); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, _("A server is required to connect this account")); return; @@ -3770,7 +3766,7 @@ purple_connection_update_progress(gc, _("Connecting"), 1, MW_CONNECT_STEPS); if (purple_proxy_connect(gc, account, host, port, connect_cb, pd) == NULL) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); } } @@ -3781,7 +3777,7 @@ g_return_if_fail(gc != NULL); - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); g_return_if_fail(pd != NULL); /* get rid of the blist save timeout */ @@ -3795,12 +3791,12 @@ mwSession_stop(pd->session, 0x00); /* no longer necessary */ - gc->proto_data = NULL; + purple_connection_set_protocol_data(gc, NULL); /* stop watching the socket */ - if(gc->inpa) { - purple_input_remove(gc->inpa); - gc->inpa = 0; + if(pd->inpa) { + purple_input_remove(pd->inpa); + pd->inpa = 0; } /* clean up the rest */ @@ -3986,7 +3982,7 @@ struct mwConversation *conv; g_return_val_if_fail(gc != NULL, 0); - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); g_return_val_if_fail(pd != NULL, 0); @@ -4061,7 +4057,7 @@ gpointer t = GINT_TO_POINTER(!! state); g_return_val_if_fail(gc != NULL, 0); - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); g_return_val_if_fail(pd != NULL, 0); @@ -4157,53 +4153,54 @@ g_return_if_fail(who != NULL); g_return_if_fail(*who != '\0'); - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); acct = purple_connection_get_account(gc); b = purple_find_buddy(acct, who); user_info = purple_notify_user_info_new(); if(purple_str_has_prefix(who, "@E ")) { - purple_notify_user_info_add_pair(user_info, _("External User"), NULL); + purple_notify_user_info_add_pair_html(user_info, _("External User"), NULL); } - purple_notify_user_info_add_pair(user_info, _("User ID"), who); + purple_notify_user_info_add_pair_plaintext(user_info, _("User ID"), who); if(b) { guint32 type; if(purple_buddy_get_server_alias(b)) { - purple_notify_user_info_add_pair(user_info, _("Full Name"), purple_buddy_get_server_alias(b)); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Full Name"), purple_buddy_get_server_alias(b)); } type = purple_blist_node_get_int((PurpleBlistNode *) b, BUDDY_KEY_CLIENT); if(type) { - tmp = g_strdup(mw_client_name(type)); - if (!tmp) + tmp2 = mw_client_name(type); + if (tmp2) { + purple_notify_user_info_add_pair_plaintext(user_info, _("Last Known Client"), tmp2); + } else { tmp = g_strdup_printf(_("Unknown (0x%04x)
"), type); - - purple_notify_user_info_add_pair(user_info, _("Last Known Client"), tmp); - - g_free(tmp); + purple_notify_user_info_add_pair_html(user_info, _("Last Known Client"), tmp); + g_free(tmp); + } } } tmp = user_supports_text(pd->srvc_aware, who); if(tmp) { - purple_notify_user_info_add_pair(user_info, _("Supports"), tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Supports"), tmp); g_free(tmp); } if(b) { - purple_notify_user_info_add_pair(user_info, _("Status"), status_text(b)); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), status_text(b)); /* XXX Is this adding a status message in its own section rather than with the "Status" label? */ tmp2 = mwServiceAware_getText(pd->srvc_aware, &idb); if(tmp2 && g_utf8_validate(tmp2, -1, NULL)) { - tmp = g_markup_escape_text(tmp2, -1); purple_notify_user_info_add_section_break(user_info); - purple_notify_user_info_add_pair(user_info, NULL, tmp); - g_free(tmp); + purple_notify_user_info_add_pair_plaintext(user_info, NULL, tmp2); } } @@ -4401,7 +4398,7 @@ buddy = data->buddy; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); if(results) res = results->data; @@ -4480,9 +4477,10 @@ static void mw_prpl_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, - PurpleGroup *group) { - - struct mwPurplePluginData *pd = gc->proto_data; + PurpleGroup *group, + const char *message) { + + struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc); struct mwServiceResolve *srvc; GList *query; enum mwResolveFlag flags; @@ -4527,13 +4525,14 @@ static void mw_prpl_add_buddies(PurpleConnection *gc, GList *buddies, - GList *groups) { + GList *groups, + const char *message) { struct mwPurplePluginData *pd; GHashTable *group_sets; struct mwAwareIdBlock *idbs, *idb; - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); /* map PurpleGroup:GList of mwAwareIdBlock */ group_sets = g_hash_table_new(g_direct_hash, g_direct_equal); @@ -4584,7 +4583,7 @@ GList *rem = g_list_prepend(NULL, &idb); - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); group = purple_buddy_get_group(buddy); list = list_ensure(pd, group); @@ -4631,13 +4630,13 @@ acct = purple_connection_get_account(gc); g_return_if_fail(acct != NULL); - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); g_return_if_fail(pd != NULL); session = pd->session; g_return_if_fail(session != NULL); - switch(acct->perm_deny) { + switch(purple_account_get_privacy_type(acct)) { case PURPLE_PRIVACY_DENY_USERS: DEBUG_INFO("PURPLE_PRIVACY_DENY_USERS\n"); privacy_fill(&privacy, acct->deny); @@ -4661,7 +4660,7 @@ break; default: - DEBUG_INFO("acct->perm_deny is 0x%x\n", acct->perm_deny); + DEBUG_INFO("acct->perm_deny is 0x%x\n", purple_account_get_privacy_type(acct)); return; } @@ -4715,7 +4714,7 @@ struct mwPurplePluginData *pd; char *c, *t; - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); c = g_hash_table_lookup(components, CHAT_KEY_NAME); t = g_hash_table_lookup(components, CHAT_KEY_TOPIC); @@ -4757,7 +4756,7 @@ struct mwServiceConference *srvc; char *c; - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); srvc = pd->srvc_conf; if(g_hash_table_lookup(components, CHAT_KEY_IS_PLACE)) { @@ -4789,7 +4788,7 @@ struct mwPlace *place; struct mwIdBlock idb = { (char *) who, NULL }; - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); g_return_if_fail(pd != NULL); conf = ID_TO_CONF(pd, id); @@ -4813,7 +4812,7 @@ struct mwPurplePluginData *pd; struct mwConference *conf; - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); g_return_if_fail(pd != NULL); conf = ID_TO_CONF(pd, id); @@ -4849,7 +4848,7 @@ char *msg; int ret; - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); g_return_val_if_fail(pd != NULL, 0); conf = ID_TO_CONF(pd, id); @@ -4887,7 +4886,7 @@ const char *who, const char *alias) { - struct mwPurplePluginData *pd = gc->proto_data; + struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc); g_return_if_fail(pd != NULL); /* it's a change to the buddy list, so we've gotta reflect that in @@ -4905,7 +4904,7 @@ struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL }; GList *gl = g_list_prepend(NULL, &idb); - struct mwPurplePluginData *pd = gc->proto_data; + struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc); PurpleGroup *group; struct mwAwareList *list; @@ -4931,7 +4930,7 @@ PurpleGroup *group, GList *buddies) { - struct mwPurplePluginData *pd = gc->proto_data; + struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc); g_return_if_fail(pd != NULL); /* it's a change in the buddy list, so we've gotta reflect that in @@ -4951,7 +4950,7 @@ static void mw_prpl_convo_closed(PurpleConnection *gc, const char *who) { - struct mwPurplePluginData *pd = gc->proto_data; + struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc); struct mwServiceIm *srvc; struct mwConversation *conv; struct mwIdBlock idb = { (char *) who, NULL }; @@ -4986,7 +4985,7 @@ struct mwPurplePluginData *pd; struct mwAwareList *list; - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); g_return_if_fail(pd != NULL); g_return_if_fail(pd->group_list_map != NULL); @@ -5010,7 +5009,7 @@ g_return_val_if_fail(gc != NULL, FALSE); - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); g_return_val_if_fail(pd != NULL, FALSE); srvc = pd->srvc_aware; @@ -5042,12 +5041,12 @@ acct = purple_xfer_get_account(xfer); gc = purple_account_get_connection(acct); - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); srvc = pd->srvc_ft; filename = purple_xfer_get_local_filename(xfer); filesize = purple_xfer_get_size(xfer); - idb.user = xfer->who; + idb.user = purple_xfer_get_remote_user(xfer); purple_xfer_update_progress(xfer); @@ -5056,7 +5055,7 @@ if(! fp) { char *msg = g_strdup_printf(_("Error reading file %s: \n%s\n"), filename, g_strerror(errno)); - purple_xfer_error(purple_xfer_get_type(xfer), acct, xfer->who, msg); + purple_xfer_error(purple_xfer_get_type(xfer), acct, purple_xfer_get_remote_user(xfer), msg); g_free(msg); return; } @@ -5071,14 +5070,14 @@ purple_xfer_ref(xfer); mwFileTransfer_setClientData(ft, xfer, (GDestroyNotify) purple_xfer_unref); - xfer->data = ft; + purple_xfer_set_protocol_data(xfer, ft); mwFileTransfer_offer(ft); } static void ft_outgoing_cancel(PurpleXfer *xfer) { - struct mwFileTransfer *ft = xfer->data; + struct mwFileTransfer *ft = purple_xfer_get_protocol_data(xfer); DEBUG_INFO("ft_outgoing_cancel called\n"); @@ -5119,6 +5118,7 @@ static PurplePluginProtocolInfo mw_prpl_info = { + sizeof(PurplePluginProtocolInfo), OPT_PROTO_IM_IMAGE, NULL, /*< set in mw_plugin_init */ NULL, /*< set in mw_plugin_init */ @@ -5159,7 +5159,6 @@ mw_prpl_keepalive, NULL, NULL, - NULL, mw_prpl_alias_buddy, mw_prpl_group_buddy, mw_prpl_rename_group, @@ -5184,9 +5183,6 @@ NULL, NULL, NULL, - sizeof(PurplePluginProtocolInfo), - NULL, - NULL, NULL, NULL, NULL, @@ -5514,7 +5510,7 @@ enum mwResolveFlag flags; guint32 req; - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); srvc = pd->srvc_resolve; query = g_list_prepend(NULL, (char *) name); @@ -5639,7 +5635,7 @@ enum mwResolveFlag flags; guint32 req; - pd = gc->proto_data; + pd = purple_connection_get_protocol_data(gc); srvc = pd->srvc_resolve; query = g_list_prepend(NULL, (char *) name); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc/buddy.c --- a/libpurple/protocols/silc/buddy.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/silc/buddy.c Fri Apr 06 04:30:00 2012 +0000 @@ -72,7 +72,7 @@ void *context) { PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); if (!sg->conn) return; @@ -146,7 +146,7 @@ silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name, gboolean force_local) { - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcDList clients; SilcClientEntry client_entry; SilcClientConnectionParams params; @@ -314,7 +314,7 @@ a->port = port; purple_request_action(client->application, _("Key Agreement Request"), tmp, - hostname ? tmp2 : NULL, 1, gc->account, client_entry->nickname, + hostname ? tmp2 : NULL, 1, purple_connection_get_account(gc), client_entry->nickname, NULL, a, 2, _("Yes"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb), _("No"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb)); } @@ -346,7 +346,7 @@ b = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(b)); - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); /* Find client entry */ clients = silc_client_get_clients_local(sg->client, sg->conn, @@ -426,7 +426,7 @@ static void silcpurple_buddy_privkey(PurpleConnection *gc, const char *name) { - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcPurplePrivkey p; SilcDList clients; SilcClientEntry client_entry; @@ -457,7 +457,7 @@ _("Set IM Password"), NULL, FALSE, TRUE, NULL, _("OK"), G_CALLBACK(silcpurple_buddy_privkey_cb), _("Cancel"), G_CALLBACK(silcpurple_buddy_privkey_cb), - gc->account, NULL, NULL, p); + purple_connection_get_account(gc), NULL, NULL, p); silc_client_list_free(sg->client, sg->conn, clients); } @@ -554,7 +554,7 @@ static void silcpurple_buddy_getkey(PurpleConnection *gc, const char *name) { - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClient client = sg->client; SilcClientConnection conn = sg->conn; SilcClientEntry client_entry; @@ -618,7 +618,7 @@ b = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(b)); - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); pkfile = purple_blist_node_get_string(node, "public-key"); if (!silc_pkcs_load_public_key(pkfile, &public_key)) { @@ -669,7 +669,7 @@ void silcpurple_get_info(PurpleConnection *gc, const char *who) { - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClient client = sg->client; SilcClientConnection conn = sg->conn; SilcClientEntry client_entry; @@ -686,7 +686,7 @@ if (strlen(who) > 2 && who[0] == '*' && who[1] == '@') nick = who + 2; - b = purple_find_buddy(gc->account, nick); + b = purple_find_buddy(purple_connection_get_account(gc), nick); if (b) { /* See if we have this buddy's public key. If we do use that to search the details. */ @@ -1338,7 +1338,7 @@ static void silcpurple_add_buddy_i(PurpleConnection *gc, PurpleBuddy *b, gboolean init) { - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClient client = sg->client; SilcClientConnection conn = sg->conn; SilcPurpleBuddyRes r; @@ -1396,7 +1396,7 @@ silc_buffer_free(attrs); } -void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) +void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message) { /* Don't add if the buddy is already on the list. * @@ -1437,7 +1437,7 @@ const char *server; int port; - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); if (sg == NULL) return; @@ -1467,7 +1467,7 @@ { PurpleAccount *account = purple_buddy_get_account(b); PurpleConnection *gc = purple_account_get_connection(account); - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClient client = sg->client; SilcClientConnection conn = sg->conn; SilcClientID *client_id = purple_buddy_get_protocol_data(b); @@ -1533,7 +1533,7 @@ { PurpleAccount *account = purple_buddy_get_account(b); PurpleConnection *gc = purple_account_get_connection(account); - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClient client = sg->client; SilcClientConnection conn = sg->conn; SilcClientID *client_id = purple_buddy_get_protocol_data(b); @@ -1547,54 +1547,72 @@ return; if (client_entry->nickname) - purple_notify_user_info_add_pair(user_info, _("Nickname"), + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Nickname"), client_entry->nickname); if (client_entry->username && client_entry->hostname) { g_snprintf(tmp, sizeof(tmp), "%s@%s", client_entry->username, client_entry->hostname); - purple_notify_user_info_add_pair(user_info, _("Username"), tmp); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Username"), tmp); } if (client_entry->mode) { memset(tmp, 0, sizeof(tmp)); silcpurple_get_umode_string(client_entry->mode, tmp, sizeof(tmp) - strlen(tmp)); - purple_notify_user_info_add_pair(user_info, _("User Modes"), tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("User Modes"), tmp); } silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr); if (statusstr) { - purple_notify_user_info_add_pair(user_info, _("Message"), statusstr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Message"), statusstr); g_free(statusstr); } if (full) { if (moodstr) { - purple_notify_user_info_add_pair(user_info, _("Mood"), moodstr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Mood"), moodstr); g_free(moodstr); } if (contactstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Contact"), contactstr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Preferred Contact"), contactstr); g_free(contactstr); } if (langstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Language"), langstr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Preferred Language"), langstr); g_free(langstr); } if (devicestr) { - purple_notify_user_info_add_pair(user_info, _("Device"), devicestr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Device"), devicestr); g_free(devicestr); } if (tzstr) { - purple_notify_user_info_add_pair(user_info, _("Timezone"), tzstr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Timezone"), tzstr); g_free(tzstr); } if (geostr) { - purple_notify_user_info_add_pair(user_info, _("Geolocation"), geostr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Geolocation"), geostr); g_free(geostr); } } @@ -1611,7 +1629,7 @@ b = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(b)); - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); /* Call KILL */ silc_client_command_call(sg->client, sg->conn, NULL, "KILL", @@ -1635,7 +1653,7 @@ { PurpleAccount *account = purple_buddy_get_account(buddy); PurpleConnection *gc = purple_account_get_connection(account); - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClientConnection conn = sg->conn; const char *pkfile = NULL; SilcClientEntry client_entry = NULL; @@ -1701,7 +1719,7 @@ void silcpurple_buddy_set_icon(PurpleConnection *gc, PurpleStoredImage *img) { - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClient client = sg->client; SilcClientConnection conn = sg->conn; SilcMime mime; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc/chat.c --- a/libpurple/protocols/silc/chat.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/silc/chat.c Fri Apr 06 04:30:00 2012 +0000 @@ -91,7 +91,7 @@ static void silcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components) { - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); const char *chname; char tmp[256], *tmp2; GString *s; @@ -500,7 +500,7 @@ chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", g_hash_table_lookup(purple_chat_get_components(chat), "channel"), @@ -587,7 +587,7 @@ chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); p = silc_calloc(1, sizeof(*p)); if (!p) @@ -637,7 +637,7 @@ chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", g_hash_table_lookup(purple_chat_get_components(chat), "channel"), @@ -656,7 +656,7 @@ chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); if (!sg->conn) return; @@ -733,7 +733,7 @@ chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); if (!sg->conn) return; @@ -768,7 +768,7 @@ chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", g_hash_table_lookup(purple_chat_get_components(chat), "channel"), @@ -786,7 +786,7 @@ chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", g_hash_table_lookup(purple_chat_get_components(chat), "channel"), @@ -804,7 +804,7 @@ chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", g_hash_table_lookup(purple_chat_get_components(chat), "channel"), @@ -822,7 +822,7 @@ chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", g_hash_table_lookup(purple_chat_get_components(chat), "channel"), @@ -840,7 +840,7 @@ chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", g_hash_table_lookup(purple_chat_get_components(chat), "channel"), @@ -858,7 +858,7 @@ chat = (PurpleChat *) node; gc = purple_account_get_connection(purple_chat_get_account(chat)); - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", g_hash_table_lookup(purple_chat_get_components(chat), "channel"), @@ -882,7 +882,7 @@ { GHashTable *components = purple_chat_get_components(chat); PurpleConnection *gc = purple_account_get_connection(purple_chat_get_account(chat)); - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClientConnection conn = sg->conn; const char *chname = NULL; SilcChannelEntry channel = NULL; @@ -1020,7 +1020,7 @@ void silcpurple_chat_join(PurpleConnection *gc, GHashTable *data) { - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClient client = sg->client; SilcClientConnection conn = sg->conn; const char *channel, *passphrase, *parentch; @@ -1103,7 +1103,7 @@ void silcpurple_chat_invite(PurpleConnection *gc, int id, const char *msg, const char *name) { - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClient client = sg->client; SilcClientConnection conn = sg->conn; SilcHashTableList htl; @@ -1148,7 +1148,7 @@ void silcpurple_chat_leave(PurpleConnection *gc, int id) { - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClient client = sg->client; SilcClientConnection conn = sg->conn; SilcHashTableList htl; @@ -1218,7 +1218,7 @@ int silcpurple_chat_send(PurpleConnection *gc, int id, const char *msg, PurpleMessageFlags msgflags) { - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClient client = sg->client; SilcClientConnection conn = sg->conn; SilcHashTableList htl; @@ -1340,7 +1340,7 @@ void silcpurple_chat_set_topic(PurpleConnection *gc, int id, const char *topic) { - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClient client = sg->client; SilcClientConnection conn = sg->conn; SilcHashTableList htl; @@ -1384,7 +1384,7 @@ PurpleRoomlist *silcpurple_roomlist_get_list(PurpleConnection *gc) { - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClient client = sg->client; SilcClientConnection conn = sg->conn; GList *fields = NULL; @@ -1419,12 +1419,13 @@ void silcpurple_roomlist_cancel(PurpleRoomlist *list) { - PurpleConnection *gc = purple_account_get_connection(list->account); + PurpleAccount *account = purple_roomlist_get_account(list); + PurpleConnection *gc = purple_account_get_connection(account); SilcPurple sg; if (!gc) return; - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); purple_roomlist_set_in_progress(list, FALSE); if (sg->roomlist == list) { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc/ft.c --- a/libpurple/protocols/silc/ft.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/silc/ft.c Fri Apr 06 04:30:00 2012 +0000 @@ -76,7 +76,7 @@ if (status == SILC_CLIENT_FILE_MONITOR_CLOSED) { /* All started sessions terminate here */ - xfer->xfer->data = NULL; + purple_xfer_set_protocol_data(xfer->xfer, NULL); purple_xfer_unref(xfer->xfer); silc_free(xfer); return; @@ -86,7 +86,7 @@ purple_notify_error(gc, _("Secure File Transfer"), _("Error during file transfer"), _("Remote disconnected")); - xfer->xfer->status = PURPLE_XFER_STATUS_CANCEL_REMOTE; + purple_xfer_set_status(xfer->xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE); purple_xfer_update_progress(xfer->xfer); silc_client_file_close(client, conn, session_id); return; @@ -122,7 +122,7 @@ _("Error during file transfer"), _("File transfer session does not exist")); } - xfer->xfer->status = PURPLE_XFER_STATUS_CANCEL_REMOTE; + purple_xfer_set_status(xfer->xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE); purple_xfer_update_progress(xfer->xfer); silc_client_file_close(client, conn, session_id); return; @@ -132,8 +132,7 @@ if (!offset && filesize) purple_xfer_set_size(xfer->xfer, filesize); if (offset && filesize) { - xfer->xfer->bytes_sent = offset; - xfer->xfer->bytes_remaining = filesize - offset; + purple_xfer_set_bytes_sent(xfer->xfer, offset); } purple_xfer_update_progress(xfer->xfer); @@ -150,12 +149,12 @@ static void silcpurple_ftp_cancel(PurpleXfer *x) { - SilcPurpleXfer xfer = x->data; + SilcPurpleXfer xfer = purple_xfer_get_protocol_data(x); if (!xfer) return; - xfer->xfer->status = PURPLE_XFER_STATUS_CANCEL_LOCAL; + purple_xfer_set_status(xfer->xfer, PURPLE_XFER_STATUS_CANCEL_LOCAL); purple_xfer_update_progress(xfer->xfer); silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); } @@ -163,7 +162,7 @@ static void silcpurple_ftp_ask_name_cancel(PurpleXfer *x) { - SilcPurpleXfer xfer = x->data; + SilcPurpleXfer xfer = purple_xfer_get_protocol_data(x); if (!xfer) return; @@ -176,7 +175,7 @@ static void silcpurple_ftp_ask_name_ok(PurpleXfer *x) { - SilcPurpleXfer xfer = x->data; + SilcPurpleXfer xfer = purple_xfer_get_protocol_data(x); const char *name; if (!xfer) @@ -212,7 +211,7 @@ static void silcpurple_ftp_request_result(PurpleXfer *x) { - SilcPurpleXfer xfer = x->data; + SilcPurpleXfer xfer = purple_xfer_get_protocol_data(x); SilcClientFileError status; PurpleConnection *gc = xfer->sg->gc; SilcClientConnectionParams params; @@ -310,7 +309,7 @@ const char *hostname, SilcUInt16 port) { PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcPurpleXfer xfer; xfer = silc_calloc(1, sizeof(*xfer)); @@ -337,7 +336,7 @@ purple_xfer_set_cancel_recv_fnc(xfer->xfer, silcpurple_ftp_cancel); xfer->xfer->remote_ip = g_strdup(hostname); xfer->xfer->remote_port = port; - xfer->xfer->data = xfer; + purple_xfer_set_protocol_data(xfer->xfer, xfer); /* File transfer request */ purple_xfer_request(xfer->xfer); @@ -346,7 +345,7 @@ static void silcpurple_ftp_send_cancel(PurpleXfer *x) { - SilcPurpleXfer xfer = x->data; + SilcPurpleXfer xfer = purple_xfer_get_protocol_data(x); if (!xfer) return; @@ -358,7 +357,7 @@ static void silcpurple_ftp_send(PurpleXfer *x) { - SilcPurpleXfer xfer = x->data; + SilcPurpleXfer xfer = purple_xfer_get_protocol_data(x); const char *name; char *local_ip = NULL, *remote_ip = NULL; gboolean local = TRUE; @@ -435,7 +434,7 @@ PurpleXfer *silcpurple_ftp_new_xfer(PurpleConnection *gc, const char *name) { - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClient client = sg->client; SilcClientConnection conn = sg->conn; SilcDList clients; @@ -467,7 +466,7 @@ purple_xfer_set_init_fnc(xfer->xfer, silcpurple_ftp_send); purple_xfer_set_request_denied_fnc(xfer->xfer, silcpurple_ftp_request_denied); purple_xfer_set_cancel_send_fnc(xfer->xfer, silcpurple_ftp_send_cancel); - xfer->xfer->data = xfer; + purple_xfer_set_protocol_data(xfer->xfer, xfer); silc_free(clients); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc/ops.c --- a/libpurple/protocols/silc/ops.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/silc/ops.c Fri Apr 06 04:30:00 2012 +0000 @@ -72,7 +72,7 @@ gc = client->application; if (gc != NULL) - purple_connection_error_reason(gc, reason, tmp); + purple_connection_error(gc, reason, tmp); else purple_notify_error(NULL, _("Error"), _("Error occurred"), tmp); } @@ -88,7 +88,7 @@ gboolean recursive) { PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); const char *type; const unsigned char *data; SilcUInt32 data_len; @@ -224,7 +224,6 @@ tmp, cflags, time(NULL)); purple_imgstore_unref_by_id(imgid); - cflags = 0; ret = TRUE; } goto out; @@ -264,7 +263,7 @@ SilcUInt32 message_len) { PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); PurpleConversation *convo = NULL; char *msg, *tmp; @@ -361,7 +360,7 @@ SilcUInt32 message_len) { PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); PurpleConversation *convo = NULL; char *msg, *tmp; @@ -445,7 +444,7 @@ { va_list va; PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); PurpleAccount *account = purple_connection_get_account(gc); PurpleConversation *convo; SilcClientEntry client_entry, client_entry2; @@ -955,7 +954,7 @@ SilcUInt32 argc, unsigned char **argv) { PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); switch (command) { @@ -1092,7 +1091,7 @@ SilcStatus error, va_list ap) { PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); PurpleConversation *convo; switch (command) { @@ -1176,7 +1175,7 @@ SilcUInt32 idle, *user_modes; SilcDList channels; SilcClientEntry client_entry; - char tmp[1024], *tmp2; + char tmp[1024]; char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr; PurpleNotifyUserInfo *user_info; @@ -1198,71 +1197,80 @@ user_modes = va_arg(ap, SilcUInt32 *); user_info = purple_notify_user_info_new(); - tmp2 = g_markup_escape_text(client_entry->nickname, -1); - purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp2); - g_free(tmp2); + purple_notify_user_info_add_pair_plaintext(user_info, _("Nickname"), client_entry->nickname); if (client_entry->realname) { - tmp2 = g_markup_escape_text(client_entry->realname, -1); - purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp2); - g_free(tmp2); + purple_notify_user_info_add_pair_plaintext(user_info, _("Real Name"), client_entry->realname); } - tmp2 = g_markup_escape_text(client_entry->username, -1); if (*client_entry->hostname) { - gchar *tmp3; - tmp3 = g_strdup_printf("%s@%s", tmp2, client_entry->hostname); - purple_notify_user_info_add_pair(user_info, _("Username"), tmp3); - g_free(tmp3); + gchar *tmp2; + tmp2 = g_strdup_printf("%s@%s", client_entry->username, client_entry->hostname); + purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), tmp2); + g_free(tmp2); } else - purple_notify_user_info_add_pair(user_info, _("Username"), tmp2); - g_free(tmp2); + purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), client_entry->username); if (client_entry->mode) { memset(tmp, 0, sizeof(tmp)); silcpurple_get_umode_string(client_entry->mode, tmp, sizeof(tmp) - strlen(tmp)); - purple_notify_user_info_add_pair(user_info, _("User Modes"), tmp); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("User Modes"), tmp); } silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr); if (moodstr) { - purple_notify_user_info_add_pair(user_info, _("Mood"), moodstr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Mood"), moodstr); g_free(moodstr); } if (statusstr) { - tmp2 = g_markup_escape_text(statusstr, -1); - purple_notify_user_info_add_pair(user_info, _("Status Text"), tmp2); + purple_notify_user_info_add_pair_plaintext(user_info, _("Status Text"), statusstr); g_free(statusstr); - g_free(tmp2); } if (contactstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Contact"), contactstr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Preferred Contact"), contactstr); g_free(contactstr); } if (langstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Language"), langstr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Preferred Language"), langstr); g_free(langstr); } if (devicestr) { - purple_notify_user_info_add_pair(user_info, _("Device"), devicestr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Device"), devicestr); g_free(devicestr); } if (tzstr) { - purple_notify_user_info_add_pair(user_info, _("Timezone"), tzstr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Timezone"), tzstr); g_free(tzstr); } if (geostr) { - purple_notify_user_info_add_pair(user_info, _("Geolocation"), geostr); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Geolocation"), geostr); g_free(geostr); } - if (*client_entry->server) - purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server); + if (*client_entry->server) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Server"), client_entry->server); + } if (channels && user_modes) { SilcChannelPayload entry; @@ -1280,9 +1288,7 @@ silc_strncat(tmp, sizeof(tmp) - 1, " ", 1); silc_free(m); } - tmp2 = g_markup_escape_text(tmp, -1); - purple_notify_user_info_add_pair(user_info, _("Currently on"), tmp2); - g_free(tmp2); + purple_notify_user_info_add_pair_plaintext(user_info, _("Currently on"), tmp); } if (client_entry->public_key) { @@ -1293,8 +1299,8 @@ if (pk) { fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint); - purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint); + purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Fingerprint"), fingerprint); + purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Babbleprint"), babbleprint); silc_free(fingerprint); silc_free(babbleprint); silc_free(pk); @@ -1318,7 +1324,7 @@ case SILC_COMMAND_WHOWAS: { SilcClientEntry client_entry; - char *nickname, *realname, *username, *tmp; + char *nickname, *realname, *username; PurpleNotifyUserInfo *user_info; if (status != SILC_STATUS_OK) { @@ -1336,27 +1342,23 @@ break; user_info = purple_notify_user_info_new(); - tmp = g_markup_escape_text(nickname, -1); - purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp); - g_free(tmp); - if (realname) { - tmp = g_markup_escape_text(realname, -1); - purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp); - g_free(tmp); - } + purple_notify_user_info_add_pair_plaintext(user_info, _("Nickname"), nickname); + if (realname) + purple_notify_user_info_add_pair_plaintext(user_info, _("Real Name"), realname); if (username) { - tmp = g_markup_escape_text(username, -1); if (client_entry && *client_entry->hostname) { - gchar *tmp3; - tmp3 = g_strdup_printf("%s@%s", tmp, client_entry->hostname); - purple_notify_user_info_add_pair(user_info, _("Username"), tmp3); - g_free(tmp3); + gchar *tmp; + tmp = g_strdup_printf("%s@%s", username, client_entry->hostname); + purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), tmp); + g_free(tmp); } else - purple_notify_user_info_add_pair(user_info, _("Username"), tmp); - g_free(tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), username); } - if (client_entry && *client_entry->server) - purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server); + if (client_entry && *client_entry->server) { + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("Server"), client_entry->server); + } if (client_entry && client_entry->public_key) { @@ -1367,8 +1369,8 @@ if (pk) { fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint); - purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint); + purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Fingerprint"), fingerprint); + purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Babbleprint"), babbleprint); silc_free(fingerprint); silc_free(babbleprint); silc_free(pk); @@ -1735,7 +1737,7 @@ SilcGetAuthMeth completion, void *context) { PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcPurpleAskPassphrase internal; const char *password; @@ -1786,7 +1788,7 @@ SilcVerifyPublicKey completion, void *context) { PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); if (!sg->conn && (conn_type == SILC_CONN_SERVER || conn_type == SILC_CONN_ROUTER)) { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc/pk.c --- a/libpurple/protocols/silc/pk.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/silc/pk.c Fri Apr 06 04:30:00 2012 +0000 @@ -79,7 +79,7 @@ static void silcpurple_verify_details(PublicKeyVerify verify, gint id) { PurpleConnection *gc = verify->client->application; - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); silcpurple_show_public_key(sg, verify->entity_name, verify->public_key, G_CALLBACK(silcpurple_verify_details_cb), diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc/silc.c --- a/libpurple/protocols/silc/silc.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/silc/silc.c Fri Apr 06 04:30:00 2012 +0000 @@ -78,7 +78,7 @@ const char *state; if (gc != NULL) - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); if (status == NULL) return; @@ -125,7 +125,7 @@ static void silcpurple_keepalive(PurpleConnection *gc) { - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); silc_packet_send(sg->conn->stream, SILC_PACKET_HEARTBEAT, 0, NULL, 0); } @@ -180,7 +180,7 @@ { SilcClient client = (SilcClient)context; PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcPurpleTask ptask = NULL; if (added) { @@ -252,7 +252,7 @@ struct utsname u; #endif - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); switch (status) { case SILC_CLIENT_CONN_SUCCESS: @@ -316,7 +316,7 @@ /* Close the connection */ if (!sg->detaching) - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Disconnected by server")); else @@ -325,30 +325,30 @@ break; case SILC_CLIENT_CONN_ERROR: - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Error connecting to SILC Server")); g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); break; case SILC_CLIENT_CONN_ERROR_KE: - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, _("Key Exchange failed")); break; case SILC_CLIENT_CONN_ERROR_AUTH: - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Authentication failed")); break; case SILC_CLIENT_CONN_ERROR_RESUME: - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Resuming detached session failed. " "Press Reconnect to create new connection.")); g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); break; case SILC_CLIENT_CONN_ERROR_TIMEOUT: - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Connection timed out")); break; } @@ -367,16 +367,16 @@ SilcClientConnectionParams params; const char *dfile; - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); if (status != SILC_SOCKET_OK) { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Connection failed")); silc_pkcs_public_key_free(sg->public_key); silc_pkcs_private_key_free(sg->private_key); silc_free(sg); - gc->proto_data = NULL; + purple_connection_set_protocol_data(gc, NULL); return; } @@ -400,7 +400,7 @@ } /* Perform SILC Key Exchange. */ - silc_client_key_exchange(sg->client, ¶ms, sg->public_key, + silc_client_key_exchange(client, ¶ms, sg->public_key, sg->private_key, stream, SILC_CONN_SERVER, silcpurple_connect_cb, gc); @@ -415,15 +415,15 @@ g_return_if_fail(gc != NULL); - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); if (source < 0) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Connection failed")); silc_pkcs_public_key_free(sg->public_key); silc_pkcs_private_key_free(sg->private_key); silc_free(sg); - gc->proto_data = NULL; + purple_connection_set_protocol_data(gc, NULL); return; } @@ -447,9 +447,9 @@ purple_account_get_int(account, "port", 706), silcpurple_login_connected, gc) == NULL) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); - gc->proto_data = NULL; + purple_connection_set_protocol_data(gc, NULL); silc_free(sg); return; } @@ -457,7 +457,7 @@ static void silcpurple_got_password_cb(PurpleConnection *gc, PurpleRequestFields *fields) { - SilcPurple sg = (SilcPurple)gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); PurpleAccount *account = purple_connection_get_account(gc); char pkd[256], prd[256]; const char *password; @@ -473,7 +473,7 @@ if (!password || !*password) { purple_notify_error(gc, NULL, _("Password is required to sign on."), NULL); - gc->proto_data = NULL; + purple_connection_set_protocol_data(gc, NULL); silc_free(sg); return; } @@ -490,9 +490,9 @@ (char *)purple_account_get_string(account, "private-key", prd), password, &sg->public_key, &sg->private_key)) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Unable to load SILC key pair")); - gc->proto_data = NULL; + purple_connection_set_protocol_data(gc, NULL); silc_free(sg); return; } @@ -505,10 +505,10 @@ /* The password prompt dialog doesn't get disposed if the account disconnects */ if (!PURPLE_CONNECTION_IS_VALID(gc)) return; - sg = gc->proto_data; - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, + sg = purple_connection_get_protocol_data(gc); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Unable to load SILC key pair")); - gc->proto_data = NULL; + purple_connection_set_protocol_data(gc, NULL); silc_free(sg); } @@ -528,16 +528,16 @@ g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir()); if (!silc_load_key_pair((char *)purple_account_get_string(account, "public-key", pkd), (char *)purple_account_get_string(account, "private-key", prd), - (gc->password == NULL) ? "" : gc->password, + (purple_connection_get_password(gc) == NULL) ? "" : purple_connection_get_password(gc), &sg->public_key, &sg->private_key)) { if (!purple_account_get_password(account)) { purple_account_request_password(account, G_CALLBACK(silcpurple_got_password_cb), G_CALLBACK(silcpurple_no_password_cb), gc); return; } - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Unable to load SILC key pair")); - gc->proto_data = NULL; + purple_connection_set_protocol_data(gc, NULL); silc_free(sg); return; } @@ -555,10 +555,10 @@ char *username, *hostname, *realname, **up; int i; - gc = account->gc; + gc = purple_account_get_connection(account); if (!gc) return; - gc->proto_data = NULL; + purple_connection_set_protocol_data(gc, NULL); memset(¶ms, 0, sizeof(params)); strcat(params.nickname_format, "%n#a"); @@ -566,7 +566,7 @@ /* Allocate SILC client */ client = silc_client_alloc(&ops, ¶ms, gc, NULL); if (!client) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Out of memory")); return; } @@ -612,14 +612,14 @@ sg->client = client; sg->gc = gc; sg->account = account; - gc->proto_data = sg; + purple_connection_set_protocol_data(gc, sg); /* Init SILC client */ if (!silc_client_init(client, username, hostname, realname, silcpurple_running, sg)) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Unable to initialize SILC protocol")); - gc->proto_data = NULL; + purple_connection_set_protocol_data(gc, NULL); silc_free(sg); silc_free(hostname); g_free(username); @@ -630,9 +630,9 @@ /* Check the ~/.silc dir and create it, and new key pair if necessary. */ if (!silcpurple_check_silc_dir(gc)) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Error loading SILC key pair")); - gc->proto_data = NULL; + purple_connection_set_protocol_data(gc, NULL); silc_free(sg); return; } @@ -669,7 +669,7 @@ static void silcpurple_close(PurpleConnection *gc) { - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); #if __SILC_TOOLKIT_VERSION >= SILC_VERSION(1,1,1) SilcPurpleTask task; #endif /* __SILC_TOOLKIT_VERSION */ @@ -733,7 +733,7 @@ static void silcpurple_attrs_cb(PurpleConnection *gc, PurpleRequestFields *fields) { - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClient client = sg->client; SilcClientConnection conn = sg->conn; PurpleRequestField *f; @@ -744,7 +744,7 @@ SilcVCardStruct vcard; const char *val; - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); if (!sg) return; @@ -905,7 +905,7 @@ silcpurple_attrs(PurplePluginAction *action) { PurpleConnection *gc = (PurpleConnection *) action->context; - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClient client = sg->client; SilcClientConnection conn = sg->conn; PurpleRequestFields *fields; @@ -922,7 +922,7 @@ gboolean device = TRUE; char status[1024], tz[16]; - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); if (!sg) return; @@ -1061,7 +1061,7 @@ fields, _("OK"), G_CALLBACK(silcpurple_attrs_cb), _("Cancel"), G_CALLBACK(silcpurple_attrs_cancel), - gc->account, NULL, NULL, gc); + purple_connection_get_account(gc), NULL, NULL, gc); } static void @@ -1072,7 +1072,7 @@ if (!gc) return; - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); if (!sg) return; @@ -1090,7 +1090,7 @@ if (!gc) return; - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); if (!sg) return; @@ -1125,7 +1125,7 @@ int keylen = SILCPURPLE_DEF_PKCS_LEN; SilcPublicKey public_key; - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); if (!sg) return; @@ -1208,7 +1208,7 @@ silcpurple_create_keypair(PurplePluginAction *action) { PurpleConnection *gc = (PurpleConnection *) action->context; - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); PurpleRequestFields *fields; PurpleRequestFieldGroup *g; PurpleRequestField *f; @@ -1226,9 +1226,9 @@ g_snprintf(pkd2, sizeof(pkd2), "%s" G_DIR_SEPARATOR_S"public_key.pub", silcpurple_silcdir()); g_snprintf(prd2, sizeof(prd2), "%s" G_DIR_SEPARATOR_S"private_key.prv", silcpurple_silcdir()); g_snprintf(pkd, sizeof(pkd) - 1, "%s", - purple_account_get_string(gc->account, "public-key", pkd2)); + purple_account_get_string(purple_connection_get_account(gc), "public-key", pkd2)); g_snprintf(prd, sizeof(prd) - 1, "%s", - purple_account_get_string(gc->account, "private-key", prd2)); + purple_account_get_string(purple_connection_get_account(gc), "private-key", prd2)); fields = purple_request_fields_new(); @@ -1269,7 +1269,7 @@ _("Create New SILC Key Pair"), NULL, fields, _("Generate Key Pair"), G_CALLBACK(silcpurple_create_keypair_cb), _("Cancel"), G_CALLBACK(silcpurple_create_keypair_cancel), - gc->account, NULL, NULL, gc); + purple_connection_get_account(gc), NULL, NULL, gc); g_strfreev(u); silc_free(hostname); @@ -1287,7 +1287,7 @@ { char prd[256]; g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.pub", silcpurple_silcdir()); - silc_change_private_key_passphrase(purple_account_get_string(gc->account, + silc_change_private_key_passphrase(purple_account_get_string(purple_connection_get_account(gc), "private-key", prd), old ? old : "", new ? new : ""); } @@ -1356,7 +1356,7 @@ void *context) { PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcPurpleIM im = context; PurpleConversation *convo; char tmp[256]; @@ -1433,7 +1433,7 @@ silcpurple_send_im(PurpleConnection *gc, const char *who, const char *message, PurpleMessageFlags flags) { - SilcPurple sg = gc->proto_data; + SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClient client = sg->client; SilcClientConnection conn = sg->conn; SilcDList clients; @@ -1548,14 +1548,14 @@ PurpleConversation *convo = conv; int id = 0; - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); if (gc == NULL) return PURPLE_CMD_RET_FAILED; if(args && args[0]) convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[0], - gc->account); + purple_connection_get_account(gc)); if (convo != NULL) id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)); @@ -1577,7 +1577,7 @@ char *buf, *tmp, *tmp2; const char *topic; - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)); if (gc == NULL || id == 0) @@ -1593,7 +1593,7 @@ g_free(tmp2); } else buf = g_strdup(_("No topic is set")); - purple_conv_chat_write(PURPLE_CONV_CHAT(conv), gc->account->username, buf, + purple_conv_chat_write(PURPLE_CONV_CHAT(conv), purple_account_get_username(purple_connection_get_account(gc)), buf, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); g_free(buf); @@ -1623,7 +1623,7 @@ if(args[1]) g_hash_table_replace(comp, "passphrase", args[1]); - silcpurple_chat_join(purple_conversation_get_gc(conv), comp); + silcpurple_chat_join(purple_conversation_get_connection(conv), comp); g_hash_table_destroy(comp); return PURPLE_CMD_RET_OK; @@ -1633,7 +1633,7 @@ const char *cmd, char **args, char **error, void *data) { PurpleConnection *gc; - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); purple_roomlist_show_with_account(purple_connection_get_account(gc)); return PURPLE_CMD_RET_OK; } @@ -1643,7 +1643,7 @@ { PurpleConnection *gc; - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); if (gc == NULL) return PURPLE_CMD_RET_FAILED; @@ -1659,7 +1659,7 @@ int ret; PurpleConnection *gc; - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); if (gc == NULL) return PURPLE_CMD_RET_FAILED; @@ -1685,7 +1685,7 @@ return PURPLE_CMD_RET_FAILED; } - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); if (gc == NULL) return PURPLE_CMD_RET_FAILED; @@ -1713,12 +1713,12 @@ SilcPurple sg; char *tmp; - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); if (gc == NULL) return PURPLE_CMD_RET_FAILED; - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); if (sg == NULL) return PURPLE_CMD_RET_FAILED; @@ -1742,12 +1742,12 @@ PurpleConnection *gc; SilcPurple sg; - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); if (gc == NULL) return PURPLE_CMD_RET_FAILED; - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); if (sg == NULL) return PURPLE_CMD_RET_FAILED; @@ -1767,12 +1767,12 @@ char *silccmd, *silcargs, *msg, tmp[256]; const char *chname; - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); - if (gc == NULL || !args || gc->proto_data == NULL) + if (gc == NULL || !args || purple_connection_get_protocol_data(gc) == NULL) return PURPLE_CMD_RET_FAILED; - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); if (args[0]) chname = args[0]; @@ -1818,12 +1818,12 @@ SilcPurple sg; char *silccmd, *silcargs; - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); if (gc == NULL) return PURPLE_CMD_RET_FAILED; - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); if (sg == NULL) return PURPLE_CMD_RET_FAILED; @@ -1850,12 +1850,12 @@ const char *ui_name = NULL, *ui_website = NULL; char *quit_msg; - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); if (gc == NULL) return PURPLE_CMD_RET_FAILED; - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); if (sg == NULL) return PURPLE_CMD_RET_FAILED; @@ -1887,12 +1887,12 @@ PurpleConnection *gc; SilcPurple sg; - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); if (gc == NULL) return PURPLE_CMD_RET_FAILED; - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); if (sg == NULL) return PURPLE_CMD_RET_FAILED; @@ -2050,6 +2050,7 @@ static PurplePluginProtocolInfo prpl_info = { + sizeof(PurplePluginProtocolInfo), /* struct_size */ OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_PASSWORD_OPTIONAL | OPT_PROTO_IM_IMAGE | OPT_PROTO_SLASH_COMMANDS_NATIVE, @@ -2092,7 +2093,6 @@ silcpurple_keepalive, /* keepalive */ NULL, /* register_user */ NULL, /* get_cb_info */ - NULL, /* get_cb_away */ NULL, /* alias_buddy */ NULL, /* group_buddy */ NULL, /* rename_group */ @@ -2117,15 +2117,12 @@ NULL, /* unregister_user */ NULL, /* send_attention */ NULL, /* get_attention_types */ - sizeof(PurplePluginProtocolInfo), /* struct_size */ NULL, /* get_account_text_table */ NULL, /* initiate_media */ NULL, /* get_media_caps */ NULL, /* get_moods */ NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - NULL, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ + NULL /* get_public_alias */ }; static PurplePluginInfo info = diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc/silcpurple.h --- a/libpurple/protocols/silc/silcpurple.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/silc/silcpurple.h Fri Apr 06 04:30:00 2012 +0000 @@ -105,7 +105,7 @@ SilcVerifyPublicKey completion, void *context); GList *silcpurple_buddy_menu(PurpleBuddy *buddy); -void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); +void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message); void silcpurple_send_buddylist(PurpleConnection *gc); void silcpurple_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); void silcpurple_buddy_keyagr_request(SilcClient client, diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc/util.c --- a/libpurple/protocols/silc/util.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/silc/util.c Fri Apr 06 04:30:00 2012 +0000 @@ -198,9 +198,9 @@ g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir()); g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir()); g_snprintf(file_public_key, sizeof(file_public_key) - 1, "%s", - purple_account_get_string(gc->account, "public-key", pkd)); + purple_account_get_string(purple_connection_get_account(gc), "public-key", pkd)); g_snprintf(file_private_key, sizeof(file_public_key) - 1, "%s", - purple_account_get_string(gc->account, "private-key", prd)); + purple_account_get_string(purple_connection_get_account(gc), "private-key", prd)); if ((g_stat(file_public_key, &st)) == -1) { /* If file doesn't exist */ @@ -210,10 +210,9 @@ SILCPURPLE_DEF_PKCS_LEN, file_public_key, file_private_key, NULL, - (gc->password == NULL) - ? "" : gc->password, + (purple_connection_get_password(gc) == NULL) ? "" : purple_connection_get_password(gc), NULL, NULL, FALSE)) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Unable to create SILC key pair")); return FALSE; } @@ -253,10 +252,9 @@ SILCPURPLE_DEF_PKCS_LEN, file_public_key, file_private_key, NULL, - (gc->password == NULL) - ? "" : gc->password, + (purple_connection_get_password(gc) == NULL) ? "" : purple_connection_get_password(gc), NULL, NULL, FALSE)) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Unable to create SILC key pair")); return FALSE; } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc/wb.c --- a/libpurple/protocols/silc/wb.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/silc/wb.c Fri Apr 06 04:30:00 2012 +0000 @@ -105,18 +105,16 @@ PurpleWhiteboard *silcpurple_wb_init(SilcPurple sg, SilcClientEntry client_entry) { - SilcClientConnection conn; PurpleWhiteboard *wb; SilcPurpleWb wbs; - conn = sg->conn; wb = purple_whiteboard_get_session(sg->account, client_entry->nickname); if (!wb) wb = purple_whiteboard_create(sg->account, client_entry->nickname, 0); if (!wb) return NULL; - if (!wb->proto_data) { + if (!purple_whiteboard_get_protocol_data(wb)) { wbs = silc_calloc(1, sizeof(*wbs)); if (!wbs) return NULL; @@ -126,7 +124,7 @@ wbs->height = SILCPURPLE_WB_HEIGHT; wbs->brush_size = SILCPURPLE_WB_BRUSH_SMALL; wbs->brush_color = SILCPURPLE_WB_COLOR_BLACK; - wb->proto_data = wbs; + purple_whiteboard_set_protocol_data(wb, wbs); /* Start the whiteboard */ purple_whiteboard_start(wb); @@ -147,7 +145,7 @@ if (!wb) return NULL; - if (!wb->proto_data) { + if (!purple_whiteboard_get_protocol_data(wb)) { wbs = silc_calloc(1, sizeof(*wbs)); if (!wbs) return NULL; @@ -157,7 +155,7 @@ wbs->height = SILCPURPLE_WB_HEIGHT; wbs->brush_size = SILCPURPLE_WB_BRUSH_SMALL; wbs->brush_color = SILCPURPLE_WB_COLOR_BLACK; - wb->proto_data = wbs; + purple_whiteboard_set_protocol_data(wb, wbs); /* Start the whiteboard */ purple_whiteboard_start(wb); @@ -168,9 +166,10 @@ } static void -silcpurple_wb_parse(SilcPurpleWb wbs, PurpleWhiteboard *wb, +silcpurple_wb_parse(PurpleWhiteboard *wb, unsigned char *message, SilcUInt32 message_len) { + SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb); SilcUInt8 command; SilcUInt16 width, height, brush_size; SilcUInt32 brush_color, x, y, dx, dy; @@ -238,15 +237,15 @@ { PurpleWhiteboard *wb; - if (id != 1) - goto out; + if (id != 1) + goto out; if (!req->channel) wb = silcpurple_wb_init(req->sg, req->sender); else wb = silcpurple_wb_init_ch(req->sg, req->channel); - silcpurple_wb_parse(wb->proto_data, wb, req->message, req->message_len); + silcpurple_wb_parse(wb, req->message, req->message_len); out: silc_free(req->message); @@ -264,7 +263,7 @@ SilcPurple sg; gc = client->application; - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); /* Open whiteboard automatically if requested */ if (purple_account_get_bool(sg->account, "open-wb", FALSE)) { @@ -275,7 +274,7 @@ else wb = silcpurple_wb_init_ch(sg, channel); - silcpurple_wb_parse(wb->proto_data, wb, + silcpurple_wb_parse(wb, (unsigned char *)message, message_len); return; @@ -318,12 +317,11 @@ SilcUInt32 message_len) { SilcPurple sg; - PurpleConnection *gc; + PurpleConnection *gc; PurpleWhiteboard *wb; - SilcPurpleWb wbs; gc = client->application; - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); wb = purple_whiteboard_get_session(sg->account, sender->nickname); if (!wb) { @@ -333,8 +331,7 @@ return; } - wbs = wb->proto_data; - silcpurple_wb_parse(wbs, wb, (unsigned char *)message, message_len); + silcpurple_wb_parse(wb, (unsigned char *)message, message_len); } /* Process incoming whiteboard message on channel */ @@ -347,12 +344,11 @@ SilcUInt32 message_len) { SilcPurple sg; - PurpleConnection *gc; + PurpleConnection *gc; PurpleWhiteboard *wb; - SilcPurpleWb wbs; gc = client->application; - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); wb = purple_whiteboard_get_session(sg->account, channel->channel_name); if (!wb) { @@ -362,25 +358,24 @@ return; } - wbs = wb->proto_data; - silcpurple_wb_parse(wbs, wb, (unsigned char *)message, message_len); + silcpurple_wb_parse(wb, (unsigned char *)message, message_len); } /* Send whiteboard message */ void silcpurple_wb_send(PurpleWhiteboard *wb, GList *draw_list) { - SilcPurpleWb wbs = wb->proto_data; + SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb); SilcBuffer packet; GList *list; int len; - PurpleConnection *gc; - SilcPurple sg; + PurpleConnection *gc; + SilcPurple sg; g_return_if_fail(draw_list); - gc = purple_account_get_connection(wb->account); + gc = purple_account_get_connection(purple_whiteboard_get_account(wb)); g_return_if_fail(gc); - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); g_return_if_fail(sg); len = SILCPURPLE_WB_HEADER; @@ -435,20 +430,22 @@ void silcpurple_wb_end(PurpleWhiteboard *wb) { - silc_free(wb->proto_data); - wb->proto_data = NULL; + SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb); + + silc_free(wbs); + purple_whiteboard_set_protocol_data(wb, NULL); } void silcpurple_wb_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height) { - SilcPurpleWb wbs = wb->proto_data; + SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb); *width = wbs->width; *height = wbs->height; } void silcpurple_wb_set_dimensions(PurpleWhiteboard *wb, int width, int height) { - SilcPurpleWb wbs = wb->proto_data; + SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb); wbs->width = width > SILCPURPLE_WB_WIDTH_MAX ? SILCPURPLE_WB_WIDTH_MAX : width; wbs->height = height > SILCPURPLE_WB_HEIGHT_MAX ? SILCPURPLE_WB_HEIGHT_MAX : @@ -460,14 +457,14 @@ void silcpurple_wb_get_brush(const PurpleWhiteboard *wb, int *size, int *color) { - SilcPurpleWb wbs = wb->proto_data; + SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb); *size = wbs->brush_size; *color = wbs->brush_color; } void silcpurple_wb_set_brush(PurpleWhiteboard *wb, int size, int color) { - SilcPurpleWb wbs = wb->proto_data; + SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb); wbs->brush_size = size; wbs->brush_color = color; @@ -477,15 +474,15 @@ void silcpurple_wb_clear(PurpleWhiteboard *wb) { - SilcPurpleWb wbs = wb->proto_data; + SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb); SilcBuffer packet; int len; - PurpleConnection *gc; - SilcPurple sg; + PurpleConnection *gc; + SilcPurple sg; - gc = purple_account_get_connection(wb->account); + gc = purple_account_get_connection(purple_whiteboard_get_account(wb)); g_return_if_fail(gc); - sg = gc->proto_data; + sg = purple_connection_get_protocol_data(gc); g_return_if_fail(sg); len = SILCPURPLE_WB_HEADER; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc10/Makefile.am --- a/libpurple/protocols/silc10/Makefile.am Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -EXTRA_DIST = \ - Makefile.mingw \ - README \ - TODO - -pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION) - -SILCSOURCES = silc.c silcpurple.h buddy.c chat.c ft.c ops.c pk.c util.c wb.c wb.h - -AM_CFLAGS = $(st) - -libsilcpurple_la_LDFLAGS = -module -avoid-version - -if STATIC_SILC - -st = -DPURPLE_STATIC_PRPL $(SILC_CFLAGS) -noinst_LTLIBRARIES = libsilcpurple.la -libsilcpurple_la_SOURCES = $(SILCSOURCES) -libsilcpurple_la_CFLAGS = $(AM_CFLAGS) -libsilcpurple_la_LIBADD = $(SILC_LIBS) - -else - -st = $(SILC_CFLAGS) -pkg_LTLIBRARIES = libsilcpurple.la -libsilcpurple_la_SOURCES = $(SILCSOURCES) -libsilcpurple_la_LIBADD = $(GLIB_LIBS) $(SILC_LIBS) - -endif - -AM_CPPFLAGS = \ - -I$(top_srcdir)/libpurple \ - -I$(top_builddir)/libpurple \ - $(DEBUG_CFLAGS) \ - $(GLIB_CFLAGS) \ - $(SILC_CFLAGS) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc10/Makefile.mingw --- a/libpurple/protocols/silc10/Makefile.mingw Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -# -# Makefile.mingw -# -# Description: Makefile for win32 (mingw) version of libsilc protocol plugin -# - -PIDGIN_TREE_TOP := ../../.. -include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak - -DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES)) - -TARGET = libsilc -NEEDED_DLLS = $(SILC_TOOLKIT)/lib/silc.dll \ - $(SILC_TOOLKIT)/lib/silcclient.dll -TYPE = PLUGIN - -# Static or Plugin... -ifeq ($(TYPE),STATIC) - DEFINES += -DSTATIC - DLL_INSTALL_DIR = $(PURPLE_INSTALL_DIR) -else -ifeq ($(TYPE),PLUGIN) - DLL_INSTALL_DIR = $(PURPLE_INSTALL_PLUGINS_DIR) -endif -endif - -## -## INCLUDE PATHS -## -INCLUDE_PATHS += -I. \ - -I$(GTK_TOP)/include \ - -I$(GTK_TOP)/include/glib-2.0 \ - -I$(GTK_TOP)/lib/glib-2.0/include \ - -I$(PURPLE_TOP) \ - -I$(PURPLE_TOP)/win32 \ - -I$(PIDGIN_TREE_TOP) \ - -I$(SILC_TOOLKIT)/include - -LIB_PATHS += -L$(GTK_TOP)/lib \ - -L$(PURPLE_TOP) \ - -L$(SILC_TOOLKIT)/lib - -## -## SOURCES, OBJECTS -## -C_SRC = silc.c \ - buddy.c \ - chat.c \ - ft.c \ - ops.c \ - pk.c \ - util.c \ - wb.c - -OBJECTS = $(C_SRC:%.c=%.o) - -## -## LIBRARIES -## -LIBS = \ - -lglib-2.0 \ - -lws2_32 \ - -lintl \ - -lpurple \ - -lsilc \ - -lsilcclient - -include $(PIDGIN_COMMON_RULES) - -## -## TARGET DEFINITIONS -## -.PHONY: all install clean - -all: $(TARGET).dll - -install: all $(DLL_INSTALL_DIR) $(PURPLE_INSTALL_DIR) - cp $(TARGET).dll $(DLL_INSTALL_DIR) - cp $(NEEDED_DLLS) $(PURPLE_INSTALL_DIR) - -$(OBJECTS): $(PURPLE_CONFIG_H) - -$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS) - $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--image-base,0x64000000 -o $(TARGET).dll - -## -## CLEAN RULES -## -clean: - rm -f $(OBJECTS) - rm -f $(TARGET).dll - -include $(PIDGIN_COMMON_TARGETS) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc10/README --- a/libpurple/protocols/silc10/README Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -SILC Purple Plugin -================== - -This is the Purple protocol plugin of the protocol called Secure Internet -Live Conferencing (SILC). The implementation will use the SILC Toolkit, -freely available from the http://silcnet.org/ site, for the actual SILC -protocol implementation. - -To include SILC into Purple, one needs to first compile and install -the SILC Toolkit. It is done as follows: - - ./configure --enable-shared - make - make install - -This will compile shared libraries of the SILC Toolkit. If the --prefix -is not given to ./configure, the binaries are installed into the -/usr/local/silc directory. - -Once the Toolkit is installed one needs to tell Purple's ./configure -script where the SILC Toolkit is located. It is done as simply as: - - ./configure - -if pkg-config is installed in your system. If it is isn't it's done as: - - ./configure --with-silc-libs=/path/to/silc/lib - --with-silc-includes=/path/to/silc/include - -If the SILC Toolkit cannot be found then the SILC protocol plugin will -not be compiled. diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc10/TODO --- a/libpurple/protocols/silc10/TODO Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -Features TODO (maybe) -===================== - -Preferences - - Add joined channels to buddy list automatically (during - session) - - Add joined channels to buddy list automatically permanently - diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc10/buddy.c --- a/libpurple/protocols/silc10/buddy.c Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1748 +0,0 @@ -/* - - silcpurple_buddy.c - - Author: Pekka Riikonen - - Copyright (C) 2004 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#include "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" -#include "wb.h" - -/***************************** Key Agreement *********************************/ - -static void -silcpurple_buddy_keyagr(PurpleBlistNode *node, gpointer data); - -static void -silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name, - gboolean force_local); - -typedef struct { - char *nick; - PurpleConnection *gc; -} *SilcPurpleResolve; - -static void -silcpurple_buddy_keyagr_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - PurpleConnection *gc = client->application; - SilcPurpleResolve r = context; - char tmp[256]; - - if (!clients) { - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), r->nick); - purple_notify_error(gc, _("Key Agreement"), - _("Cannot perform the key agreement"), tmp); - silc_free(r->nick); - silc_free(r); - return; - } - - silcpurple_buddy_keyagr_do(gc, r->nick, FALSE); - silc_free(r->nick); - silc_free(r); -} - -typedef struct { - gboolean responder; -} *SilcPurpleKeyAgr; - -static void -silcpurple_buddy_keyagr_cb(SilcClient client, - SilcClientConnection conn, - SilcClientEntry client_entry, - SilcKeyAgreementStatus status, - SilcSKEKeyMaterial *key, - void *context) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - SilcPurpleKeyAgr a = context; - - if (!sg->conn) - return; - - switch (status) { - case SILC_KEY_AGREEMENT_OK: - { - PurpleConversation *convo; - char tmp[128]; - - /* Set the private key for this client */ - silc_client_del_private_message_key(client, conn, client_entry); - silc_client_add_private_message_key_ske(client, conn, client_entry, - NULL, NULL, key, a->responder); - silc_ske_free_key_material(key); - - - /* Open IM window */ - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - client_entry->nickname, sg->account); - if (convo) { - /* we don't have windows in the core anymore...but we may want to - * provide some method for asking the UI to show the window - purple_conv_window_show(purple_conversation_get_window(convo)); - */ - } else { - convo = purple_conversation_new(PURPLE_CONV_TYPE_IM, sg->account, - client_entry->nickname); - } - g_snprintf(tmp, sizeof(tmp), "%s [private key]", client_entry->nickname); - purple_conversation_set_title(convo, tmp); - } - break; - - case SILC_KEY_AGREEMENT_ERROR: - purple_notify_error(gc, _("Key Agreement"), - _("Error occurred during key agreement"), NULL); - break; - - case SILC_KEY_AGREEMENT_FAILURE: - purple_notify_error(gc, _("Key Agreement"), _("Key Agreement failed"), NULL); - break; - - case SILC_KEY_AGREEMENT_TIMEOUT: - purple_notify_error(gc, _("Key Agreement"), - _("Timeout during key agreement"), NULL); - break; - - case SILC_KEY_AGREEMENT_ABORTED: - purple_notify_error(gc, _("Key Agreement"), - _("Key agreement was aborted"), NULL); - break; - - case SILC_KEY_AGREEMENT_ALREADY_STARTED: - purple_notify_error(gc, _("Key Agreement"), - _("Key agreement is already started"), NULL); - break; - - case SILC_KEY_AGREEMENT_SELF_DENIED: - purple_notify_error(gc, _("Key Agreement"), - _("Key agreement cannot be started with yourself"), - NULL); - break; - - default: - break; - } - - silc_free(a); -} - -static void -silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name, - gboolean force_local) -{ - SilcPurple sg = gc->proto_data; - SilcClientEntry *clients; - SilcUInt32 clients_count; - char *local_ip = NULL, *remote_ip = NULL; - gboolean local = TRUE; - char *nickname; - SilcPurpleKeyAgr a; - - if (!sg->conn || !name) - return; - - if (!silc_parse_userfqdn(name, &nickname, NULL)) - return; - - /* Find client entry */ - clients = silc_client_get_clients_local(sg->client, sg->conn, nickname, name, - &clients_count); - if (!clients) { - /* Resolve unknown user */ - SilcPurpleResolve r = silc_calloc(1, sizeof(*r)); - if (!r) - return; - r->nick = g_strdup(name); - r->gc = gc; - silc_client_get_clients(sg->client, sg->conn, nickname, NULL, - silcpurple_buddy_keyagr_resolved, r); - silc_free(nickname); - return; - } - - /* Resolve the local IP from the outgoing socket connection. We resolve - it to check whether we have a private range IP address or public IP - address. If we have public then we will assume that we are not behind - NAT and will provide automatically the point of connection to the - agreement. If we have private range address we assume that we are - behind NAT and we let the responder provide the point of connection. - - The algorithm also checks the remote IP address of server connection. - If it is private range address and we have private range address we - assume that we are chatting in LAN and will provide the point of - connection. - - Naturally this algorithm does not always get things right. */ - - if (silc_net_check_local_by_sock(sg->conn->sock->sock, NULL, &local_ip)) { - /* Check if the IP is private */ - if (!force_local && silcpurple_ip_is_private(local_ip)) { - local = FALSE; - - /* Local IP is private, resolve the remote server IP to see whether - we are talking to Internet or just on LAN. */ - if (silc_net_check_host_by_sock(sg->conn->sock->sock, NULL, - &remote_ip)) - if (silcpurple_ip_is_private(remote_ip)) - /* We assume we are in LAN. Let's provide - the connection point. */ - local = TRUE; - } - } - - if (force_local) - local = TRUE; - - if (local && !local_ip) - local_ip = silc_net_localip(); - - a = silc_calloc(1, sizeof(*a)); - if (!a) - return; - a->responder = local; - - /* Send the key agreement request */ - silc_client_send_key_agreement(sg->client, sg->conn, clients[0], - local ? local_ip : NULL, NULL, 0, 60, - silcpurple_buddy_keyagr_cb, a); - - silc_free(local_ip); - silc_free(remote_ip); - silc_free(clients); -} - -typedef struct { - SilcClient client; - SilcClientConnection conn; - SilcClientID client_id; - char *hostname; - SilcUInt16 port; -} *SilcPurpleKeyAgrAsk; - -static void -silcpurple_buddy_keyagr_request_cb(SilcPurpleKeyAgrAsk a, gint id) -{ - SilcPurpleKeyAgr ai; - SilcClientEntry client_entry; - - if (id != 1) - goto out; - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(a->client, a->conn, - &a->client_id); - if (!client_entry) { - purple_notify_error(a->client->application, _("Key Agreement"), - _("The remote user is not present in the network any more"), - NULL); - goto out; - } - - /* If the hostname was provided by the requestor perform the key agreement - now. Otherwise, we will send him a request to connect to us. */ - if (a->hostname) { - ai = silc_calloc(1, sizeof(*ai)); - if (!ai) - goto out; - ai->responder = FALSE; - silc_client_perform_key_agreement(a->client, a->conn, client_entry, - a->hostname, a->port, - silcpurple_buddy_keyagr_cb, ai); - } else { - /* Send request. Force us as the point of connection since requestor - did not provide the point of connection. */ - silcpurple_buddy_keyagr_do(a->client->application, - client_entry->nickname, TRUE); - } - - out: - silc_free(a->hostname); - silc_free(a); -} - -void silcpurple_buddy_keyagr_request(SilcClient client, - SilcClientConnection conn, - SilcClientEntry client_entry, - const char *hostname, SilcUInt16 port) -{ - char tmp[128], tmp2[128]; - SilcPurpleKeyAgrAsk a; - PurpleConnection *gc = client->application; - - g_snprintf(tmp, sizeof(tmp), - _("Key agreement request received from %s. Would you like to " - "perform the key agreement?"), client_entry->nickname); - if (hostname) - g_snprintf(tmp2, sizeof(tmp2), - _("The remote user is waiting key agreement on:\n" - "Remote host: %s\nRemote port: %d"), hostname, port); - - a = silc_calloc(1, sizeof(*a)); - if (!a) - return; - a->client = client; - a->conn = conn; - a->client_id = *client_entry->id; - if (hostname) - a->hostname = strdup(hostname); - a->port = port; - - purple_request_action(client->application, _("Key Agreement Request"), tmp, - hostname ? tmp2 : NULL, 1, gc->account, client_entry->nickname, - NULL, a, 2, _("Yes"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb), - _("No"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb)); -} - -static void -silcpurple_buddy_keyagr(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *buddy; - - buddy = (PurpleBuddy *)node; - silcpurple_buddy_keyagr_do(buddy->account->gc, buddy->name, FALSE); -} - - -/**************************** Static IM Key **********************************/ - -static void -silcpurple_buddy_resetkey(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *b; - PurpleConnection *gc; - SilcPurple sg; - char *nickname; - SilcClientEntry *clients; - SilcUInt32 clients_count; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - b = (PurpleBuddy *) node; - gc = purple_account_get_connection(b->account); - sg = gc->proto_data; - - if (!silc_parse_userfqdn(b->name, &nickname, NULL)) - return; - - /* Find client entry */ - clients = silc_client_get_clients_local(sg->client, sg->conn, - nickname, b->name, - &clients_count); - if (!clients) { - silc_free(nickname); - return; - } - - clients[0]->prv_resp = FALSE; - silc_client_del_private_message_key(sg->client, sg->conn, - clients[0]); - silc_free(clients); - silc_free(nickname); -} - -typedef struct { - SilcClient client; - SilcClientConnection conn; - SilcClientID client_id; -} *SilcPurplePrivkey; - -static void -silcpurple_buddy_privkey(PurpleConnection *gc, const char *name); - -static void -silcpurple_buddy_privkey_cb(SilcPurplePrivkey p, const char *passphrase) -{ - SilcClientEntry client_entry; - - if (!passphrase || !(*passphrase)) { - silc_free(p); - return; - } - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(p->client, p->conn, - &p->client_id); - if (!client_entry) { - purple_notify_error(p->client->application, _("IM With Password"), - _("The remote user is not present in the network any more"), - NULL); - silc_free(p); - return; - } - - /* Set the private message key */ - silc_client_del_private_message_key(p->client, p->conn, - client_entry); - silc_client_add_private_message_key(p->client, p->conn, - client_entry, NULL, NULL, - (unsigned char *)passphrase, - strlen(passphrase), FALSE, - client_entry->prv_resp); - if (!client_entry->prv_resp) - silc_client_send_private_message_key_request(p->client, - p->conn, - client_entry); - silc_free(p); -} - -static void -silcpurple_buddy_privkey_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - char tmp[256]; - - if (!clients) { - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), - (const char *)context); - purple_notify_error(client->application, _("IM With Password"), - _("Cannot set IM key"), tmp); - g_free(context); - return; - } - - silcpurple_buddy_privkey(client->application, context); - silc_free(context); -} - -static void -silcpurple_buddy_privkey(PurpleConnection *gc, const char *name) -{ - SilcPurple sg = gc->proto_data; - char *nickname; - SilcPurplePrivkey p; - SilcClientEntry *clients; - SilcUInt32 clients_count; - - if (!name) - return; - if (!silc_parse_userfqdn(name, &nickname, NULL)) - return; - - /* Find client entry */ - clients = silc_client_get_clients_local(sg->client, sg->conn, - nickname, name, - &clients_count); - if (!clients) { - silc_client_get_clients(sg->client, sg->conn, nickname, NULL, - silcpurple_buddy_privkey_resolved, - g_strdup(name)); - silc_free(nickname); - return; - } - - p = silc_calloc(1, sizeof(*p)); - if (!p) - return; - p->client = sg->client; - p->conn = sg->conn; - p->client_id = *clients[0]->id; - purple_request_input(gc, _("IM With Password"), NULL, - _("Set IM Password"), NULL, FALSE, TRUE, NULL, - _("OK"), G_CALLBACK(silcpurple_buddy_privkey_cb), - _("Cancel"), G_CALLBACK(silcpurple_buddy_privkey_cb), - gc->account, NULL, NULL, p); - - silc_free(clients); - silc_free(nickname); -} - -static void -silcpurple_buddy_privkey_menu(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *buddy; - PurpleConnection *gc; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - buddy = (PurpleBuddy *) node; - gc = purple_account_get_connection(buddy->account); - - silcpurple_buddy_privkey(gc, buddy->name); -} - - -/**************************** Get Public Key *********************************/ - -typedef struct { - SilcClient client; - SilcClientConnection conn; - SilcClientID client_id; -} *SilcPurpleBuddyGetkey; - -static void -silcpurple_buddy_getkey(PurpleConnection *gc, const char *name); - -static void -silcpurple_buddy_getkey_cb(SilcPurpleBuddyGetkey g, - SilcClientCommandReplyContext cmd) -{ - SilcClientEntry client_entry; - unsigned char *pk; - SilcUInt32 pk_len; - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(g->client, g->conn, - &g->client_id); - if (!client_entry) { - purple_notify_error(g->client->application, _("Get Public Key"), - _("The remote user is not present in the network any more"), - NULL); - silc_free(g); - return; - } - - if (!client_entry->public_key) { - silc_free(g); - return; - } - - /* Now verify the public key */ - pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); - silcpurple_verify_public_key(g->client, g->conn, client_entry->nickname, - SILC_SOCKET_TYPE_CLIENT, - pk, pk_len, SILC_SKE_PK_TYPE_SILC, - NULL, NULL); - silc_free(pk); - silc_free(g); -} - -static void -silcpurple_buddy_getkey_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - char tmp[256]; - - if (!clients) { - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), - (const char *)context); - purple_notify_error(client->application, _("Get Public Key"), - _("Cannot fetch the public key"), tmp); - g_free(context); - return; - } - - silcpurple_buddy_getkey(client->application, context); - silc_free(context); -} - -static void -silcpurple_buddy_getkey(PurpleConnection *gc, const char *name) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientEntry *clients; - SilcUInt32 clients_count; - SilcPurpleBuddyGetkey g; - char *nickname; - - if (!name) - return; - - if (!silc_parse_userfqdn(name, &nickname, NULL)) - return; - - /* Find client entry */ - clients = silc_client_get_clients_local(client, conn, nickname, name, - &clients_count); - if (!clients) { - silc_client_get_clients(client, conn, nickname, NULL, - silcpurple_buddy_getkey_resolved, - g_strdup(name)); - silc_free(nickname); - return; - } - - /* Call GETKEY */ - g = silc_calloc(1, sizeof(*g)); - if (!g) - return; - g->client = client; - g->conn = conn; - g->client_id = *clients[0]->id; - silc_client_command_call(client, conn, NULL, "GETKEY", - clients[0]->nickname, NULL); - silc_client_command_pending(conn, SILC_COMMAND_GETKEY, - conn->cmd_ident, - (SilcCommandCb)silcpurple_buddy_getkey_cb, g); - silc_free(clients); - silc_free(nickname); -} - -static void -silcpurple_buddy_getkey_menu(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *buddy; - PurpleConnection *gc; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - buddy = (PurpleBuddy *) node; - gc = purple_account_get_connection(buddy->account); - - silcpurple_buddy_getkey(gc, buddy->name); -} - -static void -silcpurple_buddy_showkey(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *b; - PurpleConnection *gc; - SilcPurple sg; - SilcPublicKey public_key; - const char *pkfile; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - b = (PurpleBuddy *) node; - gc = purple_account_get_connection(b->account); - sg = gc->proto_data; - - pkfile = purple_blist_node_get_string(node, "public-key"); - if (!silc_pkcs_load_public_key(pkfile, &public_key, SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(pkfile, &public_key, SILC_PKCS_FILE_BIN)) { - purple_notify_error(gc, - _("Show Public Key"), - _("Could not load public key"), NULL); - return; - } - - silcpurple_show_public_key(sg, b->name, public_key, NULL, NULL); - silc_pkcs_public_key_free(public_key); -} - - -/**************************** Buddy routines *********************************/ - -/* The buddies are implemented by using the WHOIS and WATCH commands that - can be used to search users by their public key. Since nicknames aren't - unique in SILC we cannot trust the buddy list using their nickname. We - associate public keys to buddies and use those to search and watch - in the network. - - The problem is that Purple does not return PurpleBuddy contexts to the - callbacks but the buddy names. Naturally, this is not going to work - with SILC. But, for now, we have to do what we can... */ - -typedef struct { - SilcClient client; - SilcClientConnection conn; - SilcClientID client_id; - PurpleBuddy *b; - unsigned char *offline_pk; - SilcUInt32 offline_pk_len; - unsigned int offline : 1; - unsigned int pubkey_search : 1; - unsigned int init : 1; -} *SilcPurpleBuddyRes; - -static void -silcpurple_add_buddy_ask_pk_cb(SilcPurpleBuddyRes r, gint id); -static void -silcpurple_add_buddy_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context); - -void silcpurple_get_info(PurpleConnection *gc, const char *who) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientEntry client_entry; - PurpleBuddy *b; - const char *filename, *nick = who; - char tmp[256]; - - if (!who) - return; - if (strlen(who) > 1 && who[0] == '@') - nick = who + 1; - if (strlen(who) > 1 && who[0] == '*') - nick = who + 1; - if (strlen(who) > 2 && who[0] == '*' && who[1] == '@') - nick = who + 2; - - b = purple_find_buddy(gc->account, nick); - if (b) { - /* See if we have this buddy's public key. If we do use that - to search the details. */ - filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key"); - if (filename) { - /* Call WHOIS. The user info is displayed in the WHOIS - command reply. */ - silc_client_command_call(client, conn, NULL, "WHOIS", - "-details", "-pubkey", filename, NULL); - return; - } - - if (!b->proto_data) { - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), b->name); - purple_notify_error(gc, _("User Information"), - _("Cannot get user information"), tmp); - return; - } - - client_entry = silc_client_get_client_by_id(client, conn, b->proto_data); - if (client_entry) { - /* Call WHOIS. The user info is displayed in the WHOIS - command reply. */ - silc_client_command_call(client, conn, NULL, "WHOIS", - client_entry->nickname, "-details", NULL); - } - } else { - /* Call WHOIS just with nickname. */ - silc_client_command_call(client, conn, NULL, "WHOIS", nick, NULL); - } -} - -static void -silcpurple_add_buddy_pk_no(SilcPurpleBuddyRes r) -{ - char tmp[512]; - g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not trusted"), - r->b->name); - purple_notify_error(r->client->application, _("Add Buddy"), tmp, - _("You cannot receive buddy notifications until you " - "import his/her public key. You can use the Get Public Key " - "command to get the public key.")); - purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL); -} - -static void -silcpurple_add_buddy_save(bool success, void *context) -{ - SilcPurpleBuddyRes r = context; - PurpleBuddy *b = r->b; - SilcClient client = r->client; - SilcClientEntry client_entry; - SilcAttributePayload attr; - SilcAttribute attribute; - SilcVCardStruct vcard; - SilcAttributeObjMime message, extension; -#ifdef SILC_ATTRIBUTE_USER_ICON - SilcAttributeObjMime usericon; -#endif - SilcAttributeObjPk serverpk, usersign, serversign; - gboolean usign_success = TRUE, ssign_success = TRUE; - char filename[512], filename2[512], *fingerprint = NULL, *tmp; - SilcUInt32 len; - int i; - - if (!success) { - /* The user did not trust the public key. */ - silcpurple_add_buddy_pk_no(r); - silc_free(r); - return; - } - - if (r->offline) { - /* User is offline. Associate the imported public key with - this user. */ - fingerprint = silc_hash_fingerprint(NULL, r->offline_pk, - r->offline_pk_len); - for (i = 0; i < strlen(fingerprint); i++) - if (fingerprint[i] == ' ') - fingerprint[i] = '_'; - g_snprintf(filename, sizeof(filename) - 1, - "%s" G_DIR_SEPARATOR_S "clientkeys" G_DIR_SEPARATOR_S "clientkey_%s.pub", - silcpurple_silcdir(), fingerprint); - purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename); - purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL); - silc_free(fingerprint); - silc_free(r->offline_pk); - silc_free(r); - return; - } - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(r->client, r->conn, - &r->client_id); - if (!client_entry) { - silc_free(r); - return; - } - - memset(&vcard, 0, sizeof(vcard)); - memset(&message, 0, sizeof(message)); - memset(&extension, 0, sizeof(extension)); -#ifdef SILC_ATTRIBUTE_USER_ICON - memset(&usericon, 0, sizeof(usericon)); -#endif - memset(&serverpk, 0, sizeof(serverpk)); - memset(&usersign, 0, sizeof(usersign)); - memset(&serversign, 0, sizeof(serversign)); - - /* Now that we have the public key and we trust it now we - save the attributes of the buddy and update its status. */ - - if (client_entry->attrs) { - silc_dlist_start(client_entry->attrs); - while ((attr = silc_dlist_get(client_entry->attrs)) - != SILC_LIST_END) { - attribute = silc_attribute_get_attribute(attr); - - switch (attribute) { - case SILC_ATTRIBUTE_USER_INFO: - if (!silc_attribute_get_object(attr, (void *)&vcard, - sizeof(vcard))) - continue; - break; - - case SILC_ATTRIBUTE_STATUS_MESSAGE: - if (!silc_attribute_get_object(attr, (void *)&message, - sizeof(message))) - continue; - break; - - case SILC_ATTRIBUTE_EXTENSION: - if (!silc_attribute_get_object(attr, (void *)&extension, - sizeof(extension))) - continue; - break; - -#ifdef SILC_ATTRIBUTE_USER_ICON - case SILC_ATTRIBUTE_USER_ICON: - if (!silc_attribute_get_object(attr, (void *)&usericon, - sizeof(usericon))) - continue; - break; -#endif - - case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY: - if (serverpk.type) - continue; - if (!silc_attribute_get_object(attr, (void *)&serverpk, - sizeof(serverpk))) - continue; - break; - - case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE: - if (usersign.data) - continue; - if (!silc_attribute_get_object(attr, (void *)&usersign, - sizeof(usersign))) - continue; - break; - - case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE: - if (serversign.data) - continue; - if (!silc_attribute_get_object(attr, (void *)&serversign, - sizeof(serversign))) - continue; - break; - - default: - break; - } - } - } - - /* Verify the attribute signatures */ - - if (usersign.data) { - SilcPKCS pkcs; - unsigned char *verifyd; - SilcUInt32 verify_len; - - silc_pkcs_alloc((unsigned char*)"rsa", &pkcs); - verifyd = silc_attribute_get_verify_data(client_entry->attrs, - FALSE, &verify_len); - if (verifyd && silc_pkcs_public_key_set(pkcs, client_entry->public_key)){ - if (!silc_pkcs_verify_with_hash(pkcs, client->sha1hash, - usersign.data, - usersign.data_len, - verifyd, verify_len)) - usign_success = FALSE; - } - silc_free(verifyd); - } - - if (serversign.data && !strcmp(serverpk.type, "silc-rsa")) { - SilcPublicKey public_key; - SilcPKCS pkcs; - unsigned char *verifyd; - SilcUInt32 verify_len; - - if (silc_pkcs_public_key_decode(serverpk.data, serverpk.data_len, - &public_key)) { - silc_pkcs_alloc((unsigned char *)"rsa", &pkcs); - verifyd = silc_attribute_get_verify_data(client_entry->attrs, - TRUE, &verify_len); - if (verifyd && silc_pkcs_public_key_set(pkcs, public_key)) { - if (!silc_pkcs_verify_with_hash(pkcs, client->sha1hash, - serversign.data, - serversign.data_len, - verifyd, verify_len)) - ssign_success = FALSE; - } - silc_pkcs_public_key_free(public_key); - silc_free(verifyd); - } - } - - fingerprint = silc_fingerprint(client_entry->fingerprint, - client_entry->fingerprint_len); - for (i = 0; i < strlen(fingerprint); i++) - if (fingerprint[i] == ' ') - fingerprint[i] = '_'; - - if (usign_success || ssign_success) { - struct passwd *pw; - struct stat st; - - memset(filename2, 0, sizeof(filename2)); - - /* Filename for dir */ - tmp = fingerprint + strlen(fingerprint) - 9; - g_snprintf(filename, sizeof(filename) - 1, - "%s" G_DIR_SEPARATOR_S "friends" G_DIR_SEPARATOR_S "%s", - silcpurple_silcdir(), tmp); - - pw = getpwuid(getuid()); - if (!pw) - return; - - /* Create dir if it doesn't exist */ - if ((g_stat(filename, &st)) == -1) { - if (errno == ENOENT) { - if (pw->pw_uid == geteuid()) { - int ret = g_mkdir(filename, 0755); - if (ret < 0) - return; - } - } - } - - /* Save VCard */ - g_snprintf(filename2, sizeof(filename2) - 1, - "%s" G_DIR_SEPARATOR_S "vcard", filename); - if (vcard.full_name) { - tmp = (char *)silc_vcard_encode(&vcard, &len); - silc_file_writefile(filename2, tmp, len); - silc_free(tmp); - } - - /* Save status message */ - if (message.mime) { - memset(filename2, 0, sizeof(filename2)); - g_snprintf(filename2, sizeof(filename2) - 1, - "%s" G_DIR_SEPARATOR_S "status_message.mime", - filename); - silc_file_writefile(filename2, (char *)message.mime, - message.mime_len); - } - - /* Save extension data */ - if (extension.mime) { - memset(filename2, 0, sizeof(filename2)); - g_snprintf(filename2, sizeof(filename2) - 1, - "%s" G_DIR_SEPARATOR_S "extension.mime", - filename); - silc_file_writefile(filename2, (char *)extension.mime, - extension.mime_len); - } - -#ifdef SILC_ATTRIBUTE_USER_ICON - /* Save user icon */ - if (usericon.mime) { - SilcMime m = silc_mime_decode(usericon.mime, - usericon.mime_len); - if (m) { - const char *type = silc_mime_get_field(m, "Content-Type"); - if (!strcmp(type, "image/jpeg") || - !strcmp(type, "image/gif") || - !strcmp(type, "image/bmp") || - !strcmp(type, "image/png")) { - const unsigned char *data; - SilcUInt32 data_len; - data = silc_mime_get_data(m, &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); - } - } -#endif - } - - /* Save the public key path to buddy properties, as it is used - to identify the buddy in the network (and not the nickname). */ - memset(filename, 0, sizeof(filename)); - g_snprintf(filename, sizeof(filename) - 1, - "%s" G_DIR_SEPARATOR_S "clientkeys" G_DIR_SEPARATOR_S "clientkey_%s.pub", - silcpurple_silcdir(), fingerprint); - purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename); - - /* Update online status */ - purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL); - - /* Finally, start watching this user so we receive its status - changes from the server */ - g_snprintf(filename2, sizeof(filename2) - 1, "+%s", filename); - silc_client_command_call(r->client, r->conn, NULL, "WATCH", "-pubkey", - filename2, NULL); - - silc_free(fingerprint); - silc_free(r); -} - -static void -silcpurple_add_buddy_ask_import(void *user_data, const char *name) -{ - SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data; - SilcPublicKey public_key; - - /* Load the public key */ - if (!silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_BIN)) { - silcpurple_add_buddy_ask_pk_cb(r, 0); - purple_notify_error(r->client->application, - _("Add Buddy"), _("Could not load public key"), NULL); - return; - } - - /* Now verify the public key */ - r->offline_pk = silc_pkcs_public_key_encode(public_key, &r->offline_pk_len); - silcpurple_verify_public_key(r->client, r->conn, r->b->name, - SILC_SOCKET_TYPE_CLIENT, - r->offline_pk, r->offline_pk_len, - SILC_SKE_PK_TYPE_SILC, - silcpurple_add_buddy_save, r); -} - -static void -silcpurple_add_buddy_ask_pk_cancel(void *user_data, const char *name) -{ - SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data; - - /* The user did not import public key. The buddy is unusable. */ - silcpurple_add_buddy_pk_no(r); - silc_free(r); -} - -static void -silcpurple_add_buddy_ask_pk_cb(SilcPurpleBuddyRes r, gint id) -{ - if (id != 0) { - /* The user did not import public key. The buddy is unusable. */ - silcpurple_add_buddy_pk_no(r); - silc_free(r); - return; - } - - /* Open file selector to select the public key. */ - purple_request_file(r->client->application, _("Open..."), NULL, FALSE, - G_CALLBACK(silcpurple_add_buddy_ask_import), - G_CALLBACK(silcpurple_add_buddy_ask_pk_cancel), - purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r); - -} - -static void -silcpurple_add_buddy_ask_pk(SilcPurpleBuddyRes r) -{ - char tmp[512]; - g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not present in the network"), - r->b->name); - purple_request_action(r->client->application, _("Add Buddy"), tmp, - _("To add the buddy you must import his/her public key. " - "Press Import to import a public key."), 0, - purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r, 2, - _("Cancel"), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb), - _("_Import..."), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb)); -} - -static void -silcpurple_add_buddy_getkey_cb(SilcPurpleBuddyRes r, - SilcClientCommandReplyContext cmd) -{ - SilcClientEntry client_entry; - unsigned char *pk; - SilcUInt32 pk_len; - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(r->client, r->conn, - &r->client_id); - if (!client_entry || !client_entry->public_key) { - /* The buddy is offline/nonexistent. We will require user - to associate a public key with the buddy or the buddy - cannot be added. */ - r->offline = TRUE; - silcpurple_add_buddy_ask_pk(r); - return; - } - - /* Now verify the public key */ - pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); - silcpurple_verify_public_key(r->client, r->conn, client_entry->nickname, - SILC_SOCKET_TYPE_CLIENT, - pk, pk_len, SILC_SKE_PK_TYPE_SILC, - silcpurple_add_buddy_save, r); - silc_free(pk); -} - -static void -silcpurple_add_buddy_select_cb(SilcPurpleBuddyRes r, PurpleRequestFields *fields) -{ - PurpleRequestField *f; - GList *list; - SilcClientEntry client_entry; - - f = purple_request_fields_get_field(fields, "list"); - list = purple_request_field_list_get_selected(f); - if (!list) { - /* The user did not select any user. */ - silcpurple_add_buddy_pk_no(r); - silc_free(r); - return; - } - - client_entry = purple_request_field_list_get_data(f, list->data); - silcpurple_add_buddy_resolved(r->client, r->conn, &client_entry, 1, r); -} - -static void -silcpurple_add_buddy_select_cancel(SilcPurpleBuddyRes r, PurpleRequestFields *fields) -{ - /* The user did not select any user. */ - silcpurple_add_buddy_pk_no(r); - silc_free(r); -} - -static void -silcpurple_add_buddy_select(SilcPurpleBuddyRes r, - SilcClientEntry *clients, - SilcUInt32 clients_count) -{ - PurpleRequestFields *fields; - PurpleRequestFieldGroup *g; - PurpleRequestField *f; - char tmp[512], tmp2[128]; - int i; - char *fingerprint; - - fields = purple_request_fields_new(); - g = purple_request_field_group_new(NULL); - f = purple_request_field_list_new("list", NULL); - purple_request_field_group_add_field(g, f); - purple_request_field_list_set_multi_select(f, FALSE); - purple_request_fields_add_group(fields, g); - - for (i = 0; i < clients_count; i++) { - fingerprint = NULL; - if (clients[i]->fingerprint) { - fingerprint = silc_fingerprint(clients[i]->fingerprint, - clients[i]->fingerprint_len); - g_snprintf(tmp2, sizeof(tmp2), "\n%s", fingerprint); - } - g_snprintf(tmp, sizeof(tmp), "%s - %s (%s@%s)%s", - clients[i]->realname, clients[i]->nickname, - clients[i]->username, clients[i]->hostname ? - clients[i]->hostname : "", - fingerprint ? tmp2 : ""); - purple_request_field_list_add_icon(f, tmp, NULL, clients[i]); - silc_free(fingerprint); - } - - purple_request_fields(r->client->application, _("Add Buddy"), - _("Select correct user"), - r->pubkey_search - ? _("More than one user was found with the same public key. Select " - "the correct user from the list to add to the buddy list.") - : _("More than one user was found with the same name. Select " - "the correct user from the list to add to the buddy list."), - fields, - _("OK"), G_CALLBACK(silcpurple_add_buddy_select_cb), - _("Cancel"), G_CALLBACK(silcpurple_add_buddy_select_cancel), - purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r); -} - -static void -silcpurple_add_buddy_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - SilcPurpleBuddyRes r = context; - PurpleBuddy *b = r->b; - SilcAttributePayload pub; - SilcAttributeObjPk userpk; - unsigned char *pk; - SilcUInt32 pk_len; - const char *filename; - - filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key"); - - /* If the buddy is offline/nonexistent, we will require user - to associate a public key with the buddy or the buddy - cannot be added. */ - if (!clients_count) { - if (r->init) { - silc_free(r); - return; - } - - r->offline = TRUE; - /* If the user has already associated a public key, try loading it - * before prompting the user to load it again */ - if (filename != NULL) - silcpurple_add_buddy_ask_import(r, filename); - else - silcpurple_add_buddy_ask_pk(r); - return; - } - - /* If more than one client was found with nickname, we need to verify - from user which one is the correct. */ - if (clients_count > 1 && !r->pubkey_search) { - if (r->init) { - silc_free(r); - return; - } - - silcpurple_add_buddy_select(r, clients, clients_count); - return; - } - - /* If we searched using public keys and more than one entry was found - the same person is logged on multiple times. */ - if (clients_count > 1 && r->pubkey_search && b->name) { - if (r->init) { - /* Find the entry that closest matches to the - buddy nickname. */ - int i; - for (i = 0; i < clients_count; i++) { - if (!g_ascii_strncasecmp(b->name, clients[i]->nickname, - strlen(b->name))) { - clients[0] = clients[i]; - break; - } - } - } else { - /* Verify from user which one is correct */ - silcpurple_add_buddy_select(r, clients, clients_count); - return; - } - } - - /* The client was found. Now get its public key and verify - that before adding the buddy. */ - memset(&userpk, 0, sizeof(userpk)); - b->proto_data = silc_memdup(clients[0]->id, sizeof(*clients[0]->id)); - r->client_id = *clients[0]->id; - - /* Get the public key from attributes, if not present then - resolve it with GETKEY unless we have it cached already. */ - if (clients[0]->attrs && !clients[0]->public_key) { - pub = silcpurple_get_attr(clients[0]->attrs, - SILC_ATTRIBUTE_USER_PUBLIC_KEY); - if (!pub || !silc_attribute_get_object(pub, (void *)&userpk, - sizeof(userpk))) { - /* Get public key with GETKEY */ - silc_client_command_call(client, conn, NULL, - "GETKEY", clients[0]->nickname, NULL); - silc_client_command_pending(conn, SILC_COMMAND_GETKEY, - conn->cmd_ident, - (SilcCommandCb)silcpurple_add_buddy_getkey_cb, - r); - return; - } - if (!silc_pkcs_public_key_decode(userpk.data, userpk.data_len, - &clients[0]->public_key)) - return; - silc_free(userpk.data); - } else if (filename && !clients[0]->public_key) { - if (!silc_pkcs_load_public_key(filename, &clients[0]->public_key, - SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(filename, &clients[0]->public_key, - SILC_PKCS_FILE_BIN)) { - /* Get public key with GETKEY */ - silc_client_command_call(client, conn, NULL, - "GETKEY", clients[0]->nickname, NULL); - silc_client_command_pending(conn, SILC_COMMAND_GETKEY, - conn->cmd_ident, - (SilcCommandCb)silcpurple_add_buddy_getkey_cb, - r); - return; - } - } else if (!clients[0]->public_key) { - /* Get public key with GETKEY */ - silc_client_command_call(client, conn, NULL, - "GETKEY", clients[0]->nickname, NULL); - silc_client_command_pending(conn, SILC_COMMAND_GETKEY, - conn->cmd_ident, - (SilcCommandCb)silcpurple_add_buddy_getkey_cb, - r); - return; - } - - /* We have the public key, verify it. */ - pk = silc_pkcs_public_key_encode(clients[0]->public_key, &pk_len); - silcpurple_verify_public_key(client, conn, clients[0]->nickname, - SILC_SOCKET_TYPE_CLIENT, - pk, pk_len, SILC_SKE_PK_TYPE_SILC, - silcpurple_add_buddy_save, r); - silc_free(pk); -} - -static void -silcpurple_add_buddy_i(PurpleConnection *gc, PurpleBuddy *b, gboolean init) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcPurpleBuddyRes r; - SilcBuffer attrs; - const char *filename, *name = b->name; - - r = silc_calloc(1, sizeof(*r)); - if (!r) - return; - r->client = client; - r->conn = conn; - r->b = b; - r->init = init; - - /* See if we have this buddy's public key. If we do use that - to search the details. */ - filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key"); - if (filename) { - SilcPublicKey public_key; - SilcAttributeObjPk userpk; - - if (!silc_pkcs_load_public_key(filename, &public_key, - SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(filename, &public_key, - SILC_PKCS_FILE_BIN)) - return; - - /* Get all attributes, and use the public key to search user */ - name = NULL; - attrs = silc_client_attributes_request(SILC_ATTRIBUTE_USER_INFO, - SILC_ATTRIBUTE_SERVICE, - SILC_ATTRIBUTE_STATUS_MOOD, - SILC_ATTRIBUTE_STATUS_FREETEXT, - SILC_ATTRIBUTE_STATUS_MESSAGE, - SILC_ATTRIBUTE_PREFERRED_LANGUAGE, - SILC_ATTRIBUTE_PREFERRED_CONTACT, - SILC_ATTRIBUTE_TIMEZONE, - SILC_ATTRIBUTE_GEOLOCATION, -#ifdef SILC_ATTRIBUTE_USER_ICON - SILC_ATTRIBUTE_USER_ICON, -#endif - SILC_ATTRIBUTE_DEVICE_INFO, 0); - userpk.type = "silc-rsa"; - userpk.data = silc_pkcs_public_key_encode(public_key, &userpk.data_len); - attrs = silc_attribute_payload_encode(attrs, - SILC_ATTRIBUTE_USER_PUBLIC_KEY, - SILC_ATTRIBUTE_FLAG_VALID, - &userpk, sizeof(userpk)); - silc_free(userpk.data); - silc_pkcs_public_key_free(public_key); - r->pubkey_search = TRUE; - } else { - /* Get all attributes */ - attrs = silc_client_attributes_request(0); - } - - /* Resolve */ - silc_client_get_clients_whois(client, conn, name, NULL, attrs, - silcpurple_add_buddy_resolved, r); - silc_buffer_free(attrs); -} - -void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) -{ - /* Don't add if the buddy is already on the list. - * - * SILC doesn't have groups, so we don't need to do anything - * for a move. */ - if (purple_buddy_get_protocol_data(buddy) == NULL) - silcpurple_add_buddy_i(gc, buddy, FALSE); -} - -void silcpurple_send_buddylist(PurpleConnection *gc) -{ - PurpleBuddyList *blist; - PurpleBlistNode *gnode, *cnode, *bnode; - PurpleBuddy *buddy; - PurpleAccount *account; - - account = purple_connection_get_account(gc); - - if ((blist = purple_get_blist()) != NULL) - { - for (gnode = blist->root; gnode != NULL; gnode = gnode->next) - { - if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) - continue; - for (cnode = gnode->child; cnode != NULL; cnode = cnode->next) - { - if (!PURPLE_BLIST_NODE_IS_CONTACT(cnode)) - continue; - for (bnode = cnode->child; bnode != NULL; bnode = bnode->next) - { - if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) - continue; - buddy = (PurpleBuddy *)bnode; - if (purple_buddy_get_account(buddy) == account) - silcpurple_add_buddy_i(gc, buddy, TRUE); - } - } - } - } -} - -void silcpurple_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, - PurpleGroup *group) -{ - silc_free(buddy->proto_data); -} - -void silcpurple_idle_set(PurpleConnection *gc, int idle) - -{ - SilcPurple sg; - SilcClient client; - SilcClientConnection conn; - SilcAttributeObjService service; - const char *server; - int port; - - sg = gc->proto_data; - if (sg == NULL) - return; - - client = sg->client; - if (client == NULL) - return; - - conn = sg->conn; - if (conn == NULL) - return; - - server = purple_account_get_string(sg->account, "server", - "silc.silcnet.org"); - port = purple_account_get_int(sg->account, "port", 706), - - memset(&service, 0, sizeof(service)); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_SERVICE, NULL); - service.port = port; - g_snprintf(service.address, sizeof(service.address), "%s", server); - service.idle = idle; - silc_client_attribute_add(client, conn, SILC_ATTRIBUTE_SERVICE, - &service, sizeof(service)); -} - -char *silcpurple_status_text(PurpleBuddy *b) -{ - SilcPurple sg = b->account->gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientID *client_id = b->proto_data; - SilcClientEntry client_entry; - SilcAttributePayload attr; - SilcAttributeMood mood = 0; - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(client, conn, client_id); - if (!client_entry) - return NULL; - - /* If user is online, we show the mood status, if available. - If user is offline or away that status is indicated. */ - - if (client_entry->mode & SILC_UMODE_DETACHED) - return g_strdup(_("Detached")); - if (client_entry->mode & SILC_UMODE_GONE) - return g_strdup(_("Away")); - if (client_entry->mode & SILC_UMODE_INDISPOSED) - return g_strdup(_("Indisposed")); - if (client_entry->mode & SILC_UMODE_BUSY) - return g_strdup(_("Busy")); - if (client_entry->mode & SILC_UMODE_PAGE) - return g_strdup(_("Wake Me Up")); - if (client_entry->mode & SILC_UMODE_HYPER) - return g_strdup(_("Hyper Active")); - if (client_entry->mode & SILC_UMODE_ROBOT) - return g_strdup(_("Robot")); - - attr = silcpurple_get_attr(client_entry->attrs, SILC_ATTRIBUTE_STATUS_MOOD); - if (attr && silc_attribute_get_object(attr, &mood, sizeof(mood))) { - /* The mood is a bit mask, so we could show multiple moods, - but let's show only one for now. */ - if (mood & SILC_ATTRIBUTE_MOOD_HAPPY) - return g_strdup(_("Happy")); - if (mood & SILC_ATTRIBUTE_MOOD_SAD) - return g_strdup(_("Sad")); - if (mood & SILC_ATTRIBUTE_MOOD_ANGRY) - return g_strdup(_("Angry")); - if (mood & SILC_ATTRIBUTE_MOOD_JEALOUS) - return g_strdup(_("Jealous")); - if (mood & SILC_ATTRIBUTE_MOOD_ASHAMED) - return g_strdup(_("Ashamed")); - if (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE) - return g_strdup(_("Invincible")); - if (mood & SILC_ATTRIBUTE_MOOD_INLOVE) - return g_strdup(_("In Love")); - if (mood & SILC_ATTRIBUTE_MOOD_SLEEPY) - return g_strdup(_("Sleepy")); - if (mood & SILC_ATTRIBUTE_MOOD_BORED) - return g_strdup(_("Bored")); - if (mood & SILC_ATTRIBUTE_MOOD_EXCITED) - return g_strdup(_("Excited")); - if (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS) - return g_strdup(_("Anxious")); - } - - return NULL; -} - -void silcpurple_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) -{ - SilcPurple sg = b->account->gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientID *client_id = b->proto_data; - SilcClientEntry client_entry; - char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr; - char tmp[256]; - - /* Get the client entry. */ - client_entry = silc_client_get_client_by_id(client, conn, client_id); - if (!client_entry) - return; - - if (client_entry->nickname) - purple_notify_user_info_add_pair(user_info, _("Nickname"), - client_entry->nickname); - if (client_entry->username && client_entry->hostname) { - g_snprintf(tmp, sizeof(tmp), "%s@%s", client_entry->username, client_entry->hostname); - purple_notify_user_info_add_pair(user_info, _("Username"), tmp); - } - if (client_entry->mode) { - memset(tmp, 0, sizeof(tmp)); - silcpurple_get_umode_string(client_entry->mode, - tmp, sizeof(tmp) - strlen(tmp)); - purple_notify_user_info_add_pair(user_info, _("User Modes"), tmp); - } - - silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr); - - if (statusstr) { - purple_notify_user_info_add_pair(user_info, _("Message"), statusstr); - g_free(statusstr); - } - - if (full) { - if (moodstr) { - purple_notify_user_info_add_pair(user_info, _("Mood"), moodstr); - g_free(moodstr); - } - - if (contactstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Contact"), contactstr); - g_free(contactstr); - } - - if (langstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Language"), langstr); - g_free(langstr); - } - - if (devicestr) { - purple_notify_user_info_add_pair(user_info, _("Device"), devicestr); - g_free(devicestr); - } - - if (tzstr) { - purple_notify_user_info_add_pair(user_info, _("Timezone"), tzstr); - g_free(tzstr); - } - - if (geostr) { - purple_notify_user_info_add_pair(user_info, _("Geolocation"), geostr); - g_free(geostr); - } - } -} - -static void -silcpurple_buddy_kill(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *b; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); - - b = (PurpleBuddy *) node; - gc = purple_account_get_connection(b->account); - sg = gc->proto_data; - - /* Call KILL */ - silc_client_command_call(sg->client, sg->conn, NULL, "KILL", - b->name, "Killed by operator", NULL); -} - -typedef struct { - SilcPurple sg; - SilcClientEntry client_entry; -} *SilcPurpleBuddyWb; - -static void -silcpurple_buddy_wb(PurpleBlistNode *node, gpointer data) -{ - SilcPurpleBuddyWb wb = data; - silcpurple_wb_init(wb->sg, wb->client_entry); - silc_free(wb); -} - -GList *silcpurple_buddy_menu(PurpleBuddy *buddy) -{ - PurpleConnection *gc = purple_account_get_connection(buddy->account); - SilcPurple sg = gc->proto_data; - SilcClientConnection conn = sg->conn; - const char *pkfile = NULL; - SilcClientEntry client_entry = NULL; - PurpleMenuAction *act; - GList *m = NULL; - SilcPurpleBuddyWb wb; - - pkfile = purple_blist_node_get_string((PurpleBlistNode *) buddy, "public-key"); - client_entry = silc_client_get_client_by_id(sg->client, - sg->conn, - buddy->proto_data); - - if (client_entry && client_entry->send_key) { - act = purple_menu_action_new(_("Reset IM Key"), - PURPLE_CALLBACK(silcpurple_buddy_resetkey), - NULL, NULL); - m = g_list_append(m, act); - - } else { - act = purple_menu_action_new(_("IM with Key Exchange"), - PURPLE_CALLBACK(silcpurple_buddy_keyagr), - NULL, NULL); - m = g_list_append(m, act); - - act = purple_menu_action_new(_("IM with Password"), - PURPLE_CALLBACK(silcpurple_buddy_privkey_menu), - NULL, NULL); - m = g_list_append(m, act); - } - - if (pkfile) { - act = purple_menu_action_new(_("Show Public Key"), - PURPLE_CALLBACK(silcpurple_buddy_showkey), - NULL, NULL); - m = g_list_append(m, act); - - } else { - act = purple_menu_action_new(_("Get Public Key..."), - PURPLE_CALLBACK(silcpurple_buddy_getkey_menu), - NULL, NULL); - m = g_list_append(m, act); - } - - if (conn && conn->local_entry->mode & SILC_UMODE_ROUTER_OPERATOR) { - act = purple_menu_action_new(_("Kill User"), - PURPLE_CALLBACK(silcpurple_buddy_kill), - NULL, NULL); - m = g_list_append(m, act); - } - - if (client_entry) { - wb = silc_calloc(1, sizeof(*wb)); - wb->sg = sg; - wb->client_entry = client_entry; - act = purple_menu_action_new(_("Draw On Whiteboard"), - PURPLE_CALLBACK(silcpurple_buddy_wb), - (void *)wb, NULL); - m = g_list_append(m, act); - } - return m; -} - -#ifdef SILC_ATTRIBUTE_USER_ICON -void silcpurple_buddy_set_icon(PurpleConnection *gc, PurpleStoredImage *img) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcMime mime; - char type[32]; - unsigned char *icon; - const char *t; - SilcAttributeObjMime obj; - - /* Remove */ - if (!img) { - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_USER_ICON, NULL); - return; - } - - /* Add */ - mime = silc_mime_alloc(); - if (!mime) - return; - - t = purple_imgstore_get_extension(img); - if (!t || !strcmp(t, "icon")) { - silc_mime_free(mime); - return; - } - if (!strcmp(t, "jpg")) - t = "jpeg"; - g_snprintf(type, sizeof(type), "image/%s", t); - silc_mime_add_field(mime, "Content-Type", type); - 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) - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_USER_ICON, &obj, sizeof(obj)); - - silc_free(icon); - silc_mime_free(mime); -} -#endif diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc10/chat.c --- a/libpurple/protocols/silc10/chat.c Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1456 +0,0 @@ -/* - - silcpurple_chat.c - - Author: Pekka Riikonen - - Copyright (C) 2004 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#include "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" -#include "wb.h" - -/***************************** Channel Routines ******************************/ - -GList *silcpurple_chat_info(PurpleConnection *gc) -{ - GList *ci = NULL; - struct proto_chat_entry *pce; - - pce = g_new0(struct proto_chat_entry, 1); - pce->label = _("_Channel:"); - pce->identifier = "channel"; - pce->required = TRUE; - ci = g_list_append(ci, pce); - - pce = g_new0(struct proto_chat_entry, 1); - pce->label = _("_Passphrase:"); - pce->identifier = "passphrase"; - pce->secret = TRUE; - ci = g_list_append(ci, pce); - - return ci; -} - -GHashTable *silcpurple_chat_info_defaults(PurpleConnection *gc, const char *chat_name) -{ - GHashTable *defaults; - - defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); - - if (chat_name != NULL) - g_hash_table_insert(defaults, "channel", g_strdup(chat_name)); - - return defaults; -} - -static void -silcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components); - -static void -silcpurple_chat_getinfo_res(SilcClient client, - SilcClientConnection conn, - SilcChannelEntry *channels, - SilcUInt32 channels_count, - void *context) -{ - GHashTable *components = context; - PurpleConnection *gc = client->application; - const char *chname; - char tmp[256]; - - chname = g_hash_table_lookup(components, "channel"); - if (!chname) - return; - - if (!channels) { - g_snprintf(tmp, sizeof(tmp), - _("Channel %s does not exist in the network"), chname); - purple_notify_error(gc, _("Channel Information"), - _("Cannot get channel information"), tmp); - return; - } - - silcpurple_chat_getinfo(gc, components); -} - - -static void -silcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components) -{ - SilcPurple sg = gc->proto_data; - const char *chname; - char *buf, tmp[256], *tmp2; - GString *s; - SilcChannelEntry channel; - SilcHashTableList htl; - SilcChannelUser chu; - - if (!components) - return; - - chname = g_hash_table_lookup(components, "channel"); - if (!chname) - return; - channel = silc_client_get_channel(sg->client, sg->conn, - (char *)chname); - if (!channel) { - silc_client_get_channel_resolve(sg->client, sg->conn, - (char *)chname, - silcpurple_chat_getinfo_res, - components); - return; - } - - s = g_string_new(""); - tmp2 = g_markup_escape_text(channel->channel_name, -1); - g_string_append_printf(s, _("Channel Name: %s"), tmp2); - g_free(tmp2); - if (channel->user_list && silc_hash_table_count(channel->user_list)) - g_string_append_printf(s, _("
User Count: %d"), - (int)silc_hash_table_count(channel->user_list)); - - silc_hash_table_list(channel->user_list, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) { - tmp2 = g_markup_escape_text(chu->client->nickname, -1); - g_string_append_printf(s, _("
Channel Founder: %s"), - tmp2); - g_free(tmp2); - break; - } - } - silc_hash_table_list_reset(&htl); - - if (channel->channel_key) - g_string_append_printf(s, _("
Channel Cipher: %s"), - silc_cipher_get_name(channel->channel_key)); - if (channel->hmac) - /* Definition of HMAC: http://en.wikipedia.org/wiki/HMAC */ - g_string_append_printf(s, _("
Channel HMAC: %s"), - silc_hmac_get_name(channel->hmac)); - - if (channel->topic) { - tmp2 = g_markup_escape_text(channel->topic, -1); - g_string_append_printf(s, _("
Channel Topic:
%s"), tmp2); - g_free(tmp2); - } - - if (channel->mode) { - g_string_append_printf(s, _("
Channel Modes: ")); - silcpurple_get_chmode_string(channel->mode, tmp, sizeof(tmp)); - g_string_append(s, tmp); - } - - if (channel->founder_key) { - char *fingerprint, *babbleprint; - unsigned char *pk; - SilcUInt32 pk_len; - pk = silc_pkcs_public_key_encode(channel->founder_key, &pk_len); - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - - g_string_append_printf(s, _("
Founder Key Fingerprint:
%s"), fingerprint); - g_string_append_printf(s, _("
Founder Key Babbleprint:
%s"), babbleprint); - - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - } - - buf = g_string_free(s, FALSE); - purple_notify_formatted(gc, NULL, _("Channel Information"), NULL, buf, NULL, NULL); - g_free(buf); -} - - -static void -silcpurple_chat_getinfo_menu(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat = (PurpleChat *)node; - silcpurple_chat_getinfo(chat->account->gc, chat->components); -} - - -#if 0 /* XXX For now these are not implemented. We need better - listview dialog from Purple for these. */ -/************************** Channel Invite List ******************************/ - -static void -silcpurple_chat_invitelist(PurpleBlistNode *node, gpointer data); -{ - -} - - -/**************************** Channel Ban List *******************************/ - -static void -silcpurple_chat_banlist(PurpleBlistNode *node, gpointer data); -{ - -} -#endif - - -/************************* Channel Authentication ****************************/ - -typedef struct { - SilcPurple sg; - SilcChannelEntry channel; - PurpleChat *c; - SilcBuffer pubkeys; -} *SilcPurpleChauth; - -static void -silcpurple_chat_chpk_add(void *user_data, const char *name) -{ - SilcPurpleChauth sgc = (SilcPurpleChauth)user_data; - SilcPurple sg = sgc->sg; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcPublicKey public_key; - SilcBuffer chpks, pk, chidp; - unsigned char mode[4]; - SilcUInt32 m; - - /* Load the public key */ - if (!silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_BIN)) { - silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys); - silc_buffer_free(sgc->pubkeys); - silc_free(sgc); - purple_notify_error(client->application, - _("Add Channel Public Key"), - _("Could not load public key"), NULL); - return; - } - - pk = silc_pkcs_public_key_payload_encode(public_key); - chpks = silc_buffer_alloc_size(2); - SILC_PUT16_MSB(1, chpks->head); - chpks = silc_argument_payload_encode_one(chpks, pk->data, - pk->len, 0x00); - silc_buffer_free(pk); - - m = sgc->channel->mode; - m |= SILC_CHANNEL_MODE_CHANNEL_AUTH; - - /* Send CMODE */ - SILC_PUT32_MSB(m, mode); - chidp = silc_id_payload_encode(sgc->channel->id, SILC_ID_CHANNEL); - silc_client_command_send(client, conn, SILC_COMMAND_CMODE, - ++conn->cmd_ident, 3, - 1, chidp->data, chidp->len, - 2, mode, sizeof(mode), - 9, chpks->data, chpks->len); - silc_buffer_free(chpks); - silc_buffer_free(chidp); - silc_buffer_free(sgc->pubkeys); - silc_free(sgc); -} - -static void -silcpurple_chat_chpk_cancel(void *user_data, const char *name) -{ - SilcPurpleChauth sgc = (SilcPurpleChauth)user_data; - silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys); - silc_buffer_free(sgc->pubkeys); - silc_free(sgc); -} - -static void -silcpurple_chat_chpk_cb(SilcPurpleChauth sgc, PurpleRequestFields *fields) -{ - SilcPurple sg = sgc->sg; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - PurpleRequestField *f; - GList *list; - SilcPublicKey public_key; - SilcBuffer chpks, pk, chidp; - SilcUInt16 c = 0, ct; - unsigned char mode[4]; - SilcUInt32 m; - - f = purple_request_fields_get_field(fields, "list"); - if (!purple_request_field_list_get_selected(f)) { - /* Add new public key */ - purple_request_file(sg->gc, _("Open Public Key..."), NULL, FALSE, - G_CALLBACK(silcpurple_chat_chpk_add), - G_CALLBACK(silcpurple_chat_chpk_cancel), - purple_connection_get_account(sg->gc), NULL, NULL, sgc); - return; - } - - list = purple_request_field_list_get_items(f); - chpks = silc_buffer_alloc_size(2); - - for (ct = 0; list; list = list->next, ct++) { - public_key = purple_request_field_list_get_data(f, list->data); - if (purple_request_field_list_is_selected(f, list->data)) { - /* Delete this public key */ - pk = silc_pkcs_public_key_payload_encode(public_key); - chpks = silc_argument_payload_encode_one(chpks, pk->data, - pk->len, 0x01); - silc_buffer_free(pk); - c++; - } - silc_pkcs_public_key_free(public_key); - } - if (!c) { - silc_buffer_free(chpks); - return; - } - SILC_PUT16_MSB(c, chpks->head); - - m = sgc->channel->mode; - if (ct == c) - m &= ~SILC_CHANNEL_MODE_CHANNEL_AUTH; - - /* Send CMODE */ - SILC_PUT32_MSB(m, mode); - chidp = silc_id_payload_encode(sgc->channel->id, SILC_ID_CHANNEL); - silc_client_command_send(client, conn, SILC_COMMAND_CMODE, - ++conn->cmd_ident, 3, - 1, chidp->data, chidp->len, - 2, mode, sizeof(mode), - 9, chpks->data, chpks->len); - silc_buffer_free(chpks); - silc_buffer_free(chidp); - silc_buffer_free(sgc->pubkeys); - silc_free(sgc); -} - -static void -silcpurple_chat_chauth_ok(SilcPurpleChauth sgc, PurpleRequestFields *fields) -{ - SilcPurple sg = sgc->sg; - PurpleRequestField *f; - const char *curpass, *val; - int set; - - f = purple_request_fields_get_field(fields, "passphrase"); - val = purple_request_field_string_get_value(f); - curpass = purple_blist_node_get_string((PurpleBlistNode *)sgc->c, "passphrase"); - - if (!val && curpass) - set = 0; - else if (val && !curpass) - set = 1; - else if (val && curpass && strcmp(val, curpass)) - set = 1; - else - set = -1; - - if (set == 1) { - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - sgc->channel->channel_name, "+a", val, NULL); - purple_blist_node_set_string((PurpleBlistNode *)sgc->c, "passphrase", val); - } else if (set == 0) { - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - sgc->channel->channel_name, "-a", NULL); - purple_blist_node_remove_setting((PurpleBlistNode *)sgc->c, "passphrase"); - } - - silc_buffer_free(sgc->pubkeys); - silc_free(sgc); -} - -void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel, - SilcBuffer channel_pubkeys) -{ - SilcUInt16 argc; - SilcArgumentPayload chpks; - unsigned char *pk; - SilcUInt32 pk_len, type; - char *fingerprint, *babbleprint; - SilcPublicKey pubkey; - SilcPublicKeyIdentifier ident; - char tmp2[1024], t[512]; - PurpleRequestFields *fields; - PurpleRequestFieldGroup *g; - PurpleRequestField *f; - SilcPurpleChauth sgc; - const char *curpass = NULL; - - sgc = silc_calloc(1, sizeof(*sgc)); - if (!sgc) - return; - sgc->sg = sg; - sgc->channel = channel; - - fields = purple_request_fields_new(); - - if (sgc->c) - curpass = purple_blist_node_get_string((PurpleBlistNode *)sgc->c, "passphrase"); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("passphrase", _("Channel Passphrase"), - curpass, FALSE); - purple_request_field_string_set_masked(f, TRUE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_label_new("l1", _("Channel Public Keys List")); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g_snprintf(t, sizeof(t), - _("Channel authentication is used to secure the channel from " - "unauthorized access. The authentication may be based on " - "passphrase and digital signatures. If passphrase is set, it " - "is required to be able to join. If channel public keys are set " - "then only users whose public keys are listed are able to join.")); - - if (!channel_pubkeys) { - f = purple_request_field_list_new("list", NULL); - purple_request_field_group_add_field(g, f); - purple_request_fields(sg->gc, _("Channel Authentication"), - _("Channel Authentication"), t, fields, - _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb), - _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok), - purple_connection_get_account(sg->gc), NULL, NULL, sgc); - return; - } - sgc->pubkeys = silc_buffer_copy(channel_pubkeys); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_list_new("list", NULL); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - SILC_GET16_MSB(argc, channel_pubkeys->data); - chpks = silc_argument_payload_parse(channel_pubkeys->data + 2, - channel_pubkeys->len - 2, argc); - if (!chpks) - return; - - pk = silc_argument_get_first_arg(chpks, &type, &pk_len); - while (pk) { - fingerprint = silc_hash_fingerprint(NULL, pk + 4, pk_len - 4); - babbleprint = silc_hash_babbleprint(NULL, pk + 4, pk_len - 4); - silc_pkcs_public_key_payload_decode(pk, pk_len, &pubkey); - ident = silc_pkcs_decode_identifier(pubkey->identifier); - - g_snprintf(tmp2, sizeof(tmp2), "%s\n %s\n %s", - ident->realname ? ident->realname : ident->username ? - ident->username : "", fingerprint, babbleprint); - purple_request_field_list_add_icon(f, tmp2, NULL, pubkey); - - silc_free(fingerprint); - silc_free(babbleprint); - silc_pkcs_free_identifier(ident); - pk = silc_argument_get_next_arg(chpks, &type, &pk_len); - } - - purple_request_field_list_set_multi_select(f, FALSE); - purple_request_fields(sg->gc, _("Channel Authentication"), - _("Channel Authentication"), t, fields, - _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb), - _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok), - purple_connection_get_account(sg->gc), NULL, NULL, sgc); - - silc_argument_payload_free(chpks); -} - -static void -silcpurple_chat_chauth(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "+C", NULL); -} - - -/************************** Channel Private Groups **************************/ - -/* Private groups are "virtual" channels. They are groups inside a channel. - This is implemented by using channel private keys. By knowing a channel - private key user becomes part of that group and is able to talk on that - group. Other users, on the same channel, won't be able to see the - messages of that group. It is possible to have multiple groups inside - a channel - and thus having multiple private keys on the channel. */ - -typedef struct { - SilcPurple sg; - PurpleChat *c; - const char *channel; -} *SilcPurpleCharPrv; - -static void -silcpurple_chat_prv_add(SilcPurpleCharPrv p, PurpleRequestFields *fields) -{ - SilcPurple sg = p->sg; - char tmp[512]; - PurpleRequestField *f; - const char *name, *passphrase, *alias; - GHashTable *comp; - PurpleGroup *g; - PurpleChat *cn; - - f = purple_request_fields_get_field(fields, "name"); - name = purple_request_field_string_get_value(f); - if (!name) { - silc_free(p); - return; - } - f = purple_request_fields_get_field(fields, "passphrase"); - passphrase = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "alias"); - alias = purple_request_field_string_get_value(f); - - /* Add private group to buddy list */ - g_snprintf(tmp, sizeof(tmp), "%s [Private Group]", name); - comp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - g_hash_table_replace(comp, g_strdup("channel"), g_strdup(tmp)); - g_hash_table_replace(comp, g_strdup("passphrase"), g_strdup(passphrase)); - - cn = purple_chat_new(sg->account, alias, comp); - g = (PurpleGroup *)p->c->node.parent; - purple_blist_add_chat(cn, g, (PurpleBlistNode *)p->c); - - /* Associate to a real channel */ - purple_blist_node_set_string((PurpleBlistNode *)cn, "parentch", p->channel); - - /* Join the group */ - silcpurple_chat_join(sg->gc, comp); - - silc_free(p); -} - -static void -silcpurple_chat_prv_cancel(SilcPurpleCharPrv p, PurpleRequestFields *fields) -{ - silc_free(p); -} - -static void -silcpurple_chat_prv(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - SilcPurpleCharPrv p; - PurpleRequestFields *fields; - PurpleRequestFieldGroup *g; - PurpleRequestField *f; - char tmp[512]; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - p = silc_calloc(1, sizeof(*p)); - if (!p) - return; - p->sg = sg; - - p->channel = g_hash_table_lookup(chat->components, "channel"); - p->c = purple_blist_find_chat(sg->account, p->channel); - - fields = purple_request_fields_new(); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("name", _("Group Name"), - NULL, FALSE); - purple_request_field_group_add_field(g, f); - - f = purple_request_field_string_new("passphrase", _("Passphrase"), - NULL, FALSE); - purple_request_field_string_set_masked(f, TRUE); - purple_request_field_group_add_field(g, f); - - f = purple_request_field_string_new("alias", _("Alias"), - NULL, FALSE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g_snprintf(tmp, sizeof(tmp), - _("Please enter the %s channel private group name and passphrase."), - p->channel); - purple_request_fields(gc, _("Add Channel Private Group"), NULL, tmp, fields, - _("Add"), G_CALLBACK(silcpurple_chat_prv_add), - _("Cancel"), G_CALLBACK(silcpurple_chat_prv_cancel), - purple_connection_get_account(gc), NULL, NULL, p); -} - - -/****************************** Channel Modes ********************************/ - -static void -silcpurple_chat_permanent_reset(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "-f", NULL); -} - -static void -silcpurple_chat_permanent(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - const char *channel; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - if (!sg->conn) - return; - - /* XXX we should have ability to define which founder - key to use. Now we use the user's own public key - (default key). */ - - /* Call CMODE */ - channel = g_hash_table_lookup(chat->components, "channel"); - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", channel, - "+f", NULL); -} - -typedef struct { - SilcPurple sg; - char *channel; -} *SilcPurpleChatInput; - -static void -silcpurple_chat_ulimit_cb(SilcPurpleChatInput s, const char *limit) -{ - SilcChannelEntry channel; - int ulimit = 0; - - channel = silc_client_get_channel(s->sg->client, s->sg->conn, - (char *)s->channel); - if (!channel) - return; - if (limit) - ulimit = atoi(limit); - - if (!limit || !(*limit) || *limit == '0') { - if (limit && ulimit == channel->user_limit) { - silc_free(s); - return; - } - silc_client_command_call(s->sg->client, s->sg->conn, NULL, "CMODE", - s->channel, "-l", NULL); - - silc_free(s); - return; - } - - if (ulimit == channel->user_limit) { - silc_free(s); - return; - } - - /* Call CMODE */ - silc_client_command_call(s->sg->client, s->sg->conn, NULL, "CMODE", - s->channel, "+l", limit, NULL); - - silc_free(s); -} - -static void -silcpurple_chat_ulimit(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - SilcPurpleChatInput s; - SilcChannelEntry channel; - char *ch; - char tmp[32]; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - if (!sg->conn) - return; - - ch = g_strdup(g_hash_table_lookup(chat->components, "channel")); - channel = silc_client_get_channel(sg->client, sg->conn, (char *)ch); - if (!channel) - return; - - s = silc_calloc(1, sizeof(*s)); - if (!s) - return; - s->channel = ch; - s->sg = sg; - g_snprintf(tmp, sizeof(tmp), "%d", (int)channel->user_limit); - purple_request_input(gc, _("User Limit"), NULL, - _("Set user limit on channel. Set to zero to reset user limit."), - tmp, FALSE, FALSE, NULL, - _("OK"), G_CALLBACK(silcpurple_chat_ulimit_cb), - _("Cancel"), G_CALLBACK(silcpurple_chat_ulimit_cb), - purple_connection_get_account(gc), NULL, NULL, s); -} - -static void -silcpurple_chat_resettopic(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "-t", NULL); -} - -static void -silcpurple_chat_settopic(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "+t", NULL); -} - -static void -silcpurple_chat_resetprivate(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "-p", NULL); -} - -static void -silcpurple_chat_setprivate(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "+p", NULL); -} - -static void -silcpurple_chat_resetsecret(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "-s", NULL); -} - -static void -silcpurple_chat_setsecret(PurpleBlistNode *node, gpointer data) -{ - PurpleChat *chat; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node)); - - chat = (PurpleChat *) node; - gc = purple_account_get_connection(chat->account); - sg = gc->proto_data; - - silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", - g_hash_table_lookup(chat->components, "channel"), - "+s", NULL); -} - -typedef struct { - SilcPurple sg; - SilcChannelEntry channel; -} *SilcPurpleChatWb; - -static void -silcpurple_chat_wb(PurpleBlistNode *node, gpointer data) -{ - SilcPurpleChatWb wb = data; - silcpurple_wb_init_ch(wb->sg, wb->channel); - silc_free(wb); -} - -GList *silcpurple_chat_menu(PurpleChat *chat) -{ - GHashTable *components = chat->components; - PurpleConnection *gc = purple_account_get_connection(chat->account); - SilcPurple sg = gc->proto_data; - SilcClientConnection conn = sg->conn; - const char *chname = NULL; - SilcChannelEntry channel = NULL; - SilcChannelUser chu = NULL; - SilcUInt32 mode = 0; - - GList *m = NULL; - PurpleMenuAction *act; - - if (components) - chname = g_hash_table_lookup(components, "channel"); - if (chname) - channel = silc_client_get_channel(sg->client, sg->conn, - (char *)chname); - if (channel) { - chu = silc_client_on_channel(channel, conn->local_entry); - if (chu) - mode = chu->mode; - } - - if (strstr(chname, "[Private Group]")) - return NULL; - - act = purple_menu_action_new(_("Get Info"), - PURPLE_CALLBACK(silcpurple_chat_getinfo_menu), - NULL, NULL); - m = g_list_append(m, act); - -#if 0 /* XXX For now these are not implemented. We need better - listview dialog from Purple for these. */ - if (mode & SILC_CHANNEL_UMODE_CHANOP) { - act = purple_menu_action_new(_("Invite List"), - PURPLE_CALLBACK(silcpurple_chat_invitelist), - NULL, NULL); - m = g_list_append(m, act); - - act = purple_menu_action_new(_("Ban List"), - PURPLE_CALLBACK(silcpurple_chat_banlist), - NULL, NULL); - m = g_list_append(m, act); - } -#endif - - if (chu) { - act = purple_menu_action_new(_("Add Private Group"), - PURPLE_CALLBACK(silcpurple_chat_prv), - NULL, NULL); - m = g_list_append(m, act); - } - - if (mode & SILC_CHANNEL_UMODE_CHANFO) { - act = purple_menu_action_new(_("Channel Authentication"), - PURPLE_CALLBACK(silcpurple_chat_chauth), - NULL, NULL); - m = g_list_append(m, act); - - if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) { - act = purple_menu_action_new(_("Reset Permanent"), - PURPLE_CALLBACK(silcpurple_chat_permanent_reset), - NULL, NULL); - m = g_list_append(m, act); - } else { - act = purple_menu_action_new(_("Set Permanent"), - PURPLE_CALLBACK(silcpurple_chat_permanent), - NULL, NULL); - m = g_list_append(m, act); - } - } - - if (mode & SILC_CHANNEL_UMODE_CHANOP) { - act = purple_menu_action_new(_("Set User Limit"), - PURPLE_CALLBACK(silcpurple_chat_ulimit), - NULL, NULL); - m = g_list_append(m, act); - - if (channel->mode & SILC_CHANNEL_MODE_TOPIC) { - act = purple_menu_action_new(_("Reset Topic Restriction"), - PURPLE_CALLBACK(silcpurple_chat_resettopic), - NULL, NULL); - m = g_list_append(m, act); - } else { - act = purple_menu_action_new(_("Set Topic Restriction"), - PURPLE_CALLBACK(silcpurple_chat_settopic), - NULL, NULL); - m = g_list_append(m, act); - } - - if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) { - act = purple_menu_action_new(_("Reset Private Channel"), - PURPLE_CALLBACK(silcpurple_chat_resetprivate), - NULL, NULL); - m = g_list_append(m, act); - } else { - act = purple_menu_action_new(_("Set Private Channel"), - PURPLE_CALLBACK(silcpurple_chat_setprivate), - NULL, NULL); - m = g_list_append(m, act); - } - - if (channel->mode & SILC_CHANNEL_MODE_SECRET) { - act = purple_menu_action_new(_("Reset Secret Channel"), - PURPLE_CALLBACK(silcpurple_chat_resetsecret), - NULL, NULL); - m = g_list_append(m, act); - } else { - act = purple_menu_action_new(_("Set Secret Channel"), - PURPLE_CALLBACK(silcpurple_chat_setsecret), - NULL, NULL); - m = g_list_append(m, act); - } - } - - if (channel) { - SilcPurpleChatWb wb; - wb = silc_calloc(1, sizeof(*wb)); - wb->sg = sg; - wb->channel = channel; - act = purple_menu_action_new(_("Draw On Whiteboard"), - PURPLE_CALLBACK(silcpurple_chat_wb), - (void *)wb, NULL); - m = g_list_append(m, act); - } - - return m; -} - - -/******************************* Joining Etc. ********************************/ - -void silcpurple_chat_join_done(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - SilcChannelEntry channel = context; - PurpleConversation *convo; - SilcUInt32 retry = SILC_PTR_TO_32(channel->context); - SilcHashTableList htl; - SilcChannelUser chu; - GList *users = NULL, *flags = NULL; - char tmp[256]; - - if (!clients && retry < 1) { - /* Resolving users failed, try again. */ - channel->context = SILC_32_TO_PTR(retry + 1); - silc_client_get_clients_by_channel(client, conn, channel, - silcpurple_chat_join_done, channel); - return; - } - - /* Add channel to Purple */ - channel->context = SILC_32_TO_PTR(++sg->channel_ids); - serv_got_joined_chat(gc, sg->channel_ids, channel->channel_name); - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - return; - - /* Add all users to channel */ - silc_hash_table_list(channel->user_list, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - PurpleConvChatBuddyFlags f = PURPLE_CBFLAGS_NONE; - if (!chu->client->nickname) - continue; - chu->context = SILC_32_TO_PTR(sg->channel_ids); - - if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) - f |= PURPLE_CBFLAGS_FOUNDER; - if (chu->mode & SILC_CHANNEL_UMODE_CHANOP) - f |= PURPLE_CBFLAGS_OP; - users = g_list_append(users, g_strdup(chu->client->nickname)); - flags = g_list_append(flags, GINT_TO_POINTER(f)); - - if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) { - if (chu->client == conn->local_entry) - g_snprintf(tmp, sizeof(tmp), - _("You are channel founder on %s"), - channel->channel_name); - else - g_snprintf(tmp, sizeof(tmp), - _("Channel founder on %s is %s"), - channel->channel_name, chu->client->nickname); - - purple_conversation_write(convo, NULL, tmp, - PURPLE_MESSAGE_SYSTEM, time(NULL)); - - } - } - silc_hash_table_list_reset(&htl); - - purple_conv_chat_add_users(PURPLE_CONV_CHAT(convo), users, NULL, flags, FALSE); - g_list_free(users); - g_list_free(flags); - - /* Set topic */ - if (channel->topic) - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, channel->topic); - - /* Set nick */ - purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), conn->local_entry->nickname); -} - -char *silcpurple_get_chat_name(GHashTable *data) -{ - return g_strdup(g_hash_table_lookup(data, "channel")); -} - -void silcpurple_chat_join(PurpleConnection *gc, GHashTable *data) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - const char *channel, *passphrase, *parentch; - - if (!conn) - return; - - channel = g_hash_table_lookup(data, "channel"); - passphrase = g_hash_table_lookup(data, "passphrase"); - - /* Check if we are joining a private group. Handle it - purely locally as it's not a real channel */ - if (strstr(channel, "[Private Group]")) { - SilcChannelEntry channel_entry; - SilcChannelPrivateKey key; - PurpleChat *c; - SilcPurplePrvgrp grp; - - c = purple_blist_find_chat(sg->account, channel); - parentch = purple_blist_node_get_string((PurpleBlistNode *)c, "parentch"); - if (!parentch) - return; - - channel_entry = silc_client_get_channel(sg->client, sg->conn, - (char *)parentch); - if (!channel_entry || - !silc_client_on_channel(channel_entry, sg->conn->local_entry)) { - char tmp[512]; - g_snprintf(tmp, sizeof(tmp), - _("You have to join the %s channel before you are " - "able to join the private group"), parentch); - purple_notify_error(gc, _("Join Private Group"), - _("Cannot join private group"), tmp); - return; - } - - /* Add channel private key */ - if (!silc_client_add_channel_private_key(client, conn, - channel_entry, channel, - NULL, NULL, - (unsigned char *)passphrase, - strlen(passphrase), &key)) - return; - - /* Join the group */ - grp = silc_calloc(1, sizeof(*grp)); - if (!grp) - return; - grp->id = ++sg->channel_ids + SILCPURPLE_PRVGRP; - grp->chid = SILC_PTR_TO_32(channel_entry->context); - grp->parentch = parentch; - grp->channel = channel; - grp->key = key; - sg->grps = g_list_append(sg->grps, grp); - serv_got_joined_chat(gc, grp->id, channel); - return; - } - - /* XXX We should have other properties here as well: - 1. whether to try to authenticate to the channel - 1a. with default key, - 1b. with specific key. - 2. whether to try to authenticate to become founder. - 2a. with default key, - 2b. with specific key. - - Since now such variety is not possible in the join dialog - we always use -founder and -auth options, which try to - do both 1 and 2 with default keys. */ - - /* Call JOIN */ - if ((passphrase != NULL) && (*passphrase != '\0')) - silc_client_command_call(client, conn, NULL, "JOIN", - channel, passphrase, "-auth", "-founder", NULL); - else - silc_client_command_call(client, conn, NULL, "JOIN", - channel, "-auth", "-founder", NULL); -} - -void silcpurple_chat_invite(PurpleConnection *gc, int id, const char *msg, - const char *name) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcHashTableList htl; - SilcChannelUser chu; - gboolean found = FALSE; - - if (!conn) - return; - - /* See if we are inviting on a private group. Invite - to the actual channel */ - if (id > SILCPURPLE_PRVGRP) { - GList *l; - SilcPurplePrvgrp prv; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->id == id) - break; - if (!l) - return; - prv = l->data; - id = prv->chid; - } - - /* Find channel by id */ - silc_hash_table_list(conn->local_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - if (SILC_PTR_TO_32(chu->channel->context) == id ) { - found = TRUE; - break; - } - } - silc_hash_table_list_reset(&htl); - if (!found) - return; - - /* Call INVITE */ - silc_client_command_call(client, conn, NULL, "INVITE", - chu->channel->channel_name, - name, NULL); -} - -void silcpurple_chat_leave(PurpleConnection *gc, int id) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcHashTableList htl; - SilcChannelUser chu; - gboolean found = FALSE; - GList *l; - SilcPurplePrvgrp prv; - - if (!conn) - return; - - /* See if we are leaving a private group */ - if (id > SILCPURPLE_PRVGRP) { - SilcChannelEntry channel; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->id == id) - break; - if (!l) - return; - prv = l->data; - channel = silc_client_get_channel(sg->client, sg->conn, - (char *)prv->parentch); - if (!channel) - return; - silc_client_del_channel_private_key(client, conn, - channel, prv->key); - silc_free(prv); - sg->grps = g_list_remove(sg->grps, prv); - serv_got_chat_left(gc, id); - return; - } - - /* Find channel by id */ - silc_hash_table_list(conn->local_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - if (SILC_PTR_TO_32(chu->channel->context) == id ) { - found = TRUE; - break; - } - } - silc_hash_table_list_reset(&htl); - if (!found) - return; - - /* Call LEAVE */ - silc_client_command_call(client, conn, NULL, "LEAVE", - chu->channel->channel_name, NULL); - - serv_got_chat_left(gc, id); - - /* Leave from private groups on this channel as well */ - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->chid == id) { - prv = l->data; - silc_client_del_channel_private_key(client, conn, - chu->channel, - prv->key); - serv_got_chat_left(gc, prv->id); - silc_free(prv); - sg->grps = g_list_remove(sg->grps, prv); - if (!sg->grps) - break; - } -} - -int silcpurple_chat_send(PurpleConnection *gc, int id, const char *msg, PurpleMessageFlags msgflags) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcHashTableList htl; - SilcChannelUser chu; - SilcChannelEntry channel = NULL; - SilcChannelPrivateKey key = NULL; - SilcUInt32 flags; - int ret; - char *msg2, *tmp; - gboolean found = FALSE; - gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE); - - if (!msg || !conn) - return 0; - - flags = SILC_MESSAGE_FLAG_UTF8; - - tmp = msg2 = purple_unescape_html(msg); - - if (!g_ascii_strncasecmp(msg2, "/me ", 4)) - { - msg2 += 4; - if (!*msg2) { - g_free(tmp); - return 0; - } - flags |= SILC_MESSAGE_FLAG_ACTION; - } else if (strlen(msg) > 1 && msg[0] == '/') { - if (!silc_client_command_call(client, conn, msg + 1)) - purple_notify_error(gc, _("Call Command"), _("Cannot call command"), - _("Unknown command")); - g_free(tmp); - return 0; - } - - - if (sign) - flags |= SILC_MESSAGE_FLAG_SIGNED; - - /* Get the channel private key if we are sending on - private group */ - if (id > SILCPURPLE_PRVGRP) { - GList *l; - SilcPurplePrvgrp prv; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->id == id) - break; - if (!l) { - g_free(tmp); - return 0; - } - prv = l->data; - channel = silc_client_get_channel(sg->client, sg->conn, - (char *)prv->parentch); - if (!channel) { - g_free(tmp); - return 0; - } - key = prv->key; - } - - if (!channel) { - /* Find channel by id */ - silc_hash_table_list(conn->local_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - if (SILC_PTR_TO_32(chu->channel->context) == id ) { - found = TRUE; - break; - } - } - silc_hash_table_list_reset(&htl); - if (!found) { - g_free(tmp); - return 0; - } - channel = chu->channel; - } - - /* Send channel message */ - ret = silc_client_send_channel_message(client, conn, channel, key, - flags, (unsigned char *)msg2, - strlen(msg2), TRUE); - if (ret) { - serv_got_chat_in(gc, id, purple_connection_get_display_name(gc), msgflags, msg, - time(NULL)); - } - g_free(tmp); - - return ret; -} - -void silcpurple_chat_set_topic(PurpleConnection *gc, int id, const char *topic) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcHashTableList htl; - SilcChannelUser chu; - gboolean found = FALSE; - - if (!conn) - return; - - /* See if setting topic on private group. Set it - on the actual channel */ - if (id > SILCPURPLE_PRVGRP) { - GList *l; - SilcPurplePrvgrp prv; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->id == id) - break; - if (!l) - return; - prv = l->data; - id = prv->chid; - } - - /* Find channel by id */ - silc_hash_table_list(conn->local_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - if (SILC_PTR_TO_32(chu->channel->context) == id ) { - found = TRUE; - break; - } - } - silc_hash_table_list_reset(&htl); - if (!found) - return; - - /* Call TOPIC */ - silc_client_command_call(client, conn, NULL, "TOPIC", - chu->channel->channel_name, topic, NULL); -} - -PurpleRoomlist *silcpurple_roomlist_get_list(PurpleConnection *gc) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - GList *fields = NULL; - PurpleRoomlistField *f; - - if (!conn) - return NULL; - - if (sg->roomlist) - purple_roomlist_unref(sg->roomlist); - - sg->roomlist_cancelled = FALSE; - - sg->roomlist = purple_roomlist_new(purple_connection_get_account(gc)); - f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", "channel", TRUE); - fields = g_list_append(fields, f); - f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_INT, - _("Users"), "users", FALSE); - fields = g_list_append(fields, f); - f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, - _("Topic"), "topic", FALSE); - fields = g_list_append(fields, f); - purple_roomlist_set_fields(sg->roomlist, fields); - - /* Call LIST */ - silc_client_command_call(client, conn, "LIST"); - - purple_roomlist_set_in_progress(sg->roomlist, TRUE); - - return sg->roomlist; -} - -void silcpurple_roomlist_cancel(PurpleRoomlist *list) -{ - PurpleConnection *gc = purple_account_get_connection(list->account); - SilcPurple sg; - - if (!gc) - return; - sg = gc->proto_data; - - purple_roomlist_set_in_progress(list, FALSE); - if (sg->roomlist == list) { - purple_roomlist_unref(sg->roomlist); - sg->roomlist = NULL; - sg->roomlist_cancelled = TRUE; - } -} diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc10/ft.c --- a/libpurple/protocols/silc10/ft.c Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,412 +0,0 @@ -/* - - silcpurple_ft.c - - Author: Pekka Riikonen - - Copyright (C) 2004 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#include "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" - -/****************************** File Transfer ********************************/ - -/* This implements the secure file transfer protocol (SFTP) using the SILC - SFTP library implementation. The API we use from the SILC Toolkit is the - SILC Client file transfer API, as it provides a simple file transfer we - need in this case. We could use the SILC SFTP API directly, but it would - be an overkill since we'd effectively re-implement the file transfer what - the SILC Client's file transfer API already provides. - - From Purple we do NOT use the FT API to do the transfer as it is very limiting. - In fact it does not suite to file transfers like SFTP at all. For example, - it assumes that read operations are synchronous what they are not in SFTP. - It also assumes that the file transfer socket is to be handled by the Purple - eventloop, and this naturally is something we don't want to do in case of - SILC Toolkit. The FT API suites well to purely stream based file transfers - like HTTP GET and similar. - - For this reason, we directly access the Purple GKT FT API and hack the FT - API to merely provide the user interface experience and all the magic - is done in the SILC Toolkit. Ie. we update the statistics information in - the FT API for user interface, and that's it. A bit dirty but until the - FT API gets better this is the way to go. Good thing that FT API allowed - us to do this. */ - -typedef struct { - SilcPurple sg; - SilcClientEntry client_entry; - SilcUInt32 session_id; - char *hostname; - SilcUInt16 port; - PurpleXfer *xfer; - - SilcClientFileName completion; - void *completion_context; -} *SilcPurpleXfer; - -static void -silcpurple_ftp_monitor(SilcClient client, - SilcClientConnection conn, - SilcClientMonitorStatus status, - SilcClientFileError error, - SilcUInt64 offset, - SilcUInt64 filesize, - SilcClientEntry client_entry, - SilcUInt32 session_id, - const char *filepath, - void *context) -{ - SilcPurpleXfer xfer = context; - PurpleConnection *gc = xfer->sg->gc; - char tmp[256]; - - if (status == SILC_CLIENT_FILE_MONITOR_CLOSED) { - purple_xfer_unref(xfer->xfer); - silc_free(xfer); - return; - } - - if (status == SILC_CLIENT_FILE_MONITOR_KEY_AGREEMENT) - return; - - if (status == SILC_CLIENT_FILE_MONITOR_ERROR) { - if (error == SILC_CLIENT_FILE_NO_SUCH_FILE) { - g_snprintf(tmp, sizeof(tmp), "No such file %s", - filepath ? filepath : "[N/A]"); - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), tmp); - } else if (error == SILC_CLIENT_FILE_PERMISSION_DENIED) { - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), - _("Permission denied")); - } else if (error == SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED) { - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), - _("Key agreement failed")); - } else if (error == SILC_CLIENT_FILE_UNKNOWN_SESSION) { - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), - _("File transfer session does not exist")); - } else { - purple_notify_error(gc, _("Secure File Transfer"), - _("Error during file transfer"), NULL); - } - silc_client_file_close(client, conn, session_id); - purple_xfer_unref(xfer->xfer); - silc_free(xfer); - return; - } - - /* Update file transfer UI */ - if (!offset && filesize) - purple_xfer_set_size(xfer->xfer, filesize); - if (offset && filesize) { - xfer->xfer->bytes_sent = offset; - xfer->xfer->bytes_remaining = filesize - offset; - } - purple_xfer_update_progress(xfer->xfer); - - if (status == SILC_CLIENT_FILE_MONITOR_SEND || - status == SILC_CLIENT_FILE_MONITOR_RECEIVE) { - if (offset == filesize) { - /* Download finished */ - purple_xfer_set_completed(xfer->xfer, TRUE); - silc_client_file_close(client, conn, session_id); - } - } -} - -static void -silcpurple_ftp_cancel(PurpleXfer *x) -{ - SilcPurpleXfer xfer = x->data; - xfer->xfer->status = PURPLE_XFER_STATUS_CANCEL_LOCAL; - purple_xfer_update_progress(xfer->xfer); - silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); -} - -static void -silcpurple_ftp_ask_name_cancel(PurpleXfer *x) -{ - SilcPurpleXfer xfer = x->data; - - /* Cancel the transmission */ - xfer->completion(NULL, xfer->completion_context); - silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); -} - -static void -silcpurple_ftp_ask_name_ok(PurpleXfer *x) -{ - SilcPurpleXfer xfer = x->data; - const char *name; - - name = purple_xfer_get_local_filename(x); - g_unlink(name); - xfer->completion(name, xfer->completion_context); -} - -static void -silcpurple_ftp_ask_name(SilcClient client, - SilcClientConnection conn, - SilcUInt32 session_id, - const char *remote_filename, - SilcClientFileName completion, - void *completion_context, - void *context) -{ - SilcPurpleXfer xfer = context; - - xfer->completion = completion; - xfer->completion_context = completion_context; - - purple_xfer_set_init_fnc(xfer->xfer, silcpurple_ftp_ask_name_ok); - purple_xfer_set_request_denied_fnc(xfer->xfer, silcpurple_ftp_ask_name_cancel); - - /* Request to save the file */ - purple_xfer_set_filename(xfer->xfer, remote_filename); - purple_xfer_request(xfer->xfer); -} - -static void -silcpurple_ftp_request_result(PurpleXfer *x) -{ - SilcPurpleXfer xfer = x->data; - SilcClientFileError status; - PurpleConnection *gc = xfer->sg->gc; - - if (purple_xfer_get_status(x) != PURPLE_XFER_STATUS_ACCEPTED) - return; - - /* Start the file transfer */ - status = silc_client_file_receive(xfer->sg->client, xfer->sg->conn, - silcpurple_ftp_monitor, xfer, - NULL, xfer->session_id, - silcpurple_ftp_ask_name, xfer); - switch (status) { - case SILC_CLIENT_FILE_OK: - return; - break; - - case SILC_CLIENT_FILE_UNKNOWN_SESSION: - purple_notify_error(gc, _("Secure File Transfer"), - _("No file transfer session active"), NULL); - break; - - case SILC_CLIENT_FILE_ALREADY_STARTED: - purple_notify_error(gc, _("Secure File Transfer"), - _("File transfer already started"), NULL); - break; - - case SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED: - purple_notify_error(gc, _("Secure File Transfer"), - _("Could not perform key agreement for file transfer"), - NULL); - break; - - default: - purple_notify_error(gc, _("Secure File Transfer"), - _("Could not start the file transfer"), NULL); - break; - } - - /* Error */ - purple_xfer_unref(xfer->xfer); - g_free(xfer->hostname); - silc_free(xfer); -} - -static void -silcpurple_ftp_request_denied(PurpleXfer *x) -{ - -} - -void silcpurple_ftp_request(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, SilcUInt32 session_id, - const char *hostname, SilcUInt16 port) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - SilcPurpleXfer xfer; - - xfer = silc_calloc(1, sizeof(*xfer)); - if (!xfer) { - silc_client_file_close(sg->client, sg->conn, session_id); - return; - } - - xfer->sg = sg; - xfer->client_entry = client_entry; - xfer->session_id = session_id; - xfer->hostname = g_strdup(hostname); - xfer->port = port; - xfer->xfer = purple_xfer_new(xfer->sg->account, PURPLE_XFER_RECEIVE, - xfer->client_entry->nickname); - if (!xfer->xfer) { - silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); - g_free(xfer->hostname); - silc_free(xfer); - return; - } - purple_xfer_set_init_fnc(xfer->xfer, silcpurple_ftp_request_result); - purple_xfer_set_request_denied_fnc(xfer->xfer, silcpurple_ftp_request_denied); - purple_xfer_set_cancel_recv_fnc(xfer->xfer, silcpurple_ftp_cancel); - xfer->xfer->remote_ip = g_strdup(hostname); - xfer->xfer->remote_port = port; - xfer->xfer->data = xfer; - - /* File transfer request */ - purple_xfer_request(xfer->xfer); -} - -static void -silcpurple_ftp_send_cancel(PurpleXfer *x) -{ - SilcPurpleXfer xfer = x->data; - silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); - purple_xfer_unref(xfer->xfer); - g_free(xfer->hostname); - silc_free(xfer); -} - -static void -silcpurple_ftp_send(PurpleXfer *x) -{ - SilcPurpleXfer xfer = x->data; - const char *name; - char *local_ip = NULL, *remote_ip = NULL; - gboolean local = TRUE; - - name = purple_xfer_get_local_filename(x); - - /* Do the same magic what we do with key agreement (see silcpurple_buddy.c) - to see if we are behind NAT. */ - if (silc_net_check_local_by_sock(xfer->sg->conn->sock->sock, - NULL, &local_ip)) { - /* Check if the IP is private */ - if (silcpurple_ip_is_private(local_ip)) { - local = FALSE; - /* Local IP is private, resolve the remote server IP to see whether - we are talking to Internet or just on LAN. */ - if (silc_net_check_host_by_sock(xfer->sg->conn->sock->sock, NULL, - &remote_ip)) - if (silcpurple_ip_is_private(remote_ip)) - /* We assume we are in LAN. Let's provide the connection point. */ - local = TRUE; - } - } - - if (local && !local_ip) - local_ip = silc_net_localip(); - - /* Send the file */ - silc_client_file_send(xfer->sg->client, xfer->sg->conn, - silcpurple_ftp_monitor, xfer, - local_ip, 0, !local, xfer->client_entry, - name, &xfer->session_id); - - silc_free(local_ip); - silc_free(remote_ip); -} - -static void -silcpurple_ftp_send_file_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - PurpleConnection *gc = client->application; - char tmp[256]; - - if (!clients) { - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), - (const char *)context); - purple_notify_error(gc, _("Secure File Transfer"), - _("Cannot send file"), tmp); - silc_free(context); - return; - } - - silcpurple_ftp_send_file(client->application, (const char *)context, NULL); - silc_free(context); -} - -PurpleXfer *silcpurple_ftp_new_xfer(PurpleConnection *gc, const char *name) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientEntry *clients; - SilcUInt32 clients_count; - SilcPurpleXfer xfer; - char *nickname; - - g_return_val_if_fail(name != NULL, NULL); - - if (!silc_parse_userfqdn(name, &nickname, NULL)) - return NULL; - - /* Find client entry */ - clients = silc_client_get_clients_local(client, conn, nickname, name, - &clients_count); - if (!clients) { - silc_client_get_clients(client, conn, nickname, NULL, - silcpurple_ftp_send_file_resolved, - strdup(name)); - silc_free(nickname); - return NULL; - } - - xfer = silc_calloc(1, sizeof(*xfer)); - - g_return_val_if_fail(xfer != NULL, NULL); - - xfer->sg = sg; - xfer->client_entry = clients[0]; - xfer->xfer = purple_xfer_new(xfer->sg->account, PURPLE_XFER_SEND, - xfer->client_entry->nickname); - if (!xfer->xfer) { - silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); - g_free(xfer->hostname); - silc_free(xfer); - return NULL; - } - purple_xfer_set_init_fnc(xfer->xfer, silcpurple_ftp_send); - purple_xfer_set_request_denied_fnc(xfer->xfer, silcpurple_ftp_request_denied); - purple_xfer_set_cancel_send_fnc(xfer->xfer, silcpurple_ftp_send_cancel); - xfer->xfer->data = xfer; - - silc_free(clients); - silc_free(nickname); - - return xfer->xfer; -} - -void silcpurple_ftp_send_file(PurpleConnection *gc, const char *name, const char *file) -{ - PurpleXfer *xfer = silcpurple_ftp_new_xfer(gc, name); - - g_return_if_fail(xfer != NULL); - - /* Choose file to send */ - if (file) - purple_xfer_request_accepted(xfer, file); - else - purple_xfer_request(xfer); -} diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc10/ops.c --- a/libpurple/protocols/silc10/ops.c Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2063 +0,0 @@ -/* - - silcpurple_ops.c - - Author: Pekka Riikonen - - Copyright (C) 2004 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#include "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" -#include "imgstore.h" -#include "wb.h" - -static void -silc_channel_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcChannelEntry channel, - SilcMessagePayload payload, SilcChannelPrivateKey key, - SilcMessageFlags flags, const unsigned char *message, - SilcUInt32 message_len); -static void -silc_private_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcMessagePayload payload, - SilcMessageFlags flags, const unsigned char *message, - SilcUInt32 message_len); - -/* Message sent to the application by library. `conn' associates the - message to a specific connection. `conn', however, may be NULL. - The `type' indicates the type of the message sent by the library. - The application can for example filter the message according the - type. */ - -static void -silc_say(SilcClient client, SilcClientConnection conn, - SilcClientMessageType type, char *msg, ...) -{ - /* Nothing */ -} - -#ifdef HAVE_SILCMIME_H -/* Processes incoming MIME message. Can be private message or channel - message. */ - -static void -silcpurple_mime_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcChannelEntry channel, - SilcMessagePayload payload, SilcChannelPrivateKey key, - SilcMessageFlags flags, SilcMime mime, - gboolean recursive) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - const char *type; - const unsigned char *data; - SilcUInt32 data_len; - PurpleMessageFlags cflags = 0; - PurpleConversation *convo = NULL; - - if (!mime) - return; - - /* Check for fragmented MIME message */ - if (silc_mime_is_partial(mime)) { - if (!sg->mimeass) - sg->mimeass = silc_mime_assembler_alloc(); - - /* Defragment */ - mime = silc_mime_assemble(sg->mimeass, mime); - if (!mime) - /* More fragments to come */ - return; - - /* Process the complete message */ - silcpurple_mime_message(client, conn, sender, channel, - payload, key, flags, mime, FALSE); - return; - } - - /* Check for multipart message */ - if (silc_mime_is_multipart(mime)) { - SilcMime p; - const char *mtype; - SilcDList parts = silc_mime_get_multiparts(mime, &mtype); - - /* Only "mixed" type supported */ - if (strcmp(mtype, "mixed")) - goto out; - - silc_dlist_start(parts); - while ((p = silc_dlist_get(parts)) != SILC_LIST_END) { - /* Recursively process parts */ - silcpurple_mime_message(client, conn, sender, channel, - payload, key, flags, p, TRUE); - } - goto out; - } - - /* Get content type and MIME data */ - type = silc_mime_get_field(mime, "Content-Type"); - if (!type) - goto out; - data = silc_mime_get_data(mime, &data_len); - if (!data) - goto out; - - /* Process according to content type */ - - /* Plain text */ - if (strstr(type, "text/plain")) { - /* Default is UTF-8, don't check for other charsets */ - if (!strstr(type, "utf-8")) - goto out; - - if (channel) - silc_channel_message(client, conn, sender, channel, - payload, key, - SILC_MESSAGE_FLAG_UTF8, data, - data_len); - else - silc_private_message(client, conn, sender, payload, - SILC_MESSAGE_FLAG_UTF8, data, - data_len); - goto out; - } - - /* Image */ - if (strstr(type, "image/png") || - strstr(type, "image/jpeg") || - strstr(type, "image/gif") || - strstr(type, "image/tiff")) { - char tmp[32]; - int imgid; - - /* Get channel convo (if message is for channel) */ - if (key && channel) { - GList *l; - SilcPurplePrvgrp prv; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->key == key) { - prv = l->data; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - prv->channel, sg->account); - break; - } - } - if (channel && !convo) - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (channel && !convo) - goto out; - - 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), "", imgid); - - if (channel) - serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), - sender->nickname ? - sender->nickname : - "", cflags, - tmp, time(NULL)); - else - serv_got_im(gc, sender->nickname ? - sender->nickname : "", - tmp, cflags, time(NULL)); - - purple_imgstore_unref_by_id(imgid); - cflags = 0; - } - goto out; - } - - /* Whiteboard message */ - if (strstr(type, "application/x-wb") && - !purple_account_get_bool(sg->account, "block-wb", FALSE)) { - if (channel) - silcpurple_wb_receive_ch(client, conn, sender, channel, - payload, flags, data, data_len); - else - silcpurple_wb_receive(client, conn, sender, payload, - flags, data, data_len); - goto out; - } - - out: - if (!recursive) - silc_mime_free(mime); -} -#endif /* HAVE_SILCMIME_H */ - -/* Message for a channel. The `sender' is the sender of the message - The `channel' is the channel. The `message' is the message. Note - that `message' maybe NULL. The `flags' indicates message flags - and it is used to determine how the message can be interpreted - (like it may tell the message is multimedia message). */ - -static void -silc_channel_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcChannelEntry channel, - SilcMessagePayload payload, SilcChannelPrivateKey key, - SilcMessageFlags flags, const unsigned char *message, - SilcUInt32 message_len) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - PurpleConversation *convo = NULL; - char *msg, *tmp; - - if (!message) - return; - - if (key) { - GList *l; - SilcPurplePrvgrp prv; - - for (l = sg->grps; l; l = l->next) - if (((SilcPurplePrvgrp)l->data)->key == key) { - prv = l->data; - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - prv->channel, sg->account); - break; - } - } - if (!convo) - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - return; - - if (flags & SILC_MESSAGE_FLAG_SIGNED && - purple_account_get_bool(sg->account, "sign-verify", FALSE)) { - /* XXX */ - } - - if (flags & SILC_MESSAGE_FLAG_DATA) { - /* Process MIME message */ -#ifdef HAVE_SILCMIME_H - SilcMime mime; - mime = silc_mime_decode(message, message_len); - silcpurple_mime_message(client, conn, sender, channel, payload, - key, flags, mime, FALSE); -#else - char type[128], enc[128]; - unsigned char *data; - SilcUInt32 data_len; - - memset(type, 0, sizeof(type)); - memset(enc, 0, sizeof(enc)); - - if (!silc_mime_parse(message, message_len, NULL, 0, - type, sizeof(type) - 1, enc, sizeof(enc) - 1, &data, - &data_len)) - return; - - if (!strcmp(type, "application/x-wb") && - !strcmp(enc, "binary") && - !purple_account_get_bool(sg->account, "block-wb", FALSE)) - silcpurple_wb_receive_ch(client, conn, sender, channel, - payload, flags, data, data_len); -#endif - return; - } - - if (flags & SILC_MESSAGE_FLAG_ACTION) { - msg = g_strdup_printf("/me %s", - (const char *)message); - if (!msg) - return; - - tmp = g_markup_escape_text(msg, -1); - /* Send to Purple */ - serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), - sender->nickname ? - sender->nickname : "", 0, - tmp, time(NULL)); - g_free(tmp); - g_free(msg); - return; - } - - if (flags & SILC_MESSAGE_FLAG_NOTICE) { - msg = g_strdup_printf("(notice) %s %s", - sender->nickname ? - sender->nickname : "", - (const char *)message); - if (!msg) - return; - - /* Send to Purple */ - purple_conversation_write(convo, NULL, (const char *)msg, - PURPLE_MESSAGE_SYSTEM, time(NULL)); - g_free(msg); - return; - } - - if (flags & SILC_MESSAGE_FLAG_UTF8) { - tmp = g_markup_escape_text((const char *)message, -1); - /* Send to Purple */ - serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)), - sender->nickname ? - sender->nickname : "", 0, - tmp, time(NULL)); - g_free(tmp); - } -} - - -/* Private message to the client. The `sender' is the sender of the - message. The message is `message'and maybe NULL. The `flags' - indicates message flags and it is used to determine how the message - can be interpreted (like it may tell the message is multimedia - message). */ - -static void -silc_private_message(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcMessagePayload payload, - SilcMessageFlags flags, const unsigned char *message, - SilcUInt32 message_len) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - PurpleConversation *convo = NULL; - char *msg, *tmp; - - if (!message) - return; - - if (sender->nickname) - /* XXX - Should this be PURPLE_CONV_TYPE_IM? */ - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, - sender->nickname, sg->account); - - if (flags & SILC_MESSAGE_FLAG_SIGNED && - purple_account_get_bool(sg->account, "sign-verify", FALSE)) { - /* XXX */ - } - - if (flags & SILC_MESSAGE_FLAG_DATA) { -#ifdef HAVE_SILCMIME_H - /* Process MIME message */ - SilcMime mime; - mime = silc_mime_decode(message, message_len); - silcpurple_mime_message(client, conn, sender, NULL, payload, - NULL, flags, mime, FALSE); -#else - char type[128], enc[128]; - unsigned char *data; - SilcUInt32 data_len; - - memset(type, 0, sizeof(type)); - memset(enc, 0, sizeof(enc)); - - if (!silc_mime_parse(message, message_len, NULL, 0, - type, sizeof(type) - 1, enc, sizeof(enc) - 1, &data, - &data_len)) - return; - - if (!strcmp(type, "application/x-wb") && - !strcmp(enc, "binary") && - !purple_account_get_bool(sg->account, "block-wb", FALSE)) - silcpurple_wb_receive(client, conn, sender, payload, - flags, data, data_len); -#endif - return; - } - - if (flags & SILC_MESSAGE_FLAG_ACTION && convo) { - msg = g_strdup_printf("/me %s", - (const char *)message); - if (!msg) - return; - - tmp = g_markup_escape_text(msg, -1); - /* Send to Purple */ - serv_got_im(gc, sender->nickname ? - sender->nickname : "", - tmp, 0, time(NULL)); - g_free(msg); - g_free(tmp); - return; - } - - if (flags & SILC_MESSAGE_FLAG_NOTICE && convo) { - msg = g_strdup_printf("(notice) %s %s", - sender->nickname ? - sender->nickname : "", - (const char *)message); - if (!msg) - return; - - /* Send to Purple */ - purple_conversation_write(convo, NULL, (const char *)msg, - PURPLE_MESSAGE_SYSTEM, time(NULL)); - g_free(msg); - return; - } - - if (flags & SILC_MESSAGE_FLAG_UTF8) { - tmp = g_markup_escape_text((const char *)message, -1); - /* Send to Purple */ - serv_got_im(gc, sender->nickname ? - sender->nickname : "", - tmp, 0, time(NULL)); - g_free(tmp); - } -} - - -/* Notify message to the client. The notify arguments are sent in the - same order as servers sends them. The arguments are same as received - from the server except for ID's. If ID is received application receives - the corresponding entry to the ID. For example, if Client ID is received - application receives SilcClientEntry. Also, if the notify type is - for channel the channel entry is sent to application (even if server - does not send it because client library gets the channel entry from - the Channel ID in the packet's header). */ - -static void -silc_notify(SilcClient client, SilcClientConnection conn, - SilcNotifyType type, ...) -{ - va_list va; - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - PurpleConversation *convo; - SilcClientEntry client_entry, client_entry2; - SilcChannelEntry channel; - SilcServerEntry server_entry; - SilcIdType idtype; - void *entry; - SilcUInt32 mode; - SilcHashTableList htl; - SilcChannelUser chu; - char buf[512], buf2[512], *tmp, *name; - SilcNotifyType notify; - PurpleBuddy *b; - int i; - - va_start(va, type); - memset(buf, 0, sizeof(buf)); - - switch (type) { - - case SILC_NOTIFY_TYPE_NONE: - break; - - case SILC_NOTIFY_TYPE_INVITE: - { - GHashTable *components; - va_arg(va, SilcChannelEntry); - name = va_arg(va, char *); - client_entry = va_arg(va, SilcClientEntry); - - components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - g_hash_table_insert(components, strdup("channel"), strdup(name)); - serv_got_chat_invite(gc, name, client_entry->nickname, NULL, components); - } - break; - - case SILC_NOTIFY_TYPE_JOIN: - client_entry = va_arg(va, SilcClientEntry); - channel = va_arg(va, SilcChannelEntry); - - /* If we joined channel, do nothing */ - if (client_entry == conn->local_entry) - break; - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - break; - - /* Join user to channel */ - g_snprintf(buf, sizeof(buf), "%s@%s", - client_entry->username, client_entry->hostname); - purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo), - g_strdup(client_entry->nickname), buf, PURPLE_CBFLAGS_NONE, TRUE); - - break; - - case SILC_NOTIFY_TYPE_LEAVE: - client_entry = va_arg(va, SilcClientEntry); - channel = va_arg(va, SilcChannelEntry); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - break; - - /* Remove user from channel */ - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), - client_entry->nickname, NULL); - - break; - - case SILC_NOTIFY_TYPE_SIGNOFF: - client_entry = va_arg(va, SilcClientEntry); - tmp = va_arg(va, char *); - - if (!client_entry->nickname) - break; - - /* Remove from all channels */ - silc_hash_table_list(client_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - chu->channel->channel_name, sg->account); - if (!convo) - continue; - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), - client_entry->nickname, - tmp); - } - silc_hash_table_list_reset(&htl); - - break; - - case SILC_NOTIFY_TYPE_TOPIC_SET: - { - char *esc, *tmp2; - idtype = va_arg(va, int); - entry = va_arg(va, void *); - tmp = va_arg(va, char *); - channel = va_arg(va, SilcChannelEntry); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - break; - - if (!tmp) - break; - - esc = g_markup_escape_text(tmp, -1); - tmp2 = purple_markup_linkify(esc); - g_free(esc); - - if (idtype == SILC_ID_CLIENT) { - client_entry = (SilcClientEntry)entry; - g_snprintf(buf, sizeof(buf), - _("%s has changed the topic of %s to: %s"), - client_entry->nickname, channel->channel_name, tmp2); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), - client_entry->nickname, tmp); - } else if (idtype == SILC_ID_SERVER) { - server_entry = (SilcServerEntry)entry; - g_snprintf(buf, sizeof(buf), - _("%s has changed the topic of %s to: %s"), - server_entry->server_name, channel->channel_name, tmp2); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), server_entry->server_name, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), - server_entry->server_name, tmp); - } else if (idtype == SILC_ID_CHANNEL) { - channel = (SilcChannelEntry)entry; - g_snprintf(buf, sizeof(buf), - _("%s has changed the topic of %s to: %s"), - channel->channel_name, channel->channel_name, tmp2); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), - channel->channel_name, tmp); - } else { - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, tmp); - } - - g_free(tmp2); - - break; - - } - case SILC_NOTIFY_TYPE_NICK_CHANGE: - client_entry = va_arg(va, SilcClientEntry); - client_entry2 = va_arg(va, SilcClientEntry); - - if (!strcmp(client_entry->nickname, client_entry2->nickname)) - break; - - /* Change nick on all channels */ - silc_hash_table_list(client_entry2->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - chu->channel->channel_name, sg->account); - if (!convo) - continue; - if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(convo), client_entry->nickname)) - purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo), - client_entry->nickname, - client_entry2->nickname); - } - silc_hash_table_list_reset(&htl); - - break; - - case SILC_NOTIFY_TYPE_CMODE_CHANGE: - idtype = va_arg(va, int); - entry = va_arg(va, void *); - mode = va_arg(va, SilcUInt32); - (void)va_arg(va, char *); - (void)va_arg(va, char *); - (void)va_arg(va, char *); - (void)va_arg(va, SilcPublicKey); - (void)va_arg(va, SilcBuffer); - channel = va_arg(va, SilcChannelEntry); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - break; - - if (idtype == SILC_ID_CLIENT) - name = ((SilcClientEntry)entry)->nickname; - else if (idtype == SILC_ID_SERVER) - name = ((SilcServerEntry)entry)->server_name; - else - name = ((SilcChannelEntry)entry)->channel_name; - if (!name) - break; - - if (mode) { - silcpurple_get_chmode_string(mode, buf2, sizeof(buf2)); - g_snprintf(buf, sizeof(buf), - _("%s set channel %s modes to: %s"), name, - channel->channel_name, buf2); - } else { - g_snprintf(buf, sizeof(buf), - _("%s removed all channel %s modes"), name, - channel->channel_name); - } - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - break; - - case SILC_NOTIFY_TYPE_CUMODE_CHANGE: - { - PurpleConvChatBuddyFlags flags = PURPLE_CBFLAGS_NONE; - idtype = va_arg(va, int); - entry = va_arg(va, void *); - mode = va_arg(va, SilcUInt32); - client_entry2 = va_arg(va, SilcClientEntry); - channel = va_arg(va, SilcChannelEntry); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - break; - - if (idtype == SILC_ID_CLIENT) - name = ((SilcClientEntry)entry)->nickname; - else if (idtype == SILC_ID_SERVER) - name = ((SilcServerEntry)entry)->server_name; - else - name = ((SilcChannelEntry)entry)->channel_name; - if (!name) - break; - - if (mode) { - silcpurple_get_chumode_string(mode, buf2, sizeof(buf2)); - g_snprintf(buf, sizeof(buf), - _("%s set %s's modes to: %s"), name, - client_entry2->nickname, buf2); - if (mode & SILC_CHANNEL_UMODE_CHANFO) - flags |= PURPLE_CBFLAGS_FOUNDER; - if (mode & SILC_CHANNEL_UMODE_CHANOP) - flags |= PURPLE_CBFLAGS_OP; - } else { - g_snprintf(buf, sizeof(buf), - _("%s removed all %s's modes"), name, - client_entry2->nickname); - } - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(convo), client_entry2->nickname, flags); - break; - } - - case SILC_NOTIFY_TYPE_MOTD: - tmp = va_arg(va, char *); - silc_free(sg->motd); - sg->motd = silc_memdup(tmp, strlen(tmp)); - break; - - case SILC_NOTIFY_TYPE_KICKED: - client_entry = va_arg(va, SilcClientEntry); - tmp = va_arg(va, char *); - client_entry2 = va_arg(va, SilcClientEntry); - channel = va_arg(va, SilcChannelEntry); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) - break; - - if (client_entry == conn->local_entry) { - /* Remove us from channel */ - g_snprintf(buf, sizeof(buf), - _("You have been kicked off %s by %s (%s)"), - channel->channel_name, client_entry2->nickname, - tmp ? tmp : ""); - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo))); - } else { - /* Remove user from channel */ - g_snprintf(buf, sizeof(buf), _("Kicked by %s (%s)"), - client_entry2->nickname, tmp ? tmp : ""); - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), - client_entry->nickname, - buf); - } - - break; - - case SILC_NOTIFY_TYPE_KILLED: - client_entry = va_arg(va, SilcClientEntry); - tmp = va_arg(va, char *); - idtype = va_arg(va, int); - entry = va_arg(va, SilcClientEntry); - - if (!client_entry->nickname) - break; - - if (client_entry == conn->local_entry) { - if (idtype == SILC_ID_CLIENT) { - client_entry2 = (SilcClientEntry)entry; - g_snprintf(buf, sizeof(buf), - _("You have been killed by %s (%s)"), - client_entry2->nickname, tmp ? tmp : ""); - } else if (idtype == SILC_ID_SERVER) { - server_entry = (SilcServerEntry)entry; - g_snprintf(buf, sizeof(buf), - _("You have been killed by %s (%s)"), - server_entry->server_name, tmp ? tmp : ""); - } else if (idtype == SILC_ID_CHANNEL) { - channel = (SilcChannelEntry)entry; - g_snprintf(buf, sizeof(buf), - _("You have been killed by %s (%s)"), - channel->channel_name, tmp ? tmp : ""); - } - - /* Remove us from all channels */ - silc_hash_table_list(client_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - chu->channel->channel_name, sg->account); - if (!convo) - continue; - purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname, - buf, PURPLE_MESSAGE_SYSTEM, time(NULL)); - serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo))); - } - silc_hash_table_list_reset(&htl); - - } else { - if (idtype == SILC_ID_CLIENT) { - client_entry2 = (SilcClientEntry)entry; - g_snprintf(buf, sizeof(buf), - _("Killed by %s (%s)"), - client_entry2->nickname, tmp ? tmp : ""); - } else if (idtype == SILC_ID_SERVER) { - server_entry = (SilcServerEntry)entry; - g_snprintf(buf, sizeof(buf), - _("Killed by %s (%s)"), - server_entry->server_name, tmp ? tmp : ""); - } else if (idtype == SILC_ID_CHANNEL) { - channel = (SilcChannelEntry)entry; - g_snprintf(buf, sizeof(buf), - _("Killed by %s (%s)"), - channel->channel_name, tmp ? tmp : ""); - } - - /* Remove user from all channels */ - silc_hash_table_list(client_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - chu->channel->channel_name, sg->account); - if (!convo) - continue; - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), - client_entry->nickname, tmp); - } - silc_hash_table_list_reset(&htl); - } - - break; - - case SILC_NOTIFY_TYPE_CHANNEL_CHANGE: - break; - - case SILC_NOTIFY_TYPE_SERVER_SIGNOFF: - { - int i; - SilcClientEntry *clients; - SilcUInt32 clients_count; - - (void)va_arg(va, void *); - clients = va_arg(va, SilcClientEntry *); - clients_count = va_arg(va, SilcUInt32); - - for (i = 0; i < clients_count; i++) { - if (!clients[i]->nickname) - break; - - /* Remove from all channels */ - silc_hash_table_list(clients[i]->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = - purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - chu->channel->channel_name, sg->account); - if (!convo) - continue; - purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), - clients[i]->nickname, - _("Server signoff")); - } - silc_hash_table_list_reset(&htl); - } - } - break; - - case SILC_NOTIFY_TYPE_ERROR: - { - SilcStatus error = va_arg(va, int); - purple_notify_error(gc, "Error Notify", - silc_get_status_message(error), - NULL); - } - break; - - case SILC_NOTIFY_TYPE_WATCH: - { - SilcPublicKey public_key; - unsigned char *pk; - SilcUInt32 pk_len; - char *fingerprint; - - client_entry = va_arg(va, SilcClientEntry); - (void)va_arg(va, char *); - mode = va_arg(va, SilcUInt32); - notify = va_arg(va, int); - public_key = va_arg(va, SilcPublicKey); - - b = NULL; - if (public_key) { - PurpleBlistNode *gnode, *cnode, *bnode; - const char *f; - - pk = silc_pkcs_public_key_encode(public_key, &pk_len); - if (!pk) - break; - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - for (i = 0; i < strlen(fingerprint); i++) - if (fingerprint[i] == ' ') - fingerprint[i] = '_'; - g_snprintf(buf, sizeof(buf) - 1, - "%s" G_DIR_SEPARATOR_S "clientkeys" - G_DIR_SEPARATOR_S "clientkey_%s.pub", - silcpurple_silcdir(), fingerprint); - silc_free(fingerprint); - silc_free(pk); - - /* Find buddy by associated public key */ - for (gnode = purple_get_blist()->root; gnode; - gnode = gnode->next) { - if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) - continue; - for (cnode = gnode->child; cnode; cnode = cnode->next) { - if( !PURPLE_BLIST_NODE_IS_CONTACT(cnode)) - continue; - for (bnode = cnode->child; bnode; - bnode = bnode->next) { - if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) - continue; - b = (PurpleBuddy *)bnode; - if (b->account != gc->account) - continue; - f = purple_blist_node_get_string(bnode, "public-key"); - if (f && !strcmp(f, buf)) - goto cont; - b = NULL; - } - } - } - } - cont: - if (!b) { - /* Find buddy by nickname */ - b = purple_find_buddy(sg->account, client_entry->nickname); - if (!b) { - purple_debug_warning("silc", "WATCH for %s, unknown buddy\n", - client_entry->nickname); - break; - } - } - - silc_free(b->proto_data); - b->proto_data = silc_memdup(client_entry->id, - sizeof(*client_entry->id)); - if (notify == SILC_NOTIFY_TYPE_NICK_CHANGE) { - break; - } else if (notify == SILC_NOTIFY_TYPE_UMODE_CHANGE) { - /* See if client was away and is now present */ - if (!(mode & (SILC_UMODE_GONE | SILC_UMODE_INDISPOSED | - SILC_UMODE_BUSY | SILC_UMODE_PAGE | - SILC_UMODE_DETACHED)) && - (client_entry->mode & SILC_UMODE_GONE || - client_entry->mode & SILC_UMODE_INDISPOSED || - client_entry->mode & SILC_UMODE_BUSY || - client_entry->mode & SILC_UMODE_PAGE || - client_entry->mode & SILC_UMODE_DETACHED)) { - client_entry->mode = mode; - purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL); - } - else if ((mode & SILC_UMODE_GONE) || - (mode & SILC_UMODE_INDISPOSED) || - (mode & SILC_UMODE_BUSY) || - (mode & SILC_UMODE_PAGE) || - (mode & SILC_UMODE_DETACHED)) { - client_entry->mode = mode; - purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_OFFLINE, NULL); - } - } else if (notify == SILC_NOTIFY_TYPE_SIGNOFF || - notify == SILC_NOTIFY_TYPE_SERVER_SIGNOFF || - notify == SILC_NOTIFY_TYPE_KILLED) { - client_entry->mode = mode; - purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_OFFLINE, NULL); - } else if (notify == SILC_NOTIFY_TYPE_NONE) { - client_entry->mode = mode; - purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL); - } - } - break; - - default: - purple_debug_info("silc", "Unhandled notification: %d\n", type); - break; - } - - va_end(va); -} - - -/* Command handler. This function is called always in the command function. - If error occurs it will be called as well. `conn' is the associated - client connection. `cmd_context' is the command context that was - originally sent to the command. `success' is FALSE if error occurred - during command. `command' is the command being processed. It must be - noted that this is not reply from server. This is merely called just - after application has called the command. Just to tell application - that the command really was processed. */ - -static void -silc_command(SilcClient client, SilcClientConnection conn, - SilcClientCommandContext cmd_context, bool success, - SilcCommand command, SilcStatus status) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - - switch (command) { - - case SILC_COMMAND_CMODE: - if (cmd_context->argc == 3 && - !strcmp((char *)cmd_context->argv[2], "+C")) - sg->chpk = TRUE; - else - sg->chpk = FALSE; - break; - - default: - break; - } -} - -#if 0 -static void -silcpurple_whois_more(SilcClientEntry client_entry, gint id) -{ - SilcAttributePayload attr; - SilcAttribute attribute; - char *buf; - GString *s; - SilcVCardStruct vcard; - int i; - - if (id != 0) - return; - - memset(&vcard, 0, sizeof(vcard)); - - s = g_string_new(""); - - silc_dlist_start(client_entry->attrs); - while ((attr = silc_dlist_get(client_entry->attrs)) != SILC_LIST_END) { - attribute = silc_attribute_get_attribute(attr); - switch (attribute) { - - case SILC_ATTRIBUTE_USER_INFO: - if (!silc_attribute_get_object(attr, (void *)&vcard, - sizeof(vcard))) - continue; - g_string_append_printf(s, "%s:\n\n", _("Personal Information")); - if (vcard.full_name) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Full Name"), - vcard.full_name); - if (vcard.first_name) - g_string_append_printf(s, "%s:\t%s\n", - _("First Name"), - vcard.first_name); - if (vcard.middle_names) - g_string_append_printf(s, "%s:\t%s\n", - _("Middle Name"), - vcard.middle_names); - if (vcard.family_name) - g_string_append_printf(s, "%s:\t%s\n", - _("Family Name"), - vcard.family_name); - if (vcard.nickname) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Nickname"), - vcard.nickname); - if (vcard.bday) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Birth Day"), - vcard.bday); - if (vcard.title) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Job Title"), - vcard.title); - if (vcard.role) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Job Role"), - vcard.role); - if (vcard.org_name) - g_string_append_printf(s, "%s:\t%s\n", - _("Organization"), - vcard.org_name); - if (vcard.org_unit) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Unit"), - vcard.org_unit); - if (vcard.url) - g_string_append_printf(s, "%s:\t%s\n", - _("Homepage"), - vcard.url); - if (vcard.label) - g_string_append_printf(s, "%s:\t%s\n", - _("Address"), - vcard.label); - for (i = 0; i < vcard.num_tels; i++) { - if (vcard.tels[i].telnum) - g_string_append_printf(s, "%s:\t\t\t%s\n", - _("Phone"), - vcard.tels[i].telnum); - } - for (i = 0; i < vcard.num_emails; i++) { - if (vcard.emails[i].address) - g_string_append_printf(s, "%s:\t\t%s\n", - _("Email"), - vcard.emails[i].address); - } - if (vcard.note) - g_string_append_printf(s, "\n%s:\t\t%s\n", - _("Note"), - vcard.note); - break; - } - } - - buf = g_string_free(s, FALSE); - purple_notify_info(NULL, _("User Information"), _("User Information"), - buf); - g_free(buf); -} -#endif - -/* Command reply handler. This function is called always in the command reply - function. If error occurs it will be called as well. Normal scenario - is that it will be called after the received command data has been parsed - and processed. The function is used to pass the received command data to - the application. - - `conn' is the associated client connection. `cmd_payload' is the command - payload data received from server and it can be ignored. It is provided - if the application would like to re-parse the received command data, - however, it must be noted that the data is parsed already by the library - thus the payload can be ignored. `success' is FALSE if error occurred. - In this case arguments are not sent to the application. The `status' is - the command reply status server returned. The `command' is the command - reply being processed. The function has variable argument list and each - command defines the number and type of arguments it passes to the - application (on error they are not sent). */ - -static void -silc_command_reply(SilcClient client, SilcClientConnection conn, - SilcCommandPayload cmd_payload, bool success, - SilcCommand command, SilcStatus status, ...) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - PurpleConversation *convo; - va_list vp; - - va_start(vp, status); - - switch (command) { - case SILC_COMMAND_JOIN: - { - SilcChannelEntry channel_entry; - - if (!success) { - purple_notify_error(gc, _("Join Chat"), _("Cannot join channel"), - silc_get_status_message(status)); - return; - } - - (void)va_arg(vp, char *); - channel_entry = va_arg(vp, SilcChannelEntry); - - /* Resolve users on channel */ - silc_client_get_clients_by_channel(client, conn, channel_entry, - silcpurple_chat_join_done, - channel_entry); - } - break; - - case SILC_COMMAND_LEAVE: - break; - - case SILC_COMMAND_USERS: - break; - - case SILC_COMMAND_WHOIS: - { - SilcUInt32 idle, mode; - SilcBuffer channels, user_modes; - SilcClientEntry client_entry; - char tmp[1024], *tmp2; - char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr; - PurpleNotifyUserInfo *user_info; - - if (!success) { - purple_notify_error(gc, _("User Information"), - _("Cannot get user information"), - silc_get_status_message(status)); - break; - } - - client_entry = va_arg(vp, SilcClientEntry); - if (!client_entry->nickname) - break; - (void)va_arg(vp, char *); - (void)va_arg(vp, char *); - (void)va_arg(vp, char *); - channels = va_arg(vp, SilcBuffer); - mode = va_arg(vp, SilcUInt32); - idle = va_arg(vp, SilcUInt32); - (void)va_arg(vp, unsigned char *); - user_modes = va_arg(vp, SilcBuffer); - - user_info = purple_notify_user_info_new(); - tmp2 = g_markup_escape_text(client_entry->nickname, -1); - purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp2); - g_free(tmp2); - if (client_entry->realname) { - tmp2 = g_markup_escape_text(client_entry->realname, -1); - purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp2); - g_free(tmp2); - } - if (client_entry->username) { - tmp2 = g_markup_escape_text(client_entry->username, -1); - if (client_entry->hostname) { - gchar *tmp3; - tmp3 = g_strdup_printf("%s@%s", tmp2, client_entry->hostname); - purple_notify_user_info_add_pair(user_info, _("Username"), tmp3); - g_free(tmp3); - } else - purple_notify_user_info_add_pair(user_info, _("Username"), tmp2); - g_free(tmp2); - } - - if (client_entry->mode) { - memset(tmp, 0, sizeof(tmp)); - silcpurple_get_umode_string(client_entry->mode, - tmp, sizeof(tmp) - strlen(tmp)); - purple_notify_user_info_add_pair(user_info, _("User Modes"), tmp); - } - - silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr); - if (moodstr) { - purple_notify_user_info_add_pair(user_info, _("Mood"), moodstr); - g_free(moodstr); - } - - if (statusstr) { - tmp2 = g_markup_escape_text(statusstr, -1); - purple_notify_user_info_add_pair(user_info, _("Status Text"), tmp2); - g_free(statusstr); - g_free(tmp2); - } - - if (contactstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Contact"), contactstr); - g_free(contactstr); - } - - if (langstr) { - purple_notify_user_info_add_pair(user_info, _("Preferred Language"), langstr); - g_free(langstr); - } - - if (devicestr) { - purple_notify_user_info_add_pair(user_info, _("Device"), devicestr); - g_free(devicestr); - } - - if (tzstr) { - purple_notify_user_info_add_pair(user_info, _("Timezone"), tzstr); - g_free(tzstr); - } - - if (geostr) { - purple_notify_user_info_add_pair(user_info, _("Geolocation"), geostr); - g_free(geostr); - } - - if (client_entry->server) - purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server); - - if (channels && user_modes) { - SilcUInt32 *umodes; - SilcDList list = - silc_channel_payload_parse_list(channels->data, - channels->len); - if (list && silc_get_mode_list(user_modes, - silc_dlist_count(list), - &umodes)) { - SilcChannelPayload entry; - int i = 0; - - memset(tmp, 0, sizeof(tmp)); - silc_dlist_start(list); - while ((entry = silc_dlist_get(list)) - != SILC_LIST_END) { - SilcUInt32 name_len; - char *m = silc_client_chumode_char(umodes[i++]); - char *name = (char *)silc_channel_get_name(entry, &name_len); - if (m) - silc_strncat(tmp, sizeof(tmp) - 1, m, strlen(m)); - silc_strncat(tmp, sizeof(tmp) - 1, name, name_len); - silc_strncat(tmp, sizeof(tmp) - 1, " ", 1); - silc_free(m); - - } - tmp2 = g_markup_escape_text(tmp, -1); - purple_notify_user_info_add_pair(user_info, _("Currently on"), tmp2); - g_free(tmp2); - silc_free(umodes); - } - } - - if (client_entry->public_key) { - char *fingerprint, *babbleprint; - unsigned char *pk; - SilcUInt32 pk_len; - pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint); - purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - } - -#if 0 /* XXX for now, let's not show attrs here */ - if (client_entry->attrs) - purple_request_action(gc, _("User Information"), - _("User Information"), - buf, 1, client_entry, 2, - _("OK"), G_CALLBACK(silcpurple_whois_more), - _("_More..."), G_CALLBACK(silcpurple_whois_more), gc->account, NULL, NULL); - else -#endif - purple_notify_userinfo(gc, client_entry->nickname, user_info, NULL, NULL); - purple_notify_user_info_destroy(user_info); - } - break; - - case SILC_COMMAND_WHOWAS: - { - SilcClientEntry client_entry; - char *nickname, *realname, *username, *tmp; - PurpleNotifyUserInfo *user_info; - - if (!success) { - purple_notify_error(gc, _("User Information"), - _("Cannot get user information"), - silc_get_status_message(status)); - break; - } - - client_entry = va_arg(vp, SilcClientEntry); - nickname = va_arg(vp, char *); - username = va_arg(vp, char *); - realname = va_arg(vp, char *); - if (!nickname) - break; - - user_info = purple_notify_user_info_new(); - tmp = g_markup_escape_text(nickname, -1); - purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp); - g_free(tmp); - if (realname) { - tmp = g_markup_escape_text(realname, -1); - purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp); - g_free(tmp); - } - if (username) { - tmp = g_markup_escape_text(username, -1); - if (client_entry && client_entry->hostname) { - gchar *tmp3; - tmp3 = g_strdup_printf("%s@%s", tmp, client_entry->hostname); - purple_notify_user_info_add_pair(user_info, _("Username"), tmp3); - g_free(tmp3); - } else - purple_notify_user_info_add_pair(user_info, _("Username"), tmp); - g_free(tmp); - } - if (client_entry && client_entry->server) - purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server); - - - if (client_entry && client_entry->public_key) { - char *fingerprint, *babbleprint; - unsigned char *pk; - SilcUInt32 pk_len; - pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint); - purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - } - - purple_notify_userinfo(gc, nickname, user_info, NULL, NULL); - purple_notify_user_info_destroy(user_info); - } - break; - - case SILC_COMMAND_DETACH: - if (!success) { - purple_notify_error(gc, _("Detach From Server"), _("Cannot detach"), - silc_get_status_message(status)); - return; - } - break; - - case SILC_COMMAND_TOPIC: - { - SilcChannelEntry channel; - - if (!success) { - purple_notify_error(gc, _("Topic"), _("Cannot set topic"), - silc_get_status_message(status)); - return; - } - - channel = va_arg(vp, SilcChannelEntry); - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - channel->channel_name, sg->account); - if (!convo) { - purple_debug_error("silc", "Got a topic for %s, which doesn't exist\n", - channel->channel_name); - break; - } - - /* Set topic */ - if (channel->topic) - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, channel->topic); - } - break; - - case SILC_COMMAND_NICK: - { - /* I don't think we should need to do this because the server should - * be sending a SILC_NOTIFY_TYPE_NICK_CHANGE when we change our own - * nick, but it isn't, so we deal with it here instead. Stu. */ - SilcClientEntry local_entry; - SilcHashTableList htl; - SilcChannelUser chu; - const char *oldnick; - - if (!success) { - purple_notify_error(gc, _("Nick"), _("Failed to change nickname"), - silc_get_status_message(status)); - return; - } - - local_entry = va_arg(vp, SilcClientEntry); - - /* Change nick on all channels */ - silc_hash_table_list(local_entry->channels, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - chu->channel->channel_name, sg->account); - if (!convo) - continue; - oldnick = purple_conv_chat_get_nick(PURPLE_CONV_CHAT(convo)); - if (strcmp(oldnick, purple_normalize(purple_conversation_get_account(convo), local_entry->nickname))) { - purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo), - oldnick, local_entry->nickname); - purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), local_entry->nickname); - } - } - silc_hash_table_list_reset(&htl); - - purple_connection_set_display_name(gc, local_entry->nickname); - } - break; - - case SILC_COMMAND_LIST: - { - char *topic, *name; - int usercount; - PurpleRoomlistRoom *room; - - if (sg->roomlist_cancelled) - break; - - if (!success) { - purple_notify_error(gc, _("Error"), _("Error retrieving room list"), - silc_get_status_message(status)); - purple_roomlist_set_in_progress(sg->roomlist, FALSE); - purple_roomlist_unref(sg->roomlist); - sg->roomlist = NULL; - return; - } - - (void)va_arg(vp, SilcChannelEntry); - name = va_arg(vp, char *); - if (!name) { - purple_notify_error(gc, _("Roomlist"), _("Cannot get room list"), - silc_get_status_message(status)); - purple_roomlist_set_in_progress(sg->roomlist, FALSE); - purple_roomlist_unref(sg->roomlist); - sg->roomlist = NULL; - return; - } - topic = va_arg(vp, char *); - usercount = va_arg(vp, int); - - room = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, name, NULL); - purple_roomlist_room_add_field(sg->roomlist, room, name); - purple_roomlist_room_add_field(sg->roomlist, room, - SILC_32_TO_PTR(usercount)); - purple_roomlist_room_add_field(sg->roomlist, room, - topic ? topic : ""); - purple_roomlist_room_add(sg->roomlist, room); - - if (status == SILC_STATUS_LIST_END || - status == SILC_STATUS_OK) { - purple_roomlist_set_in_progress(sg->roomlist, FALSE); - purple_roomlist_unref(sg->roomlist); - sg->roomlist = NULL; - } - } - break; - - case SILC_COMMAND_GETKEY: - { - SilcPublicKey public_key; - - if (!success) { - purple_notify_error(gc, _("Get Public Key"), - _("Cannot fetch the public key"), - silc_get_status_message(status)); - return; - } - - (void)va_arg(vp, SilcUInt32); - (void)va_arg(vp, void *); - public_key = va_arg(vp, SilcPublicKey); - - if (!public_key) - purple_notify_error(gc, _("Get Public Key"), - _("Cannot fetch the public key"), - _("No public key was received")); - } - break; - - case SILC_COMMAND_INFO: - { - - char *server_name; - char *server_info; - char tmp[256]; - - if (!success) { - purple_notify_error(gc, _("Server Information"), - _("Cannot get server information"), - silc_get_status_message(status)); - return; - } - - (void)va_arg(vp, SilcServerEntry); - server_name = va_arg(vp, char *); - server_info = va_arg(vp, char *); - - if (server_name && server_info) { - g_snprintf(tmp, sizeof(tmp), "Server: %s\n%s", - server_name, server_info); - purple_notify_info(gc, NULL, _("Server Information"), tmp); - } - } - break; - - case SILC_COMMAND_STATS: - { - SilcUInt32 starttime, uptime, my_clients, my_channels, my_server_ops, - my_router_ops, cell_clients, cell_channels, cell_servers, - clients, channels, servers, routers, server_ops, router_ops; - SilcUInt32 buffer_length; - SilcBufferStruct buf; - - unsigned char *server_stats; - char *msg; - - if (!success) { - purple_notify_error(gc, _("Server Statistics"), - _("Cannot get server statistics"), - silc_get_status_message(status)); - return; - } - - server_stats = va_arg(vp, unsigned char *); - buffer_length = va_arg(vp, SilcUInt32); - if (!server_stats || !buffer_length) { - purple_notify_error(gc, _("Server Statistics"), - _("No server statistics available"), NULL); - break; - } - silc_buffer_set(&buf, server_stats, buffer_length); - silc_buffer_unformat(&buf, - SILC_STR_UI_INT(&starttime), - SILC_STR_UI_INT(&uptime), - SILC_STR_UI_INT(&my_clients), - SILC_STR_UI_INT(&my_channels), - SILC_STR_UI_INT(&my_server_ops), - SILC_STR_UI_INT(&my_router_ops), - SILC_STR_UI_INT(&cell_clients), - SILC_STR_UI_INT(&cell_channels), - SILC_STR_UI_INT(&cell_servers), - SILC_STR_UI_INT(&clients), - SILC_STR_UI_INT(&channels), - SILC_STR_UI_INT(&servers), - SILC_STR_UI_INT(&routers), - SILC_STR_UI_INT(&server_ops), - SILC_STR_UI_INT(&router_ops), - SILC_STR_END); - - msg = g_strdup_printf(_("Local server start time: %s\n" - "Local server uptime: %s\n" - "Local server clients: %d\n" - "Local server channels: %d\n" - "Local server operators: %d\n" - "Local router operators: %d\n" - "Local cell clients: %d\n" - "Local cell channels: %d\n" - "Local cell servers: %d\n" - "Total clients: %d\n" - "Total channels: %d\n" - "Total servers: %d\n" - "Total routers: %d\n" - "Total server operators: %d\n" - "Total router operators: %d\n"), - silc_get_time(starttime), - purple_str_seconds_to_string((int)uptime), - (int)my_clients, (int)my_channels, (int)my_server_ops, (int)my_router_ops, - (int)cell_clients, (int)cell_channels, (int)cell_servers, - (int)clients, (int)channels, (int)servers, (int)routers, - (int)server_ops, (int)router_ops); - - purple_notify_info(gc, NULL, - _("Network Statistics"), msg); - g_free(msg); - } - break; - - case SILC_COMMAND_PING: - { - if (!success) { - purple_notify_error(gc, _("Ping"), _("Ping failed"), - silc_get_status_message(status)); - return; - } - - purple_notify_info(gc, _("Ping"), _("Ping reply received from server"), - NULL); - } - break; - - case SILC_COMMAND_KILL: - if (!success) { - purple_notify_error(gc, _("Kill User"), - _("Could not kill user"), - silc_get_status_message(status)); - return; - } - break; - - case SILC_COMMAND_CMODE: - { - SilcChannelEntry channel_entry; - SilcBuffer channel_pubkeys; - - if (!success) - return; - - channel_entry = va_arg(vp, SilcChannelEntry); - (void)va_arg(vp, SilcUInt32); - (void)va_arg(vp, SilcPublicKey); - channel_pubkeys = va_arg(vp, SilcBuffer); - - if (sg->chpk) - silcpurple_chat_chauth_show(sg, channel_entry, channel_pubkeys); - } - break; - - default: - if (success) - purple_debug_info("silc", "Unhandled command: %d (succeeded)\n", command); - else - purple_debug_info("silc", "Unhandled command: %d (failed: %s)\n", command, - silc_get_status_message(status)); - break; - } - - va_end(vp); -} - - -/* Called to indicate that connection was either successfully established - or connecting failed. This is also the first time application receives - the SilcClientConnection object which it should save somewhere. - If the `success' is FALSE the application must always call the function - silc_client_close_connection. */ - -static void -silc_connected(SilcClient client, SilcClientConnection conn, - SilcClientConnectionStatus status) -{ - PurpleConnection *gc = client->application; - SilcPurple sg; - - if (gc == NULL) { - silc_client_close_connection(client, conn); - return; - } - sg = gc->proto_data; - - switch (status) { - case SILC_CLIENT_CONN_SUCCESS: - case SILC_CLIENT_CONN_SUCCESS_RESUME: - purple_connection_set_state(gc, PURPLE_CONNECTED); - - /* Send the server our buddy list */ - silcpurple_send_buddylist(gc); - - g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); - - /* Send any UMODEs configured for account */ - if (purple_account_get_bool(sg->account, "block-ims", FALSE)) { - silc_client_command_call(sg->client, sg->conn, NULL, - "UMODE", "+P", NULL); - } - - return; - break; - case SILC_CLIENT_CONN_ERROR: - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Error during connecting to SILC Server")); - g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); - break; - - case SILC_CLIENT_CONN_ERROR_KE: - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, - _("Key Exchange failed")); - break; - - case SILC_CLIENT_CONN_ERROR_AUTH: - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, - _("Authentication failed")); - break; - - case SILC_CLIENT_CONN_ERROR_RESUME: - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - _("Resuming detached session failed. " - "Press Reconnect to create new connection.")); - g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); - break; - - case SILC_CLIENT_CONN_ERROR_TIMEOUT: - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Connection timed out")); - break; - } - - /* Error */ - sg->conn = NULL; - silc_client_close_connection(client, conn); -} - - -/* Called to indicate that connection was disconnected to the server. - The `status' may tell the reason of the disconnection, and if the - `message' is non-NULL it may include the disconnection message - received from server. */ - -static void -silc_disconnected(SilcClient client, SilcClientConnection conn, - SilcStatus status, const char *message) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - - if (sg->resuming && !sg->detaching) - g_unlink(silcpurple_session_file(purple_account_get_username(sg->account))); - - sg->conn = NULL; - - /* Close the connection */ - if (!sg->detaching) - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Disconnected by server")); - else - /* TODO: Does this work correctly? Maybe we need to set wants_to_die? */ - purple_account_disconnect(purple_connection_get_account(gc)); -} - - -typedef struct { - SilcGetAuthMeth completion; - void *context; -} *SilcPurpleGetAuthMethod; - -/* Callback called when we've received the authentication method information - from the server after we've requested it. */ - -static void silc_get_auth_method_callback(SilcClient client, - SilcClientConnection conn, - SilcAuthMethod auth_meth, - void *context) -{ - SilcPurpleGetAuthMethod internal = context; - - switch (auth_meth) { - case SILC_AUTH_NONE: - /* No authentication required. */ - (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); - break; - - case SILC_AUTH_PASSWORD: - /* By returning NULL here the library will ask the passphrase from us - by calling the silc_ask_passphrase. */ - (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); - break; - - case SILC_AUTH_PUBLIC_KEY: - /* Do not get the authentication data now, the library will generate - it using our default key, if we do not provide it here. */ - (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); - break; - } - - silc_free(internal); -} - -/* Find authentication method and authentication data by hostname and - port. The hostname may be IP address as well. When the authentication - method has been resolved the `completion' callback with the found - authentication method and authentication data is called. The `conn' - may be NULL. */ - -static void -silc_get_auth_method(SilcClient client, SilcClientConnection conn, - char *hostname, SilcUInt16 port, - SilcGetAuthMeth completion, void *context) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - SilcPurpleGetAuthMethod internal; - const char *password; - - /* Progress */ - if (sg->resuming) - purple_connection_update_progress(gc, _("Resuming session"), 4, 5); - else - purple_connection_update_progress(gc, _("Authenticating connection"), 4, 5); - - /* Check configuration if we have this connection configured. If we - have then return that data immediately, as it's faster way. */ - if (purple_account_get_bool(sg->account, "pubkey-auth", FALSE)) { - completion(TRUE, SILC_AUTH_PUBLIC_KEY, NULL, 0, context); - return; - } - password = purple_connection_get_password(gc); - if (password && *password) { - completion(TRUE, SILC_AUTH_PASSWORD, (unsigned char *)password, strlen(password), context); - return; - } - - /* Resolve the authentication method from server, as we may not know it. */ - internal = silc_calloc(1, sizeof(*internal)); - if (!internal) - return; - internal->completion = completion; - internal->context = context; - silc_client_request_authentication_method(client, conn, - silc_get_auth_method_callback, - internal); -} - - -/* Verifies received public key. The `conn_type' indicates which entity - (server, client etc.) has sent the public key. If user decides to trust - the application may save the key as trusted public key for later - use. The `completion' must be called after the public key has been - verified. */ - -static void -silc_verify_public_key(SilcClient client, SilcClientConnection conn, - SilcSocketType conn_type, unsigned char *pk, - SilcUInt32 pk_len, SilcSKEPKType pk_type, - SilcVerifyPublicKey completion, void *context) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - - if (!sg->conn && (conn_type == SILC_SOCKET_TYPE_SERVER || - conn_type == SILC_SOCKET_TYPE_ROUTER)) { - /* Progress */ - if (sg->resuming) - purple_connection_update_progress(gc, _("Resuming session"), 3, 5); - else - purple_connection_update_progress(gc, _("Verifying server public key"), - 3, 5); - } - - /* Verify public key */ - silcpurple_verify_public_key(client, conn, NULL, conn_type, pk, - pk_len, pk_type, completion, context); -} - -typedef struct { - SilcAskPassphrase completion; - void *context; -} *SilcPurpleAskPassphrase; - -static void -silc_ask_passphrase_cb(SilcPurpleAskPassphrase internal, const char *passphrase) -{ - if (!passphrase || !(*passphrase)) - internal->completion(NULL, 0, internal->context); - else - internal->completion((unsigned char *)passphrase, - strlen(passphrase), internal->context); - silc_free(internal); -} - -/* Ask (interact, that is) a passphrase from user. The passphrase is - returned to the library by calling the `completion' callback with - the `context'. The returned passphrase SHOULD be in UTF-8 encoded, - if not then the library will attempt to encode. */ - -static void -silc_ask_passphrase(SilcClient client, SilcClientConnection conn, - SilcAskPassphrase completion, void *context) -{ - PurpleConnection *gc = client->application; - SilcPurpleAskPassphrase internal = silc_calloc(1, sizeof(*internal)); - - if (!internal) - return; - internal->completion = completion; - internal->context = context; - purple_request_input(gc, _("Passphrase"), NULL, - _("Passphrase required"), NULL, FALSE, TRUE, NULL, - _("OK"), G_CALLBACK(silc_ask_passphrase_cb), - _("Cancel"), G_CALLBACK(silc_ask_passphrase_cb), - purple_connection_get_account(gc), NULL, NULL, internal); -} - - -/* Notifies application that failure packet was received. This is called - if there is some protocol active in the client. The `protocol' is the - protocol context. The `failure' is opaque pointer to the failure - indication. Note, that the `failure' is protocol dependant and - application must explicitly cast it to correct type. Usually `failure' - is 32 bit failure type (see protocol specs for all protocol failure - types). */ - -static void -silc_failure(SilcClient client, SilcClientConnection conn, - SilcProtocol protocol, void *failure) -{ - PurpleConnection *gc = client->application; - char buf[128]; - - memset(buf, 0, sizeof(buf)); - - if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) { - SilcSKEStatus status = (SilcSKEStatus)SILC_PTR_TO_32(failure); - - if (status == SILC_SKE_STATUS_BAD_VERSION) - g_snprintf(buf, sizeof(buf), - _("Failure: Version mismatch, upgrade your client")); - if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) - g_snprintf(buf, sizeof(buf), - _("Failure: Remote does not trust/support your public key")); - if (status == SILC_SKE_STATUS_UNKNOWN_GROUP) - g_snprintf(buf, sizeof(buf), - _("Failure: Remote does not support proposed KE group")); - if (status == SILC_SKE_STATUS_UNKNOWN_CIPHER) - g_snprintf(buf, sizeof(buf), - _("Failure: Remote does not support proposed cipher")); - if (status == SILC_SKE_STATUS_UNKNOWN_PKCS) - g_snprintf(buf, sizeof(buf), - _("Failure: Remote does not support proposed PKCS")); - if (status == SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION) - g_snprintf(buf, sizeof(buf), - _("Failure: Remote does not support proposed hash function")); - if (status == SILC_SKE_STATUS_UNKNOWN_HMAC) - g_snprintf(buf, sizeof(buf), - _("Failure: Remote does not support proposed HMAC")); - if (status == SILC_SKE_STATUS_INCORRECT_SIGNATURE) - g_snprintf(buf, sizeof(buf), _("Failure: Incorrect signature")); - if (status == SILC_SKE_STATUS_INVALID_COOKIE) - g_snprintf(buf, sizeof(buf), _("Failure: Invalid cookie")); - - /* Show the error on the progress bar. A more generic error message - is going to be showed to user after this in the silc_connected. */ - purple_connection_update_progress(gc, buf, 2, 5); - } - - if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) { - SilcUInt32 err = SILC_PTR_TO_32(failure); - - if (err == SILC_AUTH_FAILED) - g_snprintf(buf, sizeof(buf), _("Failure: Authentication failed")); - - /* Show the error on the progress bar. A more generic error message - is going to be showed to user after this in the silc_connected. */ - purple_connection_update_progress(gc, buf, 4, 5); - } -} - -/* Asks whether the user would like to perform the key agreement protocol. - This is called after we have received an key agreement packet or an - reply to our key agreement packet. This returns TRUE if the user wants - the library to perform the key agreement protocol and FALSE if it is not - desired (application may start it later by calling the function - silc_client_perform_key_agreement). If TRUE is returned also the - `completion' and `context' arguments must be set by the application. */ - -static bool -silc_key_agreement(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, const char *hostname, - SilcUInt16 port, SilcKeyAgreementCallback *completion, - void **context) -{ - silcpurple_buddy_keyagr_request(client, conn, client_entry, hostname, port); - *completion = NULL; - *context = NULL; - return FALSE; -} - - -/* Notifies application that file transfer protocol session is being - requested by the remote client indicated by the `client_entry' from - the `hostname' and `port'. The `session_id' is the file transfer - session and it can be used to either accept or reject the file - transfer request, by calling the silc_client_file_receive or - silc_client_file_close, respectively. */ - -static void -silc_ftp(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, SilcUInt32 session_id, - const char *hostname, SilcUInt16 port) -{ - silcpurple_ftp_request(client, conn, client_entry, session_id, - hostname, port); -} - - -/* Delivers SILC session detachment data indicated by `detach_data' to the - application. If application has issued SILC_COMMAND_DETACH command - the client session in the SILC network is not quit. The client remains - in the network but is detached. The detachment data may be used later - to resume the session in the SILC Network. The appliation is - responsible of saving the `detach_data', to for example in a file. - - The detachment data can be given as argument to the functions - silc_client_connect_to_server, or silc_client_add_connection when - creating connection to remote server, inside SilcClientConnectionParams - structure. If it is provided the client library will attempt to resume - the session in the network. After the connection is created - successfully, the application is responsible of setting the user - interface for user into the same state it was before detaching (showing - same channels, channel modes, etc). It can do this by fetching the - information (like joined channels) from the client library. */ - -static void -silc_detach(SilcClient client, SilcClientConnection conn, - const unsigned char *detach_data, SilcUInt32 detach_data_len) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - const char *file; - - /* Save the detachment data to file. */ - file = silcpurple_session_file(purple_account_get_username(sg->account)); - g_unlink(file); - silc_file_writefile(file, (char *)detach_data, detach_data_len); -} - -SilcClientOperations ops = { - silc_say, - silc_channel_message, - silc_private_message, - silc_notify, - silc_command, - silc_command_reply, - silc_connected, - silc_disconnected, - silc_get_auth_method, - silc_verify_public_key, - silc_ask_passphrase, - silc_failure, - silc_key_agreement, - silc_ftp, - silc_detach -}; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc10/pk.c --- a/libpurple/protocols/silc10/pk.c Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,274 +0,0 @@ -/* - - silcpurple_pk.c - - Author: Pekka Riikonen - - Copyright (C) 2004 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#include "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" - -/************************* Public Key Verification ***************************/ - -typedef struct { - SilcClient client; - SilcClientConnection conn; - char *filename; - char *entity; - char *entity_name; - char *fingerprint; - char *babbleprint; - unsigned char *pk; - SilcUInt32 pk_len; - SilcSKEPKType pk_type; - SilcVerifyPublicKey completion; - void *context; - gboolean changed; -} *PublicKeyVerify; - -static void silcpurple_verify_ask(const char *entity, - const char *fingerprint, - const char *babbleprint, - PublicKeyVerify verify); - -static void silcpurple_verify_cb(PublicKeyVerify verify, gint id) -{ - if (id != 2) { - if (verify->completion) - verify->completion(FALSE, verify->context); - } else { - if (verify->completion) - verify->completion(TRUE, verify->context); - - /* Save the key for future checking */ - silc_pkcs_save_public_key_data(verify->filename, verify->pk, - verify->pk_len, SILC_PKCS_FILE_PEM); - } - - silc_free(verify->filename); - silc_free(verify->entity); - silc_free(verify->entity_name); - silc_free(verify->fingerprint); - silc_free(verify->babbleprint); - silc_free(verify->pk); - silc_free(verify); -} - -static void silcpurple_verify_details_cb(PublicKeyVerify verify) -{ - /* What a hack. We have to display the accept dialog _again_ - because Purple closes the dialog after you press the button. Purple - should have option for the dialogs whether the buttons close them - or not. */ - silcpurple_verify_ask(verify->entity, verify->fingerprint, - verify->babbleprint, verify); -} - -static void silcpurple_verify_details(PublicKeyVerify verify, gint id) -{ - SilcPublicKey public_key; - PurpleConnection *gc = verify->client->application; - SilcPurple sg = gc->proto_data; - - silc_pkcs_public_key_decode(verify->pk, verify->pk_len, - &public_key); - silcpurple_show_public_key(sg, verify->entity_name, public_key, - G_CALLBACK(silcpurple_verify_details_cb), - verify); - silc_pkcs_public_key_free(public_key); -} - -static void silcpurple_verify_ask(const char *entity, - const char *fingerprint, - const char *babbleprint, - PublicKeyVerify verify) -{ - PurpleConnection *gc = verify->client->application; - char tmp[256], tmp2[256]; - - if (verify->changed) { - g_snprintf(tmp, sizeof(tmp), - _("Received %s's public key. Your local copy does not match this " - "key. Would you still like to accept this public key?"), - entity); - } else { - g_snprintf(tmp, sizeof(tmp), - _("Received %s's public key. Would you like to accept this " - "public key?"), entity); - } - g_snprintf(tmp2, sizeof(tmp2), - _("Fingerprint and babbleprint for the %s key are:\n\n" - "%s\n%s\n"), entity, fingerprint, babbleprint); - - purple_request_action(gc, _("Verify Public Key"), tmp, tmp2, - PURPLE_DEFAULT_ACTION_NONE, - purple_connection_get_account(gc), entity, NULL, verify, 3, - _("Yes"), G_CALLBACK(silcpurple_verify_cb), - _("No"), G_CALLBACK(silcpurple_verify_cb), - _("_View..."), G_CALLBACK(silcpurple_verify_details)); -} - -void silcpurple_verify_public_key(SilcClient client, SilcClientConnection conn, - const char *name, SilcSocketType conn_type, - unsigned char *pk, SilcUInt32 pk_len, - SilcSKEPKType pk_type, - SilcVerifyPublicKey completion, void *context) -{ - PurpleConnection *gc = client->application; - int i; - char file[256], filename[256], filename2[256], *ipf, *hostf = NULL; - char *fingerprint, *babbleprint; - struct passwd *pw; - struct stat st; - char *entity = ((conn_type == SILC_SOCKET_TYPE_SERVER || - conn_type == SILC_SOCKET_TYPE_ROUTER) ? - "server" : "client"); - PublicKeyVerify verify; - - if (pk_type != SILC_SKE_PK_TYPE_SILC) { - purple_notify_error(gc, _("Verify Public Key"), - _("Unsupported public key type"), NULL); - if (completion) - completion(FALSE, context); - return; - } - - pw = getpwuid(getuid()); - if (!pw) { - if (completion) - completion(FALSE, context); - return; - } - - memset(filename, 0, sizeof(filename)); - memset(filename2, 0, sizeof(filename2)); - memset(file, 0, sizeof(file)); - - if (conn_type == SILC_SOCKET_TYPE_SERVER || - conn_type == SILC_SOCKET_TYPE_ROUTER) { - if (!name) { - g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, - conn->sock->ip, conn->sock->port); - g_snprintf(filename, sizeof(filename) - 1, - "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s", - silcpurple_silcdir(), entity, file); - - g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, - conn->sock->hostname, conn->sock->port); - g_snprintf(filename2, sizeof(filename2) - 1, - "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s", - silcpurple_silcdir(), entity, file); - - ipf = filename; - hostf = filename2; - } else { - g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, - name, conn->sock->port); - g_snprintf(filename, sizeof(filename) - 1, - "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s", - silcpurple_silcdir(), entity, file); - - ipf = filename; - } - } else { - /* Replace all whitespaces with `_'. */ - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - for (i = 0; i < strlen(fingerprint); i++) - if (fingerprint[i] == ' ') - fingerprint[i] = '_'; - - g_snprintf(file, sizeof(file) - 1, "%skey_%s.pub", entity, fingerprint); - g_snprintf(filename, sizeof(filename) - 1, - "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s", - silcpurple_silcdir(), entity, file); - silc_free(fingerprint); - - ipf = filename; - } - - verify = silc_calloc(1, sizeof(*verify)); - if (!verify) - return; - verify->client = client; - verify->conn = conn; - verify->filename = strdup(ipf); - verify->entity = strdup(entity); - verify->entity_name = (conn_type != SILC_SOCKET_TYPE_CLIENT ? - (name ? strdup(name) : strdup(conn->sock->hostname)) - : NULL); - verify->pk = silc_memdup(pk, pk_len); - verify->pk_len = pk_len; - verify->pk_type = pk_type; - verify->completion = completion; - verify->context = context; - fingerprint = verify->fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = verify->babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - - /* Check whether this key already exists */ - if (g_stat(ipf, &st) < 0 && (!hostf || g_stat(hostf, &st) < 0)) { - /* Key does not exist, ask user to verify the key and save it */ - silcpurple_verify_ask(name ? name : entity, - fingerprint, babbleprint, verify); - return; - } else { - /* The key already exists, verify it. */ - SilcPublicKey public_key; - unsigned char *encpk; - SilcUInt32 encpk_len; - - /* Load the key file, try for both IP filename and hostname filename */ - if (!silc_pkcs_load_public_key(ipf, &public_key, - SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(ipf, &public_key, - SILC_PKCS_FILE_BIN) && - (!hostf || (!silc_pkcs_load_public_key(hostf, &public_key, - SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(hostf, &public_key, - SILC_PKCS_FILE_BIN)))) { - silcpurple_verify_ask(name ? name : entity, - fingerprint, babbleprint, verify); - return; - } - - /* Encode the key data */ - encpk = silc_pkcs_public_key_encode(public_key, &encpk_len); - if (!encpk) { - silcpurple_verify_ask(name ? name : entity, - fingerprint, babbleprint, verify); - return; - } - - /* Compare the keys */ - if (memcmp(encpk, pk, encpk_len)) { - /* Ask user to verify the key and save it */ - verify->changed = TRUE; - silcpurple_verify_ask(name ? name : entity, - fingerprint, babbleprint, verify); - return; - } - - /* Local copy matched */ - if (completion) - completion(TRUE, context); - silc_free(verify->filename); - silc_free(verify->entity); - silc_free(verify->entity_name); - silc_free(verify->pk); - silc_free(verify->fingerprint); - silc_free(verify->babbleprint); - silc_free(verify); - } -} diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc10/silc.c --- a/libpurple/protocols/silc10/silc.c Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1965 +0,0 @@ -/* - - silcpurple.c - - Author: Pekka Riikonen - - Copyright (C) 2004 - 2005 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#include "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" -#include "version.h" -#include "wb.h" -#include "core.h" - -extern SilcClientOperations ops; -static PurplePlugin *silc_plugin = NULL; - -static const char * -silcpurple_list_icon(PurpleAccount *a, PurpleBuddy *b) -{ - return (const char *)"silc"; -} - -static GList * -silcpurple_away_states(PurpleAccount *account) -{ - PurpleStatusType *type; - GList *types = NULL; - - type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_AVAILABLE, NULL, TRUE, TRUE, FALSE); - types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_HYPER, _("Hyper Active"), TRUE, TRUE, FALSE); - types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_AWAY, NULL, TRUE, TRUE, FALSE); - types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, SILCPURPLE_STATUS_ID_BUSY, _("Busy"), TRUE, TRUE, FALSE); - types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_INDISPOSED, _("Indisposed"), TRUE, TRUE, FALSE); - types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_PAGE, _("Wake Me Up"), TRUE, TRUE, FALSE); - types = g_list_append(types, type); - type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, SILCPURPLE_STATUS_ID_OFFLINE, NULL, TRUE, TRUE, FALSE); - types = g_list_append(types, type); - - return types; -} - -static void -silcpurple_set_status(PurpleAccount *account, PurpleStatus *status) -{ - PurpleConnection *gc = purple_account_get_connection(account); - SilcPurple sg = NULL; - SilcUInt32 mode; - SilcBuffer idp; - unsigned char mb[4]; - const char *state; - - if (gc != NULL) - sg = gc->proto_data; - - if (status == NULL) - return; - - state = purple_status_get_id(status); - - if (state == NULL) - return; - - if ((sg == NULL) || (sg->conn == NULL)) - return; - - mode = sg->conn->local_entry->mode; - mode &= ~(SILC_UMODE_GONE | - SILC_UMODE_HYPER | - SILC_UMODE_BUSY | - SILC_UMODE_INDISPOSED | - SILC_UMODE_PAGE); - - if (!strcmp(state, "hyper")) - mode |= SILC_UMODE_HYPER; - else if (!strcmp(state, "away")) - mode |= SILC_UMODE_GONE; - else if (!strcmp(state, "busy")) - mode |= SILC_UMODE_BUSY; - else if (!strcmp(state, "indisposed")) - mode |= SILC_UMODE_INDISPOSED; - else if (!strcmp(state, "page")) - mode |= SILC_UMODE_PAGE; - - /* Send UMODE */ - idp = silc_id_payload_encode(sg->conn->local_id, SILC_ID_CLIENT); - SILC_PUT32_MSB(mode, mb); - silc_client_command_send(sg->client, sg->conn, SILC_COMMAND_UMODE, - ++sg->conn->cmd_ident, 2, - 1, idp->data, idp->len, - 2, mb, sizeof(mb)); - silc_buffer_free(idp); -} - - -/*************************** Connection Routines *****************************/ - -static void -silcpurple_keepalive(PurpleConnection *gc) -{ - SilcPurple sg = gc->proto_data; - silc_client_send_packet(sg->client, sg->conn, SILC_PACKET_HEARTBEAT, - NULL, 0); -} - -static gboolean -silcpurple_scheduler(gpointer *context) -{ - SilcPurple sg = (SilcPurple)context; - silc_client_run_one(sg->client); - return TRUE; -} - -static void -silcpurple_nickname_parse(const char *nickname, - char **ret_nickname) -{ - silc_parse_userfqdn(nickname, ret_nickname, NULL); -} - -static void -silcpurple_login_connected(gpointer data, gint source, const gchar *error_message) -{ - PurpleConnection *gc = data; - SilcPurple sg; - SilcClient client; - SilcClientConnection conn; - PurpleAccount *account; - SilcClientConnectionParams params; - SilcUInt32 mask; - const char *dfile, *tmp; -#ifdef SILC_ATTRIBUTE_USER_ICON - PurpleStoredImage *img; -#endif -#ifdef HAVE_SYS_UTSNAME_H - struct utsname u; -#endif - - - g_return_if_fail(gc != NULL); - - sg = gc->proto_data; - - if (source < 0) { - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Connection failed")); - return; - } - - client = sg->client; - account = sg->account; - - /* Get session detachment data, if available */ - memset(¶ms, 0, sizeof(params)); - dfile = silcpurple_session_file(purple_account_get_username(sg->account)); - params.detach_data = (unsigned char *)silc_file_readfile(dfile, ¶ms.detach_data_len); - if (params.detach_data) - params.detach_data[params.detach_data_len] = 0; - - /* Add connection to SILC client library */ - conn = silc_client_add_connection( - sg->client, ¶ms, - (char *)purple_account_get_string(account, "server", - "silc.silcnet.org"), - purple_account_get_int(account, "port", 706), sg); - if (!conn) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Unable to initialize SILC Client connection")); - gc->proto_data = NULL; - return; - } - sg->conn = conn; - - /* Progress */ - if (params.detach_data) { - purple_connection_update_progress(gc, _("Resuming session"), 2, 5); - sg->resuming = TRUE; - } else { - purple_connection_update_progress(gc, _("Performing key exchange"), 2, 5); - } - - /* Perform SILC Key Exchange. The "silc_connected" will be called - eventually. */ - silc_client_start_key_exchange(sg->client, sg->conn, source); - - /* Set default attributes */ - mask = SILC_ATTRIBUTE_MOOD_NORMAL; - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_STATUS_MOOD, - SILC_32_TO_PTR(mask), - sizeof(SilcUInt32)); - mask = SILC_ATTRIBUTE_CONTACT_CHAT; - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_PREFERRED_CONTACT, - SILC_32_TO_PTR(mask), - sizeof(SilcUInt32)); -#ifdef HAVE_SYS_UTSNAME_H - if (!uname(&u)) { - SilcAttributeObjDevice dev; - memset(&dev, 0, sizeof(dev)); - dev.type = SILC_ATTRIBUTE_DEVICE_COMPUTER; - dev.version = u.release; - dev.model = u.sysname; - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_DEVICE_INFO, - (void *)&dev, sizeof(dev)); - } -#endif -#ifdef _WIN32 - tmp = _tzname[0]; -#else - tmp = tzname[0]; -#endif - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_TIMEZONE, - (void *)tmp, strlen(tmp)); - -#ifdef SILC_ATTRIBUTE_USER_ICON - /* Set our buddy icon */ - img = purple_buddy_icons_find_account_icon(account); - silcpurple_buddy_set_icon(gc, img); - purple_imgstore_unref(img); -#endif - - silc_free(params.detach_data); -} - -static void -silcpurple_login(PurpleAccount *account) -{ - SilcPurple sg; - SilcClient client; - SilcClientParams params; - PurpleConnection *gc; - char pkd[256], prd[256]; - const char *cipher, *hmac; - char *realname; - int i; - - gc = account->gc; - if (!gc) - return; - gc->proto_data = NULL; - - memset(¶ms, 0, sizeof(params)); - strcat(params.nickname_format, "%n@%h%a"); - params.nickname_parse = silcpurple_nickname_parse; - params.ignore_requested_attributes = FALSE; - - /* Allocate SILC client */ - client = silc_client_alloc(&ops, ¶ms, gc, NULL); - if (!client) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - _("Out of memory")); - return; - } - - /* Get username, real name and local hostname for SILC library */ - if (purple_account_get_username(account)) { - const char *u = purple_account_get_username(account); - char **up = g_strsplit(u, "@", 2); - client->username = strdup(up[0]); - g_strfreev(up); - } else { - client->username = silc_get_username(); - purple_account_set_username(account, client->username); - } - realname = silc_get_real_name(); - if (purple_account_get_user_info(account)) { - client->realname = strdup(purple_account_get_user_info(account)); - free(realname); - } else if ((silc_get_real_name() != NULL) && (*realname != '\0')) { - client->realname = realname; - purple_account_set_user_info(account, client->realname); - } else { - free(realname); - client->realname = strdup(_("John Noname")); - } - client->hostname = silc_net_localhost(); - - purple_connection_set_display_name(gc, client->username); - - /* Register requested cipher and HMAC */ - cipher = purple_account_get_string(account, "cipher", SILC_DEFAULT_CIPHER); - for (i = 0; silc_default_ciphers[i].name; i++) - if (!strcmp(silc_default_ciphers[i].name, cipher)) { - silc_cipher_register(&(silc_default_ciphers[i])); - break; - } - hmac = purple_account_get_string(account, "hmac", SILC_DEFAULT_HMAC); - for (i = 0; silc_default_hmacs[i].name; i++) - if (!strcmp(silc_default_hmacs[i].name, hmac)) { - silc_hmac_register(&(silc_default_hmacs[i])); - break; - } - - /* Init SILC client */ - if (!silc_client_init(client)) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - _("Unable to initialize SILC protocol")); - return; - } - - /* Check the ~/.silc dir and create it, and new key pair if necessary. */ - if (!silcpurple_check_silc_dir(gc)) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - _("Error loading SILC key pair")); - return; - } - - /* Progress */ - purple_connection_update_progress(gc, _("Connecting to SILC Server"), 1, 5); - - /* Load SILC key pair */ - g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir()); - g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir()); - if (!silc_load_key_pair((char *)purple_account_get_string(account, "public-key", pkd), - (char *)purple_account_get_string(account, "private-key", prd), - (gc->password == NULL) ? "" : gc->password, &client->pkcs, - &client->public_key, &client->private_key)) { - g_snprintf(pkd, sizeof(pkd), _("Unable to load SILC key pair: %s"), g_strerror(errno)); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, - pkd); - return; - } - - sg = silc_calloc(1, sizeof(*sg)); - if (!sg) - return; - memset(sg, 0, sizeof(*sg)); - sg->client = client; - sg->gc = gc; - sg->account = account; - gc->proto_data = sg; - - /* Connect to the SILC server */ - if (purple_proxy_connect(gc, account, - purple_account_get_string(account, "server", - "silc.silcnet.org"), - purple_account_get_int(account, "port", 706), - silcpurple_login_connected, gc) == NULL) - { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Unable to create connection")); - return; - } - - /* Schedule SILC using Glib's event loop */ - sg->scheduler = purple_timeout_add(300, (GSourceFunc)silcpurple_scheduler, sg); -} - -static int -silcpurple_close_final(gpointer *context) -{ - SilcPurple sg = (SilcPurple)context; - silc_client_stop(sg->client); - silc_client_free(sg->client); -#ifdef HAVE_SILCMIME_H - if (sg->mimeass) - silc_mime_assembler_free(sg->mimeass); -#endif - silc_free(sg); - return 0; -} - -static void -silcpurple_close(PurpleConnection *gc) -{ - SilcPurple sg = gc->proto_data; - GHashTable *ui_info; - const char *ui_name = NULL, *ui_website = NULL; - char *quit_msg; - - g_return_if_fail(sg != NULL); - - ui_info = purple_core_get_ui_info(); - - if(ui_info) { - ui_name = g_hash_table_lookup(ui_info, "name"); - ui_website = g_hash_table_lookup(ui_info, "website"); - } - - if(!ui_name || !ui_website) { - ui_name = "Pidgin"; - ui_website = PURPLE_WEBSITE; - } - quit_msg = g_strdup_printf(_("Download %s: %s"), - ui_name, ui_website); - - /* Send QUIT */ - silc_client_command_call(sg->client, sg->conn, NULL, - "QUIT", quit_msg, NULL); - g_free(quit_msg); - - if (sg->conn) - silc_client_close_connection(sg->client, sg->conn); - - purple_timeout_remove(sg->scheduler); - purple_timeout_add(1, (GSourceFunc)silcpurple_close_final, sg); -} - - -/****************************** Protocol Actions *****************************/ - -static void -silcpurple_attrs_cancel(PurpleConnection *gc, PurpleRequestFields *fields) -{ - /* Nothing */ -} - -static void -silcpurple_attrs_cb(PurpleConnection *gc, PurpleRequestFields *fields) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - PurpleRequestField *f; - char *tmp; - SilcUInt32 tmp_len, mask; - SilcAttributeObjService service; - SilcAttributeObjDevice dev; - SilcVCardStruct vcard; - const char *val; - - sg = gc->proto_data; - if (!sg) - return; - - memset(&service, 0, sizeof(service)); - memset(&dev, 0, sizeof(dev)); - memset(&vcard, 0, sizeof(vcard)); - - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_USER_INFO, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_SERVICE, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_STATUS_MOOD, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_STATUS_FREETEXT, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_STATUS_MESSAGE, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_PREFERRED_LANGUAGE, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_PREFERRED_CONTACT, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_TIMEZONE, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_GEOLOCATION, NULL); - silc_client_attribute_del(client, conn, - SILC_ATTRIBUTE_DEVICE_INFO, NULL); - - /* Set mood */ - mask = 0; - f = purple_request_fields_get_field(fields, "mood_normal"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_NORMAL; - f = purple_request_fields_get_field(fields, "mood_happy"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_HAPPY; - f = purple_request_fields_get_field(fields, "mood_sad"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_SAD; - f = purple_request_fields_get_field(fields, "mood_angry"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_ANGRY; - f = purple_request_fields_get_field(fields, "mood_jealous"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_JEALOUS; - f = purple_request_fields_get_field(fields, "mood_ashamed"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_ASHAMED; - f = purple_request_fields_get_field(fields, "mood_invincible"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_INVINCIBLE; - f = purple_request_fields_get_field(fields, "mood_inlove"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_INLOVE; - f = purple_request_fields_get_field(fields, "mood_sleepy"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_SLEEPY; - f = purple_request_fields_get_field(fields, "mood_bored"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_BORED; - f = purple_request_fields_get_field(fields, "mood_excited"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_EXCITED; - f = purple_request_fields_get_field(fields, "mood_anxious"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_MOOD_ANXIOUS; - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_STATUS_MOOD, - SILC_32_TO_PTR(mask), - sizeof(SilcUInt32)); - - /* Set preferred contact */ - mask = 0; - f = purple_request_fields_get_field(fields, "contact_chat"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_CONTACT_CHAT; - f = purple_request_fields_get_field(fields, "contact_email"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_CONTACT_EMAIL; - f = purple_request_fields_get_field(fields, "contact_call"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_CONTACT_CALL; - f = purple_request_fields_get_field(fields, "contact_sms"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_CONTACT_SMS; - f = purple_request_fields_get_field(fields, "contact_mms"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_CONTACT_MMS; - f = purple_request_fields_get_field(fields, "contact_video"); - if (f && purple_request_field_bool_get_value(f)) - mask |= SILC_ATTRIBUTE_CONTACT_VIDEO; - if (mask) - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_PREFERRED_CONTACT, - SILC_32_TO_PTR(mask), - sizeof(SilcUInt32)); - - /* Set status text */ - val = NULL; - f = purple_request_fields_get_field(fields, "status_text"); - if (f) - val = purple_request_field_string_get_value(f); - if (val && *val) - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_STATUS_FREETEXT, - (void *)val, strlen(val)); - - /* Set vcard */ - val = NULL; - f = purple_request_fields_get_field(fields, "vcard"); - if (f) - val = purple_request_field_string_get_value(f); - if (val && *val) { - purple_account_set_string(sg->account, "vcard", val); - tmp = silc_file_readfile(val, &tmp_len); - if (tmp) { - tmp[tmp_len] = 0; - if (silc_vcard_decode((unsigned char *)tmp, tmp_len, &vcard)) - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_USER_INFO, - (void *)&vcard, - sizeof(vcard)); - } - silc_vcard_free(&vcard); - silc_free(tmp); - } else { - purple_account_set_string(sg->account, "vcard", ""); - } - -#ifdef HAVE_SYS_UTSNAME_H - /* Set device info */ - f = purple_request_fields_get_field(fields, "device"); - if (f && purple_request_field_bool_get_value(f)) { - struct utsname u; - if (!uname(&u)) { - dev.type = SILC_ATTRIBUTE_DEVICE_COMPUTER; - dev.version = u.release; - dev.model = u.sysname; - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_DEVICE_INFO, - (void *)&dev, sizeof(dev)); - } - } -#endif - - /* Set timezone */ - val = NULL; - f = purple_request_fields_get_field(fields, "timezone"); - if (f) - val = purple_request_field_string_get_value(f); - if (val && *val) - silc_client_attribute_add(client, conn, - SILC_ATTRIBUTE_TIMEZONE, - (void *)val, strlen(val)); -} - -static void -silcpurple_attrs(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - PurpleRequestFields *fields; - PurpleRequestFieldGroup *g; - PurpleRequestField *f; - SilcHashTable attrs; - SilcAttributePayload attr; - gboolean mnormal = TRUE, mhappy = FALSE, msad = FALSE, - mangry = FALSE, mjealous = FALSE, mashamed = FALSE, - minvincible = FALSE, minlove = FALSE, msleepy = FALSE, - mbored = FALSE, mexcited = FALSE, manxious = FALSE; - gboolean cemail = FALSE, ccall = FALSE, csms = FALSE, - cmms = FALSE, cchat = TRUE, cvideo = FALSE; - gboolean device = TRUE; - char status[1024]; - - sg = gc->proto_data; - if (!sg) - return; - - memset(status, 0, sizeof(status)); - - attrs = silc_client_attributes_get(client, conn); - if (attrs) { - if (silc_hash_table_find(attrs, - SILC_32_TO_PTR(SILC_ATTRIBUTE_STATUS_MOOD), - NULL, (void *)&attr)) { - SilcUInt32 mood = 0; - silc_attribute_get_object(attr, &mood, sizeof(mood)); - mnormal = !mood; - mhappy = (mood & SILC_ATTRIBUTE_MOOD_HAPPY); - msad = (mood & SILC_ATTRIBUTE_MOOD_SAD); - mangry = (mood & SILC_ATTRIBUTE_MOOD_ANGRY); - mjealous = (mood & SILC_ATTRIBUTE_MOOD_JEALOUS); - mashamed = (mood & SILC_ATTRIBUTE_MOOD_ASHAMED); - minvincible = (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE); - minlove = (mood & SILC_ATTRIBUTE_MOOD_INLOVE); - msleepy = (mood & SILC_ATTRIBUTE_MOOD_SLEEPY); - mbored = (mood & SILC_ATTRIBUTE_MOOD_BORED); - mexcited = (mood & SILC_ATTRIBUTE_MOOD_EXCITED); - manxious = (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS); - } - - if (silc_hash_table_find(attrs, - SILC_32_TO_PTR(SILC_ATTRIBUTE_PREFERRED_CONTACT), - NULL, (void *)&attr)) { - SilcUInt32 contact = 0; - silc_attribute_get_object(attr, &contact, sizeof(contact)); - cemail = (contact & SILC_ATTRIBUTE_CONTACT_EMAIL); - ccall = (contact & SILC_ATTRIBUTE_CONTACT_CALL); - csms = (contact & SILC_ATTRIBUTE_CONTACT_SMS); - cmms = (contact & SILC_ATTRIBUTE_CONTACT_MMS); - cchat = (contact & SILC_ATTRIBUTE_CONTACT_CHAT); - cvideo = (contact & SILC_ATTRIBUTE_CONTACT_VIDEO); - } - - if (silc_hash_table_find(attrs, - SILC_32_TO_PTR(SILC_ATTRIBUTE_STATUS_FREETEXT), - NULL, (void *)&attr)) - silc_attribute_get_object(attr, &status, sizeof(status)); - - if (!silc_hash_table_find(attrs, - SILC_32_TO_PTR(SILC_ATTRIBUTE_DEVICE_INFO), - NULL, (void *)&attr)) - device = FALSE; - } - - fields = purple_request_fields_new(); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_label_new("l3", _("Your Current Mood")); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_normal", _("Normal"), mnormal); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_happy", _("Happy"), mhappy); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_sad", _("Sad"), msad); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_angry", _("Angry"), mangry); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_jealous", _("Jealous"), mjealous); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_ashamed", _("Ashamed"), mashamed); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_invincible", _("Invincible"), minvincible); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_inlove", _("In love"), minlove); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_sleepy", _("Sleepy"), msleepy); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_bored", _("Bored"), mbored); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_excited", _("Excited"), mexcited); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("mood_anxious", _("Anxious"), manxious); - purple_request_field_group_add_field(g, f); - - f = purple_request_field_label_new("l4", _("\nYour Preferred Contact Methods")); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("contact_chat", _("Chat"), cchat); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("contact_email", _("Email"), cemail); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("contact_call", _("Phone"), ccall); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("contact_sms", _("SMS"), csms); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("contact_mms", _("MMS"), cmms); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("contact_video", _("Video conferencing"), cvideo); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("status_text", _("Your Current Status"), - status[0] ? status : NULL, TRUE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g = purple_request_field_group_new(NULL); -#if 0 - f = purple_request_field_label_new("l2", _("Online Services")); - purple_request_field_group_add_field(g, f); - f = purple_request_field_bool_new("services", - _("Let others see what services you are using"), - TRUE); - purple_request_field_group_add_field(g, f); -#endif -#ifdef HAVE_SYS_UTSNAME_H - f = purple_request_field_bool_new("device", - _("Let others see what computer you are using"), - device); - purple_request_field_group_add_field(g, f); -#endif - purple_request_fields_add_group(fields, g); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("vcard", _("Your VCard File"), - purple_account_get_string(sg->account, "vcard", ""), - FALSE); - purple_request_field_group_add_field(g, f); -#ifdef _WIN32 - f = purple_request_field_string_new("timezone", _("Timezone"), _tzname[0], FALSE); -#else - f = purple_request_field_string_new("timezone", _("Timezone"), tzname[0], FALSE); -#endif - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - purple_request_fields(gc, _("User Online Status Attributes"), - _("User Online Status Attributes"), - _("You can let other users see your online status information " - "and your personal information. Please fill the information " - "you would like other users to see about yourself."), - fields, - _("OK"), G_CALLBACK(silcpurple_attrs_cb), - _("Cancel"), G_CALLBACK(silcpurple_attrs_cancel), - gc->account, NULL, NULL, gc); -} - -static void -silcpurple_detach(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - SilcPurple sg; - - if (!gc) - return; - sg = gc->proto_data; - if (!sg) - return; - - /* Call DETACH */ - silc_client_command_call(sg->client, sg->conn, "DETACH"); - sg->detaching = TRUE; -} - -static void -silcpurple_view_motd(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - SilcPurple sg; - char *tmp; - - if (!gc) - return; - sg = gc->proto_data; - if (!sg) - return; - - if (!sg->motd) { - purple_notify_error( - gc, _("Message of the Day"), _("No Message of the Day available"), - _("There is no Message of the Day associated with this connection")); - return; - } - - tmp = g_markup_escape_text(sg->motd, -1); - purple_notify_formatted(gc, NULL, _("Message of the Day"), NULL, - tmp, NULL, NULL); - g_free(tmp); -} - -static void -silcpurple_create_keypair_cancel(PurpleConnection *gc, PurpleRequestFields *fields) -{ - /* Nothing */ -} - -static void -silcpurple_create_keypair_cb(PurpleConnection *gc, PurpleRequestFields *fields) -{ - SilcPurple sg = gc->proto_data; - PurpleRequestField *f; - const char *val, *pkfile = NULL, *prfile = NULL; - const char *pass1 = NULL, *pass2 = NULL, *un = NULL, *hn = NULL; - const char *rn = NULL, *e = NULL, *o = NULL, *c = NULL; - char *identifier; - int keylen = SILCPURPLE_DEF_PKCS_LEN; - SilcPublicKey public_key; - - sg = gc->proto_data; - if (!sg) - return; - - val = NULL; - f = purple_request_fields_get_field(fields, "pass1"); - if (f) - val = purple_request_field_string_get_value(f); - if (val && *val) - pass1 = val; - else - pass1 = ""; - val = NULL; - f = purple_request_fields_get_field(fields, "pass2"); - if (f) - val = purple_request_field_string_get_value(f); - if (val && *val) - pass2 = val; - else - pass2 = ""; - - if (strcmp(pass1, pass2)) { - purple_notify_error( - gc, _("Create New SILC Key Pair"), _("Passphrases do not match"), NULL); - return; - } - - val = NULL; - f = purple_request_fields_get_field(fields, "key"); - if (f) - val = purple_request_field_string_get_value(f); - if (val && *val) - keylen = atoi(val); - f = purple_request_fields_get_field(fields, "pkfile"); - if (f) - pkfile = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "prfile"); - if (f) - prfile = purple_request_field_string_get_value(f); - - f = purple_request_fields_get_field(fields, "un"); - if (f) - un = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "hn"); - if (f) - hn = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "rn"); - if (f) - rn = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "e"); - if (f) - e = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "o"); - if (f) - o = purple_request_field_string_get_value(f); - f = purple_request_fields_get_field(fields, "c"); - if (f) - c = purple_request_field_string_get_value(f); - - identifier = silc_pkcs_encode_identifier((char *)un, (char *)hn, - (char *)rn, (char *)e, (char *)o, (char *)c); - - /* Create the key pair */ - if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS, keylen, pkfile, prfile, - identifier, pass1, NULL, &public_key, NULL, - FALSE)) { - purple_notify_error( - gc, _("Create New SILC Key Pair"), _("Key Pair Generation failed"), NULL); - return; - } - - silcpurple_show_public_key(sg, NULL, public_key, NULL, NULL); - - silc_pkcs_public_key_free(public_key); - silc_free(identifier); -} - -static void -silcpurple_create_keypair(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - SilcPurple sg = gc->proto_data; - PurpleRequestFields *fields; - PurpleRequestFieldGroup *g; - PurpleRequestField *f; - const char *username, *realname; - char *hostname, **u; - char tmp[256], pkd[256], pkd2[256], prd[256], prd2[256]; - - username = purple_account_get_username(sg->account); - u = g_strsplit(username, "@", 2); - username = u[0]; - realname = purple_account_get_user_info(sg->account); - hostname = silc_net_localhost(); - g_snprintf(tmp, sizeof(tmp), "%s@%s", username, hostname); - - g_snprintf(pkd2, sizeof(pkd2), "%s" G_DIR_SEPARATOR_S"public_key.pub", silcpurple_silcdir()); - g_snprintf(prd2, sizeof(prd2), "%s" G_DIR_SEPARATOR_S"private_key.prv", silcpurple_silcdir()); - g_snprintf(pkd, sizeof(pkd) - 1, "%s", - purple_account_get_string(gc->account, "public-key", pkd2)); - g_snprintf(prd, sizeof(prd) - 1, "%s", - purple_account_get_string(gc->account, "private-key", prd2)); - - fields = purple_request_fields_new(); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("key", _("Key length"), "2048", FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("pkfile", _("Public key file"), pkd, FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("prfile", _("Private key file"), prd, FALSE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("un", _("Username"), username ? username : "", FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("hn", _("Hostname"), hostname ? hostname : "", FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("rn", _("Real name"), realname ? realname : "", FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("e", _("Email"), tmp, FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("o", _("Organization"), "", FALSE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("c", _("Country"), "", FALSE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - g = purple_request_field_group_new(NULL); - f = purple_request_field_string_new("pass1", _("Passphrase"), "", FALSE); - purple_request_field_string_set_masked(f, TRUE); - purple_request_field_group_add_field(g, f); - f = purple_request_field_string_new("pass2", _("Passphrase (retype)"), "", FALSE); - purple_request_field_string_set_masked(f, TRUE); - purple_request_field_group_add_field(g, f); - purple_request_fields_add_group(fields, g); - - purple_request_fields(gc, _("Create New SILC Key Pair"), - _("Create New SILC Key Pair"), NULL, fields, - _("Generate Key Pair"), G_CALLBACK(silcpurple_create_keypair_cb), - _("Cancel"), G_CALLBACK(silcpurple_create_keypair_cancel), - gc->account, NULL, NULL, gc); - - g_strfreev(u); - silc_free(hostname); -} - -static void -silcpurple_change_pass(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - purple_account_request_change_password(purple_connection_get_account(gc)); -} - -static void -silcpurple_change_passwd(PurpleConnection *gc, const char *old, const char *new) -{ - char prd[256]; - g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.pub", silcpurple_silcdir()); - silc_change_private_key_passphrase(purple_account_get_string(gc->account, - "private-key", - prd), old ? old : "", new ? new : ""); -} - -static void -silcpurple_show_set_info(PurplePluginAction *action) -{ - PurpleConnection *gc = (PurpleConnection *) action->context; - purple_account_request_change_user_info(purple_connection_get_account(gc)); -} - -static void -silcpurple_set_info(PurpleConnection *gc, const char *text) -{ -} - -static GList * -silcpurple_actions(PurplePlugin *plugin, gpointer context) -{ - GList *list = NULL; - PurplePluginAction *act; - - act = purple_plugin_action_new(_("Online Status"), - silcpurple_attrs); - list = g_list_append(list, act); - - act = purple_plugin_action_new(_("Detach From Server"), - silcpurple_detach); - list = g_list_append(list, act); - - act = purple_plugin_action_new(_("View Message of the Day"), - silcpurple_view_motd); - list = g_list_append(list, act); - - act = purple_plugin_action_new(_("Create SILC Key Pair..."), - silcpurple_create_keypair); - list = g_list_append(list, act); - - act = purple_plugin_action_new(_("Change Password..."), - silcpurple_change_pass); - list = g_list_append(list, act); - - act = purple_plugin_action_new(_("Set User Info..."), - silcpurple_show_set_info); - list = g_list_append(list, act); - - return list; -} - - -/******************************* IM Routines *********************************/ - -typedef struct { - char *nick; - char *message; - SilcUInt32 message_len; - SilcMessageFlags flags; - PurpleMessageFlags gflags; -} *SilcPurpleIM; - -static void -silcpurple_send_im_resolved(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - PurpleConnection *gc = client->application; - SilcPurple sg = gc->proto_data; - SilcPurpleIM im = context; - PurpleConversation *convo; - char tmp[256], *nickname = NULL; - SilcClientEntry client_entry; -#ifdef HAVE_SILCMIME_H - SilcDList list; -#endif - - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, im->nick, - sg->account); - if (!convo) - return; - - if (!clients) - goto err; - - if (clients_count > 1) { - silc_parse_userfqdn(im->nick, &nickname, NULL); - - /* Find the correct one. The im->nick might be a formatted nick - so this will find the correct one. */ - clients = silc_client_get_clients_local(client, conn, - nickname, im->nick, - &clients_count); - if (!clients) - goto err; - client_entry = clients[0]; - silc_free(clients); - } else { - client_entry = clients[0]; - } - -#ifdef HAVE_SILCMIME_H - /* Check for images */ - if (im->gflags & PURPLE_MESSAGE_IMAGES) { - list = silcpurple_image_message(im->message, (SilcUInt32 *)&im->flags); - if (list) { - /* Send one or more MIME message. If more than one, they - are MIME fragments due to over large message */ - SilcBuffer buf; - - silc_dlist_start(list); - while ((buf = silc_dlist_get(list)) != SILC_LIST_END) - silc_client_send_private_message(client, conn, - client_entry, im->flags, - buf->data, buf->len, - TRUE); - silc_mime_partial_free(list); - purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname, - im->message, 0, time(NULL)); - goto out; - } - } -#endif - - /* Send the message */ - silc_client_send_private_message(client, conn, client_entry, im->flags, - (unsigned char *)im->message, im->message_len, TRUE); - purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname, - im->message, 0, time(NULL)); - goto out; - - err: - g_snprintf(tmp, sizeof(tmp), - _("User %s is not present in the network"), im->nick); - purple_conversation_write(convo, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); - - out: - g_free(im->nick); - g_free(im->message); - silc_free(im); - silc_free(nickname); -} - -static int -silcpurple_send_im(PurpleConnection *gc, const char *who, const char *message, - PurpleMessageFlags flags) -{ - SilcPurple sg = gc->proto_data; - SilcClient client = sg->client; - SilcClientConnection conn = sg->conn; - SilcClientEntry *clients; - SilcUInt32 clients_count, mflags; - char *nickname, *msg, *tmp; - int ret = 0; - gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE); -#ifdef HAVE_SILCMIME_H - SilcDList list; -#endif - - if (!who || !message) - return 0; - - mflags = SILC_MESSAGE_FLAG_UTF8; - - tmp = msg = purple_unescape_html(message); - - if (!g_ascii_strncasecmp(msg, "/me ", 4)) { - msg += 4; - if (!*msg) { - g_free(tmp); - return 0; - } - mflags |= SILC_MESSAGE_FLAG_ACTION; - } else if (strlen(msg) > 1 && msg[0] == '/') { - if (!silc_client_command_call(client, conn, msg + 1)) - purple_notify_error(gc, _("Call Command"), _("Cannot call command"), - _("Unknown command")); - g_free(tmp); - return 0; - } - - - if (!silc_parse_userfqdn(who, &nickname, NULL)) { - g_free(tmp); - return 0; - } - - if (sign) - mflags |= SILC_MESSAGE_FLAG_SIGNED; - - /* Find client entry */ - clients = silc_client_get_clients_local(client, conn, nickname, who, - &clients_count); - if (!clients) { - /* Resolve unknown user */ - SilcPurpleIM im = silc_calloc(1, sizeof(*im)); - if (!im) { - g_free(tmp); - return 0; - } - im->nick = g_strdup(who); - im->message = g_strdup(message); - im->message_len = strlen(im->message); - im->flags = mflags; - im->gflags = flags; - silc_client_get_clients(client, conn, nickname, NULL, - silcpurple_send_im_resolved, im); - silc_free(nickname); - g_free(tmp); - return 0; - } - -#ifdef HAVE_SILCMIME_H - /* Check for images */ - if (flags & PURPLE_MESSAGE_IMAGES) { - list = silcpurple_image_message(message, &mflags); - if (list) { - /* Send one or more MIME message. If more than one, they - are MIME fragments due to over large message */ - SilcBuffer buf; - - silc_dlist_start(list); - while ((buf = silc_dlist_get(list)) != SILC_LIST_END) - ret = - silc_client_send_private_message(client, conn, - clients[0], mflags, - buf->data, buf->len, - TRUE); - silc_mime_partial_free(list); - g_free(tmp); - silc_free(nickname); - silc_free(clients); - return ret; - } - } -#endif - - /* Send private message directly */ - ret = silc_client_send_private_message(client, conn, clients[0], - mflags, - (unsigned char *)msg, - strlen(msg), TRUE); - - g_free(tmp); - silc_free(nickname); - silc_free(clients); - return ret; -} - - -static GList *silcpurple_blist_node_menu(PurpleBlistNode *node) { - /* split this single menu building function back into the two - original: one for buddies and one for chats */ - - if(PURPLE_BLIST_NODE_IS_CHAT(node)) { - return silcpurple_chat_menu((PurpleChat *) node); - } else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { - return silcpurple_buddy_menu((PurpleBuddy *) node); - } else { - g_return_val_if_reached(NULL); - } -} - -/********************************* Commands **********************************/ - -static PurpleCmdRet silcpurple_cmd_chat_part(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - PurpleConversation *convo = conv; - int id = 0; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - if(args && args[0]) - convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[0], - gc->account); - - if (convo != NULL) - id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)); - - if (id == 0) - return PURPLE_CMD_RET_FAILED; - - silcpurple_chat_leave(gc, id); - - return PURPLE_CMD_RET_OK; - -} - -static PurpleCmdRet silcpurple_cmd_chat_topic(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - int id = 0; - char *buf, *tmp, *tmp2; - const char *topic; - - gc = purple_conversation_get_gc(conv); - id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)); - - if (gc == NULL || id == 0) - return PURPLE_CMD_RET_FAILED; - - if (!args || !args[0]) { - topic = purple_conv_chat_get_topic (PURPLE_CONV_CHAT(conv)); - if (topic) { - tmp = g_markup_escape_text(topic, -1); - tmp2 = purple_markup_linkify(tmp); - buf = g_strdup_printf(_("current topic is: %s"), tmp2); - g_free(tmp); - g_free(tmp2); - } else - buf = g_strdup(_("No topic is set")); - purple_conv_chat_write(PURPLE_CONV_CHAT(conv), gc->account->username, buf, - PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); - g_free(buf); - - } - - if (args && args[0] && (strlen(args[0]) > 255)) { - *error = g_strdup(_("Topic too long")); - return PURPLE_CMD_RET_FAILED; - } - - silcpurple_chat_set_topic(gc, id, args ? args[0] : NULL); - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_chat_join(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - GHashTable *comp; - - if(!args || !args[0]) - return PURPLE_CMD_RET_FAILED; - - comp = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); - - g_hash_table_replace(comp, "channel", args[0]); - if(args[1]) - g_hash_table_replace(comp, "passphrase", args[1]); - - silcpurple_chat_join(purple_conversation_get_gc(conv), comp); - - g_hash_table_destroy(comp); - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_chat_list(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - gc = purple_conversation_get_gc(conv); - purple_roomlist_show_with_account(purple_connection_get_account(gc)); - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_whois(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - silcpurple_get_info(gc, args[0]); - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_msg(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - int ret; - PurpleConnection *gc; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - ret = silcpurple_send_im(gc, args[0], args[1], PURPLE_MESSAGE_SEND); - - if (ret) - return PURPLE_CMD_RET_OK; - else - return PURPLE_CMD_RET_FAILED; -} - -static PurpleCmdRet silcpurple_cmd_query(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - int ret = 1; - PurpleConversation *convo; - PurpleConnection *gc; - PurpleAccount *account; - - if (!args || !args[0]) { - *error = g_strdup(_("You must specify a nick")); - return PURPLE_CMD_RET_FAILED; - } - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - account = purple_connection_get_account(gc); - - convo = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, args[0]); - - if (args[1]) { - ret = silcpurple_send_im(gc, args[0], args[1], PURPLE_MESSAGE_SEND); - purple_conv_im_write(PURPLE_CONV_IM(convo), purple_connection_get_display_name(gc), - args[1], PURPLE_MESSAGE_SEND, time(NULL)); - } - - if (ret) - return PURPLE_CMD_RET_OK; - else - return PURPLE_CMD_RET_FAILED; -} - -static PurpleCmdRet silcpurple_cmd_motd(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - SilcPurple sg; - char *tmp; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = gc->proto_data; - - if (sg == NULL) - return PURPLE_CMD_RET_FAILED; - - if (!sg->motd) { - *error = g_strdup(_("There is no Message of the Day associated with this connection")); - return PURPLE_CMD_RET_FAILED; - } - - tmp = g_markup_escape_text(sg->motd, -1); - purple_notify_formatted(gc, NULL, _("Message of the Day"), NULL, - tmp, NULL, NULL); - g_free(tmp); - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_detach(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - SilcPurple sg; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = gc->proto_data; - - if (sg == NULL) - return PURPLE_CMD_RET_FAILED; - - silc_client_command_call(sg->client, sg->conn, "DETACH"); - sg->detaching = TRUE; - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_cmode(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - SilcPurple sg; - SilcChannelEntry channel; - char *silccmd, *silcargs, *msg, tmp[256]; - const char *chname; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL || !args || gc->proto_data == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = gc->proto_data; - - if (args[0]) - chname = args[0]; - else - chname = purple_conversation_get_name(conv); - - if (!args[1]) { - channel = silc_client_get_channel(sg->client, sg->conn, - (char *)chname); - if (!channel) { - *error = g_strdup_printf(_("channel %s not found"), chname); - return PURPLE_CMD_RET_FAILED; - } - if (channel->mode) { - silcpurple_get_chmode_string(channel->mode, tmp, sizeof(tmp)); - msg = g_strdup_printf(_("channel modes for %s: %s"), chname, tmp); - } else { - msg = g_strdup_printf(_("no channel modes are set on %s"), chname); - } - purple_conv_chat_write(PURPLE_CONV_CHAT(conv), "", - msg, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL)); - g_free(msg); - return PURPLE_CMD_RET_OK; - } - - silcargs = g_strjoinv(" ", args); - silccmd = g_strconcat(cmd, " ", args ? silcargs : NULL, NULL); - g_free(silcargs); - if (!silc_client_command_call(sg->client, sg->conn, silccmd)) { - g_free(silccmd); - *error = g_strdup_printf(_("Failed to set cmodes for %s"), args[0]); - return PURPLE_CMD_RET_FAILED; - } - g_free(silccmd); - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_generic(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - SilcPurple sg; - char *silccmd, *silcargs; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = gc->proto_data; - - if (sg == NULL) - return PURPLE_CMD_RET_FAILED; - - silcargs = g_strjoinv(" ", args); - silccmd = g_strconcat(cmd, " ", args ? silcargs : NULL, NULL); - g_free(silcargs); - if (!silc_client_command_call(sg->client, sg->conn, silccmd)) { - g_free(silccmd); - *error = g_strdup_printf(_("Unknown command: %s, (may be a client bug)"), cmd); - return PURPLE_CMD_RET_FAILED; - } - g_free(silccmd); - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_quit(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - SilcPurple sg; - GHashTable *ui_info; - const char *ui_name = NULL, *ui_website = NULL; - char *quit_msg; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = gc->proto_data; - - if (sg == NULL) - return PURPLE_CMD_RET_FAILED; - - ui_info = purple_core_get_ui_info(); - - if(ui_info) { - ui_name = g_hash_table_lookup(ui_info, "name"); - ui_website = g_hash_table_lookup(ui_info, "website"); - } - - if(!ui_name || !ui_website) { - ui_name = "Pidgin"; - ui_website = PURPLE_WEBSITE; - } - quit_msg = g_strdup_printf(_("Download %s: %s"), - ui_name, ui_website); - - silc_client_command_call(sg->client, sg->conn, NULL, - "QUIT", (args && args[0]) ? args[0] : quit_msg, NULL); - g_free(quit_msg); - - return PURPLE_CMD_RET_OK; -} - -static PurpleCmdRet silcpurple_cmd_call(PurpleConversation *conv, - const char *cmd, char **args, char **error, void *data) -{ - PurpleConnection *gc; - SilcPurple sg; - - gc = purple_conversation_get_gc(conv); - - if (gc == NULL) - return PURPLE_CMD_RET_FAILED; - - sg = gc->proto_data; - - if (sg == NULL) - return PURPLE_CMD_RET_FAILED; - - if (!silc_client_command_call(sg->client, sg->conn, args[0])) { - *error = g_strdup_printf(_("Unknown command: %s"), args[0]); - return PURPLE_CMD_RET_FAILED; - } - - return PURPLE_CMD_RET_OK; -} - - -/************************** Plugin Initialization ****************************/ - -static void -silcpurple_register_commands(void) -{ - purple_cmd_register("part", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, - "prpl-silc", silcpurple_cmd_chat_part, _("part [channel]: Leave the chat"), NULL); - purple_cmd_register("leave", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, - "prpl-silc", silcpurple_cmd_chat_part, _("leave [channel]: Leave the chat"), NULL); - purple_cmd_register("topic", "s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", - silcpurple_cmd_chat_topic, _("topic [<new topic>]: View or change the topic"), NULL); - purple_cmd_register("join", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, - "prpl-silc", silcpurple_cmd_chat_join, - _("join <channel> [<password>]: Join a chat on this network"), NULL); - purple_cmd_register("list", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", - silcpurple_cmd_chat_list, _("list: List channels on this network"), NULL); - purple_cmd_register("whois", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", - silcpurple_cmd_whois, _("whois <nick>: View nick's information"), NULL); - purple_cmd_register("msg", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_msg, - _("msg <nick> <message>: Send a private message to a user"), NULL); - purple_cmd_register("query", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_query, - _("query <nick> [<message>]: Send a private message to a user"), NULL); - purple_cmd_register("motd", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_motd, - _("motd: View the server's Message Of The Day"), NULL); - purple_cmd_register("detach", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_detach, - _("detach: Detach this session"), NULL); - purple_cmd_register("quit", "s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_quit, - _("quit [message]: Disconnect from the server, with an optional message"), NULL); - purple_cmd_register("call", "s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_call, - _("call <command>: Call any silc client command"), NULL); - /* These below just get passed through for the silc client library to deal - * with */ - purple_cmd_register("kill", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("kill <nick> [-pubkey|<reason>]: Kill nick"), NULL); - purple_cmd_register("nick", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("nick <newnick>: Change your nickname"), NULL); - purple_cmd_register("whowas", "ww", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("whowas <nick>: View nick's information"), NULL); - purple_cmd_register("cmode", "wws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_cmode, - _("cmode <channel> [+|-<modes>] [arguments]: Change or display channel modes"), NULL); - purple_cmd_register("cumode", "wws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("cumode <channel> +|-<modes> <nick>: Change nick's modes on channel"), NULL); - purple_cmd_register("umode", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("umode <usermodes>: Set your modes in the network"), NULL); - purple_cmd_register("oper", "s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("oper <nick> [-pubkey]: Get server operator privileges"), NULL); - purple_cmd_register("invite", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("invite <channel> [-|+]<nick>: invite nick or add/remove from channel invite list"), NULL); - purple_cmd_register("kick", "wws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("kick <channel> <nick> [comment]: Kick client from channel"), NULL); - purple_cmd_register("info", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("info [server]: View server administrative details"), NULL); - purple_cmd_register("ban", "ww", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic, - _("ban [<channel> +|-<nick>]: Ban client from channel"), NULL); - purple_cmd_register("getkey", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("getkey <nick|server>: Retrieve client's or server's public key"), NULL); - purple_cmd_register("stats", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("stats: View server and network statistics"), NULL); - purple_cmd_register("ping", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_generic, - _("ping: Send PING to the connected server"), NULL); -#if 0 /* Purple doesn't handle these yet */ - purple_cmd_register("users", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, - "prpl-silc", silcpurple_cmd_users, - _("users <channel>: List users in channel")); - purple_cmd_register("names", "ww", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | - PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_names, - _("names [-count|-ops|-halfops|-voices|-normal] <channel(s)>: List specific users in channel(s)")); -#endif -} - -static PurpleWhiteboardPrplOps silcpurple_wb_ops = -{ - silcpurple_wb_start, - silcpurple_wb_end, - silcpurple_wb_get_dimensions, - silcpurple_wb_set_dimensions, - silcpurple_wb_get_brush, - silcpurple_wb_set_brush, - silcpurple_wb_send, - silcpurple_wb_clear, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - -static PurplePluginProtocolInfo prpl_info = -{ -#ifdef HAVE_SILCMIME_H - OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | - OPT_PROTO_PASSWORD_OPTIONAL | OPT_PROTO_IM_IMAGE | - OPT_PROTO_SLASH_COMMANDS_NATIVE, -#else - OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | - OPT_PROTO_PASSWORD_OPTIONAL | - OPT_PROTO_SLASH_COMMANDS_NATIVE, -#endif - NULL, /* user_splits */ - NULL, /* protocol_options */ -#ifdef SILC_ATTRIBUTE_USER_ICON - {"jpeg,gif,png,bmp", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ -#else - NO_BUDDY_ICONS, -#endif - silcpurple_list_icon, /* list_icon */ - NULL, /* list_emblems */ - silcpurple_status_text, /* status_text */ - silcpurple_tooltip_text, /* tooltip_text */ - silcpurple_away_states, /* away_states */ - silcpurple_blist_node_menu, /* blist_node_menu */ - silcpurple_chat_info, /* chat_info */ - silcpurple_chat_info_defaults,/* chat_info_defaults */ - silcpurple_login, /* login */ - silcpurple_close, /* close */ - silcpurple_send_im, /* send_im */ - silcpurple_set_info, /* set_info */ - NULL, /* send_typing */ - silcpurple_get_info, /* get_info */ - silcpurple_set_status, /* set_status */ - silcpurple_idle_set, /* set_idle */ - silcpurple_change_passwd, /* change_passwd */ - silcpurple_add_buddy, /* add_buddy */ - NULL, /* add_buddies */ - silcpurple_remove_buddy, /* remove_buddy */ - NULL, /* remove_buddies */ - NULL, /* add_permit */ - NULL, /* add_deny */ - NULL, /* rem_permit */ - NULL, /* rem_deny */ - NULL, /* set_permit_deny */ - silcpurple_chat_join, /* join_chat */ - NULL, /* reject_chat */ - silcpurple_get_chat_name, /* get_chat_name */ - silcpurple_chat_invite, /* chat_invite */ - silcpurple_chat_leave, /* chat_leave */ - NULL, /* chat_whisper */ - silcpurple_chat_send, /* chat_send */ - silcpurple_keepalive, /* keepalive */ - NULL, /* register_user */ - NULL, /* get_cb_info */ - NULL, /* get_cb_away */ - NULL, /* alias_buddy */ - NULL, /* group_buddy */ - NULL, /* rename_group */ - NULL, /* buddy_free */ - NULL, /* convo_closed */ - NULL, /* normalize */ -#ifdef SILC_ATTRIBUTE_USER_ICON - silcpurple_buddy_set_icon, /* set_buddy_icon */ -#else - NULL, -#endif - NULL, /* remove_group */ - NULL, /* get_cb_real_name */ - silcpurple_chat_set_topic, /* set_chat_topic */ - NULL, /* find_blist_chat */ - silcpurple_roomlist_get_list, /* roomlist_get_list */ - silcpurple_roomlist_cancel, /* roomlist_cancel */ - NULL, /* roomlist_expand_category */ - NULL, /* can_receive_file */ - silcpurple_ftp_send_file, /* send_file */ - silcpurple_ftp_new_xfer, /* new_xfer */ - NULL, /* offline_message */ - &silcpurple_wb_ops, /* whiteboard_prpl_ops */ - NULL, /* send_raw */ - NULL, /* roomlist_room_serialize */ - NULL, /* unregister_user */ - NULL, /* send_attention */ - NULL, /* get_attention_types */ - sizeof(PurplePluginProtocolInfo), /* struct_size */ - NULL, /* get_account_text_table */ - NULL, /* initiate_media */ - NULL, /* get_media_caps */ - NULL, /* get_moods */ - NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - NULL, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ -}; - -static PurplePluginInfo info = -{ - PURPLE_PLUGIN_MAGIC, - PURPLE_MAJOR_VERSION, - PURPLE_MINOR_VERSION, - PURPLE_PLUGIN_PROTOCOL, /**< type */ - NULL, /**< ui_requirement */ - 0, /**< flags */ - NULL, /**< dependencies */ - PURPLE_PRIORITY_DEFAULT, /**< priority */ - - "prpl-silc", /**< id */ - "SILC", /**< name */ - "1.0", /**< version */ - /** summary */ - N_("SILC Protocol Plugin"), - /** description */ - N_("Secure Internet Live Conferencing (SILC) Protocol"), - "Pekka Riikonen", /**< author */ - "http://silcnet.org/", /**< homepage */ - - NULL, /**< load */ - NULL, /**< unload */ - NULL, /**< destroy */ - - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, /**< prefs_info */ - silcpurple_actions, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - -static void -init_plugin(PurplePlugin *plugin) -{ - PurpleAccountOption *option; - PurpleAccountUserSplit *split; - char tmp[256]; - int i; - PurpleKeyValuePair *kvp; - GList *list = NULL; - - silc_plugin = plugin; - - split = purple_account_user_split_new(_("Network"), "silcnet.org", '@'); - prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); - - /* Account options */ - option = purple_account_option_string_new(_("Connect server"), - "server", - "silc.silcnet.org"); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - option = purple_account_option_int_new(_("Port"), "port", 706); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir()); - option = purple_account_option_string_new(_("Public Key file"), - "public-key", tmp); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir()); - option = purple_account_option_string_new(_("Private Key file"), - "private-key", tmp); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - for (i = 0; silc_default_ciphers[i].name; i++) { - kvp = g_new0(PurpleKeyValuePair, 1); - kvp->key = g_strdup(silc_default_ciphers[i].name); - kvp->value = g_strdup(silc_default_ciphers[i].name); - list = g_list_append(list, kvp); - } - option = purple_account_option_list_new(_("Cipher"), "cipher", list); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - list = NULL; - for (i = 0; silc_default_hmacs[i].name; i++) { - kvp = g_new0(PurpleKeyValuePair, 1); - kvp->key = g_strdup(silc_default_hmacs[i].name); - kvp->value = g_strdup(silc_default_hmacs[i].name); - list = g_list_append(list, kvp); - } - option = purple_account_option_list_new(_("HMAC"), "hmac", list); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - option = purple_account_option_bool_new(_("Public key authentication"), - "pubkey-auth", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - option = purple_account_option_bool_new(_("Block IMs without Key Exchange"), - "block-ims", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - option = purple_account_option_bool_new(_("Block messages to whiteboard"), - "block-wb", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - option = purple_account_option_bool_new(_("Automatically open whiteboard"), - "open-wb", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - option = purple_account_option_bool_new(_("Digitally sign and verify all messages"), - "sign-verify", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - purple_prefs_remove("/plugins/prpl/silc"); - - silcpurple_register_commands(); - -#ifdef _WIN32 - silc_net_win32_init(); -#endif -} - -PURPLE_INIT_PLUGIN(silc10, init_plugin, info); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc10/silcpurple.h --- a/libpurple/protocols/silc10/silcpurple.h Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,173 +0,0 @@ -/* - - silcpurple.h - - Author: Pekka Riikonen - - Copyright (C) 2004 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#ifndef SILCPURPLE_H -#define SILCPURPLE_H - -/* Purple includes */ -#include "internal.h" -#include "account.h" -#include "accountopt.h" -#include "cmds.h" -#include "conversation.h" -#include "debug.h" -#include "ft.h" -#include "notify.h" -#include "prpl.h" -#include "request.h" -#include "roomlist.h" -#include "server.h" -#include "util.h" - -/* Default public and private key file names */ -#define SILCPURPLE_PUBLIC_KEY_NAME "public_key.pub" -#define SILCPURPLE_PRIVATE_KEY_NAME "private_key.prv" - -/* Default settings for creating key pair */ -#define SILCPURPLE_DEF_PKCS "rsa" -#define SILCPURPLE_DEF_PKCS_LEN 2048 - -#define SILCPURPLE_PRVGRP 0x001fffff - -/* Status IDs */ -#define SILCPURPLE_STATUS_ID_OFFLINE "offline" -#define SILCPURPLE_STATUS_ID_AVAILABLE "available" -#define SILCPURPLE_STATUS_ID_HYPER "hyper" -#define SILCPURPLE_STATUS_ID_AWAY "away" -#define SILCPURPLE_STATUS_ID_BUSY "busy" -#define SILCPURPLE_STATUS_ID_INDISPOSED "indisposed" -#define SILCPURPLE_STATUS_ID_PAGE "page" - -typedef struct { - unsigned long id; - const char *channel; - unsigned long chid; - const char *parentch; - SilcChannelPrivateKey key; -} *SilcPurplePrvgrp; - -/* The SILC Purple plugin context */ -typedef struct SilcPurpleStruct { - SilcClient client; - SilcClientConnection conn; - - guint scheduler; - PurpleConnection *gc; - PurpleAccount *account; - unsigned long channel_ids; - GList *grps; - - char *motd; - PurpleRoomlist *roomlist; -#ifdef HAVE_SILCMIME_H - SilcMimeAssembler mimeass; -#endif - unsigned int detaching : 1; - unsigned int resuming : 1; - unsigned int roomlist_cancelled : 1; - unsigned int chpk : 1; -} *SilcPurple; - - -gboolean silcpurple_check_silc_dir(PurpleConnection *gc); -void silcpurple_chat_join_done(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context); -const char *silcpurple_silcdir(void); -const char *silcpurple_session_file(const char *account); -void silcpurple_verify_public_key(SilcClient client, SilcClientConnection conn, - const char *name, SilcSocketType conn_type, - unsigned char *pk, SilcUInt32 pk_len, - SilcSKEPKType pk_type, - SilcVerifyPublicKey completion, void *context); -GList *silcpurple_buddy_menu(PurpleBuddy *buddy); -void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); -void silcpurple_send_buddylist(PurpleConnection *gc); -void silcpurple_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); -void silcpurple_buddy_keyagr_request(SilcClient client, - SilcClientConnection conn, - SilcClientEntry client_entry, - const char *hostname, SilcUInt16 port); -void silcpurple_idle_set(PurpleConnection *gc, int idle); -void silcpurple_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full); -char *silcpurple_status_text(PurpleBuddy *b); -gboolean silcpurple_ip_is_private(const char *ip); -void silcpurple_ftp_send_file(PurpleConnection *gc, const char *name, const char *file); -PurpleXfer *silcpurple_ftp_new_xfer(PurpleConnection *gc, const char *name); -void silcpurple_ftp_request(SilcClient client, SilcClientConnection conn, - SilcClientEntry client_entry, SilcUInt32 session_id, - const char *hostname, SilcUInt16 port); -void silcpurple_show_public_key(SilcPurple sg, - const char *name, SilcPublicKey public_key, - GCallback callback, void *context); -void silcpurple_get_info(PurpleConnection *gc, const char *who); -SilcAttributePayload -silcpurple_get_attr(SilcDList attrs, SilcAttribute attribute); -void silcpurple_get_umode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size); -void silcpurple_get_chmode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size); -void silcpurple_get_chumode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size); -GList *silcpurple_chat_info(PurpleConnection *gc); -GHashTable *silcpurple_chat_info_defaults(PurpleConnection *gc, const char *chat_name); -GList *silcpurple_chat_menu(PurpleChat *); -void silcpurple_chat_join(PurpleConnection *gc, GHashTable *data); -char *silcpurple_get_chat_name(GHashTable *data); -void silcpurple_chat_invite(PurpleConnection *gc, int id, const char *msg, - const char *name); -void silcpurple_chat_leave(PurpleConnection *gc, int id); -int silcpurple_chat_send(PurpleConnection *gc, int id, const char *msg, PurpleMessageFlags flags); -void silcpurple_chat_set_topic(PurpleConnection *gc, int id, const char *topic); -PurpleRoomlist *silcpurple_roomlist_get_list(PurpleConnection *gc); -void silcpurple_roomlist_cancel(PurpleRoomlist *list); -void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel, - SilcBuffer channel_pubkeys); -void silcpurple_parse_attrs(SilcDList attrs, char **moodstr, char **statusstr, - char **contactstr, char **langstr, char **devicestr, - char **tzstr, char **geostr); -#ifdef SILC_ATTRIBUTE_USER_ICON -void silcpurple_buddy_set_icon(PurpleConnection *gc, PurpleStoredImage *img); -#endif -#ifdef HAVE_SILCMIME_H -char *silcpurple_file2mime(const char *filename); -SilcDList silcpurple_image_message(const char *msg, SilcUInt32 *mflags); -#endif - -#ifdef _WIN32 -typedef int uid_t; - -struct passwd { - char *pw_name; /* user name */ - char *pw_passwd; /* user password */ - int pw_uid; /* user id */ - int pw_gid; /* group id */ - char *pw_gecos; /* real name */ - char *pw_dir; /* home directory */ - char *pw_shell; /* shell program */ -}; - -struct passwd *getpwuid(int uid); -int getuid(void); -int geteuid(void); -#endif - -#endif /* SILCPURPLE_H */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc10/util.c --- a/libpurple/protocols/silc10/util.c Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,776 +0,0 @@ -/* - - silcpurple_util.c - - Author: Pekka Riikonen - - Copyright (C) 2004 - 2005 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#include "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" -#include "imgstore.h" - -/**************************** Utility Routines *******************************/ - -static char str[256], str2[256]; - -const char *silcpurple_silcdir(void) -{ - const char *hd = purple_home_dir(); - memset(str, 0, sizeof(str)); - g_snprintf(str, sizeof(str) - 1, "%s" G_DIR_SEPARATOR_S ".silc", hd ? hd : "/tmp"); - return (const char *)str; -} - -const char *silcpurple_session_file(const char *account) -{ - memset(str2, 0, sizeof(str2)); - g_snprintf(str2, sizeof(str2) - 1, "%s" G_DIR_SEPARATOR_S "%s_session", - silcpurple_silcdir(), account); - return (const char *)str2; -} - -gboolean silcpurple_ip_is_private(const char *ip) -{ - if (silc_net_is_ip4(ip)) { - if (!strncmp(ip, "10.", 3)) { - return TRUE; - } else if (!strncmp(ip, "172.", 4) && strlen(ip) > 6) { - char tmp[3]; - int s; - memset(tmp, 0, sizeof(tmp)); - strncpy(tmp, ip + 4, 2); - s = atoi(tmp); - if (s >= 16 && s <= 31) - return TRUE; - } else if (!strncmp(ip, "192.168.", 8)) { - return TRUE; - } - } - - return FALSE; -} - -/* This checks stats for various SILC files and directories. First it - checks if ~/.silc directory exist and is owned by the correct user. If - it doesn't exist, it will create the directory. After that it checks if - user's Public and Private key files exists and creates them if needed. */ - -gboolean silcpurple_check_silc_dir(PurpleConnection *gc) -{ - char filename[256], file_public_key[256], file_private_key[256]; - char servfilename[256], clientfilename[256], friendsfilename[256]; - char pkd[256], prd[256]; - struct stat st; - struct passwd *pw; - int fd; - - pw = getpwuid(getuid()); - if (!pw) { - purple_debug_error("silc", "silc: %s\n", g_strerror(errno)); - return FALSE; - } - - g_snprintf(filename, sizeof(filename) - 1, "%s", silcpurple_silcdir()); - g_snprintf(servfilename, sizeof(servfilename) - 1, "%s" G_DIR_SEPARATOR_S "serverkeys", - silcpurple_silcdir()); - g_snprintf(clientfilename, sizeof(clientfilename) - 1, "%s" G_DIR_SEPARATOR_S "clientkeys", - silcpurple_silcdir()); - g_snprintf(friendsfilename, sizeof(friendsfilename) - 1, "%s" G_DIR_SEPARATOR_S "friends", - silcpurple_silcdir()); - - /* - * Check ~/.silc directory - */ - if ((g_stat(filename, &st)) == -1) { - /* If dir doesn't exist */ - if (errno == ENOENT) { - if (pw->pw_uid == geteuid()) { - if ((g_mkdir(filename, 0755)) == -1) { - purple_debug_error("silc", "Couldn't create '%s' directory\n", filename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n", - filename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", filename, g_strerror(errno)); - return FALSE; - } - } else { -#ifndef _WIN32 - /* Check the owner of the dir */ - if (st.st_uid != 0 && st.st_uid != pw->pw_uid) { - purple_debug_error("silc", "You don't seem to own '%s' directory\n", - filename); - return FALSE; - } -#endif - } - - /* - * Check ~./silc/serverkeys directory - */ - if ((g_stat(servfilename, &st)) == -1) { - /* If dir doesn't exist */ - if (errno == ENOENT) { - if (pw->pw_uid == geteuid()) { - if ((g_mkdir(servfilename, 0755)) == -1) { - purple_debug_error("silc", "Couldn't create '%s' directory\n", servfilename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n", - servfilename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", - servfilename, g_strerror(errno)); - return FALSE; - } - } - - /* - * Check ~./silc/clientkeys directory - */ - if ((g_stat(clientfilename, &st)) == -1) { - /* If dir doesn't exist */ - if (errno == ENOENT) { - if (pw->pw_uid == geteuid()) { - if ((g_mkdir(clientfilename, 0755)) == -1) { - purple_debug_error("silc", "Couldn't create '%s' directory\n", clientfilename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n", - clientfilename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", - clientfilename, g_strerror(errno)); - return FALSE; - } - } - - /* - * Check ~./silc/friends directory - */ - if ((g_stat(friendsfilename, &st)) == -1) { - /* If dir doesn't exist */ - if (errno == ENOENT) { - if (pw->pw_uid == geteuid()) { - if ((g_mkdir(friendsfilename, 0755)) == -1) { - purple_debug_error("silc", "Couldn't create '%s' directory\n", friendsfilename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n", - friendsfilename); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", - friendsfilename, g_strerror(errno)); - return FALSE; - } - } - - /* - * Check Public and Private keys - */ - g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir()); - g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir()); - g_snprintf(file_public_key, sizeof(file_public_key) - 1, "%s", - purple_account_get_string(gc->account, "public-key", pkd)); - g_snprintf(file_private_key, sizeof(file_public_key) - 1, "%s", - purple_account_get_string(gc->account, "private-key", prd)); - - if ((g_stat(file_public_key, &st)) == -1) { - /* If file doesn't exist */ - if (errno == ENOENT) { - purple_connection_update_progress(gc, _("Creating SILC key pair..."), 1, 5); - if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS, - SILCPURPLE_DEF_PKCS_LEN, - file_public_key, file_private_key, NULL, - (gc->password == NULL) ? "" : gc->password, - NULL, NULL, NULL, FALSE)) { - purple_debug_error("silc", "Couldn't create key pair\n"); - return FALSE; - } - - if ((g_stat(file_public_key, &st)) == -1) { - purple_debug_error("silc", "Couldn't stat '%s' public key, error: %s\n", - file_public_key, g_strerror(errno)); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't stat '%s' public key, error: %s\n", - file_public_key, g_strerror(errno)); - return FALSE; - } - } - -#ifndef _WIN32 - /* Check the owner of the public key */ - if (st.st_uid != 0 && st.st_uid != pw->pw_uid) { - purple_debug_error("silc", "You don't seem to own your public key!?\n"); - return FALSE; - } -#endif - - if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) { - if ((fstat(fd, &st)) == -1) { - purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n", - file_private_key, g_strerror(errno)); - close(fd); - return FALSE; - } - } else if ((g_stat(file_private_key, &st)) == -1) { - /* If file doesn't exist */ - if (errno == ENOENT) { - purple_connection_update_progress(gc, _("Creating SILC key pair..."), 1, 5); - if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS, - SILCPURPLE_DEF_PKCS_LEN, - file_public_key, file_private_key, NULL, - (gc->password == NULL) ? "" : gc->password, - NULL, NULL, NULL, FALSE)) { - purple_debug_error("silc", "Couldn't create key pair\n"); - return FALSE; - } - - if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) { - if ((fstat(fd, &st)) == -1) { - purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n", - file_private_key, g_strerror(errno)); - close(fd); - return FALSE; - } - } - /* This shouldn't really happen because silc_create_key_pair() - * will set the permissions */ - else if ((g_stat(file_private_key, &st)) == -1) { - purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n", - file_private_key, g_strerror(errno)); - return FALSE; - } - } else { - purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n", - file_private_key, g_strerror(errno)); - return FALSE; - } - } - -#ifndef _WIN32 - /* Check the owner of the private key */ - if (st.st_uid != 0 && st.st_uid != pw->pw_uid) { - purple_debug_error("silc", "You don't seem to own your private key!?\n"); - if (fd != -1) - close(fd); - return FALSE; - } - - /* Check the permissions for the private key */ - if ((st.st_mode & 0777) != 0600) { - purple_debug_warning("silc", "Wrong permissions in your private key file `%s'!\n" - "Trying to change them ...\n", file_private_key); - if ((fd == -1) || (fchmod(fd, S_IRUSR | S_IWUSR)) == -1) { - purple_debug_error("silc", - "Failed to change permissions for private key file!\n" - "Permissions for your private key file must be 0600.\n"); - if (fd != -1) - close(fd); - return FALSE; - } - purple_debug_warning("silc", "Done.\n\n"); - } -#endif - - if (fd != -1) - close(fd); - - return TRUE; -} - -#ifdef _WIN32 -struct passwd *getpwuid(uid_t uid) { - struct passwd *pwd = calloc(1, sizeof(struct passwd)); - return pwd; -} - -uid_t getuid() { - return 0; -} - -uid_t geteuid() { - return 0; -} -#endif - -void silcpurple_show_public_key(SilcPurple sg, - const char *name, SilcPublicKey public_key, - GCallback callback, void *context) -{ - SilcPublicKeyIdentifier ident; - SilcPKCS pkcs; - char *fingerprint, *babbleprint; - unsigned char *pk; - SilcUInt32 pk_len, key_len = 0; - GString *s; - char *buf; - - ident = silc_pkcs_decode_identifier(public_key->identifier); - if (!ident) - return; - - pk = silc_pkcs_public_key_encode(public_key, &pk_len); - fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); - babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); - - if (silc_pkcs_alloc((unsigned char *)public_key->name, &pkcs)) { - key_len = silc_pkcs_public_key_set(pkcs, public_key); - silc_pkcs_free(pkcs); - } - - s = g_string_new(""); - if (ident->realname) - /* Hint for translators: Please check the tabulator width here and in - the next strings (short strings: 2 tabs, longer strings 1 tab, - sum: 3 tabs or 24 characters) */ - g_string_append_printf(s, _("Real Name: \t%s\n"), ident->realname); - if (ident->username) - g_string_append_printf(s, _("User Name: \t%s\n"), ident->username); - if (ident->email) - g_string_append_printf(s, _("Email: \t\t%s\n"), ident->email); - if (ident->host) - g_string_append_printf(s, _("Host Name: \t%s\n"), ident->host); - if (ident->org) - g_string_append_printf(s, _("Organization: \t%s\n"), ident->org); - if (ident->country) - g_string_append_printf(s, _("Country: \t%s\n"), ident->country); - g_string_append_printf(s, _("Algorithm: \t%s\n"), public_key->name); - g_string_append_printf(s, _("Key Length: \t%d bits\n"), (int)key_len); - g_string_append_printf(s, "\n"); - g_string_append_printf(s, _("Public Key Fingerprint:\n%s\n\n"), fingerprint); - g_string_append_printf(s, _("Public Key Babbleprint:\n%s"), babbleprint); - - buf = g_string_free(s, FALSE); - - purple_request_action(sg->gc, _("Public Key Information"), - _("Public Key Information"), - buf, 0, purple_connection_get_account(sg->gc), - NULL, NULL, context, 1, _("Close"), callback); - - g_free(buf); - silc_free(fingerprint); - silc_free(babbleprint); - silc_free(pk); - silc_pkcs_free_identifier(ident); -} - -SilcAttributePayload -silcpurple_get_attr(SilcDList attrs, SilcAttribute attribute) -{ - SilcAttributePayload attr = NULL; - - if (!attrs) - return NULL; - - silc_dlist_start(attrs); - while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) - if (attribute == silc_attribute_get_attribute(attr)) - break; - - return attr; -} - -void silcpurple_get_umode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size) -{ - memset(buf, 0, buf_size); - if ((mode & SILC_UMODE_SERVER_OPERATOR) || - (mode & SILC_UMODE_ROUTER_OPERATOR)) { - strcat(buf, (mode & SILC_UMODE_SERVER_OPERATOR) ? - "[server operator] " : - (mode & SILC_UMODE_ROUTER_OPERATOR) ? - "[SILC operator] " : "[unknown mode] "); - } - if (mode & SILC_UMODE_GONE) - strcat(buf, "[away] "); - if (mode & SILC_UMODE_INDISPOSED) - strcat(buf, "[indisposed] "); - if (mode & SILC_UMODE_BUSY) - strcat(buf, "[busy] "); - if (mode & SILC_UMODE_PAGE) - strcat(buf, "[wake me up] "); - if (mode & SILC_UMODE_HYPER) - strcat(buf, "[hyperactive] "); - if (mode & SILC_UMODE_ROBOT) - strcat(buf, "[robot] "); - if (mode & SILC_UMODE_ANONYMOUS) - strcat(buf, "[anonymous] "); - if (mode & SILC_UMODE_BLOCK_PRIVMSG) - strcat(buf, "[blocks private messages] "); - if (mode & SILC_UMODE_DETACHED) - strcat(buf, "[detached] "); - if (mode & SILC_UMODE_REJECT_WATCHING) - strcat(buf, "[rejects watching] "); - if (mode & SILC_UMODE_BLOCK_INVITE) - strcat(buf, "[blocks invites] "); - g_strchomp(buf); -} - -void silcpurple_get_chmode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size) -{ - memset(buf, 0, buf_size); - if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) - strcat(buf, "[permanent] "); - if (mode & SILC_CHANNEL_MODE_PRIVATE) - strcat(buf, "[private] "); - if (mode & SILC_CHANNEL_MODE_SECRET) - strcat(buf, "[secret] "); - if (mode & SILC_CHANNEL_MODE_PRIVKEY) - strcat(buf, "[private key] "); - if (mode & SILC_CHANNEL_MODE_INVITE) - strcat(buf, "[invite only] "); - if (mode & SILC_CHANNEL_MODE_TOPIC) - strcat(buf, "[topic restricted] "); - if (mode & SILC_CHANNEL_MODE_ULIMIT) - strcat(buf, "[user count limit] "); - if (mode & SILC_CHANNEL_MODE_PASSPHRASE) - strcat(buf, "[passphrase auth] "); - if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) - strcat(buf, "[public key auth] "); - if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) - strcat(buf, "[users silenced] "); - if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) - strcat(buf, "[operators silenced] "); - g_strchomp(buf); -} - -void silcpurple_get_chumode_string(SilcUInt32 mode, char *buf, - SilcUInt32 buf_size) -{ - memset(buf, 0, buf_size); - if (mode & SILC_CHANNEL_UMODE_CHANFO) - strcat(buf, "[founder] "); - if (mode & SILC_CHANNEL_UMODE_CHANOP) - strcat(buf, "[operator] "); - if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) - strcat(buf, "[blocks messages] "); - if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) - strcat(buf, "[blocks user messages] "); - if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) - strcat(buf, "[blocks robot messages] "); - if (mode & SILC_CHANNEL_UMODE_QUIET) - strcat(buf, "[quieted] "); - g_strchomp(buf); -} - -void -silcpurple_parse_attrs(SilcDList attrs, char **moodstr, char **statusstr, - char **contactstr, char **langstr, char **devicestr, - char **tzstr, char **geostr) -{ - SilcAttributePayload attr; - SilcAttributeMood mood = 0; - SilcAttributeContact contact; - SilcAttributeObjDevice device; - SilcAttributeObjGeo geo; - - char tmp[1024]; - GString *s; - - *moodstr = NULL; - *statusstr = NULL; - *contactstr = NULL; - *langstr = NULL; - *devicestr = NULL; - *tzstr = NULL; - *geostr = NULL; - - if (!attrs) - return; - - s = g_string_new(""); - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_STATUS_MOOD); - if (attr && silc_attribute_get_object(attr, &mood, sizeof(mood))) { - if (mood & SILC_ATTRIBUTE_MOOD_HAPPY) - g_string_append_printf(s, "[%s] ", _("Happy")); - if (mood & SILC_ATTRIBUTE_MOOD_SAD) - g_string_append_printf(s, "[%s] ", _("Sad")); - if (mood & SILC_ATTRIBUTE_MOOD_ANGRY) - g_string_append_printf(s, "[%s] ", _("Angry")); - if (mood & SILC_ATTRIBUTE_MOOD_JEALOUS) - g_string_append_printf(s, "[%s] ", _("Jealous")); - if (mood & SILC_ATTRIBUTE_MOOD_ASHAMED) - g_string_append_printf(s, "[%s] ", _("Ashamed")); - if (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE) - g_string_append_printf(s, "[%s] ", _("Invincible")); - if (mood & SILC_ATTRIBUTE_MOOD_INLOVE) - g_string_append_printf(s, "[%s] ", _("In Love")); - if (mood & SILC_ATTRIBUTE_MOOD_SLEEPY) - g_string_append_printf(s, "[%s] ", _("Sleepy")); - if (mood & SILC_ATTRIBUTE_MOOD_BORED) - g_string_append_printf(s, "[%s] ", _("Bored")); - if (mood & SILC_ATTRIBUTE_MOOD_EXCITED) - g_string_append_printf(s, "[%s] ", _("Excited")); - if (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS) - g_string_append_printf(s, "[%s] ", _("Anxious")); - } - if (strlen(s->str)) { - *moodstr = s->str; - g_string_free(s, FALSE); - g_strchomp(*moodstr); - } else - g_string_free(s, TRUE); - - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_STATUS_FREETEXT); - memset(tmp, 0, sizeof(tmp)); - if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp))) - *statusstr = g_strdup(tmp); - - s = g_string_new(""); - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_PREFERRED_CONTACT); - if (attr && silc_attribute_get_object(attr, &contact, sizeof(contact))) { - if (contact & SILC_ATTRIBUTE_CONTACT_CHAT) - g_string_append_printf(s, "[%s] ", _("Chat")); - if (contact & SILC_ATTRIBUTE_CONTACT_EMAIL) - g_string_append_printf(s, "[%s] ", _("Email")); - if (contact & SILC_ATTRIBUTE_CONTACT_CALL) - g_string_append_printf(s, "[%s] ", _("Phone")); - if (contact & SILC_ATTRIBUTE_CONTACT_PAGE) - g_string_append_printf(s, "[%s] ", _("Paging")); - if (contact & SILC_ATTRIBUTE_CONTACT_SMS) - g_string_append_printf(s, "[%s] ", _("SMS")); - if (contact & SILC_ATTRIBUTE_CONTACT_MMS) - g_string_append_printf(s, "[%s] ", _("MMS")); - if (contact & SILC_ATTRIBUTE_CONTACT_VIDEO) - g_string_append_printf(s, "[%s] ", _("Video Conferencing")); - } - if (strlen(s->str)) { - *contactstr = s->str; - g_string_free(s, FALSE); - g_strchomp(*contactstr); - } else - g_string_free(s, TRUE); - - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_PREFERRED_LANGUAGE); - memset(tmp, 0, sizeof(tmp)); - if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp))) - *langstr = g_strdup(tmp); - - s = g_string_new(""); - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_DEVICE_INFO); - memset(&device, 0, sizeof(device)); - if (attr && silc_attribute_get_object(attr, &device, sizeof(device))) { - if (device.type == SILC_ATTRIBUTE_DEVICE_COMPUTER) - g_string_append_printf(s, "%s: ", _("Computer")); - if (device.type == SILC_ATTRIBUTE_DEVICE_MOBILE_PHONE) - g_string_append_printf(s, "%s: ", _("Mobile Phone")); - if (device.type == SILC_ATTRIBUTE_DEVICE_PDA) - g_string_append_printf(s, "%s: ", _("PDA")); - if (device.type == SILC_ATTRIBUTE_DEVICE_TERMINAL) - g_string_append_printf(s, "%s: ", _("Terminal")); - g_string_append_printf(s, "%s %s %s %s", - device.manufacturer ? device.manufacturer : "", - device.version ? device.version : "", - device.model ? device.model : "", - device.language ? device.language : ""); - } - if (strlen(s->str)) { - *devicestr = s->str; - g_string_free(s, FALSE); - } else - g_string_free(s, TRUE); - - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_TIMEZONE); - memset(tmp, 0, sizeof(tmp)); - if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp))) - *tzstr = g_strdup(tmp); - - attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_GEOLOCATION); - memset(&geo, 0, sizeof(geo)); - if (attr && silc_attribute_get_object(attr, &geo, sizeof(geo))) - *geostr = g_strdup_printf("%s %s %s (%s)", - geo.longitude ? geo.longitude : "", - geo.latitude ? geo.latitude : "", - geo.altitude ? geo.altitude : "", - geo.accuracy ? geo.accuracy : ""); -} - -#ifdef HAVE_SILCMIME_H -/* Returns MIME type of filetype */ - -char *silcpurple_file2mime(const char *filename) -{ - const char *ct; - - ct = strrchr(filename, '.'); - if (!ct) - return NULL; - else if (!g_ascii_strcasecmp(".png", ct)) - return strdup("image/png"); - else if (!g_ascii_strcasecmp(".jpg", ct)) - return strdup("image/jpeg"); - else if (!g_ascii_strcasecmp(".jpeg", ct)) - return strdup("image/jpeg"); - else if (!g_ascii_strcasecmp(".gif", ct)) - return strdup("image/gif"); - else if (!g_ascii_strcasecmp(".tiff", ct)) - return strdup("image/tiff"); - - return NULL; -} - -/* Checks if message has images, and assembles MIME message if it has. - If only one image is present, creates simple MIME image message. If - there are multiple images and/or text with images multipart MIME - message is created. */ - -SilcDList silcpurple_image_message(const char *msg, SilcUInt32 *mflags) -{ - SilcMime mime = NULL, p; - SilcDList list, parts = NULL; - const char *start, *end, *last; - GData *attribs; - char *type; - gboolean images = FALSE; - - last = msg; - while (last && *last && purple_markup_find_tag("img", last, &start, - &end, &attribs)) { - PurpleStoredImage *image = NULL; - const char *id; - - /* Check if there is text before image */ - if (start - last) { - char *text, *tmp; - p = silc_mime_alloc(); - - /* Add content type */ - silc_mime_add_field(p, "Content-Type", - "text/plain; charset=utf-8"); - - tmp = g_strndup(last, start - last); - text = purple_unescape_html(tmp); - g_free(tmp); - /* Add text */ - silc_mime_add_data(p, (unsigned char *)text, strlen(text)); - g_free(text); - - if (!parts) - parts = silc_dlist_init(); - silc_dlist_add(parts, p); - } - - id = g_datalist_get_data(&attribs, "id"); - if (id && (image = purple_imgstore_find_by_id(atoi(id)))) { - unsigned long imglen = purple_imgstore_get_size(image); - gconstpointer img = purple_imgstore_get_data(image); - - p = silc_mime_alloc(); - - /* Add content type */ - type = silcpurple_file2mime(purple_imgstore_get_filename(image)); - if (!type) { - g_datalist_clear(&attribs); - last = end + 1; - continue; - } - silc_mime_add_field(p, "Content-Type", type); - silc_free(type); - - /* Add content transfer encoding */ - silc_mime_add_field(p, "Content-Transfer-Encoding", "binary"); - - /* Add image data */ - silc_mime_add_data(p, img, imglen); - - if (!parts) - parts = silc_dlist_init(); - silc_dlist_add(parts, p); - images = TRUE; - } - - g_datalist_clear(&attribs); - - /* Continue after tag */ - last = end + 1; - } - - /* Check for text after the image(s) */ - if (images && last && *last) { - char *tmp = purple_unescape_html(last); - p = silc_mime_alloc(); - - /* Add content type */ - silc_mime_add_field(p, "Content-Type", - "text/plain; charset=utf-8"); - - /* Add text */ - silc_mime_add_data(p, (unsigned char *)tmp, strlen(tmp)); - g_free(tmp); - - if (!parts) - parts = silc_dlist_init(); - silc_dlist_add(parts, p); - } - - /* If there weren't any images, don't return anything. */ - if (!images) { - if (parts) - silc_dlist_uninit(parts); - return NULL; - } - - if (silc_dlist_count(parts) > 1) { - /* Multipart MIME message */ - char b[32]; - mime = silc_mime_alloc(); - silc_mime_add_field(mime, "MIME-Version", "1.0"); - g_snprintf(b, sizeof(b), "b%4X%4X", - (unsigned int)time(NULL), - silc_dlist_count(parts)); - silc_mime_set_multipart(mime, "mixed", b); - silc_dlist_start(parts); - while ((p = silc_dlist_get(parts)) != SILC_LIST_END) - silc_mime_add_multipart(mime, p); - } else { - /* Simple MIME message */ - silc_dlist_start(parts); - mime = silc_dlist_get(parts); - silc_mime_add_field(mime, "MIME-Version", "1.0"); - } - - *mflags &= ~SILC_MESSAGE_FLAG_UTF8; - *mflags |= SILC_MESSAGE_FLAG_DATA; - - /* Encode message. Fragment if it is too large */ - list = silc_mime_encode_partial(mime, 0xfc00); - - silc_dlist_uninit(parts); - - /* Added multiparts gets freed here */ - silc_mime_free(mime); - - return list; -} - -#endif /* HAVE_SILCMIME_H */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc10/wb.c --- a/libpurple/protocols/silc10/wb.c Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,520 +0,0 @@ -/* - - wb.c - - Author: Pekka Riikonen - - Copyright (C) 2005 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#include "silcincludes.h" -#include "silcclient.h" -#include "silcpurple.h" -#include "wb.h" - -/* - SILC Whiteboard packet: - - 1 byte command - 2 bytes width - 2 bytes height - 4 bytes brush color - 2 bytes brush size - n bytes data - - Data: - - 4 bytes x - 4 bytes y - - Commands: - - 0x01 draw - 0x02 clear - - MIME: - - MIME-Version: 1.0 - Content-Type: application/x-wb - Content-Transfer-Encoding: binary - -*/ - -#define SILCPURPLE_WB_MIME "MIME-Version: 1.0\r\nContent-Type: application/x-wb\r\nContent-Transfer-Encoding: binary\r\n\r\n" -#define SILCPURPLE_WB_HEADER strlen(SILCPURPLE_WB_MIME) + 11 - -#define SILCPURPLE_WB_WIDTH 500 -#define SILCPURPLE_WB_HEIGHT 400 -#define SILCPURPLE_WB_WIDTH_MAX 1024 -#define SILCPURPLE_WB_HEIGHT_MAX 1024 - -/* Commands */ -typedef enum { - SILCPURPLE_WB_DRAW = 0x01, - SILCPURPLE_WB_CLEAR = 0x02 -} SilcPurpleWbCommand; - -/* Brush size */ -typedef enum { - SILCPURPLE_WB_BRUSH_SMALL = 2, - SILCPURPLE_WB_BRUSH_MEDIUM = 5, - SILCPURPLE_WB_BRUSH_LARGE = 10 -} SilcPurpleWbBrushSize; - -/* Brush color (XXX Purple should provide default colors) */ -typedef enum { - SILCPURPLE_WB_COLOR_BLACK = 0, - SILCPURPLE_WB_COLOR_RED = 13369344, - SILCPURPLE_WB_COLOR_GREEN = 52224, - SILCPURPLE_WB_COLOR_BLUE = 204, - SILCPURPLE_WB_COLOR_YELLOW = 15658496, - SILCPURPLE_WB_COLOR_ORANGE = 16737792, - SILCPURPLE_WB_COLOR_CYAN = 52428, - SILCPURPLE_WB_COLOR_VIOLET = 5381277, - SILCPURPLE_WB_COLOR_PURPLE = 13369548, - SILCPURPLE_WB_COLOR_TAN = 12093547, - SILCPURPLE_WB_COLOR_BROWN = 5256485, - SILCPURPLE_WB_COLOR_GREY = 11184810, - SILCPURPLE_WB_COLOR_WHITE = 16777215 -} SilcPurpleWbColor; - -typedef struct { - int type; /* 0 = buddy, 1 = channel */ - union { - SilcClientEntry client; - SilcChannelEntry channel; - } u; - int width; - int height; - int brush_size; - int brush_color; -} *SilcPurpleWb; - -/* Initialize whiteboard */ - -PurpleWhiteboard *silcpurple_wb_init(SilcPurple sg, SilcClientEntry client_entry) -{ - SilcClientConnection conn; - PurpleWhiteboard *wb; - SilcPurpleWb wbs; - - conn = sg->conn; - wb = purple_whiteboard_get_session(sg->account, client_entry->nickname); - if (!wb) - wb = purple_whiteboard_create(sg->account, client_entry->nickname, 0); - if (!wb) - return NULL; - - if (!wb->proto_data) { - wbs = silc_calloc(1, sizeof(*wbs)); - if (!wbs) - return NULL; - wbs->type = 0; - wbs->u.client = client_entry; - wbs->width = SILCPURPLE_WB_WIDTH; - wbs->height = SILCPURPLE_WB_HEIGHT; - wbs->brush_size = SILCPURPLE_WB_BRUSH_SMALL; - wbs->brush_color = SILCPURPLE_WB_COLOR_BLACK; - wb->proto_data = wbs; - - /* Start the whiteboard */ - purple_whiteboard_start(wb); - purple_whiteboard_clear(wb); - } - - return wb; -} - -PurpleWhiteboard *silcpurple_wb_init_ch(SilcPurple sg, SilcChannelEntry channel) -{ - PurpleWhiteboard *wb; - SilcPurpleWb wbs; - - wb = purple_whiteboard_get_session(sg->account, channel->channel_name); - if (!wb) - wb = purple_whiteboard_create(sg->account, channel->channel_name, 0); - if (!wb) - return NULL; - - if (!wb->proto_data) { - wbs = silc_calloc(1, sizeof(*wbs)); - if (!wbs) - return NULL; - wbs->type = 1; - wbs->u.channel = channel; - wbs->width = SILCPURPLE_WB_WIDTH; - wbs->height = SILCPURPLE_WB_HEIGHT; - wbs->brush_size = SILCPURPLE_WB_BRUSH_SMALL; - wbs->brush_color = SILCPURPLE_WB_COLOR_BLACK; - wb->proto_data = wbs; - - /* Start the whiteboard */ - purple_whiteboard_start(wb); - purple_whiteboard_clear(wb); - } - - return wb; -} - -static void -silcpurple_wb_parse(SilcPurpleWb wbs, PurpleWhiteboard *wb, - unsigned char *message, SilcUInt32 message_len) -{ - SilcUInt8 command; - SilcUInt16 width, height, brush_size; - SilcUInt32 brush_color, x, y, dx, dy; - SilcBufferStruct buf; - int ret; - - /* Parse the packet */ - silc_buffer_set(&buf, message, message_len); - ret = silc_buffer_unformat(&buf, - SILC_STR_UI_CHAR(&command), - SILC_STR_UI_SHORT(&width), - SILC_STR_UI_SHORT(&height), - SILC_STR_UI_INT(&brush_color), - SILC_STR_UI_SHORT(&brush_size), - SILC_STR_END); - if (ret < 0) - return; - silc_buffer_pull(&buf, ret); - - /* Update whiteboard if its dimensions changed */ - if (width != wbs->width || height != wbs->height) - silcpurple_wb_set_dimensions(wb, height, width); - - if (command == SILCPURPLE_WB_DRAW) { - /* Parse data and draw it */ - ret = silc_buffer_unformat(&buf, - SILC_STR_UI_INT(&dx), - SILC_STR_UI_INT(&dy), - SILC_STR_END); - if (ret < 0) - return; - silc_buffer_pull(&buf, 8); - x = dx; - y = dy; - while (buf.len > 0) { - ret = silc_buffer_unformat(&buf, - SILC_STR_UI_INT(&dx), - SILC_STR_UI_INT(&dy), - SILC_STR_END); - if (ret < 0) - return; - silc_buffer_pull(&buf, 8); - - purple_whiteboard_draw_line(wb, x, y, x + dx, y + dy, - brush_color, brush_size); - x += dx; - y += dy; - } - } - - if (command == SILCPURPLE_WB_CLEAR) - purple_whiteboard_clear(wb); -} - -typedef struct { - unsigned char *message; - SilcUInt32 message_len; - SilcPurple sg; - SilcClientEntry sender; - SilcChannelEntry channel; -} *SilcPurpleWbRequest; - -static void -silcpurple_wb_request_cb(SilcPurpleWbRequest req, gint id) -{ - PurpleWhiteboard *wb; - - if (id != 1) - goto out; - - if (!req->channel) - wb = silcpurple_wb_init(req->sg, req->sender); - else - wb = silcpurple_wb_init_ch(req->sg, req->channel); - - silcpurple_wb_parse(wb->proto_data, wb, req->message, req->message_len); - - out: - silc_free(req->message); - silc_free(req); -} - -static void -silcpurple_wb_request(SilcClient client, const unsigned char *message, - SilcUInt32 message_len, SilcClientEntry sender, - SilcChannelEntry channel) -{ - char tmp[128]; - SilcPurpleWbRequest req; - PurpleConnection *gc; - SilcPurple sg; - - gc = client->application; - sg = gc->proto_data; - - /* Open whiteboard automatically if requested */ - if (purple_account_get_bool(sg->account, "open-wb", FALSE)) { - PurpleWhiteboard *wb; - - if (!channel) - wb = silcpurple_wb_init(sg, sender); - else - wb = silcpurple_wb_init_ch(sg, channel); - - silcpurple_wb_parse(wb->proto_data, wb, (unsigned char *)message, - message_len); - return; - } - - /* Close any previous unaccepted requests */ - purple_request_close_with_handle(sender); - - if (!channel) { - g_snprintf(tmp, sizeof(tmp), - _("%s sent message to whiteboard. Would you like " - "to open the whiteboard?"), sender->nickname); - } else { - g_snprintf(tmp, sizeof(tmp), - _("%s sent message to whiteboard on %s channel. " - "Would you like to open the whiteboard?"), - sender->nickname, channel->channel_name); - } - - req = silc_calloc(1, sizeof(*req)); - if (!req) - return; - req->message = silc_memdup(message, message_len); - req->message_len = message_len; - req->sender = sender; - req->channel = channel; - req->sg = sg; - - purple_request_action(sender, _("Whiteboard"), tmp, NULL, 1, - sg->account, sender->nickname, NULL, req, 2, - _("Yes"), G_CALLBACK(silcpurple_wb_request_cb), - _("No"), G_CALLBACK(silcpurple_wb_request_cb)); -} - -/* Process incoming whiteboard message */ - -void silcpurple_wb_receive(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcMessagePayload payload, - SilcMessageFlags flags, const unsigned char *message, - SilcUInt32 message_len) -{ - SilcPurple sg; - PurpleConnection *gc; - PurpleWhiteboard *wb; - SilcPurpleWb wbs; - - gc = client->application; - sg = gc->proto_data; - - wb = purple_whiteboard_get_session(sg->account, sender->nickname); - if (!wb) { - /* Ask user if they want to open the whiteboard */ - silcpurple_wb_request(client, message, message_len, - sender, NULL); - return; - } - - wbs = wb->proto_data; - silcpurple_wb_parse(wbs, wb, (unsigned char *)message, message_len); -} - -/* Process incoming whiteboard message on channel */ - -void silcpurple_wb_receive_ch(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcChannelEntry channel, - SilcMessagePayload payload, - SilcMessageFlags flags, - const unsigned char *message, - SilcUInt32 message_len) -{ - SilcPurple sg; - PurpleConnection *gc; - PurpleWhiteboard *wb; - SilcPurpleWb wbs; - - gc = client->application; - sg = gc->proto_data; - - wb = purple_whiteboard_get_session(sg->account, channel->channel_name); - if (!wb) { - /* Ask user if they want to open the whiteboard */ - silcpurple_wb_request(client, message, message_len, - sender, channel); - return; - } - - wbs = wb->proto_data; - silcpurple_wb_parse(wbs, wb, (unsigned char *)message, message_len); -} - -/* Send whiteboard message */ - -void silcpurple_wb_send(PurpleWhiteboard *wb, GList *draw_list) -{ - SilcPurpleWb wbs = wb->proto_data; - SilcBuffer packet; - GList *list; - int len; - PurpleConnection *gc; - SilcPurple sg; - - g_return_if_fail(draw_list); - gc = purple_account_get_connection(wb->account); - g_return_if_fail(gc); - sg = gc->proto_data; - g_return_if_fail(sg); - - len = SILCPURPLE_WB_HEADER; - for (list = draw_list; list; list = list->next) - len += 4; - - packet = silc_buffer_alloc_size(len); - if (!packet) - return; - - /* Assmeble packet */ - silc_buffer_format(packet, - SILC_STR_UI32_STRING(SILCPURPLE_WB_MIME), - SILC_STR_UI_CHAR(SILCPURPLE_WB_DRAW), - SILC_STR_UI_SHORT(wbs->width), - SILC_STR_UI_SHORT(wbs->height), - SILC_STR_UI_INT(wbs->brush_color), - SILC_STR_UI_SHORT(wbs->brush_size), - SILC_STR_END); - silc_buffer_pull(packet, SILCPURPLE_WB_HEADER); - for (list = draw_list; list; list = list->next) { - silc_buffer_format(packet, - SILC_STR_UI_INT(GPOINTER_TO_INT(list->data)), - SILC_STR_END); - silc_buffer_pull(packet, 4); - } - - /* Send the message */ - if (wbs->type == 0) { - /* Private message */ - silc_client_send_private_message(sg->client, sg->conn, - wbs->u.client, - SILC_MESSAGE_FLAG_DATA, - packet->head, len, TRUE); - } else if (wbs->type == 1) { - /* Channel message. Channel private keys are not supported. */ - silc_client_send_channel_message(sg->client, sg->conn, - wbs->u.channel, NULL, - SILC_MESSAGE_FLAG_DATA, - packet->head, len, TRUE); - } - - silc_buffer_free(packet); -} - -/* Purple Whiteboard operations */ - -void silcpurple_wb_start(PurpleWhiteboard *wb) -{ - /* Nothing here. Everything is in initialization */ -} - -void silcpurple_wb_end(PurpleWhiteboard *wb) -{ - silc_free(wb->proto_data); - wb->proto_data = NULL; -} - -void silcpurple_wb_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height) -{ - SilcPurpleWb wbs = wb->proto_data; - *width = wbs->width; - *height = wbs->height; -} - -void silcpurple_wb_set_dimensions(PurpleWhiteboard *wb, int width, int height) -{ - SilcPurpleWb wbs = wb->proto_data; - wbs->width = width > SILCPURPLE_WB_WIDTH_MAX ? SILCPURPLE_WB_WIDTH_MAX : - width; - wbs->height = height > SILCPURPLE_WB_HEIGHT_MAX ? SILCPURPLE_WB_HEIGHT_MAX : - height; - - /* Update whiteboard */ - purple_whiteboard_set_dimensions(wb, wbs->width, wbs->height); -} - -void silcpurple_wb_get_brush(const PurpleWhiteboard *wb, int *size, int *color) -{ - SilcPurpleWb wbs = wb->proto_data; - *size = wbs->brush_size; - *color = wbs->brush_color; -} - -void silcpurple_wb_set_brush(PurpleWhiteboard *wb, int size, int color) -{ - SilcPurpleWb wbs = wb->proto_data; - wbs->brush_size = size; - wbs->brush_color = color; - - /* Update whiteboard */ - purple_whiteboard_set_brush(wb, size, color); -} - -void silcpurple_wb_clear(PurpleWhiteboard *wb) -{ - SilcPurpleWb wbs = wb->proto_data; - SilcBuffer packet; - int len; - PurpleConnection *gc; - SilcPurple sg; - - gc = purple_account_get_connection(wb->account); - g_return_if_fail(gc); - sg = gc->proto_data; - g_return_if_fail(sg); - - len = SILCPURPLE_WB_HEADER; - packet = silc_buffer_alloc_size(len); - if (!packet) - return; - - /* Assmeble packet */ - silc_buffer_format(packet, - SILC_STR_UI32_STRING(SILCPURPLE_WB_MIME), - SILC_STR_UI_CHAR(SILCPURPLE_WB_CLEAR), - SILC_STR_UI_SHORT(wbs->width), - SILC_STR_UI_SHORT(wbs->height), - SILC_STR_UI_INT(wbs->brush_color), - SILC_STR_UI_SHORT(wbs->brush_size), - SILC_STR_END); - - /* Send the message */ - if (wbs->type == 0) { - /* Private message */ - silc_client_send_private_message(sg->client, sg->conn, - wbs->u.client, - SILC_MESSAGE_FLAG_DATA, - packet->head, len, TRUE); - } else if (wbs->type == 1) { - /* Channel message */ - silc_client_send_channel_message(sg->client, sg->conn, - wbs->u.channel, NULL, - SILC_MESSAGE_FLAG_DATA, - packet->head, len, TRUE); - } - - silc_buffer_free(packet); -} diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/silc10/wb.h --- a/libpurple/protocols/silc10/wb.h Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - - silcpurple.h - - Author: Pekka Riikonen - - Copyright (C) 2005 Pekka Riikonen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -*/ - -#ifndef SILCPURPLE_WB_H -#define SILCPURPLE_WB_H - -#include "silcpurple.h" -#include "whiteboard.h" - -PurpleWhiteboard * -silcpurple_wb_init(SilcPurple sg, SilcClientEntry client_entry); -PurpleWhiteboard * -silcpurple_wb_init_ch(SilcPurple sg, SilcChannelEntry channel); -void silcpurple_wb_receive(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcMessagePayload payload, - SilcMessageFlags flags, const unsigned char *message, - SilcUInt32 message_len); -void silcpurple_wb_receive_ch(SilcClient client, SilcClientConnection conn, - SilcClientEntry sender, SilcChannelEntry channel, - SilcMessagePayload payload, - SilcMessageFlags flags, - const unsigned char *message, - SilcUInt32 message_len); -void silcpurple_wb_start(PurpleWhiteboard *wb); -void silcpurple_wb_end(PurpleWhiteboard *wb); -void silcpurple_wb_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height); -void silcpurple_wb_set_dimensions(PurpleWhiteboard *wb, int width, int height); -void silcpurple_wb_get_brush(const PurpleWhiteboard *wb, int *size, int *color); -void silcpurple_wb_set_brush(PurpleWhiteboard *wb, int size, int color); -void silcpurple_wb_send(PurpleWhiteboard *wb, GList *draw_list); -void silcpurple_wb_clear(PurpleWhiteboard *wb); - -#endif /* SILCPURPLE_WB_H */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/simple/simple.c --- a/libpurple/protocols/simple/simple.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/simple/simple.c Fri Apr 06 04:30:00 2012 +0000 @@ -67,7 +67,7 @@ } static void simple_keep_alive(PurpleConnection *gc) { - struct simple_account_data *sip = gc->proto_data; + struct simple_account_data *sip = purple_connection_get_protocol_data(gc); if(sip->udp) { /* in case of UDP send a packet only with a 0 byte to remain in the NAT table */ gchar buf[2] = {0, 0}; @@ -100,14 +100,15 @@ } static void simple_set_status(PurpleAccount *account, PurpleStatus *status) { + PurpleConnection *gc = purple_account_get_connection(account); PurpleStatusPrimitive primitive = purple_status_type_get_primitive(purple_status_get_type(status)); struct simple_account_data *sip = NULL; if (!purple_status_is_active(status)) return; - if (account->gc) - sip = account->gc->proto_data; + if (gc) + sip = purple_connection_get_protocol_data(gc); if (sip) { @@ -192,9 +193,9 @@ } } -static void simple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) +static void simple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message) { - struct simple_account_data *sip = (struct simple_account_data *)gc->proto_data; + struct simple_account_data *sip = purple_connection_get_protocol_data(gc); struct simple_buddy *b; const char *name = purple_buddy_get_name(buddy); if(strncmp(name, "sip:", 4)) { @@ -222,7 +223,7 @@ buddies = purple_find_buddies(account, NULL); while (buddies) { PurpleBuddy *buddy = buddies->data; - simple_add_buddy(gc, buddy, purple_buddy_get_group(buddy)); + simple_add_buddy(gc, buddy, purple_buddy_get_group(buddy), NULL); buddies = g_slist_delete_link(buddies, buddies); } @@ -231,7 +232,7 @@ static void simple_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { const char *name = purple_buddy_get_name(buddy); - struct simple_account_data *sip = (struct simple_account_data *)gc->proto_data; + struct simple_account_data *sip = purple_connection_get_protocol_data(gc); struct simple_buddy *b = g_hash_table_lookup(sip->buddies, name); g_hash_table_remove(sip->buddies, name); g_free(b->name); @@ -412,7 +413,7 @@ static void simple_canwrite_cb(gpointer data, gint source, PurpleInputCondition cond) { PurpleConnection *gc = data; - struct simple_account_data *sip = gc->proto_data; + struct simple_account_data *sip = purple_connection_get_protocol_data(gc); gsize max_write; gssize written; @@ -432,7 +433,7 @@ /*TODO: do we really want to disconnect on a failure to write?*/ gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; @@ -451,13 +452,13 @@ if(source < 0) { gchar *tmp = g_strdup_printf(_("Unable to connect: %s"), error_message); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; } - sip = gc->proto_data; + sip = purple_connection_get_protocol_data(gc); sip->fd = source; sip->connecting = FALSE; @@ -474,12 +475,12 @@ static void sendlater(PurpleConnection *gc, const char *buf) { - struct simple_account_data *sip = gc->proto_data; + struct simple_account_data *sip = purple_connection_get_protocol_data(gc); if(!sip->connecting) { purple_debug_info("simple", "connecting to %s port %d\n", sip->realhostname ? sip->realhostname : "{NULL}", sip->realport); if (purple_proxy_connect(gc, sip->account, sip->realhostname, sip->realport, send_later_cb, gc) == NULL) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); } sip->connecting = TRUE; } @@ -491,7 +492,7 @@ } static void sendout_pkt(PurpleConnection *gc, const char *buf) { - struct simple_account_data *sip = gc->proto_data; + struct simple_account_data *sip = purple_connection_get_protocol_data(gc); time_t currtime = time(NULL); int writelen = strlen(buf); @@ -629,7 +630,7 @@ static void send_sip_request(PurpleConnection *gc, const gchar *method, const gchar *url, const gchar *to, const gchar *addheaders, const gchar *body, struct sip_dialog *dialog, TransCallback tc) { - struct simple_account_data *sip = gc->proto_data; + struct simple_account_data *sip = purple_connection_get_protocol_data(gc); char *callid = dialog ? g_strdup(dialog->callid) : gencallid(); char *auth = NULL; const char *addh = ""; @@ -1026,7 +1027,7 @@ } static int simple_im_send(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags) { - struct simple_account_data *sip = gc->proto_data; + struct simple_account_data *sip = purple_connection_get_protocol_data(gc); char *to = g_strdup(who); char *text = purple_unescape_html(what); simple_send_message(sip, to, text, NULL); @@ -1120,9 +1121,9 @@ if(sip->registerstatus != SIMPLE_REGISTER_RETRY) { purple_debug_info("simple", "REGISTER retries %d\n", sip->registrar.retries); if(sip->registrar.retries > SIMPLE_REGISTER_RETRY_MAX) { - if (!purple_account_get_remember_password(sip->gc->account)) - purple_account_set_password(sip->gc->account, NULL); - purple_connection_error_reason(sip->gc, + if (!purple_account_get_remember_password(purple_connection_get_account(sip->gc))) + purple_account_set_password(purple_connection_get_account(sip->gc), NULL); + purple_connection_error(sip->gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Incorrect password")); return TRUE; @@ -1137,7 +1138,7 @@ if (sip->registerstatus != SIMPLE_REGISTER_RETRY) { purple_debug_info("simple", "Unrecognized return code for REGISTER.\n"); if (sip->registrar.retries > SIMPLE_REGISTER_RETRY_MAX) { - purple_connection_error_reason(sip->gc, + purple_connection_error(sip->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Unknown server response")); return TRUE; @@ -1285,7 +1286,7 @@ } static unsigned int simple_typing(PurpleConnection *gc, const char *name, PurpleTypingState state) { - struct simple_account_data *sip = gc->proto_data; + struct simple_account_data *sip = purple_connection_get_protocol_data(gc); gchar *xml = "\n" "proto_data; + struct simple_account_data *sip = purple_connection_get_protocol_data(gc); struct sipmsg *msg; int len; time_t currtime = time(NULL); @@ -1681,7 +1682,7 @@ static void simple_input_cb(gpointer data, gint source, PurpleInputCondition cond) { PurpleConnection *gc = data; - struct simple_account_data *sip = gc->proto_data; + struct simple_account_data *sip = purple_connection_get_protocol_data(gc); int len; struct sip_connection *conn = connection_find(sip, source); if(!conn) { @@ -1704,7 +1705,7 @@ if(sip->fd == source) sip->fd = -1; return; } - gc->last_received = time(NULL); + purple_connection_update_last_received(gc); conn->inbufused += len; conn->inbuf[conn->inbufused] = '\0'; @@ -1714,7 +1715,7 @@ /* Callback for new connections on incoming TCP port */ static void simple_newconn_cb(gpointer data, gint source, PurpleInputCondition cond) { PurpleConnection *gc = data; - struct simple_account_data *sip = gc->proto_data; + struct simple_account_data *sip = purple_connection_get_protocol_data(gc); struct sip_connection *conn; int newfd, flags; @@ -1739,13 +1740,13 @@ if(source < 0) { gchar *tmp = g_strdup_printf(_("Unable to connect: %s"), error_message); - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; } - sip = gc->proto_data; + sip = purple_connection_get_protocol_data(gc); sip->fd = source; conn = connection_create(sip, source); @@ -1775,7 +1776,7 @@ sip->listen_data = NULL; if(listenfd == -1) { - purple_connection_error_reason(sip->gc, + purple_connection_error(sip->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to create listen socket")); return; @@ -1804,7 +1805,7 @@ sip->query_data = NULL; if (!hosts || !hosts->data) { - purple_connection_error_reason(sip->gc, + purple_connection_error(sip->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to resolve hostname")); return; @@ -1822,10 +1823,10 @@ } /* create socket for incoming connections */ - sip->listen_data = purple_network_listen_range(5060, 5160, SOCK_DGRAM, + sip->listen_data = purple_network_listen_range(5060, 5160, AF_UNSPEC, SOCK_DGRAM, TRUE, simple_udp_host_resolved_listen_cb, sip); if (sip->listen_data == NULL) { - purple_connection_error_reason(sip->gc, + purple_connection_error(sip->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to create listen socket")); return; @@ -1840,7 +1841,7 @@ sip->listenfd = listenfd; if(sip->listenfd == -1) { - purple_connection_error_reason(sip->gc, + purple_connection_error(sip->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to create listen socket")); return; @@ -1855,7 +1856,7 @@ /* open tcp connection to the server */ if (purple_proxy_connect(sip->gc, sip->account, sip->realhostname, sip->realport, login_cb, sip->gc) == NULL) { - purple_connection_error_reason(sip->gc, + purple_connection_error(sip->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); } @@ -1892,10 +1893,10 @@ /* TCP case */ if(!sip->udp) { /* create socket for incoming connections */ - sip->listen_data = purple_network_listen_range(5060, 5160, SOCK_STREAM, + sip->listen_data = purple_network_listen_range(5060, 5160, AF_UNSPEC, SOCK_STREAM, TRUE, simple_tcp_connect_listen_cb, sip); if (sip->listen_data == NULL) { - purple_connection_error_reason(sip->gc, + purple_connection_error(sip->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to create listen socket")); return; @@ -1903,10 +1904,10 @@ } else { /* UDP */ purple_debug_info("simple", "using udp with server %s and port %d\n", hostname, port); - sip->query_data = purple_dnsquery_a_account(sip->account, hostname, + sip->query_data = purple_dnsquery_a(sip->account, hostname, port, simple_udp_host_resolved, sip); if (sip->query_data == NULL) { - purple_connection_error_reason(sip->gc, + purple_connection_error(sip->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to resolve hostname")); } @@ -1924,13 +1925,14 @@ gc = purple_account_get_connection(account); if (strpbrk(username, " \t\v\r\n") != NULL) { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, _("SIP usernames may not contain whitespaces or @ symbols")); return; } - gc->proto_data = sip = g_new0(struct simple_account_data, 1); + sip = g_new0(struct simple_account_data, 1); + purple_connection_set_protocol_data(gc, sip); sip->gc = gc; sip->fd = -1; sip->listenfd = -1; @@ -1943,7 +1945,7 @@ userserver = g_strsplit(username, "@", 2); if (userserver[1] == NULL || userserver[1][0] == '\0') { - purple_connection_error_reason(gc, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, _("SIP connect server not specified")); return; @@ -1968,13 +1970,13 @@ hosttoconnect = purple_account_get_string(account, "proxy", sip->servername); } - sip->srv_query_data = purple_srv_resolve_account(account, "sip", + sip->srv_query_data = purple_srv_resolve(account, "sip", sip->udp ? "udp" : "tcp", hosttoconnect, srvresolved, sip); } static void simple_close(PurpleConnection *gc) { - struct simple_account_data *sip = gc->proto_data; + struct simple_account_data *sip = purple_connection_get_protocol_data(gc); if (!sip) return; @@ -2005,7 +2007,7 @@ purple_dnsquery_destroy(sip->query_data); if (sip->srv_query_data != NULL) - purple_srv_cancel(sip->srv_query_data); + purple_srv_txt_query_destroy(sip->srv_query_data); if (sip->listen_data != NULL) purple_network_listen_cancel(sip->listen_data); @@ -2039,11 +2041,12 @@ g_free(sip->realhostname); g_free(sip); - gc->proto_data = NULL; + purple_connection_set_protocol_data(gc, NULL); } static PurplePluginProtocolInfo prpl_info = { + sizeof(PurplePluginProtocolInfo), /* struct_size */ 0, NULL, /* user_splits */ NULL, /* protocol_options */ @@ -2084,7 +2087,6 @@ simple_keep_alive, /* keepalive */ NULL, /* register_user */ NULL, /* get_cb_info */ - NULL, /* get_cb_away */ NULL, /* alias_buddy */ NULL, /* group_buddy */ NULL, /* rename_group */ @@ -2109,15 +2111,12 @@ NULL, /* unregister_user */ NULL, /* send_attention */ NULL, /* get_attention_types */ - sizeof(PurplePluginProtocolInfo), /* struct_size */ NULL, /* get_account_text_table */ NULL, /* initiate_media */ NULL, /* get_media_caps */ NULL, /* get_moods */ NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - NULL, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ + NULL /* get_public_alias */ }; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/yahoo/libyahoo.c --- a/libpurple/protocols/yahoo/libyahoo.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/yahoo/libyahoo.c Fri Apr 06 04:30:00 2012 +0000 @@ -194,6 +194,7 @@ static PurplePluginProtocolInfo prpl_info = { + sizeof(PurplePluginProtocolInfo), /* struct_size */ OPT_PROTO_MAIL_CHECK | OPT_PROTO_CHAT_TOPIC, NULL, /* user_splits */ NULL, /* protocol_options */ @@ -234,7 +235,6 @@ yahoo_keepalive, NULL, /* register_user */ NULL, /* get_cb_info */ - NULL, /* get_cb_away */ yahoo_update_alias, /* alias_buddy */ yahoo_change_buddys_group, yahoo_rename_group, @@ -257,19 +257,14 @@ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ NULL, /* unregister_user */ - yahoo_send_attention, yahoo_attention_types, - - sizeof(PurplePluginProtocolInfo), /* struct_size */ yahoo_get_account_text_table, /* get_account_text_table */ NULL, /* initiate_media */ NULL, /* get_media_caps */ NULL, /* get_moods */ NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - NULL, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ + NULL /* get_public_alias */ }; static PurplePluginInfo info = diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/yahoo/libyahoojp.c --- a/libpurple/protocols/yahoo/libyahoojp.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/yahoo/libyahoojp.c Fri Apr 06 04:30:00 2012 +0000 @@ -90,6 +90,7 @@ static PurplePluginProtocolInfo prpl_info = { + sizeof(PurplePluginProtocolInfo), /* struct_size */ OPT_PROTO_MAIL_CHECK | OPT_PROTO_CHAT_TOPIC, NULL, /* user_splits */ NULL, /* protocol_options */ @@ -130,7 +131,6 @@ yahoo_keepalive, NULL, /* register_user */ NULL, /* get_cb_info */ - NULL, /* get_cb_away */ yahoo_update_alias, /* alias_buddy */ yahoo_change_buddys_group, yahoo_rename_group, @@ -157,15 +157,12 @@ yahoo_send_attention, yahoo_attention_types, - sizeof(PurplePluginProtocolInfo), /* struct_size */ yahoojp_get_account_text_table, /* get_account_text_table */ NULL, /* initiate_media */ NULL, /* get_media_caps */ NULL, /* get_moods */ NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - NULL, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ + NULL /* get_public_alias */ }; static PurplePluginInfo info = diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/yahoo/libymsg.c --- a/libpurple/protocols/yahoo/libymsg.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/yahoo/libymsg.c Fri Apr 06 04:30:00 2012 +0000 @@ -159,7 +159,7 @@ if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) { if (!purple_account_get_remember_password(account)) purple_account_set_password(account, NULL); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NAME_IN_USE, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NAME_IN_USE, _("You have signed on from another location")); return; } @@ -337,12 +337,12 @@ if (!name) break; - b = purple_find_buddy(gc->account, name); + b = purple_find_buddy(purple_connection_get_account(gc), name); 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, NULL); + purple_buddy_icons_set_for_user(purple_connection_get_account(gc), name, NULL, 0, NULL); break; } @@ -496,7 +496,7 @@ GSList *l = pkt->hash; PurpleAccount *account = purple_connection_get_account(gc); - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); GHashTable *ht; char *norm_bud = NULL; char *temp = NULL; @@ -573,7 +573,7 @@ yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_DO_NOT_CONNECT); } else { /* This buddy is on the ignore list (and therefore in no group) */ - purple_debug_info("yahoo", "%s adding %s to the deny list because of the ignore list / no group was found\n",account->username, norm_bud); + purple_debug_info("yahoo", "%s adding %s to the deny list because of the ignore list / no group was found\n", purple_account_get_username(account), norm_bud); purple_privacy_deny_add(account, norm_bud, 1); } @@ -634,11 +634,10 @@ static void yahoo_process_list(PurpleConnection *gc, struct yahoo_packet *pkt) { GSList *l = pkt->hash; - gboolean export = FALSE; gboolean got_serv_list = FALSE; YahooFriend *f = NULL; PurpleAccount *account = purple_connection_get_account(gc); - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); GHashTable *ht; char **lines; @@ -712,7 +711,6 @@ } b = purple_buddy_new(account, norm_bud, NULL); purple_blist_add_buddy(b, NULL, g, NULL); - export = TRUE; } yahoo_do_group_check(account, ht, norm_bud, grp); @@ -748,13 +746,13 @@ } if (got_serv_list && - ((account->perm_deny != PURPLE_PRIVACY_ALLOW_BUDDYLIST) && - (account->perm_deny != PURPLE_PRIVACY_DENY_ALL) && - (account->perm_deny != PURPLE_PRIVACY_ALLOW_USERS))) + ((purple_account_get_privacy_type(account) != PURPLE_PRIVACY_ALLOW_BUDDYLIST) && + (purple_account_get_privacy_type(account) != PURPLE_PRIVACY_DENY_ALL) && + (purple_account_get_privacy_type(account) != PURPLE_PRIVACY_ALLOW_USERS))) { - account->perm_deny = PURPLE_PRIVACY_DENY_USERS; + purple_account_set_privacy_type(account, PURPLE_PRIVACY_DENY_USERS); purple_debug_info("yahoo", "%s privacy defaulting to PURPLE_PRIVACY_DENY_USERS.\n", - account->username); + purple_account_get_username(account)); } if (yd->tmp_serv_plist) { @@ -763,7 +761,7 @@ f = yahoo_friend_find(gc, *bud); if (f) { purple_debug_info("yahoo", "%s setting presence for %s to PERM_OFFLINE\n", - account->username, *bud); + purple_account_get_username(account), *bud); f->presence = YAHOO_PRESENCE_PERM_OFFLINE; } } @@ -787,7 +785,7 @@ YahooFriend *f = NULL; GSList *l = pkt->hash; gint val_11 = 0; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); YahooFederation fed = YAHOO_FEDERATION_NONE; account = purple_connection_get_account(gc); @@ -899,7 +897,7 @@ char *server_msg = NULL; char *m; - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); account = purple_connection_get_account(gc); while (l != NULL) { @@ -960,7 +958,7 @@ static void yahoo_process_message(PurpleConnection *gc, struct yahoo_packet *pkt, yahoo_pkt_type pkt_type) { PurpleAccount *account; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); GSList *l = pkt->hash; GSList *list = NULL; struct _yahoo_im *im = NULL; @@ -1061,7 +1059,7 @@ doodle_session *ds; wb = purple_whiteboard_create(account, im->from, DOODLE_STATE_REQUESTED); - ds = wb->proto_data; + ds = purple_whiteboard_get_protocol_data(wb); ds->imv_key = g_strdup(pair->value); yahoo_doodle_command_send_request(gc, im->from, pair->value); @@ -1202,7 +1200,7 @@ { struct yahoo_add_request *add_req = data; struct yahoo_packet *pkt; - YahooData *yd = add_req->gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(add_req->gc); const char *who = add_req->who; pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15, YAHOO_STATUS_AVAILABLE, yd->session_id); @@ -1233,7 +1231,7 @@ static void yahoo_buddy_add_deny_cb(struct yahoo_add_request *add_req, const char *msg) { - YahooData *yd = add_req->gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(add_req->gc); struct yahoo_packet *pkt; char *encoded_msg = NULL; const char *who = add_req->who; @@ -1295,7 +1293,7 @@ static void yahoo_buddy_denied_our_add(PurpleConnection *gc, const char *who, const char *reason) { char *notify_msg; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); if (who == NULL) return; @@ -1625,7 +1623,7 @@ static void yahoo_process_mail(PurpleConnection *gc, struct yahoo_packet *pkt) { PurpleAccount *account = purple_connection_get_account(gc); - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); const char *who = NULL; const char *email = NULL; const char *subj = NULL; @@ -1709,7 +1707,7 @@ static void yahoo_auth16_stage3(PurpleConnection *gc, const char *crypt) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); PurpleAccount *account = purple_connection_get_account(gc); const char *name = purple_normalize(account, purple_account_get_username(account)); PurpleCipher *md5_cipher; @@ -1803,7 +1801,7 @@ if (error_message != NULL) { purple_debug_error("yahoo", "Login Failed, unable to retrieve stage 2 url: %s\n", error_message); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message); g_free(auth_data->seed); g_free(auth_data); return; @@ -1890,7 +1888,7 @@ if(error_reason) { purple_debug_error("yahoo", "Authentication error: %s. " "Code %d\n", error_reason, response_no); - purple_connection_error_reason(gc, error, error_reason); + purple_connection_error(gc, error, error_reason); g_free(error_reason); g_free(auth_data->seed); g_free(auth_data); @@ -1919,7 +1917,7 @@ if (error_message != NULL) { purple_debug_error("yahoo", "Login Failed, unable to retrieve login url: %s\n", error_message); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message); g_free(auth_data->seed); g_free(auth_data); return; @@ -2000,7 +1998,7 @@ } purple_debug_error("yahoo", "Authentication error: %s. Code %d\n", error_reason, response_no); - purple_connection_error_reason(gc, error, error_reason); + purple_connection_error(gc, error, error_reason); g_free(error_reason); g_free(auth_data->seed); g_free(auth_data); @@ -2014,7 +2012,7 @@ gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE); url = g_strdup_printf(yahoojp ? YAHOOJP_LOGIN_URL : YAHOO_LOGIN_URL, token); - url_data = purple_util_fetch_url_request_len_with_account( + url_data = purple_util_fetch_url_request( proxy_ssl ? account : NULL, url, TRUE, YAHOO_CLIENT_USERAGENT, TRUE, NULL, TRUE, -1, yahoo_auth16_stage2, auth_data); if (url_data) @@ -2040,7 +2038,7 @@ purple_debug_info("yahoo", "Authentication: In yahoo_auth16_stage1\n"); if(!purple_ssl_is_supported()) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("SSL support unavailable")); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("SSL support unavailable")); return; } @@ -2055,7 +2053,7 @@ g_free(encoded_password); g_free(encoded_username); - url_data = purple_util_fetch_url_request_len_with_account( + url_data = purple_util_fetch_url_request( proxy_ssl ? account : NULL, url, TRUE, YAHOO_CLIENT_USERAGENT, TRUE, NULL, FALSE, -1, yahoo_auth16_stage1_cb, auth_data); @@ -2180,12 +2178,12 @@ who, (ignore ? "ignoring" : "unignoring")); if (ignore) { - b = purple_find_buddy(gc->account, who); + b = purple_find_buddy(purple_connection_get_account(gc), who); g_snprintf(buf, sizeof(buf), _("You have tried to ignore %s, but the " "user is on your buddy list. Clicking \"Yes\" " "will remove and ignore the buddy."), who); purple_request_yes_no(gc, NULL, _("Ignore buddy?"), buf, 0, - gc->account, who, NULL, + purple_connection_get_account(gc), who, NULL, b, G_CALLBACK(ignore_buddy), G_CALLBACK(keep_buddy)); @@ -2207,14 +2205,14 @@ static void yahoo_process_authresp(PurpleConnection *gc, struct yahoo_packet *pkt) { #ifdef TRY_WEBMESSENGER_LOGIN - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); #endif /* TRY_WEBMESSENGER_LOGIN */ GSList *l = pkt->hash; int err = 0; char *msg; char *url = NULL; char *fullmsg; - PurpleAccount *account = gc->account; + PurpleAccount *account = purple_connection_get_account(gc); PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR; while (l) { @@ -2244,10 +2242,12 @@ yd->wm = TRUE; if (yd->fd >= 0) close(yd->fd); - if (gc->inpa) - purple_input_remove(gc->inpa); + if (yd->inpa) { + purple_input_remove(yd->inpa); + yd->inpa = 0; + } url_data = purple_util_fetch_url(WEBMESSENGER_URL, TRUE, - "Purple/" VERSION, FALSE, yahoo_login_page_cb, gc); + "Purple/" VERSION, FALSE, -1, yahoo_login_page_cb, gc); if (url_data != NULL) yd->url_datas = g_slist_prepend(yd->url_datas, url_data); return; @@ -2285,7 +2285,7 @@ else fullmsg = g_strdup(msg); - purple_connection_error_reason(gc, reason, fullmsg); + purple_connection_error(gc, reason, fullmsg); g_free(msg); g_free(fullmsg); } @@ -2300,7 +2300,7 @@ char *buf; YahooFriend *f; GSList *l = pkt->hash; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); YahooFederation fed = YAHOO_FEDERATION_NONE; while (l) { @@ -2394,7 +2394,7 @@ PurpleConnection *gc = user_data; struct yahoo_packet *pkt_to_send; PurpleAccount *account; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); account = purple_connection_get_account(gc); @@ -2413,7 +2413,7 @@ static gboolean yahoo_p2p_keepalive(gpointer data) { PurpleConnection *gc = data; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); g_hash_table_foreach(yd->peers, yahoo_p2p_keepalive_cb, gc); @@ -2460,7 +2460,7 @@ if(!(p2p_data = data)) return ; - yd = p2p_data->gc->proto_data; + yd = purple_connection_get_protocol_data(p2p_data->gc); /* lets see whats in the packet */ while (l) { @@ -2545,7 +2545,7 @@ if(!(p2p_data = data)) return ; - yd = p2p_data->gc->proto_data; + yd = purple_connection_get_protocol_data(p2p_data->gc); len = read(source, buf, sizeof(buf)); if ((len < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) @@ -2617,7 +2617,7 @@ if(!(p2p_data = data)) return ; - yd = p2p_data->gc->proto_data; + yd = purple_connection_get_protocol_data(p2p_data->gc); acceptfd = accept(source, NULL, 0); if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) @@ -2657,7 +2657,7 @@ if(!(p2p_data = data)) return FALSE; - yd = p2p_data->gc->proto_data; + yd = purple_connection_get_protocol_data(p2p_data->gc); purple_debug_warning("yahoo","yahoo p2p server timeout, peer failed to connect\n"); yahoo_p2p_disconnect_destroy_data(data); @@ -2678,7 +2678,7 @@ if(!(p2p_data = data)) return ; - yd = p2p_data->gc->proto_data; + yd = purple_connection_get_protocol_data(p2p_data->gc); yd->listen_data = NULL; if(listenfd == -1) { @@ -2706,7 +2706,7 @@ YahooFriend *f; struct yahoo_packet *pkt; PurpleAccount *account; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_p2p_data *p2p_data; const char *norm_username; @@ -2770,7 +2770,7 @@ if (yd->listen_data) purple_debug_warning("yahoo","p2p: Failed to create p2p server - server already exists\n"); else { - yd->listen_data = purple_network_listen(YAHOO_PAGER_PORT_P2P, SOCK_STREAM, yahoo_p2p_server_listen_cb, p2p_data); + yd->listen_data = purple_network_listen(YAHOO_PAGER_PORT_P2P, AF_UNSPEC, SOCK_STREAM, TRUE, yahoo_p2p_server_listen_cb, p2p_data); if (yd->listen_data == NULL) purple_debug_warning("yahoo","p2p: Failed to created p2p server\n"); } @@ -2787,7 +2787,7 @@ YahooData *yd; p2p_data = data; - yd = p2p_data->gc->proto_data; + yd = purple_connection_get_protocol_data(p2p_data->gc); if(error_message != NULL) { purple_debug_warning("yahoo","p2p: %s\n",error_message); @@ -3132,7 +3132,7 @@ static void yahoo_pending(gpointer data, gint source, PurpleInputCondition cond) { PurpleConnection *gc = data; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); char buf[1024]; int len; @@ -3147,15 +3147,15 @@ tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; } else if (len == 0) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Server closed the connection")); return; } - gc->last_received = time(NULL); + purple_connection_update_last_received(gc); yd->rxqueue = g_realloc(yd->rxqueue, len + yd->rxlen); memcpy(yd->rxqueue + yd->rxlen, buf, len); yd->rxlen += len; @@ -3235,20 +3235,20 @@ if (source < 0) { gchar *tmp; tmp = g_strdup_printf(_("Unable to connect: %s"), error_message); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; } - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); yd->fd = source; pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, yd->current_status, yd->session_id); - yahoo_packet_hash_str(pkt, 1, purple_normalize(gc->account, purple_account_get_username(purple_connection_get_account(gc)))); + yahoo_packet_hash_str(pkt, 1, purple_normalize(purple_connection_get_account(gc), purple_account_get_username(purple_connection_get_account(gc)))); yahoo_packet_send_and_free(pkt, yd); - gc->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc); + yd->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc); } #ifdef TRY_WEBMESSENGER_LOGIN @@ -3261,31 +3261,31 @@ if (source < 0) { gchar *tmp; tmp = g_strdup_printf(_("Unable to connect: %s"), error_message); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; } - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); yd->fd = source; pkt = yahoo_packet_new(YAHOO_SERVICE_WEBLOGIN, YAHOO_STATUS_WEBLOGIN, yd->session_id); yahoo_packet_hash(pkt, "sss", 0, - purple_normalize(gc->account, purple_account_get_username(purple_connection_get_account(gc))), - 1, purple_normalize(gc->account, purple_account_get_username(purple_connection_get_account(gc))), + purple_normalize(purple_connection_get_account(gc), purple_account_get_username(purple_connection_get_account(gc))), + 1, purple_normalize(purple_connection_get_account(gc), purple_account_get_username(purple_connection_get_account(gc))), 6, yd->auth); yahoo_packet_send_and_free(pkt, yd); g_free(yd->auth); - gc->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc); + yd->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc); } static void yahoo_web_pending(gpointer data, gint source, PurpleInputCondition cond) { PurpleConnection *gc = data; PurpleAccount *account = purple_connection_get_account(gc); - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); char bufread[2048], *i = bufread, *buf = bufread; int len; GString *s; @@ -3301,11 +3301,11 @@ tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; } else if (len == 0) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Server closed the connection")); return; } @@ -3321,7 +3321,7 @@ if ((strncmp(buf, "HTTP/1.0 302", strlen("HTTP/1.0 302")) && strncmp(buf, "HTTP/1.1 302", strlen("HTTP/1.1 302")))) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Received unexpected HTTP response from server")); purple_debug_misc("yahoo", "Unexpected HTTP response: %s\n", buf); return; @@ -3342,7 +3342,8 @@ } yd->auth = g_string_free(s, FALSE); - purple_input_remove(gc->inpa); + purple_input_remove(yd->inpa); + yd->inpa = 0; close(source); g_free(yd->rxqueue); yd->rxqueue = NULL; @@ -3351,7 +3352,7 @@ if (purple_proxy_connect(gc, account, "wcs2.msg.dcn.yahoo.com", purple_account_get_int(account, "port", YAHOO_PAGER_PORT), yahoo_got_web_connected, gc) == NULL) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); return; } @@ -3359,13 +3360,10 @@ static void yahoo_got_cookies_send_cb(gpointer data, gint source, PurpleInputCondition cond) { - PurpleConnection *gc; - YahooData *yd; + PurpleConnection *gc = data; + YahooData *yd = purple_connection_get_protocol_data(gc); int written, remaining; - gc = data; - yd = gc->proto_data; - remaining = strlen(yd->auth) - yd->auth_written; written = write(source, yd->auth + yd->auth_written, remaining); @@ -3375,12 +3373,13 @@ gchar *tmp; g_free(yd->auth); yd->auth = NULL; - if (gc->inpa) - purple_input_remove(gc->inpa); - gc->inpa = 0; + if (yd->inpa) { + purple_input_remove(yd->inpa); + yd->inpa = 0; + } tmp = g_strdup_printf(_("Lost connection with %s: %s"), "login.yahoo.com:80", g_strerror(errno)); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; } @@ -3393,26 +3392,27 @@ g_free(yd->auth); yd->auth = NULL; yd->auth_written = 0; - purple_input_remove(gc->inpa); - gc->inpa = purple_input_add(source, PURPLE_INPUT_READ, yahoo_web_pending, gc); + purple_input_remove(yd->inpa); + yd->inpa = purple_input_add(source, PURPLE_INPUT_READ, yahoo_web_pending, gc); } static void yahoo_got_cookies(gpointer data, gint source, const gchar *error_message) { PurpleConnection *gc = data; + YahooData *yd = purple_connection_get_protocol_data(gc); if (source < 0) { gchar *tmp; tmp = g_strdup_printf(_("Unable to establish a connection with %s: %s"), "login.yahoo.com:80", error_message); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; } - if (gc->inpa == 0) + if (yd->inpa == 0) { - gc->inpa = purple_input_add(source, PURPLE_INPUT_WRITE, + yd->inpa = purple_input_add(source, PURPLE_INPUT_WRITE, yahoo_got_cookies_send_cb, gc); yahoo_got_cookies_send_cb(gc, source, PURPLE_INPUT_WRITE); } @@ -3474,7 +3474,7 @@ { PurpleConnection *gc = (PurpleConnection *)user_data; PurpleAccount *account = purple_connection_get_account(gc); - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); const char *sn = purple_account_get_username(account); const char *pass = purple_connection_get_password(gc); GHashTable *hash = yahoo_login_page_hash(url_text, len); @@ -3489,7 +3489,7 @@ if (error_message != NULL) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message); return; } @@ -3539,7 +3539,7 @@ g_hash_table_destroy(hash); yd->auth = g_string_free(url, FALSE); if (purple_proxy_connect(gc, account, "login.yahoo.com", 80, yahoo_got_cookies, gc) == NULL) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); return; } @@ -3619,12 +3619,12 @@ error_message ? error_message : "(null)"); if(yahoo_is_japan(a)) { /* We don't know fallback hosts for Yahoo Japan :( */ - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect: The server returned an empty response.")); } else { if(purple_proxy_connect(gc, a, YAHOO_PAGER_HOST_FALLBACK, port, yahoo_got_connected, gc) == NULL) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); } } @@ -3646,20 +3646,20 @@ if(cs_server) { /* got an address; get on with connecting */ if(purple_proxy_connect(gc, a, cs_server, port, yahoo_got_connected, gc) == NULL) - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); } else { purple_debug_error("yahoo", "No CS address retrieved! Server " "response:\n%s\n", url_text ? url_text : "(null)"); if(yahoo_is_japan(a)) { /* We don't know fallback hosts for Yahoo Japan :( */ - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect: The server's response did not contain " "the necessary information")); } else if(purple_proxy_connect(gc, a, YAHOO_PAGER_HOST_FALLBACK, port, yahoo_got_connected, gc) == NULL) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect")); } } @@ -3671,13 +3671,14 @@ void yahoo_login(PurpleAccount *account) { PurpleConnection *gc = purple_account_get_connection(account); - YahooData *yd = gc->proto_data = g_new0(YahooData, 1); + YahooData *yd = g_new0(YahooData, 1); PurpleStatus *status = purple_account_get_active_status(account); gboolean use_whole_url = yahoo_account_use_http_proxy(gc); gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE); PurpleUtilFetchUrlData *url_data; - gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC; + purple_connection_set_protocol_data(gc, yd); + purple_connection_set_flags(gc, PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC); purple_connection_update_progress(gc, _("Connecting"), 1, 2); @@ -3708,7 +3709,7 @@ /* Get the pager server. Actually start connecting in the callback since we * must have the contents of the HTTP response to proceed. */ - url_data = purple_util_fetch_url_request_len_with_account( + url_data = purple_util_fetch_url_request( proxy_ssl ? purple_connection_get_account(gc) : NULL, yd->jp ? YAHOOJP_PAGER_HOST_REQ_URL : YAHOO_PAGER_HOST_REQ_URL, use_whole_url ? TRUE : FALSE, @@ -3721,11 +3722,13 @@ } void yahoo_close(PurpleConnection *gc) { - YahooData *yd = (YahooData *)gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); GSList *l; - if (gc->inpa) - purple_input_remove(gc->inpa); + if (yd->inpa) { + purple_input_remove(yd->inpa); + yd->inpa = 0; + } while (yd->url_datas) { purple_util_fetch_url_cancel(yd->url_datas->data); @@ -3810,7 +3813,7 @@ g_free(yd->current_list15_grp); g_free(yd); - gc->proto_data = NULL; + purple_connection_set_protocol_data(gc, NULL); } const char *yahoo_list_icon(PurpleAccount *a, PurpleBuddy *b) @@ -3827,7 +3830,7 @@ if (!b || !(account = purple_buddy_get_account(b)) || !(gc = purple_account_get_connection(account)) || - !gc->proto_data) + !purple_connection_get_protocol_data(gc)) return NULL; f = yahoo_friend_find(gc, purple_buddy_get_name(b)); @@ -3892,7 +3895,7 @@ buddy = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); id = yd->conf_id; components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); @@ -4036,22 +4039,12 @@ if (f && full) { YahooPersonalDetails *ypd = &f->ypd; - int i; - struct { - char *id; - char *text; - char *value; - } yfields[] = { - {"hp", N_("Home Phone Number"), ypd->phone.home}, - {"wp", N_("Work Phone Number"), ypd->phone.work}, - {"mo", N_("Mobile Phone Number"), ypd->phone.mobile}, - {NULL, NULL, NULL} - }; - for (i = 0; yfields[i].id; i++) { - if (!yfields[i].value || !*yfields[i].value) - continue; - purple_notify_user_info_add_pair(user_info, _(yfields[i].text), yfields[i].value); - } + if (ypd->phone.home && *ypd->phone.home) + purple_notify_user_info_add_pair_plaintext(user_info, _("Home Phone Number"), ypd->phone.home); + if (ypd->phone.work && *ypd->phone.work) + purple_notify_user_info_add_pair_plaintext(user_info, _("Work Phone Number"), ypd->phone.work); + if (ypd->phone.mobile && *ypd->phone.mobile) + purple_notify_user_info_add_pair_plaintext(user_info, _("Mobile Phone Number"), ypd->phone.mobile); } } @@ -4065,7 +4058,7 @@ buddy = (PurpleBuddy *) node; gc = purple_account_get_connection(purple_buddy_get_account(buddy)); - yahoo_add_buddy(gc, buddy, NULL); + yahoo_add_buddy(gc, buddy, NULL, NULL); } @@ -4085,7 +4078,7 @@ static GList *build_presence_submenu(YahooFriend *f, PurpleConnection *gc) { GList *m = NULL; PurpleMenuAction *act; - YahooData *yd = (YahooData *) gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); if (yd->current_status == YAHOO_STATUS_INVISIBLE) { if (f->presence != YAHOO_PRESENCE_ONLINE) { @@ -4145,7 +4138,7 @@ PurpleMenuAction *act; PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(buddy)); - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); static char buf2[1024]; YahooFriend *f; @@ -4228,7 +4221,7 @@ static void yahoo_act_id(PurpleConnection *gc, PurpleRequestFields *fields) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); const char *name = yd->profiles[purple_request_fields_get_choice(fields, "id")]; struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_IDACT, YAHOO_STATUS_AVAILABLE, yd->session_id); @@ -4245,7 +4238,7 @@ PurpleConnection *gc = user_data; gboolean set_cookie = FALSE; gchar *url; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc)); @@ -4281,7 +4274,7 @@ /* XXX I have no idea how this will work with Yahoo! Japan. */ PurpleConnection *gc = action->context; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); PurpleUtilFetchUrlData *url_data; const char* base_url = "http://login.yahoo.com"; @@ -4296,7 +4289,7 @@ use_whole_url ? base_url : "", yd->cookie_t, yd->cookie_y); - url_data = purple_util_fetch_url_request_len_with_account( + url_data = purple_util_fetch_url_request( purple_connection_get_account(gc), base_url, use_whole_url, YAHOO_CLIENT_USERAGENT, TRUE, request, FALSE, -1, yahoo_get_inbox_token_cb, gc); @@ -4395,7 +4388,7 @@ { struct yahoo_sms_carrier_cb_data *sms_cb_data = user_data; PurpleConnection *gc = sms_cb_data->gc; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); char *status = NULL; char *carrier = NULL; PurpleAccount *account = purple_connection_get_account(gc); @@ -4450,7 +4443,7 @@ static void yahoo_get_sms_carrier(PurpleConnection *gc, gpointer data) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); PurpleUtilFetchUrlData *url_data; struct yahoo_sms_carrier_cb_data *sms_cb_data; char *validate_request_str = NULL; @@ -4485,10 +4478,10 @@ YAHOO_CLIENT_VERSION, yd->cookie_t, yd->cookie_y, strlen(validate_request_str), validate_request_str); /* use whole URL if using HTTP Proxy */ - if ((gc->account->proxy_info) && (gc->account->proxy_info->type == PURPLE_PROXY_HTTP)) + if ((purple_account_get_proxy_info(purple_connection_get_account(gc))) && (purple_proxy_info_get_type(purple_account_get_proxy_info(purple_connection_get_account(gc))) == PURPLE_PROXY_HTTP)) use_whole_url = TRUE; - url_data = purple_util_fetch_url_request_len_with_account( + url_data = purple_util_fetch_url_request( purple_connection_get_account(gc), YAHOO_SMS_CARRIER_URL, use_whole_url, YAHOO_CLIENT_USERAGENT, TRUE, request, FALSE, -1, yahoo_get_sms_carrier_cb, data); @@ -4510,7 +4503,7 @@ int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt = NULL; char *msg = yahoo_html_to_codes(what); char *msg2; @@ -4621,7 +4614,7 @@ * * If they have not set an IMVironment, then use the default. */ - wb = purple_whiteboard_get_session(gc->account, who); + wb = purple_whiteboard_get_session(purple_connection_get_account(gc), who); if (wb) yahoo_packet_hash_str(pkt, 63, DOODLE_IMV_KEY); else @@ -4667,7 +4660,7 @@ unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_p2p_data *p2p_data; YahooFederation fed = YAHOO_FEDERATION_NONE; struct yahoo_packet *pkt = NULL; @@ -4738,7 +4731,7 @@ gc = purple_account_get_connection(account); presence = purple_status_get_presence(status); - yd = (YahooData *)gc->proto_data; + yd = purple_connection_get_protocol_data(gc); old_status = yd->current_status; yd->current_status = get_yahoo_status_from_purple_status(status); @@ -4804,7 +4797,7 @@ void yahoo_set_idle(PurpleConnection *gc, int idle) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt = NULL; char *msg = NULL, *msg2 = NULL; PurpleStatus *status = NULL; @@ -4923,7 +4916,7 @@ void yahoo_keepalive(PurpleConnection *gc) { struct yahoo_packet *pkt; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); time_t now = time(NULL); /* We're only allowed to send a ping once an hour or the servers will boot us */ @@ -4954,9 +4947,9 @@ } -void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g) +void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g, const char *message) { - YahooData *yd = (YahooData *)gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt; const char *group = NULL; char *group2; @@ -5019,7 +5012,7 @@ void yahoo_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { - YahooData *yd = (YahooData *)gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt; GSList *buddies, *l; PurpleGroup *g; @@ -5075,7 +5068,7 @@ } void yahoo_add_deny(PurpleConnection *gc, const char *who) { - YahooData *yd = (YahooData *)gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt; YahooFederation fed = YAHOO_FEDERATION_NONE; @@ -5098,7 +5091,7 @@ } void yahoo_rem_deny(PurpleConnection *gc, const char *who) { - YahooData *yd = (YahooData *)gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt; YahooFederation fed = YAHOO_FEDERATION_NONE; @@ -5126,7 +5119,7 @@ account = purple_connection_get_account(gc); - switch (account->perm_deny) + switch (purple_account_get_privacy_type(account)) { case PURPLE_PRIVACY_ALLOW_ALL: for (deny = account->deny; deny; deny = deny->next) @@ -5146,7 +5139,7 @@ void yahoo_change_buddys_group(PurpleConnection *gc, const char *who, const char *old_group, const char *new_group) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt; char *gpn, *gpo; YahooFriend *f = yahoo_friend_find(gc, who); @@ -5193,7 +5186,7 @@ void yahoo_rename_group(PurpleConnection *gc, const char *old_name, PurpleGroup *group, GList *moved_buddies) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt; char *gpn, *gpo; @@ -5222,7 +5215,7 @@ if (*args && args[0]) return PURPLE_CMD_RET_FAILED; - purple_prpl_send_attention(account->gc, c->name, YAHOO_BUZZ); + purple_prpl_send_attention(purple_account_get_connection(account), purple_conversation_get_name(c), YAHOO_BUZZ); return PURPLE_CMD_RET_OK; } @@ -5237,7 +5230,7 @@ if (!args || !args[0]) return PURPLE_CMD_RET_FAILED; - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); purple_debug_info("yahoo", "Trying to join %s \n", args[0]); comp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); @@ -5271,12 +5264,12 @@ PurpleConversation *c; c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, - username, gc->account); + username, purple_connection_get_account(gc)); g_return_val_if_fail(c != NULL, FALSE); purple_debug_info("yahoo", "Sending on account %s to buddy %s.\n", - username, c->name); + username, purple_conversation_get_name(c)); purple_conv_im_send_with_flags(PURPLE_CONV_IM(c), "", PURPLE_MESSAGE_INVISIBLE); return TRUE; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/yahoo/libymsg.h --- a/libpurple/protocols/yahoo/libymsg.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/yahoo/libymsg.h Fri Apr 06 04:30:00 2012 +0000 @@ -188,6 +188,7 @@ typedef struct { PurpleConnection *gc; int fd; + guint inpa; guchar *rxqueue; int rxlen; PurpleCircBuffer *txbuf; @@ -371,7 +372,7 @@ unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state); void yahoo_set_status(PurpleAccount *account, PurpleStatus *status); void yahoo_set_idle(PurpleConnection *gc, int idle); -void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g); +void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g, const char *message); void yahoo_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); void yahoo_add_deny(PurpleConnection *gc, const char *who); void yahoo_rem_deny(PurpleConnection *gc, const char *who); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/yahoo/util.c --- a/libpurple/protocols/yahoo/util.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/yahoo/util.c Fri Apr 06 04:30:00 2012 +0000 @@ -63,8 +63,9 @@ char firstflag = 1; gchar *t1,*t2,*t3; GSList *tmp; - GSList *cookies; - cookies = ((YahooData*)(gc->proto_data))->cookies; + YahooData *yd = purple_connection_get_protocol_data(gc); + GSList *cookies = yd->cookies; + tmp = cookies; while(tmp) { @@ -129,7 +130,7 @@ */ char *yahoo_string_encode(PurpleConnection *gc, const char *str, gboolean *utf8) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); char *ret; const char *to_codeset; @@ -158,7 +159,7 @@ */ char *yahoo_string_decode(PurpleConnection *gc, const char *str, gboolean utf8) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); char *ret; const char *from_codeset; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/yahoo/yahoo_aliases.c --- a/libpurple/protocols/yahoo/yahoo_aliases.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/yahoo/yahoo_aliases.c Fri Apr 06 04:30:00 2012 +0000 @@ -74,7 +74,7 @@ yahoo_fetch_aliases_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message) { PurpleConnection *gc = user_data; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); yd->url_datas = g_slist_remove(yd->url_datas, url_data); @@ -186,7 +186,7 @@ void yahoo_fetch_aliases(PurpleConnection *gc) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); const char *url; gchar *request, *webpage, *webaddress; PurpleUtilFetchUrlData *url_data; @@ -207,7 +207,7 @@ webaddress); /* We have a URL and some header information, let's connect and get some aliases */ - url_data = purple_util_fetch_url_request_len_with_account(purple_connection_get_account(gc), + url_data = purple_util_fetch_url_request(purple_connection_get_account(gc), url, use_whole_url, NULL, TRUE, request, FALSE, -1, yahoo_fetch_aliases_cb, gc); if (url_data != NULL) @@ -230,7 +230,7 @@ PurpleConnection *gc = cb->gc; YahooData *yd; - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); yd->url_datas = g_slist_remove(yd->url_datas, url_data); if (len == 0 || error_message != NULL) { @@ -310,7 +310,7 @@ return; } - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); /* Using callback_data so I have access to gc in the callback function */ cb = g_new0(struct callback_data, 1); @@ -331,7 +331,7 @@ gchar *converted_alias_jp = yahoo_convert_to_numeric(alias_jp); content = g_strdup_printf("\n" "\n\r\n", - purple_account_get_username(gc->account), + purple_account_get_username(purple_connection_get_account(gc)), who, converted_alias_jp); g_free(converted_alias_jp); g_free(alias_jp); @@ -339,7 +339,7 @@ gchar *escaped_alias = g_markup_escape_text(alias, -1); content = g_strdup_printf("\n" "\n\r\n", - purple_account_get_username(gc->account), + purple_account_get_username(purple_connection_get_account(gc)), who, escaped_alias); g_free(escaped_alias); } @@ -351,7 +351,7 @@ gchar *converted_alias_jp = yahoo_convert_to_numeric(alias_jp); content = g_strdup_printf("\n" "\n\r\n", - purple_account_get_username(gc->account), + purple_account_get_username(purple_connection_get_account(gc)), who, cb->id, converted_alias_jp); g_free(converted_alias_jp); g_free(alias_jp); @@ -359,7 +359,7 @@ gchar *escaped_alias = g_markup_escape_text(alias, -1); content = g_strdup_printf("\n" "\n\r\n", - purple_account_get_username(gc->account), + purple_account_get_username(purple_connection_get_account(gc)), who, cb->id, escaped_alias); g_free(escaped_alias); } @@ -379,7 +379,7 @@ content); /* We have a URL and some header information, let's connect and update the alias */ - url_data = purple_util_fetch_url_request_len_with_account( + url_data = purple_util_fetch_url_request( purple_connection_get_account(gc), url, use_whole_url, NULL, TRUE, request, FALSE, -1, yahoo_update_alias_cb, cb); if (url_data != NULL) @@ -517,7 +517,7 @@ } #endif - url_data = purple_util_fetch_url_request_len_with_account(account, webaddress, FALSE, + url_data = purple_util_fetch_url_request(account, webaddress, FALSE, YAHOO_CLIENT_USERAGENT, TRUE, request, FALSE, -1, yahoo_fetch_aliases_cb, gc); if (url_data != NULL) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/yahoo/yahoo_doodle.c --- a/libpurple/protocols/yahoo/yahoo_doodle.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/yahoo/yahoo_doodle.c Fri Apr 06 04:30:00 2012 +0000 @@ -161,7 +161,7 @@ */ wb = purple_whiteboard_create(account, from, DOODLE_STATE_REQUESTED); - ds = wb->proto_data; + ds = purple_whiteboard_get_protocol_data(wb); ds->imv_key = g_strdup(imv_key); yahoo_doodle_command_send_ready(gc, from, imv_key); @@ -189,19 +189,19 @@ if(wb == NULL) return; - if(wb->state == DOODLE_STATE_REQUESTING) + if(purple_whiteboard_get_state(wb) == DOODLE_STATE_REQUESTING) { - doodle_session *ds = wb->proto_data; + doodle_session *ds = purple_whiteboard_get_protocol_data(wb); purple_whiteboard_start(wb); - wb->state = DOODLE_STATE_ESTABLISHED; + purple_whiteboard_set_state(wb, DOODLE_STATE_ESTABLISHED); yahoo_doodle_command_send_confirm(gc, from, imv_key); /* Let's steal the imv_key and reuse it */ g_free(ds->imv_key); ds->imv_key = g_strdup(imv_key); } - else if(wb->state == DOODLE_STATE_ESTABLISHED) + else if(purple_whiteboard_get_state(wb) == DOODLE_STATE_ESTABLISHED) { /* TODO Ask whether to save picture too */ purple_whiteboard_clear(wb); @@ -211,7 +211,7 @@ * already thinks we're in a session with them (when their chat message * contains the doodle imv key) */ - else if(wb->state == DOODLE_STATE_REQUESTED) + else if(purple_whiteboard_get_state(wb) == DOODLE_STATE_REQUESTED) { /* purple_whiteboard_start(wb); */ yahoo_doodle_command_send_ready(gc, from, imv_key); @@ -292,7 +292,7 @@ if(wb == NULL) return; - if(wb->state == DOODLE_STATE_ESTABLISHED) + if(purple_whiteboard_get_state(wb) == DOODLE_STATE_ESTABLISHED) { /* TODO Ask user whether to save the image before clearing it */ @@ -333,9 +333,9 @@ /* TODO Combine the following IF's? */ /* Check if we requested a doodle session */ - /*if(wb->state == DOODLE_STATE_REQUESTING) + /*if(purple_whiteboard_get_state(wb) == DOODLE_STATE_REQUESTING) { - wb->state = DOODLE_STATE_ESTABLISHED; + purple_whiteboard_set_state(wb, DOODLE_STATE_ESTABLISHED); purple_whiteboard_start(wb); @@ -343,9 +343,9 @@ }*/ /* Check if we accepted a request for a doodle session */ - if(wb->state == DOODLE_STATE_REQUESTED) + if(purple_whiteboard_get_state(wb) == DOODLE_STATE_REQUESTED) { - wb->state = DOODLE_STATE_ESTABLISHED; + purple_whiteboard_set_state(wb, DOODLE_STATE_ESTABLISHED); purple_whiteboard_start(wb); } @@ -372,7 +372,7 @@ /* TODO Ask if user wants to save picture before the session is closed */ - wb->state = DOODLE_STATE_CANCELLED; + purple_whiteboard_set_state(wb, DOODLE_STATE_CANCELLED); purple_whiteboard_destroy(wb); } @@ -389,12 +389,12 @@ purple_debug_info("yahoo", "doodle: Sent %s (%s)\n", type, to); - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); /* Make and send an acknowledge (ready) Doodle packet */ pkt = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id); yahoo_packet_hash_str(pkt, 49, "IMVIRONMENT"); - yahoo_packet_hash_str(pkt, 1, purple_account_get_username(gc->account)); + yahoo_packet_hash_str(pkt, 1, purple_account_get_username(purple_connection_get_account(gc))); yahoo_packet_hash_str(pkt, 14, message); yahoo_packet_hash_int(pkt, 13, command); yahoo_packet_hash_str(pkt, 5, to); @@ -450,21 +450,23 @@ ds->brush_size = DOODLE_BRUSH_SMALL; ds->brush_color = DOODLE_COLOR_RED; - wb->proto_data = ds; + purple_whiteboard_set_protocol_data(wb, ds); } void yahoo_doodle_end(PurpleWhiteboard *wb) { - PurpleConnection *gc = purple_account_get_connection(wb->account); - doodle_session *ds = wb->proto_data; + PurpleAccount *account = purple_whiteboard_get_account(wb); + PurpleConnection *gc = purple_account_get_connection(account); + doodle_session *ds = purple_whiteboard_get_protocol_data(wb); /* g_debug_debug("yahoo", "doodle: yahoo_doodle_end()\n"); */ - if (gc && wb->state != DOODLE_STATE_CANCELLED) - yahoo_doodle_command_send_shutdown(gc, wb->who); + if (gc && (purple_whiteboard_get_state(wb) != DOODLE_STATE_CANCELLED)) + yahoo_doodle_command_send_shutdown(gc, purple_whiteboard_get_who(wb)); g_free(ds->imv_key); - g_free(wb->proto_data); + g_free(ds); + purple_whiteboard_set_protocol_data(wb, NULL); } void yahoo_doodle_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height) @@ -494,20 +496,25 @@ void yahoo_doodle_send_draw_list(PurpleWhiteboard *wb, GList *draw_list) { - doodle_session *ds = wb->proto_data; + PurpleAccount *account = purple_whiteboard_get_account(wb); + PurpleConnection *gc = purple_account_get_connection(account); + doodle_session *ds = purple_whiteboard_get_protocol_data(wb); char *message; g_return_if_fail(draw_list != NULL); message = yahoo_doodle_build_draw_string(ds, draw_list); - yahoo_doodle_command_send_draw(wb->account->gc, wb->who, message, ds->imv_key); + yahoo_doodle_command_send_draw(gc, purple_whiteboard_get_who(wb), message, ds->imv_key); g_free(message); } void yahoo_doodle_clear(PurpleWhiteboard *wb) { - doodle_session *ds = wb->proto_data; - yahoo_doodle_command_send_clear(wb->account->gc, wb->who, ds->imv_key); + PurpleAccount *account = purple_whiteboard_get_account(wb); + PurpleConnection *gc = purple_account_get_connection(account); + doodle_session *ds = purple_whiteboard_get_protocol_data(wb); + + yahoo_doodle_command_send_clear(gc, purple_whiteboard_get_who(wb), ds->imv_key); } @@ -560,14 +567,14 @@ void yahoo_doodle_get_brush(const PurpleWhiteboard *wb, int *size, int *color) { - doodle_session *ds = wb->proto_data; + doodle_session *ds = purple_whiteboard_get_protocol_data(wb); *size = ds->brush_size; *color = ds->brush_color; } void yahoo_doodle_set_brush(PurpleWhiteboard *wb, int size, int color) { - doodle_session *ds = wb->proto_data; + doodle_session *ds = purple_whiteboard_get_protocol_data(wb); ds->brush_size = size; ds->brush_color = color; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/yahoo/yahoo_filexfer.c --- a/libpurple/protocols/yahoo/yahoo_filexfer.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/yahoo/yahoo_filexfer.c Fri Apr 06 04:30:00 2012 +0000 @@ -43,7 +43,7 @@ PurpleConnection *gc; long expires; gboolean started; - gchar *txbuf; + guchar *txbuf; gsize txbuflen; gsize txbuf_written; guint tx_handler; @@ -85,7 +85,7 @@ GSList *l; gc = xd->gc; - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); /* remove entry from map */ if(xd->xfer_peer_idstring) { @@ -120,13 +120,13 @@ { PurpleXfer *xfer; struct yahoo_xfer_data *xd; - int remaining, written; + gssize remaining, written; xfer = data; - xd = xfer->data; + xd = purple_xfer_get_protocol_data(xfer); remaining = xd->txbuflen - xd->txbuf_written; - written = write(xfer->fd, xd->txbuf + xd->txbuf_written, remaining); + written = purple_xfer_write(xfer, xd->txbuf + xd->txbuf_written, remaining); if (written < 0 && errno == EAGAIN) written = 0; @@ -160,22 +160,23 @@ if (!(xfer = data)) return; - if (!(xd = xfer->data)) + if (!(xd = purple_xfer_get_protocol_data(xfer))) return; if ((source < 0) || (xd->path == NULL) || (xd->host == NULL)) { purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer), - xfer->who, _("Unable to connect.")); + purple_xfer_get_remote_user(xfer), _("Unable to connect.")); purple_xfer_cancel_remote(xfer); return; } - xfer->fd = source; + purple_xfer_set_fd(xfer, source); /* The first time we get here, assemble the tx buffer */ if (xd->txbuflen == 0) { - xd->txbuf = g_strdup_printf("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n", + gchar *header = g_strdup_printf("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n", xd->path, xd->host); - xd->txbuflen = strlen(xd->txbuf); + xd->txbuf = (guchar*) header; + xd->txbuflen = strlen(header); xd->txbuf_written = 0; } @@ -191,13 +192,13 @@ { PurpleXfer *xfer; struct yahoo_xfer_data *xd; - int written, remaining; + gssize written, remaining; xfer = data; - xd = xfer->data; + xd = purple_xfer_get_protocol_data(xfer); remaining = xd->txbuflen - xd->txbuf_written; - written = write(xfer->fd, xd->txbuf + xd->txbuf_written, remaining); + written = purple_xfer_write(xfer, xd->txbuf + xd->txbuf_written, remaining); if (written < 0 && errno == EAGAIN) written = 0; @@ -239,32 +240,32 @@ if (!(xfer = data)) return; - if (!(xd = xfer->data)) + if (!(xd = purple_xfer_get_protocol_data(xfer))) return; if (source < 0) { purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer), - xfer->who, _("Unable to connect.")); + purple_xfer_get_remote_user(xfer), _("Unable to connect.")); purple_xfer_cancel_remote(xfer); return; } - xfer->fd = source; + purple_xfer_set_fd(xfer, source); /* Assemble the tx buffer */ gc = xd->gc; account = purple_connection_get_account(gc); - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANSFER, YAHOO_STATUS_AVAILABLE, yd->session_id); - size = g_strdup_printf("%" G_GSIZE_FORMAT, purple_xfer_get_size(xfer)); + size = g_strdup_printf("%" G_GOFFSET_FORMAT, purple_xfer_get_size(xfer)); filename = g_path_get_basename(purple_xfer_get_local_filename(xfer)); encoded_filename = yahoo_string_encode(gc, filename, NULL); yahoo_packet_hash(pkt, "sssss", 0, purple_connection_get_display_name(gc), - 5, xfer->who, 14, "", 27, encoded_filename, 28, size); + 5, purple_xfer_get_remote_user(xfer), 14, "", 27, encoded_filename, 28, size); g_free(size); g_free(encoded_filename); g_free(filename); @@ -278,7 +279,7 @@ port = purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT); header = g_strdup_printf( "POST http://%s:%d/notifyft HTTP/1.0\r\n" - "Content-length: %" G_GSIZE_FORMAT "\r\n" + "Content-length: %" G_GOFFSET_FORMAT "\r\n" "Host: %s:%d\r\n" "Cookie: Y=%s; T=%s\r\n" "\r\n", @@ -313,9 +314,9 @@ PurpleAccount *account; YahooData *yd; - xfer_data = xfer->data; + xfer_data = purple_xfer_get_protocol_data(xfer); gc = xfer_data->gc; - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); account = purple_connection_get_account(gc); if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) { @@ -339,7 +340,7 @@ } } } else { - xfer->fd = -1; + purple_xfer_set_fd(xfer, -1); if (purple_proxy_connect(gc, account, xfer_data->host, xfer_data->port, yahoo_receivefile_connected, xfer) == NULL) { purple_notify_error(gc, NULL, _("File Transfer Failed"), @@ -357,9 +358,9 @@ YahooData *yd; struct yahoo_packet *pkt; - xfer_data = xfer->data; + xfer_data = purple_xfer_get_protocol_data(xfer); gc = xfer_data->gc; - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); account = purple_connection_get_account(gc); if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) { @@ -370,14 +371,14 @@ yd->session_id); yahoo_packet_hash(pkt, "sssiiiisiii", 1, purple_normalize(account, purple_account_get_username(account)), - 5, xfer->who, + 5, purple_xfer_get_remote_user(xfer), 265, xfer_data->xfer_peer_idstring, 222, 1, 266, 1, 302, 268, 300, 268, 27, filename, - 28, xfer->size, + 28, (int)purple_xfer_get_size(xfer), 301, 268, 303, 268); g_free(filename); @@ -388,7 +389,7 @@ yahoo_packet_hash(pkt, "sssi", 1, purple_normalize(account, purple_account_get_username(account)), - 5, xfer->who, + 5, purple_xfer_get_remote_user(xfer), 265, xfer_data->xfer_peer_idstring, 222, 3); } else { @@ -397,7 +398,7 @@ yahoo_packet_hash(pkt, "sssi", 1, purple_normalize(account, purple_account_get_username(account)), - 5, xfer->who, + 5, purple_xfer_get_remote_user(xfer), 265, xfer_data->xfer_peer_idstring, 271, 1); } @@ -410,14 +411,14 @@ /* We don't need to do anything here, do we? */ } -static guint calculate_length(const gchar *l, size_t len) +static goffset calculate_length(const gchar *l, size_t len) { int i; for (i = 0; i < len; i++) { if (!g_ascii_isdigit(l[i])) continue; - return strtol(l + i, NULL, 10); + return g_ascii_strtoll(l + i, NULL, 10); } return 0; } @@ -429,14 +430,14 @@ gchar *start = NULL; gchar *length; gchar *end; - int filelen; - struct yahoo_xfer_data *xd = xfer->data; + goffset filelen; + struct yahoo_xfer_data *xd = purple_xfer_get_protocol_data(xfer); if (purple_xfer_get_type(xfer) != PURPLE_XFER_RECEIVE) { return 0; } - len = read(xfer->fd, buf, sizeof(buf)); + len = read(purple_xfer_get_fd(xfer), buf, sizeof(buf)); if (len <= 0) { if ((purple_xfer_get_size(xfer) > 0) && @@ -490,7 +491,7 @@ static gssize yahoo_xfer_write(const guchar *buffer, size_t size, PurpleXfer *xfer) { gssize len; - struct yahoo_xfer_data *xd = xfer->data; + struct yahoo_xfer_data *xd = purple_xfer_get_protocol_data(xfer); if (!xd) return -1; @@ -499,7 +500,7 @@ return -1; } - len = write(xfer->fd, buffer, size); + len = write(purple_xfer_get_fd(xfer), buffer, size); if (len == -1) { if (purple_xfer_get_bytes_sent(xfer) >= purple_xfer_get_size(xfer)) @@ -516,7 +517,7 @@ { struct yahoo_xfer_data *xfer_data; - xfer_data = xfer->data; + xfer_data = purple_xfer_get_protocol_data(xfer); if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL && xfer_data->version == 15) { @@ -526,7 +527,7 @@ struct yahoo_packet *pkt; gc = xfer_data->gc; - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); account = purple_connection_get_account(gc); if(xfer_data->xfer_idstring_for_relay) /* hack to see if file trans acc/info packet has been received */ { @@ -535,7 +536,7 @@ yd->session_id); yahoo_packet_hash(pkt, "sssi", 1, purple_normalize(account, purple_account_get_username(account)), - 5, xfer->who, + 5, purple_xfer_get_remote_user(xfer), 265, xfer_data->xfer_peer_idstring, 66, -1); } @@ -546,7 +547,7 @@ yd->session_id); yahoo_packet_hash(pkt, "sssi", 1, purple_normalize(account, purple_account_get_username(account)), - 5, xfer->who, + 5, purple_xfer_get_remote_user(xfer), 265, xfer_data->xfer_peer_idstring, 222, 2); } @@ -556,14 +557,14 @@ if (xfer_data) yahoo_xfer_data_free(xfer_data); - xfer->data = NULL; + purple_xfer_set_protocol_data(xfer, NULL); } static void yahoo_xfer_cancel_recv(PurpleXfer *xfer) { struct yahoo_xfer_data *xfer_data; - xfer_data = xfer->data; + xfer_data = purple_xfer_get_protocol_data(xfer); if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL && xfer_data->version == 15) { @@ -574,7 +575,7 @@ struct yahoo_packet *pkt; gc = xfer_data->gc; - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); account = purple_connection_get_account(gc); if(!xfer_data->xfer_idstring_for_relay) /* hack to see if file trans acc/info packet has been received */ { @@ -583,7 +584,7 @@ yd->session_id); yahoo_packet_hash(pkt, "sssi", 1, purple_normalize(account, purple_account_get_username(account)), - 5, xfer->who, + 5, purple_xfer_get_remote_user(xfer), 265, xfer_data->xfer_peer_idstring, 222, 4); } @@ -594,7 +595,7 @@ yd->session_id); yahoo_packet_hash(pkt, "sssi", 1, purple_normalize(account, purple_account_get_username(account)), - 5, xfer->who, + 5, purple_xfer_get_remote_user(xfer), 265, xfer_data->xfer_peer_idstring, 66, -1); } @@ -603,7 +604,7 @@ if (xfer_data) yahoo_xfer_data_free(xfer_data); - xfer->data = NULL; + purple_xfer_set_protocol_data(xfer, NULL); } /* Send HTTP OK after receiving file */ @@ -611,9 +612,10 @@ { char *tx = NULL; int written; + int fd = purple_xfer_get_fd(xfer); - tx = g_strdup_printf("HTTP/1.1 200 OK\r\nContent-Length: 0\r\nContent-Type: application/octet-stream\r\nConnection: close\r\n\r\n"); - written = write(xfer->fd, tx, strlen(tx)); + tx = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\nContent-Type: application/octet-stream\r\nConnection: close\r\n\r\n"; + written = write(fd, tx, strlen(tx)); if (written < 0 && errno == EAGAIN) written = 0; @@ -621,9 +623,8 @@ purple_debug_info("yahoo", "p2p filetransfer: Unable to write HTTP OK"); /* close connection */ - close(xfer->fd); - xfer->fd = -1; - g_free(tx); + close(fd); + purple_xfer_set_fd(xfer, -1); } static void yahoo_xfer_end(PurpleXfer *xfer_old) @@ -633,13 +634,13 @@ PurpleConnection *gc; YahooData *yd; - xfer_data = xfer_old->data; + xfer_data = purple_xfer_get_protocol_data(xfer_old); if(xfer_data && xfer_data->version == 15 && purple_xfer_get_type(xfer_old) == PURPLE_XFER_RECEIVE && xfer_data->filename_list) { /* Send HTTP OK in case of p2p transfer, when we act as server */ - if((xfer_data->xfer_url != NULL) && (xfer_old->fd >=0) && (purple_xfer_get_status(xfer_old) == PURPLE_XFER_STATUS_DONE)) + if((xfer_data->xfer_url != NULL) && (purple_xfer_get_fd(xfer_old) >=0) && (purple_xfer_get_status(xfer_old) == PURPLE_XFER_STATUS_DONE)) yahoo_p2p_ft_server_send_OK(xfer_old); /* removing top of filename & size list completely */ @@ -656,13 +657,13 @@ if(xfer_data->filename_list) { gchar* filename; - long filesize; + goffset filesize; filename = xfer_data->filename_list->data; - filesize = atol( xfer_data->size_list->data ); + filesize = g_ascii_strtoll( xfer_data->size_list->data, NULL, 10 ); gc = xfer_data->gc; - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); /* setting up xfer_data for next file's tranfer */ g_free(xfer_data->host); @@ -689,10 +690,10 @@ xfer_data->firstoflist = FALSE; /* Dereference xfer_data from old xfer */ - xfer_old->data = NULL; + purple_xfer_set_protocol_data(xfer_old, NULL); /* Build the file transfer handle. */ - xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, xfer_old->who); + xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_RECEIVE, purple_xfer_get_remote_user(xfer_old)); if (xfer) { @@ -702,7 +703,7 @@ g_free(utf8_filename); purple_xfer_set_size(xfer, filesize); - xfer->data = xfer_data; + purple_xfer_set_protocol_data(xfer, xfer_data); /* Setup our I/O op functions */ purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15); @@ -726,8 +727,7 @@ } if (xfer_data) yahoo_xfer_data_free(xfer_data); - xfer_old->data = NULL; - + purple_xfer_set_protocol_data(xfer_old, NULL); } void yahoo_process_p2pfilexfer(PurpleConnection *gc, struct yahoo_packet *pkt) @@ -803,10 +803,10 @@ struct yahoo_xfer_data *xfer_data; char *service = NULL; char *filename = NULL; - unsigned long filesize = 0L; + goffset filesize = G_GOFFSET_CONSTANT(0); GSList *l; - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; @@ -831,7 +831,7 @@ filename = pair->value; break; case 28: - filesize = atol(pair->value); + filesize = g_ascii_strtoll(pair->value, NULL, 10); break; case 49: service = pair->value; @@ -880,13 +880,13 @@ xfer_data->host, xfer_data->port, xfer_data->path, url); /* Build the file transfer handle. */ - xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, from); + xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_RECEIVE, from); if (xfer == NULL) { g_free(xfer_data); g_return_if_reached(); } - xfer->data = xfer_data; + purple_xfer_set_protocol_data(xfer, xfer_data); /* Set the info about the incoming file. */ if (filename) { @@ -936,14 +936,14 @@ xfer_data->gc = gc; /* Build the file transfer handle. */ - xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who); + xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_SEND, who); if (xfer == NULL) { g_free(xfer_data); g_return_val_if_reached(NULL); } - xfer->data = xfer_data; + purple_xfer_set_protocol_data(xfer, xfer_data); /* Setup our I/O op functions */ purple_xfer_set_init_fnc(xfer, yahoo_xfer_init); @@ -993,11 +993,11 @@ if (!(xfer = data)) return; - if (!(xd = xfer->data)) + if (!(xd = purple_xfer_get_protocol_data(xfer))) return; gc = xd->gc; account = purple_connection_get_account(gc); - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); if(!hosts) { @@ -1057,7 +1057,7 @@ yahoo_packet_hash(pkt, "ssssis", 1, purple_normalize(account, purple_account_get_username(account)), - 5, xfer->who, + 5, purple_xfer_get_remote_user(xfer), 265, xd->xfer_peer_idstring, 27, filename, 249, 3, @@ -1077,7 +1077,7 @@ void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file) { struct yahoo_xfer_data *xfer_data; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); PurpleXfer *xfer = yahoo_new_xfer(gc, who); g_return_if_fail(xfer != NULL); @@ -1086,7 +1086,7 @@ if( !g_hash_table_lookup(yd->peers, who) ) yahoo_send_p2p_pkt(gc, who, 0); - xfer_data = xfer->data; + xfer_data = purple_xfer_get_protocol_data(xfer); xfer_data->status_15 = STARTED; purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15); xfer_data->version = 15; @@ -1108,26 +1108,22 @@ PurpleXfer *xfer; struct yahoo_xfer_data *xd; int did; - gchar* buf; - gchar* t; + guchar buf[1000]; PurpleAccount *account; PurpleConnection *gc; xfer = data; - xd = xfer->data; + xd = purple_xfer_get_protocol_data(xfer); account = purple_connection_get_account(xd->gc); gc = xd->gc; - buf=g_strnfill(1000, 0); - while((did = read(source, buf, 998)) > 0) + while((did = read(source, buf, sizeof(buf))) > 0) { + /* TODO: Convert to circ buffer, this all is pretty horrible */ + xd->txbuf = g_realloc(xd->txbuf, xd->txbuflen + did); + g_memmove(xd->txbuf + xd->txbuflen, buf, did); xd->txbuflen += did; - buf[did] = '\0'; - t = xd->txbuf; - xd->txbuf = g_strconcat(t,buf,NULL); - g_free(t); } - g_free(buf); if (did < 0 && errno == EAGAIN) return; @@ -1167,7 +1163,7 @@ int remaining, written; xfer = data; - xd = xfer->data; + xd = purple_xfer_get_protocol_data(xfer); remaining = xd->txbuflen - xd->txbuf_written; written = write(source, xd->txbuf + xd->txbuf_written, remaining); @@ -1200,13 +1196,13 @@ else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == HEAD_REPLY_RECEIVED) { xd->status_15 = TRANSFER_PHASE; - xfer->fd = source; + purple_xfer_set_fd(xfer, source); purple_xfer_start(xfer, source, NULL, 0); } else if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && (xd->status_15 == ACCEPTED || xd->status_15 == P2P_GET_REQUESTED) ) { xd->status_15 = TRANSFER_PHASE; - xfer->fd = source; + purple_xfer_set_fd(xfer, source); /* Remove Read event */ purple_input_remove(xd->input_event); xd->input_event = 0; @@ -1219,9 +1215,9 @@ purple_input_remove(xd->input_event); xd->input_event = 0; close(source); - xfer->fd = -1; + purple_xfer_set_fd(xfer, -1); /* start local server, listen for connections */ - purple_network_listen(xd->yahoo_local_p2p_ft_server_port, SOCK_STREAM, yahoo_p2p_ft_server_listen_cb, xfer); + purple_network_listen(xd->yahoo_local_p2p_ft_server_port, AF_UNSPEC, SOCK_STREAM, TRUE, yahoo_p2p_ft_server_listen_cb, xfer); } else { @@ -1239,13 +1235,13 @@ if (!(xfer = data)) return; - if (!(xd = xfer->data)) + if (!(xd = purple_xfer_get_protocol_data(xfer))) return; gc = xd->gc; account = purple_connection_get_account(gc); if ((source < 0) || (xd->path == NULL) || (xd->host == NULL)) { purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer), - xfer->who, _("Unable to connect.")); + purple_xfer_get_remote_user(xfer), _("Unable to connect.")); purple_xfer_cancel_remote(xfer); return; } @@ -1253,7 +1249,8 @@ if (xd->txbuflen == 0) { gchar* cookies; - YahooData *yd = gc->proto_data; + gchar* initial_buffer; + YahooData *yd = purple_connection_get_protocol_data(gc); /* cookies = yahoo_get_cookies(gc); * This doesn't seem to be working. The function is returning NULL, which yahoo servers don't like @@ -1266,30 +1263,30 @@ if(xd->info_val_249 == 2) { /* sending file via p2p, we are connected as client */ - xd->txbuf = g_strdup_printf("POST /%s HTTP/1.1\r\n" + initial_buffer = g_strdup_printf("POST /%s HTTP/1.1\r\n" "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n" "Host: %s\r\n" - "Content-Length: %ld\r\n" + "Content-Length: %" G_GOFFSET_FORMAT "\r\n" "Cache-Control: no-cache\r\n\r\n", xd->path, xd->host, - (long int)xfer->size); /* to do, add Referer */ + purple_xfer_get_size(xfer)); /* to do, add Referer */ } else { /* sending file via relaying */ - xd->txbuf = g_strdup_printf("POST /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n" + initial_buffer = g_strdup_printf("POST /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n" "Cookie:%s\r\n" "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n" "Host: %s\r\n" - "Content-Length: %ld\r\n" + "Content-Length: %" G_GOFFSET_FORMAT "\r\n" "Cache-Control: no-cache\r\n\r\n", purple_url_encode(xd->xfer_idstring_for_relay), purple_normalize(account, purple_account_get_username(account)), - xfer->who, + purple_xfer_get_remote_user(xfer), cookies, xd->host, - (long int)xfer->size); + purple_xfer_get_size(xfer)); /* to do, add Referer */ } } else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == STARTED) @@ -1297,7 +1294,7 @@ if(xd->info_val_249 == 1) { /* receiving file via p2p, connected as client */ - xd->txbuf = g_strdup_printf("HEAD /%s HTTP/1.1\r\n" + initial_buffer = g_strdup_printf("HEAD /%s HTTP/1.1\r\n" "Accept: */*\r\n" "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n" "Host: %s\r\n" @@ -1308,7 +1305,7 @@ else { /* receiving file via relaying */ - xd->txbuf = g_strdup_printf("HEAD /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n" + initial_buffer = g_strdup_printf("HEAD /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n" "Accept: */*\r\n" "Cookie: %s\r\n" "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n" @@ -1317,7 +1314,7 @@ "Cache-Control: no-cache\r\n\r\n", purple_url_encode(xd->xfer_idstring_for_relay), purple_normalize(account, purple_account_get_username(account)), - xfer->who, + purple_xfer_get_remote_user(xfer), cookies, xd->host); } @@ -1327,7 +1324,7 @@ if(xd->info_val_249 == 1) { /* receiving file via p2p, connected as client */ - xd->txbuf = g_strdup_printf("GET /%s HTTP/1.1\r\n" + initial_buffer = g_strdup_printf("GET /%s HTTP/1.1\r\n" "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n" "Host: %s\r\n" "Connection: Keep-Alive\r\n\r\n", @@ -1336,14 +1333,14 @@ else { /* receiving file via relaying */ - xd->txbuf = g_strdup_printf("GET /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n" + initial_buffer = g_strdup_printf("GET /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n" "Cookie: %s\r\n" "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n" "Host: %s\r\n" "Connection: Keep-Alive\r\n\r\n", purple_url_encode(xd->xfer_idstring_for_relay), purple_normalize(account, purple_account_get_username(account)), - xfer->who, + purple_xfer_get_remote_user(xfer), cookies, xd->host); } @@ -1354,7 +1351,8 @@ g_free(cookies); return; } - xd->txbuflen = strlen(xd->txbuf); + xd->txbuf = (guchar*) initial_buffer; + xd->txbuflen = strlen(initial_buffer); xd->txbuf_written = 0; g_free(cookies); } @@ -1373,14 +1371,14 @@ struct yahoo_xfer_data *xd; xfer = data; - if (!(xd = xfer->data)) { + if (!(xd = purple_xfer_get_protocol_data(xfer))) { purple_xfer_cancel_remote(xfer); return; } purple_input_remove(xd->input_event); xd->status_15 = TRANSFER_PHASE; - xfer->fd = source; + purple_xfer_set_fd(xfer, source); purple_xfer_start(xfer, source, NULL, 0); } @@ -1396,7 +1394,7 @@ char *time_str; xfer = data; - if (!(xd = xfer->data)) { + if (!(xd = purple_xfer_get_protocol_data(xfer))) { purple_xfer_cancel_remote(xfer); return; } @@ -1431,14 +1429,15 @@ time_str[strlen(time_str) - 1] = '\0'; if (xd->txbuflen == 0) { - xd->txbuf = g_strdup_printf("HTTP/1.0 200 OK\r\n" + gchar *initial_buffer = g_strdup_printf("HTTP/1.0 200 OK\r\n" "Date: %s GMT\r\n" "Server: Y!/1.0\r\n" "MIME-version: 1.0\r\n" "Last-modified: %s GMT\r\n" - "Content-length: %" G_GSIZE_FORMAT "\r\n\r\n", - time_str, time_str, xfer->size); - xd->txbuflen = strlen(xd->txbuf); + "Content-length: %" G_GOFFSET_FORMAT "\r\n\r\n", + time_str, time_str, purple_xfer_get_size(xfer)); + xd->txbuf = (guchar *)initial_buffer; + xd->txbuflen = strlen(initial_buffer); xd->txbuf_written = 0; } @@ -1458,7 +1457,7 @@ struct yahoo_xfer_data *xd; xfer = data; - if (!(xd = xfer->data)) { + if (!(xd = purple_xfer_get_protocol_data(xfer))) { purple_xfer_cancel_remote(xfer); return; } @@ -1480,8 +1479,8 @@ close(xd->yahoo_local_p2p_ft_server_fd); /* Add an Input Read event to the file descriptor */ - xfer->fd = acceptfd; - if(xfer->type == PURPLE_XFER_RECEIVE) + purple_xfer_set_fd(xfer, acceptfd); + if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) xd->input_event = purple_input_add(acceptfd, PURPLE_INPUT_READ, yahoo_p2p_ft_POST_cb, data); else xd->input_event = purple_input_add(acceptfd, PURPLE_INPUT_READ, yahoo_p2p_ft_HEAD_GET_cb, data); @@ -1500,14 +1499,14 @@ char *filename_without_spaces = NULL; xfer = data; - if (!(xd = xfer->data) || (listenfd == -1)) { + if (!(xd = purple_xfer_get_protocol_data(xfer)) || (listenfd == -1)) { purple_debug_warning("yahoo","p2p: error starting server for p2p file transfer\n"); purple_xfer_cancel_remote(xfer); return; } - if( (xfer->type == PURPLE_XFER_RECEIVE) || (xd->status_15 != P2P_HEAD_REPLIED) ) { - yd = xd->gc->proto_data; + if( (purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) || (xd->status_15 != P2P_HEAD_REPLIED) ) { + yd = purple_connection_get_protocol_data(xd->gc); account = purple_connection_get_account(xd->gc); local_ip = purple_network_get_my_ip(listenfd); xd->yahoo_local_p2p_ft_server_port = purple_network_get_port_from_fd(listenfd); @@ -1515,18 +1514,18 @@ filename = g_path_get_basename(purple_xfer_get_local_filename(xfer)); filename_without_spaces = g_strdup(filename); purple_util_chrreplace(filename_without_spaces, ' ', '+'); - xd->xfer_url = g_strdup_printf("/Messenger.%s.%d000%s?AppID=Messenger&UserID=%s&K=lc9lu2u89gz1llmplwksajkjx", xfer->who, (int)time(NULL), filename_without_spaces, xfer->who); + xd->xfer_url = g_strdup_printf("/Messenger.%s.%d000%s?AppID=Messenger&UserID=%s&K=lc9lu2u89gz1llmplwksajkjx", purple_xfer_get_remote_user(xfer), (int)time(NULL), filename_without_spaces, purple_xfer_get_remote_user(xfer)); url_to_send = g_strdup_printf("http://%s:%d%s", local_ip, xd->yahoo_local_p2p_ft_server_port, xd->xfer_url); - if(xfer->type == PURPLE_XFER_RECEIVE) { + if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) { xd->info_val_249 = 2; /* 249=2: we are p2p server, and receiving file */ pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15, YAHOO_STATUS_AVAILABLE, yd->session_id); yahoo_packet_hash(pkt, "ssssis", 1, purple_normalize(account, purple_account_get_username(account)), - 5, xfer->who, + 5, purple_xfer_get_remote_user(xfer), 265, xd->xfer_peer_idstring, - 27, xfer->filename, + 27, purple_xfer_get_filename(xfer), 249, 2, 250, url_to_send); } @@ -1535,7 +1534,7 @@ pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id); yahoo_packet_hash(pkt, "ssssis", 1, purple_normalize(account, purple_account_get_username(account)), - 5, xfer->who, + 5, purple_xfer_get_remote_user(xfer), 265, xd->xfer_peer_idstring, 27, filename, 249, 1, @@ -1564,15 +1563,15 @@ gchar *filename; struct yahoo_p2p_data *p2p_data; - if (!(xd = xfer->data)) + if (!(xd = purple_xfer_get_protocol_data(xfer))) return; account = purple_connection_get_account(gc); - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); - p2p_data = g_hash_table_lookup(yd->peers, xfer->who); + p2p_data = g_hash_table_lookup(yd->peers, purple_xfer_get_remote_user(xfer)); if( p2p_data->connection_type == YAHOO_P2P_WE_ARE_SERVER ) - if(purple_network_listen_range(0, 0, SOCK_STREAM, yahoo_p2p_ft_server_listen_cb, xfer)) + if(purple_network_listen_range(0, 0, AF_UNSPEC, SOCK_STREAM, TRUE, yahoo_p2p_ft_server_listen_cb, xfer)) return; pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id); @@ -1580,7 +1579,7 @@ yahoo_packet_hash(pkt, "ssssi", 1, purple_normalize(account, purple_account_get_username(account)), - 5, xfer->who, + 5, purple_xfer_get_remote_user(xfer), 265, xd->xfer_peer_idstring, 27, filename, 249, 2); /* 249=2: we are p2p client */ @@ -1603,13 +1602,13 @@ char *filename = NULL; char *xfer_peer_idstring = NULL; char *utf8_filename; - unsigned long filesize = 0L; + goffset filesize = G_GOFFSET_CONSTANT(0); GSList *l; GSList *filename_list = NULL; GSList *size_list = NULL; int nooffiles = 0; - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; @@ -1683,13 +1682,13 @@ account = purple_connection_get_account(gc); if (yd->jp) { - purple_dnsquery_a_account(account, YAHOOJP_XFER_RELAY_HOST, + purple_dnsquery_a(account, YAHOOJP_XFER_RELAY_HOST, YAHOOJP_XFER_RELAY_PORT, yahoo_xfer_dns_connected_15, xfer); } else { - purple_dnsquery_a_account(account, YAHOO_XFER_RELAY_HOST, + purple_dnsquery_a(account, YAHOO_XFER_RELAY_HOST, YAHOO_XFER_RELAY_PORT, yahoo_xfer_dns_connected_15, xfer); } @@ -1720,7 +1719,7 @@ filename_list = g_slist_reverse(filename_list); size_list = g_slist_reverse(size_list); filename = filename_list->data; - filesize = atol(size_list->data); + filesize = g_ascii_strtoll(size_list->data, NULL, 10); if(!from) return; xfer_data = g_new0(struct yahoo_xfer_data, 1); @@ -1732,22 +1731,20 @@ xfer_data->size_list = size_list; /* Build the file transfer handle. */ - xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, from); + xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_RECEIVE, from); if (xfer == NULL) { g_free(xfer_data); g_return_if_reached(); } - xfer->message = NULL; - /* Set the info about the incoming file. */ utf8_filename = yahoo_string_decode(gc, filename, TRUE); purple_xfer_set_filename(xfer, utf8_filename); g_free(utf8_filename); purple_xfer_set_size(xfer, filesize); - xfer->data = xfer_data; + purple_xfer_set_protocol_data(xfer, xfer_data); /* Setup our I/O op functions */ purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15); @@ -1765,7 +1762,7 @@ if(nooffiles > 1) { gchar* message; - message = g_strdup_printf(_("%s is trying to send you a group of %d files.\n"), xfer->who, nooffiles); + message = g_strdup_printf(_("%s is trying to send you a group of %d files.\n"), purple_xfer_get_remote_user(xfer), nooffiles); purple_xfer_conversation_write(xfer, message, FALSE); g_free(message); } @@ -1790,7 +1787,7 @@ struct yahoo_packet *pkt_to_send; struct yahoo_p2p_data *p2p_data; - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; @@ -1837,7 +1834,7 @@ return; } - xfer_data = xfer->data; + xfer_data = purple_xfer_get_protocol_data(xfer); xfer_data->info_val_249 = val_249; xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay); @@ -1854,9 +1851,9 @@ YAHOO_STATUS_AVAILABLE, yd->session_id); yahoo_packet_hash(pkt_to_send, "ssssis", 1, purple_normalize(account, purple_account_get_username(account)), - 5, xfer->who, + 5, purple_xfer_get_remote_user(xfer), 265, xfer_data->xfer_peer_idstring, - 27, xfer->filename, + 27, purple_xfer_get_filename(xfer), 249, xfer_data->info_val_249, 251, xfer_data->xfer_idstring_for_relay); @@ -1870,12 +1867,12 @@ } } else if(val_249 == 2) { - p2p_data = g_hash_table_lookup(yd->peers, xfer->who); + p2p_data = g_hash_table_lookup(yd->peers, purple_xfer_get_remote_user(xfer)); if( !( p2p_data && (p2p_data->connection_type == YAHOO_P2P_WE_ARE_SERVER) ) ) { purple_xfer_cancel_remote(xfer); return; } - if(!purple_network_listen_range(0, 0, SOCK_STREAM, yahoo_p2p_ft_server_listen_cb, xfer)) { + if(!purple_network_listen_range(0, 0, AF_UNSPEC, SOCK_STREAM, TRUE, yahoo_p2p_ft_server_listen_cb, xfer)) { purple_xfer_cancel_remote(xfer); return; } @@ -1896,7 +1893,7 @@ gchar *url = NULL; int val_249 = 0; - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); for (l = pkt->hash; l; l = l->next) { struct yahoo_pair *pair = l->data; @@ -1934,7 +1931,7 @@ return; } - xfer_data = xfer->data; + xfer_data = purple_xfer_get_protocol_data(xfer); if(url) purple_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/yahoo/yahoo_friend.c --- a/libpurple/protocols/yahoo/yahoo_friend.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/yahoo/yahoo_friend.c Fri Apr 06 04:30:00 2012 +0000 @@ -46,9 +46,10 @@ const char *norm; g_return_val_if_fail(gc != NULL, NULL); - g_return_val_if_fail(gc->proto_data != NULL, NULL); - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); + g_return_val_if_fail(yd != NULL, NULL); + norm = purple_normalize(purple_connection_get_account(gc), name); return g_hash_table_lookup(yd->friends, norm); @@ -61,9 +62,10 @@ const char *norm; g_return_val_if_fail(gc != NULL, NULL); - g_return_val_if_fail(gc->proto_data != NULL, NULL); - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); + g_return_val_if_fail(yd != NULL, NULL); + norm = purple_normalize(purple_connection_get_account(gc), name); f = g_hash_table_lookup(yd->friends, norm); @@ -225,7 +227,7 @@ void yahoo_friend_update_presence(PurpleConnection *gc, const char *name, YahooPresenceVisibility presence) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt = NULL; YahooFriend *f; const char *thirtyone, *thirteen; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/yahoo/yahoo_packet.c --- a/libpurple/protocols/yahoo/yahoo_packet.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/yahoo/yahoo_packet.c Fri Apr 06 04:30:00 2012 +0000 @@ -302,7 +302,7 @@ return; else if (ret < 0) { /* TODO: what to do here - do we really have to disconnect? */ - purple_connection_error_reason(yd->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error(yd->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Write Error")); return; } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/yahoo/yahoo_picture.c --- a/libpurple/protocols/yahoo/yahoo_picture.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/yahoo/yahoo_picture.c Fri Apr 06 04:30:00 2012 +0000 @@ -52,7 +52,7 @@ YahooData *yd; d = user_data; - yd = d->gc->proto_data; + yd = purple_connection_get_protocol_data(d->gc); yd->url_datas = g_slist_remove(yd->url_datas, url_data); if (error_message != NULL) { @@ -132,10 +132,10 @@ data->checksum = checksum; /* TODO: Does this need to be MSIE 5.0? */ url_data = purple_util_fetch_url(url, use_whole_url, - "Mozilla/4.0 (compatible; MSIE 5.5)", FALSE, + "Mozilla/4.0 (compatible; MSIE 5.5)", FALSE, -1, yahoo_fetch_picture_cb, data); if (url_data != NULL) { - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); yd->url_datas = g_slist_prepend(yd->url_datas, url_data); } else { g_free(data->who); @@ -170,7 +170,7 @@ } if (who) { - PurpleBuddy *b = purple_find_buddy(gc->account, who); + PurpleBuddy *b = purple_find_buddy(purple_connection_get_account(gc), who); const char *locksum = NULL; /* FIXME: Cleanup this strtol() stuff if possible. */ @@ -185,7 +185,7 @@ void yahoo_process_picture_upload(PurpleConnection *gc, struct yahoo_packet *pkt) { PurpleAccount *account = purple_connection_get_account(gc); - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); GSList *l = pkt->hash; char *url = NULL; @@ -251,7 +251,7 @@ yahoo_send_picture_request(gc, who); else if ((avatar == 0) || (avatar == 1)) { YahooFriend *f; - purple_buddy_icons_set_for_user(gc->account, who, NULL, 0, NULL); + purple_buddy_icons_set_for_user(purple_connection_get_account(gc), 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); @@ -261,7 +261,7 @@ void yahoo_send_picture_info(PurpleConnection *gc, const char *who) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt; if (!yd->picture_url) { @@ -278,7 +278,7 @@ void yahoo_send_picture_request(PurpleConnection *gc, const char *who) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt; pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, yd->session_id); @@ -290,7 +290,7 @@ void yahoo_send_picture_checksum(PurpleConnection *gc) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt; pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM, YAHOO_STATUS_AVAILABLE, yd->session_id); @@ -301,7 +301,7 @@ void yahoo_send_picture_update_to_user(PurpleConnection *gc, const char *who, int type) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt; pkt = yahoo_packet_new(YAHOO_SERVICE_AVATAR_UPDATE, YAHOO_STATUS_AVAILABLE, yd->session_id); @@ -326,7 +326,7 @@ void yahoo_send_picture_update(PurpleConnection *gc, int type) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yspufe data; data.gc = gc; @@ -425,7 +425,7 @@ gboolean use_whole_url = yahoo_account_use_http_proxy(gc); account = purple_connection_get_account(gc); - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); /* Buddy icon connect is now complete; clear the PurpleProxyConnectData */ yd->buddy_icon_connect_data = NULL; @@ -490,7 +490,7 @@ void yahoo_buddy_icon_upload(PurpleConnection *gc, struct yahoo_buddy_icon_upload_data *d) { PurpleAccount *account = purple_connection_get_account(gc); - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); if (yd->buddy_icon_connect_data != NULL) { /* Cancel any in-progress buddy icon upload */ @@ -535,8 +535,8 @@ void yahoo_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img) { - YahooData *yd = gc->proto_data; - PurpleAccount *account = gc->account; + YahooData *yd = purple_connection_get_protocol_data(gc); + PurpleAccount *account = purple_connection_get_account(gc); if (img == NULL) { g_free(yd->picture_url); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/yahoo/yahoo_profile.c --- a/libpurple/protocols/yahoo/yahoo_profile.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/yahoo/yahoo_profile.c Fri Apr 06 04:30:00 2012 +0000 @@ -789,7 +789,7 @@ purple_debug_info("yahoo", "In yahoo_got_info\n"); - yd = info_data->gc->proto_data; + yd = purple_connection_get_protocol_data(info_data->gc); yd->url_datas = g_slist_remove(yd->url_datas, url_data); user_info = purple_notify_user_info_new(); @@ -805,7 +805,7 @@ * to send back HTML, with a 200 status code. */ if (error_message != NULL || url_text == NULL || strcmp(url_text, "") == 0) { - purple_notify_user_info_add_pair(user_info, _("Error retrieving profile"), NULL); + purple_notify_user_info_add_pair_html(user_info, _("Error retrieving profile"), NULL); purple_notify_userinfo(info_data->gc, info_data->name, user_info, NULL, NULL); purple_notify_user_info_destroy(user_info); @@ -840,7 +840,7 @@ _("If you wish to view this profile, " "you will need to visit this link in your web browser:"), profile_url_text, profile_url_text); - purple_notify_user_info_add_pair(user_info, NULL, tmp); + purple_notify_user_info_add_pair_html(user_info, NULL, tmp); g_free(tmp); purple_notify_userinfo(info_data->gc, info_data->name, @@ -940,7 +940,7 @@ * we specify HTTP 1.1. So we have to specify 1.0 & fix purple_util_fetch_url */ url_data = purple_util_fetch_url(photo_url_text, use_whole_url, NULL, - FALSE, yahoo_got_photo, info2_data); + FALSE, -1, yahoo_got_photo, info2_data); if (url_data != NULL) yd->url_datas = g_slist_prepend(yd->url_datas, url_data); } else { @@ -983,7 +983,7 @@ /* in to purple_markup_strip_html*/ char *fudged_buffer; - yd = info_data->gc->proto_data; + yd = purple_connection_get_protocol_data(info_data->gc); yd->url_datas = g_slist_remove(yd->url_datas, url_data); fudged_buffer = purple_strcasereplace(url_buffer, "", "
"); @@ -1048,7 +1048,7 @@ id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL); tmp = g_strdup_printf("
", id); - purple_notify_user_info_add_pair(user_info, NULL, tmp); + purple_notify_user_info_add_pair_html(user_info, NULL, tmp); g_free(tmp); } } @@ -1195,7 +1195,7 @@ const gchar *str; purple_notify_user_info_add_section_break(user_info); - purple_notify_user_info_add_pair(user_info, + purple_notify_user_info_add_pair_html(user_info, _("Error retrieving profile"), NULL); if (profile_state == PROFILE_STATE_UNKNOWN_LANGUAGE) { @@ -1228,14 +1228,14 @@ str = _("The user's profile is empty."); } - purple_notify_user_info_add_pair(user_info, NULL, str); + purple_notify_user_info_add_pair_plaintext(user_info, NULL, str); } /* put a link to the actual profile URL */ purple_notify_user_info_add_section_break(user_info); tmp = g_strdup_printf("%s", profile_url_text, _("View web profile")); - purple_notify_user_info_add_pair(user_info, NULL, tmp); + purple_notify_user_info_add_pair_html(user_info, NULL, tmp); g_free(tmp); g_free(stripped); @@ -1262,7 +1262,7 @@ void yahoo_get_info(PurpleConnection *gc, const char *name) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); YahooGetInfoData *data; char *url; PurpleUtilFetchUrlData *url_data; @@ -1274,7 +1274,7 @@ url = g_strdup_printf("%s%s", (yd->jp ? YAHOOJP_PROFILE_URL : YAHOO_PROFILE_URL), name); - url_data = purple_util_fetch_url(url, TRUE, NULL, FALSE, yahoo_got_info, data); + url_data = purple_util_fetch_url(url, TRUE, NULL, FALSE, -1, yahoo_got_info, data); if (url_data != NULL) yd->url_datas = g_slist_prepend(yd->url_datas, url_data); else { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/yahoo/yahoochat.c --- a/libpurple/protocols/yahoo/yahoochat.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/yahoo/yahoochat.c Fri Apr 06 04:30:00 2012 +0000 @@ -53,7 +53,7 @@ /* special function to log us on to the yahoo chat service */ static void yahoo_chat_online(PurpleConnection *gc) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt; const char *rll; @@ -101,7 +101,7 @@ YahooData *yd; GSList *l; - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); for (l = yd->confs; l; l = l->next) { PurpleConversation *c = l->data; @@ -372,7 +372,7 @@ static void yahoo_chat_join(PurpleConnection *gc, const char *dn, const char *room, const char *topic, const char *id) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt; char *room2; gboolean utf8 = TRUE; @@ -400,7 +400,7 @@ /* this is a confirmation of yahoo_chat_online(); */ void yahoo_process_chat_online(PurpleConnection *gc, struct yahoo_packet *pkt) { - YahooData *yd = (YahooData *) gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); if (pkt->status == 1) { yd->chat_online = TRUE; @@ -432,7 +432,7 @@ /* this is basicly the opposite of chat_online */ void yahoo_process_chat_logout(PurpleConnection *gc, struct yahoo_packet *pkt) { - YahooData *yd = (YahooData *) gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); GSList *l; for (l = pkt->hash; l; l = l->next) { @@ -462,7 +462,7 @@ void yahoo_process_chat_join(PurpleConnection *gc, struct yahoo_packet *pkt) { PurpleAccount *account = purple_connection_get_account(gc); - YahooData *yd = (YahooData *) gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); PurpleConversation *c = NULL; GSList *l; GList *members = NULL; @@ -786,7 +786,7 @@ static int yahoo_conf_send(PurpleConnection *gc, const char *dn, const char *room, GList *members, const char *what) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt; GList *who; char *msg, *msg2; @@ -843,7 +843,7 @@ static void yahoo_conf_invite(PurpleConnection *gc, PurpleConversation *c, const char *dn, const char *buddy, const char *room, const char *msg) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt; GList *members; char *msg2 = NULL; @@ -873,7 +873,7 @@ static void yahoo_chat_leave(PurpleConnection *gc, const char *room, const char *dn, gboolean logout) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt; char *eroom; @@ -924,7 +924,7 @@ static int yahoo_chat_send(PurpleConnection *gc, const char *dn, const char *room, const char *what, PurpleMessageFlags flags) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt; int me = 0; char *msg1, *msg2, *room2; @@ -969,7 +969,7 @@ static void yahoo_chat_invite(PurpleConnection *gc, const char *dn, const char *buddy, const char *room, const char *msg) { - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); struct yahoo_packet *pkt; char *room2, *msg2 = NULL; gboolean utf8 = TRUE; @@ -997,7 +997,7 @@ YahooData *yd; struct yahoo_packet *pkt; - yd = gc->proto_data; + yd = purple_connection_get_protocol_data(gc); if (yd->wm) { g_return_if_fail(yd->ycht != NULL); @@ -1029,7 +1029,7 @@ void yahoo_c_leave(PurpleConnection *gc, int id) { - YahooData *yd = (YahooData *) gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); PurpleConversation *c; if (!yd) @@ -1056,7 +1056,7 @@ int ret; YahooData *yd; - yd = (YahooData *) gc->proto_data; + yd = purple_connection_get_protocol_data(gc); if (!yd) return -1; @@ -1114,7 +1114,7 @@ char *room, *topic, *type; PurpleConversation *c; - yd = (YahooData *) gc->proto_data; + yd = purple_connection_get_protocol_data(gc); if (!yd) return; @@ -1166,7 +1166,7 @@ PurpleConversation *c; c = purple_find_chat(gc, id); - if (!c || !c->name) + if (!c || !purple_conversation_get_name(c)) return; if (id != YAHOO_CHAT_ID) { @@ -1375,7 +1375,9 @@ purple_roomlist_set_in_progress(list, FALSE); if (yrl) { - list->proto_data = g_list_remove(list->proto_data, yrl); + GList *proto_data = purple_roomlist_get_proto_data(list); + proto_data = g_list_remove(proto_data, yrl); + purple_roomlist_set_proto_data(list, proto_data); yahoo_roomlist_destroy(yrl); } @@ -1451,7 +1453,7 @@ yrl->inpa = 0; g_free(yrl->txbuf); yrl->txbuf = NULL; - purple_notify_error(purple_account_get_connection(list->account), NULL, _("Unable to connect"), _("Fetching the room list failed.")); + purple_notify_error(purple_account_get_connection(purple_roomlist_get_account(list)), NULL, _("Unable to connect"), _("Fetching the room list failed.")); yahoo_roomlist_cleanup(list, yrl); return; } @@ -1474,10 +1476,12 @@ { struct yahoo_roomlist *yrl = data; PurpleRoomlist *list = yrl->list; - YahooData *yd = purple_account_get_connection(list->account)->proto_data; + PurpleAccount *account = purple_roomlist_get_account(list); + PurpleConnection *pc = purple_account_get_connection(account); + YahooData *yd = purple_connection_get_protocol_data(pc); if (source < 0) { - purple_notify_error(purple_account_get_connection(list->account), NULL, _("Unable to connect"), _("Fetching the room list failed.")); + purple_notify_error(pc, NULL, _("Unable to connect"), _("Fetching the room list failed.")); yahoo_roomlist_cleanup(list, yrl); return; } @@ -1506,6 +1510,7 @@ struct yahoo_roomlist *yrl; const char *rll, *rlurl; char *url; + GList *proto_data; account = purple_connection_get_account(gc); @@ -1556,7 +1561,9 @@ return NULL; } - rl->proto_data = g_list_append(rl->proto_data, yrl); + proto_data = purple_roomlist_get_proto_data(rl); + proto_data = g_list_append(proto_data, yrl); + purple_roomlist_set_proto_data(rl, proto_data); purple_roomlist_set_in_progress(rl, TRUE); return rl; @@ -1566,8 +1573,8 @@ { GList *l, *k; - k = l = list->proto_data; - list->proto_data = NULL; + k = l = purple_roomlist_get_proto_data(list); + purple_roomlist_set_proto_data(list, NULL); purple_roomlist_set_in_progress(list, FALSE); @@ -1580,36 +1587,42 @@ void yahoo_roomlist_expand_category(PurpleRoomlist *list, PurpleRoomlistRoom *category) { + PurpleAccount *account; struct yahoo_roomlist *yrl; char *url; char *id; const char *rll; + GList *proto_data; - if (category->type != PURPLE_ROOMLIST_ROOMTYPE_CATEGORY) + if (purple_roomlist_room_get_type(category) != PURPLE_ROOMLIST_ROOMTYPE_CATEGORY) return; - if (!(id = g_list_nth_data(category->fields, 1))) { + if (!(id = g_list_nth_data(purple_roomlist_room_get_fields(category), 1))) { purple_roomlist_set_in_progress(list, FALSE); return; } - rll = purple_account_get_string(list->account, "room_list_locale", + account = purple_roomlist_get_account(list); + rll = purple_account_get_string(account, "room_list_locale", YAHOO_ROOMLIST_LOCALE); if (rll != NULL && *rll != '\0') { url = g_strdup_printf("%s?chatroom_%s=0&intl=%s", - purple_account_get_string(list->account,"room_list", + purple_account_get_string(account,"room_list", YAHOO_ROOMLIST_URL), id, rll); } else { url = g_strdup_printf("%s?chatroom_%s=0", - purple_account_get_string(list->account,"room_list", + purple_account_get_string(account,"room_list", YAHOO_ROOMLIST_URL), id); } yrl = g_new0(struct yahoo_roomlist, 1); yrl->list = list; yrl->cat = category; - list->proto_data = g_list_append(list->proto_data, yrl); + + proto_data = purple_roomlist_get_proto_data(list); + proto_data = g_list_append(proto_data, yrl); + purple_roomlist_set_proto_data(list, proto_data); purple_url_parse(url, &(yrl->host), NULL, &(yrl->path), NULL, NULL); g_free(url); @@ -1617,11 +1630,11 @@ yrl->ucat = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY, _("User Rooms"), yrl->cat); purple_roomlist_room_add(list, yrl->ucat); - if (purple_proxy_connect(purple_account_get_connection(list->account), - list->account, yrl->host, 80, + if (purple_proxy_connect(purple_account_get_connection(account), + account, yrl->host, 80, yahoo_roomlist_got_connected, yrl) == NULL) { - purple_notify_error(purple_account_get_connection(list->account), + purple_notify_error(purple_account_get_connection(account), NULL, _("Connection problem"), _("Unable to fetch room list.")); purple_roomlist_ref(list); yahoo_roomlist_cleanup(list, yrl); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/yahoo/ycht.c --- a/libpurple/protocols/yahoo/ycht.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/yahoo/ycht.c Fri Apr 06 04:30:00 2012 +0000 @@ -53,7 +53,7 @@ static void ycht_process_login(YchtConn *ycht, YchtPkt *pkt) { PurpleConnection *gc = ycht->gc; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); if (ycht->logged_in) return; @@ -68,7 +68,7 @@ static void ycht_process_logout(YchtConn *ycht, YchtPkt *pkt) { PurpleConnection *gc = ycht->gc; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); yd->chat_online = FALSE; ycht->logged_in = FALSE; @@ -173,7 +173,7 @@ { #if 0 PurpleConnection *gc = ycht->gc; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); if (ycht->logged_in) return; @@ -285,7 +285,7 @@ /* gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); - purple_connection_error_reason(purple_account_get_connection(irc->account), + purple_connection_error(purple_account_get_connection(irc->account), PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); */ @@ -429,7 +429,7 @@ void ycht_connection_close(YchtConn *ycht) { - YahooData *yd = ycht->gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(ycht->gc); if (yd) { yd->ycht = NULL; @@ -541,7 +541,7 @@ { YchtConn *ycht = data; PurpleConnection *gc = ycht->gc; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); YchtPkt *pkt; char *buf; @@ -568,7 +568,7 @@ void ycht_connection_open(PurpleConnection *gc) { YchtConn *ycht; - YahooData *yd = gc->proto_data; + YahooData *yd = purple_connection_get_protocol_data(gc); PurpleAccount *account = purple_connection_get_account(gc); ycht = g_new0(YchtConn, 1); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/zephyr/ZRetSubs.c --- a/libpurple/protocols/zephyr/ZRetSubs.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/zephyr/ZRetSubs.c Fri Apr 06 04:30:00 2012 +0000 @@ -132,6 +132,11 @@ __subscriptions_num = __subscriptions_num / 3; + if (!__subscriptions_num) { + ZFreeNotice(&retnotice); + continue; + } + __subscriptions_list = (ZSubscription_t *) malloc((unsigned)(__subscriptions_num* sizeof(ZSubscription_t))); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/protocols/zephyr/zephyr.c --- a/libpurple/protocols/zephyr/zephyr.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/protocols/zephyr/zephyr.c Fri Apr 06 04:30:00 2012 +0000 @@ -146,7 +146,7 @@ return TRUE; #define z_call_s(func, err) if (func != ZERR_NONE) {\ - purple_connection_error(gc, err);\ + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, err);\ return;\ } @@ -347,7 +347,7 @@ { gchar *utf8; GError *err = NULL; - zephyr_account *zephyr = gc->proto_data; + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); if (g_utf8_validate(string, -1, NULL)) { return g_strdup(string); } else { @@ -762,7 +762,7 @@ static void handle_message(PurpleConnection *gc,ZNotice_t notice) { - zephyr_account* zephyr = gc->proto_data; + zephyr_account* zephyr = purple_connection_get_protocol_data(gc); if (!g_ascii_strcasecmp(notice.z_class, LOGIN_CLASS)) { /* well, we'll be updating in 20 seconds anyway, might as well ignore this. */ @@ -777,9 +777,9 @@ if (ZParseLocations(¬ice, NULL, &nlocs, &user) != ZERR_NONE) return; - if ((b = purple_find_buddy(gc->account, user)) == NULL) { + if ((b = purple_find_buddy(purple_connection_get_account(gc), user)) == NULL) { char* stripped_user = zephyr_strip_local_realm(zephyr,user); - b = purple_find_buddy(gc->account,stripped_user); + b = purple_find_buddy(purple_connection_get_account(gc),stripped_user); g_free(stripped_user); } @@ -791,20 +791,23 @@ char *tmp; const char *balias; - purple_notify_user_info_add_pair(user_info, _("User"), (b ? bname : user)); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("User"), (b ? bname : user)); balias = purple_buddy_get_local_buddy_alias(b); if (b && balias) - purple_notify_user_info_add_pair(user_info, _("Alias"), balias); + purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), balias); if (!nlocs) { - purple_notify_user_info_add_pair(user_info, NULL, _("Hidden or not logged-in")); + purple_notify_user_info_add_pair_plaintext(user_info, NULL, _("Hidden or not logged-in")); } for (; nlocs > 0; nlocs--) { /* XXX add real error reporting */ ZGetLocations(&locs, &one); + /* TODO: Need to escape locs.host and locs.time? */ tmp = g_strdup_printf(_("
At %s since %s"), locs.host, locs.time); - purple_notify_user_info_add_pair(user_info, _("Location"), tmp); + purple_notify_user_info_add_pair_html(user_info, _("Location"), tmp); g_free(tmp); } purple_notify_userinfo(gc, (b ? bname : user), @@ -812,9 +815,9 @@ purple_notify_user_info_destroy(user_info); } else { if (nlocs>0) - purple_prpl_got_user_status(gc->account, b ? bname : user, "available", NULL); + purple_prpl_got_user_status(purple_connection_get_account(gc), b ? bname : user, "available", NULL); else - purple_prpl_got_user_status(gc->account, b ? bname : user, "offline", NULL); + purple_prpl_got_user_status(purple_connection_get_account(gc), b ? bname : user, "offline", NULL); } g_free(user); @@ -869,7 +872,7 @@ } else { zephyr_triple *zt1, *zt2; gchar *send_inst_utf8; - zephyr_account *zephyr = gc->proto_data; + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); zt1 = new_triple(zephyr,notice.z_class, notice.z_class_inst, notice.z_recipient); zt2 = find_sub_by_triple(zephyr,zt1); if (!zt2) { @@ -897,7 +900,7 @@ } gconv1 = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - zt2->name, gc->account); + zt2->name, purple_connection_get_account(gc)); gcc = purple_conversation_get_chat_data(gconv1); #ifndef INET_ADDRSTRLEN #define INET_ADDRSTRLEN 16 @@ -1106,7 +1109,7 @@ static gint check_notify_tzc(gpointer data) { PurpleConnection *gc = (PurpleConnection *)data; - zephyr_account* zephyr = gc->proto_data; + zephyr_account* zephyr = purple_connection_get_protocol_data(gc); parse_tree *newparsetree = read_from_tzc(zephyr); if (newparsetree != NULL) { gchar *spewtype; @@ -1153,15 +1156,15 @@ gchar *locval; user = tree_child(find_node(newparsetree,"user"),2)->contents; - if ((b = purple_find_buddy(gc->account, user)) == NULL) { + if ((b = purple_find_buddy(purple_connection_get_account(gc), user)) == NULL) { gchar *stripped_user = zephyr_strip_local_realm(zephyr,user); - b = purple_find_buddy(gc->account, stripped_user); + b = purple_find_buddy(purple_connection_get_account(gc), stripped_user); g_free(stripped_user); } locations = find_node(newparsetree,"locations"); locval = tree_child(tree_child(tree_child(tree_child(locations,2),0),0),2)->contents; - if (!locval || !g_ascii_strcasecmp(locval," ") || (strlen(locval) == 0)) { + if (!locval || !g_ascii_strcasecmp(locval," ") || !*locval) { nlocs = 0; } else { nlocs = 1; @@ -1173,19 +1176,22 @@ char *tmp; const char *balias; - purple_notify_user_info_add_pair(user_info, _("User"), (b ? bname : user)); + /* TODO: Check whether it's correct to call add_pair_html, + or if we should be using add_pair_plaintext */ + purple_notify_user_info_add_pair_html(user_info, _("User"), (b ? bname : user)); balias = b ? purple_buddy_get_local_buddy_alias(b) : NULL; if (balias) - purple_notify_user_info_add_pair(user_info, _("Alias"), balias); + purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), balias); if (!nlocs) { - purple_notify_user_info_add_pair(user_info, NULL, _("Hidden or not logged-in")); + purple_notify_user_info_add_pair_plaintext(user_info, NULL, _("Hidden or not logged-in")); } else { + /* TODO: Need to escape the two strings that make up tmp? */ tmp = g_strdup_printf(_("
At %s since %s"), tree_child(tree_child(tree_child(tree_child(locations,2),0),0),2)->contents, tree_child(tree_child(tree_child(tree_child(locations,2),0),2),2)->contents); - purple_notify_user_info_add_pair(user_info, _("Location"), tmp); + purple_notify_user_info_add_pair_html(user_info, _("Location"), tmp); g_free(tmp); } @@ -1194,9 +1200,9 @@ purple_notify_user_info_destroy(user_info); } else { if (nlocs>0) - purple_prpl_got_user_status(gc->account, b ? bname : user, "available", NULL); + purple_prpl_got_user_status(purple_connection_get_account(gc), b ? bname : user, "available", NULL); else - purple_prpl_got_user_status(gc->account, b ? bname : user, "offline", NULL); + purple_prpl_got_user_status(purple_connection_get_account(gc), b ? bname : user, "offline", NULL); } } else if (!g_ascii_strncasecmp(spewtype,"subscribed",10)) { @@ -1259,7 +1265,7 @@ GSList *buddies; ZLocations_t locations; PurpleConnection *gc = data; - zephyr_account *zephyr = gc->proto_data; + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); PurpleAccount *account = purple_connection_get_account(gc); int numlocs; int one = 1; @@ -1290,7 +1296,7 @@ GSList *buddies; ZAsyncLocateData_t ald; PurpleConnection *gc = (PurpleConnection *)data; - zephyr_account *zephyr = gc->proto_data; + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); PurpleAccount *account = purple_connection_get_account(gc); if (use_zeph02(zephyr)) { @@ -1515,11 +1521,11 @@ while (fgets(buff, BUFSIZ, fd)) { strip_comments(buff); if (buff[0]) { - if (!(b = purple_find_buddy(gc->account, buff))) { + if (!(b = purple_find_buddy(purple_connection_get_account(gc), buff))) { char *stripped_user = zephyr_strip_local_realm(zephyr,buff); purple_debug_info("zephyr","stripped_user %s\n",stripped_user); - if (!(b = purple_find_buddy(gc->account,stripped_user))){ - b = purple_buddy_new(gc->account, stripped_user, NULL); + if (!(b = purple_find_buddy(purple_connection_get_account(gc),stripped_user))){ + b = purple_buddy_new(purple_connection_get_account(gc), stripped_user, NULL); purple_blist_add_buddy(b, NULL, g, NULL); } g_free(stripped_user); @@ -1558,34 +1564,35 @@ gchar *exposure; gc = purple_account_get_connection(account); - read_anyone = purple_account_get_bool(gc->account,"read_anyone",TRUE); - read_zsubs = purple_account_get_bool(gc->account,"read_zsubs",TRUE); - exposure = (gchar *)purple_account_get_string(gc->account, "exposure_level", EXPOSE_REALMVIS); + read_anyone = purple_account_get_bool(purple_connection_get_account(gc),"read_anyone",TRUE); + read_zsubs = purple_account_get_bool(purple_connection_get_account(gc),"read_zsubs",TRUE); + exposure = (gchar *)purple_account_get_string(purple_connection_get_account(gc), "exposure_level", EXPOSE_REALMVIS); #ifdef WIN32 username = purple_account_get_username(account); #endif - gc->flags |= PURPLE_CONNECTION_AUTO_RESP | PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC; - gc->proto_data = zephyr=g_new0(zephyr_account,1); + purple_connection_set_flags(gc, PURPLE_CONNECTION_AUTO_RESP | PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC); + zephyr = g_new0(zephyr_account, 1); + purple_connection_set_protocol_data(gc, zephyr); zephyr->account = account; /* Make sure that the exposure (visibility) is set to a sane value */ zephyr->exposure=g_strdup(normalize_zephyr_exposure(exposure)); - if (purple_account_get_bool(gc->account,"use_tzc",0)) { + if (purple_account_get_bool(purple_connection_get_account(gc),"use_tzc",0)) { zephyr->connection_type = PURPLE_ZEPHYR_TZC; } else { zephyr->connection_type = PURPLE_ZEPHYR_KRB4; } - zephyr->encoding = (char *)purple_account_get_string(gc->account, "encoding", ZEPHYR_FALLBACK_CHARSET); + zephyr->encoding = (char *)purple_account_get_string(purple_connection_get_account(gc), "encoding", ZEPHYR_FALLBACK_CHARSET); purple_connection_update_progress(gc, _("Connecting"), 0, 8); /* XXX z_call_s should actually try to report the com_err determined error */ if (use_tzc(zephyr)) { pid_t pid; - /* purple_connection_error(gc,"tzc not supported yet"); */ + /* purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, "tzc not supported yet"); */ if ((pipe(zephyr->totzc) != 0) || (pipe(zephyr->fromtzc) != 0)) { purple_debug_error("zephyr", "pipe creation failed. killing\n"); exit(-1); @@ -1600,7 +1607,7 @@ if (pid == 0) { unsigned int i=0; gboolean found_ps = FALSE; - gchar ** tzc_cmd_array = g_strsplit(purple_account_get_string(gc->account,"tzc_command","/usr/bin/tzc -e %s")," ",0); + gchar ** tzc_cmd_array = g_strsplit(purple_account_get_string(purple_connection_get_account(gc),"tzc_command","/usr/bin/tzc -e %s")," ",0); if (close(1) == -1) { exit(-1); } @@ -1706,7 +1713,7 @@ ptr++; } if (ptr >=bufcur) { - purple_connection_error(gc,"invalid output by tzc (or bad parsing code)"); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, "invalid output by tzc (or bad parsing code)"); free(buf); return; } @@ -1772,7 +1779,7 @@ if ((realm = strchr(username,'@'))) zephyr->realm = g_strdup_printf("%s",realm+1); else { - realm = (gchar *)purple_account_get_string(gc->account,"realm",""); + realm = (gchar *)purple_account_get_string(purple_connection_get_account(gc),"realm",""); if (!*realm) { realm = "local-realm"; } @@ -1809,7 +1816,7 @@ z_call_s(ZOpenPort(&(zephyr->port)), "Couldn't open port"); z_call_s(ZSetLocation((char *)zephyr->exposure), "Couldn't set location"); - realm = (gchar *)purple_account_get_string(gc->account,"realm",""); + realm = (gchar *)purple_account_get_string(purple_connection_get_account(gc),"realm",""); if (!*realm) { realm = ZGetRealm(); } @@ -1821,7 +1828,7 @@ purple_debug_info("zephyr","realm: %s\n",zephyr->realm); } else { - purple_connection_error(gc,"Only ZEPH0.2 supported currently"); + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, "Only ZEPH0.2 supported currently"); return; } purple_debug_info("zephyr","does it get here\n"); @@ -1835,7 +1842,7 @@ if (zephyr_subscribe_to(zephyr,"MESSAGE","PERSONAL",zephyr->username,NULL) != ZERR_NONE) { /* XXX don't translate this yet. It could be written better */ /* XXX error messages could be handled with more detail */ - purple_notify_error(account->gc, NULL, + purple_notify_error(purple_account_get_connection(account), NULL, "Unable to subscribe to messages", "Unable to subscribe to initial messages"); return; } @@ -1955,7 +1962,7 @@ { GList *l; GSList *s; - zephyr_account *zephyr = gc->proto_data; + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); pid_t tzc_pid = zephyr->tzc_pid; l = zephyr->pending_zloc_names; @@ -1965,10 +1972,10 @@ } g_list_free(zephyr->pending_zloc_names); - if (purple_account_get_bool(gc->account, "write_anyone", FALSE)) + if (purple_account_get_bool(purple_connection_get_account(gc), "write_anyone", FALSE)) write_anyone(zephyr); - if (purple_account_get_bool(gc->account, "write_zsubs", FALSE)) + if (purple_account_get_bool(purple_connection_get_account(gc), "write_zsubs", FALSE)) write_zsubs(zephyr); s = zephyr->subscrips; @@ -2030,7 +2037,7 @@ PurpleConvChat *gcc; char *inst; char *recipient; - zephyr_account *zephyr = gc->proto_data; + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); zt = find_sub_by_id(zephyr,id); if (!zt) @@ -2040,7 +2047,7 @@ sig = zephyr_get_signature(); gconv1 = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, zt->name, - gc->account); + purple_connection_get_account(gc)); gcc = purple_conversation_get_chat_data(gconv1); if (!(inst = (char *)purple_conv_chat_get_topic(gcc))) @@ -2059,7 +2066,7 @@ static int zephyr_send_im(PurpleConnection * gc, const char *who, const char *im, PurpleMessageFlags flags) { const char *sig; - zephyr_account *zephyr = gc->proto_data; + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); if (flags & PURPLE_MESSAGE_AUTO_RESP) sig = "Automated reply:"; else { @@ -2079,7 +2086,7 @@ int pos2 = 0; char *newmsg; - if (message && (strlen(message) > 0)) { + if (message && *message) { newmsg = g_new0(char,1+strlen(message)*2); while(pos < strlen(message)) { if (message[pos]=='\\') { @@ -2111,7 +2118,7 @@ int pos2 = 0; char *newmsg; - if (message && (strlen(message) > 0)) { + if (message && *message) { newmsg = g_new0(char,strlen(message)+1); while(pos < strlen(message)) { if (message[pos]=='\\') { @@ -2228,7 +2235,7 @@ if (gc == NULL) return NULL; - tmp = local_zephyr_normalize(gc->proto_data, who); + tmp = local_zephyr_normalize(purple_connection_get_protocol_data(gc), who); if (strlen(tmp) >= sizeof(buf)) { g_free(tmp); @@ -2244,7 +2251,7 @@ static void zephyr_zloc(PurpleConnection *gc, const char *who) { ZAsyncLocateData_t ald; - zephyr_account *zephyr = gc->proto_data; + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); gchar* normalized_who = local_zephyr_normalize(zephyr,who); if (use_zeph02(zephyr)) { @@ -2271,7 +2278,8 @@ static void zephyr_set_status(PurpleAccount *account, PurpleStatus *status) { size_t len; size_t result; - zephyr_account *zephyr = purple_account_get_connection(account)->proto_data; + PurpleConnection *gc = purple_account_get_connection(account); + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); PurpleStatusPrimitive primitive = purple_status_type_get_primitive(purple_status_get_type(status)); if (zephyr->away) { @@ -2405,7 +2413,7 @@ const char *classname; const char *instname; const char *recip; - zephyr_account *zephyr=gc->proto_data; + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); classname = g_hash_table_lookup(data, "class"); instname = g_hash_table_lookup(data, "instance"); recip = g_hash_table_lookup(data, "recipient"); @@ -2468,7 +2476,7 @@ static void zephyr_chat_leave(PurpleConnection * gc, int id) { zephyr_triple *zt; - zephyr_account *zephyr = gc->proto_data; + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); zt = find_sub_by_id(zephyr,id); if (zt) { @@ -2518,7 +2526,7 @@ static unsigned int zephyr_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state) { gchar *recipient; - zephyr_account *zephyr = gc->proto_data; + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); if (use_tzc(zephyr)) return 0; @@ -2560,7 +2568,7 @@ PurpleConversation *gconv; PurpleConvChat *gcc; gchar *topic_utf8; - zephyr_account* zephyr = gc->proto_data; + zephyr_account* zephyr = purple_connection_get_protocol_data(gc); char *sender = (char *)zephyr->username; zt = find_sub_by_id(zephyr,id); @@ -2568,7 +2576,7 @@ if (!zt) return; gconv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, zt->name, - gc->account); + purple_connection_get_account(gc)); gcc = purple_conversation_get_chat_data(gconv); topic_utf8 = zephyr_recv_convert(gc,(gchar *)topic); @@ -2583,7 +2591,8 @@ const char *cmd, char **args, char **error, void *data) { char *recipient; - zephyr_account *zephyr = purple_conversation_get_gc(conv)->proto_data; + PurpleConnection *gc = purple_conversation_get_connection(conv); + zephyr_account *zephyr = purple_connection_get_protocol_data(gc);; if (!g_ascii_strcasecmp(args[0],"*")) return PURPLE_CMD_RET_FAILED; /* "*" is not a valid argument */ else @@ -2601,7 +2610,7 @@ static PurpleCmdRet zephyr_purple_cmd_zlocate(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data) { - zephyr_zloc(purple_conversation_get_gc(conv),args[0]); + zephyr_zloc(purple_conversation_get_connection(conv),args[0]); return PURPLE_CMD_RET_OK; } @@ -2613,9 +2622,8 @@ * one word isn't ideal either. */ PurpleConvChat *gcc = purple_conversation_get_chat_data(conv); - int id = gcc->id; const char* instance = args[0]; - zephyr_chat_set_topic(purple_conversation_get_gc(conv),id,instance); + zephyr_chat_set_topic(purple_conversation_get_connection(conv),purple_conv_chat_get_id(gcc),instance); return PURPLE_CMD_RET_OK; } @@ -2627,7 +2635,7 @@ g_hash_table_insert(triple,"class",args[0]); g_hash_table_insert(triple,"instance",args[1]); g_hash_table_insert(triple,"recipient",args[2]); - zephyr_join_chat(purple_conversation_get_gc(conv),triple); + zephyr_join_chat(purple_conversation_get_connection(conv),triple); return PURPLE_CMD_RET_OK; } @@ -2635,7 +2643,8 @@ const char *cmd, char **args, char **error, void *data) { /* args = instance, message */ - zephyr_account *zephyr = purple_conversation_get_gc(conv)->proto_data; + PurpleConnection *gc = purple_conversation_get_connection(conv); + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); if ( zephyr_send_message(zephyr,"message",args[0],"",args[1],zephyr_get_signature(),"")) return PURPLE_CMD_RET_OK; else @@ -2646,7 +2655,8 @@ const char *cmd, char **args, char **error, void *data) { /* args = class, instance, message */ - zephyr_account *zephyr = purple_conversation_get_gc(conv)->proto_data; + PurpleConnection *gc = purple_conversation_get_connection(conv); + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); if ( zephyr_send_message(zephyr,args[0],args[1],"",args[2],zephyr_get_signature(),"")) return PURPLE_CMD_RET_OK; else @@ -2657,7 +2667,8 @@ const char *cmd, char **args, char **error, void *data) { /* args = class, instance, recipient, message */ - zephyr_account *zephyr = purple_conversation_get_gc(conv)->proto_data; + PurpleConnection *gc = purple_conversation_get_connection(conv); + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); if ( zephyr_send_message(zephyr,args[0],args[1],args[2],args[3],zephyr_get_signature(),"")) return PURPLE_CMD_RET_OK; else @@ -2668,7 +2679,8 @@ const char *cmd, char **args, char **error, void *data) { /* args = instance, recipient, message */ - zephyr_account *zephyr = purple_conversation_get_gc(conv)->proto_data; + PurpleConnection *gc = purple_conversation_get_connection(conv); + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); if ( zephyr_send_message(zephyr,"message",args[0],args[1],args[2],zephyr_get_signature(),"")) return PURPLE_CMD_RET_OK; else @@ -2679,7 +2691,8 @@ const char *cmd, char **args, char **error, void *data) { /* args = class, message */ - zephyr_account *zephyr = purple_conversation_get_gc(conv)->proto_data; + PurpleConnection *gc = purple_conversation_get_connection(conv); + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); if ( zephyr_send_message(zephyr,args[0],"PERSONAL","",args[1],zephyr_get_signature(),"")) return PURPLE_CMD_RET_OK; else @@ -2760,7 +2773,7 @@ { /* Resubscribe to the in-memory list of subscriptions and also unsubscriptions*/ - zephyr_account *zephyr = gc->proto_data; + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); GSList *s = zephyr->subscrips; zephyr_triple *zt; while (s) { @@ -2785,7 +2798,7 @@ static void zephyr_action_get_subs_from_server(PurplePluginAction *action) { PurpleConnection *gc = (PurpleConnection *) action->context; - zephyr_account *zephyr = gc->proto_data; + zephyr_account *zephyr = purple_connection_get_protocol_data(gc); gchar *title; int retval, nsubs, one,i; ZSubscription_t subs; @@ -2839,6 +2852,7 @@ static PurplePlugin *my_protocol = NULL; static PurplePluginProtocolInfo prpl_info = { + sizeof(PurplePluginProtocolInfo), /* struct_size */ OPT_PROTO_CHAT_TOPIC | OPT_PROTO_NO_PASSWORD, NULL, /* ??? user_splits */ NULL, /* ??? protocol_options */ @@ -2879,7 +2893,6 @@ NULL, /* keepalive -- Not necessary*/ NULL, /* register_user -- Not supported*/ NULL, /* XXX get_cb_info */ - NULL, /* get_cb_away */ NULL, /* alias_buddy */ NULL, /* group_buddy */ NULL, /* rename_group */ @@ -2905,15 +2918,12 @@ NULL, NULL, NULL, - sizeof(PurplePluginProtocolInfo), /* struct_size */ NULL, /* get_account_text_table */ NULL, /* initate_media */ NULL, /* get_media_caps */ NULL, /* get_moods */ NULL, /* set_public_alias */ - NULL, /* get_public_alias */ - NULL, /* add_buddy_with_invite */ - NULL /* add_buddies_with_invite */ + NULL /* get_public_alias */ }; static PurplePluginInfo info = { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/proxy.c --- a/libpurple/proxy.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/proxy.c Fri Apr 06 04:30:00 2012 +0000 @@ -41,6 +41,16 @@ #include "proxy.h" #include "util.h" +struct _PurpleProxyInfo +{ + PurpleProxyType type; /**< The proxy type. */ + + char *host; /**< The host. */ + int port; /**< The port number. */ + char *username; /**< The username. */ + char *password; /**< The password. */ +}; + struct _PurpleProxyConnectData { void *handle; PurpleProxyConnectFunction connect_cb; @@ -1369,7 +1379,7 @@ proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); } else { - connect_data->query_data = purple_dnsquery_a_account( + connect_data->query_data = purple_dnsquery_a( connect_data->account, connect_data->host, connect_data->port, s4_host_resolved, connect_data); @@ -2014,7 +2024,6 @@ return; } - i = 0; buf[0] = 0x05; /* SOCKS version 5 */ if (purple_proxy_info_get_username(connect_data->gpi) != NULL) { @@ -2088,7 +2097,7 @@ /** * This function attempts to connect to the next IP address in the list - * of IP addresses returned to us by purple_dnsquery_a() and attemps + * of IP addresses returned to us by purple_dnsquery_a() and attempts * to connect to each one. This is called after the hostname is * resolved, and each time a connection attempt fails (assuming there * is another IP address to try). @@ -2317,7 +2326,7 @@ return NULL; } - connect_data->query_data = purple_dnsquery_a_account(account, connecthost, + connect_data->query_data = purple_dnsquery_a(account, connecthost, connectport, connection_host_resolved, connect_data); if (connect_data->query_data == NULL) { @@ -2385,7 +2394,7 @@ return NULL; } - connect_data->query_data = purple_dnsquery_a_account(account, connecthost, + connect_data->query_data = purple_dnsquery_a(account, connecthost, connectport, connection_host_resolved, connect_data); if (connect_data->query_data == NULL) { @@ -2398,17 +2407,6 @@ return connect_data; } -PurpleProxyConnectData * -purple_proxy_connect_socks5(void *handle, PurpleProxyInfo *gpi, - const char *host, int port, - PurpleProxyConnectFunction connect_cb, - gpointer data) -{ - return purple_proxy_connect_socks5_account(handle, NULL, gpi, - host, port, connect_cb, data); -} - - /* This is called when we connect to the SOCKS5 proxy server (through any * relevant account proxy) */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/proxy.h --- a/libpurple/proxy.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/proxy.h Fri Apr 06 04:30:00 2012 +0000 @@ -47,16 +47,7 @@ /** * Information on proxy settings. */ -typedef struct -{ - PurpleProxyType type; /**< The proxy type. */ - - char *host; /**< The host. */ - int port; /**< The port number. */ - char *username; /**< The username. */ - char *password; /**< The password. */ - -} PurpleProxyInfo; +typedef struct _PurpleProxyInfo PurpleProxyInfo; typedef struct _PurpleProxyConnectData PurpleProxyConnectData; @@ -65,9 +56,7 @@ #include "account.h" -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Proxy structure API */ @@ -191,7 +180,6 @@ * Set purple's global proxy information. * * @param info The proxy information. - * @since 2.6.0 */ void purple_global_proxy_set_info(PurpleProxyInfo *info); @@ -316,35 +304,6 @@ const char *host, int port, PurpleProxyConnectFunction connect_cb, gpointer data); -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_PROXY_C_) -/** - * Makes a connection through a SOCKS5 proxy. - * - * @param handle A handle that should be associated with this - * connection attempt. The handle can be used - * to cancel the connection attempt using the - * purple_proxy_connect_cancel_with_handle() - * function. - * @param gpi The PurpleProxyInfo specifying the proxy settings - * @param host The destination host. - * @param port The destination port. - * @param connect_cb The function to call when the connection is - * established. If the connection failed then - * fd will be -1 and error message will be set - * to something descriptive (hopefully). - * @param data User-defined data. - * - * @return NULL if there was an error, or a reference to an - * opaque data structure that can be used to cancel - * the pending connection, if needed. - * @deprecated Use purple_proxy_connect_socks5_account instead - */ -PurpleProxyConnectData *purple_proxy_connect_socks5(void *handle, - PurpleProxyInfo *gpi, - const char *host, int port, - PurpleProxyConnectFunction connect_cb, gpointer data); -#endif - /** * Cancel an in-progress connection attempt. This should be called * by the PRPL if the user disables an account while it is still @@ -365,8 +324,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_PROXY_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/prpl.c --- a/libpurple/prpl.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/prpl.c Fri Apr 06 04:30:00 2012 +0000 @@ -32,6 +32,17 @@ /**************************************************************************/ /** @name Attention Type API */ /**************************************************************************/ + +struct _PurpleAttentionType +{ + const char *name; /**< Shown in GUI elements */ + const char *incoming_description; /**< Shown when sent */ + const char *outgoing_description; /**< Shown when receied */ + const char *icon_name; /**< Icon to display (optional) */ + const char *unlocalized_name; /**< Unlocalized name for UIs needing it */ +}; + + PurpleAttentionType * purple_attention_type_new(const char *ulname, const char *name, const char *inc_desc, const char *out_desc) @@ -435,13 +446,13 @@ g_return_if_fail(gc != NULL); g_return_if_fail(who != NULL); - prpl = purple_find_prpl(purple_account_get_protocol_id(gc->account)); + prpl = purple_find_prpl(purple_account_get_protocol_id(purple_connection_get_account(gc))); send_attention = PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->send_attention; g_return_if_fail(send_attention != NULL); mtime = time(NULL); - attn = purple_get_attention_type_from_code(gc->account, type_code); + attn = purple_get_attention_type_from_code(purple_connection_get_account(gc), type_code); if ((buddy = purple_find_buddy(purple_connection_get_account(gc), who)) != NULL) alias = purple_buddy_get_contact_alias(buddy); @@ -462,7 +473,7 @@ if (!send_attention(gc, who, type_code)) return; - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, gc->account, who); + conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, purple_connection_get_account(gc), who); purple_conv_im_write(PURPLE_CONV_IM(conv), NULL, description, flags, mtime); purple_prpl_attention(conv, who, type_code, PURPLE_MESSAGE_SEND, time(NULL)); @@ -481,7 +492,7 @@ mtime = time(NULL); - attn = purple_get_attention_type_from_code(gc->account, type_code); + attn = purple_get_attention_type_from_code(purple_connection_get_account(gc), type_code); /* PURPLE_MESSAGE_NOTIFY is for attention messages. */ flags = PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NOTIFY | PURPLE_MESSAGE_RECV; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/prpl.h --- a/libpurple/prpl.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/prpl.h Fri Apr 06 04:30:00 2012 +0000 @@ -31,7 +31,10 @@ #define _PURPLE_PRPL_H_ typedef struct _PurplePluginProtocolInfo PurplePluginProtocolInfo; -/** @copydoc _PurpleAttentionType */ + +/** Represents "nudges" and "buzzes" that you may send to a buddy to attract + * their attention (or vice-versa). + */ typedef struct _PurpleAttentionType PurpleAttentionType; /**************************************************************************/ @@ -111,23 +114,6 @@ gboolean secret; /**< True if the entry is secret (password) */ }; -/** Represents "nudges" and "buzzes" that you may send to a buddy to attract - * their attention (or vice-versa). - */ -struct _PurpleAttentionType -{ - const char *name; /**< Shown in GUI elements */ - const char *incoming_description; /**< Shown when sent */ - const char *outgoing_description; /**< Shown when receied */ - const char *icon_name; /**< Icon to display (optional) */ - const char *unlocalized_name; /**< Unlocalized name for UIs needing it */ - - /* Reserved fields for future purposes */ - gpointer _reserved2; - gpointer _reserved3; - gpointer _reserved4; -}; - /** * Protocol options * @@ -200,14 +186,12 @@ /** * Indicates that slash commands are native to this protocol. * Used as a hint that unknown commands should not be sent as messages. - * @since 2.1.0 */ OPT_PROTO_SLASH_COMMANDS_NATIVE = 0x00000400, /** * Indicates that this protocol supports sending a user-supplied message * along with an invitation. - * @since 2.8.0 */ OPT_PROTO_INVITE_MESSAGE = 0x00000800 @@ -222,6 +206,27 @@ */ struct _PurplePluginProtocolInfo { + /** + * The size of the PurplePluginProtocolInfo. This should always be sizeof(PurplePluginProtocolInfo). + * This allows adding more functions to this struct without requiring a major version bump. + */ + unsigned long struct_size; + + /* NOTE: + * If more functions are added, they should accessed using the following syntax: + * + * if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl, new_function)) + * prpl->new_function(...); + * + * instead of + * + * if (prpl->new_function != NULL) + * prpl->new_function(...); + * + * The PURPLE_PROTOCOL_PLUGIN_HAS_FUNC macro can be used for the older member + * functions (e.g. login, send_im etc.) too. + */ + PurpleProtocolOptions options; /**< Protocol options. */ GList *user_splits; /**< A GList of PurpleAccountUserSplit */ @@ -333,6 +338,7 @@ void (*set_idle)(PurpleConnection *, int idletime); void (*change_passwd)(PurpleConnection *, const char *old_pass, const char *new_pass); + /** * Add a buddy to a group on the server. * @@ -341,11 +347,10 @@ * authorization and the user is not already authorized to see the * status of \a buddy, \a add_buddy should request authorization. * - * @deprecated Since 2.8.0, add_buddy_with_invite is preferred. - * @see add_buddy_with_invite + * If authorization is required, then use the supplied invite message. */ - void (*add_buddy)(PurpleConnection *, PurpleBuddy *buddy, PurpleGroup *group); - void (*add_buddies)(PurpleConnection *, GList *buddies, GList *groups); + void (*add_buddy)(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group, const char *message); + void (*add_buddies)(PurpleConnection *pc, GList *buddies, GList *groups, const char *message); void (*remove_buddy)(PurpleConnection *, PurpleBuddy *buddy, PurpleGroup *group); void (*remove_buddies)(PurpleConnection *, GList *buddies, GList *groups); void (*add_permit)(PurpleConnection *, const char *name); @@ -444,11 +449,6 @@ * @deprecated Use #PurplePluginProtocolInfo.get_info instead. */ void (*get_cb_info)(PurpleConnection *, int, const char *who); - /** - * @deprecated Use #PurplePluginProtocolInfo.get_cb_real_name and - * #PurplePluginProtocolInfo.status_text instead. - */ - void (*get_cb_away)(PurpleConnection *, int, const char *who); /** save/store buddy's alias on server list/roster */ void (*alias_buddy)(PurpleConnection *, const char *who, @@ -534,27 +534,6 @@ gboolean (*send_attention)(PurpleConnection *gc, const char *username, guint type); GList *(*get_attention_types)(PurpleAccount *acct); - /** - * The size of the PurplePluginProtocolInfo. This should always be sizeof(PurplePluginProtocolInfo). - * This allows adding more functions to this struct without requiring a major version bump. - */ - unsigned long struct_size; - - /* NOTE: - * If more functions are added, they should accessed using the following syntax: - * - * if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl, new_function)) - * prpl->new_function(...); - * - * instead of - * - * if (prpl->new_function != NULL) - * prpl->new_function(...); - * - * The PURPLE_PROTOCOL_PLUGIN_HAS_FUNC macro can be used for the older member - * functions (e.g. login, send_im etc.) too. - */ - /** This allows protocols to specify additional strings to be used for * various purposes. The idea is to stuff a bunch of strings in this hash * table instead of expanding the struct for every addition. This hash @@ -590,7 +569,6 @@ /** * Returns an array of "PurpleMood"s, with the last one having * "mood" set to @c NULL. - * @since 2.7.0 */ PurpleMood *(*get_moods)(PurpleAccount *account); @@ -610,7 +588,6 @@ * @param failure_cb Callback to be called if setting the public alias * fails * @see purple_account_set_public_alias - * @since 2.7.0 */ void (*set_public_alias)(PurpleConnection *gc, const char *alias, PurpleSetPublicAliasSuccessCallback success_cb, @@ -627,31 +604,14 @@ * @param failure_cb Callback to be called if the prpl is unable to * retrieve the alias * @see purple_account_get_public_alias - * @since 2.7.0 */ void (*get_public_alias)(PurpleConnection *gc, PurpleGetPublicAliasSuccessCallback success_cb, PurpleGetPublicAliasFailureCallback failure_cb); - - /** - * Add a buddy to a group on the server. - * - * This PRPL function may be called in situations in which the buddy is - * already in the specified group. If the protocol supports - * authorization and the user is not already authorized to see the - * status of \a buddy, \a add_buddy should request authorization. - * - * If authorization is required, then use the supplied invite message. - * - * @since 2.8.0 - */ - void (*add_buddy_with_invite)(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group, const char *message); - void (*add_buddies_with_invite)(PurpleConnection *pc, GList *buddies, GList *groups, const char *message); }; #define PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl, member) \ - (((G_STRUCT_OFFSET(PurplePluginProtocolInfo, member) < G_STRUCT_OFFSET(PurplePluginProtocolInfo, struct_size)) \ - || (G_STRUCT_OFFSET(PurplePluginProtocolInfo, member) < prpl->struct_size)) && \ + (G_STRUCT_OFFSET(PurplePluginProtocolInfo, member) < prpl->struct_size && \ prpl->member != NULL) @@ -661,9 +621,7 @@ #define PURPLE_PLUGIN_PROTOCOL_INFO(plugin) \ ((PurplePluginProtocolInfo *)(plugin)->info->extra_info) -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Attention Type API */ @@ -680,8 +638,8 @@ * should be the same string as @a ulname, with localization. * @param inc_desc A localized description shown when the event is received. * @param out_desc A localized description shown when the event is sent. + * * @return A pointer to the new object. - * @since 2.4.0 */ PurpleAttentionType *purple_attention_type_new(const char *ulname, const char *name, const char *inc_desc, const char *out_desc); @@ -693,7 +651,6 @@ * @param name The localized name that will be displayed by UIs. This should be * the same string given as the unlocalized name, but with * localization. - * @since 2.4.0 */ void purple_attention_type_set_name(PurpleAttentionType *type, const char *name); @@ -703,7 +660,6 @@ * * @param type The attention type. * @param desc The localized description for incoming events. - * @since 2.4.0 */ void purple_attention_type_set_incoming_desc(PurpleAttentionType *type, const char *desc); @@ -713,7 +669,6 @@ * * @param type The attention type. * @param desc The localized description for outgoing events. - * @since 2.4.0 */ void purple_attention_type_set_outgoing_desc(PurpleAttentionType *type, const char *desc); @@ -723,7 +678,6 @@ * @param type The attention type. * @param name The icon's name. * @note Icons are optional for attention events. - * @since 2.4.0 */ void purple_attention_type_set_icon_name(PurpleAttentionType *type, const char *name); @@ -734,7 +688,6 @@ * @param type The attention type. * @param ulname The unlocalized name. This should be the same string given as * the localized name, but without localization. - * @since 2.4.0 */ void purple_attention_type_set_unlocalized_name(PurpleAttentionType *type, const char *ulname); @@ -742,8 +695,8 @@ * Get the attention type's name as displayed by the UI. * * @param type The attention type. + * * @return The name. - * @since 2.4.0 */ const char *purple_attention_type_get_name(const PurpleAttentionType *type); @@ -752,7 +705,6 @@ * * @param type The attention type. * @return The description. - * @since 2.4.0 */ const char *purple_attention_type_get_incoming_desc(const PurpleAttentionType *type); @@ -761,7 +713,6 @@ * * @param type The attention type. * @return The description. - * @since 2.4.0 */ const char *purple_attention_type_get_outgoing_desc(const PurpleAttentionType *type); @@ -771,7 +722,6 @@ * @param type The attention type. * @return The icon name or @c NULL if unset/empty. * @note Icons are optional for attention events. - * @since 2.4.0 */ const char *purple_attention_type_get_icon_name(const PurpleAttentionType *type); @@ -780,7 +730,6 @@ * * @param type The attention type * @return The unlocalized name. - * @since 2.4.0 */ const char *purple_attention_type_get_unlocalized_name(const PurpleAttentionType *type); @@ -836,7 +785,6 @@ * @param account The account. * * @see account-actions-changed - * @since 2.6.0 */ void purple_prpl_got_account_actions(PurpleAccount *account); @@ -927,8 +875,6 @@ * * Note that you can't send arbitrary PurpleAttentionType's, because there is * only a fixed set of attention commands. - * - * @since 2.5.0 */ void purple_prpl_send_attention(PurpleConnection *gc, const char *who, guint type_code); @@ -939,8 +885,6 @@ * @param who Who requested your attention. * @param type_code An index into the prpl's attention_types list determining the type * of the attention request command to send. - * - * @since 2.5.0 */ void purple_prpl_got_attention(PurpleConnection *gc, const char *who, guint type_code); @@ -952,8 +896,6 @@ * @param who Who requested your attention. * @param type_code An index into the prpl's attention_types list determining the type * of the attention request command to send. - * - * @since 2.5.0 */ void purple_prpl_got_attention_in_chat(PurpleConnection *gc, int id, const char *who, guint type_code); @@ -988,7 +930,6 @@ * * @param account The account the user is on. * @param who The name of the contact for which capabilities have been received. - * @since 2.7.0 */ void purple_prpl_got_media_caps(PurpleAccount *account, const char *who); @@ -1008,8 +949,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PRPL_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/purple-2-uninstalled.pc.in --- a/libpurple/purple-2-uninstalled.pc.in Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ -datarootdir=@datarootdir@ -datadir=@datadir@ -sysconfdir=@sysconfdir@ - -abs_srcdir=@abs_srcdir@ -abs_builddir=@abs_builddir@ - -abs_top_srcdir=@abs_top_srcdir@ -abs_top_builddir=@abs_top_builddir@ - -plugindir=${libdir}/purple-@PURPLE_MAJOR_VERSION@ - -Name: libpurple -Description: libpurple is a GLib-based instant messenger library. -Version: @VERSION@ -Requires: glib-2.0 -Cflags: -I${abs_top_srcdir} -I${abs_top_builddir} -Libs: ${abs_builddir}/libpurple.la diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/purple-2.pc.in --- a/libpurple/purple-2.pc.in Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ -datarootdir=@datarootdir@ -datadir=@datadir@ -sysconfdir=@sysconfdir@ - -plugindir=${libdir}/purple-@PURPLE_MAJOR_VERSION@ - -Name: libpurple -Description: libpurple is a GLib-based instant messenger library. -Version: @VERSION@ -Requires: glib-2.0 -Cflags: -I${includedir} -Libs: -L${libdir} -lpurple diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/purple-3-uninstalled.pc.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/purple-3-uninstalled.pc.in Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,22 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ +datarootdir=@datarootdir@ +datadir=@datadir@ +sysconfdir=@sysconfdir@ + +abs_srcdir=@abs_srcdir@ +abs_builddir=@abs_builddir@ + +abs_top_srcdir=@abs_top_srcdir@ +abs_top_builddir=@abs_top_builddir@ + +plugindir=${libdir}/purple-@PURPLE_MAJOR_VERSION@ + +Name: libpurple +Description: libpurple is a GLib-based instant messenger library. +Version: @VERSION@ +Requires: glib-2.0 +Cflags: -I${abs_top_srcdir} -I${abs_top_builddir} +Libs: ${abs_builddir}/libpurple.la diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/purple-3.pc.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/purple-3.pc.in Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/libpurple +datarootdir=@datarootdir@ +datadir=@datadir@ +sysconfdir=@sysconfdir@ + +plugindir=${libdir}/purple-@PURPLE_MAJOR_VERSION@ + +Name: libpurple +Description: libpurple is a GLib-based instant messenger library. +Version: @VERSION@ +Requires: glib-2.0 +Cflags: -I${includedir} +Libs: -L${libdir} -lpurple diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/purple-uninstalled.pc.in --- a/libpurple/purple-uninstalled.pc.in Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ -datarootdir=@datarootdir@ -datadir=@datadir@ -sysconfdir=@sysconfdir@ - -abs_srcdir=@abs_srcdir@ -abs_builddir=@abs_builddir@ - -plugindir=${libdir}/purple-@PURPLE_MAJOR_VERSION@ - -Name: libpurple -Description: libpurple is a GLib-based instant messenger library. -Version: @VERSION@ -Requires: glib-2.0 -Cflags: -I${abs_srcdir} -I${abs_builddir} -Libs: ${abs_builddir}/libpurple.la diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/purple.h.in --- a/libpurple/purple.h.in Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/purple.h.in Fri Apr 06 04:30:00 2012 +0000 @@ -6,7 +6,6 @@ * include any other libpurple files. * * @ingroup core libpurple - * @since 2.3.0 */ /* purple diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/purple.pc.in --- a/libpurple/purple.pc.in Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ -datarootdir=@datarootdir@ -datadir=@datadir@ -sysconfdir=@sysconfdir@ - -plugindir=${libdir}/purple-@PURPLE_MAJOR_VERSION@ - -Name: libpurple -Description: libpurple is a GLib-based instant messenger library. -Version: @VERSION@ -Requires: glib-2.0 -Cflags: -I${includedir}/libpurple -Libs: -L${libdir} -lpurple diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/request.c --- a/libpurple/request.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/request.c Fri Apr 06 04:30:00 2012 +0000 @@ -42,6 +42,113 @@ } PurpleRequestInfo; +struct _PurpleRequestField +{ + PurpleRequestFieldType type; + PurpleRequestFieldGroup *group; + + char *id; + char *label; + char *type_hint; + + gboolean visible; + gboolean required; + + union + { + struct + { + gboolean multiline; + gboolean masked; + gboolean editable; + char *default_value; + char *value; + + } string; + + struct + { + int default_value; + int value; + + } integer; + + struct + { + gboolean default_value; + gboolean value; + + } boolean; + + struct + { + int default_value; + int value; + + GList *labels; + + } choice; + + struct + { + GList *items; + GList *icons; + GHashTable *item_data; + GList *selected; + GHashTable *selected_table; + + gboolean multiple_selection; + + } list; + + struct + { + PurpleAccount *default_account; + PurpleAccount *account; + gboolean show_all; + + PurpleFilterAccountFunc filter_func; + + } account; + + struct + { + unsigned int scale_x; + unsigned int scale_y; + const char *buffer; + gsize size; + } image; + + struct + { + PurpleCertificate *cert; + } certificate; + + } u; + + void *ui_data; + char *tooltip; +}; + +struct _PurpleRequestFields +{ + GList *groups; + + GHashTable *fields; + + GList *required_fields; + + void *ui_data; +}; + +struct _PurpleRequestFieldGroup +{ + PurpleRequestFields *fields_list; + + char *title; + + GList *fields; +}; PurpleRequestFields * purple_request_fields_new(void) @@ -271,6 +378,20 @@ return purple_request_field_account_get_value(field); } +gpointer purple_request_fields_get_ui_data(const PurpleRequestFields *fields) +{ + g_return_val_if_fail(fields != NULL, NULL); + + return fields->ui_data; +} + +void purple_request_fields_set_ui_data(PurpleRequestFields *fields, gpointer ui_data) +{ + g_return_if_fail(fields != NULL); + + fields->ui_data = ui_data; +} + PurpleRequestFieldGroup * purple_request_field_group_new(const char *title) { @@ -337,6 +458,14 @@ return group->fields; } +PurpleRequestFields * +purple_request_field_group_get_fields_list(const PurpleRequestFieldGroup *group) +{ + g_return_val_if_fail(group != NULL, NULL); + + return group->fields_list; +} + PurpleRequestField * purple_request_field_new(const char *id, const char *text, PurpleRequestFieldType type) @@ -365,6 +494,7 @@ g_free(field->id); g_free(field->label); g_free(field->type_hint); + g_free(field->tooltip); if (field->type == PURPLE_REQUEST_FIELD_STRING) { @@ -428,6 +558,15 @@ } void +purple_request_field_set_tooltip(PurpleRequestField *field, const char *tooltip) +{ + g_return_if_fail(field != NULL); + + g_free(field->tooltip); + field->tooltip = g_strdup(tooltip); +} + +void purple_request_field_set_required(PurpleRequestField *field, gboolean required) { g_return_if_fail(field != NULL); @@ -502,6 +641,14 @@ return field->type_hint; } +const char * +purple_request_field_get_tooltip(const PurpleRequestField *field) +{ + g_return_val_if_fail(field != NULL, NULL); + + return field->tooltip; +} + gboolean purple_request_field_is_required(const PurpleRequestField *field) { @@ -847,13 +994,6 @@ } void -purple_request_field_list_add(PurpleRequestField *field, const char *item, - void *data) -{ - purple_request_field_list_add_icon(field, item, NULL, data); -} - -void purple_request_field_list_add_icon(PurpleRequestField *field, const char *item, const char* icon_path, void *data) { @@ -1194,6 +1334,31 @@ return field->u.account.filter_func; } +PurpleRequestField * +purple_request_field_certificate_new(const char *id, const char *text, PurpleCertificate *cert) +{ + PurpleRequestField *field; + + g_return_val_if_fail(id != NULL, NULL); + g_return_val_if_fail(text != NULL, NULL); + g_return_val_if_fail(cert != NULL, NULL); + + field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_CERTIFICATE); + + field->u.certificate.cert = cert; + + return field; +} + +PurpleCertificate * +purple_request_field_certificate_get_value(const PurpleRequestField *field) +{ + g_return_val_if_fail(field != NULL, NULL); + g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_CERTIFICATE, NULL); + + return field->u.certificate.cert; +} + /* -- */ void * @@ -1501,6 +1666,29 @@ return NULL; } +void * +purple_request_certificate(void *handle, const char *title, + const char *primary, const char *secondary, + PurpleCertificate *cert, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + void *user_data) +{ + PurpleRequestFields *fields; + PurpleRequestFieldGroup *group; + PurpleRequestField *field; + + fields = purple_request_fields_new(); + group = purple_request_field_group_new(NULL); + purple_request_fields_add_group(fields, group); + field = purple_request_field_certificate_new("certificate", "Certificate", cert); + purple_request_field_group_add_field(group, field); + + return purple_request_fields(handle, title, primary, secondary, fields, + ok_text, ok_cb, cancel_text, cancel_cb, + NULL, NULL, NULL, user_data); +} + static void purple_request_close_info(PurpleRequestInfo *info) { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/request.h --- a/libpurple/request.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/request.h Fri Apr 06 04:30:00 2012 +0000 @@ -30,9 +30,21 @@ #include #include -/** @copydoc _PurpleRequestField */ +/** + * A request field. + */ typedef struct _PurpleRequestField PurpleRequestField; +/** + * Multiple fields request data. + */ +typedef struct _PurpleRequestFields PurpleRequestFields; + +/** + * A group of fields with a title. + */ +typedef struct _PurpleRequestFieldGroup PurpleRequestFieldGroup; + #include "account.h" #define PURPLE_DEFAULT_ACTION_NONE -1 @@ -64,127 +76,12 @@ PURPLE_REQUEST_FIELD_LIST, PURPLE_REQUEST_FIELD_LABEL, PURPLE_REQUEST_FIELD_IMAGE, - PURPLE_REQUEST_FIELD_ACCOUNT + PURPLE_REQUEST_FIELD_ACCOUNT, + PURPLE_REQUEST_FIELD_CERTIFICATE } PurpleRequestFieldType; /** - * Multiple fields request data. - */ -typedef struct -{ - GList *groups; - - GHashTable *fields; - - GList *required_fields; - - void *ui_data; - -} PurpleRequestFields; - -/** - * A group of fields with a title. - */ -typedef struct -{ - PurpleRequestFields *fields_list; - - char *title; - - GList *fields; - -} PurpleRequestFieldGroup; - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_REQUEST_C_) -/** - * A request field. - */ -struct _PurpleRequestField -{ - PurpleRequestFieldType type; - PurpleRequestFieldGroup *group; - - char *id; - char *label; - char *type_hint; - - gboolean visible; - gboolean required; - - union - { - struct - { - gboolean multiline; - gboolean masked; - gboolean editable; - char *default_value; - char *value; - - } string; - - struct - { - int default_value; - int value; - - } integer; - - struct - { - gboolean default_value; - gboolean value; - - } boolean; - - struct - { - int default_value; - int value; - - GList *labels; - - } choice; - - struct - { - GList *items; - GList *icons; - GHashTable *item_data; - GList *selected; - GHashTable *selected_table; - - gboolean multiple_selection; - - } list; - - struct - { - PurpleAccount *default_account; - PurpleAccount *account; - gboolean show_all; - - PurpleFilterAccountFunc filter_func; - - } account; - - struct - { - unsigned int scale_x; - unsigned int scale_y; - const char *buffer; - gsize size; - } image; - - } u; - - void *ui_data; - -}; -#endif - -/** * Request UI operations. */ typedef struct @@ -262,9 +159,7 @@ typedef void (*PurpleRequestFieldsCb)(void *, PurpleRequestFields *fields); typedef void (*PurpleRequestFileCb)(void *, const char *filename); -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Field List API */ @@ -410,6 +305,25 @@ PurpleAccount *purple_request_fields_get_account(const PurpleRequestFields *fields, const char *id); +/** + * Returns the UI data associated with this object. + * + * @param fields The fields list. + * + * @return The UI data associated with this object. This is a + * convenience field provided to the UIs--it is not + * used by the libuprple core. + */ +gpointer purple_request_fields_get_ui_data(const PurpleRequestFields *fields); + +/** + * Set the UI data associated with this object. + * + * @param fields The fields list. + * @param ui_data A pointer to associate with this object. + */ +void purple_request_fields_set_ui_data(PurpleRequestFields *fields, gpointer ui_data); + /*@}*/ /**************************************************************************/ @@ -462,6 +376,16 @@ GList *purple_request_field_group_get_fields( const PurpleRequestFieldGroup *group); +/** + * Returns a list of all fields in a group. + * + * @param group The group. + * + * @constreturn The list of fields in the group. + */ +PurpleRequestFields *purple_request_field_group_get_fields_list( + const PurpleRequestFieldGroup *group); + /*@}*/ /**************************************************************************/ @@ -517,6 +441,18 @@ const char *type_hint); /** + * Sets the tooltip for the field. + * + * This is optionally used by the UIs to provide a tooltip for + * the field. + * + * @param field The field. + * @param tooltip The tooltip text. + */ +void purple_request_field_set_tooltip(PurpleRequestField *field, + const char *tooltip); + +/** * Sets whether or not a field is required. * * @param field The field. @@ -540,8 +476,6 @@ * @param field The field. * * @return The UI data. - * - * @since 2.6.0 */ PurpleRequestFieldGroup *purple_request_field_get_group(const PurpleRequestField *field); @@ -582,6 +516,15 @@ const char *purple_request_field_get_type_hint(const PurpleRequestField *field); /** + * Returns the field's tooltip. + * + * @param field The field. + * + * @return The field's tooltip. + */ +const char *purple_request_field_get_tooltip(const PurpleRequestField *field); + +/** * Returns whether or not a field is required. * * @param field The field. @@ -596,8 +539,6 @@ * @param field The field. * * @return The UI data. - * - * @since 2.6.0 */ gpointer purple_request_field_get_ui_data(const PurpleRequestField *field); @@ -608,8 +549,6 @@ * @param ui_data The UI data. * * @return The UI data. - * - * @since 2.6.0 */ void purple_request_field_set_ui_data(PurpleRequestField *field, gpointer ui_data); @@ -961,18 +900,6 @@ * * @param field The list field. * @param item The list item. - * @param data The associated data. - * - * @deprecated Use purple_request_field_list_add_icon() instead. - */ -void purple_request_field_list_add(PurpleRequestField *field, - const char *item, void *data); - -/** - * Adds an item to a list field. - * - * @param field The list field. - * @param item The list item. * @param icon_path The path to icon file, or @c NULL for no icon. * @param data The associated data. */ @@ -1244,6 +1171,36 @@ /*@}*/ /**************************************************************************/ +/** @name Certificate Field API */ +/**************************************************************************/ +/*@{*/ + +/** + * Creates a certificate field. + * + * @param id The field ID. + * @param text The label of the field. + * @param cert The certificate of the field. + * + * @return The new field. + */ +PurpleRequestField *purple_request_field_certificate_new(const char *id, + const char *text, + PurpleCertificate *cert); + +/** + * Returns the certificate in a certificate field. + * + * @param field The field. + * + * @return The certificate. + */ +PurpleCertificate *purple_request_field_certificate_get_value( + const PurpleRequestField *field); + +/*@}*/ + +/**************************************************************************/ /** @name Request API */ /**************************************************************************/ /*@{*/ @@ -1402,8 +1359,7 @@ /** * Version of purple_request_action() supplying an image for the UI to - * optionally display as an icon in the dialog; see its documentation - * @since 2.7.0 + * optionally display as an icon in the dialog; see its documentation. */ void *purple_request_action_with_icon(void *handle, const char *title, const char *primary, const char *secondary, int default_action, @@ -1414,7 +1370,6 @@ /** * va_list version of purple_request_action_with_icon(); * see its documentation. - * @since 2.7.0 */ void *purple_request_action_with_icon_varg(void *handle, const char *title, const char *primary, const char *secondary, int default_action, @@ -1576,6 +1531,37 @@ PurpleAccount *account, const char *who, PurpleConversation *conv, void *user_data); +/** + * Prompts the user for action over a certificate. + * + * This is often represented as a dialog with a button for each action. + * + * @param handle The plugin or connection handle. For some things this + * is extremely important. See the comments on + * purple_request_input(). + * @param title The title of the message, or @c NULL if it should have + * no title. + * @param primary The main point of the message, or @c NULL if you're + * feeling enigmatic. + * @param secondary Secondary information, or @c NULL if there is none. + * @param cert The #PurpleCertificate associated with this request. + * @param ok_text The text for the @c OK button, which may not be @c NULL. + * @param ok_cb The callback for the @c OK button, which may not be + * @c NULL. + * @param cancel_text The text for the @c Cancel button, which may not be + * @c NULL. + * @param cancel_cb The callback for the @c Cancel button, which may be + * @c NULL. + * @param user_data The data to pass to the callback. + * + * @return A UI-specific handle. + */ +void *purple_request_certificate(void *handle, const char *title, + const char *primary, const char *secondary, PurpleCertificate *cert, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + void *user_data); + /*@}*/ /**************************************************************************/ @@ -1601,8 +1587,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_REQUEST_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/roomlist.c --- a/libpurple/roomlist.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/roomlist.c Fri Apr 06 04:30:00 2012 +0000 @@ -32,6 +32,39 @@ #include "roomlist.h" #include "server.h" +/** + * Represents a list of rooms for a given connection on a given protocol. + */ +struct _PurpleRoomlist { + PurpleAccount *account; /**< The account this list belongs to. */ + GList *fields; /**< The fields. */ + GList *rooms; /**< The list of rooms. */ + gboolean in_progress; /**< The listing is in progress. */ + gpointer ui_data; /**< UI private data. */ + gpointer proto_data; /** Prpl private data. */ + guint ref; /**< The reference count. */ +}; + +/** + * Represents a room. + */ +struct _PurpleRoomlistRoom { + PurpleRoomlistRoomType type; /**< The type of room. */ + gchar *name; /**< The name of the room. */ + GList *fields; /**< Other fields. */ + PurpleRoomlistRoom *parent; /**< The parent room, or NULL. */ + gboolean expanded_once; /**< A flag the UI uses to avoid multiple expand prpl cbs. */ +}; + +/** + * A field a room might have. + */ +struct _PurpleRoomlistField { + PurpleRoomlistFieldType type; /**< The type of field. */ + gchar *label; /**< The i18n user displayed name of the field. */ + gchar *name; /**< The internal name of the field. */ + gboolean hidden; /**< Hidden? */ +}; static PurpleRoomlistUiOps *ops = NULL; @@ -127,6 +160,13 @@ purple_roomlist_destroy(list); } +PurpleAccount *purple_roomlist_get_account(PurpleRoomlist *list) +{ + g_return_val_if_fail(list != NULL, NULL); + + return list->account; +} + void purple_roomlist_set_fields(PurpleRoomlist *list, GList *fields) { g_return_if_fail(list != NULL); @@ -234,6 +274,34 @@ return list->fields; } +gpointer purple_roomlist_get_proto_data(PurpleRoomlist *list) +{ + g_return_val_if_fail(list != NULL, NULL); + + return list->proto_data; +} + +void purple_roomlist_set_proto_data(PurpleRoomlist *list, gpointer proto_data) +{ + g_return_if_fail(list != NULL); + + list->proto_data = proto_data; +} + +gpointer purple_roomlist_get_ui_data(PurpleRoomlist *list) +{ + g_return_val_if_fail(list != NULL, NULL); + + return list->ui_data; +} + +void purple_roomlist_set_ui_data(PurpleRoomlist *list, gpointer ui_data) +{ + g_return_if_fail(list != NULL); + + list->ui_data = ui_data; +} + /*@}*/ /**************************************************************************/ @@ -329,7 +397,21 @@ return room->parent; } -GList * purple_roomlist_room_get_fields(PurpleRoomlistRoom *room) +gboolean purple_roomlist_room_get_expanded_once(PurpleRoomlistRoom *room) +{ + g_return_val_if_fail(room != NULL, FALSE); + + return room->expanded_once; +} + +void purple_roomlist_room_set_expanded_once(PurpleRoomlistRoom *room, gboolean expanded_once) +{ + g_return_if_fail(room != NULL); + + room->expanded_once = expanded_once; +} + +GList *purple_roomlist_room_get_fields(PurpleRoomlistRoom *room) { return room->fields; } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/roomlist.h --- a/libpurple/roomlist.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/roomlist.h Fri Apr 06 04:30:00 2012 +0000 @@ -64,40 +64,6 @@ /**************************************************************************/ /** - * Represents a list of rooms for a given connection on a given protocol. - */ -struct _PurpleRoomlist { - PurpleAccount *account; /**< The account this list belongs to. */ - GList *fields; /**< The fields. */ - GList *rooms; /**< The list of rooms. */ - gboolean in_progress; /**< The listing is in progress. */ - gpointer ui_data; /**< UI private data. */ - gpointer proto_data; /** Prpl private data. */ - guint ref; /**< The reference count. */ -}; - -/** - * Represents a room. - */ -struct _PurpleRoomlistRoom { - PurpleRoomlistRoomType type; /**< The type of room. */ - gchar *name; /**< The name of the room. */ - GList *fields; /**< Other fields. */ - PurpleRoomlistRoom *parent; /**< The parent room, or NULL. */ - gboolean expanded_once; /**< A flag the UI uses to avoid multiple expand prpl cbs. */ -}; - -/** - * A field a room might have. - */ -struct _PurpleRoomlistField { - PurpleRoomlistFieldType type; /**< The type of field. */ - gchar *label; /**< The i18n user displayed name of the field. */ - gchar *name; /**< The internal name of the field. */ - gboolean hidden; /**< Hidden? */ -}; - -/** * The room list ops to be filled out by the UI. */ struct _PurpleRoomlistUiOps { @@ -115,9 +81,7 @@ }; -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Room List API */ @@ -163,6 +127,14 @@ void purple_roomlist_unref(PurpleRoomlist *list); /** + * Retrieve the PurpleAccount that was given when the room list was + * created. + * + * @return The PurpleAccount tied to this room list. + */ +PurpleAccount *purple_roomlist_get_account(PurpleRoomlist *list); + +/** * Set the different field types and their names for this protocol. * * This must be called before purple_roomlist_room_add(). @@ -241,11 +213,48 @@ /** * Get the list of fields for a roomlist. * - * @param roomlist The roomlist, which must not be @c NULL. + * @param roomlist The roomlist, which must not be @c NULL. * @constreturn A list of fields - * @since 2.4.0 + */ +GList *purple_roomlist_get_fields(PurpleRoomlist *roomlist); + +/** + * Get the protocol data associated with this room list. + * + * @param list The roomlist, which must not be @c NULL. + * + * @return The protocol data associated with this room list. This is a + * convenience field provided to the protocol plugin--it is not + * used the libpurple core. + */ +gpointer purple_roomlist_get_proto_data(PurpleRoomlist *list); + +/** + * Set the protocol data associated with this room list. + * + * @param list The roomlist, which must not be @c NULL. + * @param proto_data A pointer to associate with this room list. */ -GList * purple_roomlist_get_fields(PurpleRoomlist *roomlist); +void purple_roomlist_set_proto_data(PurpleRoomlist *list, gpointer proto_data); + +/** + * Get the UI data associated with this room list. + * + * @param list The roomlist, which must not be @c NULL. + * + * @return The UI data associated with this room list. This is a + * convenience field provided to the UIs--it is not + * used by the libpurple core. + */ +gpointer purple_roomlist_get_ui_data(PurpleRoomlist *list); + +/** + * Set the UI data associated with this room list. + * + * @param list The roomlist, which must not be @c NULL. + * @param ui_data A pointer to associate with this room list. + */ +void purple_roomlist_set_ui_data(PurpleRoomlist *list, gpointer ui_data); /*@}*/ @@ -287,7 +296,6 @@ * Get the type of a room. * @param room The room, which must not be @c NULL. * @return The type of the room. - * @since 2.4.0 */ PurpleRoomlistRoomType purple_roomlist_room_get_type(PurpleRoomlistRoom *room); @@ -295,7 +303,6 @@ * Get the name of a room. * @param room The room, which must not be @c NULL. * @return The name of the room. - * @since 2.4.0 */ const char * purple_roomlist_room_get_name(PurpleRoomlistRoom *room); @@ -303,16 +310,31 @@ * Get the parent of a room. * @param room The room, which must not be @c NULL. * @return The parent of the room, which can be @c NULL. - * @since 2.4.0 */ PurpleRoomlistRoom * purple_roomlist_room_get_parent(PurpleRoomlistRoom *room); /** + * Get the value of the expanded_once flag. + * + * @param room The room, which must not be @c NULL. + * + * @return The value of the expanded_once flag. + */ +gboolean purple_roomlist_room_get_expanded_once(PurpleRoomlistRoom *room); + +/** + * Set the expanded_once flag. + * + * @param room The room, which must not be @c NULL. + * @param expanded_once The new value of the expanded_once flag. + */ +void purple_roomlist_room_set_expanded_once(PurpleRoomlistRoom *room, gboolean expanded_once); + +/** * Get the list of fields for a room. * * @param room The room, which must not be @c NULL. * @constreturn A list of fields - * @since 2.4.0 */ GList * purple_roomlist_room_get_fields(PurpleRoomlistRoom *room); @@ -344,7 +366,6 @@ * @param field A PurpleRoomlistField, which must not be @c NULL. * * @return The type of the field. - * @since 2.4.0 */ PurpleRoomlistFieldType purple_roomlist_field_get_type(PurpleRoomlistField *field); @@ -354,7 +375,6 @@ * @param field A PurpleRoomlistField, which must not be @c NULL. * * @return The label of the field. - * @since 2.4.0 */ const char * purple_roomlist_field_get_label(PurpleRoomlistField *field); @@ -363,7 +383,6 @@ * @param field A PurpleRoomlistField, which must not be @c NULL. * * @return @c TRUE if the field is hidden, @c FALSE otherwise. - * @since 2.4.0 */ gboolean purple_roomlist_field_get_hidden(PurpleRoomlistField *field); @@ -391,8 +410,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_ROOMLIST_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/savedstatuses.c --- a/libpurple/savedstatuses.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/savedstatuses.c Fri Apr 06 04:30:00 2012 +0000 @@ -387,7 +387,6 @@ const char *protocol; acct_name = xmlnode_get_data(node); protocol = xmlnode_get_attrib(node, "protocol"); - protocol = _purple_oscar_convert(acct_name, protocol); /* XXX: Remove */ if ((acct_name != NULL) && (protocol != NULL)) ret->account = purple_accounts_find(acct_name, protocol); g_free(acct_name); @@ -404,7 +403,7 @@ if ((node != NULL) && ((data = xmlnode_get_data(node)) != NULL)) { ret->type = purple_status_type_find_with_id( - ret->account->status_types, data); + purple_account_get_status_types(ret->account), data); g_free(data); } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/savedstatuses.h --- a/libpurple/savedstatuses.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/savedstatuses.h Fri Apr 06 04:30:00 2012 +0000 @@ -60,9 +60,7 @@ #include "status.h" -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Saved status subsystem */ @@ -418,8 +416,7 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_SAVEDSTATUSES_H_ */ + diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/server.c --- a/libpurple/server.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/server.c Fri Apr 06 04:30:00 2012 +0000 @@ -149,7 +149,7 @@ * this only reset lar->sent if we're away AND idle? */ auto_reply_pref = purple_prefs_get_string("/purple/away/auto_reply"); - if((gc->flags & PURPLE_CONNECTION_AUTO_RESP) && + if((purple_connection_get_flags(gc) & PURPLE_CONNECTION_AUTO_RESP) && !purple_presence_is_available(presence) && !purple_strequal(auto_reply_pref, "never")) { @@ -325,18 +325,6 @@ return attn; } -void -serv_send_attention(PurpleConnection *gc, const char *who, guint type_code) -{ - purple_prpl_send_attention(gc, who, type_code); -} - -void -serv_got_attention(PurpleConnection *gc, const char *who, guint type_code) -{ - purple_prpl_got_attention(gc, who, type_code); -} - /* * Move a buddy from one group to another on server. @@ -582,7 +570,7 @@ * We should update the conversation window buttons and menu, * if it exists. */ - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, gc->account); + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, purple_connection_get_account(gc)); /* * Make copies of the message and the sender in case plugins want @@ -593,7 +581,7 @@ plugin_return = GPOINTER_TO_INT( purple_signal_emit_return_1(purple_conversations_get_handle(), - "receiving-im-msg", gc->account, + "receiving-im-msg", purple_connection_get_account(gc), &angel, &buffy, conv, &flags)); if (!buffy || !angel || plugin_return) { @@ -605,12 +593,12 @@ name = angel; message = buffy; - purple_signal_emit(purple_conversations_get_handle(), "received-im-msg", gc->account, + purple_signal_emit(purple_conversations_get_handle(), "received-im-msg", purple_connection_get_account(gc), name, message, conv, flags); /* search for conversation again in case it was created by received-im-msg handler */ if (conv == NULL) - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, gc->account); + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, purple_connection_get_account(gc)); if (conv == NULL) conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, name); @@ -627,7 +615,7 @@ * - or we're not idle and the 'only auto respond if idle' pref * is set */ - if (gc->flags & PURPLE_CONNECTION_AUTO_RESP) + if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_AUTO_RESP) { PurplePresence *presence; PurpleStatus *status; @@ -700,7 +688,7 @@ PurpleConversation *conv; PurpleConvIm *im = NULL; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, gc->account); + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, purple_connection_get_account(gc)); if (conv != NULL) { im = PURPLE_CONV_IM(conv); @@ -710,15 +698,15 @@ { case PURPLE_TYPING: purple_signal_emit(purple_conversations_get_handle(), - "buddy-typing", gc->account, name); + "buddy-typing", purple_connection_get_account(gc), name); break; case PURPLE_TYPED: purple_signal_emit(purple_conversations_get_handle(), - "buddy-typed", gc->account, name); + "buddy-typed", purple_connection_get_account(gc), name); break; case PURPLE_NOT_TYPING: purple_signal_emit(purple_conversations_get_handle(), - "buddy-typing-stopped", gc->account, name); + "buddy-typing-stopped", purple_connection_get_account(gc), name); break; } } @@ -732,12 +720,12 @@ PurpleConversation *conv; PurpleConvIm *im; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, gc->account); + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, purple_connection_get_account(gc)); if (conv != NULL) { im = PURPLE_CONV_IM(conv); - if (im->typing_state == PURPLE_NOT_TYPING) + if (purple_conv_im_get_typing_state(im) == PURPLE_NOT_TYPING) return; purple_conv_im_stop_typing_timeout(im); @@ -746,7 +734,7 @@ else { purple_signal_emit(purple_conversations_get_handle(), - "buddy-typing-stopped", gc->account, name); + "buddy-typing-stopped", purple_connection_get_account(gc), name); } } @@ -937,7 +925,7 @@ plugin_return = GPOINTER_TO_INT( purple_signal_emit_return_1(purple_conversations_get_handle(), - "receiving-chat-msg", g->account, + "receiving-chat-msg", purple_connection_get_account(g), &angel, &buffy, conv, &flags)); if (!buffy || !angel || plugin_return) { @@ -949,7 +937,7 @@ who = angel; message = buffy; - purple_signal_emit(purple_conversations_get_handle(), "received-chat-msg", g->account, + purple_signal_emit(purple_conversations_get_handle(), "received-chat-msg", purple_connection_get_account(g), who, message, conv, flags); purple_conv_chat_write(chat, who, message, flags, mtime); diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/server.h --- a/libpurple/server.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/server.h Fri Apr 06 04:30:00 2012 +0000 @@ -30,9 +30,7 @@ #include "conversation.h" #include "prpl.h" -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /** * Send a typing message to a given user over a given connection. @@ -61,32 +59,6 @@ */ PurpleAttentionType *purple_get_attention_type_from_code(PurpleAccount *account, guint type_code); -/** Send an attention request message. - * - * @deprecated Use purple_prpl_send_attention() instead. - * - * @param gc The connection to send the message on. - * @param who Whose attention to request. - * @param type_code An index into the prpl's attention_types list determining the type - * of the attention request command to send. 0 if prpl only defines one - * (for example, Yahoo and MSN), but some protocols define more (MySpaceIM). - * - * Note that you can't send arbitrary PurpleAttentionType's, because there is - * only a fixed set of attention commands. - */ -void serv_send_attention(PurpleConnection *gc, const char *who, guint type_code); - -/** Process an incoming attention message. - * - * @deprecated Use purple_prpl_got_attention() instead. - * - * @param gc The connection that received the attention message. - * @param who Who requested your attention. - * @param type_code An index into the prpl's attention_types list determining the type - * of the attention request command to send. - */ -void serv_got_attention(PurpleConnection *gc, const char *who, guint type_code); - void serv_get_info(PurpleConnection *, const char *); void serv_set_info(PurpleConnection *, const char *); @@ -211,8 +183,7 @@ PurpleMessageFlags flags, const char *message, time_t mtime); void serv_send_file(PurpleConnection *gc, const char *who, const char *file); -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_SERVER_H_ */ + diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/signals.h --- a/libpurple/signals.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/signals.h Fri Apr 06 04:30:00 2012 +0000 @@ -35,9 +35,7 @@ typedef void (*PurpleSignalMarshalFunc)(PurpleCallback cb, va_list args, void *data, void **return_val); -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Signal API */ @@ -373,8 +371,7 @@ PurpleCallback cb, va_list args, void *data, void **return_val); /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_SIGNALS_H_ */ + diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/smiley.h --- a/libpurple/smiley.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/smiley.h Fri Apr 06 04:30:00 2012 +0000 @@ -1,7 +1,6 @@ /** * @file smiley.h Smiley API * @ingroup core - * @since 2.5.0 */ /* purple @@ -51,9 +50,7 @@ #define PURPLE_IS_SMILEY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PURPLE_TYPE_SMILEY)) #define PURPLE_SMILEY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PURPLE_TYPE_SMILEY, PurpleSmileyClass)) -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Custom Smiley API */ @@ -254,9 +251,7 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_SMILEY_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/sound-theme-loader.c --- a/libpurple/sound-theme-loader.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/sound-theme-loader.c Fri Apr 06 04:30:00 2012 +0000 @@ -32,23 +32,26 @@ *****************************************************************************/ static PurpleTheme * -purple_sound_loader_build(const gchar *dir) +purple_sound_loader_build(const gchar *theme_dir) { xmlnode *root_node = NULL, *sub_node; - gchar *filename_full, *data = NULL; + gchar *dir, *filename_full, *data = NULL; PurpleSoundTheme *theme = NULL; const gchar *name; /* Find the theme file */ - g_return_val_if_fail(dir != NULL, NULL); + g_return_val_if_fail(theme_dir != NULL, NULL); + dir = g_build_filename(theme_dir, "purple", "sound", NULL); filename_full = g_build_filename(dir, "theme.xml", NULL); if (g_file_test(filename_full, G_FILE_TEST_IS_REGULAR)) root_node = xmlnode_from_file(dir, "theme.xml", "sound themes", "sound-theme-loader"); g_free(filename_full); - if (root_node == NULL) + if (root_node == NULL) { + g_free(dir); return NULL; + } name = xmlnode_get_attrib(root_node, "name"); @@ -79,6 +82,7 @@ xmlnode_free(root_node); g_free(data); + g_free(dir); return PURPLE_THEME(theme); } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/sound-theme.c --- a/libpurple/sound-theme.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/sound-theme.c Fri Apr 06 04:30:00 2012 +0000 @@ -24,7 +24,7 @@ #include "sound-theme.h" #define PURPLE_SOUND_THEME_GET_PRIVATE(Gobject) \ - ((PurpleSoundThemePrivate *) ((PURPLE_SOUND_THEME(Gobject))->priv)) + (G_TYPE_INSTANCE_GET_PRIVATE((Gobject), PURPLE_TYPE_SOUND_THEME, PurpleSoundThemePrivate)) /****************************************************************************** * Structs @@ -55,8 +55,6 @@ { PurpleSoundThemePrivate *priv; - (PURPLE_SOUND_THEME(instance))->priv = g_new0(PurpleSoundThemePrivate, 1); - priv = PURPLE_SOUND_THEME_GET_PRIVATE(instance); priv->sound_files = g_hash_table_new_full(g_str_hash, @@ -82,6 +80,8 @@ parent_class = g_type_class_peek_parent(klass); + g_type_class_add_private(klass, sizeof(PurpleSoundThemePrivate)); + obj_class->finalize = purple_sound_theme_finalize; } diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/sound-theme.h --- a/libpurple/sound-theme.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/sound-theme.h Fri Apr 06 04:30:00 2012 +0000 @@ -51,7 +51,6 @@ struct _PurpleSoundTheme { PurpleTheme parent; - gpointer priv; }; struct _PurpleSoundThemeClass diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/sound.h --- a/libpurple/sound.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/sound.h Fri Apr 06 04:30:00 2012 +0000 @@ -38,7 +38,7 @@ * A type of sound. */ -typedef enum _PurpleSoundEventID +typedef enum { PURPLE_SOUND_BUDDY_ARRIVE = 0, /**< Buddy signs on. */ PURPLE_SOUND_BUDDY_LEAVE, /**< Buddy signs off. */ @@ -72,9 +72,7 @@ void (*_purple_reserved4)(void); } PurpleSoundUiOps; -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name Sound API */ @@ -136,8 +134,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_SOUND_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/sslconn.c --- a/libpurple/sslconn.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/sslconn.c Fri Apr 06 04:30:00 2012 +0000 @@ -185,15 +185,6 @@ } PurpleSslConnection * -purple_ssl_connect_fd(PurpleAccount *account, int fd, - PurpleSslInputFunction func, - PurpleSslErrorFunction error_func, - void *data) -{ - return purple_ssl_connect_with_host_fd(account, fd, func, error_func, NULL, data); -} - -PurpleSslConnection * purple_ssl_connect_with_host_fd(PurpleAccount *account, int fd, PurpleSslInputFunction func, PurpleSslErrorFunction error_func, diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/sslconn.h --- a/libpurple/sslconn.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/sslconn.h Fri Apr 06 04:30:00 2012 +0000 @@ -140,9 +140,7 @@ void (*_purple_reserved4)(void); } PurpleSslOps; -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name SSL API */ @@ -203,7 +201,6 @@ * @param data User-defined data. * * @return The SSL connection handle. - * @since 2.6.0 */ PurpleSslConnection *purple_ssl_connect_with_ssl_cn(PurpleAccount *account, const char *host, int port, PurpleSslInputFunction func, @@ -211,26 +208,6 @@ const char *ssl_host, void *data); -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_SSLCONN_C_) -/** - * Makes a SSL connection using an already open file descriptor. - * - * @deprecated Use purple_ssl_connect_with_host_fd() instead. - * - * @param account The account making the connection. - * @param fd The file descriptor. - * @param func The SSL input handler function. - * @param error_func The SSL error handler function. - * @param data User-defined data. - * - * @return The SSL connection handle. - */ -PurpleSslConnection *purple_ssl_connect_fd(PurpleAccount *account, int fd, - PurpleSslInputFunction func, - PurpleSslErrorFunction error_func, - void *data); -#endif - /** * Makes a SSL connection using an already open file descriptor. * @@ -242,8 +219,6 @@ * @param data User-defined data. * * @return The SSL connection handle. - * - * @since 2.2.0 */ PurpleSslConnection *purple_ssl_connect_with_host_fd(PurpleAccount *account, int fd, PurpleSslInputFunction func, @@ -298,8 +273,6 @@ * * @return The peer certificate chain, in the order of certificate, issuer, * issuer's issuer, etc. @a NULL if no certificates have been provided, - * - * @since 2.2.0 */ GList * purple_ssl_get_peer_certificates(PurpleSslConnection *gsc); @@ -336,8 +309,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_SSLCONN_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/status.c --- a/libpurple/status.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/status.c Fri Apr 06 04:30:00 2012 +0000 @@ -44,7 +44,6 @@ char *id; char *name; - char *primary_attr_id; gboolean saveable; gboolean user_settable; @@ -258,6 +257,42 @@ user_settable, FALSE); } +static void +status_type_add_attr(PurpleStatusType *status_type, const char *id, + const char *name, PurpleValue *value) +{ + PurpleStatusAttr *attr; + + g_return_if_fail(status_type != NULL); + g_return_if_fail(id != NULL); + g_return_if_fail(name != NULL); + g_return_if_fail(value != NULL); + + attr = purple_status_attr_new(id, name, value); + + status_type->attrs = g_list_append(status_type->attrs, attr); +} + +static void +status_type_add_attrs_vargs(PurpleStatusType *status_type, va_list args) +{ + const char *id, *name; + PurpleValue *value; + + g_return_if_fail(status_type != NULL); + + while ((id = va_arg(args, const char *)) != NULL) + { + name = va_arg(args, const char *); + g_return_if_fail(name != NULL); + + value = va_arg(args, PurpleValue *); + g_return_if_fail(value != NULL); + + status_type_add_attr(status_type, id, name, value); + } +} + PurpleStatusType * purple_status_type_new_with_attrs(PurpleStatusPrimitive primitive, const char *id, const char *name, @@ -278,10 +313,10 @@ user_settable, independent); /* Add the first attribute */ - purple_status_type_add_attr(status_type, attr_id, attr_name, attr_value); + status_type_add_attr(status_type, attr_id, attr_name, attr_value); va_start(args, attr_value); - purple_status_type_add_attrs_vargs(status_type, args); + status_type_add_attrs_vargs(status_type, args); va_end(args); return status_type; @@ -294,7 +329,6 @@ g_free(status_type->id); g_free(status_type->name); - g_free(status_type->primary_attr_id); g_list_foreach(status_type->attrs, (GFunc)purple_status_attr_destroy, NULL); g_list_free(status_type->attrs); @@ -303,70 +337,6 @@ g_free(status_type); } -void -purple_status_type_set_primary_attr(PurpleStatusType *status_type, const char *id) -{ - g_return_if_fail(status_type != NULL); - - g_free(status_type->primary_attr_id); - status_type->primary_attr_id = g_strdup(id); -} - -void -purple_status_type_add_attr(PurpleStatusType *status_type, const char *id, - const char *name, PurpleValue *value) -{ - PurpleStatusAttr *attr; - - g_return_if_fail(status_type != NULL); - g_return_if_fail(id != NULL); - g_return_if_fail(name != NULL); - g_return_if_fail(value != NULL); - - attr = purple_status_attr_new(id, name, value); - - status_type->attrs = g_list_append(status_type->attrs, attr); -} - -void -purple_status_type_add_attrs_vargs(PurpleStatusType *status_type, va_list args) -{ - const char *id, *name; - PurpleValue *value; - - g_return_if_fail(status_type != NULL); - - while ((id = va_arg(args, const char *)) != NULL) - { - name = va_arg(args, const char *); - g_return_if_fail(name != NULL); - - value = va_arg(args, PurpleValue *); - g_return_if_fail(value != NULL); - - purple_status_type_add_attr(status_type, id, name, value); - } -} - -void -purple_status_type_add_attrs(PurpleStatusType *status_type, const char *id, - const char *name, PurpleValue *value, ...) -{ - va_list args; - - g_return_if_fail(status_type != NULL); - g_return_if_fail(id != NULL); - g_return_if_fail(name != NULL); - g_return_if_fail(value != NULL); - - /* Add the first attribute */ - purple_status_type_add_attr(status_type, id, name, value); - - va_start(args, value); - purple_status_type_add_attrs_vargs(status_type, args); - va_end(args); -} - PurpleStatusPrimitive purple_status_type_get_primitive(const PurpleStatusType *status_type) { @@ -435,14 +405,6 @@ return (primitive == PURPLE_STATUS_AVAILABLE); } -const char * -purple_status_type_get_primary_attr(const PurpleStatusType *status_type) -{ - g_return_val_if_fail(status_type != NULL, NULL); - - return status_type->primary_attr_id; -} - PurpleStatusAttr * purple_status_type_get_attr(const PurpleStatusType *status_type, const char *id) { @@ -706,6 +668,68 @@ notify_status_update(presence, old_status, status); } +static void +status_set_attr_boolean(PurpleStatus *status, const char *id, + gboolean value) +{ + PurpleValue *attr_value; + + g_return_if_fail(status != NULL); + g_return_if_fail(id != NULL); + + /* Make sure this attribute exists and is the correct type. */ + attr_value = purple_status_get_attr_value(status, id); + g_return_if_fail(attr_value != NULL); + g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_BOOLEAN); + + purple_value_set_boolean(attr_value, value); +} + +static void +status_set_attr_int(PurpleStatus *status, const char *id, int value) +{ + PurpleValue *attr_value; + + g_return_if_fail(status != NULL); + g_return_if_fail(id != NULL); + + /* Make sure this attribute exists and is the correct type. */ + attr_value = purple_status_get_attr_value(status, id); + g_return_if_fail(attr_value != NULL); + g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_INT); + + purple_value_set_int(attr_value, value); +} + +static void +status_set_attr_string(PurpleStatus *status, const char *id, + const char *value) +{ + PurpleValue *attr_value; + + g_return_if_fail(status != NULL); + g_return_if_fail(id != NULL); + + /* Make sure this attribute exists and is the correct type. */ + attr_value = purple_status_get_attr_value(status, id); + /* This used to be g_return_if_fail, but it's failing a LOT, so + * let's generate a log error for now. */ + /* g_return_if_fail(attr_value != NULL); */ + if (attr_value == NULL) { + purple_debug_error("status", + "Attempted to set status attribute '%s' for " + "status '%s', which is not legal. Fix " + "this!\n", id, + purple_status_type_get_name(purple_status_get_type(status))); + return; + } + g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_STRING); + + /* XXX: Check if the value has actually changed. If it has, and the status + * is active, should this trigger 'status_has_changed'? */ + purple_value_set_string(attr_value, value); +} + void purple_status_set_active(PurpleStatus *status, gboolean active) { @@ -782,31 +806,31 @@ specified_attr_ids = g_list_prepend(specified_attr_ids, (gpointer)id); - if (value->type == PURPLE_TYPE_STRING) + if (purple_value_get_type(value) == PURPLE_TYPE_STRING) { const gchar *string_data = l->data; l = l->next; - if (purple_strequal(string_data, value->data.string_data)) + if (purple_strequal(string_data, purple_value_get_string(value))) continue; - purple_status_set_attr_string(status, id, string_data); + status_set_attr_string(status, id, string_data); changed = TRUE; } - else if (value->type == PURPLE_TYPE_INT) + else if (purple_value_get_type(value) == PURPLE_TYPE_INT) { int int_data = GPOINTER_TO_INT(l->data); l = l->next; - if (int_data == value->data.int_data) + if (int_data == purple_value_get_int(value)) continue; - purple_status_set_attr_int(status, id, int_data); + status_set_attr_int(status, id, int_data); changed = TRUE; } - else if (value->type == PURPLE_TYPE_BOOLEAN) + else if (purple_value_get_type(value) == PURPLE_TYPE_BOOLEAN) { gboolean boolean_data = GPOINTER_TO_INT(l->data); l = l->next; - if (boolean_data == value->data.boolean_data) + if (boolean_data == purple_value_get_boolean(value)) continue; - purple_status_set_attr_boolean(status, id, boolean_data); + status_set_attr_boolean(status, id, boolean_data); changed = TRUE; } else @@ -828,7 +852,7 @@ if (!g_list_find_custom(specified_attr_ids, attr->id, (GCompareFunc)strcmp)) { PurpleValue *default_value; default_value = purple_status_attr_get_value(attr); - if (default_value->type == PURPLE_TYPE_STRING) { + if (purple_value_get_type(default_value) == PURPLE_TYPE_STRING) { const char *cur = purple_status_get_attr_string(status, attr->id); const char *def = purple_value_get_string(default_value); if ((cur == NULL && def == NULL) @@ -837,21 +861,21 @@ continue; } - purple_status_set_attr_string(status, attr->id, def); - } else if (default_value->type == PURPLE_TYPE_INT) { + status_set_attr_string(status, attr->id, def); + } else if (purple_value_get_type(default_value) == PURPLE_TYPE_INT) { int cur = purple_status_get_attr_int(status, attr->id); int def = purple_value_get_int(default_value); if (cur == def) continue; - purple_status_set_attr_int(status, attr->id, def); - } else if (default_value->type == PURPLE_TYPE_BOOLEAN) { + status_set_attr_int(status, attr->id, def); + } else if (purple_value_get_type(default_value) == PURPLE_TYPE_BOOLEAN) { gboolean cur = purple_status_get_attr_boolean(status, attr->id); gboolean def = purple_value_get_boolean(default_value); if (cur == def) continue; - purple_status_set_attr_boolean(status, attr->id, def); + status_set_attr_boolean(status, attr->id, def); } changed = TRUE; } @@ -863,68 +887,6 @@ status_has_changed(status); } -void -purple_status_set_attr_boolean(PurpleStatus *status, const char *id, - gboolean value) -{ - PurpleValue *attr_value; - - g_return_if_fail(status != NULL); - g_return_if_fail(id != NULL); - - /* Make sure this attribute exists and is the correct type. */ - attr_value = purple_status_get_attr_value(status, id); - g_return_if_fail(attr_value != NULL); - g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_BOOLEAN); - - purple_value_set_boolean(attr_value, value); -} - -void -purple_status_set_attr_int(PurpleStatus *status, const char *id, int value) -{ - PurpleValue *attr_value; - - g_return_if_fail(status != NULL); - g_return_if_fail(id != NULL); - - /* Make sure this attribute exists and is the correct type. */ - attr_value = purple_status_get_attr_value(status, id); - g_return_if_fail(attr_value != NULL); - g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_INT); - - purple_value_set_int(attr_value, value); -} - -void -purple_status_set_attr_string(PurpleStatus *status, const char *id, - const char *value) -{ - PurpleValue *attr_value; - - g_return_if_fail(status != NULL); - g_return_if_fail(id != NULL); - - /* Make sure this attribute exists and is the correct type. */ - attr_value = purple_status_get_attr_value(status, id); - /* This used to be g_return_if_fail, but it's failing a LOT, so - * let's generate a log error for now. */ - /* g_return_if_fail(attr_value != NULL); */ - if (attr_value == NULL) { - purple_debug_error("status", - "Attempted to set status attribute '%s' for " - "status '%s', which is not legal. Fix " - "this!\n", id, - purple_status_type_get_name(purple_status_get_type(status))); - return; - } - g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_STRING); - - /* XXX: Check if the value has actually changed. If it has, and the status - * is active, should this trigger 'status_has_changed'? */ - purple_value_set_string(attr_value, value); -} - PurpleStatusType * purple_status_get_type(const PurpleStatus *status) { @@ -1137,7 +1099,7 @@ presence = purple_presence_new(PURPLE_PRESENCE_CONTEXT_CONV); presence->u.chat.conv = conv; - /* presence->statuses = purple_prpl_get_statuses(conv->account, presence); ? */ + /* presence->statuses = purple_prpl_get_statuses(purple_conversation_get_account(conv), presence); ? */ return presence; } @@ -1186,30 +1148,6 @@ } void -purple_presence_add_status(PurplePresence *presence, PurpleStatus *status) -{ - g_return_if_fail(presence != NULL); - g_return_if_fail(status != NULL); - - presence->statuses = g_list_append(presence->statuses, status); - - g_hash_table_insert(presence->status_table, - g_strdup(purple_status_get_id(status)), status); -} - -void -purple_presence_add_list(PurplePresence *presence, GList *source_list) -{ - GList *l; - - g_return_if_fail(presence != NULL); - g_return_if_fail(source_list != NULL); - - for (l = source_list; l != NULL; l = l->next) - purple_presence_add_status(presence, (PurpleStatus *)l->data); -} - -void purple_presence_set_status_active(PurplePresence *presence, const char *status_id, gboolean active) { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/status.h --- a/libpurple/status.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/status.h Fri Apr 06 04:30:00 2012 +0000 @@ -148,9 +148,7 @@ #define PURPLE_MOOD_NAME "mood" #define PURPLE_MOOD_COMMENT "moodtext" -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name PurpleStatusPrimitive API */ @@ -271,73 +269,6 @@ */ void purple_status_type_destroy(PurpleStatusType *status_type); -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_) -/** - * Sets a status type's primary attribute. - * - * The value for the primary attribute is used as the description for - * the particular status type. An example is an away message. The message - * would be the primary attribute. - * - * @param status_type The status type. - * @param attr_id The ID of the primary attribute. - * - * @deprecated This function isn't used and should be removed in 3.0.0. - */ -void purple_status_type_set_primary_attr(PurpleStatusType *status_type, - const char *attr_id); -#endif - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_) -/** - * Adds an attribute to a status type. - * - * @param status_type The status type to add the attribute to. - * @param id The ID of the attribute. - * @param name The name presented to the user. - * @param value The value type of this attribute. - * - * @deprecated This function isn't needed and should be removed in 3.0.0. - * Status type attributes should be set when the status type - * is created, in the call to purple_status_type_new_with_attrs. - */ -void purple_status_type_add_attr(PurpleStatusType *status_type, const char *id, - const char *name, PurpleValue *value); -#endif - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_) -/** - * Adds multiple attributes to a status type. - * - * @param status_type The status type to add the attribute to. - * @param id The ID of the first attribute. - * @param name The description of the first attribute. - * @param value The value type of the first attribute attribute. - * @param ... Additional attribute information. - * - * @deprecated This function isn't needed and should be removed in 3.0.0. - * Status type attributes should be set when the status type - * is created, in the call to purple_status_type_new_with_attrs. - */ -void purple_status_type_add_attrs(PurpleStatusType *status_type, const char *id, - const char *name, PurpleValue *value, ...) G_GNUC_NULL_TERMINATED; -#endif - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_) -/** - * Adds multiple attributes to a status type using a va_list. - * - * @param status_type The status type to add the attribute to. - * @param args The va_list of attributes. - * - * @deprecated This function isn't needed and should be removed in 3.0.0. - * Status type attributes should be set when the status type - * is created, in the call to purple_status_type_new_with_attrs. - */ -void purple_status_type_add_attrs_vargs(PurpleStatusType *status_type, - va_list args); -#endif - /** * Returns the primitive type of a status type. * @@ -419,19 +350,6 @@ */ gboolean purple_status_type_is_available(const PurpleStatusType *status_type); -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_) -/** - * Returns a status type's primary attribute ID. - * - * @param type The status type. - * - * @return The primary attribute's ID. - * - * @deprecated This function isn't used and should be removed in 3.0.0. - */ -const char *purple_status_type_get_primary_attr(const PurpleStatusType *type); -#endif - /** * Returns the attribute with the specified ID. * @@ -582,51 +500,6 @@ void purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean active, GList *attrs); -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_) -/** - * Sets the boolean value of an attribute in a status with the specified ID. - * - * @param status The status. - * @param id The attribute ID. - * @param value The boolean value. - * - * @deprecated This function is only used by status.c and should be made - * static in 3.0.0. - */ -void purple_status_set_attr_boolean(PurpleStatus *status, const char *id, - gboolean value); -#endif - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_) -/** - * Sets the integer value of an attribute in a status with the specified ID. - * - * @param status The status. - * @param id The attribute ID. - * @param value The integer value. - * - * @deprecated This function is only used by status.c and should be made - * static in 3.0.0. - */ -void purple_status_set_attr_int(PurpleStatus *status, const char *id, - int value); -#endif - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_) -/** - * Sets the string value of an attribute in a status with the specified ID. - * - * @param status The status. - * @param id The attribute ID. - * @param value The string value. - * - * @deprecated This function is only used by status.c and should be made - * static in 3.0.0. - */ -void purple_status_set_attr_string(PurpleStatus *status, const char *id, - const char *value); -#endif - /** * Returns the status's type. * @@ -833,32 +706,6 @@ */ void purple_presence_destroy(PurplePresence *presence); -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_) -/** - * Adds a status to a presence. - * - * @param presence The presence. - * @param status The status to add. - * - * @deprecated This function is only used by purple_presence_add_list, - * and both should be removed in 3.0.0. - */ -void purple_presence_add_status(PurplePresence *presence, PurpleStatus *status); -#endif - -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_STATUS_C_) -/** - * Adds a list of statuses to the presence. - * - * @param presence The presence. - * @param source_list The source list of statuses to add, which is not - * modified or freed by this function. - * - * @deprecated This function isn't used and should be removed in 3.0.0. - */ -void purple_presence_add_list(PurplePresence *presence, GList *source_list); -#endif - /** * Sets the active state of a status in a presence. * @@ -1096,8 +943,7 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_STATUS_H_ */ + diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/stringref.h --- a/libpurple/stringref.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/stringref.h Fri Apr 06 04:30:00 2012 +0000 @@ -29,11 +29,9 @@ #ifndef _PURPLE_STRINGREF_H_ #define _PURPLE_STRINGREF_H_ -#ifdef __cplusplus -extern "C" { -#endif +typedef struct _PurpleStringref PurpleStringref; -typedef struct _PurpleStringref PurpleStringref; +G_BEGIN_DECLS /** * Creates an immutable reference-counted string object. The newly @@ -131,8 +129,6 @@ */ size_t purple_stringref_len(const PurpleStringref *stringref); -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_STRINGREF_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/stun.c --- a/libpurple/stun.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/stun.c Fri Apr 06 04:30:00 2012 +0000 @@ -338,7 +338,7 @@ return; } - if (!purple_network_listen_range(12108, 12208, SOCK_DGRAM, hbn_listen_cb, hosts)) { + if (!purple_network_listen_range(12108, 12208, AF_UNSPEC, SOCK_DGRAM, TRUE, hbn_listen_cb, hosts)) { while (hosts) { hosts = g_slist_delete_link(hosts, hosts); g_free(hosts->data); @@ -365,7 +365,7 @@ purple_debug_info("stun", "got %d SRV responses, server: %s, port: %d\n", results, servername, port); - purple_dnsquery_a_account(NULL, servername, port, hbn_cb, NULL); + purple_dnsquery_a(NULL, servername, port, hbn_cb, NULL); g_free(resp); } @@ -424,7 +424,7 @@ nattype.servername = g_strdup(servername); callbacks = g_slist_append(callbacks, cb); - purple_srv_resolve_account(NULL, "stun", "udp", servername, do_test1, + purple_srv_resolve(NULL, "stun", "udp", servername, do_test1, (gpointer) servername); return &nattype; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/stun.h --- a/libpurple/stun.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/stun.h Fri Apr 06 04:30:00 2012 +0000 @@ -26,10 +26,6 @@ #ifndef _PURPLE_STUN_H_ #define _PURPLE_STUN_H_ -#ifdef __cplusplus -extern "C" { -#endif - /**************************************************************************/ /** @name STUN API */ /**************************************************************************/ @@ -63,6 +59,8 @@ typedef void (*StunCallback) (PurpleStunNatDiscovery *); +G_BEGIN_DECLS + /** * Starts a NAT discovery. It returns a PurpleStunNatDiscovery if the discovery * is already done. Otherwise the callback is called when the discovery is over @@ -81,8 +79,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_STUN_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/tests/test_xmlnode.c --- a/libpurple/tests/test_xmlnode.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/tests/test_xmlnode.c Fri Apr 06 04:30:00 2012 +0000 @@ -21,6 +21,101 @@ } END_TEST +#define check_doc_structure(x) { \ + xmlnode *ping, *child1, *child2; \ + fail_if(x == NULL, "Failed to parse document"); \ + ping = xmlnode_get_child(x, "ping"); \ + fail_if(ping == NULL, "Failed to find 'ping' child"); \ + child1 = xmlnode_get_child(ping, "child1"); \ + fail_if(child1 == NULL, "Failed to find 'child1'"); \ + child2 = xmlnode_get_child(child1, "child2"); \ + fail_if(child2 == NULL, "Failed to find 'child2'"); \ + xmlnode_new_child(child2, "a"); \ + \ + assert_string_equal("jabber:client", xmlnode_get_namespace(x)); \ + /* NOTE: xmlnode_get_namespace() returns the namespace of the element, not the + * current default namespace. See http://www.w3.org/TR/xml-names/#defaulting and + * http://www.w3.org/TR/xml-names/#dt-defaultNS. + */ \ + assert_string_equal("urn:xmpp:ping", xmlnode_get_namespace(ping)); \ + assert_string_equal("jabber:client", xmlnode_get_namespace(child1)); \ + assert_string_equal("urn:xmpp:ping", xmlnode_get_namespace(child2)); \ + /* + * This fails (well, actually crashes [the ns is NULL]) unless + * xmlnode_new_child() actually sets the element namespace. + assert_string_equal("jabber:client", xmlnode_get_namespace(xmlnode_get_child(child2, "a"))); + */ \ + \ + assert_string_equal("jabber:client", xmlnode_get_default_namespace(x)); \ + assert_string_equal("jabber:client", xmlnode_get_default_namespace(ping)); \ + assert_string_equal("jabber:client", xmlnode_get_default_namespace(child1)); \ + assert_string_equal("jabber:client", xmlnode_get_default_namespace(child2)); \ +} + +START_TEST(test_xmlnode_prefixes) +{ + const char *xml_doc = + "" + "" + "" + "" /* xmlns='jabber:child' */ + "" + "" + ""; + char *str; + xmlnode *xml, *reparsed; + + xml = xmlnode_from_str(xml_doc, -1); + check_doc_structure(xml); + + /* Check that xmlnode_from_str(xmlnode_to_str(xml, NULL), -1) is idempotent. */ + str = xmlnode_to_str(xml, NULL); + fail_if(str == NULL, "Failed to serialize XMLnode"); + reparsed = xmlnode_from_str(str, -1); + fail_if(reparsed == NULL, "Failed to reparse xml document"); + check_doc_structure(reparsed); + + g_free(str); + xmlnode_free(xml); + xmlnode_free(reparsed); +} +END_TEST + + +START_TEST(test_strip_prefixes) +{ + const char *xml_doc = "" + "" + "xvlc xvlc" + "" + "" + "xvlc xvlc" + "" + "" + ""; + const char *out = "" + "" + "xvlc xvlc" + "" + "" + "

xvlc xvlc

" + "" + "" + "
"; + char *str; + xmlnode *xml; + + xml = xmlnode_from_str(xml_doc, -1); + fail_if(xml == NULL, "Failed to parse XML"); + + xmlnode_strip_prefixes(xml); + str = xmlnode_to_str(xml, NULL); + assert_string_equal_free(out, str); + + xmlnode_free(xml); +} +END_TEST + Suite * xmlnode_suite(void) { @@ -28,6 +123,9 @@ TCase *tc = tcase_create("xmlnode"); tcase_add_test(tc, test_xmlnode_billion_laughs_attack); + tcase_add_test(tc, test_xmlnode_prefixes); + tcase_add_test(tc, test_strip_prefixes); + suite_add_tcase(s, tc); return s; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/theme-loader.c --- a/libpurple/theme-loader.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/theme-loader.c Fri Apr 06 04:30:00 2012 +0000 @@ -24,7 +24,7 @@ #include "theme-loader.h" #define PURPLE_THEME_LOADER_GET_PRIVATE(PurpleThemeLoader) \ - ((PurpleThemeLoaderPrivate *) ((PurpleThemeLoader)->priv)) + (G_TYPE_INSTANCE_GET_PRIVATE((PurpleThemeLoader), PURPLE_TYPE_THEME_LOADER, PurpleThemeLoaderPrivate)) void purple_theme_loader_set_type_string(PurpleThemeLoader *loader, const gchar *type); @@ -85,12 +85,19 @@ } } -static void -purple_theme_loader_init(GTypeInstance *instance, - gpointer klass) +static gboolean +purple_theme_loader_probe_directory(PurpleThemeLoader *loader, const gchar *dir) { - PurpleThemeLoader *loader = PURPLE_THEME_LOADER(instance); - loader->priv = g_new0(PurpleThemeLoaderPrivate, 1); + const gchar *type = purple_theme_loader_get_type_string(loader); + char *themedir; + gboolean result; + + /* Checks for directory as $root/purple/$type */ + themedir = g_build_filename(dir, "purple", type, NULL); + result = g_file_test(themedir, G_FILE_TEST_IS_DIR); + g_free(themedir); + + return result; } static void @@ -100,7 +107,6 @@ PurpleThemeLoaderPrivate *priv = PURPLE_THEME_LOADER_GET_PRIVATE(loader); g_free(priv->type); - g_free(priv); parent_class->finalize(obj); } @@ -113,6 +119,8 @@ parent_class = g_type_class_peek_parent(klass); + g_type_class_add_private(klass, sizeof(PurpleThemeLoaderPrivate)); + obj_class->get_property = purple_theme_loader_get_property; obj_class->set_property = purple_theme_loader_set_property; obj_class->finalize = purple_theme_loader_finalize; @@ -139,7 +147,7 @@ NULL, /* class_data */ sizeof(PurpleThemeLoader), 0, /* n_preallocs */ - purple_theme_loader_init, /* instance_init */ + NULL, /* instance_init */ NULL, /* value table */ }; type = g_type_register_static(G_TYPE_OBJECT, @@ -182,3 +190,13 @@ { return PURPLE_THEME_LOADER_GET_CLASS(loader)->purple_theme_loader_build(dir); } + +gboolean +purple_theme_loader_probe(PurpleThemeLoader *loader, const gchar *dir) +{ + if (PURPLE_THEME_LOADER_GET_CLASS(loader)->probe_directory != NULL) + return PURPLE_THEME_LOADER_GET_CLASS(loader)->probe_directory(dir); + else + return purple_theme_loader_probe_directory(loader, dir); +} + diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/theme-loader.h --- a/libpurple/theme-loader.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/theme-loader.h Fri Apr 06 04:30:00 2012 +0000 @@ -50,13 +50,13 @@ struct _PurpleThemeLoader { GObject parent; - gpointer priv; }; struct _PurpleThemeLoaderClass { GObjectClass parent_class; PurpleTheme *((*purple_theme_loader_build)(const gchar*)); + gboolean (*probe_directory)(const gchar *); }; /**************************************************************************/ @@ -89,5 +89,19 @@ */ PurpleTheme *purple_theme_loader_build(PurpleThemeLoader *loader, const gchar *dir); +/** + * Probes a directory to see if it might possibly contain a theme + * + * This function might only check for obvious files or directory structure. + * Loading of a theme may fail for other reasons. + * The default prober checks for $dir/purple/$type. + * + * @param loader The theme loader + * @param dir The directory that may contain the theme + * + * @returns TRUE if the directory appears to contain a theme, FALSE otherwise. + */ +gboolean purple_theme_loader_probe(PurpleThemeLoader *loader, const gchar *dir); + G_END_DECLS #endif /* PURPLE_THEME_LOADER_H */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/theme-manager.c --- a/libpurple/theme-manager.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/theme-manager.c Fri Apr 06 04:30:00 2012 +0000 @@ -80,11 +80,14 @@ } static gboolean -purple_theme_manager_is_theme(gchar *key, - gpointer value, - gchar *user_data) +check_if_theme_or_loader(gchar *key, gpointer value, GSList **loaders) { - return PURPLE_IS_THEME(value); + if (PURPLE_IS_THEME(value)) + return TRUE; + else if (PURPLE_IS_THEME_LOADER(value)) + *loaders = g_slist_prepend(*loaders, value); + + return FALSE; } static void @@ -97,11 +100,12 @@ } static void -purple_theme_manager_build_dir(const gchar *root) +purple_theme_manager_build_dir(GSList *loaders, const gchar *root) { - gchar *purple_dir, *theme_dir; - const gchar *name = NULL, *type = NULL; - GDir *rdir, *tdir; + gchar *theme_dir; + const gchar *name; + GDir *rdir; + GSList *tmp; PurpleThemeLoader *loader; rdir = g_dir_open(root, 0, NULL); @@ -109,33 +113,20 @@ if (!rdir) return; - /* Parses directory by root/name/purple/type */ while ((name = g_dir_read_name(rdir))) { - purple_dir = g_build_filename(root, name, "purple", NULL); - tdir = g_dir_open(purple_dir, 0, NULL); - - if (!tdir) { - g_free(purple_dir); + theme_dir = g_build_filename(root, name, NULL); - continue; - } + for (tmp = loaders; tmp; tmp = g_slist_next(tmp)) { + loader = PURPLE_THEME_LOADER(tmp->data); - while ((type = g_dir_read_name(tdir))) { - if ((loader = g_hash_table_lookup(theme_table, type))) { - PurpleTheme *theme = NULL; - - theme_dir = g_build_filename(purple_dir, type, NULL); - - theme = purple_theme_loader_build(loader, theme_dir); - g_free(theme_dir); - + if (purple_theme_loader_probe(loader, theme_dir)) { + PurpleTheme *theme = purple_theme_loader_build(loader, theme_dir); if (PURPLE_IS_THEME(theme)) purple_theme_manager_add_theme(theme); } } - g_dir_close(tdir); - g_free(purple_dir); + g_free(theme_dir); } g_dir_close(rdir); @@ -155,16 +146,17 @@ void purple_theme_manager_refresh(void) { - gchar *path = NULL; - const gchar *xdg = NULL; - gint i = 0; + gchar *path; + const gchar *xdg; + gint i; + GSList *loaders = NULL; - g_hash_table_foreach_remove(theme_table, - (GHRFunc) purple_theme_manager_is_theme, NULL); + g_hash_table_foreach_remove(theme_table, (GHRFunc)check_if_theme_or_loader, + &loaders); /* Add themes from ~/.purple */ path = g_build_filename(purple_user_dir(), "themes", NULL); - purple_theme_manager_build_dir(path); + purple_theme_manager_build_dir(loaders, path); g_free(path); /* look for XDG_DATA_HOME. If we don't have it use ~/.local, and add it */ @@ -173,7 +165,7 @@ else path = g_build_filename(purple_home_dir(), ".local", "themes", NULL); - purple_theme_manager_build_dir(path); + purple_theme_manager_build_dir(loaders, path); g_free(path); /* now dig through XDG_DATA_DIRS and add those too */ @@ -183,12 +175,14 @@ for (i = 0; xdg_dirs[i]; i++) { path = g_build_filename(xdg_dirs[i], "themes", NULL); - purple_theme_manager_build_dir(path); + purple_theme_manager_build_dir(loaders, path); g_free(path); } g_strfreev(xdg_dirs); } + + g_slist_free(loaders); } void diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/theme.c --- a/libpurple/theme.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/theme.c Fri Apr 06 04:30:00 2012 +0000 @@ -25,7 +25,7 @@ #include "util.h" #define PURPLE_THEME_GET_PRIVATE(PurpleTheme) \ - ((PurpleThemePrivate *) ((PurpleTheme)->priv)) + (G_TYPE_INSTANCE_GET_PRIVATE((PurpleTheme), PURPLE_TYPE_THEME, PurpleThemePrivate)) void purple_theme_set_type_string(PurpleTheme *theme, const gchar *type); @@ -129,14 +129,6 @@ } static void -purple_theme_init(GTypeInstance *instance, - gpointer klass) -{ - PurpleTheme *theme = PURPLE_THEME(instance); - theme->priv = g_new0(PurpleThemePrivate, 1); -} - -static void purple_theme_finalize(GObject *obj) { PurpleTheme *theme = PURPLE_THEME(obj); @@ -160,6 +152,8 @@ parent_class = g_type_class_peek_parent(klass); + g_type_class_add_private(klass, sizeof(PurpleThemePrivate)); + obj_class->get_property = purple_theme_get_property; obj_class->set_property = purple_theme_set_property; obj_class->finalize = purple_theme_finalize; @@ -222,7 +216,7 @@ NULL, /* class_data */ sizeof(PurpleTheme), 0, /* n_preallocs */ - purple_theme_init, /* instance_init */ + NULL, /* instance_init */ NULL, /* value table */ }; type = g_type_register_static (G_TYPE_OBJECT, diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/theme.h --- a/libpurple/theme.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/theme.h Fri Apr 06 04:30:00 2012 +0000 @@ -49,7 +49,6 @@ struct _PurpleTheme { GObject parent; - gpointer priv; }; struct _PurpleThemeClass diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/upnp.c --- a/libpurple/upnp.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/upnp.c Fri Apr 06 04:30:00 2012 +0000 @@ -464,7 +464,7 @@ purple_timeout_remove(dd->tima); dd->tima = 0; - purple_util_fetch_url_request_len(descriptionURL, TRUE, NULL, TRUE, httpRequest, + purple_util_fetch_url_request(NULL, descriptionURL, TRUE, NULL, TRUE, httpRequest, TRUE, MAX_UPNP_DOWNLOAD, upnp_parse_description_cb, dd); g_free(httpRequest); @@ -730,7 +730,7 @@ g_free(pathOfControl); g_free(soapMessage); - gfud = purple_util_fetch_url_request_len(control_info.control_url, FALSE, NULL, TRUE, + gfud = purple_util_fetch_url_request(NULL, control_info.control_url, FALSE, NULL, TRUE, totalSendMessage, TRUE, MAX_UPNP_DOWNLOAD, cb, cb_data); g_free(totalSendMessage); @@ -744,7 +744,7 @@ { if (control_info.status == PURPLE_UPNP_STATUS_DISCOVERED && control_info.publicip - && strlen(control_info.publicip) > 0) + && *control_info.publicip) return control_info.publicip; /* Trigger another UPnP discovery if 5 minutes have elapsed since the @@ -803,7 +803,7 @@ { if (control_info.status == PURPLE_UPNP_STATUS_DISCOVERED && control_info.internalip - && strlen(control_info.internalip) > 0) + && *control_info.internalip) return control_info.internalip; /* Trigger another UPnP discovery if 5 minutes have elapsed since the diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/upnp.h --- a/libpurple/upnp.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/upnp.h Fri Apr 06 04:30:00 2012 +0000 @@ -29,9 +29,7 @@ typedef struct _UPnPMappingAddRemove UPnPMappingAddRemove; -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /**************************************************************************/ /** @name UPnP API */ @@ -125,8 +123,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_UPNP_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/util.c --- a/libpurple/util.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/util.c Fri Apr 06 04:30:00 2012 +0000 @@ -73,6 +73,14 @@ PurpleAccount *account; }; +struct _PurpleMenuAction +{ + char *label; + PurpleCallback callback; + gpointer data; + GList *children; +}; + static char *custom_user_dir = NULL; static char *user_dir = NULL; @@ -98,6 +106,62 @@ g_free(act); } +char * purple_menu_action_get_label(const PurpleMenuAction *act) +{ + g_return_val_if_fail(act != NULL, NULL); + + return act->label; +} + +PurpleCallback purple_menu_action_get_callback(const PurpleMenuAction *act) +{ + g_return_val_if_fail(act != NULL, NULL); + + return act->callback; +} + +gpointer purple_menu_action_get_data(const PurpleMenuAction *act) +{ + g_return_val_if_fail(act != NULL, NULL); + + return act->data; +} + +GList* purple_menu_action_get_children(const PurpleMenuAction *act) +{ + g_return_val_if_fail(act != NULL, NULL); + + return act->children; +} + +void purple_menu_action_set_label(PurpleMenuAction *act, char *label) +{ + g_return_if_fail(act != NULL); + + act-> label = label; +} + +void purple_menu_action_set_callback(PurpleMenuAction *act, PurpleCallback callback) +{ + g_return_if_fail(act != NULL); + + act->callback = callback; +} + +void purple_menu_action_set_data(PurpleMenuAction *act, gpointer data) +{ + g_return_if_fail(act != NULL); + + act->data = data; +} + +void purple_menu_action_set_children(PurpleMenuAction *act, GList *children) +{ + g_return_if_fail(act != NULL); + + act->children = children; +} + void purple_util_init(void) { @@ -147,7 +211,7 @@ len = strlen(str); - g_return_val_if_fail(strlen(str) > 0, 0); + g_return_val_if_fail(*str, 0); g_return_val_if_fail(len % 2 == 0, 0); data = g_malloc(len / 2); @@ -612,7 +676,7 @@ } else { - purple_strlcpy(buf, utf8); + g_strlcpy(buf, utf8, sizeof(buf)); g_free(utf8); } @@ -1321,7 +1385,7 @@ g_string_append_len(dest, p, q - p); } - purple_notify_user_info_add_pair(user_info, display_name, dest->str); + purple_notify_user_info_add_pair_html(user_info, display_name, dest->str); g_string_free(dest, TRUE); return TRUE; @@ -2267,7 +2331,7 @@ url_buf = g_string_free(gurl_buf, FALSE); /* strip off trailing periods */ - if (strlen(url_buf) > 0) { + if (*url_buf) { for (d = url_buf + strlen(url_buf) - 1; *d == '.'; d--, t--) *d = '\0'; } @@ -3267,9 +3331,9 @@ } char * -purple_str_size_to_units(size_t size) +purple_str_size_to_units(goffset size) { - static const char * const size_str[] = { "bytes", "KiB", "MiB", "GiB" }; + static const char * const size_str[] = { "bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB" }; float size_mag; int size_index = 0; @@ -3282,7 +3346,7 @@ else { size_mag = (float)size; - while ((size_index < 3) && (size_mag > 1024)) { + while ((size_index < G_N_ELEMENTS(size_str) - 1) && (size_mag > 1024)) { size_mag /= 1024; size_index++; } @@ -4103,30 +4167,7 @@ } PurpleUtilFetchUrlData * -purple_util_fetch_url_request(const char *url, gboolean full, - const char *user_agent, gboolean http11, - const char *request, gboolean include_headers, - PurpleUtilFetchUrlCallback callback, void *user_data) -{ - return purple_util_fetch_url_request_len_with_account(NULL, url, full, - user_agent, http11, - request, include_headers, -1, - callback, user_data); -} - -PurpleUtilFetchUrlData * -purple_util_fetch_url_request_len(const char *url, gboolean full, - const char *user_agent, gboolean http11, - const char *request, gboolean include_headers, gssize max_len, - PurpleUtilFetchUrlCallback callback, void *user_data) -{ - return purple_util_fetch_url_request_len_with_account(NULL, url, full, - user_agent, http11, request, include_headers, max_len, callback, - user_data); -} - -PurpleUtilFetchUrlData * -purple_util_fetch_url_request_len_with_account(PurpleAccount *account, +purple_util_fetch_url_request(PurpleAccount *account, const char *url, gboolean full, const char *user_agent, gboolean http11, const char *request, gboolean include_headers, gssize max_len, PurpleUtilFetchUrlCallback callback, void *user_data) @@ -4413,11 +4454,10 @@ return (double_colon && chunks < 8) || (!double_colon && chunks == 8); } -/* TODO 3.0.0: Add ipv6 check, too */ gboolean purple_ip_address_is_valid(const char *ip) { - return purple_ipv4_address_is_valid(ip); + return (purple_ipv4_address_is_valid(ip) || purple_ipv6_address_is_valid(ip)); } /* Stolen from gnome_uri_list_extract_uris */ @@ -4597,7 +4637,7 @@ * This function is copied from g_strerror() but changed to use * gai_strerror(). */ -G_CONST_RETURN gchar * +const gchar * purple_gai_strerror(gint errnum) { static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT; @@ -4943,18 +4983,6 @@ return buf; } -const char *_purple_oscar_convert(const char *act, const char *protocol) -{ - if (act && purple_strequal(protocol, "prpl-oscar")) { - int i; - for (i = 0; act[i] != '\0'; i++) - if (!isdigit(act[i])) - return "prpl-aim"; - return "prpl-icq"; - } - return protocol; -} - void purple_restore_default_signal_handlers(void) { #ifndef _WIN32 diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/util.h --- a/libpurple/util.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/util.h Fri Apr 06 04:30:00 2012 +0000 @@ -36,9 +36,20 @@ * the request. */ typedef struct _PurpleUtilFetchUrlData PurpleUtilFetchUrlData; -/** @copydoc _PurpleMenuAction */ + +/** + * A generic structure that contains information about an "action." One + * place this is is used is by PRPLs to tell the core the list of available + * right-click actions for a buddy list row. + */ typedef struct _PurpleMenuAction PurpleMenuAction; -/** @copydoc _PurpleKeyValuePair */ + +/** + * A key-value pair. + * + * This is used by, among other things, purple_gtk_combo* functions to pass in a + * list of key-value pairs so it can display a user-friendly value. + */ typedef struct _PurpleKeyValuePair PurpleKeyValuePair; #include "account.h" @@ -47,26 +58,8 @@ #include "notify.h" -#ifdef __cplusplus -extern "C" { -#endif - -struct _PurpleMenuAction -{ - char *label; - PurpleCallback callback; - gpointer data; - GList *children; -}; - typedef char *(*PurpleInfoFieldFormatCallback)(const char *field, size_t len); -/** - * A key-value pair. - * - * This is used by, among other things, purple_gtk_combo* functions to pass in a - * list of key-value pairs so it can display a user-friendly value. - */ struct _PurpleKeyValuePair { gchar *key; @@ -74,6 +67,8 @@ }; +G_BEGIN_DECLS + /** * Creates a new PurpleMenuAction. * @@ -96,12 +91,79 @@ void purple_menu_action_free(PurpleMenuAction *act); /** + * Returns the label of the PurpleMenuAction. + * + * @param act The PurpleMenuAction. + * + * @return The label string. + */ +char * purple_menu_action_get_label(const PurpleMenuAction *act); + +/** + * Returns the callback of the PurpleMenuAction. + * + * @param act The PurpleMenuAction. + * + * @return The callback function. + */ +PurpleCallback purple_menu_action_get_callback(const PurpleMenuAction *act); + +/** + * Returns the data stored in the PurpleMenuAction. + * + * @param act The PurpleMenuAction. + * + * @return The data. + */ +gpointer purple_menu_action_get_data(const PurpleMenuAction *act); + +/** + * Returns the children of the PurpleMenuAction. + * + * @param act The PurpleMenuAction. + * + * @return The GList of children. + */ +GList* purple_menu_action_get_children(const PurpleMenuAction *act); + +/** + * Set the label to the PurpleMenuAction. + * + * @param act The menu action. + * @param label The label for the menu action. + */ +void purple_menu_action_set_label(PurpleMenuAction *act, char *label); + +/** + * Set the callback that will be used by the PurpleMenuAction. + * + * @param act The menu action. + * @param callback The callback. + */ +void purple_menu_action_set_callback(PurpleMenuAction *act, PurpleCallback callback); + +/** + * Set the label to the PurpleMenuAction. + * + * @param act The menu action. + * @param data The data used by this PurpleMenuAction + */ +void purple_menu_action_set_data(PurpleMenuAction *act, gpointer data); + +/** + * Set the children of the PurpleMenuAction. + * + * @param act The menu action. + * @param children The PurpleMenuAtion children + */ +void purple_menu_action_set_children(PurpleMenuAction *act, GList *children); + +/** * Set the appropriate presence values for the currently playing song. * * @param title The title of the song, @c NULL to unset the value. * @param artist The artist of the song, can be @c NULL. * @param album The album of the song, can be @c NULL. - * @since 2.4.0 */ void purple_util_set_current_song(const char *title, const char *artist, const char *album); @@ -115,7 +177,6 @@ * @param unused Currently unused, must be @c NULL. * * @return The formatted string. The caller must g_free the returned string. - * @since 2.4.0 */ char * purple_util_format_song_info(const char *title, const char *artist, const char *album, gpointer unused); @@ -127,15 +188,11 @@ /** * Initializes the utility subsystem. - * - * @since 2.3.0 */ void purple_util_init(void); /** * Uninitializes the util subsystem. - * - * @since 2.3.0 */ void purple_util_uninit(void); @@ -429,8 +486,6 @@ * This is exactly the same as g_markup_escape_text(), except that it * does not change ' to ' because ' is not a valid HTML 4 entity, * and is displayed literally in IE7. - * - * @since 2.6.0 */ gchar *purple_markup_escape_text(const gchar *text, gssize length); @@ -531,7 +586,6 @@ * this string when finished with it. * * @see purple_unescape_html() - * @since 2.7.0 */ char *purple_unescape_text(const char *text); @@ -624,8 +678,6 @@ * @param html The HTML text. * * @return TRUE if the text contains RTL text, FALSE otherwise. - * - * @since 2.6.0 */ gboolean purple_markup_is_rtl(const char *html); @@ -826,7 +878,6 @@ * * @return The address family of the socket (AF_INET, AF_INET6, etc) or -1 * on error. - * @since 2.7.0 */ int purple_socket_get_family(int fd); @@ -838,7 +889,6 @@ * * @param fd The socket file descriptor * @return TRUE if a socket can speak IPv4. - * @since 2.7.0 */ gboolean purple_socket_speaks_ipv4(int fd); @@ -860,8 +910,6 @@ * @param right A string to compare with left * * @return @c TRUE if the strings are the same, else @c FALSE. - * - * @since 2.6.0 */ gboolean purple_strequal(const gchar *left, const gchar *right); @@ -1041,7 +1089,7 @@ * * @return The string in units form. This must be freed. */ -char *purple_str_size_to_units(size_t size); +char *purple_str_size_to_units(goffset size); /** * Converts seconds into a human-readable form. @@ -1117,75 +1165,17 @@ * partial URL. * @param user_agent The user agent field to use, or NULL. * @param http11 TRUE if HTTP/1.1 should be used to download the file. - * @param cb The callback function. - * @param data The user data to pass to the callback function. - */ -#define purple_util_fetch_url(url, full, user_agent, http11, cb, data) \ - purple_util_fetch_url_request(url, full, user_agent, http11, NULL, \ - FALSE, cb, data); - -/** - * Fetches the data from a URL, and passes it to a callback function. - * - * @param url The URL. - * @param full TRUE if this is the full URL, or FALSE if it's a - * partial URL. - * @param user_agent The user agent field to use, or NULL. - * @param http11 TRUE if HTTP/1.1 should be used to download the file. * @param max_len The maximum number of bytes to retrieve (-1 for unlimited) * @param cb The callback function. * @param data The user data to pass to the callback function. - * @deprecated In 3.0.0, we'll rename this to "purple_util_fetch_url" and get rid of the old one */ -#define purple_util_fetch_url_len(url, full, user_agent, http11, max_len, cb, data) \ - purple_util_fetch_url_request_len(url, full, user_agent, http11, NULL, \ +#define purple_util_fetch_url(url, full, user_agent, http11, max_len, cb, data) \ + purple_util_fetch_url_request(NULL, url, full, user_agent, http11, NULL, \ FALSE, max_len, cb, data); /** * Fetches the data from a URL, and passes it to a callback function. * - * @param url The URL. - * @param full TRUE if this is the full URL, or FALSE if it's a - * partial URL. - * @param user_agent The user agent field to use, or NULL. - * @param http11 TRUE if HTTP/1.1 should be used to download the file. - * @param request A HTTP request to send to the server instead of the - * standard GET - * @param include_headers - * If TRUE, include the HTTP headers in the response. - * @param callback The callback function. - * @param data The user data to pass to the callback function. - */ -PurpleUtilFetchUrlData *purple_util_fetch_url_request(const gchar *url, - gboolean full, const gchar *user_agent, gboolean http11, - const gchar *request, gboolean include_headers, - PurpleUtilFetchUrlCallback callback, gpointer data); - -/** - * Fetches the data from a URL, and passes it to a callback function. - * - * @param url The URL. - * @param full TRUE if this is the full URL, or FALSE if it's a - * partial URL. - * @param user_agent The user agent field to use, or NULL. - * @param http11 TRUE if HTTP/1.1 should be used to download the file. - * @param request A HTTP request to send to the server instead of the - * standard GET - * @param include_headers - * If TRUE, include the HTTP headers in the response. - * @param max_len The maximum number of bytes to retrieve (-1 for unlimited) - * @param callback The callback function. - * @param data The user data to pass to the callback function. - * @deprecated In 3.0.0, this will go away. - */ -PurpleUtilFetchUrlData *purple_util_fetch_url_request_len(const gchar *url, - gboolean full, const gchar *user_agent, gboolean http11, - const gchar *request, gboolean include_headers, gssize max_len, - PurpleUtilFetchUrlCallback callback, gpointer data); - -/** - * Fetches the data from a URL, and passes it to a callback function. - * * @param account The account for which the request is needed, or NULL. * @param url The URL. * @param full TRUE if this is the full URL, or FALSE if it's a @@ -1199,9 +1189,8 @@ * @param max_len The maximum number of bytes to retrieve (-1 for unlimited) * @param callback The callback function. * @param data The user data to pass to the callback function. - * @deprecated In 3.0.0, we'll rename this to "purple_util_fetch_url_request" and get rid of the old one */ -PurpleUtilFetchUrlData *purple_util_fetch_url_request_len_with_account( +PurpleUtilFetchUrlData *purple_util_fetch_url_request( PurpleAccount *account, const gchar *url, gboolean full, const gchar *user_agent, gboolean http11, const gchar *request, gboolean include_headers, gssize max_len, @@ -1247,14 +1236,15 @@ gboolean purple_email_is_valid(const char *address); /** - * Checks if the given IP address is a syntactically valid IPv4 address. + * Checks if the given IP address is a syntactically valid IPv4 or + * IPv6 address. + * If you specifically want to check for an IPv4 address use + * purple_ipv4_address_is_valid(), or for an IPv6 address use + * purple_ipv6_address_is_valid(). * * @param ip The IP address to validate. * * @return True if the IP address is syntactically correct. - * @deprecated This function will be replaced with one that validates - * as either IPv4 or IPv6 in 3.0.0. If you don't want this, - * behavior, use one of the more specific functions. */ gboolean purple_ip_address_is_valid(const char *ip); @@ -1264,7 +1254,6 @@ * @param ip The IP address to validate. * * @return True if the IP address is syntactically correct. - * @since 2.6.0 */ gboolean purple_ipv4_address_is_valid(const char *ip); @@ -1274,7 +1263,6 @@ * @param ip The IP address to validate. * * @return True if the IP address is syntactically correct. - * @since 2.6.0 */ gboolean purple_ipv6_address_is_valid(const char *ip); @@ -1342,7 +1330,6 @@ * @param str A valid UTF-8 string. * * @return A newly allocated UTF-8 string without the unprintable characters. - * @since 2.6.0 */ gchar *purple_utf8_strip_unprintables(const gchar *str); @@ -1354,9 +1341,8 @@ * @param errnum The error code. * * @return The UTF-8 error message. - * @since 2.4.0 */ -G_CONST_RETURN gchar *purple_gai_strerror(gint errnum); +const gchar *purple_gai_strerror(gint errnum); /** * Compares two UTF-8 strings case-insensitively. This comparison is @@ -1450,16 +1436,6 @@ const char *purple_escape_filename(const char *str); /** - * This is added temporarily to assist the split of oscar into aim and icq. - * This should not be used by plugins. - * - * @deprecated This function should not be used in new code and should be - * removed in 3.0.0. The aim/icq prpl split happened a long - * time ago, and we don't need to keep migrating old data. - */ -const char *_purple_oscar_convert(const char *act, const char *protocol); - -/** * Restore default signal handlers for signals which might reasonably have * handlers. This should be called by a fork()'d child process, since child processes * inherit the handlers of the parent. @@ -1478,12 +1454,9 @@ * Returns a type 4 (random) UUID * * @return A UUID, caller is responsible for freeing it - * @since 2.7.0 */ gchar *purple_uuid_random(void); -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_UTIL_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/value.c --- a/libpurple/value.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/value.c Fri Apr 06 04:30:00 2012 +0000 @@ -29,6 +29,44 @@ #define OUTGOING_FLAG 0x01 +/** + * A wrapper for a type, subtype, and specific type of value. + */ +struct _PurpleValue +{ + PurpleType type; + unsigned short flags; + + union + { + char char_data; + unsigned char uchar_data; + gboolean boolean_data; + short short_data; + unsigned short ushort_data; + int int_data; + unsigned int uint_data; + long long_data; + unsigned long ulong_data; + gint64 int64_data; + guint64 uint64_data; + char *string_data; + void *object_data; + void *pointer_data; + int enum_data; + void *boxed_data; + + } data; + + union + { + unsigned int subtype; + char *specific_type; + + } u; + +}; + PurpleValue * purple_value_new(PurpleType type, ...) { diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/value.h --- a/libpurple/value.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/value.h Fri Apr 06 04:30:00 2012 +0000 @@ -86,44 +86,9 @@ /** * A wrapper for a type, subtype, and specific type of value. */ -typedef struct -{ - PurpleType type; - unsigned short flags; +typedef struct _PurpleValue PurpleValue; - union - { - char char_data; - unsigned char uchar_data; - gboolean boolean_data; - short short_data; - unsigned short ushort_data; - int int_data; - unsigned int uint_data; - long long_data; - unsigned long ulong_data; - gint64 int64_data; - guint64 uint64_data; - char *string_data; - void *object_data; - void *pointer_data; - int enum_data; - void *boxed_data; - - } data; - - union - { - unsigned int subtype; - char *specific_type; - - } u; - -} PurpleValue; - -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /** * Creates a new PurpleValue. @@ -497,8 +462,6 @@ */ void *purple_value_get_boxed(const PurpleValue *value); -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_VALUE_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/version.h.in --- a/libpurple/version.h.in Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/version.h.in Fri Apr 06 04:30:00 2012 +0000 @@ -56,8 +56,6 @@ * The major version of the running libpurple. Contrast with * #PURPLE_MAJOR_VERSION, which expands at compile time to the major version of * libpurple being compiled against. - * - * @since 2.4.0 */ extern const guint purple_major_version; @@ -65,8 +63,6 @@ * The minor version of the running libpurple. Contrast with * #PURPLE_MINOR_VERSION, which expands at compile time to the minor version of * libpurple being compiled against. - * - * @since 2.4.0 */ extern const guint purple_minor_version; @@ -75,8 +71,6 @@ * The micro version of the running libpurple. Contrast with * #PURPLE_MICRO_VERSION, which expands at compile time to the micro version of * libpurple being compiled against. - * - * @since 2.4.0 */ extern const guint purple_micro_version; diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/whiteboard.c --- a/libpurple/whiteboard.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/whiteboard.c Fri Apr 06 04:30:00 2012 +0000 @@ -25,6 +25,23 @@ #include "whiteboard.h" #include "prpl.h" +/** + * A PurpleWhiteboard + */ +struct _PurpleWhiteboard +{ + int state; /**< State of whiteboard session */ + + PurpleAccount *account; /**< Account associated with this session */ + char *who; /**< Name of the remote user */ + + void *ui_data; /**< Graphical user-interface data */ + void *proto_data; /**< Protocol specific data */ + PurpleWhiteboardPrplOps *prpl_ops; /**< Protocol-plugin operations */ + + GList *draw_list; /**< List of drawing elements/deltas to send */ +}; + /****************************************************************************** * Globals *****************************************************************************/ @@ -90,6 +107,34 @@ g_free(wb); } +PurpleAccount *purple_whiteboard_get_account(const PurpleWhiteboard *wb) +{ + g_return_val_if_fail(wb != NULL, NULL); + + return wb->account; +} + +const char *purple_whiteboard_get_who(const PurpleWhiteboard *wb) +{ + g_return_val_if_fail(wb != NULL, NULL); + + return wb->who; +} + +void purple_whiteboard_set_state(PurpleWhiteboard *wb, int state) +{ + g_return_if_fail(wb != NULL); + + wb->state = state; +} + +int purple_whiteboard_get_state(const PurpleWhiteboard *wb) +{ + g_return_val_if_fail(wb != NULL, -1); + + return wb->state; +} + void purple_whiteboard_start(PurpleWhiteboard *wb) { /* Create frontend for whiteboard */ @@ -206,3 +251,44 @@ whiteboard_ui_ops->set_brush(wb, size, color); } +GList *purple_whiteboard_get_draw_list(const PurpleWhiteboard *wb) +{ + g_return_val_if_fail(wb != NULL, NULL); + + return wb->draw_list; +} + +void purple_whiteboard_set_draw_list(PurpleWhiteboard *wb, GList* draw_list) +{ + g_return_if_fail(wb != NULL); + + wb->draw_list = draw_list; +} + +void purple_whiteboard_set_protocol_data(PurpleWhiteboard *wb, gpointer proto_data) +{ + g_return_if_fail(wb != NULL); + + wb->proto_data = proto_data; +} + +gpointer purple_whiteboard_get_protocol_data(const PurpleWhiteboard *wb) +{ + g_return_val_if_fail(wb != NULL, NULL); + + return wb->proto_data; +} + +void purple_whiteboard_set_ui_data(PurpleWhiteboard *wb, gpointer ui_data) +{ + g_return_if_fail(wb != NULL); + + wb->ui_data = ui_data; +} + +gpointer purple_whiteboard_get_ui_data(const PurpleWhiteboard *wb) +{ + g_return_val_if_fail(wb != NULL, NULL); + + return wb->ui_data; +} diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/whiteboard.h --- a/libpurple/whiteboard.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/whiteboard.h Fri Apr 06 04:30:00 2012 +0000 @@ -26,6 +26,9 @@ #ifndef _PURPLE_WHITEBOARD_H_ #define _PURPLE_WHITEBOARD_H_ +/** @copydoc _PurpleWhiteboard */ +typedef struct _PurpleWhiteboard PurpleWhiteboard; + /** * Whiteboard PRPL Operations */ @@ -33,22 +36,6 @@ #include "account.h" -/** - * A PurpleWhiteboard - */ -typedef struct _PurpleWhiteboard -{ - int state; /**< State of whiteboard session */ - - PurpleAccount *account; /**< Account associated with this session */ - char *who; /**< Name of the remote user */ - - void *ui_data; /**< Graphical user-interface data */ - void *proto_data; /**< Protocol specific data */ - PurpleWhiteboardPrplOps *prpl_ops; /**< Protocol-plugin operations */ - - GList *draw_list; /**< List of drawing elements/deltas to send */ -} PurpleWhiteboard; /** * The PurpleWhiteboard UI Operations @@ -92,9 +79,7 @@ void (*_purple_reserved4)(void); }; -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ +G_BEGIN_DECLS /******************************************************************************/ /** @name PurpleWhiteboard API */ @@ -135,6 +120,41 @@ void purple_whiteboard_destroy(PurpleWhiteboard *wb); /** + * Returns the whiteboard's account. + * + * @param wb The whiteboard. + * + * @return The whiteboard's account. + */ +PurpleAccount *purple_whiteboard_get_account(const PurpleWhiteboard *wb); + +/** + * Return who you're drawing with. + * + * @param wb The whiteboard + * + * @return Who you're drawing with. + */ +const char *purple_whiteboard_get_who(const PurpleWhiteboard *wb); + +/** + * Set the state of the whiteboard. + * + * @param wb The whiteboard. + * @param state The state + */ +void purple_whiteboard_set_state(PurpleWhiteboard *wb, int state); + +/** + * Return the state of the whiteboard. + * + * @param wb The whiteboard. + * + * @return The state of the whiteboard. + */ +int purple_whiteboard_get_state(const PurpleWhiteboard *wb); + +/** * Starts a whiteboard * * @param wb The whiteboard. @@ -253,10 +273,61 @@ */ void purple_whiteboard_set_brush(PurpleWhiteboard *wb, int size, int color); +/** + * Return the drawing list. + * + * @param wb The whiteboard. + * + * @return The drawing list + */ +GList *purple_whiteboard_get_draw_list(const PurpleWhiteboard *wb); + +/** + * Set the drawing list. + * + * @param wb The whiteboard + * @param draw_list The drawing list. + */ +void purple_whiteboard_set_draw_list(PurpleWhiteboard *wb, GList* draw_list); + +/** + * Sets the protocol data for a whiteboard. + * + * @param wb The whiteboard. + * @param proto_data The protocol data to set for the whiteboard. + */ +void purple_whiteboard_set_protocol_data(PurpleWhiteboard *wb, gpointer proto_data); + +/** + * Gets the protocol data for a whiteboard. + * + * @param wb The whiteboard. + * + * @return The protocol data for the whiteboard. + */ +gpointer purple_whiteboard_get_protocol_data(const PurpleWhiteboard *wb); + +/** + * Set the UI data associated with this whiteboard. + * + * @param wb The whiteboard. + * @param ui_data A pointer to associate with this whiteboard. + */ +void purple_whiteboard_set_ui_data(PurpleWhiteboard *wb, gpointer ui_data); + +/** + * Get the UI data associated with this whiteboard. + * + * @param wb The whiteboard.. + * + * @return The UI data associated with this whiteboard. This is a + * convenience field provided to the UIs--it is not + * used by the libpurple core. + */ +gpointer purple_whiteboard_get_ui_data(const PurpleWhiteboard *wb); + /*@}*/ -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS #endif /* _PURPLE_WHITEBOARD_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/win32/libc_interface.c --- a/libpurple/win32/libc_interface.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/win32/libc_interface.c Fri Apr 06 04:30:00 2012 +0000 @@ -511,12 +511,6 @@ return res; } -/* stdio.h */ - -int wpurple_rename (const char *oldname, const char *newname) { - return g_rename(oldname, newname); -} - /* time.h */ struct tm * wpurple_localtime_r (const time_t *time, struct tm *resultp) { @@ -1091,15 +1085,3 @@ purple_debug_warning("wpurple", "could not find a match for Windows timezone \"%s\"\n", tzname); return ""; } - -int wpurple_g_access (const gchar *filename, int mode); -/** - * @deprecated - remove for 3.0.0 - */ -int -wpurple_g_access (const gchar *filename, int mode) -{ - return g_access(filename, mode); -} - - diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/win32/libc_interface.h --- a/libpurple/win32/libc_interface.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/win32/libc_interface.h Fri Apr 06 04:30:00 2012 +0000 @@ -138,7 +138,7 @@ #define vsnprintf _vsnprintf #define rename( oldname, newname ) \ -wpurple_rename( oldname, newname ) +g_rename( oldname, newname ) /* sys/stat.h */ #define fchmod(a,b) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/win32/libc_internal.h --- a/libpurple/win32/libc_internal.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/win32/libc_internal.h Fri Apr 06 04:30:00 2012 +0000 @@ -142,9 +142,6 @@ int wpurple_gethostname(char *name, size_t size); -/* stdio.h */ -int wpurple_rename(const char *oldname, const char *newname); - #ifdef __cplusplus } #endif /* __cplusplus */ diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/xmlnode.c --- a/libpurple/xmlnode.c Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/xmlnode.c Fri Apr 06 04:30:00 2012 +0000 @@ -78,6 +78,19 @@ node = new_node(name, XMLNODE_TYPE_TAG); xmlnode_insert_child(parent, node); +#if 0 + /* This would give xmlnodes more appropriate namespacing + * when creating them. Otherwise, unless an explicit namespace + * is set, xmlnode_get_namespace() will return NULL, when + * there may be a default namespace. + * + * I'm unconvinced that it's useful, and concerned it may break things. + * + * _insert_child would need the same thing, probably (assuming + * xmlns->node == NULL) + */ + xmlnode_set_namespace(node, xmlnode_get_default_namespace(node)) +#endif return node; } @@ -191,18 +204,6 @@ } void -xmlnode_set_attrib_with_namespace(xmlnode *node, const char *attr, const char *xmlns, const char *value) -{ - xmlnode_set_attrib_full(node, attr, xmlns, NULL, value); -} - -void -xmlnode_set_attrib_with_prefix(xmlnode *node, const char *attr, const char *prefix, const char *value) -{ - xmlnode_set_attrib_full(node, attr, NULL, prefix, value); -} - -void xmlnode_set_attrib_full(xmlnode *node, const char *attr, const char *xmlns, const char *prefix, const char *value) { xmlnode *attrib_node; @@ -261,19 +262,53 @@ void xmlnode_set_namespace(xmlnode *node, const char *xmlns) { + char *tmp; g_return_if_fail(node != NULL); - g_free(node->xmlns); + tmp = node->xmlns; node->xmlns = g_strdup(xmlns); + + if (node->namespace_map) { + g_hash_table_insert(node->namespace_map, + g_strdup(""), g_strdup(xmlns)); + } + + g_free(tmp); } -const char *xmlnode_get_namespace(xmlnode *node) +const char *xmlnode_get_namespace(const xmlnode *node) { g_return_val_if_fail(node != NULL, NULL); return node->xmlns; } +const char *xmlnode_get_default_namespace(const xmlnode *node) +{ + const xmlnode *current_node; + const char *ns = NULL; + + g_return_val_if_fail(node != NULL, NULL); + + current_node = node; + while (current_node) { + /* If this node does *not* have a prefix, node->xmlns is the default + * namespace. Otherwise, it's the prefix namespace. + */ + if (!current_node->prefix && current_node->xmlns) { + return current_node->xmlns; + } else if (current_node->namespace_map) { + ns = g_hash_table_lookup(current_node->namespace_map, ""); + if (ns && *ns) + return ns; + } + + current_node = current_node->parent; + } + + return ns; +} + void xmlnode_set_prefix(xmlnode *node, const char *prefix) { g_return_if_fail(node != NULL); @@ -288,6 +323,53 @@ return node->prefix; } +const char *xmlnode_get_prefix_namespace(const xmlnode *node, const char *prefix) +{ + const xmlnode *current_node; + + g_return_val_if_fail(node != NULL, NULL); + g_return_val_if_fail(prefix != NULL, xmlnode_get_default_namespace(node)); + + current_node = node; + while (current_node) { + if (current_node->prefix && g_str_equal(prefix, current_node->prefix) && + current_node->xmlns) { + return current_node->xmlns; + } else if (current_node->namespace_map) { + const char *ns = g_hash_table_lookup(current_node->namespace_map, prefix); + if (ns && *ns) { + return ns; + } + } + + current_node = current_node->parent; + } + + return NULL; +} + +void xmlnode_strip_prefixes(xmlnode *node) +{ + xmlnode *child; + const char *prefix; + + g_return_if_fail(node != NULL); + + for (child = node->child; child; child = child->next) { + if (child->type == XMLNODE_TYPE_TAG) + xmlnode_strip_prefixes(child); + } + + prefix = xmlnode_get_prefix(node); + if (prefix) { + const char *ns = xmlnode_get_prefix_namespace(node, prefix); + xmlnode_set_namespace(node, ns); + xmlnode_set_prefix(node, NULL); + } else { + xmlnode_set_namespace(node, xmlnode_get_default_namespace(node)); + } +} + xmlnode *xmlnode_get_parent(const xmlnode *child) { g_return_val_if_fail(child != NULL, NULL); @@ -455,12 +537,22 @@ if (node->namespace_map) { g_hash_table_foreach(node->namespace_map, (GHFunc)xmlnode_to_str_foreach_append_ns, text); - } else if (node->xmlns) { - if(!node->parent || !purple_strequal(node->xmlns, node->parent->xmlns)) + } else { + /* Figure out if this node has a different default namespace from parent */ + const char *xmlns = NULL; + const char *parent_xmlns = NULL; + if (!prefix) + xmlns = node->xmlns; + + if (!xmlns) + xmlns = xmlnode_get_default_namespace(node); + if (node->parent) + parent_xmlns = xmlnode_get_default_namespace(node->parent); + if (!purple_strequal(xmlns, parent_xmlns)) { - char *xmlns = g_markup_escape_text(node->xmlns, -1); - g_string_append_printf(text, " xmlns='%s'", xmlns); - g_free(xmlns); + char *escaped_xmlns = g_markup_escape_text(xmlns, -1); + g_string_append_printf(text, " xmlns='%s'", escaped_xmlns); + g_free(escaped_xmlns); } } for(c = node->child; c; c = c->next) diff -r 2908b16efa07 -r f01d6c9f3492 libpurple/xmlnode.h --- a/libpurple/xmlnode.h Mon Apr 02 23:36:20 2012 +0000 +++ b/libpurple/xmlnode.h Fri Apr 06 04:30:00 2012 +0000 @@ -28,14 +28,10 @@ #include -#ifdef __cplusplus -extern "C" { -#endif - /** * The valid types for an xmlnode */ -typedef enum _XMLNodeType +typedef enum { XMLNODE_TYPE_TAG, /**< Just a tag */ XMLNODE_TYPE_ATTRIB, /**< Has attributes */ @@ -61,6 +57,8 @@ GHashTable *namespace_map; /**< The namespace map. */ }; +G_BEGIN_DECLS + /** * Creates a new xmlnode. * @@ -157,42 +155,14 @@ */ void xmlnode_set_attrib(xmlnode *node, const char *attr, const char *value); -#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_XMLNODE_C_) -/** - * Sets a prefixed attribute for a node - * - * @param node The node to set an attribute for. - * @param attr The name of the attribute to set - * @param prefix The prefix of the attribute to ste - * @param value The value of the attribute - * - * @deprecated Use xmlnode_set_attrib_full instead. - */ -void xmlnode_set_attrib_with_prefix(xmlnode *node, const char *attr, const char *prefix, const char *value); - -/** - * Sets a namespaced attribute for a node - * - * @param node The node to set an attribute for. - * @param attr The name of the attribute to set - * @param xmlns The namespace of the attribute to ste - * @param value The value of the attribute - * - * @deprecated Use xmlnode_set_attrib_full instead. - */ -void xmlnode_set_attrib_with_namespace(xmlnode *node, const char *attr, const char *xmlns, const char *value); -#endif /* PURPLE_DISABLE_DEPRECATED */ - /** * Sets a namespaced attribute for a node * * @param node The node to set an attribute for. * @param attr The name of the attribute to set - * @param xmlns The namespace of the attribute to ste - * @param prefix The prefix of the attribute to ste + * @param xmlns The namespace of the attribute to set + * @param prefix The prefix of the attribute to set * @param value The value of the attribute - * - * @since 2.6.0 */ void xmlnode_set_attrib_full(xmlnode *node, const char *attr, const char *xmlns, const char *prefix, const char *value); @@ -249,7 +219,37 @@ * @param node The node to get the namepsace from * @return The namespace of this node */ -const char *xmlnode_get_namespace(xmlnode *node); +const char *xmlnode_get_namespace(const xmlnode *node); + +/** + * Returns the current default namespace. The default + * namespace is the current namespace which applies to child + * elements which are unprefixed and which do not contain their + * own namespace. + * + * For example, given: + * \verbatim + * + * + * + * \endverbatim + * + * The default namespace of all nodes (including 'child1') is "jabber:client", + * though the namespace for 'element' is "http://example.org/ns1". + * + * @param node The node for which to return the default namespace + * @return The default namespace of this node + */ +const char *xmlnode_get_default_namespace(const xmlnode *node); + +/** + * Returns the defined namespace for a prefix. + * + * @param node The node from which to start the search. + * @param prefix The prefix for which to return the associated namespace. + * @return The namespace for this prefix. + */ +const char *xmlnode_get_prefix_namespace(const xmlnode *node, const char *prefix); /** * Sets the prefix of a node @@ -268,13 +268,24 @@ const char *xmlnode_get_prefix(const xmlnode *node); /** + * Remove all element prefixes from an xmlnode tree. The prefix's + * namespace is transformed into the default namespace for an element. + * + * Note that this will not necessarily remove all prefixes in use + * (prefixed attributes may still exist), and that this usage may + * break some applications (SOAP / XPath apparently often rely on + * the prefixes having the same name. + * + * @param node The node from which to strip prefixes + */ +void xmlnode_strip_prefixes(xmlnode *node); + +/** * Gets the parent node. * * @param child The child node. * * @return The parent or NULL. - * - * @since 2.6.0 */ xmlnode *xmlnode_get_parent(const xmlnode *child); @@ -343,14 +354,11 @@ * the category for debugging. * * @return The new node or NULL if an error occurred. - * - * @since 2.6.0 */ xmlnode *xmlnode_from_file(const char *dir, const char *filename, const char *description, const char *process); -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PURPLE_XMLNODE_H_ */ + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/Makefile.am --- a/pidgin/Makefile.am Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/Makefile.am Fri Apr 06 04:30:00 2012 +0000 @@ -3,8 +3,8 @@ getopt.h \ getopt1.c \ Makefile.mingw \ - pidgin.pc.in \ - pidgin-uninstalled.pc.in \ + pidgin-3.pc.in \ + pidgin-3-uninstalled.pc.in \ win32/MinimizeToTray.h \ win32/MinimizeToTray.c \ win32/pidgin_dll_rc.rc.in \ @@ -32,9 +32,9 @@ if ENABLE_GTK pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = pidgin.pc +pkgconfig_DATA = pidgin-3.pc -SUBDIRS = pixmaps plugins +SUBDIRS = pixmaps plugins themes bin_PROGRAMS = pidgin @@ -48,11 +48,12 @@ gtkcertmgr.c \ gtkconn.c \ gtkconv.c \ + gtkconv-theme.c \ + gtkconv-theme-loader.c \ gtkdebug.c \ gtkdialogs.c \ gtkdnd-hints.c \ gtkdocklet.c \ - gtkdocklet-gtk.c \ gtkeventloop.c \ gtkft.c \ gtkicon-theme.c \ @@ -84,9 +85,12 @@ gtkstatusbox.c \ gtkthemes.c \ gtkutils.c \ + gtkwebview.c \ + gtkwebviewtoolbar.c \ gtkwhiteboard.c \ minidialog.c \ - pidgintooltip.c + pidgintooltip.c \ + smileyparser.c pidgin_headers = \ gtkaccount.h \ @@ -98,6 +102,8 @@ gtkconn.h \ gtkconv.h \ gtkconvwin.h \ + gtkconv-theme.h \ + gtkconv-theme-loader.h \ gtkdebug.h \ gtkdialogs.h \ gtkdnd-hints.h \ @@ -107,7 +113,6 @@ gtkicon-theme.h \ gtkicon-theme-loader.h \ gtkidle.h \ - gtkgaim-compat.h \ gtkimhtml.h \ gtkimhtmltoolbar.h \ gtklog.h \ @@ -135,10 +140,13 @@ pidginstock.h \ gtkthemes.h \ gtkutils.h \ + gtkwebview.h \ + gtkwebviewtoolbar.h \ gtkwhiteboard.h \ minidialog.h \ pidgintooltip.h \ - pidgin.h + pidgin.h \ + smileyparser.h pidginincludedir=$(includedir)/pidgin pidgininclude_HEADERS = \ @@ -150,6 +158,7 @@ pidgin_LDADD = \ @LIBOBJS@ \ $(GLIB_LIBS) \ + $(GCR_LIBS) \ $(DBUS_LIBS) \ $(GSTREAMER_LIBS) \ $(XSS_LIBS) \ @@ -157,6 +166,7 @@ $(INTLLIBS) \ $(GTKSPELL_LIBS) \ $(LIBXML_LIBS) \ + $(WEBKIT_LIBS) \ $(GTK_LIBS) \ $(top_builddir)/libpurple/libpurple.la @@ -174,11 +184,14 @@ -I$(top_builddir) \ -I$(top_srcdir) \ $(GLIB_CFLAGS) \ + $(GCR_CFLAGS) \ $(GSTREAMER_CFLAGS) \ $(DEBUG_CFLAGS) \ $(GTK_CFLAGS) \ $(DBUS_CFLAGS) \ $(GTKSPELL_CFLAGS) \ $(LIBXML_CFLAGS) \ + $(WEBKIT_CFLAGS) \ $(INTGG_CFLAGS) endif # ENABLE_GTK + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/Makefile.mingw --- a/pidgin/Makefile.mingw Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/Makefile.mingw Fri Apr 06 04:30:00 2012 +0000 @@ -58,6 +58,8 @@ gtkcertmgr.c \ gtkconn.c \ gtkconv.c \ + gtkconv-theme.c \ + gtkconv-theme-loader.c \ gtkdebug.c \ gtkdialogs.c \ gtkdnd-hints.c \ @@ -91,12 +93,13 @@ gtkstatusbox.c \ gtkthemes.c \ gtkutils.c \ + gtkwebview.c \ + gtkwebviewtoolbar.c \ gtkwhiteboard.c \ minidialog.c \ pidginstock.c \ pidgintooltip.c \ - win32/MinimizeToTray.c \ - win32/gtkdocklet-win32.c \ + smileyparser.c \ win32/gtkwin32dep.c \ win32/untar.c \ win32/wspell.c diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkaccount.c --- a/pidgin/gtkaccount.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkaccount.c Fri Apr 06 04:30:00 2012 +0000 @@ -220,7 +220,7 @@ } static void -set_account_protocol_cb(GtkWidget *item, const char *id, +set_account_protocol_cb(GtkWidget *widget, const char *id, AccountPrefsDialog *dialog) { PurplePlugin *new_plugin; @@ -247,8 +247,7 @@ gtk_widget_grab_focus(dialog->protocol_menu); - if (!dialog->prpl_info || !dialog->prpl_info->register_user || - g_object_get_data(G_OBJECT(item), "fake")) { + if (!dialog->prpl_info || !dialog->prpl_info->register_user) { gtk_widget_hide(dialog->register_button); } else { if (dialog->prpl_info != NULL && @@ -424,8 +423,6 @@ GtkWidget *hbox; GtkWidget *vbox; GtkWidget *entry; - GtkWidget *menu; - GtkWidget *item; GList *user_splits; GList *l, *l2; char *username = NULL; @@ -563,17 +560,6 @@ if (value == NULL) value = purple_account_user_split_get_default_value(split); - /* Google Talk default domain hackery! */ - menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(dialog->protocol_menu)); - item = gtk_menu_get_active(GTK_MENU(menu)); - if (value == NULL && g_object_get_data(G_OBJECT(item), "fakegoogle") && - !strcmp(purple_account_user_split_get_text(split), _("Domain"))) - value = "gmail.com"; - - if (value == NULL && g_object_get_data(G_OBJECT(item), "fakefacebook") && - !strcmp(purple_account_user_split_get_text(split), _("Domain"))) - value = "chat.facebook.com"; - if (value != NULL) gtk_entry_set_text(GTK_ENTRY(entry), value); } @@ -769,7 +755,7 @@ { PurpleAccountOption *option; PurpleAccount *account; - GtkWidget *vbox, *check, *entry, *combo, *menu, *item; + GtkWidget *vbox, *check, *entry, *combo; GList *list, *node; gint i, idx, int_value; GtkListStore *model; @@ -808,9 +794,6 @@ gtk_label_new_with_mnemonic(_("Ad_vanced")), 1); gtk_widget_show(vbox); - menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(dialog->protocol_menu)); - item = gtk_menu_get_active(GTK_MENU(menu)); - for (l = dialog->prpl_info->protocol_options; l != NULL; l = l->next) { option = (PurpleAccountOption *)l->data; @@ -925,10 +908,6 @@ model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); opt_entry->widget = combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model)); - if (g_object_get_data(G_OBJECT(item), "fakefacebook") && - !strcmp(opt_entry->setting, "connection_security")) - str_value = "opportunistic_tls"; - /* Loop through list of PurpleKeyValuePair items */ for (node = list; node != NULL; node = node->next) { if (node->data != NULL) { @@ -1213,8 +1192,12 @@ gtk_widget_show_all(dialog->voice_frame); } - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->suppression_check), - purple_account_get_silence_suppression(dialog->account)); + if (dialog->account) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->suppression_check), + purple_account_get_silence_suppression(dialog->account)); + } else { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->suppression_check), FALSE); + } #endif } @@ -2726,4 +2709,3 @@ purple_signals_unregister_by_instance(pidgin_account_get_handle()); } - diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkaccount.h --- a/pidgin/gtkaccount.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkaccount.h Fri Apr 06 04:30:00 2012 +0000 @@ -37,6 +37,8 @@ } PidginAccountDialogType; +G_BEGIN_DECLS + /** * Shows the accounts window. */ @@ -80,4 +82,6 @@ */ void pidgin_account_uninit(void); +G_END_DECLS + #endif /* _PIDGINACCOUNT_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkblist-theme-loader.c --- a/pidgin/gtkblist-theme-loader.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkblist-theme-loader.c Fri Apr 06 04:30:00 2012 +0000 @@ -73,10 +73,10 @@ } static PurpleTheme * -pidgin_blist_loader_build(const gchar *dir) +pidgin_blist_loader_build(const gchar *theme_dir) { xmlnode *root_node = NULL, *sub_node, *sub_sub_node; - gchar *filename_full, *data = NULL; + gchar *dir, *filename_full, *data = NULL; const gchar *temp, *name; gboolean success = TRUE; GdkColor *bgcolor, *expanded_bgcolor, *collapsed_bgcolor, *contact_color; @@ -112,15 +112,18 @@ status = NULL; /* Find the theme file */ - g_return_val_if_fail(dir != NULL, NULL); + g_return_val_if_fail(theme_dir != NULL, NULL); + dir = g_build_filename(theme_dir, "purple", "blist", NULL); filename_full = g_build_filename(dir, "theme.xml", NULL); if (g_file_test(filename_full, G_FILE_TEST_IS_REGULAR)) root_node = xmlnode_from_file(dir, "theme.xml", "buddy list themes", "blist-loader"); g_free(filename_full); - if (root_node == NULL) + if (root_node == NULL) { + g_free(dir); return NULL; + } sub_node = xmlnode_get_child(root_node, "description"); data = xmlnode_get_data(sub_node); @@ -227,6 +230,7 @@ xmlnode_free(root_node); g_free(data); + g_free(dir); /* malformed xml file - also frees all partial data*/ if (!success) { diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkblist-theme.c --- a/pidgin/gtkblist-theme.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkblist-theme.c Fri Apr 06 04:30:00 2012 +0000 @@ -24,7 +24,7 @@ #include "gtkblist-theme.h" #define PIDGIN_BLIST_THEME_GET_PRIVATE(Gobject) \ - ((PidginBlistThemePrivate *) ((PIDGIN_BLIST_THEME(Gobject))->priv)) + (G_TYPE_INSTANCE_GET_PRIVATE((Gobject), PIDGIN_TYPE_BLIST_THEME, PidginBlistThemePrivate)) /****************************************************************************** * Structs @@ -189,13 +189,6 @@ *****************************************************************************/ static void -pidgin_blist_theme_init(GTypeInstance *instance, - gpointer klass) -{ - (PIDGIN_BLIST_THEME(instance))->priv = g_new0(PidginBlistThemePrivate, 1); -} - -static void pidgin_blist_theme_get_property(GObject *obj, guint param_id, GValue *value, GParamSpec *psec) { @@ -349,8 +342,6 @@ pidgin_theme_font_free(priv->message_nick_said); pidgin_theme_font_free(priv->status); - g_free(priv); - parent_class->finalize (obj); } @@ -362,6 +353,8 @@ parent_class = g_type_class_peek_parent (klass); + g_type_class_add_private(klass, sizeof(PidginBlistThemePrivate)); + obj_class->get_property = pidgin_blist_theme_get_property; obj_class->set_property = pidgin_blist_theme_set_property; obj_class->finalize = pidgin_blist_theme_finalize; @@ -484,7 +477,7 @@ NULL, /* class_data */ sizeof(PidginBlistTheme), 0, /* n_preallocs */ - pidgin_blist_theme_init, /* instance_init */ + NULL, /* instance_init */ NULL, /* value table */ }; type = g_type_register_static (PURPLE_TYPE_THEME, @@ -507,7 +500,7 @@ g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); return priv->bgcolor; } @@ -519,7 +512,7 @@ g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), 1.0); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); return priv->opacity; } @@ -531,7 +524,7 @@ g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); return priv->layout; } @@ -543,7 +536,7 @@ g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); return priv->expanded_color; } @@ -555,7 +548,7 @@ g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); return priv->expanded; } @@ -567,7 +560,7 @@ g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); return priv->collapsed_color; } @@ -579,7 +572,7 @@ g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); return priv->collapsed; } @@ -591,7 +584,7 @@ g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); return priv->contact_color; } @@ -603,7 +596,7 @@ g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); return priv->contact; } @@ -615,7 +608,7 @@ g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); return priv->online; } @@ -627,7 +620,7 @@ g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); return priv->away; } @@ -639,7 +632,7 @@ g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); return priv->offline; } @@ -651,7 +644,7 @@ g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); return priv->idle; } @@ -663,7 +656,7 @@ g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); return priv->message; } @@ -675,7 +668,7 @@ g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); return priv->message_nick_said; } @@ -687,7 +680,7 @@ g_return_val_if_fail(PIDGIN_IS_BLIST_THEME(theme), NULL); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); return priv->status; } @@ -700,7 +693,7 @@ g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme)); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); if (priv->bgcolor) gdk_color_free(priv->bgcolor); @@ -714,7 +707,7 @@ g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme) || opacity < 0.0 || opacity > 1.0); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); priv->opacity = opacity; } @@ -726,7 +719,7 @@ g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme)); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); g_free(priv->layout); priv->layout = g_memdup(layout, sizeof(PidginBlistLayout)); @@ -739,7 +732,7 @@ g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme)); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); if (priv->expanded_color) gdk_color_free(priv->expanded_color); @@ -753,7 +746,7 @@ g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme)); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); pidgin_theme_font_free(priv->expanded); priv->expanded = copy_font_and_color(pair); @@ -766,7 +759,7 @@ g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme)); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); if (priv->collapsed_color) gdk_color_free(priv->collapsed_color); @@ -780,7 +773,7 @@ g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme)); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); pidgin_theme_font_free(priv->collapsed); priv->collapsed = copy_font_and_color(pair); @@ -793,7 +786,7 @@ g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme)); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); if (priv->contact_color) gdk_color_free(priv->contact_color); @@ -807,7 +800,7 @@ g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme)); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); pidgin_theme_font_free(priv->contact); priv->contact = copy_font_and_color(pair); @@ -820,7 +813,7 @@ g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme)); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); pidgin_theme_font_free(priv->online); priv->online = copy_font_and_color(pair); @@ -833,7 +826,7 @@ g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme)); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); pidgin_theme_font_free(priv->away); priv->away = copy_font_and_color(pair); @@ -846,7 +839,7 @@ g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme)); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); pidgin_theme_font_free(priv->offline); priv->offline = copy_font_and_color(pair); @@ -859,7 +852,7 @@ g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme)); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); pidgin_theme_font_free(priv->idle); priv->idle = copy_font_and_color(pair); @@ -872,7 +865,7 @@ g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme)); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); pidgin_theme_font_free(priv->message); priv->message = copy_font_and_color(pair); @@ -885,7 +878,7 @@ g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme)); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); pidgin_theme_font_free(priv->message_nick_said); priv->message_nick_said = copy_font_and_color(pair); @@ -898,7 +891,7 @@ g_return_if_fail(PIDGIN_IS_BLIST_THEME(theme)); - priv = PIDGIN_BLIST_THEME_GET_PRIVATE(G_OBJECT(theme)); + priv = PIDGIN_BLIST_THEME_GET_PRIVATE(theme); pidgin_theme_font_free(priv->status); priv->status = copy_font_and_color(pair); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkblist-theme.h --- a/pidgin/gtkblist-theme.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkblist-theme.h Fri Apr 06 04:30:00 2012 +0000 @@ -51,7 +51,6 @@ struct _PidginBlistTheme { PurpleTheme parent; - gpointer priv; }; struct _PidginBlistThemeClass @@ -80,6 +79,8 @@ } PidginBlistLayout; +G_BEGIN_DECLS + /**************************************************************************/ /** @name PidginThemeFont API */ /**************************************************************************/ @@ -147,7 +148,6 @@ /**************************************************************************/ /** @name Purple Buddy List Theme API */ /**************************************************************************/ -G_BEGIN_DECLS /** * GObject foo. @@ -183,7 +183,7 @@ * * @returns The buddy list layout. */ - PidginBlistLayout *pidgin_blist_theme_get_layout(PidginBlistTheme *theme); +PidginBlistLayout *pidgin_blist_theme_get_layout(PidginBlistTheme *theme); /** * Returns the background color to be used with expanded groups. @@ -192,7 +192,7 @@ * * @returns A gdk color. */ - GdkColor *pidgin_blist_theme_get_expanded_background_color(PidginBlistTheme *theme); +GdkColor *pidgin_blist_theme_get_expanded_background_color(PidginBlistTheme *theme); /** * Returns the text font and color to be used with expanded groups. @@ -201,7 +201,7 @@ * * @returns A font and color pair. */ - PidginThemeFont *pidgin_blist_theme_get_expanded_text_info(PidginBlistTheme *theme); +PidginThemeFont *pidgin_blist_theme_get_expanded_text_info(PidginBlistTheme *theme); /** * Returns the background color to be used with collapsed groups. @@ -210,7 +210,7 @@ * * @returns A gdk color. */ - GdkColor *pidgin_blist_theme_get_collapsed_background_color(PidginBlistTheme *theme); +GdkColor *pidgin_blist_theme_get_collapsed_background_color(PidginBlistTheme *theme); /** * Returns the text font and color to be used with collapsed groups. @@ -219,7 +219,7 @@ * * @returns A font and color pair. */ - PidginThemeFont *pidgin_blist_theme_get_collapsed_text_info(PidginBlistTheme *theme); +PidginThemeFont *pidgin_blist_theme_get_collapsed_text_info(PidginBlistTheme *theme); /** * Returns the colors to be used for contacts and chats. @@ -228,7 +228,7 @@ * * @returns A gdkcolor for contacts and chats. */ - GdkColor *pidgin_blist_theme_get_contact_color(PidginBlistTheme *theme); +GdkColor *pidgin_blist_theme_get_contact_color(PidginBlistTheme *theme); /** * Returns the text font and color to be used for expanded contacts. @@ -237,7 +237,7 @@ * * @returns A font and color pair. */ - PidginThemeFont *pidgin_blist_theme_get_contact_text_info(PidginBlistTheme *theme); +PidginThemeFont *pidgin_blist_theme_get_contact_text_info(PidginBlistTheme *theme); /** * Returns the text font and color to be used for online buddies. @@ -246,7 +246,7 @@ * * @returns A font and color pair. */ - PidginThemeFont *pidgin_blist_theme_get_online_text_info(PidginBlistTheme *theme); +PidginThemeFont *pidgin_blist_theme_get_online_text_info(PidginBlistTheme *theme); /** * Returns the text font and color to be used for away and idle buddies. @@ -255,7 +255,7 @@ * * @returns A font and color pair. */ - PidginThemeFont *pidgin_blist_theme_get_away_text_info(PidginBlistTheme *theme); +PidginThemeFont *pidgin_blist_theme_get_away_text_info(PidginBlistTheme *theme); /** * Returns the text font and color to be used for offline buddies. @@ -264,7 +264,7 @@ * * @returns A font and color pair. */ - PidginThemeFont *pidgin_blist_theme_get_offline_text_info(PidginBlistTheme *theme); +PidginThemeFont *pidgin_blist_theme_get_offline_text_info(PidginBlistTheme *theme); /** * Returns the text font and color to be used for idle buddies. @@ -273,7 +273,7 @@ * * @returns A font and color pair. */ - PidginThemeFont *pidgin_blist_theme_get_idle_text_info(PidginBlistTheme *theme); +PidginThemeFont *pidgin_blist_theme_get_idle_text_info(PidginBlistTheme *theme); /** * Returns the text font and color to be used for buddies with unread messages. @@ -282,7 +282,7 @@ * * @returns A font and color pair. */ - PidginThemeFont *pidgin_blist_theme_get_unread_message_text_info(PidginBlistTheme *theme); +PidginThemeFont *pidgin_blist_theme_get_unread_message_text_info(PidginBlistTheme *theme); /** * Returns the text font and color to be used for chats with unread messages @@ -292,7 +292,7 @@ * * @returns A font and color pair. */ - PidginThemeFont *pidgin_blist_theme_get_unread_message_nick_said_text_info(PidginBlistTheme *theme); +PidginThemeFont *pidgin_blist_theme_get_unread_message_nick_said_text_info(PidginBlistTheme *theme); /** * Returns the text font and color to be used for a buddy's status message. @@ -301,7 +301,7 @@ * * @returns A font and color pair. */ - PidginThemeFont *pidgin_blist_theme_get_status_text_info(PidginBlistTheme *theme); +PidginThemeFont *pidgin_blist_theme_get_status_text_info(PidginBlistTheme *theme); /* Set Methods */ @@ -435,4 +435,5 @@ void pidgin_blist_theme_set_status_text_info(PidginBlistTheme *theme, const PidginThemeFont *pair); G_END_DECLS + #endif /* PIDGIN_BLIST_THEME_H */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkblist.c --- a/pidgin/gtkblist.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkblist.c Fri Apr 06 04:30:00 2012 +0000 @@ -124,6 +124,11 @@ #define PIDGIN_BUDDY_LIST_GET_PRIVATE(list) \ ((PidginBuddyListPrivate *)((list)->priv)) +#if !GTK_CHECK_VERSION(2,18,0) +#define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE(x) +#define gtk_widget_has_focus(x) GTK_WIDGET_HAS_FOCUS(x) +#endif + static GtkWidget *accountmenu = NULL; static guint visibility_manager_count = 0; @@ -138,6 +143,9 @@ static void sort_method_alphabetical(PurpleBlistNode *node, PurpleBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter); static void sort_method_status(PurpleBlistNode *node, PurpleBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter); static void sort_method_log_activity(PurpleBlistNode *node, PurpleBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter); +static guint sort_merge_id; +static GtkActionGroup *sort_action_group = NULL; + static PidginBuddyList *gtkblist = NULL; static GList *groups_tree(void); @@ -148,7 +156,6 @@ static void pidgin_blist_update_group(PurpleBuddyList *list, PurpleBlistNode *node); static void pidgin_blist_update_contact(PurpleBuddyList *list, PurpleBlistNode *node); static char *pidgin_get_tooltip_text(PurpleBlistNode *node, gboolean full); -static const char *item_factory_translate_func (const char *path, gpointer func_data); static gboolean get_iter_from_node(PurpleBlistNode *node, GtkTreeIter *iter); static gboolean buddy_is_displayable(PurpleBuddy *buddy); static void redo_buddy_list(PurpleBuddyList *list, gboolean remove, gboolean rerender); @@ -242,7 +249,7 @@ /* check for visibility because when we aren't visible, this will * * give us bogus (0,0) coordinates. - xOr */ - if (GTK_WIDGET_VISIBLE(w)) + if (gtk_widget_get_visible(w)) gtk_window_get_position(GTK_WINDOW(w), &x, &y); else return FALSE; /* carry on normally */ @@ -343,13 +350,13 @@ static void gtk_blist_menu_autojoin_cb(GtkWidget *w, PurpleChat *chat) { - purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-autojoin", + purple_blist_node_set_bool(PURPLE_BLIST_NODE(chat), "gtk-autojoin", gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))); } static void gtk_blist_menu_persistent_cb(GtkWidget *w, PurpleChat *chat) { - purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-persistent", + purple_blist_node_set_bool(PURPLE_BLIST_NODE(chat), "gtk-persistent", gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))); } @@ -916,7 +923,7 @@ gtk_dialog_set_response_sensitive(GTK_DIALOG(data->rq_data.window), GTK_RESPONSE_OK, sensitive); gc = purple_account_get_connection(data->rq_data.account); - prpl_info = (gc != NULL) ? PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl) : NULL; + prpl_info = (gc != NULL) ? PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)) : NULL; sensitive = (prpl_info != NULL && prpl_info->roomlist_get_list != NULL); gtk_dialog_set_response_sensitive(GTK_DIALOG(data->rq_data.window), 1, sensitive); @@ -940,7 +947,7 @@ if (gc == NULL) return FALSE; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); return (prpl_info->chat_info != NULL); } @@ -1030,6 +1037,7 @@ rebuild_chat_entries(PidginChatData *data, const char *default_chat_name) { PurpleConnection *gc; + PurplePluginProtocolInfo *prpl_info; GList *list = NULL, *tmp; GHashTable *defaults = NULL; struct proto_chat_entry *pce; @@ -1038,17 +1046,18 @@ g_return_if_fail(data->rq_data.account != NULL); gc = purple_account_get_connection(data->rq_data.account); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); gtk_container_foreach(GTK_CONTAINER(data->rq_data.vbox), (GtkCallback)gtk_widget_destroy, NULL); g_list_free(data->entries); data->entries = NULL; - if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info != NULL) - list = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info(gc); - - if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) - defaults = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, default_chat_name); + if (prpl_info->chat_info != NULL) + list = prpl_info->chat_info(gc); + + if (prpl_info->chat_info_defaults != NULL) + defaults = prpl_info->chat_info_defaults(gc, default_chat_name); for (tmp = list; tmp; tmp = tmp->next) { @@ -1411,7 +1420,7 @@ PurpleBlistNode *node) { GList *l, *ll; - PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if(!prpl_info || !prpl_info->blist_node_menu) return; @@ -1519,7 +1528,7 @@ if (prpl_info && prpl_info->send_file) { if (!prpl_info->can_receive_file || - prpl_info->can_receive_file(buddy->account->gc, buddy->name)) + prpl_info->can_receive_file(purple_account_get_connection(purple_buddy_get_account(buddy)), purple_buddy_get_name(buddy))) { pidgin_new_item_from_stock(menu, _("_Send File..."), PIDGIN_STOCK_TOOLBAR_SEND_FILE, @@ -1547,11 +1556,11 @@ NULL, G_CALLBACK(gtk_blist_menu_showoffline_cb), node, 0, 0, NULL); } - pidgin_append_blist_node_proto_menu(menu, buddy->account->gc, node); + pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(purple_buddy_get_account(buddy)), node); pidgin_append_blist_node_extended_menu(menu, node); if (!contact_expanded && contact != NULL) - pidgin_append_blist_node_move_to_menu(menu, (PurpleBlistNode *)contact); + pidgin_append_blist_node_move_to_menu(menu, PURPLE_BLIST_NODE(contact)); if (node->parent && node->parent->child->next && !sub && !contact_expanded) { @@ -1600,7 +1609,7 @@ return FALSE; } if(buddy) - pidgin_retrieve_user_info(buddy->account->gc, buddy->name); + pidgin_retrieve_user_info(purple_account_get_connection(purple_buddy_get_account(buddy)), purple_buddy_get_name(buddy)); } else { switch (event->keyval) { case GDK_F2: @@ -1753,7 +1762,7 @@ pidgin_new_item_from_stock(menu, _("View _Log"), NULL, G_CALLBACK(gtk_blist_menu_showlog_cb), node, 0, 0, NULL); - pidgin_append_blist_node_proto_menu(menu, c->account->gc, node); + pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(purple_chat_get_account(c)), node); pidgin_append_blist_node_extended_menu(menu, node); pidgin_separator(menu); @@ -1803,7 +1812,7 @@ static GtkWidget * create_buddy_menu(PurpleBlistNode *node, PurpleBuddy *b) { - struct _pidgin_blist_node *gtknode = (struct _pidgin_blist_node *)node->ui_data; + struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node); GtkWidget *menu; GtkWidget *menuitem; gboolean show_offline = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies"); @@ -1838,13 +1847,13 @@ if(buddy == b) continue; - if(!buddy->account->gc) + if(!purple_account_get_connection(purple_buddy_get_account(buddy))) continue; if(!show_offline && !PURPLE_BUDDY_IS_ONLINE(buddy)) continue; - menuitem = gtk_image_menu_item_new_with_label(buddy->name); - buf = pidgin_create_prpl_icon(buddy->account,PIDGIN_PRPL_ICON_SMALL); + menuitem = gtk_image_menu_item_new_with_label(purple_buddy_get_name(buddy)); + buf = pidgin_create_prpl_icon(purple_buddy_get_account(buddy), PIDGIN_PRPL_ICON_SMALL); image = gtk_image_new_from_pixbuf(buf); g_object_unref(G_OBJECT(buf)); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), @@ -1871,12 +1880,10 @@ guint button, guint32 time) { - struct _pidgin_blist_node *gtknode; + struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node); GtkWidget *menu = NULL; gboolean handled = FALSE; - gtknode = (struct _pidgin_blist_node *)node->ui_data; - /* Create a menu based on the thing we right-clicked on */ if (PURPLE_BLIST_NODE_IS_GROUP(node)) { PurpleGroup *g = (PurpleGroup *)node; @@ -1938,7 +1945,7 @@ return FALSE; gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); - gtknode = (struct _pidgin_blist_node *)node->ui_data; + gtknode = purple_blist_node_get_ui_data(node); /* Right click draws a context menu */ if ((event->button == 3) && (event->type == GDK_BUTTON_PRESS)) { @@ -1962,12 +1969,12 @@ else b = (PurpleBuddy *)node; - prpl = purple_find_prpl(purple_account_get_protocol_id(b->account)); + prpl = purple_find_prpl(purple_account_get_protocol_id(purple_buddy_get_account(b))); if (prpl != NULL) prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); if (prpl && prpl_info->get_info) - pidgin_retrieve_user_info(b->account->gc, b->name); + pidgin_retrieve_user_info(purple_account_get_connection(purple_buddy_get_account(b)), purple_buddy_get_name(b)); handled = TRUE; } @@ -2012,64 +2019,70 @@ return handled; } -static void pidgin_blist_buddy_details_cb(gpointer data, guint action, GtkWidget *item) +static void gtk_blist_show_xfer_dialog_cb(GtkAction *item, gpointer data) +{ + pidgin_xfer_dialog_show(NULL); +} + +static void pidgin_blist_buddy_details_cb(GtkToggleAction *item, gpointer data) { pidgin_set_cursor(gtkblist->window, GDK_WATCH); purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons", - gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item))); + gtk_toggle_action_get_active(item)); pidgin_clear_cursor(gtkblist->window); } -static void pidgin_blist_show_idle_time_cb(gpointer data, guint action, GtkWidget *item) +static void pidgin_blist_show_idle_time_cb(GtkToggleAction *item, gpointer data) { pidgin_set_cursor(gtkblist->window, GDK_WATCH); purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_idle_time", - gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item))); + gtk_toggle_action_get_active(item)); pidgin_clear_cursor(gtkblist->window); } -static void pidgin_blist_show_protocol_icons_cb(gpointer data, guint action, GtkWidget *item) +static void pidgin_blist_show_protocol_icons_cb(GtkToggleAction *item, gpointer data) { purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons", - gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item))); -} - -static void pidgin_blist_show_empty_groups_cb(gpointer data, guint action, GtkWidget *item) + gtk_toggle_action_get_active(item)); +} + +static void pidgin_blist_show_empty_groups_cb(GtkToggleAction *item, gpointer data) { pidgin_set_cursor(gtkblist->window, GDK_WATCH); purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_empty_groups", - gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item))); + gtk_toggle_action_get_active(item)); pidgin_clear_cursor(gtkblist->window); } -static void pidgin_blist_edit_mode_cb(gpointer callback_data, guint callback_action, - GtkWidget *checkitem) +static void pidgin_blist_edit_mode_cb(GtkToggleAction *checkitem, gpointer data) { pidgin_set_cursor(gtkblist->window, GDK_WATCH); purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies", - gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(checkitem))); + gtk_toggle_action_get_active(checkitem)); pidgin_clear_cursor(gtkblist->window); } -static void pidgin_blist_mute_sounds_cb(gpointer data, guint action, GtkWidget *item) -{ - purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/sound/mute", GTK_CHECK_MENU_ITEM(item)->active); -} +static void pidgin_blist_mute_sounds_cb(GtkToggleAction *item, gpointer data) +{ + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/sound/mute", + gtk_toggle_action_get_active(item)); +} + static void pidgin_blist_mute_pref_cb(const char *name, PurplePrefType type, gconstpointer value, gpointer data) { - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item(gtkblist->ift, - N_("/Tools/Mute Sounds"))), (gboolean)GPOINTER_TO_INT(value)); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, + "/BList/ToolsMenu/MuteSounds")), (gboolean)GPOINTER_TO_INT(value)); } static void @@ -2081,7 +2094,7 @@ if(!strcmp(value, "none")) sensitive = FALSE; - gtk_widget_set_sensitive(gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Mute Sounds")), sensitive); + gtk_action_set_sensitive(gtk_ui_manager_get_action(gtkblist->ui, "/BList/ToolsMenu/MuteSounds"), sensitive); } static void @@ -2111,7 +2124,7 @@ for (l = list; l != NULL; l = l->next) { purple_blist_request_add_buddy(account, l->data, - (group ? group->name : NULL), + (group ? purple_group_get_name(group) : NULL), alias); } } @@ -2292,7 +2305,7 @@ buddy = (PurpleBuddy *)node; } - gc = purple_account_get_connection(buddy->account); + gc = purple_account_get_connection(purple_buddy_get_account(buddy)); if (gc == NULL) { @@ -2301,7 +2314,7 @@ } protocol = - PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->list_icon(buddy->account, + PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->list_icon(purple_buddy_get_account(buddy), buddy); str = g_string_new(NULL); @@ -2311,13 +2324,13 @@ "X-IM-Protocol: %s\r\n" "X-IM-Username: %s\r\n", protocol, - buddy->name); - - if (buddy->alias != NULL) + purple_buddy_get_name(buddy)); + + if (purple_buddy_get_local_buddy_alias(buddy) != NULL) { g_string_append_printf(str, "X-IM-Alias: %s\r\n", - buddy->alias); + purple_buddy_get_local_buddy_alias(buddy)); } g_string_append(str, "\r\n"); @@ -2356,7 +2369,7 @@ &iter, path); gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1); - gtknode = node->ui_data; + gtknode = purple_blist_node_get_ui_data(node); if (PURPLE_BLIST_NODE_IS_CONTACT(n)) { PurpleContact *c = (PurpleContact*)n; @@ -2533,7 +2546,7 @@ else { purple_blist_request_add_buddy(account, username, - (group ? group->name : NULL), + (group ? purple_group_get_name(group) : NULL), alias); } } @@ -2600,7 +2613,7 @@ if (PURPLE_BLIST_NODE_IS_BUDDY(node) || PURPLE_BLIST_NODE_IS_CONTACT(node)) { PurpleBuddy *b = PURPLE_BLIST_NODE_IS_BUDDY(node) ? PURPLE_BUDDY(node) : purple_contact_get_priority_buddy(PURPLE_CONTACT(node)); - pidgin_dnd_file_manage(sd, b->account, b->name); + pidgin_dnd_file_manage(sd, purple_buddy_get_account(b), purple_buddy_get_name(b)); gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); } else { gtk_drag_finish(dc, FALSE, FALSE, t); @@ -2673,8 +2686,8 @@ account = purple_buddy_get_account(buddy); } - if(account && account->gc) { - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(account->gc->prpl); + if(account && purple_account_get_connection(account)) { + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(purple_account_get_connection(account))); } #if 0 @@ -2687,7 +2700,7 @@ * a contact then this is a group or some other type of node and we * want to use that directly. */ if (contact) { - custom_img = purple_buddy_icons_node_find_custom_icon((PurpleBlistNode*)contact); + custom_img = purple_buddy_icons_node_find_custom_icon(PURPLE_BLIST_NODE(contact)); } else { custom_img = purple_buddy_icons_node_find_custom_icon(node); } @@ -2700,7 +2713,7 @@ if (data == NULL) { if (buddy) { /* Not sure I like this...*/ - if (!(icon = purple_buddy_icons_find(buddy->account, buddy->name))) + if (!(icon = purple_buddy_icons_find(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy)))) return NULL; data = purple_buddy_icon_get_data(icon, &len); } @@ -2870,9 +2883,9 @@ char *tmp = NULL, *node_name = NULL, *tooltip_text = NULL; if (PURPLE_BLIST_NODE_IS_BUDDY(node)) { - account = ((PurpleBuddy*)(node))->account; + account = purple_buddy_get_account((PurpleBuddy*)(node)); } else if (PURPLE_BLIST_NODE_IS_CHAT(node)) { - account = ((PurpleChat*)(node))->account; + account = purple_chat_get_account((PurpleChat*)(node)); } td->padding = TOOLTIP_BORDER; @@ -2926,6 +2939,7 @@ pidgin_blist_paint_tip(GtkWidget *widget, gpointer null) { GtkStyle *style; + cairo_t *cr; int current_height, max_width; int max_text_width; int max_avatar_width; @@ -2959,6 +2973,7 @@ else prpl_col = TOOLTIP_BORDER + status_size + SMALL_SPACE + max_text_width - PRPL_SIZE; + cr = gdk_cairo_create(GDK_DRAWABLE(gtk_widget_get_window(gtkblist->tipwindow))); current_height = 12; for(l = gtkblist->tooltipdata; l; l = l->next) { @@ -2978,30 +2993,37 @@ } if (td->status_icon) { - if (dir == GTK_TEXT_DIR_RTL) - gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, td->status_icon, - 0, 0, max_width - TOOLTIP_BORDER - status_size, current_height, -1, -1, GDK_RGB_DITHER_NONE, 0, 0); - else - gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, td->status_icon, - 0, 0, TOOLTIP_BORDER, current_height, -1 , -1, GDK_RGB_DITHER_NONE, 0, 0); + if (dir == GTK_TEXT_DIR_RTL) { + gdk_cairo_set_source_pixbuf(cr, td->status_icon, + max_width - TOOLTIP_BORDER - status_size, + current_height); + cairo_paint(cr); + } else { + gdk_cairo_set_source_pixbuf(cr, td->status_icon, + TOOLTIP_BORDER, current_height); + cairo_paint(cr); + } } if(td->avatar) { - if (dir == GTK_TEXT_DIR_RTL) - gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, - td->avatar, 0, 0, TOOLTIP_BORDER, current_height, -1, -1, GDK_RGB_DITHER_NONE, 0, 0); - else - gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, - td->avatar, 0, 0, max_width - (td->avatar_width + TOOLTIP_BORDER), - current_height, -1 , -1, GDK_RGB_DITHER_NONE, 0, 0); - } - - if (!td->avatar_is_prpl_icon && td->prpl_icon) - gdk_draw_pixbuf(GDK_DRAWABLE(gtkblist->tipwindow->window), NULL, td->prpl_icon, - 0, 0, - prpl_col, - current_height + ((td->name_height / 2) - (PRPL_SIZE / 2)), - -1 , -1, GDK_RGB_DITHER_NONE, 0, 0); + if (dir == GTK_TEXT_DIR_RTL) { + gdk_cairo_set_source_pixbuf(cr, td->avatar, + TOOLTIP_BORDER, current_height); + cairo_paint(cr); + } else { + gdk_cairo_set_source_pixbuf(cr, td->avatar, + max_width - (td->avatar_width + TOOLTIP_BORDER), + current_height); + cairo_paint(cr); + } + } + + if (!td->avatar_is_prpl_icon && td->prpl_icon) { + gdk_cairo_set_source_pixbuf(cr, td->prpl_icon, prpl_col, + current_height + + (td->name_height - PRPL_SIZE) / 2); + cairo_paint(cr); + } if (td->name_layout) { if (dir == GTK_TEXT_DIR_RTL) { @@ -3032,6 +3054,8 @@ current_height += MAX(td->name_height + td->height, td->avatar_height) + td->padding; } + + cairo_destroy(cr); return FALSE; } @@ -3172,7 +3196,7 @@ return FALSE; } - gtknode = node->ui_data; + gtknode = purple_blist_node_get_ui_data(node); if (!gtknode->contact_expanded) { GtkTreeIter i; @@ -3201,13 +3225,13 @@ if(!buddy) return FALSE; - gtknode = ((PurpleBlistNode*)buddy)->ui_data; - - return (purple_account_is_connected(buddy->account) && - (purple_presence_is_online(buddy->presence) || + gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy)); + + return (purple_account_is_connected(purple_buddy_get_account(buddy)) && + (purple_presence_is_online(purple_buddy_get_presence(buddy)) || (gtknode && gtknode->recent_signonoff) || purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies") || - purple_blist_node_get_bool((PurpleBlistNode*)buddy, "show_offline"))); + purple_blist_node_get_bool(PURPLE_BLIST_NODE(buddy), "show_offline"))); } void pidgin_blist_draw_tooltip(PurpleBlistNode *node, GtkWidget *widget) @@ -3382,7 +3406,7 @@ const char *text; PurpleAccount *account = purple_connection_get_account(gc); - if (gc->flags & PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES) { + if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES) { PurpleRequestField *text_field; text_field = purple_request_fields_get_field(fields, "text"); text = purple_request_field_string_get_value(text_field); @@ -3398,7 +3422,7 @@ PurpleAccount *account = (PurpleAccount *) accounts->data; PurpleConnection *gc = purple_account_get_connection(account); - if (gc && gc->flags & PURPLE_CONNECTION_SUPPORT_MOODS) { + if (gc && (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOODS)) { update_status_with_mood(account, mood, NULL); } } @@ -3433,9 +3457,9 @@ if (purple_account_is_connected(account)) { PurpleConnection *gc = purple_account_get_connection(account); - if (gc->flags & PURPLE_CONNECTION_SUPPORT_MOODS) { + if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOODS) { PurplePluginProtocolInfo *prpl_info = - PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); PurpleMood *mood = NULL; /* PURPLE_CONNECTION_SUPPORT_MOODS would not be set if the prpl doesn't @@ -3493,7 +3517,7 @@ PurpleAccount *account = (PurpleAccount *) accounts->data; if (purple_account_is_connected(account) && - (purple_account_get_connection(account)->flags & + (purple_connection_get_flags(purple_account_get_connection(account)) & PURPLE_CONNECTION_SUPPORT_MOODS)) { PurplePresence *presence = purple_account_get_presence(account); PurpleStatus *status = purple_presence_get_status(presence, "mood"); @@ -3528,8 +3552,8 @@ PurplePresence *presence = purple_account_get_presence(account); PurpleStatus *status = purple_presence_get_status(presence, "mood"); gc = purple_account_get_connection(account); - g_return_if_fail(gc->prpl != NULL); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + g_return_if_fail(purple_connection_get_prpl(gc) != NULL); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); current_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME); } else { current_mood = get_global_mood_status(); @@ -3539,7 +3563,7 @@ g = purple_request_field_group_new(NULL); f = purple_request_field_list_new("mood", _("Please select your mood from the list")); - purple_request_field_list_add(f, _("None"), ""); + purple_request_field_list_add_icon(f, _("None"), NULL, ""); if (current_mood == NULL) purple_request_field_list_add_selected(f, _("None")); @@ -3568,7 +3592,7 @@ purple_request_fields_add_group(fields, g); /* if the connection allows setting a mood message */ - if (gc && (gc->flags & PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES)) { + if (gc && (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES)) { g = purple_request_field_group_new(NULL); f = purple_request_field_string_new("text", _("Message (optional)"), NULL, FALSE); @@ -3595,64 +3619,121 @@ /*************************************************** * Crap * ***************************************************/ -static GtkItemFactoryEntry blist_menu[] = -{ +/* TODO: fill out tooltips... */ +static const GtkActionEntry blist_menu_entries[] = { /* NOTE: Do not set any accelerator to Control+O. It is mapped by gtk_blist_key_press_cb to "Get User Info" on the selected buddy. */ - /* Buddies menu */ - { N_("/_Buddies"), NULL, NULL, 0, "", NULL }, - { N_("/Buddies/New Instant _Message..."), "M", pidgin_dialogs_im, 0, "", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW }, - { N_("/Buddies/Join a _Chat..."), "C", pidgin_blist_joinchat_show, 0, "", PIDGIN_STOCK_CHAT }, - { N_("/Buddies/Get User _Info..."), "I", pidgin_dialogs_info, 0, "", PIDGIN_STOCK_TOOLBAR_USER_INFO }, - { N_("/Buddies/View User _Log..."), "L", pidgin_dialogs_log, 0, "", NULL }, - { "/Buddies/sep1", NULL, NULL, 0, "", NULL }, - { N_("/Buddies/Sh_ow"), NULL, NULL, 0, "", NULL}, - { N_("/Buddies/Show/_Offline Buddies"), NULL, pidgin_blist_edit_mode_cb, 1, "", NULL }, - { N_("/Buddies/Show/_Empty Groups"), NULL, pidgin_blist_show_empty_groups_cb, 1, "", NULL }, - { N_("/Buddies/Show/Buddy _Details"), NULL, pidgin_blist_buddy_details_cb, 1, "", NULL }, - { N_("/Buddies/Show/Idle _Times"), NULL, pidgin_blist_show_idle_time_cb, 1, "", NULL }, - { N_("/Buddies/Show/_Protocol Icons"), NULL, pidgin_blist_show_protocol_icons_cb, 1, "", NULL }, - { N_("/Buddies/_Sort Buddies"), NULL, NULL, 0, "", NULL }, - { "/Buddies/sep2", NULL, NULL, 0, "", NULL }, - { N_("/Buddies/_Add Buddy..."), "B", pidgin_blist_add_buddy_cb, 0, "", GTK_STOCK_ADD }, - { N_("/Buddies/Add C_hat..."), NULL, pidgin_blist_add_chat_cb, 0, "", GTK_STOCK_ADD }, - { N_("/Buddies/Add _Group..."), NULL, purple_blist_request_add_group, 0, "", GTK_STOCK_ADD }, - { "/Buddies/sep3", NULL, NULL, 0, "", NULL }, - { N_("/Buddies/_Quit"), "Q", purple_core_quit, 0, "", GTK_STOCK_QUIT }, + { "BuddiesMenu", NULL, N_("_Buddies"), NULL, NULL, NULL }, + { "NewInstantMessage", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, N_("New Instant _Message..."), "M", NULL, pidgin_dialogs_im }, + { "JoinAChat", PIDGIN_STOCK_CHAT, N_("Join a _Chat..."), "C", NULL, pidgin_blist_joinchat_show }, + { "GetUserInfo", PIDGIN_STOCK_TOOLBAR_USER_INFO, N_("Get User _Info..."), "I", NULL, pidgin_dialogs_info }, + { "ViewUserLog", NULL, N_("View User _Log..."), "L", NULL, pidgin_dialogs_log }, + { "ShowMenu", NULL, N_("Sh_ow"), NULL, NULL, NULL }, + { "SortMenu", NULL, N_("_Sort Buddies"), NULL, NULL, NULL }, + { "AddBuddy", GTK_STOCK_ADD, N_("_Add Buddy..."), "B", NULL, pidgin_blist_add_buddy_cb }, + { "AddChat", GTK_STOCK_ADD, N_("Add C_hat..."), NULL, NULL, pidgin_blist_add_chat_cb }, + { "AddGroup", GTK_STOCK_ADD, N_("Add _Group..."), NULL, NULL, purple_blist_request_add_group }, + { "Quit", GTK_STOCK_QUIT, N_("_Quit"), "Q", NULL, purple_core_quit }, /* Accounts menu */ - { N_("/_Accounts"), NULL, NULL, 0, "", NULL }, - { N_("/Accounts/Manage Accounts"), "A", pidgin_accounts_window_show, 0, "", NULL }, + { "AccountsMenu", NULL, N_("_Accounts"), NULL, NULL, NULL }, + { "ManageAccounts", NULL, N_("Manage Accounts"), "A", NULL, pidgin_accounts_window_show }, /* Tools */ - { N_("/_Tools"), NULL, NULL, 0, "", NULL }, - { N_("/Tools/Buddy _Pounces"), NULL, pidgin_pounces_manager_show, 1, "", NULL }, - { N_("/Tools/_Certificates"), NULL, pidgin_certmgr_show, 0, "", NULL }, - { N_("/Tools/Custom Smile_ys"), "Y", pidgin_smiley_manager_show, 0, "", PIDGIN_STOCK_TOOLBAR_SMILEY }, - { N_("/Tools/Plu_gins"), "U", pidgin_plugin_dialog_show, 2, "", PIDGIN_STOCK_TOOLBAR_PLUGINS }, - { N_("/Tools/Pr_eferences"), "P", pidgin_prefs_show, 0, "", GTK_STOCK_PREFERENCES }, - { N_("/Tools/Pr_ivacy"), NULL, pidgin_privacy_dialog_show, 0, "", NULL }, - { N_("/Tools/Set _Mood"), "D", set_mood_show, 0, "", NULL }, - { "/Tools/sep2", NULL, NULL, 0, "", NULL }, - { N_("/Tools/_File Transfers"), "T", pidgin_xfer_dialog_show, 0, "", PIDGIN_STOCK_TOOLBAR_TRANSFER }, - { N_("/Tools/R_oom List"), NULL, pidgin_roomlist_dialog_show, 0, "", NULL }, - { N_("/Tools/System _Log"), NULL, gtk_blist_show_systemlog_cb, 3, "", NULL }, - { "/Tools/sep3", NULL, NULL, 0, "", NULL }, - { N_("/Tools/Mute _Sounds"), NULL, pidgin_blist_mute_sounds_cb, 0, "", NULL }, + { "ToolsMenu", NULL, N_("_Tools"), NULL, NULL, NULL }, + { "BuddyPounces", NULL, N_("Buddy _Pounces"), NULL, NULL, pidgin_pounces_manager_show }, + { "Certificates", NULL, N_("_Certificates"), NULL, NULL, pidgin_certmgr_show }, + { "CustomSmileys", PIDGIN_STOCK_TOOLBAR_SMILEY, N_("Custom Smile_ys"), "Y", NULL, pidgin_smiley_manager_show }, + { "Plugins", PIDGIN_STOCK_TOOLBAR_PLUGINS, N_("Plu_gins"), "U", NULL, pidgin_plugin_dialog_show }, + { "Preferences", GTK_STOCK_PREFERENCES, N_("Pr_eferences"), "P", NULL, pidgin_prefs_show }, + { "Privacy", NULL, N_("Pr_ivacy"), NULL, NULL, pidgin_privacy_dialog_show }, + { "SetMood", NULL, N_("Set _Mood"), "D", NULL, set_mood_show }, + { "FileTransfers", PIDGIN_STOCK_TOOLBAR_TRANSFER, N_("_File Transfers"), "T", NULL, G_CALLBACK(gtk_blist_show_xfer_dialog_cb) }, + { "RoomList", NULL, N_("R_oom List"), NULL, NULL, pidgin_roomlist_dialog_show }, + { "SystemLog", NULL, N_("System _Log"), NULL, NULL, gtk_blist_show_systemlog_cb }, + /* Help */ - { N_("/_Help"), NULL, NULL, 0, "", NULL }, - { N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, "", GTK_STOCK_HELP }, - { "/Help/sep1", NULL, NULL, 0, "", NULL }, - { N_("/Help/_Build Information"), NULL, pidgin_dialogs_buildinfo, 0, "", NULL }, - { N_("/Help/_Debug Window"), NULL, toggle_debug, 0, "", NULL }, - { N_("/Help/De_veloper Information"), NULL, pidgin_dialogs_developers, 0, "", NULL }, - { N_("/Help/_Plugin Information"), NULL, pidgin_dialogs_plugins_info, 0, "", NULL }, - { N_("/Help/_Translator Information"), NULL, pidgin_dialogs_translators, 0, "", NULL }, - { "/Help/sep2", NULL, NULL, 0, "", NULL }, - { N_("/Help/_About"), NULL, pidgin_dialogs_about, 4, "", GTK_STOCK_ABOUT }, + { "HelpMenu", NULL, N_("_Help"), NULL, NULL, NULL }, + { "OnlineHelp", GTK_STOCK_HELP, N_("Online _Help"), "F1", NULL, gtk_blist_show_onlinehelp_cb }, + { "BuildInformation", NULL, N_("_Build Information"), NULL, NULL, pidgin_dialogs_buildinfo }, + { "DebugWindow", NULL, N_("_Debug Window"), NULL, NULL, toggle_debug }, + { "DeveloperInformation", NULL, N_("De_veloper Information"), NULL, NULL, pidgin_dialogs_developers }, + { "PluginInformation", NULL, N_("_Plugin Information"), NULL, NULL, pidgin_dialogs_plugins_info }, + { "TranslatorInformation", NULL, N_("_Translator Information"), NULL, NULL, pidgin_dialogs_translators }, + { "About", GTK_STOCK_ABOUT, N_("_About"), NULL, NULL, pidgin_dialogs_about }, +}; + +/* Toggle items */ +static const GtkToggleActionEntry blist_menu_toggle_entries[] = { + /* Buddies->Show menu */ + { "ShowOffline", NULL, N_("_Offline Buddies"), NULL, NULL, G_CALLBACK(pidgin_blist_edit_mode_cb), FALSE }, + { "ShowEmptyGroups", NULL, N_("_Empty Groups"), NULL, NULL, G_CALLBACK(pidgin_blist_show_empty_groups_cb), FALSE }, + { "ShowBuddyDetails", NULL, N_("Buddy _Details"), NULL, NULL, G_CALLBACK(pidgin_blist_buddy_details_cb), FALSE }, + { "ShowIdleTimes", NULL, N_("Idle _Times"), NULL, NULL, G_CALLBACK(pidgin_blist_show_idle_time_cb), FALSE }, + { "ShowProtocolIcons", NULL, N_("_Protocol Icons"), NULL, NULL, G_CALLBACK(pidgin_blist_show_protocol_icons_cb), FALSE }, + + /* Tools menu */ + { "MuteSounds", NULL, N_("Mute _Sounds"), NULL, NULL, G_CALLBACK(pidgin_blist_mute_sounds_cb), FALSE }, }; +static const char *blist_menu = +"" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" +""; + /********************************************************* * Private Utility functions * *********************************************************/ @@ -3672,16 +3753,16 @@ struct proto_chat_entry *pce; char *name, *value; PurpleConversation *conv; - PidginBlistNode *bnode = node->ui_data; + PidginBlistNode *bnode = purple_blist_node_get_ui_data(node); chat = (PurpleChat *)node; - prpl = purple_find_prpl(purple_account_get_protocol_id(chat->account)); + prpl = purple_find_prpl(purple_account_get_protocol_id(purple_chat_get_account(chat))); prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); connections = purple_connections_get_all(); if (connections && connections->next) { - tmp = g_markup_escape_text(chat->account->username, -1); + tmp = g_markup_escape_text(purple_account_get_username(purple_chat_get_account(chat)), -1); g_string_append_printf(str, _("Account: %s"), tmp); g_free(tmp); } @@ -3691,12 +3772,12 @@ } else { char *chat_name; if (prpl_info && prpl_info->get_chat_name) - chat_name = prpl_info->get_chat_name(chat->components); + chat_name = prpl_info->get_chat_name(purple_chat_get_components(chat)); else chat_name = g_strdup(purple_chat_get_name(chat)); conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, chat_name, - chat->account); + purple_chat_get_account(chat)); g_free(chat_name); } @@ -3713,7 +3794,7 @@ } if (prpl_info && prpl_info->chat_info != NULL) - cur = prpl_info->chat_info(chat->account->gc); + cur = prpl_info->chat_info(purple_account_get_connection(purple_chat_get_account(chat))); else cur = NULL; @@ -3722,13 +3803,13 @@ pce = cur->data; if (!pce->secret && (!pce->required && - g_hash_table_lookup(chat->components, pce->identifier) == NULL)) + g_hash_table_lookup(purple_chat_get_components(chat), pce->identifier) == NULL)) { tmp = purple_text_strip_mnemonic(pce->label); name = g_markup_escape_text(tmp, -1); g_free(tmp); value = g_markup_escape_text(g_hash_table_lookup( - chat->components, pce->identifier), -1); + purple_chat_get_components(chat), pce->identifier), -1); g_string_append_printf(str, "\n%s %s", name ? name : "", value ? value : ""); @@ -3764,7 +3845,7 @@ c = purple_buddy_get_contact(b); } - prpl = purple_find_prpl(purple_account_get_protocol_id(b->account)); + prpl = purple_find_prpl(purple_account_get_protocol_id(purple_buddy_get_account(b))); prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); presence = purple_buddy_get_presence(b); @@ -3774,22 +3855,19 @@ connections = purple_connections_get_all(); if (full && connections && connections->next) { - tmp = g_markup_escape_text(purple_account_get_username( - purple_buddy_get_account(b)), -1); - purple_notify_user_info_add_pair(user_info, _("Account"), tmp); - g_free(tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Account"), + purple_account_get_username(purple_buddy_get_account(b))); } /* Alias */ /* If there's not a contact alias, the node is being displayed with * this alias, so there's no point in showing it in the tooltip. */ - if (full && c && b->alias != NULL && b->alias[0] != '\0' && + if (full && c && purple_buddy_get_local_buddy_alias(b) != NULL && purple_buddy_get_local_buddy_alias(b)[0] != '\0' && (c->alias != NULL && c->alias[0] != '\0') && - strcmp(c->alias, b->alias) != 0) + strcmp(c->alias, purple_buddy_get_local_buddy_alias(b)) != 0) { - tmp = g_markup_escape_text(b->alias, -1); - purple_notify_user_info_add_pair(user_info, _("Buddy Alias"), tmp); - g_free(tmp); + purple_notify_user_info_add_pair_plaintext(user_info, + _("Buddy Alias"), purple_buddy_get_local_buddy_alias(b)); } /* Nickname/Server Alias */ @@ -3797,11 +3875,10 @@ * alias, but many people on MSN set long nicknames, which * get ellipsized, so the only way to see the whole thing is * to look at the tooltip. */ - if (full && b->server_alias != NULL && b->server_alias[0] != '\0') + if (full && purple_buddy_get_server_alias(b)) { - tmp = g_markup_escape_text(b->server_alias, -1); - purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp); - g_free(tmp); + purple_notify_user_info_add_pair_plaintext(user_info, + _("Nickname"), purple_buddy_get_server_alias(b)); } /* Logged In */ @@ -3817,7 +3894,7 @@ tmp = g_strdup(purple_date_format_long(localtime(&signon))); } else tmp = purple_str_seconds_to_string(time(NULL) - signon); - purple_notify_user_info_add_pair(user_info, _("Logged In"), tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Logged In"), tmp); g_free(tmp); } @@ -3828,7 +3905,7 @@ if (idle_secs > 0) { tmp = purple_str_seconds_to_string(time(NULL) - idle_secs); - purple_notify_user_info_add_pair(user_info, _("Idle"), tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Idle"), tmp); g_free(tmp); } } @@ -3836,7 +3913,7 @@ /* Last Seen */ if (full && c && !PURPLE_BUDDY_IS_ONLINE(b)) { - struct _pidgin_blist_node *gtknode = ((PurpleBlistNode *)c)->ui_data; + struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(c)); PurpleBlistNode *bnode; int lastseen = 0; @@ -3863,7 +3940,7 @@ if (lastseen > 0) { tmp = purple_str_seconds_to_string(time(NULL) - lastseen); - purple_notify_user_info_add_pair(user_info, _("Last Seen"), tmp); + purple_notify_user_info_add_pair_plaintext(user_info, _("Last Seen"), tmp); g_free(tmp); } } @@ -3873,10 +3950,10 @@ /* FIXME: Why is this status special-cased by the core? --rlaager * FIXME: Alternatively, why not have the core do all of them? --rlaager */ if (!PURPLE_BUDDY_IS_ONLINE(b)) { - purple_notify_user_info_add_pair(user_info, _("Status"), _("Offline")); - } - - if (purple_account_is_connected(b->account) && + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), _("Offline")); + } + + if (purple_account_is_connected(purple_buddy_get_account(b)) && prpl_info && prpl_info->tooltip_text) { /* Additional text from the PRPL */ @@ -3884,12 +3961,12 @@ } /* These are Easter Eggs. Patches to remove them will be rejected. */ - if (!g_ascii_strcasecmp(b->name, "robflynn")) - purple_notify_user_info_add_pair(user_info, _("Description"), _("Spooky")); - if (!g_ascii_strcasecmp(b->name, "seanegn")) - purple_notify_user_info_add_pair(user_info, _("Status"), _("Awesome")); - if (!g_ascii_strcasecmp(b->name, "chipx86")) - purple_notify_user_info_add_pair(user_info, _("Status"), _("Rockin'")); + if (!g_ascii_strcasecmp(purple_buddy_get_name(b), "robflynn")) + purple_notify_user_info_add_pair_plaintext(user_info, _("Description"), _("Spooky")); + if (!g_ascii_strcasecmp(purple_buddy_get_name(b), "seanegn")) + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), _("Awesome")); + if (!g_ascii_strcasecmp(purple_buddy_get_name(b), "chipx86")) + purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), _("Rockin'")); tmp = purple_notify_user_info_get_text_with_newline(user_info, "\n"); g_string_append(str, tmp); @@ -3904,24 +3981,21 @@ user_info = purple_notify_user_info_new(); count = purple_blist_get_group_online_count(group); - if (count != 0) { /* Online buddies in group */ - tmp = g_strdup_printf("%d", count); - purple_notify_user_info_add_pair(user_info, - _("Online Buddies"), - tmp); - g_free(tmp); + char tmp2[12]; + sprintf(tmp2, "%d", count); + purple_notify_user_info_add_pair_plaintext(user_info, + _("Online Buddies"), tmp2); } count = purple_blist_get_group_size(group, FALSE); if (count != 0) { /* Total buddies (from online accounts) in group */ - tmp = g_strdup_printf("%d", count); - purple_notify_user_info_add_pair(user_info, - _("Total Buddies"), - tmp); - g_free(tmp); + char tmp2[12]; + sprintf(tmp2, "%d", count); + purple_notify_user_info_add_pair_html(user_info, + _("Total Buddies"), tmp2); } tmp = purple_notify_user_info_get_text_with_newline(user_info, "\n"); @@ -3968,7 +4042,7 @@ pidgin_blist_get_emblem(PurpleBlistNode *node) { PurpleBuddy *buddy = NULL; - struct _pidgin_blist_node *gtknode = node->ui_data; + struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node); PurplePlugin *prpl; PurplePluginProtocolInfo *prpl_info; const char *name = NULL; @@ -3991,10 +4065,10 @@ return _pidgin_blist_get_cached_emblem(path); } - if (((struct _pidgin_blist_node*)(node->parent->ui_data))->contact_expanded) { + if (((struct _pidgin_blist_node*)purple_blist_node_get_ui_data(node->parent))->contact_expanded) { if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons")) return NULL; - return pidgin_create_prpl_icon(((PurpleBuddy*)node)->account, PIDGIN_PRPL_ICON_SMALL); + return pidgin_create_prpl_icon(purple_buddy_get_account((PurpleBuddy*)node), PIDGIN_PRPL_ICON_SMALL); } } else { return NULL; @@ -4002,7 +4076,7 @@ g_return_val_if_fail(buddy != NULL, NULL); - if (!purple_privacy_check(buddy->account, purple_buddy_get_name(buddy))) { + if (!purple_privacy_check(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy))) { path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "blocked.png", NULL); return _pidgin_blist_get_cached_emblem(path); } @@ -4038,7 +4112,7 @@ return _pidgin_blist_get_cached_emblem(path); } - prpl = purple_find_prpl(purple_account_get_protocol_id(buddy->account)); + prpl = purple_find_prpl(purple_account_get_protocol_id(purple_buddy_get_account(buddy))); if (!prpl) return NULL; @@ -4075,7 +4149,7 @@ { GdkPixbuf *ret; const char *icon = NULL; - struct _pidgin_blist_node *gtknode = node->ui_data; + struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node); struct _pidgin_blist_node *gtkbuddynode = NULL; PurpleBuddy *buddy = NULL; PurpleChat *chat = NULL; @@ -4086,11 +4160,11 @@ if(!gtknode->contact_expanded) { buddy = purple_contact_get_priority_buddy((PurpleContact*)node); if (buddy != NULL) - gtkbuddynode = ((PurpleBlistNode*)buddy)->ui_data; + gtkbuddynode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy)); } } else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) { buddy = (PurpleBuddy*)node; - gtkbuddynode = node->ui_data; + gtkbuddynode = purple_blist_node_get_ui_data(node); } else if(PURPLE_BLIST_NODE_IS_CHAT(node)) { chat = (PurpleChat*)node; } else { @@ -4102,9 +4176,9 @@ PurplePlugin *prpl; if(buddy) - account = buddy->account; + account = purple_buddy_get_account(buddy); else - account = chat->account; + account = purple_chat_get_account(chat); prpl = purple_find_prpl(purple_account_get_protocol_id(account)); if(!prpl) @@ -4119,7 +4193,7 @@ if(conv != NULL) { PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); if (gtkconv == NULL && size == PIDGIN_STATUS_ICON_SMALL) { - PidginBlistNode *ui = buddy->node.ui_data; + PidginBlistNode *ui = purple_blist_node_get_ui_data(&(buddy->node)); if (ui == NULL || (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE)) return gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_MESSAGE, icon_size, "GtkTreeView"); @@ -4203,7 +4277,7 @@ PidginBlistTheme *theme; if (conv != NULL) { - PidginBlistNode *ui = b->node.ui_data; + PidginBlistNode *ui = purple_blist_node_get_ui_data(&(b->node)); if (ui) { if (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE) hidden_conv = TRUE; @@ -4237,12 +4311,12 @@ if (!aliased || biglist) { /* Status Info */ - prpl = purple_find_prpl(purple_account_get_protocol_id(b->account)); + prpl = purple_find_prpl(purple_account_get_protocol_id(purple_buddy_get_account(b))); if (prpl != NULL) prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (prpl_info && prpl_info->status_text && b->account->gc) { + if (prpl_info && prpl_info->status_text && purple_account_get_connection(purple_buddy_get_account(b))) { char *tmp = prpl_info->status_text(b); const char *end; @@ -4393,7 +4467,7 @@ /* if the window exists, is hidden, we're saving positions, and the * position is sane... */ if (gtkblist && gtkblist->window && - !GTK_WIDGET_VISIBLE(gtkblist->window) && blist_width != 0) { + !gtk_widget_get_visible(gtkblist->window) && blist_width != 0) { blist_x = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/x"); blist_y = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/y"); @@ -4423,7 +4497,7 @@ PurpleBlistNode *gnode, *cnode; if (gtk_blist_visibility == GDK_VISIBILITY_FULLY_OBSCURED - || !GTK_WIDGET_VISIBLE(gtkblist->window)) + || !gtk_widget_get_visible(gtkblist->window)) return TRUE; for(gnode = list->root; gnode; gnode = gnode->next) { @@ -4437,7 +4511,7 @@ if (buddy && purple_presence_is_idle(purple_buddy_get_presence(buddy))) - pidgin_blist_update_contact(list, (PurpleBlistNode*)buddy); + pidgin_blist_update_contact(list, PURPLE_BLIST_NODE(buddy)); } } } @@ -4448,7 +4522,7 @@ static void pidgin_blist_hide_node(PurpleBuddyList *list, PurpleBlistNode *node, gboolean update) { - struct _pidgin_blist_node *gtknode = (struct _pidgin_blist_node *)node->ui_data; + struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node); GtkTreeIter iter; if (!gtknode || !gtknode->row || !gtkblist) @@ -4469,12 +4543,13 @@ static const char *require_connection[] = { - N_("/Buddies/New Instant Message..."), - N_("/Buddies/Join a Chat..."), - N_("/Buddies/Get User Info..."), - N_("/Buddies/Add Buddy..."), - N_("/Buddies/Add Chat..."), - N_("/Buddies/Add Group..."), + "/BList/BuddiesMenu/NewInstantMessage", + "/BList/BuddiesMenu/JoinAChat", + "/BList/BuddiesMenu/GetUserInfo", + "/BList/BuddiesMenu/AddBuddy", + "/BList/BuddiesMenu/AddChat", + "/BList/BuddiesMenu/AddGroup", + "/BList/ToolsMenu/Privacy", }; static const int require_connection_size = sizeof(require_connection) @@ -4487,7 +4562,7 @@ static void update_menu_bar(PidginBuddyList *gtkblist) { - GtkWidget *widget; + GtkAction *action; gboolean sensitive; int i; @@ -4499,21 +4574,18 @@ for (i = 0; i < require_connection_size; i++) { - widget = gtk_item_factory_get_widget(gtkblist->ift, require_connection[i]); - gtk_widget_set_sensitive(widget, sensitive); - } - - widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Buddies/Join a Chat...")); - gtk_widget_set_sensitive(widget, pidgin_blist_joinchat_is_showable()); - - widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Buddies/Add Chat...")); - gtk_widget_set_sensitive(widget, pidgin_blist_joinchat_is_showable()); - - widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Privacy")); - gtk_widget_set_sensitive(widget, sensitive); - - widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Room List")); - gtk_widget_set_sensitive(widget, pidgin_roomlist_is_showable()); + action = gtk_ui_manager_get_action(gtkblist->ui, require_connection[i]); + gtk_action_set_sensitive(action, sensitive); + } + + action = gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/JoinAChat"); + gtk_action_set_sensitive(action, pidgin_blist_joinchat_is_showable()); + + action = gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/AddChat"); + gtk_action_set_sensitive(action, pidgin_blist_joinchat_is_showable()); + + action = gtk_ui_manager_get_action(gtkblist->ui, "/BList/ToolsMenu/RoomList"); + gtk_action_set_sensitive(action, pidgin_roomlist_is_showable()); } static void @@ -4597,6 +4669,7 @@ conversation_updated_cb(PurpleConversation *conv, PurpleConvUpdateType type, PidginBuddyList *gtkblist) { + PurpleAccount *account = purple_conversation_get_account(conv); GList *convs = NULL; GList *ims, *chats; GList *l = NULL; @@ -4604,10 +4677,10 @@ if (type != PURPLE_CONV_UPDATE_UNSEEN) return; - if(conv->account != NULL && conv->name != NULL) { - PurpleBuddy *buddy = purple_find_buddy(conv->account, conv->name); + if(account != NULL && purple_conversation_get_name(conv) != NULL) { + PurpleBuddy *buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); if(buddy != NULL) - pidgin_blist_update_buddy(NULL, (PurpleBlistNode *)buddy, TRUE); + pidgin_blist_update_buddy(NULL, PURPLE_BLIST_NODE(buddy), TRUE); } if (gtkblist->menutrayicon) { @@ -4687,7 +4760,7 @@ written_msg_update_ui_cb(PurpleAccount *account, const char *who, const char *message, PurpleConversation *conv, PurpleMessageFlags flag, PurpleBlistNode *node) { - PidginBlistNode *ui = node->ui_data; + PidginBlistNode *ui = purple_blist_node_get_ui_data(node); if (ui->conv.conv != conv || !pidgin_conv_is_hidden(PIDGIN_CONVERSATION(conv)) || !(flag & (PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_RECV))) return; @@ -4703,7 +4776,7 @@ static void displayed_msg_update_ui_cb(PidginConversation *gtkconv, PurpleBlistNode *node) { - PidginBlistNode *ui = node->ui_data; + PidginBlistNode *ui = purple_blist_node_get_ui_data(node); if (ui->conv.conv != gtkconv->active_conv) return; ui->conv.flags &= ~(PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE | @@ -4714,13 +4787,15 @@ static void conversation_created_cb(PurpleConversation *conv, PidginBuddyList *gtkblist) { - switch (conv->type) { + PurpleAccount *account = purple_conversation_get_account(conv); + + switch (purple_conversation_get_type(conv)) { case PURPLE_CONV_TYPE_IM: { - GSList *buddies = purple_find_buddies(conv->account, conv->name); + GSList *buddies = purple_find_buddies(account, purple_conversation_get_name(conv)); while (buddies) { PurpleBlistNode *buddy = buddies->data; - struct _pidgin_blist_node *ui = buddy->ui_data; + struct _pidgin_blist_node *ui = purple_blist_node_get_ui_data(buddy); buddies = g_slist_delete_link(buddies, buddies); if (!ui) continue; @@ -4738,11 +4813,11 @@ break; case PURPLE_CONV_TYPE_CHAT: { - PurpleChat *chat = purple_blist_find_chat(conv->account, conv->name); + PurpleChat *chat = purple_blist_find_chat(account, purple_conversation_get_name(conv)); struct _pidgin_blist_node *ui; if (!chat) break; - ui = chat->node.ui_data; + ui = purple_blist_node_get_ui_data(&(chat->node)); if (!ui) break; ui->conv.conv = conv; @@ -4770,8 +4845,6 @@ PidginBuddyList *gtkblist; gtkblist = g_new0(PidginBuddyList, 1); - gtkblist->connection_errors = g_hash_table_new_full(g_direct_hash, - g_direct_equal, NULL, g_free); gtkblist->priv = g_new0(PidginBuddyListPrivate, 1); blist->ui_data = gtkblist; @@ -4779,7 +4852,7 @@ static void pidgin_blist_new_node(PurpleBlistNode *node) { - node->ui_data = g_new0(struct _pidgin_blist_node, 1); + purple_blist_node_set_ui_data(node, g_new0(struct _pidgin_blist_node, 1)); } gboolean pidgin_blist_node_is_contact_expanded(PurpleBlistNode *node) @@ -4792,7 +4865,7 @@ g_return_val_if_fail(PURPLE_BLIST_NODE_IS_CONTACT(node), FALSE); - return ((struct _pidgin_blist_node *)node->ui_data)->contact_expanded; + return ((struct _pidgin_blist_node *)purple_blist_node_get_ui_data(node))->contact_expanded; } enum { @@ -4804,12 +4877,6 @@ NUM_TARGETS }; -static const char * -item_factory_translate_func (const char *path, gpointer func_data) -{ - return _((char *)path); -} - void pidgin_blist_setup_sort_methods() { const char *id; @@ -4848,7 +4915,7 @@ struct _pidgin_blist_node *gtknode; GtkTreePath *path; - gtknode = node->ui_data; + gtknode = purple_blist_node_get_ui_data(node); if (gtknode && gtknode->row) { path = gtk_tree_row_reference_get_path(gtknode->row); @@ -5085,7 +5152,6 @@ generic_error_destroy_cb(GtkObject *dialog, PurpleAccount *account) { - g_hash_table_remove(gtkblist->connection_errors, account); /* If the error dialog is being destroyed in response to the * account-error-changed signal, we don't want to clear the current * error. @@ -5356,12 +5422,6 @@ if (old == NULL && new == NULL) return; - /* For backwards compatibility: */ - if (new) - pidgin_blist_update_account_error_state(account, new->description); - else - pidgin_blist_update_account_error_state(account, NULL); - if (new != NULL) pidgin_blist_select_notebook_page(gtkblist); @@ -5427,18 +5487,6 @@ } } -void -pidgin_blist_update_account_error_state(PurpleAccount *account, const char *text) -{ - /* connection_errors isn't actually used anywhere; it's just kept in - * sync with reality in case a plugin uses it. - */ - if (text == NULL) - g_hash_table_remove(gtkblist->connection_errors, account); - else - g_hash_table_insert(gtkblist->connection_errors, account, g_strdup(text)); -} - static gboolean paint_headline_hbox (GtkWidget *widget, GdkEventExpose *event, @@ -5478,8 +5526,28 @@ headline_style_set (GtkWidget *widget, GtkStyle *prev_style) { + GtkStyle *style; +#if GTK_CHECK_VERSION(2,12,0) + GtkWidget *window; + + if (gtkblist->changing_style) + return; + + /* This is a hack needed to use the tooltip background colour */ + window = gtk_window_new(GTK_WINDOW_POPUP); + gtk_widget_set_name(window, "gtk-tooltip"); + gtk_widget_ensure_style(window); + style = gtk_widget_get_style(window); + + gtkblist->changing_style = TRUE; + gtk_widget_set_style(gtkblist->headline_hbox, style); + gtkblist->changing_style = FALSE; + + gtk_widget_destroy(window); + + gtk_widget_queue_draw(gtkblist->headline_hbox); +#else GtkTooltips *tooltips; - GtkStyle *style; if (gtkblist->changing_style) return; @@ -5488,9 +5556,6 @@ g_object_ref_sink (tooltips); gtk_tooltips_force_window (tooltips); -#if GTK_CHECK_VERSION(2, 12, 0) - gtk_widget_set_name (tooltips->tip_window, "gtk-tooltips"); -#endif gtk_widget_ensure_style (tooltips->tip_window); style = gtk_widget_get_style (tooltips->tip_window); @@ -5499,6 +5564,7 @@ gtkblist->changing_style = FALSE; g_object_unref (tooltips); +#endif } /******************************************/ @@ -5735,6 +5801,8 @@ GtkWidget *close; char *pretty, *tmp; const char *theme_name; + GtkActionGroup *action_group; + GError *error; GtkAccelGroup *accel_group; GtkTreeSelection *selection; GtkTargetEntry dte[] = {{"PURPLE_BLIST_NODE", GTK_TARGET_SAME_APP, DRAG_ROW}, @@ -5784,27 +5852,45 @@ gtk_widget_add_events(gtkblist->window, GDK_VISIBILITY_NOTIFY_MASK); /******************************* Menu bar *************************************/ - accel_group = gtk_accel_group_new(); - gtk_window_add_accel_group(GTK_WINDOW (gtkblist->window), accel_group); - g_object_unref(accel_group); - gtkblist->ift = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "", accel_group); - gtk_item_factory_set_translate_func(gtkblist->ift, - (GtkTranslateFunc)item_factory_translate_func, - NULL, NULL); - gtk_item_factory_create_items(gtkblist->ift, sizeof(blist_menu) / sizeof(*blist_menu), - blist_menu, NULL); + action_group = gtk_action_group_new("BListActions"); + gtk_action_group_add_actions(action_group, + blist_menu_entries, + G_N_ELEMENTS(blist_menu_entries), + GTK_WINDOW(gtkblist->window)); + gtk_action_group_add_toggle_actions(action_group, + blist_menu_toggle_entries, + G_N_ELEMENTS(blist_menu_toggle_entries), + GTK_WINDOW(gtkblist->window)); +#ifdef ENABLE_NLS + gtk_action_group_set_translation_domain(action_group, + PACKAGE); +#endif + + gtkblist->ui = gtk_ui_manager_new(); + gtk_ui_manager_insert_action_group(gtkblist->ui, action_group, 0); + + accel_group = gtk_ui_manager_get_accel_group(gtkblist->ui); + gtk_window_add_accel_group(GTK_WINDOW(gtkblist->window), accel_group); pidgin_load_accels(); g_signal_connect(G_OBJECT(accel_group), "accel-changed", G_CALLBACK(pidgin_save_accels_cb), NULL); - menu = gtk_item_factory_get_widget(gtkblist->ift, ""); + error = NULL; + if (!gtk_ui_manager_add_ui_from_string(gtkblist->ui, blist_menu, -1, &error)) + { + g_message("building menus failed: %s", error->message); + g_error_free(error); + exit(EXIT_FAILURE); + } + + menu = gtk_ui_manager_get_widget(gtkblist->ui, "/BList"); gtkblist->menutray = pidgin_menu_tray_new(); gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtkblist->menutray); gtk_widget_show(gtkblist->menutray); gtk_widget_show(menu); gtk_box_pack_start(GTK_BOX(gtkblist->main_vbox), menu, FALSE, FALSE, 0); - accountmenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Accounts")); - + menu = gtk_ui_manager_get_widget(gtkblist->ui, "/BList/AccountsMenu"); + accountmenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu)); /****************************** Notebook *************************************/ gtkblist->notebook = gtk_notebook_new(); @@ -5992,26 +6078,26 @@ /* set the Show Offline Buddies option. must be done * after the treeview or faceprint gets mad. -Robot101 */ - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Offline Buddies"))), + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/ShowMenu/ShowOffline")), purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies")); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Empty Groups"))), + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/ShowMenu/ShowEmptyGroups")), purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_empty_groups")); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Tools/Mute Sounds"))), + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, "/BList/ToolsMenu/MuteSounds")), purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/sound/mute")); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Buddy Details"))), + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/ShowMenu/ShowBuddyDetails")), purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons")); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Idle Times"))), + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/ShowMenu/ShowIdleTimes")), purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_idle_time")); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Protocol Icons"))), + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/ShowMenu/ShowProtocolIcons")), purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons")); if(!strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"), "none")) - gtk_widget_set_sensitive(gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Mute Sounds")), FALSE); + gtk_action_set_sensitive(gtk_ui_manager_get_action(gtkblist->ui, "/BList/ToolsMenu/MuteSounds"), FALSE); /* Update some dynamic things */ update_menu_bar(gtkblist); @@ -6153,7 +6239,7 @@ } static gboolean get_iter_from_node(PurpleBlistNode *node, GtkTreeIter *iter) { - struct _pidgin_blist_node *gtknode = (struct _pidgin_blist_node *)node->ui_data; + struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node); GtkTreePath *path; if (!gtknode) { @@ -6182,7 +6268,7 @@ static void pidgin_blist_remove(PurpleBuddyList *list, PurpleBlistNode *node) { - struct _pidgin_blist_node *gtknode = node->ui_data; + struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node); purple_request_close_with_handle(node); @@ -6204,9 +6290,9 @@ if(gtknode->recent_signonoff_timer > 0) purple_timeout_remove(gtknode->recent_signonoff_timer); - purple_signals_disconnect_by_handle(node->ui_data); - g_free(node->ui_data); - node->ui_data = NULL; + purple_signals_disconnect_by_handle(gtknode); + g_free(gtknode); + purple_blist_node_set_ui_data(node, NULL); } } @@ -6250,8 +6336,8 @@ static gboolean insert_node(PurpleBuddyList *list, PurpleBlistNode *node, GtkTreeIter *iter) { - GtkTreeIter parent_iter, cur, *curptr = NULL; - struct _pidgin_blist_node *gtknode = node->ui_data; + GtkTreeIter parent_iter = {0, NULL, NULL, NULL}, cur, *curptr = NULL; + struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node); GtkTreePath *newpath; if(!iter) @@ -6273,7 +6359,7 @@ gtk_tree_row_reference_free(gtknode->row); } else { pidgin_blist_new_node(node); - gtknode = (struct _pidgin_blist_node *)node->ui_data; + gtknode = purple_blist_node_get_ui_data(node); } newpath = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), @@ -6291,7 +6377,7 @@ if(node->parent) { GtkTreePath *expand = NULL; - struct _pidgin_blist_node *gtkparentnode = node->parent->ui_data; + struct _pidgin_blist_node *gtkparentnode = purple_blist_node_get_ui_data(node->parent); if(PURPLE_BLIST_NODE_IS_GROUP(node->parent)) { if(!purple_blist_node_get_bool(node->parent, "collapsed")) @@ -6313,12 +6399,12 @@ { PurpleBlistNode *gnode, *cnode, *bnode; - gnode = (PurpleBlistNode *)group; + gnode = PURPLE_BLIST_NODE(group); for(cnode = gnode->child; cnode; cnode = cnode->next) { if(PURPLE_BLIST_NODE_IS_CONTACT(cnode)) { for(bnode = cnode->child; bnode; bnode = bnode->next) { PurpleBuddy *buddy = (PurpleBuddy *)bnode; - if (purple_account_is_connected(buddy->account) && + if (purple_account_is_connected(purple_buddy_get_account(buddy)) && purple_blist_node_get_bool(bnode, "show_offline")) return TRUE; } @@ -6458,7 +6544,7 @@ text_color = selected ? NULL : theme_font_get_color_default(pair, NULL); text_font = theme_font_get_face_default(pair, ""); - esc = g_markup_escape_text(group->name, -1); + esc = g_markup_escape_text(purple_group_get_name(group), -1); if (text_color) { mark = g_strdup_printf("%s%s%s%s", text_color, text_font, @@ -6485,7 +6571,7 @@ GdkColor *color = NULL; char *mark; char *idle = NULL; - gboolean expanded = ((struct _pidgin_blist_node *)(node->parent->ui_data))->contact_expanded; + gboolean expanded = ((struct _pidgin_blist_node *)purple_blist_node_get_ui_data(node->parent))->contact_expanded; gboolean selected = (gtkblist->selected_node == node); gboolean biglist = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"); PidginBlistTheme *theme; @@ -6493,12 +6579,12 @@ if (editing_blist) return; - status = pidgin_blist_get_status_icon((PurpleBlistNode*)buddy, + status = pidgin_blist_get_status_icon(PURPLE_BLIST_NODE(buddy), biglist ? PIDGIN_STATUS_ICON_LARGE : PIDGIN_STATUS_ICON_SMALL); /* Speed it up if we don't want buddy icons. */ if(biglist) - avatar = pidgin_blist_get_buddy_icon((PurpleBlistNode *)buddy, TRUE, TRUE); + avatar = pidgin_blist_get_buddy_icon(PURPLE_BLIST_NODE(buddy), TRUE, TRUE); else avatar = NULL; @@ -6509,7 +6595,7 @@ do_alphashift(avatar, 77); } - emblem = pidgin_blist_get_emblem((PurpleBlistNode*) buddy); + emblem = pidgin_blist_get_emblem(PURPLE_BLIST_NODE(buddy)); mark = pidgin_blist_get_name_markup(buddy, selected, TRUE); theme = pidgin_blist_get_theme(); @@ -6550,7 +6636,7 @@ } } - prpl_icon = pidgin_create_prpl_icon(buddy->account, PIDGIN_PRPL_ICON_SMALL); + prpl_icon = pidgin_create_prpl_icon(purple_buddy_get_account(buddy), PIDGIN_PRPL_ICON_SMALL); if (theme != NULL) color = pidgin_blist_theme_get_contact_color(theme); @@ -6621,7 +6707,7 @@ if(!insert_node(list, cnode, &iter)) return; - gtknode = (struct _pidgin_blist_node *)cnode->ui_data; + gtknode = purple_blist_node_get_ui_data(cnode); if(gtknode->contact_expanded) { GdkPixbuf *status; @@ -6698,7 +6784,7 @@ /* First things first, update the contact */ pidgin_blist_update_contact(list, node); - gtkparentnode = (struct _pidgin_blist_node *)node->parent->ui_data; + gtkparentnode = purple_blist_node_get_ui_data(node->parent); if (gtkparentnode->contact_expanded && buddy_is_displayable(buddy)) { @@ -6729,7 +6815,7 @@ chat = (PurpleChat*)node; - if(purple_account_is_connected(chat->account)) { + if(purple_account_is_connected(purple_chat_get_account(chat))) { GtkTreeIter iter; GdkPixbuf *status, *avatar, *emblem, *prpl_icon; const gchar *color, *font; @@ -6748,7 +6834,7 @@ if (!insert_node(list, node, &iter)) return; - ui = node->ui_data; + ui = purple_blist_node_get_ui_data(node); conv = ui->conv.conv; if (conv && pidgin_conv_is_hidden(PIDGIN_CONVERSATION(conv))) { hidden = (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE); @@ -6793,7 +6879,7 @@ g_free(mark); mark = tmp; - prpl_icon = pidgin_create_prpl_icon(chat->account, PIDGIN_PRPL_ICON_SMALL); + prpl_icon = pidgin_create_prpl_icon(purple_chat_get_account(chat), PIDGIN_PRPL_ICON_SMALL); if (theme != NULL) bgcolor = pidgin_blist_theme_get_contact_color(theme); @@ -6834,10 +6920,10 @@ if(!gtkblist || !gtkblist->treeview || !node) return; - if (node->ui_data == NULL) + if (purple_blist_node_get_ui_data(node) == NULL) pidgin_blist_new_node(node); - switch(node->type) { + switch (purple_blist_node_get_type(node)) { case PURPLE_BLIST_GROUP_NODE: pidgin_blist_update_group(list, node); break; @@ -6868,7 +6954,7 @@ purple_signals_disconnect_by_handle(gtkblist); if (gtkblist->headline_close) - gdk_pixbuf_unref(gtkblist->headline_close); + g_object_unref(G_OBJECT(gtkblist->headline_close)); gtk_widget_destroy(gtkblist->window); @@ -6881,14 +6967,13 @@ if (gtkblist->drag_timeout) g_source_remove(gtkblist->drag_timeout); - g_hash_table_destroy(gtkblist->connection_errors); gtkblist->refresh_timer = 0; gtkblist->timeout = 0; gtkblist->drag_timeout = 0; gtkblist->window = gtkblist->vbox = gtkblist->treeview = NULL; g_object_unref(G_OBJECT(gtkblist->treemodel)); gtkblist->treemodel = NULL; - g_object_unref(G_OBJECT(gtkblist->ift)); + g_object_unref(G_OBJECT(gtkblist->ui)); g_object_unref(G_OBJECT(gtkblist->empty_avatar)); gdk_cursor_unref(gtkblist->hand_cursor); @@ -6913,7 +6998,7 @@ return; if (show) { - if(!PIDGIN_WINDOW_ICONIFIED(gtkblist->window) && !GTK_WIDGET_VISIBLE(gtkblist->window)) + if(!PIDGIN_WINDOW_ICONIFIED(gtkblist->window) && !gtk_widget_get_visible(gtkblist->window)) purple_signal_emit(pidgin_blist_get_handle(), "gtkblist-unhiding", gtkblist); pidgin_blist_restore_position(); gtk_window_present(GTK_WINDOW(gtkblist->window)); @@ -6922,7 +7007,7 @@ purple_signal_emit(pidgin_blist_get_handle(), "gtkblist-hiding", gtkblist); gtk_widget_hide(gtkblist->window); } else { - if (!GTK_WIDGET_VISIBLE(gtkblist->window)) + if (!gtk_widget_get_visible(gtkblist->window)) gtk_widget_show(gtkblist->window); gtk_window_iconify(GTK_WINDOW(gtkblist->window)); } @@ -6933,7 +7018,6 @@ groups_tree(void) { static GList *list = NULL; - char *tmp2; PurpleGroup *g; PurpleBlistNode *gnode; @@ -6953,8 +7037,7 @@ if (PURPLE_BLIST_NODE_IS_GROUP(gnode)) { g = (PurpleGroup *)gnode; - tmp2 = g->name; - list = g_list_append(list, tmp2); + list = g_list_append(list, (char *) purple_group_get_name(g)); } } } @@ -7037,11 +7120,11 @@ purple_blist_add_buddy(b, NULL, g, NULL); } - purple_account_add_buddy_with_invite(account, b, invite); + purple_account_add_buddy(account, b, invite); /* Offer to merge people with the same alias. */ if (whoalias != NULL && g != NULL) - gtk_blist_auto_personize((PurpleBlistNode *)g, whoalias); + gtk_blist_auto_personize(PURPLE_BLIST_NODE(g), whoalias); /* * XXX @@ -7189,10 +7272,10 @@ purple_blist_add_chat(chat, group, NULL); if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->autojoin))) - purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-autojoin", TRUE); + purple_blist_node_set_bool(PURPLE_BLIST_NODE(chat), "gtk-autojoin", TRUE); if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->persistent))) - purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-persistent", TRUE); + purple_blist_node_set_bool(PURPLE_BLIST_NODE(chat), "gtk-persistent", TRUE); } gtk_widget_destroy(data->chat_data.rq_data.window); @@ -7229,11 +7312,13 @@ GList *l; PurpleConnection *gc; GtkBox *vbox; + PurplePluginProtocolInfo *prpl_info = NULL; if (account != NULL) { gc = purple_account_get_connection(account); - - if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->join_chat == NULL) { + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + + if (prpl_info->join_chat == NULL) { purple_notify_error(gc, NULL, _("This protocol does not support chat rooms."), NULL); return; } @@ -7241,8 +7326,9 @@ /* Find an account with chat capabilities */ for (l = purple_connections_get_all(); l != NULL; l = l->next) { gc = (PurpleConnection *)l->data; - - if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->join_chat != NULL) { + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + + if (prpl_info->join_chat != NULL) { account = purple_connection_get_account(gc); break; } @@ -7286,7 +7372,7 @@ if (name != NULL) gtk_widget_grab_focus(data->alias_entry); - data->group_combo = pidgin_text_combo_box_entry_new(group ? group->name : NULL, groups_tree()); + data->group_combo = pidgin_text_combo_box_entry_new(group ? purple_group_get_name(group) : NULL, groups_tree()); pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Group:"), data->chat_data.rq_data.sg, data->group_combo, TRUE, NULL); @@ -7327,7 +7413,7 @@ pidgin_blist_toggle_visibility() { if (gtkblist && gtkblist->window) { - if (GTK_WIDGET_VISIBLE(gtkblist->window)) { + if (gtk_widget_get_visible(gtkblist->window)) { /* make the buddy list visible if it is iconified or if it is * obscured and not currently focused (the focus part ensures * that we do something reasonable if the buddy list is obscured @@ -7392,7 +7478,7 @@ static void set_urgent(void) { - if (gtkblist->window && !GTK_WIDGET_HAS_FOCUS(gtkblist->window)) + if (gtkblist->window && !gtk_widget_has_focus(gtkblist->window)) pidgin_set_urgent(GTK_WINDOW(gtkblist->window), TRUE); } @@ -7443,11 +7529,11 @@ chat = (PurpleChat *)cnode; - if(chat->account != account) + if(purple_chat_get_account(chat) != account) continue; - if (purple_blist_node_get_bool((PurpleBlistNode*)chat, "gtk-autojoin")) - serv_join_chat(gc, chat->components); + if (purple_blist_node_get_bool(PURPLE_BLIST_NODE(chat), "gtk-autojoin")) + serv_join_chat(gc, purple_chat_get_components(chat)); } } @@ -7464,25 +7550,25 @@ static gboolean buddy_signonoff_timeout_cb(PurpleBuddy *buddy) { - struct _pidgin_blist_node *gtknode = ((PurpleBlistNode*)buddy)->ui_data; + struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy)); gtknode->recent_signonoff = FALSE; gtknode->recent_signonoff_timer = 0; - pidgin_blist_update(NULL, (PurpleBlistNode*)buddy); + pidgin_blist_update(NULL, PURPLE_BLIST_NODE(buddy)); return FALSE; } static void buddy_signonoff_cb(PurpleBuddy *buddy) { - struct _pidgin_blist_node *gtknode; - - if(!((PurpleBlistNode*)buddy)->ui_data) { - pidgin_blist_new_node((PurpleBlistNode*)buddy); - } - - gtknode = ((PurpleBlistNode*)buddy)->ui_data; + struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy)); + + if(!gtknode) { + pidgin_blist_new_node(PURPLE_BLIST_NODE(buddy)); + } + + gtknode = purple_blist_node_get_ui_data(PURPLE_BLIST_NODE(buddy)); gtknode->recent_signonoff = TRUE; @@ -7849,7 +7935,7 @@ PurpleBuddy *buddy; for (n = node->child; n; n = n->next) { buddy = (PurpleBuddy*)n; - activity_score += purple_log_get_activity_score(PURPLE_LOG_IM, buddy->name, buddy->account); + activity_score += purple_log_get_activity_score(PURPLE_LOG_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); } buddy_name = purple_contact_get_alias((PurpleContact*)node); } else if(PURPLE_BLIST_NODE_IS_CHAT(node)) { @@ -7885,7 +7971,7 @@ if(PURPLE_BLIST_NODE_IS_CONTACT(n)) { for (n2 = n->child; n2; n2 = n2->next) { buddy = (PurpleBuddy*)n2; - this_log_activity_score += purple_log_get_activity_score(PURPLE_LOG_IM, buddy->name, buddy->account); + this_log_activity_score += purple_log_get_activity_score(PURPLE_LOG_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); } this_buddy_name = purple_contact_get_alias((PurpleContact*)n); } else { @@ -7927,40 +8013,43 @@ } static void -build_plugin_actions(GtkWidget *menu, PurplePlugin *plugin, - gpointer context) -{ - GtkWidget *menuitem; +build_plugin_actions(GtkActionGroup *action_group, GString *ui, char *parent, + PurplePlugin *plugin, gpointer context) +{ + GtkAction *menuaction; PurplePluginAction *action = NULL; GList *actions, *l; + char *name; + int count = 0; actions = PURPLE_PLUGIN_ACTIONS(plugin, context); - for (l = actions; l != NULL; l = l->next) - { - if (l->data) - { - action = (PurplePluginAction *) l->data; + for (l = actions; l != NULL; l = l->next) { + if (l->data) { + action = (PurplePluginAction *)l->data; action->plugin = plugin; action->context = context; - menuitem = gtk_menu_item_new_with_label(action->label); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - - g_signal_connect(G_OBJECT(menuitem), "activate", + name = g_strdup_printf("%s-action-%d", parent, count++); + menuaction = gtk_action_new(name, action->label, NULL, NULL); + gtk_action_group_add_action(action_group, menuaction); + g_string_append_printf(ui, "", name); + + g_signal_connect(G_OBJECT(menuaction), "activate", G_CALLBACK(plugin_act), action); - g_object_set_data_full(G_OBJECT(menuitem), "plugin_action", + g_object_set_data_full(G_OBJECT(menuaction), "plugin_action", action, (GDestroyNotify)purple_plugin_action_free); - gtk_widget_show(menuitem); + g_free(name); } else - pidgin_separator(menu); + g_string_append(ui, ""); } g_list_free(actions); } + static void modify_account_cb(GtkWidget *widget, gpointer data) { @@ -7987,14 +8076,12 @@ purple_account_set_enabled(account, PIDGIN_UI, FALSE); } - - void pidgin_blist_update_accounts_menu(void) { - GtkWidget *menuitem = NULL, *submenu = NULL; - GtkAccelGroup *accel_group = NULL; - GList *l = NULL, *accounts = NULL; + GtkWidget *menuitem, *submenu; + GtkAccelGroup *accel_group; + GList *l, *accounts; gboolean disabled_accounts = FALSE; gboolean enabled_accounts = FALSE; @@ -8005,10 +8092,12 @@ for (l = gtk_container_get_children(GTK_CONTAINER(accountmenu)); l; l = g_list_delete_link(l, l)) { menuitem = l->data; - if (menuitem != gtk_item_factory_get_widget(gtkblist->ift, N_("/Accounts/Manage Accounts"))) + if (menuitem != gtk_ui_manager_get_widget(gtkblist->ui, "/BList/AccountsMenu/ManageAccounts")) gtk_widget_destroy(menuitem); } + accel_group = gtk_menu_get_accel_group(GTK_MENU(accountmenu)); + for (accounts = purple_accounts_get_all(); accounts; accounts = accounts->next) { char *buf = NULL; GtkWidget *image = NULL; @@ -8017,14 +8106,14 @@ account = accounts->data; - if(!purple_account_get_enabled(account, PIDGIN_UI)) { + if (!purple_account_get_enabled(account, PIDGIN_UI)) { if (!disabled_accounts) { menuitem = gtk_menu_item_new_with_label(_("Enable Account")); gtk_menu_shell_append(GTK_MENU_SHELL(accountmenu), menuitem); submenu = gtk_menu_new(); gtk_menu_set_accel_group(GTK_MENU(submenu), accel_group); - gtk_menu_set_accel_path(GTK_MENU(submenu), N_("/Accounts/Enable Account")); + gtk_menu_set_accel_path(GTK_MENU(submenu), "/BListActions/EnableAccount"); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); disabled_accounts = TRUE; @@ -8034,9 +8123,9 @@ purple_account_get_protocol_name(account), ")", NULL); menuitem = gtk_image_menu_item_new_with_label(buf); g_free(buf); + pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); - if (pixbuf != NULL) - { + if (pixbuf != NULL) { if (!purple_account_is_connected(account)) gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE); image = gtk_image_new_from_pixbuf(pixbuf); @@ -8044,9 +8133,11 @@ gtk_widget_show(image); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image); } + g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(enable_account_cb), account); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); + } else { enabled_accounts = TRUE; } @@ -8058,7 +8149,6 @@ } pidgin_separator(accountmenu); - accel_group = gtk_menu_get_accel_group(GTK_MENU(accountmenu)); for (accounts = purple_accounts_get_all(); accounts; accounts = accounts->next) { char *buf = NULL; @@ -8078,8 +8168,9 @@ buf = g_strconcat(purple_account_get_username(account), " (", purple_account_get_protocol_name(account), ")", NULL); menuitem = gtk_image_menu_item_new_with_label(buf); - accel_path_buf = g_strconcat(N_("/Accounts/"), buf, NULL); + accel_path_buf = g_strconcat("/AccountActions/", buf, NULL); g_free(buf); + pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); if (pixbuf != NULL) { if (!purple_account_is_connected(account)) @@ -8090,6 +8181,7 @@ gtk_widget_show(image); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image); } + gtk_menu_shell_append(GTK_MENU_SHELL(accountmenu), menuitem); submenu = gtk_menu_new(); @@ -8098,7 +8190,6 @@ g_free(accel_path_buf); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); - menuitem = gtk_menu_item_new_with_mnemonic(_("_Edit Account")); g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(modify_account_cb), account); @@ -8107,14 +8198,14 @@ pidgin_separator(submenu); gc = purple_account_get_connection(account); - plugin = gc && PURPLE_CONNECTION_IS_CONNECTED(gc) ? gc->prpl : NULL; + plugin = gc && PURPLE_CONNECTION_IS_CONNECTED(gc) ? purple_connection_get_prpl(gc) : NULL; prpl_info = plugin ? PURPLE_PLUGIN_PROTOCOL_INFO(plugin) : NULL; if (prpl_info && (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods) || PURPLE_PLUGIN_HAS_ACTIONS(plugin))) { if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods) && - gc->flags & PURPLE_CONNECTION_SUPPORT_MOODS) { + (purple_connection_get_flags(gc) & PURPLE_CONNECTION_SUPPORT_MOODS)) { if (purple_account_get_status(account, "mood")) { menuitem = gtk_menu_item_new_with_mnemonic(_("Set _Mood...")); @@ -8123,8 +8214,37 @@ gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); } } + if (PURPLE_PLUGIN_HAS_ACTIONS(plugin)) { - build_plugin_actions(submenu, plugin, gc); + GtkWidget *menuitem; + PurplePluginAction *action = NULL; + GList *actions, *l; + + actions = PURPLE_PLUGIN_ACTIONS(plugin, gc); + + for (l = actions; l != NULL; l = l->next) + { + if (l->data) + { + action = (PurplePluginAction *) l->data; + action->plugin = plugin; + action->context = gc; + + menuitem = gtk_menu_item_new_with_label(action->label); + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); + + g_signal_connect(G_OBJECT(menuitem), "activate", + G_CALLBACK(plugin_act), action); + g_object_set_data_full(G_OBJECT(menuitem), "plugin_action", + action, + (GDestroyNotify)purple_plugin_action_free); + gtk_widget_show(menuitem); + } + else + pidgin_separator(submenu); + } + + g_list_free(actions); } } else { menuitem = gtk_menu_item_new_with_label(_("No actions available")); @@ -8139,36 +8259,45 @@ G_CALLBACK(disable_account_cb), account); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem); } + gtk_widget_show_all(accountmenu); } -static GList *plugin_submenus = NULL; +static guint plugins_merge_id; +static GtkActionGroup *plugins_action_group = NULL; void pidgin_blist_update_plugin_actions(void) { - GtkWidget *menuitem, *submenu; PurplePlugin *plugin = NULL; GList *l; - GtkAccelGroup *accel_group; - - GtkWidget *pluginmenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools")); - - g_return_if_fail(pluginmenu != NULL); - - /* Remove old plugin action submenus from the Tools menu */ - for (l = plugin_submenus; l; l = l->next) - gtk_widget_destroy(GTK_WIDGET(l->data)); - g_list_free(plugin_submenus); - plugin_submenus = NULL; - - accel_group = gtk_menu_get_accel_group(GTK_MENU(pluginmenu)); + + GtkAction *action; + GString *plugins_ui; + gchar *ui_string; + int count = 0; + + if ((gtkblist == NULL) || (gtkblist->ui == NULL)) + return; + + /* Clear the old menu */ + if (plugins_action_group) { + gtk_ui_manager_remove_ui(gtkblist->ui, plugins_merge_id); + gtk_ui_manager_remove_action_group(gtkblist->ui, plugins_action_group); + g_object_unref(G_OBJECT(plugins_action_group)); + } + + plugins_action_group = gtk_action_group_new("PluginActions"); +#ifdef ENABLE_NLS + gtk_action_group_set_translation_domain(plugins_action_group, PACKAGE); +#endif + plugins_ui = g_string_new(NULL); /* Add a submenu for each plugin with custom actions */ for (l = purple_plugins_get_loaded(); l; l = l->next) { - char *path; - - plugin = (PurplePlugin *) l->data; + char *name; + + plugin = (PurplePlugin *)l->data; if (PURPLE_IS_PROTOCOL_PLUGIN(plugin)) continue; @@ -8176,28 +8305,34 @@ if (!PURPLE_PLUGIN_HAS_ACTIONS(plugin)) continue; - menuitem = gtk_image_menu_item_new_with_label(_(plugin->info->name)); - gtk_menu_shell_append(GTK_MENU_SHELL(pluginmenu), menuitem); - - plugin_submenus = g_list_append(plugin_submenus, menuitem); - - submenu = gtk_menu_new(); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); - - gtk_menu_set_accel_group(GTK_MENU(submenu), accel_group); - path = g_strdup_printf("%s/Tools/%s", gtkblist->ift->path, plugin->info->name); - gtk_menu_set_accel_path(GTK_MENU(submenu), path); - g_free(path); - - build_plugin_actions(submenu, plugin, NULL); - } - gtk_widget_show_all(pluginmenu); + name = g_strdup_printf("plugin%d", count); + action = gtk_action_new(name, plugin->info->name, NULL, NULL); + gtk_action_group_add_action(plugins_action_group, action); + g_string_append_printf(plugins_ui, "", name); + + build_plugin_actions(plugins_action_group, plugins_ui, name, plugin, NULL); + + g_string_append(plugins_ui, ""); + count++; + + g_free(name); + } + + ui_string = g_strconcat("", + plugins_ui->str, + "", + NULL); + gtk_ui_manager_insert_action_group(gtkblist->ui, plugins_action_group, 1); + plugins_merge_id = gtk_ui_manager_add_ui_from_string(gtkblist->ui, ui_string, -1, NULL); + + g_string_free(plugins_ui, TRUE); + g_free(ui_string); } static void -sortmethod_act(GtkCheckMenuItem *checkmenuitem, char *id) -{ - if (gtk_check_menu_item_get_active(checkmenuitem)) +sortmethod_act(GtkRadioAction *action, GtkRadioAction *current, char *id) +{ + if (action == current) { pidgin_set_cursor(gtkblist->window, GDK_WATCH); /* This is redundant. I think. */ @@ -8211,40 +8346,58 @@ void pidgin_blist_update_sort_methods(void) { - GtkWidget *menuitem = NULL, *activeitem = NULL; PidginBlistSortMethod *method = NULL; GList *l; GSList *sl = NULL; - GtkWidget *sortmenu; const char *m = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/blist/sort_type"); - if ((gtkblist == NULL) || (gtkblist->ift == NULL)) - return; - - g_return_if_fail(m != NULL); - - sortmenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Buddies/Sort Buddies")); - - if (sortmenu == NULL) + GtkRadioAction *action; + GString *ui_string; + + if ((gtkblist == NULL) || (gtkblist->ui == NULL)) return; /* Clear the old menu */ - for (l = gtk_container_get_children(GTK_CONTAINER(sortmenu)); l; l = g_list_delete_link(l, l)) { - menuitem = l->data; - gtk_widget_destroy(GTK_WIDGET(menuitem)); - } + if (sort_action_group) { + gtk_ui_manager_remove_ui(gtkblist->ui, sort_merge_id); + gtk_ui_manager_remove_action_group(gtkblist->ui, sort_action_group); + g_object_unref(G_OBJECT(sort_action_group)); + } + + sort_action_group = gtk_action_group_new("SortMethods"); +#ifdef ENABLE_NLS + gtk_action_group_set_translation_domain(sort_action_group, PACKAGE); +#endif + ui_string = g_string_new("" + ""); for (l = pidgin_blist_sort_methods; l; l = l->next) { - method = (PidginBlistSortMethod *) l->data; - menuitem = gtk_radio_menu_item_new_with_label(sl, _(method->name)); - if (g_str_equal(m, method->id)) - activeitem = menuitem; - sl = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem)); - gtk_menu_shell_append(GTK_MENU_SHELL(sortmenu), menuitem); - g_signal_connect(G_OBJECT(menuitem), "toggled", - G_CALLBACK(sortmethod_act), method->id); - gtk_widget_show(menuitem); - } - if (activeitem) - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(activeitem), TRUE); -} + method = (PidginBlistSortMethod *)l->data; + + g_string_append_printf(ui_string, "", method->id); + action = gtk_radio_action_new(method->id, + method->name, + NULL, + NULL, + 0); + gtk_action_group_add_action_with_accel(sort_action_group, GTK_ACTION(action), NULL); + + gtk_radio_action_set_group(action, sl); + sl = gtk_radio_action_get_group(action); + + if (!strcmp(m, method->id)) + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE); + else + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), FALSE); + + g_signal_connect(G_OBJECT(action), "changed", + G_CALLBACK(sortmethod_act), method->id); + } + + g_string_append(ui_string, ""); + gtk_ui_manager_insert_action_group(gtkblist->ui, sort_action_group, 1); + sort_merge_id = gtk_ui_manager_add_ui_from_string(gtkblist->ui, ui_string->str, -1, NULL); + + g_string_free(ui_string, TRUE); +} + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkblist.h --- a/pidgin/gtkblist.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkblist.h Fri Apr 06 04:30:00 2012 +0000 @@ -82,19 +82,10 @@ GtkCellRenderer *text_rend; - GtkItemFactory *ift; + GtkUIManager *ui; GtkWidget *menutray; /**< The menu tray widget. */ GtkWidget *menutrayicon; /**< The menu tray icon. */ - /** Caches connection error messages; keys are #PurpleAccount and - * values are non-@c NULL const char *s containing localised - * error messages. (If an account does not have an error, it will not - * appear in the table.) - * @deprecated in favour of purple_account_get_current_error(), which also - * gives you the #PurpleConnectionError value. - */ - GHashTable *connection_errors; - guint refresh_timer; /**< The timer for refreshing every 30 seconds */ guint timeout; /**< The timeout for the tooltip. */ @@ -136,6 +127,8 @@ #define PIDGIN_IS_PIDGIN_BLIST(list) \ (purple_blist_get_ui_ops() == pidgin_blist_get_ui_ops()) +G_BEGIN_DECLS + /************************************************************************** * @name GTK+ Buddy List API **************************************************************************/ @@ -259,8 +252,6 @@ * Sets the current theme for Pidgin to use * * @param theme the new theme to use - * - * @since 2.6.0 */ void pidgin_blist_set_theme(PidginBlistTheme *theme); @@ -268,8 +259,6 @@ * Gets Pidgin's current buddy list theme * * @returns the current theme - * - * @since 2.6.0 */ PidginBlistTheme *pidgin_blist_get_theme(void); @@ -370,20 +359,6 @@ void pidgin_append_blist_node_extended_menu(GtkWidget *menu, PurpleBlistNode *node); /** - * Was used by the connection API to tell the blist if an account has a - * connection error or no longer has a connection error, but the blist now does - * this itself with the @ref account-error-changed signal. - * - * @param account The account that either has a connection error - * or no longer has a connection error. - * @param message The connection error message, or NULL if this - * account is no longer in an error state. - * @deprecated There was no good reason for code other than gtkconn to call - * this. - */ -void pidgin_blist_update_account_error_state(PurpleAccount *account, const char *message); - -/** * Sets a headline notification * * This is currently used for mail notification, but could theoretically be used for anything. @@ -405,8 +380,6 @@ * @param selected Whether this buddy is selected. If TRUE, the markup will not change the color. * @param aliased TRUE to return the appropriate alias of this buddy, FALSE to return its username and status information * @return The markup for this buddy - * - * @since 2.1.0 */ gchar *pidgin_blist_get_name_markup(PurpleBuddy *buddy, gboolean selected, gboolean aliased); @@ -418,17 +391,14 @@ * * @param node The buddy list node to show a tooltip for * @param widget The widget to draw the tooltip on - * - * @since 2.1.0 */ void pidgin_blist_draw_tooltip(PurpleBlistNode *node, GtkWidget *widget); /** * Destroys the current (if any) Buddy List tooltip - * - * @since 2.1.0 */ void pidgin_blist_tooltip_destroy(void); +G_END_DECLS #endif /* _PIDGINBLIST_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkcellrendererexpander.c --- a/pidgin/gtkcellrendererexpander.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkcellrendererexpander.c Fri Apr 06 04:30:00 2012 +0000 @@ -250,8 +250,13 @@ state = GTK_STATE_INSENSITIVE; else if (flags & GTK_CELL_RENDERER_PRELIT) state = GTK_STATE_PRELIGHT; +#if GTK_CHECK_VERSION(2,18,0) + else if (gtk_widget_has_focus (widget) && flags & GTK_CELL_RENDERER_SELECTED) + state = GTK_STATE_ACTIVE; +#else else if (GTK_WIDGET_HAS_FOCUS (widget) && flags & GTK_CELL_RENDERER_SELECTED) state = GTK_STATE_ACTIVE; +#endif else state = GTK_STATE_NORMAL; diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkcellrendererexpander.h --- a/pidgin/gtkcellrendererexpander.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkcellrendererexpander.h Fri Apr 06 04:30:00 2012 +0000 @@ -23,11 +23,6 @@ #include -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - - #define PIDGIN_TYPE_GTK_CELL_RENDERER_EXPANDER (pidgin_cell_renderer_expander_get_type()) #define PIDGIN_CELL_RENDERER_EXPANDER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PIDGIN_TYPE_GTK_CELL_RENDERER_EXPANDER, PidginCellRendererExpander)) #define PIDGIN_CELL_RENDERER_EXPANDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PURPLE_TYPE_GTK_CELL_RENDERER_EXPANDER, PidginCellRendererExpanderClass)) @@ -48,12 +43,11 @@ GtkCellRendererClass parent_class; }; +G_BEGIN_DECLS + GType pidgin_cell_renderer_expander_get_type (void); GtkCellRenderer *pidgin_cell_renderer_expander_new (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS #endif /* _PIDGINCELLRENDEREREXPANDER_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkcertmgr.c --- a/pidgin/gtkcertmgr.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkcertmgr.c Fri Apr 06 04:30:00 2012 +0000 @@ -310,6 +310,7 @@ GtkTreeModel *model; gchar *id; PurpleCertificate *crt; + char *title; /* See if things are selected */ if (!gtk_tree_selection_get_selected(select, &model, &iter)) { @@ -326,10 +327,20 @@ g_return_if_fail(crt); /* Fire the notification */ - purple_certificate_display_x509(crt); + title = g_strdup_printf(_("Certificate Information for %s"), id); + purple_request_certificate(tpm_dat, title, NULL, NULL, crt, + _("OK"), G_CALLBACK(purple_certificate_destroy), + _("Cancel"), G_CALLBACK(purple_certificate_destroy), + crt); g_free(id); - purple_certificate_destroy(crt); + g_free(title); +} + +static void +tls_peers_mgmt_activated_cb(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer data) +{ + tls_peers_mgmt_info_cb(NULL, NULL); } static void @@ -452,6 +463,9 @@ g_signal_connect(G_OBJECT(select), "changed", G_CALLBACK(tls_peers_mgmt_select_chg_cb), NULL); + g_signal_connect(G_OBJECT(listview), "row-activated", + G_CALLBACK(tls_peers_mgmt_activated_cb), NULL); + gtk_box_pack_start(GTK_BOX(mgmt_widget), pidgin_make_scrollable(GTK_WIDGET(listview), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS, GTK_SHADOW_IN, -1, -1), TRUE, TRUE, /* Take up lots of space */ @@ -471,9 +485,8 @@ gtk_widget_show(bbox); /* Import button */ - /* TODO: This is the wrong stock button */ tpm_dat->importbutton = importbutton = - gtk_button_new_from_stock(GTK_STOCK_ADD); + gtk_button_new_from_stock(GTK_STOCK_OPEN); gtk_box_pack_start(GTK_BOX(bbox), importbutton, FALSE, FALSE, 0); gtk_widget_show(importbutton); g_signal_connect(G_OBJECT(importbutton), "clicked", @@ -481,9 +494,8 @@ /* Export button */ - /* TODO: This is the wrong stock button */ tpm_dat->exportbutton = exportbutton = - gtk_button_new_from_stock(GTK_STOCK_SAVE); + gtk_button_new_from_stock(GTK_STOCK_SAVE_AS); gtk_box_pack_start(GTK_BOX(bbox), exportbutton, FALSE, FALSE, 0); gtk_widget_show(exportbutton); g_signal_connect(G_OBJECT(exportbutton), "clicked", diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkcertmgr.h --- a/pidgin/gtkcertmgr.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkcertmgr.h Fri Apr 06 04:30:00 2012 +0000 @@ -43,6 +43,8 @@ gchar *label; }; +G_BEGIN_DECLS + /**************************************************************************/ /** @name Certificate Manager API */ /**************************************************************************/ @@ -59,4 +61,6 @@ /*@}*/ +G_END_DECLS + #endif /* _PIDGINCERTMGR_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkconn.c --- a/pidgin/gtkconn.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkconn.c Fri Apr 06 04:30:00 2012 +0000 @@ -136,9 +136,9 @@ } static void -pidgin_connection_report_disconnect_reason (PurpleConnection *gc, - PurpleConnectionError reason, - const char *text) +pidgin_connection_report_disconnect(PurpleConnection *gc, + PurpleConnectionError reason, + const char *text) { PurpleAccount *account = NULL; PidginAutoRecon *info; @@ -215,10 +215,9 @@ pidgin_connection_connected, pidgin_connection_disconnected, pidgin_connection_notice, - NULL, /* report_disconnect */ pidgin_connection_network_connected, pidgin_connection_network_disconnected, - pidgin_connection_report_disconnect_reason, + pidgin_connection_report_disconnect, NULL, NULL, NULL diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkconn.h --- a/pidgin/gtkconn.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkconn.h Fri Apr 06 04:30:00 2012 +0000 @@ -25,6 +25,8 @@ #ifndef _PIDGINCONN_H_ #define _PIDGINCONN_H_ +G_BEGIN_DECLS + /**************************************************************************/ /** @name GTK+ Connection API */ /**************************************************************************/ @@ -56,4 +58,6 @@ */ void pidgin_connection_uninit(void); +G_END_DECLS + #endif /* _PIDGINCONN_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkconv-theme-loader.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/gtkconv-theme-loader.c Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,294 @@ +/* + * PidginConvThemeLoader for Pidgin + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "pidgin.h" +#include "gtkconv-theme-loader.h" +#include "gtkconv-theme.h" + +#include "xmlnode.h" +#include "debug.h" + +/***************************************************************************** + * Conversation Theme Builder + *****************************************************************************/ + +static GHashTable * +read_info_plist(xmlnode *plist) +{ + GHashTable *info; + xmlnode *key, *value; + gboolean fail = FALSE; + + info = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + + for (key = xmlnode_get_child(plist, "dict/key"); + key; + key = xmlnode_get_next_twin(key)) { + char *keyname; + GValue *val; + + ; + for (value = key->next; value && value->type != XMLNODE_TYPE_TAG; value = value->next) + ; + if (!value) { + fail = TRUE; + break; + } + + val = g_new0(GValue, 1); + if (g_str_equal(value->name, "string")) { + g_value_init(val, G_TYPE_STRING); + g_value_take_string(val, xmlnode_get_data_unescaped(value)); + + } else if (g_str_equal(value->name, "true")) { + g_value_init(val, G_TYPE_BOOLEAN); + g_value_set_boolean(val, TRUE); + + } else if (g_str_equal(value->name, "false")) { + g_value_init(val, G_TYPE_BOOLEAN); + g_value_set_boolean(val, FALSE); + + } else if (g_str_equal(value->name, "real")) { + char *temp = xmlnode_get_data_unescaped(value); + g_value_init(val, G_TYPE_FLOAT); + g_value_set_float(val, atof(temp)); + g_free(temp); + + } else if (g_str_equal(value->name, "integer")) { + char *temp = xmlnode_get_data_unescaped(value); + g_value_init(val, G_TYPE_INT); + g_value_set_int(val, atoi(temp)); + g_free(temp); + + } else { + /* NOTE: We don't support array, data, date, or dict as values, + since they don't seem to be needed for styles. */ + g_free(val); + fail = TRUE; + break; + } + + keyname = xmlnode_get_data_unescaped(key); + g_hash_table_insert(info, keyname, val); + } + + if (fail) { + g_hash_table_destroy(info); + info = NULL; + } + + return info; +} + +static gboolean +pidgin_conv_loader_probe(const gchar *dir) +{ + gboolean result; + gchar *plist_file; + + plist_file = g_build_filename(dir, "Contents", "Info.plist", NULL); + result = g_file_test(plist_file, G_FILE_TEST_IS_REGULAR); + g_free(plist_file); + + return result; +} + +static PurpleTheme * +pidgin_conv_loader_build(const gchar *dir) +{ + PidginConvTheme *theme = NULL; + char *contents; + xmlnode *plist; + GHashTable *info; + GValue *val; + int MessageViewVersion; + const char *CFBundleName; + const char *CFBundleIdentifier; + GDir *variants; + char *variant_dir; + + g_return_val_if_fail(dir != NULL, NULL); + + /* Load Info.plist for theme information */ + contents = g_build_filename(dir, "Contents", NULL); + plist = xmlnode_from_file(contents, "Info.plist", "Info.plist", "gtkconv-theme-loader"); + g_free(contents); + if (plist == NULL) { + purple_debug_error("gtkconv-theme-loader", + "Failed to load Contents/Info.plist in %s\n", dir); + return NULL; + } + + info = read_info_plist(plist); + xmlnode_free(plist); + if (info == NULL) { + purple_debug_error("gtkconv-theme-loader", + "Failed to load Contents/Info.plist in %s\n", dir); + return NULL; + } + + /* Check for required keys: CFBundleName */ + val = g_hash_table_lookup(info, "CFBundleName"); + if (!val || !G_VALUE_HOLDS_STRING(val)) { + purple_debug_error("gtkconv-theme-loader", + "%s/Contents/Info.plist missing required string key CFBundleName.\n", + dir); + g_hash_table_destroy(info); + return NULL; + } + CFBundleName = g_value_get_string(val); + + /* Check for required keys: CFBundleIdentifier */ + val = g_hash_table_lookup(info, "CFBundleIdentifier"); + if (!val || !G_VALUE_HOLDS_STRING(val)) { + purple_debug_error("gtkconv-theme-loader", + "%s/Contents/Info.plist missing required string key CFBundleIdentifier.\n", + dir); + g_hash_table_destroy(info); + return NULL; + } + CFBundleIdentifier = g_value_get_string(val); + + /* Check for required keys: MessageViewVersion */ + val = g_hash_table_lookup(info, "MessageViewVersion"); + if (!val || !G_VALUE_HOLDS_INT(val)) { + purple_debug_error("gtkconv-theme-loader", + "%s/Contents/Info.plist missing required integer key MessageViewVersion.\n", + dir); + g_hash_table_destroy(info); + return NULL; + } + + MessageViewVersion = g_value_get_int(val); + if (MessageViewVersion < 3) { + purple_debug_error("gtkconv-theme-loader", + "%s is a legacy style (version %d) and will not be loaded.\n", + CFBundleName, MessageViewVersion); + g_hash_table_destroy(info); + return NULL; + } + + theme = g_object_new(PIDGIN_TYPE_CONV_THEME, + "type", "conversation", + "name", CFBundleName, + "directory", dir, + "info", info, NULL); + + /* Read list of variants */ + variant_dir = g_build_filename(dir, "Contents", "Resources", "Variants", NULL); + variants = g_dir_open(variant_dir, 0, NULL); + g_free(variant_dir); + + if (variants) { + char *prefname; + const char *default_variant = NULL; + const char *file; + + /* Make sure prefs exist */ + prefname = g_strdup_printf(PIDGIN_PREFS_ROOT "/conversations/themes/%s", + CFBundleIdentifier); + purple_prefs_add_none(prefname); + g_free(prefname); + + /* Try user-set variant */ + prefname = g_strdup_printf(PIDGIN_PREFS_ROOT "/conversations/themes/%s/variant", + CFBundleIdentifier); + if (purple_prefs_exists(prefname)) + default_variant = purple_prefs_get_string(prefname); + g_free(prefname); + + if (default_variant && *default_variant) { + pidgin_conversation_theme_set_variant(theme, default_variant); + + } else { + /* Try theme default */ + val = g_hash_table_lookup(info, "DefaultVariant"); + if (val && G_VALUE_HOLDS_STRING(val)) { + default_variant = g_value_get_string(val); + if (default_variant && *default_variant) + pidgin_conversation_theme_set_variant(theme, default_variant); + else + default_variant = NULL; + } else + default_variant = NULL; + } + + while ((file = g_dir_read_name(variants)) != NULL) { + const char *end = g_strrstr(file, ".css"); + char *name; + + if ((end == NULL) || (*(end + 4) != '\0')) + continue; + + name = g_strndup(file, end - file); + pidgin_conversation_theme_add_variant(theme, name); + + /* Set variant with first found */ + if (!default_variant) { + pidgin_conversation_theme_set_variant(theme, name); + default_variant = name; + } + } + + g_dir_close(variants); + } + + return PURPLE_THEME(theme); +} + +/****************************************************************************** + * GObject Stuff + *****************************************************************************/ + +static void +pidgin_conv_theme_loader_class_init(PidginConvThemeLoaderClass *klass) +{ + PurpleThemeLoaderClass *loader_klass = PURPLE_THEME_LOADER_CLASS(klass); + + loader_klass->purple_theme_loader_build = pidgin_conv_loader_build; + loader_klass->probe_directory = pidgin_conv_loader_probe; +} + + +GType +pidgin_conversation_theme_loader_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof(PidginConvThemeLoaderClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)pidgin_conv_theme_loader_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (PidginConvThemeLoader), + 0, /* n_preallocs */ + NULL, /* instance_init */ + NULL, /* value table */ + }; + type = g_type_register_static(PURPLE_TYPE_THEME_LOADER, + "PidginConvThemeLoader", &info, 0); + } + return type; +} + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkconv-theme-loader.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/gtkconv-theme-loader.h Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,72 @@ +/** + * @file gtkconv-theme-loader.h Pidgin Conversation Theme Loader Class API + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#ifndef PIDGIN_CONV_THEME_LOADER_H +#define PIDGIN_CONV_THEME_LOADER_H + +#include +#include +#include "theme-loader.h" + +/** + * A pidgin conversation theme loader. Extends PurpleThemeLoader (theme-loader.h) + * This is a class designed to build conversation themes + * + * PidginConvThemeLoader is a GObject. + */ +typedef struct _PidginConvThemeLoader PidginConvThemeLoader; +typedef struct _PidginConvThemeLoaderClass PidginConvThemeLoaderClass; + +#define PIDGIN_TYPE_CONV_THEME_LOADER (pidgin_conversation_theme_loader_get_type ()) +#define PIDGIN_CONV_THEME_LOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIDGIN_TYPE_CONV_THEME_LOADER, PidginConvThemeLoader)) +#define PIDGIN_CONV_THEME_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIDGIN_TYPE_CONV_THEME_LOADER, PidginConvThemeLoaderClass)) +#define PIDGIN_IS_CONV_THEME_LOADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIDGIN_TYPE_CONV_THEME_LOADER)) +#define PIDGIN_IS_CONV_THEME_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIDGIN_TYPE_CONV_THEME_LOADER)) +#define PIDGIN_CONV_THEME_LOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIDGIN_TYPE_CONV_THEME_LOADER, PidginConvThemeLoaderClass)) + +struct _PidginConvThemeLoader +{ + PurpleThemeLoader parent; +}; + +struct _PidginConvThemeLoaderClass +{ + PurpleThemeLoaderClass parent_class; +}; + +/**************************************************************************/ +/** @name Pidgin Conversation Theme-Loader API */ +/**************************************************************************/ +G_BEGIN_DECLS + +/** + * GObject foo. + * @internal. + */ +GType pidgin_conversation_theme_loader_get_type(void); + +G_END_DECLS +#endif /* PIDGIN_CONV_THEME_LOADER_H */ + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkconv-theme.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/gtkconv-theme.c Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,751 @@ +/* + * Conversation Themes for Pidgin + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "gtkconv-theme.h" + +#include "conversation.h" +#include "debug.h" +#include "prefs.h" +#include "xmlnode.h" + +#include "pidgin.h" +#include "internal.h" +#include "gtkconv.h" +#include "gtkwebview.h" + +#include +#include + +#define PIDGIN_CONV_THEME_GET_PRIVATE(Gobject) \ + (G_TYPE_INSTANCE_GET_PRIVATE((Gobject), PIDGIN_TYPE_CONV_THEME, PidginConvThemePrivate)) + +/****************************************************************************** + * Structs + *****************************************************************************/ + +typedef struct { + /* current config options */ + char *variant; /* allowed to be NULL if there are no variants */ + GList *variants; + + /* Info.plist keys/values */ + GHashTable *info; + + /* caches */ + char *template_html; + char *header_html; + char *footer_html; + char *topic_html; + char *status_html; + char *content_html; + char *incoming_content_html; + char *outgoing_content_html; + char *incoming_next_content_html; + char *outgoing_next_content_html; + char *incoming_context_html; + char *outgoing_context_html; + char *incoming_next_context_html; + char *outgoing_next_context_html; + char *basestyle_css; +} PidginConvThemePrivate; + +/****************************************************************************** + * Enums + *****************************************************************************/ + +enum { + PROP_ZERO = 0, + PROP_INFO, + PROP_VARIANT, + PROP_LAST +}; + +/****************************************************************************** + * Globals + *****************************************************************************/ + +static GObjectClass *parent_class = NULL; +#if GLIB_CHECK_VERSION(2,26,0) +static GParamSpec *properties[PROP_LAST]; +#endif + +/****************************************************************************** + * Helper Functions + *****************************************************************************/ + +static const GValue * +get_key(PidginConvThemePrivate *priv, const char *key, gboolean specific) +{ + GValue *val = NULL; + + /* Try variant-specific key */ + if (specific && priv->variant) { + char *name = g_strdup_printf("%s:%s", key, priv->variant); + val = g_hash_table_lookup(priv->info, name); + g_free(name); + } + + /* Try generic key */ + if (!val) { + val = g_hash_table_lookup(priv->info, key); + } + + return val; +} + +/* The template path can either come from the theme, or can + * be stock Template.html that comes with Pidgin */ +static char * +get_template_path(const char *dir) +{ + char *file; + + file = g_build_filename(dir, "Contents", "Resources", "Template.html", NULL); + + if (!g_file_test(file, G_FILE_TEST_EXISTS)) { + g_free(file); + file = g_build_filename(DATADIR, "pidgin", "theme", "Template.html", NULL); + } + + return file; +} + +static const char * +get_template_html(PidginConvThemePrivate *priv, const char *dir) +{ + char *file; + + if (priv->template_html) + return priv->template_html; + + file = get_template_path(dir); + + if (!g_file_get_contents(file, &priv->template_html, NULL, NULL)) { + purple_debug_error("webkit", "Could not locate a Template.html (%s)\n", file); + priv->template_html = g_strdup(""); + } + g_free(file); + + return priv->template_html; +} + +static const char * +get_basestyle_css(PidginConvThemePrivate *priv, const char *dir) +{ + char *file; + + if (priv->basestyle_css) + return priv->basestyle_css; + + file = g_build_filename(dir, "Contents", "Resources", "main.css", NULL); + if (!g_file_get_contents(file, &priv->basestyle_css, NULL, NULL)) + priv->basestyle_css = g_strdup(""); + g_free(file); + + return priv->basestyle_css; +} + +static const char * +get_header_html(PidginConvThemePrivate *priv, const char *dir) +{ + char *file; + + if (priv->header_html) + return priv->header_html; + + file = g_build_filename(dir, "Contents", "Resources", "Header.html", NULL); + if (!g_file_get_contents(file, &priv->header_html, NULL, NULL)) + priv->header_html = g_strdup(""); + g_free(file); + + return priv->header_html; +} + +static const char * +get_footer_html(PidginConvThemePrivate *priv, const char *dir) +{ + char *file; + + if (priv->footer_html) + return priv->footer_html; + + file = g_build_filename(dir, "Contents", "Resources", "Footer.html", NULL); + if (!g_file_get_contents(file, &priv->footer_html, NULL, NULL)) + priv->footer_html = g_strdup(""); + g_free(file); + + return priv->footer_html; +} + +static const char * +get_topic_html(PidginConvThemePrivate *priv, const char *dir) +{ + char *file; + + if (priv->topic_html) + return priv->topic_html; + + file = g_build_filename(dir, "Contents", "Resources", "Topic.html", NULL); + if (!g_file_get_contents(file, &priv->topic_html, NULL, NULL)) { + purple_debug_info("webkit", "%s could not find Resources/Topic.html\n", dir); + priv->topic_html = g_strdup(""); + } + g_free(file); + + return priv->topic_html; +} + +static const char * +get_content_html(PidginConvThemePrivate *priv, const char *dir) +{ + char *file; + + if (priv->content_html) + return priv->content_html; + + file = g_build_filename(dir, "Contents", "Resources", "Content.html", NULL); + if (!g_file_get_contents(file, &priv->content_html, NULL, NULL)) { + purple_debug_info("webkit", "%s did not have a Content.html\n", dir); + priv->content_html = g_strdup(""); + } + g_free(file); + + return priv->content_html; +} + +static const char * +get_status_html(PidginConvThemePrivate *priv, const char *dir) +{ + char *file; + + if (priv->status_html) + return priv->status_html; + + file = g_build_filename(dir, "Contents", "Resources", "Status.html", NULL); + if (!g_file_get_contents(file, &priv->status_html, NULL, NULL)) { + purple_debug_info("webkit", "%s could not find Resources/Status.html\n", dir); + priv->status_html = g_strdup(get_content_html(priv, dir)); + } + g_free(file); + + return priv->status_html; +} + +static const char * +get_incoming_content_html(PidginConvThemePrivate *priv, const char *dir) +{ + char *file; + + if (priv->incoming_content_html) + return priv->incoming_content_html; + + file = g_build_filename(dir, "Contents", "Resources", "Incoming", "Content.html", NULL); + if (!g_file_get_contents(file, &priv->incoming_content_html, NULL, NULL)) { + purple_debug_info("webkit", "%s did not have a Incoming/Content.html\n", dir); + priv->incoming_content_html = g_strdup(get_content_html(priv, dir)); + } + g_free(file); + + return priv->incoming_content_html; +} + +static const char * +get_incoming_next_content_html(PidginConvThemePrivate *priv, const char *dir) +{ + char *file; + + if (priv->incoming_next_content_html) + return priv->incoming_next_content_html; + + file = g_build_filename(dir, "Contents", "Resources", "Incoming", "NextContent.html", NULL); + if (!g_file_get_contents(file, &priv->incoming_next_content_html, NULL, NULL)) { + priv->incoming_next_content_html = g_strdup(get_incoming_content_html(priv, dir)); + } + g_free(file); + + return priv->incoming_next_content_html; +} + +static const char * +get_incoming_context_html(PidginConvThemePrivate *priv, const char *dir) +{ + char *file; + + if (priv->incoming_context_html) + return priv->incoming_context_html; + + file = g_build_filename(dir, "Contents", "Resources", "Incoming", "Context.html", NULL); + if (!g_file_get_contents(file, &priv->incoming_context_html, NULL, NULL)) { + purple_debug_info("webkit", "%s did not have a Incoming/Context.html\n", dir); + priv->incoming_context_html = g_strdup(get_incoming_content_html(priv, dir)); + } + g_free(file); + + return priv->incoming_context_html; +} + +static const char * +get_incoming_next_context_html(PidginConvThemePrivate *priv, const char *dir) +{ + char *file; + + if (priv->incoming_next_context_html) + return priv->incoming_next_context_html; + + file = g_build_filename(dir, "Contents", "Resources", "Incoming", "NextContext.html", NULL); + if (!g_file_get_contents(file, &priv->incoming_next_context_html, NULL, NULL)) { + priv->incoming_next_context_html = g_strdup(get_incoming_context_html(priv, dir)); + } + g_free(file); + + return priv->incoming_next_context_html; +} + +static const char * +get_outgoing_content_html(PidginConvThemePrivate *priv, const char *dir) +{ + char *file; + + if (priv->outgoing_content_html) + return priv->outgoing_content_html; + + file = g_build_filename(dir, "Contents", "Resources", "Outgoing", "Content.html", NULL); + if (!g_file_get_contents(file, &priv->outgoing_content_html, NULL, NULL)) { + priv->outgoing_content_html = g_strdup(get_incoming_content_html(priv, dir)); + } + g_free(file); + + return priv->outgoing_content_html; +} + +static const char * +get_outgoing_next_content_html(PidginConvThemePrivate *priv, const char *dir) +{ + char *file; + + if (priv->outgoing_next_content_html) + return priv->outgoing_next_content_html; + + file = g_build_filename(dir, "Contents", "Resources", "Outgoing", "NextContent.html", NULL); + if (!g_file_get_contents(file, &priv->outgoing_next_content_html, NULL, NULL)) { + priv->outgoing_next_content_html = g_strdup(get_outgoing_content_html(priv, dir)); + } + + return priv->outgoing_next_content_html; +} + +static const char * +get_outgoing_context_html(PidginConvThemePrivate *priv, const char *dir) +{ + char *file; + + if (priv->outgoing_context_html) + return priv->outgoing_context_html; + + file = g_build_filename(dir, "Contents", "Resources", "Outgoing", "Context.html", NULL); + if (!g_file_get_contents(file, &priv->outgoing_context_html, NULL, NULL)) { + priv->outgoing_context_html = g_strdup(get_incoming_context_html(priv, dir)); + } + g_free(file); + + return priv->outgoing_context_html; +} + +static const char * +get_outgoing_next_context_html(PidginConvThemePrivate *priv, const char *dir) +{ + char *file; + + if (priv->outgoing_next_context_html) + return priv->outgoing_next_context_html; + + file = g_build_filename(dir, "Contents", "Resources", "Outgoing", "NextContext.html", NULL); + if (!g_file_get_contents(file, &priv->outgoing_next_context_html, NULL, NULL)) { + priv->outgoing_next_context_html = g_strdup(get_outgoing_context_html(priv, dir)); + } + g_free(file); + + return priv->outgoing_next_context_html; +} + +static void +_set_variant(PidginConvTheme *theme, const char *variant) +{ + PidginConvThemePrivate *priv; + const GValue *val; + char *prefname; + + g_return_if_fail(theme != NULL); + g_return_if_fail(variant != NULL); + + priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme); + + g_free(priv->variant); + priv->variant = g_strdup(variant); + + val = get_key(priv, "CFBundleIdentifier", FALSE); + prefname = g_strdup_printf(PIDGIN_PREFS_ROOT "/conversations/themes/%s/variant", + g_value_get_string(val)); + purple_prefs_set_string(prefname, variant); + g_free(prefname); +} + +/****************************************************************************** + * GObject Stuff + *****************************************************************************/ + +static void +pidgin_conv_theme_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *psec) +{ + PidginConvTheme *theme = PIDGIN_CONV_THEME(obj); + + switch (param_id) { + case PROP_INFO: + g_value_set_boxed(value, (gpointer)pidgin_conversation_theme_get_info(theme)); + break; + + case PROP_VARIANT: + g_value_set_string(value, pidgin_conversation_theme_get_variant(theme)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, psec); + break; + } +} + +static void +pidgin_conv_theme_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *psec) +{ + PidginConvTheme *theme = PIDGIN_CONV_THEME(obj); + + switch (param_id) { + case PROP_INFO: + pidgin_conversation_theme_set_info(theme, g_value_get_boxed(value)); + break; + + case PROP_VARIANT: + _set_variant(theme, g_value_get_string(value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, psec); + break; + } +} + +static void +pidgin_conv_theme_init(GTypeInstance *instance, + gpointer klass) +{ + PidginConvThemePrivate *priv; + + priv = PIDGIN_CONV_THEME_GET_PRIVATE(instance); +} + +static void +pidgin_conv_theme_finalize(GObject *obj) +{ + PidginConvThemePrivate *priv; + GList *list; + + priv = PIDGIN_CONV_THEME_GET_PRIVATE(obj); + + g_free(priv->template_html); + g_free(priv->header_html); + g_free(priv->footer_html); + g_free(priv->topic_html); + g_free(priv->status_html); + g_free(priv->content_html); + g_free(priv->incoming_content_html); + g_free(priv->outgoing_content_html); + g_free(priv->incoming_next_content_html); + g_free(priv->outgoing_next_content_html); + g_free(priv->incoming_context_html); + g_free(priv->outgoing_context_html); + g_free(priv->incoming_next_context_html); + g_free(priv->outgoing_next_context_html); + g_free(priv->basestyle_css); + + if (priv->info) + g_hash_table_destroy(priv->info); + + list = priv->variants; + while (list) { + g_free(list->data); + list = g_list_delete_link(list, list); + } + g_free(priv->variant); + + parent_class->finalize(obj); +} + +static void +pidgin_conv_theme_class_init(PidginConvThemeClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + GParamSpec *pspec; + + parent_class = g_type_class_peek_parent(klass); + + g_type_class_add_private(klass, sizeof(PidginConvThemePrivate)); + + obj_class->get_property = pidgin_conv_theme_get_property; + obj_class->set_property = pidgin_conv_theme_set_property; + obj_class->finalize = pidgin_conv_theme_finalize; + + /* INFO */ + pspec = g_param_spec_boxed("info", "Info", + "The information about this theme", + G_TYPE_HASH_TABLE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property(obj_class, PROP_INFO, pspec); +#if GLIB_CHECK_VERSION(2,26,0) + properties[PROP_INFO] = pspec; +#endif + + /* VARIANT */ + pspec = g_param_spec_string("variant", "Variant", + "The current variant for this theme", + NULL, G_PARAM_READWRITE); + g_object_class_install_property(obj_class, PROP_VARIANT, pspec); +#if GLIB_CHECK_VERSION(2,26,0) + properties[PROP_VARIANT] = pspec; +#endif +} + +GType +pidgin_conversation_theme_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof(PidginConvThemeClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)pidgin_conv_theme_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(PidginConvTheme), + 0, /* n_preallocs */ + pidgin_conv_theme_init, /* instance_init */ + NULL, /* value table */ + }; + type = g_type_register_static(PURPLE_TYPE_THEME, + "PidginConvTheme", &info, 0); + } + return type; +} + +/***************************************************************************** + * Public API functions + *****************************************************************************/ + +const GHashTable * +pidgin_conversation_theme_get_info(const PidginConvTheme *theme) +{ + PidginConvThemePrivate *priv; + + g_return_val_if_fail(theme != NULL, NULL); + + priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme); + return priv->info; +} + +void +pidgin_conversation_theme_set_info(PidginConvTheme *theme, GHashTable *info) +{ + PidginConvThemePrivate *priv; + + g_return_if_fail(theme != NULL); + + priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme); + + if (priv->info) + g_hash_table_destroy(priv->info); + + priv->info = info; +} + +const GValue * +pidgin_conversation_theme_lookup(PidginConvTheme *theme, const char *key, gboolean specific) +{ + PidginConvThemePrivate *priv; + + g_return_val_if_fail(theme != NULL, NULL); + + priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme); + + return get_key(priv, key, specific); +} + +const char * +pidgin_conversation_theme_get_template(PidginConvTheme *theme, PidginConvThemeTemplateType type) +{ + PidginConvThemePrivate *priv; + const char *dir; + const char *html; + + g_return_val_if_fail(theme != NULL, NULL); + + priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme); + dir = purple_theme_get_dir(PURPLE_THEME(theme)); + + switch (type) { + case PIDGIN_CONVERSATION_THEME_TEMPLATE_MAIN: + html = get_template_html(priv, dir); + break; + case PIDGIN_CONVERSATION_THEME_TEMPLATE_HEADER: + html = get_header_html(priv, dir); + break; + case PIDGIN_CONVERSATION_THEME_TEMPLATE_FOOTER: + html = get_footer_html(priv, dir); + break; + case PIDGIN_CONVERSATION_THEME_TEMPLATE_TOPIC: + html = get_topic_html(priv, dir); + break; + case PIDGIN_CONVERSATION_THEME_TEMPLATE_STATUS: + html = get_status_html(priv, dir); + break; + case PIDGIN_CONVERSATION_THEME_TEMPLATE_CONTENT: + html = get_content_html(priv, dir); + break; + case PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTENT: + html = get_incoming_content_html(priv, dir); + break; + case PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_NEXT_CONTENT: + html = get_incoming_next_content_html(priv, dir); + break; + case PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTEXT: + html = get_incoming_context_html(priv, dir); + break; + case PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_NEXT_CONTEXT: + html = get_incoming_next_context_html(priv, dir); + break; + case PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTENT: + html = get_outgoing_content_html(priv, dir); + break; + case PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_NEXT_CONTENT: + html = get_outgoing_next_content_html(priv, dir); + break; + case PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTEXT: + html = get_outgoing_context_html(priv, dir); + break; + case PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_NEXT_CONTEXT: + html = get_outgoing_next_context_html(priv, dir); + break; + case PIDGIN_CONVERSATION_THEME_TEMPLATE_BASESTYLE_CSS: + html = get_basestyle_css(priv, dir); + break; + default: + purple_debug_error("gtkconv-theme", + "Requested invalid template type (%d) for theme %s.\n", + type, purple_theme_get_name(PURPLE_THEME(theme))); + html = NULL; + } + + return html; +} + +void +pidgin_conversation_theme_add_variant(PidginConvTheme *theme, char *variant) +{ + PidginConvThemePrivate *priv; + + g_return_if_fail(theme != NULL); + g_return_if_fail(variant != NULL); + + priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme); + + priv->variants = g_list_prepend(priv->variants, variant); +} + +const char * +pidgin_conversation_theme_get_variant(PidginConvTheme *theme) +{ + PidginConvThemePrivate *priv; + + g_return_val_if_fail(theme != NULL, NULL); + + priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme); + + return priv->variant; +} + +void +pidgin_conversation_theme_set_variant(PidginConvTheme *theme, const char *variant) +{ + _set_variant(theme, variant); +#if GLIB_CHECK_VERSION(2,26,0) + g_object_notify_by_pspec(G_OBJECT(theme), properties[PROP_VARIANT]); +#else + g_object_notify(G_OBJECT(theme), "variant"); +#endif +} + +const GList * +pidgin_conversation_theme_get_variants(PidginConvTheme *theme) +{ + PidginConvThemePrivate *priv; + + g_return_val_if_fail(theme != NULL, NULL); + + priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme); + + return priv->variants; +} + +char * +pidgin_conversation_theme_get_template_path(PidginConvTheme *theme) +{ + const char *dir; + + g_return_val_if_fail(theme != NULL, NULL); + + dir = purple_theme_get_dir(PURPLE_THEME(theme)); + + return get_template_path(dir); +} + +char * +pidgin_conversation_theme_get_css_path(PidginConvTheme *theme) +{ + PidginConvThemePrivate *priv; + const char *dir; + + g_return_val_if_fail(theme != NULL, NULL); + + priv = PIDGIN_CONV_THEME_GET_PRIVATE(theme); + + dir = purple_theme_get_dir(PURPLE_THEME(theme)); + if (!priv->variant) { + return g_build_filename(dir, "Contents", "Resources", "main.css", NULL); + } else { + char *file = g_strdup_printf("%s.css", priv->variant); + char *ret = g_build_filename(dir, "Contents", "Resources", "Variants", file, NULL); + g_free(file); + return ret; + } +} + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkconv-theme.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/gtkconv-theme.h Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,196 @@ +/** + * @file gtkconv-theme.h Pidgin Conversation Theme Class API + */ + +/* pidgin + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#ifndef PIDGIN_CONV_THEME_H +#define PIDGIN_CONV_THEME_H + +#include +#include +#include "conversation.h" +#include "theme.h" + +/** + * extends PurpleTheme (theme.h) + * A pidgin icon theme. + * This object represents a Pidgin icon theme. + * + * PidginConvTheme is a PurpleTheme Object. + */ +typedef struct _PidginConvTheme PidginConvTheme; +typedef struct _PidginConvThemeClass PidginConvThemeClass; + +#define PIDGIN_TYPE_CONV_THEME (pidgin_conversation_theme_get_type ()) +#define PIDGIN_CONV_THEME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIDGIN_TYPE_CONV_THEME, PidginConvTheme)) +#define PIDGIN_CONV_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIDGIN_TYPE_CONV_THEME, PidginConvThemeClass)) +#define PIDGIN_IS_CONV_THEME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIDGIN_TYPE_CONV_THEME)) +#define PIDGIN_IS_CONV_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIDGIN_TYPE_CONV_THEME)) +#define PIDGIN_CONV_THEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIDGIN_TYPE_CONV_THEME, PidginConvThemeClass)) + +struct _PidginConvTheme +{ + PurpleTheme parent; +}; + +struct _PidginConvThemeClass +{ + PurpleThemeClass parent_class; +}; + +typedef enum { + PIDGIN_CONVERSATION_THEME_TEMPLATE_MAIN, + PIDGIN_CONVERSATION_THEME_TEMPLATE_HEADER, + PIDGIN_CONVERSATION_THEME_TEMPLATE_FOOTER, + PIDGIN_CONVERSATION_THEME_TEMPLATE_TOPIC, + PIDGIN_CONVERSATION_THEME_TEMPLATE_STATUS, + PIDGIN_CONVERSATION_THEME_TEMPLATE_CONTENT, + PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTENT, + PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_NEXT_CONTENT, + PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTEXT, + PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_NEXT_CONTEXT, + PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTENT, + PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_NEXT_CONTENT, + PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTEXT, + PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_NEXT_CONTEXT, + PIDGIN_CONVERSATION_THEME_TEMPLATE_BASESTYLE_CSS + +} PidginConvThemeTemplateType; + +/**************************************************************************/ +/** @name Pidgin Conversation Theme API */ +/**************************************************************************/ +G_BEGIN_DECLS + +/** + * GObject foo. + * @internal. + */ +GType pidgin_conversation_theme_get_type(void); + +/** + * Get the Info.plist hash table from a conversation theme. + * + * @param theme The conversation theme + * + * @return The hash table. Keys are strings as outlined for message styles, + * values are GValue*s. This is an internal structure. Take a ref if + * necessary, but don't destroy it yourself. + */ +const GHashTable *pidgin_conversation_theme_get_info(const PidginConvTheme *theme); + +/** + * Set the Info.plist hash table for a conversation theme. + * + * @param theme The conversation theme + * @param info The new hash table. The theme will take ownership of this hash + * table. Do not use it yourself afterwards with holding a ref. + * For key and value specifications, @see pidgin_conversation_theme_get_info. + * + */ +void pidgin_conversation_theme_set_info(PidginConvTheme *theme, GHashTable *info); + +/** + * Lookup a key in a theme + * + * @param theme The conversation theme + * @param key The key to find + * @param specific Whether to search variant-specific keys + * + * @return The key information. If @a specific is @c TRUE, then keys are first + * searched by variant, then by general ones. Otherwise, only general + * key values are returned. + */ +const GValue *pidgin_conversation_theme_lookup(PidginConvTheme *theme, const char *key, gboolean specific); + +/** + * Get the template data from a conversation theme. + * + * @param theme The conversation theme + * @param type The type of template data + * + * @return The template data requested. Fallback is made as required by styles. + * Subsequent calls to this function will return cached values. + */ +const char *pidgin_conversation_theme_get_template(PidginConvTheme *theme, PidginConvThemeTemplateType type); + +/** + * Add an available variant name to a conversation theme. + * + * @param theme The conversation theme + * @param variant The name of the variant + * + * @Note The conversation theme will take ownership of the variant name string. + * This function should normally only be called by the theme loader. + */ +void pidgin_conversation_theme_add_variant(PidginConvTheme *theme, char *variant); + +/** + * Get the currently set variant name for a conversation theme. + * + * @param theme The conversation theme + * + * @return The current variant name. + */ +const char *pidgin_conversation_theme_get_variant(PidginConvTheme *theme); + +/** + * Set the variant name for a conversation theme. + * + * @param theme The conversation theme + * @param variant The name of the variant + * + */ +void pidgin_conversation_theme_set_variant(PidginConvTheme *theme, const char *variant); + +/** + * Get a list of available variants for a conversation theme. + * + * @param theme The conversation theme + * + * @return The list of variants. This GList and the string data are owned by + * the theme and should not be freed by the caller. + */ +const GList *pidgin_conversation_theme_get_variants(PidginConvTheme *theme); + +/** + * Get the path to the template HTML file. + * + * @param theme The conversation theme + * + * @return The path to the HTML file. + */ +char *pidgin_conversation_theme_get_template_path(PidginConvTheme *theme); + +/** + * Get the path to the current variant CSS file. + * + * @param theme The conversation theme + * + * @return The path to the CSS file. + */ +char *pidgin_conversation_theme_get_css_path(PidginConvTheme *theme); + +G_END_DECLS +#endif /* PIDGIN_CONV_THEME_H */ + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkconv.c --- a/pidgin/gtkconv.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkconv.c Fri Apr 06 04:30:00 2012 +0000 @@ -52,6 +52,8 @@ #include "notify.h" #include "prpl.h" #include "request.h" +#include "theme-loader.h" +#include "theme-manager.h" #include "util.h" #include "version.h" @@ -59,6 +61,8 @@ #include "gtkblist.h" #include "gtkconv.h" #include "gtkconvwin.h" +#include "gtkconv-theme.h" +#include "gtkconv-theme-loader.h" #include "gtkdialogs.h" #include "gtkimhtml.h" #include "gtkimhtmltoolbar.h" @@ -69,11 +73,55 @@ #include "gtkprivacy.h" #include "gtkthemes.h" #include "gtkutils.h" +#include "gtkwebview.h" #include "pidginstock.h" #include "pidgintooltip.h" +#include "smileyparser.h" #include "gtknickcolors.h" +#if !GTK_CHECK_VERSION(2,20,0) +#define gtk_widget_get_realized(x) GTK_WIDGET_REALIZED(x) + +#if !GTK_CHECK_VERSION(2,18,0) +#define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE(x) +#define gtk_widget_is_drawable(x) GTK_WIDGET_DRAWABLE(x) +#endif +#endif + +/** + * A GTK+ Instant Message pane. + */ +struct _PidginImPane +{ + GtkWidget *block; + GtkWidget *send_file; + GtkWidget *sep1; + GtkWidget *sep2; + GtkWidget *check; + GtkWidget *progress; + guint32 typing_timer; + + /* Buddy icon stuff */ + GtkWidget *icon_container; + GtkWidget *icon; + gboolean show_icon; + gboolean animate; + GdkPixbufAnimation *anim; + GdkPixbufAnimationIter *iter; + guint32 icon_timer; +}; + +/** + * GTK+ Chat panes. + */ +struct _PidginChatPane +{ + GtkWidget *count; + GtkWidget *list; + GtkWidget *topic_text; +}; + #define CLOSE_CONV_TIMEOUT_SECS (10 * 60) #define AUTO_RESPONSE "<AUTO-REPLY> : " @@ -144,10 +192,13 @@ static GList *offline_list = NULL; static GHashTable *prpl_lists = NULL; +static PurpleTheme *default_conv_theme = NULL; + static gboolean update_send_to_selection(PidginWindow *win); static void generate_send_to_items(PidginWindow *win); /* Prototypes. <-- because Paco-Paco hates this comment. */ +static void load_conv_theme(PidginConversation *gtkconv); static gboolean infopane_entry_activate(PidginConversation *gtkconv); static void got_typing_keypress(PidginConversation *gtkconv, gboolean first); static void gray_stuff_out(PidginConversation *gtkconv); @@ -158,7 +209,6 @@ static void gtkconv_set_unseen(PidginConversation *gtkconv, PidginUnseenState state); static void update_typing_icon(PidginConversation *gtkconv); static void update_typing_message(PidginConversation *gtkconv, const char *message); -static const char *item_factory_translate_func (const char *path, gpointer func_data); gboolean pidgin_conv_has_focus(PurpleConversation *conv); static GdkColor* generate_nick_colors(guint *numcolors, GdkColor background); static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast); @@ -176,7 +226,7 @@ static const GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name) { static GdkColor col; - GtkStyle *style = gtk_widget_get_style(gtkconv->imhtml); + GtkStyle *style = gtk_widget_get_style(gtkconv->webview); float scale; col = nick_colors[g_str_hash(name) % nbr_nick_colors]; @@ -196,15 +246,16 @@ static PurpleBlistNode * get_conversation_blist_node(PurpleConversation *conv) { + PurpleAccount *account = purple_conversation_get_account(conv); PurpleBlistNode *node = NULL; switch (purple_conversation_get_type(conv)) { case PURPLE_CONV_TYPE_IM: - node = PURPLE_BLIST_NODE(purple_find_buddy(conv->account, conv->name)); + node = PURPLE_BLIST_NODE(purple_find_buddy(account, purple_conversation_get_name(conv))); node = node ? node->parent : NULL; break; case PURPLE_CONV_TYPE_CHAT: - node = PURPLE_BLIST_NODE(purple_blist_find_chat(conv->account, conv->name)); + node = PURPLE_BLIST_NODE(purple_blist_find_chat(account, purple_conversation_get_name(conv))); break; default: break; @@ -276,7 +327,7 @@ default_formatize(PidginConversation *c) { PurpleConversation *conv = c->active_conv; - gtk_imhtml_setup_entry(GTK_IMHTML(c->entry), conv->features); + gtk_imhtml_setup_entry(GTK_IMHTML(c->entry), purple_conversation_get_features(conv)); } static void @@ -356,8 +407,32 @@ } tmp = g_string_free(str, FALSE); + } else if (!g_ascii_strcasecmp(args[0], "unsafe")) { + if (purple_debug_is_unsafe()) { + purple_debug_set_unsafe(FALSE); + purple_conversation_write(conv, NULL, _("Unsafe debugging is now disabled."), + PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL)); + } else { + purple_debug_set_unsafe(TRUE); + purple_conversation_write(conv, NULL, _("Unsafe debugging is now enabled."), + PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL)); + } + + return PURPLE_CMD_RET_OK; + } else if (!g_ascii_strcasecmp(args[0], "verbose")) { + if (purple_debug_is_verbose()) { + purple_debug_set_verbose(FALSE); + purple_conversation_write(conv, NULL, _("Verbose debugging is now disabled."), + PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL)); + } else { + purple_debug_set_verbose(TRUE); + purple_conversation_write(conv, NULL, _("Verbose debugging is now enabled."), + PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_SYSTEM, time(NULL)); + } + + return PURPLE_CMD_RET_OK; } else { - purple_conversation_write(conv, NULL, _("Supported debug options are: plugins version"), + purple_conversation_write(conv, NULL, _("Supported debug options are: plugins version unsafe verbose"), PURPLE_MESSAGE_NO_LOG|PURPLE_MESSAGE_ERROR, time(NULL)); return PURPLE_CMD_RET_OK; } @@ -376,11 +451,12 @@ static void clear_conversation_scrollback_cb(PurpleConversation *conv, void *data) { - PidginConversation *gtkconv = NULL; - - gtkconv = PIDGIN_CONVERSATION(conv); - if (gtkconv) - gtk_imhtml_clear(GTK_IMHTML(gtkconv->imhtml)); + PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); + + if (PIDGIN_CONVERSATION(conv)) { + load_conv_theme(gtkconv); + gtkconv->last_flags = 0; + } } static PurpleCmdRet @@ -420,8 +496,8 @@ g_string_append(s, _("No such command (in this context).")); } } else { - s = g_string_new(_("Use \"/help <command>\" for help on a specific command.\n" - "The following commands are available in this context:\n")); + s = g_string_new(_("Use \"/help <command>\" for help on a specific command.
" + "The following commands are available in this context:
")); text = purple_cmd_list(conv); for (l = text; l; l = l->next) @@ -498,8 +574,8 @@ PurplePluginProtocolInfo *prpl_info = NULL; PurpleConnection *gc; - if ((gc = purple_conversation_get_gc(conv))) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + if ((gc = purple_conversation_get_connection(conv))) + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if ((prpl_info != NULL) && (prpl_info->options & OPT_PROTO_SLASH_COMMANDS_NATIVE)) { char *spaceslash; @@ -578,7 +654,7 @@ gtk_widget_grab_focus(gtkconv->entry); - if (strlen(clean) == 0) { + if (!*clean) { g_free(buf); g_free(clean); return; @@ -591,7 +667,7 @@ flags |= PURPLE_MESSAGE_IMAGES; gc = purple_account_get_connection(account); - if (gc && (conv->features & PURPLE_CONNECTION_NO_NEWLINES)) { + if (gc && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_NO_NEWLINES)) { char **bufs; int i; @@ -657,7 +733,7 @@ PurpleConversation *conv = gtkconv->active_conv; PurpleConnection *gc; - if ((gc = purple_conversation_get_gc(conv))) { + if ((gc = purple_conversation_get_connection(conv))) { pidgin_retrieve_user_info_in_chat(gc, who, purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv))); } } @@ -669,7 +745,7 @@ PurpleConversation *conv = gtkconv->active_conv; if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - pidgin_retrieve_user_info(purple_conversation_get_gc(conv), + pidgin_retrieve_user_info(purple_conversation_get_connection(conv), purple_conversation_get_name(conv)); gtk_widget_grab_focus(gtkconv->entry); } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { @@ -757,7 +833,7 @@ if (!g_ascii_strcasecmp(buddy, "")) return; - serv_chat_invite(purple_conversation_get_gc(conv), + serv_chat_invite(purple_conversation_get_connection(conv), purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), message, buddy); } @@ -792,7 +868,7 @@ else return; - if (strcmp(convprotocol, purple_account_get_protocol_id(buddy->account))) + if (strcmp(convprotocol, purple_account_get_protocol_id(purple_buddy_get_account(buddy)))) { purple_notify_error(PIDGIN_CONVERSATION(info->conv), NULL, _("That buddy is not on the same protocol as this " @@ -877,7 +953,9 @@ GTK_RESPONSE_OK); gtk_container_set_border_width(GTK_CONTAINER(invite_dialog), PIDGIN_HIG_BOX_SPACE); gtk_window_set_resizable(GTK_WINDOW(invite_dialog), FALSE); +#if !GTK_CHECK_VERSION(2,22,0) gtk_dialog_set_has_separator(GTK_DIALOG(invite_dialog), FALSE); +#endif info->window = GTK_WIDGET(invite_dialog); @@ -974,13 +1052,13 @@ } static void -menu_new_conv_cb(gpointer data, guint action, GtkWidget *widget) +menu_new_conv_cb(GtkAction *action, gpointer data) { pidgin_dialogs_im(); } static void -menu_join_chat_cb(gpointer data, guint action, GtkWidget *widget) +menu_join_chat_cb(GtkAction *action, gpointer data) { pidgin_blist_joinchat_show(); } @@ -988,6 +1066,8 @@ static void savelog_writefile_cb(void *user_data, const char *filename) { + /* TODO WEBKIT: I don't know how to support this using webkit yet. */ +#if 0 PurpleConversation *conv = (PurpleConversation *)user_data; FILE *fp; const char *name; @@ -1014,6 +1094,7 @@ fprintf(fp, "\n\n\n"); fclose(fp); +#endif /* if 0 */ } /* @@ -1021,11 +1102,12 @@ * plaintext v. HTML file. */ static void -menu_save_as_cb(gpointer data, guint action, GtkWidget *widget) +menu_save_as_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); - PurpleBuddy *buddy = purple_find_buddy(conv->account, conv->name); + PurpleAccount *account = purple_conversation_get_account(conv); + PurpleBuddy *buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); const char *name; gchar *buf; gchar *c; @@ -1033,7 +1115,7 @@ if (buddy != NULL) name = purple_buddy_get_contact_alias(buddy); else - name = purple_normalize(conv->account, conv->name); + name = purple_normalize(account, purple_conversation_get_name(conv)); buf = g_strdup_printf("%s.html", name); for (c = buf ; *c ; c++) @@ -1051,7 +1133,7 @@ } static void -menu_view_log_cb(gpointer data, guint action, GtkWidget *widget) +menu_view_log_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1078,7 +1160,6 @@ gdk_window_set_cursor(gtkblist->window->window, cursor); gdk_window_set_cursor(win->window->window, cursor); gdk_cursor_unref(cursor); - gdk_display_flush(gdk_drawable_get_display(GDK_DRAWABLE(widget->window))); name = purple_conversation_get_name(conv); account = purple_conversation_get_account(conv); @@ -1105,7 +1186,7 @@ } static void -menu_clear_cb(gpointer data, guint action, GtkWidget *widget) +menu_clear_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1115,7 +1196,7 @@ } static void -menu_find_cb(gpointer data, guint action, GtkWidget *widget) +menu_find_cb(GtkAction *action, gpointer data) { PidginWindow *gtkwin = data; PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(gtkwin); @@ -1125,7 +1206,7 @@ #ifdef USE_VV static void -menu_initiate_media_call_cb(gpointer data, guint action, GtkWidget *widget) +menu_initiate_media_call_cb(GtkAction *action, gpointer data) { PidginWindow *win = (PidginWindow *)data; PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); @@ -1133,39 +1214,44 @@ purple_prpl_initiate_media(account, purple_conversation_get_name(conv), - action == 0 ? PURPLE_MEDIA_AUDIO : - action == 1 ? PURPLE_MEDIA_VIDEO : - action == 2 ? PURPLE_MEDIA_AUDIO | + action == win->audio_call ? PURPLE_MEDIA_AUDIO : + action == win->video_call ? PURPLE_MEDIA_VIDEO : + action == win->audio_video_call ? PURPLE_MEDIA_AUDIO | PURPLE_MEDIA_VIDEO : PURPLE_MEDIA_NONE); } #endif static void -menu_send_file_cb(gpointer data, guint action, GtkWidget *widget) +menu_send_file_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - serv_send_file(purple_conversation_get_gc(conv), purple_conversation_get_name(conv), NULL); - } - -} - -static void -menu_get_attention_cb(gpointer data, guint action, GtkWidget *widget) + serv_send_file(purple_conversation_get_connection(conv), purple_conversation_get_name(conv), NULL); + } + +} + +static void +menu_get_attention_cb(GObject *obj, gpointer data) { PidginWindow *win = data; PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - purple_prpl_send_attention(purple_conversation_get_gc(conv), - purple_conversation_get_name(conv), 0); - } -} - -static void -menu_add_pounce_cb(gpointer data, guint action, GtkWidget *widget) + int index; + if ((GtkAction *)obj == win->menu.get_attention) + index = 0; + else + index = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(obj), "index")); + purple_prpl_send_attention(purple_conversation_get_connection(conv), + purple_conversation_get_name(conv), index); + } +} + +static void +menu_add_pounce_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1177,7 +1263,7 @@ } static void -menu_insert_link_cb(gpointer data, guint action, GtkWidget *widget) +menu_insert_link_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PidginConversation *gtkconv; @@ -1191,7 +1277,7 @@ } static void -menu_insert_image_cb(gpointer data, guint action, GtkWidget *widget) +menu_insert_image_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PidginConversation *gtkconv; @@ -1206,7 +1292,7 @@ static void -menu_alias_cb(gpointer data, guint action, GtkWidget *widget) +menu_alias_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1233,7 +1319,7 @@ } static void -menu_get_info_cb(gpointer data, guint action, GtkWidget *widget) +menu_get_info_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1244,7 +1330,7 @@ } static void -menu_invite_cb(gpointer data, guint action, GtkWidget *widget) +menu_invite_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1255,7 +1341,7 @@ } static void -menu_block_cb(gpointer data, guint action, GtkWidget *widget) +menu_block_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1266,7 +1352,7 @@ } static void -menu_unblock_cb(gpointer data, guint action, GtkWidget *widget) +menu_unblock_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1277,7 +1363,7 @@ } static void -menu_add_remove_cb(gpointer data, guint action, GtkWidget *widget) +menu_add_remove_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1322,7 +1408,7 @@ } static void -menu_close_conv_cb(gpointer data, guint action, GtkWidget *widget) +menu_close_conv_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; @@ -1330,7 +1416,7 @@ } static void -menu_logging_cb(gpointer data, guint action, GtkWidget *widget) +menu_logging_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1342,7 +1428,7 @@ if (conv == NULL) return; - logging = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)); + logging = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)); if (logging == purple_conversation_is_logging(conv)) return; @@ -1356,16 +1442,14 @@ purple_conversation_write(conv, NULL, _("Logging started. Future messages in this conversation will be logged."), - conv->logs ? (PURPLE_MESSAGE_SYSTEM) : - (PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG), + PURPLE_MESSAGE_SYSTEM, time(NULL)); } else { purple_conversation_write(conv, NULL, _("Logging stopped. Future messages in this conversation will not be logged."), - conv->logs ? (PURPLE_MESSAGE_SYSTEM) : - (PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG), + PURPLE_MESSAGE_SYSTEM, time(NULL)); /* Disable the logging second, so that the above message can be logged. */ @@ -1373,7 +1457,7 @@ } /* Save the setting IFF it's different than the pref. */ - switch (conv->type) + switch (purple_conversation_get_type(conv)) { case PURPLE_CONV_TYPE_IM: if (logging == purple_prefs_get_bool("/purple/logging/log_ims")) @@ -1395,14 +1479,14 @@ } static void -menu_toolbar_cb(gpointer data, guint action, GtkWidget *widget) +menu_toolbar_cb(GtkAction *action, gpointer data) { purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar", - gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))); -} - -static void -menu_sounds_cb(gpointer data, guint action, GtkWidget *widget) + gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action))); +} + +static void +menu_sounds_cb(GtkAction *action, gpointer data) { PidginWindow *win = data; PurpleConversation *conv; @@ -1417,17 +1501,17 @@ gtkconv = PIDGIN_CONVERSATION(conv); gtkconv->make_sound = - gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)); + gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)); node = get_conversation_blist_node(conv); if (node) purple_blist_node_set_bool(node, "gtk-mute-sound", !gtkconv->make_sound); } static void -menu_timestamps_cb(gpointer data, guint action, GtkWidget *widget) +menu_timestamps_cb(GtkAction *action, gpointer data) { purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps", - gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))); + gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action))); } static void @@ -1445,7 +1529,7 @@ gc = purple_account_get_connection(account); g_return_if_fail(gc != NULL); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (prpl_info && prpl_info->get_cb_real_name) real_who = prpl_info->get_cb_real_name(gc, @@ -1496,12 +1580,12 @@ PurplePluginProtocolInfo *prpl_info; PurpleConversation *conv = gtkconv->active_conv; const char *who = g_object_get_data(G_OBJECT(w), "user_data"); - PurpleConnection *gc = purple_conversation_get_gc(conv); + PurpleConnection *gc = purple_conversation_get_connection(conv); gchar *real_who = NULL; g_return_if_fail(gc != NULL); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (prpl_info && prpl_info->get_cb_real_name) real_who = prpl_info->get_cb_real_name(gc, @@ -1522,32 +1606,6 @@ } static void -menu_chat_get_away_cb(GtkWidget *w, PidginConversation *gtkconv) -{ - PurpleConversation *conv = gtkconv->active_conv; - PurplePluginProtocolInfo *prpl_info = NULL; - PurpleConnection *gc; - char *who; - - gc = purple_conversation_get_gc(conv); - who = g_object_get_data(G_OBJECT(w), "user_data"); - - if (gc != NULL) { - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); - - /* - * May want to expand this to work similarly to menu_info_cb? - */ - - if (prpl_info->get_cb_away != NULL) - { - prpl_info->get_cb_away(gc, - purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), who); - } - } -} - -static void menu_chat_add_remove_cb(GtkWidget *w, PidginConversation *gtkconv) { PurpleConversation *conv = gtkconv->active_conv; @@ -1570,7 +1628,7 @@ static GtkTextMark * get_mark_for_user(PidginConversation *gtkconv, const char *who) { - GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)); + GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->webview)); char *tmp = g_strconcat("user:", who, NULL); GtkTextMark *mark = gtk_text_buffer_get_mark(buf, tmp); @@ -1581,6 +1639,8 @@ static void menu_last_said_cb(GtkWidget *w, PidginConversation *gtkconv) { +/* TODO WEBKIT: This doesn't work yet, of course... */ +#if 0 GtkTextMark *mark; const char *who; @@ -1591,6 +1651,7 @@ gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0); else g_return_if_reached(); +#endif /* if 0 */ } static GtkWidget * @@ -1599,12 +1660,13 @@ static GtkWidget *menu = NULL; PurplePluginProtocolInfo *prpl_info = NULL; PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); + PurpleAccount *account = purple_conversation_get_account(conv); gboolean is_me = FALSE; GtkWidget *button; PurpleBuddy *buddy = NULL; if (gc != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); /* * If a menu already exists, destroy it before creating a new one, @@ -1613,7 +1675,7 @@ if (menu) gtk_widget_destroy(menu); - if (!strcmp(chat->nick, purple_normalize(conv->account, who))) + if (!strcmp(purple_conv_chat_get_nick(chat), purple_normalize(account, who))) is_me = TRUE; menu = gtk_menu_new(); @@ -1678,18 +1740,8 @@ g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free); } - if (prpl_info && prpl_info->get_cb_away) { - button = pidgin_new_item_from_stock(menu, _("Get Away Message"), PIDGIN_STOCK_AWAY, - G_CALLBACK(menu_chat_get_away_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL); - - if (gc == NULL) - gtk_widget_set_sensitive(button, FALSE); - else - g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free); - } - if (!is_me && prpl_info && !(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { - if ((buddy = purple_find_buddy(conv->account, who)) != NULL) + if ((buddy = purple_find_buddy(account, who)) != NULL) button = pidgin_new_item_from_stock(menu, _("Remove"), GTK_STOCK_REMOVE, G_CALLBACK(menu_chat_add_remove_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL); else @@ -1710,8 +1762,8 @@ if (buddy != NULL) { - if (purple_account_is_connected(conv->account)) - pidgin_append_blist_node_proto_menu(menu, conv->account->gc, + if (purple_account_is_connected(account)) + pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(account), (PurpleBlistNode *)buddy); pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy); gtk_widget_show_all(menu); @@ -1737,7 +1789,7 @@ gtkconv = PIDGIN_CONVERSATION(conv); gtkchat = gtkconv->u.chat; account = purple_conversation_get_account(conv); - gc = account->gc; + gc = purple_account_get_connection(account); model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); @@ -1773,7 +1825,7 @@ gtkchat = gtkconv->u.chat; account = purple_conversation_get_account(conv); - gc = account->gc; + gc = purple_account_get_connection(account); model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); @@ -1805,10 +1857,13 @@ chat_do_im(gtkconv, who); } else if (event->button == 2 && event->type == GDK_BUTTON_PRESS) { /* Move to user's anchor */ +/* TODO WEBKIT: This isn't implemented yet. */ +#if 0 GtkTextMark *mark = get_mark_for_user(gtkconv, who); if(mark != NULL) gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0); +#endif /* if 0 */ } else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) { GtkWidget *menu = create_chat_menu (conv, who, gc); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, @@ -1885,8 +1940,8 @@ GtkWidget *from; GtkWidget *to; } transitions[] = { - {gtkconv->entry, gtkconv->imhtml}, - {gtkconv->imhtml, chat ? gtkconv->u.chat->list : gtkconv->entry}, + {gtkconv->entry, gtkconv->webview}, + {gtkconv->webview, chat ? gtkconv->u.chat->list : gtkconv->entry}, {chat ? gtkconv->u.chat->list : NULL, gtkconv->entry}, {NULL, NULL} }, *ptr; @@ -2142,14 +2197,14 @@ break; case GDK_Page_Up: - case GDK_KP_Page_Up: - gtk_imhtml_page_up(GTK_IMHTML(gtkconv->imhtml)); + case GDK_KP_Page_Up: + gtk_webview_page_up(GTK_WEBVIEW(gtkconv->webview)); return TRUE; break; case GDK_Page_Down: - case GDK_KP_Page_Down: - gtk_imhtml_page_down(GTK_IMHTML(gtkconv->imhtml)); + case GDK_KP_Page_Down: + gtk_webview_page_down(GTK_WEBVIEW(gtkconv->webview)); return TRUE; break; @@ -2236,6 +2291,7 @@ PurpleConversation *old_conv; GtkIMHtml *entry; const char *protocol_name; + PurpleConnectionFlags features; g_return_if_fail(conv != NULL); @@ -2254,17 +2310,18 @@ gtkconv->active_conv = conv; purple_conversation_set_logging(conv, - gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging))); + gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(gtkconv->win->menu.logging))); entry = GTK_IMHTML(gtkconv->entry); - protocol_name = purple_account_get_protocol_name(conv->account); + protocol_name = purple_account_get_protocol_name(purple_conversation_get_account(conv)); gtk_imhtml_set_protocol_name(entry, protocol_name); - gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), protocol_name); - - if (!(conv->features & PURPLE_CONNECTION_HTML)) + /* TODO WEBKIT: gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), protocol_name); */ + + features = purple_conversation_get_features(conv); + if (!(features & PURPLE_CONNECTION_HTML)) gtk_imhtml_clear_formatting(GTK_IMHTML(gtkconv->entry)); - else if (conv->features & PURPLE_CONNECTION_FORMATTING_WBFO && - !(old_conv->features & PURPLE_CONNECTION_FORMATTING_WBFO)) + else if (features & PURPLE_CONNECTION_FORMATTING_WBFO && + !(purple_conversation_get_features(old_conv) & PURPLE_CONNECTION_FORMATTING_WBFO)) { /* The old conversation allowed formatting on parts of the * buffer, but the new one only allows it on the whole @@ -2304,12 +2361,12 @@ gtk_imhtml_toggle_fontface(entry, fontface); - if (!(conv->features & PURPLE_CONNECTION_NO_FONTSIZE)) + if (!(features & PURPLE_CONNECTION_NO_FONTSIZE)) gtk_imhtml_font_set_size(entry, fontsize); gtk_imhtml_toggle_forecolor(entry, forecolor); - if (!(conv->features & PURPLE_CONNECTION_NO_BGCOLOR)) + if (!(features & PURPLE_CONNECTION_NO_BGCOLOR)) { gtk_imhtml_toggle_backcolor(entry, backcolor); gtk_imhtml_toggle_background(entry, background); @@ -2327,7 +2384,7 @@ * here, we didn't call gtk_imhtml_clear_formatting() (because we want to * preserve the formatting exactly as it is), so we have to do this now. */ gtk_imhtml_set_whole_buffer_formatting_only(entry, - (conv->features & PURPLE_CONNECTION_FORMATTING_WBFO)); + (features & PURPLE_CONNECTION_FORMATTING_WBFO)); } purple_signal_emit(pidgin_conversations_get_handle(), "conversation-switched", conv); @@ -2392,7 +2449,7 @@ /* We deleted all the text, so turn off typing. */ purple_conv_im_stop_send_typed_timeout(im); - serv_send_typing(purple_conversation_get_gc(conv), + serv_send_typing(purple_conversation_get_connection(conv), purple_conversation_get_name(conv), PURPLE_NOT_TYPING); } @@ -2557,7 +2614,7 @@ status = infopane_status = pidgin_conv_get_icon_stock(conv); if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - PurpleBuddy *b = purple_find_buddy(conv->account, conv->name); + PurpleBuddy *b = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); if (b) emblem = pidgin_blist_get_emblem((PurpleBlistNode*)b); } @@ -2578,7 +2635,7 @@ g_object_unref(emblem); if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons")) { - emblem = pidgin_create_prpl_icon(gtkconv->active_conv->account, PIDGIN_PRPL_ICON_SMALL); + emblem = pidgin_create_prpl_icon(purple_conversation_get_account(gtkconv->active_conv), PIDGIN_PRPL_ICON_SMALL); } else { emblem = NULL; } @@ -2634,7 +2691,7 @@ gtkconv = PIDGIN_CONVERSATION(conv); account = purple_conversation_get_account(conv); - if (!(account && account->gc)) { + if (!(account && purple_account_get_connection(account))) { gtkconv->u.im->icon_timer = 0; return FALSE; } @@ -2841,11 +2898,11 @@ 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); + buf = g_strdup_printf("%s.%s", purple_normalize(purple_conversation_get_account(conv), purple_conversation_get_name(conv)), ext); purple_request_file(gtkconv, _("Save Icon"), buf, TRUE, G_CALLBACK(saveicon_writefile_cb), NULL, - conv->account, NULL, conv, + purple_conversation_get_account(conv), NULL, conv, gtkconv); g_free(buf); @@ -3068,91 +3125,98 @@ return gtkconv->win; } -static GtkItemFactoryEntry menu_items[] = +static GtkActionEntry menu_entries[] = +/* TODO: fill out tooltips... */ { /* Conversation menu */ - { N_("/_Conversation"), NULL, NULL, 0, "", NULL }, - - { N_("/Conversation/New Instant _Message..."), "M", menu_new_conv_cb, - 0, "", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW }, - { N_("/Conversation/Join a _Chat..."), NULL, menu_join_chat_cb, - 0, "", PIDGIN_STOCK_CHAT }, - - { "/Conversation/sep0", NULL, NULL, 0, "", NULL }, - - { N_("/Conversation/_Find..."), NULL, menu_find_cb, 0, - "", GTK_STOCK_FIND }, - { N_("/Conversation/View _Log"), NULL, menu_view_log_cb, 0, "", NULL }, - { N_("/Conversation/_Save As..."), NULL, menu_save_as_cb, 0, - "", GTK_STOCK_SAVE_AS }, - { N_("/Conversation/Clea_r Scrollback"), "L", menu_clear_cb, 0, "", GTK_STOCK_CLEAR }, - - { "/Conversation/sep1", NULL, NULL, 0, "", NULL }, + { "ConversationMenu", NULL, N_("_Conversation"), NULL, NULL, NULL }, + { "NewInstantMessage", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, N_("New Instant _Message..."), "M", NULL, G_CALLBACK(menu_new_conv_cb) }, + { "JoinAChat", PIDGIN_STOCK_CHAT, N_("Join a _Chat..."), NULL, NULL, G_CALLBACK(menu_join_chat_cb) }, + { "Find", GTK_STOCK_FIND, N_("_Find..."), NULL, NULL, G_CALLBACK(menu_find_cb) }, + { "ViewLog", NULL, N_("View _Log"), NULL, NULL, G_CALLBACK(menu_view_log_cb) }, + { "SaveAs", GTK_STOCK_SAVE_AS, N_("_Save As..."), NULL, NULL, G_CALLBACK(menu_save_as_cb) }, + { "ClearScrollback", GTK_STOCK_CLEAR, N_("Clea_r Scrollback"), "L", NULL, G_CALLBACK(menu_clear_cb) }, #ifdef USE_VV - { N_("/Conversation/M_edia"), NULL, NULL, 0, "", NULL }, - - { N_("/Conversation/Media/_Audio Call"), NULL, menu_initiate_media_call_cb, 0, - "", PIDGIN_STOCK_TOOLBAR_AUDIO_CALL }, - { N_("/Conversation/Media/_Video Call"), NULL, menu_initiate_media_call_cb, 1, - "", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL }, - { N_("/Conversation/Media/Audio\\/Video _Call"), NULL, menu_initiate_media_call_cb, 2, - "", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL }, + { "MediaMenu", NULL, N_("M_edia"), NULL, NULL, NULL }, + { "AudioCall", PIDGIN_STOCK_TOOLBAR_AUDIO_CALL, N_("_Audio Call"), NULL, NULL, G_CALLBACK(menu_initiate_media_call_cb) }, + { "VideoCall", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL, N_("_Video Call"), NULL, NULL, G_CALLBACK(menu_initiate_media_call_cb) }, + { "AudioVideoCall", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL, N_("Audio/Video _Call"), NULL, NULL, G_CALLBACK(menu_initiate_media_call_cb) }, #endif - { N_("/Conversation/Se_nd File..."), NULL, menu_send_file_cb, 0, "", PIDGIN_STOCK_TOOLBAR_SEND_FILE }, - { N_("/Conversation/Get _Attention"), NULL, menu_get_attention_cb, 0, "", PIDGIN_STOCK_TOOLBAR_SEND_ATTENTION }, - { N_("/Conversation/Add Buddy _Pounce..."), NULL, menu_add_pounce_cb, - 0, "", NULL }, - { N_("/Conversation/_Get Info"), "O", menu_get_info_cb, 0, - "", PIDGIN_STOCK_TOOLBAR_USER_INFO }, - { N_("/Conversation/In_vite..."), NULL, menu_invite_cb, 0, - "", NULL }, - { N_("/Conversation/M_ore"), NULL, NULL, 0, "", NULL }, - - { "/Conversation/sep2", NULL, NULL, 0, "", NULL }, - - { N_("/Conversation/Al_ias..."), NULL, menu_alias_cb, 0, - "", NULL }, - { N_("/Conversation/_Block..."), NULL, menu_block_cb, 0, - "", PIDGIN_STOCK_TOOLBAR_BLOCK }, - { N_("/Conversation/_Unblock..."), NULL, menu_unblock_cb, 0, - "", PIDGIN_STOCK_TOOLBAR_UNBLOCK }, - { N_("/Conversation/_Add..."), NULL, menu_add_remove_cb, 0, - "", GTK_STOCK_ADD }, - { N_("/Conversation/_Remove..."), NULL, menu_add_remove_cb, 0, - "", GTK_STOCK_REMOVE }, - - { "/Conversation/sep3", NULL, NULL, 0, "", NULL }, - - { N_("/Conversation/Insert Lin_k..."), NULL, menu_insert_link_cb, 0, - "", PIDGIN_STOCK_TOOLBAR_INSERT_LINK }, - { N_("/Conversation/Insert Imag_e..."), NULL, menu_insert_image_cb, 0, - "", PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE }, - - { "/Conversation/sep4", NULL, NULL, 0, "", NULL }, - - - { N_("/Conversation/_Close"), NULL, menu_close_conv_cb, 0, - "", GTK_STOCK_CLOSE }, + { "SendFile", PIDGIN_STOCK_TOOLBAR_SEND_FILE, N_("Se_nd File..."), NULL, NULL, G_CALLBACK(menu_send_file_cb) }, + { "GetAttention", PIDGIN_STOCK_TOOLBAR_SEND_ATTENTION, N_("Get _Attention"), NULL, NULL, G_CALLBACK(menu_get_attention_cb) }, + { "AddBuddyPounce", NULL, N_("Add Buddy _Pounce..."), NULL, NULL, G_CALLBACK(menu_add_pounce_cb) }, + { "GetInfo", PIDGIN_STOCK_TOOLBAR_USER_INFO, N_("_Get Info"), "O", NULL, G_CALLBACK(menu_get_info_cb) }, + { "Invite", NULL, N_("In_vite..."), NULL, NULL, G_CALLBACK(menu_invite_cb) }, + { "MoreMenu", NULL, N_("M_ore"), NULL, NULL, NULL }, + { "Alias", NULL, N_("Al_ias..."), NULL, NULL, G_CALLBACK(menu_alias_cb) }, + { "Block", PIDGIN_STOCK_TOOLBAR_BLOCK, N_("_Block..."), NULL, NULL, G_CALLBACK(menu_block_cb) }, + { "Unblock", PIDGIN_STOCK_TOOLBAR_UNBLOCK, N_("_Unblock..."), NULL, NULL, G_CALLBACK(menu_unblock_cb) }, + { "Add", GTK_STOCK_ADD, N_("_Add..."), NULL, NULL, G_CALLBACK(menu_add_remove_cb) }, + { "Remove", GTK_STOCK_REMOVE, N_("_Remove..."), NULL, NULL, G_CALLBACK(menu_add_remove_cb) }, + { "InsertLink", PIDGIN_STOCK_TOOLBAR_INSERT_LINK, N_("Insert Lin_k..."), NULL, NULL, G_CALLBACK(menu_insert_link_cb) }, + { "InsertImage", PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE, N_("Insert Imag_e..."), NULL, NULL, G_CALLBACK(menu_insert_image_cb) }, + { "Close", GTK_STOCK_CLOSE, N_("_Close"), NULL, NULL, G_CALLBACK(menu_close_conv_cb) }, /* Options */ - { N_("/_Options"), NULL, NULL, 0, "", NULL }, - { N_("/Options/Enable _Logging"), NULL, menu_logging_cb, 0, "", NULL }, - { N_("/Options/Enable _Sounds"), NULL, menu_sounds_cb, 0, "", NULL }, - { "/Options/sep0", NULL, NULL, 0, "", NULL }, - { N_("/Options/Show Formatting _Toolbars"), NULL, menu_toolbar_cb, 0, "", NULL }, - { N_("/Options/Show Ti_mestamps"), NULL, menu_timestamps_cb, 0, "", NULL }, + { "OptionsMenu", NULL, N_("_Options"), NULL, NULL, NULL }, +}; + +/* Toggle items */ +static const GtkToggleActionEntry menu_toggle_entries[] = { + { "EnableLogging", NULL, N_("Enable _Logging"), NULL, NULL, G_CALLBACK(menu_logging_cb), FALSE }, + { "EnableSounds", NULL, N_("Enable _Sounds"), NULL, NULL, G_CALLBACK(menu_sounds_cb), FALSE }, + { "ShowFormattingToolbars", NULL, N_("Show Formatting _Toolbars"), NULL, NULL, G_CALLBACK(menu_toolbar_cb), FALSE }, + { "ShowTimestamps", NULL, N_("Show Ti_mestamps"), NULL, NULL, G_CALLBACK(menu_timestamps_cb), FALSE }, }; -static const int menu_item_count = -sizeof(menu_items) / sizeof(*menu_items); - -static const char * -item_factory_translate_func (const char *path, gpointer func_data) -{ - return _(path); -} +static const char *conversation_menu = +"" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" +#ifdef USE_VV + "" + "" + "" + "" + "" +#endif + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" +""; static void sound_method_pref_changed_cb(const char *name, PurplePrefType type, @@ -3163,19 +3227,18 @@ if (!strcmp(method, "none")) { - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.sounds), - FALSE); - gtk_widget_set_sensitive(win->menu.sounds, FALSE); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.sounds), + FALSE); + gtk_action_set_sensitive(win->menu.sounds, FALSE); } else { PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(win); if (gtkconv != NULL) - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.sounds), - gtkconv->make_sound); - gtk_widget_set_sensitive(win->menu.sounds, TRUE); - + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.sounds), + gtkconv->make_sound); + gtk_action_set_sensitive(win->menu.sounds, TRUE); } } @@ -3185,21 +3248,23 @@ { GList *list; PurpleConversation *conv; + PurpleAccount *account; PurpleBlistNode *node = NULL; PurpleChat *chat = NULL; PurpleBuddy *buddy = NULL; gboolean ret; conv = gtkconv->active_conv; + account = purple_conversation_get_account(conv); if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { - chat = purple_blist_find_chat(conv->account, conv->name); - - if ((chat == NULL) && (gtkconv->imhtml != NULL)) { - chat = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_chat"); - } - - if ((chat == NULL) && (gtkconv->imhtml != NULL)) { + chat = purple_blist_find_chat(account, purple_conversation_get_name(conv)); + + if ((chat == NULL) && (gtkconv->webview != NULL)) { + chat = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_chat"); + } + + if ((chat == NULL) && (gtkconv->webview != NULL)) { GHashTable *components; PurpleAccount *account = purple_conversation_get_account(conv); PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account)); @@ -3214,30 +3279,30 @@ g_hash_table_replace(components, g_strdup("channel"), g_strdup(purple_conversation_get_name(conv))); } - chat = purple_chat_new(conv->account, NULL, components); + chat = purple_chat_new(account, NULL, components); purple_blist_node_set_flags((PurpleBlistNode *)chat, PURPLE_BLIST_NODE_FLAG_NO_SAVE); - g_object_set_data_full(G_OBJECT(gtkconv->imhtml), "transient_chat", + g_object_set_data_full(G_OBJECT(gtkconv->webview), "transient_chat", chat, (GDestroyNotify)purple_blist_remove_chat); } } else { - if (!purple_account_is_connected(conv->account)) + if (!purple_account_is_connected(account)) return FALSE; - buddy = purple_find_buddy(conv->account, conv->name); + buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); /* gotta remain bug-compatible :( libpurple < 2.0.2 didn't handle * removing "isolated" buddy nodes well */ if (purple_version_check(2, 0, 2) == NULL) { - if ((buddy == NULL) && (gtkconv->imhtml != NULL)) { - buddy = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_buddy"); + if ((buddy == NULL) && (gtkconv->webview != NULL)) { + buddy = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_buddy"); } - if ((buddy == NULL) && (gtkconv->imhtml != NULL)) { - buddy = purple_buddy_new(conv->account, conv->name, NULL); + if ((buddy == NULL) && (gtkconv->webview != NULL)) { + buddy = purple_buddy_new(account, purple_conversation_get_name(conv), NULL); purple_blist_node_set_flags((PurpleBlistNode *)buddy, PURPLE_BLIST_NODE_FLAG_NO_SAVE); - g_object_set_data_full(G_OBJECT(gtkconv->imhtml), "transient_buddy", + g_object_set_data_full(G_OBJECT(gtkconv->webview), "transient_buddy", buddy, (GDestroyNotify)purple_buddy_destroy); } } @@ -3256,8 +3321,8 @@ /* XXX: */ } } else if (node) { - if (purple_account_is_connected(conv->account)) - pidgin_append_blist_node_proto_menu(menu, conv->account->gc, node); + if (purple_account_is_connected(account)) + pidgin_append_blist_node_proto_menu(menu, purple_account_get_connection(account), node); pidgin_append_blist_node_extended_menu(menu, node); } @@ -3303,38 +3368,100 @@ purple_prpl_get_media_caps(account, purple_conversation_get_name(conv)); - gtk_widget_set_sensitive(win->audio_call, + gtk_action_set_sensitive(win->audio_call, caps & PURPLE_MEDIA_CAPS_AUDIO ? TRUE : FALSE); - gtk_widget_set_sensitive(win->video_call, + gtk_action_set_sensitive(win->video_call, caps & PURPLE_MEDIA_CAPS_VIDEO ? TRUE : FALSE); - gtk_widget_set_sensitive(win->audio_video_call, + gtk_action_set_sensitive(win->audio_video_call, caps & PURPLE_MEDIA_CAPS_AUDIO_VIDEO ? TRUE : FALSE); } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { /* for now, don't care about chats... */ - gtk_widget_set_sensitive(win->audio_call, FALSE); - gtk_widget_set_sensitive(win->video_call, FALSE); - gtk_widget_set_sensitive(win->audio_video_call, FALSE); + gtk_action_set_sensitive(win->audio_call, FALSE); + gtk_action_set_sensitive(win->video_call, FALSE); + gtk_action_set_sensitive(win->audio_video_call, FALSE); } else { - gtk_widget_set_sensitive(win->audio_call, FALSE); - gtk_widget_set_sensitive(win->video_call, FALSE); - gtk_widget_set_sensitive(win->audio_video_call, FALSE); + gtk_action_set_sensitive(win->audio_call, FALSE); + gtk_action_set_sensitive(win->video_call, FALSE); + gtk_action_set_sensitive(win->audio_video_call, FALSE); } #endif } static void +regenerate_attention_items(PidginWindow *win) +{ + GtkWidget *attention; + GtkWidget *menu; + PurpleConversation *conv; + PurpleConnection *pc; + PurplePlugin *prpl = NULL; + PurplePluginProtocolInfo *prpl_info = NULL; + GList *list; + + conv = pidgin_conv_window_get_active_conversation(win); + if (!conv) + return; + + attention = gtk_ui_manager_get_widget(win->menu.ui, + "/Conversation/ConversationMenu/GetAttention"); + + /* Remove the previous entries */ + gtk_menu_item_set_submenu(GTK_MENU_ITEM(attention), NULL); + + pc = purple_conversation_get_connection(conv); + if (pc != NULL) + prpl = purple_connection_get_prpl(pc); + if (prpl != NULL) + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + + if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_attention_types)) { + list = prpl_info->get_attention_types(purple_connection_get_account(pc)); + + /* Multiple attention types */ + if (list && list->next) { + int index = 0; + + menu = gtk_menu_new(); + while (list) { + PurpleAttentionType *type; + GtkWidget *menuitem; + + type = list->data; + + menuitem = gtk_menu_item_new_with_label(purple_attention_type_get_name(type)); + g_object_set_data(G_OBJECT(menuitem), "index", GINT_TO_POINTER(index)); + g_signal_connect(G_OBJECT(menuitem), "activate", + G_CALLBACK(menu_get_attention_cb), + win); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + + index++; + list = g_list_delete_link(list, list); + } + + gtk_menu_item_set_submenu(GTK_MENU_ITEM(attention), menu); + gtk_widget_show_all(menu); + } + } +} + +static void regenerate_options_items(PidginWindow *win) { GtkWidget *menu; PidginConversation *gtkconv; GList *list; + GtkWidget *more_menu; gtkconv = pidgin_conv_window_get_active_gtkconv(win); - menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Conversation/More")); + more_menu = gtk_ui_manager_get_widget(win->menu.ui, + "/Conversation/ConversationMenu/MoreMenu"); + gtk_widget_show(more_menu); + menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(more_menu)); /* Remove the previous entries */ for (list = gtk_container_get_children(GTK_CONTAINER(menu)); list; ) @@ -3390,7 +3517,8 @@ action_items = g_list_delete_link(action_items, action_items); } - menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Options")); + item = gtk_ui_manager_get_widget(win->menu.ui, "/Conversation/OptionsMenu"); + menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(item)); list = purple_conversation_get_extended_menu(conv); if (list) { @@ -3414,6 +3542,7 @@ regenerate_media_items(win); regenerate_options_items(win); regenerate_plugins_items(win); + regenerate_attention_items(win); /* The following are to make sure the 'More' submenu is not regenerated every time * the focus shifts from 'Conversations' to some other menu and back. */ @@ -3426,7 +3555,7 @@ { /* The menubar has been deactivated. Make sure the 'More' submenu is regenerated next time * the 'Conversation' menu pops up. */ - GtkWidget *menuitem = gtk_item_factory_get_item(win->menu.item_factory, N_("/Conversation")); + GtkWidget *menuitem = gtk_ui_manager_get_widget(win->menu.ui, "/Conversation/ConversationMenu"); g_signal_handlers_unblock_by_func(G_OBJECT(menuitem), G_CALLBACK(menubar_activated), win); g_signal_handlers_disconnect_by_func(G_OBJECT(win->menu.menubar), G_CALLBACK(focus_out_from_menubar), win); @@ -3437,129 +3566,145 @@ { GtkAccelGroup *accel_group; const char *method; + GtkActionGroup *action_group; + GError *error; GtkWidget *menuitem; - accel_group = gtk_accel_group_new (); + action_group = gtk_action_group_new("ConversationActions"); + gtk_action_group_add_actions(action_group, + menu_entries, + G_N_ELEMENTS(menu_entries), + win); + gtk_action_group_add_toggle_actions(action_group, + menu_toggle_entries, + G_N_ELEMENTS(menu_toggle_entries), + win); +#ifdef ENABLE_NLS + gtk_action_group_set_translation_domain(action_group, + PACKAGE); +#endif + + win->menu.ui = gtk_ui_manager_new(); + gtk_ui_manager_insert_action_group(win->menu.ui, action_group, 0); + + accel_group = gtk_ui_manager_get_accel_group(win->menu.ui); gtk_window_add_accel_group(GTK_WINDOW(win->window), accel_group); - g_object_unref(accel_group); - - win->menu.item_factory = - gtk_item_factory_new(GTK_TYPE_MENU_BAR, "
", accel_group); - - gtk_item_factory_set_translate_func(win->menu.item_factory, - (GtkTranslateFunc)item_factory_translate_func, - NULL, NULL); - - gtk_item_factory_create_items(win->menu.item_factory, menu_item_count, - menu_items, win); g_signal_connect(G_OBJECT(accel_group), "accel-changed", G_CALLBACK(pidgin_save_accels_cb), NULL); + error = NULL; + if (!gtk_ui_manager_add_ui_from_string(win->menu.ui, conversation_menu, -1, &error)) + { + g_message("building menus failed: %s", error->message); + g_error_free(error); + exit(EXIT_FAILURE); + } + + win->menu.menubar = + gtk_ui_manager_get_widget(win->menu.ui, "/Conversation"); + /* Make sure the 'Conversation -> More' menuitems are regenerated whenever * the 'Conversation' menu pops up because the entries can change after the * conversation is created. */ - menuitem = gtk_item_factory_get_item(win->menu.item_factory, N_("/Conversation")); + menuitem = gtk_ui_manager_get_widget(win->menu.ui, "/Conversation/ConversationMenu"); g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menubar_activated), win); - win->menu.menubar = - gtk_item_factory_get_widget(win->menu.item_factory, "
"); - win->menu.view_log = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/View Log")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/ViewLog"); #ifdef USE_VV win->audio_call = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Media/Audio Call")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/MediaMenu/AudioCall"); win->video_call = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Media/Video Call")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/MediaMenu/VideoCall"); win->audio_video_call = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Media/Audio\\/Video Call")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/MediaMenu/AudioVideoCall"); #endif /* --- */ win->menu.send_file = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Send File...")); - - g_object_set_data(G_OBJECT(win->window), "get_attention", - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Get Attention"))); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/SendFile"); + + win->menu.get_attention = + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/GetAttention"); + win->menu.add_pounce = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Add Buddy Pounce...")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/AddBuddyPounce"); /* --- */ win->menu.get_info = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Get Info")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/GetInfo"); win->menu.invite = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Invite...")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/Invite"); /* --- */ win->menu.alias = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Alias...")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/Alias"); win->menu.block = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Block...")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/Block"); win->menu.unblock = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Unblock...")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/Unblock"); win->menu.add = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Add...")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/Add"); win->menu.remove = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Remove...")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/Remove"); /* --- */ win->menu.insert_link = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Insert Link...")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/InsertLink"); win->menu.insert_image = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Conversation/Insert Image...")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/ConversationMenu/InsertImage"); /* --- */ win->menu.logging = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Options/Enable Logging")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/OptionsMenu/EnableLogging"); win->menu.sounds = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Options/Enable Sounds")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/OptionsMenu/EnableSounds"); method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"); if (method != NULL && !strcmp(method, "none")) { - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.sounds), + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.sounds), FALSE); - gtk_widget_set_sensitive(win->menu.sounds, FALSE); + gtk_action_set_sensitive(win->menu.sounds, FALSE); } purple_prefs_connect_callback(win, PIDGIN_PREFS_ROOT "/sound/method", sound_method_pref_changed_cb, win); win->menu.show_formatting_toolbar = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Options/Show Formatting Toolbars")); + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/OptionsMenu/ShowFormattingToolbars"); win->menu.show_timestamps = - gtk_item_factory_get_widget(win->menu.item_factory, - N_("/Options/Show Timestamps")); - win->menu.show_icon = NULL; + gtk_ui_manager_get_action(win->menu.ui, + "/Conversation/OptionsMenu/ShowTimestamps"); win->menu.tray = pidgin_menu_tray_new(); gtk_menu_shell_append(GTK_MENU_SHELL(win->menu.menubar), @@ -3597,7 +3742,7 @@ time(NULL) > purple_conv_im_get_type_again(im))) { unsigned int timeout; - timeout = serv_send_typing(purple_conversation_get_gc(conv), + timeout = serv_send_typing(purple_conversation_get_connection(conv), purple_conversation_get_name(conv), PURPLE_TYPING); purple_conv_im_set_type_again(im, timeout); @@ -3648,6 +3793,8 @@ static void update_typing_message(PidginConversation *gtkconv, const char *message) { + /* TODO WEBKIT: this is not handled at all */ +#if 0 GtkTextBuffer *buffer; GtkTextMark *stmark, *enmark; @@ -3680,6 +3827,7 @@ gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_create_mark(buffer, "typing-notification-end", &iter, TRUE); } +#endif /* if 0 */ } static void @@ -3736,10 +3884,9 @@ if (win->menu.send_to == NULL) return FALSE; - if (!(b = purple_find_buddy(account, conv->name))) + if (!(b = purple_find_buddy(account, purple_conversation_get_name(conv)))) return FALSE; - gtk_widget_show(win->menu.send_to); menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(win->menu.send_to)); @@ -3896,8 +4043,8 @@ gtk_widget_show(menu); - if (gtkconv->active_conv->type == PURPLE_CONV_TYPE_IM) { - buds = purple_find_buddies(gtkconv->active_conv->account, gtkconv->active_conv->name); + if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_IM) { + buds = purple_find_buddies(purple_conversation_get_account(gtkconv->active_conv), purple_conversation_get_name(gtkconv->active_conv)); if (buds == NULL) { @@ -3921,7 +4068,8 @@ continue; account = purple_buddy_get_account(buddy); - if (purple_account_is_connected(account) || account == gtkconv->active_conv->account) + /* TODO WEBKIT: (I'm not actually sure if this is webkit-related --Mark Doliner) */ + if (purple_account_is_connected(account) /*|| account == purple_conversation_get_account(gtkconv->active_conv)*/) { /* Use the PurplePresence to get unique buddies. */ PurplePresence *presence = purple_buddy_get_presence(buddy); @@ -3980,10 +4128,11 @@ static void deleting_chat_buddy_cb(PurpleConvChatBuddy *cb) { - if (cb->ui_data) { - GtkTreeRowReference *ref = cb->ui_data; + GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cb); + + if (ref) { gtk_tree_row_reference_free(ref); - cb->ui_data = NULL; + purple_conv_chat_cb_set_ui_data(cb, NULL); } } @@ -4002,20 +4151,21 @@ GtkTreeIter iter; gboolean is_me = FALSE; gboolean is_buddy; - gchar *tmp, *alias_key, *name, *alias; + const gchar *name, *alias; + gchar *tmp, *alias_key; PurpleConvChatBuddyFlags flags; GdkColor *color = NULL; - alias = cb->alias; - name = cb->name; - flags = cb->flags; + alias = purple_conv_chat_cb_get_alias(cb); + name = purple_conv_chat_cb_get_name(cb); + flags = purple_conv_chat_cb_get_flags(cb); chat = PURPLE_CONV_CHAT(conv); gtkconv = PIDGIN_CONVERSATION(conv); gtkchat = gtkconv->u.chat; - gc = purple_conversation_get_gc(conv); - - if (!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl))) + gc = purple_conversation_get_connection(conv); + + if (!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)))) return; tm = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); @@ -4023,20 +4173,23 @@ stock = get_chat_buddy_status_icon(chat, name, flags); - if (!strcmp(chat->nick, purple_normalize(conv->account, old_name != NULL ? old_name : name))) + if (!strcmp(purple_conv_chat_get_nick(chat), purple_normalize(purple_conversation_get_account(conv), old_name != NULL ? old_name : name))) is_me = TRUE; - is_buddy = cb->buddy; + is_buddy = purple_conv_chat_cb_is_buddy(cb); tmp = g_utf8_casefold(alias, -1); alias_key = g_utf8_collate_key(tmp, -1); g_free(tmp); if (is_me) { +#if 0 + /* TODO WEBKIT: No tags in webkit stuff, yet. */ GtkTextTag *tag = gtk_text_tag_table_lookup( - gtk_text_buffer_get_tag_table(GTK_IMHTML(gtkconv->imhtml)->text_buffer), + gtk_text_buffer_get_tag_table(GTK_IMHTML(gtkconv->webview)->text_buffer), "send-name"); g_object_get(tag, "foreground-gdk", &color, NULL); +#endif /* if 0 */ } else { GtkTextTag *tag; if ((tag = get_buddy_tag(conv, name, 0, FALSE))) @@ -4064,13 +4217,13 @@ CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, -1); - if (cb->ui_data) { - GtkTreeRowReference *ref = cb->ui_data; + if (purple_conv_chat_cb_get_ui_data(cb)) { + GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cb); gtk_tree_row_reference_free(ref); } newpath = gtk_tree_model_get_path(tm, &iter); - cb->ui_data = gtk_tree_row_reference_new(tm, newpath); + purple_conv_chat_cb_set_ui_data(cb, gtk_tree_row_reference_new(tm, newpath)); gtk_tree_path_free(newpath); if (is_me && color) @@ -4100,7 +4253,7 @@ */ static void tab_complete_process_item(int *most_matched, const char *entered, gsize entered_bytes, char **partial, char *nick_partial, - GList **matches, char *name) + GList **matches, const char *name) { memcpy(nick_partial, name, entered_bytes); if (purple_utf8_strcasecmp(nick_partial, entered)) @@ -4222,7 +4375,7 @@ /* Users */ for (; l != NULL; l = l->next) { tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial, - &matches, ((PurpleConvChatBuddy *)l->data)->name); + &matches, purple_conv_chat_cb_get_name((PurpleConvChatBuddy *)l->data)); } @@ -4320,9 +4473,9 @@ char *new_topic; const char *current_topic; - gc = purple_conversation_get_gc(conv); - - if(!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl))) + gc = purple_conversation_get_connection(conv); + + if(!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)))) return; if(prpl_info->set_chat_topic == NULL) @@ -4397,6 +4550,7 @@ { PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); + PurpleAccount *account = purple_conversation_get_account(conv); GtkTreeModel *model; char *normalized_name; GtkTreeIter iter; @@ -4411,23 +4565,23 @@ if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) return; - normalized_name = g_strdup(purple_normalize(conv->account, buddy->name)); + normalized_name = g_strdup(purple_normalize(account, purple_buddy_get_name(buddy))); do { char *name; gtk_tree_model_get(model, &iter, CHAT_USERS_NAME_COLUMN, &name, -1); - if (!strcmp(normalized_name, purple_normalize(conv->account, name))) { + if (!strcmp(normalized_name, purple_normalize(account, name))) { const char *alias = name; char *tmp; char *alias_key = NULL; PurpleBuddy *buddy2; - if (strcmp(chat->nick, purple_normalize(conv->account, name))) { + if (strcmp(purple_conv_chat_get_nick(chat), purple_normalize(account, name))) { /* This user is not me, so look into updating the alias. */ - if ((buddy2 = purple_find_buddy(conv->account, name)) != NULL) { + if ((buddy2 = purple_find_buddy(account, name)) != NULL) { alias = purple_buddy_get_contact_alias(buddy2); } @@ -4462,10 +4616,10 @@ g_return_if_fail(node != NULL); g_return_if_fail(conv != NULL); - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); g_return_if_fail(gc != NULL); - g_return_if_fail(gc->prpl != NULL); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + g_return_if_fail(purple_connection_get_prpl(gc) != NULL); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME) return; @@ -4485,7 +4639,7 @@ else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) update_chat_alias((PurpleBuddy *)node, conv, gc, prpl_info); else if (PURPLE_BLIST_NODE_IS_CHAT(node) && - purple_conversation_get_account(conv) == ((PurpleChat*)node)->account) + purple_conversation_get_account(conv) == purple_chat_get_account((PurpleChat*)node)) { if (old_alias == NULL || g_utf8_collate(old_alias, purple_conversation_get_title(conv)) == 0) pidgin_conv_update_fields(conv, PIDGIN_CONV_SET_TITLE); @@ -4514,14 +4668,14 @@ if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) return; - normalized_name = g_strdup(purple_normalize(conv->account, buddy->name)); + normalized_name = g_strdup(purple_normalize(purple_conversation_get_account(conv), purple_buddy_get_name(buddy))); do { char *name; gtk_tree_model_get(model, &iter, CHAT_USERS_NAME_COLUMN, &name, -1); - if (!strcmp(normalized_name, purple_normalize(conv->account, name))) { + if (!strcmp(normalized_name, purple_normalize(purple_conversation_get_account(conv), name))) { gtk_list_store_set(GTK_LIST_STORE(model), &iter, CHAT_USERS_WEIGHT_COLUMN, is_buddy ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, -1); g_free(name); @@ -4600,7 +4754,7 @@ GdkRectangle oneline; int height, diff; int pad_top, pad_inside, pad_bottom; - int total_height = (gtkconv->imhtml->allocation.height + gtkconv->entry->allocation.height); + int total_height = (gtkconv->webview->allocation.height + gtkconv->entry->allocation.height); int max_height = total_height / 2; int min_lines = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/minimum_entry_lines"); int min_height; @@ -4672,8 +4826,8 @@ setup_chat_topic(PidginConversation *gtkconv, GtkWidget *vbox) { PurpleConversation *conv = gtkconv->active_conv; - PurpleConnection *gc = purple_conversation_get_gc(conv); - PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + PurpleConnection *gc = purple_conversation_get_connection(conv); + PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (prpl_info->options & OPT_PROTO_CHAT_TOPIC) { GtkWidget *hbox, *label; @@ -4714,7 +4868,7 @@ PurpleAccount *account = purple_conversation_get_account(conv); char *who = NULL; - if (account->gc == NULL) + if (purple_account_get_connection(account) == NULL) return FALSE; if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, path)) @@ -4722,8 +4876,8 @@ gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(account->gc->prpl); - node = (PurpleBlistNode*)(purple_find_buddy(conv->account, who)); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(purple_account_get_connection(account))); + node = (PurpleBlistNode*)(purple_find_buddy(purple_conversation_get_account(conv), who)); if (node && prpl_info && (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) pidgin_blist_draw_tooltip(node, gtkconv->infopane); @@ -4824,7 +4978,7 @@ gtkchat->list = list; - gtk_box_pack_start(GTK_BOX(lbox), + gtk_box_pack_start(GTK_BOX(lbox), pidgin_make_scrollable(list, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_IN, -1, -1), TRUE, TRUE, 0); } @@ -4838,15 +4992,15 @@ conv = gtkconv->active_conv; if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { - node = (PurpleBlistNode*)(purple_blist_find_chat(conv->account, conv->name)); + node = (PurpleBlistNode*)(purple_blist_find_chat(purple_conversation_get_account(conv), purple_conversation_get_name(conv))); if (!node) - node = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_chat"); + node = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_chat"); } else { - node = (PurpleBlistNode*)(purple_find_buddy(conv->account, conv->name)); + node = (PurpleBlistNode*)(purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv))); #if 0 /* Using the transient blist nodes to show the tooltip doesn't quite work yet. */ if (!node) - node = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_buddy"); + node = g_object_get_data(G_OBJECT(gtkconv->webview), "transient_buddy"); #endif } @@ -4861,7 +5015,7 @@ { gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL); - gtk_imhtml_search_clear(GTK_IMHTML(gtkconv->imhtml)); + webkit_web_view_unmark_text_matches(WEBKIT_WEB_VIEW(gtkconv->webview)); gtk_widget_hide_all(gtkconv->quickfind.container); gtk_widget_grab_focus(gtkconv->entry); @@ -4874,7 +5028,7 @@ switch (event->keyval) { case GDK_Return: case GDK_KP_Enter: - if (gtk_imhtml_search_find(GTK_IMHTML(gtkconv->imhtml), gtk_entry_get_text(GTK_ENTRY(entry)))) { + if (webkit_web_view_search_text(WEBKIT_WEB_VIEW(gtkconv->webview), gtk_entry_get_text(GTK_ENTRY(entry)), FALSE, TRUE, TRUE)) { gtk_widget_modify_base(gtkconv->quickfind.entry, GTK_STATE_NORMAL, NULL); } else { GdkColor col; @@ -4903,8 +5057,12 @@ close = pidgin_create_small_button(gtk_label_new("×")); gtk_box_pack_start(GTK_BOX(widget), close, FALSE, FALSE, 0); +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(close, _("Close Find bar")); +#else gtk_tooltips_set_tip(gtkconv->tooltips, close, _("Close Find bar"), NULL); +#endif label = gtk_label_new(_("Find:")); gtk_box_pack_start(GTK_BOX(widget), label, FALSE, FALSE, 10); @@ -4924,15 +5082,233 @@ /* }}} */ +static char * +replace_header_tokens(PurpleConversation *conv, const char *text) +{ + PurpleAccount *account = purple_conversation_get_account(conv); + GString *str; + const char *cur = text; + const char *prev = cur; + time_t mtime; + struct tm *tm = NULL; + + if (text == NULL || *text == '\0') + return NULL; + + str = g_string_new(NULL); + while ((cur = strchr(cur, '%'))) { + const char *replace = NULL; + const char *fin = NULL; + + if (g_str_has_prefix(cur, "%chatName%")) { + replace = purple_conversation_get_name(conv); + + } else if (g_str_has_prefix(cur, "%sourceName%")) { + replace = purple_account_get_alias(account); + if (replace == NULL) + replace = purple_account_get_username(account); + + } else if (g_str_has_prefix(cur, "%destinationName%")) { + PurpleBuddy *buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); + if (buddy) { + replace = purple_buddy_get_alias(buddy); + } else { + replace = purple_conversation_get_name(conv); + } + + } else if (g_str_has_prefix(cur, "%incomingIconPath%")) { + PurpleBuddyIcon *icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv)); + if (icon) + replace = purple_buddy_icon_get_full_path(icon); + + } else if (g_str_has_prefix(cur, "%outgoingIconPath%")) { + replace = purple_account_get_buddy_icon_path(account); + + } else if (g_str_has_prefix(cur, "%timeOpened")) { + const char *tmp = cur + strlen("%timeOpened"); + char *format = NULL; + + if (*tmp == '{') { + const char *end; + tmp++; + end = strstr(tmp, "}%"); + if (!end) /* Invalid string */ + continue; + format = g_strndup(tmp, end - tmp); + fin = end + 1; + } + + if (!tm) { + mtime = time(NULL); + tm = localtime(&mtime); + } + + replace = purple_utf8_strftime(format ? format : "%X", tm); + g_free(format); + + } else if (g_str_has_prefix(cur, "%dateOpened%")) { + if (!tm) { + mtime = time(NULL); + tm = localtime(&mtime); + } + + replace = purple_date_format_short(tm); + + } else { + cur++; + continue; + } + + /* Here we have a replacement to make */ + g_string_append_len(str, prev, cur - prev); + if (replace) + g_string_append(str, replace); + + /* And update the pointers */ + if (fin) { + prev = cur = fin + 1; + } else { + prev = cur = strchr(cur + 1, '%') + 1; + } + } + + /* And wrap it up */ + g_string_append(str, prev); + return g_string_free(str, FALSE); +} + +static char * +replace_template_tokens(PidginConvTheme *theme, const char *header, const char *footer) +{ + GString *str; + const char *text; + char **ms; + char *path; + + text = pidgin_conversation_theme_get_template(theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_MAIN); + if (text == NULL) + return NULL; + + ms = g_strsplit(text, "%@", 6); + if (ms[0] == NULL || ms[1] == NULL || ms[2] == NULL || ms[3] == NULL || ms[4] == NULL || ms[5] == NULL) { + g_strfreev(ms); + return NULL; + } + + str = g_string_new(NULL); + + g_string_append(str, ms[0]); + g_string_append(str, "file://"); + path = pidgin_conversation_theme_get_template_path(theme); + g_string_append(str, path); + g_free(path); + + g_string_append(str, ms[1]); + + text = pidgin_conversation_theme_get_template(theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_BASESTYLE_CSS); + g_string_append(str, text); + + g_string_append(str, ms[2]); + + g_string_append(str, "file://"); + path = pidgin_conversation_theme_get_css_path(theme); + g_string_append(str, path); + g_free(path); + + g_string_append(str, ms[3]); + if (header) + g_string_append(str, header); + g_string_append(str, ms[4]); + if (footer) + g_string_append(str, footer); + g_string_append(str, ms[5]); + + g_strfreev(ms); + + return g_string_free(str, FALSE); +} + +static void +set_theme_webkit_settings(WebKitWebView *webview, PidginConvTheme *theme) +{ + WebKitWebSettings *settings; + const GValue *val; + + g_object_get(G_OBJECT(webview), "settings", &settings, NULL); + + val = pidgin_conversation_theme_lookup(theme, "DefaultFontFamily", TRUE); + if (val && G_VALUE_HOLDS_STRING(val)) + g_object_set(G_OBJECT(settings), "default-font-family", g_value_get_string(val), NULL); + + val = pidgin_conversation_theme_lookup(theme, "DefaultFontSize", TRUE); + if (val && G_VALUE_HOLDS_INT(val)) + g_object_set(G_OBJECT(settings), "default-font-size", GINT_TO_POINTER(g_value_get_int(val)), NULL); + + val = pidgin_conversation_theme_lookup(theme, "DefaultBackgroundIsTransparent", TRUE); + if (val && G_VALUE_HOLDS_BOOLEAN(val)) + /* this does not work :( */ + webkit_web_view_set_transparent(webview, g_value_get_boolean(val)); +} + +static void +conv_variant_changed_cb(GObject *gobject, GParamSpec *pspec, gpointer user_data) +{ + PidginConversation *gtkconv = user_data; + char *path, *js; + + path = pidgin_conversation_theme_get_css_path(PIDGIN_CONV_THEME(gobject)); + js = g_strdup_printf("setStylesheet(\"mainStyle\", \"file://%s\");", path); + g_free(path); + gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), js); + g_free(js); +} + +static void +load_conv_theme(PidginConversation *gtkconv) +{ + char *header, *footer; + char *template; + char *basedir, *baseuri; + + header = replace_header_tokens(gtkconv->active_conv, + pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_HEADER)); + footer = replace_header_tokens(gtkconv->active_conv, + pidgin_conversation_theme_get_template(gtkconv->theme, PIDGIN_CONVERSATION_THEME_TEMPLATE_FOOTER)); + template = replace_template_tokens(gtkconv->theme, header, footer); + g_free(header); + g_free(footer); + + if (template == NULL) + return; + + set_theme_webkit_settings(WEBKIT_WEB_VIEW(gtkconv->webview), gtkconv->theme); + + basedir = pidgin_conversation_theme_get_template_path(gtkconv->theme); + baseuri = g_strdup_printf("file://%s", basedir); + webkit_web_view_load_string(WEBKIT_WEB_VIEW(gtkconv->webview), template, + "text/html", "UTF-8", baseuri); + + if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_CHAT) + gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), + "document.getElementById('Chat').className = 'groupchat'"); + + g_signal_connect(G_OBJECT(gtkconv->theme), "notify::variant", + G_CALLBACK(conv_variant_changed_cb), gtkconv); + + g_free(basedir); + g_free(baseuri); + g_free(template); +} + static GtkWidget * setup_common_pane(PidginConversation *gtkconv) { - GtkWidget *vbox, *frame, *imhtml_sw, *event_box; + GtkWidget *vbox, *frame, *webview_sw, *event_box; GtkCellRenderer *rend; GtkTreePath *path; PurpleConversation *conv = gtkconv->active_conv; PurpleBuddy *buddy; - gboolean chat = (conv->type == PURPLE_CONV_TYPE_CHAT); + gboolean chat = (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT); int buddyicon_size = 0; /* Setup the top part of the pane */ @@ -5023,9 +5399,12 @@ gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkconv->infopane), rend, "pixbuf", CONV_EMBLEM_COLUMN, NULL); g_object_set(rend, "xalign", 0.0, "xpad", 6, "ypad", 0, NULL); - /* Setup the gtkimhtml widget */ - frame = pidgin_create_imhtml(FALSE, >kconv->imhtml, NULL, &imhtml_sw); - gtk_widget_set_size_request(gtkconv->imhtml, -1, 0); + /* Setup the webkit widget */ + frame = pidgin_create_webview(FALSE, >kconv->webview, NULL, &webview_sw); + gtk_widget_set_size_request(gtkconv->webview, -1, 0); + + load_conv_theme(gtkconv); + if (chat) { GtkWidget *hpaned; @@ -5043,19 +5422,16 @@ } else { gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); } - gtk_widget_show(frame); - - gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml"); - gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),TRUE); - g_object_set_data(G_OBJECT(gtkconv->imhtml), "gtkconv", gtkconv); - - g_object_set(G_OBJECT(imhtml_sw), "vscrollbar-policy", GTK_POLICY_ALWAYS, NULL); - - g_signal_connect_after(G_OBJECT(gtkconv->imhtml), "button_press_event", + gtk_widget_show_all(frame); + + gtk_widget_set_name(gtkconv->webview, "pidgin_conv_webview"); + g_object_set_data(G_OBJECT(gtkconv->webview), "gtkconv", gtkconv); + + g_signal_connect_after(G_OBJECT(gtkconv->webview), "button_press_event", G_CALLBACK(entry_stop_rclick_cb), NULL); - g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_press_event", + g_signal_connect(G_OBJECT(gtkconv->webview), "key_press_event", G_CALLBACK(refocus_entry_cb), gtkconv); - g_signal_connect(G_OBJECT(gtkconv->imhtml), "key_release_event", + g_signal_connect(G_OBJECT(gtkconv->webview), "key_release_event", G_CALLBACK(refocus_entry_cb), gtkconv); pidgin_conv_setup_quickfind(gtkconv, vbox); @@ -5071,7 +5447,7 @@ gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry"); gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry), - purple_account_get_protocol_name(conv->account)); + purple_account_get_protocol_name(purple_conversation_get_account(conv))); g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup", G_CALLBACK(entry_popup_menu_cb), gtkconv); @@ -5118,7 +5494,7 @@ PurpleConversation *c; PurpleAccount *convaccount = purple_conversation_get_account(conv); PurpleConnection *gc = purple_account_get_connection(convaccount); - PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl) : NULL; + PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)) : NULL; if (sd->target == gdk_atom_intern("PURPLE_BLIST_NODE", FALSE)) { @@ -5238,7 +5614,7 @@ static PidginConversation * pidgin_conv_find_gtkconv(PurpleConversation * conv) { - PurpleBuddy *bud = purple_find_buddy(conv->account, conv->name); + PurpleBuddy *bud = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); PurpleContact *c; PurpleBlistNode *cn, *bn; @@ -5252,9 +5628,9 @@ for (bn = purple_blist_node_get_first_child(cn); bn; bn = purple_blist_node_get_sibling_next(bn)) { PurpleBuddy *b = PURPLE_BUDDY(bn); PurpleConversation *conv; - if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, b->name, b->account))) { - if (conv->ui_data) - return conv->ui_data; + if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(b), purple_buddy_get_account(b)))) { + if (PIDGIN_CONVERSATION(conv)) + return PIDGIN_CONVERSATION(conv); } } @@ -5296,6 +5672,8 @@ static void set_typing_font(GtkWidget *widget, GtkStyle *style, PidginConversation *gtkconv) { +/* TODO WEBKIT */ +#if 0 static PangoFontDescription *font_desc = NULL; static GdkColor *color = NULL; static gboolean enable = TRUE; @@ -5326,6 +5704,7 @@ } g_signal_handlers_disconnect_by_func(G_OBJECT(widget), set_typing_font, gtkconv); +#endif /* if 0 */ } /************************************************************************** @@ -5335,14 +5714,15 @@ private_gtkconv_new(PurpleConversation *conv, gboolean hidden) { PidginConversation *gtkconv; + const char *theme_name; + PurpleTheme *theme = NULL; PurpleConversationType conv_type = purple_conversation_get_type(conv); GtkWidget *pane = NULL; GtkWidget *tab_cont; PurpleBlistNode *convnode; - PurpleValue *value; if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) { - conv->ui_data = gtkconv; + purple_conversation_set_ui_data(conv, gtkconv); if (!g_list_find(gtkconv->convs, conv)) gtkconv->convs = g_list_prepend(gtkconv->convs, conv); pidgin_conv_switch_active_conversation(conv); @@ -5350,15 +5730,24 @@ } gtkconv = g_new0(PidginConversation, 1); - conv->ui_data = gtkconv; + purple_conversation_set_ui_data(conv, gtkconv); gtkconv->active_conv = conv; gtkconv->convs = g_list_prepend(gtkconv->convs, conv); gtkconv->send_history = g_list_append(NULL, NULL); /* Setup some initial variables. */ +#if !GTK_CHECK_VERSION(2,12,0) gtkconv->tooltips = gtk_tooltips_new(); +#endif gtkconv->unseen_state = PIDGIN_UNSEEN_NONE; gtkconv->unseen_count = 0; + theme_name = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/theme"); + if (theme_name && *theme_name) + theme = purple_theme_manager_find_theme(theme_name, "conversation"); + if (!theme) + theme = default_conv_theme; + gtkconv->theme = PIDGIN_CONV_THEME(g_object_ref(theme)); + gtkconv->last_flags = 0; if (conv_type == PURPLE_CONV_TYPE_IM) { gtkconv->u.im = g_malloc0(sizeof(PidginImPane)); @@ -5367,9 +5756,6 @@ } pane = setup_common_pane(gtkconv); - gtk_imhtml_set_format_functions(GTK_IMHTML(gtkconv->imhtml), - gtk_imhtml_get_format_functions(GTK_IMHTML(gtkconv->imhtml)) | GTK_IMHTML_IMAGE); - if (pane == NULL) { if (conv_type == PURPLE_CONV_TYPE_CHAT) g_free(gtkconv->u.chat); @@ -5377,7 +5763,7 @@ g_free(gtkconv->u.im); g_free(gtkconv); - conv->ui_data = NULL; + purple_conversation_set_ui_data(conv, NULL); return; } @@ -5392,7 +5778,7 @@ GTK_DEST_DEFAULT_DROP, te, sizeof(te) / sizeof(GtkTargetEntry), GDK_ACTION_COPY); - gtk_drag_dest_set(gtkconv->imhtml, 0, + gtk_drag_dest_set(gtkconv->webview, 0, te, sizeof(te) / sizeof(GtkTargetEntry), GDK_ACTION_COPY); @@ -5404,12 +5790,12 @@ G_CALLBACK(ignore_middle_click), NULL); g_signal_connect(G_OBJECT(pane), "drag_data_received", G_CALLBACK(conv_dnd_recv), gtkconv); - g_signal_connect(G_OBJECT(gtkconv->imhtml), "drag_data_received", + g_signal_connect(G_OBJECT(gtkconv->webview), "drag_data_received", G_CALLBACK(conv_dnd_recv), gtkconv); g_signal_connect(G_OBJECT(gtkconv->entry), "drag_data_received", G_CALLBACK(conv_dnd_recv), gtkconv); - g_signal_connect(gtkconv->imhtml, "style-set", G_CALLBACK(set_typing_font), gtkconv); + g_signal_connect(gtkconv->webview, "style-set", G_CALLBACK(set_typing_font), gtkconv); /* Setup the container for the tab. */ gtkconv->tab_cont = tab_cont = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); @@ -5422,11 +5808,9 @@ if (convnode == NULL || !purple_blist_node_get_bool(convnode, "gtk-mute-sound")) gtkconv->make_sound = TRUE; - if (convnode != NULL && - (value = g_hash_table_lookup(convnode->settings, "enable-logging")) && - purple_value_get_type(value) == PURPLE_TYPE_BOOLEAN) - { - purple_conversation_set_logging(conv, purple_value_get_boolean(value)); + if (convnode != NULL && purple_blist_node_has_setting(convnode, "enable-logging")) { + gboolean logging = purple_blist_node_get_bool(convnode, "enable-logging"); + purple_conversation_set_logging(conv, logging); } if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar")) @@ -5439,10 +5823,6 @@ else gtk_widget_hide(gtkconv->infopane_hbox); - gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml), - purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps")); - gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), - purple_account_get_protocol_name(conv->account)); g_signal_connect_swapped(G_OBJECT(pane), "focus", G_CALLBACK(gtk_widget_grab_focus), @@ -5455,10 +5835,10 @@ if (nick_colors == NULL) { nbr_nick_colors = NUM_NICK_COLORS; - nick_colors = generate_nick_colors(&nbr_nick_colors, gtk_widget_get_style(gtkconv->imhtml)->base[GTK_STATE_NORMAL]); - } - - if (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) + nick_colors = generate_nick_colors(&nbr_nick_colors, gtk_widget_get_style(gtkconv->webview)->base[GTK_STATE_NORMAL]); + } + + if (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) pidgin_themes_smiley_themeize_custom(gtkconv->entry); } @@ -5559,7 +5939,9 @@ g_free(gtkconv->u.chat); } +#if !GTK_CHECK_VERSION(2,12,0) gtk_object_sink(GTK_OBJECT(gtkconv->tooltips)); +#endif gtkconv->send_history = g_list_first(gtkconv->send_history); g_list_foreach(gtkconv->send_history, (GFunc)g_free, NULL); @@ -5569,6 +5951,10 @@ g_source_remove(gtkconv->attach.timer); } + g_object_disconnect(G_OBJECT(gtkconv->theme), "any_signal::notify", + conv_variant_changed_cb, gtkconv, NULL); + g_object_unref(gtkconv->theme); + g_free(gtkconv); } @@ -5596,6 +5982,7 @@ purple_conversation_write(conv, who, message, flags, mtime); } +#if 0 static const char * get_text_tag_color(GtkTextTag *tag) { @@ -5659,7 +6046,7 @@ &start, &end)) { GtkWidget *menu = NULL; PurpleConnection *gc = - purple_conversation_get_gc(conv); + purple_conversation_get_connection(conv); menu = create_chat_menu(conv, buddyname, gc); @@ -5676,10 +6063,13 @@ return FALSE; } +#endif static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag, gboolean create) { +/* TODO WEBKIT */ +#if 0 PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); GtkTextTag *buddytag; gchar *str; @@ -5713,8 +6103,11 @@ g_free(str); return buddytag; -} - +#endif /* if 0 */ + return NULL; +} + +#if 0 static void pidgin_conv_calculate_newday(PidginConversation *gtkconv, time_t mtime) { struct tm *tm = localtime(&mtime); @@ -5760,6 +6153,142 @@ *str = ret; #endif } +#endif + +static char * +replace_message_tokens( + const char *text, + PurpleConversation *conv, + const char *name, + const char *alias, + const char *message, + PurpleMessageFlags flags, + time_t mtime) +{ + GString *str; + const char *cur = text; + const char *prev = cur; + struct tm *tm = NULL; + + if (text == NULL || *text == '\0') + return NULL; + + str = g_string_new(NULL); + while ((cur = strchr(cur, '%'))) { + const char *replace = NULL; + const char *fin = NULL; + gpointer freeval = NULL; + + if (g_str_has_prefix(cur, "%message%")) { + replace = message; + + } else if (g_str_has_prefix(cur, "%messageClasses%")) { + GString *classes = g_string_new(NULL); +#define ADD_CLASS(f, class) \ + if (flags & f) \ + g_string_append(classes, class); + ADD_CLASS(PURPLE_MESSAGE_SEND, "outgoing "); + ADD_CLASS(PURPLE_MESSAGE_RECV, "incoming "); + ADD_CLASS(PURPLE_MESSAGE_SYSTEM, "event "); + ADD_CLASS(PURPLE_MESSAGE_AUTO_RESP, "autoreply "); + ADD_CLASS(PURPLE_MESSAGE_DELAYED, "history "); + ADD_CLASS(PURPLE_MESSAGE_NICK, "mention "); +#undef ADD_CLASS + + replace = freeval = g_string_free(classes, FALSE); + + } else if (g_str_has_prefix(cur, "%time")) { + const char *tmp = cur + strlen("%time"); + char *format = NULL; + + if (*tmp == '{') { + char *end; + tmp++; + end = strstr(tmp, "}%"); + if (!end) /* Invalid string */ + continue; + format = g_strndup(tmp, end - tmp); + fin = end + 1; + } + + if (!tm) + tm = localtime(&mtime); + + replace = purple_utf8_strftime(format ? format : "%X", tm); + g_free(format); + + } else if (g_str_has_prefix(cur, "%shortTime%")) { + if (!tm) + tm = localtime(&mtime); + + replace = purple_utf8_strftime("%H:%M", tm); + + } else if (g_str_has_prefix(cur, "%userIconPath%")) { + if (flags & PURPLE_MESSAGE_SEND) { + if (purple_account_get_bool(purple_conversation_get_account(conv), "use-global-buddyicon", TRUE)) { + replace = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon"); + } else { + PurpleStoredImage *img = purple_buddy_icons_find_account_icon(purple_conversation_get_account(conv)); + replace = purple_imgstore_get_filename(img); + } + if (replace == NULL || !g_file_test(replace, G_FILE_TEST_EXISTS)) { + replace = freeval = g_build_filename("Outgoing", "buddy_icon.png", NULL); + } + } else if (flags & PURPLE_MESSAGE_RECV) { + PurpleBuddyIcon *icon = purple_conv_im_get_icon(PURPLE_CONV_IM(conv)); + if (icon) + replace = purple_buddy_icon_get_full_path(icon); + if (replace == NULL || !g_file_test(replace, G_FILE_TEST_EXISTS)) { + replace = freeval = g_build_filename("Incoming", "buddy_icon.png", NULL); + } + } + + } else if (g_str_has_prefix(cur, "%senderScreenName%")) { + replace = name; + + } else if (g_str_has_prefix(cur, "%sender%")) { + replace = alias; + + } else if (g_str_has_prefix(cur, "%service%")) { + replace = purple_account_get_protocol_name(purple_conversation_get_account(conv)); + + } else if (g_str_has_prefix(cur, "%messageDirection%")) { + replace = purple_markup_is_rtl(message) ? "rtl" : "ltr"; + + } else if (g_str_has_prefix(cur, "%status%")) { + GString *classes = g_string_new(NULL); + + if (flags & PURPLE_MESSAGE_ERROR) + g_string_append(classes, "error "); + + replace = freeval = g_string_free(classes, FALSE); + + } else { + cur++; + continue; + } + + /* Here we have a replacement to make */ + g_string_append_len(str, prev, cur - prev); + if (replace) + g_string_append(str, replace); + g_free(freeval); + replace = freeval = NULL; + + /* And update the pointers */ + if (fin) { + prev = cur = fin + 1; + } else { + prev = cur = strchr(cur + 1, '%') + 1; + } + + } + + /* And wrap it up */ + g_string_append(str, prev); + + return g_string_free(str, FALSE); +} static void pidgin_conv_write_conv(PurpleConversation *conv, const char *name, const char *alias, @@ -5769,23 +6298,31 @@ PidginConversation *gtkconv; PurpleConnection *gc; PurpleAccount *account; +#if 0 int gtk_font_options = 0; int gtk_font_options_all = 0; - int max_scrollback_lines; - int line_count; char buf2[BUF_LONG]; gboolean show_date; char *mdate; char *str; char *with_font_tag; char *sml_attrib = NULL; +#endif size_t length; PurpleConversationType type; char *displaying; gboolean plugin_return; - char *bracket; - int tag_count = 0; +#if 0 gboolean is_rtl_message = FALSE; +#endif + + const char *message_html; + char *msg; + char *escape; + char *script; + char *smileyed; + PurpleMessageFlags old_flags; + const char *func = "appendMessage"; g_return_if_fail(conv != NULL); gtkconv = PIDGIN_CONVERSATION(conv); @@ -5842,56 +6379,56 @@ } length = strlen(displaying) + 1; - /* Awful hack to work around GtkIMHtml's inefficient rendering of messages with lots of formatting changes. - * If a message has over 100 '<' characters, strip formatting before appending it. Hopefully nobody actually - * needs that much formatting, anyway. - */ - for (bracket = strchr(displaying, '<'); bracket && *(bracket + 1); bracket = strchr(bracket + 1, '<')) - tag_count++; - - if (tag_count > 100) { - char *tmp = displaying; - displaying = purple_markup_strip_html(tmp); - g_free(tmp); - } - - line_count = gtk_text_buffer_get_line_count( - gtk_text_view_get_buffer(GTK_TEXT_VIEW( - gtkconv->imhtml))); - - max_scrollback_lines = purple_prefs_get_int( - PIDGIN_PREFS_ROOT "/conversations/scrollback_lines"); - /* If we're sitting at more than 100 lines more than the - max scrollback, trim down to max scrollback */ - if (max_scrollback_lines > 0 - && line_count > (max_scrollback_lines + 100)) { - GtkTextBuffer *text_buffer = gtk_text_view_get_buffer( - GTK_TEXT_VIEW(gtkconv->imhtml)); - GtkTextIter start, end; - - gtk_text_buffer_get_start_iter(text_buffer, &start); - gtk_text_buffer_get_iter_at_line(text_buffer, &end, - (line_count - max_scrollback_lines)); - gtk_imhtml_delete(GTK_IMHTML(gtkconv->imhtml), &start, &end); - } - - if (type == PURPLE_CONV_TYPE_CHAT) - { - /* Create anchor for user */ - GtkTextIter iter; - char *tmp = g_strconcat("user:", name, NULL); - - gtk_text_buffer_get_end_iter(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)), &iter); - gtk_text_buffer_create_mark(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)), - tmp, &iter, TRUE); - g_free(tmp); - } - - if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling")) - gtk_font_options_all |= GTK_IMHTML_USE_SMOOTHSCROLLING; - - if (gtk_text_buffer_get_char_count(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)))) - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "
", gtk_font_options_all | GTK_IMHTML_NO_SCROLL); + old_flags = gtkconv->last_flags; + if ((flags & PURPLE_MESSAGE_SEND) && (old_flags & PURPLE_MESSAGE_SEND)) { + message_html = pidgin_conversation_theme_get_template(gtkconv->theme, + PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_NEXT_CONTENT); + func = "appendNextMessage"; + + } else if (flags & PURPLE_MESSAGE_SEND) { + message_html = pidgin_conversation_theme_get_template(gtkconv->theme, + PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTENT); + + } else if ((flags & PURPLE_MESSAGE_RECV) && (old_flags & PURPLE_MESSAGE_RECV)) { + GList *history = purple_conversation_get_message_history(conv); + PurpleConvMessage *last_msg = (PurpleConvMessage *)history->data; + + /* If the senders are the same, use appendNextMessage */ + if (purple_strequal(purple_conversation_message_get_sender(last_msg), name)) { + message_html = pidgin_conversation_theme_get_template(gtkconv->theme, + PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_NEXT_CONTENT); + func = "appendNextMessage"; + } else { + message_html = pidgin_conversation_theme_get_template(gtkconv->theme, + PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTENT); + } + } else if (flags & PURPLE_MESSAGE_RECV) { + message_html = pidgin_conversation_theme_get_template(gtkconv->theme, + PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTENT); + + } else { + message_html = pidgin_conversation_theme_get_template(gtkconv->theme, + PIDGIN_CONVERSATION_THEME_TEMPLATE_STATUS); + } + gtkconv->last_flags = flags; + + smileyed = smiley_parse_markup(message, purple_account_get_protocol_id(account)); + msg = replace_message_tokens(message_html, conv, name, alias, smileyed, flags, mtime); + escape = gtk_webview_quote_js_string(msg ? msg : ""); + script = g_strdup_printf("%s(%s)", func, escape); + + purple_debug_info("webkit", "JS: %s\n", script); + gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), script); + + g_free(script); + g_free(smileyed); + g_free(msg); + g_free(escape); + +#if 0 + /* if the buffer is not empty add a
*/ + if (!gtk_webview_is_empty(GTK_WEBVIEW(gtkconv->webview))) + gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), "
"); /* First message in a conversation. */ if (gtkconv->newday == 0) @@ -5934,40 +6471,40 @@ gtk_font_options |= GTK_IMHTML_NO_COLOURS | GTK_IMHTML_NO_FONTS | GTK_IMHTML_NO_SIZES | GTK_IMHTML_NO_FORMATTING; /* this is gonna crash one day, I can feel it. */ - if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(conv->account)))->options & + if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(purple_conversation_get_account(conv))))->options & OPT_PROTO_USE_POINTSIZE) { gtk_font_options |= GTK_IMHTML_USE_POINTSIZE; } - if (!(flags & PURPLE_MESSAGE_RECV) && (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)) + if (!(flags & PURPLE_MESSAGE_RECV) && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)) { /* We want to see our own smileys. Need to revert it after send*/ - pidgin_themes_smiley_themeize_custom(gtkconv->imhtml); + pidgin_themes_smiley_themeize_custom(gtkconv->webview); } /* TODO: These colors should not be hardcoded so log.c can use them */ if (flags & PURPLE_MESSAGE_RAW) { - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), message, gtk_font_options_all); + gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), message); } else if (flags & PURPLE_MESSAGE_SYSTEM) { g_snprintf(buf2, sizeof(buf2), - "%s", + "%s%s", sml_attrib ? sml_attrib : "", mdate, displaying); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); + gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2); } else if (flags & PURPLE_MESSAGE_ERROR) { g_snprintf(buf2, sizeof(buf2), - "%s", + "%s %s", sml_attrib ? sml_attrib : "", mdate, displaying); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); + gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2); } else if (flags & PURPLE_MESSAGE_NO_LOG) { g_snprintf(buf2, BUF_LONG, - "%s", + "%s", sml_attrib ? sml_attrib : "", displaying); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all); + gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2); } else { char *new_message = g_memdup(displaying, length); char *alias_escaped = (alias ? g_markup_escape_text(alias, strlen(alias)) : g_strdup("")); @@ -5977,11 +6514,6 @@ int tag_end_offset = 0; const char *tagname = NULL; - GtkTextIter start, end; - GtkTextMark *mark; - GtkTextTag *tag; - GtkTextBuffer *buffer = GTK_IMHTML(gtkconv->imhtml)->text_buffer; - /* Enforce direction on alias */ if (is_rtl_message) str_embed_direction_chars(&alias_escaped); @@ -6042,55 +6574,41 @@ g_free(alias_escaped); + /* TODO WEBKIT */ +#if 0 if (tagname) tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), tagname); else tag = get_buddy_tag(conv, name, flags, TRUE); if (GTK_IMHTML(gtkconv->imhtml)->show_comments) { + { /* The color for the timestamp has to be set in the font-tags, unfortunately. * Applying the nick-tag to timestamps would work, but that can make it * bold. I thought applying the "comment" tag again, which has "weight" set * to PANGO_WEIGHT_NORMAL, would remove the boldness. But it doesn't. So * this will have to do. I don't terribly like it. -- sadrul */ - const char *color = get_text_tag_color(tag); + /* const char *color = get_text_tag_color(tag); */ g_snprintf(buf2, BUF_LONG, "", color ? "COLOR=\"" : "", color ? color : "", color ? "\"" : "", mdate); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all | GTK_IMHTML_NO_SCROLL); - } - - gtk_text_buffer_get_end_iter(buffer, &end); - mark = gtk_text_buffer_create_mark(buffer, NULL, &end, TRUE); - - g_snprintf(buf2, BUF_LONG, "%s ", sml_attrib ? sml_attrib : "", str); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, gtk_font_options_all | GTK_IMHTML_NO_SCROLL); - - gtk_text_buffer_get_end_iter(buffer, &end); - gtk_text_buffer_get_iter_at_mark(buffer, &start, mark); - gtk_text_buffer_apply_tag(buffer, tag, &start, &end); - gtk_text_buffer_delete_mark(buffer, mark); + gtk_webview_append_html (GTK_WEBVIEW(gtkconv->webview), buf2); + } +#endif /* if 0 */ + g_snprintf(buf2, BUF_LONG, "%s ", sml_attrib ? sml_attrib : "", str); + gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), buf2); g_free(str); - if(gc){ + if (gc) { char *pre = g_strdup_printf("", sml_attrib ? sml_attrib : ""); char *post = ""; - int pre_len = strlen(pre); - int post_len = strlen(post); - - with_font_tag = g_malloc(length + pre_len + post_len + 1); - - strcpy(with_font_tag, pre); - memcpy(with_font_tag + pre_len, new_message, length); - strcpy(with_font_tag + pre_len + length, post); - - length += pre_len + post_len; + with_font_tag = g_strdup_printf("%s%s%s", pre, new_message, post); g_free(pre); } else with_font_tag = g_memdup(new_message, length); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), - with_font_tag, gtk_font_options | gtk_font_options_all); + gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), + with_font_tag); g_free(with_font_tag); g_free(new_message); @@ -6099,6 +6617,8 @@ g_free(mdate); g_free(sml_attrib); +#endif + /* Tab highlighting stuff */ if (!(flags & PURPLE_MESSAGE_SEND) && !pidgin_conv_has_focus(conv)) { @@ -6117,11 +6637,13 @@ gtkconv_set_unseen(gtkconv, unseen); } - if (!(flags & PURPLE_MESSAGE_RECV) && (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)) +#if 0 + if (!(flags & PURPLE_MESSAGE_RECV) && (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)) { /* Restore the smiley-data */ - pidgin_themes_smiley_themeize(gtkconv->imhtml); - } + pidgin_themes_smiley_themeize(gtkconv->webview); + } +#endif purple_signal_emit(pidgin_conversations_get_handle(), (type == PURPLE_CONV_TYPE_IM ? "displayed-im-msg" : "displayed-chat-msg"), @@ -6132,7 +6654,7 @@ static gboolean get_iter_from_chatbuddy(PurpleConvChatBuddy *cb, GtkTreeIter *iter) { - GtkTreeRowReference *ref = cb->ui_data; + GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cb); GtkTreePath *path; GtkTreeModel *model; @@ -6226,11 +6748,11 @@ return; if (get_iter_from_chatbuddy(old_cbuddy, &iter)) { - GtkTreeRowReference *ref = old_cbuddy->ui_data; + GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(old_cbuddy); gtk_list_store_remove(GTK_LIST_STORE(model), &iter); gtk_tree_row_reference_free(ref); - old_cbuddy->ui_data = NULL; + purple_conv_chat_cb_set_ui_data(old_cbuddy, NULL); } g_return_if_fail(new_alias != NULL); @@ -6316,10 +6838,10 @@ cbuddy = purple_conv_chat_cb_find(chat, user); if (get_iter_from_chatbuddy(cbuddy, &iter)) { - GtkTreeRowReference *ref = cbuddy->ui_data; + GtkTreeRowReference *ref = purple_conv_chat_cb_get_ui_data(cbuddy); gtk_list_store_remove(GTK_LIST_STORE(model), &iter); gtk_tree_row_reference_free(ref); - cbuddy->ui_data = NULL; + purple_conv_chat_cb_set_ui_data(cbuddy, NULL); } if (cbuddy) @@ -6366,6 +6888,13 @@ } static gboolean +add_custom_smiley_for_webview(GtkWebView *webview, const char *sml, const char *smile) +{ + /* TODO WEBKIT: Smileys need to be added to webkit stuff */ + return TRUE; +} + +static gboolean pidgin_conv_custom_smiley_add(PurpleConversation *conv, const char *smile, gboolean remote) { PidginConversation *gtkconv; @@ -6382,7 +6911,7 @@ /* If possible add this smiley to the current theme. * The addition is only temporary: custom smilies aren't saved to disk. */ - conv_sml = purple_account_get_protocol_name(conv->account); + conv_sml = purple_account_get_protocol_name(purple_conversation_get_account(conv)); gtkconv = PIDGIN_CONVERSATION(conv); for (list = (struct smiley_list *)current_smiley_theme->list; list; list = list->next) { @@ -6392,7 +6921,7 @@ } } - if (!add_custom_smiley_for_imhtml(GTK_IMHTML(gtkconv->imhtml), sml, smile)) + if (!add_custom_smiley_for_webview(GTK_WEBVIEW(gtkconv->webview), sml, smile)) return FALSE; if (!remote) /* If it's a local custom smiley, then add it for the entry */ @@ -6406,12 +6935,14 @@ pidgin_conv_custom_smiley_write(PurpleConversation *conv, const char *smile, const guchar *data, gsize size) { +/* TODO WEBKIT */ +#if 0 PidginConversation *gtkconv; GtkIMHtmlSmiley *smiley; const char *sml; GError *error = NULL; - sml = purple_account_get_protocol_name(conv->account); + sml = purple_account_get_protocol_name(purple_conversation_get_account(conv)); gtkconv = PIDGIN_CONVERSATION(conv); smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile); @@ -6427,7 +6958,7 @@ if (!gdk_pixbuf_loader_write(smiley->loader, data, size, &error) || error) { purple_debug_warning("gtkconv", "gdk_pixbuf_loader_write() " - "failed with size=%zu: %s\n", size, + "failed with size=%" G_GSIZE_FORMAT ": %s\n", size, error ? error->message : "(no error message)"); if (error) g_error_free(error); @@ -6440,11 +6971,14 @@ g_object_unref(G_OBJECT(smiley->loader)); smiley->loader = gdk_pixbuf_loader_new(); } +#endif /* if 0 */ } static void pidgin_conv_custom_smiley_close(PurpleConversation *conv, const char *smile) { +/* TODO WEBKIT */ +#if 0 PidginConversation *gtkconv; GtkIMHtmlSmiley *smiley; const char *sml; @@ -6453,7 +6987,7 @@ g_return_if_fail(conv != NULL); g_return_if_fail(smile != NULL); - sml = purple_account_get_protocol_name(conv->account); + sml = purple_account_get_protocol_name(purple_conversation_get_account(conv)); gtkconv = PIDGIN_CONVERSATION(conv); smiley = gtk_imhtml_smiley_get(GTK_IMHTML(gtkconv->imhtml), sml, smile); @@ -6481,6 +7015,7 @@ g_object_unref(G_OBJECT(smiley->loader)); smiley->loader = gdk_pixbuf_loader_new(); } +#endif /* if 0 */ } static void @@ -6508,11 +7043,11 @@ PurpleAccount *account; win = pidgin_conv_get_window(gtkconv); - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); account = purple_conversation_get_account(conv); if (gc != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (win->menu.send_to != NULL) update_send_to_selection(win); @@ -6529,57 +7064,57 @@ /* Show stuff that applies to IMs, hide stuff that applies to chats */ /* Deal with menu items */ - gtk_widget_show(win->menu.view_log); - gtk_widget_show(win->menu.send_file); - gtk_widget_show(g_object_get_data(G_OBJECT(win->window), "get_attention")); - gtk_widget_show(win->menu.add_pounce); - gtk_widget_show(win->menu.get_info); - gtk_widget_hide(win->menu.invite); - gtk_widget_show(win->menu.alias); + gtk_action_set_visible(win->menu.view_log, TRUE); + gtk_action_set_visible(win->menu.send_file, TRUE); + gtk_action_set_visible(win->menu.get_attention, TRUE); + gtk_action_set_visible(win->menu.add_pounce, TRUE); + gtk_action_set_visible(win->menu.get_info, TRUE); + gtk_action_set_visible(win->menu.invite, FALSE); + gtk_action_set_visible(win->menu.alias, TRUE); if (purple_privacy_check(account, purple_conversation_get_name(conv))) { - gtk_widget_hide(win->menu.unblock); - gtk_widget_show(win->menu.block); + gtk_action_set_visible(win->menu.unblock, FALSE); + gtk_action_set_visible(win->menu.block, TRUE); } else { - gtk_widget_hide(win->menu.block); - gtk_widget_show(win->menu.unblock); + gtk_action_set_visible(win->menu.block, FALSE); + gtk_action_set_visible(win->menu.unblock, TRUE); } if ((account == NULL) || purple_find_buddy(account, purple_conversation_get_name(conv)) == NULL) { - gtk_widget_show(win->menu.add); - gtk_widget_hide(win->menu.remove); + gtk_action_set_visible(win->menu.add, TRUE); + gtk_action_set_visible(win->menu.remove, FALSE); } else { - gtk_widget_show(win->menu.remove); - gtk_widget_hide(win->menu.add); - } - - gtk_widget_show(win->menu.insert_link); - gtk_widget_show(win->menu.insert_image); + gtk_action_set_visible(win->menu.remove, TRUE); + gtk_action_set_visible(win->menu.add, FALSE); + } + + gtk_action_set_visible(win->menu.insert_link, TRUE); + gtk_action_set_visible(win->menu.insert_image, TRUE); } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { /* Show stuff that applies to Chats, hide stuff that applies to IMs */ /* Deal with menu items */ - gtk_widget_show(win->menu.view_log); - gtk_widget_hide(win->menu.send_file); - gtk_widget_hide(g_object_get_data(G_OBJECT(win->window), "get_attention")); - gtk_widget_hide(win->menu.add_pounce); - gtk_widget_hide(win->menu.get_info); - gtk_widget_show(win->menu.invite); - gtk_widget_show(win->menu.alias); - gtk_widget_hide(win->menu.block); - gtk_widget_hide(win->menu.unblock); + gtk_action_set_visible(win->menu.view_log, TRUE); + gtk_action_set_visible(win->menu.send_file, FALSE); + gtk_action_set_visible(win->menu.get_attention, FALSE); + gtk_action_set_visible(win->menu.add_pounce, FALSE); + gtk_action_set_visible(win->menu.get_info, FALSE); + gtk_action_set_visible(win->menu.invite, TRUE); + gtk_action_set_visible(win->menu.alias, TRUE); + gtk_action_set_visible(win->menu.block, FALSE); + gtk_action_set_visible(win->menu.unblock, FALSE); if ((account == NULL) || purple_blist_find_chat(account, purple_conversation_get_name(conv)) == NULL) { /* If the chat is NOT in the buddy list */ - gtk_widget_show(win->menu.add); - gtk_widget_hide(win->menu.remove); + gtk_action_set_visible(win->menu.add, TRUE); + gtk_action_set_visible(win->menu.remove, FALSE); } else { /* If the chat IS in the buddy list */ - gtk_widget_hide(win->menu.add); - gtk_widget_show(win->menu.remove); - } - - gtk_widget_show(win->menu.insert_link); - gtk_widget_show(win->menu.insert_image); + gtk_action_set_visible(win->menu.add, FALSE); + gtk_action_set_visible(win->menu.remove, TRUE); + } + + gtk_action_set_visible(win->menu.insert_link, TRUE); + gtk_action_set_visible(win->menu.insert_image, TRUE); } /* @@ -6590,31 +7125,35 @@ ((purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_CHAT) || !purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)) )) { + PurpleConnectionFlags features = purple_conversation_get_features(conv); /* Account is online */ /* Deal with the toolbar */ - if (conv->features & PURPLE_CONNECTION_HTML) + if (features & PURPLE_CONNECTION_HTML) { buttons = GTK_IMHTML_ALL; /* Everything on */ - if (conv->features & PURPLE_CONNECTION_NO_BGCOLOR) + if (features & PURPLE_CONNECTION_NO_BGCOLOR) buttons &= ~GTK_IMHTML_BACKCOLOR; - if (conv->features & PURPLE_CONNECTION_NO_FONTSIZE) + if (features & PURPLE_CONNECTION_NO_FONTSIZE) { buttons &= ~GTK_IMHTML_GROW; buttons &= ~GTK_IMHTML_SHRINK; } - if (conv->features & PURPLE_CONNECTION_NO_URLDESC) + if (features & PURPLE_CONNECTION_NO_URLDESC) buttons &= ~GTK_IMHTML_LINKDESC; } else { buttons = GTK_IMHTML_SMILEY | GTK_IMHTML_IMAGE; } - if (!(prpl_info->options & OPT_PROTO_IM_IMAGE)) - conv->features |= PURPLE_CONNECTION_NO_IMAGES; - - if(conv->features & PURPLE_CONNECTION_NO_IMAGES) + if (!(prpl_info->options & OPT_PROTO_IM_IMAGE) + && !(features & PURPLE_CONNECTION_NO_IMAGES)) { + features |= PURPLE_CONNECTION_NO_IMAGES; + purple_conversation_set_features(conv, features); + } + + if (features & PURPLE_CONNECTION_NO_IMAGES) buttons &= ~GTK_IMHTML_IMAGE; - if (conv->features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) + if (features & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) buttons |= GTK_IMHTML_CUSTOM_SMILEY; else buttons &= ~GTK_IMHTML_CUSTOM_SMILEY; @@ -6624,30 +7163,30 @@ gtk_imhtmltoolbar_associate_smileys(GTK_IMHTMLTOOLBAR(gtkconv->toolbar), purple_account_get_protocol_id(account)); /* Deal with menu items */ - gtk_widget_set_sensitive(win->menu.view_log, TRUE); - gtk_widget_set_sensitive(win->menu.add_pounce, TRUE); - gtk_widget_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL)); - gtk_widget_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL)); - gtk_widget_set_sensitive(win->menu.insert_link, (conv->features & PURPLE_CONNECTION_HTML)); - gtk_widget_set_sensitive(win->menu.insert_image, !(conv->features & PURPLE_CONNECTION_NO_IMAGES)); + gtk_action_set_sensitive(win->menu.view_log, TRUE); + gtk_action_set_sensitive(win->menu.add_pounce, TRUE); + gtk_action_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL)); + gtk_action_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL)); + gtk_action_set_sensitive(win->menu.insert_link, (features & PURPLE_CONNECTION_HTML)); + gtk_action_set_sensitive(win->menu.insert_image, !(features & PURPLE_CONNECTION_NO_IMAGES)); if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - gtk_widget_set_sensitive(win->menu.add, (prpl_info->add_buddy != NULL) || (prpl_info->add_buddy_with_invite != NULL)); - gtk_widget_set_sensitive(win->menu.remove, (prpl_info->remove_buddy != NULL)); - gtk_widget_set_sensitive(win->menu.send_file, + gtk_action_set_sensitive(win->menu.add, (prpl_info->add_buddy != NULL)); + gtk_action_set_sensitive(win->menu.remove, (prpl_info->remove_buddy != NULL)); + gtk_action_set_sensitive(win->menu.send_file, (prpl_info->send_file != NULL && (!prpl_info->can_receive_file || prpl_info->can_receive_file(gc, purple_conversation_get_name(conv))))); - gtk_widget_set_sensitive(g_object_get_data(G_OBJECT(win->window), "get_attention"), (prpl_info->send_attention != NULL)); - gtk_widget_set_sensitive(win->menu.alias, + gtk_action_set_sensitive(win->menu.get_attention, (prpl_info->send_attention != NULL)); + gtk_action_set_sensitive(win->menu.alias, (account != NULL) && (purple_find_buddy(account, purple_conversation_get_name(conv)) != NULL)); } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { - gtk_widget_set_sensitive(win->menu.add, (prpl_info->join_chat != NULL)); - gtk_widget_set_sensitive(win->menu.remove, (prpl_info->join_chat != NULL)); - gtk_widget_set_sensitive(win->menu.alias, + gtk_action_set_sensitive(win->menu.add, (prpl_info->join_chat != NULL)); + gtk_action_set_sensitive(win->menu.remove, (prpl_info->join_chat != NULL)); + gtk_action_set_sensitive(win->menu.alias, (account != NULL) && (purple_blist_find_chat(account, purple_conversation_get_name(conv)) != NULL)); } @@ -6657,18 +7196,17 @@ /* Or it's a chat that we've left. */ /* Then deal with menu items */ - gtk_widget_set_sensitive(win->menu.view_log, TRUE); - gtk_widget_set_sensitive(win->menu.send_file, FALSE); - gtk_widget_set_sensitive(g_object_get_data(G_OBJECT(win->window), - "get_attention"), FALSE); - gtk_widget_set_sensitive(win->menu.add_pounce, TRUE); - gtk_widget_set_sensitive(win->menu.get_info, FALSE); - gtk_widget_set_sensitive(win->menu.invite, FALSE); - gtk_widget_set_sensitive(win->menu.alias, FALSE); - gtk_widget_set_sensitive(win->menu.add, FALSE); - gtk_widget_set_sensitive(win->menu.remove, FALSE); - gtk_widget_set_sensitive(win->menu.insert_link, TRUE); - gtk_widget_set_sensitive(win->menu.insert_image, FALSE); + gtk_action_set_sensitive(win->menu.view_log, TRUE); + gtk_action_set_sensitive(win->menu.send_file, FALSE); + gtk_action_set_sensitive(win->menu.get_attention, FALSE); + gtk_action_set_sensitive(win->menu.add_pounce, TRUE); + gtk_action_set_sensitive(win->menu.get_info, FALSE); + gtk_action_set_sensitive(win->menu.invite, FALSE); + gtk_action_set_sensitive(win->menu.alias, FALSE); + gtk_action_set_sensitive(win->menu.add, FALSE); + gtk_action_set_sensitive(win->menu.remove, FALSE); + gtk_action_set_sensitive(win->menu.insert_link, TRUE); + gtk_action_set_sensitive(win->menu.insert_image, FALSE); } /* @@ -6680,7 +7218,7 @@ if ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) && (gtkconv->u.im->anim)) { - PurpleBuddy *buddy = purple_find_buddy(conv->account, conv->name); + PurpleBuddy *buddy = purple_find_buddy(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); window_icon = gdk_pixbuf_animation_get_static_image(gtkconv->u.im->anim); @@ -6728,6 +7266,7 @@ { gray_stuff_out(PIDGIN_CONVERSATION(conv)); generate_send_to_items(win); + regenerate_plugins_items(win); } if (fields & PIDGIN_CONV_TAB_ICON) @@ -6748,13 +7287,20 @@ topic = purple_conv_chat_get_topic(chat); gtk_entry_set_text(GTK_ENTRY(gtkchat->topic_text), topic ? topic : ""); +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(gtkchat->topic_text, + topic ? topic : ""); +#else gtk_tooltips_set_tip(gtkconv->tooltips, gtkchat->topic_text, topic ? topic : "", NULL); - } - } - +#endif + } + } + +#if 0 if (fields & PIDGIN_CONV_SMILEY_THEME) - pidgin_themes_smiley_themeize(PIDGIN_CONVERSATION(conv)->imhtml); + pidgin_themes_smiley_themeize(PIDGIN_CONVERSATION(conv)->webview); +#endif if ((fields & PIDGIN_CONV_COLORIZE_TITLE) || (fields & PIDGIN_CONV_SET_TITLE) || @@ -6781,7 +7327,7 @@ title = g_strdup(purple_conversation_get_title(conv)); if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - buddy = purple_find_buddy(account, conv->name); + buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); if (buddy) { markup = pidgin_blist_get_name_markup(buddy, FALSE, FALSE); } else { @@ -6809,7 +7355,7 @@ if (title != markup) g_free(markup); - if (!GTK_WIDGET_REALIZED(gtkconv->tab_label)) + if (!gtk_widget_get_realized(gtkconv->tab_label)) gtk_widget_realize(gtkconv->tab_label); accessibility_obj = gtk_widget_get_accessible(gtkconv->tab_cont); @@ -6826,7 +7372,7 @@ style = "tab-label-attention"; } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT) { atk_object_set_description(accessibility_obj, _("Unread Messages")); - if (gtkconv->active_conv->type == PURPLE_CONV_TYPE_CHAT) + if (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_CHAT) style = "tab-label-unreadchat"; else style = "tab-label-attention"; @@ -7038,7 +7584,7 @@ if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons")) return; - if (purple_conversation_get_gc(conv) == NULL) + if (purple_conversation_get_connection(conv) == NULL) return; buddy = purple_find_buddy(account, purple_conversation_get_name(conv)); @@ -7203,7 +7749,7 @@ tab = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page); /* Make sure the tab is not hidden beyond an arrow */ - if (!GTK_WIDGET_DRAWABLE(tab) && gtk_notebook_get_show_tabs(notebook)) + if (!gtk_widget_is_drawable(tab) && gtk_notebook_get_show_tabs(notebook)) continue; if (horiz) { @@ -7328,12 +7874,15 @@ gtkconv = PIDGIN_CONVERSATION(conv); win = gtkconv->win; - gtk_check_menu_item_set_active( - GTK_CHECK_MENU_ITEM(win->menu.show_timestamps), + gtk_toggle_action_set_active( + GTK_TOGGLE_ACTION(win->menu.show_timestamps), (gboolean)GPOINTER_TO_INT(value)); +/* TODO WEBKIT: Use WebKit version of this. */ +#if 0 gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml), (gboolean)GPOINTER_TO_INT(value)); +#endif /* if 0 */ } } @@ -7356,8 +7905,8 @@ gtkconv = PIDGIN_CONVERSATION(conv); win = gtkconv->win; - gtk_check_menu_item_set_active( - GTK_CHECK_MENU_ITEM(win->menu.show_formatting_toolbar), + gtk_toggle_action_set_active( + GTK_TOGGLE_ACTION(win->menu.show_formatting_toolbar), (gboolean)GPOINTER_TO_INT(value)); if ((gboolean)GPOINTER_TO_INT(value)) @@ -7501,7 +8050,7 @@ conv = gtkconv->active_conv; - if (conv->type == PURPLE_CONV_TYPE_CHAT || + if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT || gtkconv->unseen_count == 0 || (when_away && !purple_status_is_available( purple_account_get_active_status( @@ -7541,7 +8090,7 @@ { PurpleBuddy *buddy = (PurpleBuddy*)node; PurpleConversation *conv; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account); + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); if (conv) return PIDGIN_CONVERSATION(conv); } @@ -7566,16 +8115,18 @@ PIDGIN_CONV_MENU | PIDGIN_CONV_COLORIZE_TITLE); if (PURPLE_CONNECTION_IS_CONNECTED(gc) && - conv->type == PURPLE_CONV_TYPE_CHAT && - conv->account == gc->account && + purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT && + purple_conversation_get_account(conv) == purple_connection_get_account(gc) && purple_conversation_get_data(conv, "want-to-rejoin")) { GHashTable *comps = NULL; - PurpleChat *chat = purple_blist_find_chat(conv->account, conv->name); + PurpleChat *chat = purple_blist_find_chat(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); if (chat == NULL) { - if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) - comps = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, conv->name); + PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + + if (prpl_info->chat_info_defaults != NULL) + comps = prpl_info->chat_info_defaults(gc, purple_conversation_get_name(conv)); } else { - comps = chat->components; + comps = purple_chat_get_components(chat); } serv_join_chat(gc, comps); if (chat == NULL && comps != NULL) @@ -7642,7 +8193,7 @@ { PurpleConversation *conv; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account); + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); if (conv) pidgin_conv_update_fields(conv, PIDGIN_CONV_TAB_ICON); } @@ -7652,7 +8203,7 @@ { PurpleConversation *conv; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, buddy->name, buddy->account); + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy)); if (conv) pidgin_conv_update_fields(conv, PIDGIN_CONV_BUDDY_ICON); } @@ -7717,7 +8268,7 @@ message_compare(gconstpointer p1, gconstpointer p2) { const PurpleConvMessage *m1 = p1, *m2 = p2; - return (m1->when > m2->when); + return (purple_conversation_message_get_timestamp(m1) > purple_conversation_message_get_timestamp(m2)); } /* Adds some message history to the gtkconv. This happens in a idle-callback. */ @@ -7725,19 +8276,27 @@ add_message_history_to_gtkconv(gpointer data) { PidginConversation *gtkconv = data; + GtkWebView *webview = GTK_WEBVIEW(gtkconv->webview); int count = 0; int timer = gtkconv->attach.timer; time_t when = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtkconv->entry), "attach-start-time")); - gboolean im = (gtkconv->active_conv->type == PURPLE_CONV_TYPE_IM); + gboolean im = (purple_conversation_get_type(gtkconv->active_conv) == PURPLE_CONV_TYPE_IM); gtkconv->attach.timer = 0; while (gtkconv->attach.current && count < 100) { /* XXX: 100 is a random value here */ PurpleConvMessage *msg = gtkconv->attach.current->data; - if (!im && when && when < msg->when) { - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "

", 0); + if (!im && when && when < purple_conversation_message_get_timestamp(msg)) { + gtk_webview_append_html(webview, "

"); + gtk_webview_scroll_to_end(webview, TRUE); g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL); } - pidgin_conv_write_conv(msg->conv, msg->who, msg->alias, msg->what, msg->flags, msg->when); + pidgin_conv_write_conv( + purple_conversation_message_get_conv(msg), + purple_conversation_message_get_sender(msg), + purple_conversation_message_get_alias(msg), + purple_conversation_message_get_message(msg), + purple_conversation_message_get_flags(msg), + purple_conversation_message_get_timestamp(msg)); if (im) { gtkconv->attach.current = g_list_delete_link(gtkconv->attach.current, gtkconv->attach.current); } else { @@ -7760,16 +8319,23 @@ GList *history = purple_conversation_get_message_history(conv); for (; history; history = history->next) { PurpleConvMessage *msg = history->data; - if (msg->when > when) + if (purple_conversation_message_get_timestamp(msg) > when) msgs = g_list_prepend(msgs, msg); } } msgs = g_list_sort(msgs, message_compare); for (; msgs; msgs = g_list_delete_link(msgs, msgs)) { PurpleConvMessage *msg = msgs->data; - pidgin_conv_write_conv(msg->conv, msg->who, msg->alias, msg->what, msg->flags, msg->when); - } - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "

", 0); + pidgin_conv_write_conv( + purple_conversation_message_get_conv(msg), + purple_conversation_message_get_sender(msg), + purple_conversation_message_get_alias(msg), + purple_conversation_message_get_message(msg), + purple_conversation_message_get_flags(msg), + purple_conversation_message_get_timestamp(msg)); + } + gtk_webview_append_html(webview, "

"); + gtk_webview_scroll_to_end(webview, TRUE); g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", NULL); } @@ -7845,16 +8411,16 @@ g_return_val_if_reached(TRUE); } g_object_set_data(G_OBJECT(gtkconv->entry), "attach-start-time", - GINT_TO_POINTER(((PurpleConvMessage*)(list->data))->when)); + GINT_TO_POINTER(purple_conversation_message_get_timestamp((PurpleConvMessage*)(list->data)))); gtkconv->attach.timer = g_idle_add(add_message_history_to_gtkconv, gtkconv); } else { purple_signal_emit(pidgin_conversations_get_handle(), "conversation-displayed", gtkconv); } - if (conv->type == PURPLE_CONV_TYPE_CHAT) { + if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { pidgin_conv_update_fields(conv, PIDGIN_CONV_TOPIC); - pidgin_conv_chat_add_users(conv, PURPLE_CONV_CHAT(conv)->in_room, TRUE); + pidgin_conv_chat_add_users(conv, purple_conv_chat_get_users(PURPLE_CONV_CHAT(conv)), TRUE); } return TRUE; @@ -7873,14 +8439,17 @@ { void *handle = pidgin_conversations_get_handle(); void *blist_handle = purple_blist_get_handle(); + char *theme_dir; /* Conversations */ purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations"); + purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/themes"); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/use_smooth_scrolling", TRUE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/close_on_tabs", TRUE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold", FALSE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic", FALSE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline", FALSE); + purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/send_strike", FALSE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/spellcheck", TRUE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/show_incoming_formatting", TRUE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/resize_custom_smileys", TRUE); @@ -8159,6 +8728,11 @@ purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", handle, PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL); + purple_theme_manager_register_type(g_object_new(PIDGIN_TYPE_CONV_THEME_LOADER, "type", "conversation", NULL)); + theme_dir = g_build_filename(DATADIR, "pidgin", "theme", NULL); + default_conv_theme = purple_theme_manager_load_theme(theme_dir, "conversation"); + g_free(theme_dir); + { /* Set default tab colors */ GString *str = g_string_new(NULL); @@ -8304,8 +8878,9 @@ gtk_container_set_border_width(GTK_CONTAINER(warn_close_dialog), 6); gtk_window_set_resizable(GTK_WINDOW(warn_close_dialog), FALSE); - gtk_dialog_set_has_separator(GTK_DIALOG(warn_close_dialog), - FALSE); +#if !GTK_CHECK_VERSION(2,22,0) + gtk_dialog_set_has_separator(GTK_DIALOG(warn_close_dialog), FALSE); +#endif /* Setup the outside spacing. */ vbox = GTK_DIALOG(warn_close_dialog)->vbox; @@ -8607,9 +9182,9 @@ /* Right click was pressed. Popup the context menu. */ GtkWidget *menu = gtk_menu_new(), *sub; gboolean populated = populate_menu_with_options(menu, gtkconv, TRUE); + sub = gtk_menu_item_get_submenu(GTK_MENU_ITEM(gtkconv->win->menu.send_to)); - - if (sub && GTK_WIDGET_IS_SENSITIVE(gtkconv->win->menu.send_to)) { + if (sub && gtk_widget_is_sensitive(gtkconv->win->menu.send_to)) { GtkWidget *item = gtk_menu_item_new_with_mnemonic(_("S_end To")); if (populated) pidgin_separator(menu); @@ -9042,18 +9617,18 @@ PurpleConversation *conv = gtkconv->active_conv; const char *text = NULL; - if (!GTK_WIDGET_VISIBLE(gtkconv->infopane)) { + if (!gtk_widget_get_visible(gtkconv->infopane)) { /* There's already an entry for alias. Let's not create another one. */ return FALSE; } - if (!purple_account_is_connected(gtkconv->active_conv->account)) { + if (!purple_account_is_connected(purple_conversation_get_account(gtkconv->active_conv))) { /* Do not allow aliasing someone on a disconnected account. */ return FALSE; } if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - PurpleBuddy *buddy = purple_find_buddy(gtkconv->active_conv->account, gtkconv->active_conv->name); + PurpleBuddy *buddy = purple_find_buddy(purple_conversation_get_account(gtkconv->active_conv), purple_conversation_get_name(gtkconv->active_conv)); if (!buddy) /* This buddy isn't in your buddy list, so we can't alias him */ return FALSE; @@ -9063,9 +9638,9 @@ PurpleConnection *gc; PurplePluginProtocolInfo *prpl_info = NULL; - gc = purple_conversation_get_gc(conv); + gc = purple_conversation_get_connection(conv); if (gc != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (prpl_info && prpl_info->set_chat_topic == NULL) /* This protocol doesn't support setting the chat room topic */ return FALSE; @@ -9126,8 +9701,8 @@ /* Update the menubar */ - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging), - purple_conversation_is_logging(conv)); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtkconv->win->menu.logging), + purple_conversation_is_logging(conv)); generate_send_to_items(win); regenerate_options_items(win); @@ -9137,14 +9712,14 @@ sound_method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"); if (strcmp(sound_method, "none") != 0) - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.sounds), - gtkconv->make_sound); - - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.show_formatting_toolbar), - purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar")); - - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.show_timestamps), - purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps")); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.sounds), + gtkconv->make_sound); + + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.show_formatting_toolbar), + purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar")); + + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.show_timestamps), + purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps")); /* * We pause icons when they are not visible. If this icon should @@ -9202,7 +9777,7 @@ static gboolean gtk_conv_configure_cb(GtkWidget *w, GdkEventConfigure *event, gpointer data) { int x, y; - if (GTK_WIDGET_VISIBLE(w)) + if (gtk_widget_get_visible(w)) gtk_window_get_position(GTK_WINDOW(w), &x, &y); else return FALSE; /* carry on normally */ @@ -9237,7 +9812,7 @@ /* if the window exists, is hidden, we're saving positions, and the * position is sane... */ if (win && win->window && - !GTK_WIDGET_VISIBLE(win->window) && conv_width != 0) { + !gtk_widget_get_visible(win->window) && conv_width != 0) { #ifdef _WIN32 /* only override window manager placement on Windows */ /* ...check position is on screen... */ @@ -9392,7 +9967,7 @@ } gtk_widget_destroy(win->window); - g_object_unref(G_OBJECT(win->menu.item_factory)); + g_object_unref(G_OBJECT(win->menu.ui)); purple_notify_close_with_handle(win); purple_signals_disconnect_by_handle(win); @@ -9470,8 +10045,12 @@ /* Close button. */ gtkconv->close = pidgin_create_small_button(gtk_label_new("×")); +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(gtkconv->close, _("Close conversation")); +#else gtk_tooltips_set_tip(gtkconv->tooltips, gtkconv->close, _("Close conversation"), NULL); +#endif g_signal_connect(gtkconv->close, "clicked", G_CALLBACK (close_conv_cb), gtkconv); @@ -9607,9 +10186,9 @@ gtk_notebook_set_tab_label(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, ebox); } - gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, - !tabs_side && !angle, - TRUE, GTK_PACK_START); + gtk_container_child_set(GTK_CONTAINER(win->notebook), gtkconv->tab_cont, + "tab-expand", !tabs_side && !angle, + "tab-fill", TRUE, NULL); if (pidgin_conv_window_get_gtkconv_count(win) == 1) gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), @@ -9633,8 +10212,7 @@ index = gtk_notebook_page_num(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont); - g_object_ref(gtkconv->tab_cont); - gtk_object_sink(GTK_OBJECT(gtkconv->tab_cont)); + g_object_ref_sink(G_OBJECT(gtkconv->tab_cont)); gtk_notebook_remove_page(GTK_NOTEBOOK(win->notebook), index); @@ -9839,7 +10417,7 @@ PurpleConversationType type = purple_conversation_get_type(conv->active_conv); GList *all; - if (GTK_WIDGET_VISIBLE(w)) + if (gtk_widget_get_visible(w)) gtk_window_get_position(GTK_WINDOW(w), &x, &y); else return FALSE; /* carry on normally */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkconv.h --- a/pidgin/gtkconv.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkconv.h Fri Apr 06 04:30:00 2012 +0000 @@ -51,12 +51,12 @@ CHAT_USERS_FLAGS_COLUMN, CHAT_USERS_COLOR_COLUMN, CHAT_USERS_WEIGHT_COLUMN, - CHAT_USERS_ICON_STOCK_COLUMN, /** @since 2.6.0 */ + CHAT_USERS_ICON_STOCK_COLUMN, CHAT_USERS_COLUMNS }; #define PIDGIN_CONVERSATION(conv) \ - ((PidginConversation *)(conv)->ui_data) + ((PidginConversation *)purple_conversation_get_ui_data(conv)) #define PIDGIN_IS_PIDGIN_CONVERSATION(conv) \ (purple_conversation_get_ui_ops(conv) == \ @@ -65,6 +65,7 @@ #include "pidgin.h" #include "conversation.h" #include "gtkconvwin.h" +#include "gtkconv-theme.h" /************************************************************************** * @name Structures @@ -77,39 +78,6 @@ */ /** - * A GTK+ Instant Message pane. - */ -struct _PidginImPane -{ - GtkWidget *block; - GtkWidget *send_file; - GtkWidget *sep1; - GtkWidget *sep2; - GtkWidget *check; - GtkWidget *progress; - guint32 typing_timer; - - /* Buddy icon stuff */ - GtkWidget *icon_container; - GtkWidget *icon; - gboolean show_icon; - gboolean animate; - GdkPixbufAnimation *anim; - GdkPixbufAnimationIter *iter; - guint32 icon_timer; -}; - -/** - * GTK+ Chat panes. - */ -struct _PidginChatPane -{ - GtkWidget *count; - GtkWidget *list; - GtkWidget *topic_text; -}; - -/** * A GTK+ conversation pane. */ struct _PidginConversation @@ -122,18 +90,24 @@ gboolean make_sound; +#if GTK_CHECK_VERSION(2,12,0) + gpointer depr2; +#else GtkTooltips *tooltips; +#endif GtkWidget *tab_cont; GtkWidget *tabby; GtkWidget *menu_tabby; - GtkWidget *imhtml; + PidginConvTheme *theme; + PurpleMessageFlags last_flags; + GtkWidget *webview; GtkTextBuffer *entry_buffer; GtkWidget *entry; gboolean auto_resize; /* this is set to TRUE if the conversation - * is being resized by a non-user-initiated - * event, such as the buddy icon appearing + * is being resized by a non-user-initiated + * event, such as the buddy icon appearing */ gboolean entry_growing; /* True if the size of the entry was set * automatically by typing too much to fit @@ -144,12 +118,6 @@ GtkWidget *tab_label; GtkWidget *menu_icon; GtkWidget *menu_label; -#if !(defined PIDGIN_DISABLE_DEPRECATED) || (defined _PIDGIN_GTKCONV_C_) - /** @deprecated */ - GtkSizeGroup *sg; -#else - gpointer depr1; -#endif GtkWidget *lower_hbox; @@ -180,8 +148,6 @@ /** * Quick Find. - * - * @since 2.7.0 */ struct { GtkWidget *entry; @@ -191,6 +157,8 @@ /*@}*/ +G_BEGIN_DECLS + /************************************************************************** * @name GTK+ Conversation API **************************************************************************/ @@ -269,8 +237,6 @@ * @param conv The conversation. * * @return Wheter Pidgin UI was successfully attached. - * - * @since 2.2.0 */ gboolean pidgin_conv_attach_to_conversation(PurpleConversation *conv); @@ -305,4 +271,6 @@ /*@}*/ +G_END_DECLS + #endif /* _PIDGIN_CONVERSATION_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkconvwin.h --- a/pidgin/gtkconvwin.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkconvwin.h Fri Apr 06 04:30:00 2012 +0000 @@ -48,27 +48,27 @@ { GtkWidget *menubar; - GtkWidget *view_log; + GtkAction *view_log; - GtkWidget *send_file; - GtkWidget *add_pounce; - GtkWidget *get_info; - GtkWidget *invite; + GtkAction *send_file; + GtkAction *get_attention; + GtkAction *add_pounce; + GtkAction *get_info; + GtkAction *invite; - GtkWidget *alias; - GtkWidget *block; - GtkWidget *unblock; - GtkWidget *add; - GtkWidget *remove; + GtkAction *alias; + GtkAction *block; + GtkAction *unblock; + GtkAction *add; + GtkAction *remove; - GtkWidget *insert_link; - GtkWidget *insert_image; + GtkAction *insert_link; + GtkAction *insert_image; - GtkWidget *logging; - GtkWidget *sounds; - GtkWidget *show_formatting_toolbar; - GtkWidget *show_timestamps; - GtkWidget *show_icon; + GtkAction *logging; + GtkAction *sounds; + GtkAction *show_formatting_toolbar; + GtkAction *show_timestamps; GtkWidget *send_to; @@ -76,7 +76,7 @@ GtkWidget *typing_icon; - GtkItemFactory *item_factory; + GtkUIManager *ui; } menu; @@ -98,13 +98,15 @@ gint drag_leave_signal; /* Media menu options. */ - GtkWidget *audio_call; - GtkWidget *video_call; - GtkWidget *audio_video_call; + GtkAction *audio_call; + GtkAction *video_call; + GtkAction *audio_video_call; }; /*@}*/ +G_BEGIN_DECLS + /************************************************************************** * @name GTK+ Conversation Window API **************************************************************************/ @@ -151,4 +153,6 @@ /*@}*/ +G_END_DECLS + #endif /* _PIDGIN_CONVERSATION_WINDOW_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkdebug.c --- a/pidgin/gtkdebug.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkdebug.c Fri Apr 06 04:30:00 2012 +0000 @@ -128,7 +128,11 @@ static gboolean configure_cb(GtkWidget *w, GdkEventConfigure *event, DebugWindow *win) { +#if GTK_CHECK_VERSION(2,18,0) + if (gtk_widget_get_visible(w)) { +#else if (GTK_WIDGET_VISIBLE(w)) { +#endif purple_prefs_set_int(PIDGIN_PREFS_ROOT "/debug/width", event->width); purple_prefs_set_int(PIDGIN_PREFS_ROOT "/debug/height", event->height); } @@ -186,7 +190,9 @@ gtk_container_set_border_width(GTK_CONTAINER(win->find), PIDGIN_HIG_BOX_SPACE); gtk_window_set_resizable(GTK_WINDOW(win->find), FALSE); +#if !GTK_CHECK_VERSION(2,22,0) gtk_dialog_set_has_separator(GTK_DIALOG(win->find), FALSE); +#endif gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(win->find)->vbox), PIDGIN_HIG_BORDER); gtk_container_set_border_width( GTK_CONTAINER(GTK_DIALOG(win->find)->vbox), PIDGIN_HIG_BOX_SPACE); @@ -623,7 +629,11 @@ static void regex_key_release_cb(GtkWidget *w, GdkEventKey *e, DebugWindow *win) { if(e->keyval == GDK_Return && +#if GTK_CHECK_VERSION(2,18,0) + gtk_widget_is_sensitive(win->filter) && +#else GTK_WIDGET_IS_SENSITIVE(win->filter) && +#endif !gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) { gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(win->filter), TRUE); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkdebug.h --- a/pidgin/gtkdebug.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkdebug.h Fri Apr 06 04:30:00 2012 +0000 @@ -28,6 +28,8 @@ #include "debug.h" +G_BEGIN_DECLS + /** * Initializes the GTK+ debug system. */ @@ -62,4 +64,6 @@ */ PurpleDebugUiOps *pidgin_debug_get_ui_ops(void); +G_END_DECLS + #endif /* _PIDGINDEBUG_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkdialogs.c --- a/pidgin/gtkdialogs.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkdialogs.c Fri Apr 06 04:30:00 2012 +0000 @@ -39,10 +39,9 @@ #include "gtkblist.h" #include "gtkdialogs.h" -#include "gtkimhtml.h" -#include "gtkimhtmltoolbar.h" #include "gtklog.h" #include "gtkutils.h" +#include "gtkwebview.h" #include "pidginstock.h" static GList *dialogwindows = NULL; @@ -79,8 +78,6 @@ {"Hylke Bons", N_("artist"), "hylkebons@gmail.com"}, {"Sadrul Habib Chowdhury", NULL, NULL}, {"Mark 'KingAnt' Doliner", NULL, "mark@kingant.net"}, - {"Casey Harkins", NULL, NULL}, - {"Ivan Komarov", NULL, "ivan.komarov@pidgin.im"}, {"Gary 'grim' Kramlich", NULL, "grim@pidgin.im"}, {"Richard 'rlaager' Laager", NULL, "rlaager@pidgin.im"}, {"Marcus 'malu' Lundblad", NULL, NULL}, @@ -113,12 +110,14 @@ {"Herman Bloggs", N_("win32 port"), "herman@bluedigits.com"}, {"Thomas Butter", NULL, NULL}, /* feel free to not translate this */ - {N_("Ka-Hing Cheung"), NULL, NULL}, + {N_("Ka-Hing Cheung"), NULL, NULL}, {"Jim Duchek", N_("maintainer"), "jim@linuxpimps.com"}, {"Sean Egan", NULL, "sean.egan@gmail.com"}, {"Rob Flynn", N_("maintainer"), NULL}, {"Adam Fritzler", N_("libfaim maintainer"), NULL}, {"Christian 'ChipX86' Hammond", N_("webmaster"), NULL}, + {"Casey Harkins", NULL, NULL}, + {"Ivan Komarov", NULL, "ivan.komarov@pidgin.im"}, /* If "lazy bum" translates literally into a serious insult, use something else or omit it. */ {"Syd Logan", N_("hacker and designated driver [lazy bum]"), NULL}, {"Christopher 'siege' O'Brien", NULL, "taliesein@users.sf.net"}, @@ -143,33 +142,34 @@ {NULL, NULL, NULL} }; -/* Order: Code, then Alphabetical by Last Name */ +/* Order: Code, then Alphabetical by Last Name + Use NULL language and code for secondary translators. */ static const struct translator translators[] = { {N_("Afrikaans"), "af", "Samuel Murray", "afrikaans@gmail.com"}, - {N_("Afrikaans"), "af", "Friedel Wolff", "friedel@translate.org.za"}, + {NULL, NULL, "Friedel Wolff", "friedel@translate.org.za"}, {N_("Arabic"), "ar", "Khaled Hosny", "khaledhosny@eglug.org"}, {N_("Assamese"), "as", "Amitakhya Phukan", "aphukan@fedoraproject.org"}, {N_("Belarusian Latin"), "be@latin", "Ihar Hrachyshka", "ihar.hrachyshka@gmail.com"}, {N_("Bulgarian"), "bg", "Vladimira Girginova", "missing@here.is"}, - {N_("Bulgarian"), "bg", "Vladimir (Kaladan) Petkov", "vpetkov@i-space.org"}, + {NULL, NULL, "Vladimir (Kaladan) Petkov", "kaladan@gmail.com"}, {N_("Bengali"), "bn", "Israt Jahan", "israt@ankur.org.bd"}, - {N_("Bengali"), "bn", "Jamil Ahmed", "jamil@bengalinux.org"}, - {N_("Bengali"), "bn", "Samia Nimatullah", "mailsamia2001@yahoo.com"}, + {NULL, NULL, "Jamil Ahmed", "jamil@bengalinux.org"}, + {NULL, NULL, "Samia Nimatullah", "mailsamia2001@yahoo.com"}, {N_("Bengali-India"), "bn_IN", "Runa Bhattacharjee", "runab@fedoraproject.org"}, {N_("Bosnian"), "bs", "Lejla Hadzialic", "lejlah@gmail.com"}, {N_("Catalan"), "ca", "Josep Puigdemont", "josep.puigdemont@gmail.com"}, {N_("Valencian-Catalan"), "ca@valencia", "Toni Hermoso", "toniher@softcatala.org"}, - {N_("Valencian-Catalan"), "ca@valencia", "Josep Puigdemont", "tradgnome@softcatala.org"}, + {NULL, NULL, "Josep Puigdemont", "tradgnome@softcatala.org"}, {N_("Czech"), "cs", "David Vachulka", "david@konstrukce-cad.com"}, {N_("Danish"), "da", "Morten Brix Pedersen", "morten@wtf.dk"}, - {N_("Danish"), "da", "Peter Bach", "bach.peter@gmail.com"}, + {NULL, NULL, "Peter Bach", "bach.peter@gmail.com"}, {N_("German"), "de", "Björn Voigt", "bjoern@cs.tu-berlin.de"}, - {N_("German"), "de", "Jochen Kemnade", "jochenkemnade@web.de"}, + {NULL, NULL, "Jochen Kemnade", "jochenkemnade@web.de"}, {N_("Dzongkha"), "dz", "Norbu", "nor_den@hotmail.com"}, - {N_("Dzongkha"), "dz", "Jurmey Rabgay", "jur_gay@yahoo.com"}, - {N_("Dzongkha"), "dz", "Wangmo Sherpa", "rinwanshe@yahoo.com"}, + {NULL, NULL, "Jurmey Rabgay", "jur_gay@yahoo.com"}, + {NULL, NULL, "Wangmo Sherpa", "rinwanshe@yahoo.com"}, {N_("Greek"), "el", "Katsaloulis Panayotis", "panayotis@panayotis.com"}, - {N_("Greek"), "el", "Bouklis Panos", "panos@echidna-band.com"}, + {NULL, NULL, "Bouklis Panos", "panos@echidna-band.com"}, {N_("Australian English"), "en_AU", "Peter Lawler", "trans@six-by-nine.com.au"}, {N_("British English"), "en_GB", "Phil Hannent", "phil@hannent.co.uk"}, {N_("Canadian English"), "en_CA", "Adam Weinberger", "adamw@gnome.org"}, @@ -178,18 +178,18 @@ {N_("Estonian"), "et", "Ivar Smolin", "okul@linux.ee"}, {N_("Basque"), "eu", "Mikel Pascual Aldabaldetreku", "mikel.paskual@gmail.com"}, {N_("Persian"), "fa", "Elnaz Sarbar", "elnaz@farsiweb.info"}, - {N_("Persian"), "fa", "Meelad Zakaria", "meelad@farsiweb.info"}, - {N_("Persian"), "fa", "Roozbeh Pournader ", "roozbeh@farsiweb.info"}, + {NULL, NULL, "Meelad Zakaria", "meelad@farsiweb.info"}, + {NULL, NULL, "Roozbeh Pournader ", "roozbeh@farsiweb.info"}, {N_("Finnish"), "fi", "Timo Jyrinki", "timo.jyrinki@iki.fi"}, {N_("French"), "fr", "Éric Boumaour", "zongo_fr@users.sourceforge.net"}, {N_("Irish"), "ga", "Aaron Kearns", "ajkearns6@gmail.com"}, {N_("Galician"), "gl", "Mar Castro", "mariamarcp@gmail.com"}, - {N_("Galician"), "gl", "Frco. Javier Rial", "fjrial@cesga.es"}, + {NULL, NULL, "Frco. Javier Rial", "fjrial@cesga.es"}, {N_("Gujarati"), "gu", "Ankit Patel", "ankit_patel@users.sf.net"}, - {N_("Gujarati"), "gu", N_("Gujarati Language Team"), "indianoss-gujarati@lists.sourceforge.net"}, + {NULL, NULL, N_("Gujarati Language Team"), "indianoss-gujarati@lists.sourceforge.net"}, {N_("Hebrew"), "he", "Shalom Craimer", "scraimer@gmail.com"}, {N_("Hindi"), "hi", "Sangeeta Kumari", "sangeeta_0975@yahoo.com"}, - {N_("Hindi"), "hi", "Rajesh Ranjan", "rajeshkajha@yahoo.com"}, + {NULL, NULL, "Rajesh Ranjan", "rajeshkajha@yahoo.com"}, {N_("Croatian"), "hr", "Sabina Drempetić", "bina91991@googlemail.com"}, {N_("Hungarian"), "hu", "Kelemen Gábor", "kelemeng@gnome.hu"}, {N_("Armenian"), "hy", "David Avsharyan", "avsharyan@gmail.com"}, @@ -201,15 +201,15 @@ {N_("Kannada"), "kn", N_("Kannada Translation team"), "translation@sampada.info"}, {N_("Korean"), "ko", "Sushizang", "sushizang@empal.com"}, {N_("Kurdish"), "ku", "Erdal Ronahi", "erdal.ronahi@gmail.com"}, - {N_("Kurdish"), "ku", "Amed Ç. Jiyan", "amedcj@hotmail.com"}, - {N_("Kurdish"), "ku", "Rizoyê Xerzî", "rizoxerzi@hotmail.com"}, + {NULL, NULL, "Amed Ç. Jiyan", "amedcj@hotmail.com"}, + {NULL, NULL, "Rizoyê Xerzî", "rizoxerzi@hotmail.com"}, {N_("Lao"), "lo", "Anousak Souphavah", "anousak@gmail.com"}, {N_("Maithili"), "mai", "Sangeeta Kumari", "sangeeta_0975@yahoo.com"}, - {N_("Maithili"), "mai", "Rajesh Ranjan", "rajeshkajha@yahoo.com"}, + {NULL, NULL, "Rajesh Ranjan", "rajeshkajha@yahoo.com"}, {N_("Meadow Mari"), "mhr", "David Preece", "davidpreece1@gmail.com"}, {N_("Macedonian"), "mk", "Arangel Angov ", "arangel@linux.net.mk"}, - {N_("Macedonian"), "mk", "Ivana Kirkovska", "ivana.kirkovska@gmail.com"}, - {N_("Macedonian"), "mk", "Jovan Naumovski", "jovan@lugola.net"}, + {NULL, NULL, "Ivana Kirkovska", "ivana.kirkovska@gmail.com"}, + {NULL, NULL, "Jovan Naumovski", "jovan@lugola.net"}, {N_("Malayalam"), "ml", "Ani Peter", "apeter@redhat.com"}, {N_("Mongolian"), "mn", "gooyo", NULL}, {N_("Marathi"), "mr", "Sandeep Shedmake", "sandeep.shedmake@gmail.com"}, @@ -222,25 +222,24 @@ {N_("Oriya"), "or", "Manoj Kumar Giri", "giri.manojkr@gmail.com"}, {N_("Punjabi"), "pa", "Amanpreet Singh Alam", "aalam@users.sf.net"}, {N_("Polish"), "pl", "Piotr Drąg", "piotrdrag@gmail.com"}, - {N_("Polish"), "pl", "Piotr Makowski", "pmakowski@aviary.pl"}, {N_("Portuguese"), "pt", "Duarte Henriques", "duarte_henriques@myrealbox.com"}, {N_("Portuguese-Brazil"), "pt_BR", "Rodrigo Luiz Marques Flores", "rodrigomarquesflores@gmail.com"}, {N_("Pashto"), "ps", "Kashif Masood", "masudmails@yahoo.com"}, {N_("Romanian"), "ro", "Mișu Moldovan", "dumol@gnome.org"}, - {N_("Romanian"), "ro", "Andrei Popescu", "andreimpopescu@gmail.com"}, + {NULL, NULL, "Andrei Popescu", "andreimpopescu@gmail.com"}, {N_("Russian"), "ru", "Антон Самохвалов", "samant.ua@mail.ru"}, {N_("Slovak"), "sk", "Jozef Káčer", "quickparser@gmail.com"}, - {N_("Slovak"), "sk", "loptosko", "loptosko@gmail.com"}, + {NULL, NULL, "loptosko", "loptosko@gmail.com"}, {N_("Slovenian"), "sl", "Martin Srebotnjak", "miles@filmsi.net"}, {N_("Albanian"), "sq", "Besnik Bleta", "besnik@programeshqip.org"}, {N_("Serbian"), "sr", "Miloš Popović", "gpopac@gmail.com"}, - {N_("Serbian"), "sr@Latn", "Miloš Popović", "gpopac@gmail.com"}, + {N_("Serbian Latin"), "sr@latin", "Miloš Popović", "gpopac@gmail.com"}, {N_("Sinhala"), "si", "Danishka Navin", "snavin@redhat.com"}, - {N_("Sinhala"), "si", "Yajith Ajantha Dayarathna", "yajith@gmail.com"}, + {NULL, NULL, "Yajith Ajantha Dayarathna", "yajith@gmail.com"}, {N_("Swedish"), "sv", "Peter Hjalmarsson", "xake@telia.com"}, {N_("Swahili"), "sw", "Paul Msegeya", "msegeya@gmail.com"}, {N_("Tamil"), "ta", "I. Felix", "ifelix25@gmail.com"}, - {N_("Tamil"), "ta", "Viveka Nathan K", "vivekanathan@users.sourceforge.net"}, + {NULL, NULL, "Viveka Nathan K", "vivekanathan@users.sourceforge.net"}, {N_("Telugu"), "te", "Krishnababu Krottapalli", "krottapalli@ymail.com"}, {N_("Thai"), "th", "Isriya Paireepairit", "markpeak@gmail.com"}, {N_("Turkish"), "tr", "Serdar Soytetir", "tulliana@gmail.com"}, @@ -249,10 +248,10 @@ {N_("Vietnamese"), "vi", "Nguyễn Vũ Hưng", "vuhung16plus@gmail.com"}, {N_("Simplified Chinese"), "zh_CN", "Aron Xu", "happyaron.xu@gmail.com"}, {N_("Hong Kong Chinese"), "zh_HK", "Abel Cheung", "abelindsay@gmail.com"}, - {N_("Hong Kong Chinese"), "zh_HK", "Ambrose C. Li", "acli@ada.dhs.org"}, - {N_("Hong Kong Chinese"), "zh_HK", "Paladin R. Liu", "paladin@ms1.hinet.net"}, + {NULL, NULL, "Ambrose C. Li", "acli@ada.dhs.org"}, + {NULL, NULL, "Paladin R. Liu", "paladin@ms1.hinet.net"}, {N_("Traditional Chinese"), "zh_TW", "Ambrose C. Li", "acli@ada.dhs.org"}, - {N_("Traditional Chinese"), "zh_TW", "Paladin R. Liu", "paladin@ms1.hinet.net"}, + {NULL, NULL, "Paladin R. Liu", "paladin@ms1.hinet.net"}, {NULL, NULL, NULL, NULL} }; @@ -262,67 +261,72 @@ {N_("Arabic"), "ar", "Mohamed Magdy", "alnokta@yahoo.com"}, {N_("Bulgarian"), "bg", "Hristo Todorov", NULL}, {N_("Bengali"), "bn", "INDRANIL DAS GUPTA", "indradg@l2c2.org"}, - {N_("Bengali"), "bn", "Tisa Nafisa", "tisa_nafisa@yahoo.com"}, + {NULL, NULL, "Tisa Nafisa", "tisa_nafisa@yahoo.com"}, {N_("Catalan"), "ca", "JM Pérez Cáncer", NULL}, - {N_("Catalan"), "ca", "Robert Millan", NULL}, + {NULL, NULL, "Robert Millan", NULL}, {N_("Czech"), "cs", "Honza Král", NULL}, - {N_("Czech"), "cs", "Miloslav Trmac", "mitr@volny.cz"}, - {N_("German"), "de", "Daniel Seifert, Karsten Weiss", NULL}, + {NULL, NULL, "Miloslav Trmac", "mitr@volny.cz"}, + {N_("German"), "de", "Daniel Seifert", NULL}, + {NULL, NULL, "Karsten Weiss", NULL}, {N_("British English"), "en_GB", "Luke Ross", "luke@lukeross.name"}, {N_("Spanish"), "es", "JM Pérez Cáncer", NULL}, - {N_("Spanish"), "es", "Nicolás Lichtmaier", NULL}, - {N_("Spanish"), "es", "Amaya Rodrigo", NULL}, - {N_("Spanish"), "es", "Alejandro G Villar", NULL}, + {NULL, NULL, "Nicolás Lichtmaier", NULL}, + {NULL, NULL, "Amaya Rodrigo", NULL}, + {NULL, NULL, "Alejandro G Villar", NULL}, {N_("Basque"), "eu", "Iñaki Larrañaga Murgoitio", "dooteo@zundan.com"}, - {N_("Basque"), "eu", "Hizkuntza Politikarako Sailburuordetza", "hizkpol@ej-gv.es"}, + {NULL, NULL, "Hizkuntza Politikarako Sailburuordetza", "hizkpol@ej-gv.es"}, {N_("Finnish"), "fi", "Arto Alakulju", NULL}, - {N_("Finnish"), "fi", "Tero Kuusela", NULL}, + {NULL, NULL, "Tero Kuusela", NULL}, {N_("French"), "fr", "Sébastien François", NULL}, - {N_("French"), "fr", "Stéphane Pontier", NULL}, - {N_("French"), "fr", "Stéphane Wirtel", NULL}, - {N_("French"), "fr", "Loïc Jeannin", NULL}, + {NULL, NULL, "Stéphane Pontier", NULL}, + {NULL, NULL, "Stéphane Wirtel", NULL}, + {NULL, NULL, "Loïc Jeannin", NULL}, {N_("Galician"), "gl", "Ignacio Casal Quinteiro", NULL}, {N_("Hebrew"), "he", "Pavel Bibergal", NULL}, {N_("Hindi"), "hi", "Ravishankar Shrivastava", NULL}, {N_("Hungarian"), "hu", "Zoltan Sutto", NULL}, {N_("Italian"), "it", "Salvatore di Maggio", NULL}, {N_("Japanese"), "ja", "Takashi Aihana", NULL}, - {N_("Japanese"), "ja", "Ryosuke Kutsuna", NULL}, - {N_("Japanese"), "ja", "Taku Yasui", NULL}, - {N_("Japanese"), "ja", "Junichi Uekawa", NULL}, + {NULL, NULL, "Ryosuke Kutsuna", NULL}, + {NULL, NULL, "Taku Yasui", NULL}, + {NULL, NULL, "Junichi Uekawa", NULL}, {N_("Georgian"), "ka", "Temuri Doghonadze", NULL}, - {N_("Korean"), "ko", "Sang-hyun S, A Ho-seok Lee", NULL}, - {N_("Korean"), "ko", "Kyeong-uk Son", NULL}, + {N_("Korean"), "ko", "Sang-hyun S", NULL}, + {NULL, NULL, "A Ho-seok Lee", NULL}, + {NULL, NULL, "Kyeong-uk Son", NULL}, {N_("Lithuanian"), "lt", "Laurynas Biveinis", "laurynas.biveinis@gmail.com"}, - {N_("Lithuanian"), "lt", "Gediminas Čičinskas", NULL}, - {N_("Lithuanian"), "lt", "Andrius Štikonas", NULL}, + {NULL, NULL, "Gediminas Čičinskas", NULL}, + {NULL, NULL, "Andrius Štikonas", NULL}, {N_("Macedonian"), "mk", "Tomislav Markovski", NULL}, {N_("Bokmål Norwegian"), "nb", "Hallvard Glad", "hallvard.glad@gmail.com"}, - {N_("Bokmål Norwegian"), "nb", "Petter Johan Olsen", NULL}, - {N_("Bokmål Norwegian"), "nb", "Espen Stefansen", "espenas@gmail.com"}, + {NULL, NULL, "Petter Johan Olsen", NULL}, + {NULL, NULL, "Espen Stefansen", "espenas@gmail.com"}, {N_("Dutch, Flemish"), "nl", "Vincent van Adrighem", "V.vanAdrighem@dirck.mine.nu"}, {N_("Polish"), "pl", "Emil Nowak", "emil5@go2.pl"}, - {N_("Polish"), "pl", "Paweł Godlewski", "pawel@bajk.pl"}, - {N_("Polish"), "pl", "Krzysztof Foltman", "krzysztof@foltman.com"}, - {N_("Polish"), "pl", "Przemysław Sułek", NULL}, + {NULL, NULL, "Paweł Godlewski", "pawel@bajk.pl"}, + {NULL, NULL, "Krzysztof Foltman", "krzysztof@foltman.com"}, + {NULL, NULL, "Piotr Makowski", NULL}, + {NULL, NULL, "Przemysław Sułek", NULL}, {N_("Portuguese-Brazil"), "pt_BR", "Maurício de Lemos Rodrigues Collares Neto", "mauricioc@gmail.com"}, {N_("Russian"), "ru", "Dmitry Beloglazov", "dmaa@users.sf.net"}, - {N_("Russian"), "ru", "Alexandre Prokoudine", NULL}, - {N_("Russian"), "ru", "Sergey Volozhanin", NULL}, + {NULL, NULL, "Alexandre Prokoudine", NULL}, + {NULL, NULL, "Sergey Volozhanin", NULL}, {N_("Slovak"), "sk", "Daniel Režný", NULL}, - {N_("Slovak"), "sk", "helix84", NULL}, - {N_("Slovak"), "sk", "Richard Golier", NULL}, + {NULL, NULL, "helix84", NULL}, + {NULL, NULL, "Richard Golier", NULL}, {N_("Slovenian"), "sl", "Matjaz Horvat", NULL}, {N_("Serbian"), "sr", "Danilo Šegan", "dsegan@gmx.net"}, - {N_("Serbian"), "sr", "Aleksandar Urosevic", "urke@users.sourceforge.net"}, + {NULL, NULL, "Aleksandar Urosevic", "urke@users.sourceforge.net"}, {N_("Swedish"), "sv", "Tore Lundqvist", NULL}, - {N_("Swedish"), "sv", "Christian Rose", NULL}, + {NULL, NULL, "Christian Rose", NULL}, {N_("Telugu"), "te", "Mr. Subbaramaih", "info.gist@cdac.in"}, {N_("Turkish"), "tr", "Ahmet Alp BALKAN", NULL}, {N_("Vietnamese"), "vi", N_("T.M.Thanh and the Gnome-Vi Team"), "gnomevi-list@lists.sf.net"}, - {N_("Simplified Chinese"), "zh_CN", "Hashao, Rocky S. Lee", NULL}, - {N_("Simplified Chinese"), "zh_CN", "Funda Wang", "fundawang@linux.net.cn"}, - {N_("Traditional Chinese"), "zh_TW", "Hashao, Rocky S. Lee", NULL}, + {N_("Simplified Chinese"), "zh_CN", "Hashao", NULL}, + {NULL, NULL, "Rocky S. Lee", NULL}, + {NULL, NULL, "Funda Wang", "fundawang@linux.net.cn"}, + {N_("Traditional Chinese"), "zh_TW", "Hashao", NULL}, + {NULL, NULL, "Rocky S. Lee", NULL}, {NULL, NULL, NULL, NULL} }; @@ -331,13 +335,14 @@ { for (; list->name != NULL; list++) { if (list->email != NULL) { - g_string_append_printf(str, " %s%s%s%s
", - list->email, _(list->name), + g_string_append_printf(str, + "
  • %s%s%s%s
  • ", + list->email, list->email, _(list->name), list->role ? " (" : "", list->role ? _(list->role) : "", list->role ? ")" : ""); } else { - g_string_append_printf(str, " %s%s%s%s
    ", + g_string_append_printf(str, "
  • %s%s%s%s
  • ", _(list->name), list->role ? " (" : "", list->role ? _(list->role) : "", @@ -349,18 +354,18 @@ static void add_translators(GString *str, const struct translator *list) { - for (; list->language != NULL; list++) { + for (; list->name != NULL; list++) { + if (list->language && list->abbr) { + g_string_append_printf(str, "
    %s (%s)
    ", + _(list->language), list->abbr); + } if (list->email != NULL) { - g_string_append_printf(str, " %s (%s) - %s
    ", - _(list->language), - list->abbr, - list->email, + g_string_append_printf(str, + "
    %s
    ", + list->email, list->email, _(list->name)); } else { - g_string_append_printf(str, " %s (%s) - %s
    ", - _(list->language), - list->abbr, - _(list->name)); + g_string_append_printf(str, "
    %s
    ", _(list->name)); } } } @@ -423,9 +428,8 @@ static GtkWidget * pidgin_build_help_dialog(const char *title, const char *role, GString *string) { - GtkWidget *win, *vbox, *frame, *logo, *imhtml, *button; + GtkWidget *win, *vbox, *frame, *logo, *webview, *button; GdkPixbuf *pixbuf; - GtkTextIter iter; AtkObject *obj; char *filename, *tmp; @@ -452,18 +456,22 @@ g_free(tmp); gtk_box_pack_start(GTK_BOX(vbox), logo, FALSE, FALSE, 0); - frame = pidgin_create_imhtml(FALSE, &imhtml, NULL, NULL); + frame = pidgin_create_webview(FALSE, &webview, NULL, NULL); + /* TODO WEBKIT: Compile now and fix it later when we have a proper replacement for this function gtk_imhtml_set_format_functions(GTK_IMHTML(imhtml), GTK_IMHTML_ALL ^ GTK_IMHTML_SMILEY); + */ gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); - gtk_imhtml_append_text(GTK_IMHTML(imhtml), string->str, GTK_IMHTML_NO_SCROLL); - gtk_text_buffer_get_start_iter(gtk_text_view_get_buffer(GTK_TEXT_VIEW(imhtml)), &iter); - gtk_text_buffer_place_cursor(gtk_text_view_get_buffer(GTK_TEXT_VIEW(imhtml)), &iter); + gtk_webview_append_html(GTK_WEBVIEW(webview), string->str); button = pidgin_dialog_add_button(GTK_DIALOG(win), GTK_STOCK_CLOSE, G_CALLBACK(destroy_win), win); +#if GTK_CHECK_VERSION(2,18,0) + gtk_widget_set_can_default(button, TRUE); +#else GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); +#endif gtk_widget_grab_default(button); gtk_widget_show_all(win); @@ -488,37 +496,45 @@ str = g_string_sized_new(4096); g_string_append_printf(str, - "
    %s %s
    (libpurple %s)" - "
    %s

    ", PIDGIN_NAME, DISPLAY_VERSION, + "

    %s %s

    " + "(libpurple %s)
    %s
    ", + PIDGIN_NAME, DISPLAY_VERSION, purple_core_get_version(), REVISION); g_string_append_printf(str, - _("%s is a messaging client based on libpurple which is capable of " + _("

    %s is a messaging client based on libpurple which is capable of " "connecting to multiple messaging services at once. %s is written " "in C using GTK+. %s is released, and may be modified and " "redistributed, under the terms of the GPL version 2 (or later). " "A copy of the GPL is distributed with %s. %s is copyrighted by " "its contributors, a list of whom is also distributed with %s. " - "There is no warranty for %s.

    "), PIDGIN_NAME, PIDGIN_NAME, + "There is no warranty for %s.

    "), PIDGIN_NAME, PIDGIN_NAME, PIDGIN_NAME, PIDGIN_NAME, PIDGIN_NAME, PIDGIN_NAME, PIDGIN_NAME); g_string_append_printf(str, - _("Helpful Resources
    \tWebsite
    \tFrequently Asked " - "Questions
    \tIRC Channel: #pidgin on irc.freenode.net
    " - "\tXMPP MUC: devel@conference.pidgin.im

    "), PURPLE_WEBSITE, + _("

    Helpful Resources

    " + ""), + PURPLE_WEBSITE, PURPLE_WEBSITE, + "http://developer.pidgin.im/wiki/FAQ", "http://developer.pidgin.im/wiki/FAQ"); g_string_append_printf(str, - _("Help from other Pidgin users is " - "available by e-mailing support@pidgin.im
    " - "This is a public mailing list! " - "(archive)
    " + _("

    Help from other Pidgin users is available " + "by e-mailing %s.
    " + "This is a public mailing list! " + "(archive)
    " "We can't help with third-party protocols or plugins!
    " - "This list's primary language is English. You are " - "welcome to post in another language, but the responses may " - "be less helpful.
    ")); + "This list's primary language is English. You " + "are welcome to post in another language, but the responses may " + "be less helpful.

    "), + "support@pidgin.im", "support@pidgin.im", + "http://pidgin.im/pipermail/support/", + "http://pidgin.im/pipermail/support/"); tmp = g_strdup_printf(_("About %s"), PIDGIN_NAME); about = pidgin_build_help_dialog(tmp, "about", str); @@ -540,175 +556,179 @@ str = g_string_sized_new(4096); g_string_append_printf(str, - "%s %s (libpurple %s)
    %s

    ", PIDGIN_NAME, DISPLAY_VERSION, purple_core_get_version(), REVISION); + "

    %s %s

    " + "(libpurple %s)
    %s
    ", + PIDGIN_NAME, DISPLAY_VERSION, purple_core_get_version(), REVISION); - g_string_append_printf(str, "%s
    ", _("Build Information")); + g_string_append_printf(str, "

    %s

    ", _("Build Information")); - /* The following primarly intented for user/developer interaction and thus - ought not be translated */ + /* The following is primarily intended for user/developer interaction and + thus ought not be translated */ #ifdef CONFIG_ARGS /* win32 build doesn't use configure */ - g_string_append(str, " Arguments to ./configure: " CONFIG_ARGS "
    "); + g_string_append(str, "
    Arguments to ./configure:
    " CONFIG_ARGS "
    "); #endif #ifndef _WIN32 #ifdef DEBUG - g_string_append(str, " Print debugging messages: Yes
    "); + g_string_append(str, "
    Print debugging messages:
    Yes
    "); #else - g_string_append(str, " Print debugging messages: No
    "); + g_string_append(str, "
    Print debugging messages:
    No
    "); #endif #endif #ifdef PURPLE_PLUGINS - g_string_append(str, " Plugins: Enabled
    "); + g_string_append(str, "
    Plugins:
    Enabled
    "); #else - g_string_append(str, " Plugins: Disabled
    "); + g_string_append(str, "
    Plugins:
    Disabled
    "); #endif #ifdef HAVE_SSL - g_string_append(str, " SSL: SSL support is present.
    "); + g_string_append(str, "
    SSL:
    SSL support is present.
    "); #else - g_string_append(str, " SSL: SSL support was NOT compiled!
    "); + g_string_append(str, "
    SSL:
    SSL support was NOT compiled!
    "); #endif /* This might be useful elsewhere too, but it is particularly useful for - * debugging stuff known to be GTK+/Glib bugs on Windows */ + * debugging stuff known to be GTK+/GLib bugs on Windows */ #ifdef _WIN32 - g_string_append_printf(str, " GTK+ Runtime: %u.%u.%u
    " - " Glib Runtime: %u.%u.%u
    ", + g_string_append_printf(str, "
    GTK+ Runtime:
    %u.%u.%u
    " + "
    GLib Runtime:
    %u.%u.%u
    ", gtk_major_version, gtk_minor_version, gtk_micro_version, glib_major_version, glib_minor_version, glib_micro_version); #endif -g_string_append(str, "
    Library Support
    "); + g_string_append(str, "

    Library Support

    "); #ifdef HAVE_CYRUS_SASL - g_string_append_printf(str, " Cyrus SASL: Enabled
    "); + g_string_append_printf(str, "
    Cyrus SASL:
    Enabled
    "); #else - g_string_append_printf(str, " Cyrus SASL: Disabled
    "); + g_string_append_printf(str, "
    Cyrus SASL:
    Disabled
    "); #endif #ifndef _WIN32 #ifdef HAVE_DBUS - g_string_append_printf(str, " D-Bus: Enabled
    "); + g_string_append_printf(str, "
    D-Bus:
    Enabled
    "); #else - g_string_append_printf(str, " D-Bus: Disabled
    "); + g_string_append_printf(str, "
    D-Bus:
    Disabled
    "); #endif #ifdef HAVE_EVOLUTION_ADDRESSBOOK - g_string_append_printf(str, " Evolution Addressbook: Enabled
    "); + g_string_append_printf(str, "
    Evolution Addressbook:
    Enabled
    "); #else - g_string_append_printf(str, " Evolution Addressbook: Disabled
    "); + g_string_append_printf(str, "
    Evolution Addressbook:
    Disabled
    "); #endif #endif #if defined(_WIN32) || defined(USE_INTERNAL_LIBGADU) - g_string_append(str, " Gadu-Gadu library (libgadu): Internal
    "); + g_string_append(str, "
    Gadu-Gadu library (libgadu):
    Internal
    "); #else #ifdef HAVE_LIBGADU - g_string_append(str, " Gadu-Gadu library (libgadu): Enabled
    "); + g_string_append(str, "
    Gadu-Gadu library (libgadu):
    Enabled
    "); #else - g_string_append(str, " Gadu-Gadu library (libgadu): Disabled
    "); + g_string_append(str, "
    Gadu-Gadu library (libgadu):
    Disabled
    "); #endif #endif #ifdef USE_GTKSPELL - g_string_append(str, " GtkSpell: Enabled
    "); + g_string_append(str, "
    GtkSpell:
    Enabled
    "); #else - g_string_append(str, " GtkSpell: Disabled
    "); + g_string_append(str, "
    GtkSpell:
    Disabled
    "); #endif #ifdef HAVE_GNUTLS - g_string_append(str, " GnuTLS: Enabled
    "); + g_string_append(str, "
    GnuTLS:
    Enabled
    "); #else - g_string_append(str, " GnuTLS: Disabled
    "); + g_string_append(str, "
    GnuTLS:
    Disabled
    "); #endif #ifndef _WIN32 #ifdef USE_GSTREAMER - g_string_append(str, " GStreamer: Enabled
    "); + g_string_append(str, "
    GStreamer:
    Enabled
    "); #else - g_string_append(str, " GStreamer: Disabled
    "); + g_string_append(str, "
    GStreamer:
    Disabled
    "); #endif #endif #ifndef _WIN32 #ifdef ENABLE_MONO - g_string_append(str, " Mono: Enabled
    "); + g_string_append(str, "
    Mono:
    Enabled
    "); #else - g_string_append(str, " Mono: Disabled
    "); + g_string_append(str, "
    Mono:
    Disabled
    "); #endif #endif #ifndef _WIN32 #ifdef HAVE_NETWORKMANAGER - g_string_append(str, " NetworkManager: Enabled
    "); + g_string_append(str, "
    NetworkManager:
    Enabled
    "); #else - g_string_append(str, " NetworkManager: Disabled
    "); + g_string_append(str, "
    NetworkManager:
    Disabled
    "); #endif #endif #ifdef HAVE_NSS - g_string_append(str, " Network Security Services (NSS): Enabled
    "); + g_string_append(str, "
    Network Security Services (NSS):
    Enabled
    "); #else - g_string_append(str, " Network Security Services (NSS): Disabled
    "); + g_string_append(str, "
    Network Security Services (NSS):
    Disabled
    "); #endif -if (purple_plugins_find_with_id("core-perl") != NULL) - g_string_append(str, " Perl: Enabled
    "); -else - g_string_append(str, " Perl: Disabled
    "); + if (purple_plugins_find_with_id("core-perl") != NULL) + g_string_append(str, "
    Perl:
    Enabled
    "); + else + g_string_append(str, "
    Perl:
    Disabled
    "); -if (purple_plugins_find_with_id("core-tcl") != NULL) { - g_string_append(str, " Tcl: Enabled
    "); + if (purple_plugins_find_with_id("core-tcl") != NULL) { + g_string_append(str, "
    Tcl:
    Enabled
    "); #ifdef HAVE_TK - g_string_append(str, " Tk: Enabled
    "); + g_string_append(str, "
    Tk:
    Enabled
    "); #else - g_string_append(str, " Tk: Disabled
    "); + g_string_append(str, "
    Tk:
    Disabled
    "); #endif -} else { - g_string_append(str, " Tcl: Disabled
    "); - g_string_append(str, " Tk: Disabled
    "); -} + } else { + g_string_append(str, "
    Tcl:
    Disabled
    "); + g_string_append(str, "
    Tk:
    Disabled
    "); + } #ifdef USE_IDN - g_string_append(str, " UTF-8 DNS (IDN): Enabled
    "); + g_string_append(str, "
    UTF-8 DNS (IDN):
    Enabled
    "); #else - g_string_append(str, " UTF-8 DNS (IDN): Disabled
    "); + g_string_append(str, "
    UTF-8 DNS (IDN):
    Disabled
    "); #endif #ifdef USE_VV - g_string_append(str, " Voice and Video: Enabled
    "); + g_string_append(str, "
    Voice and Video:
    Enabled
    "); #else - g_string_append(str, " Voice and Video: Disabled
    "); + g_string_append(str, "
    Voice and Video:
    Disabled
    "); #endif #ifndef _WIN32 #ifdef USE_SM - g_string_append(str, " X Session Management: Enabled
    "); + g_string_append(str, "
    X Session Management:
    Enabled
    "); #else - g_string_append(str, " X Session Management: Disabled
    "); + g_string_append(str, "
    X Session Management:
    Disabled
    "); #endif #ifdef USE_SCREENSAVER - g_string_append(str, " XScreenSaver: Enabled
    "); + g_string_append(str, "
    XScreenSaver:
    Enabled
    "); #else - g_string_append(str, " XScreenSaver: Disabled
    "); + g_string_append(str, "
    XScreenSaver:
    Disabled
    "); #endif #ifdef LIBZEPHYR_EXT - g_string_append(str, " Zephyr library (libzephyr): External
    "); + g_string_append(str, "
    Zephyr library (libzephyr):
    External
    "); #else - g_string_append(str, " Zephyr library (libzephyr): Internal
    "); + g_string_append(str, "
    Zephyr library (libzephyr):
    Internal
    "); #endif #ifdef ZEPHYR_USES_KERBEROS - g_string_append(str, " Zephyr uses Kerberos: Yes
    "); + g_string_append(str, "
    Zephyr uses Kerberos:
    Yes
    "); #else - g_string_append(str, " Zephyr uses Kerberos: No
    "); + g_string_append(str, "
    Zephyr uses Kerberos:
    No
    "); #endif #endif + g_string_append(str, "
    "); + /* End of not to be translated section */ tmp = g_strdup_printf(_("%s Build Information"), PIDGIN_NAME); @@ -731,27 +751,28 @@ str = g_string_sized_new(4096); /* Current Developers */ - g_string_append_printf(str, "%s:
    ", + g_string_append_printf(str, "

    %s

      ", _("Current Developers")); add_developers(str, developers); - g_string_append(str, "
      "); + g_string_append(str, "
    "); /* Crazy Patch Writers */ - g_string_append_printf(str, "%s:
    ", + g_string_append_printf(str, "

    %s

      ", _("Crazy Patch Writers")); add_developers(str, patch_writers); - g_string_append(str, "
      "); + g_string_append(str, "
    "); /* Retired Developers */ - g_string_append_printf(str, "%s:
    ", + g_string_append_printf(str, "

    %s

      ", _("Retired Developers")); add_developers(str, retired_developers); - g_string_append(str, "
      "); + g_string_append(str, "
    "); /* Retired Crazy Patch Writers */ - g_string_append_printf(str, "%s:
    ", + g_string_append_printf(str, "

    %s

      ", _("Retired Crazy Patch Writers")); add_developers(str, retired_patch_writers); + g_string_append(str, "
    "); tmp = g_strdup_printf(_("%s Developer Information"), PIDGIN_NAME); developer_info = pidgin_build_help_dialog(tmp, "developer_info", str); @@ -773,15 +794,16 @@ str = g_string_sized_new(4096); /* Current Translators */ - g_string_append_printf(str, "%s:
    ", + g_string_append_printf(str, "

    %s

    ", _("Current Translators")); add_translators(str, translators); - g_string_append(str, "
    "); + g_string_append(str, "
    "); /* Past Translators */ - g_string_append_printf(str, "%s:
    ", + g_string_append_printf(str, "

    %s

    ", _("Past Translators")); add_translators(str, past_translators); + g_string_append(str, "
    "); tmp = g_strdup_printf(_("%s Translator Information"), PIDGIN_NAME); translator_info = pidgin_build_help_dialog(tmp, "translator_info", str); @@ -802,14 +824,14 @@ str = g_string_sized_new(4096); - g_string_append_printf(str, "%s
    ", - _("Plugin Information")); + g_string_append_printf(str, "

    %s

    ", _("Plugin Information")); for(l = purple_plugins_get_all(); l; l = l->next) { plugin = (PurplePlugin *)l->data; pname = g_markup_escape_text(purple_plugin_get_name(plugin), -1); - pauthor = g_markup_escape_text(purple_plugin_get_author(plugin), -1); + if ((pauthor = (char *)purple_plugin_get_author(plugin)) != NULL) + pauthor = g_markup_escape_text(pauthor, -1); pver = purple_plugin_get_version(plugin); pwebsite = purple_plugin_get_homepage(plugin); pid = purple_plugin_get_id(plugin); @@ -817,22 +839,29 @@ ploaded = purple_plugin_is_loaded(plugin); g_string_append_printf(str, - "%s
    " - "\tAuthor: %s
    \tVersion: %s
    " - "\tWebsite: %s
    \tID String: %s
    " - "\tLoadable: %s
    \tLoaded: %s
    " - "
    ", pname, pauthor ? pauthor : "(null)", + "
    %s
    " + "Author: %s
    " + "Version: %s
    " + "Website: %s
    " + "ID String: %s
    " + "Loadable: %s
    " + "Loaded: %s" + "

    ", + pname, pauthor ? pauthor : "(null)", pver, pwebsite, pid, - punloadable ? "No" : "Yes", + punloadable ? "No" : "Yes", ploaded ? "Yes" : "No"); + + g_free(pname); + g_free(pauthor); } + g_string_append(str, "
    "); + plugins_info = pidgin_build_help_dialog(title, "plugins_info", str); g_signal_connect(G_OBJECT(plugins_info), "destroy", G_CALLBACK(gtk_widget_destroyed), &plugins_info); g_free(title); - g_free(pname); - g_free(pauthor); } static void @@ -948,7 +977,9 @@ gtk_container_set_border_width (GTK_CONTAINER(window), PIDGIN_HIG_BOX_SPACE); gtk_window_set_resizable(GTK_WINDOW(window), FALSE); +#if !GTK_CHECK_VERSION(2,22,0) gtk_dialog_set_has_separator(GTK_DIALOG(window), FALSE); +#endif gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(window)->vbox), PIDGIN_HIG_BORDER); gtk_container_set_border_width (GTK_CONTAINER(GTK_DIALOG(window)->vbox), PIDGIN_HIG_BOX_SPACE); @@ -1115,26 +1146,6 @@ } static void -pidgin_dialogs_alias_contact_cb(PurpleContact *contact, const char *new_alias) -{ - purple_blist_alias_contact(contact, new_alias); -} - -void -pidgin_dialogs_alias_contact(PurpleContact *contact) -{ - g_return_if_fail(contact != NULL); - - purple_request_input(NULL, _("Alias Contact"), NULL, - _("Enter an alias for this contact."), - contact->alias, FALSE, FALSE, NULL, - _("Alias"), G_CALLBACK(pidgin_dialogs_alias_contact_cb), - _("Cancel"), NULL, - NULL, purple_contact_get_alias(contact), NULL, - contact); -} - -static void pidgin_dialogs_alias_buddy_cb(PurpleBuddy *buddy, const char *new_alias) { purple_blist_alias_buddy(buddy, new_alias); @@ -1148,10 +1159,10 @@ g_return_if_fail(buddy != NULL); - secondary = g_strdup_printf(_("Enter an alias for %s."), buddy->name); + secondary = g_strdup_printf(_("Enter an alias for %s."), purple_buddy_get_name(buddy)); purple_request_input(NULL, _("Alias Buddy"), NULL, - secondary, buddy->alias, FALSE, FALSE, NULL, + secondary, purple_buddy_get_local_buddy_alias(buddy), FALSE, FALSE, NULL, _("Alias"), G_CALLBACK(pidgin_dialogs_alias_buddy_cb), _("Cancel"), NULL, purple_buddy_get_account(buddy), purple_buddy_get_name(buddy), NULL, @@ -1176,7 +1187,7 @@ chat->alias, FALSE, FALSE, NULL, _("Alias"), G_CALLBACK(pidgin_dialogs_alias_chat_cb), _("Cancel"), NULL, - chat->account, NULL, NULL, + purple_chat_get_account(chat), NULL, NULL, chat); } @@ -1190,8 +1201,8 @@ group = (PurpleGroup*)cnode->parent; for (bnode = cnode->child; bnode; bnode = bnode->next) { PurpleBuddy *buddy = (PurpleBuddy*)bnode; - if (purple_account_is_connected(buddy->account)) - purple_account_remove_buddy(buddy->account, buddy, group); + if (purple_account_is_connected(purple_buddy_get_account(buddy))) + purple_account_remove_buddy(purple_buddy_get_account(buddy), buddy, group); } purple_blist_remove_contact(contact); } @@ -1216,8 +1227,8 @@ "want to continue?", "You are about to remove the contact containing %s " "and %d other buddies from your buddy list. Do you " - "want to continue?", contact->totalsize - 1), - buddy->name, contact->totalsize - 1); + "want to continue?", purple_contact_get_contact_size(contact, TRUE) - 1), + purple_buddy_get_name(buddy), purple_contact_get_contact_size(contact, TRUE) - 1); purple_request_action(contact, NULL, _("Remove Contact"), text, 0, NULL, purple_contact_get_alias(contact), NULL, @@ -1254,7 +1265,7 @@ text = g_strdup_printf( _("You are about to merge the group called %s into the group " - "called %s. Do you want to continue?"), source->name, new_name); + "called %s. Do you want to continue?"), purple_group_get_name(source), new_name); ggp = g_new(struct _PidginGroupMergeObject, 1); ggp->parent = source; @@ -1285,8 +1296,8 @@ if (PURPLE_BLIST_NODE_IS_BUDDY(bnode)) { buddy = (PurpleBuddy*)bnode; bnode = bnode->next; - if (purple_account_is_connected(buddy->account)) { - purple_account_remove_buddy(buddy->account, buddy, group); + if (purple_account_is_connected(purple_buddy_get_account(buddy))) { + purple_account_remove_buddy(purple_buddy_get_account(buddy), buddy, group); purple_blist_remove_buddy(buddy); } } else { @@ -1296,7 +1307,7 @@ } else if (PURPLE_BLIST_NODE_IS_CHAT(cnode)) { PurpleChat *chat = (PurpleChat *)cnode; cnode = cnode->next; - if (purple_account_is_connected(chat->account)) + if (purple_account_is_connected(purple_chat_get_account(chat))) purple_blist_remove_chat(chat); } else { cnode = cnode->next; @@ -1314,7 +1325,7 @@ g_return_if_fail(group != NULL); text = g_strdup_printf(_("You are about to remove the group %s and all its members from your buddy list. Do you want to continue?"), - group->name); + purple_group_get_name(group)); purple_request_action(group, NULL, _("Remove Group"), text, 0, NULL, NULL, NULL, @@ -1334,10 +1345,10 @@ PurpleAccount *account; group = purple_buddy_get_group(buddy); - name = g_strdup(buddy->name); /* b->name is a crasher after remove_buddy */ - account = buddy->account; + name = g_strdup(purple_buddy_get_name(buddy)); /* purple_buddy_get_name() is a crasher after remove_buddy */ + account = purple_buddy_get_account(buddy); - purple_debug_info("blist", "Removing '%s' from buddy list.\n", buddy->name); + purple_debug_info("blist", "Removing '%s' from buddy list.\n", purple_buddy_get_name(buddy)); /* TODO - Should remove from blist first... then call purple_account_remove_buddy()? */ purple_account_remove_buddy(account, buddy, group); purple_blist_remove_buddy(buddy); @@ -1353,7 +1364,7 @@ g_return_if_fail(buddy != NULL); text = g_strdup_printf(_("You are about to remove %s from your buddy list. Do you want to continue?"), - buddy->name); + purple_buddy_get_name(buddy)); purple_request_action(buddy, NULL, _("Remove Buddy"), text, 0, purple_buddy_get_account(buddy), purple_buddy_get_name(buddy), NULL, @@ -1383,7 +1394,7 @@ name ? name : ""); purple_request_action(chat, NULL, _("Remove Chat"), text, 0, - chat->account, NULL, NULL, + purple_chat_get_account(chat), NULL, NULL, chat, 2, _("_Remove Chat"), G_CALLBACK(pidgin_dialogs_remove_chat_cb), _("Cancel"), NULL); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkdialogs.h --- a/pidgin/gtkdialogs.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkdialogs.h Fri Apr 06 04:30:00 2012 +0000 @@ -30,6 +30,8 @@ #include "account.h" #include "conversation.h" +G_BEGIN_DECLS + /* Functions in gtkdialogs.c (these should actually stay in this file) */ void pidgin_dialogs_destroy_all(void); void pidgin_dialogs_about(void); @@ -42,14 +44,6 @@ void pidgin_dialogs_info(void); void pidgin_dialogs_log(void); -#if !(defined PIDGIN_DISABLE_DEPRECATED) || (defined _PIDGIN_GTKDIALOGS_C_) -/** - * @deprecated This function is no longer used and will be removed in - * Pidgin 3.0.0 unless there is sufficient demand to keep it. - */ -void pidgin_dialogs_alias_contact(PurpleContact *); -#endif - void pidgin_dialogs_alias_buddy(PurpleBuddy *); void pidgin_dialogs_alias_chat(PurpleChat *); void pidgin_dialogs_remove_buddy(PurpleBuddy *); @@ -58,15 +52,9 @@ void pidgin_dialogs_remove_contact(PurpleContact *); void pidgin_dialogs_merge_groups(PurpleGroup *, const char *); -/* Everything after this should probably be moved elsewhere */ - -#ifndef PIDGIN_DISABLE_DEPRECATED -/* This PIDGIN_DISABLE_DEPRECATED doesn't need to be deactivated by - * _PIDGIN_GTKDIALOGS_C_, because it shouldn't be using this macro. */ -#define PIDGIN_DIALOG(x) x = gtk_window_new(GTK_WINDOW_TOPLEVEL); \ - gtk_window_set_type_hint(GTK_WINDOW(x), GDK_WINDOW_TYPE_HINT_DIALOG) -#endif - +/* This macro should probably be moved elsewhere */ #define PIDGIN_WINDOW_ICONIFIED(x) (gdk_window_get_state(GTK_WIDGET(x)->window) & GDK_WINDOW_STATE_ICONIFIED) +G_END_DECLS + #endif /* _PIDGINDIALOGS_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkdnd-hints.c --- a/pidgin/gtkdnd-hints.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkdnd-hints.c Fri Apr 06 04:30:00 2012 +0000 @@ -62,19 +62,20 @@ GdkBitmap *bitmap; GtkWidget *pix; GtkWidget *win; + GdkColormap *colormap; pixbuf = gdk_pixbuf_new_from_file(fname, NULL); g_return_val_if_fail(pixbuf, NULL); - gdk_pixbuf_render_pixmap_and_mask(pixbuf, &pixmap, &bitmap, 128); + win = gtk_window_new(GTK_WINDOW_POPUP); + colormap = gtk_widget_get_colormap(win); + gdk_pixbuf_render_pixmap_and_mask_for_colormap(pixbuf, colormap, + &pixmap, &bitmap, 128); g_object_unref(G_OBJECT(pixbuf)); - gtk_widget_push_colormap(gdk_rgb_get_colormap()); - win = gtk_window_new(GTK_WINDOW_POPUP); pix = gtk_image_new_from_pixmap(pixmap, bitmap); gtk_container_add(GTK_CONTAINER(win), pix); gtk_widget_shape_combine_mask(win, bitmap, 0, 0); - gtk_widget_pop_colormap(); g_object_unref(G_OBJECT(pixmap)); g_object_unref(G_OBJECT(bitmap)); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkdnd-hints.h --- a/pidgin/gtkdnd-hints.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkdnd-hints.h Fri Apr 06 04:30:00 2012 +0000 @@ -52,6 +52,8 @@ } DndHintPosition; +G_BEGIN_DECLS + /** * Shows a drag-and-drop hint at the specified location. * @@ -84,4 +86,6 @@ void dnd_hints_show_relative(DndHintWindowId id, GtkWidget *widget, DndHintPosition horiz, DndHintPosition vert); +G_END_DECLS + #endif /* _PIDGIN_DND_HINTS_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkdocklet-gtk.c --- a/pidgin/gtkdocklet-gtk.c Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,296 +0,0 @@ -/* - * System tray icon (aka docklet) plugin for Purple - * - * Copyright (C) 2007 Anders Hasselqvist - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "internal.h" -#include "pidgin.h" -#include "debug.h" -#include "prefs.h" -#include "pidginstock.h" -#include "gtkdocklet.h" - -#define SHORT_EMBED_TIMEOUT 5 -#define LONG_EMBED_TIMEOUT 15 - -/* globals */ -static GtkStatusIcon *docklet = NULL; -static guint embed_timeout = 0; - -/* protos */ -static void docklet_gtk_status_create(gboolean); - -static gboolean -docklet_gtk_recreate_cb(gpointer data) -{ - docklet_gtk_status_create(TRUE); - - return FALSE; -} - -static gboolean -docklet_gtk_embed_timeout_cb(gpointer data) -{ -#if !GTK_CHECK_VERSION(2,12,0) - if (gtk_status_icon_is_embedded(docklet)) { - /* Older GTK+ (<2.12) don't implement the embedded signal, but the - information is still accessable through the above function. */ - purple_debug_info("docklet", "embedded\n"); - - pidgin_docklet_embedded(); - purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE); - } - else -#endif - { - /* The docklet was not embedded within the timeout. - * Remove it as a visibility manager, but leave the plugin - * loaded so that it can embed automatically if/when a notification - * area becomes available. - */ - purple_debug_info("docklet", "failed to embed within timeout\n"); - pidgin_docklet_remove(); - purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE); - } - -#if GTK_CHECK_VERSION(2,12,0) - embed_timeout = 0; - return FALSE; -#else - return TRUE; -#endif -} - -#if GTK_CHECK_VERSION(2,12,0) -static gboolean -docklet_gtk_embedded_cb(GtkWidget *widget, gpointer data) -{ - if (embed_timeout) { - purple_timeout_remove(embed_timeout); - embed_timeout = 0; - } - - if (gtk_status_icon_is_embedded(docklet)) { - purple_debug_info("docklet", "embedded\n"); - - pidgin_docklet_embedded(); - purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE); - } else { - purple_debug_info("docklet", "detached\n"); - - pidgin_docklet_remove(); - purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE); - } - - return TRUE; -} -#endif - -static void -docklet_gtk_destroyed_cb(GtkWidget *widget, gpointer data) -{ - purple_debug_info("docklet", "destroyed\n"); - - pidgin_docklet_remove(); - - g_object_unref(G_OBJECT(docklet)); - docklet = NULL; - - g_idle_add(docklet_gtk_recreate_cb, NULL); -} - -static void -docklet_gtk_status_activated_cb(GtkStatusIcon *status_icon, gpointer user_data) -{ - pidgin_docklet_clicked(1); -} - -static void -docklet_gtk_status_clicked_cb(GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data) -{ - purple_debug_info("docklet", "The button is %u\n", button); -#ifdef GDK_WINDOWING_QUARTZ - /* You can only click left mouse button on MacOSX native GTK. Let that be the menu */ - pidgin_docklet_clicked(3); -#else - pidgin_docklet_clicked(button); -#endif -} - -static void -docklet_gtk_status_update_icon(PurpleStatusPrimitive status, gboolean connecting, gboolean pending) -{ - const gchar *icon_name = NULL; - - switch (status) { - case PURPLE_STATUS_OFFLINE: - icon_name = PIDGIN_STOCK_TRAY_OFFLINE; - break; - case PURPLE_STATUS_AWAY: - icon_name = PIDGIN_STOCK_TRAY_AWAY; - break; - case PURPLE_STATUS_UNAVAILABLE: - icon_name = PIDGIN_STOCK_TRAY_BUSY; - break; - case PURPLE_STATUS_EXTENDED_AWAY: - icon_name = PIDGIN_STOCK_TRAY_XA; - break; - case PURPLE_STATUS_INVISIBLE: - icon_name = PIDGIN_STOCK_TRAY_INVISIBLE; - break; - default: - icon_name = PIDGIN_STOCK_TRAY_AVAILABLE; - break; - } - - if (pending) - icon_name = PIDGIN_STOCK_TRAY_PENDING; - if (connecting) - icon_name = PIDGIN_STOCK_TRAY_CONNECT; - - if (icon_name) { - gtk_status_icon_set_from_icon_name(docklet, icon_name); - } - - if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/blink")) { - gtk_status_icon_set_blinking(docklet, (pending && !connecting)); - } else if (gtk_status_icon_get_blinking(docklet)) { - gtk_status_icon_set_blinking(docklet, FALSE); - } -} - -static void -docklet_gtk_status_set_tooltip(gchar *tooltip) -{ - gtk_status_icon_set_tooltip(docklet, tooltip); -} - -static void -docklet_gtk_status_position_menu(GtkMenu *menu, - int *x, int *y, gboolean *push_in, - gpointer user_data) -{ - gtk_status_icon_position_menu(menu, x, y, push_in, docklet); -} - -static void -docklet_gtk_status_destroy(void) -{ - g_return_if_fail(docklet != NULL); - - pidgin_docklet_remove(); - - if (embed_timeout) { - purple_timeout_remove(embed_timeout); - embed_timeout = 0; - } - - gtk_status_icon_set_visible(docklet, FALSE); - g_signal_handlers_disconnect_by_func(G_OBJECT(docklet), G_CALLBACK(docklet_gtk_destroyed_cb), NULL); - g_object_unref(G_OBJECT(docklet)); - docklet = NULL; - - purple_debug_info("docklet", "GTK+ destroyed\n"); -} - -static void -docklet_gtk_status_create(gboolean recreate) -{ - if (docklet) { - /* if this is being called when a tray icon exists, it's because - something messed up. try destroying it before we proceed, - although docklet_refcount may be all hosed. hopefully won't happen. */ - purple_debug_warning("docklet", "trying to create icon but it already exists?\n"); - docklet_gtk_status_destroy(); - } - - docklet = gtk_status_icon_new(); - g_return_if_fail(docklet != NULL); - - g_signal_connect(G_OBJECT(docklet), "activate", G_CALLBACK(docklet_gtk_status_activated_cb), NULL); - g_signal_connect(G_OBJECT(docklet), "popup-menu", G_CALLBACK(docklet_gtk_status_clicked_cb), NULL); -#if GTK_CHECK_VERSION(2,12,0) - g_signal_connect(G_OBJECT(docklet), "notify::embedded", G_CALLBACK(docklet_gtk_embedded_cb), NULL); -#endif - g_signal_connect(G_OBJECT(docklet), "destroy", G_CALLBACK(docklet_gtk_destroyed_cb), NULL); - - gtk_status_icon_set_visible(docklet, TRUE); - - /* This is a hack to avoid a race condition between the docklet getting - * embedded in the notification area and the gtkblist restoring its - * 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. This only happens when the docklet is first - * created, not when being recreated. - * - * The gtk 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 Pidgin is started on login. - */ - if (!recreate) { - pidgin_docklet_embedded(); -#if GTK_CHECK_VERSION(2,12,0) - if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded")) { - embed_timeout = purple_timeout_add_seconds(LONG_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL); - } else { - embed_timeout = purple_timeout_add_seconds(SHORT_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL); - } -#else - embed_timeout = purple_timeout_add_seconds(SHORT_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL); -#endif - } - - purple_debug_info("docklet", "GTK+ created\n"); -} - -static void -docklet_gtk_status_create_ui_op(void) -{ - docklet_gtk_status_create(FALSE); -} - -static struct docklet_ui_ops ui_ops = -{ - docklet_gtk_status_create_ui_op, - docklet_gtk_status_destroy, - docklet_gtk_status_update_icon, - NULL, - docklet_gtk_status_set_tooltip, - docklet_gtk_status_position_menu -}; - -void -docklet_ui_init(void) -{ - pidgin_docklet_set_ui_ops(&ui_ops); - - purple_prefs_add_none(PIDGIN_PREFS_ROOT "/docklet/gtk"); - if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/x11/embedded")) { - purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE); - purple_prefs_remove(PIDGIN_PREFS_ROOT "/docklet/x11/embedded"); - } else { - purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE); - } - - gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), - DATADIR G_DIR_SEPARATOR_S "pixmaps" G_DIR_SEPARATOR_S "pidgin" G_DIR_SEPARATOR_S "tray"); -} - diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkdocklet.c --- a/pidgin/gtkdocklet.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkdocklet.c Fri Apr 06 04:30:00 2012 +0000 @@ -30,6 +30,7 @@ #include "prefs.h" #include "signals.h" #include "sound.h" +#include "status.h" #include "gtkaccount.h" #include "gtkblist.h" @@ -48,8 +49,12 @@ #define DOCKLET_TOOLTIP_LINE_LIMIT 5 #endif +#define SHORT_EMBED_TIMEOUT 5 +#define LONG_EMBED_TIMEOUT 15 + /* globals */ -static struct docklet_ui_ops *ui_ops = NULL; +static GtkStatusIcon *docklet = NULL; +static guint embed_timeout = 0; static PurpleStatusPrimitive status = PURPLE_STATUS_OFFLINE; static gboolean pending = FALSE; static gboolean connecting = FALSE; @@ -58,9 +63,55 @@ static gboolean visible = FALSE; static gboolean visibility_manager = FALSE; +/* protos */ +static void docklet_gtk_status_create(gboolean); +static void docklet_gtk_status_destroy(void); + /************************************************************************** * docklet status and utility functions **************************************************************************/ +static void +docklet_gtk_status_update_icon(PurpleStatusPrimitive status, gboolean connecting, gboolean pending) +{ + const gchar *icon_name = NULL; + + switch (status) { + case PURPLE_STATUS_OFFLINE: + icon_name = PIDGIN_STOCK_TRAY_OFFLINE; + break; + case PURPLE_STATUS_AWAY: + icon_name = PIDGIN_STOCK_TRAY_AWAY; + break; + case PURPLE_STATUS_UNAVAILABLE: + icon_name = PIDGIN_STOCK_TRAY_BUSY; + break; + case PURPLE_STATUS_EXTENDED_AWAY: + icon_name = PIDGIN_STOCK_TRAY_XA; + break; + case PURPLE_STATUS_INVISIBLE: + icon_name = PIDGIN_STOCK_TRAY_INVISIBLE; + break; + default: + icon_name = PIDGIN_STOCK_TRAY_AVAILABLE; + break; + } + + if (pending) + icon_name = PIDGIN_STOCK_TRAY_PENDING; + if (connecting) + icon_name = PIDGIN_STOCK_TRAY_CONNECT; + + if (icon_name) { + gtk_status_icon_set_from_icon_name(docklet, icon_name); + } + + if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/blink")) { + gtk_status_icon_set_blinking(docklet, (pending && !connecting)); + } else if (gtk_status_icon_get_blinking(docklet)) { + gtk_status_icon_set_blinking(docklet, FALSE); + } +} + static gboolean docklet_blink_icon(gpointer data) { @@ -70,11 +121,8 @@ blinked = !blinked; if(pending && !connecting) { - if (blinked) { - if (ui_ops && ui_ops->blank_icon) - ui_ops->blank_icon(); - } else { - pidgin_docklet_update_icon(); + if (!blinked) { + docklet_gtk_status_update_icon(status, connecting, pending); } ret = TRUE; /* keep blinking */ } else { @@ -126,12 +174,12 @@ convs = get_pending_list(DOCKLET_TOOLTIP_LINE_LIMIT); if (!strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/docklet/show"), "pending")) { - if (convs && ui_ops->create && !visible) { + if (convs && !visible) { g_list_free(convs); - ui_ops->create(); + docklet_gtk_status_create(FALSE); return FALSE; - } else if (!convs && ui_ops->destroy && visible) { - ui_ops->destroy(); + } else if (!convs && visible) { + docklet_gtk_status_destroy(); return FALSE; } } @@ -142,53 +190,49 @@ } if (convs != NULL) { + /* set tooltip if messages are pending */ + GString *tooltip_text = g_string_new(""); newpending = TRUE; - /* set tooltip if messages are pending */ - if (ui_ops->set_tooltip) { - GString *tooltip_text = g_string_new(""); - for (l = convs, count = 0 ; l != NULL ; l = l->next, count++) { - PurpleConversation *conv = (PurpleConversation *)l->data; - PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); + for (l = convs, count = 0 ; l != NULL ; l = l->next, count++) { + PurpleConversation *conv = (PurpleConversation *)l->data; + PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); - if (count == DOCKLET_TOOLTIP_LINE_LIMIT - 1) { - g_string_append(tooltip_text, _("Right-click for more unread messages...\n")); - } else if(gtkconv) { - g_string_append_printf(tooltip_text, - ngettext("%d unread message from %s\n", "%d unread messages from %s\n", gtkconv->unseen_count), - gtkconv->unseen_count, - purple_conversation_get_title(conv)); - } else { - g_string_append_printf(tooltip_text, - ngettext("%d unread message from %s\n", "%d unread messages from %s\n", - GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count"))), - GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count")), - purple_conversation_get_title(conv)); - } + if (count == DOCKLET_TOOLTIP_LINE_LIMIT - 1) { + g_string_append(tooltip_text, _("Right-click for more unread messages...\n")); + } else if(gtkconv) { + g_string_append_printf(tooltip_text, + ngettext("%d unread message from %s\n", "%d unread messages from %s\n", gtkconv->unseen_count), + gtkconv->unseen_count, + purple_conversation_get_title(conv)); + } else { + g_string_append_printf(tooltip_text, + ngettext("%d unread message from %s\n", "%d unread messages from %s\n", + GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count"))), + GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count")), + purple_conversation_get_title(conv)); } - - /* get rid of the last newline */ - if (tooltip_text->len > 0) - tooltip_text = g_string_truncate(tooltip_text, tooltip_text->len - 1); - - ui_ops->set_tooltip(tooltip_text->str); - - g_string_free(tooltip_text, TRUE); } + /* get rid of the last newline */ + if (tooltip_text->len > 0) + tooltip_text = g_string_truncate(tooltip_text, tooltip_text->len - 1); + + gtk_status_icon_set_tooltip(docklet, tooltip_text->str); + + g_string_free(tooltip_text, TRUE); g_list_free(convs); - } else if (ui_ops->set_tooltip) { + } else { char *tooltip_text = g_strconcat(PIDGIN_NAME, " - ", purple_savedstatus_get_title(saved_status), NULL); - ui_ops->set_tooltip(tooltip_text); + gtk_status_icon_set_tooltip(docklet, tooltip_text); g_free(tooltip_text); } for(l = purple_accounts_get_all(); l != NULL; l = l->next) { PurpleAccount *account = (PurpleAccount*)l->data; - PurpleStatus *account_status; if (!purple_account_get_enabled(account, PIDGIN_UI)) continue; @@ -196,7 +240,6 @@ if (purple_account_is_disconnected(account)) continue; - account_status = purple_account_get_active_status(account); if (purple_account_is_connecting(account)) newconnecting = TRUE; } @@ -209,7 +252,7 @@ pending = newpending; connecting = newconnecting; - pidgin_docklet_update_icon(); + docklet_gtk_status_update_icon(status, connecting, pending); /* and schedule the blinker function if messages are pending */ if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/blink") @@ -229,7 +272,7 @@ while(c != NULL) { PurpleConnection *gc = c->data; - PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (prpl_info != NULL && prpl_info->chat_info != NULL) return TRUE; c = c->next; @@ -266,7 +309,7 @@ docklet_signed_on_cb(PurpleConnection *gc) { if (!enable_join_chat) { - if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info != NULL) + if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->chat_info != NULL) enable_join_chat = TRUE; } docklet_update_status(); @@ -276,7 +319,7 @@ docklet_signed_off_cb(PurpleConnection *gc) { if (enable_join_chat) { - if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info != NULL) + if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->chat_info != NULL) enable_join_chat = online_account_supports_chat(); } docklet_update_status(); @@ -288,17 +331,15 @@ { const char *val = value; if (!strcmp(val, "always")) { - if (ui_ops->create) { - if (!visible) - ui_ops->create(); - else if (!visibility_manager) { - pidgin_blist_visibility_manager_add(); - visibility_manager = TRUE; - } + if (!visible) + docklet_gtk_status_create(FALSE); + else if (!visibility_manager) { + pidgin_blist_visibility_manager_add(); + visibility_manager = TRUE; } } else if (!strcmp(val, "never")) { - if (visible && ui_ops->destroy) - ui_ops->destroy(); + if (visible) + docklet_gtk_status_destroy(); } else { if (visibility_manager) { pidgin_blist_visibility_manager_remove(); @@ -523,7 +564,7 @@ new_menu_item_with_status_icon(menu, purple_status_type_get_name(status_type), prim, G_CALLBACK(activate_status_account_cb), - status_type, 0, 0, NULL); + GINT_TO_POINTER(status_type), 0, 0, NULL); } } @@ -674,6 +715,7 @@ { static GtkWidget *menu = NULL; GtkWidget *menuitem; + GtkMenuPositionFunc pos_func = gtk_status_icon_position_menu; if (menu) { gtk_widget_destroy(menu); @@ -749,24 +791,15 @@ #ifdef _WIN32 g_signal_connect(menu, "leave-notify-event", G_CALLBACK(docklet_menu_leave_enter), NULL); g_signal_connect(menu, "enter-notify-event", G_CALLBACK(docklet_menu_leave_enter), NULL); + pos_func = NULL; #endif gtk_widget_show_all(menu); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, - ui_ops->position_menu, - NULL, 0, gtk_get_current_event_time()); + pos_func, + docklet, 0, gtk_get_current_event_time()); } -/************************************************************************** - * public api for ui_ops - **************************************************************************/ -void -pidgin_docklet_update_icon() -{ - if (ui_ops && ui_ops->update_icon) - ui_ops->update_icon(status, connecting, pending); -} - -void +static void pidgin_docklet_clicked(int button_type) { switch (button_type) { @@ -787,8 +820,8 @@ } } -void -pidgin_docklet_embedded() +static void +pidgin_docklet_embedded(void) { if (!visibility_manager && strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/docklet/show"), "pending")) { @@ -797,11 +830,11 @@ } visible = TRUE; docklet_update_status(); - pidgin_docklet_update_icon(); + docklet_gtk_status_update_icon(status, connecting, pending); } -void -pidgin_docklet_remove() +static void +pidgin_docklet_remove(void) { if (visible) { if (visibility_manager) { @@ -817,12 +850,183 @@ } } -void -pidgin_docklet_set_ui_ops(struct docklet_ui_ops *ops) +static gboolean +docklet_gtk_recreate_cb(gpointer data) +{ + docklet_gtk_status_create(TRUE); + + return FALSE; +} + +#ifndef _WIN32 +static gboolean +docklet_gtk_embed_timeout_cb(gpointer data) { - ui_ops = ops; +#if !GTK_CHECK_VERSION(2,12,0) + if (gtk_status_icon_is_embedded(docklet)) { + /* Older GTK+ (<2.12) don't implement the embedded signal, but the + information is still accessible through the above function. */ + purple_debug_info("docklet", "embedded\n"); + + pidgin_docklet_embedded(); + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE); + } + else +#endif + { + /* The docklet was not embedded within the timeout. + * Remove it as a visibility manager, but leave the plugin + * loaded so that it can embed automatically if/when a notification + * area becomes available. + */ + purple_debug_info("docklet", "failed to embed within timeout\n"); + pidgin_docklet_remove(); + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE); + } + +#if GTK_CHECK_VERSION(2,12,0) + embed_timeout = 0; + return FALSE; +#else + return TRUE; +#endif +} +#endif + +#if GTK_CHECK_VERSION(2,12,0) +static gboolean +docklet_gtk_embedded_cb(GtkWidget *widget, gpointer data) +{ + if (embed_timeout) { + purple_timeout_remove(embed_timeout); + embed_timeout = 0; + } + + if (gtk_status_icon_is_embedded(docklet)) { + purple_debug_info("docklet", "embedded\n"); + + pidgin_docklet_embedded(); + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE); + } else { + purple_debug_info("docklet", "detached\n"); + + pidgin_docklet_remove(); + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE); + } + + return TRUE; +} +#endif + +static void +docklet_gtk_destroyed_cb(GtkWidget *widget, gpointer data) +{ + purple_debug_info("docklet", "destroyed\n"); + + pidgin_docklet_remove(); + + g_object_unref(G_OBJECT(docklet)); + docklet = NULL; + + g_idle_add(docklet_gtk_recreate_cb, NULL); +} + +static void +docklet_gtk_status_activated_cb(GtkStatusIcon *status_icon, gpointer user_data) +{ + pidgin_docklet_clicked(1); } +static void +docklet_gtk_status_clicked_cb(GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data) +{ + purple_debug_info("docklet", "The button is %u\n", button); +#ifdef GDK_WINDOWING_QUARTZ + /* You can only click left mouse button on MacOSX native GTK. Let that be the menu */ + pidgin_docklet_clicked(3); +#else + pidgin_docklet_clicked(button); +#endif +} + +static void +docklet_gtk_status_destroy(void) +{ + g_return_if_fail(docklet != NULL); + + pidgin_docklet_remove(); + + if (embed_timeout) { + purple_timeout_remove(embed_timeout); + embed_timeout = 0; + } + + gtk_status_icon_set_visible(docklet, FALSE); + g_signal_handlers_disconnect_by_func(G_OBJECT(docklet), G_CALLBACK(docklet_gtk_destroyed_cb), NULL); + g_object_unref(G_OBJECT(docklet)); + docklet = NULL; + + purple_debug_info("docklet", "GTK+ destroyed\n"); +} + +static void +docklet_gtk_status_create(gboolean recreate) +{ + if (docklet) { + /* if this is being called when a tray icon exists, it's because + something messed up. try destroying it before we proceed, + although docklet_refcount may be all hosed. hopefully won't happen. */ + purple_debug_warning("docklet", "trying to create icon but it already exists?\n"); + docklet_gtk_status_destroy(); + } + + docklet = gtk_status_icon_new(); + g_return_if_fail(docklet != NULL); + + g_signal_connect(G_OBJECT(docklet), "activate", G_CALLBACK(docklet_gtk_status_activated_cb), NULL); + g_signal_connect(G_OBJECT(docklet), "popup-menu", G_CALLBACK(docklet_gtk_status_clicked_cb), NULL); +#if GTK_CHECK_VERSION(2,12,0) + g_signal_connect(G_OBJECT(docklet), "notify::embedded", G_CALLBACK(docklet_gtk_embedded_cb), NULL); +#endif + g_signal_connect(G_OBJECT(docklet), "destroy", G_CALLBACK(docklet_gtk_destroyed_cb), NULL); + + gtk_status_icon_set_visible(docklet, TRUE); + + /* This is a hack to avoid a race condition between the docklet getting + * embedded in the notification area and the gtkblist restoring its + * 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. This only happens when the docklet is first + * created, not when being recreated. + * + * The gtk 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 Pidgin is started on login. + */ + if (!recreate) { + pidgin_docklet_embedded(); +#ifndef _WIN32 +#if GTK_CHECK_VERSION(2,12,0) + if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded")) { + embed_timeout = purple_timeout_add_seconds(LONG_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL); + } else { + embed_timeout = purple_timeout_add_seconds(SHORT_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL); + } +#else + embed_timeout = purple_timeout_add_seconds(SHORT_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL); +#endif +#endif + } + + purple_debug_info("docklet", "GTK+ created\n"); +} + +/************************************************************************** + * public api + **************************************************************************/ + void* pidgin_docklet_get_handle() { @@ -838,6 +1042,7 @@ void *accounts_handle = purple_accounts_get_handle(); void *status_handle = purple_savedstatuses_get_handle(); void *docklet_handle = pidgin_docklet_get_handle(); + gchar *tmp; purple_prefs_add_none(PIDGIN_PREFS_ROOT "/docklet"); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/docklet/blink", FALSE); @@ -845,9 +1050,20 @@ purple_prefs_connect_callback(docklet_handle, PIDGIN_PREFS_ROOT "/docklet/show", docklet_show_pref_changed_cb, NULL); - docklet_ui_init(); - if (!strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/docklet/show"), "always") && ui_ops && ui_ops->create) - ui_ops->create(); + purple_prefs_add_none(PIDGIN_PREFS_ROOT "/docklet/gtk"); + if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/x11/embedded")) { + purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE); + purple_prefs_remove(PIDGIN_PREFS_ROOT "/docklet/x11/embedded"); + } else { + purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE); + } + + tmp = g_build_path(G_DIR_SEPARATOR_S, DATADIR, "pixmaps", "pidgin", "tray", NULL); + gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), tmp); + g_free(tmp); + + if (!strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/docklet/show"), "always")) + docklet_gtk_status_create(FALSE); purple_signal_connect(conn_handle, "signed-on", docklet_handle, PURPLE_CALLBACK(docklet_signed_on_cb), NULL); @@ -876,6 +1092,7 @@ void pidgin_docklet_uninit() { - if (visible && ui_ops && ui_ops->destroy) - ui_ops->destroy(); + if (visible) + docklet_gtk_status_destroy(); } + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkdocklet.h --- a/pidgin/gtkdocklet.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkdocklet.h Fri Apr 06 04:30:00 2012 +0000 @@ -25,31 +25,13 @@ #ifndef _GTKDOCKLET_H_ #define _GTKDOCKLET_H_ -#include "status.h" +G_BEGIN_DECLS -struct docklet_ui_ops -{ - void (*create)(void); - void (*destroy)(void); - void (*update_icon)(PurpleStatusPrimitive, gboolean, gboolean); - void (*blank_icon)(void); - void (*set_tooltip)(gchar *); - GtkMenuPositionFunc position_menu; -}; - - -/* functions in gtkdocklet.c */ -void pidgin_docklet_update_icon(void); -void pidgin_docklet_clicked(int); -void pidgin_docklet_embedded(void); -void pidgin_docklet_remove(void); -void pidgin_docklet_set_ui_ops(struct docklet_ui_ops *); -void pidgin_docklet_unload(void); void pidgin_docklet_init(void); void pidgin_docklet_uninit(void); void*pidgin_docklet_get_handle(void); -/* function in gtkdocklet-{gtk,x11,win32}.c */ -void docklet_ui_init(void); +G_END_DECLS #endif /* _GTKDOCKLET_H_ */ + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkeventloop.h --- a/pidgin/gtkeventloop.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkeventloop.h Fri Apr 06 04:30:00 2012 +0000 @@ -28,6 +28,8 @@ #include "eventloop.h" +G_BEGIN_DECLS + /** * Returns the GTK+ event loop UI operations structure. * @@ -35,4 +37,6 @@ */ PurpleEventLoopUiOps *pidgin_eventloop_get_ui_ops(void); +G_END_DECLS + #endif /* _PIDGINEVENTLOOP_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkft.c --- a/pidgin/gtkft.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkft.c Fri Apr 06 04:30:00 2012 +0000 @@ -37,9 +37,6 @@ #include "pidginstock.h" #include "gtkutils.h" -#define PIDGINXFER(xfer) \ - (PidginXferUiData *)(xfer)->ui_data - /* the maximum size of files we will try to make a thumbnail for */ #define PIDGIN_XFER_MAX_SIZE_IMAGE_THUMBNAIL 10 * 1024 * 1024 @@ -116,14 +113,17 @@ double kbps = 0.0; time_t elapsed, now; - if (xfer->end_time != 0) - now = xfer->end_time; - else + now = purple_xfer_get_end_time(xfer); + if (now == 0) now = time(NULL); kb_sent = purple_xfer_get_bytes_sent(xfer) / 1024.0; kb_rem = purple_xfer_get_bytes_remaining(xfer) / 1024.0; - elapsed = (xfer->start_time > 0 ? now - xfer->start_time : 0); + elapsed = purple_xfer_get_start_time(xfer); + if (elapsed > 0) + elapsed = now - elapsed; + else + elapsed = 0; kbps = (elapsed > 0 ? (kb_sent / elapsed) : 0); if (kbsec != NULL) { @@ -135,9 +135,9 @@ int h, m, s; int secs_elapsed; - if (xfer->start_time > 0) + if (purple_xfer_get_start_time(xfer) > 0) { - secs_elapsed = now - xfer->start_time; + secs_elapsed = now - purple_xfer_get_start_time(xfer); h = secs_elapsed / 3600; m = (secs_elapsed % 3600) / 60; @@ -155,7 +155,7 @@ if (purple_xfer_is_completed(xfer)) { *time_remaining = g_strdup(_("Finished")); } - else if (purple_xfer_is_canceled(xfer)) { + else if (purple_xfer_is_cancelled(xfer)) { *time_remaining = g_strdup(_("Cancelled")); } else if (purple_xfer_get_size(xfer) == 0 || (kb_sent > 0 && kbps == 0)) { @@ -243,11 +243,11 @@ if (dialog == NULL || xfer == NULL) return; - data = PIDGINXFER(xfer); + data = purple_xfer_get_ui_data(xfer); get_xfer_info_strings(xfer, &kbsec, &time_elapsed, &time_remaining); - status = g_strdup_printf("%d%% (%" G_GSIZE_FORMAT " of %" G_GSIZE_FORMAT " bytes)", + status = g_strdup_printf("%d%% (%" G_GOFFSET_FORMAT " of %" G_GOFFSET_FORMAT " bytes)", (int)(purple_xfer_get_progress(xfer)*100), purple_xfer_get_bytes_sent(xfer), purple_xfer_get_size(xfer)); @@ -281,10 +281,10 @@ } gtk_label_set_text(GTK_LABEL(dialog->local_user_label), - purple_account_get_username(xfer->account)); - gtk_label_set_text(GTK_LABEL(dialog->remote_user_label), xfer->who); + purple_account_get_username(purple_xfer_get_account(xfer))); + gtk_label_set_text(GTK_LABEL(dialog->remote_user_label), purple_xfer_get_remote_user(xfer)); gtk_label_set_text(GTK_LABEL(dialog->protocol_label), - purple_account_get_protocol_name(xfer->account)); + purple_account_get_protocol_name(purple_xfer_get_account(xfer))); if (purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) { gtk_label_set_text(GTK_LABEL(dialog->filename_label), @@ -357,7 +357,7 @@ #endif gtk_widget_set_sensitive(dialog->remove_button, TRUE); - } else if (purple_xfer_is_canceled(xfer)) { + } else if (purple_xfer_is_cancelled(xfer)) { gtk_widget_hide(dialog->stop_button); gtk_widget_show(dialog->remove_button); @@ -732,8 +732,8 @@ gtk_widget_show(vbox2); /* Setup the listbox */ - gtk_box_pack_start(GTK_BOX(vbox2), - pidgin_make_scrollable(setup_tree(dialog), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_IN, -1, 140), + gtk_box_pack_start(GTK_BOX(vbox2), + pidgin_make_scrollable(setup_tree(dialog), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_IN, -1, 140), TRUE, TRUE, 0); /* "Close this window when all transfers finish" */ @@ -869,7 +869,7 @@ purple_xfer_ref(xfer); - data = PIDGINXFER(xfer); + data = purple_xfer_get_ui_data(xfer); data->in_list = TRUE; pidgin_xfer_dialog_show(dialog); @@ -926,7 +926,7 @@ g_return_if_fail(dialog != NULL); g_return_if_fail(xfer != NULL); - data = PIDGINXFER(xfer); + data = purple_xfer_get_ui_data(xfer); if (data == NULL) return; @@ -957,7 +957,7 @@ g_return_if_fail(dialog != NULL); g_return_if_fail(xfer != NULL); - data = PIDGINXFER(xfer); + data = purple_xfer_get_ui_data(xfer); if (data == NULL) return; @@ -970,7 +970,7 @@ return; } - data = PIDGINXFER(xfer); + data = purple_xfer_get_ui_data(xfer); update_detailed_info(dialog, xfer); update_title_progress(dialog); @@ -979,7 +979,7 @@ PIDGIN_STOCK_FILE_CANCELED, GTK_ICON_SIZE_MENU, NULL); - if (purple_xfer_is_canceled(xfer)) + if (purple_xfer_is_cancelled(xfer)) status = _("Cancelled"); else status = _("Failed"); @@ -1007,7 +1007,7 @@ g_return_if_fail(dialog != NULL); g_return_if_fail(xfer != NULL); - if ((data = PIDGINXFER(xfer)) == NULL) + if ((data = purple_xfer_get_ui_data(xfer)) == NULL) return; if (data->in_list == FALSE) @@ -1095,9 +1095,9 @@ { PidginXferUiData *data; - /* This is where we're setting xfer->ui_data for the first time. */ + /* This is where we're setting xfer's "ui_data" for the first time. */ data = g_new0(PidginXferUiData, 1); - xfer->ui_data = data; + purple_xfer_set_ui_data(xfer, data); } static void @@ -1105,11 +1105,11 @@ { PidginXferUiData *data; - data = PIDGINXFER(xfer); + data = purple_xfer_get_ui_data(xfer); if (data) { g_free(data->name); g_free(data); - xfer->ui_data = NULL; + purple_xfer_set_ui_data(xfer, NULL); } } diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkft.h --- a/pidgin/gtkft.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkft.h Fri Apr 06 04:30:00 2012 +0000 @@ -36,6 +36,8 @@ */ typedef struct _PidginXferDialog PidginXferDialog; +G_BEGIN_DECLS + /**************************************************************************/ /** @name GTK+ File Transfer Dialog API */ /**************************************************************************/ @@ -145,4 +147,6 @@ /*@}*/ +G_END_DECLS + #endif /* _PIDGINFT_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkgaim-compat.h --- a/pidgin/gtkgaim-compat.h Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,412 +0,0 @@ -/** - * @file gtkgaim-compat.h Gtk Gaim Compat macros - */ - -/* pidgin - * - * Pidgin is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - * - */ -#ifndef _GTKGAIM_COMPAT_H_ -#define _GTKGAIM_COMPAT_H_ - -#include - -#define GAIM_ALERT_TITLE PIDGIN_ALERT_TITLE -#define GAIM_BROWSER_CURRENT PIDGIN_BROWSER_CURRENT -#define GAIM_BROWSER_DEFAULT PIDGIN_BROWSER_DEFAULT -#define GAIM_BROWSER_NEW_TAB PIDGIN_BROWSER_NEW_TAB -#define GAIM_BROWSER_NEW_WINDOW PIDGIN_BROWSER_NEW_WINDOW -#define GaimBrowserPlace PidginBrowserPlace -#define GAIM_BUTTON_HORIZONTAL PIDGIN_BUTTON_HORIZONTAL -#define GAIM_BUTTON_IMAGE PIDGIN_BUTTON_IMAGE -#define GAIM_BUTTON_NONE PIDGIN_BUTTON_NONE -#define GaimButtonOrientation PidginButtonOrientation -#define GaimButtonStyle PidginButtonStyle -#define GAIM_BUTTON_TEXT_IMAGE PIDGIN_BUTTON_TEXT_IMAGE -#define GAIM_BUTTON_TEXT PIDGIN_BUTTON_TEXT -#define GAIM_BUTTON_VERTICAL PIDGIN_BUTTON_VERTICAL -#define GaimConvPlacementFunc PidginConvPlacementFunc -#define GAIM_DIALOG PIDGIN_DIALOG -#define gaim_dnd_file_manage pidgin_dnd_file_manage -#define gaim_get_gtkxfer_dialog pidgin_get_xfer_dialog -#define gaim_gtk_account_dialog_show pidgin_account_dialog_show -#define GaimGtkAccountDialogType PidginAccountDialogType -#define gaim_gtk_account_get_handle pidgin_account_get_handle -#define gaim_gtk_account_init pidgin_account_init -#define gaim_gtk_account_option_menu_get_selected pidgin_account_option_menu_get_selected -#define gaim_gtk_account_option_menu_new pidgin_account_option_menu_new -#define gaim_gtk_account_option_menu_set_selected pidgin_account_option_menu_set_selected -#define gaim_gtk_accounts_get_ui_ops pidgin_accounts_get_ui_ops -#define gaim_gtk_accounts_window_hide pidgin_accounts_window_hide -#define gaim_gtk_accounts_window_show pidgin_accounts_window_show -#define gaim_gtk_account_uninit pidgin_account_uninit -#define GAIM_GTK_ADD_ACCOUNT_DIALOG PIDGIN_ADD_ACCOUNT_DIALOG -#define gaim_gtk_append_blist_node_extended_menu pidgin_append_blist_node_extended_menu -#define gaim_gtk_append_blist_node_privacy_menu pidgin_append_blist_node_privacy_menu -#define gaim_gtk_append_blist_node_proto_menu pidgin_append_blist_node_proto_menu -#define gaim_gtk_append_menu_action pidgin_append_menu_action -#define gaim_gtk_blist_add_alert pidgin_blist_add_alert -#define gaim_gtk_blist_get_default_gtk_blist pidgin_blist_get_default_gtk_blist -#define gaim_gtk_blist_get_handle pidgin_blist_get_handle -#define gaim_gtk_blist_get_sort_methods pidgin_blist_get_sort_methods -#define gaim_gtk_blist_get_status_icon pidgin_blist_get_status_icon -#define gaim_gtk_blist_get_ui_ops pidgin_blist_get_ui_ops -#define gaim_gtk_blist_init pidgin_blist_init -#define gaim_gtk_blist_joinchat_is_showable pidgin_blist_joinchat_is_showable -#define gaim_gtk_blist_joinchat_show pidgin_blist_joinchat_show -#define gaim_gtk_blist_make_buddy_menu pidgin_blist_make_buddy_menu -#define gaim_gtk_blist_node_is_contact_expanded pidgin_blist_node_is_contact_expanded -#define GAIM_GTK_BLIST PIDGIN_BLIST -#define gaim_gtk_blist_refresh pidgin_blist_refresh -#define gaim_gtk_blist_set_headline pidgin_blist_set_headline -#define gaim_gtk_blist_setup_sort_methods pidgin_blist_setup_sort_methods -#define gaim_gtk_blist_sort_function pidgin_blist_sort_function -#define gaim_gtk_blist_sort_method pidgin_blist_sort_method -#define GaimGtkBlistSortMethod PidginBlistSortMethod -#define gaim_gtk_blist_sort_method_reg pidgin_blist_sort_method_reg -#define gaim_gtk_blist_sort_method_set pidgin_blist_sort_method_set -#define gaim_gtk_blist_sort_method_unreg pidgin_blist_sort_method_unreg -#define gaim_gtk_blist_toggle_visibility pidgin_blist_toggle_visibility -#define gaim_gtk_blist_uninit pidgin_blist_uninit -#define gaim_gtk_blist_update_account_error_state pidgin_blist_update_account_error_state -#define gaim_gtk_blist_update_accounts_menu pidgin_blist_update_accounts_menu -#define gaim_gtk_blist_update_columns pidgin_blist_update_columns -#define gaim_gtk_blist_update_plugin_actions pidgin_blist_update_plugin_actions -#define gaim_gtk_blist_update_refresh_timeout pidgin_blist_update_refresh_timeout -#define gaim_gtk_blist_update_sort_methods pidgin_blist_update_sort_methods -#define gaim_gtk_blist_visibility_manager_add pidgin_blist_visibility_manager_add -#define gaim_gtk_blist_visibility_manager_remove pidgin_blist_visibility_manager_remove -#define gaim_gtk_buddy_icon_chooser_new pidgin_buddy_icon_chooser_new -#define gaim_gtk_buddy_icon_get_scale_size pidgin_buddy_icon_get_scale_size -#define GaimGtkBuddyList PidginBuddyList -#define GaimGtkCellRendererExpanderClass PidginCellRendererExpanderClass -#define gaim_gtk_cell_renderer_expander_get_type pidgin_cell_renderer_expander_get_type -#define gaim_gtk_cell_renderer_expander_new pidgin_cell_renderer_expander_new -#define GaimGtkCellRendererExpander PidginCellRendererExpander -#define GaimGtkCellRendererProgressClass PidginCellRendererProgressClass -#define gaim_gtk_cell_renderer_progress_get_type pidgin_cell_renderer_progress_get_type -#define gaim_gtk_cell_renderer_progress_new pidgin_cell_renderer_progress_new -#define GaimGtkCellRendererProgress PidginCellRendererProgress -#define GaimGtkChatPane PidginChatPane -#define gaim_gtk_check_if_dir pidgin_check_if_dir -#define gaim_gtk_clear_cursor pidgin_clear_cursor -#define gaim_gtk_connection_get_handle pidgin_connection_get_handle -#define gaim_gtk_connection_init pidgin_connection_init -#define gaim_gtk_connections_get_ui_ops pidgin_connections_get_ui_ops -#define gaim_gtk_connection_uninit pidgin_connection_uninit -#define GaimGtkConversation PidginConversation -#define GAIM_GTK_CONVERSATION PIDGIN_CONVERSATION -#define gaim_gtk_conversations_fill_menu pidgin_conversations_fill_menu -#define gaim_gtk_conversations_find_unseen_list pidgin_conversations_find_unseen_list -#define gaim_gtk_conversations_get_conv_ui_ops pidgin_conversations_get_conv_ui_ops -#define gaim_gtk_conversations_get_handle pidgin_conversations_get_handle -#define gaim_gtk_conversations_init pidgin_conversations_init -#define gaim_gtk_conversations_uninit pidgin_conversations_uninit -#define gaim_gtk_convert_buddy_icon pidgin_convert_buddy_icon -#define gaim_gtkconv_get_tab_at_xy pidgin_conv_get_tab_at_xy -#define gaim_gtkconv_get_tab_icon pidgin_conv_get_tab_icon -#define gaim_gtkconv_get_window pidgin_conv_get_window -#define gaim_gtkconv_is_hidden pidgin_conv_is_hidden -#define gaim_gtkconv_new pidgin_conv_new -#define gaim_gtkconv_placement_add_fnc pidgin_conv_placement_add_fnc -#define gaim_gtkconv_placement_get_current_func pidgin_conv_placement_get_current_func -#define gaim_gtkconv_placement_get_fnc pidgin_conv_placement_get_fnc -#define gaim_gtkconv_placement_get_name pidgin_conv_placement_get_name -#define gaim_gtkconv_placement_get_options pidgin_conv_placement_get_options -#define gaim_gtkconv_placement_place pidgin_conv_placement_place -#define gaim_gtkconv_placement_remove_fnc pidgin_conv_placement_remove_fnc -#define gaim_gtkconv_placement_set_current_func pidgin_conv_placement_set_current_func -#define gaim_gtkconv_present_conversation pidgin_conv_present_conversation -#define gaim_gtkconv_switch_active_conversation pidgin_conv_switch_active_conversation -#define gaim_gtkconv_update_buddy_icon pidgin_conv_update_buddy_icon -#define gaim_gtkconv_update_buttons_by_protocol pidgin_conv_update_buttons_by_protocol -#define gaim_gtk_conv_window_add_gtkconv pidgin_conv_window_add_gtkconv -#define gaim_gtk_conv_window_destroy pidgin_conv_window_destroy -#define gaim_gtk_conv_window_first_with_type pidgin_conv_window_first_with_type -#define gaim_gtk_conv_window_get_active_conversation pidgin_conv_window_get_active_conversation -#define gaim_gtk_conv_window_get_active_gtkconv pidgin_conv_window_get_active_gtkconv -#define gaim_gtk_conv_window_get_at_xy pidgin_conv_window_get_at_xy -#define gaim_gtk_conv_window_get_gtkconv_at_index pidgin_conv_window_get_gtkconv_at_index -#define gaim_gtk_conv_window_get_gtkconv_count pidgin_conv_window_get_gtkconv_count -#define gaim_gtk_conv_window_get_gtkconvs pidgin_conv_window_get_gtkconvs -#define gaim_gtk_conv_window_has_focus pidgin_conv_window_has_focus -#define gaim_gtk_conv_window_hide pidgin_conv_window_hide -#define gaim_gtk_conv_window_is_active_conversation pidgin_conv_window_is_active_conversation -#define gaim_gtk_conv_window_last_with_type pidgin_conv_window_last_with_type -#define gaim_gtk_conv_window_new pidgin_conv_window_new -#define gaim_gtk_conv_window_raise pidgin_conv_window_raise -#define gaim_gtk_conv_window_remove_gtkconv pidgin_conv_window_remove_gtkconv -#define gaim_gtk_conv_windows_get_list pidgin_conv_windows_get_list -#define gaim_gtk_conv_window_show pidgin_conv_window_show -#define gaim_gtk_conv_window_switch_gtkconv pidgin_conv_window_switch_gtkconv -#define gaim_gtk_create_imhtml pidgin_create_imhtml -#define gaim_gtk_debug_get_handle pidgin_debug_get_handle -#define gaim_gtk_debug_get_ui_ops pidgin_debug_get_ui_ops -#define gaim_gtk_debug_init pidgin_debug_init -#define gaim_gtk_debug_uninit pidgin_debug_uninit -#define gaim_gtk_debug_window_hide pidgin_debug_window_hide -#define gaim_gtk_debug_window_show pidgin_debug_window_show -#define gaim_gtkdialogs_about pidgin_dialogs_about -#define gaim_gtkdialogs_alias_buddy pidgin_dialogs_alias_buddy -#define gaim_gtkdialogs_alias_chat pidgin_dialogs_alias_chat -#define gaim_gtkdialogs_alias_contact pidgin_dialogs_alias_contact -#define gaim_gtkdialogs_destroy_all pidgin_dialogs_destroy_all -#define gaim_gtkdialogs_im pidgin_dialogs_im -#define gaim_gtkdialogs_im_with_user pidgin_dialogs_im_with_user -#define gaim_gtkdialogs_info pidgin_dialogs_info -#define gaim_gtkdialogs_log pidgin_dialogs_log -#define gaim_gtkdialogs_merge_groups pidgin_dialogs_merge_groups -#define gaim_gtkdialogs_remove_buddy pidgin_dialogs_remove_buddy -#define gaim_gtkdialogs_remove_chat pidgin_dialogs_remove_chat -#define gaim_gtkdialogs_remove_contact pidgin_dialogs_remove_contact -#define gaim_gtkdialogs_remove_group pidgin_dialogs_remove_group -#define gaim_gtk_docklet_clicked pidgin_docklet_clicked -#define gaim_gtk_docklet_embedded pidgin_docklet_embedded -#define gaim_gtk_docklet_get_handle pidgin_docklet_get_handle -#define gaim_gtk_docklet_init pidgin_docklet_init -#define gaim_gtk_docklet_remove pidgin_docklet_remove -#define gaim_gtk_docklet_set_ui_ops pidgin_docklet_set_ui_ops -#define gaim_gtk_docklet_uninit pidgin_docklet_uninit -#define gaim_gtk_docklet_unload pidgin_docklet_unload -#define gaim_gtk_eventloop_get_ui_ops pidgin_eventloop_get_ui_ops -#define gaim_gtk_idle_get_ui_ops pidgin_idle_get_ui_ops -#define GaimGtkImPane PidginImPane -#define gaim_gtk_load_accels pidgin_load_accels -#define gaim_gtk_log_get_handle pidgin_log_get_handle -#define gaim_gtk_log_init pidgin_log_init -#define gaim_gtk_log_show_contact pidgin_log_show_contact -#define gaim_gtk_log_show pidgin_log_show -#define gaim_gtk_log_uninit pidgin_log_uninit -#define GaimGtkLogViewer PidginLogViewer -#define gaim_gtk_make_frame pidgin_make_frame -#define gaim_gtk_make_mini_dialog pidgin_make_mini_dialog -#define gaim_gtk_make_pretty_arrows pidgin_make_pretty_arrows -#define gaim_gtk_menu_tray_append pidgin_menu_tray_append -#define GaimGtkMenuTrayClass PidginMenuTrayClass -#define gaim_gtk_menu_tray_get_box pidgin_menu_tray_get_box -#define gaim_gtk_menu_tray_get_gtype pidgin_menu_tray_get_gtype -#define gaim_gtk_menu_tray_new pidgin_menu_tray_new -#define GaimGtkMenuTray PidginMenuTray -#define GAIM_GTK_MENU_TRAY PIDGIN_MENU_TRAY -#define gaim_gtk_menu_tray_prepend pidgin_menu_tray_prepend -#define gaim_gtk_menu_tray_set_tooltip pidgin_menu_tray_set_tooltip -#define GAIM_GTK_MODIFY_ACCOUNT_DIALOG PIDGIN_MODIFY_ACCOUNT_DIALOG -#define gaim_gtk_notify_get_ui_ops pidgin_notify_get_ui_ops -#define gaim_gtk_parse_x_im_contact pidgin_parse_x_im_contact -#define gaim_gtk_plugin_dialog_show pidgin_plugin_dialog_show -#define gaim_gtk_plugin_get_config_frame pidgin_plugin_get_config_frame -#define GAIM_GTK_PLUGIN PIDGIN_PLUGIN -#define gaim_gtk_plugin_pref_create_frame pidgin_plugin_pref_create_frame -#define gaim_gtk_plugins_save pidgin_plugins_save -#define GAIM_GTK_PLUGIN_TYPE PIDGIN_PLUGIN_TYPE -#define GaimGtkPluginUiInfo PidginPluginUiInfo -#define GAIM_GTK_PLUGIN_UI_INFO PIDGIN_PLUGIN_UI_INFO -#define gaim_gtk_pounce_editor_show pidgin_pounce_editor_show -#define gaim_gtk_pounces_get_handle pidgin_pounces_get_handle -#define gaim_gtk_pounces_init pidgin_pounces_init -#define gaim_gtk_pounces_manager_hide pidgin_pounces_manager_hide -#define gaim_gtk_pounces_manager_show pidgin_pounces_manager_show -#define gaim_gtk_prefs_checkbox pidgin_prefs_checkbox -#define gaim_gtk_prefs_dropdown_from_list pidgin_prefs_dropdown_from_list -#define gaim_gtk_prefs_dropdown pidgin_prefs_dropdown -#define gaim_gtk_prefs_init pidgin_prefs_init -#define gaim_gtk_prefs_labeled_entry pidgin_prefs_labeled_entry -#define gaim_gtk_prefs_labeled_spin_button pidgin_prefs_labeled_spin_button -#define gaim_gtk_prefs_show pidgin_prefs_show -#define gaim_gtk_prefs_update_old pidgin_prefs_update_old -#define gaim_gtk_privacy_dialog_hide pidgin_privacy_dialog_hide -#define gaim_gtk_privacy_dialog_show pidgin_privacy_dialog_show -#define gaim_gtk_privacy_get_ui_ops pidgin_privacy_get_ui_ops -#define gaim_gtk_privacy_init pidgin_privacy_init -#define gaim_gtk_protocol_option_menu_new pidgin_protocol_option_menu_new -#define gaim_gtk_request_add_block pidgin_request_add_block -#define gaim_gtk_request_add_permit pidgin_request_add_permit -#define gaim_gtk_request_get_ui_ops pidgin_request_get_ui_ops -#define gaim_gtk_roomlist_dialog_show pidgin_roomlist_dialog_show -#define gaim_gtk_roomlist_dialog_show_with_account pidgin_roomlist_dialog_show_with_account -#define gaim_gtk_roomlist_init pidgin_roomlist_init -#define gaim_gtk_roomlist_is_showable pidgin_roomlist_is_showable -#define gaim_gtk_save_accels_cb pidgin_save_accels_cb -#define gaim_gtk_save_accels pidgin_save_accels -#define gaim_gtk_session_end pidgin_session_end -#define gaim_gtk_session_init pidgin_session_init -#define gaim_gtk_set_cursor pidgin_set_cursor -#define gaim_gtk_set_custom_buddy_icon pidgin_set_custom_buddy_icon -#define gaim_gtk_set_sensitive_if_input pidgin_set_sensitive_if_input -#define gaim_gtk_setup_gtkspell pidgin_setup_gtkspell -#define gaim_gtk_setup_screenname_autocomplete pidgin_setup_screenname_autocomplete -#define gaim_gtk_set_urgent pidgin_set_urgent -#define gaim_gtk_sound_get_event_label pidgin_sound_get_event_label -#define gaim_gtk_sound_get_event_option pidgin_sound_get_event_option -#define gaim_gtk_sound_get_handle pidgin_sound_get_handle -#define gaim_gtk_sound_get_ui_ops pidgin_sound_get_ui_ops -#define gaim_gtk_status_editor_show pidgin_status_editor_show -#define gaim_gtk_status_get_handle pidgin_status_get_handle -#define gaim_gtk_status_init pidgin_status_init -#define gaim_gtk_status_menu pidgin_status_menu -#define gaim_gtk_status_uninit pidgin_status_uninit -#define gaim_gtk_status_window_hide pidgin_status_window_hide -#define gaim_gtk_status_window_show pidgin_status_window_show -#define gaim_gtk_stock_init pidgin_stock_init -#define gaim_gtk_syslog_show pidgin_syslog_show -#define gaim_gtkthemes_get_proto_smileys pidgin_themes_get_proto_smileys -#define gaim_gtkthemes_init pidgin_themes_init -#define gaim_gtkthemes_load_smiley_theme pidgin_themes_load_smiley_theme -#define gaim_gtkthemes_smileys_disabled pidgin_themes_smileys_disabled -#define gaim_gtkthemes_smiley_themeize pidgin_themes_smiley_themeize -#define gaim_gtkthemes_smiley_theme_probe pidgin_themes_smiley_theme_probe -#define gaim_gtk_toggle_sensitive_array pidgin_toggle_sensitive_array -#define gaim_gtk_toggle_sensitive pidgin_toggle_sensitive -#define gaim_gtk_toggle_showhide pidgin_toggle_showhide -#define gaim_gtk_treeview_popup_menu_position_func pidgin_treeview_popup_menu_position_func -#define gaim_gtk_tree_view_search_equal_func pidgin_tree_view_search_equal_func -#define GAIM_GTK_TYPE_MENU_TRAY PIDGIN_TYPE_MENU_TRAY -#define GAIM_GTK_UI PIDGIN_UI -#define gaim_gtk_whiteboard_get_ui_ops pidgin_whiteboard_get_ui_ops -#define GaimGtkWhiteboard PidginWhiteboard -#define GaimGtkWindow PidginWindow -#define gaim_gtkxfer_dialog_add_xfer pidgin_xfer_dialog_add_xfer -#define gaim_gtkxfer_dialog_cancel_xfer pidgin_xfer_dialog_cancel_xfer -#define gaim_gtkxfer_dialog_destroy pidgin_xfer_dialog_destroy -#define gaim_gtkxfer_dialog_hide pidgin_xfer_dialog_hide -#define gaim_gtkxfer_dialog_new pidgin_xfer_dialog_new -#define GaimGtkXferDialog PidginXferDialog -#define gaim_gtkxfer_dialog_remove_xfer pidgin_xfer_dialog_remove_xfer -#define gaim_gtkxfer_dialog_show pidgin_xfer_dialog_show -#define gaim_gtkxfer_dialog_update_xfer pidgin_xfer_dialog_update_xfer -#define gaim_gtk_xfers_get_ui_ops pidgin_xfers_get_ui_ops -#define gaim_gtk_xfers_init pidgin_xfers_init -#define gaim_gtk_xfers_uninit pidgin_xfers_uninit -#define GAIM_HIG_BORDER PIDGIN_HIG_BORDER -#define GAIM_HIG_BOX_SPACE PIDGIN_HIG_BOX_SPACE -#define GAIM_HIG_CAT_SPACE PIDGIN_HIG_CAT_SPACE -#if !GTK_CHECK_VERSION(2,16,0) -#define GAIM_INVISIBLE_CHAR PIDGIN_INVISIBLE_CHAR -#endif /* Less than GTK+ 2.16 */ -#define GAIM_IS_GTK_CONVERSATION PIDGIN_IS_PIDGIN_CONVERSATION -#define GAIM_IS_GTK_PLUGIN PIDGIN_IS_PIDGIN_PLUGIN -#define gaim_new_check_item pidgin_new_check_item -#define gaim_new_item_from_stock pidgin_new_item_from_stock -#define gaim_new_item pidgin_new_item -#define gaim_pixbuf_button_from_stock pidgin_pixbuf_button_from_stock -#define gaim_pixbuf_toolbar_button_from_stock pidgin_pixbuf_toolbar_button_from_stock -#define GaimScrollBookClass PidginScrollBookClass -#define gaim_scroll_book_get_type pidgin_scroll_book_get_type -#define gaim_scroll_book_new pidgin_scroll_book_new -#define GaimScrollBook PidginScrollBook -#define gaim_separator pidgin_separator -#define gaim_set_accessible_label pidgin_set_accessible_label -#define gaim_set_gtkxfer_dialog pidgin_set_xfer_dialog -#define gaim_setup_imhtml pidgin_setup_imhtml -#define gaim_status_box_add pidgin_status_box_add -#define gaim_status_box_add_separator pidgin_status_box_add_separator -#define GaimStatusBoxClass PidginStatusBoxClass -#define gaim_status_box_get_buddy_icon pidgin_status_box_get_buddy_icon -#define gaim_status_box_get_message pidgin_status_box_get_message -#define gaim_status_box_get_type pidgin_status_box_get_type -#define GaimStatusBoxItemType PidginStatusBoxItemType -#define gaim_status_box_new pidgin_status_box_new -#define gaim_status_box_new_with_account pidgin_status_box_new_with_account -#define GaimStatusBox PidginStatusBox -#define gaim_status_box_pulse_connecting pidgin_status_box_pulse_connecting -#define gaim_status_box_set_buddy_icon pidgin_status_box_set_buddy_icon -#define gaim_status_box_set_connecting pidgin_status_box_set_connecting -#define gaim_status_box_set_network_available pidgin_status_box_set_network_available -#define GAIM_STATUS_ICON_LARGE PIDGIN_STATUS_ICON_LARGE -#define GaimStatusIconSize PidginStatusIconSize -#define GAIM_STATUS_ICON_SMALL PIDGIN_STATUS_ICON_SMALL -#define GAIM_STOCK_ABOUT PIDGIN_STOCK_ABOUT -#define GAIM_STOCK_ACTION PIDGIN_STOCK_ACTION -#define GAIM_STOCK_ALIAS PIDGIN_STOCK_ALIAS -#define GAIM_STOCK_AWAY PIDGIN_STOCK_AWAY -#define GAIM_STOCK_CHAT PIDGIN_STOCK_CHAT -#define GAIM_STOCK_CLEAR PIDGIN_STOCK_CLEAR -#define GAIM_STOCK_CLOSE_TABS PIDGIN_STOCK_CLOSE_TABS -#define GAIM_STOCK_DEBUG PIDGIN_STOCK_DEBUG -#define GAIM_STOCK_DIALOG_AUTH PIDGIN_STOCK_DIALOG_AUTH -#define GAIM_STOCK_DIALOG_COOL PIDGIN_STOCK_DIALOG_COOL -#define GAIM_STOCK_DIALOG_ERROR PIDGIN_STOCK_DIALOG_ERROR -#define GAIM_STOCK_DIALOG_INFO PIDGIN_STOCK_DIALOG_INFO -#define GAIM_STOCK_DIALOG_QUESTION PIDGIN_STOCK_DIALOG_QUESTION -#define GAIM_STOCK_DIALOG_WARNING PIDGIN_STOCK_DIALOG_WARNING -#define GAIM_STOCK_DISCONNECT PIDGIN_STOCK_DISCONNECT -#define GAIM_STOCK_DOWNLOAD PIDGIN_STOCK_DOWNLOAD -#define GAIM_STOCK_EDIT PIDGIN_STOCK_EDIT -#define GAIM_STOCK_FGCOLOR PIDGIN_STOCK_FGCOLOR -#define GAIM_STOCK_FILE_CANCELED PIDGIN_STOCK_FILE_CANCELED -#define GAIM_STOCK_FILE_DONE PIDGIN_STOCK_FILE_DONE -#define GAIM_STOCK_FILE_TRANSFER PIDGIN_STOCK_FILE_TRANSFER -#define GAIM_STOCK_IGNORE PIDGIN_STOCK_IGNORE -#define GAIM_STOCK_IM "gaim-im" /* foo... */ -#define GAIM_STOCK_INVITE PIDGIN_STOCK_INVITE -#define GAIM_STOCK_MODIFY PIDGIN_STOCK_MODIFY -#define GAIM_STOCK_OPEN_MAIL PIDGIN_STOCK_OPEN_MAIL -#define GAIM_STOCK_PAUSE PIDGIN_STOCK_PAUSE -#define GAIM_STOCK_POUNCE PIDGIN_STOCK_POUNCE -#define GAIM_STOCK_SIGN_OFF PIDGIN_STOCK_SIGN_OFF -#define GAIM_STOCK_SIGN_ON PIDGIN_STOCK_SIGN_ON -#define GAIM_STOCK_STATUS_OFFLINE PIDGIN_STOCK_STATUS_OFFLINE -#define GAIM_STOCK_TEXT_NORMAL PIDGIN_STOCK_TEXT_NORMAL -#define GAIM_STOCK_TYPED PIDGIN_STOCK_TYPED -#define GAIM_STOCK_UPLOAD PIDGIN_STOCK_UPLOAD -#define GAIM_TYPE_GTK_CELL_RENDERER_EXPANDER PIDGIN_TYPE_GTK_CELL_RENDERER_EXPANDER -#define GAIM_TYPE_GTK_CELL_RENDERER_PROGRESS PIDGIN_TYPE_GTK_CELL_RENDERER_PROGRESS -#define GAIM_UNSEEN_EVENT PIDGIN_UNSEEN_EVENT -#define GAIM_UNSEEN_NICK PIDGIN_UNSEEN_NICK -#define GAIM_UNSEEN_NO_LOG PIDGIN_UNSEEN_NO_LOG -#define GAIM_UNSEEN_NONE PIDGIN_UNSEEN_NONE -#define GaimUnseenState PidginUnseenState -#define GAIM_UNSEEN_TEXT PIDGIN_UNSEEN_TEXT -#define GAIM_WINDOW_ICONIFIED PIDGIN_WINDOW_ICONIFIED -#define GTK_GAIM_IS_SCROLL_BOOK_CLASS PIDGIN_IS_SCROLL_BOOK_CLASS -#define GTK_GAIM_IS_SCROLL_BOOK PIDGIN_IS_SCROLL_BOOK -#define GTK_GAIM_IS_STATUS_BOX_CLASS PIDGIN_IS_STATUS_BOX_CLASS -#define GTK_GAIM_IS_STATUS_BOX PIDGIN_IS_STATUS_BOX -#define GTK_GAIM_SCROLL_BOOK_CLASS PIDGIN_SCROLL_BOOK_CLASS -#define GTK_GAIM_SCROLL_BOOK_GET_CLASS PIDGIN_SCROLL_BOOK_GET_CLASS -#define gtk_gaim_scroll_book_get_type pidgin_scroll_book_get_type -#define gtk_gaim_scroll_book_new pidgin_scroll_book_new -#define GTK_GAIM_SCROLL_BOOK PIDGIN_SCROLL_BOOK -#define gtk_gaim_status_box_add pidgin_status_box_add -#define gtk_gaim_status_box_add_separator pidgin_status_box_add_separator -#define GTK_GAIM_STATUS_BOX_CLASS PIDGIN_STATUS_BOX_CLASS -#define gtk_gaim_status_box_get_buddy_icon pidgin_status_box_get_buddy_icon -#define GTK_GAIM_STATUS_BOX_GET_CLASS PIDGIN_STATUS_BOX_GET_CLASS -#define gtk_gaim_status_box_get_message pidgin_status_box_get_message -#define gtk_gaim_status_box_get_type pidgin_status_box_get_type -#define GtkGaimStatusBoxItemType PidginStatusBoxItemType -#define gtk_gaim_status_box_new pidgin_status_box_new -#define gtk_gaim_status_box_new_with_account pidgin_status_box_new_with_account -#define GTK_GAIM_STATUS_BOX_NUM_TYPES PIDGIN_STATUS_BOX_NUM_TYPES -#define GtkGaimStatusBox PidginStatusBox -#define GTK_GAIM_STATUS_BOX PIDGIN_STATUS_BOX -#define gtk_gaim_status_box_pulse_connecting pidgin_status_box_pulse_connecting -#define gtk_gaim_status_box_set_buddy_icon pidgin_status_box_set_buddy_icon -#define gtk_gaim_status_box_set_connecting pidgin_status_box_set_connecting -#define gtk_gaim_status_box_set_network_available pidgin_status_box_set_network_available -#define GTK_GAIM_STATUS_BOX_TYPE_CUSTOM PIDGIN_STATUS_BOX_TYPE_CUSTOM -#define GTK_GAIM_STATUS_BOX_TYPE_POPULAR PIDGIN_STATUS_BOX_TYPE_POPULAR -#define GTK_GAIM_STATUS_BOX_TYPE_PRIMITIVE PIDGIN_STATUS_BOX_TYPE_PRIMITIVE -#define GTK_GAIM_STATUS_BOX_TYPE_SAVED PIDGIN_STATUS_BOX_TYPE_SAVED -#define GTK_GAIM_STATUS_BOX_TYPE_SEPARATOR PIDGIN_STATUS_BOX_TYPE_SEPARATOR -#define GTK_GAIM_TYPE_SCROLL_BOOK PIDGIN_TYPE_SCROLL_BOOK -#define GTK_GAIM_TYPE_STATUS_BOX PIDGIN_TYPE_STATUS_BOX - -#endif /* _GTKGAIM_COMPAT_H */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkicon-theme-loader.c --- a/pidgin/gtkicon-theme-loader.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkicon-theme-loader.c Fri Apr 06 04:30:00 2012 +0000 @@ -31,23 +31,26 @@ *****************************************************************************/ static PurpleTheme * -pidgin_icon_loader_build(const gchar *dir) +pidgin_icon_loader_build(const gchar *theme_dir) { xmlnode *root_node = NULL, *sub_node; - gchar *filename_full, *data = NULL; + gchar *dir, *filename_full, *data = NULL; PidginIconTheme *theme = NULL; const gchar *name; /* Find the theme file */ - g_return_val_if_fail(dir != NULL, NULL); + g_return_val_if_fail(theme_dir != NULL, NULL); + dir = g_build_filename(theme_dir, "purple", "status-icon", NULL); filename_full = g_build_filename(dir, "theme.xml", NULL); if (g_file_test(filename_full, G_FILE_TEST_IS_REGULAR)) root_node = xmlnode_from_file(dir, "theme.xml", "icon themes", "icon-theme-loader"); g_free(filename_full); - if (root_node == NULL) + if (root_node == NULL) { + g_free(dir); return NULL; + } name = xmlnode_get_attrib(root_node, "name"); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkicon-theme.c --- a/pidgin/gtkicon-theme.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkicon-theme.c Fri Apr 06 04:30:00 2012 +0000 @@ -26,7 +26,7 @@ #include #define PIDGIN_ICON_THEME_GET_PRIVATE(Gobject) \ - ((PidginIconThemePrivate *) ((PIDGIN_ICON_THEME(Gobject))->priv)) + (G_TYPE_INSTANCE_GET_PRIVATE((Gobject), PIDGIN_TYPE_ICON_THEME, PidginIconThemePrivate)) /****************************************************************************** * Structs @@ -53,8 +53,6 @@ { PidginIconThemePrivate *priv; - (PIDGIN_ICON_THEME(instance))->priv = g_new0(PidginIconThemePrivate, 1); - priv = PIDGIN_ICON_THEME_GET_PRIVATE(instance); priv->icon_files = g_hash_table_new_full(g_str_hash, @@ -69,7 +67,6 @@ priv = PIDGIN_ICON_THEME_GET_PRIVATE(obj); g_hash_table_destroy(priv->icon_files); - g_free(priv); parent_class->finalize(obj); } @@ -82,6 +79,8 @@ parent_class = g_type_class_peek_parent(klass); obj_class->finalize = pidgin_icon_theme_finalize; + + g_type_class_add_private(klass, sizeof(PidginIconThemePrivate)); } GType diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkicon-theme.h --- a/pidgin/gtkicon-theme.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkicon-theme.h Fri Apr 06 04:30:00 2012 +0000 @@ -50,7 +50,6 @@ struct _PidginIconTheme { PurpleTheme parent; - gpointer priv; }; struct _PidginIconThemeClass diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkidle.c --- a/pidgin/gtkidle.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkidle.c Fri Apr 06 04:30:00 2012 +0000 @@ -107,14 +107,16 @@ int event_base, error_base; if (has_extension == -1) - has_extension = XScreenSaverQueryExtension(GDK_DISPLAY(), &event_base, &error_base); + has_extension = XScreenSaverQueryExtension(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), + &event_base, &error_base); if (has_extension) { if (mit_info == NULL) mit_info = XScreenSaverAllocInfo(); - XScreenSaverQueryInfo(GDK_DISPLAY(), GDK_ROOT_WINDOW(), mit_info); + XScreenSaverQueryInfo(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), + GDK_ROOT_WINDOW(), mit_info); return (mit_info->idle) / 1000; } else diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkidle.h --- a/pidgin/gtkidle.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkidle.h Fri Apr 06 04:30:00 2012 +0000 @@ -28,6 +28,8 @@ #include "idle.h" +G_BEGIN_DECLS + /**************************************************************************/ /** @name GTK+ Idle API */ /**************************************************************************/ @@ -42,4 +44,6 @@ /*@}*/ +G_END_DECLS + #endif /* _PIDGIN_IDLE_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkimhtml.c --- a/pidgin/gtkimhtml.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkimhtml.c Fri Apr 06 04:30:00 2012 +0000 @@ -65,6 +65,16 @@ #define TOOLTIP_TIMEOUT 500 +#if !GTK_CHECK_VERSION(2,20,0) +#define gtk_widget_get_realized(x) GTK_WIDGET_REALIZED(x) + +#if !GTK_CHECK_VERSION(2,18,0) +#define gtk_widget_get_has_window(x) !GTK_WIDGET_NO_WINDOW(x) +#define gtk_widget_get_state(x) GTK_WIDGET_STATE(x) +#define gtk_widget_is_drawable(x) GTK_WIDGET_DRAWABLE(x) +#endif +#endif + static GtkTextViewClass *parent_class = NULL; struct scalable_data { @@ -83,6 +93,36 @@ GtkTextMark *mark; }; +struct _GtkIMHtmlScalable { + void (*scale)(struct _GtkIMHtmlScalable *, int, int); + void (*add_to)(struct _GtkIMHtmlScalable *, GtkIMHtml *, GtkTextIter *); + void (*free)(struct _GtkIMHtmlScalable *); +}; + +struct _GtkIMHtmlHr { + GtkIMHtmlScalable scalable; + GtkWidget *sep; +}; + +struct _GtkIMHtmlImage { + GtkIMHtmlScalable scalable; + GtkImage *image; /**< Contains the scaled version of this pixbuf. */ + GdkPixbuf *pixbuf; /**< The original pixbuf, before any scaling. */ + GtkTextMark *mark; + gchar *filename; + int width; + int height; + int id; + GtkWidget *filesel; +}; + +struct _GtkIMHtmlAnimation { + GtkIMHtmlImage imhtmlimage; + GdkPixbufAnimation *anim; /**< The original animation, before any scaling. */ + GdkPixbufAnimationIter *iter; + guint timer; +}; + struct _GtkIMHtmlLink { GtkIMHtml *imhtml; @@ -90,8 +130,13 @@ GtkTextTag *tag; }; -typedef struct _GtkIMHtmlProtocol -{ +struct _GtkSmileyTree { + GString *values; + GtkSmileyTree **children; + GtkIMHtmlSmiley *image; +}; + +typedef struct { char *name; int length; @@ -99,7 +144,8 @@ gboolean (*context_menu)(GtkIMHtml *imhtml, GtkIMHtmlLink *link, GtkWidget *menu); } GtkIMHtmlProtocol; -typedef struct _GtkIMHtmlFontDetail { +/* The five elements contained in a FONT tag */ +typedef struct { gushort size; gchar *face; gchar *fore; @@ -422,7 +468,7 @@ /* Don't scroll here if we're in the middle of a smooth scroll */ if (scroll && imhtml->scroll_time == NULL && - GTK_WIDGET_REALIZED(imhtml)) + gtk_widget_get_realized(GTK_WIDGET(imhtml))) gtk_imhtml_scroll_to_end(imhtml, FALSE); } @@ -539,7 +585,7 @@ g_return_val_if_fail(GTK_IS_IMHTML(imhtml), FALSE); - if (!imhtml->tip || !GTK_WIDGET_DRAWABLE (GTK_WIDGET(imhtml))) { + if (!imhtml->tip || !gtk_widget_is_drawable (GTK_WIDGET(imhtml))) { imhtml->tip_timer = 0; return FALSE; } @@ -592,7 +638,7 @@ h = 8 + baseline_skip; gdk_window_get_pointer (NULL, &x, &y, NULL); - if (GTK_WIDGET_NO_WINDOW (GTK_WIDGET(imhtml))) + if (!gtk_widget_get_has_window (GTK_WIDGET(imhtml))) y += GTK_WIDGET(imhtml)->allocation.y; scr_w = gdk_screen_width(); @@ -788,7 +834,7 @@ gdk_color_parse(GTK_IMHTML(widget)->edit.background, &gcolor); gdk_cairo_set_source_color(cr, &gcolor); } else { - gdk_cairo_set_source_color(cr, &(widget->style->base[GTK_WIDGET_STATE(widget)])); + gdk_cairo_set_source_color(cr, &(widget->style->base[gtk_widget_get_state(widget)])); } cairo_rectangle(cr, @@ -3593,125 +3639,38 @@ gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &iter, 0, TRUE, 0, 0); } -/* GtkIMHtmlScalable, gtk_imhtml_image, gtk_imhtml_hr */ -GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id) -{ - GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); - - GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; - GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; - GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free; - - im_image->pixbuf = img; - im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf)); - im_image->width = gdk_pixbuf_get_width(img); - im_image->height = gdk_pixbuf_get_height(img); - im_image->mark = NULL; - im_image->filename = g_strdup(filename); - im_image->id = id; - im_image->filesel = NULL; - - g_object_ref(img); - return GTK_IMHTML_SCALABLE(im_image); -} - -static gboolean -animate_image_cb(gpointer data) -{ - GtkIMHtmlImage *im_image; - int width, height; - int delay; - - im_image = data; - - /* Update the pointer to this GdkPixbuf frame of the animation */ - if (gdk_pixbuf_animation_iter_advance(GTK_IMHTML_ANIMATION(im_image)->iter, NULL)) { - GdkPixbuf *pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter); - g_object_unref(G_OBJECT(im_image->pixbuf)); - im_image->pixbuf = gdk_pixbuf_copy(pb); - - /* Update the displayed GtkImage */ - width = gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image)); - height = gdk_pixbuf_get_height(gtk_image_get_pixbuf(im_image->image)); - if (width > 0 && height > 0) - { - /* Need to scale the new frame to the same size as the old frame */ - GdkPixbuf *tmp; - tmp = gdk_pixbuf_scale_simple(im_image->pixbuf, width, height, GDK_INTERP_BILINEAR); - gtk_image_set_from_pixbuf(im_image->image, tmp); - g_object_unref(G_OBJECT(tmp)); - } else { - /* Display at full-size */ - gtk_image_set_from_pixbuf(im_image->image, im_image->pixbuf); - } - } - - delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100); - GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image); - - return FALSE; -} - -GtkIMHtmlScalable *gtk_imhtml_animation_new(GdkPixbufAnimation *anim, const gchar *filename, int id) -{ - GtkIMHtmlImage *im_image = (GtkIMHtmlImage *) g_new0(GtkIMHtmlAnimation, 1); - - GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; - GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; - GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_animation_free; - - GTK_IMHTML_ANIMATION(im_image)->anim = anim; - if (gdk_pixbuf_animation_is_static_image(anim)) { - im_image->pixbuf = gdk_pixbuf_animation_get_static_image(anim); - g_object_ref(im_image->pixbuf); - } else { - int delay; - GdkPixbuf *pb; - GTK_IMHTML_ANIMATION(im_image)->iter = gdk_pixbuf_animation_get_iter(anim, NULL); - pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter); - im_image->pixbuf = gdk_pixbuf_copy(pb); - delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100); - GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image); - } - im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf)); - im_image->width = gdk_pixbuf_animation_get_width(anim); - im_image->height = gdk_pixbuf_animation_get_height(anim); - im_image->filename = g_strdup(filename); - im_image->id = id; - - g_object_ref(anim); - - return GTK_IMHTML_SCALABLE(im_image); -} - -void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height) -{ - GtkIMHtmlImage *im_image = (GtkIMHtmlImage *)scale; - - if (im_image->width > width || im_image->height > height) { - double ratio_w, ratio_h, ratio; - int new_h, new_w; - GdkPixbuf *new_image = NULL; - - ratio_w = ((double)width - 2) / im_image->width; - ratio_h = ((double)height - 2) / im_image->height; - - ratio = (ratio_w < ratio_h) ? ratio_w : ratio_h; - - new_w = (int)(im_image->width * ratio); - new_h = (int)(im_image->height * ratio); - - new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, new_w, new_h, GDK_INTERP_BILINEAR); - gtk_image_set_from_pixbuf(im_image->image, new_image); - g_object_unref(G_OBJECT(new_image)); - } else if (gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image)) != im_image->width) { - /* Enough space to show the full-size of the image. */ - GdkPixbuf *new_image; - - new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, im_image->width, im_image->height, GDK_INTERP_BILINEAR); - gtk_image_set_from_pixbuf(im_image->image, new_image); - g_object_unref(G_OBJECT(new_image)); - } +/** + * Destroys and frees a GTK+ IM/HTML scalable image. + * + * @param scale The GTK+ IM/HTML scalable. + */ +static void gtk_imhtml_image_free(GtkIMHtmlScalable *scale) +{ + GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; + + g_object_unref(image->pixbuf); + g_free(image->filename); + if (image->filesel) + gtk_widget_destroy(image->filesel); + g_free(scale); +} + +/** + * Destroys and frees a GTK+ IM/HTML scalable animation. + * + * @param scale The GTK+ IM/HTML scalable. + */ +static void gtk_imhtml_animation_free(GtkIMHtmlScalable *scale) +{ + GtkIMHtmlAnimation *animation = (GtkIMHtmlAnimation *)scale; + + if (animation->timer > 0) + g_source_remove(animation->timer); + if (animation->iter != NULL) + g_object_unref(animation->iter); + g_object_unref(animation->anim); + + gtk_imhtml_image_free(scale); } static void @@ -3918,55 +3877,51 @@ } -static gboolean gtk_imhtml_smiley_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlSmiley *smiley) -{ - GdkPixbufAnimation *anim = NULL; - GtkIMHtmlImageSave *save = NULL; - gboolean ret; - - if (event->type != GDK_BUTTON_RELEASE || ((GdkEventButton*)event)->button != 3) - return FALSE; - - anim = gtk_smiley_get_image(smiley); - if (!anim) - return FALSE; - - save = g_new0(GtkIMHtmlImageSave, 1); - save->image = (GtkIMHtmlScalable *)gtk_imhtml_animation_new(anim, smiley->smile, 0); - save->data = smiley->data; /* Do not need to memdup here, since the smiley is not - destroyed before this GtkIMHtmlImageSave */ - save->datasize = smiley->datasize; - ret = gtk_imhtml_image_clicked(w, event, save); - g_object_set_data_full(G_OBJECT(w), "image-data", save->image, (GDestroyNotify)gtk_imhtml_animation_free); - g_object_set_data_full(G_OBJECT(w), "image-save-data", save, (GDestroyNotify)g_free); - return ret; -} - -void gtk_imhtml_image_free(GtkIMHtmlScalable *scale) -{ - GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; - - g_object_unref(image->pixbuf); - g_free(image->filename); - if (image->filesel) - gtk_widget_destroy(image->filesel); - g_free(scale); -} - -void gtk_imhtml_animation_free(GtkIMHtmlScalable *scale) -{ - GtkIMHtmlAnimation *animation = (GtkIMHtmlAnimation *)scale; - - if (animation->timer > 0) - g_source_remove(animation->timer); - if (animation->iter != NULL) - g_object_unref(animation->iter); - g_object_unref(animation->anim); - - gtk_imhtml_image_free(scale); -} - -void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) +/** + * Rescales a GTK+ IM/HTML scalable image to a given size. + * + * @param scale The GTK+ IM/HTML scalable. + * @param width The new width. + * @param height The new height. + */ +static void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height) +{ + GtkIMHtmlImage *im_image = (GtkIMHtmlImage *)scale; + + if (im_image->width > width || im_image->height > height) { + double ratio_w, ratio_h, ratio; + int new_h, new_w; + GdkPixbuf *new_image = NULL; + + ratio_w = ((double)width - 2) / im_image->width; + ratio_h = ((double)height - 2) / im_image->height; + + ratio = (ratio_w < ratio_h) ? ratio_w : ratio_h; + + new_w = (int)(im_image->width * ratio); + new_h = (int)(im_image->height * ratio); + + new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, new_w, new_h, GDK_INTERP_BILINEAR); + gtk_image_set_from_pixbuf(im_image->image, new_image); + g_object_unref(G_OBJECT(new_image)); + } else if (gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image)) != im_image->width) { + /* Enough space to show the full-size of the image. */ + GdkPixbuf *new_image; + + new_image = gdk_pixbuf_scale_simple(im_image->pixbuf, im_image->width, im_image->height, GDK_INTERP_BILINEAR); + gtk_image_set_from_pixbuf(im_image->image, new_image); + g_object_unref(G_OBJECT(new_image)); + } +} + +/** + * Adds a GTK+ IM/HTML scalable image to a given GTK+ IM/HTML at a given iter. + * + * @param scale The GTK+ IM/HTML scalable. + * @param imhtml The GTK+ IM/HTML. + * @param iter The GtkTextIter at which to add the scalable. + */ +static void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter) { GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale; GtkWidget *box = gtk_event_box_new(); @@ -3994,6 +3949,121 @@ g_object_set_data_full(G_OBJECT(box), "image-save-data", save, (GDestroyNotify)g_free); } +/** + * Creates and returns a new GTK+ IM/HTML scalable object with an image. + * + * @param img A GdkPixbuf of the image to add. + * @param filename The filename to associate with the image. + * @param id The id to associate with the image. + * + * @return A new IM/HTML Scalable object with an image. + */ +static GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id) +{ + GtkIMHtmlImage *im_image = g_malloc(sizeof(GtkIMHtmlImage)); + + GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; + GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; + GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_image_free; + + im_image->pixbuf = img; + im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf)); + im_image->width = gdk_pixbuf_get_width(img); + im_image->height = gdk_pixbuf_get_height(img); + im_image->mark = NULL; + im_image->filename = g_strdup(filename); + im_image->id = id; + im_image->filesel = NULL; + + g_object_ref(img); + return GTK_IMHTML_SCALABLE(im_image); +} + +static gboolean +animate_image_cb(gpointer data) +{ + GtkIMHtmlImage *im_image; + int width, height; + int delay; + + im_image = data; + + /* Update the pointer to this GdkPixbuf frame of the animation */ + if (gdk_pixbuf_animation_iter_advance(GTK_IMHTML_ANIMATION(im_image)->iter, NULL)) { + GdkPixbuf *pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter); + g_object_unref(G_OBJECT(im_image->pixbuf)); + im_image->pixbuf = gdk_pixbuf_copy(pb); + + /* Update the displayed GtkImage */ + width = gdk_pixbuf_get_width(gtk_image_get_pixbuf(im_image->image)); + height = gdk_pixbuf_get_height(gtk_image_get_pixbuf(im_image->image)); + if (width > 0 && height > 0) + { + /* Need to scale the new frame to the same size as the old frame */ + GdkPixbuf *tmp; + tmp = gdk_pixbuf_scale_simple(im_image->pixbuf, width, height, GDK_INTERP_BILINEAR); + gtk_image_set_from_pixbuf(im_image->image, tmp); + g_object_unref(G_OBJECT(tmp)); + } else { + /* Display at full-size */ + gtk_image_set_from_pixbuf(im_image->image, im_image->pixbuf); + } + } + + delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100); + GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image); + + return FALSE; +} + +/** + * Creates and returns a new GTK+ IM/HTML scalable object with an + * animated image. + * + * @param img A GdkPixbufAnimation of the image to add. + * @param filename The filename to associate with the image. + * @param id The id to associate with the image. + * + * @return A new IM/HTML Scalable object with an image. + */ +/* + * TODO: All this animation code could be combined much better with + * the image code. It couldn't be done when it was written + * because it requires breaking backward compatibility. It + * would be good to do it for 3.0.0. + */ +static GtkIMHtmlScalable *gtk_imhtml_animation_new(GdkPixbufAnimation *anim, const gchar *filename, int id) +{ + GtkIMHtmlImage *im_image = (GtkIMHtmlImage *) g_new0(GtkIMHtmlAnimation, 1); + + GTK_IMHTML_SCALABLE(im_image)->scale = gtk_imhtml_image_scale; + GTK_IMHTML_SCALABLE(im_image)->add_to = gtk_imhtml_image_add_to; + GTK_IMHTML_SCALABLE(im_image)->free = gtk_imhtml_animation_free; + + GTK_IMHTML_ANIMATION(im_image)->anim = anim; + if (gdk_pixbuf_animation_is_static_image(anim)) { + im_image->pixbuf = gdk_pixbuf_animation_get_static_image(anim); + g_object_ref(im_image->pixbuf); + } else { + int delay; + GdkPixbuf *pb; + GTK_IMHTML_ANIMATION(im_image)->iter = gdk_pixbuf_animation_get_iter(anim, NULL); + pb = gdk_pixbuf_animation_iter_get_pixbuf(GTK_IMHTML_ANIMATION(im_image)->iter); + im_image->pixbuf = gdk_pixbuf_copy(pb); + delay = MIN(gdk_pixbuf_animation_iter_get_delay_time(GTK_IMHTML_ANIMATION(im_image)->iter), 100); + GTK_IMHTML_ANIMATION(im_image)->timer = g_timeout_add(delay, animate_image_cb, im_image); + } + im_image->image = GTK_IMAGE(gtk_image_new_from_pixbuf(im_image->pixbuf)); + im_image->width = gdk_pixbuf_animation_get_width(anim); + im_image->height = gdk_pixbuf_animation_get_height(anim); + im_image->filename = g_strdup(filename); + im_image->id = id; + + g_object_ref(anim); + + return GTK_IMHTML_SCALABLE(im_image); +} + GtkIMHtmlScalable *gtk_imhtml_hr_new() { GtkIMHtmlHr *hr = g_malloc(sizeof(GtkIMHtmlHr)); @@ -4918,6 +4988,30 @@ } } +static gboolean gtk_imhtml_smiley_clicked(GtkWidget *w, GdkEvent *event, GtkIMHtmlSmiley *smiley) +{ + GdkPixbufAnimation *anim = NULL; + GtkIMHtmlImageSave *save = NULL; + gboolean ret; + + if (event->type != GDK_BUTTON_RELEASE || ((GdkEventButton*)event)->button != 3) + return FALSE; + + anim = gtk_smiley_get_image(smiley); + if (!anim) + return FALSE; + + save = g_new0(GtkIMHtmlImageSave, 1); + save->image = (GtkIMHtmlScalable *)gtk_imhtml_animation_new(anim, smiley->smile, 0); + save->data = smiley->data; /* Do not need to memdup here, since the smiley is not + destroyed before this GtkIMHtmlImageSave */ + save->datasize = smiley->datasize; + ret = gtk_imhtml_image_clicked(w, event, save); + g_object_set_data_full(G_OBJECT(w), "image-data", save->image, (GDestroyNotify)gtk_imhtml_animation_free); + g_object_set_data_full(G_OBJECT(w), "image-save-data", save, (GDestroyNotify)g_free); + return ret; +} + void gtk_imhtml_insert_smiley_at_iter(GtkIMHtml *imhtml, const char *sml, char *smiley, GtkTextIter *iter) { GdkPixbuf *pixbuf = NULL; @@ -5367,9 +5461,9 @@ tag = sl->data; /** don't worry about non-printing tags ending */ if (tag_ends_here(tag, &iter, &next_iter) && - strlen(tag_to_html_end(tag)) > 0 && - strlen(tag_to_html_start(tag)) > 0) { - + *tag_to_html_end(tag) && + *tag_to_html_start(tag)) + { PidginTextTagData *tmp; GQueue *r = g_queue_new(); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkimhtml.h --- a/pidgin/gtkimhtml.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkimhtml.h Fri Apr 06 04:30:00 2012 +0000 @@ -31,9 +31,7 @@ #include "connection.h" -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /************************************************************************** * @name Structures @@ -50,9 +48,6 @@ typedef struct _GtkIMHtml GtkIMHtml; typedef struct _GtkIMHtmlClass GtkIMHtmlClass; -#if !(defined PIDGIN_DISABLE_DEPRECATED) && !(defined _PIDGIN_GTKIMHTML_C_) -typedef struct _GtkIMHtmlFontDetail GtkIMHtmlFontDetail; /* The five elements contained in a FONT tag */ -#endif typedef struct _GtkSmileyTree GtkSmileyTree; typedef struct _GtkIMHtmlSmiley GtkIMHtmlSmiley; typedef struct _GtkIMHtmlScalable GtkIMHtmlScalable; @@ -61,9 +56,6 @@ typedef struct _GtkIMHtmlHr GtkIMHtmlHr; typedef struct _GtkIMHtmlFuncs GtkIMHtmlFuncs; -/** - * @since 2.6.0 - */ typedef struct _GtkIMHtmlLink GtkIMHtmlLink; typedef enum { @@ -81,7 +73,7 @@ GTK_IMHTML_SMILEY = 1 << 11, GTK_IMHTML_LINKDESC = 1 << 12, GTK_IMHTML_STRIKE = 1 << 13, - /** Show custom smileys when appropriate. @since 2.5.0 */ + /** Show custom smileys when appropriate. */ GTK_IMHTML_CUSTOM_SMILEY = 1 << 14, GTK_IMHTML_ALL = -1 } GtkIMHtmlButtons; @@ -135,16 +127,6 @@ GtkTextTag *link; } edit; -#if !(defined PIDGIN_DISABLE_DEPRECATED) || (defined _PIDGIN_GTKIMHTML_C_) - /** @deprecated */ - char *clipboard_text_string; - /** @deprecated */ - char *clipboard_html_string; -#else - char *depr1; - char *depr2; -#endif - GSList *im_images; GtkIMHtmlFuncs *funcs; GtkSourceUndoManager *undo_manager; @@ -164,26 +146,6 @@ GList *protocols; /* List of GtkIMHtmlProtocol's */ }; -#if !(defined PIDGIN_DISABLE_DEPRECATED) && !(defined _PIDGIN_GTKIMHTML_C_) -/** @deprecated as of 2.7.10 */ -struct _GtkIMHtmlFontDetail { - gushort size; - gchar *face; - gchar *fore; - gchar *back; - gchar *bg; - gchar *sml; - gboolean underline; - gshort bold; -}; -#endif - -struct _GtkSmileyTree { - GString *values; - GtkSmileyTree **children; - GtkIMHtmlSmiley *image; -}; - struct _GtkIMHtmlSmiley { gchar *smile; gchar *file; @@ -193,38 +155,8 @@ GSList *anchors; GtkIMHtmlSmileyFlags flags; GtkIMHtml *imhtml; - gpointer data; /** @since 2.6.0 */ - gsize datasize; /** @since 2.6.0 */ -}; - -struct _GtkIMHtmlScalable { - void (*scale)(struct _GtkIMHtmlScalable *, int, int); - void (*add_to)(struct _GtkIMHtmlScalable *, GtkIMHtml *, GtkTextIter *); - void (*free)(struct _GtkIMHtmlScalable *); -}; - -struct _GtkIMHtmlImage { - GtkIMHtmlScalable scalable; - GtkImage *image; /**< Contains the scaled version of this pixbuf. */ - GdkPixbuf *pixbuf; /**< The original pixbuf, before any scaling. */ - GtkTextMark *mark; - gchar *filename; - int width; - int height; - int id; - GtkWidget *filesel; -}; - -struct _GtkIMHtmlAnimation { - GtkIMHtmlImage imhtmlimage; - GdkPixbufAnimation *anim; /**< The original animation, before any scaling. */ - GdkPixbufAnimationIter *iter; - guint timer; -}; - -struct _GtkIMHtmlHr { - GtkIMHtmlScalable scalable; - GtkWidget *sep; + gpointer data; + gsize datasize; }; typedef enum { @@ -443,73 +375,6 @@ GtkIMHtmlScalable *gtk_imhtml_scalable_new(void); /** - * Creates and returns a new GTK+ IM/HTML scalable object with an image. - * - * @param img A GdkPixbuf of the image to add. - * @param filename The filename to associate with the image. - * @param id The id to associate with the image. - * - * @return A new IM/HTML Scalable object with an image. - */ -GtkIMHtmlScalable *gtk_imhtml_image_new(GdkPixbuf *img, const gchar *filename, int id); - -/** - * Creates and returns a new GTK+ IM/HTML scalable object with an - * animated image. - * - * @param img A GdkPixbufAnimation of the image to add. - * @param filename The filename to associate with the image. - * @param id The id to associate with the image. - * - * @return A new IM/HTML Scalable object with an image. - * - * @since 2.1.0 - */ -/* - * TODO: All this animation code could be combined much better with - * the image code. It couldn't be done when it was written - * because it requires breaking backward compatibility. It - * would be good to do it for 3.0.0. - */ -GtkIMHtmlScalable *gtk_imhtml_animation_new(GdkPixbufAnimation *img, const gchar *filename, int id); - -/** - * Destroys and frees a GTK+ IM/HTML scalable image. - * - * @param scale The GTK+ IM/HTML scalable. - */ -/* TODO: Is there any reason this isn't private? */ -void gtk_imhtml_image_free(GtkIMHtmlScalable *scale); - -/** - * Destroys and frees a GTK+ IM/HTML scalable animation. - * - * @param scale The GTK+ IM/HTML scalable. - */ -/* TODO: Is there any reason this isn't private? */ -void gtk_imhtml_animation_free(GtkIMHtmlScalable *scale); - -/** - * Rescales a GTK+ IM/HTML scalable image to a given size. - * - * @param scale The GTK+ IM/HTML scalable. - * @param width The new width. - * @param height The new height. - */ -/* TODO: Is there any reason this isn't private? */ -void gtk_imhtml_image_scale(GtkIMHtmlScalable *scale, int width, int height); - -/** - * Adds a GTK+ IM/HTML scalable image to a given GTK+ IM/HTML at a given iter. - * - * @param scale The GTK+ IM/HTML scalable. - * @param imhtml The GTK+ IM/HTML. - * @param iter The GtkTextIter at which to add the scalable. - */ -/* TODO: Is there any reason this isn't private? */ -void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter); - -/** * Creates and returns an new GTK+ IM/HTML scalable with a horizontal rule. * * @return A new IM/HTML Scalable object with an image. @@ -860,8 +725,6 @@ * * @param imhtml The GTK+ IM/HTML. * @param flags The connection flag which describes the allowed types of formatting. - * - * @since 2.1.0 */ void gtk_imhtml_setup_entry(GtkIMHtml *imhtml, PurpleConnectionFlags flags); @@ -874,7 +737,6 @@ * @param flags The smiley flags * * @return The newly created smiley - * @since 2.5.0 */ GtkIMHtmlSmiley *gtk_imhtml_smiley_create(const char *file, const char *shortcut, gboolean hide, GtkIMHtmlSmileyFlags flags); @@ -883,8 +745,6 @@ * Reload the image data for the smiley. * * @param smiley The smiley to reload - * - * @since 2.5.0 */ void gtk_imhtml_smiley_reload(GtkIMHtmlSmiley *smiley); @@ -892,8 +752,6 @@ * Destroy a GtkIMHtmlSmiley. * * @param smiley The smiley to destroy - * - * @since 2.5.0 */ void gtk_imhtml_smiley_destroy(GtkIMHtmlSmiley *smiley); @@ -912,8 +770,6 @@ * successfully, @c FALSE otherwise. * * @return @c TRUE if the protocol was successfully registered (or unregistered, when \a activate is @c NULL) - * - * @since 2.6.0 */ gboolean gtk_imhtml_class_register_protocol(const char *name, gboolean (*activate)(GtkIMHtml *imhtml, GtkIMHtmlLink *link), @@ -925,8 +781,6 @@ * @param link The GtkIMHtmlLink object sent to the callback functions * * @return The URL - * - * @since 2.6.0 */ const char *gtk_imhtml_link_get_url(GtkIMHtmlLink *link); @@ -936,8 +790,6 @@ * @param link The GtkIMHtmlLink object sent to the callback functions * * @return The GtkTextTag object, or @c NULL - * - * @since 2.6.0 */ const GtkTextTag *gtk_imhtml_link_get_text_tag(GtkIMHtmlLink *link); @@ -948,8 +800,6 @@ * @param link The GtkIMHtmlLink object sent to the callback functions * * @return @c TRUE if 'url-clicked' signal was emitted, @c FALSE otherwise. - * - * @since 2.6.0 */ gboolean gtk_imhtml_link_activate(GtkIMHtmlLink *link); @@ -976,8 +826,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PIDGINIMHTML_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkimhtmltoolbar.c --- a/pidgin/gtkimhtmltoolbar.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkimhtmltoolbar.c Fri Apr 06 04:30:00 2012 +0000 @@ -43,6 +43,11 @@ #include +#if !GTK_CHECK_VERSION(2,18,0) +#define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE(x) +#define gtk_widget_is_sensitive(x) GTK_WIDGET_IS_SENSITIVE(x) +#endif + static GtkHBoxClass *parent_class = NULL; static void toggle_button_set_active_block(GtkToggleButton *button, @@ -658,7 +663,11 @@ g_object_set_data(G_OBJECT(button), "smiley_text", face); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(insert_smiley_text), toolbar); +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(button, face); +#else gtk_tooltips_set_tip(toolbar->tooltips, button, face, NULL); +#endif /* these look really weird with borders */ gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); @@ -672,7 +681,11 @@ g_snprintf(tip, sizeof(tip), _("This smiley is disabled because a custom smiley exists for this shortcut:\n %s"), face); +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(button, tip); +#else gtk_tooltips_set_tip(toolbar->tooltips, button, tip, NULL); +#endif gtk_widget_set_sensitive(button, FALSE); } else if (psmiley) { /* Remove the button if the smiley is destroyed */ @@ -904,7 +917,7 @@ PurpleConversation *conv = g_object_get_data(G_OBJECT(toolbar), "active_conv"); const gchar *who = purple_conversation_get_name(conv); - PurpleConnection *gc = purple_conversation_get_gc(conv); + PurpleConnection *gc = purple_conversation_get_connection(conv); toggle_button_set_active_block(GTK_TOGGLE_BUTTON(attention), FALSE, toolbar); purple_prpl_send_attention(gc, who, 0); @@ -1155,7 +1168,9 @@ } g_free(toolbar->sml); +#if !GTK_CHECK_VERSION(2,12,0) gtk_object_sink(GTK_OBJECT(toolbar->tooltips)); +#endif menu = g_object_get_data(object, "font_menu"); if (menu) @@ -1186,7 +1201,7 @@ if (event->button != 3) return FALSE; - wide = GTK_WIDGET_VISIBLE(toolbar->bold); + wide = gtk_widget_get_visible(toolbar->bold); menu = gtk_menu_new(); item = gtk_menu_item_new_with_mnemonic(wide ? _("Group Items") : _("Ungroup Items")); @@ -1239,6 +1254,7 @@ {PIDGIN_STOCK_TOOLBAR_INSERT_LINK, insert_link_cb, &toolbar->link, _("Insert Link")}, {"", NULL, NULL, NULL}, {PIDGIN_STOCK_TOOLBAR_SMILEY, insert_smiley_cb, &toolbar->smiley, _("Insert Smiley")}, + {PIDGIN_STOCK_TOOLBAR_SEND_ATTENTION, send_attention_cb, &toolbar->attention, _("Send Attention")}, {NULL, NULL, NULL, NULL} }; int iter; @@ -1252,19 +1268,15 @@ g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(buttons[iter].callback), toolbar); *(buttons[iter].button) = button; +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(button, buttons[iter].tooltip); +#else gtk_tooltips_set_tip(toolbar->tooltips, button, buttons[iter].tooltip, NULL); +#endif } else button = gtk_vseparator_new(); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); } - /* create the attention button (this is a bit hacky to not break ABI) */ - button = pidgin_pixbuf_toolbar_button_from_stock(PIDGIN_STOCK_TOOLBAR_SEND_ATTENTION); - g_signal_connect(G_OBJECT(button), "button-press-event", G_CALLBACK(gtk_imhtmltoolbar_popup_menu), toolbar); - g_signal_connect(G_OBJECT(button), "clicked", - G_CALLBACK(send_attention_cb), toolbar); - g_object_set_data(G_OBJECT(toolbar), "attention", button); - gtk_tooltips_set_tip(toolbar->tooltips, button, _("Send Attention"), NULL); - gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(toolbar), hbox, FALSE, FALSE, 0); g_object_set_data(G_OBJECT(toolbar), "wide-view", hbox); @@ -1273,7 +1285,7 @@ static void button_visibility_changed(GtkWidget *button, gpointer dontcare, GtkWidget *item) { - if (GTK_WIDGET_VISIBLE(button)) + if (gtk_widget_get_visible(button)) gtk_widget_hide(item); else gtk_widget_show(item); @@ -1282,7 +1294,7 @@ static void button_sensitiveness_changed(GtkWidget *button, gpointer dontcare, GtkWidget *item) { - gtk_widget_set_sensitive(item, GTK_WIDGET_IS_SENSITIVE(button)); + gtk_widget_set_sensitive(item, gtk_widget_is_sensitive(button)); } static void @@ -1327,7 +1339,6 @@ GtkWidget *insert_menu; GtkWidget *menuitem; GtkWidget *sep; - GObject *wide_attention_button; int i; struct { const char *label; @@ -1361,7 +1372,9 @@ toolbar->smiley_dialog = NULL; toolbar->image_dialog = NULL; +#if !GTK_CHECK_VERSION(2,12,0) toolbar->tooltips = gtk_tooltips_new(); +#endif gtk_box_set_spacing(GTK_BOX(toolbar), 3); @@ -1478,8 +1491,6 @@ gtk_widget_show_all(sep); /* Attention */ - wide_attention_button = g_object_get_data(G_OBJECT(toolbar), "attention"); - attention_button = gtk_button_new(); gtk_button_set_relief(GTK_BUTTON(attention_button), GTK_RELIEF_NONE); bbox = gtk_hbox_new(FALSE, 3); @@ -1491,16 +1502,16 @@ gtk_box_pack_start(GTK_BOX(bbox), label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(box), attention_button, FALSE, FALSE, 0); g_signal_connect_swapped(G_OBJECT(attention_button), "clicked", - G_CALLBACK(gtk_button_clicked), wide_attention_button); + G_CALLBACK(gtk_button_clicked), toolbar->attention); gtk_widget_show_all(attention_button); - g_signal_connect(wide_attention_button, "notify::sensitive", + g_signal_connect(G_OBJECT(toolbar->attention), "notify::sensitive", G_CALLBACK(button_sensitiveness_changed), attention_button); - g_signal_connect(wide_attention_button, "notify::visible", + g_signal_connect(G_OBJECT(toolbar->attention), "notify::visible", G_CALLBACK(button_visibility_changed), attention_button); /* set attention button to be greyed out until we get a conversation */ - gtk_widget_set_sensitive(GTK_WIDGET(wide_attention_button), FALSE); + gtk_widget_set_sensitive(toolbar->attention, FALSE); gtk_box_pack_start(GTK_BOX(hbox), box, FALSE, FALSE, 0); g_object_set_data(G_OBJECT(hbox), "lean-view", box); @@ -1581,16 +1592,14 @@ void gtk_imhtmltoolbar_switch_active_conversation(GtkIMHtmlToolbar *toolbar, PurpleConversation *conv) { - PurpleConnection *gc = purple_conversation_get_gc(conv); + PurpleConnection *gc = purple_conversation_get_connection(conv); PurplePlugin *prpl = purple_connection_get_prpl(gc); - GtkWidget *attention = - g_object_get_data(G_OBJECT(toolbar), "attention"); g_object_set_data(G_OBJECT(toolbar), "active_conv", conv); /* gray out attention button on protocols that don't support it for the time being it is always disabled for chats */ - gtk_widget_set_sensitive(attention, + gtk_widget_set_sensitive(toolbar->attention, conv && prpl && purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM && PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->send_attention != NULL); } diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkimhtmltoolbar.h --- a/pidgin/gtkimhtmltoolbar.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkimhtmltoolbar.h Fri Apr 06 04:30:00 2012 +0000 @@ -26,9 +26,7 @@ #include #include "gtkimhtml.h" -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS #define DEFAULT_FONT_FACE "Helvetica 12" @@ -46,7 +44,11 @@ GtkWidget *imhtml; +#if GTK_CHECK_VERSION(2,12,0) + gpointer depr1; +#else GtkTooltips *tooltips; +#endif GtkWidget *bold; GtkWidget *italic; @@ -65,6 +67,7 @@ GtkWidget *image; GtkWidget *link; GtkWidget *smiley; + GtkWidget *attention; GtkWidget *font_dialog; GtkWidget *fgcolor_dialog; @@ -90,14 +93,9 @@ void gtk_imhtmltoolbar_attach (GtkIMHtmlToolbar *toolbar, GtkWidget *imhtml); void gtk_imhtmltoolbar_associate_smileys (GtkIMHtmlToolbar *toolbar, const char *proto_id); -/** - * @since 2.7.0 - */ void gtk_imhtmltoolbar_switch_active_conversation(GtkIMHtmlToolbar *toolbar, PurpleConversation *conv); -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PIDGINIMHTMLTOOLBAR_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtklog.c --- a/pidgin/gtklog.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtklog.c Fri Apr 06 04:30:00 2012 +0000 @@ -35,9 +35,9 @@ #include "pidginstock.h" #include "gtkblist.h" -#include "gtkimhtml.h" #include "gtklog.h" #include "gtkutils.h" +#include "gtkwebview.h" static GHashTable *log_viewers = NULL; static void populate_log_tree(PidginLogViewer *lv); @@ -130,7 +130,7 @@ populate_log_tree(lv); g_free(lv->search); lv->search = NULL; - gtk_imhtml_search_clear(GTK_IMHTML(lv->imhtml)); + webkit_web_view_unmark_text_matches(WEBKIT_WEB_VIEW(lv->web_view)); select_first_log(lv); return; } @@ -138,7 +138,7 @@ if (lv->search != NULL && !strcmp(lv->search, search_term)) { /* Searching for the same term acts as "Find Next" */ - gtk_imhtml_search_find(GTK_IMHTML(lv->imhtml), lv->search); + webkit_web_view_search_text(WEBKIT_WEB_VIEW(lv->web_view), lv->search, FALSE, TRUE, TRUE); return; } @@ -148,7 +148,7 @@ lv->search = g_strdup(search_term); gtk_tree_store_clear(lv->treestore); - gtk_imhtml_clear(GTK_IMHTML(lv->imhtml)); + webkit_web_view_open(WEBKIT_WEB_VIEW(lv->web_view), "about:blank"); /* clear the view */ for (logs = lv->logs; logs != NULL; logs = logs->next) { char *read = purple_log_read((PurpleLog*)logs->data, NULL); @@ -419,8 +419,9 @@ static gboolean search_find_cb(gpointer data) { PidginLogViewer *viewer = data; - gtk_imhtml_search_find(GTK_IMHTML(viewer->imhtml), viewer->search); - g_object_steal_data(G_OBJECT(viewer->entry), "search-find-cb"); + webkit_web_view_mark_text_matches(WEBKIT_WEB_VIEW(viewer->web_view), viewer->search, FALSE, 0); + webkit_web_view_set_highlight_text_matches(WEBKIT_WEB_VIEW(viewer->web_view), TRUE); + webkit_web_view_search_text(WEBKIT_WEB_VIEW(viewer->web_view), viewer->search, FALSE, TRUE, TRUE); return FALSE; } @@ -461,23 +462,16 @@ read = purple_log_read(log, &flags); viewer->flags = flags; - gtk_imhtml_clear(GTK_IMHTML(viewer->imhtml)); - gtk_imhtml_set_protocol_name(GTK_IMHTML(viewer->imhtml), - purple_account_get_protocol_name(log->account)); + webkit_web_view_open(WEBKIT_WEB_VIEW(viewer->web_view), "about:blank"); purple_signal_emit(pidgin_log_get_handle(), "log-displaying", viewer, log); - gtk_imhtml_append_text(GTK_IMHTML(viewer->imhtml), read, - GTK_IMHTML_NO_COMMENTS | GTK_IMHTML_NO_TITLE | GTK_IMHTML_NO_SCROLL | - ((flags & PURPLE_LOG_READ_NO_NEWLINE) ? GTK_IMHTML_NO_NEWLINE : 0)); + webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(viewer->web_view), read, ""); g_free(read); if (viewer->search != NULL) { - guint source; - gtk_imhtml_search_clear(GTK_IMHTML(viewer->imhtml)); - source = g_idle_add(search_find_cb, viewer); - g_object_set_data_full(G_OBJECT(viewer->entry), "search-find-cb", - GINT_TO_POINTER(source), (GDestroyNotify)g_source_remove); + webkit_web_view_unmark_text_matches(WEBKIT_WEB_VIEW(viewer->web_view)); + g_idle_add(search_find_cb, viewer); } pidgin_clear_cursor(viewer->window); @@ -581,7 +575,9 @@ gtk_dialog_add_button(GTK_DIALOG(lv->window), _("_Browse logs folder"), GTK_RESPONSE_HELP); #endif gtk_container_set_border_width (GTK_CONTAINER(lv->window), PIDGIN_HIG_BOX_SPACE); +#if !GTK_CHECK_VERSION(2,22,0) gtk_dialog_set_has_separator(GTK_DIALOG(lv->window), FALSE); +#endif gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(lv->window)->vbox), 0); g_signal_connect(G_OBJECT(lv->window), "response", G_CALLBACK(destroy_cb), ht); @@ -620,7 +616,7 @@ col = gtk_tree_view_column_new_with_attributes ("time", rend, "markup", 0, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW(lv->treeview), col); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (lv->treeview), FALSE); - gtk_paned_add1(GTK_PANED(pane), + gtk_paned_add1(GTK_PANED(pane), pidgin_make_scrollable(lv->treeview, GTK_POLICY_NEVER, GTK_POLICY_ALWAYS, GTK_SHADOW_IN, -1, -1)); populate_log_tree(lv); @@ -655,9 +651,9 @@ gtk_paned_add2(GTK_PANED(pane), vbox); /* Viewer ************/ - frame = pidgin_create_imhtml(FALSE, &lv->imhtml, NULL, NULL); - gtk_widget_set_name(lv->imhtml, "pidgin_log_imhtml"); - gtk_widget_set_size_request(lv->imhtml, 320, 200); + frame = pidgin_create_webview(FALSE, &lv->web_view, NULL, NULL); + gtk_widget_set_name(lv->web_view, "pidgin_log_web_view"); + gtk_widget_set_size_request(lv->web_view, 320, 200); gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); gtk_widget_show(frame); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtklog.h --- a/pidgin/gtklog.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtklog.h Fri Apr 06 04:30:00 2012 +0000 @@ -43,7 +43,7 @@ GtkWidget *window; /**< The viewer's window */ GtkTreeStore *treestore; /**< The treestore containing said logs */ GtkWidget *treeview; /**< The treeview representing said treestore */ - GtkWidget *imhtml; /**< The imhtml to display said logs */ + GtkWidget *web_view; /**< The webkit web view to display said logs */ GtkWidget *entry; /**< The search entry, in which search terms * are entered */ PurpleLogReadFlags flags; /**< The most recently used log flags */ @@ -52,6 +52,7 @@ }; +G_BEGIN_DECLS void pidgin_log_show(PurpleLogType type, const char *buddyname, PurpleAccount *account); void pidgin_log_show_contact(PurpleContact *contact); @@ -82,4 +83,6 @@ /*@}*/ +G_END_DECLS + #endif diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkmain.c --- a/pidgin/gtkmain.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkmain.c Fri Apr 06 04:30:00 2012 +0000 @@ -498,7 +498,6 @@ int opt; gboolean gui_check; gboolean debug_enabled; - gboolean migration_failed = FALSE; GList *active_accounts; struct stat st; @@ -720,7 +719,16 @@ /* set a user-specified config directory */ if (opt_config_dir_arg != NULL) { - purple_util_set_user_dir(opt_config_dir_arg); + if (g_path_is_absolute(opt_config_dir_arg)) { + purple_util_set_user_dir(opt_config_dir_arg); + } else { + /* Make an absolute (if not canonical) path */ + char *cwd = g_get_current_dir(); + char *path = g_build_path(G_DIR_SEPARATOR_S, cwd, opt_config_dir_arg, NULL); + purple_util_set_user_dir(path); + g_free(path); + g_free(cwd); + } } /* @@ -730,16 +738,6 @@ 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); g_free(search_path); @@ -765,37 +763,6 @@ 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. Please report this error at http://developer.pidgin.im"); - 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()); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkmedia.c --- a/pidgin/gtkmedia.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkmedia.c Fri Apr 06 04:30:00 2012 +0000 @@ -40,6 +40,8 @@ #ifdef _WIN32 #include +#elif defined(GDK_WINDOWING_QUARTZ) +#include #endif #include @@ -455,7 +457,7 @@ progress = pidgin_media_get_widget(gtkmedia, session_id, participant); if (progress) - gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), level * 5); + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), level); } @@ -560,6 +562,8 @@ window_id = GDK_WINDOW_HWND(window); #elif defined(HAVE_X11) window_id = GDK_WINDOW_XWINDOW(window); +#elif defined(GDK_WINDOWING_QUARTZ) + window_id = (gulong) gdk_quartz_window_get_nsview(window); #else # error "Unsupported windowing system" #endif @@ -969,7 +973,7 @@ pidgin_media_set_state(gtkmedia, PIDGIN_MEDIA_ACCEPTED); pidgin_media_emit_message(gtkmedia, _("Call in progress.")); gtk_statusbar_push(GTK_STATUSBAR(gtkmedia->priv->statusbar), - 0, _("Call in progress.")); + 0, _("Call in progress")); gtk_widget_show(GTK_WIDGET(gtkmedia)); } } @@ -1082,6 +1086,10 @@ src = gst_element_factory_make("dshowvideosrc", NULL); if (src == NULL) src = gst_element_factory_make("autovideosrc", NULL); +#elif defined(__APPLE__) + src = gst_element_factory_make("osxvideosrc", NULL); + if (src == NULL) + src = gst_element_factory_make("autovideosrc", NULL); #else src = gst_element_factory_make("gconfvideosrc", NULL); if (src == NULL) @@ -1136,6 +1144,8 @@ src = gst_element_factory_make("osssrc", NULL); if (src == NULL) src = gst_element_factory_make("dshowaudiosrc", NULL); + if (src == NULL) + src = gst_element_factory_make("osxaudiosrc", NULL); if (src == NULL) { purple_debug_error("gtkmedia", "Unable to find a suitable " "element for the default audio source.\n"); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkmenutray.c --- a/pidgin/gtkmenutray.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkmenutray.c Fri Apr 06 04:30:00 2012 +0000 @@ -40,6 +40,10 @@ * Internal Stuff *****************************************************************************/ +#if !GTK_CHECK_VERSION(2,18,0) +#define gtk_widget_get_has_window(x) !GTK_WIDGET_NO_WINDOW(x) +#endif + /****************************************************************************** * Item Stuff *****************************************************************************/ @@ -92,7 +96,9 @@ static void pidgin_menu_tray_finalize(GObject *obj) { +#if !GTK_CHECK_VERSION(2,12,0) PidginMenuTray *tray = PIDGIN_MENU_TRAY(obj); +#endif #if 0 /* This _might_ be leaking, but I have a sneaking suspicion that the widget is * getting destroyed in GtkContainer's finalize function. But if were are @@ -104,9 +110,11 @@ gtk_widget_destroy(GTK_WIDGET(tray->tray)); #endif +#if !GTK_CHECK_VERSION(2,12,0) if (tray->tooltips) { gtk_object_sink(GTK_OBJECT(tray->tooltips)); } +#endif G_OBJECT_CLASS(parent_class)->finalize(obj); } @@ -205,7 +213,7 @@ g_return_if_fail(PIDGIN_IS_MENU_TRAY(menu_tray)); g_return_if_fail(GTK_IS_WIDGET(widget)); - if (GTK_WIDGET_NO_WINDOW(widget)) + if (!gtk_widget_get_has_window(widget)) { GtkWidget *event; @@ -238,21 +246,27 @@ void pidgin_menu_tray_set_tooltip(PidginMenuTray *menu_tray, GtkWidget *widget, const char *tooltip) { +#if !GTK_CHECK_VERSION(2,12,0) if (!menu_tray->tooltips) menu_tray->tooltips = gtk_tooltips_new(); +#endif /* Should we check whether widget is a child of menu_tray? */ /* - * If the widget does not have it's own window, then it + * If the widget does not have its own window, then it * must have automatically been added to an event box * when it was added to the menu tray. If this is the * case, we want to set the tooltip on the widget's parent, * not on the widget itself. */ - if (GTK_WIDGET_NO_WINDOW(widget)) + if (!gtk_widget_get_has_window(widget)) widget = widget->parent; +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(widget, tooltip); +#else gtk_tooltips_set_tip(menu_tray->tooltips, widget, tooltip, NULL); +#endif } diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkmenutray.h --- a/pidgin/gtkmenutray.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkmenutray.h Fri Apr 06 04:30:00 2012 +0000 @@ -40,7 +40,9 @@ struct _PidginMenuTray { GtkMenuItem gparent; /**< The parent instance */ GtkWidget *tray; /**< The tray */ +#if !GTK_CHECK_VERSION(2,12,0) GtkTooltips *tooltips; /**< Tooltips */ +#endif }; /** A PidginMenuTrayClass */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtknotify.c --- a/pidgin/gtknotify.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtknotify.c Fri Apr 06 04:30:00 2012 +0000 @@ -36,10 +36,10 @@ #include "util.h" #include "gtkblist.h" -#include "gtkimhtml.h" #include "gtknotify.h" #include "gtkpounce.h" #include "gtkutils.h" +#include "gtkwebview.h" typedef struct { @@ -534,7 +534,9 @@ gtk_container_set_border_width(GTK_CONTAINER(dialog), PIDGIN_HIG_BORDER); gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); +#if !GTK_CHECK_VERSION(2,22,0) gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); +#endif gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER); gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BOX_SPACE); @@ -689,6 +691,8 @@ PurpleAccount *account; PidginNotifyMailData *data = NULL, *data2; gboolean new_data = FALSE; + GtkTreeSelection *sel; + GtkTreeIter iter; /* Don't bother updating if there aren't new emails and we don't have any displayed currently */ if (count == 0 && mail_dialog == NULL) @@ -775,7 +779,18 @@ } } + /* Select first item if nothing selected */ + sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(mail_dialog->treeview)); + if ((gtk_tree_selection_count_selected_rows(sel) < 1) + && gtk_tree_model_get_iter_first(GTK_TREE_MODEL(mail_dialog->treemodel), &iter)) { + gtk_tree_selection_select_iter(sel, &iter); + } + +#if GTK_CHECK_VERSION(2,18,0) + if (!gtk_widget_get_visible(mail_dialog->dialog)) { +#else if (!GTK_WIDGET_VISIBLE(mail_dialog->dialog)) { +#endif GdkPixbuf *pixbuf = gtk_widget_render_icon(mail_dialog->dialog, PIDGIN_STOCK_DIALOG_MAIL, gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL), NULL); char *label_text = g_strdup_printf(ngettext("%d new email.", @@ -791,7 +806,11 @@ g_free(label_text); if (pixbuf) g_object_unref(pixbuf); +#if GTK_CHECK_VERSION(2,18,0) + } else if (!gtk_widget_has_focus(mail_dialog->dialog)) +#else } else if (!GTK_WIDGET_HAS_FOCUS(mail_dialog->dialog)) +#endif pidgin_set_urgent(GTK_WINDOW(mail_dialog->dialog), TRUE); return data; @@ -810,21 +829,6 @@ return FALSE; } -static GtkIMHtmlOptions -notify_imhtml_options(void) -{ - GtkIMHtmlOptions options = 0; - - if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_incoming_formatting")) - options |= GTK_IMHTML_NO_COLOURS | GTK_IMHTML_NO_FONTS | GTK_IMHTML_NO_SIZES; - - options |= GTK_IMHTML_NO_COMMENTS; - options |= GTK_IMHTML_NO_TITLE; - options |= GTK_IMHTML_NO_NEWLINE; - options |= GTK_IMHTML_NO_SCROLL; - return options; -} - static void * pidgin_notify_formatted(const char *title, const char *primary, const char *secondary, const char *text) @@ -833,7 +837,7 @@ GtkWidget *vbox; GtkWidget *label; GtkWidget *button; - GtkWidget *imhtml; + GtkWidget *web_view; GtkWidget *frame; char label_text[2048]; char *linked_text, *primary_esc, *secondary_esc; @@ -869,12 +873,10 @@ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); gtk_widget_show(label); - /* Add the imhtml */ - frame = pidgin_create_imhtml(FALSE, &imhtml, NULL, NULL); - gtk_widget_set_name(imhtml, "pidgin_notify_imhtml"); - gtk_imhtml_set_format_functions(GTK_IMHTML(imhtml), - gtk_imhtml_get_format_functions(GTK_IMHTML(imhtml)) | GTK_IMHTML_IMAGE); - gtk_widget_set_size_request(imhtml, 300, 250); + /* Add the webview */ + frame = pidgin_create_webview(FALSE, &web_view, NULL, NULL); + gtk_widget_set_name(web_view, "pidgin_notify_webview"); + gtk_widget_set_size_request(web_view, 300, 250); gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); gtk_widget_show(frame); @@ -889,10 +891,10 @@ /* Make sure URLs are clickable */ linked_text = purple_markup_linkify(text); - gtk_imhtml_append_text(GTK_IMHTML(imhtml), linked_text, notify_imhtml_options()); + webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(web_view), linked_text, ""); g_free(linked_text); - g_object_set_data(G_OBJECT(window), "info-widget", imhtml); + g_object_set_data(G_OBJECT(window), "webview-widget", web_view); /* Show the window */ pidgin_auto_parent_window(window); @@ -1034,7 +1036,11 @@ renderer = gtk_cell_renderer_text_new(); gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview), -1, - column->title, renderer, "text", i, NULL); + purple_notify_searchresult_column_get_title(column), renderer, "text", i, NULL); + + if (!purple_notify_searchresult_column_is_visible(column)) + gtk_tree_view_column_set_visible(gtk_tree_view_get_column(GTK_TREE_VIEW(treeview), i), FALSE); + i++; } @@ -1044,7 +1050,7 @@ switch (b->type) { case PURPLE_NOTIFY_BUTTON_LABELED: if(b->label) { - button = gtk_button_new_with_label(b->label); + button = gtk_dialog_add_button(GTK_DIALOG(window), b->label, GTK_RESPONSE_NONE); } else { purple_debug_warning("gtknotify", "Missing button label\n"); } @@ -1089,7 +1095,7 @@ g_signal_connect_swapped(G_OBJECT(close_button), "clicked", G_CALLBACK(searchresults_close_cb), data); - data->account = gc->account; + data->account = purple_connection_get_account(gc); data->model = model; data->treeview = treeview; data->window = window; @@ -1143,10 +1149,9 @@ info = purple_notify_user_info_get_text_with_newline(user_info, "
    "); pinfo = g_hash_table_lookup(userinfo, key); if (pinfo != NULL) { - GtkIMHtml *imhtml = g_object_get_data(G_OBJECT(pinfo->window), "info-widget"); + GtkWidget *webview = g_object_get_data(G_OBJECT(pinfo->window), "webview-widget"); char *linked_text = purple_markup_linkify(info); - gtk_imhtml_clear(imhtml); - gtk_imhtml_append_text(imhtml, linked_text, notify_imhtml_options()); + gtk_webview_load_html_string_with_imgstore(GTK_WEBVIEW(webview), linked_text); g_free(linked_text); g_free(key); ui_handle = pinfo->window; @@ -1508,7 +1513,9 @@ /* Setup the dialog */ gtk_container_set_border_width(GTK_CONTAINER(dialog), PIDGIN_HIG_BOX_SPACE); gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BOX_SPACE); +#if !GTK_CHECK_VERSION(2,22,0) gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); +#endif gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER); /* Vertical box */ @@ -1544,11 +1551,13 @@ gtk_tree_view_set_search_column(GTK_TREE_VIEW(spec_dialog->treeview), PIDGIN_MAIL_TEXT); gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(spec_dialog->treeview), pidgin_tree_view_search_equal_func, NULL, NULL); + sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(spec_dialog->treeview)); + gtk_tree_selection_set_mode(sel, GTK_SELECTION_BROWSE); g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(email_response_cb), spec_dialog); - g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(spec_dialog->treeview))), - "changed", G_CALLBACK(selection_changed_cb), spec_dialog); + g_signal_connect(G_OBJECT(sel), "changed", + G_CALLBACK(selection_changed_cb), spec_dialog); g_signal_connect(G_OBJECT(spec_dialog->treeview), "row-activated", G_CALLBACK(email_row_activated_cb), NULL); column = gtk_tree_view_column_new(); @@ -1646,7 +1655,7 @@ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); gtk_misc_set_alignment(GTK_MISC(label), 0, 0); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(vbox), + gtk_box_pack_start(GTK_BOX(vbox), pidgin_make_scrollable(spec_dialog->treeview, GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS, GTK_SHADOW_IN, -1, -1), TRUE, TRUE, 2); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtknotify.h --- a/pidgin/gtknotify.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtknotify.h Fri Apr 06 04:30:00 2012 +0000 @@ -29,6 +29,8 @@ #include "notify.h" #include "pounce.h" +G_BEGIN_DECLS + /** * Adds a buddy pounce to the buddy pounce dialog * @@ -59,4 +61,6 @@ */ void pidgin_notify_uninit(void); +G_END_DECLS + #endif /* _PIDGINNOTIFY_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkplugin.h --- a/pidgin/gtkplugin.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkplugin.h Fri Apr 06 04:30:00 2012 +0000 @@ -56,6 +56,8 @@ #define PIDGIN_PLUGIN_UI_INFO(plugin) \ ((PidginPluginUiInfo *)(plugin)->info->ui_info) +G_BEGIN_DECLS + /** * Returns the configuration frame widget for a GTK+ plugin, if one * exists. @@ -77,4 +79,6 @@ */ void pidgin_plugin_dialog_show(void); +G_END_DECLS + #endif /* _PIDGINPLUGIN_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkpluginpref.h --- a/pidgin/gtkpluginpref.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkpluginpref.h Fri Apr 06 04:30:00 2012 +0000 @@ -31,9 +31,7 @@ #include "pidgin.h" -#ifdef __cplusplus -extern "C" { -#endif +G_BEGIN_DECLS /** * Creates a Gtk Preference frame for a PurplePluginPrefFrame @@ -43,8 +41,6 @@ */ GtkWidget *pidgin_plugin_pref_create_frame(PurplePluginPrefFrame *frame); -#ifdef __cplusplus -} -#endif +G_END_DECLS #endif /* _PIDGINPLUGINPREF_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkpounce.c --- a/pidgin/gtkpounce.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkpounce.c Fri Apr 06 04:30:00 2012 +0000 @@ -427,9 +427,9 @@ dialog = (PidginPounceDialog *)data; - gtk_entry_set_text(GTK_ENTRY(dialog->buddy_entry), buddy->name); - dialog->account = buddy->account; - pidgin_account_option_menu_set_selected(dialog->account_menu, buddy->account); + gtk_entry_set_text(GTK_ENTRY(dialog->buddy_entry), purple_buddy_get_name(buddy)); + dialog->account = purple_buddy_get_account(buddy); + pidgin_account_option_menu_set_selected(dialog->account_menu, purple_buddy_get_account(buddy)); gtk_drag_finish(dc, TRUE, (dc->action == GDK_ACTION_MOVE), t); } @@ -476,7 +476,7 @@ { PurpleAccount *account = pidgin_account_option_menu_get_selected(dialog->account_menu); gtk_imhtml_setup_entry(GTK_IMHTML(dialog->send_msg_entry), - (account && account->gc) ? account->gc->flags : PURPLE_CONNECTION_HTML); + (account && purple_account_get_connection(account)) ? purple_connection_get_flags(purple_account_get_connection(account)) : PURPLE_CONNECTION_HTML); } void @@ -1018,7 +1018,11 @@ static gboolean pounces_manager_configure_cb(GtkWidget *widget, GdkEventConfigure *event, PouncesManager *dialog) { +#if GTK_CHECK_VERSION(2,18,0) + if (gtk_widget_get_visible(widget)) { +#else if (GTK_WIDGET_VISIBLE(widget)) { +#endif purple_prefs_set_int(PIDGIN_PREFS_ROOT "/pounces/dialog/width", event->width); purple_prefs_set_int(PIDGIN_PREFS_ROOT "/pounces/dialog/height", event->height); } @@ -1419,7 +1423,6 @@ if (purple_pounce_action_is_enabled(pounce, "popup-notify")) { char *tmp; - const char *name_shown; const char *reason; reason = purple_pounce_action_get_attribute(pounce, "popup-notify", "reason"); @@ -1452,14 +1455,6 @@ _("Unknown.... Please report this!") ); - /* - * Ok here is where I change the second argument, title, from - * NULL to the account alias if we have it or the account - * name if that's all we have - */ - if ((name_shown = purple_account_get_alias(account)) == NULL) - name_shown = purple_account_get_username(account); - pidgin_notify_pounce_add(account, pounce, alias, tmp, reason, purple_date_format_full(NULL)); @@ -1483,7 +1478,7 @@ purple_conversation_write(conv, NULL, message, PURPLE_MESSAGE_SEND, time(NULL)); - serv_send_im(account->gc, (char *)pouncee, (char *)message, 0); + serv_send_im(purple_account_get_connection(account), (char *)pouncee, (char *)message, 0); } } diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkpounce.h --- a/pidgin/gtkpounce.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkpounce.h Fri Apr 06 04:30:00 2012 +0000 @@ -28,6 +28,8 @@ #include "pounce.h" +G_BEGIN_DECLS + /** * Displays a New Buddy Pounce or Edit Buddy Pounce dialog. * @@ -60,4 +62,6 @@ */ void pidgin_pounces_init(void); +G_END_DECLS + #endif /* _PIDGINPOUNCE_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkprefs.c --- a/pidgin/gtkprefs.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkprefs.c Fri Apr 06 04:30:00 2012 +0000 @@ -45,16 +45,17 @@ #include "gtkblist.h" #include "gtkconv.h" +#include "gtkconv-theme.h" #include "gtkdebug.h" #include "gtkdialogs.h" -#include "gtkimhtml.h" -#include "gtkimhtmltoolbar.h" #include "gtkprefs.h" #include "gtksavedstatuses.h" #include "gtksound.h" #include "gtkstatus-icon-theme.h" #include "gtkthemes.h" #include "gtkutils.h" +#include "gtkwebview.h" +#include "gtkwebviewtoolbar.h" #include "pidginstock.h" #define PROXYHOST 0 @@ -78,11 +79,13 @@ static int notebook_page = 0; /* Conversations page */ -static GtkWidget *sample_imhtml = NULL; +static GtkWidget *sample_webview = NULL; /* Themes page */ static GtkWidget *prefs_sound_themes_combo_box; static GtkWidget *prefs_blist_themes_combo_box; +static GtkWidget *prefs_conv_themes_combo_box; +static GtkWidget *prefs_conv_variants_combo_box; static GtkWidget *prefs_status_themes_combo_box; static GtkWidget *prefs_smiley_themes_combo_box; @@ -94,6 +97,8 @@ /* These exist outside the lifetime of the prefs dialog */ static GtkListStore *prefs_sound_themes; static GtkListStore *prefs_blist_themes; +static GtkListStore *prefs_conv_themes; +static GtkListStore *prefs_conv_variants; static GtkListStore *prefs_status_icon_themes; static GtkListStore *prefs_smiley_themes; @@ -182,29 +187,49 @@ return pidgin_add_widget_to_vbox(GTK_BOX(page), title, sg, entry, TRUE, NULL); } +/* TODO: Maybe move this up somewheres... */ +enum { + PREF_DROPDOWN_TEXT, + PREF_DROPDOWN_VALUE, + PREF_DROPDOWN_COUNT +}; static void dropdown_set(GObject *w, const char *key) { const char *str_value; int int_value; + gboolean bool_value; PurplePrefType type; + GtkTreeIter iter; + GtkTreeModel *tree_model; + + tree_model = gtk_combo_box_get_model(GTK_COMBO_BOX(w)); + if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w), &iter)) + return; type = GPOINTER_TO_INT(g_object_get_data(w, "type")); if (type == PURPLE_PREF_INT) { - int_value = GPOINTER_TO_INT(g_object_get_data(w, "value")); + gtk_tree_model_get(tree_model, &iter, + PREF_DROPDOWN_VALUE, &int_value, + -1); purple_prefs_set_int(key, int_value); } else if (type == PURPLE_PREF_STRING) { - str_value = (const char *)g_object_get_data(w, "value"); + gtk_tree_model_get(tree_model, &iter, + PREF_DROPDOWN_VALUE, &str_value, + -1); purple_prefs_set_string(key, str_value); } else if (type == PURPLE_PREF_BOOLEAN) { - purple_prefs_set_bool(key, - GPOINTER_TO_INT(g_object_get_data(w, "value"))); + gtk_tree_model_get(tree_model, &iter, + PREF_DROPDOWN_VALUE, &bool_value, + -1); + + purple_prefs_set_bool(key, bool_value); } } @@ -212,69 +237,89 @@ pidgin_prefs_dropdown_from_list(GtkWidget *box, const gchar *title, PurplePrefType type, const char *key, GList *menuitems) { - GtkWidget *dropdown, *opt, *menu; + GtkWidget *dropdown; GtkWidget *label = NULL; gchar *text; const char *stored_str = NULL; int stored_int = 0; + gboolean stored_bool = FALSE; int int_value = 0; const char *str_value = NULL; - int o = 0; + gboolean bool_value = FALSE; + GtkListStore *store = NULL; + GtkTreeIter iter; + GtkTreeIter active; + GtkCellRenderer *renderer; g_return_val_if_fail(menuitems != NULL, NULL); - dropdown = gtk_option_menu_new(); - menu = gtk_menu_new(); - - if (type == PURPLE_PREF_INT) + if (type == PURPLE_PREF_INT) { + store = gtk_list_store_new(PREF_DROPDOWN_COUNT, G_TYPE_STRING, G_TYPE_INT); stored_int = purple_prefs_get_int(key); - else if (type == PURPLE_PREF_STRING) + } else if (type == PURPLE_PREF_STRING) { + store = gtk_list_store_new(PREF_DROPDOWN_COUNT, G_TYPE_STRING, G_TYPE_STRING); stored_str = purple_prefs_get_string(key); - - while (menuitems != NULL && (text = (char *) menuitems->data) != NULL) { + } else if (type == PURPLE_PREF_BOOLEAN) { + store = gtk_list_store_new(PREF_DROPDOWN_COUNT, G_TYPE_STRING, G_TYPE_BOOLEAN); + stored_bool = purple_prefs_get_bool(key); + } else { + g_warn_if_reached(); + return NULL; + } + + dropdown = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); + g_object_set_data(G_OBJECT(dropdown), "type", GINT_TO_POINTER(type)); + + while (menuitems != NULL && (text = (char *)menuitems->data) != NULL) { menuitems = g_list_next(menuitems); g_return_val_if_fail(menuitems != NULL, NULL); - opt = gtk_menu_item_new_with_label(text); - - g_object_set_data(G_OBJECT(opt), "type", GINT_TO_POINTER(type)); + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, + PREF_DROPDOWN_TEXT, text, + -1); if (type == PURPLE_PREF_INT) { int_value = GPOINTER_TO_INT(menuitems->data); - g_object_set_data(G_OBJECT(opt), "value", - GINT_TO_POINTER(int_value)); + gtk_list_store_set(store, &iter, + PREF_DROPDOWN_VALUE, int_value, + -1); } else if (type == PURPLE_PREF_STRING) { str_value = (const char *)menuitems->data; - - g_object_set_data(G_OBJECT(opt), "value", (char *)str_value); + gtk_list_store_set(store, &iter, + PREF_DROPDOWN_VALUE, str_value, + -1); } else if (type == PURPLE_PREF_BOOLEAN) { - g_object_set_data(G_OBJECT(opt), "value", - menuitems->data); + bool_value = (gboolean)GPOINTER_TO_INT(menuitems->data); + gtk_list_store_set(store, &iter, + PREF_DROPDOWN_VALUE, bool_value, + -1); } - g_signal_connect(G_OBJECT(opt), "activate", - G_CALLBACK(dropdown_set), (char *)key); - - gtk_widget_show(opt); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), opt); - if ((type == PURPLE_PREF_INT && stored_int == int_value) || (type == PURPLE_PREF_STRING && stored_str != NULL && !strcmp(stored_str, str_value)) || (type == PURPLE_PREF_BOOLEAN && - (purple_prefs_get_bool(key) == GPOINTER_TO_INT(menuitems->data)))) { - - gtk_menu_set_active(GTK_MENU(menu), o); + (stored_bool == bool_value))) { + + active = iter; } menuitems = g_list_next(menuitems); - - o++; } - gtk_option_menu_set_menu(GTK_OPTION_MENU(dropdown), menu); + renderer = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(dropdown), renderer, TRUE); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(dropdown), renderer, + "text", 0, + NULL); + + gtk_combo_box_set_active_iter(GTK_COMBO_BOX(dropdown), &active); + + g_signal_connect(G_OBJECT(dropdown), "changed", + G_CALLBACK(dropdown_set), (char *)key); pidgin_add_widget_to_vbox(GTK_BOX(box), title, NULL, dropdown, FALSE, &label); @@ -339,10 +384,12 @@ prefs_sound_themes_combo_box = NULL; prefs_blist_themes_combo_box = NULL; + prefs_conv_themes_combo_box = NULL; + prefs_conv_variants_combo_box = NULL; prefs_status_themes_combo_box = NULL; prefs_smiley_themes_combo_box = NULL; - sample_imhtml = NULL; + sample_webview = NULL; notebook_page = 0; prefsnotebook = NULL; @@ -490,6 +537,18 @@ g_free(markup); if (pixbuf != NULL) g_object_unref(G_OBJECT(pixbuf)); + + } else if (PIDGIN_IS_CONV_THEME(theme)) { + /* No image available? */ + + name = purple_theme_get_name(theme); + /* No author available */ + /* No description available */ + + markup = get_theme_markup(name, FALSE, NULL, NULL); + + gtk_list_store_append(prefs_conv_themes, &iter); + gtk_list_store_set(prefs_conv_themes, &iter, 1, markup, 2, name, -1); } } @@ -545,6 +604,17 @@ gtk_list_store_set(prefs_blist_themes, &iter, 0, pixbuf, 1, tmp, 2, "", -1); g_free(tmp); + /* conversation themes */ + gtk_list_store_clear(prefs_conv_themes); + gtk_list_store_append(prefs_conv_themes, &iter); + tmp = get_theme_markup(_("Default"), FALSE, _("Penguin Pimps"), + _("The default Pidgin conversation theme")); + gtk_list_store_set(prefs_conv_themes, &iter, 0, pixbuf, 1, tmp, 2, "", -1); + g_free(tmp); + + /* conversation theme variants */ + gtk_list_store_clear(prefs_conv_variants); + /* status icon themes */ gtk_list_store_clear(prefs_status_icon_themes); gtk_list_store_append(prefs_status_icon_themes, &iter); @@ -565,6 +635,7 @@ /* set active */ prefs_set_active_theme_combo(prefs_sound_themes_combo_box, prefs_sound_themes, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/theme")); prefs_set_active_theme_combo(prefs_blist_themes_combo_box, prefs_blist_themes, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/blist/theme")); + prefs_set_active_theme_combo(prefs_conv_themes_combo_box, prefs_conv_themes, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/theme")); prefs_set_active_theme_combo(prefs_status_themes_combo_box, prefs_status_icon_themes, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/status/icon-theme")); prefs_set_active_theme_combo(prefs_smiley_themes_combo_box, prefs_smiley_themes, purple_prefs_get_string(PIDGIN_PREFS_ROOT "/smileys/theme")); prefs_sound_themes_loading = FALSE; @@ -578,6 +649,10 @@ prefs_blist_themes = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING); + prefs_conv_themes = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING); + + prefs_conv_variants = gtk_list_store_new(1, G_TYPE_STRING); + prefs_status_icon_themes = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING); prefs_smiley_themes = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING); @@ -856,7 +931,7 @@ } else if (!g_ascii_strncasecmp(name, "http://", 7)) { /* Oo, a web drag and drop. This is where things * will start to get interesting */ - purple_util_fetch_url(name, TRUE, NULL, FALSE, theme_got_url, info); + purple_util_fetch_url(name, TRUE, NULL, FALSE, -1, theme_got_url, info); } else if (!g_ascii_strncasecmp(name, "https://", 8)) { /* purple_util_fetch_url() doesn't support HTTPS, but we want users * to be able to drag and drop links from the SF trackers, so @@ -867,7 +942,7 @@ tmp[2] = 't'; tmp[3] = 'p'; - purple_util_fetch_url(tmp, TRUE, NULL, FALSE, theme_got_url, info); + purple_util_fetch_url(tmp, TRUE, NULL, FALSE, -1, theme_got_url, info); g_free(tmp); } else free_theme_info(info); @@ -956,7 +1031,10 @@ gtk_tree_model_get(GTK_TREE_MODEL(prefs_smiley_themes), &new_iter, 2, &new_theme, -1); purple_prefs_set_string(PIDGIN_PREFS_ROOT "/smileys/theme", new_theme); - pidgin_themes_smiley_themeize(sample_imhtml); +#if 0 +/* TODO: WebKit-ify smileys */ + pidgin_themes_smiley_themeize(sample_webview); +#endif g_free(new_theme); } @@ -1019,6 +1097,76 @@ } } +/* sets the current conversation theme variant */ +static void +prefs_set_conv_variant_cb(GtkComboBox *combo_box, gpointer user_data) +{ + PidginConvTheme *theme = NULL; + GtkTreeIter iter; + gchar *name = NULL; + + if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(prefs_conv_themes_combo_box), &iter)) { + gtk_tree_model_get(GTK_TREE_MODEL(prefs_conv_themes), &iter, 2, &name, -1); + theme = PIDGIN_CONV_THEME(purple_theme_manager_find_theme(name, "conversation")); + g_free(name); + + if (gtk_combo_box_get_active_iter(combo_box, &iter)) { + gtk_tree_model_get(GTK_TREE_MODEL(prefs_conv_variants), &iter, 0, &name, -1); + pidgin_conversation_theme_set_variant(theme, name); + g_free(name); + } + } +} + +/* sets the current conversation theme */ +static void +prefs_set_conv_theme_cb(GtkComboBox *combo_box, gpointer user_data) +{ + GtkTreeIter iter; + + if (gtk_combo_box_get_active_iter(combo_box, &iter)) { + gchar *name = NULL; + + gtk_tree_model_get(GTK_TREE_MODEL(prefs_conv_themes), &iter, 2, &name, -1); + + purple_prefs_set_string(PIDGIN_PREFS_ROOT "/conversations/theme", name); + + g_signal_handlers_block_by_func(prefs_conv_variants_combo_box, + prefs_set_conv_variant_cb, NULL); + + /* Update list of variants */ + gtk_list_store_clear(prefs_conv_variants); + + if (name && *name) { + PidginConvTheme *theme; + const char *current_variant; + const GList *variants; + gboolean unset = TRUE; + + theme = PIDGIN_CONV_THEME(purple_theme_manager_find_theme(name, "conversation")); + current_variant = pidgin_conversation_theme_get_variant(theme); + + variants = pidgin_conversation_theme_get_variants(theme); + for (; variants && current_variant; variants = g_list_next(variants)) { + gtk_list_store_append(prefs_conv_variants, &iter); + gtk_list_store_set(prefs_conv_variants, &iter, 0, variants->data, -1); + + if (g_str_equal(variants->data, current_variant)) { + gtk_combo_box_set_active_iter(GTK_COMBO_BOX(prefs_conv_variants_combo_box), &iter); + unset = FALSE; + } + } + + if (unset) + gtk_combo_box_set_active(GTK_COMBO_BOX(prefs_conv_variants_combo_box), 0); + } + + g_signal_handlers_unblock_by_func(prefs_conv_variants_combo_box, + prefs_set_conv_variant_cb, NULL); + g_free(name); + } +} + /* sets the current icon theme */ static void prefs_set_status_icon_theme_cb(GtkComboBox *combo_box, gpointer user_data) @@ -1072,6 +1220,40 @@ } static GtkWidget * +add_child_theme_prefs_combo(GtkWidget *vbox, GtkSizeGroup *combo_sg, + GtkSizeGroup *label_sg, GtkListStore *theme_store, + GCallback combo_box_cb, gpointer combo_box_cb_user_data, + const char *label_str) +{ + GtkWidget *label; + GtkWidget *combo_box; + GtkWidget *themesel_hbox; + GtkCellRenderer *cell_rend; + + themesel_hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); + gtk_box_pack_start(GTK_BOX(vbox), themesel_hbox, FALSE, FALSE, 0); + + label = gtk_label_new(label_str); + gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5); + gtk_size_group_add_widget(label_sg, label); + gtk_box_pack_start(GTK_BOX(themesel_hbox), label, FALSE, FALSE, 0); + + combo_box = gtk_combo_box_new_with_model(GTK_TREE_MODEL(theme_store)); + + cell_rend = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo_box), cell_rend, TRUE); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo_box), cell_rend, "text", 0, NULL); + g_object_set(cell_rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL); + + g_signal_connect(G_OBJECT(combo_box), "changed", + (GCallback)combo_box_cb, combo_box_cb_user_data); + gtk_size_group_add_widget(combo_sg, combo_box); + gtk_box_pack_start(GTK_BOX(themesel_hbox), combo_box, TRUE, TRUE, 0); + + return combo_box; +} + +static GtkWidget * theme_page(void) { GtkWidget *label; @@ -1101,6 +1283,20 @@ (GCallback)prefs_set_blist_theme_cb, NULL, _("Buddy List Theme:"), PIDGIN_PREFS_ROOT "/blist/theme", "blist"); + /* Conversation Themes */ + prefs_conv_themes_combo_box = add_theme_prefs_combo( + vbox, combo_sg, label_sg, prefs_conv_themes, + (GCallback)prefs_set_conv_theme_cb, NULL, + _("Conversation Theme:"), PIDGIN_PREFS_ROOT "/conversations/theme", "conversation"); + + /* Conversation Theme Variants */ + prefs_conv_variants_combo_box = add_child_theme_prefs_combo( + vbox, combo_sg, label_sg, prefs_conv_variants, + (GCallback)prefs_set_conv_variant_cb, NULL, _("\tVariant:")); + + gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(prefs_conv_variants), + 0, GTK_SORT_ASCENDING); + /* Status Icon Themes */ prefs_status_themes_combo_box = add_theme_prefs_combo( vbox, combo_sg, label_sg, prefs_status_icon_themes, @@ -1131,82 +1327,69 @@ } static void -formatting_toggle_cb(GtkIMHtml *imhtml, GtkIMHtmlButtons buttons, void *toolbar) +formatting_toggle_cb(GtkWebView *webview, GtkWebViewButtons buttons, void *toolbar) { - gboolean bold, italic, uline; - - gtk_imhtml_get_current_format(GTK_IMHTML(imhtml), - &bold, &italic, &uline); - - if (buttons & GTK_IMHTML_BOLD) - purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold", bold); - if (buttons & GTK_IMHTML_ITALIC) - purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic", italic); - if (buttons & GTK_IMHTML_UNDERLINE) - purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline", uline); - - if (buttons & GTK_IMHTML_GROW || buttons & GTK_IMHTML_SHRINK) + gboolean bold, italic, uline, strike; + + gtk_webview_get_current_format(webview, &bold, &italic, &uline, &strike); + + if (buttons & GTK_WEBVIEW_BOLD) + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold", + bold); + if (buttons & GTK_WEBVIEW_ITALIC) + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic", + italic); + if (buttons & GTK_WEBVIEW_UNDERLINE) + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline", + uline); + if (buttons & GTK_WEBVIEW_STRIKE) + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/send_strike", + strike); + + if (buttons & GTK_WEBVIEW_GROW || buttons & GTK_WEBVIEW_SHRINK) purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/font_size", - gtk_imhtml_get_current_fontsize(GTK_IMHTML(imhtml))); - if (buttons & GTK_IMHTML_FACE) { - char *face = gtk_imhtml_get_current_fontface(GTK_IMHTML(imhtml)); - if (!face) - face = g_strdup(""); - - purple_prefs_set_string(PIDGIN_PREFS_ROOT "/conversations/font_face", face); + gtk_webview_get_current_fontsize(webview)); + if (buttons & GTK_WEBVIEW_FACE) { + char *face = gtk_webview_get_current_fontface(webview); + + if (face) + purple_prefs_set_string(PIDGIN_PREFS_ROOT "/conversations/font_face", face); + else + purple_prefs_set_string(PIDGIN_PREFS_ROOT "/conversations/font_face", ""); + g_free(face); } - if (buttons & GTK_IMHTML_FORECOLOR) { - char *color = gtk_imhtml_get_current_forecolor(GTK_IMHTML(imhtml)); - if (!color) - color = g_strdup(""); - - purple_prefs_set_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor", color); - g_free(color); - } - - if (buttons & GTK_IMHTML_BACKCOLOR) { - char *color; - GObject *object; - - color = gtk_imhtml_get_current_backcolor(GTK_IMHTML(imhtml)); - if (!color) - color = g_strdup(""); - - /* Block the signal to prevent a loop. */ - object = g_object_ref(G_OBJECT(imhtml)); - g_signal_handlers_block_matched(object, G_SIGNAL_MATCH_DATA, 0, 0, NULL, - NULL, toolbar); - /* Clear the backcolor. */ - gtk_imhtml_toggle_backcolor(GTK_IMHTML(imhtml), ""); - /* Unblock the signal. */ - g_signal_handlers_unblock_matched(object, G_SIGNAL_MATCH_DATA, 0, 0, NULL, - NULL, toolbar); - g_object_unref(object); - - /* This will fire a toggle signal and get saved below. */ - gtk_imhtml_toggle_background(GTK_IMHTML(imhtml), color); + if (buttons & GTK_WEBVIEW_FORECOLOR) { + char *color = gtk_webview_get_current_forecolor(webview); + + if (color) + purple_prefs_set_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor", color); + else + purple_prefs_set_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor", ""); g_free(color); } - if (buttons & GTK_IMHTML_BACKGROUND) { - char *color = gtk_imhtml_get_current_background(GTK_IMHTML(imhtml)); - if (!color) - color = g_strdup(""); - - purple_prefs_set_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor", color); + if (buttons & GTK_WEBVIEW_BACKCOLOR) { + char *color = gtk_webview_get_current_backcolor(webview); + + if (color) + purple_prefs_set_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor", color); + else + purple_prefs_set_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor", ""); + g_free(color); } } static void -formatting_clear_cb(GtkIMHtml *imhtml, void *data) +formatting_clear_cb(GtkWebView *webview, void *data) { purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold", FALSE); purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic", FALSE); purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline", FALSE); + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/send_strike", FALSE); purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/font_size", 3); @@ -1422,7 +1605,7 @@ desc = pango_font_description_from_string(font); } - gtk_widget_modify_font(sample_imhtml, desc); + gtk_widget_modify_font(sample_webview, desc); if (desc) pango_font_description_free(desc); @@ -1446,7 +1629,7 @@ GtkWidget *toolbar; GtkWidget *iconpref1; GtkWidget *iconpref2; - GtkWidget *imhtml; + GtkWidget *webview; GtkWidget *frame; GtkWidget *hbox; GtkWidget *checkbox; @@ -1536,33 +1719,38 @@ vbox = pidgin_make_frame(ret, _("Default Formatting")); - frame = pidgin_create_imhtml(TRUE, &imhtml, &toolbar, NULL); + frame = pidgin_create_webview(TRUE, &webview, &toolbar, NULL); gtk_widget_show(frame); - gtk_widget_set_name(imhtml, "pidgin_prefs_font_imhtml"); + gtk_widget_set_name(webview, "pidgin_prefs_font_webview"); gtk_widget_set_size_request(frame, 450, -1); - gtk_imhtml_set_whole_buffer_formatting_only(GTK_IMHTML(imhtml), TRUE); - gtk_imhtml_set_format_functions(GTK_IMHTML(imhtml), - GTK_IMHTML_BOLD | - GTK_IMHTML_ITALIC | - GTK_IMHTML_UNDERLINE | - GTK_IMHTML_GROW | - GTK_IMHTML_SHRINK | - GTK_IMHTML_FACE | - GTK_IMHTML_FORECOLOR | - GTK_IMHTML_BACKCOLOR | - GTK_IMHTML_BACKGROUND); - - gtk_imhtml_append_text(GTK_IMHTML(imhtml), _("This is how your outgoing message text will appear when you use protocols that support formatting."), 0); + gtk_webview_set_whole_buffer_formatting_only(GTK_WEBVIEW(webview), TRUE); + gtk_webview_set_format_functions(GTK_WEBVIEW(webview), + GTK_WEBVIEW_BOLD | + GTK_WEBVIEW_ITALIC | + GTK_WEBVIEW_UNDERLINE | + GTK_WEBVIEW_STRIKE | + GTK_WEBVIEW_GROW | + GTK_WEBVIEW_SHRINK | + GTK_WEBVIEW_FACE | + GTK_WEBVIEW_FORECOLOR | + GTK_WEBVIEW_BACKCOLOR); + + gtk_webview_append_html(GTK_WEBVIEW(webview), + _("This is how your outgoing message text will " + "appear when you use protocols that support " + "formatting.")); gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0); - gtk_imhtml_setup_entry(GTK_IMHTML(imhtml), PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_FORMATTING_WBFO); - - g_signal_connect_after(G_OBJECT(imhtml), "format_function_toggle", - G_CALLBACK(formatting_toggle_cb), toolbar); - g_signal_connect_after(G_OBJECT(imhtml), "format_function_clear", - G_CALLBACK(formatting_clear_cb), NULL); - sample_imhtml = imhtml; + gtk_webview_setup_entry(GTK_WEBVIEW(webview), + PURPLE_CONNECTION_HTML | + PURPLE_CONNECTION_FORMATTING_WBFO); + + g_signal_connect_after(G_OBJECT(webview), "format-toggled", + G_CALLBACK(formatting_toggle_cb), toolbar); + g_signal_connect_after(G_OBJECT(webview), "format-cleared", + G_CALLBACK(formatting_clear_cb), NULL); + sample_webview = webview; gtk_widget_show(ret); @@ -2883,6 +3071,10 @@ /* Themes */ prefs_themes_init(); + /* Conversation Themes */ + purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations"); + purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/theme", "Default"); + /* Smiley Themes */ purple_prefs_add_none(PIDGIN_PREFS_ROOT "/smileys"); purple_prefs_add_string(PIDGIN_PREFS_ROOT "/smileys/theme", "Default"); @@ -2899,15 +3091,12 @@ { const char *str = NULL; - 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"); purple_prefs_rename("/purple/conversations/placement", PIDGIN_PREFS_ROOT "/conversations/placement"); - purple_prefs_rename(PIDGIN_PREFS_ROOT "/debug/timestamps", "/purple/debug/timestamps"); purple_prefs_rename(PIDGIN_PREFS_ROOT "/conversations/im/raise_on_events", "/plugins/gtk/X11/notify/method_raise"); purple_prefs_rename_boolean_toggle(PIDGIN_PREFS_ROOT "/conversations/ignore_colors", @@ -2924,12 +3113,6 @@ purple_prefs_remove(PIDGIN_PREFS_ROOT "/browsers/command"); } - /* 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"); purple_prefs_remove(PIDGIN_PREFS_ROOT "/blist/button_style"); @@ -2959,6 +3142,7 @@ purple_prefs_remove(PIDGIN_PREFS_ROOT "/conversations/ignore_fonts"); purple_prefs_remove(PIDGIN_PREFS_ROOT "/conversations/ignore_font_sizes"); purple_prefs_remove(PIDGIN_PREFS_ROOT "/conversations/passthrough_unknown_commands"); + purple_prefs_remove(PIDGIN_PREFS_ROOT "/debug/timestamps"); purple_prefs_remove(PIDGIN_PREFS_ROOT "/idle"); purple_prefs_remove(PIDGIN_PREFS_ROOT "/logging/individual_logs"); purple_prefs_remove(PIDGIN_PREFS_ROOT "/sound/signon"); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkprefs.h --- a/pidgin/gtkprefs.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkprefs.h Fri Apr 06 04:30:00 2012 +0000 @@ -29,6 +29,8 @@ #include "prefs.h" +G_BEGIN_DECLS + /** * Initializes all UI-specific preferences. */ @@ -92,8 +94,6 @@ * @return An hbox containing both the label and the entry. Can be used to set * the widgets to sensitive or insensitive based on the value of a * checkbox. - * - * @since 2.6.0 */ GtkWidget *pidgin_prefs_labeled_password(GtkWidget *page, const gchar *title, const char *key, GtkSizeGroup *sg); @@ -130,4 +130,6 @@ */ void pidgin_prefs_update_old(void); +G_END_DECLS + #endif /* _PIDGINPREFS_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkprivacy.c --- a/pidgin/gtkprivacy.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkprivacy.c Fri Apr 06 04:30:00 2012 +0000 @@ -211,7 +211,7 @@ dialog->account = account; for (i = 0; i < menu_entry_count; i++) { - if (menu_entries[i].num == account->perm_deny) { + if (menu_entries[i].num == purple_account_get_privacy_type(account)) { gtk_combo_box_set_active(GTK_COMBO_BOX(dialog->type_menu), i); break; } @@ -230,7 +230,7 @@ { int new_type = menu_entries[gtk_combo_box_get_active(combo)].num; - dialog->account->perm_deny = new_type; + purple_account_set_privacy_type(dialog->account, new_type); serv_set_permit_deny(purple_account_get_connection(dialog->account)); gtk_widget_hide(dialog->allow_widget); @@ -371,7 +371,7 @@ gtk_combo_box_append_text(GTK_COMBO_BOX(dialog->type_menu), _(menu_entries[i].text)); - if (menu_entries[i].num == dialog->account->perm_deny) + if (menu_entries[i].num == purple_account_get_privacy_type(dialog->account)) selected = i; } @@ -411,12 +411,12 @@ type_changed_cb(GTK_COMBO_BOX(dialog->type_menu), dialog); #if 0 - if (dialog->account->perm_deny == PURPLE_PRIVACY_ALLOW_USERS) { + if (purple_account_get_privacy_type(dialog->account) == PURPLE_PRIVACY_ALLOW_USERS) { gtk_widget_show(dialog->allow_widget); gtk_widget_show(dialog->button_box); dialog->in_allow_list = TRUE; } - else if (dialog->account->perm_deny == PURPLE_PRIVACY_DENY_USERS) { + else if (purple_account_get_privacy_type(dialog->account) == PURPLE_PRIVACY_DENY_USERS) { gtk_widget_show(dialog->block_widget); gtk_widget_show(dialog->button_box); dialog->in_allow_list = FALSE; diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkprivacy.h --- a/pidgin/gtkprivacy.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkprivacy.h Fri Apr 06 04:30:00 2012 +0000 @@ -28,6 +28,8 @@ #include "privacy.h" +G_BEGIN_DECLS + /** * Initializes the GTK+ privacy subsystem. */ @@ -72,4 +74,6 @@ */ PurplePrivacyUiOps *pidgin_privacy_get_ui_ops(void); +G_END_DECLS + #endif /* _PIDGINPRIVACY_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkrequest.c --- a/pidgin/gtkrequest.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkrequest.c Fri Apr 06 04:30:00 2012 +0000 @@ -39,6 +39,27 @@ #include +#ifdef ENABLE_GCR +#define GCR_API_SUBJECT_TO_CHANGE +#include +#include +#endif + +#if !GTK_CHECK_VERSION(2,18,0) +#define gtk_widget_set_can_default(x,y) do {\ + if (y) \ + GTK_WIDGET_SET_FLAGS(x, GTK_CAN_DEFAULT); \ + else \ + GTK_WIDGET_UNSET_FLAGS(x, GTK_CAN_DEFAULT); \ +} while(0) +#define gtk_widget_set_can_focus(x,y) do {\ + if (y) \ + GTK_WIDGET_SET_FLAGS(x, GTK_CAN_FOCUS); \ + else \ + GTK_WIDGET_UNSET_FLAGS(x, GTK_CAN_FOCUS); \ +} while(0) +#endif + static GtkWidget * create_account_field(PurpleRequestField *field); typedef struct @@ -86,7 +107,9 @@ { GtkWidget *image; GdkPixbuf *pixbuf; +#if !GTK_CHECK_VERSION(2,12,0) GtkTooltips *tips; +#endif if (!account) return; @@ -95,8 +118,12 @@ image = gtk_image_new_from_pixbuf(pixbuf); g_object_unref(G_OBJECT(pixbuf)); +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(image, purple_account_get_username(account)); +#else tips = gtk_tooltips_new(); gtk_tooltips_set_tip(tips, image, purple_account_get_username(account), NULL); +#endif if (GTK_IS_DIALOG(cont)) { gtk_box_pack_start(GTK_BOX(GTK_DIALOG(cont)->action_area), image, FALSE, TRUE, 0); @@ -257,7 +284,11 @@ { generic_response_start(data); +#if GTK_CHECK_VERSION(2,18,0) + if (!gtk_widget_has_focus(button)) +#else if (!GTK_WIDGET_HAS_FOCUS(button)) +#endif gtk_widget_grab_focus(button); if (data->cbs[0] != NULL) @@ -356,7 +387,9 @@ gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER/2); if (!multiline) gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); +#if !GTK_CHECK_VERSION(2,22,0) gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); +#endif gtk_dialog_set_default_response(GTK_DIALOG(dialog), 0); gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER); @@ -522,7 +555,9 @@ gtk_container_set_border_width(GTK_CONTAINER(dialog), PIDGIN_HIG_BORDER/2); gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER/2); gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); +#if !GTK_CHECK_VERSION(2,22,0) gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); +#endif gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER); /* Setup the main horizontal box */ @@ -644,7 +679,9 @@ gtk_container_set_border_width(GTK_CONTAINER(dialog), PIDGIN_HIG_BORDER/2); gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER/2); gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); +#if !GTK_CHECK_VERSION(2,22,0) gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); +#endif gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER); /* Setup the main horizontal box */ @@ -715,8 +752,8 @@ if (default_action == PURPLE_DEFAULT_ACTION_NONE) { - GTK_WIDGET_SET_FLAGS(img, GTK_CAN_DEFAULT); - GTK_WIDGET_SET_FLAGS(img, GTK_CAN_FOCUS); + gtk_widget_set_can_default(img, TRUE); + gtk_widget_set_can_focus(img, TRUE); gtk_widget_grab_focus(img); gtk_widget_grab_default(img); } else @@ -749,6 +786,7 @@ req_entry_field_changed_cb(GtkWidget *entry, PurpleRequestField *field) { PurpleRequestFieldGroup *group; + PurpleRequestFields *fields; PidginRequestData *req_data; if (purple_request_field_string_is_multiline(field)) @@ -771,10 +809,11 @@ } group = purple_request_field_get_group(field); - req_data = (PidginRequestData *)group->fields_list->ui_data; + fields = purple_request_field_group_get_fields_list(group); + req_data = purple_request_fields_get_ui_data(fields); gtk_widget_set_sensitive(req_data->ok_button, - purple_request_fields_all_required_filled(group->fields_list)); + purple_request_fields_all_required_filled(fields)); } static void @@ -796,7 +835,7 @@ { GtkWidget *optmenu = NULL; PurpleRequestFieldGroup *group = purple_request_field_get_group(field); - GList *fields = group->fields; + GList *fields = purple_request_field_group_get_fields(group); /* Ensure the account option menu is created (if the widget hasn't * been initialized already) for username auto-completion. */ @@ -857,6 +896,10 @@ gtk_text_buffer_set_text(buffer, value, -1); } +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(textview, purple_request_field_get_tooltip(field)); +#endif + gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), purple_request_field_string_is_editable(field)); @@ -881,6 +924,10 @@ if (value != NULL) gtk_entry_set_text(GTK_ENTRY(widget), value); +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field)); +#endif + if (purple_request_field_string_is_masked(field)) { gtk_entry_set_visibility(GTK_ENTRY(widget), FALSE); @@ -921,6 +968,10 @@ gtk_entry_set_text(GTK_ENTRY(widget), buf); } +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field)); +#endif + g_signal_connect(G_OBJECT(widget), "focus-out-event", G_CALLBACK(field_int_focus_out_cb), field); @@ -935,6 +986,10 @@ widget = gtk_check_button_new_with_label( purple_request_field_get_label(field)); +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field)); +#endif + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), purple_request_field_bool_get_default_value(field)); @@ -965,6 +1020,10 @@ gtk_combo_box_set_active(GTK_COMBO_BOX(widget), purple_request_field_choice_get_default_value(field)); +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field)); +#endif + g_signal_connect(G_OBJECT(widget), "changed", G_CALLBACK(field_choice_menu_cb), field); } @@ -982,6 +1041,10 @@ widget = box; +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field)); +#endif + for (l = labels, i = 0; l != NULL; l = l->next, i++) { const char *text = l->data; @@ -1024,6 +1087,10 @@ g_object_unref(G_OBJECT(buf)); g_object_unref(G_OBJECT(scale)); +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field)); +#endif + return widget; } @@ -1039,6 +1106,10 @@ purple_request_field_account_get_filter(field), field); +#if GTK_CHECK_VERSION(2,12,0) + gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field)); +#endif + return widget; } @@ -1157,6 +1228,51 @@ return pidgin_make_scrollable(treeview, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_IN, -1, -1); } +static GtkWidget * +create_certificate_field(PurpleRequestField *field) +{ + PurpleCertificate *cert; +#ifdef ENABLE_GCR + GcrCertificateBasicsWidget *cert_widget; + GByteArray *der; + GcrCertificate *gcrt; +#else + GtkWidget *cert_label; + char *str; + char *escaped; +#endif + + cert = purple_request_field_certificate_get_value(field); + +#ifdef ENABLE_GCR + der = purple_certificate_get_der_data(cert); + g_return_val_if_fail(der, NULL); + + gcrt = gcr_simple_certificate_new(der->data, der->len); + g_return_val_if_fail(gcrt, NULL); + + cert_widget = gcr_certificate_basics_widget_new(gcrt); + + g_byte_array_free(der, TRUE); + g_object_unref(G_OBJECT(gcrt)); + + return GTK_WIDGET(cert_widget); +#else + str = purple_certificate_get_display_string(cert); + escaped = g_markup_escape_text(str, -1); + + cert_label = gtk_label_new(NULL); + gtk_label_set_markup(GTK_LABEL(cert_label), escaped); + gtk_label_set_line_wrap(GTK_LABEL(cert_label), TRUE); + gtk_misc_set_alignment(GTK_MISC(cert_label), 0, 0); + + g_free(str); + g_free(escaped); + + return cert_label; +#endif +} + static void * pidgin_request_fields(const char *title, const char *primary, const char *secondary, PurpleRequestFields *fields, @@ -1188,7 +1304,7 @@ data->user_data = user_data; data->u.multifield.fields = fields; - fields->ui_data = data; + purple_request_fields_set_ui_data(fields, data); data->cb_count = 2; data->cbs = g_new0(GCallback, 2); @@ -1220,12 +1336,12 @@ /* Cancel button */ button = pidgin_dialog_add_button(GTK_DIALOG(win), text_to_stock(cancel_text), G_CALLBACK(multifield_cancel_cb), data); - GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); + gtk_widget_set_can_default(button, TRUE); /* OK button */ button = pidgin_dialog_add_button(GTK_DIALOG(win), text_to_stock(ok_text), G_CALLBACK(multifield_ok_cb), data); data->ok_button = button; - GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); + gtk_widget_set_can_default(button, TRUE); gtk_window_set_default(GTK_WINDOW(win), button); pidgin_widget_decorate_account(hbox, account); @@ -1444,6 +1560,8 @@ widget = create_image_field(field); else if (type == PURPLE_REQUEST_FIELD_ACCOUNT) widget = create_account_field(field); + else if (type == PURPLE_REQUEST_FIELD_CERTIFICATE) + widget = create_certificate_field(field); else continue; } diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkrequest.h --- a/pidgin/gtkrequest.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkrequest.h Fri Apr 06 04:30:00 2012 +0000 @@ -28,6 +28,8 @@ #include "request.h" +G_BEGIN_DECLS + /** * Returns the UI operations structure for GTK+ request functions. * @@ -35,4 +37,6 @@ */ PurpleRequestUiOps *pidgin_request_get_ui_ops(void); +G_END_DECLS + #endif /* _PIDGINREQUEST_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkroomlist.c --- a/pidgin/gtkroomlist.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkroomlist.c Fri Apr 06 04:30:00 2012 +0000 @@ -91,7 +91,7 @@ purple_timeout_remove(dialog->pg_update_to); if (dialog->roomlist) { - PidginRoomlist *rl = dialog->roomlist->ui_data; + PidginRoomlist *rl = purple_roomlist_get_ui_data(dialog->roomlist); if (dialog->pg_update_to > 0) /* yes, that's right, unref it twice. */ @@ -115,7 +115,7 @@ dialog->account = account; if (change && dialog->roomlist) { - PidginRoomlist *rl = dialog->roomlist->ui_data; + PidginRoomlist *rl = purple_roomlist_get_ui_data(dialog->roomlist); if (rl->tree) { gtk_widget_destroy(rl->tree); rl->tree = NULL; @@ -135,7 +135,7 @@ return; if (dialog->roomlist != NULL) { - rl = dialog->roomlist->ui_data; + rl = purple_roomlist_get_ui_data(dialog->roomlist); gtk_widget_destroy(rl->tree); purple_roomlist_unref(dialog->roomlist); } @@ -144,7 +144,7 @@ if (!dialog->roomlist) return; purple_roomlist_ref(dialog->roomlist); - rl = dialog->roomlist->ui_data; + rl = purple_roomlist_get_ui_data(dialog->roomlist); rl->dialog = dialog; if (dialog->account_widget) @@ -203,7 +203,7 @@ val.g_type = 0; gtk_tree_model_get_value(GTK_TREE_MODEL(grl->model), &iter, ROOM_COLUMN, &val); room = g_value_get_pointer(&val); - if (!room || !(room->type & PURPLE_ROOMLIST_ROOMTYPE_ROOM)) { + if (!room || !(purple_roomlist_room_get_type(room) & PURPLE_ROOMLIST_ROOMTYPE_ROOM)) { gtk_widget_set_sensitive(dialog->join_button, FALSE); gtk_widget_set_sensitive(dialog->add_button, FALSE); return; @@ -228,18 +228,19 @@ static void do_add_room_cb(GtkWidget *w, struct _menu_cb_info *info) { char *name; - PurpleConnection *gc = purple_account_get_connection(info->list->account); + PurpleAccount *account = purple_roomlist_get_account(info->list); + PurpleConnection *gc = purple_account_get_connection(account); PurplePluginProtocolInfo *prpl_info = NULL; if(gc != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if(prpl_info != NULL && prpl_info->roomlist_room_serialize) name = prpl_info->roomlist_room_serialize(info->room); else - name = g_strdup(info->room->name); + name = g_strdup(purple_roomlist_room_get_name(info->room)); - purple_blist_request_add_chat(info->list->account, NULL, NULL, name); + purple_blist_request_add_chat(account, NULL, NULL, name); g_free(name); } @@ -247,7 +248,7 @@ static void add_room_to_blist_cb(GtkButton *button, PidginRoomlistDialog *dialog) { PurpleRoomlist *rl = dialog->roomlist; - PidginRoomlist *grl = rl->ui_data; + PidginRoomlist *grl = purple_roomlist_get_ui_data(rl); struct _menu_cb_info *info = g_object_get_data(G_OBJECT(button), "room-info"); if(info != NULL) @@ -262,7 +263,7 @@ static void join_button_cb(GtkButton *button, PidginRoomlistDialog *dialog) { PurpleRoomlist *rl = dialog->roomlist; - PidginRoomlist *grl = rl->ui_data; + PidginRoomlist *grl = purple_roomlist_get_ui_data(rl); struct _menu_cb_info *info = g_object_get_data(G_OBJECT(button), "room-info"); if(info != NULL) @@ -272,7 +273,7 @@ static void row_activated_cb(GtkTreeView *tv, GtkTreePath *path, GtkTreeViewColumn *arg2, PurpleRoomlist *list) { - PidginRoomlist *grl = list->ui_data; + PidginRoomlist *grl = purple_roomlist_get_ui_data(list); GtkTreeIter iter; PurpleRoomlistRoom *room; GValue val; @@ -282,7 +283,7 @@ val.g_type = 0; gtk_tree_model_get_value(GTK_TREE_MODEL(grl->model), &iter, ROOM_COLUMN, &val); room = g_value_get_pointer(&val); - if (!room || !(room->type & PURPLE_ROOMLIST_ROOMTYPE_ROOM)) + if (!room || !(purple_roomlist_room_get_type(room) & PURPLE_ROOMLIST_ROOMTYPE_ROOM)) return; info.list = list; @@ -294,7 +295,7 @@ static gboolean room_click_cb(GtkWidget *tv, GdkEventButton *event, PurpleRoomlist *list) { GtkTreePath *path; - PidginRoomlist *grl = list->ui_data; + PidginRoomlist *grl = purple_roomlist_get_ui_data(list); GValue val; PurpleRoomlistRoom *room; GtkTreeIter iter; @@ -313,7 +314,7 @@ gtk_tree_model_get_value (GTK_TREE_MODEL(grl->model), &iter, ROOM_COLUMN, &val); room = g_value_get_pointer(&val); - if (!room || !(room->type & PURPLE_ROOMLIST_ROOMTYPE_ROOM)) + if (!room || !(purple_roomlist_room_get_type(room) & PURPLE_ROOMLIST_ROOMTYPE_ROOM)) return FALSE; info.list = list; @@ -341,9 +342,9 @@ gtk_tree_model_get_value(gtk_tree_view_get_model(treeview), arg1, ROOM_COLUMN, &val); category = g_value_get_pointer(&val); - if (!category->expanded_once) { + if (!purple_roomlist_room_get_expanded_once(category)) { purple_roomlist_expand_category(list, category); - category->expanded_once = TRUE; + purple_roomlist_room_set_expanded_once(category, TRUE); } } @@ -354,7 +355,7 @@ pidgin_roomlist_paint_tooltip(GtkWidget *widget, gpointer user_data) { PurpleRoomlist *list = user_data; - PidginRoomlist *grl = list->ui_data; + PidginRoomlist *grl = purple_roomlist_get_ui_data(list); GtkStyle *style; int current_height, max_width; int max_text_width; @@ -393,7 +394,7 @@ static gboolean pidgin_roomlist_create_tip(PurpleRoomlist *list, GtkTreePath *path) { - PidginRoomlist *grl = list->ui_data; + PidginRoomlist *grl = purple_roomlist_get_ui_data(list); PurpleRoomlistRoom *room; GtkTreeIter iter; GValue val; @@ -414,19 +415,23 @@ gtk_tree_model_get_value(GTK_TREE_MODEL(grl->model), &iter, ROOM_COLUMN, &val); room = g_value_get_pointer(&val); - if (!room || !(room->type & PURPLE_ROOMLIST_ROOMTYPE_ROOM)) + if (!room || !(purple_roomlist_room_get_type(room) & PURPLE_ROOMLIST_ROOMTYPE_ROOM)) return FALSE; tooltip_text = g_string_new(""); gtk_tree_model_get(GTK_TREE_MODEL(grl->model), &iter, NAME_COLUMN, &name, -1); - for (j = NUM_OF_COLUMNS, l = room->fields, k = list->fields; l && k; j++, l = l->next, k = k->next) { + for (j = NUM_OF_COLUMNS, + l = purple_roomlist_room_get_fields(room), + k = purple_roomlist_get_fields(list); + l && k; j++, l = l->next, k = k->next) + { PurpleRoomlistField *f = k->data; gchar *label; - if (f->hidden) + if (purple_roomlist_field_get_hidden(f)) continue; - label = g_markup_escape_text(f->label, -1); - switch (f->type) { + label = g_markup_escape_text(purple_roomlist_field_get_label(f), -1); + switch (purple_roomlist_field_get_type(f)) { case PURPLE_ROOMLIST_FIELD_BOOL: g_string_append_printf(tooltip_text, "%s%s: %s", first ? "" : "\n", label, l->data ? "True" : "False"); break; @@ -478,7 +483,7 @@ gpointer data, int *w, int *h) { PurpleRoomlist *list = data; - PidginRoomlist *grl = list->ui_data; + PidginRoomlist *grl = purple_roomlist_get_ui_data(list); grl->tipwindow = widget; if (!pidgin_roomlist_create_tip(data, path)) return FALSE; @@ -497,7 +502,7 @@ PurplePluginProtocolInfo *prpl_info = NULL; if (conn && PURPLE_CONNECTION_IS_CONNECTED(conn)) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(conn->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(conn)); return (prpl_info && prpl_info->roomlist_get_list != NULL); } @@ -622,7 +627,7 @@ { PidginRoomlist *rl = g_new0(PidginRoomlist, 1); - list->ui_data = rl; + purple_roomlist_set_ui_data(list, rl); rl->cats = g_hash_table_new_full(NULL, NULL, NULL, (GDestroyNotify)gtk_tree_row_reference_free); @@ -685,7 +690,7 @@ static void pidgin_roomlist_set_fields(PurpleRoomlist *list, GList *fields) { - PidginRoomlist *grl = list->ui_data; + PidginRoomlist *grl = purple_roomlist_get_ui_data(list); gint columns = NUM_OF_COLUMNS; int j; GtkTreeStore *model; @@ -707,7 +712,7 @@ for (j = NUM_OF_COLUMNS, l = fields; l; l = l->next, j++) { PurpleRoomlistField *f = l->data; - switch (f->type) { + switch (purple_roomlist_field_get_type(f)) { case PURPLE_ROOMLIST_FIELD_BOOL: types[j] = G_TYPE_BOOLEAN; break; @@ -749,18 +754,19 @@ for (j = NUM_OF_COLUMNS, l = fields; l; l = l->next, j++) { PurpleRoomlistField *f = l->data; - if (f->hidden) + if (purple_roomlist_field_get_hidden(f)) continue; renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes(f->label, renderer, - "text", j, NULL); + column = gtk_tree_view_column_new_with_attributes( + purple_roomlist_field_get_label(f), renderer, + "text", j, NULL); gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column), GTK_TREE_VIEW_COLUMN_GROW_ONLY); gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE); gtk_tree_view_column_set_sort_column_id(GTK_TREE_VIEW_COLUMN(column), j); gtk_tree_view_column_set_reorderable(GTK_TREE_VIEW_COLUMN(column), TRUE); - if (f->type == PURPLE_ROOMLIST_FIELD_INT) { + if (purple_roomlist_field_get_type(f) == PURPLE_ROOMLIST_FIELD_INT) { gtk_tree_view_column_set_cell_data_func(column, renderer, int_cell_data_func, GINT_TO_POINTER(j), NULL); gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(model), j, int_sort_func, @@ -789,7 +795,7 @@ static gboolean pidgin_progress_bar_pulse(gpointer data) { PurpleRoomlist *list = data; - PidginRoomlist *rl = list->ui_data; + PidginRoomlist *rl = purple_roomlist_get_ui_data(list); if (!rl || !rl->dialog || !rl->dialog->pg_needs_pulse) { if (rl && rl->dialog) @@ -805,7 +811,7 @@ static void pidgin_roomlist_add_room(PurpleRoomlist *list, PurpleRoomlistRoom *room) { - PidginRoomlist *rl = list->ui_data; + PidginRoomlist *rl = purple_roomlist_get_ui_data(list); GtkTreeRowReference *rr, *parentrr = NULL; GtkTreePath *path; GtkTreeIter iter, parent, child; @@ -814,7 +820,7 @@ gboolean append = TRUE; rl->total_rooms++; - if (room->type == PURPLE_ROOMLIST_ROOMTYPE_ROOM) + if (purple_roomlist_room_get_type(room) == PURPLE_ROOMLIST_ROOMTYPE_ROOM) rl->num_rooms++; if (rl->dialog) { @@ -826,8 +832,8 @@ rl->dialog->pg_needs_pulse = TRUE; } - if (room->parent) { - parentrr = g_hash_table_lookup(rl->cats, room->parent); + if (purple_roomlist_room_get_parent(room)) { + parentrr = g_hash_table_lookup(rl->cats, purple_roomlist_room_get_parent(room)); path = gtk_tree_row_reference_get_path(parentrr); if (path) { PurpleRoomlistRoom *tmproom = NULL; @@ -848,24 +854,28 @@ else iter = child; - if (room->type & PURPLE_ROOMLIST_ROOMTYPE_CATEGORY) + if (purple_roomlist_room_get_type(room) & PURPLE_ROOMLIST_ROOMTYPE_CATEGORY) gtk_tree_store_append(rl->model, &child, &iter); path = gtk_tree_model_get_path(GTK_TREE_MODEL(rl->model), &iter); - if (room->type & PURPLE_ROOMLIST_ROOMTYPE_CATEGORY) { + if (purple_roomlist_room_get_type(room) & PURPLE_ROOMLIST_ROOMTYPE_CATEGORY) { rr = gtk_tree_row_reference_new(GTK_TREE_MODEL(rl->model), path); g_hash_table_insert(rl->cats, room, rr); } gtk_tree_path_free(path); - gtk_tree_store_set(rl->model, &iter, NAME_COLUMN, room->name, -1); + gtk_tree_store_set(rl->model, &iter, NAME_COLUMN, purple_roomlist_room_get_name(room), -1); gtk_tree_store_set(rl->model, &iter, ROOM_COLUMN, room, -1); - for (j = NUM_OF_COLUMNS, l = room->fields, k = list->fields; l && k; j++, l = l->next, k = k->next) { + for (j = NUM_OF_COLUMNS, + l = purple_roomlist_room_get_fields(room), + k = purple_roomlist_get_fields(list); + l && k; j++, l = l->next, k = k->next) + { PurpleRoomlistField *f = k->data; - if (f->hidden) + if (purple_roomlist_field_get_hidden(f)) continue; gtk_tree_store_set(rl->model, &iter, j, l->data, -1); } @@ -873,7 +883,7 @@ static void pidgin_roomlist_in_progress(PurpleRoomlist *list, gboolean in_progress) { - PidginRoomlist *rl = list->ui_data; + PidginRoomlist *rl = purple_roomlist_get_ui_data(list); if (!rl || !rl->dialog) return; @@ -895,7 +905,7 @@ static void pidgin_roomlist_destroy(PurpleRoomlist *list) { - PidginRoomlist *rl = list->ui_data; + PidginRoomlist *rl = purple_roomlist_get_ui_data(list); roomlists = g_list_remove(roomlists, list); @@ -903,7 +913,7 @@ g_hash_table_destroy(rl->cats); g_free(rl); - list->ui_data = NULL; + purple_roomlist_set_ui_data(list, NULL); } static PurpleRoomlistUiOps ops = { diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkroomlist.h --- a/pidgin/gtkroomlist.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkroomlist.h Fri Apr 06 04:30:00 2012 +0000 @@ -28,6 +28,8 @@ #include "roomlist.h" +G_BEGIN_DECLS + /** * Initializes the room list subsystem. */ @@ -53,4 +55,6 @@ */ void pidgin_roomlist_dialog_show_with_account(PurpleAccount *account); +G_END_DECLS + #endif /* _PIDGINROOMLIST_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtksavedstatuses.c --- a/pidgin/gtksavedstatuses.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtksavedstatuses.c Fri Apr 06 04:30:00 2012 +0000 @@ -524,7 +524,11 @@ static gboolean configure_cb(GtkWidget *widget, GdkEventConfigure *event, StatusWindow *dialog) { +#if GTK_CHECK_VERSION(2,18,0) + if (gtk_widget_get_visible(widget)) +#else if (GTK_WIDGET_VISIBLE(widget)) +#endif { purple_prefs_set_int(PIDGIN_PREFS_ROOT "/status/dialog/width", event->width); purple_prefs_set_int(PIDGIN_PREFS_ROOT "/status/dialog/height", event->height); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtksavedstatuses.h --- a/pidgin/gtksavedstatuses.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtksavedstatuses.h Fri Apr 06 04:30:00 2012 +0000 @@ -29,6 +29,8 @@ #include "savedstatuses.h" #include "status.h" +G_BEGIN_DECLS + /** * Shows the status window. */ @@ -85,4 +87,6 @@ */ void pidgin_status_uninit(void); +G_END_DECLS + #endif /* _PIDGINSAVEDSTATUSES_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkscrollbook.c --- a/pidgin/gtkscrollbook.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkscrollbook.c Fri Apr 06 04:30:00 2012 +0000 @@ -147,7 +147,7 @@ } static void -switch_page_cb(GtkNotebook *notebook, GtkNotebookPage *page, guint page_num, PidginScrollBook *scroll_book) +switch_page_cb(GtkNotebook *notebook, GtkWidget *page, guint page_num, PidginScrollBook *scroll_book) { int count; count = gtk_notebook_get_n_pages(GTK_NOTEBOOK(scroll_book->notebook)); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtksession.h --- a/pidgin/gtksession.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtksession.h Fri Apr 06 04:30:00 2012 +0000 @@ -26,6 +26,8 @@ #ifndef _PIDGINSESSION_H_ #define _PIDGINSESSION_H_ +G_BEGIN_DECLS + /**************************************************************************/ /** @name X Windows session subsystem */ /**************************************************************************/ @@ -51,4 +53,6 @@ /*@}*/ +G_END_DECLS + #endif /* _PIDGINSESSION_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtksmiley.c --- a/pidgin/gtksmiley.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtksmiley.c Fri Apr 06 04:30:00 2012 +0000 @@ -47,9 +47,9 @@ GtkWidget *smiley_image; gchar *filename; GdkPixbuf *custom_pixbuf; - gpointer data; /** @since 2.6.0 */ - gsize datasize; /** @since 2.6.0 */ - gint entry_len; /** @since 2.6.0 */ + gpointer data; + gsize datasize; + gint entry_len; }; typedef struct @@ -750,7 +750,7 @@ } else if (!g_ascii_strncasecmp(name, "http://", 7)) { /* Oo, a web drag and drop. This is where things * will start to get interesting */ - purple_util_fetch_url(name, TRUE, NULL, FALSE, smiley_got_url, dialog); + purple_util_fetch_url(name, TRUE, NULL, FALSE, -1, smiley_got_url, dialog); } else if (!g_ascii_strncasecmp(name, "https://", 8)) { /* purple_util_fetch_url() doesn't support HTTPS */ char *tmp = g_strdup(name + 1); @@ -759,7 +759,7 @@ tmp[2] = 't'; tmp[3] = 'p'; - purple_util_fetch_url(tmp, TRUE, NULL, FALSE, smiley_got_url, dialog); + purple_util_fetch_url(tmp, TRUE, NULL, FALSE, -1, smiley_got_url, dialog); g_free(tmp); } diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtksmiley.h --- a/pidgin/gtksmiley.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtksmiley.h Fri Apr 06 04:30:00 2012 +0000 @@ -1,7 +1,6 @@ /** * @file gtksmiley.h GTK+ Custom Smiley API * @ingroup pidgin - * @since 2.5.0 */ /* pidgin @@ -32,6 +31,8 @@ typedef struct _PidginSmiley PidginSmiley; +G_BEGIN_DECLS + /** * Add a PurpleSmiley to the GtkIMHtmlSmiley's list to be able to use it * in pidgin @@ -106,9 +107,9 @@ * @param editor A smiley editor dialog * @param data A pointer to smiley's data * @param datasize The size of smiley's data - * - * @since 2.6.0 */ void pidgin_smiley_editor_set_data(PidginSmiley *editor, gpointer data, gsize datasize); +G_END_DECLS + #endif /* PIDGIN_GTKSMILEY_H */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtksound.c --- a/pidgin/gtksound.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtksound.c Fri Apr 06 04:30:00 2012 +0000 @@ -96,8 +96,8 @@ if (chat==NULL) return ret; - nick = g_strdup(purple_normalize(conv->account, chat->nick)); - name = g_strdup(purple_normalize(conv->account, aname)); + nick = g_strdup(purple_normalize(purple_conversation_get_account(conv), purple_conv_chat_get_nick(chat))); + name = g_strdup(purple_normalize(purple_conversation_get_account(conv), aname)); if (g_utf8_collate(nick, name) == 0) ret = TRUE; @@ -212,7 +212,7 @@ if (chat_nick_matches_name(conv, sender)) return; - if (flags & PURPLE_MESSAGE_NICK || purple_utf8_has_word(message, chat->nick)) + if (flags & PURPLE_MESSAGE_NICK || purple_utf8_has_word(message, purple_conv_chat_get_nick(chat))) /* This isn't quite right; if you have the PURPLE_SOUND_CHAT_NICK event disabled * and the PURPLE_SOUND_CHAT_SAY event enabled, you won't get a sound at all */ play_conv_event(conv, PURPLE_SOUND_CHAT_NICK); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtksound.h --- a/pidgin/gtksound.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtksound.h Fri Apr 06 04:30:00 2012 +0000 @@ -28,6 +28,8 @@ #include "sound.h" +G_BEGIN_DECLS + /**************************************************************************/ /** @name GTK+ Sound API */ /**************************************************************************/ @@ -67,11 +69,11 @@ * Returns true Pidgin is using customized sounds * * @return TRUE if non default sounds are used. - * - * @since 2.6.0 */ gboolean pidgin_sound_is_customized(void); /*@}*/ +G_END_DECLS + #endif /* _PIDGINSOUND_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtksourceundomanager.h --- a/pidgin/gtksourceundomanager.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtksourceundomanager.h Fri Apr 06 04:30:00 2012 +0000 @@ -57,6 +57,8 @@ void (*can_redo) (GtkSourceUndoManager *um, gboolean can_redo); }; +G_BEGIN_DECLS + GType gtk_source_undo_manager_get_type (void) G_GNUC_CONST; GtkSourceUndoManager* gtk_source_undo_manager_new (GtkTextBuffer *buffer); @@ -78,6 +80,8 @@ (GtkSourceUndoManager *um, gint undo_levels); +G_END_DECLS + #endif /* __GTK_SOURCE_UNDO_MANAGER_H__ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkstatusbox.c --- a/pidgin/gtkstatusbox.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkstatusbox.c Fri Apr 06 04:30:00 2012 +0000 @@ -70,6 +70,16 @@ /* Timeout for typing notifications in seconds */ #define TYPING_TIMEOUT 4 +#if !GTK_CHECK_VERSION(2,18,0) +#define gtk_widget_is_sensitive(x) GTK_WIDGET_IS_SENSITIVE(x) +#define gtk_widget_set_has_window(x, y) do { \ + if (y) \ + GTK_WIDGET_UNSET_FLAGS(x, GTK_WIDGET_NO_WINDOW); \ + else \ + GTK_WIDGET_SET_FLAGS(x, GTK_WIDGET_NO_WINDOW); \ +} while (0) +#endif + static void imhtml_changed_cb(GtkTextBuffer *buffer, void *data); static void imhtml_format_changed_cb(GtkIMHtml *imhtml, GtkIMHtmlButtons buttons, void *data); static void remove_typing_cb(PidginStatusBox *box); @@ -412,7 +422,7 @@ if (src == NULL) return FALSE; - purple_util_fetch_url(src, TRUE, NULL, FALSE, statusbox_got_url, data); + purple_util_fetch_url(src, TRUE, NULL, FALSE, -1, statusbox_got_url, data); return TRUE; } @@ -1749,7 +1759,7 @@ GtkWidget *toplevel; GtkTreeSelection *sel; - GTK_WIDGET_SET_FLAGS (status_box, GTK_NO_WINDOW); + gtk_widget_set_has_window(GTK_WIDGET(status_box), FALSE); status_box->imhtml_visible = FALSE; status_box->network_available = purple_network_is_available(); status_box->connecting = FALSE; @@ -2625,7 +2635,7 @@ purple_timeout_remove(status_box->typing); status_box->typing = 0; - if (GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET(status_box))) + if (gtk_widget_is_sensitive(GTK_WIDGET(status_box))) { if (type == PIDGIN_STATUS_BOX_TYPE_POPULAR || type == PIDGIN_STATUS_BOX_TYPE_SAVED_POPULAR) { @@ -2687,7 +2697,7 @@ } g_list_free(accounts); - if (GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET(status_box))) + if (gtk_widget_is_sensitive(GTK_WIDGET(status_box))) { if (status_box->imhtml_visible) { @@ -2743,7 +2753,7 @@ static void imhtml_changed_cb(GtkTextBuffer *buffer, void *data) { PidginStatusBox *status_box = (PidginStatusBox*)data; - if (GTK_WIDGET_IS_SENSITIVE(GTK_WIDGET(status_box))) + if (gtk_widget_is_sensitive(GTK_WIDGET(status_box))) { if (status_box->typing != 0) { pidgin_status_box_pulse_typing(status_box); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkthemes.c --- a/pidgin/gtkthemes.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkthemes.c Fri Apr 06 04:30:00 2012 +0000 @@ -122,6 +122,8 @@ static void _pidgin_themes_smiley_themeize(GtkWidget *imhtml, gboolean custom) { + /* TODO WEBKIT: move imhtml dependency to use webview. */ +#if 0 struct smiley_list *list; if (!current_smiley_theme) return; @@ -147,6 +149,7 @@ list = list->next; } +#endif /* if 0 */ } void pidgin_themes_smiley_themeize(GtkWidget *imhtml) @@ -278,6 +281,8 @@ if (*i == '[' && strchr(i, ']') && load) { struct smiley_list *child = g_new0(struct smiley_list, 1); child->sml = g_strndup(i+1, strchr(i, ']') - i - 1); + child->files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + if (theme->list) list->next = child; else @@ -320,6 +325,7 @@ } else { GtkIMHtmlSmiley *smiley = gtk_imhtml_smiley_create(sfile, l, hidden, 0); list->smileys = g_slist_prepend(list->smileys, smiley); + g_hash_table_insert (list->files, g_strdup(l), g_strdup(sfile)); } while (isspace(*i)) i++; @@ -358,7 +364,6 @@ if (PIDGIN_IS_PIDGIN_CONVERSATION(conv)) { /* We want to see our custom smileys on our entry if we write the shortcut */ - pidgin_themes_smiley_themeize(PIDGIN_CONVERSATION(conv)->imhtml); pidgin_themes_smiley_themeize_custom(PIDGIN_CONVERSATION(conv)->entry); } } diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkthemes.h --- a/pidgin/gtkthemes.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkthemes.h Fri Apr 06 04:30:00 2012 +0000 @@ -29,6 +29,7 @@ struct smiley_list { char *sml; GSList *smileys; + GHashTable *files; /**< map from smiley shortcut to filename */ struct smiley_list *next; }; @@ -45,26 +46,24 @@ extern struct smiley_theme *current_smiley_theme; extern GSList *smiley_themes; +G_BEGIN_DECLS + void pidgin_themes_init(void); gboolean pidgin_themes_smileys_disabled(void); void pidgin_themes_smiley_themeize(GtkWidget *); -/** - * @since 2.5.0 - */ void pidgin_themes_smiley_themeize_custom(GtkWidget *); void pidgin_themes_smiley_theme_probe(void); void pidgin_themes_load_smiley_theme(const char *file, gboolean load); -/** - * @since 2.1.0 - */ void pidgin_themes_remove_smiley_theme(const char *file); GSList *pidgin_themes_get_proto_smileys(const char *id); +G_END_DECLS + #endif /* _PIDGINTHEMES_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkutils.c --- a/pidgin/gtkutils.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkutils.c Fri Apr 06 04:30:00 2012 +0000 @@ -67,10 +67,24 @@ #include "pidginstock.h" #include "gtkthemes.h" #include "gtkutils.h" +#include "gtkwebview.h" +#include "gtkwebviewtoolbar.h" #include "pidgin/minidialog.h" +#if !GTK_CHECK_VERSION(2,18,0) +#define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE(x) +#define gtk_widget_is_sensitive(x) GTK_WIDGET_IS_SENSITIVE(x) +#endif + +enum { + AOP_ICON_COLUMN, + AOP_NAME_COLUMN, + AOP_DATA_COLUMN, + AOP_COLUMN_COUNT +}; + typedef struct { - GtkWidget *menu; + GtkTreeModel *model; gint default_item; } AopMenu; @@ -126,6 +140,32 @@ } +void +pidgin_setup_webview(GtkWidget *webview) +{ + g_return_if_fail(webview != NULL); + g_return_if_fail(GTK_IS_WEBVIEW(webview)); + +#if 0 +/* TODO: WebKit this stuff... */ + pidgin_themes_smiley_themeize(webview); +#endif + +#ifdef _WIN32 + if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/use_theme_font")) { + WebKitWebSettings *settings = webkit_web_settings_new(); + g_object_set(G_OBJECT(settings), "default-font-size", + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/font_size"), + NULL); + g_object_set(G_OBJECT(settings), "default-font-family", + purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/custom_font"), + NULL); + + webkit_web_view_set_settings(WEBKIT_WEB_VIEW(webview), settings); + } +#endif +} + static void pidgin_window_init(GtkWindow *wnd, const char *title, guint border_width, const char *role, gboolean resizable) { @@ -276,6 +316,67 @@ return frame; } +GtkWidget * +pidgin_create_webview(gboolean editable, GtkWidget **webview_ret, GtkWidget **toolbar_ret, GtkWidget **sw_ret) +{ + GtkWidget *frame; + GtkWidget *webview; + GtkWidget *sep; + GtkWidget *sw; + GtkWidget *toolbar = NULL; + GtkWidget *vbox; + + frame = gtk_frame_new(NULL); + gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); + + vbox = gtk_vbox_new(FALSE, 0); + gtk_container_add(GTK_CONTAINER(frame), vbox); + gtk_widget_show(vbox); + + if (editable) { + toolbar = gtk_webviewtoolbar_new(); + gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0); + gtk_widget_show(toolbar); + + sep = gtk_hseparator_new(); + gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, 0); + g_signal_connect_swapped(G_OBJECT(toolbar), "show", G_CALLBACK(gtk_widget_show), sep); + g_signal_connect_swapped(G_OBJECT(toolbar), "hide", G_CALLBACK(gtk_widget_hide), sep); + gtk_widget_show(sep); + } + + webview = gtk_webview_new(); + gtk_webview_set_editable(GTK_WEBVIEW(webview), editable); +#ifdef USE_GTKSPELL + if (editable && purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/spellcheck")) + pidgin_setup_gtkspell(GTK_TEXT_VIEW(webview)); +#endif + gtk_widget_show(webview); + + if (editable) { + gtk_webviewtoolbar_attach(GTK_WEBVIEWTOOLBAR(toolbar), webview); + gtk_webviewtoolbar_associate_smileys(GTK_WEBVIEWTOOLBAR(toolbar), "default"); + } + pidgin_setup_webview(webview); + + sw = pidgin_make_scrollable(webview, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_NONE, -1, -1); + gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); + + gtk_webview_set_vadjustment(GTK_WEBVIEW(webview), + gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(sw))); + + if (webview_ret != NULL) + *webview_ret = webview; + + if (editable && (toolbar_ret != NULL)) + *toolbar_ret = toolbar; + + if (sw_ret != NULL) + *sw_ret = sw; + + return frame; +} + void pidgin_set_sensitive_if_input(GtkWidget *entry, GtkWidget *dialog) { @@ -292,7 +393,7 @@ if (to_toggle == NULL) return; - sensitivity = GTK_WIDGET_IS_SENSITIVE(to_toggle); + sensitivity = gtk_widget_is_sensitive(to_toggle); gtk_widget_set_sensitive(to_toggle, !sensitivity); } @@ -309,7 +410,7 @@ if (element == NULL) continue; - sensitivity = GTK_WIDGET_IS_SENSITIVE(element); + sensitivity = gtk_widget_is_sensitive(element); gtk_widget_set_sensitive(element, !sensitivity); } @@ -321,7 +422,7 @@ if (to_toggle == NULL) return; - if (GTK_WIDGET_VISIBLE(to_toggle)) + if (gtk_widget_get_visible(to_toggle)) gtk_widget_hide(to_toggle); else gtk_widget_show(to_toggle); @@ -522,68 +623,36 @@ } static gpointer -aop_option_menu_get_selected(GtkWidget *optmenu, GtkWidget **p_item) +aop_option_menu_get_selected(GtkWidget *optmenu) { - GtkWidget *menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu)); - GtkWidget *item = gtk_menu_get_active(GTK_MENU(menu)); - if (p_item) - (*p_item) = item; - return item ? g_object_get_data(G_OBJECT(item), "aop_per_item_data") : NULL; + gpointer data = NULL; + GtkTreeIter iter; + + g_return_val_if_fail(optmenu != NULL, NULL); + + if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(optmenu), &iter)) + gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(optmenu)), + &iter, AOP_DATA_COLUMN, &data, -1); + + return data; } static void aop_menu_cb(GtkWidget *optmenu, GCallback cb) { - GtkWidget *item; - gpointer per_item_data; - - per_item_data = aop_option_menu_get_selected(optmenu, &item); - if (cb != NULL) { - ((void (*)(GtkWidget *, gpointer, gpointer))cb)(item, per_item_data, g_object_get_data(G_OBJECT(optmenu), "user_data")); + ((void (*)(GtkWidget *, gpointer, gpointer))cb)(optmenu, + aop_option_menu_get_selected(optmenu), + g_object_get_data(G_OBJECT(optmenu), "user_data")); } } -static GtkWidget * -aop_menu_item_new(GtkSizeGroup *sg, GdkPixbuf *pixbuf, const char *lbl, gpointer per_item_data, const char *data) +static void +aop_option_menu_replace_menu(GtkWidget *optmenu, AopMenu *new_aop_menu) { - GtkWidget *item; - GtkWidget *hbox; - GtkWidget *image; - GtkWidget *label; - - item = gtk_menu_item_new(); - gtk_widget_show(item); - - hbox = gtk_hbox_new(FALSE, 4); - gtk_widget_show(hbox); - - /* Create the image */ - if (pixbuf == NULL) - image = gtk_image_new(); - else - image = gtk_image_new_from_pixbuf(pixbuf); - gtk_widget_show(image); - - if (sg) - gtk_size_group_add_widget(sg, image); - - /* Create the label */ - label = gtk_label_new (lbl); - gtk_widget_show (label); - gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); - gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); - - gtk_container_add(GTK_CONTAINER(item), hbox); - gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); - - g_object_set_data(G_OBJECT (item), data, per_item_data); - g_object_set_data(G_OBJECT (item), "aop_per_item_data", per_item_data); - - pidgin_set_accessible_label(item, label); - - return item; + gtk_combo_box_set_model(GTK_COMBO_BOX(optmenu), new_aop_menu->model); + gtk_combo_box_set_active(GTK_COMBO_BOX(optmenu), new_aop_menu->default_item); + g_free(new_aop_menu); } static GdkPixbuf * @@ -624,16 +693,17 @@ static GtkWidget * aop_option_menu_new(AopMenu *aop_menu, GCallback cb, gpointer user_data) { - GtkWidget *optmenu; - - optmenu = gtk_option_menu_new(); + GtkWidget *optmenu = NULL; + GtkCellRenderer *cr = NULL; + + optmenu = gtk_combo_box_new(); gtk_widget_show(optmenu); - gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), aop_menu->menu); - - if (aop_menu->default_item != -1) - gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), aop_menu->default_item); - - g_object_set_data_full(G_OBJECT(optmenu), "aop_menu", aop_menu, (GDestroyNotify)g_free); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(optmenu), cr = gtk_cell_renderer_pixbuf_new(), FALSE); + gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(optmenu), cr, "pixbuf", AOP_ICON_COLUMN); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(optmenu), cr = gtk_cell_renderer_text_new(), TRUE); + gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(optmenu), cr, "text", AOP_NAME_COLUMN); + + aop_option_menu_replace_menu(optmenu, aop_menu); g_object_set_data(G_OBJECT(optmenu), "user_data", user_data); g_signal_connect(G_OBJECT(optmenu), "changed", G_CALLBACK(aop_menu_cb), cb); @@ -642,32 +712,20 @@ } static void -aop_option_menu_replace_menu(GtkWidget *optmenu, AopMenu *new_aop_menu) -{ - if (gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu))) - gtk_option_menu_remove_menu(GTK_OPTION_MENU(optmenu)); - - gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), new_aop_menu->menu); - - if (new_aop_menu->default_item != -1) - gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), new_aop_menu->default_item); - - g_object_set_data_full(G_OBJECT(optmenu), "aop_menu", new_aop_menu, (GDestroyNotify)g_free); -} - -static void aop_option_menu_select_by_data(GtkWidget *optmenu, gpointer data) { - guint idx; - GList *llItr = NULL; - - for (idx = 0, llItr = GTK_MENU_SHELL(gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu)))->children; - llItr != NULL; - llItr = llItr->next, idx++) { - if (data == g_object_get_data(G_OBJECT(llItr->data), "aop_per_item_data")) { - gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), idx); - break; - } + GtkTreeModel *model; + GtkTreeIter iter; + gpointer iter_data; + model = gtk_combo_box_get_model(GTK_COMBO_BOX(optmenu)); + if (gtk_tree_model_get_iter_first(model, &iter)) { + do { + gtk_tree_model_get(model, &iter, AOP_DATA_COLUMN, &iter_data, -1); + if (iter_data == data) { + gtk_combo_box_set_active_iter(GTK_COMBO_BOX(optmenu), &iter); + return; + } + } while (gtk_tree_model_iter_next(model, &iter)); } } @@ -677,21 +735,16 @@ AopMenu *aop_menu = NULL; PurplePlugin *plugin; GdkPixbuf *pixbuf = NULL; - GtkSizeGroup *sg; + GtkTreeIter iter; + GtkListStore *ls; GList *p; - const char *gtalk_name = NULL, *facebook_name = NULL; int i; + ls = gtk_list_store_new(AOP_COLUMN_COUNT, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER); + aop_menu = g_malloc0(sizeof(AopMenu)); - aop_menu->default_item = -1; - aop_menu->menu = gtk_menu_new(); - gtk_widget_show(aop_menu->menu); - sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); - - if (purple_find_prpl("prpl-jabber")) { - gtalk_name = _("Google Talk"); - facebook_name = _("Facebook (XMPP)"); - } + aop_menu->default_item = 0; + aop_menu->model = GTK_TREE_MODEL(ls); for (p = purple_plugins_get_protocols(), i = 0; p != NULL; @@ -699,48 +752,14 @@ plugin = (PurplePlugin *)p->data; - if (gtalk_name && strcmp(gtalk_name, plugin->info->name) < 0) { - char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", - "16", "google-talk.png", NULL); - GtkWidget *item; - - pixbuf = pidgin_pixbuf_new_from_file(filename); - g_free(filename); - - gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), - item = aop_menu_item_new(sg, pixbuf, gtalk_name, "prpl-jabber", "protocol")); - g_object_set_data(G_OBJECT(item), "fakegoogle", GINT_TO_POINTER(1)); - - if (pixbuf) - g_object_unref(pixbuf); - - gtalk_name = NULL; - i++; - } - - if (facebook_name && strcmp(facebook_name, plugin->info->name) < 0) { - char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", - "16", "facebook.png", NULL); - GtkWidget *item; - - pixbuf = pidgin_pixbuf_new_from_file(filename); - g_free(filename); - - gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), - item = aop_menu_item_new(sg, pixbuf, facebook_name, "prpl-jabber", "protocol")); - g_object_set_data(G_OBJECT(item), "fakefacebook", GINT_TO_POINTER(1)); - - if (pixbuf) - g_object_unref(pixbuf); - - facebook_name = NULL; - i++; - } - pixbuf = pidgin_create_prpl_icon_from_prpl(plugin, PIDGIN_PRPL_ICON_SMALL, NULL); - gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), - aop_menu_item_new(sg, pixbuf, plugin->info->name, plugin->info->id, "protocol")); + gtk_list_store_append(ls, &iter); + gtk_list_store_set(ls, &iter, + AOP_ICON_COLUMN, pixbuf, + AOP_NAME_COLUMN, plugin->info->name, + AOP_DATA_COLUMN, plugin->info->id, + -1); if (pixbuf) g_object_unref(pixbuf); @@ -749,8 +768,6 @@ aop_menu->default_item = i; } - g_object_unref(sg); - return aop_menu; } @@ -764,13 +781,13 @@ const char * pidgin_protocol_option_menu_get_selected(GtkWidget *optmenu) { - return (const char *)aop_option_menu_get_selected(optmenu, NULL); + return (const char *)aop_option_menu_get_selected(optmenu); } PurpleAccount * pidgin_account_option_menu_get_selected(GtkWidget *optmenu) { - return (PurpleAccount *)aop_option_menu_get_selected(optmenu, NULL); + return (PurpleAccount *)aop_option_menu_get_selected(optmenu); } static AopMenu * @@ -782,7 +799,8 @@ GdkPixbuf *pixbuf = NULL; GList *list; GList *p; - GtkSizeGroup *sg; + GtkListStore *ls; + GtkTreeIter iter; int i; char buf[256]; @@ -791,11 +809,11 @@ else list = purple_connections_get_all(); + ls = gtk_list_store_new(AOP_COLUMN_COUNT, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER); + aop_menu = g_malloc0(sizeof(AopMenu)); - aop_menu->default_item = -1; - aop_menu->menu = gtk_menu_new(); - gtk_widget_show(aop_menu->menu); - sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); + aop_menu->default_item = 0; + aop_menu->model = GTK_TREE_MODEL(ls); for (p = list, i = 0; p != NULL; p = p->next, i++) { if (show_all) @@ -830,8 +848,12 @@ purple_account_get_protocol_name(account)); } - gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), - aop_menu_item_new(sg, pixbuf, buf, account, "account")); + gtk_list_store_append(ls, &iter); + gtk_list_store_set(ls, &iter, + AOP_ICON_COLUMN, pixbuf, + AOP_NAME_COLUMN, buf, + AOP_DATA_COLUMN, account, + -1); if (pixbuf) g_object_unref(pixbuf); @@ -840,8 +862,6 @@ aop_menu->default_item = i; } - g_object_unref(sg); - return aop_menu; } @@ -852,7 +872,7 @@ PurpleAccount *account; PurpleFilterAccountFunc filter_func; - account = (PurpleAccount *)aop_option_menu_get_selected(optmenu, NULL); + account = (PurpleAccount *)aop_option_menu_get_selected(optmenu); show_all = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(optmenu), "show_all")); filter_func = g_object_get_data(G_OBJECT(optmenu), "filter_func"); @@ -922,24 +942,6 @@ return optmenu; } -gboolean -pidgin_check_if_dir(const char *path, GtkFileSelection *filesel) -{ - char *dirname = NULL; - - if (g_file_test(path, G_FILE_TEST_IS_DIR)) { - /* append a / if needed */ - if (path[strlen(path) - 1] != G_DIR_SEPARATOR) { - dirname = g_strconcat(path, G_DIR_SEPARATOR_S, NULL); - } - gtk_file_selection_set_filename(filesel, (dirname != NULL) ? dirname : path); - g_free(dirname); - return TRUE; - } - - return FALSE; -} - void pidgin_setup_gtkspell(GtkTextView *textview) { @@ -1002,7 +1004,7 @@ show_retrieveing_info(PurpleConnection *conn, const char *name) { PurpleNotifyUserInfo *info = purple_notify_user_info_new(); - purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving...")); + purple_notify_user_info_add_pair_plaintext(info, _("Information"), _("Retrieving...")); purple_notify_userinfo(conn, name, info, NULL, NULL); purple_notify_user_info_destroy(info); } @@ -1023,7 +1025,7 @@ return; } - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(conn->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(conn)); if (prpl_info != NULL && prpl_info->get_cb_real_name) who = prpl_info->get_cb_real_name(conn, chat, name); if (prpl_info == NULL || prpl_info->get_cb_info == NULL) { @@ -1149,7 +1151,7 @@ gc = (PurpleConnection *)l->data; account = purple_connection_get_account(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); } protoname = prpl_info->list_icon(account, NULL); @@ -1191,7 +1193,7 @@ gc = (PurpleConnection *)l->data; account = purple_connection_get_account(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); } protoname = prpl_info->list_icon(account, NULL); @@ -1308,7 +1310,7 @@ monitor_num = gdk_screen_get_monitor_at_point (screen, *x, *y); - push_in = FALSE; + *push_in = FALSE; /* * The placement of popup menus horizontally works like this (with @@ -1603,7 +1605,7 @@ data->account = account; if (gc) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); if (prpl_info && prpl_info->options & OPT_PROTO_IM_IMAGE) im = TRUE; @@ -1834,21 +1836,27 @@ gpointer object) { GtkWidget *menuitem; + GList *list; if (act == NULL) { return pidgin_separator(menu); } - if (act->children == NULL) { - menuitem = gtk_menu_item_new_with_mnemonic(act->label); - - if (act->callback != NULL) { + list = purple_menu_action_get_children(act); + menuitem = gtk_menu_item_new_with_mnemonic(purple_menu_action_get_label(act)); + + if (list == NULL) { + PurpleCallback callback; + + callback = purple_menu_action_get_callback(act); + + if (callback != NULL) { g_object_set_data(G_OBJECT(menuitem), "purplecallback", - act->callback); + callback); g_object_set_data(G_OBJECT(menuitem), "purplecallbackdata", - act->data); + purple_menu_action_get_data(act)); g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menu_action_cb), object); @@ -1862,7 +1870,6 @@ GtkWidget *submenu = NULL; GtkAccelGroup *group; - menuitem = gtk_menu_item_new_with_mnemonic(act->label); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); submenu = gtk_menu_new(); @@ -1870,24 +1877,34 @@ group = gtk_menu_get_accel_group(GTK_MENU(menu)); if (group) { - char *path = g_strdup_printf("%s/%s", GTK_MENU_ITEM(menuitem)->accel_path, act->label); + char *path = g_strdup_printf("%s/%s", GTK_MENU_ITEM(menuitem)->accel_path, + purple_menu_action_get_label(act)); gtk_menu_set_accel_path(GTK_MENU(submenu), path); g_free(path); gtk_menu_set_accel_group(GTK_MENU(submenu), group); } - for (l = act->children; l; l = l->next) { + for (l = list; l; l = l->next) { PurpleMenuAction *act = (PurpleMenuAction *)l->data; pidgin_append_menu_action(submenu, act, object); } - g_list_free(act->children); - act->children = NULL; + g_list_free(list); + purple_menu_action_set_children(act, NULL); } purple_menu_action_free(act); return menuitem; } +enum { + COMPLETION_DISPLAYED_COLUMN, /* displayed completion value */ + COMPLETION_BUDDY_COLUMN, /* buddy name */ + COMPLETION_NORMALIZED_COLUMN, /* UTF-8 normalized & casefolded buddy name */ + COMPLETION_COMPARISON_COLUMN, /* UTF-8 normalized & casefolded value for comparison */ + COMPLETION_ACCOUNT_COLUMN, /* account */ + COMPLETION_COLUMN_COUNT +}; + typedef struct { GtkWidget *entry; @@ -1907,10 +1924,10 @@ GValue val2; const char *tmp; - model = gtk_entry_completion_get_model (completion); + model = gtk_entry_completion_get_model(completion); val1.g_type = 0; - gtk_tree_model_get_value(model, iter, 2, &val1); + gtk_tree_model_get_value(model, iter, COMPLETION_NORMALIZED_COLUMN, &val1); tmp = g_value_get_string(&val1); if (tmp != NULL && purple_str_has_prefix(tmp, key)) { @@ -1920,7 +1937,7 @@ g_value_unset(&val1); val2.g_type = 0; - gtk_tree_model_get_value(model, iter, 3, &val2); + gtk_tree_model_get_value(model, iter, COMPLETION_COMPARISON_COLUMN, &val2); tmp = g_value_get_string(&val2); if (tmp != NULL && purple_str_has_prefix(tmp, key)) { @@ -1940,11 +1957,11 @@ PurpleAccount *account; val.g_type = 0; - gtk_tree_model_get_value(model, iter, 1, &val); + gtk_tree_model_get_value(model, iter, COMPLETION_BUDDY_COLUMN, &val); gtk_entry_set_text(GTK_ENTRY(data->entry), g_value_get_string(&val)); g_value_unset(&val); - gtk_tree_model_get_value(model, iter, 4, &val); + gtk_tree_model_get_value(model, iter, COMPLETION_ACCOUNT_COLUMN, &val); account = g_value_get_pointer(&val); g_value_unset(&val); @@ -1981,11 +1998,11 @@ gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, - 0, completion_entry, - 1, buddyname, - 2, normalized_buddyname, - 3, tmp, - 4, account, + COMPLETION_DISPLAYED_COLUMN, completion_entry, + COMPLETION_BUDDY_COLUMN, buddyname, + COMPLETION_NORMALIZED_COLUMN, normalized_buddyname, + COMPLETION_COMPARISON_COLUMN, tmp, + COMPLETION_ACCOUNT_COLUMN, account, -1); g_free(completion_entry); g_free(tmp); @@ -2006,11 +2023,11 @@ gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, - 0, completion_entry, - 1, buddyname, - 2, normalized_buddyname, - 3, tmp, - 4, account, + COMPLETION_DISPLAYED_COLUMN, completion_entry, + COMPLETION_BUDDY_COLUMN, buddyname, + COMPLETION_NORMALIZED_COLUMN, normalized_buddyname, + COMPLETION_COMPARISON_COLUMN, tmp, + COMPLETION_ACCOUNT_COLUMN, account, -1); g_free(completion_entry); g_free(tmp); @@ -2022,11 +2039,11 @@ /* Add the buddy's name. */ gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, - 0, buddyname, - 1, buddyname, - 2, normalized_buddyname, - 3, NULL, - 4, account, + COMPLETION_DISPLAYED_COLUMN, buddyname, + COMPLETION_BUDDY_COLUMN, buddyname, + COMPLETION_NORMALIZED_COLUMN, normalized_buddyname, + COMPLETION_COMPARISON_COLUMN, NULL, + COMPLETION_ACCOUNT_COLUMN, account, -1); } @@ -2082,8 +2099,8 @@ add_buddyname_autocomplete_entry(data->store, ((PurpleContact *)cnode)->alias, purple_buddy_get_contact_alias(entry.entry.buddy), - entry.entry.buddy->account, - entry.entry.buddy->name + purple_buddy_get_account(entry.entry.buddy), + purple_buddy_get_name(entry.entry.buddy) ); } } @@ -2124,7 +2141,9 @@ GtkEntryCompletion *completion; data = g_new0(PidginCompletionData, 1); - store = gtk_list_store_new(5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); + store = gtk_list_store_new(COMPLETION_COLUMN_COUNT, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_POINTER); data->entry = entry; data->accountopt = accountopt; @@ -2141,7 +2160,8 @@ /* Sort the completion list by buddy name */ gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), - 1, GTK_SORT_ASCENDING); + COMPLETION_BUDDY_COLUMN, + GTK_SORT_ASCENDING); completion = gtk_entry_completion_new(); gtk_entry_completion_set_match_func(completion, buddyname_completion_match_func, NULL, NULL); @@ -2155,7 +2175,7 @@ gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(store)); g_object_unref(store); - gtk_entry_completion_set_text_column(completion, 0); + gtk_entry_completion_set_text_column(completion, COMPLETION_DISPLAYED_COLUMN); purple_signal_connect(purple_connections_get_handle(), "signed-on", entry, PURPLE_CALLBACK(repopulate_autocomplete), data); @@ -2175,19 +2195,12 @@ gboolean all = GPOINTER_TO_INT(all_accounts); if (completion_entry->is_buddy) { - return all || purple_account_is_connected(completion_entry->entry.buddy->account); + return all || purple_account_is_connected(purple_buddy_get_account(completion_entry->entry.buddy)); } else { return all || (completion_entry->entry.logged_buddy->account != NULL && purple_account_is_connected(completion_entry->entry.logged_buddy->account)); } } -void -pidgin_setup_screenname_autocomplete(GtkWidget *entry, GtkWidget *accountopt, gboolean all) { - pidgin_setup_screenname_autocomplete_with_filter(entry, accountopt, pidgin_screenname_autocomplete_default_filter, GINT_TO_POINTER(all)); -} - - - void pidgin_set_cursor(GtkWidget *widget, GdkCursorType cursor_type) { GdkCursor *cursor; @@ -2488,9 +2501,9 @@ the image. */ purple_debug_info("buddyicon", "Converted image from " "%dx%d to %dx%d, format=%s, quality=%u, " - "filesize=%zu\n", orig_width, orig_height, - new_width, new_height, prpl_formats[i], quality, - length); + "filesize=%" G_GSIZE_FORMAT "\n", + orig_width, orig_height, new_width, new_height, + prpl_formats[i], quality, length); if (len) *len = length; g_strfreev(prpl_formats); @@ -2533,21 +2546,6 @@ return NULL; } -void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename) -{ - PurpleBuddy *buddy; - PurpleContact *contact; - - buddy = purple_find_buddy(account, who); - if (!buddy) { - purple_debug_info("custom-icon", "You can only set custom icon for someone in your buddylist.\n"); - return; - } - - contact = purple_buddy_get_contact(buddy); - purple_buddy_icons_node_set_custom_icon_from_file((PurpleBlistNode*)contact, filename); -} - char *pidgin_make_pretty_arrows(const char *str) { char *ret; @@ -3012,7 +3010,7 @@ windows = g_list_delete_link(windows, windows); if (window == widget || - !GTK_WIDGET_VISIBLE(window)) + !gtk_widget_get_visible(window)) continue; if (!gdk_property_get(window->window, _WindowTime, _Cardinal, 0, sizeof(time_t), FALSE, @@ -3066,7 +3064,7 @@ windows = g_list_delete_link(windows, windows); if (window == widget || - !GTK_WIDGET_VISIBLE(window)) { + !gtk_widget_get_visible(window)) { continue; } @@ -3096,7 +3094,7 @@ if (!gdk_pixbuf_loader_write(loader, buf, count, &error) || error) { purple_debug_warning("gtkutils", "gdk_pixbuf_loader_write() " - "failed with size=%zu: %s\n", count, + "failed with size=%" G_GSIZE_FORMAT ": %s\n", count, error ? error->message : "(no error message)"); if (error) g_error_free(error); @@ -3106,7 +3104,7 @@ if (!gdk_pixbuf_loader_close(loader, &error) || error) { purple_debug_warning("gtkutils", "gdk_pixbuf_loader_close() " - "failed for image of size %zu: %s\n", count, + "failed for image of size %" G_GSIZE_FORMAT ": %s\n", count, error ? error->message : "(no error message)"); if (error) g_error_free(error); @@ -3120,7 +3118,7 @@ pixbuf = G_OBJECT(gdk_pixbuf_loader_get_pixbuf(loader)); if (!pixbuf) { purple_debug_warning("gtkutils", "%s() returned NULL for image " - "of size %zu\n", + "of size %" G_GSIZE_FORMAT "\n", animated ? "gdk_pixbuf_loader_get_animation" : "gdk_pixbuf_loader_get_pixbuf", count); g_object_unref(G_OBJECT(loader)); @@ -3450,7 +3448,7 @@ return TRUE; purple_request_file(conv->active_conv, _("Save File"), NULL, TRUE, G_CALLBACK(savefile_write_cb), NULL, - conv->active_conv->account, NULL, conv->active_conv, + purple_conversation_get_account(conv->active_conv), NULL, conv->active_conv, (void *)url); return TRUE; } @@ -3707,4 +3705,3 @@ gtk_imhtml_class_register_protocol("mailto:", NULL, NULL); gtk_imhtml_class_register_protocol("gopher://", NULL, NULL); } - diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkutils.h --- a/pidgin/gtkutils.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkutils.h Fri Apr 06 04:30:00 2012 +0000 @@ -31,10 +31,6 @@ #include "prpl.h" #include "util.h" - - - - typedef enum { PIDGIN_BUTTON_HORIZONTAL, @@ -80,6 +76,8 @@ typedef gboolean (*PidginFilterBuddyCompletionEntryFunc) (const PidginBuddyCompletionEntry *completion_entry, gpointer user_data); +G_BEGIN_DECLS + /** * Sets up a gtkimhtml widget, loads it with smileys, and sets the * default signal handlers. @@ -109,12 +107,42 @@ GtkWidget *pidgin_create_imhtml(gboolean editable, GtkWidget **imhtml_ret, GtkWidget **toolbar_ret, GtkWidget **sw_ret); /** + * Sets up a gtkwebview widget, loads it with smileys, and sets the + * default signal handlers. + * + * @param webview The gtkwebview widget to setup. + */ +void pidgin_setup_webview(GtkWidget *webview); + +/** + * Create an GtkWebView widget and associated GtkIMHtmlToolbar widget. This + * function puts both widgets in a nice GtkFrame. They're separated by an + * attractive GtkSeparator. + * TODO WEBKIT: editable isn't supported yet + * + * @param editable @c TRUE if this webview should be editable. If this is + * @c FALSE, then the toolbar will NOT be created. If this webview + * should be read-only at first, but may become editable later, then + * pass in @c TRUE here and then manually call gtk_webview_set_editable() + * later. + * @param webview_ret A pointer to a pointer to a GtkWidget. This pointer + * will be set to the webview when this function exits. + * @param toolbar_ret A pointer to a pointer to a GtkWidget. If editable is + * TRUE then this will be set to the toolbar when this function exits. + * Otherwise this will be set to @c NULL. + * @param sw_ret This will be filled with a pointer to the scrolled window + * widget which contains the webview. + * + * @return The GtkFrame containing the toolbar and webview. + */ +GtkWidget *pidgin_create_webview(gboolean editable, GtkWidget **webview_ret, GtkWidget **toolbar_ret, GtkWidget **sw_ret); + +/** * Creates a small button * * @param image A button image. * * @return A GtkButton created from the image. - * @since 2.7.0 */ GtkWidget *pidgin_create_small_button(GtkWidget *image); @@ -125,8 +153,6 @@ * @param border_width The window's desired border width * @param role A string indicating what the window is responsible for doing, or @c NULL * @param resizable Whether the window should be resizable (@c TRUE) or not (@c FALSE) - * - * @since 2.1.0 */ GtkWidget *pidgin_create_window(const char *title, guint border_width, const char *role, gboolean resizable); @@ -137,8 +163,6 @@ * @param border_width The window's desired border width * @param role A string indicating what the window is responsible for doing, or @c NULL * @param resizable Whether the window should be resizable (@c TRUE) or not (@c FALSE) - * - * @since 2.4.0 */ GtkWidget *pidgin_create_dialog(const char *title, guint border_width, const char *role, gboolean resizable); @@ -148,8 +172,6 @@ * @param dialog The dialog window * @param homogeneous TRUE if all children are to be given equal space allotments. * @param spacing the number of pixels to place by default between children - * - * @since 2.4.0 */ GtkWidget *pidgin_dialog_get_vbox_with_properties(GtkDialog *dialog, gboolean homogeneous, gint spacing); @@ -157,8 +179,6 @@ * Retrieves the main content box (vbox) from a pidgin dialog window * * @param dialog The dialog window - * - * @since 2.4.0 */ GtkWidget *pidgin_dialog_get_vbox(GtkDialog *dialog); @@ -171,7 +191,6 @@ * @param callbackdata The user data for the callback function * * @return The created button. - * @since 2.4.0 */ GtkWidget *pidgin_dialog_add_button(GtkDialog *dialog, const char *label, GCallback callback, gpointer callbackdata); @@ -180,8 +199,6 @@ * Retrieves the action area (button box) from a pidgin dialog window * * @param dialog The dialog window - * - * @since 2.4.0 */ GtkWidget *pidgin_dialog_get_action_area(GtkDialog *dialog); @@ -384,39 +401,6 @@ gboolean pidgin_screenname_autocomplete_default_filter(const PidginBuddyCompletionEntry *completion_entry, gpointer all_accounts); /** - * Add autocompletion of screenames to an entry. - * - * @deprecated - * For new code, use the equivalent: - * #pidgin_setup_screenname_autocomplete_with_filter(@a entry, @a optmenu, - * #pidgin_screenname_autocomplete_default_filter, GINT_TO_POINTER(@a - * all)) - * - * @param entry The GtkEntry on which to setup autocomplete. - * @param optmenu A menu for accounts, returned by - * pidgin_account_option_menu_new(). If @a optmenu is not @c - * NULL, it'll be updated when a username is chosen from the - * autocomplete list. - * @param all Whether to include usernames from disconnected accounts. - */ -void pidgin_setup_screenname_autocomplete(GtkWidget *entry, GtkWidget *optmenu, gboolean all); - -/** - * Check if the given path is a directory or not. If it is, then modify - * the given GtkFileSelection dialog so that it displays the given path. - * If the given path is not a directory, then do nothing. - * - * @param path The path entered in the file selection window by the user. - * @param filesel The file selection window. - * - * @return TRUE if given path is a directory, FALSE otherwise. - * @deprecated Pidgin no longer uses GtkFileSelection internally. It has also - * been deprecated by GTK+. Use GtkFileChooser instead and ignore - * this function. - */ -gboolean pidgin_check_if_dir(const char *path, GtkFileSelection *filesel); - -/** * Sets up GtkSpell for the given GtkTextView, reporting errors * if encountered. * @@ -448,8 +432,6 @@ * * @param conn The connection to get information from. * @param name The user to get information about. - * - * @since 2.1.0 */ void pidgin_retrieve_user_info(PurpleConnection *conn, const char *name); @@ -459,8 +441,6 @@ * @param conn The connection to get information from. * @param name The user to get information about. * @param chatid The chat id. - * - * @since 2.1.0 */ void pidgin_retrieve_user_info_in_chat(PurpleConnection *conn, const char *name, int chatid); @@ -499,8 +479,6 @@ * * @param w The widget that we want to label. * @param l A GtkLabel that we want to use as the label for the widget. - * - * @since 2.2.0 */ void pidgin_set_accessible_relations(GtkWidget *w, GtkWidget *l); @@ -515,8 +493,6 @@ * where the menu shall be drawn. This is an output parameter. * @param push_in This is an output parameter? * @param data Not used by this particular position function. - * - * @since 2.1.0 */ void pidgin_menu_position_func_helper(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data); @@ -588,8 +564,6 @@ * @param prim The status primitive * * @return The stock-id - * - * @since 2.6.0 */ const char *pidgin_stock_id_from_status_primitive(PurpleStatusPrimitive prim); @@ -599,8 +573,6 @@ * @param presence The presence. * * @return The stock-id - * - * @since 2.6.0 */ const char *pidgin_stock_id_from_presence(PurplePresence *presence); @@ -661,19 +633,6 @@ */ gpointer pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path, size_t *len); -#if !(defined PIDGIN_DISABLE_DEPRECATED) || (defined _PIDGIN_GTKUTILS_C_) -/** - * Set or unset a custom buddyicon for a user. - * - * @param account The account the user belongs to. - * @param who The name of the user. - * @param filename The path of the custom icon. If this is @c NULL, then any - * previously set custom buddy icon for the user is removed. - * @deprecated See purple_buddy_icons_node_set_custom_icon_from_file() - */ -void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename); -#endif - /** * Converts "->" and "<-" in strings to Unicode arrow characters, for use in referencing * menu items. @@ -781,8 +740,6 @@ * * @return A newly created text GtkComboBox containing a GtkEntry * child. - * - * @since 2.2.0 */ GtkWidget *pidgin_text_combo_box_entry_new(const char *default_item, GList *items); @@ -792,8 +749,6 @@ * @param widget The simple text GtkComboBoxEntry equivalent widget * * @return The text in the widget's entry. It must not be freed - * - * @since 2.2.0 */ const char *pidgin_text_combo_box_entry_get_text(GtkWidget *widget); @@ -802,8 +757,6 @@ * * @param widget The simple text GtkComboBoxEntry equivalent widget * @param text The text to set - * - * @since 2.2.0 */ void pidgin_text_combo_box_entry_set_text(GtkWidget *widget, const char *text); @@ -813,8 +766,6 @@ * @param window The window to make transient. * * @return Whether the window was made transient or not. - * - * @since 2.4.0 */ gboolean pidgin_auto_parent_window(GtkWidget *window); @@ -829,7 +780,6 @@ * @param p_label Place to store a pointer to the GtkLabel, or @c NULL if you don't care. * * @return A GtkHBox already added to the GtkVBox containing the GtkLabel and the GtkWidget. - * @since 2.4.0 */ GtkWidget *pidgin_add_widget_to_vbox(GtkBox *vbox, const char *widget_label, GtkSizeGroup *sg, GtkWidget *widget, gboolean expand, GtkWidget **p_label); @@ -841,8 +791,6 @@ * * @return A GdkPixbuf created from the image data, or NULL if * there was an error parsing the data. - * - * @since 2.9.0 */ GdkPixbuf *pidgin_pixbuf_from_data(const guchar *buf, gsize count); @@ -854,8 +802,6 @@ * * @return A GdkPixbufAnimation created from the image data, or NULL if * there was an error parsing the data. - * - * @since 2.9.0 */ GdkPixbufAnimation *pidgin_pixbuf_anim_from_data(const guchar *buf, gsize count); @@ -865,8 +811,6 @@ * @param image A PurpleStoredImage. * * @return A GdkPixbuf created from the stored image. - * - * @since 2.5.0 */ GdkPixbuf *pidgin_pixbuf_from_imgstore(PurpleStoredImage *image); @@ -890,8 +834,6 @@ * * @return The GdkPixbuf if successful. Otherwise NULL is returned and * a warning is logged. - * - * @since 2.9.0 */ GdkPixbuf *pidgin_pixbuf_new_from_file(const char *filename); @@ -917,8 +859,6 @@ * * @return The GdkPixbuf if successful. Otherwise NULL is returned and * a warning is logged. - * - * @since 2.9.0 */ GdkPixbuf *pidgin_pixbuf_new_from_file_at_size(const char *filename, int width, int height); @@ -945,37 +885,31 @@ * * @return The GdkPixbuf if successful. Otherwise NULL is returned and * a warning is logged. - * - * @since 2.9.0 */ GdkPixbuf *pidgin_pixbuf_new_from_file_at_scale(const char *filename, int width, int height, gboolean preserve_aspect_ratio); /** * Add scrollbars to a widget - * @param widget The child widget - * @hscrollbar_policy Horizontal scrolling policy - * @vscrollbar_policy Vertical scrolling policy - * @shadow Shadow type - * @width Desired widget width, or -1 for default - * @height Desired widget height, or -1 for default - * - * @since 2.8.0 + * @param child The child widget + * @param hscrollbar_policy Horizontal scrolling policy + * @param vscrollbar_policy Vertical scrolling policy + * @param shadow_type Shadow type + * @param width Desired widget width, or -1 for default + * @param height Desired widget height, or -1 for default */ GtkWidget *pidgin_make_scrollable(GtkWidget *child, GtkPolicyType hscrollbar_policy, GtkPolicyType vscrollbar_policy, GtkShadowType shadow_type, int width, int height); /** * Initialize some utility functions. - * - * @since 2.6.0 */ void pidgin_utils_init(void); /** * Uninitialize some utility functions. - * - * @since 2.6.0 */ void pidgin_utils_uninit(void); +G_END_DECLS + #endif /* _PIDGINUTILS_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkwebview.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/gtkwebview.c Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,941 @@ +/* + * @file gtkwebview.c GTK+ WebKitWebView wrapper class. + * @ingroup pidgin + */ + +/* pidgin + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + */ + +#include "internal.h" +#include "pidgin.h" + +#include +#include "gtkwebview.h" + +#define MAX_FONT_SIZE 7 +#define MAX_SCROLL_TIME 0.4 /* seconds */ +#define SCROLL_DELAY 33 /* milliseconds */ + +#define GTK_WEBVIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), GTK_TYPE_WEBVIEW, GtkWebViewPriv)) + +enum { + BUTTONS_UPDATE, + TOGGLE_FORMAT, + CLEAR_FORMAT, + UPDATE_FORMAT, + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = { 0 }; + +/****************************************************************************** + * Structs + *****************************************************************************/ + +typedef struct _GtkWebViewPriv { + GHashTable *images; /**< a map from id to temporary file for the image */ + gboolean empty; /**< whether anything has been appended **/ + + /* JS execute queue */ + GQueue *js_queue; + gboolean is_loading; + + /* Scroll adjustments */ + GtkAdjustment *vadj; + guint scroll_src; + GTimer *scroll_time; + + /* Format options */ + GtkWebViewButtons format_functions; + struct { + gboolean wbfo:1; /* Whole buffer formatting only. */ + } edit; + +} GtkWebViewPriv; + +/****************************************************************************** + * Globals + *****************************************************************************/ + +static WebKitWebViewClass *parent_class = NULL; + +/****************************************************************************** + * Helpers + *****************************************************************************/ + +static const char * +get_image_src_from_id(GtkWebViewPriv *priv, int id) +{ + char *src; + PurpleStoredImage *img; + + if (priv->images) { + /* Check for already loaded image */ + src = (char *)g_hash_table_lookup(priv->images, GINT_TO_POINTER(id)); + if (src) + return src; + } else { + priv->images = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, g_free); + } + + /* Find image in store */ + img = purple_imgstore_find_by_id(id); + + src = (char *)purple_imgstore_get_filename(img); + if (src) { + src = g_strdup_printf("file://%s", src); + } else { + char *tmp; + tmp = purple_base64_encode(purple_imgstore_get_data(img), + purple_imgstore_get_size(img)); + src = g_strdup_printf("data:base64,%s", tmp); + g_free(tmp); + } + + g_hash_table_insert(priv->images, GINT_TO_POINTER(id), src); + + return src; +} + +/* + * Replace all tags with . I hoped to never + * write any HTML parsing code, but I'm forced to do this, until + * purple changes the way it works. + */ +static char * +replace_img_id_with_src(GtkWebViewPriv *priv, const char *html) +{ + GString *buffer = g_string_new(NULL); + const char *cur = html; + char *id; + int nid; + + while (*cur) { + const char *img = strstr(cur, ""); + if (!cur) + cur = strstr(img, ">"); + + if (!cur) { /* invalid html? */ + g_string_printf(buffer, "%s", html); + break; + } + + if (strstr(img, "src=") || !strstr(img, "id=")) { + g_string_printf(buffer, "%s", html); + break; + } + + /* + * if this is valid HTML, then I can be sure that it + * has an id= and does not have an src=, since + * '=' cannot appear in parameters. + */ + + id = strstr(img, "id=") + 3; + + /* *id can't be \0, since a ">" appears after this */ + if (isdigit(*id)) + nid = atoi(id); + else + nid = atoi(id + 1); + + /* let's dump this, tag and then dump the src information */ + g_string_append_len(buffer, img, cur - img); + + g_string_append_printf(buffer, " src='%s' ", get_image_src_from_id(priv, nid)); + } + + return g_string_free(buffer, FALSE); +} + +static gboolean +process_js_script_queue(GtkWebView *webview) +{ + GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + char *script; + + if (priv->is_loading) + return FALSE; /* we will be called when loaded */ + if (!priv->js_queue || g_queue_is_empty(priv->js_queue)) + return FALSE; /* nothing to do! */ + + script = g_queue_pop_head(priv->js_queue); + webkit_web_view_execute_script(WEBKIT_WEB_VIEW(webview), script); + g_free(script); + + return TRUE; /* there may be more for now */ +} + +static void +webview_load_started(WebKitWebView *webview, WebKitWebFrame *frame, + gpointer userdata) +{ + GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + + /* is there a better way to test for is_loading? */ + priv->is_loading = TRUE; +} + +static void +webview_load_finished(WebKitWebView *webview, WebKitWebFrame *frame, + gpointer userdata) +{ + GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + + priv->is_loading = FALSE; + g_idle_add((GSourceFunc)process_js_script_queue, webview); +} + +static gboolean +webview_link_clicked(WebKitWebView *webview, + WebKitWebFrame *frame, + WebKitNetworkRequest *request, + WebKitWebNavigationAction *navigation_action, + WebKitWebPolicyDecision *policy_decision, + gpointer userdata) +{ + const gchar *uri; + WebKitWebNavigationReason reason; + + uri = webkit_network_request_get_uri(request); + reason = webkit_web_navigation_action_get_reason(navigation_action); + + if (reason == WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED) { + /* the gtk imhtml way was to create an idle cb, not sure + * why, so right now just using purple_notify_uri directly */ + purple_notify_uri(NULL, uri); + webkit_web_policy_decision_ignore(policy_decision); + } else if (reason == WEBKIT_WEB_NAVIGATION_REASON_OTHER) + webkit_web_policy_decision_use(policy_decision); + else + webkit_web_policy_decision_ignore(policy_decision); + + return TRUE; +} + +/* + * Smoothly scroll a WebView. + * + * @return TRUE if the window needs to be scrolled further, FALSE if we're at the bottom. + */ +static gboolean +smooth_scroll_cb(gpointer data) +{ + GtkWebViewPriv *priv = data; + GtkAdjustment *adj; + gdouble max_val; + gdouble scroll_val; + + g_return_val_if_fail(priv->scroll_time != NULL, FALSE); + + adj = priv->vadj; +#if GTK_CHECK_VERSION(2,14,0) + max_val = gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj); +#else + max_val = adj->upper - adj->page_size; +#endif + scroll_val = gtk_adjustment_get_value(adj) + + ((max_val - gtk_adjustment_get_value(adj)) / 3); + + if (g_timer_elapsed(priv->scroll_time, NULL) > MAX_SCROLL_TIME + || scroll_val >= max_val) { + /* time's up. jump to the end and kill the timer */ + gtk_adjustment_set_value(adj, max_val); + g_timer_destroy(priv->scroll_time); + priv->scroll_time = NULL; + g_source_remove(priv->scroll_src); + priv->scroll_src = 0; + return FALSE; + } + + /* scroll by 1/3rd the remaining distance */ + gtk_adjustment_set_value(adj, scroll_val); + return TRUE; +} + +static gboolean +scroll_idle_cb(gpointer data) +{ + GtkWebViewPriv *priv = data; + GtkAdjustment *adj = priv->vadj; + gdouble max_val; + + if (adj) { +#if GTK_CHECK_VERSION(2,14,0) + max_val = gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj); +#else + max_val = adj->upper - adj->page_size; +#endif + gtk_adjustment_set_value(adj, max_val); + } + + priv->scroll_src = 0; + return FALSE; +} + +static void +webview_clear_formatting(GtkWebView *webview) +{ + WebKitDOMDocument *dom; + + if (!webkit_web_view_get_editable(WEBKIT_WEB_VIEW(webview))) + return; + + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); + webkit_dom_document_exec_command(dom, "removeFormat", FALSE, ""); +} + +static void +webview_toggle_format(GtkWebView *webview, GtkWebViewButtons buttons) +{ + /* since this function is the handler for the formatting keystrokes, + we need to check here that the formatting attempted is permitted */ + buttons &= gtk_webview_get_format_functions(webview); + + switch (buttons) { + case GTK_WEBVIEW_BOLD: + gtk_webview_toggle_bold(webview); + break; + case GTK_WEBVIEW_ITALIC: + gtk_webview_toggle_italic(webview); + break; + case GTK_WEBVIEW_UNDERLINE: + gtk_webview_toggle_underline(webview); + break; + case GTK_WEBVIEW_STRIKE: + gtk_webview_toggle_strike(webview); + break; + case GTK_WEBVIEW_SHRINK: + gtk_webview_font_shrink(webview); + break; + case GTK_WEBVIEW_GROW: + gtk_webview_font_grow(webview); + break; + default: + break; + } +} + +/****************************************************************************** + * GObject Stuff + *****************************************************************************/ + +GtkWidget * +gtk_webview_new(void) +{ + return GTK_WIDGET(g_object_new(gtk_webview_get_type(), NULL)); +} + +static void +gtk_webview_finalize(GObject *webview) +{ + GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + gpointer temp; + + while ((temp = g_queue_pop_head(priv->js_queue))) + g_free(temp); + g_queue_free(priv->js_queue); + + if (priv->images) + g_hash_table_unref(priv->images); + + G_OBJECT_CLASS(parent_class)->finalize(G_OBJECT(webview)); +} + +static void +gtk_webview_class_init(GtkWebViewClass *klass, gpointer userdata) +{ + GObjectClass *gobject_class; + GtkBindingSet *binding_set; + + parent_class = g_type_class_ref(webkit_web_view_get_type()); + gobject_class = G_OBJECT_CLASS(klass); + + g_type_class_add_private(klass, sizeof(GtkWebViewPriv)); + + signals[BUTTONS_UPDATE] = g_signal_new("allowed-formats-updated", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(GtkWebViewClass, buttons_update), + NULL, 0, g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[TOGGLE_FORMAT] = g_signal_new("format-toggled", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(GtkWebViewClass, toggle_format), + NULL, 0, g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + signals[CLEAR_FORMAT] = g_signal_new("format-cleared", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(GtkWebViewClass, clear_format), + NULL, 0, g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals[UPDATE_FORMAT] = g_signal_new("format-updated", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(GtkWebViewClass, update_format), + NULL, 0, g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + klass->toggle_format = webview_toggle_format; + klass->clear_format = webview_clear_formatting; + + gobject_class->finalize = gtk_webview_finalize; + + binding_set = gtk_binding_set_by_class(parent_class); + gtk_binding_entry_add_signal(binding_set, GDK_KEY_b, GDK_CONTROL_MASK, + "format-toggled", 1, G_TYPE_INT, + GTK_WEBVIEW_BOLD); + gtk_binding_entry_add_signal(binding_set, GDK_KEY_i, GDK_CONTROL_MASK, + "format-toggled", 1, G_TYPE_INT, + GTK_WEBVIEW_ITALIC); + gtk_binding_entry_add_signal(binding_set, GDK_KEY_u, GDK_CONTROL_MASK, + "format-toggled", 1, G_TYPE_INT, + GTK_WEBVIEW_UNDERLINE); + gtk_binding_entry_add_signal(binding_set, GDK_KEY_plus, GDK_CONTROL_MASK, + "format-toggled", 1, G_TYPE_INT, + GTK_WEBVIEW_GROW); + gtk_binding_entry_add_signal(binding_set, GDK_KEY_equal, GDK_CONTROL_MASK, + "format-toggled", 1, G_TYPE_INT, + GTK_WEBVIEW_GROW); + gtk_binding_entry_add_signal(binding_set, GDK_KEY_minus, GDK_CONTROL_MASK, + "format-toggled", 1, G_TYPE_INT, + GTK_WEBVIEW_SHRINK); + + binding_set = gtk_binding_set_by_class(klass); + gtk_binding_entry_add_signal(binding_set, GDK_KEY_r, GDK_CONTROL_MASK, + "format-cleared", 0); +} + +static void +gtk_webview_init(GtkWebView *webview, gpointer userdata) +{ + GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + + priv->empty = TRUE; + priv->js_queue = g_queue_new(); + + g_signal_connect(webview, "navigation-policy-decision-requested", + G_CALLBACK(webview_link_clicked), NULL); + + g_signal_connect(webview, "load-started", + G_CALLBACK(webview_load_started), NULL); + + g_signal_connect(webview, "load-finished", + G_CALLBACK(webview_load_finished), NULL); +} + +GType +gtk_webview_get_type(void) +{ + static GType mview_type = 0; + if (G_UNLIKELY(mview_type == 0)) { + static const GTypeInfo mview_info = { + sizeof(GtkWebViewClass), + NULL, + NULL, + (GClassInitFunc)gtk_webview_class_init, + NULL, + NULL, + sizeof(GtkWebView), + 0, + (GInstanceInitFunc)gtk_webview_init, + NULL + }; + mview_type = g_type_register_static(webkit_web_view_get_type(), + "GtkWebView", &mview_info, 0); + } + return mview_type; +} + +/***************************************************************************** + * Public API functions + *****************************************************************************/ + +gboolean +gtk_webview_is_empty(GtkWebView *webview) +{ + GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + return priv->empty; +} + +char * +gtk_webview_quote_js_string(const char *text) +{ + GString *str = g_string_new("\""); + const char *cur = text; + + while (cur && *cur) { + switch (*cur) { + case '\\': + g_string_append(str, "\\\\"); + break; + case '\"': + g_string_append(str, "\\\""); + break; + case '\r': + g_string_append(str, "
    "); + break; + case '\n': + break; + default: + g_string_append_c(str, *cur); + } + cur++; + } + + g_string_append_c(str, '"'); + + return g_string_free(str, FALSE); +} + +void +gtk_webview_safe_execute_script(GtkWebView *webview, const char *script) +{ + GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + g_queue_push_tail(priv->js_queue, g_strdup(script)); + g_idle_add((GSourceFunc)process_js_script_queue, webview); +} + +void +gtk_webview_load_html_string_with_imgstore(GtkWebView *webview, const char *html) +{ + GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + char *html_imged; + + if (priv->images) { + g_hash_table_unref(priv->images); + priv->images = NULL; + } + + html_imged = replace_img_id_with_src(priv, html); + webkit_web_view_load_string(WEBKIT_WEB_VIEW(webview), html_imged, NULL, + NULL, "file:///"); + g_free(html_imged); +} + +/* this is a "hack", my plan is to eventually handle this + * correctly using a signals and a plugin: the plugin will have + * the information as to what javascript function to call. It seems + * wrong to hardcode that here. + */ +void +gtk_webview_append_html(GtkWebView *webview, const char *html) +{ + GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + char *escaped = gtk_webview_quote_js_string(html); + char *script = g_strdup_printf("document.write(%s)", escaped); + webkit_web_view_execute_script(WEBKIT_WEB_VIEW(webview), script); + priv->empty = FALSE; + g_free(script); + g_free(escaped); +} + +void +gtk_webview_set_vadjustment(GtkWebView *webview, GtkAdjustment *vadj) +{ + GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + priv->vadj = vadj; +} + +void +gtk_webview_scroll_to_end(GtkWebView *webview, gboolean smooth) +{ + GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + if (priv->scroll_time) + g_timer_destroy(priv->scroll_time); + if (priv->scroll_src) + g_source_remove(priv->scroll_src); + if (smooth) { + priv->scroll_time = g_timer_new(); + priv->scroll_src = g_timeout_add_full(G_PRIORITY_LOW, SCROLL_DELAY, smooth_scroll_cb, priv, NULL); + } else { + priv->scroll_time = NULL; + priv->scroll_src = g_idle_add_full(G_PRIORITY_LOW, scroll_idle_cb, priv, NULL); + } +} + +void +gtk_webview_page_up(GtkWebView *webview) +{ + GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + GtkAdjustment *vadj = priv->vadj; + gdouble scroll_val; + +#if GTK_CHECK_VERSION(2,14,0) + scroll_val = gtk_adjustment_get_value(vadj) - gtk_adjustment_get_page_size(vadj); + scroll_val = MAX(scroll_val, gtk_adjustment_get_lower(vadj)); +#else + scroll_val = gtk_adjustment_get_value(vadj) - vadj->page_size; + scroll_val = MAX(scroll_val, vadj->lower); +#endif + + gtk_adjustment_set_value(vadj, scroll_val); +} + +void +gtk_webview_page_down(GtkWebView *webview) +{ + GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + GtkAdjustment *vadj = priv->vadj; + gdouble scroll_val; + gdouble page_size; + +#if GTK_CHECK_VERSION(2,14,0) + page_size = gtk_adjustment_get_page_size(vadj); + scroll_val = gtk_adjustment_get_value(vadj) + page_size; + scroll_val = MIN(scroll_val, gtk_adjustment_get_upper(vadj) - page_size); +#else + page_size = vadj->page_size; + scroll_val = gtk_adjustment_get_value(vadj) + page_size; + scroll_val = MIN(scroll_val, vadj->upper - page_size); +#endif + + gtk_adjustment_set_value(vadj, scroll_val); +} + +void +gtk_webview_set_editable(GtkWebView *webview, gboolean editable) +{ + webkit_web_view_set_editable(WEBKIT_WEB_VIEW(webview), editable); +} + +void +gtk_webview_setup_entry(GtkWebView *webview, PurpleConnectionFlags flags) +{ + GtkWebViewButtons buttons; + + if (flags & PURPLE_CONNECTION_HTML) { + char color[8]; + GdkColor fg_color, bg_color; + gboolean bold, italic, underline, strike; + + buttons = GTK_WEBVIEW_ALL; + + if (flags & PURPLE_CONNECTION_NO_BGCOLOR) + buttons &= ~GTK_WEBVIEW_BACKCOLOR; + if (flags & PURPLE_CONNECTION_NO_FONTSIZE) + { + buttons &= ~GTK_WEBVIEW_GROW; + buttons &= ~GTK_WEBVIEW_SHRINK; + } + if (flags & PURPLE_CONNECTION_NO_URLDESC) + buttons &= ~GTK_WEBVIEW_LINKDESC; + + gtk_webview_get_current_format(webview, &bold, &italic, &underline, &strike); + + gtk_webview_set_format_functions(webview, GTK_WEBVIEW_ALL); + if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_bold") != bold) + gtk_webview_toggle_bold(webview); + + if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_italic") != italic) + gtk_webview_toggle_italic(webview); + + if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_underline") != underline) + gtk_webview_toggle_underline(webview); + + if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/send_strike") != strike) + gtk_webview_toggle_strike(webview); + + gtk_webview_toggle_fontface(webview, + purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/font_face")); + + if (!(flags & PURPLE_CONNECTION_NO_FONTSIZE)) + { + int size = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/font_size"); + + /* 3 is the default. */ + if (size != 3) + gtk_webview_font_set_size(webview, size); + } + + if (strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor"), "") != 0) + { + gdk_color_parse(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/fgcolor"), + &fg_color); + g_snprintf(color, sizeof(color), + "#%02x%02x%02x", + fg_color.red / 256, + fg_color.green / 256, + fg_color.blue / 256); + } else + strcpy(color, ""); + + gtk_webview_toggle_forecolor(webview, color); + + if (!(flags & PURPLE_CONNECTION_NO_BGCOLOR) && + strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor"), "") != 0) + { + gdk_color_parse(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/bgcolor"), + &bg_color); + g_snprintf(color, sizeof(color), + "#%02x%02x%02x", + bg_color.red / 256, + bg_color.green / 256, + bg_color.blue / 256); + } else + strcpy(color, ""); + + gtk_webview_toggle_backcolor(webview, color); + + if (flags & PURPLE_CONNECTION_FORMATTING_WBFO) + gtk_webview_set_whole_buffer_formatting_only(webview, TRUE); + else + gtk_webview_set_whole_buffer_formatting_only(webview, FALSE); + } else { + buttons = GTK_WEBVIEW_SMILEY | GTK_WEBVIEW_IMAGE; + webview_clear_formatting(webview); + } + + if (flags & PURPLE_CONNECTION_NO_IMAGES) + buttons &= ~GTK_WEBVIEW_IMAGE; + + if (flags & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) + buttons |= GTK_WEBVIEW_CUSTOM_SMILEY; + else + buttons &= ~GTK_WEBVIEW_CUSTOM_SMILEY; + + gtk_webview_set_format_functions(webview, buttons); +} + +void +gtk_webview_set_whole_buffer_formatting_only(GtkWebView *webview, gboolean wbfo) +{ + GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + priv->edit.wbfo = wbfo; +} + +void +gtk_webview_set_format_functions(GtkWebView *webview, GtkWebViewButtons buttons) +{ + GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + GObject *object = g_object_ref(G_OBJECT(webview)); + priv->format_functions = buttons; + g_signal_emit(object, signals[BUTTONS_UPDATE], 0, buttons); + g_object_unref(object); +} + +GtkWebViewButtons +gtk_webview_get_format_functions(GtkWebView *webview) +{ + GtkWebViewPriv *priv = GTK_WEBVIEW_GET_PRIVATE(webview); + return priv->format_functions; +} + +void +gtk_webview_get_current_format(GtkWebView *webview, gboolean *bold, + gboolean *italic, gboolean *underline, + gboolean *strike) +{ + WebKitDOMDocument *dom; + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); + + if (bold) + *bold = webkit_dom_document_query_command_state(dom, "bold"); + if (italic) + *italic = webkit_dom_document_query_command_state(dom, "italic"); + if (underline) + *underline = webkit_dom_document_query_command_state(dom, "underline"); + if (strike) + *strike = webkit_dom_document_query_command_state(dom, "strikethrough"); +} + +char * +gtk_webview_get_current_fontface(GtkWebView *webview) +{ + WebKitDOMDocument *dom; + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); + return webkit_dom_document_query_command_value(dom, "fontName"); +} + +char * +gtk_webview_get_current_forecolor(GtkWebView *webview) +{ + WebKitDOMDocument *dom; + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); + return webkit_dom_document_query_command_value(dom, "foreColor"); +} + +char * +gtk_webview_get_current_backcolor(GtkWebView *webview) +{ + WebKitDOMDocument *dom; + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); + return webkit_dom_document_query_command_value(dom, "backColor"); +} + +gint +gtk_webview_get_current_fontsize(GtkWebView *webview) +{ + WebKitDOMDocument *dom; + gchar *text; + gint size; + + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); + text = webkit_dom_document_query_command_value(dom, "fontSize"); + size = atoi(text); + g_free(text); + + return size; +} + +gboolean +gtk_webview_get_editable(GtkWebView *webview) +{ + return webkit_web_view_get_editable(WEBKIT_WEB_VIEW(webview)); +} + +void +gtk_webview_clear_formatting(GtkWebView *webview) +{ + GObject *object; + + object = g_object_ref(G_OBJECT(webview)); + g_signal_emit(object, signals[CLEAR_FORMAT], 0); + + gtk_widget_grab_focus(GTK_WIDGET(webview)); + + g_object_unref(object); +} + +void +gtk_webview_toggle_bold(GtkWebView *webview) +{ + WebKitDOMDocument *dom; + + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); + webkit_dom_document_exec_command(dom, "bold", FALSE, ""); +} + +void +gtk_webview_toggle_italic(GtkWebView *webview) +{ + WebKitDOMDocument *dom; + + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); + webkit_dom_document_exec_command(dom, "italic", FALSE, ""); +} + +void +gtk_webview_toggle_underline(GtkWebView *webview) +{ + WebKitDOMDocument *dom; + + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); + webkit_dom_document_exec_command(dom, "underline", FALSE, ""); +} + +void +gtk_webview_toggle_strike(GtkWebView *webview) +{ + WebKitDOMDocument *dom; + + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); + webkit_dom_document_exec_command(dom, "strikethrough", FALSE, ""); +} + +gboolean +gtk_webview_toggle_forecolor(GtkWebView *webview, const char *color) +{ + WebKitDOMDocument *dom; + + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); + webkit_dom_document_exec_command(dom, "foreColor", FALSE, color); + + return FALSE; +} + +gboolean +gtk_webview_toggle_backcolor(GtkWebView *webview, const char *color) +{ + WebKitDOMDocument *dom; + + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); + webkit_dom_document_exec_command(dom, "backColor", FALSE, color); + + return FALSE; +} + +gboolean +gtk_webview_toggle_fontface(GtkWebView *webview, const char *face) +{ + WebKitDOMDocument *dom; + + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); + webkit_dom_document_exec_command(dom, "fontName", FALSE, face); + + return FALSE; +} + +void +gtk_webview_font_set_size(GtkWebView *webview, gint size) +{ + WebKitDOMDocument *dom; + char *tmp; + + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); + tmp = g_strdup_printf("%d", size); + webkit_dom_document_exec_command(dom, "fontSize", FALSE, tmp); + g_free(tmp); +} + +void +gtk_webview_font_shrink(GtkWebView *webview) +{ + WebKitDOMDocument *dom; + gint fontsize; + char *tmp; + + fontsize = gtk_webview_get_current_fontsize(webview); + fontsize = MAX(fontsize - 1, 1); + + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); + tmp = g_strdup_printf("%d", fontsize); + webkit_dom_document_exec_command(dom, "fontSize", FALSE, tmp); + g_free(tmp); +} + +void +gtk_webview_font_grow(GtkWebView *webview) +{ + WebKitDOMDocument *dom; + gint fontsize; + char *tmp; + + fontsize = gtk_webview_get_current_fontsize(webview); + fontsize = MIN(fontsize + 1, MAX_FONT_SIZE); + + dom = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(webview)); + tmp = g_strdup_printf("%d", fontsize); + webkit_dom_document_exec_command(dom, "fontSize", FALSE, tmp); + g_free(tmp); +} + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkwebview.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/gtkwebview.h Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,379 @@ +/** + * @file gtkwebview.h Wrapper over the Gtk WebKitWebView component + * @ingroup pidgin + */ + +/* pidgin + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + */ + +#ifndef _PIDGIN_WEBVIEW_H_ +#define _PIDGIN_WEBVIEW_H_ + +#include +#include +#include + +#define GTK_TYPE_WEBVIEW (gtk_webview_get_type()) +#define GTK_WEBVIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_WEBVIEW, GtkWebView)) +#define GTK_WEBVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_WEBVIEW, GtkWebViewClass)) +#define GTK_IS_WEBVIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_WEBVIEW)) +#define GTK_IS_WEBVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_WEBVIEW)) +#define GTK_WEBVIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_WEBVIEW, GtkWebViewClass)) + +typedef enum { + GTK_WEBVIEW_BOLD = 1 << 0, + GTK_WEBVIEW_ITALIC = 1 << 1, + GTK_WEBVIEW_UNDERLINE = 1 << 2, + GTK_WEBVIEW_GROW = 1 << 3, + GTK_WEBVIEW_SHRINK = 1 << 4, + GTK_WEBVIEW_FACE = 1 << 5, + GTK_WEBVIEW_FORECOLOR = 1 << 6, + GTK_WEBVIEW_BACKCOLOR = 1 << 7, + GTK_WEBVIEW_LINK = 1 << 8, + GTK_WEBVIEW_IMAGE = 1 << 9, + GTK_WEBVIEW_SMILEY = 1 << 10, + GTK_WEBVIEW_LINKDESC = 1 << 11, + GTK_WEBVIEW_STRIKE = 1 << 12, + /** Show custom smileys when appropriate. */ + GTK_WEBVIEW_CUSTOM_SMILEY = 1 << 13, + GTK_WEBVIEW_ALL = -1 +} GtkWebViewButtons; + +typedef struct _GtkWebView GtkWebView; +typedef struct _GtkWebViewClass GtkWebViewClass; + +struct _GtkWebView +{ + WebKitWebView parent; +}; + +struct _GtkWebViewClass +{ + WebKitWebViewClass parent; + + void (*buttons_update)(GtkWebView *, GtkWebViewButtons); + void (*toggle_format)(GtkWebView *, GtkWebViewButtons); + void (*clear_format)(GtkWebView *); + void (*update_format)(GtkWebView *); +}; + +G_BEGIN_DECLS + +/** + * Returns the GType for a GtkWebView widget + * + * @return The GType for GtkWebView widget + */ +GType gtk_webview_get_type(void); + +/** + * Create a new GtkWebView object + * + * @return A GtkWidget corresponding to the GtkWebView object + */ +GtkWidget *gtk_webview_new(void); + +/** + * TODO WEBKIT: Right now this just tests whether an append has been called + * since the last clear or since the Widget was created. So it does not + * test for load_string's called in between. + * + * @param webview The GtkWebView object + * + * @return gboolean indicating whether the webview is empty + */ +gboolean gtk_webview_is_empty(GtkWebView *webview); + +/** + * A very basic routine to append html, which can be considered + * equivalent to a "document.write" using JavaScript. + * + * @param webview The GtkWebView object + * @param markup The html markup to append + */ +void gtk_webview_append_html(GtkWebView *webview, const char *markup); + +/** + * Rather than use webkit_webview_load_string, this routine + * parses and displays the \ tags that make use of the + * Pidgin imgstore. + * + * @param webview The GtkWebView object + * @param html The HTML content to load + */ +void gtk_webview_load_html_string_with_imgstore(GtkWebView *webview, const char *html); + +/** + * Execute the JavaScript only after the webkit_webview_load_string + * loads completely. We also guarantee that the scripts are executed + * in the order they are called here. This is useful to avoid race + * conditions when calling JS functions immediately after opening the + * page. + * + * @param webview The GtkWebView object + * @param script The script to execute + */ +void gtk_webview_safe_execute_script(GtkWebView *webview, const char *script); + +/** + * A convenience routine to quote a string for use as a JavaScript + * string. For instance, "hello 'world'" becomes "'hello \\'world\\''" + * + * @param str The string to escape and quote + * + * @return The quoted string + */ +char *gtk_webview_quote_js_string(const char *str); + +/** + * Set the vertical adjustment for the GtkWebView. + * + * @param webview The GtkWebView object + * @param vadj The GtkAdjustment that control the webview + */ +void gtk_webview_set_vadjustment(GtkWebView *webview, GtkAdjustment *vadj); + +/** + * Scrolls the Webview to the end of its contents. + * + * @param webview The GtkWebView object + * @param smooth A boolean indicating if smooth scrolling should be used + */ +void gtk_webview_scroll_to_end(GtkWebView *webview, gboolean smooth); + +/** + * Scrolls a GtkWebView up by one page. + * + * @param webview The GtkWebView. + */ +void gtk_webview_page_up(GtkWebView *webview); + +/** + * Scrolls a GtkWebView down by one page. + * + * @param webview The GtkWebView. + */ +void gtk_webview_page_down(GtkWebView *webview); + +/** + * Enables or disables editing in a GtkWebView. + * + * @param webview The GtkWebView + * @param editable @c TRUE to make the widget editable, or @c FALSE otherwise. + */ +void gtk_webview_set_editable(GtkWebView *webview, gboolean editable); + +/** + * Setup formatting for a GtkWebView depending on the flags specified. + * + * @param webview The GtkWebView. + * @param flags The connection flags describing the allowed formatting. + */ +void gtk_webview_setup_entry(GtkWebView *webview, PurpleConnectionFlags flags); + +/** + * Enables or disables whole buffer formatting only (wbfo) in a GtkWebView. + * In this mode formatting options to the buffer take effect for the entire + * buffer instead of specific text. + * + * @param webview The GtkWebView + * @param wbfo @c TRUE to enable the mode, or @c FALSE otherwise. + */ +void gtk_webview_set_whole_buffer_formatting_only(GtkWebView *webview, + gboolean wbfo); + +/** + * Indicates which formatting functions to enable and disable in a GtkWebView. + * + * @param webview The GtkWebView + * @param buttons A GtkWebViewButtons bitmask indicating which functions to use + */ +void gtk_webview_set_format_functions(GtkWebView *webview, + GtkWebViewButtons buttons); + +/** + * Returns which formatting functions are enabled in a GtkWebView. + * + * @param webview The GtkWebView + * + * @return A GtkWebViewButtons bitmask indicating which functions to are enabled + */ +GtkWebViewButtons gtk_webview_get_format_functions(GtkWebView *webview); + +/** + * Sets each boolean to @c TRUE or @c FALSE to indicate if that formatting + * option is enabled at the current position in a GtkWebView. + * + * @param webview The GtkWebView + * @param bold The boolean to set for bold or @c NULL. + * @param italic The boolean to set for italic or @c NULL. + * @param underline The boolean to set for underline or @c NULL. + * @param strikethrough The boolean to set for strikethrough or @c NULL. + */ +void gtk_webview_get_current_format(GtkWebView *webview, gboolean *bold, + gboolean *italic, gboolean *underline, + gboolean *strike); + +/** + * Returns a string containing the selected font face at the current position + * in a GtkWebView. + * + * @param webview The GtkWebView + * + * @return A string containing the font face or @c NULL if none is set. + */ +char *gtk_webview_get_current_fontface(GtkWebView *webview); + +/** + * Returns a string containing the selected foreground color at the current + * position in a GtkWebView. + * + * @param webview The GtkWebView + * + * @return A string containing the foreground color or @c NULL if none is set. + */ +char *gtk_webview_get_current_forecolor(GtkWebView *webview); + +/** + * Returns a string containing the selected font background color at the current + * position in a GtkWebView. + * + * @param webview The GtkWebView + * + * @return A string containing the background color or @c NULL if none is set. + */ +char *gtk_webview_get_current_backcolor(GtkWebView *webview); + +/** + * Returns a integer containing the selected HTML font size at the current + * position in a GtkWebView. + * + * @param webview The GtkWebView + * + * @return The HTML font size. + */ +gint gtk_webview_get_current_fontsize(GtkWebView *webview); + +/** + * Checks whether a GtkWebView is marked as editable. + * + * @param webview The GtkWebView + * + * @return @c TRUE if the IM/HTML is editable, or @c FALSE otherwise. + */ +gboolean gtk_webview_get_editable(GtkWebView *webview); + +/** + * Clear all the formatting on a GtkWebView. + * + * @param webview The GtkWebView + */ +void gtk_webview_clear_formatting(GtkWebView *webview); + +/** + * Toggles bold at the cursor location or selection in a GtkWebView. + * + * @param webview The GtkWebView + */ +void gtk_webview_toggle_bold(GtkWebView *webview); + +/** + * Toggles italic at the cursor location or selection in a GtkWebView. + * + * @param webview The GtkWebView + */ +void gtk_webview_toggle_italic(GtkWebView *webview); + +/** + * Toggles underline at the cursor location or selection in a GtkWebView. + * + * @param webview The GtkWebView + */ +void gtk_webview_toggle_underline(GtkWebView *webview); + +/** + * Toggles strikethrough at the cursor location or selection in a GtkWebView. + * + * @param webview The GtkWebView + */ +void gtk_webview_toggle_strike(GtkWebView *webview); + +/** + * Toggles a foreground color at the current location or selection in a + * GtkWebView. + * + * @param webview The GtkWebView + * @param color The HTML-style color, or @c NULL or "" to clear the color. + * + * @return @c TRUE if a color was set, or @c FALSE if it was cleared. + */ +gboolean gtk_webview_toggle_forecolor(GtkWebView *webview, const char *color); + +/** + * Toggles a background color at the current location or selection in a + * GtkWebView. + * + * @param webview The GtkWebView + * @param color The HTML-style color, or @c NULL or "" to clear the color. + * + * @return @c TRUE if a color was set, or @c FALSE if it was cleared. + */ +gboolean gtk_webview_toggle_backcolor(GtkWebView *webview, const char *color); + +/** + * Toggles a font face at the current location or selection in a GtkWebView. + * + * @param webview The GtkWebView + * @param face The font face name, or @c NULL or "" to clear the font. + * + * @return @c TRUE if a font name was set, or @c FALSE if it was cleared. + */ +gboolean gtk_webview_toggle_fontface(GtkWebView *webview, const char *face); + +/** + * Sets the font size at the current location or selection in a GtkWebView. + * + * @param webview The GtkWebView + * @param size The HTML font size to use. + */ +void gtk_webview_font_set_size(GtkWebView *webview, gint size); + +/** + * Decreases the font size by 1 at the current location or selection in a + * GtkWebView. + * + * @param webview The GtkWebView + */ +void gtk_webview_font_shrink(GtkWebView *webview); + +/** + * Increases the font size by 1 at the current location or selection in a + * GtkWebView. + * + * @param webview The GtkWebView + */ +void gtk_webview_font_grow(GtkWebView *webview); + +G_END_DECLS + +#endif /* _PIDGIN_WEBVIEW_H_ */ + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkwebviewtoolbar.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/gtkwebviewtoolbar.c Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,1749 @@ +/* + * @file gtkwebviewtoolbar.c GTK+ WebView Toolbar + * @ingroup pidgin + */ + +/* pidgin + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + */ +#include "internal.h" +#include "pidgin.h" + +#include "imgstore.h" +#include "notify.h" +#include "prefs.h" +#include "request.h" +#include "pidginstock.h" +#include "util.h" +#include "debug.h" + +#include "gtkdialogs.h" +#include "gtkwebviewtoolbar.h" +#include "gtksmiley.h" +#include "gtkthemes.h" +#include "gtkutils.h" + +#include + +#if !GTK_CHECK_VERSION(2,18,0) +#define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE((x)) +#define gtk_widget_is_sensitive(x) GTK_WIDGET_IS_SENSITIVE((x)) +#if !GTK_CHECK_VERSION(2,12,0) +#define gtk_widget_set_tooltip_text(w, t) \ + gtk_tooltips_set_tip(priv->tooltips, (w), (t), NULL) +#endif +#endif + +#define GTK_WEBVIEWTOOLBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), GTK_TYPE_WEBVIEWTOOLBAR, GtkWebViewToolbarPriv)) + +/****************************************************************************** + * Structs + *****************************************************************************/ + +typedef struct _GtkWebViewToolbarPriv { + PurpleConversation *active_conv; + + GtkWidget *wide_view; + GtkWidget *lean_view; + +#if !GTK_CHECK_VERSION(2,12,0) + GtkTooltips *tooltips; +#endif + + GtkWidget *font_label; + GtkWidget *font_menu; + + GtkWidget *bold; + GtkWidget *italic; + GtkWidget *underline; + GtkWidget *strike; + + GtkWidget *larger_size; + GtkWidget *normal_size; + GtkWidget *smaller_size; + + GtkWidget *font; + GtkWidget *fgcolor; + GtkWidget *bgcolor; + + GtkWidget *clear; + + GtkWidget *insert_menu; + GtkWidget *image; + GtkWidget *link; + GtkWidget *insert_hr; + + GtkWidget *smiley; + GtkWidget *attention; + GtkWidget *call; + + GtkWidget *font_dialog; + GtkWidget *fgcolor_dialog; + GtkWidget *bgcolor_dialog; + GtkWidget *link_dialog; + GtkWidget *smiley_dialog; + GtkWidget *image_dialog; + + char *sml; +} GtkWebViewToolbarPriv; + +/****************************************************************************** + * Globals + *****************************************************************************/ + +static GtkHBoxClass *parent_class = NULL; + +/****************************************************************************** + * Prototypes + *****************************************************************************/ + +static void +toggle_button_set_active_block(GtkToggleButton *button, gboolean is_active, + GtkWebViewToolbar *toolbar); + +static gboolean +gtk_webviewtoolbar_popup_menu(GtkWidget *widget, GdkEventButton *event, + GtkWebViewToolbar *toolbar); + +/****************************************************************************** + * Helpers + *****************************************************************************/ + +static void +do_bold(GtkWidget *bold, GtkWebViewToolbar *toolbar) +{ + g_return_if_fail(toolbar != NULL); + gtk_webview_toggle_bold(GTK_WEBVIEW(toolbar->webview)); + gtk_widget_grab_focus(toolbar->webview); +} + +static void +do_italic(GtkWidget *italic, GtkWebViewToolbar *toolbar) +{ + g_return_if_fail(toolbar != NULL); + gtk_webview_toggle_italic(GTK_WEBVIEW(toolbar->webview)); + gtk_widget_grab_focus(toolbar->webview); +} + +static void +do_underline(GtkWidget *underline, GtkWebViewToolbar *toolbar) +{ + g_return_if_fail(toolbar != NULL); + gtk_webview_toggle_underline(GTK_WEBVIEW(toolbar->webview)); + gtk_widget_grab_focus(toolbar->webview); +} + +static void +do_strikethrough(GtkWidget *strikethrough, GtkWebViewToolbar *toolbar) +{ + g_return_if_fail(toolbar != NULL); + gtk_webview_toggle_strike(GTK_WEBVIEW(toolbar->webview)); + gtk_widget_grab_focus(toolbar->webview); +} + +static void +do_small(GtkWidget *smalltb, GtkWebViewToolbar *toolbar) +{ + g_return_if_fail(toolbar != NULL); + /* Only shrink the font on activation, not deactivation as well */ + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(smalltb))) + gtk_webview_font_shrink(GTK_WEBVIEW(toolbar->webview)); + gtk_widget_grab_focus(toolbar->webview); +} + +static void +do_big(GtkWidget *large, GtkWebViewToolbar *toolbar) +{ + g_return_if_fail(toolbar); + /* Only grow the font on activation, not deactivation as well */ + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(large))) + gtk_webview_font_grow(GTK_WEBVIEW(toolbar->webview)); + gtk_widget_grab_focus(toolbar->webview); +} + +static gboolean +destroy_toolbar_font(GtkWidget *widget, GdkEvent *event, + GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + + if (widget != NULL) + gtk_webview_toggle_fontface(GTK_WEBVIEW(toolbar->webview), ""); + + if (priv->font_dialog != NULL) + { + gtk_widget_destroy(priv->font_dialog); + priv->font_dialog = NULL; + } + + return FALSE; +} + +static void +realize_toolbar_font(GtkWidget *widget, GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + GtkFontSelection *sel; + + sel = GTK_FONT_SELECTION(GTK_FONT_SELECTION_DIALOG(priv->font_dialog)->fontsel); + gtk_widget_hide_all(gtk_widget_get_parent(sel->size_entry)); + gtk_widget_show_all(sel->family_list); + gtk_widget_show(gtk_widget_get_parent(sel->family_list)); + gtk_widget_show(gtk_widget_get_parent(gtk_widget_get_parent(sel->family_list))); +} + +static void +cancel_toolbar_font(GtkWidget *widget, GtkWebViewToolbar *toolbar) +{ + destroy_toolbar_font(widget, NULL, toolbar); +} + +static void +apply_font(GtkWidget *widget, GtkWebViewToolbar *toolbar) +{ + /* this could be expanded to include font size, weight, etc. + but for now only works with font face */ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + GtkFontSelectionDialog *fontsel = GTK_FONT_SELECTION_DIALOG(priv->font_dialog); + gchar *fontname = gtk_font_selection_dialog_get_font_name(fontsel); + + if (fontname) { + const gchar *family_name = NULL; + PangoFontDescription *desc = NULL; + + desc = pango_font_description_from_string(fontname); + family_name = pango_font_description_get_family(desc); + + if (family_name) { + gtk_webview_toggle_fontface(GTK_WEBVIEW(toolbar->webview), + family_name); + } + + pango_font_description_free(desc); + g_free(fontname); + } + + cancel_toolbar_font(NULL, toolbar); +} + +static void +toggle_font(GtkWidget *font, GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv; + g_return_if_fail(toolbar); + priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(font))) { + char *fontname = gtk_webview_get_current_fontface(GTK_WEBVIEW(toolbar->webview)); + + if (!priv->font_dialog) { + priv->font_dialog = gtk_font_selection_dialog_new(_("Select Font")); + + if (fontname) { + char *fonttif = g_strdup_printf("%s 12", fontname); + gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(priv->font_dialog), + fonttif); + g_free(fonttif); + } else { + gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(priv->font_dialog), + DEFAULT_FONT_FACE); + } + + g_signal_connect(G_OBJECT(priv->font_dialog), "delete_event", + G_CALLBACK(destroy_toolbar_font), toolbar); + g_signal_connect(G_OBJECT(GTK_FONT_SELECTION_DIALOG(priv->font_dialog)->ok_button), "clicked", + G_CALLBACK(apply_font), toolbar); + g_signal_connect(G_OBJECT(GTK_FONT_SELECTION_DIALOG(priv->font_dialog)->cancel_button), "clicked", + G_CALLBACK(cancel_toolbar_font), toolbar); + g_signal_connect_after(G_OBJECT(priv->font_dialog), "realize", + G_CALLBACK(realize_toolbar_font), toolbar); + } + + gtk_window_present(GTK_WINDOW(priv->font_dialog)); + + g_free(fontname); + } else { + cancel_toolbar_font(font, toolbar); + } + + gtk_widget_grab_focus(toolbar->webview); +} + +static gboolean +destroy_toolbar_fgcolor(GtkWidget *widget, GdkEvent *event, + GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + + if (widget != NULL) + gtk_webview_toggle_forecolor(GTK_WEBVIEW(toolbar->webview), ""); + + if (priv->fgcolor_dialog != NULL) + { + gtk_widget_destroy(priv->fgcolor_dialog); + priv->fgcolor_dialog = NULL; + } + + return FALSE; +} + +static void +cancel_toolbar_fgcolor(GtkWidget *widget, GtkWebViewToolbar *toolbar) +{ + destroy_toolbar_fgcolor(widget, NULL, toolbar); +} + +static void +do_fgcolor(GtkWidget *widget, GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + GtkColorSelectionDialog *dialog; + GtkColorSelection *colorsel; + GdkColor text_color; + char *open_tag; + + dialog = GTK_COLOR_SELECTION_DIALOG(priv->fgcolor_dialog); + colorsel = GTK_COLOR_SELECTION(dialog->colorsel); + + open_tag = g_malloc(30); + gtk_color_selection_get_current_color(colorsel, &text_color); + g_snprintf(open_tag, 23, "#%02X%02X%02X", + text_color.red / 256, + text_color.green / 256, + text_color.blue / 256); + gtk_webview_toggle_forecolor(GTK_WEBVIEW(toolbar->webview), open_tag); + g_free(open_tag); + + cancel_toolbar_fgcolor(NULL, toolbar); +} + +static void +toggle_fg_color(GtkWidget *color, GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(color))) { + GtkWidget *colorsel; + GdkColor fgcolor; + char *color = gtk_webview_get_current_forecolor(GTK_WEBVIEW(toolbar->webview)); + + if (!priv->fgcolor_dialog) { + priv->fgcolor_dialog = gtk_color_selection_dialog_new(_("Select Text Color")); + colorsel = GTK_COLOR_SELECTION_DIALOG(priv->fgcolor_dialog)->colorsel; + if (color) { + gdk_color_parse(color, &fgcolor); + gtk_color_selection_set_current_color(GTK_COLOR_SELECTION(colorsel), &fgcolor); + } + + g_signal_connect(G_OBJECT(priv->fgcolor_dialog), "delete_event", + G_CALLBACK(destroy_toolbar_fgcolor), toolbar); + g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(priv->fgcolor_dialog)->ok_button), "clicked", + G_CALLBACK(do_fgcolor), toolbar); + g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(priv->fgcolor_dialog)->cancel_button), "clicked", + G_CALLBACK(cancel_toolbar_fgcolor), toolbar); + } + + gtk_window_present(GTK_WINDOW(priv->fgcolor_dialog)); + + g_free(color); + } else { + cancel_toolbar_fgcolor(color, toolbar); + } + + gtk_widget_grab_focus(toolbar->webview); +} + +static gboolean +destroy_toolbar_bgcolor(GtkWidget *widget, GdkEvent *event, + GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + if (widget != NULL) { + gtk_webview_toggle_backcolor(GTK_WEBVIEW(toolbar->webview), ""); + } + + if (priv->bgcolor_dialog != NULL) + { + gtk_widget_destroy(priv->bgcolor_dialog); + priv->bgcolor_dialog = NULL; + } + + return FALSE; +} + +static void +cancel_toolbar_bgcolor(GtkWidget *widget, GtkWebViewToolbar *toolbar) +{ + destroy_toolbar_bgcolor(widget, NULL, toolbar); +} + +static void +do_bgcolor(GtkWidget *widget, GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + GtkColorSelectionDialog *dialog; + GtkColorSelection *colorsel; + GdkColor text_color; + char *open_tag; + + dialog = GTK_COLOR_SELECTION_DIALOG(priv->bgcolor_dialog); + colorsel = GTK_COLOR_SELECTION(dialog->colorsel); + + open_tag = g_malloc(30); + gtk_color_selection_get_current_color(colorsel, &text_color); + g_snprintf(open_tag, 23, "#%02X%02X%02X", + text_color.red / 256, + text_color.green / 256, + text_color.blue / 256); + gtk_webview_toggle_backcolor(GTK_WEBVIEW(toolbar->webview), open_tag); + g_free(open_tag); + + cancel_toolbar_bgcolor(NULL, toolbar); +} + +static void +toggle_bg_color(GtkWidget *color, GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(color))) { + GtkWidget *colorsel; + GdkColor bgcolor; + char *color = gtk_webview_get_current_backcolor(GTK_WEBVIEW(toolbar->webview)); + + if (!priv->bgcolor_dialog) { + priv->bgcolor_dialog = gtk_color_selection_dialog_new(_("Select Background Color")); + colorsel = GTK_COLOR_SELECTION_DIALOG(priv->bgcolor_dialog)->colorsel; + if (color) { + gdk_color_parse(color, &bgcolor); + gtk_color_selection_set_current_color(GTK_COLOR_SELECTION(colorsel), &bgcolor); + } + + g_signal_connect(G_OBJECT(priv->bgcolor_dialog), "delete_event", + G_CALLBACK(destroy_toolbar_bgcolor), toolbar); + g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(priv->bgcolor_dialog)->ok_button), "clicked", + G_CALLBACK(do_bgcolor), toolbar); + g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(priv->bgcolor_dialog)->cancel_button), "clicked", + G_CALLBACK(cancel_toolbar_bgcolor), toolbar); + } + + gtk_window_present(GTK_WINDOW(priv->bgcolor_dialog)); + + g_free(color); + } else { + cancel_toolbar_bgcolor(color, toolbar); + } + + gtk_widget_grab_focus(toolbar->webview); +} + +static void +clear_formatting_cb(GtkWidget *clear, GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + toggle_button_set_active_block(GTK_TOGGLE_BUTTON(priv->clear), FALSE, toolbar); + gtk_webview_clear_formatting(GTK_WEBVIEW(toolbar->webview)); +} + +static void +cancel_link_cb(GtkWebViewToolbar *toolbar, PurpleRequestFields *fields) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->link), FALSE); + + priv->link_dialog = NULL; +} + +static void +close_link_dialog(GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + if (priv->link_dialog != NULL) + { + purple_request_close(PURPLE_REQUEST_FIELDS, priv->link_dialog); + priv->link_dialog = NULL; + } +} + +static void +do_insert_link_cb(GtkWebViewToolbar *toolbar, PurpleRequestFields *fields) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + const char *url, *description; + + url = purple_request_fields_get_string(fields, "url"); + if (gtk_webview_get_format_functions(GTK_WEBVIEW(toolbar->webview)) & GTK_WEBVIEW_LINKDESC) + description = purple_request_fields_get_string(fields, "description"); + else + description = NULL; + + if (description == NULL) + description = url; + +#if 0 + gtk_webview_insert_link(GTK_WEBVIEW(toolbar->webview), + gtk_text_buffer_get_insert(GTK_WEBVIEW(toolbar->webview)->text_buffer), + url, description); +#endif + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->link), FALSE); + + priv->link_dialog = NULL; +} + +static void +insert_link_cb(GtkWidget *w, GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->link))) { + PurpleRequestFields *fields; + PurpleRequestFieldGroup *group; + PurpleRequestField *field; +#if 0 + GtkTextIter start, end; +#endif + char *msg; + char *desc = NULL; + + fields = purple_request_fields_new(); + + group = purple_request_field_group_new(NULL); + purple_request_fields_add_group(fields, group); + + field = purple_request_field_string_new("url", _("_URL"), NULL, FALSE); + purple_request_field_set_required(field, TRUE); + purple_request_field_group_add_field(group, field); + + if (gtk_webview_get_format_functions(GTK_WEBVIEW(toolbar->webview)) & GTK_WEBVIEW_LINKDESC) { +#if 0 + if (gtk_text_buffer_get_selection_bounds(GTK_WEBVIEW(toolbar->webview)->text_buffer, &start, &end)) { + desc = gtk_webview_get_text(GTK_WEBVIEW(toolbar->webview), &start, &end); + } +#endif + field = purple_request_field_string_new("description", _("_Description"), + desc, FALSE); + purple_request_field_group_add_field(group, field); + msg = g_strdup(_("Please enter the URL and description of the " + "link that you want to insert. The description " + "is optional.")); + } else { + msg = g_strdup(_("Please enter the URL of the " + "link that you want to insert.")); + } + + priv->link_dialog = + purple_request_fields(toolbar, _("Insert Link"), + NULL, + msg, + fields, + _("_Insert"), G_CALLBACK(do_insert_link_cb), + _("Cancel"), G_CALLBACK(cancel_link_cb), + NULL, NULL, NULL, + toolbar); + g_free(msg); + g_free(desc); + } else { + close_link_dialog(toolbar); + } + + gtk_widget_grab_focus(toolbar->webview); +} + +static void +insert_hr_cb(GtkWidget *widget, GtkWebViewToolbar *toolbar) +{ +#if 0 + GtkTextIter iter; + GtkTextMark *ins; + GtkIMHtmlScalable *hr; + + ins = gtk_text_buffer_get_insert(gtk_text_view_get_buffer(GTK_TEXT_VIEW(toolbar->webview))); + gtk_text_buffer_get_iter_at_mark(gtk_text_view_get_buffer(GTK_TEXT_VIEW(toolbar->webview)), &iter, ins); + hr = gtk_webview_hr_new(); + gtk_webview_hr_add_to(hr, GTK_WEBVIEW(toolbar->webview), &iter); +#endif +} + +static void +do_insert_image_cb(GtkWidget *widget, int response, GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->image), FALSE); +#if 0 + gchar *filename, *name, *buf; + char *filedata; + size_t size; + GError *error = NULL; + int id; + GtkTextIter iter; + GtkTextMark *ins; + + if (response != GTK_RESPONSE_ACCEPT) + { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->image), FALSE); + return; + } + + filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget)); + + if (filename == NULL) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->image), FALSE); + return; + } + + /* The following triggers a callback that closes the widget */ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->image), FALSE); + + if (!g_file_get_contents(filename, &filedata, &size, &error)) { + purple_notify_error(NULL, NULL, error->message, NULL); + + g_error_free(error); + g_free(filename); + + return; + } + + name = strrchr(filename, G_DIR_SEPARATOR) + 1; + + id = purple_imgstore_add_with_id(filedata, size, name); + + if (id == 0) { + buf = g_strdup_printf(_("Failed to store image: %s\n"), filename); + purple_notify_error(NULL, NULL, buf, NULL); + + g_free(buf); + g_free(filename); + + return; + } + + g_free(filename); + + ins = gtk_text_buffer_get_insert(gtk_text_view_get_buffer(GTK_TEXT_VIEW(toolbar->webview))); + gtk_text_buffer_get_iter_at_mark(gtk_text_view_get_buffer(GTK_TEXT_VIEW(toolbar->webview)), + &iter, ins); + gtk_webview_insert_image_at_iter(GTK_WEBVIEW(toolbar->webview), id, &iter); + purple_imgstore_unref_by_id(id); +#endif +} + +static void +insert_image_cb(GtkWidget *save, GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + GtkWidget *window; + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->image))) { + window = gtk_file_chooser_dialog_new(_("Insert Image"), + NULL, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + gtk_dialog_set_default_response(GTK_DIALOG(window), GTK_RESPONSE_ACCEPT); + g_signal_connect(G_OBJECT(GTK_FILE_CHOOSER(window)), + "response", G_CALLBACK(do_insert_image_cb), toolbar); + + gtk_widget_show(window); + priv->image_dialog = window; + } else { + gtk_widget_destroy(priv->image_dialog); + priv->image_dialog = NULL; + } + + gtk_widget_grab_focus(toolbar->webview); +} + +#if 0 +static void +destroy_smiley_dialog(GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + if (priv->smiley_dialog != NULL) + { + gtk_widget_destroy(priv->smiley_dialog); + priv->smiley_dialog = NULL; + } +} + +static gboolean +close_smiley_dialog(GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->smiley), FALSE); + return FALSE; +} + + +static void +insert_smiley_text(GtkWidget *widget, GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + char *smiley_text, *escaped_smiley; + + smiley_text = g_object_get_data(G_OBJECT(widget), "smiley_text"); + escaped_smiley = g_markup_escape_text(smiley_text, -1); + + gtk_webview_insert_smiley(GTK_WEBVIEW(toolbar->webview), + GTK_WEBVIEW(toolbar->webview)->protocol_name, + escaped_smiley); + + g_free(escaped_smiley); + + close_smiley_dialog(toolbar); +} + +/* smiley buttons list */ +struct smiley_button_list { + int width, height; + GtkWidget *button; + const GtkIMHtmlSmiley *smiley; + struct smiley_button_list *next; +}; + +static struct smiley_button_list * +sort_smileys(struct smiley_button_list *ls, GtkWebViewToolbar *toolbar, + int *width, const GtkIMHtmlSmiley *smiley) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + GtkWidget *image; + GtkWidget *button; + GtkRequisition size; + struct smiley_button_list *cur; + struct smiley_button_list *it, *it_last; + const gchar *filename = smiley->file; + gchar *face = smiley->smile; + PurpleSmiley *psmiley = NULL; + gboolean supports_custom = (gtk_webview_get_format_functions(GTK_WEBVIEW(toolbar->webview)) & GTK_WEBVIEW_CUSTOM_SMILEY); + + cur = g_new0(struct smiley_button_list, 1); + it = ls; + it_last = ls; /* list iterators*/ + image = gtk_image_new_from_file(filename); + + gtk_widget_size_request(image, &size); + + if (size.width > 24 && + smiley->flags & GTK_WEBVIEW_SMILEY_CUSTOM) { /* This is a custom smiley, let's scale it */ + GdkPixbuf *pixbuf = NULL; + GtkImageType type; + + type = gtk_image_get_storage_type(GTK_IMAGE(image)); + + if (type == GTK_IMAGE_PIXBUF) { + pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(image)); + } else if (type == GTK_IMAGE_ANIMATION) { + GdkPixbufAnimation *animation; + + animation = gtk_image_get_animation(GTK_IMAGE(image)); + + pixbuf = gdk_pixbuf_animation_get_static_image(animation); + } + + if (pixbuf != NULL) { + GdkPixbuf *resized; + resized = gdk_pixbuf_scale_simple(pixbuf, 24, 24, + GDK_INTERP_HYPER); + + gtk_image_set_from_pixbuf(GTK_IMAGE(image), resized); /* This unrefs pixbuf */ + gtk_widget_size_request(image, &size); + g_object_unref(G_OBJECT(resized)); + } + } + + (*width) += size.width; + + button = gtk_button_new(); + gtk_container_add(GTK_CONTAINER(button), image); + + g_object_set_data(G_OBJECT(button), "smiley_text", face); + g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(insert_smiley_text), toolbar); + + gtk_widget_set_tooltip_text(button, face); + + /* these look really weird with borders */ + gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); + + psmiley = purple_smileys_find_by_shortcut(smiley->smile); + /* If this is a "non-custom" smiley, check to see if its shortcut is + "shadowed" by any custom smiley. This can only happen if the connection + is custom smiley-enabled */ + if (supports_custom && psmiley && !(smiley->flags & GTK_WEBVIEW_SMILEY_CUSTOM)) { + gchar tip[128]; + g_snprintf(tip, sizeof(tip), + _("This smiley is disabled because a custom smiley exists for this shortcut:\n %s"), + face); + gtk_widget_set_tooltip_text(button, tip); + gtk_widget_set_sensitive(button, FALSE); + } else if (psmiley) { + /* Remove the button if the smiley is destroyed */ + g_signal_connect_object(G_OBJECT(psmiley), "destroy", G_CALLBACK(gtk_widget_destroy), + button, G_CONNECT_SWAPPED); + } + + /* set current element to add */ + cur->height = size.height; + cur->width = size.width; + cur->button = button; + cur->smiley = smiley; + cur->next = ls; + + /* check where to insert by height */ + if (ls == NULL) + return cur; + while (it != NULL) { + it_last = it; + it = it->next; + } + cur->next = it; + it_last->next = cur; + return ls; +} + +static gboolean +smiley_is_unique(GSList *list, GtkIMHtmlSmiley *smiley) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + while (list) { + GtkIMHtmlSmiley *cur = (GtkIMHtmlSmiley *) list->data; + if (!strcmp(cur->file, smiley->file)) + return FALSE; + list = list->next; + } + return TRUE; +} + +static gboolean +smiley_dialog_input_cb(GtkWidget *dialog, GdkEvent *event, + GtkWebViewToolbar *toolbar) +{ + if ((event->type == GDK_KEY_PRESS && event->key.keyval == GDK_Escape) || + (event->type == GDK_BUTTON_PRESS && event->button.button == 1)) + { + close_smiley_dialog(toolbar); + return TRUE; + } + + return FALSE; +} + +static void +add_smiley_list(GtkWidget *container, struct smiley_button_list *list, + int max_width, gboolean custom) +{ + GtkWidget *line; + int line_width = 0; + + if (!list) + return; + + line = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(container), line, FALSE, FALSE, 0); + for (; list; list = list->next) { + if (custom != !!(list->smiley->flags & GTK_WEBVIEW_SMILEY_CUSTOM)) + continue; + gtk_box_pack_start(GTK_BOX(line), list->button, FALSE, FALSE, 0); + gtk_widget_show(list->button); + line_width += list->width; + if (line_width >= max_width) { + if (list->next) { + line = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(container), line, FALSE, FALSE, 0); + } + line_width = 0; + } + } +} +#endif + +static void +insert_smiley_cb(GtkWidget *smiley, GtkWebViewToolbar *toolbar) +{ +#if 0 + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + GtkWidget *dialog, *vbox; + GtkWidget *smiley_table = NULL; + GSList *smileys, *unique_smileys = NULL; + const GSList *custom_smileys = NULL; + gboolean supports_custom = FALSE; + GtkRequisition req; + GtkWidget *scrolled, *viewport; + + if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(smiley))) { + destroy_smiley_dialog(toolbar); + gtk_widget_grab_focus(toolbar->webview); + return; + } + + if (priv->sml) + smileys = pidgin_themes_get_proto_smileys(priv->sml); + else + smileys = pidgin_themes_get_proto_smileys(NULL); + + /* Note: prepend smileys to list to avoid O(n^2) overhead when there is + a large number of smileys... need to revers the list after for the dialog + work... */ + while(smileys) { + GtkIMHtmlSmiley *smiley = (GtkIMHtmlSmiley *) smileys->data; + if(!smiley->hidden) { + if(smiley_is_unique(unique_smileys, smiley)) { + unique_smileys = g_slist_prepend(unique_smileys, smiley); + } + } + smileys = smileys->next; + } + supports_custom = (gtk_webview_get_format_functions(GTK_WEBVIEW(toolbar->webview)) & GTK_WEBVIEW_CUSTOM_SMILEY); + if (toolbar->webview && supports_custom) { + const GSList *iterator = NULL; + custom_smileys = pidgin_smileys_get_all(); + + for (iterator = custom_smileys ; iterator ; + iterator = g_slist_next(iterator)) { + GtkIMHtmlSmiley *smiley = (GtkIMHtmlSmiley *) iterator->data; + unique_smileys = g_slist_prepend(unique_smileys, smiley); + } + } + + /* we need to reverse the list to get the smileys in the correct order */ + unique_smileys = g_slist_reverse(unique_smileys); + + dialog = pidgin_create_dialog(_("Smile!"), 0, "smiley_dialog", FALSE); + gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE); + vbox = pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(dialog), FALSE, 0); + + if (unique_smileys != NULL) { + struct smiley_button_list *ls; + int max_line_width, num_lines, button_width = 0; + + /* We use hboxes packed in a vbox */ + ls = NULL; + max_line_width = 0; + num_lines = floor(sqrt(g_slist_length(unique_smileys))); + smiley_table = gtk_vbox_new(FALSE, 0); + + if (supports_custom) { + GtkWidget *manage = gtk_button_new_with_mnemonic(_("_Manage custom smileys")); + GtkRequisition req; + g_signal_connect(G_OBJECT(manage), "clicked", + G_CALLBACK(pidgin_smiley_manager_show), NULL); + g_signal_connect_swapped(G_OBJECT(manage), "clicked", + G_CALLBACK(gtk_widget_destroy), dialog); + gtk_box_pack_end(GTK_BOX(vbox), manage, FALSE, TRUE, 0); + gtk_widget_size_request(manage, &req); + button_width = req.width; + } + + /* create list of smileys sorted by height */ + while (unique_smileys) { + GtkIMHtmlSmiley *smiley = (GtkIMHtmlSmiley *) unique_smileys->data; + if (!smiley->hidden) { + ls = sort_smileys(ls, toolbar, &max_line_width, smiley); + } + unique_smileys = g_slist_delete_link(unique_smileys, unique_smileys); + } + /* The window will be at least as wide as the 'Manage ..' button */ + max_line_width = MAX(button_width, max_line_width / num_lines); + + /* pack buttons of the list */ + add_smiley_list(smiley_table, ls, max_line_width, FALSE); + if (supports_custom) { + gtk_box_pack_start(GTK_BOX(smiley_table), gtk_hseparator_new(), TRUE, FALSE, 0); + add_smiley_list(smiley_table, ls, max_line_width, TRUE); + } + while (ls) { + struct smiley_button_list *tmp = ls->next; + g_free(ls); + ls = tmp; + } + + gtk_widget_add_events(dialog, GDK_KEY_PRESS_MASK); + } + else { + smiley_table = gtk_label_new(_("This theme has no available smileys.")); + gtk_widget_add_events(dialog, GDK_KEY_PRESS_MASK | GDK_BUTTON_PRESS_MASK); + g_signal_connect(G_OBJECT(dialog), "button-press-event", (GCallback)smiley_dialog_input_cb, toolbar); + } + + + scrolled = pidgin_make_scrollable(smiley_table, GTK_POLICY_NEVER, GTK_POLICY_NEVER, GTK_SHADOW_NONE, -1, -1); + gtk_box_pack_start(GTK_BOX(vbox), scrolled, TRUE, TRUE, 0); + gtk_widget_show(smiley_table); + + viewport = gtk_widget_get_parent(smiley_table); + gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE); + + /* connect signals */ + g_signal_connect_swapped(G_OBJECT(dialog), "destroy", G_CALLBACK(close_smiley_dialog), toolbar); + g_signal_connect(G_OBJECT(dialog), "key-press-event", G_CALLBACK(smiley_dialog_input_cb), toolbar); + + gtk_window_set_transient_for(GTK_WINDOW(dialog), + GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(toolbar)))); + + /* show everything */ + gtk_widget_show_all(dialog); + + gtk_widget_size_request(viewport, &req); + gtk_widget_set_size_request(scrolled, MIN(300, req.width), MIN(290, req.height)); + + /* The window has to be made resizable, and the scrollbars in the scrolled window + * enabled only after setting the desired size of the window. If we do either of + * these tasks before now, GTK+ miscalculates the required size, and erronously + * makes one or both scrollbars visible (sometimes). + * I too think this hack is gross. But I couldn't find a better way -- sadrul */ + gtk_window_set_resizable(GTK_WINDOW(dialog), TRUE); + g_object_set(G_OBJECT(scrolled), + "hscrollbar-policy", GTK_POLICY_AUTOMATIC, + "vscrollbar-policy", GTK_POLICY_AUTOMATIC, + NULL); + +#ifdef _WIN32 + winpidgin_ensure_onscreen(dialog); +#endif + + priv->smiley_dialog = dialog; + + gtk_widget_grab_focus(toolbar->webview); +#endif +} + +static void +send_attention_cb(GtkWidget *attention, GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + PurpleConversation *conv = priv->active_conv; + const gchar *who = purple_conversation_get_name(conv); + PurpleConnection *gc = purple_conversation_get_connection(conv); + + toggle_button_set_active_block(GTK_TOGGLE_BUTTON(attention), FALSE, toolbar); + purple_prpl_send_attention(gc, who, 0); + gtk_widget_grab_focus(toolbar->webview); +} + +static void +update_buttons_cb(GtkWebView *webview, GtkWebViewButtons buttons, + GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + gtk_widget_set_sensitive(GTK_WIDGET(priv->bold), buttons & GTK_WEBVIEW_BOLD); + gtk_widget_set_sensitive(GTK_WIDGET(priv->italic), buttons & GTK_WEBVIEW_ITALIC); + gtk_widget_set_sensitive(GTK_WIDGET(priv->underline), buttons & GTK_WEBVIEW_UNDERLINE); + gtk_widget_set_sensitive(GTK_WIDGET(priv->strike), buttons & GTK_WEBVIEW_STRIKE); + + gtk_widget_set_sensitive(GTK_WIDGET(priv->larger_size), buttons & GTK_WEBVIEW_GROW); + gtk_widget_set_sensitive(GTK_WIDGET(priv->smaller_size), buttons & GTK_WEBVIEW_SHRINK); + + gtk_widget_set_sensitive(GTK_WIDGET(priv->font), buttons & GTK_WEBVIEW_FACE); + gtk_widget_set_sensitive(GTK_WIDGET(priv->fgcolor), buttons & GTK_WEBVIEW_FORECOLOR); + gtk_widget_set_sensitive(GTK_WIDGET(priv->bgcolor), buttons & GTK_WEBVIEW_BACKCOLOR); + + gtk_widget_set_sensitive(GTK_WIDGET(priv->clear), + (buttons & GTK_WEBVIEW_BOLD || + buttons & GTK_WEBVIEW_ITALIC || + buttons & GTK_WEBVIEW_UNDERLINE || + buttons & GTK_WEBVIEW_STRIKE || + buttons & GTK_WEBVIEW_GROW || + buttons & GTK_WEBVIEW_SHRINK || + buttons & GTK_WEBVIEW_FACE || + buttons & GTK_WEBVIEW_FORECOLOR || + buttons & GTK_WEBVIEW_BACKCOLOR)); + + gtk_widget_set_sensitive(GTK_WIDGET(priv->image), buttons & GTK_WEBVIEW_IMAGE); + gtk_widget_set_sensitive(GTK_WIDGET(priv->link), buttons & GTK_WEBVIEW_LINK); + gtk_widget_set_sensitive(GTK_WIDGET(priv->smiley), buttons & GTK_WEBVIEW_SMILEY); +} + +/* we call this when we want to _set_active the toggle button, it'll + * block the callback thats connected to the button so we don't have to + * do the double toggling hack + */ +static void +toggle_button_set_active_block(GtkToggleButton *button, gboolean is_active, + GtkWebViewToolbar *toolbar) +{ + GObject *object; + g_return_if_fail(toolbar); + + object = g_object_ref(button); + g_signal_handlers_block_matched(object, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, toolbar); + gtk_toggle_button_set_active(button, is_active); + g_signal_handlers_unblock_matched(object, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, toolbar); + g_object_unref(object); +} + +static void +update_buttons(GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + gboolean bold, italic, underline, strike; + char *tmp; + GtkLabel *label = GTK_LABEL(priv->font_label); + + gtk_label_set_label(label, _("_Font")); + + gtk_webview_get_current_format(GTK_WEBVIEW(toolbar->webview), + &bold, &italic, &underline, &strike); + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->bold)) != bold) + toggle_button_set_active_block(GTK_TOGGLE_BUTTON(priv->bold), bold, + toolbar); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->italic)) != italic) + toggle_button_set_active_block(GTK_TOGGLE_BUTTON(priv->italic), italic, + toolbar); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->underline)) != underline) + toggle_button_set_active_block(GTK_TOGGLE_BUTTON(priv->underline), + underline, toolbar); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->strike)) != strike) + toggle_button_set_active_block(GTK_TOGGLE_BUTTON(priv->strike), + strike, toolbar); + + /* These buttons aren't ever "active". */ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->smaller_size), FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->larger_size), FALSE); + + if (bold) { + gchar *markup = g_strdup_printf("%s", + gtk_label_get_label(label)); + gtk_label_set_markup_with_mnemonic(label, markup); + g_free(markup); + } + if (italic) { + gchar *markup = g_strdup_printf("%s", + gtk_label_get_label(label)); + gtk_label_set_markup_with_mnemonic(label, markup); + g_free(markup); + } + if (underline) { + gchar *markup = g_strdup_printf("%s", + gtk_label_get_label(label)); + gtk_label_set_markup_with_mnemonic(label, markup); + g_free(markup); + } + if (strike) { + gchar *markup = g_strdup_printf("%s", + gtk_label_get_label(label)); + gtk_label_set_markup_with_mnemonic(label, markup); + g_free(markup); + } + + tmp = gtk_webview_get_current_fontface(GTK_WEBVIEW(toolbar->webview)); + toggle_button_set_active_block(GTK_TOGGLE_BUTTON(priv->font), + (tmp != NULL), toolbar); + if (tmp != NULL) { + gchar *markup = g_strdup_printf("%s", + tmp, gtk_label_get_label(label)); + gtk_label_set_markup_with_mnemonic(label, markup); + g_free(markup); + } + g_free(tmp); + + tmp = gtk_webview_get_current_forecolor(GTK_WEBVIEW(toolbar->webview)); + toggle_button_set_active_block(GTK_TOGGLE_BUTTON(priv->fgcolor), + (tmp != NULL), toolbar); + if (tmp != NULL) { + gchar *markup = g_strdup_printf("%s", + tmp, gtk_label_get_label(label)); + gtk_label_set_markup_with_mnemonic(label, markup); + g_free(markup); + } + g_free(tmp); + + tmp = gtk_webview_get_current_backcolor(GTK_WEBVIEW(toolbar->webview)); + toggle_button_set_active_block(GTK_TOGGLE_BUTTON(priv->bgcolor), + (tmp != NULL), toolbar); + if (tmp != NULL) { + gchar *markup = g_strdup_printf("%s", + tmp, gtk_label_get_label(label)); + gtk_label_set_markup_with_mnemonic(label, markup); + g_free(markup); + } + g_free(tmp); +} + +static void +toggle_button_cb(GtkWebView *webview, GtkWebViewButtons buttons, + GtkWebViewToolbar *toolbar) +{ + update_buttons(toolbar); +} + +static void +update_format_cb(GtkWebView *webview, GtkWebViewToolbar *toolbar) +{ + update_buttons(toolbar); +} + +#if 0 +static void +mark_set_cb(GtkTextBuffer *buffer, GtkTextIter *location, GtkTextMark *mark, + GtkWebViewToolbar *toolbar) +{ + if(mark != gtk_text_buffer_get_insert(buffer)) + return; + + update_buttons(toolbar); +} +#endif + +/* This comes from gtkmenutoolbutton.c from gtk+ + * Copyright (C) 2003 Ricardo Fernandez Pascual + * Copyright (C) 2004 Paolo Borelli + */ +static void +menu_position_func(GtkMenu *menu, + int *x, + int *y, + gboolean *push_in, + gpointer data) +{ + GtkWidget *widget = GTK_WIDGET(data); + GtkRequisition menu_req; + gint ythickness = widget->style->ythickness; + int savy; + + gtk_widget_size_request(GTK_WIDGET (menu), &menu_req); + gdk_window_get_origin(widget->window, x, y); + *x += widget->allocation.x; + *y += widget->allocation.y + widget->allocation.height; + savy = *y; + + pidgin_menu_position_func_helper(menu, x, y, push_in, data); + + if (savy > *y + ythickness + 1) + *y -= widget->allocation.height; +} + +static gboolean +button_activate_on_click(GtkWidget *button, GdkEventButton *event, + GtkWebViewToolbar *toolbar) +{ + if (event->button == 1 && GTK_IS_TOGGLE_BUTTON(button)) + gtk_widget_activate(button); + else if (event->button == 3) + return gtk_webviewtoolbar_popup_menu(button, event, toolbar); + return FALSE; +} + +static void +pidgin_menu_clicked(GtkWidget *button, GtkMenu *menu) +{ + gtk_widget_show_all(GTK_WIDGET(menu)); + gtk_menu_popup(menu, NULL, NULL, menu_position_func, button, 0, gtk_get_current_event_time()); +} + +static void +pidgin_menu_deactivate(GtkWidget *menu, GtkToggleButton *button) +{ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE); +} + +static void +switch_toolbar_view(GtkWidget *item, GtkWebViewToolbar *toolbar) +{ + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/toolbar/wide", + !purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/toolbar/wide")); +} + +static gboolean +gtk_webviewtoolbar_popup_menu(GtkWidget *widget, GdkEventButton *event, + GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + GtkWidget *menu; + GtkWidget *item; + gboolean wide; + + if (event->button != 3) + return FALSE; + + wide = gtk_widget_get_visible(priv->bold); + + menu = gtk_menu_new(); + item = gtk_menu_item_new_with_mnemonic(wide ? _("Group Items") : _("Ungroup Items")); + g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(switch_toolbar_view), toolbar); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + gtk_widget_show(item); + + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, pidgin_menu_position_func_helper, + widget, event->button, event->time); + return TRUE; +} + +static void +button_visibility_changed(GtkWidget *button, gpointer dontcare, GtkWidget *item) +{ + if (gtk_widget_get_visible(button)) + gtk_widget_hide(item); + else + gtk_widget_show(item); +} + +static void +button_sensitiveness_changed(GtkWidget *button, gpointer dontcare, GtkWidget *item) +{ + gtk_widget_set_sensitive(item, gtk_widget_is_sensitive(button)); +} + +static void +update_menuitem(GtkToggleButton *button, GtkCheckMenuItem *item) +{ + g_signal_handlers_block_by_func(G_OBJECT(item), G_CALLBACK(gtk_button_clicked), button); + gtk_check_menu_item_set_active(item, gtk_toggle_button_get_active(button)); + g_signal_handlers_unblock_by_func(G_OBJECT(item), G_CALLBACK(gtk_button_clicked), button); +} + +static void +enable_markup(GtkWidget *widget, gpointer null) +{ + if (GTK_IS_LABEL(widget)) + g_object_set(G_OBJECT(widget), "use-markup", TRUE, NULL); +} + +static void +webviewtoolbar_view_pref_changed(const char *name, PurplePrefType type, + gconstpointer value, gpointer toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + if (value) { + gtk_widget_hide_all(priv->lean_view); + gtk_widget_show_all(priv->wide_view); + } else { + gtk_widget_hide_all(priv->wide_view); + gtk_widget_show_all(priv->lean_view); + } +} + +/****************************************************************************** + * GObject stuff + *****************************************************************************/ + +static void +gtk_webviewtoolbar_finalize(GObject *object) +{ + GtkWebViewToolbar *toolbar = GTK_WEBVIEWTOOLBAR(object); + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + + if (priv->image_dialog != NULL) + { + gtk_widget_destroy(priv->image_dialog); + priv->image_dialog = NULL; + } + + destroy_toolbar_font(NULL, NULL, toolbar); + if (priv->smiley_dialog != NULL) { +#if 0 + g_signal_handlers_disconnect_by_func(G_OBJECT(priv->smiley_dialog), close_smiley_dialog, toolbar); + destroy_smiley_dialog(toolbar); +#endif + } + destroy_toolbar_bgcolor(NULL, NULL, toolbar); + destroy_toolbar_fgcolor(NULL, NULL, toolbar); + close_link_dialog(toolbar); + if (toolbar->webview) { + g_signal_handlers_disconnect_matched(toolbar->webview, + G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, + toolbar); +#if 0 + g_signal_handlers_disconnect_matched(GTK_WEBVIEW(toolbar->webview)->text_buffer, + G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, + toolbar); +#endif + } + + g_free(priv->sml); + +#if !GTK_CHECK_VERSION(2,12,0) + gtk_object_sink(GTK_OBJECT(priv->tooltips)); +#endif + + if (priv->font_menu) + gtk_widget_destroy(priv->font_menu); + if (priv->insert_menu) + gtk_widget_destroy(priv->insert_menu); + + purple_prefs_disconnect_by_handle(object); + + G_OBJECT_CLASS(parent_class)->finalize (object); +} + +static void +gtk_webviewtoolbar_class_init(GtkWebViewToolbarClass *class) +{ + GObjectClass *gobject_class; + gobject_class = (GObjectClass *)class; + parent_class = g_type_class_ref(GTK_TYPE_HBOX); + gobject_class->finalize = gtk_webviewtoolbar_finalize; + + g_type_class_add_private(class, sizeof(GtkWebViewToolbarPriv)); + + purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/toolbar"); + purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/toolbar/wide", FALSE); +} + +static void +gtk_webviewtoolbar_create_old_buttons(GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + GtkWidget *hbox; + GtkWidget *button; + struct { + char *stock; + gpointer callback; + GtkWidget **button; + const char *tooltip; + } buttons[] = { + {GTK_STOCK_BOLD, G_CALLBACK(do_bold), &priv->bold, _("Bold")}, + {GTK_STOCK_ITALIC, do_italic, &priv->italic, _("Italic")}, + {GTK_STOCK_UNDERLINE, do_underline, &priv->underline, _("Underline")}, + {GTK_STOCK_STRIKETHROUGH, do_strikethrough, &priv->strike, _("Strikethrough")}, + {"", NULL, NULL, NULL}, + {PIDGIN_STOCK_TOOLBAR_TEXT_LARGER, do_big, &priv->larger_size, _("Increase Font Size")}, + {PIDGIN_STOCK_TOOLBAR_TEXT_SMALLER, do_small, &priv->smaller_size, _("Decrease Font Size")}, + {"", NULL, NULL, NULL}, + {PIDGIN_STOCK_TOOLBAR_FONT_FACE, toggle_font, &priv->font, _("Font Face")}, + {PIDGIN_STOCK_TOOLBAR_FGCOLOR, toggle_fg_color, &priv->fgcolor, _("Foreground Color")}, + {PIDGIN_STOCK_TOOLBAR_BGCOLOR, toggle_bg_color, &priv->bgcolor, _("Background Color")}, + {"", NULL, NULL, NULL}, + {PIDGIN_STOCK_CLEAR, clear_formatting_cb, &priv->clear, _("Reset Formatting")}, + {"", NULL, NULL, NULL}, + {PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE, insert_image_cb, &priv->image, _("Insert IM Image")}, + {PIDGIN_STOCK_TOOLBAR_INSERT_LINK, insert_link_cb, &priv->link, _("Insert Link")}, + {"", NULL, NULL, NULL}, + {PIDGIN_STOCK_TOOLBAR_SMILEY, insert_smiley_cb, &priv->smiley, _("Insert Smiley")}, + {PIDGIN_STOCK_TOOLBAR_SEND_ATTENTION, send_attention_cb, &priv->attention, _("Send Attention")}, + {NULL, NULL, NULL, NULL} + }; + int iter; + + hbox = gtk_hbox_new(FALSE, 0); + + for (iter = 0; buttons[iter].stock; iter++) { + if (buttons[iter].stock[0]) { + button = pidgin_pixbuf_toolbar_button_from_stock(buttons[iter].stock); + g_signal_connect(G_OBJECT(button), "button-press-event", G_CALLBACK(gtk_webviewtoolbar_popup_menu), toolbar); + g_signal_connect(G_OBJECT(button), "clicked", + G_CALLBACK(buttons[iter].callback), toolbar); + *(buttons[iter].button) = button; + gtk_widget_set_tooltip_text(button, buttons[iter].tooltip); + } else + button = gtk_vseparator_new(); + gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); + } + + gtk_box_pack_start(GTK_BOX(toolbar), hbox, FALSE, FALSE, 0); + priv->wide_view = hbox; +} + +static void +gtk_webviewtoolbar_init(GtkWebViewToolbar *toolbar) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + GtkWidget *hbox = GTK_WIDGET(toolbar), *event = gtk_event_box_new(); + GtkWidget *bbox, *box = gtk_hbox_new(FALSE, 0); + GtkWidget *image; + GtkWidget *label; + GtkWidget *insert_button; + GtkWidget *font_button; + GtkWidget *smiley_button; + GtkWidget *attention_button; + GtkWidget *font_menu; + GtkWidget *insert_menu; + GtkWidget *menuitem; + GtkWidget *sep; + int i; + struct { + const char *label; + GtkWidget **button; + gboolean check; + } buttons[] = { + {_("_Bold"), &priv->bold, TRUE}, + {_("_Italic"), &priv->italic, TRUE}, + {_("_Underline"), &priv->underline, TRUE}, + {_("Strikethrough"), &priv->strike, TRUE}, + {_("_Larger"), &priv->larger_size, TRUE}, +#if 0 + {_("_Normal"), &priv->normal_size, TRUE}, +#endif + {_("_Smaller"), &priv->smaller_size, TRUE}, + /* If we want to show the formatting for the following items, we would + * need to update them when formatting changes. The above items don't need + * no updating nor nothin' */ + {_("_Font face"), &priv->font, TRUE}, + {_("Foreground _color"), &priv->fgcolor, TRUE}, + {_("Bac_kground color"), &priv->bgcolor, TRUE}, + {_("_Reset formatting"), &priv->clear, FALSE}, + {NULL, NULL, FALSE} + }; + + toolbar->webview = NULL; + priv->font_dialog = NULL; + priv->fgcolor_dialog = NULL; + priv->bgcolor_dialog = NULL; + priv->link_dialog = NULL; + priv->smiley_dialog = NULL; + priv->image_dialog = NULL; + +#if !GTK_CHECK_VERSION(2,12,0) + priv->tooltips = gtk_tooltips_new(); +#endif + + gtk_box_set_spacing(GTK_BOX(toolbar), 3); + + gtk_webviewtoolbar_create_old_buttons(toolbar); + + /* Fonts */ + font_button = gtk_toggle_button_new(); + gtk_button_set_relief(GTK_BUTTON(font_button), GTK_RELIEF_NONE); + bbox = gtk_hbox_new(FALSE, 3); + gtk_container_add(GTK_CONTAINER(font_button), bbox); + image = gtk_image_new_from_stock(GTK_STOCK_BOLD, gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL)); + gtk_box_pack_start(GTK_BOX(bbox), image, FALSE, FALSE, 0); + priv->font_label = label = gtk_label_new_with_mnemonic(_("_Font")); + gtk_label_set_use_markup(GTK_LABEL(label), TRUE); + gtk_box_pack_start(GTK_BOX(bbox), label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(box), font_button, FALSE, FALSE, 0); + gtk_widget_show_all(font_button); + + priv->font_menu = font_menu = gtk_menu_new(); + + for (i = 0; buttons[i].label; i++) { + GtkWidget *old = *buttons[i].button; + if (buttons[i].check) { + menuitem = gtk_check_menu_item_new_with_mnemonic(buttons[i].label); + g_signal_connect_after(G_OBJECT(old), "toggled", + G_CALLBACK(update_menuitem), menuitem); + } else { + menuitem = gtk_menu_item_new_with_mnemonic(buttons[i].label); + } + g_signal_connect_swapped(G_OBJECT(menuitem), "activate", + G_CALLBACK(gtk_button_clicked), old); + gtk_menu_shell_append(GTK_MENU_SHELL(font_menu), menuitem); + g_signal_connect(G_OBJECT(old), "notify::sensitive", + G_CALLBACK(button_sensitiveness_changed), menuitem); + g_signal_connect(G_OBJECT(old), "notify::visible", + G_CALLBACK(button_visibility_changed), menuitem); + gtk_container_foreach(GTK_CONTAINER(menuitem), (GtkCallback)enable_markup, NULL); + } + + g_signal_connect(G_OBJECT(font_button), "button-press-event", G_CALLBACK(button_activate_on_click), toolbar); + g_signal_connect(G_OBJECT(font_button), "activate", G_CALLBACK(pidgin_menu_clicked), font_menu); + g_signal_connect(G_OBJECT(font_menu), "deactivate", G_CALLBACK(pidgin_menu_deactivate), font_button); + + /* Sep */ + sep = gtk_vseparator_new(); + gtk_box_pack_start(GTK_BOX(box), sep, FALSE, FALSE, 0); + gtk_widget_show_all(sep); + + /* Insert */ + insert_button = gtk_toggle_button_new(); + gtk_button_set_relief(GTK_BUTTON(insert_button), GTK_RELIEF_NONE); + bbox = gtk_hbox_new(FALSE, 3); + gtk_container_add(GTK_CONTAINER(insert_button), bbox); + image = gtk_image_new_from_stock(PIDGIN_STOCK_TOOLBAR_INSERT, gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL)); + gtk_box_pack_start(GTK_BOX(bbox), image, FALSE, FALSE, 0); + label = gtk_label_new_with_mnemonic(_("_Insert")); + gtk_box_pack_start(GTK_BOX(bbox), label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(box), insert_button, FALSE, FALSE, 0); + gtk_widget_show_all(insert_button); + + priv->insert_menu = insert_menu = gtk_menu_new(); + + menuitem = gtk_menu_item_new_with_mnemonic(_("_Image")); + g_signal_connect_swapped(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_button_clicked), priv->image); + gtk_menu_shell_append(GTK_MENU_SHELL(insert_menu), menuitem); + g_signal_connect(G_OBJECT(priv->image), "notify::sensitive", + G_CALLBACK(button_sensitiveness_changed), menuitem); + g_signal_connect(G_OBJECT(priv->image), "notify::visible", + G_CALLBACK(button_visibility_changed), menuitem); + + menuitem = gtk_menu_item_new_with_mnemonic(_("_Link")); + g_signal_connect_swapped(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_button_clicked), priv->link); + gtk_menu_shell_append(GTK_MENU_SHELL(insert_menu), menuitem); + g_signal_connect(G_OBJECT(priv->link), "notify::sensitive", + G_CALLBACK(button_sensitiveness_changed), menuitem); + g_signal_connect(G_OBJECT(priv->link), "notify::visible", + G_CALLBACK(button_visibility_changed), menuitem); + + menuitem = gtk_menu_item_new_with_mnemonic(_("_Horizontal rule")); + g_signal_connect(G_OBJECT(menuitem), "activate" , G_CALLBACK(insert_hr_cb), toolbar); + gtk_menu_shell_append(GTK_MENU_SHELL(insert_menu), menuitem); + priv->insert_hr = menuitem; + + g_signal_connect(G_OBJECT(insert_button), "button-press-event", G_CALLBACK(button_activate_on_click), toolbar); + g_signal_connect(G_OBJECT(insert_button), "activate", G_CALLBACK(pidgin_menu_clicked), insert_menu); + g_signal_connect(G_OBJECT(insert_menu), "deactivate", G_CALLBACK(pidgin_menu_deactivate), insert_button); + priv->sml = NULL; + + /* Sep */ + sep = gtk_vseparator_new(); + gtk_box_pack_start(GTK_BOX(box), sep, FALSE, FALSE, 0); + gtk_widget_show_all(sep); + + /* Smiley */ + smiley_button = gtk_button_new(); + gtk_button_set_relief(GTK_BUTTON(smiley_button), GTK_RELIEF_NONE); + bbox = gtk_hbox_new(FALSE, 3); + gtk_container_add(GTK_CONTAINER(smiley_button), bbox); + image = gtk_image_new_from_stock(PIDGIN_STOCK_TOOLBAR_SMILEY, gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL)); + gtk_box_pack_start(GTK_BOX(bbox), image, FALSE, FALSE, 0); + label = gtk_label_new_with_mnemonic(_("_Smile!")); + gtk_box_pack_start(GTK_BOX(bbox), label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(box), smiley_button, FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(smiley_button), "button-press-event", G_CALLBACK(gtk_webviewtoolbar_popup_menu), toolbar); + g_signal_connect_swapped(G_OBJECT(smiley_button), "clicked", G_CALLBACK(gtk_button_clicked), priv->smiley); + gtk_widget_show_all(smiley_button); + + /* Sep */ + sep = gtk_vseparator_new(); + gtk_box_pack_start(GTK_BOX(box), sep, FALSE, FALSE, 0); + gtk_widget_show_all(sep); + + /* Attention */ + attention_button = gtk_button_new(); + gtk_button_set_relief(GTK_BUTTON(attention_button), GTK_RELIEF_NONE); + bbox = gtk_hbox_new(FALSE, 3); + gtk_container_add(GTK_CONTAINER(attention_button), bbox); + image = gtk_image_new_from_stock(PIDGIN_STOCK_TOOLBAR_SEND_ATTENTION, + gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL)); + gtk_box_pack_start(GTK_BOX(bbox), image, FALSE, FALSE, 0); + label = gtk_label_new_with_mnemonic(_("_Attention!")); + gtk_box_pack_start(GTK_BOX(bbox), label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(box), attention_button, FALSE, FALSE, 0); + g_signal_connect_swapped(G_OBJECT(attention_button), "clicked", + G_CALLBACK(gtk_button_clicked), priv->attention); + gtk_widget_show_all(attention_button); + + g_signal_connect(G_OBJECT(priv->attention), "notify::sensitive", + G_CALLBACK(button_sensitiveness_changed), attention_button); + g_signal_connect(G_OBJECT(priv->attention), "notify::visible", + G_CALLBACK(button_visibility_changed), attention_button); + + /* set attention button to be greyed out until we get a conversation */ + gtk_widget_set_sensitive(priv->attention, FALSE); + + gtk_box_pack_start(GTK_BOX(hbox), box, FALSE, FALSE, 0); + priv->lean_view = box; + gtk_widget_show(box); + + purple_prefs_connect_callback(toolbar, PIDGIN_PREFS_ROOT "/conversations/toolbar/wide", + webviewtoolbar_view_pref_changed, toolbar); + g_signal_connect_data(G_OBJECT(toolbar), "realize", + G_CALLBACK(purple_prefs_trigger_callback), PIDGIN_PREFS_ROOT "/conversations/toolbar/wide", + NULL, G_CONNECT_AFTER | G_CONNECT_SWAPPED); + + gtk_event_box_set_visible_window(GTK_EVENT_BOX(event), FALSE); + + gtk_widget_add_events(event, GDK_BUTTON_PRESS_MASK); + gtk_box_pack_start(GTK_BOX(hbox), event, TRUE, TRUE, 0); + g_signal_connect(G_OBJECT(event), "button-press-event", G_CALLBACK(gtk_webviewtoolbar_popup_menu), toolbar); + gtk_widget_show(event); +} + +/****************************************************************************** + * Public API + *****************************************************************************/ + +GtkWidget * +gtk_webviewtoolbar_new(void) +{ + return GTK_WIDGET(g_object_new(gtk_webviewtoolbar_get_type(), NULL)); +} + +GType +gtk_webviewtoolbar_get_type(void) +{ + static GType webviewtoolbar_type = 0; + + if (!webviewtoolbar_type) { + static const GTypeInfo webviewtoolbar_info = { + sizeof(GtkWebViewToolbarClass), + NULL, + NULL, + (GClassInitFunc)gtk_webviewtoolbar_class_init, + NULL, + NULL, + sizeof(GtkWebViewToolbar), + 0, + (GInstanceInitFunc)gtk_webviewtoolbar_init, + NULL + }; + + webviewtoolbar_type = g_type_register_static(GTK_TYPE_HBOX, + "GtkWebViewToolbar", &webviewtoolbar_info, 0); + } + + return webviewtoolbar_type; +} + +void +gtk_webviewtoolbar_attach(GtkWebViewToolbar *toolbar, GtkWidget *webview) +{ + GtkWebViewButtons buttons; + + g_return_if_fail(toolbar != NULL); + g_return_if_fail(GTK_IS_WEBVIEWTOOLBAR(toolbar)); + g_return_if_fail(webview != NULL); + g_return_if_fail(GTK_IS_WEBVIEW(webview)); + + toolbar->webview = webview; + g_signal_connect(G_OBJECT(webview), "allowed-formats-updated", + G_CALLBACK(update_buttons_cb), toolbar); + g_signal_connect_after(G_OBJECT(webview), "format-toggled", + G_CALLBACK(toggle_button_cb), toolbar); + g_signal_connect_after(G_OBJECT(webview), "format-cleared", + G_CALLBACK(update_format_cb), toolbar); + g_signal_connect(G_OBJECT(webview), "format-updated", + G_CALLBACK(update_format_cb), toolbar); +#if 0 + g_signal_connect_after(G_OBJECT(GTK_WEBVIEW(webview)->text_buffer), "mark-set", G_CALLBACK(mark_set_cb), toolbar); +#endif + + buttons = gtk_webview_get_format_functions(GTK_WEBVIEW(webview)); + update_buttons_cb(GTK_WEBVIEW(webview), buttons, toolbar); + update_buttons(toolbar); +} + +void +gtk_webviewtoolbar_associate_smileys(GtkWebViewToolbar *toolbar, + const char *proto_id) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + g_free(priv->sml); + priv->sml = g_strdup(proto_id); +} + +void +gtk_webviewtoolbar_switch_active_conversation(GtkWebViewToolbar *toolbar, + PurpleConversation *conv) +{ + GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); + PurpleConnection *gc = purple_conversation_get_connection(conv); + PurplePlugin *prpl = purple_connection_get_prpl(gc); + + priv->active_conv = conv; + + /* gray out attention button on protocols that don't support it + for the time being it is always disabled for chats */ + gtk_widget_set_sensitive(priv->attention, + conv && prpl && purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM && + PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->send_attention != NULL); +} + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkwebviewtoolbar.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/gtkwebviewtoolbar.h Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,96 @@ +/* + * GtkWebViewToolbar + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + */ +#ifndef _PIDGINWEBVIEWTOOLBAR_H_ +#define _PIDGINWEBVIEWTOOLBAR_H_ + +#include +#include "gtkwebview.h" + +#define DEFAULT_FONT_FACE "Helvetica 12" + +#define GTK_TYPE_WEBVIEWTOOLBAR (gtk_webviewtoolbar_get_type()) +#define GTK_WEBVIEWTOOLBAR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_WEBVIEWTOOLBAR, GtkWebViewToolbar)) +#define GTK_WEBVIEWTOOLBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_WEBVIEWTOOLBAR, GtkWebViewToolbarClass)) +#define GTK_IS_WEBVIEWTOOLBAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_WEBVIEWTOOLBAR)) +#define GTK_IS_WEBVIEWTOOLBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_WEBVIEWTOOLBAR)) +#define GTK_WEBVIEWTOOLBAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_WEBVIEWTOOLBAR, GtkWebViewToolbarClass)) + +typedef struct _GtkWebViewToolbar GtkWebViewToolbar; +typedef struct _GtkWebViewToolbarClass GtkWebViewToolbarClass; + +struct _GtkWebViewToolbar { + GtkHBox box; + + GtkWidget *webview; +}; + +struct _GtkWebViewToolbarClass { + GtkHBoxClass parent_class; +}; + +G_BEGIN_DECLS + +/** + * Returns the GType for a GtkWebViewToolbar widget + * + * @return The GType for GtkWebViewToolbar widget + */ +GType gtk_webviewtoolbar_get_type(void); + +/** + * Create a new GtkWebViewToolbar object + * + * @return A GtkWidget corresponding to the GtkWebViewToolbar object + */ +GtkWidget *gtk_webviewtoolbar_new(void); + +/** + * Attach a GtkWebViewToolbar object to a GtkWebView + * + * @param toolbar The GtkWebViewToolbar object + * @param webview The GtkWebView object + */ +void gtk_webviewtoolbar_attach(GtkWebViewToolbar *toolbar, GtkWidget *webview); + +/** + * Associate the smileys from a protocol to a GtkWebViewToolbar object + * + * @param toolbar The GtkWebViewToolbar object + * @param proto_id The ID of the protocol from which smileys are associated + */ +void gtk_webviewtoolbar_associate_smileys(GtkWebViewToolbar *toolbar, + const char *proto_id); + +/** + * Switch the active conversation for a GtkWebViewToolbar object + * + * @param toolbar The GtkWebViewToolbar object + * @param conv The new conversation + */ +void gtk_webviewtoolbar_switch_active_conversation(GtkWebViewToolbar *toolbar, + PurpleConversation *conv); + +G_END_DECLS + +#endif /* _PIDGINWEBVIEWTOOLBAR_H_ */ + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkwhiteboard.c --- a/pidgin/gtkwhiteboard.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkwhiteboard.c Fri Apr 06 04:30:00 2012 +0000 @@ -125,7 +125,7 @@ PidginWhiteboard *gtkwb = g_new0(PidginWhiteboard, 1); gtkwb->wb = wb; - wb->ui_data = gtkwb; + purple_whiteboard_set_ui_data(wb, gtkwb); /* Get dimensions (default?) for the whiteboard canvas */ if (!purple_whiteboard_get_dimensions(wb, >kwb->width, >kwb->height)) @@ -145,11 +145,11 @@ /* Try and set window title as the name of the buddy, else just use their * username */ - buddy = purple_find_buddy(wb->account, wb->who); + buddy = purple_find_buddy(purple_whiteboard_get_account(wb), purple_whiteboard_get_who(wb)); - window = pidgin_create_window(buddy != NULL ? purple_buddy_get_contact_alias(buddy) : wb->who, 0, NULL, FALSE); + window = pidgin_create_window(buddy != NULL ? purple_buddy_get_contact_alias(buddy) : purple_whiteboard_get_who(wb), 0, NULL, FALSE); gtkwb->window = window; - gtk_widget_set_name(window, wb->who); + gtk_widget_set_name(window, purple_whiteboard_get_who(wb)); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(whiteboard_close_cb), gtkwb); @@ -274,7 +274,7 @@ GtkWidget *colour_dialog; g_return_if_fail(wb != NULL); - gtkwb = wb->ui_data; + gtkwb = purple_whiteboard_get_ui_data(wb); g_return_if_fail(gtkwb != NULL); /* TODO Ask if user wants to save picture before the session is closed */ @@ -301,7 +301,7 @@ gtkwb->window = NULL; } g_free(gtkwb); - wb->ui_data = NULL; + purple_whiteboard_set_ui_data(wb, NULL); } static gboolean whiteboard_close_cb(GtkWidget *widget, GdkEvent *event, PidginWhiteboard *gtkwb) @@ -406,7 +406,7 @@ GdkPixmap *pixmap = gtkwb->pixmap; PurpleWhiteboard *wb = gtkwb->wb; - GList *draw_list = wb->draw_list; + GList *draw_list = purple_whiteboard_get_draw_list(wb); if(BrushState != BRUSH_STATE_UP) { @@ -441,7 +441,7 @@ gtkwb->brush_color, gtkwb->brush_size); } - wb->draw_list = draw_list; + purple_whiteboard_set_draw_list(wb, draw_list); return TRUE; } @@ -459,7 +459,7 @@ GdkPixmap *pixmap = gtkwb->pixmap; PurpleWhiteboard *wb = gtkwb->wb; - GList *draw_list = wb->draw_list; + GList *draw_list = purple_whiteboard_get_draw_list(wb); if(event->is_hint) gdk_window_get_pointer(event->window, &x, &y, &state); @@ -528,7 +528,7 @@ LastY = y; } - wb->draw_list = draw_list; + purple_whiteboard_set_draw_list(wb, draw_list); return TRUE; } @@ -539,7 +539,7 @@ GdkPixmap *pixmap = gtkwb->pixmap; PurpleWhiteboard *wb = gtkwb->wb; - GList *draw_list = wb->draw_list; + GList *draw_list = purple_whiteboard_get_draw_list(wb); if((BrushState != BRUSH_STATE_DOWN) && (BrushState != BRUSH_STATE_MOTION)) { @@ -583,7 +583,7 @@ if(draw_list) purple_whiteboard_draw_list_destroy(draw_list); - wb->draw_list = NULL; + purple_whiteboard_set_draw_list(wb, NULL); } return TRUE; @@ -591,7 +591,7 @@ static void pidgin_whiteboard_draw_brush_point(PurpleWhiteboard *wb, int x, int y, int color, int size) { - PidginWhiteboard *gtkwb = wb->ui_data; + PidginWhiteboard *gtkwb = purple_whiteboard_get_ui_data(wb); GtkWidget *widget = gtkwb->drawing_area; GdkPixmap *pixmap = gtkwb->pixmap; @@ -684,7 +684,7 @@ static void pidgin_whiteboard_set_dimensions(PurpleWhiteboard *wb, int width, int height) { - PidginWhiteboard *gtkwb = wb->ui_data; + PidginWhiteboard *gtkwb = purple_whiteboard_get_ui_data(wb); gtkwb->width = width; gtkwb->height = height; @@ -692,7 +692,7 @@ static void pidgin_whiteboard_set_brush(PurpleWhiteboard *wb, int size, int color) { - PidginWhiteboard *gtkwb = wb->ui_data; + PidginWhiteboard *gtkwb = purple_whiteboard_get_ui_data(wb); gtkwb->brush_size = size; gtkwb->brush_color = color; @@ -700,7 +700,7 @@ static void pidgin_whiteboard_clear(PurpleWhiteboard *wb) { - PidginWhiteboard *gtkwb = wb->ui_data; + PidginWhiteboard *gtkwb = purple_whiteboard_get_ui_data(wb); GdkPixmap *pixmap = gtkwb->pixmap; GtkWidget *drawing_area = gtkwb->drawing_area; cairo_t *cr = g_object_get_data(G_OBJECT(pixmap), "cairo-context"); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/gtkwhiteboard.h --- a/pidgin/gtkwhiteboard.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/gtkwhiteboard.h Fri Apr 06 04:30:00 2012 +0000 @@ -59,9 +59,7 @@ int brush_size; /**< Brush size */ } PidginWhiteboard; -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ +G_BEGIN_DECLS /*****************************************************************************/ /** @name PidginWhiteboard API */ @@ -77,8 +75,6 @@ /*@}*/ -#ifdef __cplusplus -} -#endif /* __cplusplus */ +G_END_DECLS #endif /* _PIDGINWHITEBOARD_H_ */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/pidgin-2-uninstalled.pc.in --- a/pidgin/pidgin-2-uninstalled.pc.in Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ -datarootdir=@datarootdir@ -datadir=@datadir@ -sysconfdir=@sysconfdir@ - -abs_srcdir=@abs_srcdir@ -abs_builddir=@abs_builddir@ - -abs_top_srcdir=@abs_top_srcdir@ -abs_top_builddir=@abs_top_builddir@ - -plugindir=${libdir}/pidgin - -Name: Pidgin -Description: Pidgin is a GTK2-based instant messenger application. -Version: @VERSION@ -Requires: gtk+-2.0 purple -Cflags: -I${abs_top_srcdir} diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/pidgin-2.pc.in --- a/pidgin/pidgin-2.pc.in Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ -datarootdir=@datarootdir@ -datadir=@datadir@ -sysconfdir=@sysconfdir@ - -plugindir=${libdir}/pidgin - -Name: Pidgin -Description: Pidgin is a GTK2-based instant messenger application. -Version: @VERSION@ -Requires: gtk+-2.0 purple -Cflags: -I${includedir} diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/pidgin-3-uninstalled.pc.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pidgin-3-uninstalled.pc.in Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,21 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ +datarootdir=@datarootdir@ +datadir=@datadir@ +sysconfdir=@sysconfdir@ + +abs_srcdir=@abs_srcdir@ +abs_builddir=@abs_builddir@ + +abs_top_srcdir=@abs_top_srcdir@ +abs_top_builddir=@abs_top_builddir@ + +plugindir=${libdir}/pidgin + +Name: Pidgin +Description: Pidgin is a GTK2-based instant messenger application. +Version: @VERSION@ +Requires: gtk+-2.0 purple-3 +Cflags: -I${abs_top_srcdir} diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/pidgin-3.pc.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/pidgin-3.pc.in Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,15 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/pidgin +datarootdir=@datarootdir@ +datadir=@datadir@ +sysconfdir=@sysconfdir@ + +plugindir=${libdir}/pidgin + +Name: Pidgin +Description: Pidgin is a GTK2-based instant messenger application. +Version: @VERSION@ +Requires: gtk+-2.0 purple-3 +Cflags: -I${includedir} diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/pidgin-uninstalled.pc.in --- a/pidgin/pidgin-uninstalled.pc.in Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ -datarootdir=@datarootdir@ -datadir=@datadir@ -sysconfdir=@sysconfdir@ - -abs_srcdir=@abs_srcdir@ -abs_builddir=@abs_builddir@ - -plugindir=${libdir}/pidgin - -Name: Pidgin -Description: Pidgin is a GTK2-based instant messenger application. -Version: @VERSION@ -Requires: gtk+-2.0 purple -Cflags: -I${abs_srcdir} diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/pidgin.pc.in --- a/pidgin/pidgin.pc.in Mon Apr 02 23:36:20 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ -datarootdir=@datarootdir@ -datadir=@datadir@ -sysconfdir=@sysconfdir@ - -plugindir=${libdir}/pidgin - -Name: Pidgin -Description: Pidgin is a GTK2-based instant messenger application. -Version: @VERSION@ -Requires: gtk+-2.0 purple -Cflags: -I${includedir}/pidgin - diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/pidgintooltip.h --- a/pidgin/pidgintooltip.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/pidgintooltip.h Fri Apr 06 04:30:00 2012 +0000 @@ -36,7 +36,6 @@ * @param h The value of this should be set to the desired height of the tooltip window. * * @return @c TRUE if the tooltip was created correctly, @c FALSE otherwise. - * @since 2.4.0 */ typedef gboolean (*PidginTooltipCreateForTree)(GtkWidget *tipwindow, GtkTreePath *path, gpointer userdata, int *w, int *h); @@ -48,7 +47,6 @@ * @param h The value of this should be set to the desired height of the tooltip window. * * @return @c TRUE if the tooltip was created correctly, @c FALSE otherwise. - * @since 2.4.0 */ typedef gboolean (*PidginTooltipCreate)(GtkWidget *tipwindow, gpointer userdata, int *w, int *h); @@ -58,10 +56,11 @@ * @param userdata The userdata set during pidgin_tooltip_setup_for_treeview or pidgin_tooltip_show. * * @return @c TRUE if the tooltip was painted correctly, @c FALSE otherwise. - * @since 2.4.0 */ typedef gboolean (*PidginTooltipPaint)(GtkWidget *tipwindow, gpointer userdata); +G_BEGIN_DECLS + /** * Setup tooltip drawing functions for a treeview. * @@ -71,7 +70,6 @@ * @param paint_cb Callback function to paint the tooltip * * @return @c TRUE if the tooltip callbacks were setup correctly. - * @since 2.4.0 */ gboolean pidgin_tooltip_setup_for_treeview(GtkWidget *tree, gpointer userdata, PidginTooltipCreateForTree create_cb, PidginTooltipPaint paint_cb); @@ -85,14 +83,12 @@ * @param paint_cb Callback function to paint the tooltip * * @return @c TRUE if the tooltip callbacks were setup correctly. - * @since 2.4.0 */ gboolean pidgin_tooltip_setup_for_widget(GtkWidget *widget, gpointer userdata, PidginTooltipCreate create_cb, PidginTooltipPaint paint_cb); /** * Destroy the tooltip. - * @since 2.4.0 */ void pidgin_tooltip_destroy(void); @@ -103,10 +99,10 @@ * @param userdata The userdata to send to the callback functions * @param create_cb Callback function to create the tooltip from the GtkTreePath * @param paint_cb Callback function to paint the tooltip - * - * @since 2.4.0 */ void pidgin_tooltip_show(GtkWidget *widget, gpointer userdata, PidginTooltipCreate create_cb, PidginTooltipPaint paint_cb); +G_END_DECLS + #endif diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/plugins/Makefile.am --- a/pidgin/plugins/Makefile.am Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/plugins/Makefile.am Fri Apr 06 04:30:00 2012 +0000 @@ -45,9 +45,8 @@ sendbutton_la_LDFLAGS = -module -avoid-version spellchk_la_LDFLAGS = -module -avoid-version themeedit_la_LDFLAGS = -module -avoid-version -timestamp_la_LDFLAGS = -module -avoid-version -timestamp_format_la_LDFLAGS = -module -avoid-version vvconfig_la_LDFLAGS = -module -avoid-version +webkit_la_LDFLAGS = -module -avoid-version xmppconsole_la_LDFLAGS = -module -avoid-version if PLUGINS @@ -64,9 +63,8 @@ relnot.la \ sendbutton.la \ spellchk.la \ - themeedit.la \ - timestamp.la \ - timestamp_format.la \ + themeedit.la \ + webkit.la \ xmppconsole.la if USE_VV @@ -91,9 +89,7 @@ sendbutton_la_SOURCES = sendbutton.c spellchk_la_SOURCES = spellchk.c themeedit_la_SOURCES = themeedit.c themeedit-icon.c themeedit-icon.h -timestamp_la_SOURCES = timestamp.c -timestamp_format_la_SOURCES = timestamp_format.c -vvconfig_la_SOURCES = vvconfig.c +webkit_la_SOURCES = webkit.c xmppconsole_la_SOURCES = xmppconsole.c convcolors_la_LIBADD = $(GTK_LIBS) @@ -103,16 +99,14 @@ gtkbuddynote_la_LIBADD = $(GTK_LIBS) history_la_LIBADD = $(GTK_LIBS) iconaway_la_LIBADD = $(GTK_LIBS) -markerline_la_LIBADD = $(GTK_LIBS) +markerline_la_LIBADD = $(GTK_LIBS) $(WEBKIT_LIBS) notify_la_LIBADD = $(GTK_LIBS) pidginrc_la_LIBADD = $(GTK_LIBS) relnot_la_LIBADD = $(GLIB_LIBS) sendbutton_la_LIBADD = $(GTK_LIBS) spellchk_la_LIBADD = $(GTK_LIBS) themeedit_la_LIBADD = $(GTK_LIBS) -timestamp_la_LIBADD = $(GTK_LIBS) -timestamp_format_la_LIBADD = $(GTK_LIBS) -vvconfig_la_LIBADD = $(GTK_LIBS) $(GSTREAMER_LIBS) +webkit_la_LIBADD = $(GTK_LIBS) $(WEBKIT_LIBS) xmppconsole_la_LIBADD = $(GTK_LIBS) endif # PLUGINS @@ -136,6 +130,7 @@ -I$(top_srcdir)/pidgin \ $(DEBUG_CFLAGS) \ $(GTK_CFLAGS) \ + $(WEBKIT_CFLAGS) \ $(GSTREAMER_CFLAGS) \ $(PLUGIN_CFLAGS) diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/plugins/contact_priority.c --- a/pidgin/plugins/contact_priority.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/plugins/contact_priority.c Fri Apr 06 04:30:00 2012 +0000 @@ -35,11 +35,11 @@ } static void -account_update(GtkWidget *widget, GtkOptionMenu *optmenu) +account_update(GtkWidget *widget, GtkWidget *optmenu) { PurpleAccount *account = NULL; - account = g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(optmenu)))), "account"); + account = pidgin_account_option_menu_get_selected(optmenu); purple_account_set_int(account, "score", gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget))); } @@ -147,8 +147,7 @@ gtk_box_pack_start(GTK_BOX(hbox), optmenu, FALSE, FALSE, 0); /* this is where we set up the spin button we made above */ - account = g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu))))), - "account"); + account = pidgin_account_option_menu_get_selected(optmenu); gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), (gdouble)purple_account_get_int(account, "score", 0)); gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(spin), GTK_ADJUSTMENT(adj)); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/plugins/gestures/gestures.c --- a/pidgin/plugins/gestures/gestures.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/plugins/gestures/gestures.c Fri Apr 06 04:30:00 2012 +0000 @@ -48,7 +48,7 @@ gtkconv = PIDGIN_CONVERSATION(conv); - gstroke_cleanup(gtkconv->imhtml); + gstroke_cleanup(gtkconv->webview); purple_conversation_destroy(conv); } @@ -126,15 +126,15 @@ gtkconv = PIDGIN_CONVERSATION(conv); - gstroke_enable(gtkconv->imhtml); - gstroke_signal_connect(gtkconv->imhtml, "14789", stroke_close, conv); - gstroke_signal_connect(gtkconv->imhtml, "1456", stroke_close, conv); - gstroke_signal_connect(gtkconv->imhtml, "1489", stroke_close, conv); - gstroke_signal_connect(gtkconv->imhtml, "74123", stroke_next_tab, conv); - gstroke_signal_connect(gtkconv->imhtml, "7456", stroke_next_tab, conv); - gstroke_signal_connect(gtkconv->imhtml, "96321", stroke_prev_tab, conv); - gstroke_signal_connect(gtkconv->imhtml, "9654", stroke_prev_tab, conv); - gstroke_signal_connect(gtkconv->imhtml, "25852", stroke_new_win, conv); + gstroke_enable(gtkconv->webview); + gstroke_signal_connect(gtkconv->webview, "14789", stroke_close, conv); + gstroke_signal_connect(gtkconv->webview, "1456", stroke_close, conv); + gstroke_signal_connect(gtkconv->webview, "1489", stroke_close, conv); + gstroke_signal_connect(gtkconv->webview, "74123", stroke_next_tab, conv); + gstroke_signal_connect(gtkconv->webview, "7456", stroke_next_tab, conv); + gstroke_signal_connect(gtkconv->webview, "96321", stroke_prev_tab, conv); + gstroke_signal_connect(gtkconv->webview, "9654", stroke_prev_tab, conv); + gstroke_signal_connect(gtkconv->webview, "25852", stroke_new_win, conv); } static void @@ -145,7 +145,6 @@ } #if 0 -#if GTK_CHECK_VERSION(2,4,0) static void mouse_button_menu_cb(GtkComboBox *opt, gpointer data) { @@ -153,15 +152,6 @@ gstroke_set_mouse_button(button + 2); } -#else -static void -mouse_button_menu_cb(GtkMenuItem *item, gpointer data) -{ - int button = (int)data; - - gstroke_set_mouse_button(button + 2); -} -#endif #endif static void @@ -215,8 +205,8 @@ gtkconv = PIDGIN_CONVERSATION(conv); - gstroke_cleanup(gtkconv->imhtml); - gstroke_disable(gtkconv->imhtml); + gstroke_cleanup(gtkconv->webview); + gstroke_disable(gtkconv->webview); } return TRUE; @@ -230,9 +220,6 @@ GtkWidget *toggle; #if 0 GtkWidget *opt; -#if GTK_CHECK_VERSION(2,4,0) - GtkWidget *menu, *item; -#endif #endif /* Outside container */ @@ -243,7 +230,6 @@ vbox = pidgin_make_frame(ret, _("Mouse Gestures Configuration")); #if 0 -#if GTK_CHECK_VERSION(2,4,0) /* Mouse button drop-down menu */ opt = gtk_combo_box_new_text(); @@ -255,26 +241,6 @@ gtk_box_pack_start(GTK_BOX(vbox), opt, FALSE, FALSE, 0); gtk_combo_box_set_active(GTK_COMBO_BOX(opt), gstroke_get_mouse_button() - 2); -#else - /* Mouse button drop-down menu */ - menu = gtk_menu_new(); - opt = gtk_option_menu_new(); - - item = gtk_menu_item_new_with_label(_("Middle mouse button")); - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK(mouse_button_menu_cb), opt); - gtk_menu_append(menu, item); - - item = gtk_menu_item_new_with_label(_("Right mouse button")); - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK(mouse_button_menu_cb), opt); - gtk_menu_append(menu, item); - - gtk_box_pack_start(GTK_BOX(vbox), opt, FALSE, FALSE, 0); - gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); - gtk_option_menu_set_history(GTK_OPTION_MENU(opt), - gstroke_get_mouse_button() - 2); -#endif #endif /* "Visual gesture display" checkbox */ diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/plugins/gevolution/gevo-util.c --- a/pidgin/plugins/gevolution/gevo-util.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/plugins/gevolution/gevo-util.c Fri Apr 06 04:30:00 2012 +0000 @@ -49,7 +49,7 @@ purple_blist_add_buddy(buddy, NULL, group, NULL); } - purple_account_add_buddy(account, buddy); + purple_account_add_buddy(account, buddy, NULL); if (conv != NULL) { diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/plugins/history.c --- a/pidgin/plugins/history.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/plugins/history.c Fri Apr 06 04:30:00 2012 +0000 @@ -16,16 +16,17 @@ #include "gtkconv.h" #include "gtkimhtml.h" #include "gtkplugin.h" +#include "gtkwebview.h" #define HISTORY_PLUGIN_ID "gtk-history" #define HISTORY_SIZE (4 * 1024) -static gboolean _scroll_imhtml_to_end(gpointer data) +static gboolean _scroll_webview_to_end(gpointer data) { - GtkIMHtml *imhtml = data; - gtk_imhtml_scroll_to_end(GTK_IMHTML(imhtml), FALSE); - g_object_unref(G_OBJECT(imhtml)); + GtkWebView *webview = data; + gtk_webview_scroll_to_end(GTK_WEBVIEW(webview), FALSE); + g_object_unref(G_OBJECT(webview)); return FALSE; } @@ -39,9 +40,15 @@ guint flags; char *history; PidginConversation *gtkconv; +#if 0 + /* FIXME: WebView has no options */ GtkIMHtmlOptions options = GTK_IMHTML_NO_COLOURS; +#endif char *header; +#if 0 + /* FIXME: WebView has no protocol setting */ char *protocol; +#endif char *escaped_alias; const char *header_date; @@ -116,15 +123,21 @@ history = purple_log_read((PurpleLog*)logs->data, &flags); gtkconv = PIDGIN_CONVERSATION(c); +#if 0 + /* FIXME: WebView has no options */ if (flags & PURPLE_LOG_READ_NO_NEWLINE) options |= GTK_IMHTML_NO_NEWLINE; +#endif +#if 0 + /* FIXME: WebView has no protocol setting */ protocol = g_strdup(gtk_imhtml_get_protocol_name(GTK_IMHTML(gtkconv->imhtml))); gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), purple_account_get_protocol_name(((PurpleLog*)logs->data)->account)); +#endif - if (gtk_text_buffer_get_char_count(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)))) - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "
    ", options); + if (!gtk_webview_is_empty(GTK_WEBVIEW(gtkconv->webview))) + gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), "
    "); escaped_alias = g_markup_escape_text(alias, -1); @@ -134,21 +147,24 @@ header_date = purple_date_format_full(localtime(&((PurpleLog *)logs->data)->time)); header = g_strdup_printf(_("Conversation with %s on %s:
    "), escaped_alias, header_date); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), header, options); + gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), header); g_free(header); g_free(escaped_alias); g_strchomp(history); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), history, options); + gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), history); g_free(history); - gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "
    ", options); + gtk_webview_append_html(GTK_WEBVIEW(gtkconv->webview), "
    "); +#if 0 + /* FIXME: WebView has no protocol setting */ gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->imhtml), protocol); g_free(protocol); +#endif - g_object_ref(G_OBJECT(gtkconv->imhtml)); - g_idle_add(_scroll_imhtml_to_end, gtkconv->imhtml); + g_object_ref(G_OBJECT(gtkconv->webview)); + g_idle_add(_scroll_webview_to_end, gtkconv->webview); g_list_foreach(logs, (GFunc)purple_log_free, NULL); g_list_free(logs); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/plugins/markerline.c --- a/pidgin/plugins/markerline.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/plugins/markerline.c Fri Apr 06 04:30:00 2012 +0000 @@ -33,81 +33,38 @@ /* Purple headers */ #include -#include #include +#include #include #define PREF_PREFIX "/plugins/gtk/" PLUGIN_ID #define PREF_IMS PREF_PREFIX "/ims" #define PREF_CHATS PREF_PREFIX "/chats" -static int -imhtml_expose_cb(GtkWidget *widget, GdkEventExpose *event, PidginConversation *gtkconv) -{ - int y, last_y, offset; - GdkRectangle visible_rect; - GtkTextIter iter; - GdkRectangle buf; - int pad; - PurpleConversation *conv = gtkconv->active_conv; - PurpleConversationType type = purple_conversation_get_type(conv); - - if ((type == PURPLE_CONV_TYPE_CHAT && !purple_prefs_get_bool(PREF_CHATS)) || - (type == PURPLE_CONV_TYPE_IM && !purple_prefs_get_bool(PREF_IMS))) - return FALSE; - - gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(widget), &visible_rect); - - offset = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "markerline")); - if (offset) - { - gtk_text_buffer_get_iter_at_offset(gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget)), - &iter, offset); - - gtk_text_view_get_iter_location(GTK_TEXT_VIEW(widget), &iter, &buf); - last_y = buf.y + buf.height; - pad = (gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(widget)) + - gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(widget))) / 2; - last_y += pad; - } - else - last_y = 0; - - gtk_text_view_buffer_to_window_coords(GTK_TEXT_VIEW(widget), GTK_TEXT_WINDOW_TEXT, - 0, last_y, 0, &y); - - if (y >= event->area.y) - { - GdkColor red = {0, 0xffff, 0, 0}; - cairo_t *cr = gdk_cairo_create(GDK_DRAWABLE(event->window)); - - gdk_cairo_set_source_color(cr, &red); - cairo_move_to(cr, 0.0, y + 0.5); - cairo_rel_line_to(cr, visible_rect.width, 0.0); - cairo_set_line_width(cr, 1.0); - cairo_stroke(cr); - cairo_destroy(cr); - } - return FALSE; -} - static void update_marker_for_gtkconv(PidginConversation *gtkconv) { - GtkTextIter iter; - GtkTextBuffer *buffer; + PurpleConversation *conv; + PurpleConversationType type; + g_return_if_fail(gtkconv != NULL); - buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml)); + conv = gtkconv->active_conv; + type = purple_conversation_get_type(conv); - if (!gtk_text_buffer_get_char_count(buffer)) + if ((type == PURPLE_CONV_TYPE_CHAT && !purple_prefs_get_bool(PREF_CHATS)) || + (type == PURPLE_CONV_TYPE_IM && !purple_prefs_get_bool(PREF_IMS))) return; - gtk_text_buffer_get_end_iter(buffer, &iter); - - g_object_set_data(G_OBJECT(gtkconv->imhtml), "markerline", - GINT_TO_POINTER(gtk_text_iter_get_offset(&iter))); - gtk_widget_queue_draw(gtkconv->imhtml); + gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), + "var mhr = document.getElementById(\"markerhr\");" + "if (!mhr) {" + "mhr = document.createElement(\"hr\");" + "mhr.setAttribute(\"id\", \"markerhr\");" + "mhr.setAttribute(\"color\", \"#ff0000\");" + "mhr.setAttribute(\"size\", \"1\");" + "}" + "document.getElementById(\"Chat\").appendChild(mhr);"); } static gboolean @@ -125,28 +82,6 @@ return FALSE; } -#if 0 -static gboolean -window_resized(GtkWidget *w, GdkEventConfigure *event, PidginWindow *win) -{ - GList *list; - - list = pidgin_conv_window_get_gtkconvs(win); - - for (; list; list = list->next) - update_marker_for_gtkconv(list->data); - - return FALSE; -} - -static gboolean -imhtml_resize_cb(GtkWidget *w, GtkAllocation *allocation, PidginConversation *gtkconv) -{ - gtk_widget_queue_draw(w); - return FALSE; -} -#endif - static void page_switched(GtkWidget *widget, GtkWidget *page, gint num, PidginWindow *win) { @@ -156,7 +91,9 @@ static void detach_from_gtkconv(PidginConversation *gtkconv, gpointer null) { - g_signal_handlers_disconnect_by_func(G_OBJECT(gtkconv->imhtml), imhtml_expose_cb, gtkconv); + gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), + "var mhr = document.getElementById(\"markerhr\");" + "if (mhr) mhr.parentNode.removeChild(mhr);"); } static void @@ -165,16 +102,13 @@ g_list_foreach(pidgin_conv_window_get_gtkconvs(win), (GFunc)detach_from_gtkconv, NULL); g_signal_handlers_disconnect_by_func(G_OBJECT(win->notebook), page_switched, win); g_signal_handlers_disconnect_by_func(G_OBJECT(win->window), focus_removed, win); - - gtk_widget_queue_draw(win->window); } static void attach_to_gtkconv(PidginConversation *gtkconv, gpointer null) { detach_from_gtkconv(gtkconv, NULL); - g_signal_connect(G_OBJECT(gtkconv->imhtml), "expose_event", - G_CALLBACK(imhtml_expose_cb), gtkconv); + update_marker_for_gtkconv(gtkconv); } static void @@ -187,8 +121,6 @@ g_signal_connect(G_OBJECT(win->notebook), "switch_page", G_CALLBACK(page_switched), win); - - gtk_widget_queue_draw(win->window); } static void @@ -220,15 +152,15 @@ jump_to_markerline(PurpleConversation *conv, gpointer null) { PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); - int offset; - GtkTextIter iter; if (!gtkconv) return; - offset = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtkconv->imhtml), "markerline")); - gtk_text_buffer_get_iter_at_offset(GTK_IMHTML(gtkconv->imhtml)->text_buffer, &iter, offset); - gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(gtkconv->imhtml), &iter, 0, TRUE, 0, 0); + gtk_webview_safe_execute_script(GTK_WEBVIEW(gtkconv->webview), + "var mhr = document.getElementById(\"markerhr\");" + "if (mhr) {" + "window.scroll(0, mhr.offsetTop);" + "}"); } static void diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/plugins/musicmessaging/musicmessaging.c --- a/pidgin/plugins/musicmessaging/musicmessaging.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/plugins/musicmessaging/musicmessaging.c Fri Apr 06 04:30:00 2012 +0000 @@ -104,7 +104,7 @@ { if (mmconv->originator) { - char *name = (mmconv->conv)->name; + const char *name = purple_conversation_get_name(mmconv->conv); send_change_request (session, name, command, parameters); } else { @@ -376,7 +376,7 @@ if (mmconv->originator) { int session = mmconv_from_conv_loc(conv); - char *id = (mmconv->conv)->name; + const char *id = purple_conversation_get_name(mmconv->conv); char *command; char *parameters; @@ -424,7 +424,8 @@ command = strtok(NULL, " "); /* char *parameters = strtok(NULL, "#"); DONT NEED PARAMETERS */ - if ((mmconv->conv)->name == id) + // TODO: Shouldn't this be strcmp() ? + if (purple_conversation_get_name(mmconv->conv) == id) { purple_notify_message(plugin_pointer, PURPLE_NOTIFY_MSG_ERROR, _("Music Messaging"), @@ -465,14 +466,14 @@ static void send_request(MMConversation *mmconv) { - PurpleConnection *connection = purple_conversation_get_gc(mmconv->conv); + PurpleConnection *connection = purple_conversation_get_connection(mmconv->conv); const char *convName = purple_conversation_get_name(mmconv->conv); serv_send_im(connection, convName, MUSICMESSAGING_START_MSG, PURPLE_MESSAGE_SEND); } static void send_request_confirmed(MMConversation *mmconv) { - PurpleConnection *connection = purple_conversation_get_gc(mmconv->conv); + PurpleConnection *connection = purple_conversation_get_connection(mmconv->conv); const char *convName = purple_conversation_get_name(mmconv->conv); serv_send_im(connection, convName, MUSICMESSAGING_CONFIRM_MSG, PURPLE_MESSAGE_SEND); } diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/plugins/notify.c --- a/pidgin/plugins/notify.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/plugins/notify.c Fri Apr 06 04:30:00 2012 +0000 @@ -303,7 +303,7 @@ attach_signals(PurpleConversation *conv) { PidginConversation *gtkconv = NULL; - GSList *imhtml_ids = NULL, *entry_ids = NULL; + GSList *webview_ids = NULL, *entry_ids = NULL; guint id; gtkconv = PIDGIN_CONVERSATION(conv); @@ -322,9 +322,9 @@ G_CALLBACK(unnotify_cb), conv); entry_ids = g_slist_append(entry_ids, GUINT_TO_POINTER(id)); - id = g_signal_connect(G_OBJECT(gtkconv->imhtml), "focus-in-event", + id = g_signal_connect(G_OBJECT(gtkconv->webview), "focus-in-event", G_CALLBACK(unnotify_cb), conv); - imhtml_ids = g_slist_append(imhtml_ids, GUINT_TO_POINTER(id)); + webview_ids = g_slist_append(webview_ids, GUINT_TO_POINTER(id)); } if (purple_prefs_get_bool("/plugins/gtk/X11/notify/notify_click")) { @@ -334,9 +334,9 @@ G_CALLBACK(unnotify_cb), conv); entry_ids = g_slist_append(entry_ids, GUINT_TO_POINTER(id)); - id = g_signal_connect(G_OBJECT(gtkconv->imhtml), "button-press-event", + id = g_signal_connect(G_OBJECT(gtkconv->webview), "button-press-event", G_CALLBACK(unnotify_cb), conv); - imhtml_ids = g_slist_append(imhtml_ids, GUINT_TO_POINTER(id)); + webview_ids = g_slist_append(webview_ids, GUINT_TO_POINTER(id)); } if (purple_prefs_get_bool("/plugins/gtk/X11/notify/notify_type")) { @@ -345,7 +345,7 @@ entry_ids = g_slist_append(entry_ids, GUINT_TO_POINTER(id)); } - purple_conversation_set_data(conv, "notify-imhtml-signals", imhtml_ids); + purple_conversation_set_data(conv, "notify-webview-signals", webview_ids); purple_conversation_set_data(conv, "notify-entry-signals", entry_ids); return 0; @@ -361,9 +361,9 @@ if (!gtkconv) return; - ids = purple_conversation_get_data(conv, "notify-imhtml-signals"); + ids = purple_conversation_get_data(conv, "notify-webview-signals"); for (l = ids; l != NULL; l = l->next) - g_signal_handler_disconnect(gtkconv->imhtml, GPOINTER_TO_INT(l->data)); + g_signal_handler_disconnect(gtkconv->webview, GPOINTER_TO_INT(l->data)); g_slist_free(ids); ids = purple_conversation_get_data(conv, "notify-entry-signals"); @@ -373,7 +373,7 @@ purple_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(0)); - purple_conversation_set_data(conv, "notify-imhtml-signals", NULL); + purple_conversation_set_data(conv, "notify-webview-signals", NULL); purple_conversation_set_data(conv, "notify-entry-signals", NULL); } diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/plugins/perl/common/GtkBlist.xs --- a/pidgin/plugins/perl/common/GtkBlist.xs Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/plugins/perl/common/GtkBlist.xs Fri Apr 06 04:30:00 2012 +0000 @@ -69,8 +69,3 @@ void pidgin_blist_joinchat_show() - -void -pidgin_blist_update_account_error_state(account, message) - Purple::Account account - const char * message diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/plugins/perl/common/GtkDialogs.xs --- a/pidgin/plugins/perl/common/GtkDialogs.xs Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/plugins/perl/common/GtkDialogs.xs Fri Apr 06 04:30:00 2012 +0000 @@ -24,10 +24,6 @@ pidgin_dialogs_log() void -pidgin_dialogs_alias_contact(contact) - Purple::BuddyList::Contact contact - -void pidgin_dialogs_alias_buddy(buddy) Purple::BuddyList::Buddy buddy diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/plugins/perl/common/GtkIMHtml.xs --- a/pidgin/plugins/perl/common/GtkIMHtml.xs Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/plugins/perl/common/GtkIMHtml.xs Fri Apr 06 04:30:00 2012 +0000 @@ -77,26 +77,6 @@ Gtk::TextIter end */ -/* This can't work at the moment since I don't have a typemap for Gdk::Pixbuf. - * I thought about using the one from libgtk2-perl but wasn't sure how to go - * about doing that. -Pidgin::IMHtml::Scalable -gtk_imhtml_image_new(img, filename, id) - Gdk::Pixbuf img - const gchar * filename - int id -*/ - -/* This can't work at the moment since I don't have a typemap for Gtk::Widget. - * I thought about using the one from libgtk2-perl but wasn't sure how to go - * about doing that. -void -gtk_imhtml_image_add_to(scale, imhtml, iter) - Pidgin::IMHtml::Scalable scale - Pidgin::IMHtml imhtml - Gtk::TextIter iter -*/ - /* This can't work at the moment since I don't have a typemap for Gtk::Widget. * I thought about using the one from libgtk2-perl but wasn't sure how to go * about doing that. @@ -323,19 +303,6 @@ } XPUSHs(sv_2mortal(newRV_noinc((SV *)lines))); -MODULE = Pidgin::IMHtml PACKAGE = Pidgin::IMHtml::Scalable PREFIX = gtk_imhtml_image_ -PROTOTYPES: ENABLE - -void -gtk_imhtml_image_free(scale) - Pidgin::IMHtml::Scalable scale - -void -gtk_imhtml_image_scale(scale, width, height) - Pidgin::IMHtml::Scalable scale - int width - int height - MODULE = Pidgin::IMHtml PACKAGE = Pidgin::IMHtml::Hr PREFIX = gtk_imhtml_hr_ PROTOTYPES: ENABLE diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/plugins/relnot.c --- a/pidgin/plugins/relnot.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/plugins/relnot.c Fri Apr 06 04:30:00 2012 +0000 @@ -152,7 +152,7 @@ url, host); - purple_util_fetch_url_request_len(url, TRUE, NULL, FALSE, + purple_util_fetch_url_request(NULL, url, TRUE, NULL, FALSE, request, TRUE, -1, version_fetch_cb, NULL); g_free(request); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/plugins/themeedit.c --- a/pidgin/plugins/themeedit.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/plugins/themeedit.c Fri Apr 06 04:30:00 2012 +0000 @@ -306,7 +306,9 @@ } } +#if !GTK_CHECK_VERSION(2,22,0) gtk_dialog_set_has_separator(GTK_DIALOG(dialog), TRUE); +#endif #ifdef NOT_SADRUL pidgin_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_SAVE, G_CALLBACK(save_blist_theme), dialog); #endif diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/plugins/ticker/gtkticker.c --- a/pidgin/plugins/ticker/gtkticker.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/plugins/ticker/gtkticker.c Fri Apr 06 04:30:00 2012 +0000 @@ -21,28 +21,24 @@ * GtkTicker Copyright 2000 Syd Logan */ -/* FIXME: GTK+ deprecated GTK_WIDGET_MAPPED/REALIZED, but don't provide - accessor functions yet. */ -#undef GSEAL_ENABLE - #include "gtkticker.h" #include -/* These don't seem to be in a release yet. See BZ #69872 */ -#define gtk_widget_is_mapped(x) GTK_WIDGET_MAPPED(x) -#define gtk_widget_is_realized(x) GTK_WIDGET_REALIZED(x) +#if !GTK_CHECK_VERSION(2,20,0) +#define gtk_widget_get_mapped(x) GTK_WIDGET_MAPPED(x) +#define gtk_widget_set_mapped(x,y) do {\ + if (y) \ + GTK_WIDGET_SET_FLAGS(x, GTK_MAPPED); \ + else \ + GTK_WIDGET_UNSET_FLAGS(x, GTK_MAPPED); \ +} while(0) +#define gtk_widget_get_realized(x) GTK_WIDGET_REALIZED(x) #define gtk_widget_set_realized(x,y) do {\ if (y) \ GTK_WIDGET_SET_FLAGS(x, GTK_REALIZED); \ else \ GTK_WIDGET_UNSET_FLAGS(x, GTK_REALIZED); \ } while(0) -#define gtk_widget_set_mapped(x,y) do {\ - if (y) \ - GTK_WIDGET_SET_FLAGS(x, GTK_MAPPED); \ - else \ - GTK_WIDGET_UNSET_FLAGS(x, GTK_MAPPED); \ -} while(0) #if !GTK_CHECK_VERSION(2,18,0) #define gtk_widget_get_visible(x) GTK_WIDGET_VISIBLE(x) @@ -51,6 +47,7 @@ #define gtk_widget_get_window(x) x->window #endif #endif +#endif static void gtk_ticker_compute_offsets (GtkTicker *ticker); static void gtk_ticker_class_init (GtkTickerClass *klass); @@ -181,13 +178,13 @@ ticker->children = g_list_append (ticker->children, child_info); - if (gtk_widget_is_realized (ticker)) + if (gtk_widget_get_realized (GTK_WIDGET (ticker))) gtk_widget_realize (widget); if (gtk_widget_get_visible (GTK_WIDGET (ticker)) && gtk_widget_get_visible (widget)) { - if (gtk_widget_is_mapped (GTK_WIDGET (ticker))) + if (gtk_widget_get_mapped (GTK_WIDGET (ticker))) gtk_widget_map (widget); gtk_widget_queue_resize (GTK_WIDGET (ticker)); @@ -298,7 +295,7 @@ children = children->next; if (gtk_widget_get_visible (child->widget) && - !gtk_widget_is_mapped (child->widget)) + !gtk_widget_get_mapped (child->widget)) gtk_widget_map (child->widget); } @@ -474,7 +471,7 @@ #else widget->allocation = *allocation; #endif - if (gtk_widget_is_realized (widget)) + if (gtk_widget_get_realized (widget)) gdk_window_move_resize (gtk_widget_get_window (widget), allocation->x, allocation->y, diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/plugins/vvconfig.c --- a/pidgin/plugins/vvconfig.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/plugins/vvconfig.c Fri Apr 06 04:30:00 2012 +0000 @@ -39,6 +39,7 @@ /* "esdmon", "ESD", ? */ "osssrc", "OSS", "pulsesrc", "PulseAudio", + "libsndiosrc", "sndio", /* "audiotestsrc wave=silence", "Silence", */ "audiotestsrc", "Test Sound", NULL @@ -50,6 +51,7 @@ "esdsink", "ESD", "osssink", "OSS", "pulsesink", "PulseAudio", + "libsndiosink", "sndio", NULL }; @@ -610,7 +612,7 @@ GstElement *valve; percent = gst_msg_db_to_percent(msg, "rms"); - gtk_progress_bar_set_fraction(ctx->level, percent * 5); + gtk_progress_bar_set_fraction(ctx->level, percent); percent = gst_msg_db_to_percent(msg, "decay"); threshold = gtk_range_get_value(ctx->threshold) / 100.0; @@ -627,7 +629,7 @@ } static void -voice_test_frame_destroy_cb(GtkObject *w, GstElement *pipeline) +voice_test_frame_destroy_cb(GtkWidget *w, GstElement *pipeline) { g_return_if_fail(GST_IS_ELEMENT(pipeline)); @@ -702,7 +704,7 @@ gtk_range_set_value(GTK_RANGE(volume), purple_prefs_get_int("/purple/media/audio/volume/input")); - gtk_widget_set(volume, "draw-value", FALSE, NULL); + gtk_scale_set_draw_value(GTK_SCALE(volume), FALSE); gtk_range_set_value(GTK_RANGE(threshold), purple_prefs_get_int("/purple/media/audio/silence_threshold")); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/plugins/webkit.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/plugins/webkit.c Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,197 @@ +/* + * WebKit - Open the inspector on any WebKit views. + * Copyright (C) 2011 Elliott Sales de Andrade + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA. + */ + +#include "internal.h" + +#include "version.h" + +#include "pidgin.h" + +#include "gtkconv.h" +#include "gtkplugin.h" +#include "gtkwebview.h" + +static WebKitWebView * +create_gtk_window_around_it(WebKitWebInspector *inspector, + WebKitWebView *webview, + PidginConversation *gtkconv) +{ + GtkWidget *win; + GtkWidget *view; + char *title; + + win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + title = g_strdup_printf(_("%s - Inspector"), + gtk_label_get_text(GTK_LABEL(gtkconv->tab_label))); + gtk_window_set_title(GTK_WINDOW(win), title); + g_free(title); + gtk_window_set_default_size(GTK_WINDOW(win), 600, 400); + g_signal_connect_swapped(G_OBJECT(gtkconv->tab_cont), "destroy", G_CALLBACK(gtk_widget_destroy), win); + + view = webkit_web_view_new(); + gtk_container_add(GTK_CONTAINER(win), view); + g_object_set_data(G_OBJECT(webview), "inspector-window", win); + + return WEBKIT_WEB_VIEW(view); +} + +static gboolean +show_inspector_window(WebKitWebInspector *inspector, + GtkWidget *webview) +{ + GtkWidget *win; + + win = g_object_get_data(G_OBJECT(webview), "inspector-window"); + + gtk_widget_show_all(win); + + return TRUE; +} + +static void +setup_inspector(PidginConversation *gtkconv) +{ + GtkWidget *webview = gtkconv->webview; + WebKitWebSettings *settings; + WebKitWebInspector *inspector; + + settings = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webview)); + inspector = webkit_web_view_get_inspector(WEBKIT_WEB_VIEW(webview)); + + g_object_set(G_OBJECT(settings), "enable-developer-extras", TRUE, NULL); + + g_signal_connect(G_OBJECT(inspector), "inspect-web-view", + G_CALLBACK(create_gtk_window_around_it), gtkconv); + g_signal_connect(G_OBJECT(inspector), "show-window", + G_CALLBACK(show_inspector_window), webview); +} + +static void +remove_inspector(PidginConversation *gtkconv) +{ + GtkWidget *webview = gtkconv->webview; + GtkWidget *win; + WebKitWebSettings *settings; + + win = g_object_get_data(G_OBJECT(webview), "inspector-window"); + gtk_widget_destroy(win); + g_object_set_data(G_OBJECT(webview), "inspector-window", NULL); + + settings = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webview)); + + g_object_set(G_OBJECT(settings), "enable-developer-extras", FALSE, NULL); +} + +static void +conversation_displayed_cb(PidginConversation *gtkconv) +{ + GtkWidget *inspect = NULL; + + inspect = g_object_get_data(G_OBJECT(gtkconv->webview), + "inspector-window"); + if (inspect == NULL) { + setup_inspector(gtkconv); + } +} + +static gboolean +plugin_load(PurplePlugin *plugin) +{ + GList *convs = purple_get_conversations(); + void *gtk_conv_handle = pidgin_conversations_get_handle(); + + purple_signal_connect(gtk_conv_handle, "conversation-displayed", plugin, + PURPLE_CALLBACK(conversation_displayed_cb), NULL); + + while (convs) { + PurpleConversation *conv = (PurpleConversation *)convs->data; + + /* Setup WebKit Inspector */ + if (PIDGIN_IS_PIDGIN_CONVERSATION(conv)) { + setup_inspector(PIDGIN_CONVERSATION(conv)); + } + + convs = convs->next; + } + + return TRUE; +} + +static gboolean +plugin_unload(PurplePlugin *plugin) +{ + GList *convs = purple_get_conversations(); + + while (convs) { + PurpleConversation *conv = (PurpleConversation *)convs->data; + + /* Remove WebKit Inspector */ + if (PIDGIN_IS_PIDGIN_CONVERSATION(conv)) { + remove_inspector(PIDGIN_CONVERSATION(conv)); + } + + convs = convs->next; + } + + return TRUE; +} + +static PurplePluginInfo info = +{ + PURPLE_PLUGIN_MAGIC, + PURPLE_MAJOR_VERSION, /**< major version */ + PURPLE_MINOR_VERSION, /**< minor version */ + PURPLE_PLUGIN_STANDARD, /**< type */ + PIDGIN_PLUGIN_TYPE, /**< ui_requirement */ + 0, /**< flags */ + NULL, /**< dependencies */ + PURPLE_PRIORITY_DEFAULT, /**< priority */ + + "gtkwebkit-inspect", /**< id */ + N_("WebKit Development"), /**< name */ + DISPLAY_VERSION, /**< version */ + N_("Enables WebKit Inspector."), /**< summary */ + N_("Enables WebKit's built-in inspector in a " + "conversation window. This may be viewed " + "by right-clicking a WebKit widget and " + "selecting 'Inspect Element'."), /**< description */ + "Elliott Sales de Andrade ", /**< author */ + PURPLE_WEBSITE, /**< homepage */ + plugin_load, /**< load */ + plugin_unload, /**< unload */ + NULL, /**< destroy */ + NULL, /**< ui_info */ + NULL, /**< extra_info */ + NULL, /**< prefs_info */ + NULL, /**< actions */ + + /* padding */ + NULL, + NULL, + NULL, + NULL +}; + +static void +init_plugin(PurplePlugin *plugin) +{ +} + +PURPLE_INIT_PLUGIN(webkit-devel, init_plugin, info) + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/plugins/xmppconsole.c --- a/pidgin/plugins/xmppconsole.c Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/plugins/xmppconsole.c Fri Apr 06 04:30:00 2012 +0000 @@ -190,7 +190,7 @@ gc = console->gc; if (gc) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(console->entry)); gtk_text_buffer_get_start_iter(buffer, &start); @@ -274,7 +274,9 @@ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); +#if !GTK_CHECK_VERSION(2,22,0) gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); +#endif gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); gtk_container_set_border_width(GTK_CONTAINER(dialog), 12); #if GTK_CHECK_VERSION(2,14,0) @@ -362,7 +364,9 @@ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); +#if !GTK_CHECK_VERSION(2,22,0) gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); +#endif gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); gtk_container_set_border_width(GTK_CONTAINER(dialog), 12); #if GTK_CHECK_VERSION(2,14,0) @@ -520,7 +524,9 @@ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); +#if !GTK_CHECK_VERSION(2,22,0) gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); +#endif gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); gtk_container_set_border_width(GTK_CONTAINER(dialog), 12); #if GTK_CHECK_VERSION(2,14,0) @@ -643,7 +649,7 @@ if (!console) return; - gtk_combo_box_append_text(GTK_COMBO_BOX(console->dropdown), purple_account_get_username(gc->account)); + gtk_combo_box_append_text(GTK_COMBO_BOX(console->dropdown), purple_account_get_username(purple_connection_get_account(gc))); console->accounts = g_list_append(console->accounts, gc); console->count++; @@ -733,10 +739,10 @@ account = purple_accounts_find(gtk_combo_box_get_active_text(GTK_COMBO_BOX(console->dropdown)), "prpl-jabber"); - if (!account || !account->gc) + if (!account || !purple_account_get_connection(account)) return; - console->gc = account->gc; + console->gc = purple_account_get_connection(account); gtk_imhtml_clear(GTK_IMHTML(console->imhtml)); } @@ -793,14 +799,17 @@ toolbar = gtk_toolbar_new(); button = gtk_tool_button_new(NULL, ""); + gtk_tool_item_set_is_important(button, TRUE); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(iq_clicked_cb), NULL); gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(button)); button = gtk_tool_button_new(NULL, ""); + gtk_tool_item_set_is_important(button, TRUE); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(presence_clicked_cb), NULL); gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(button)); button = gtk_tool_button_new(NULL, ""); + gtk_tool_item_set_is_important(button, TRUE); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(message_clicked_cb), NULL); gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(button)); diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/smileyparser.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/smileyparser.c Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,169 @@ +/* pidgin + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + */ + +#include +#include +#include "smileyparser.h" +#include +#include +#include "gtkthemes.h" + +static char * +get_fullpath(const char *filename) +{ + if (g_path_is_absolute(filename)) + return g_strdup(filename); + else + return g_build_path(g_get_current_dir(), filename, NULL); +} + +static void +parse_for_shortcut_plaintext(const char *text, const char *shortcut, const char *file, GString *ret) +{ + const char *tmp = text; + + for (;*tmp;) { + const char *end = strstr(tmp, shortcut); + char *path; + char *escaped_path; + + if (end == NULL) { + g_string_append(ret, tmp); + break; + } + path = get_fullpath(file); + escaped_path = g_markup_escape_text(path, -1); + + g_string_append_len(ret, tmp, end-tmp); + g_string_append_printf(ret,"%s", + shortcut, escaped_path); + g_free(path); + g_free(escaped_path); + g_assert(strlen(tmp) >= strlen(shortcut)); + tmp = end + strlen(shortcut); + } +} + +static char * +parse_for_shortcut(const char *markup, const char *shortcut, const char *file) +{ + GString* ret = g_string_new(""); + char *local_markup = g_strdup(markup); + char *escaped_shortcut = g_markup_escape_text(shortcut, -1); + + char *temp = local_markup; + + for (;*temp;) { + char *end = strchr(temp, '<'); + char *end_of_tag; + + if (!end) { + parse_for_shortcut_plaintext(temp, escaped_shortcut, file, ret); + break; + } + + *end = 0; + parse_for_shortcut_plaintext(temp, escaped_shortcut, file, ret); + *end = '<'; + + /* if this is well-formed, then there should be no '>' within + * the tag. TODO: handle a comment tag better :( */ + end_of_tag = strchr(end, '>'); + if (!end_of_tag) { + g_string_append(ret, end); + break; + } + + g_string_append_len(ret, end, end_of_tag - end + 1); + + temp = end_of_tag + 1; + } + g_free(local_markup); + g_free(escaped_shortcut); + return g_string_free(ret, FALSE); +} + +static char * +parse_for_purple_smiley(const char *markup, PurpleSmiley *smiley) +{ + char *file = purple_smiley_get_full_path(smiley); + char *ret = parse_for_shortcut(markup, purple_smiley_get_shortcut(smiley), file); + g_free(file); + return ret; +} + +static char * +parse_for_smiley_list(const char *markup, GHashTable *smileys) +{ + GHashTableIter iter; + char *key, *value; + char *ret = g_strdup(markup); + + g_hash_table_iter_init(&iter, smileys); + while (g_hash_table_iter_next(&iter, (gpointer *)&key, (gpointer *)&value)) + { + char *temp = parse_for_shortcut(ret, key, value); + g_free(ret); + ret = temp; + } + + return ret; +} + +char * +smiley_parse_markup(const char *markup, const char *proto_id) +{ + GList *smileys = purple_smileys_get_all(); + char *temp = g_strdup(markup), *temp2; + struct smiley_list *list; + const char *proto_name = "default"; + + if (proto_id != NULL) { + PurplePlugin *proto; + proto = purple_find_prpl(proto_id); + proto_name = proto->info->name; + } + + /* unnecessarily slow, but lets manage for now. */ + for (; smileys; smileys = g_list_next(smileys)) { + temp2 = parse_for_purple_smiley(temp, PURPLE_SMILEY(smileys->data)); + g_free(temp); + temp = temp2; + } + + /* now for each theme smiley, observe that this does look nasty */ + if (!current_smiley_theme || !(current_smiley_theme->list)) { + purple_debug_warning("smiley", "theme does not exist\n"); + return temp; + } + + for (list = current_smiley_theme->list; list; list = list->next) { + if (g_str_equal(list->sml, proto_name)) { + temp2 = parse_for_smiley_list(temp, list->files); + g_free(temp); + temp = temp2; + } + } + + return temp; +} + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/smileyparser.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/smileyparser.h Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,29 @@ +/* pidgin + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + */ + +G_BEGIN_DECLS + +char * +smiley_parse_markup(const char *markup, const char *sml); + +G_END_DECLS + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/themes/Contents/Info.plist --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/themes/Contents/Info.plist Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,16 @@ + + + + + MessageViewVersion + 4 + CFBundleName + Default + CFBundleIdentifier + im.pidgin.Default.style + DefaultFontFamily + sans-serif + DefaultFontSize + 11 + + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/themes/Contents/Resources/Content.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/themes/Contents/Resources/Content.html Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,6 @@ +
    + (%time%) +
    %sender%:
    +
    %message%
    +
    +
    diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/themes/Contents/Resources/Status.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/themes/Contents/Resources/Status.html Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,5 @@ +
    + %time% +
    %message%
    +
    +
    diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/themes/Contents/Resources/main.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/themes/Contents/Resources/main.css Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,61 @@ +body { + word-wrap: break-word; + word-break: break-word; +} + +.x-container, +.x-status_container +{ + line-height: 1.3em; + margin-bottom: 6px; +} + +.x-container .x-time, +.x-status_container .x-time +{ + display: inline; +} + +.x-container .x-sender +{ + display: inline; + font-weight: bold; +} + +.x-container .x-message, +.x-status_container .x-message +{ + display: inline; +} + +/* Colour-ify things */ + +.x-container.incoming .x-time, +.x-container.incoming .x-sender +{ + color: #cc0000; +} + +.x-container.outgoing .x-time, +.x-container.outgoing .x-sender +{ + color: #204a87; +} + +.x-container.mention .x-time, +.x-container.mention .x-sender +{ + color: #AF7F00; +} + +.x-status_container +{ + color: #777777; +} + +.x-status_container.error +{ + color: #ff0000; + font-weight: bold; +} + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/themes/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/themes/Makefile.am Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,18 @@ + +themetemplatedir = $(datadir)/pidgin/theme +themetemplate_DATA = Template.html +themecontentsdir = $(themetemplatedir)/Contents +themecontents_DATA = Contents/Info.plist +themeresourcesdir = $(themecontentsdir)/Resources +themeresources_DATA = Contents/Resources/Content.html \ + Contents/Resources/Status.html \ + Contents/Resources/main.css +themevariantsdir = $(themeresourcesdir)/Variants +themevariants_DATA = + +EXTRA_DIST = \ + $(themetemplate_DATA) \ + $(themecontents_DATA) \ + $(themeresources_DATA) \ + $(themevariants_DATA) + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/themes/Template.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pidgin/themes/Template.html Fri Apr 06 04:30:00 2012 +0000 @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + +%@ +
    +
    +%@ + + diff -r 2908b16efa07 -r f01d6c9f3492 pidgin/win32/untar.h --- a/pidgin/win32/untar.h Mon Apr 02 23:36:20 2012 +0000 +++ b/pidgin/win32/untar.h Fri Apr 06 04:30:00 2012 +0000 @@ -12,7 +12,7 @@ extern "C" { #endif /* __cplusplus */ -typedef enum _untar_opt { +typedef enum { UNTAR_LISTING = (1 << 0), UNTAR_QUIET = (1 << 1), UNTAR_VERBOSE = (1 << 2), diff -r 2908b16efa07 -r f01d6c9f3492 po/ChangeLog diff -r 2908b16efa07 -r f01d6c9f3492 po/POTFILES.in --- a/po/POTFILES.in Mon Apr 02 23:36:20 2012 +0000 +++ b/po/POTFILES.in Fri Apr 06 04:30:00 2012 +0000 @@ -160,14 +160,6 @@ libpurple/protocols/silc/silc.c libpurple/protocols/silc/util.c libpurple/protocols/silc/wb.c -libpurple/protocols/silc10/buddy.c -libpurple/protocols/silc10/chat.c -libpurple/protocols/silc10/ft.c -libpurple/protocols/silc10/ops.c -libpurple/protocols/silc10/pk.c -libpurple/protocols/silc10/silc.c -libpurple/protocols/silc10/util.c -libpurple/protocols/silc10/wb.c libpurple/protocols/simple/simple.c libpurple/protocols/yahoo/libyahoo.c libpurple/protocols/yahoo/libyahoojp.c diff -r 2908b16efa07 -r f01d6c9f3492 po/de.po --- a/po/de.po Mon Apr 02 23:36:20 2012 +0000 +++ b/po/de.po Fri Apr 06 04:30:00 2012 +0000 @@ -2,7 +2,7 @@ # Pidgin German translation # Copyright (C) 2001, Daniel Seifert # Copyright (C) 2002, Karsten Weiss -# Copyright (C) 2002-2012, Björn Voigt , +# Copyright (C) 2002-2011, Björn Voigt , # Jochen Kemnade # # This file is distributed under the same license as the Pidgin package. @@ -11,9 +11,9 @@ msgstr "" "Project-Id-Version: de\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-26 19:32+0200\n" -"PO-Revision-Date: 2012-03-26 18:53+0200\n" -"Last-Translator: Björn Voigt \n" +"POT-Creation-Date: 2012-03-26 20:19+0200\n" +"PO-Revision-Date: 2012-03-26 19:31+0200\n" +"Last-Translator: Jochen Kemnade \n" "Language-Team: German \n" "Language: de\n" "MIME-Version: 1.0\n" @@ -50,17 +50,6 @@ " -n, --nologin nicht automatisch anmelden\n" " -v, --version zeigt aktuelle Version und beendet das Programm\n" -#, c-format -msgid "" -"%s encountered errors migrating your settings from %s to %s. Please " -"investigate and complete the migration by hand. Please report this error at " -"http://developer.pidgin.im" -msgstr "" -"%s ist beim Übertragen Ihrer Einstellungen von %s nach %s auf Fehler " -"gestoßen. Bitte untersuchen Sie das Problem und vervollständigen Sie die " -"Migration per Hand. Bitte melden Sie diesen Fehler auf http://developer." -"pidgin.im" - #. the user did not fill in the captcha msgid "Error" msgstr "Fehler" @@ -213,6 +202,8 @@ msgid "Error adding buddy" msgstr "Fehler beim Hinzufügen des Buddys" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Username" msgstr "Benutzer" @@ -346,7 +337,11 @@ msgid "View Log" msgstr "Mitschnitt anzeigen" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext #. General +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Nickname" msgstr "Spitzname" @@ -800,7 +795,11 @@ msgstr "Verbleibend" #. XXX: Use of ggp_str_to_uin() is an ugly hack! +#. TODO: Check whether it's correct to call prepend_pair_html, +#. or if we should be using prepend_pair_plaintext #. presence +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Status" msgstr "Status" @@ -906,7 +905,6 @@ msgid "Hangup" msgstr "Auflegen" -#. Number of actions msgid "Accept" msgstr "Akzeptieren" @@ -914,7 +912,7 @@ msgstr "Ablehnen" msgid "Call in progress." -msgstr "Verbindungsaufbau." +msgstr "Anruf im Gange." msgid "The call has been terminated." msgstr "Der Anruf wurde beendet." @@ -1389,6 +1387,8 @@ msgid "Type" msgstr "Typ" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext #. Statuses are almost all the same. Define a macro to reduce code repetition. #. PurpleStatusPrimitive #. id - use default @@ -1397,6 +1397,8 @@ #. user_settable #. not independent #. Attributes - each status can have a message. +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Message" msgstr "Nachricht" @@ -1741,22 +1743,20 @@ msgid "An unknown certificate error occurred." msgstr "Es ist ein unbekannter Zertifikatfehler aufgetreten." +msgid "(MATCH)" +msgstr "(ÜBEREINSTIMMUNG)" + msgid "(DOES NOT MATCH)" -msgstr "(stimmt nicht überein)" - -#. Make messages +msgstr "(KEINE ÜBEREINSTIMMUNG)" + #, c-format msgid "%s has presented the following certificate for just-this-once use:" msgstr "" "%s hat das folgende Zertifikat für den einmaligen Gebrauch präsentiert:" #, c-format -msgid "" -"Common name: %s %s\n" -"Fingerprint (SHA1): %s" -msgstr "" -"Allgemeiner Name (Common name:) %s %s\n" -"Fingerabdruck (SHA1): %s" +msgid "Common name: %s %s" +msgstr "Allgemeiner Name (Common name): %s %s" #. TODO: Find what the handle ought to be msgid "Single-use Certificate Verification" @@ -1772,7 +1772,6 @@ msgid "SSL Peers Cache" msgstr "SSL-Peers-Zwischenspeicher" -#. Make messages #, c-format msgid "Accept certificate for %s?" msgstr "Akzeptieren Sie das Zertifikat für %s?" @@ -1781,9 +1780,6 @@ msgid "SSL Certificate Verification" msgstr "SSL-Zertifikatsüberprüfung" -msgid "_View Certificate..." -msgstr "Ze_rtifikat ansehen..." - #, c-format msgid "The certificate for %s could not be validated." msgstr "Das Zertifikat für %s konnte nicht validiert werden." @@ -1804,27 +1800,6 @@ "dass Sie tatsächlich nicht mit dem Dienst verbunden sind, mit dem Sie " "glauben verbunden zu sein." -#. Make messages -#, c-format -msgid "" -"Common name: %s\n" -"\n" -"Fingerprint (SHA1): %s\n" -"\n" -"Activation date: %s\n" -"Expiration date: %s\n" -msgstr "" -"Allgemeiner Name (Common name): %s\n" -"\n" -"Fingerabdruck (SHA1): %s\n" -"\n" -"Aktivierungsdatum: %s\n" -"Ablaufdatum: %s\n" - -#. TODO: Find what the handle ought to be -msgid "Certificate Information" -msgstr "Zertifikat-Information" - #. show error to user msgid "Registration Error" msgstr "Registrierungsfehler" @@ -2893,6 +2868,23 @@ msgid "Tests to see that most things are working." msgstr "Tests, um zu sehen, ob das meiste funktioniert." +#. Make messages +#, c-format +msgid "" +"Common name: %s\n" +"\n" +"Fingerprint (SHA1): %s\n" +"\n" +"Activation date: %s\n" +"Expiration date: %s\n" +msgstr "" +"Allgemeiner Name (Common name): %s\n" +"\n" +"Fingerabdruck (SHA1): %s\n" +"\n" +"Aktivierungsdatum: %s\n" +"Ablaufdatum: %s\n" + #. Scheme name msgid "X.509 Certificates" msgstr "X.509-Zertifikate" @@ -3025,19 +3017,29 @@ msgstr "Keine Verbindung zum lokalen mDNS-Server. Ist er aktiviert?" # old strings +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "First name" msgstr "Vorname" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Last name" msgstr "Nachname" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext #. email msgid "Email" msgstr "E-Mail" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "AIM Account" msgstr "AIM-Konto" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "XMPP Account" msgstr "XMPP-Konto" @@ -3152,6 +3154,8 @@ msgid "Please, fill in the following fields" msgstr "Bitte füllen Sie die folgenden Felder aus" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "City" msgstr "Stadt" @@ -3159,6 +3163,8 @@ msgstr "Geburtsjahr" #. gender +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Gender" msgstr "Geschlecht" @@ -3181,27 +3187,36 @@ msgid "Please, enter your search criteria below" msgstr "Bitte geben Sie Ihre Suchkriterien unten ein" -msgid "Fill in the fields." -msgstr "Füllen Sie die Felder aus." - -msgid "Your current password is different from the one that you specified." -msgstr "Ihr aktuelles Passwort ist anders als das angegebene." - -msgid "Unable to change password. Error occurred.\n" -msgstr "Konnte das Passwort nicht ändern. Es trat ein Fehler auf.\n" - msgid "Change password for the Gadu-Gadu account" msgstr "Ändern des Passworts für dieses Gadu-Gadu-Konto" msgid "Password was changed successfully!" msgstr "Das Passwort wurde erfolgreich geändert!" +msgid "Unable to change password. Error occurred.\n" +msgstr "Konnte das Passwort nicht ändern. Es trat ein Fehler auf.\n" + +msgid "Fill in the fields." +msgstr "Füllen Sie die Felder aus." + +msgid "New password should be at most 15 characters long." +msgstr "Das neue Passwort darf maximal 15 Zeichen lang sein." + +msgid "Your current password is different from the one that you specified." +msgstr "Ihr aktuelles Passwort ist anders als das angegebene." + +msgid "Invalid email address" +msgstr "Ungültige E-Mail-Adresse" + msgid "Current password" msgstr "Aktuelles Passwort" msgid "Password (retype)" msgstr "Passwort (nochmal)" +msgid "Email Address" +msgstr "E-Mail-Adresse" + msgid "Enter current token" msgstr "Geben Sie das aktuelle Token ein" @@ -3257,14 +3272,20 @@ msgid "Away" msgstr "Abwesend" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "UIN" msgstr "UIN" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext #. first name #. optional information msgid "First Name" msgstr "Vorname" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Birth Year" msgstr "Geburtsjahr" @@ -3304,6 +3325,30 @@ msgid "Connected" msgstr "Verbunden" +msgid "Unable to resolve hostname" +msgstr "Hostname konnte nicht aufgelöst werden" + +msgid "Incorrect password" +msgstr "Falsches Passwort" + +msgid "SSL Connection Failed" +msgstr "SSL-Verbindung gescheitert" + +msgid "" +"Your account has been disabled because too many incorrect passwords were " +"entered" +msgstr "" +"Ihr Konto wurde wegen zu vielen falsch eingegebenen Passworten gesperrt" + +msgid "Service temporarily unavailable" +msgstr "Dienst momentan nicht verfügbar" + +msgid "Error connecting to proxy server" +msgstr "Fehler beim Verbinden mit dem Proxy-Server" + +msgid "Error connecting to master server" +msgstr "Fehler beim Verbinden mit dem Master-Server" + msgid "Connection failed" msgstr "Verbindung fehlgeschlagen" @@ -3313,6 +3358,12 @@ msgid "Chat _name:" msgstr "Chat_name:" +msgid "The username specified is invalid." +msgstr "Der angegebene Benutzername ist ungültig." + +msgid "SSL support unavailable" +msgstr "SSL-Unterstützung nicht verfügbar" + #, c-format msgid "Unable to resolve hostname '%s': %s" msgstr "Hostname '%s' kann nicht aufgelöst werden: %s" @@ -3331,12 +3382,12 @@ msgid "Not connected to the server" msgstr "Nicht mit dem Server verbunden" +msgid "Change password..." +msgstr "Passwort ändern..." + msgid "Find buddies..." msgstr "Finde Buddys..." -msgid "Change password..." -msgstr "Passwort ändern..." - msgid "Upload buddylist to Server" msgstr "Buddy-Liste zum Server hochladen" @@ -3367,25 +3418,24 @@ msgid "Polish popular IM" msgstr "Beliebter polnischer IM-Dienst" -msgid "Gadu-Gadu User" -msgstr "Gadu-Gadu-Benutzer" - msgid "GG server" msgstr "GG-Server" +msgid "Use encryption if available" +msgstr "Verschlüsselung benutzen, wenn verfügbar" + +msgid "Require encryption" +msgstr "Verschlüsselung fordern" + msgid "Don't use encryption" msgstr "Keine Verschlüsselung benutzen" -msgid "Use encryption if available" -msgstr "Verschlüsselung benutzen, wenn verfügbar" - -#. TODO -msgid "Require encryption" -msgstr "Verschlüsselung fordern" - msgid "Connection security" msgstr "Verbindungssicherheit" +msgid "Show links from strangers" +msgstr "Links von Fremden anzeigen" + #, c-format msgid "Unknown command: %s" msgstr "Unbekanntes Kommando: %s" @@ -3438,9 +3488,6 @@ msgid "IRC nick and server may not contain whitespace" msgstr "IRC-Server und -Spitzname dürfen keinen Leerraum enthalten" -msgid "SSL support unavailable" -msgstr "SSL-Unterstützung nicht verfügbar" - msgid "Unable to connect" msgstr "Verbindung nicht möglich" @@ -3475,6 +3522,8 @@ msgstr "Das IRC-Protokoll-Plugin mit weniger Problemen" #. set up account ID as user:server +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Server" msgstr "Server" @@ -4013,6 +4062,8 @@ msgid "Unable to establish SSL connection" msgstr "Kann SSL-Verbindung nicht erstellen" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Full Name" msgstr "Vollständiger Name" @@ -4083,9 +4134,13 @@ "Die folgenden Punkte sind optional. Geben Sie nur die Informationen an, die " "Sie angeben möchten." +#. TODO: Check whether it's correct to call prepend_pair_html, +#. or if we should be using prepend_pair_plaintext msgid "Client" msgstr "Client" +#. TODO: Check whether it's correct to call prepend_pair_html, +#. or if we should be using prepend_pair_plaintext msgid "Operating System" msgstr "Betriebssystem" @@ -4095,6 +4150,8 @@ msgid "Priority" msgstr "Priorität" +#. TODO: Check whether it's correct to call prepend_pair_html, +#. or if we should be using prepend_pair_plaintext msgid "Resource" msgstr "Ressource" @@ -4191,9 +4248,6 @@ "Füllen Sie ein oder mehrere Felder aus, um nach entsprechenden XMPP-" "Benutzern zu suchen." -msgid "Email Address" -msgstr "E-Mail-Adresse" - msgid "Search for XMPP users" msgstr "Suche nach XMPP-Benutzern" @@ -4404,6 +4458,8 @@ msgid "Not Authorized" msgstr "Nicht autorisiert" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Mood" msgstr "Stimmung" @@ -5253,9 +5309,6 @@ msgid "Syntax Error (probably a client bug)" msgstr "Syntaxfehler (wahrscheinlich ein Client-Bug)" -msgid "Invalid email address" -msgstr "Ungültige E-Mail-Adresse" - msgid "User does not exist" msgstr "Benutzer existiert nicht" @@ -5323,9 +5376,6 @@ msgid "Not logged in" msgstr "Nicht angemeldet" -msgid "Service temporarily unavailable" -msgstr "Dienst momentan nicht verfügbar" - msgid "Database server error" msgstr "Fehler des Datenbank-Servers" @@ -5673,6 +5723,8 @@ msgid "Occupation" msgstr "Beruf" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Location" msgstr "Ort" @@ -5935,8 +5987,8 @@ "%s (There was an error receiving this message. Converting the encoding from " "%s to UTF-8 failed.)" msgstr "" -"%s (Es gab einen Fehler beim Konvertieren dieser Nachricht. Die " -"Konvertierung von %s zu UTF-8 ist gescheitert.)" +"%s (Es gab einen Fehler beim Empfang dieser Nachricht. Die Konvertierung von " +"%s zu UTF-8 ist gescheitert.)" #, c-format msgid "" @@ -6080,9 +6132,6 @@ msgid "Do you want to delete this buddy from your address book as well?" msgstr "Möchten Sie diesen Buddy außerdem aus Ihrem Adressbuch löschen?" -msgid "The username specified is invalid." -msgstr "Der angegebene Benutzername ist ungültig." - msgid "The Display Name you entered is invalid." msgstr "Der eingegebene Anzeigename ist ungültig." @@ -6098,6 +6147,8 @@ #. no profile information yet, so we cannot update #. (reference: "libpurple/request.h") +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Profile" msgstr "Profil" @@ -6211,6 +6262,8 @@ msgid "About..." msgstr "Über..." +#. we are trying to send a file to MXit +#. need to reserve some space for packet headers #. the file is too big msgid "The file you are trying to send is too large!" msgstr "Die Datei, die Sie senden möchten ist zu groß!" @@ -6331,16 +6384,14 @@ msgid "Loading menu..." msgstr "Lade das Menü..." +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Status Message" msgstr "Status-Nachricht" msgid "Rejection Message" msgstr "Ablehnungsnachricht" -#. hidden number -msgid "Hidden Number" -msgstr "Versteckte Nummer" - msgid "No profile available" msgstr "Kein Profil verfügbar" @@ -6424,6 +6475,12 @@ msgid "Message Error" msgstr "Nachrichtenfehler" +#. could not be decrypted +msgid "An encrypted message was received which could not be decrypted." +msgstr "" +"Eine verschlüsselte Nachricht wurde empfangen und konnte nicht entschlüsselt " +"werden." + msgid "Cannot perform redirect using the specified protocol" msgstr "Kann die Umleitung nicht mit dem angegebenen Protokoll durchführen" @@ -6688,18 +6745,26 @@ msgid "Base font size (points)" msgstr "Basis-Schriftgröße (Punkt)" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "User" msgstr "Benutzer" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Headline" msgstr "Überschrift" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Song" msgstr "Lied" msgid "Total Friends" msgstr "Freunde insgesamt" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Client Version" msgstr "Client-Version" @@ -6903,9 +6968,6 @@ msgid "Password has expired" msgstr "Passwort ist abgelaufen" -msgid "Incorrect password" -msgstr "Falsches Passwort" - msgid "Account has been disabled" msgstr "Konto wurde deaktiviert" @@ -6932,12 +6994,6 @@ "Konnte den Rechnernamen des Benutzers, den Sie eingegeben haben, nicht " "erkennen" -msgid "" -"Your account has been disabled because too many incorrect passwords were " -"entered" -msgstr "" -"Ihr Konto wurde wegen zu vielen falsch eingegebenen Passworten gesperrt" - msgid "You cannot add the same person twice to a conversation" msgstr "Sie können die selbe Person nicht zweimal zu einem Gespräch hinzufügen" @@ -7063,12 +7119,9 @@ msgid "User ID" msgstr "Benutzer-ID" -#. tag = _("DN"); -#. value = nm_user_record_get_dn(user_record); -#. if (value) { -#. purple_notify_user_info_add_pair(user_info, tag, value); -#. } -#. +msgid "DN" +msgstr "DN" + msgid "Full name" msgstr "Vollständiger Name" @@ -7865,9 +7918,6 @@ "senden. Ihre Buddy-Liste ist nicht verloren und wird wahrscheinlich in ein " "paar Minuten wieder verfügbar sein." -msgid "Orphans" -msgstr "Waisen" - #, c-format msgid "" "Unable to add the buddy %s because you have too many buddies in your buddy " @@ -8171,6 +8221,7 @@ msgid "Mobile Phone" msgstr "Handynummer" +#. TODO: Is it correct to pass info->email here...? msgid "Personal Web Page" msgstr "Persönliche Webseite" @@ -8191,6 +8242,7 @@ msgid "Position" msgstr "Position" +#. TODO: Is it correct to pass info->email here...? msgid "Web Page" msgstr "Webseite" @@ -8460,13 +8512,13 @@ msgid "A server is required to connect this account" msgstr "Es wird ein Server benötigt um dieses Konto zu verbinden" +msgid "Last Known Client" +msgstr "Letzter bekannter Client" + #, c-format msgid "Unknown (0x%04x)
    " msgstr "Unbekannt (0x%04x)
    " -msgid "Last Known Client" -msgstr "Letzter bekannter Client" - msgid "User Name" msgstr "Benutzername" @@ -8789,21 +8841,33 @@ msgid "Robot" msgstr "Robot" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "User Modes" msgstr "Benutzermodi" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Preferred Contact" msgstr "Bevorzugter Kontakt" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Preferred Language" msgstr "Bevorzugte Sprache" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Device" msgstr "Gerät" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Timezone" msgstr "Zeitzone" +#. TODO: Check whether it's correct to call add_pair_html, +#. or if we should be using add_pair_plaintext msgid "Geolocation" msgstr "Geographische Koordinaten" @@ -9673,78 +9737,12 @@ msgid "Whiteboard" msgstr "Whiteboard" -msgid "No server statistics available" -msgstr "Keine Serverstatistik verfügbar" - -msgid "Error during connecting to SILC Server" -msgstr "Fehler beim Verbinden mit dem SILC-Server" - -#, c-format -msgid "Failure: Version mismatch, upgrade your client" -msgstr "Fehler: Unterschiedliche Version, aktualisieren Sie Ihren Client" - -#, c-format -msgid "Failure: Remote does not trust/support your public key" -msgstr "" -"Fehler: Die entfernte Seite vertraut Ihrem öffentlichen Schlüssel nicht" - -#, c-format -msgid "Failure: Remote does not support proposed KE group" -msgstr "" -"Fehler: Entferntes Programm unterstützt nicht die vorgeschlagen KE-Gruppe" - -#, c-format -msgid "Failure: Remote does not support proposed cipher" -msgstr "" -"Fehler: Entferntes Programm unterstützt die vorgeschlagene Chiffre nicht" - -#, c-format -msgid "Failure: Remote does not support proposed PKCS" -msgstr "Fehler: Entferntes Programm unterstützt die vorgeschlagene PKCS nicht" - -#, c-format -msgid "Failure: Remote does not support proposed hash function" -msgstr "" -"Fehler: Entferntes Programm unterstützt die vorgeschlagen Hashfunktion nicht" - -#, c-format -msgid "Failure: Remote does not support proposed HMAC" -msgstr "Fehler: Entferntes Programm unterstützt das vorgeschlagene HMAC nicht" - -#, c-format -msgid "Failure: Incorrect signature" -msgstr "Fehler: Falsche Signatur" - -#, c-format -msgid "Failure: Invalid cookie" -msgstr "Fehler: Ungültiger Cookie" - -#, c-format -msgid "Failure: Authentication failed" -msgstr "Fehler: Authentifizierung fehlgeschlagen" - -msgid "Unable to initialize SILC Client connection" -msgstr "SILC-Client-Verbindung konnte nicht hergestellt werden" - -msgid "John Noname" -msgstr "Max Mustermann" - -#, c-format -msgid "Unable to load SILC key pair: %s" -msgstr "SILC-Schlüsselpaar konnte nicht geladen werden: %s" - -msgid "Unable to create connection" -msgstr "Kann Verbindung nicht erstellen" - msgid "Unknown server response" msgstr "Unbekannte Serverantwort" msgid "Unable to create listen socket" msgstr "Lauschender Socket konnte nicht erstellt werden" -msgid "Unable to resolve hostname" -msgstr "Hostname konnte nicht aufgelöst werden" - msgid "SIP usernames may not contain whitespaces or @ symbols" msgstr "SIP-Benutzernamen dürfen keine Leerzeichen oder @-Symbole enthalten" @@ -10225,6 +10223,8 @@ msgid "Hidden or not logged-in" msgstr "Versteckt oder nicht angemeldet" +#. TODO: Need to escape locs.host and locs.time? +#. TODO: Need to escape the two strings that make up tmp? #, c-format msgid "
    At %s since %s" msgstr "
    Bei %s seit %s" @@ -10433,9 +10433,6 @@ msgid "Stored Image. (that'll have to do for now)" msgstr "Gespeichertes Bild. (Das muss erstmal reichen)" -msgid "SSL Connection Failed" -msgstr "SSL-Verbindung gescheitert" - msgid "SSL Handshake Failed" msgstr "SSL-Verhandlung gescheitert" @@ -11006,9 +11003,6 @@ msgid "_Expand" msgstr "A_usklappen" -msgid "/Tools/Mute Sounds" -msgstr "/Werkzeuge/Stummschalten" - msgid "" "You are not currently signed on with an account that can add that buddy." msgstr "" @@ -11033,122 +11027,121 @@ #. NOTE: Do not set any accelerator to Control+O. It is mapped by #. gtk_blist_key_press_cb to "Get User Info" on the selected buddy. #. Buddies menu -msgid "/_Buddies" -msgstr "/_Buddys" - -msgid "/Buddies/New Instant _Message..." -msgstr "/Buddys/_Neue Sofortnachricht..." - -msgid "/Buddies/Join a _Chat..." -msgstr "/Buddys/Einen _Chat betreten..." - -msgid "/Buddies/Get User _Info..." -msgstr "/Buddys/Benu_tzer-Info abrufen..." - -msgid "/Buddies/View User _Log..." -msgstr "/Buddys/Benutzer-_Mitschnitt ansehen..." - -msgid "/Buddies/Sh_ow" -msgstr "/Buddys/_Anzeigen" - -msgid "/Buddies/Show/_Offline Buddies" -msgstr "/Buddys/Anzeigen/_Offline-Buddys" - -msgid "/Buddies/Show/_Empty Groups" -msgstr "/Buddys/Anzeigen/_Leere Gruppen" - -msgid "/Buddies/Show/Buddy _Details" -msgstr "/Buddys/Anzeigen/Buddy-_Details" - -msgid "/Buddies/Show/Idle _Times" -msgstr "/Buddys/Anzeigen/Untätigkeitszei_ten" - -msgid "/Buddies/Show/_Protocol Icons" -msgstr "/Buddys/Anzeigen/_Protokoll-Icons" - -msgid "/Buddies/_Sort Buddies" -msgstr "/Buddys/Buddys _sortieren" - -msgid "/Buddies/_Add Buddy..." -msgstr "/Buddys/B_uddy hinzufügen..." - -msgid "/Buddies/Add C_hat..." -msgstr "/Buddys/C_hat hinzufügen..." - -msgid "/Buddies/Add _Group..." -msgstr "/Buddys/_Gruppe hinzufügen..." - -msgid "/Buddies/_Quit" -msgstr "/Buddys/_Beenden" +msgid "_Buddies" +msgstr "_Buddys" + +msgid "New Instant _Message..." +msgstr "Neue Sofortnachricht..." + +msgid "Join a _Chat..." +msgstr "_Chat betreten..." + +msgid "Get User _Info..." +msgstr "Benu_tzer-Info abrufen..." + +msgid "View User _Log..." +msgstr "Benutzer-_Mitschnitt ansehen..." + +msgid "Sh_ow" +msgstr "_Anzeigen" + +msgid "_Sort Buddies" +msgstr "Buddys _sortieren" + +msgid "_Add Buddy..." +msgstr "_Buddy hinzufügen..." + +msgid "Add _Group..." +msgstr "_Gruppe hinzufügen..." + +msgid "_Quit" +msgstr "_Beenden" #. Accounts menu -msgid "/_Accounts" -msgstr "/_Konten" - -msgid "/Accounts/Manage Accounts" -msgstr "/Konten/Konten verwalten" +msgid "_Accounts" +msgstr "_Konten" + +msgid "Manage Accounts" +msgstr "Konten verwalten" #. Tools -msgid "/_Tools" -msgstr "/_Werkzeuge" - -msgid "/Tools/Buddy _Pounces" -msgstr "/Werkzeuge/Buddy-_Alarm" - -msgid "/Tools/_Certificates" -msgstr "/Werkzeuge/_Zertifikate" - -msgid "/Tools/Custom Smile_ys" -msgstr "/Werkzeuge/Benutzerdefinierte Smile_ys" - -msgid "/Tools/Plu_gins" -msgstr "/Werkzeuge/Plu_gins" - -msgid "/Tools/Pr_eferences" -msgstr "/Werkzeuge/_Einstellungen" - -msgid "/Tools/Pr_ivacy" -msgstr "/Werkzeuge/Pri_vatsphäre" - -msgid "/Tools/Set _Mood" -msgstr "/Werkzeuge/Setze Sti_mmung" - -msgid "/Tools/_File Transfers" -msgstr "/Werkzeuge/_Dateiübertragungen" - -msgid "/Tools/R_oom List" -msgstr "/Werkzeuge/Chat_räume" - -msgid "/Tools/System _Log" -msgstr "/Werkzeuge/_Systemmitschnitt" - -msgid "/Tools/Mute _Sounds" -msgstr "/Werkzeuge/S_tummschalten" +msgid "_Tools" +msgstr "_Werkzeuge" + +msgid "Buddy _Pounces" +msgstr "Buddy-_Alarm" + +msgid "_Certificates" +msgstr "_Zertifikate" + +msgid "Custom Smile_ys" +msgstr "Benutzerdefinierte Smile_ys" + +msgid "Plu_gins" +msgstr "_Plugins" + +msgid "Pr_eferences" +msgstr "_Einstellungen" + +msgid "Pr_ivacy" +msgstr "Pri_vatsphäre" + +msgid "Set _Mood" +msgstr "Setze Sti_mmung" + +msgid "_File Transfers" +msgstr "Dateiübertragungen" + +msgid "R_oom List" +msgstr "_Chaträume" + +msgid "System _Log" +msgstr "_Systemmitschnitt" #. Help -msgid "/_Help" -msgstr "/_Hilfe" - -msgid "/Help/Online _Help" -msgstr "/Hilfe/Online-_Hilfe" - -msgid "/Help/_Build Information" -msgstr "/Hilfe/_Build-Informationen" - -msgid "/Help/_Debug Window" -msgstr "/Hilfe/_Debug-Fenster" - -msgid "/Help/De_veloper Information" -msgstr "/Hilfe/_Entwickler-Informationen" - -msgid "/Help/_Plugin Information" -msgstr "/Hilfe/_Plugin-Informationen" - -msgid "/Help/_Translator Information" -msgstr "/Hilfe/Über_setzer-Informationen" - -msgid "/Help/_About" -msgstr "/Hilfe/Übe_r" +msgid "_Help" +msgstr "_Hilfe" + +msgid "Online _Help" +msgstr "Online-_Hilfe" + +msgid "_Build Information" +msgstr "_Build-Informationen" + +msgid "_Debug Window" +msgstr "_Debug-Fenster" + +msgid "De_veloper Information" +msgstr "_Entwickler-Informationen" + +msgid "_Plugin Information" +msgstr "_Plugin-Informationen" + +msgid "_Translator Information" +msgstr "Über_setzer-Informationen" + +msgid "_About" +msgstr "Übe_r" + +#. Buddies->Show menu +msgid "_Offline Buddies" +msgstr "_Offline-Buddys" + +msgid "_Empty Groups" +msgstr "_Leere Gruppen" + +msgid "Buddy _Details" +msgstr "Buddy-_Details" + +msgid "Idle _Times" +msgstr "Untätigkeitszei_ten" + +msgid "_Protocol Icons" +msgstr "_Protokoll-Icons" + +#. Tools menu +msgid "Mute _Sounds" +msgstr "Stu_mmschalten" #, c-format msgid "Account: %s" @@ -11206,30 +11199,6 @@ msgid "Idle %dm" msgstr "Untätig seit %dm" -msgid "/Buddies/New Instant Message..." -msgstr "/Buddys/Neue Sofortnachricht..." - -msgid "/Buddies/Join a Chat..." -msgstr "/Buddys/Chat betreten..." - -msgid "/Buddies/Get User Info..." -msgstr "/Buddys/Benutzer-Info abrufen..." - -msgid "/Buddies/Add Buddy..." -msgstr "/Buddys/Buddy hinzufügen..." - -msgid "/Buddies/Add Chat..." -msgstr "/Buddys/Chat hinzufügen..." - -msgid "/Buddies/Add Group..." -msgstr "/Buddys/Gruppe hinzufügen..." - -msgid "/Tools/Privacy" -msgstr "/Werkzeuge/Privatsphäre" - -msgid "/Tools/Room List" -msgstr "/Werkzeuge/Chaträume" - #, c-format msgid "%d unread message from %s\n" msgid_plural "%d unread messages from %s\n" @@ -11285,9 +11254,6 @@ msgid "_Login" msgstr "_Anmelden" -msgid "/Accounts" -msgstr "/Konten" - #. Translators: Please maintain the use of -> and <- to refer to menu heirarchy #, c-format msgid "" @@ -11304,24 +11270,6 @@ "aktiviert haben, können Sie sich anmelden, Ihren Status setzen und mit Ihren " "Freunden reden." -#. set the Show Offline Buddies option. must be done -#. * after the treeview or faceprint gets mad. -Robot101 -#. -msgid "/Buddies/Show/Offline Buddies" -msgstr "/Buddys/Anzeigen/Offline-Buddys" - -msgid "/Buddies/Show/Empty Groups" -msgstr "/Buddys/Anzeigen/Leere Gruppen" - -msgid "/Buddies/Show/Buddy Details" -msgstr "/Buddys/Anzeigen/Buddy-Details" - -msgid "/Buddies/Show/Idle Times" -msgstr "/Buddys/Anzeigen/Untätigkeitszeiten" - -msgid "/Buddies/Show/Protocol Icons" -msgstr "/Buddys/Anzeigen/Protokoll-Icons" - msgid "Add a buddy.\n" msgstr "Einen Buddy hinzufügen.\n" @@ -11370,12 +11318,6 @@ msgid "Enable Account" msgstr "Konten aktivieren" -msgid "/Accounts/Enable Account" -msgstr "/Konten/Konto aktivieren" - -msgid "/Accounts/" -msgstr "/Konten/" - msgid "_Edit Account" msgstr "Konto _bearbeiten" @@ -11388,19 +11330,40 @@ msgid "_Disable" msgstr "_Deaktivieren" -msgid "/Tools" -msgstr "/Werkzeuge" - -msgid "/Buddies/Sort Buddies" -msgstr "/Buddys/Buddys sortieren" - msgid "Type the host name for this certificate." msgstr "Geben Sie einen Hostnamen für dieses Zertifikat an." +#. Fire the notification +#, c-format +msgid "Certificate Information for %s" +msgstr "Zertifikat-Information für %s" + #. Widget creation function msgid "SSL Servers" msgstr "SSL-Server" +msgid "Unsafe debugging is now disabled." +msgstr "Unsicheres Debugging ist nun deaktiviert." + +msgid "Unsafe debugging is now enabled." +msgstr "Unsicheres Debugging ist nun aktiviert." + +msgid "Verbose debugging is now disabled." +msgstr "Ausführliches Debugging ist nun deaktiviert." + +msgid "Verbose debugging is now enabled." +msgstr "Ausführliches Debugging ist nun aktiviert." + +msgid "Supported debug options are: plugins version unsafe verbose" +msgstr "Unterstützte Debug-Optionen sind: plugins version unsafe verbose" + +msgid "" +"Use \"/help <command>\" for help on a specific command.
    The " +"following commands are available in this context:
    " +msgstr "" +"Benutzen Sie „/help <kommando>“, um Hilfe für ein bestimmtes Kommando " +"zu erhalten. Die folgenden Kommandos sind in diesem Kontext verfügbar:
    " + msgid "Unknown command." msgstr "Unbekanntes Kommando." @@ -11435,9 +11398,6 @@ msgid "Ignore" msgstr "Ignorieren" -msgid "Get Away Message" -msgstr "Neue Abwesenheitsnachricht abholen" - msgid "Last Said" msgstr "Zuletzt gesagt" @@ -11466,170 +11426,78 @@ msgstr "Alle anzeigen" #. Conversation menu -msgid "/_Conversation" -msgstr "/_Unterhaltung" - -msgid "/Conversation/New Instant _Message..." -msgstr "/Unterhaltung/_Neue Sofortnachricht..." - -msgid "/Conversation/Join a _Chat..." -msgstr "/Unterhaltung/Einen Cha_t betreten..." - -msgid "/Conversation/_Find..." -msgstr "/Unterhaltung/_Finden..." - -msgid "/Conversation/View _Log" -msgstr "/Unterhaltung/_Mitschnitt anzeigen" - -msgid "/Conversation/_Save As..." -msgstr "/Unterhaltung/S_peichern als..." - -msgid "/Conversation/Clea_r Scrollback" -msgstr "/Unterhaltung/_Leeren" - -msgid "/Conversation/M_edia" -msgstr "/Unterhaltung/M_edien" - -msgid "/Conversation/Media/_Audio Call" -msgstr "/Unterhaltung/Medien/_Audio-Anruf" - -msgid "/Conversation/Media/_Video Call" -msgstr "/Unterhaltung/Medien/_Video-Anruf" - -msgid "/Conversation/Media/Audio\\/Video _Call" -msgstr "/Unterhaltung/Medien/A_udio-\\/Video-Anruf" - -msgid "/Conversation/Se_nd File..." -msgstr "/Unterhaltung/Datei _senden..." - -msgid "/Conversation/Get _Attention" -msgstr "/Unterhaltung/_Aufmerksamkeit erregen" - -msgid "/Conversation/Add Buddy _Pounce..." -msgstr "/Unterhaltung/_Buddy-Alarm hinzufügen..." - -msgid "/Conversation/_Get Info" -msgstr "/Unterhaltung/_Info abrufen" - -msgid "/Conversation/In_vite..." -msgstr "/Unterhaltung/_Einladen..." - -msgid "/Conversation/M_ore" -msgstr "/Unterhaltung/Me_hr" - -msgid "/Conversation/Al_ias..." -msgstr "/Unterhaltung/Al_ias..." - -msgid "/Conversation/_Block..." -msgstr "/Unterhaltung/_Blockieren..." - -msgid "/Conversation/_Unblock..." -msgstr "/Unterhaltung/_Entsperren..." - -msgid "/Conversation/_Add..." -msgstr "/Unterhaltung/_Hinzufügen..." - -msgid "/Conversation/_Remove..." -msgstr "/Unterhaltung/_Entfernen..." - -msgid "/Conversation/Insert Lin_k..." -msgstr "/Unterhaltung/Lin_k einfügen..." - -msgid "/Conversation/Insert Imag_e..." -msgstr "/Unterhaltung/Bil_d einfügen..." - -msgid "/Conversation/_Close" -msgstr "/Unterhaltung/S_chließen" +msgid "_Conversation" +msgstr "_Unterhaltung" + +msgid "_Find..." +msgstr "_Finden..." + +msgid "_Save As..." +msgstr "S_peichern als..." + +msgid "Clea_r Scrollback" +msgstr "_Leeren..." + +msgid "M_edia" +msgstr "M_edien" + +msgid "Audio/Video _Call" +msgstr "A_udio/Video-Anruf" + +msgid "Se_nd File..." +msgstr "Datei _senden..." + +msgid "Get _Attention" +msgstr "_Aufmerksamkeit erregen" + +msgid "_Get Info" +msgstr "_Info abrufen" + +msgid "In_vite..." +msgstr "_Einladen..." + +msgid "M_ore" +msgstr "Me_hr" + +msgid "Al_ias..." +msgstr "Al_ias..." + +msgid "_Block..." +msgstr "_Blockieren..." + +msgid "_Unblock..." +msgstr "_Entsperren..." + +msgid "_Add..." +msgstr "_Hinzufügen..." + +msgid "_Remove..." +msgstr "_Entfernen..." + +msgid "Insert Lin_k..." +msgstr "_Entfernen..." + +msgid "Insert Imag_e..." +msgstr "Bil_d einfügen..." + +msgid "_Close" +msgstr "S_chließen" #. Options -msgid "/_Options" -msgstr "/_Optionen" - -msgid "/Options/Enable _Logging" -msgstr "/Optionen/Schalte _Mitschnitt ein" - -msgid "/Options/Enable _Sounds" -msgstr "/Optionen/Schalte _Klänge ein" - -msgid "/Options/Show Formatting _Toolbars" -msgstr "/Optionen/Zeige _Werkzeugleisten für Formatierung" - -msgid "/Options/Show Ti_mestamps" -msgstr "/Optionen/Zeige _Zeitstempel" - -msgid "/Conversation/More" -msgstr "/Unterhaltung/Mehr" - -msgid "/Options" -msgstr "/Optionen" - -#. The menubar has been deactivated. Make sure the 'More' submenu is regenerated next time -#. * the 'Conversation' menu pops up. -#. Make sure the 'Conversation -> More' menuitems are regenerated whenever -#. * the 'Conversation' menu pops up because the entries can change after the -#. * conversation is created. -msgid "/Conversation" -msgstr "/Unterhaltung" - -msgid "/Conversation/View Log" -msgstr "/Unterhaltung/Mitschnitt anzeigen" - -msgid "/Conversation/Media/Audio Call" -msgstr "/Unterhaltung/Medien/Audio-Anruf" - -msgid "/Conversation/Media/Video Call" -msgstr "/Unterhaltung/Medien/Video-Anruf" - -msgid "/Conversation/Media/Audio\\/Video Call" -msgstr "/Unterhaltung/Medien/Audio-\\/Video-Anruf" - -msgid "/Conversation/Send File..." -msgstr "/Unterhaltung/Datei senden ..." - -msgid "/Conversation/Get Attention" -msgstr "/Unterhaltung/Aufmerksamkeit erregen" - -msgid "/Conversation/Add Buddy Pounce..." -msgstr "/Unterhaltung/Buddy-Alarm hinzufügen..." - -msgid "/Conversation/Get Info" -msgstr "/Unterhaltung/Info abrufen" - -msgid "/Conversation/Invite..." -msgstr "/Unterhaltung/Einladen ..." - -msgid "/Conversation/Alias..." -msgstr "/Unterhaltung/Alias..." - -msgid "/Conversation/Block..." -msgstr "/Unterhaltung/Blockieren..." - -msgid "/Conversation/Unblock..." -msgstr "/Unterhaltung/Entsperren..." - -msgid "/Conversation/Add..." -msgstr "/Unterhaltung/Hinzufügen..." - -msgid "/Conversation/Remove..." -msgstr "/Unterhaltung/Entfernen..." - -msgid "/Conversation/Insert Link..." -msgstr "/Unterhaltung/Link einfügen..." - -msgid "/Conversation/Insert Image..." -msgstr "/Unterhaltung/Bild einfügen..." - -msgid "/Options/Enable Logging" -msgstr "/Optionen/Schalte Mitschnitt ein" - -msgid "/Options/Enable Sounds" -msgstr "/Optionen/Schalte Klänge ein" - -msgid "/Options/Show Formatting Toolbars" -msgstr "/Optionen/Zeige Werkzeugleisten für Formatierung" - -msgid "/Options/Show Timestamps" -msgstr "/Optionen/Zeige Zeitstempel" +msgid "_Options" +msgstr "_Optionen" + +msgid "Enable _Logging" +msgstr "Schalte _Mitschnitt ein" + +msgid "Enable _Sounds" +msgstr "Schalte _Klänge ein" + +msgid "Show Formatting _Toolbars" +msgstr "Zeige _Werkzeugleisten für Formatierung" + +msgid "Show Ti_mestamps" +msgstr "Zeige _Zeitstempel" msgid "User is typing..." msgstr "Benutzer tippt gerade..." @@ -12019,6 +11887,9 @@ msgid "Serbian" msgstr "Serbisch" +msgid "Serbian Latin" +msgstr "Serbisch (Latin)" + msgid "Sinhala" msgstr "Singhalesisch" @@ -12049,6 +11920,9 @@ msgid "Vietnamese" msgstr "Vietnamesisch" +msgid "T.M.Thanh and the Gnome-Vi Team" +msgstr "T.M.Thanh und das Gnome-Vi Team" + msgid "Simplified Chinese" msgstr "Vereinfachtes Chinesisch" @@ -12064,62 +11938,52 @@ msgid "Lithuanian" msgstr "Litauisch" -msgid "T.M.Thanh and the Gnome-Vi Team" -msgstr "T.M.Thanh und das Gnome-Vi Team" - -#, c-format -msgid "" -"%s is a messaging client based on libpurple which is capable of connecting " -"to multiple messaging services at once. %s is written in C using GTK+. %s " -"is released, and may be modified and redistributed, under the terms of the " -"GPL version 2 (or later). A copy of the GPL is distributed with %s. %s is " -"copyrighted by its contributors, a list of whom is also distributed with " -"%s. There is no warranty for %s.

    " -msgstr "" -"%s ist ein Nachrichtendienst, basierend auf libpurple, der die Verbindung zu " -"mehreren Nachrichtendiensten gleichzeitig unterstützt. %s wird in C " +#, c-format +msgid "" +"

    %s is a messaging client based on libpurple which is capable of " +"connecting to multiple messaging services at once. %s is written in C using " +"GTK+. %s is released, and may be modified and redistributed, under the " +"terms of the GPL version 2 (or later). A copy of the GPL is distributed " +"with %s. %s is copyrighted by its contributors, a list of whom is also " +"distributed with %s. There is no warranty for %s.

    " +msgstr "" +"

    %s ist ein Nachrichtendienst, basierend auf libpurple, der die Verbindung " +"zu mehreren Nachrichtendiensten gleichzeitig unterstützt. %s wird in C " "programmiert und nutzt GTK+. %s ist nach den Bedingungen der GPL (Version 2 " "oder später) freigegeben und darf gemäß dieser bearbeitet und weiter " "verbreitet werden. Eine Kopie der GPL wird mit %s ausgeliefert. %s wird " -"von seinen Mitwirkenden urheberrechtlich geschützt. Eine komplette Liste " -"der Mitwirkenden wird mit %s ausgeliefert. Wir übernehmen keine Haftung für " -"%s.

    " - -#, c-format -msgid "" -"Helpful Resources
    \tWebsite
    \tFrequently Asked Questions
    \tIRC " -"Channel: #pidgin on irc.freenode.net
    \tXMPP MUC: devel@conference.pidgin." -"im

    " -msgstr "" -"Hilfreiche Quellen
    \tWebseite
    \tHäufig gestellte Fragen (FAQ)
    " -"\tIRC-Channel: #pidgin auf irc.freenode.net
    \tXMPP-MUC: devel@conference." -"pidgin.im

    " - -#, c-format -msgid "" -"Help from other Pidgin users is available by " -"e-mailing support@pidgin.im
    This is a public mailing list! (archive)
    We can't help with third-party protocols or " -"plugins!
    This list's primary language is English. You are " -"welcome to post in another language, but the responses may be less helpful." -"
    " -msgstr "" -"Hilfe von anderen Pidgin-Benutzern erhält man " -"per E-Mail an support@pidgin.im
    Dies ist eine öffentliche Mailing-Liste! (Archiv)
    Wir können nicht bei Problemen mit " -"Drittanbieter-Protokollen oder Plugins helfen!
    Die Hauptsprache dieser " -"Liste ist Englisch. Sie können gern in einer anderen Sprache " -"schreiben, aber die Antworten könnten weniger hilfreich sein.
    Deutschsprachige Benutzer können auch das Portal Pidgin-IM.de nutzen. Dort finden Sie aktuelle " -"Informationen zu Pidgin, können mit anderen Benutzern im Forum diskutieren und Hilfe zu Problemen finden. " -"Beachten Sie, dass dieses Portal unabhängig vom offiziellen Pidgin-Projekt " -"ist.

    " +"von seinen Mitwirkenden urheberrechtlich geschützt. Eine Liste der " +"Mitwirkenden wird auch mit %s ausgeliefert. Wir übernehmen keine Haftung " +"für %s.

    " + +#, c-format +msgid "" +"

    Helpful Resources

    " +msgstr "" +"

    Hilfreiche Quellen

    " + +#, c-format +msgid "" +"

    Help from other Pidgin users is available by e-mailing " +"%s.
    This is a public mailing " +"list! (archive)
    We can't help with third-" +"party protocols or plugins!
    This list's primary language is " +"English. You are welcome to post in another language, but " +"the responses may be less helpful.

    " +msgstr "" +"

    Hilfe von anderen Pidgin-Benutzern erhält man per E-Mail " +"an %s
    Dies ist eine öffentliche Mailing-Liste! (Archiv)
    Wir " +"können nicht bei Problemen mit Drittanbieter-Protokollen oder Plugins helfen!" +"
    Die Hauptsprache dieser Liste ist Englisch. Sie " +"können gern in einer anderen Sprache schreiben, aber die Antworten könnten " +"weniger hilfreich sein.

    " #, c-format msgid "About %s" @@ -12185,12 +12049,6 @@ msgid "View User Log" msgstr "Benutzer-Mitschnitt anzeigen" -msgid "Alias Contact" -msgstr "Kontakt-Alias" - -msgid "Enter an alias for this contact." -msgstr "Geben Sie einen Alias für diesen Kontakt ein." - #, c-format msgid "Enter an alias for %s." msgstr "Geben Sie einen Alias %s ein." @@ -12294,24 +12152,9 @@ msgid "New _Message..." msgstr "_Neue Nachricht..." -msgid "_Accounts" -msgstr "_Konten" - -msgid "Plu_gins" -msgstr "_Plugins" - -msgid "Pr_eferences" -msgstr "_Einstellungen" - -msgid "Mute _Sounds" -msgstr "Stu_mmschalten" - msgid "_Blink on New Message" msgstr "Be_i neuen Nachrichten blinken" -msgid "_Quit" -msgstr "_Beenden" - msgid "Not started" msgstr "Nicht gestartet" @@ -12795,6 +12638,9 @@ msgid "_Mute" msgstr "Stu_mmschalten" +msgid "Call in progress" +msgstr "Anruf im Gange" + #, c-format msgid "%s has %d new message." msgid_plural "%s has %d new messages." @@ -13017,6 +12863,9 @@ msgid "The default Pidgin buddy list theme" msgstr "Das Standard-Buddy-Listen-Thema für Pidgin" +msgid "The default Pidgin conversation theme" +msgstr "Das Standard-Thema für Pidgin-Unterhaltungen" + msgid "The default Pidgin status icon theme" msgstr "Das Standard-Status-Icon-Thema für Pidgin" @@ -13044,6 +12893,12 @@ msgid "Buddy List Theme:" msgstr "Buddy-Listen-Thema:" +msgid "Conversation Theme:" +msgstr "Unterhaltungs-Thema:" + +msgid "\tVariant:" +msgstr "\tVariante:" + msgid "Status Icon Theme:" msgstr "Status-Icon-Thema:" @@ -13640,12 +13495,6 @@ msgid "Status Selector" msgstr "Statusauswahl" -msgid "Google Talk" -msgstr "Google Talk" - -msgid "Facebook (XMPP)" -msgstr "Facebook (XMPP)" - #, c-format msgid "The following error has occurred loading %s: %s" msgstr "Beim Laden von %s ist folgender Fehler aufgetreten: %s" @@ -13780,18 +13629,12 @@ msgid "Close _tabs" msgstr "_Reiter schließen" -msgid "_Get Info" -msgstr "_Info abrufen" - msgid "_Invite" msgstr "_Einladen" msgid "_Modify..." msgstr "_Bearbeiten..." -msgid "_Add..." -msgstr "_Hinzufügen..." - msgid "_Open Mail" msgstr "Mail ö_ffnen" @@ -15149,21 +14992,327 @@ msgid "You do not have permission to uninstall this application." msgstr "Sie haben keine Berechtigung, diese Anwendung zu deinstallieren." -#~ msgid "No Sametime Community Server specified" -#~ msgstr "Kein Sametime-Community Server angegeben" - #~ msgid "" -#~ "No host or IP address has been configured for the Meanwhile account %s. " -#~ "Please enter one below to continue logging in." +#~ "Common name: %s %s\n" +#~ "Fingerprint (SHA1): %s" #~ msgstr "" -#~ "Es wurde kein Rechner für das Meanwhile-Konto %s angegeben. Bitte geben " -#~ "Sie einen Rechner an, um die Anmeldung fortzusetzen." - -#~ msgid "Meanwhile Connection Setup" -#~ msgstr "Meanwhile-Verbindungseinstellungen" - -#~ msgid "No Sametime Community Server Specified" -#~ msgstr "Kein Sametime-Community Server angegeben" - -#~ msgid "Connect" -#~ msgstr "Verbinden" +#~ "Allgemeiner Name (Common name:) %s %s\n" +#~ "Fingerabdruck (SHA1): %s" + +#~ msgid "_View Certificate..." +#~ msgstr "Ze_rtifikat ansehen..." + +#~ msgid "Orphans" +#~ msgstr "Waisen" + +#~ msgid "/Tools/Mute Sounds" +#~ msgstr "/Werkzeuge/Stummschalten" + +#~ msgid "/Buddies/New Instant _Message..." +#~ msgstr "/Buddys/_Neue Sofortnachricht..." + +#~ msgid "/Buddies/Join a _Chat..." +#~ msgstr "/Buddys/Einen _Chat betreten..." + +#~ msgid "/Buddies/Get User _Info..." +#~ msgstr "/Buddys/Benu_tzer-Info abrufen..." + +#~ msgid "/Buddies/View User _Log..." +#~ msgstr "/Buddys/Benutzer-_Mitschnitt ansehen..." + +#~ msgid "/Buddies/Sh_ow" +#~ msgstr "/Buddys/_Anzeigen" + +#~ msgid "/Buddies/Show/_Offline Buddies" +#~ msgstr "/Buddys/Anzeigen/_Offline-Buddys" + +#~ msgid "/Buddies/Show/_Empty Groups" +#~ msgstr "/Buddys/Anzeigen/_Leere Gruppen" + +#~ msgid "/Buddies/Show/Idle _Times" +#~ msgstr "/Buddys/Anzeigen/Untätigkeitszei_ten" + +#~ msgid "/Buddies/Show/_Protocol Icons" +#~ msgstr "/Buddys/Anzeigen/_Protokoll-Icons" + +#~ msgid "/Buddies/_Sort Buddies" +#~ msgstr "/Buddys/Buddys _sortieren" + +#~ msgid "/Buddies/_Add Buddy..." +#~ msgstr "/Buddys/B_uddy hinzufügen..." + +#~ msgid "/Buddies/Add C_hat..." +#~ msgstr "/Buddys/C_hat hinzufügen..." + +#~ msgid "/Buddies/Add _Group..." +#~ msgstr "/Buddys/_Gruppe hinzufügen..." + +#~ msgid "/Buddies/_Quit" +#~ msgstr "/Buddys/_Beenden" + +#~ msgid "/_Accounts" +#~ msgstr "/_Konten" + +#~ msgid "/Accounts/Manage Accounts" +#~ msgstr "/Konten/Konten verwalten" + +#~ msgid "/Tools/Buddy _Pounces" +#~ msgstr "/Werkzeuge/Buddy-_Alarm" + +#~ msgid "/Tools/_Certificates" +#~ msgstr "/Werkzeuge/_Zertifikate" + +#~ msgid "/Tools/Custom Smile_ys" +#~ msgstr "/Werkzeuge/Benutzerdefinierte Smile_ys" + +#~ msgid "/Tools/Plu_gins" +#~ msgstr "/Werkzeuge/Plu_gins" + +#~ msgid "/Tools/Pr_eferences" +#~ msgstr "/Werkzeuge/_Einstellungen" + +#~ msgid "/Tools/Pr_ivacy" +#~ msgstr "/Werkzeuge/Pri_vatsphäre" + +#~ msgid "/Tools/Set _Mood" +#~ msgstr "/Werkzeuge/Setze Sti_mmung" + +#~ msgid "/Tools/_File Transfers" +#~ msgstr "/Werkzeuge/_Dateiübertragungen" + +#~ msgid "/Tools/R_oom List" +#~ msgstr "/Werkzeuge/Chat_räume" + +#~ msgid "/Tools/System _Log" +#~ msgstr "/Werkzeuge/_Systemmitschnitt" + +#~ msgid "/Tools/Mute _Sounds" +#~ msgstr "/Werkzeuge/S_tummschalten" + +#~ msgid "/Help/_Build Information" +#~ msgstr "/Hilfe/_Build-Informationen" + +#~ msgid "/Help/_Debug Window" +#~ msgstr "/Hilfe/_Debug-Fenster" + +#~ msgid "/Help/De_veloper Information" +#~ msgstr "/Hilfe/_Entwickler-Informationen" + +#~ msgid "/Help/_Plugin Information" +#~ msgstr "/Hilfe/_Plugin-Informationen" + +#~ msgid "/Help/_Translator Information" +#~ msgstr "/Hilfe/Über_setzer-Informationen" + +#~ msgid "/Help/_About" +#~ msgstr "/Hilfe/Übe_r" + +#~ msgid "/Buddies/New Instant Message..." +#~ msgstr "/Buddys/Neue Sofortnachricht..." + +#~ msgid "/Buddies/Join a Chat..." +#~ msgstr "/Buddys/Chat betreten..." + +#~ msgid "/Buddies/Get User Info..." +#~ msgstr "/Buddys/Benutzer-Info abrufen..." + +#~ msgid "/Buddies/Add Buddy..." +#~ msgstr "/Buddys/Buddy hinzufügen..." + +#~ msgid "/Buddies/Add Chat..." +#~ msgstr "/Buddys/Chat hinzufügen..." + +#~ msgid "/Buddies/Add Group..." +#~ msgstr "/Buddys/Gruppe hinzufügen..." + +#~ msgid "/Tools/Privacy" +#~ msgstr "/Werkzeuge/Privatsphäre" + +#~ msgid "/Tools/Room List" +#~ msgstr "/Werkzeuge/Chaträume" + +#~ msgid "/Accounts" +#~ msgstr "/Konten" + +#~ msgid "/Buddies/Show/Offline Buddies" +#~ msgstr "/Buddys/Anzeigen/Offline-Buddys" + +#~ msgid "/Buddies/Show/Empty Groups" +#~ msgstr "/Buddys/Anzeigen/Leere Gruppen" + +#~ msgid "/Buddies/Show/Buddy Details" +#~ msgstr "/Buddys/Anzeigen/Buddy-Details" + +#~ msgid "/Buddies/Show/Idle Times" +#~ msgstr "/Buddys/Anzeigen/Untätigkeitszeiten" + +#~ msgid "/Buddies/Show/Protocol Icons" +#~ msgstr "/Buddys/Anzeigen/Protokoll-Icons" + +#~ msgid "/Accounts/Enable Account" +#~ msgstr "/Konten/Konto aktivieren" + +#~ msgid "/Accounts/" +#~ msgstr "/Konten/" + +#~ msgid "/Tools" +#~ msgstr "/Werkzeuge" + +#~ msgid "/Buddies/Sort Buddies" +#~ msgstr "/Buddys/Buddys sortieren" + +#~ msgid "/Conversation/New Instant _Message..." +#~ msgstr "/Unterhaltung/_Neue Sofortnachricht..." + +#~ msgid "/Conversation/Join a _Chat..." +#~ msgstr "/Unterhaltung/Einen Cha_t betreten..." + +#~ msgid "/Conversation/_Find..." +#~ msgstr "/Unterhaltung/_Finden..." + +#~ msgid "/Conversation/View _Log" +#~ msgstr "/Unterhaltung/_Mitschnitt anzeigen" + +#~ msgid "/Conversation/_Save As..." +#~ msgstr "/Unterhaltung/S_peichern als..." + +#~ msgid "/Conversation/Clea_r Scrollback" +#~ msgstr "/Unterhaltung/_Leeren" + +#~ msgid "/Conversation/M_edia" +#~ msgstr "/Unterhaltung/M_edien" + +#~ msgid "/Conversation/Media/_Audio Call" +#~ msgstr "/Unterhaltung/Medien/_Audio-Anruf" + +#~ msgid "/Conversation/Media/_Video Call" +#~ msgstr "/Unterhaltung/Medien/_Video-Anruf" + +#~ msgid "/Conversation/Media/Audio\\/Video _Call" +#~ msgstr "/Unterhaltung/Medien/A_udio-\\/Video-Anruf" + +#~ msgid "/Conversation/Se_nd File..." +#~ msgstr "/Unterhaltung/Datei _senden..." + +#~ msgid "/Conversation/Get _Attention" +#~ msgstr "/Unterhaltung/_Aufmerksamkeit erregen" + +#~ msgid "/Conversation/Add Buddy _Pounce..." +#~ msgstr "/Unterhaltung/_Buddy-Alarm hinzufügen..." + +#~ msgid "/Conversation/_Get Info" +#~ msgstr "/Unterhaltung/_Info abrufen" + +#~ msgid "/Conversation/In_vite..." +#~ msgstr "/Unterhaltung/_Einladen..." + +#~ msgid "/Conversation/M_ore" +#~ msgstr "/Unterhaltung/Me_hr" + +#~ msgid "/Conversation/Al_ias..." +#~ msgstr "/Unterhaltung/Al_ias..." + +#~ msgid "/Conversation/_Block..." +#~ msgstr "/Unterhaltung/_Blockieren..." + +#~ msgid "/Conversation/_Unblock..." +#~ msgstr "/Unterhaltung/_Entsperren..." + +#~ msgid "/Conversation/_Add..." +#~ msgstr "/Unterhaltung/_Hinzufügen..." + +#~ msgid "/Conversation/_Remove..." +#~ msgstr "/Unterhaltung/_Entfernen..." + +#~ msgid "/Conversation/Insert Lin_k..." +#~ msgstr "/Unterhaltung/Lin_k einfügen..." + +#~ msgid "/Conversation/Insert Imag_e..." +#~ msgstr "/Unterhaltung/Bil_d einfügen..." + +#~ msgid "/Conversation/_Close" +#~ msgstr "/Unterhaltung/S_chließen" + +#~ msgid "/Options/Enable _Logging" +#~ msgstr "/Optionen/Schalte _Mitschnitt ein" + +#~ msgid "/Options/Enable _Sounds" +#~ msgstr "/Optionen/Schalte _Klänge ein" + +#~ msgid "/Options/Show Ti_mestamps" +#~ msgstr "/Optionen/Zeige _Zeitstempel" + +#~ msgid "/Conversation/More" +#~ msgstr "/Unterhaltung/Mehr" + +#~ msgid "/Options" +#~ msgstr "/Optionen" + +#~ msgid "/Conversation" +#~ msgstr "/Unterhaltung" + +#~ msgid "/Conversation/View Log" +#~ msgstr "/Unterhaltung/Mitschnitt anzeigen" + +#~ msgid "/Conversation/Media/Audio Call" +#~ msgstr "/Unterhaltung/Medien/Audio-Anruf" + +#~ msgid "/Conversation/Media/Video Call" +#~ msgstr "/Unterhaltung/Medien/Video-Anruf" + +#~ msgid "/Conversation/Media/Audio\\/Video Call" +#~ msgstr "/Unterhaltung/Medien/Audio-\\/Video-Anruf" + +#~ msgid "/Conversation/Send File..." +#~ msgstr "/Unterhaltung/Datei senden ..." + +#~ msgid "/Conversation/Get Attention" +#~ msgstr "/Unterhaltung/Aufmerksamkeit erregen" + +#~ msgid "/Conversation/Add Buddy Pounce..." +#~ msgstr "/Unterhaltung/Buddy-Alarm hinzufügen..." + +#~ msgid "/Conversation/Get Info" +#~ msgstr "/Unterhaltung/Info abrufen" + +#~ msgid "/Conversation/Invite..." +#~ msgstr "/Unterhaltung/Einladen ..." + +#~ msgid "/Conversation/Alias..." +#~ msgstr "/Unterhaltung/Alias..." + +#~ msgid "/Conversation/Block..." +#~ msgstr "/Unterhaltung/Blockieren..." + +#~ msgid "/Conversation/Unblock..." +#~ msgstr "/Unterhaltung/Entsperren..." + +#~ msgid "/Conversation/Add..." +#~ msgstr "/Unterhaltung/Hinzufügen..." + +#~ msgid "/Conversation/Remove..." +#~ msgstr "/Unterhaltung/Entfernen..." + +#~ msgid "/Conversation/Insert Link..." +#~ msgstr "/Unterhaltung/Link einfügen..." + +#~ msgid "/Conversation/Insert Image..." +#~ msgstr "/Unterhaltung/Bild einfügen..." + +#~ msgid "/Options/Enable Logging" +#~ msgstr "/Optionen/Schalte Mitschnitt ein" + +#~ msgid "/Options/Enable Sounds" +#~ msgstr "/Optionen/Schalte Klänge ein" + +#~ msgid "/Options/Show Formatting Toolbars" +#~ msgstr "/Optionen/Zeige Werkzeugleisten für Formatierung" + +#~ msgid "/Options/Show Timestamps" +#~ msgstr "/Optionen/Zeige Zeitstempel" + +#~ msgid "Google Talk" +#~ msgstr "Google Talk" + +#~ msgid "Facebook (XMPP)" +#~ msgstr "Facebook (XMPP)" diff -r 2908b16efa07 -r f01d6c9f3492 po/es.po diff -r 2908b16efa07 -r f01d6c9f3492 po/ru.po diff -r 2908b16efa07 -r f01d6c9f3492 po/sl.po