Sun, 18 Aug 2013 01:53:00 +0530
Merged soc.2013.gobjectification branch
| libpurple/connection.h | file | annotate | diff | comparison | revisions |
--- a/Doxyfile.in Sun Aug 18 01:52:32 2013 +0530 +++ b/Doxyfile.in Sun Aug 18 01:53:00 2013 +0530 @@ -1381,7 +1381,7 @@ # undefined via #undef or recursively expanded use the := operator # instead of the = operator. -PREDEFINED = +PREDEFINED = "@PLUGINS_MACRO@" # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded.
--- a/acinclude.m4 Sun Aug 18 01:52:32 2013 +0530 +++ b/acinclude.m4 Sun Aug 18 01:53:00 2013 +0530 @@ -6,7 +6,7 @@ # Owen Taylor 1997-2001 dnl AM_PATH_GLIB_2_0([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) -dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if gmodule, gobject or +dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if gobject or dnl gthread is specified in MODULES, pass to pkg-config dnl AC_DEFUN([AM_PATH_GLIB_2_0], @@ -20,9 +20,6 @@ for module in . $4 do case "$module" in - gmodule) - pkg_config_args="$pkg_config_args gmodule-2.0" - ;; gobject) pkg_config_args="$pkg_config_args gobject-2.0" ;;
--- a/configure.ac Sun Aug 18 01:52:32 2013 +0530 +++ b/configure.ac Sun Aug 18 01:53:00 2013 +0530 @@ -335,10 +335,7 @@ dnl ####################################################################### dnl # Check for GLib 2.20 (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.20.0 gobject-2.0 gmodule-2.0 gthread-2.0], , [ +PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.20.0 gobject-2.0 gthread-2.0], , [ AC_MSG_RESULT(no) AC_MSG_ERROR([ @@ -1282,7 +1279,7 @@ AC_ARG_ENABLE(distrib,,,enable_distrib=no) AM_CONDITIONAL(DISTRIB, test "x$enable_distrib" = "xyes") DYNAMIC_PRPLS=all -AC_ARG_WITH(static-prpls, [AS_HELP_STRING([--with-static-prpls], [Link to certain protocols statically])], [STATIC_PRPLS=`echo $withval | $sedpath 's/,/ /g'`], [STATIC_PRPLS=""]) +AC_ARG_WITH(static-prpls, [AS_HELP_STRING([--with-static-protocols], [Link to certain protocols statically])], [STATIC_PRPLS=`echo $withval | $sedpath 's/,/ /g'`], [STATIC_PRPLS=""]) if test "x$STATIC_PRPLS" != "x" -a "x$DYNAMIC_PRPLS" = "xall"; then DYNAMIC_PRPLS="" fi @@ -1301,31 +1298,43 @@ fi AC_SUBST(STATIC_PRPLS) STATIC_LINK_LIBS= -extern_init= +extern_load= load_proto= +extern_unload= +unload_proto= for i in $STATIC_PRPLS ; do dnl Ugly special case for "libsilcpurple.la": dnl ... and Ugly special case for multi-protocol oscar and yahoo if test \( "x$i" = "xoscar" -o "x$i" = "xaim" -o "x$i" = "xicq" \) -a "x$static_oscar" != "xyes"; then STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/oscar/liboscar.la" - extern_init="$extern_init extern gboolean purple_init_aim_plugin();" - extern_init="$extern_init extern gboolean purple_init_icq_plugin();" - load_proto="$load_proto purple_init_aim_plugin();" - load_proto="$load_proto purple_init_icq_plugin();" + extern_load="$extern_load extern gboolean aim_plugin_load();" + extern_load="$extern_load extern gboolean icq_plugin_load();" + load_proto="$load_proto aim_plugin_load();" + load_proto="$load_proto icq_plugin_load();" + extern_unload="$extern_unload extern gboolean aim_plugin_unload();" + extern_unload="$extern_unload extern gboolean icq_plugin_unload();" + unload_proto="$unload_proto aim_plugin_unload();" + unload_proto="$unload_proto icq_plugin_unload();" elif test "x$i" = "xyahoo"; then STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/yahoo/libymsg.la" - extern_init="$extern_init extern gboolean purple_init_yahoo_plugin();" - extern_init="$extern_init extern gboolean purple_init_yahoojp_plugin();" - load_proto="$load_proto purple_init_yahoo_plugin();" - load_proto="$load_proto purple_init_yahoojp_plugin();" + extern_load="$extern_load extern gboolean yahoo_plugin_load();" + extern_load="$extern_load extern gboolean yahoojp_plugin_load();" + load_proto="$load_proto yahoo_plugin_load();" + load_proto="$load_proto yahoojp_plugin_load();" + extern_unload="$extern_unload extern gboolean yahoo_plugin_unload();" + extern_unload="$extern_unload extern gboolean yahoojp_plugin_unload();" + unload_proto="$unload_proto yahoo_plugin_unload();" + unload_proto="$unload_proto yahoojp_plugin_unload();" else if test "x$i" = "xsilc"; then STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib${i}purple.la" else STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib$i.la" fi - extern_init="$extern_init extern gboolean purple_init_${i}_plugin();" - load_proto="$load_proto purple_init_${i}_plugin();" + extern_load="$extern_load extern gboolean ${i}_plugin_load();" + load_proto="$load_proto ${i}_plugin_load();" + extern_unload="$extern_unload extern gboolean ${i}_plugin_unload();" + unload_proto="$unload_proto ${i}_plugin_unload();" fi case $i in bonjour) static_bonjour=yes ;; @@ -1362,10 +1371,12 @@ AM_CONDITIONAL(STATIC_YAHOO, test "x$static_yahoo" = "xyes") AM_CONDITIONAL(STATIC_ZEPHYR, test "x$static_zephyr" = "xyes") AC_SUBST(STATIC_LINK_LIBS) -AC_DEFINE_UNQUOTED(STATIC_PROTO_INIT, $extern_init static void static_proto_init(void) { $load_proto }, - [Loads static protocol plugin module initialization functions.]) +AC_DEFINE_UNQUOTED(STATIC_PROTO_LOAD, $extern_load static void static_proto_load(void) { $load_proto }, + [Loads protocols from static protocol plugin modules.]) +AC_DEFINE_UNQUOTED(STATIC_PROTO_UNLOAD, $extern_unload static void static_proto_unload(void) { $unload_proto }, + [Unloads protocols from static protocol plugin modules.]) -AC_ARG_WITH(dynamic_prpls, [AS_HELP_STRING([--with-dynamic-prpls], [specify which protocols to build dynamically])], [DYNAMIC_PRPLS=`echo $withval | $sedpath 's/,/ /g'`]) +AC_ARG_WITH(dynamic_prpls, [AS_HELP_STRING([--with-dynamic-protocols], [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 mxit myspace novell oscar sametime silc simple yahoo zephyr" fi @@ -1707,6 +1718,22 @@ AM_CONDITIONAL(ENABLE_KWALLET, test "x$enable_kwallet" = "xyes") dnl ####################################################################### +dnl # Check for GPlugin 0.0.5 +dnl ####################################################################### +if test "x$enable_plugins" = "xyes" ; then + PKG_CHECK_MODULES(GPLUGIN, [gplugin >= 0.0.5 gmodule-2.0], , [ + AC_MSG_RESULT(no) + AC_MSG_ERROR([ + GPlugin 0.0.5 development headers not found, which are required if you wish to + enable plugins. + Use --disable-plugins if you want to disable plugins (will also disable + protocols). + ])]) + AC_SUBST(GPLUGIN_CFLAGS) + AC_SUBST(GPLUGIN_LIBS) +fi + +dnl ####################################################################### dnl # Check for Python dnl ####################################################################### @@ -2611,11 +2638,13 @@ AC_DEFINE(PURPLE_PLUGINS, 1, [Define if plugins are enabled.]) AM_CONDITIONAL(PLUGINS, true) PLUGINS_DEFINE="#define PURPLE_PLUGINS 1" + PLUGINS_MACRO="PURPLE_PLUGINS" else AM_CONDITIONAL(PLUGINS, false) PLUGINS_DEFINE="#undef PURPLE_PLUGINS" fi AC_SUBST(PLUGINS_DEFINE) +AC_SUBST(PLUGINS_MACRO) dnl ####################################################################### dnl # Check for Cyrus-SASL (for xmpp/irc)
--- a/doc/C-HOWTO.dox Sun Aug 18 01:52:32 2013 +0530 +++ b/doc/C-HOWTO.dox Sun Aug 18 01:53:00 2013 +0530 @@ -26,7 +26,7 @@ #include <glib.h> #include "notify.h" -#include "plugin.h" +#include "plugins.h" #include "version.h" static gboolean @@ -83,7 +83,7 @@ like described before. Next we include glib.h, mainly for gboolean and the glib wrappers of the standard C types. - Next, we include plugin.h which has all the plugin specific stuff that we + Next, we include plugins.h which has all the plugin specific stuff that we need. For example: @c PurplePlugin, @c PurplePluginInfo, @c PURPLE_PLUGIN_MAGIC, and @c PURPLE_INIT_PLUGIN().
--- a/doc/plugin-signals.dox Sun Aug 18 01:52:32 2013 +0530 +++ b/doc/plugin-signals.dox Sun Aug 18 01:53:00 2013 +0530 @@ -5,7 +5,7 @@ @signal plugin-unload @endsignals - @see plugin.h + @see plugins.h <hr>
--- a/finch/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/finch/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -72,6 +72,7 @@ $(DBUS_LIBS) \ $(INTLLIBS) \ $(GLIB_LIBS) \ + $(GPLUGIN_LIBS) \ $(LIBXML_LIBS) \ $(GNT_LIBS) \ $(GSTREAMER_LIBS) \ @@ -89,6 +90,7 @@ -I$(srcdir)/libgnt/ \ $(DEBUG_CFLAGS) \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(DBUS_CFLAGS) \ $(LIBXML_CFLAGS) \ $(GSTREAMER_CFLAGS) \
--- a/finch/finch.c Sun Aug 18 01:52:32 2013 +0530 +++ b/finch/finch.c Sun Aug 18 01:53:00 2013 +0530 @@ -30,8 +30,8 @@ #include "ft.h" #include "log.h" #include "notify.h" -#include "prefs.h" -#include "prpl.h" +#include "plugins.h" +#include "protocol.h" #include "pounce.h" #include "savedstatuses.h" #include "sound.h" @@ -361,6 +361,14 @@ purple_eventloop_set_ui_ops(gnt_eventloop_get_ui_ops()); purple_idle_set_ui_ops(finch_idle_get_ui_ops()); + if (!purple_core_init(FINCH_UI)) + { + fprintf(stderr, + "Initialization of the Purple core failed. Dumping core.\n" + "Please report this!\n"); + abort(); + } + path = g_build_filename(purple_user_dir(), "plugins", NULL); if (!g_stat(path, &st)) g_mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR); @@ -368,14 +376,7 @@ g_free(path); purple_plugins_add_search_path(LIBDIR); - - if (!purple_core_init(FINCH_UI)) - { - fprintf(stderr, - "Initialization of the Purple core failed. Dumping core.\n" - "Please report this!\n"); - abort(); - } + purple_plugins_refresh(); /* TODO: should this be moved into finch_prefs_init() ? */ finch_prefs_update_old();
--- a/finch/gntaccount.c Sun Aug 18 01:52:32 2013 +0530 +++ b/finch/gntaccount.c Sun Aug 18 01:53:00 2013 +0530 @@ -43,7 +43,7 @@ #include <accountopt.h> #include <connection.h> #include <notify.h> -#include <plugin.h> +#include <plugins.h> #include <request.h> #include <savedstatuses.h> @@ -74,7 +74,7 @@ GntWidget *splits; GList *split_entries; - GList *prpl_entries; + GList *protocol_entries; GntWidget *prpls; GntWidget *newmail; @@ -101,7 +101,7 @@ edit_dialog_destroy(AccountEditDialog *dialog) { accountdialogs = g_list_remove(accountdialogs, dialog); - g_list_free(dialog->prpl_entries); + g_list_free(dialog->protocol_entries); g_list_free(dialog->split_entries); g_free(dialog); } @@ -110,15 +110,13 @@ save_account_cb(AccountEditDialog *dialog) { PurpleAccount *account; - PurplePlugin *plugin; - PurplePluginProtocolInfo *prplinfo; + PurpleProtocol *protocol; const char *value; GString *username; /* XXX: Do some error checking first. */ - plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol)); - prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); + protocol = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol)); /* Username && user-splits */ value = gnt_entry_get_text(GNT_ENTRY(dialog->username)); @@ -133,10 +131,10 @@ username = g_string_new(value); - if (prplinfo != NULL) + if (protocol != NULL) { GList *iter, *entries; - for (iter = prplinfo->user_splits, entries = dialog->split_entries; + for (iter = protocol->user_splits, entries = dialog->split_entries; iter && entries; iter = iter->next, entries = entries->next) { PurpleAccountUserSplit *split = iter->data; @@ -153,7 +151,7 @@ if (dialog->account == NULL) { - account = purple_account_new(username->str, purple_plugin_get_id(plugin)); + account = purple_account_new(username->str, protocol->id); purple_accounts_add(account); } else @@ -162,12 +160,12 @@ /* Protocol */ if (purple_account_is_disconnected(account)) { - purple_account_set_protocol_id(account, purple_plugin_get_id(plugin)); + purple_account_set_protocol_id(account, protocol->id); purple_account_set_username(account, username->str); } else { const char *old = purple_account_get_protocol_id(account); char *oldprpl; - if (strcmp(old, purple_plugin_get_id(plugin))) { + if (strcmp(old, protocol->id)) { purple_notify_error(NULL, _("Error"), _("Account was not modified"), _("The account's protocol cannot be changed while it is connected to the server.")); return; @@ -204,11 +202,11 @@ gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->newmail))); /* Protocol options */ - if (prplinfo) + if (protocol) { GList *iter, *entries; - for (iter = prplinfo->protocol_options, entries = dialog->prpl_entries; + for (iter = protocol->protocol_options, entries = dialog->protocol_entries; iter && entries; iter = iter->next, entries = entries->next) { PurpleAccountOption *option = iter->data; @@ -253,7 +251,7 @@ gnt_box_give_focus_to_child(GNT_BOX(accounts.window), accounts.tree); } - if (prplinfo && prplinfo->register_user && + if (protocol && protocol->register_user && gnt_check_box_get_checked(GNT_CHECK_BOX(dialog->regserver))) { purple_account_register(account); } else if (dialog->account == NULL) { @@ -285,8 +283,7 @@ update_user_splits(AccountEditDialog *dialog) { GntWidget *hbox; - PurplePlugin *plugin; - PurplePluginProtocolInfo *prplinfo; + PurpleProtocol *protocol; GList *iter, *entries; char *username = NULL; @@ -304,14 +301,13 @@ dialog->split_entries = NULL; - plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol)); - if (!plugin) + protocol = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol)); + if (!protocol) return; - prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); username = dialog->account ? g_strdup(purple_account_get_username(dialog->account)) : NULL; - for (iter = prplinfo->user_splits; iter; iter = iter->next) + for (iter = protocol->user_splits; iter; iter = iter->next) { PurpleAccountUserSplit *split = iter->data; GntWidget *entry; @@ -330,7 +326,7 @@ g_free(buf); } - for (iter = g_list_last(prplinfo->user_splits), entries = g_list_last(dialog->split_entries); + for (iter = g_list_last(protocol->user_splits), entries = g_list_last(dialog->split_entries); iter && entries; iter = iter->prev, entries = entries->prev) { GntWidget *entry = entries->data; @@ -368,8 +364,7 @@ static void add_protocol_options(AccountEditDialog *dialog) { - PurplePlugin *plugin; - PurplePluginProtocolInfo *prplinfo; + PurpleProtocol *protocol; GList *iter; GntWidget *vbox, *box; PurpleAccount *account; @@ -384,23 +379,21 @@ gnt_box_set_fill(GNT_BOX(vbox), TRUE); } - if (dialog->prpl_entries) + if (dialog->protocol_entries) { - g_list_free(dialog->prpl_entries); - dialog->prpl_entries = NULL; + g_list_free(dialog->protocol_entries); + dialog->protocol_entries = NULL; } vbox = dialog->prpls; - plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol)); - if (!plugin) + protocol = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol)); + if (!protocol) return; - prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); - account = dialog->account; - for (iter = prplinfo->protocol_options; iter; iter = iter->next) + for (iter = protocol->protocol_options; iter; iter = iter->next) { PurpleAccountOption *option = iter->data; PurplePrefType type = purple_account_option_get_type(option); @@ -413,7 +406,7 @@ { GntWidget *widget = gnt_check_box_new(purple_account_option_get_text(option)); gnt_box_add_widget(GNT_BOX(box), widget); - dialog->prpl_entries = g_list_append(dialog->prpl_entries, widget); + dialog->protocol_entries = g_list_append(dialog->protocol_entries, widget); if (account) gnt_check_box_set_checked(GNT_CHECK_BOX(widget), @@ -441,7 +434,7 @@ purple_account_option_get_setting(option), dv); gnt_box_add_widget(GNT_BOX(box), combo); - dialog->prpl_entries = g_list_append(dialog->prpl_entries, combo); + dialog->protocol_entries = g_list_append(dialog->protocol_entries, combo); for ( ; opt_iter; opt_iter = opt_iter->next) { @@ -456,7 +449,7 @@ { GntWidget *entry = gnt_entry_new(NULL); gnt_box_add_widget(GNT_BOX(box), entry); - dialog->prpl_entries = g_list_append(dialog->prpl_entries, entry); + dialog->protocol_entries = g_list_append(dialog->protocol_entries, entry); if (type == PURPLE_PREF_STRING) { @@ -491,27 +484,24 @@ /* Show the registration checkbox only in a new account dialog, * and when the selected prpl has the support for it. */ gnt_widget_set_visible(dialog->regserver, account == NULL && - prplinfo->register_user != NULL); + protocol->register_user != NULL); } static void update_user_options(AccountEditDialog *dialog) { - PurplePlugin *plugin; - PurplePluginProtocolInfo *prplinfo; + PurpleProtocol *protocol; - plugin = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol)); - if (!plugin) + protocol = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(dialog->protocol)); + if (!protocol) return; - prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); - if (dialog->newmail == NULL) dialog->newmail = gnt_check_box_new(_("New mail notifications")); if (dialog->account) gnt_check_box_set_checked(GNT_CHECK_BOX(dialog->newmail), purple_account_get_check_mail(dialog->account)); - if (!prplinfo || !(prplinfo->options & OPT_PROTO_MAIL_CHECK)) + if (!protocol || !(protocol->options & OPT_PROTO_MAIL_CHECK)) gnt_widget_set_visible(dialog->newmail, FALSE); else gnt_widget_set_visible(dialog->newmail, TRUE); @@ -524,7 +514,7 @@ } static void -prpl_changed_cb(GntWidget *combo, PurplePlugin *old, PurplePlugin *new, AccountEditDialog *dialog) +protocol_changed_cb(GntWidget *combo, PurpleProtocol *old, PurpleProtocol *new, AccountEditDialog *dialog) { update_user_splits(dialog); add_protocol_options(dialog); @@ -541,7 +531,7 @@ GntWidget *combo, *button, *entry; GList *list, *iter; AccountEditDialog *dialog; - PurplePlugin *plugin; + PurpleProtocol *protocol; if (account) { @@ -554,10 +544,10 @@ } } - list = purple_plugins_get_protocols(); + list = purple_protocols_get_all(); if (list == NULL) { purple_notify_error(NULL, _("Error"), - _("There are no protocol plugins installed."), + _("There are no protocols installed."), _("(You probably forgot to 'make install'.)")); return; } @@ -582,17 +572,17 @@ for (iter = list; iter; iter = iter->next) { gnt_combo_box_add_data(GNT_COMBO_BOX(combo), iter->data, - ((PurplePlugin*)iter->data)->info->name); + ((PurpleProtocol*)iter->data)->name); } - plugin = purple_plugins_find_with_id(purple_account_get_protocol_id(account)); + protocol = purple_find_protocol_info(purple_account_get_protocol_id(account)); - if (account && plugin) - gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), plugin); + if (account && protocol) + gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), protocol); else gnt_combo_box_set_selected(GNT_COMBO_BOX(combo), list->data); - g_signal_connect(G_OBJECT(combo), "selection-changed", G_CALLBACK(prpl_changed_cb), dialog); + g_signal_connect(G_OBJECT(combo), "selection-changed", G_CALLBACK(protocol_changed_cb), dialog); gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Protocol:"))); gnt_box_add_widget(GNT_BOX(hbox), combo);
--- a/finch/gntblist.c Sun Aug 18 01:52:32 2013 +0530 +++ b/finch/gntblist.c Sun Aug 18 01:53:00 2013 +0530 @@ -31,6 +31,7 @@ #include <log.h> #include <notify.h> #include <request.h> +#include <plugins.h> #include <savedstatuses.h> #include <server.h> #include <signal.h> @@ -726,7 +727,7 @@ GHashTable *hash = NULL; PurpleConnection *gc; gboolean autojoin; - PurplePluginProtocolInfo *info; + PurpleProtocol *protocol; account = purple_request_fields_get_account(allfields, "account"); name = purple_request_fields_get_string(allfields, "name"); @@ -741,9 +742,9 @@ group = _("Chats"); gc = purple_account_get_connection(account); - info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - if (info->chat_info_defaults != NULL) - hash = info->chat_info_defaults(gc, name); + protocol = purple_connection_get_protocol_info(gc); + if (protocol->chat_info_defaults != NULL) + hash = protocol->chat_info_defaults(gc, name); chat = purple_chat_new(account, name, hash); @@ -1061,12 +1062,12 @@ append_proto_menu(GntMenu *menu, PurpleConnection *gc, PurpleBlistNode *node) { GList *list; - PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - - if(!prpl_info || !prpl_info->blist_node_menu) + PurpleProtocol *protocol = purple_connection_get_protocol_info(gc); + + if(!protocol || !protocol->blist_node_menu) return; - for(list = prpl_info->blist_node_menu(node); list; + for(list = protocol->blist_node_menu(node); list; list = g_list_delete_link(list, list)) { PurpleMenuAction *act = (PurpleMenuAction *) list->data; @@ -1125,7 +1126,7 @@ purple_request_fields_add_group(fields, group); gc = purple_account_get_connection(purple_chat_get_account(chat)); - parts = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->chat_info(gc); + parts = purple_connection_get_protocol_info(gc)->chat_info(gc); for (iter = parts; iter; iter = iter->next) { pce = iter->data; @@ -1273,11 +1274,11 @@ PurpleAccount *account; gboolean permitted; GntMenuItem *item; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(buddy)); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - if (prpl_info && prpl_info->get_info) + protocol = purple_connection_get_protocol_info(gc); + if (protocol && protocol->get_info) { add_custom_action(menu, _("Get Info"), PURPLE_CALLBACK(finch_blist_get_buddy_info_cb), buddy); @@ -1286,10 +1287,10 @@ add_custom_action(menu, _("Add Buddy Pounce"), PURPLE_CALLBACK(finch_blist_pounce_node_cb), buddy); - if (prpl_info && prpl_info->send_file) + if (protocol && protocol->send_file) { - if (!prpl_info->can_receive_file || - prpl_info->can_receive_file(gc, purple_buddy_get_name(buddy))) + if (!protocol->can_receive_file || + protocol->can_receive_file(gc, purple_buddy_get_name(buddy))) add_custom_action(menu, _("Send File"), PURPLE_CALLBACK(finch_blist_menu_send_file_cb), buddy); } @@ -1411,12 +1412,12 @@ account = purple_buddy_get_account(b); } else if (PURPLE_IS_CHAT(node)) { PurpleChat *c = (PurpleChat*) node; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; type = PURPLE_LOG_CHAT; account = purple_chat_get_account(c); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account))); - if (prpl_info && prpl_info->get_chat_name) { - name = prpl_info->get_chat_name(purple_chat_get_components(c)); + protocol = purple_find_protocol_info(purple_account_get_protocol_id(account)); + if (protocol && protocol->get_chat_name) { + name = protocol->get_chat_name(purple_chat_get_components(c)); } } else if (PURPLE_IS_CONTACT(node)) { finch_log_show_contact((PurpleContact *)node); @@ -1714,8 +1715,7 @@ static void tooltip_for_buddy(PurpleBuddy *buddy, GString *str, gboolean full) { - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; PurpleAccount *account; PurpleNotifyUserInfo *user_info; PurplePresence *presence; @@ -1737,10 +1737,9 @@ purple_notify_user_info_add_pair_plaintext(user_info, _("Account"), tmp); g_free(tmp); - prpl = purple_find_prpl(purple_account_get_protocol_id(account)); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (prpl_info && prpl_info->tooltip_text) { - prpl_info->tooltip_text(buddy, user_info, full); + protocol = purple_find_protocol_info(purple_account_get_protocol_id(account)); + if (protocol && protocol->tooltip_text) { + protocol->tooltip_text(buddy, user_info, full); } if (purple_prefs_get_bool("/finch/blist/idletime")) { @@ -2452,25 +2451,60 @@ } static void -build_plugin_actions(GntMenuItem *item, PurplePlugin *plugin, gpointer context) +build_plugin_actions(GntMenuItem *item, PurplePlugin *plugin) +{ + GntWidget *sub = gnt_menu_new(GNT_MENU_POPUP); + PurplePluginGetActionsCallback get_actions; + GList *actions; + GntMenuItem *menuitem; + + get_actions = + purple_plugin_info_get_actions_callback(purple_plugin_get_info(plugin)); + + gnt_menuitem_set_submenu(item, GNT_MENU(sub)); + for (actions = get_actions(plugin); actions; + actions = g_list_delete_link(actions, actions)) { + if (actions->data) { + PurplePluginAction *action = actions->data; + action->plugin = plugin; + menuitem = gnt_menuitem_new(action->label); + gnt_menu_add_item(GNT_MENU(sub), menuitem); + + gnt_menuitem_set_callback(menuitem, plugin_action, action); + g_object_set_data_full(G_OBJECT(menuitem), "plugin_action", + action, (GDestroyNotify)purple_plugin_action_free); + } + } +} + +static void +protocol_action(GntMenuItem *item, gpointer data) +{ + PurpleProtocolAction *action = data; + if (action && action->callback) + action->callback(action); +} + +static void +build_protocol_actions(GntMenuItem *item, PurpleProtocol *protocol, + PurpleConnection *gc) { GntWidget *sub = gnt_menu_new(GNT_MENU_POPUP); GList *actions; GntMenuItem *menuitem; gnt_menuitem_set_submenu(item, GNT_MENU(sub)); - for (actions = PURPLE_PLUGIN_ACTIONS(plugin, context); actions; + for (actions = protocol->get_actions(gc); actions; actions = g_list_delete_link(actions, actions)) { if (actions->data) { - PurplePluginAction *action = actions->data; - action->plugin = plugin; - action->context = context; + PurpleProtocolAction *action = actions->data; + action->connection = gc; menuitem = gnt_menuitem_new(action->label); gnt_menu_add_item(GNT_MENU(sub), menuitem); - gnt_menuitem_set_callback(menuitem, plugin_action, action); - g_object_set_data_full(G_OBJECT(menuitem), "plugin_action", - action, (GDestroyNotify)purple_plugin_action_free); + gnt_menuitem_set_callback(menuitem, protocol_action, action); + g_object_set_data_full(G_OBJECT(menuitem), "protocol_action", + action, (GDestroyNotify)purple_protocol_action_free); } } } @@ -2540,16 +2574,15 @@ for (iter = purple_plugins_get_loaded(); iter; iter = iter->next) { PurplePlugin *plugin = iter->data; + PurplePluginInfo *info = purple_plugin_get_info(plugin); GntMenuItem *item; - if (PURPLE_IS_PROTOCOL_PLUGIN(plugin)) + + if (!purple_plugin_info_get_actions_callback(info)) continue; - if (!PURPLE_PLUGIN_HAS_ACTIONS(plugin)) - continue; - - item = gnt_menuitem_new(_(plugin->info->name)); + item = gnt_menuitem_new(_(purple_plugin_info_get_name(info))); gnt_menu_add_item(GNT_MENU(sub), item); - build_plugin_actions(item, plugin, NULL); + build_plugin_actions(item, plugin); } } @@ -2574,16 +2607,16 @@ iter = g_list_delete_link(iter, iter)) { PurpleAccount *account = iter->data; PurpleConnection *gc = purple_account_get_connection(account); - PurplePlugin *prpl; + PurpleProtocol *protocol; if (!gc || !PURPLE_CONNECTION_IS_CONNECTED(gc)) continue; - prpl = purple_connection_get_prpl(gc); - - if (PURPLE_PLUGIN_HAS_ACTIONS(prpl)) { + protocol = purple_connection_get_protocol_info(gc); + + if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, get_actions)) { item = gnt_menuitem_new(purple_account_get_username(account)); gnt_menu_add_item(GNT_MENU(sub), item); - build_plugin_actions(item, prpl, gc); + build_protocol_actions(item, protocol, gc); } } } @@ -2783,9 +2816,9 @@ chat = purple_blist_find_chat(account, name); if (chat == NULL) { - PurplePluginProtocolInfo *info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - if (info->chat_info_defaults != NULL) - hash = info->chat_info_defaults(gc, name); + PurpleProtocol *protocol = purple_connection_get_protocol_info(gc); + if (protocol->chat_info_defaults != NULL) + hash = protocol->chat_info_defaults(gc, name); } else { hash = purple_chat_get_components(chat); }
--- a/finch/gntconv.c Sun Aug 18 01:52:32 2013 +0530 +++ b/finch/gntconv.c Sun Aug 18 01:53:00 2013 +0530 @@ -175,7 +175,7 @@ purple_conversation_write(conv, "", _("That command only works in IMs, not chats."), PURPLE_MESSAGE_NO_LOG, time(NULL)); break; - case PURPLE_CMD_STATUS_WRONG_PRPL: + case PURPLE_CMD_STATUS_WRONG_PROTOCOL: purple_conversation_write(conv, "", _("That command doesn't work on this protocol."), PURPLE_MESSAGE_NO_LOG, time(NULL)); break; @@ -339,7 +339,7 @@ chat = find_chat_for_conversation(conv); if (chat == NULL) { - PurplePluginProtocolInfo *info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + PurpleProtocol *info = purple_connection_get_protocol_info(gc); if (info->chat_info_defaults != NULL) comps = info->chat_info_defaults(gc, purple_conversation_get_name(conv)); } else { @@ -636,8 +636,8 @@ if (PURPLE_IS_IM_CONVERSATION(ggc->active_conv)) { PurpleAccount *account = purple_conversation_get_account(ggc->active_conv); PurpleConnection *gc = purple_account_get_connection(account); - PurplePluginProtocolInfo *pinfo = - gc ? PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)) : NULL; + PurpleProtocol *pinfo = + gc ? purple_connection_get_protocol_info(gc) : NULL; if (pinfo && pinfo->get_info) { item = gnt_menuitem_new(_("Get Info")); @@ -692,7 +692,7 @@ { PurpleAccount *account = purple_conversation_get_account(fc->active_conv); PurpleConnection *gc = purple_account_get_connection(account); - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; char *name, *realname; if (!gc) { @@ -703,9 +703,9 @@ name = gnt_tree_get_selection_data(GNT_TREE(widget)); - 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_chat_conversation_get_id( + protocol = purple_connection_get_protocol_info(gc); + if (protocol && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, get_cb_real_name)) + realname = protocol->get_cb_real_name(gc, purple_chat_conversation_get_id( PURPLE_CHAT_CONVERSATION(fc->active_conv)), name); else realname = NULL; @@ -1251,7 +1251,9 @@ const GList *plugins = purple_plugins_get_loaded(); if (plugins) { for (; plugins; plugins = plugins->next) { - str = g_string_append(str, purple_plugin_get_name(plugins->data)); + PurplePluginInfo *plugin_info = purple_plugin_get_info(plugins->data); + str = g_string_append(str, purple_plugin_info_get_name(plugin_info)); + if (plugins->next) str = g_string_append(str, ", "); }
--- a/finch/gntft.c Sun Aug 18 01:52:32 2013 +0530 +++ b/finch/gntft.c Sun Aug 18 01:53:00 2013 +0530 @@ -36,7 +36,7 @@ #include "debug.h" #include "notify.h" #include "ft.h" -#include "prpl.h" +#include "protocol.h" #include "util.h" #include "gntft.h"
--- a/finch/gntlog.c Sun Aug 18 01:52:32 2013 +0530 +++ b/finch/gntlog.c Sun Aug 18 01:53:00 2013 +0530 @@ -505,7 +505,7 @@ for(accounts = purple_accounts_get_all(); accounts != NULL; accounts = accounts->next) { PurpleAccount *account = (PurpleAccount *)accounts->data; - if(purple_find_prpl(purple_account_get_protocol_id(account)) == NULL) + if(purple_find_protocol_info(purple_account_get_protocol_id(account)) == NULL) continue; logs = g_list_concat(purple_log_get_system_logs(account), logs);
--- a/finch/gntmedia.c Sun Aug 18 01:52:32 2013 +0530 +++ b/finch/gntmedia.c Sun Aug 18 01:53:00 2013 +0530 @@ -405,7 +405,7 @@ { PurpleAccount *account = purple_conversation_get_account(conv); - if (!purple_prpl_initiate_media(account, + if (!purple_protocol_initiate_media(account, purple_conversation_get_name(conv), PURPLE_MEDIA_AUDIO)) return PURPLE_CMD_STATUS_FAILED;
--- a/finch/gntplugin.c Sun Aug 18 01:52:32 2013 +0530 +++ b/finch/gntplugin.c Sun Aug 18 01:53:00 2013 +0530 @@ -42,6 +42,21 @@ #include "gntplugin.h" #include "gntrequest.h" +#define FINCH_PLUGIN_INFO_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), FINCH_TYPE_PLUGIN_INFO, FinchPluginInfoPrivate)) + +typedef struct +{ + FinchPluginFrame get_pref_frame; +} FinchPluginInfoPrivate; + +enum +{ + PROP_0, + PROP_FINCH_PREFERENCES_FRAME, + PROP_LAST +}; + static struct { GntWidget *tree; @@ -54,6 +69,97 @@ static GntWidget *process_pref_frame(PurplePluginPrefFrame *frame); +/* Set method for GObject properties */ +static void +finch_plugin_info_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + FinchPluginInfoPrivate *priv = FINCH_PLUGIN_INFO_GET_PRIVATE(obj); + + switch (param_id) { + case PROP_FINCH_PREFERENCES_FRAME: + priv->get_pref_frame = g_value_get_pointer(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Get method for GObject properties */ +static void +finch_plugin_info_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + FinchPluginInfoPrivate *priv = FINCH_PLUGIN_INFO_GET_PRIVATE(obj); + + switch (param_id) { + case PROP_FINCH_PREFERENCES_FRAME: + g_value_set_pointer(value, priv->get_pref_frame); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Class initializer function */ +static void finch_plugin_info_class_init(FinchPluginInfoClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + g_type_class_add_private(klass, sizeof(FinchPluginInfoPrivate)); + + /* Setup properties */ + obj_class->get_property = finch_plugin_info_get_property; + obj_class->set_property = finch_plugin_info_set_property; + + g_object_class_install_property(obj_class, PROP_FINCH_PREFERENCES_FRAME, + g_param_spec_pointer("finch-preferences-frame", + "Finch preferences frame callback", + "Callback that returns a GNT preferences frame", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + +GType +finch_plugin_info_get_type(void) +{ + static GType type = 0; + + if (G_UNLIKELY(type == 0)) { + static const GTypeInfo info = { + .class_size = sizeof(FinchPluginInfoClass), + .class_init = (GClassInitFunc)finch_plugin_info_class_init, + .instance_size = sizeof(FinchPluginInfo), + }; + + type = g_type_register_static(PURPLE_TYPE_PLUGIN_INFO, + "FinchPluginInfo", &info, 0); + } + + return type; +} + +FinchPluginInfo * +finch_plugin_info_new(const char *first_property, ...) +{ + GObject *info; + va_list var_args; + + /* at least ID is required */ + if (!first_property) + return NULL; + + va_start(var_args, first_property); + info = g_object_new_valist(FINCH_TYPE_PLUGIN_INFO, first_property, + var_args); + va_end(var_args); + + g_object_set(info, "ui-requirement", FINCH_UI, NULL); + + return FINCH_PLUGIN_INFO(info); +} + static void free_stringlist(GList *list) { @@ -64,15 +170,21 @@ static void decide_conf_button(PurplePlugin *plugin) { - if (purple_plugin_is_loaded(plugin) && - ((PURPLE_IS_GNT_PLUGIN(plugin) && - FINCH_PLUGIN_UI_INFO(plugin) != NULL) || - (plugin->info->prefs_info && - plugin->info->prefs_info->get_plugin_pref_frame))) - gnt_widget_set_visible(plugins.conf, TRUE); - else - gnt_widget_set_visible(plugins.conf, FALSE); + gboolean visible = FALSE; + PurplePluginInfo *info = purple_plugin_get_info(plugin); + + if (purple_plugin_is_loaded(plugin)) { + FinchPluginInfoPrivate *priv = NULL; + if (FINCH_IS_PLUGIN_INFO(info)) + priv = FINCH_PLUGIN_INFO_GET_PRIVATE(info); + if ((priv && priv->get_pref_frame) || + (purple_plugin_info_get_pref_frame_callback(info))) { + visible = TRUE; + } + } + + gnt_widget_set_visible(plugins.conf, visible); gnt_box_readjust(GNT_BOX(plugins.window)); gnt_widget_draw(plugins.window); } @@ -80,21 +192,27 @@ static void plugin_toggled_cb(GntWidget *tree, PurplePlugin *plugin, gpointer null) { + GError *error = NULL; + if (gnt_tree_get_choice(GNT_TREE(tree), plugin)) { - if (!purple_plugin_load(plugin)) { - purple_notify_error(NULL, _("ERROR"), _("loading plugin failed"), NULL); + if (!purple_plugin_load(plugin, &error)) { + purple_notify_error(NULL, _("ERROR"), _("loading plugin failed"), + error->message); gnt_tree_set_choice(GNT_TREE(tree), plugin, FALSE); + g_error_free(error); } } else { GntWidget *win; - if (!purple_plugin_unload(plugin)) { - purple_notify_error(NULL, _("ERROR"), _("unloading plugin failed"), NULL); + if (!purple_plugin_unload(plugin, &error)) { + purple_notify_error(NULL, _("ERROR"), _("unloading plugin failed"), + error->message); purple_plugin_disable(plugin); gnt_tree_set_choice(GNT_TREE(tree), plugin, TRUE); + g_error_free(error); } if (confwins && (win = g_hash_table_lookup(confwins, plugin)) != NULL) @@ -117,12 +235,15 @@ selection_changed(GntWidget *widget, gpointer old, gpointer current, gpointer null) { PurplePlugin *plugin = current; + PurplePluginInfo *info; char *text; GList *list = NULL, *iter = NULL; if (!plugin) return; + info = purple_plugin_get_info(plugin); + /* If the selected plugin was unseen before, mark it as seen. But save the list * only when the plugin list is closed. So if the user enables a plugin, and it * crashes, it won't get marked as seen so the user can fix the bug and still @@ -130,17 +251,23 @@ * I probably mean 'plugin developers' by 'users' here. */ list = g_object_get_data(G_OBJECT(widget), "seen-list"); if (list) - iter = g_list_find_custom(list, plugin->path, (GCompareFunc)strcmp); + iter = g_list_find_custom(list, purple_plugin_get_filename(plugin), + (GCompareFunc)strcmp); if (!iter) { - list = g_list_prepend(list, g_strdup(plugin->path)); + list = g_list_prepend(list, g_strdup(purple_plugin_get_filename(plugin))); g_object_set_data(G_OBJECT(widget), "seen-list", list); } /* XXX: Use formatting and stuff */ gnt_text_view_clear(GNT_TEXT_VIEW(plugins.aboot)); text = g_strdup_printf(_("Name: %s\nVersion: %s\nDescription: %s\nAuthor: %s\nWebsite: %s\nFilename: %s\n"), - SAFE(_(plugin->info->name)), SAFE(_(plugin->info->version)), SAFE(_(plugin->info->description)), - SAFE(_(plugin->info->author)), SAFE(_(plugin->info->homepage)), SAFE(plugin->path)); + SAFE(_(purple_plugin_info_get_name(info))), + SAFE(_(purple_plugin_info_get_version(info))), + SAFE(_(purple_plugin_info_get_description(info))), + SAFE(_(purple_plugin_info_get_author(info))), + SAFE(_(purple_plugin_info_get_website(info))), + SAFE(purple_plugin_get_filename(plugin))); + gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(plugins.aboot), text, GNT_TEXT_FLAG_NORMAL); gnt_text_view_scroll(GNT_TEXT_VIEW(plugins.aboot), 0); @@ -164,11 +291,12 @@ static int plugin_compare(PurplePlugin *p1, PurplePlugin *p2) { - char *s1 = g_utf8_strup(p1->info->name, -1); - char *s2 = g_utf8_strup(p2->info->name, -1); + char *s1 = g_utf8_strup(purple_plugin_info_get_name(purple_plugin_get_info(p1)), -1); + char *s2 = g_utf8_strup(purple_plugin_info_get_name(purple_plugin_get_info(p2)), -1); int ret = g_utf8_collate(s1, s2); g_free(s1); g_free(s2); + return ret; } @@ -188,7 +316,8 @@ configure_plugin_cb(GntWidget *button, gpointer null) { PurplePlugin *plugin; - FinchPluginFrame callback; + PurplePluginInfo *info; + FinchPluginInfoPrivate *priv = NULL; g_return_if_fail(plugins.tree != NULL); @@ -203,17 +332,21 @@ if (confwins && g_hash_table_lookup(confwins, plugin)) return; - if (PURPLE_IS_GNT_PLUGIN(plugin) && - (callback = FINCH_PLUGIN_UI_INFO(plugin)) != NULL) + info = purple_plugin_get_info(plugin); + if (FINCH_IS_PLUGIN_INFO(info)) + priv = FINCH_PLUGIN_INFO_GET_PRIVATE(info); + + if (priv && priv->get_pref_frame != NULL) { GntWidget *window = gnt_vbox_new(FALSE); GntWidget *box, *button; gnt_box_set_toplevel(GNT_BOX(window), TRUE); - gnt_box_set_title(GNT_BOX(window), plugin->info->name); + gnt_box_set_title(GNT_BOX(window), + purple_plugin_info_get_name(info)); gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID); - box = callback(); + box = priv->get_pref_frame(); gnt_box_add_widget(GNT_BOX(window), box); box = gnt_hbox_new(FALSE); @@ -231,24 +364,23 @@ confwin_init(); g_hash_table_insert(confwins, plugin, window); } - else if (plugin->info->prefs_info && - plugin->info->prefs_info->get_plugin_pref_frame) + else if (purple_plugin_info_get_pref_frame_callback(info)) { - GntWidget *win = process_pref_frame(plugin->info->prefs_info->get_plugin_pref_frame(plugin)); + PurplePluginPrefFrameCallback get_pref_frame = purple_plugin_info_get_pref_frame_callback(info); + GntWidget *win = process_pref_frame(get_pref_frame(plugin)); if (confwins == NULL) confwin_init(); g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(remove_confwin), plugin); g_hash_table_insert(confwins, plugin, win); - return; } else { purple_notify_info(plugin, _("Error"), _("No configuration options for this plugin."), NULL); - return; } } +#if 0 static void install_selected_file_cb(gpointer handle, const char *filename) { @@ -335,11 +467,12 @@ NULL, NULL, NULL, &handle); g_signal_connect_swapped(G_OBJECT(w), "destroy", G_CALLBACK(purple_request_close_with_handle), &handle); } +#endif -void finch_plugins_show_all() +void finch_plugins_show_all(void) { GntWidget *window, *tree, *box, *aboot, *button; - GList *iter; + GList *plugin_list, *iter; GList *seen; if (plugins.window) { @@ -347,7 +480,7 @@ return; } - purple_plugins_probe(G_MODULE_SUFFIX); + purple_plugins_refresh(); plugins.window = window = gnt_vbox_new(FALSE); gnt_box_set_toplevel(GNT_BOX(window), TRUE); @@ -376,29 +509,26 @@ gnt_box_add_widget(GNT_BOX(box), aboot); seen = purple_prefs_get_path_list("/finch/plugins/seen"); - for (iter = purple_plugins_get_all(); iter; iter = iter->next) - { - PurplePlugin *plug = iter->data; - if (plug->info->type == PURPLE_PLUGIN_LOADER) { - GList *cur; - for (cur = PURPLE_PLUGIN_LOADER_INFO(plug)->exts; cur != NULL; - cur = cur->next) - purple_plugins_probe(cur->data); - continue; - } + plugin_list = purple_plugins_find_all(); + for (iter = plugin_list; iter; iter = iter->next) + { + PurplePlugin *plug = PURPLE_PLUGIN(iter->data); - if (plug->info->type != PURPLE_PLUGIN_STANDARD || - (plug->info->flags & PURPLE_PLUGIN_FLAG_INVISIBLE) || - plug->error) + if (purple_plugin_is_internal(plug)) continue; gnt_tree_add_choice(GNT_TREE(tree), plug, - gnt_tree_create_row(GNT_TREE(tree), plug->info->name), NULL, NULL); + gnt_tree_create_row(GNT_TREE(tree), + purple_plugin_info_get_name(purple_plugin_get_info(plug))), + NULL, NULL); gnt_tree_set_choice(GNT_TREE(tree), plug, purple_plugin_is_loaded(plug)); - if (!g_list_find_custom(seen, plug->path, (GCompareFunc)strcmp)) + if (!g_list_find_custom(seen, purple_plugin_get_filename(plug), + (GCompareFunc)strcmp)) gnt_tree_set_row_flags(GNT_TREE(tree), plug, GNT_TEXT_FLAG_BOLD); } + g_list_free(plugin_list); + gnt_tree_set_col_width(GNT_TREE(tree), 0, 30); g_signal_connect(G_OBJECT(tree), "toggled", G_CALLBACK(plugin_toggled_cb), NULL); g_signal_connect(G_OBJECT(tree), "selection_changed", G_CALLBACK(selection_changed), NULL); @@ -407,10 +537,12 @@ box = gnt_hbox_new(FALSE); gnt_box_add_widget(GNT_BOX(window), box); +#if 0 button = gnt_button_new(_("Install Plugin...")); gnt_box_add_widget(GNT_BOX(box), button); gnt_util_set_trigger_widget(GNT_WIDGET(tree), GNT_KEY_INS, button); g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(install_plugin_cb), NULL); +#endif button = gnt_button_new(_("Close")); gnt_box_add_widget(GNT_BOX(box), button);
--- a/finch/gntplugin.h Sun Aug 18 01:52:32 2013 +0530 +++ b/finch/gntplugin.h Sun Aug 18 01:53:00 2013 +0530 @@ -28,36 +28,87 @@ #include <gnt.h> -#include <plugin.h> +#include <plugins.h> #include <pluginpref.h> #include <string.h> #include "finch.h" +#define FINCH_TYPE_PLUGIN_INFO (finch_plugin_info_get_type()) +#define FINCH_PLUGIN_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), FINCH_TYPE_PLUGIN_INFO, FinchPluginInfo)) +#define FINCH_PLUGIN_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), FINCH_TYPE_PLUGIN_INFO, FinchPluginInfoClass)) +#define FINCH_IS_PLUGIN_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), FINCH_TYPE_PLUGIN_INFO)) +#define FINCH_IS_PLUGIN_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), FINCH_TYPE_PLUGIN_INFO)) +#define FINCH_PLUGIN_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), FINCH_TYPE_PLUGIN_INFO, FinchPluginInfoClass)) + +/** @copydoc _FinchPluginInfo */ +typedef struct _FinchPluginInfo FinchPluginInfo; +/** @copydoc _FinchPluginInfoClass */ +typedef struct _FinchPluginInfoClass FinchPluginInfoClass; + +typedef GntWidget* (*FinchPluginFrame) (void); + +/** + * Extends #PurplePluginInfo to hold UI information for finch. + */ +struct _FinchPluginInfo { + /*< private >*/ + PurplePluginInfo parent; +}; + +/** + * FinchPluginInfoClass: + * + * The base class for all #FinchPluginInfo's. + */ +struct _FinchPluginInfoClass { + /*< private >*/ + PurplePluginInfoClass parent_class; + + void (*_gnt_reserved1)(void); + void (*_gnt_reserved2)(void); + void (*_gnt_reserved3)(void); + void (*_gnt_reserved4)(void); +}; + +/********************************************************************** + * @name Plugin Info API + **********************************************************************/ +/*@{*/ + +/** + * Returns the GType for the FinchPluginInfo object. + */ +GType finch_plugin_info_get_type(void); + +/** + * Creates a new #FinchPluginInfo instance to be returned from + * gplugin_plugin_query() of a finch plugin, using the provided name/value + * pairs. + * + * See purple_plugin_info_new() for a list of available property names. + * Additionally, you can provide the property "finch-preferences-frame", + * which should be a callback that returns a GntWidget for the plugin's + * preferences (see FinchPluginFrame). + * + * @param first_property The first property name + * @param ... The value of the first property, followed optionally by more + * name/value pairs, followed by @c NULL + * + * @return A new #FinchPluginInfo instance. + * + * @see purple_plugin_info_new() + */ +FinchPluginInfo *finch_plugin_info_new(const char *first_property, ...); + +/*@}*/ + /********************************************************************** * @name GNT Plugins API **********************************************************************/ /*@{*/ -typedef GntWidget* (*FinchPluginFrame) (void); - -/* Guess where these came from */ -#define FINCH_PLUGIN_TYPE FINCH_UI - -/** - * Decide whether a plugin is a GNT-plugin. - */ -#define PURPLE_IS_GNT_PLUGIN(plugin) \ - ((plugin)->info != NULL && (plugin)->info->ui_info != NULL && \ - !strcmp((plugin)->info->ui_requirement, FINCH_PLUGIN_TYPE)) - -/** - * Get the ui-info from GNT-plugins. - */ -#define FINCH_PLUGIN_UI_INFO(plugin) \ - (FinchPluginFrame)((plugin)->info->ui_info) - /** * Show a list of plugins. */
--- a/finch/gntpounce.c Sun Aug 18 01:52:32 2013 +0530 +++ b/finch/gntpounce.c Sun Aug 18 01:53:00 2013 +0530 @@ -43,7 +43,7 @@ #include "conversation.h" #include "debug.h" #include "notify.h" -#include "prpl.h" +#include "protocol.h" #include "request.h" #include "server.h" #include "util.h"
--- a/finch/gntroomlist.c Sun Aug 18 01:52:32 2013 +0530 +++ b/finch/gntroomlist.c Sun Aug 18 01:53:00 2013 +0530 @@ -113,15 +113,15 @@ char *name; PurpleRoomlistRoom *room = gnt_tree_get_selection_data(GNT_TREE(froomlist.tree)); PurpleConnection *gc = purple_account_get_connection(froomlist.account); - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; if (gc == NULL || room == NULL) return; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + protocol = purple_connection_get_protocol_info(gc); - if(prpl_info != NULL && prpl_info->roomlist_room_serialize) - name = prpl_info->roomlist_room_serialize(room); + if(protocol != NULL && protocol->roomlist_room_serialize) + name = protocol->roomlist_room_serialize(room); else name = g_strdup(purple_roomlist_room_get_name(room)); @@ -237,12 +237,12 @@ GntComboBox *accounts = GNT_COMBO_BOX(froomlist.accounts); gnt_combo_box_remove_all(accounts); for (list = purple_connections_get_all(); list; list = list->next) { - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; PurpleConnection *gc = list->data; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + protocol = purple_connection_get_protocol_info(gc); if (PURPLE_CONNECTION_IS_CONNECTED(gc) && - prpl_info->roomlist_get_list != NULL) { + protocol->roomlist_get_list != NULL) { PurpleAccount *account = purple_connection_get_account(gc); char *text = g_strdup_printf("%s (%s)", purple_account_get_username(account),
--- a/finch/libgnt/wms/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/finch/libgnt/wms/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -35,6 +35,7 @@ -I$(top_srcdir)/finch/libgnt \ $(DEBUG_CFLAGS) \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(GNT_CFLAGS) \ $(PLUGIN_CFLAGS)
--- a/finch/plugins/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/finch/plugins/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -1,63 +1,64 @@ -gntclipboard_la_LDFLAGS = -module -avoid-version -gntgf_la_LDFLAGS = -module -avoid-version -gnthistory_la_LDFLAGS = -module -avoid-version -gntlastlog_la_LDFLAGS = -module -avoid-version -gnttinyurl_la_LDFLAGS = -module -avoid-version -grouping_la_LDFLAGS = -module -avoid-version - -if PLUGINS - -plugin_LTLIBRARIES = \ - gntclipboard.la \ - gntgf.la \ - gnthistory.la \ - gntlastlog.la \ - gnttinyurl.la \ - grouping.la - -plugindir = $(libdir)/finch - -gntclipboard_la_SOURCES = gntclipboard.c -gntgf_la_SOURCES = gntgf.c -gnthistory_la_SOURCES = gnthistory.c -gntlastlog_la_SOURCES = lastlog.c -gnttinyurl_la_SOURCES = gnttinyurl.c -grouping_la_SOURCES = grouping.c - -gntclipboard_la_CFLAGS = $(X11_CFLAGS) -gntgf_la_CFLAGS = $(X11_CFLAGS) - -gntclipboard_la_LIBADD = $(GLIB_LIBS) $(X11_LIBS) -gntgf_la_LIBADD = $(GLIB_LIBS) $(X11_LIBS) $(top_builddir)/finch/libgnt/libgnt.la -gnthistory_la_LIBADD = $(GLIB_LIBS) -gntlastlog_la_LIBADD = $(GLIB_LIBS) -gnttinyurl_la_LIBADD = $(GLIB_LIBS) -grouping_la_LIBADD = $(GLIB_LIBS) $(top_builddir)/finch/libgnt/libgnt.la - -endif # PLUGINS - -EXTRA_DIST = pietray.py - -AM_CPPFLAGS = \ - -DDATADIR=\"$(datadir)\" \ - -I$(top_builddir)/libpurple \ - -I$(top_srcdir)/libpurple \ - -I$(top_srcdir) \ - -I$(top_srcdir)/finch \ - -I$(top_srcdir)/finch/libgnt \ - $(DEBUG_CFLAGS) \ - $(GLIB_CFLAGS) \ - $(GNT_CFLAGS) \ - $(PLUGIN_CFLAGS) - +#gntclipboard_la_LDFLAGS = -module -avoid-version +#gntgf_la_LDFLAGS = -module -avoid-version +#gnthistory_la_LDFLAGS = -module -avoid-version +#gntlastlog_la_LDFLAGS = -module -avoid-version +#gnttinyurl_la_LDFLAGS = -module -avoid-version +#grouping_la_LDFLAGS = -module -avoid-version +# +#if PLUGINS +# +#plugin_LTLIBRARIES = \ +# gntclipboard.la \ +# gntgf.la \ +# gnthistory.la \ +# gntlastlog.la \ +# gnttinyurl.la \ +# grouping.la +# +#plugindir = $(libdir)/finch +# +#gntclipboard_la_SOURCES = gntclipboard.c +#gntgf_la_SOURCES = gntgf.c +#gnthistory_la_SOURCES = gnthistory.c +#gntlastlog_la_SOURCES = lastlog.c +#gnttinyurl_la_SOURCES = gnttinyurl.c +#grouping_la_SOURCES = grouping.c +# +#gntclipboard_la_CFLAGS = $(X11_CFLAGS) +#gntgf_la_CFLAGS = $(X11_CFLAGS) # -# This part allows people to build their own plugins in here. -# Yes, it's a mess. +#gntclipboard_la_LIBADD = $(GLIB_LIBS) $(X11_LIBS) +#gntgf_la_LIBADD = $(GLIB_LIBS) $(X11_LIBS) $(top_builddir)/finch/libgnt/libgnt.la +#gnthistory_la_LIBADD = $(GLIB_LIBS) +#gntlastlog_la_LIBADD = $(GLIB_LIBS) +#gnttinyurl_la_LIBADD = $(GLIB_LIBS) +#grouping_la_LIBADD = $(GLIB_LIBS) $(top_builddir)/finch/libgnt/libgnt.la +# +#endif # PLUGINS +# +#EXTRA_DIST = pietray.py # -SUFFIXES = .c .so -.c.so: - $(LIBTOOL) --mode=compile $(CC) -DHAVE_CONFIG_H -I$(top_builddir) $(AM_CPPFLAGS) $(CFLAGS) -c $< -o tmp$@.lo $(PLUGIN_CFLAGS) - $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o libtmp$@.la -rpath $(plugindir) tmp$@.lo $(LIBS) $(LDFLAGS) -module -avoid-version $(PLUGIN_LIBS) - @rm -f tmp$@.lo tmp$@.o libtmp$@.la - @cp .libs/libtmp$@.so.so $@ - @rm -rf .libs/libtmp$@.* +#AM_CPPFLAGS = \ +# -DDATADIR=\"$(datadir)\" \ +# -I$(top_builddir)/libpurple \ +# -I$(top_srcdir)/libpurple \ +# -I$(top_srcdir) \ +# -I$(top_srcdir)/finch \ +# -I$(top_srcdir)/finch/libgnt \ +# $(DEBUG_CFLAGS) \ +# $(GLIB_CFLAGS) \ +# $(GPLUGIN_CFLAGS) \ +# $(GNT_CFLAGS) \ +# $(PLUGIN_CFLAGS) +# +## +## This part allows people to build their own plugins in here. +## Yes, it's a mess. +## +#SUFFIXES = .c .so +#.c.so: +# $(LIBTOOL) --mode=compile $(CC) -DHAVE_CONFIG_H -I$(top_builddir) $(AM_CPPFLAGS) $(CFLAGS) -c $< -o tmp$@.lo $(PLUGIN_CFLAGS) +# $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o libtmp$@.la -rpath $(plugindir) tmp$@.lo $(LIBS) $(LDFLAGS) -module -avoid-version $(PLUGIN_LIBS) +# @rm -f tmp$@.lo tmp$@.o libtmp$@.la +# @cp .libs/libtmp$@.so.so $@ +# @rm -rf .libs/libtmp$@.*
--- a/finch/plugins/gntclipboard.c Sun Aug 18 01:52:32 2013 +0530 +++ b/finch/plugins/gntclipboard.c Sun Aug 18 01:53:00 2013 +0530 @@ -35,7 +35,7 @@ #include <glib.h> -#include <plugin.h> +#include <plugins.h> #include <version.h> #include <debug.h> #include <notify.h>
--- a/finch/plugins/gntgf.c Sun Aug 18 01:52:32 2013 +0530 +++ b/finch/plugins/gntgf.c Sun Aug 18 01:53:00 2013 +0530 @@ -42,7 +42,7 @@ #include <glib.h> -#include <plugin.h> +#include <plugins.h> #include <version.h> #include <buddylist.h> #include <conversation.h>
--- a/finch/plugins/gnttinyurl.c Sun Aug 18 01:52:32 2013 +0530 +++ b/finch/plugins/gnttinyurl.c Sun Aug 18 01:53:00 2013 +0530 @@ -34,7 +34,7 @@ #include <glib.h> -#include <plugin.h> +#include <plugins.h> #include <version.h> #include <debug.h> #include <notify.h>
--- a/finch/plugins/lastlog.c Sun Aug 18 01:52:32 2013 +0530 +++ b/finch/plugins/lastlog.c Sun Aug 18 01:53:00 2013 +0530 @@ -23,7 +23,7 @@ #include "internal.h" -#include <plugin.h> +#include <plugins.h> #include <version.h> #include <cmds.h>
--- a/libpurple/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -75,13 +75,13 @@ network.c \ ntlm.c \ notify.c \ - plugin.c \ + plugins.c \ pluginpref.c \ pounce.c \ prefs.c \ presence.c \ proxy.c \ - prpl.c \ + protocol.c \ request.c \ roomlist.c \ savedstatuses.c \ @@ -146,13 +146,13 @@ network.h \ notify.h \ ntlm.h \ - plugin.h \ + plugins.h \ pluginpref.h \ pounce.h \ prefs.h \ presence.h \ proxy.h \ - prpl.h \ + protocol.h \ request.h \ roomlist.h \ savedstatuses.h \ @@ -231,7 +231,7 @@ blistnodetypes.h buddylist.h buddyicon.h connection.h conversation.h \ conversationtypes.h conversations.h core.h ft.h log.h notify.h \ prefs.h presence.h roomlist.h savedstatuses.h smiley.h status.h \ - server.h util.h xmlnode.h prpl.h + server.h util.h xmlnode.h protocol.h purple_build_coreheaders = $(addprefix $(srcdir)/, $(purple_coreheaders)) \ $(addprefix $(srcdir)/media/, $(purple_mediaheaders)) \ @@ -340,6 +340,7 @@ $(STATIC_LINK_LIBS) \ $(DBUS_LIBS) \ $(GLIB_LIBS) \ + $(GPLUGIN_LIBS) \ $(LIBXML_LIBS) \ $(NETWORKMANAGER_LIBS) \ $(INTLLIBS) \ @@ -360,6 +361,7 @@ -DLOCALEDIR=\"$(datadir)/locale\" \ -DSYSCONFDIR=\"$(sysconfdir)\" \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(DEBUG_CFLAGS) \ $(DBUS_CFLAGS) \ $(LIBXML_CFLAGS) \
--- a/libpurple/account.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/account.c Sun Aug 18 01:53:00 2013 +0530 @@ -293,11 +293,11 @@ purple_account_connect_got_password_cb(PurpleAccount *account, const gchar *password, GError *error, gpointer data) { - PurplePluginProtocolInfo *prpl_info = data; + PurpleProtocol *protocol = data; if ((password == NULL || *password == '\0') && - !(prpl_info->options & OPT_PROTO_NO_PASSWORD) && - !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL)) + !(protocol->options & OPT_PROTO_NO_PASSWORD) && + !(protocol->options & OPT_PROTO_PASSWORD_OPTIONAL)) purple_account_request_password(account, G_CALLBACK(request_password_ok_cb), G_CALLBACK(request_password_cancel_cb), account); @@ -308,9 +308,8 @@ void purple_account_connect(PurpleAccount *account) { - PurplePlugin *prpl; const char *username; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; PurpleAccountPrivate *priv; g_return_if_fail(account != NULL); @@ -324,8 +323,8 @@ return; } - prpl = purple_find_prpl(purple_account_get_protocol_id(account)); - if (prpl == NULL) { + protocol = purple_find_protocol_info(purple_account_get_protocol_id(account)); + if (protocol == NULL) { gchar *message; message = g_strdup_printf(_("Missing protocol plugin for %s"), username); @@ -338,13 +337,12 @@ purple_debug_info("account", "Connecting to account %s.\n", username); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); if (priv->password != NULL) { purple_account_connect_got_password_cb(account, - priv->password, NULL, prpl_info); + priv->password, NULL, protocol); } else { purple_keyring_get_password(account, - purple_account_connect_got_password_cb, prpl_info); + purple_account_connect_got_password_cb, protocol); } } @@ -616,8 +614,7 @@ PurpleRequestFieldGroup *group; PurpleRequestField *field; PurpleConnection *gc; - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; char primary[256]; g_return_if_fail(account != NULL); @@ -625,9 +622,7 @@ 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); + protocol = purple_connection_get_protocol_info(gc); fields = purple_request_fields_new(); @@ -637,7 +632,7 @@ field = purple_request_field_string_new("password", _("Original password"), NULL, FALSE); purple_request_field_string_set_masked(field, TRUE); - if (!prpl_info || !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL)) + if (!protocol || !(protocol->options & OPT_PROTO_PASSWORD_OPTIONAL)) purple_request_field_set_required(field, TRUE); purple_request_field_group_add_field(group, field); @@ -645,7 +640,7 @@ _("New password"), NULL, FALSE); purple_request_field_string_set_masked(field, TRUE); - if (!prpl_info || !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL)) + if (!protocol || !(protocol->options & OPT_PROTO_PASSWORD_OPTIONAL)) purple_request_field_set_required(field, TRUE); purple_request_field_group_add_field(group, field); @@ -653,7 +648,7 @@ _("New password (again)"), NULL, FALSE); purple_request_field_string_set_masked(field, TRUE); - if (!prpl_info || !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL)) + if (!protocol || !(protocol->options & OPT_PROTO_PASSWORD_OPTIONAL)) purple_request_field_set_required(field, TRUE); purple_request_field_group_add_field(group, field); @@ -1020,18 +1015,16 @@ PurpleSetPublicAliasFailureCallback failure_cb) { PurpleConnection *gc; - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; g_return_if_fail(account != NULL); g_return_if_fail(purple_account_is_connected(account)); gc = purple_account_get_connection(account); - prpl = purple_connection_get_prpl(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, set_public_alias)) - prpl_info->set_public_alias(gc, alias, success_cb, failure_cb); + protocol = purple_connection_get_protocol_info(gc); + + if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, set_public_alias)) + protocol->set_public_alias(gc, alias, success_cb, failure_cb); else if (failure_cb) { struct public_alias_closure *closure = g_new0(struct public_alias_closure, 1); @@ -1060,18 +1053,16 @@ PurpleGetPublicAliasFailureCallback failure_cb) { PurpleConnection *gc; - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; g_return_if_fail(account != NULL); g_return_if_fail(purple_account_is_connected(account)); gc = purple_account_get_connection(account); - prpl = purple_connection_get_prpl(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_public_alias)) - prpl_info->get_public_alias(gc, success_cb, failure_cb); + protocol = purple_connection_get_protocol_info(gc); + + if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, get_public_alias)) + protocol->get_public_alias(gc, success_cb, failure_cb); else if (failure_cb) { struct public_alias_closure *closure = g_new0(struct public_alias_closure, 1); @@ -1429,13 +1420,13 @@ const char * purple_account_get_protocol_name(const PurpleAccount *account) { - PurplePlugin *p; + PurpleProtocol *p; g_return_val_if_fail(account != NULL, NULL); - p = purple_find_prpl(purple_account_get_protocol_id(account)); - - return ((p && p->info->name) ? _(p->info->name) : _("Unknown")); + p = purple_find_protocol_info(purple_account_get_protocol_id(account)); + + return ((p && p->name) ? _(p->name) : _("Unknown")); } PurpleConnection * @@ -2218,40 +2209,32 @@ void purple_account_add_buddy(PurpleAccount *account, PurpleBuddy *buddy, const char *message) { - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = 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)) - prpl_info->add_buddy(gc, buddy, purple_buddy_get_group(buddy), message); + protocol = purple_connection_get_protocol_info(gc); + + if (protocol != NULL) { + if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, add_buddy)) + protocol->add_buddy(gc, buddy, purple_buddy_get_group(buddy), message); } } void purple_account_add_buddies(PurpleAccount *account, GList *buddies, const char *message) { - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = 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) { + protocol = purple_connection_get_protocol_info(gc); + + if (protocol) { GList *cur, *groups = NULL; /* Make a list of what group each buddy is in */ @@ -2260,13 +2243,13 @@ groups = g_list_append(groups, purple_buddy_get_group(buddy)); } - 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)) { + if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, add_buddies)) + protocol->add_buddies(gc, buddies, groups, message); + else if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, add_buddy)) { GList *curb = buddies, *curg = groups; while ((curb != NULL) && (curg != NULL)) { - prpl_info->add_buddy(gc, curb->data, curg->data, message); + protocol->add_buddy(gc, curb->data, curg->data, message); curb = curb->next; curg = curg->next; } @@ -2280,36 +2263,28 @@ purple_account_remove_buddy(PurpleAccount *account, PurpleBuddy *buddy, PurpleGroup *group) { - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = 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 && prpl_info->remove_buddy) - prpl_info->remove_buddy(gc, buddy, group); + protocol = purple_connection_get_protocol_info(gc); + + if (protocol && protocol->remove_buddy) + protocol->remove_buddy(gc, buddy, group); } void purple_account_remove_buddies(PurpleAccount *account, GList *buddies, GList *groups) { - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = 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) { - if (prpl_info->remove_buddies) - prpl_info->remove_buddies(gc, buddies, groups); + protocol = purple_connection_get_protocol_info(gc); + + if (protocol) { + if (protocol->remove_buddies) + protocol->remove_buddies(gc, buddies, groups); else { GList *curb = buddies; GList *curg = groups; @@ -2325,45 +2300,36 @@ void purple_account_remove_group(PurpleAccount *account, PurpleGroup *group) { - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = 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 && prpl_info->remove_group) - prpl_info->remove_group(gc, group); + protocol = purple_connection_get_protocol_info(gc); + + if (protocol && protocol->remove_group) + protocol->remove_group(gc, group); } void purple_account_change_password(PurpleAccount *account, const char *orig_pw, const char *new_pw) { - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; PurpleConnection *gc = purple_account_get_connection(account); - PurplePlugin *prpl = NULL; purple_account_set_password(account, new_pw, NULL, NULL); if (gc != NULL) - prpl = purple_connection_get_prpl(gc); - - if (prpl != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if (prpl_info && prpl_info->change_passwd) - prpl_info->change_passwd(gc, orig_pw, new_pw); + protocol = purple_connection_get_protocol_info(gc); + + if (protocol && protocol->change_passwd) + protocol->change_passwd(gc, orig_pw, new_pw); } gboolean purple_account_supports_offline_message(PurpleAccount *account, PurpleBuddy *buddy) { PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info = NULL; - PurplePlugin *prpl = NULL; + PurpleProtocol *protocol = NULL; g_return_val_if_fail(account, FALSE); g_return_val_if_fail(buddy, FALSE); @@ -2372,14 +2338,11 @@ if (gc == NULL) return FALSE; - prpl = purple_connection_get_prpl(gc); - - if (prpl != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if (!prpl_info || !prpl_info->offline_message) + protocol = purple_connection_get_protocol_info(gc); + + if (!protocol || !protocol->offline_message) return FALSE; - return prpl_info->offline_message(buddy); + return protocol->offline_message(buddy); } void @@ -2906,8 +2869,7 @@ PurpleAccount *account = PURPLE_ACCOUNT(object); PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account); gchar *username, *protocol_id; - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; PurpleStatusType *status_type; parent_class->constructed(object); @@ -2920,17 +2882,16 @@ purple_signal_emit(purple_accounts_get_handle(), "account-created", account); - prpl = purple_find_prpl(protocol_id); - if (prpl == NULL) { + protocol = purple_find_protocol_info(protocol_id); + if (protocol == NULL) { g_free(username); g_free(protocol_id); return; } - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (prpl_info != NULL && prpl_info->status_types != NULL) + if (protocol->status_types != NULL) purple_account_set_status_types(account, - prpl_info->status_types(account)); + protocol->status_types(account)); priv->presence = PURPLE_PRESENCE(purple_account_presence_new(account));
--- a/libpurple/account.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/account.h Sun Aug 18 01:53:00 2013 +0530 @@ -53,7 +53,7 @@ #include "connection.h" #include "log.h" #include "proxy.h" -#include "prpl.h" +#include "protocol.h" #include "status.h" #include "keyring.h" #include "xmlnode.h"
--- a/libpurple/blistnodetypes.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/blistnodetypes.c Sun Aug 18 01:53:00 2013 +0530 @@ -628,19 +628,15 @@ { PurpleBuddy *buddy = PURPLE_BUDDY(object); PurpleBuddyPrivate *priv = PURPLE_BUDDY_GET_PRIVATE(buddy); - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; /* * Tell the owner PRPL that we're about to free the buddy so it * can free proto_data */ - prpl = purple_find_prpl(purple_account_get_protocol_id(priv->account)); - if (prpl) { - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (prpl_info && prpl_info->buddy_free) - prpl_info->buddy_free(buddy); - } + protocol = purple_find_protocol_info(purple_account_get_protocol_id(priv->account)); + if (protocol && protocol->buddy_free) + protocol->buddy_free(buddy); /* Delete the node */ purple_buddy_icon_unref(priv->icon); @@ -1119,18 +1115,16 @@ const char *purple_chat_get_name_only(PurpleChat *chat) { char *ret = NULL; - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; PurpleChatPrivate *priv = PURPLE_CHAT_GET_PRIVATE(chat); g_return_val_if_fail(priv != NULL, NULL); - prpl = purple_find_prpl(purple_account_get_protocol_id(priv->account)); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_find_protocol_info(purple_account_get_protocol_id(priv->account)); - if (prpl_info->chat_info) { + if (protocol->chat_info) { struct proto_chat_entry *pce; - GList *parts = prpl_info->chat_info(purple_account_get_connection(priv->account)); + GList *parts = protocol->chat_info(purple_account_get_connection(priv->account)); pce = parts->data; ret = g_hash_table_lookup(priv->components, pce->identifier); g_list_foreach(parts, (GFunc)g_free, NULL); @@ -1522,19 +1516,15 @@ for (accts = purple_group_get_accounts(source); accts; accts = g_slist_remove(accts, accts->data)) { PurpleAccount *account = accts->data; PurpleConnection *gc = NULL; - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; GList *l = NULL, *buddies = NULL; gc = purple_account_get_connection(account); if(gc) - prpl = purple_connection_get_prpl(gc); + protocol = purple_connection_get_protocol_info(gc); - if(gc && prpl) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if(!prpl_info) + if(!protocol) continue; for(l = moved_buddies; l; l = l->next) { @@ -1544,8 +1534,8 @@ buddies = g_list_append(buddies, (PurpleBlistNode *)buddy); } - if(prpl_info->rename_group) { - prpl_info->rename_group(gc, old_name, source, buddies); + if(protocol->rename_group) { + protocol->rename_group(gc, old_name, source, buddies); } else { GList *cur, *groups = NULL;
--- a/libpurple/buddyicon.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/buddyicon.c Sun Aug 18 01:53:00 2013 +0530 @@ -745,13 +745,13 @@ if (!purple_account_is_disconnected(account)) { PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; gc = purple_account_get_connection(account); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + protocol = purple_connection_get_protocol_info(gc); - if (prpl_info && prpl_info->set_buddy_icon) - prpl_info->set_buddy_icon(gc, img); + if (protocol && protocol->set_buddy_icon) + protocol->set_buddy_icon(gc, img); } if (old_img)
--- a/libpurple/buddyicon.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/buddyicon.h Sun Aug 18 01:53:00 2013 +0530 @@ -38,7 +38,7 @@ #include "account.h" #include "buddylist.h" #include "imgstore.h" -#include "prpl.h" +#include "protocol.h" #include "util.h" G_BEGIN_DECLS
--- a/libpurple/buddylist.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/buddylist.c Sun Aug 18 01:53:00 2013 +0530 @@ -28,7 +28,7 @@ #include "notify.h" #include "pounce.h" #include "prefs.h" -#include "prpl.h" +#include "protocol.h" #include "server.h" #include "signals.h" #include "util.h" @@ -1622,8 +1622,7 @@ { char *chat_name; PurpleChat *chat; - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; struct proto_chat_entry *pce; PurpleBlistNode *node, *group; GList *parts; @@ -1635,11 +1634,10 @@ if (!purple_account_is_connected(account)) return NULL; - prpl = purple_find_prpl(purple_account_get_protocol_id(account)); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_find_protocol_info(purple_account_get_protocol_id(account)); - if (prpl_info->find_blist_chat != NULL) - return prpl_info->find_blist_chat(account, name); + if (protocol->find_blist_chat != NULL) + return protocol->find_blist_chat(account, name); normname = g_strdup(purple_normalize(account, name)); for (group = purplebuddylist->root; group != NULL; group = group->next) { @@ -1651,7 +1649,7 @@ if (account != purple_chat_get_account(chat)) continue; - parts = prpl_info->chat_info( + parts = protocol->chat_info( purple_account_get_connection(purple_chat_get_account(chat))); pce = parts->data;
--- a/libpurple/ciphers/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/ciphers/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -24,6 +24,7 @@ $(INTGG_CFLAGS) \ $(AM_CFLAGS) \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(DEBUG_CFLAGS) \ $(GNUTLS_CFLAGS) \ $(NSS_CFLAGS)
--- a/libpurple/cmds.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/cmds.c Sun Aug 18 01:53:00 2013 +0530 @@ -36,7 +36,7 @@ gchar *args; PurpleCmdPriority priority; PurpleCmdFlag flags; - gchar *prpl_id; + gchar *protocol_id; PurpleCmdFunc func; gchar *help; void *data; @@ -54,7 +54,7 @@ PurpleCmdId purple_cmd_register(const gchar *cmd, const gchar *args, PurpleCmdPriority p, PurpleCmdFlag f, - const gchar *prpl_id, PurpleCmdFunc func, + const gchar *protocol_id, PurpleCmdFunc func, const gchar *helpstr, void *data) { PurpleCmdId id; @@ -72,7 +72,7 @@ c->args = g_strdup(args); c->priority = p; c->flags = f; - c->prpl_id = g_strdup(prpl_id); + c->protocol_id = g_strdup(protocol_id); c->func = func; c->help = g_strdup(helpstr); c->data = data; @@ -88,7 +88,7 @@ { g_free(c->cmd); g_free(c->args); - g_free(c->prpl_id); + g_free(c->protocol_id); g_free(c->help); g_free(c); } @@ -203,14 +203,14 @@ GList *l; gchar *err = NULL; gboolean is_im = TRUE; - gboolean found = FALSE, tried_cmd = FALSE, right_type = FALSE, right_prpl = FALSE; - const gchar *prpl_id; + gboolean found = FALSE, tried_cmd = FALSE, right_type = FALSE, right_protocol = FALSE; + const gchar *protocol_id; gchar **args = NULL; gchar *cmd, *rest, *mrest; PurpleCmdRet ret = PURPLE_CMD_RET_CONTINUE; *error = NULL; - prpl_id = purple_account_get_protocol_id(purple_conversation_get_account(conv)); + protocol_id = purple_account_get_protocol_id(purple_conversation_get_account(conv)); if (PURPLE_IS_CHAT_CONVERSATION(conv)) is_im = FALSE; @@ -244,11 +244,11 @@ right_type = TRUE; - if ((c->flags & PURPLE_CMD_FLAG_PRPL_ONLY) && - !purple_strequal(c->prpl_id, prpl_id)) + if ((c->flags & PURPLE_CMD_FLAG_PROTOCOL_ONLY) && + !purple_strequal(c->protocol_id, protocol_id)) continue; - right_prpl = TRUE; + right_protocol = TRUE; /* this checks the allow bad args flag for us */ if (!purple_cmd_parse_args(c, rest, mrest, &args)) { @@ -280,8 +280,8 @@ if (!right_type) return PURPLE_CMD_STATUS_WRONG_TYPE; - if (!right_prpl) - return PURPLE_CMD_STATUS_WRONG_PRPL; + if (!right_protocol) + return PURPLE_CMD_STATUS_WRONG_PROTOCOL; if (!tried_cmd) return PURPLE_CMD_STATUS_WRONG_ARGS; @@ -314,8 +314,8 @@ if (!(c->flags & PURPLE_CMD_FLAG_CHAT)) continue; - if (conv && (c->flags & PURPLE_CMD_FLAG_PRPL_ONLY) && - !purple_strequal(c->prpl_id, purple_account_get_protocol_id(purple_conversation_get_account(conv)))) + if (conv && (c->flags & PURPLE_CMD_FLAG_PROTOCOL_ONLY) && + !purple_strequal(c->protocol_id, purple_account_get_protocol_id(purple_conversation_get_account(conv)))) continue; ret = g_list_append(ret, c->cmd); @@ -346,8 +346,8 @@ if (!(c->flags & PURPLE_CMD_FLAG_CHAT)) continue; - if (conv && (c->flags & PURPLE_CMD_FLAG_PRPL_ONLY) && - !purple_strequal(c->prpl_id, purple_account_get_protocol_id(purple_conversation_get_account(conv)))) + if (conv && (c->flags & PURPLE_CMD_FLAG_PROTOCOL_ONLY) && + !purple_strequal(c->protocol_id, purple_account_get_protocol_id(purple_conversation_get_account(conv)))) continue; ret = g_list_append(ret, c->help);
--- a/libpurple/cmds.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/cmds.h Sun Aug 18 01:53:00 2013 +0530 @@ -37,7 +37,7 @@ PURPLE_CMD_STATUS_FAILED, PURPLE_CMD_STATUS_NOT_FOUND, PURPLE_CMD_STATUS_WRONG_ARGS, - PURPLE_CMD_STATUS_WRONG_PRPL, + PURPLE_CMD_STATUS_WRONG_PROTOCOL, PURPLE_CMD_STATUS_WRONG_TYPE } PurpleCmdStatus; @@ -72,7 +72,7 @@ PURPLE_CMD_P_VERY_LOW = -1000, PURPLE_CMD_P_LOW = 0, PURPLE_CMD_P_DEFAULT = 1000, - PURPLE_CMD_P_PRPL = 2000, + PURPLE_CMD_P_PROTOCOL = 2000, PURPLE_CMD_P_PLUGIN = 3000, PURPLE_CMD_P_ALIAS = 4000, PURPLE_CMD_P_HIGH = 5000, @@ -91,7 +91,7 @@ /** Command is usable in multi-user chats. */ PURPLE_CMD_FLAG_CHAT = 0x02, /** Command is usable only for a particular prpl. */ - PURPLE_CMD_FLAG_PRPL_ONLY = 0x04, + PURPLE_CMD_FLAG_PROTOCOL_ONLY = 0x04, /** Incorrect arguments to this command should be accepted anyway. */ PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS = 0x08 } PurpleCmdFlag; @@ -139,7 +139,7 @@ * <tt>|</tt> (bitwise OR). You need to at least pass one of * #PURPLE_CMD_FLAG_IM or #PURPLE_CMD_FLAG_CHAT (you may pass both) in * order for the command to ever actually be called. - * @param prpl_id If the #PURPLE_CMD_FLAG_PRPL_ONLY flag is set, this is the id + * @param protocol_id If the #PURPLE_CMD_FLAG_PROTOCOL_ONLY flag is set, this is the id * of the prpl to which the command applies (such as * <tt>"prpl-msn"</tt>). If the flag is not set, this parameter * is ignored; pass @c NULL (or a humourous string of your @@ -157,7 +157,7 @@ * #purple_cmd_unregister, or @a 0 on failure. */ PurpleCmdId purple_cmd_register(const gchar *cmd, const gchar *args, PurpleCmdPriority p, PurpleCmdFlag f, - const gchar *prpl_id, PurpleCmdFunc func, const gchar *helpstr, void *data); + const gchar *protocol_id, PurpleCmdFunc func, const gchar *helpstr, void *data); /** * Unregister a command with the core.
--- a/libpurple/connection.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/connection.c Sun Aug 18 01:53:00 2013 +0530 @@ -53,7 +53,7 @@ /** Private data for a connection */ struct _PurpleConnectionPrivate { - PurplePlugin *prpl; /**< The protocol plugin. */ + PurpleProtocol *protocol; /**< The protocol. */ PurpleConnectionFlags flags; /**< Connection flags. */ PurpleConnectionState state; /**< The connection state. */ @@ -88,7 +88,7 @@ enum { PROP_0, - PROP_PRPL, + PROP_PROTOCOL, PROP_FLAGS, PROP_STATE, PROP_ACCOUNT, @@ -112,7 +112,6 @@ send_keepalive(gpointer data) { PurpleConnection *gc = data; - PurplePluginProtocolInfo *prpl_info; PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); /* Only send keep-alives if we haven't heard from the @@ -121,9 +120,8 @@ if ((time(NULL) - priv->last_received) < KEEPALIVE_INTERVAL) return TRUE; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(priv->prpl); - if (prpl_info->keepalive) - prpl_info->keepalive(gc); + if (priv->protocol->keepalive) + priv->protocol->keepalive(gc); return TRUE; } @@ -131,13 +129,11 @@ static void update_keepalive(PurpleConnection *gc, gboolean on) { - PurplePluginProtocolInfo *prpl_info = NULL; PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); - if (priv != NULL && priv->prpl != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(priv->prpl); + g_return_if_fail(priv != NULL); - if (!prpl_info || !prpl_info->keepalive) + if (!priv->protocol->keepalive) return; if (on && !priv->keepalive) @@ -320,14 +316,14 @@ return priv->account; } -PurplePlugin * -purple_connection_get_prpl(const PurpleConnection *gc) +PurpleProtocol * +purple_connection_get_protocol_info(const PurpleConnection *gc) { PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); g_return_val_if_fail(priv != NULL, NULL); - return priv->prpl; + return priv->protocol; } const char * @@ -604,7 +600,7 @@ * GObject code **************************************************************************/ /* GObject Property names */ -#define PROP_PRPL_S "prpl" +#define PROP_PROTOCOL_S "protocol" #define PROP_FLAGS_S "flags" #define PROP_STATE_S "state" #define PROP_ACCOUNT_S "account" @@ -620,9 +616,8 @@ PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); switch (param_id) { - case PROP_PRPL: -#warning TODO: change get_pointer to get_object when prpl is a GObject - priv->prpl = g_value_get_pointer(value); + case PROP_PROTOCOL: + priv->protocol = g_value_get_object(value); break; case PROP_FLAGS: purple_connection_set_flags(gc, g_value_get_flags(value)); @@ -654,9 +649,8 @@ PurpleConnection *gc = PURPLE_CONNECTION(obj); switch (param_id) { - case PROP_PRPL: -#warning TODO: change set_pointer to set_object when prpl is a GObject - g_value_set_pointer(value, purple_connection_get_prpl(gc)); + case PROP_PROTOCOL: + g_value_set_object(value, purple_connection_get_protocol_info(gc)); break; case PROP_FLAGS: g_value_set_flags(value, purple_connection_get_flags(gc)); @@ -714,7 +708,6 @@ PurpleConnectionPrivate *priv = PURPLE_CONNECTION_GET_PRIVATE(gc); PurpleAccount *account; GSList *buddies; - PurplePluginProtocolInfo *prpl_info = NULL; gboolean remove = FALSE; account = purple_connection_get_account(gc); @@ -739,9 +732,8 @@ purple_http_conn_cancel_all(gc); purple_proxy_connect_cancel_with_handle(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(priv->prpl); - if (prpl_info->close) - (prpl_info->close)(gc); + if (priv->protocol->close) + priv->protocol->close(gc); /* Clear out the proto data that was freed in the prpl close method*/ buddies = purple_blist_find_buddies(account, NULL); @@ -803,10 +795,10 @@ obj_class->get_property = purple_connection_get_property; obj_class->set_property = purple_connection_set_property; -#warning TODO: change spec_pointer to spec_object when prpl is a GObject - g_object_class_install_property(obj_class, PROP_PRPL, - g_param_spec_pointer(PROP_PRPL_S, _("Protocol plugin"), - _("The prpl that is using the connection."), + g_object_class_install_property(obj_class, PROP_PROTOCOL, + g_param_spec_object(PROP_PROTOCOL_S, _("Protocol"), + _("The protocol that the connection is using."), + PURPLE_TYPE_PROTOCOL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY) ); @@ -875,19 +867,16 @@ _purple_connection_new(PurpleAccount *account, gboolean regist, const char *password) { PurpleConnection *gc; - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; g_return_if_fail(account != NULL); if (!purple_account_is_disconnected(account)) return; - prpl = purple_find_prpl(purple_account_get_protocol_id(account)); + protocol = purple_find_protocol_info(purple_account_get_protocol_id(account)); - if (prpl != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - else { + if (protocol == NULL) { gchar *message; message = g_strdup_printf(_("Missing protocol plugin for %s"), @@ -900,14 +889,14 @@ if (regist) { - if (prpl_info->register_user == NULL) + if (protocol->register_user == NULL) return; } else { if (((password == NULL) || (*password == '\0')) && - !(prpl_info->options & OPT_PROTO_NO_PASSWORD) && - !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL)) + !(protocol->options & OPT_PROTO_NO_PASSWORD) && + !(protocol->options & OPT_PROTO_PASSWORD_OPTIONAL)) { purple_debug_error("connection", "Cannot connect to account %s without " "a password.\n", purple_account_get_username(account)); @@ -916,7 +905,7 @@ } gc = g_object_new(PURPLE_TYPE_CONNECTION, - PROP_PRPL_S, prpl, + PROP_PROTOCOL_S, protocol, PROP_PASSWORD_S, password, PROP_ACCOUNT_S, account, NULL); @@ -928,14 +917,14 @@ /* set this so we don't auto-reconnect after registering */ PURPLE_CONNECTION_GET_PRIVATE(gc)->wants_to_die = TRUE; - prpl_info->register_user(account); + protocol->register_user(account); } else { purple_debug_info("connection", "Connecting. gc = %p\n", gc); purple_signal_emit(purple_accounts_get_handle(), "account-connecting", account); - prpl_info->login(account); + protocol->login(account); } } @@ -945,16 +934,13 @@ { /* Lots of copy/pasted code to avoid API changes. You might want to integrate that into the previous function when posssible. */ PurpleConnection *gc; - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; g_return_if_fail(account != NULL); - prpl = purple_find_prpl(purple_account_get_protocol_id(account)); + protocol = purple_find_protocol_info(purple_account_get_protocol_id(account)); - if (prpl != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - else { + if (protocol == NULL) { gchar *message; message = g_strdup_printf(_("Missing protocol plugin for %s"), @@ -965,13 +951,13 @@ } if (!purple_account_is_disconnected(account)) { - prpl_info->unregister_user(account, cb, user_data); + protocol->unregister_user(account, cb, user_data); return; } if (((password == NULL) || (*password == '\0')) && - !(prpl_info->options & OPT_PROTO_NO_PASSWORD) && - !(prpl_info->options & OPT_PROTO_PASSWORD_OPTIONAL)) + !(protocol->options & OPT_PROTO_NO_PASSWORD) && + !(protocol->options & OPT_PROTO_PASSWORD_OPTIONAL)) { purple_debug_error("connection", "Cannot connect to account %s without " "a password.\n", purple_account_get_username(account)); @@ -979,14 +965,14 @@ } gc = g_object_new(PURPLE_TYPE_CONNECTION, - PROP_PRPL_S, prpl, + PROP_PROTOCOL_S, protocol, PROP_PASSWORD_S, password, PROP_ACCOUNT_S, account, NULL); purple_debug_info("connection", "Unregistering. gc = %p\n", gc); - prpl_info->unregister_user(account, cb, user_data); + protocol->unregister_user(account, cb, user_data); } /**************************************************************************
--- a/libpurple/connection.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/connection.h Sun Aug 18 01:53:00 2013 +0530 @@ -155,7 +155,7 @@ #include <time.h> #include "account.h" -#include "plugin.h" +#include "protocol.h" #include "status.h" #include "sslconn.h" @@ -357,7 +357,7 @@ * * @return The protocol plugin. */ -PurplePlugin * purple_connection_get_prpl(const PurpleConnection *gc); +PurpleProtocol *purple_connection_get_protocol_info(const PurpleConnection *gc); /** * Returns the connection's password.
--- a/libpurple/conversation.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/conversation.c Sun Aug 18 01:53:00 2013 +0530 @@ -29,7 +29,7 @@ #include "imgstore.h" #include "notify.h" #include "prefs.h" -#include "prpl.h" +#include "protocol.h" #include "request.h" #include "signals.h" #include "util.h" @@ -478,7 +478,7 @@ const char *message, PurpleMessageFlags flags, time_t mtime) { - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; PurpleConnection *gc = NULL; PurpleAccount *account; PurpleConversationUiOps *ops; @@ -528,10 +528,10 @@ } if (account != NULL) { - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account))); + protocol = purple_find_protocol_info(purple_account_get_protocol_id(account)); if (PURPLE_IS_IM_CONVERSATION(conv) || - !(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { + !(protocol->options & OPT_PROTO_UNIQUE_CHATNAME)) { if (flags & PURPLE_MESSAGE_SEND) { b = purple_blist_find_buddy(account,
--- a/libpurple/conversationtypes.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/conversationtypes.c Sun Aug 18 01:53:00 2013 +0530 @@ -454,19 +454,19 @@ { PurpleIMConversation *im = PURPLE_IM_CONVERSATION(object); PurpleConnection *gc = purple_conversation_get_connection(PURPLE_CONVERSATION(im)); - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; const char *name = purple_conversation_get_name(PURPLE_CONVERSATION(im)); if (gc != NULL) { /* Still connected */ - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + protocol = purple_connection_get_protocol_info(gc); if (purple_prefs_get_bool("/purple/conversations/im/send_typing")) serv_send_typing(gc, name, PURPLE_IM_NOT_TYPING); - if (gc && prpl_info->convo_closed != NULL) - prpl_info->convo_closed(gc, name); + if (gc && protocol->convo_closed != NULL) + protocol->convo_closed(gc, name); } purple_im_conversation_stop_typing_timeout(im); @@ -833,7 +833,7 @@ PurpleChatConversationPrivate *priv; PurpleAccount *account; PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; GList *ul, *fl; GList *cbuddies = NULL; @@ -848,8 +848,8 @@ account = purple_conversation_get_account(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); + protocol = purple_connection_get_protocol_info(gc); + g_return_if_fail(protocol != NULL); ul = users; fl = flags; @@ -860,7 +860,7 @@ PurpleChatUserFlags flag = GPOINTER_TO_INT(fl->data); const char *extra_msg = (extra_msgs ? extra_msgs->data : NULL); - if(!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { + if(!(protocol->options & OPT_PROTO_UNIQUE_CHATNAME)) { if (purple_strequal(priv->nick, purple_normalize(account, user))) { const char *alias2 = purple_account_get_private_alias(account); if (alias2 != NULL) @@ -935,7 +935,7 @@ PurpleConversationUiOps *ops; PurpleAccount *account; PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; PurpleChatUser *cb; PurpleChatUserFlags flags; PurpleChatConversationPrivate *priv; @@ -955,8 +955,8 @@ 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); + protocol = purple_connection_get_protocol_info(gc); + g_return_if_fail(protocol != NULL); if (purple_strequal(priv->nick, purple_normalize(account, old_user))) { const char *alias; @@ -964,7 +964,7 @@ /* Note this for later. */ is_me = TRUE; - if(!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { + if(!(protocol->options & OPT_PROTO_UNIQUE_CHATNAME)) { alias = purple_account_get_private_alias(account); if (alias != NULL) new_alias = alias; @@ -975,7 +975,7 @@ new_alias = display_name; } } - } else if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { + } else if (!(protocol->options & OPT_PROTO_UNIQUE_CHATNAME)) { PurpleBuddy *buddy; if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), new_user)) != NULL) new_alias = purple_buddy_get_contact_alias(buddy); @@ -1024,7 +1024,7 @@ char *escaped; char *escaped2; - if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { + if (!(protocol->options & OPT_PROTO_UNIQUE_CHATNAME)) { PurpleBuddy *buddy; if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), old_user)) != NULL) @@ -1062,7 +1062,7 @@ { PurpleConversation *conv; PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; PurpleConversationUiOps *ops; PurpleChatUser *cb; PurpleChatConversationPrivate *priv; @@ -1078,8 +1078,8 @@ 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); + protocol = purple_connection_get_protocol_info(gc); + g_return_if_fail(protocol != NULL); ops = purple_conversation_get_ui_ops(conv); @@ -1104,7 +1104,7 @@ char *alias_esc; char *tmp; - if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) { + if (!(protocol->options & OPT_PROTO_UNIQUE_CHATNAME)) { PurpleBuddy *buddy; if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), user)) != NULL)
--- a/libpurple/core.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/core.c Sun Aug 18 01:53:00 2013 +0530 @@ -40,7 +40,7 @@ #include "keyring.h" #include "network.h" #include "notify.h" -#include "plugin.h" +#include "plugins.h" #include "pounce.h" #include "prefs.h" #include "proxy.h" @@ -75,7 +75,8 @@ static PurpleCoreUiOps *_ops = NULL; static PurpleCore *_core = NULL; -STATIC_PROTO_INIT +STATIC_PROTO_LOAD +STATIC_PROTO_UNLOAD static void purple_core_print_version(void) @@ -166,17 +167,16 @@ #endif purple_cmds_init(); + purple_protocols_init(); + + /* Load all static protocols. */ + static_proto_load(); /* Since plugins get probed so early we should probably initialize their * subsystem right away too. */ purple_plugins_init(); - /* Initialize all static protocols. */ - static_proto_init(); - - purple_plugins_probe(G_MODULE_SUFFIX); - purple_keyring_init(); /* before accounts */ purple_theme_manager_init(); @@ -253,11 +253,6 @@ /* The SSL plugins must be uninit before they're unloaded */ purple_ssl_uninit(); - /* Unload all non-loader, non-prpl plugins before shutting down - * subsystems. */ - purple_debug_info("main", "Unloading normal plugins\n"); - purple_plugins_unload(PURPLE_PLUGIN_STANDARD); - /* Save .xml files, remove signals, etc. */ purple_smileys_uninit(); purple_http_uninit(); @@ -280,11 +275,6 @@ purple_imgstore_uninit(); purple_network_uninit(); - /* Everything after unloading all plugins must not fail if prpls aren't - * around */ - purple_debug_info("main", "Unloading all plugins\n"); - purple_plugins_destroy_all(); - ops = purple_core_get_ui_ops(); if (ops != NULL && ops->quit != NULL) ops->quit(); @@ -292,6 +282,10 @@ /* Everything after prefs_uninit must not try to read any prefs */ purple_prefs_uninit(); purple_plugins_uninit(); + + static_proto_unload(); + purple_protocols_uninit(); + #ifdef HAVE_DBUS purple_dbus_uninit(); #endif
--- a/libpurple/example/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/example/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -7,6 +7,7 @@ $(DBUS_LIBS) \ $(INTLLIBS) \ $(GLIB_LIBS) \ + $(GPLUGIN_LIBS) \ $(LIBXML_LIBS) \ $(top_builddir)/libpurple/libpurple.la @@ -21,5 +22,6 @@ -I$(top_srcdir) \ $(DEBUG_CFLAGS) \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(DBUS_CFLAGS) \ $(LIBXML_CFLAGS)
--- a/libpurple/example/nullclient.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/example/nullclient.c Sun Aug 18 01:53:00 2013 +0530 @@ -198,11 +198,6 @@ * copy this verbatim. */ purple_eventloop_set_ui_ops(&glib_eventloops); - /* Set path to search for plugins. The core (libpurple) takes care of loading the - * core-plugins, which includes the protocol-plugins. So it is not essential to add - * any path here, but it might be desired, especially for ui-specific plugins. */ - purple_plugins_add_search_path(CUSTOM_PLUGIN_PATH); - /* Now that all the essential stuff has been set, let's try to init the core. It's * necessary to provide a non-NULL name for the current ui to the core. This name * is used by stuff that depends on this ui, for example the ui-specific plugins. */ @@ -214,6 +209,12 @@ abort(); } + /* Set path to search for plugins. The core (libpurple) takes care of loading the + * core-plugins, which includes the protocol-plugins. So it is not essential to add + * any path here, but it might be desired, especially for ui-specific plugins. */ + purple_plugins_add_search_path(CUSTOM_PLUGIN_PATH); + purple_plugins_refresh(); + /* Load the preferences. */ purple_prefs_load(); @@ -263,10 +264,9 @@ printf("libpurple initialized.\n"); - iter = purple_plugins_get_protocols(); + iter = purple_protocols_get_all(); for (i = 0; iter; iter = iter->next) { - PurplePlugin *plugin = iter->data; - PurplePluginInfo *info = plugin->info; + PurpleProtocol *info = iter->data; if (info && info->name) { printf("\t%d: %s\n", i++, info->name); names = g_list_append(names, (gpointer)info->id);
--- a/libpurple/ft.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/ft.c Sun Aug 18 01:53:00 2013 +0530 @@ -55,7 +55,7 @@ enum { PURPLE_XFER_READY_NONE = 0x0, PURPLE_XFER_READY_UI = 0x1, - PURPLE_XFER_READY_PRPL = 0x2, + PURPLE_XFER_READY_PROTOCOL = 0x2, } ready; /* TODO: Should really use a PurpleCircBuffer for this. */ @@ -1307,7 +1307,7 @@ } /* Need to indicate the prpl is still ready... */ - priv->ready |= PURPLE_XFER_READY_PRPL; + priv->ready |= PURPLE_XFER_READY_PROTOCOL; g_return_if_reached(); } @@ -1383,7 +1383,7 @@ /* The UI is moderating its side manually */ PurpleXferPrivData *priv = g_hash_table_lookup(xfers_data, xfer); if (0 == (priv->ready & PURPLE_XFER_READY_UI)) { - priv->ready |= PURPLE_XFER_READY_PRPL; + priv->ready |= PURPLE_XFER_READY_PROTOCOL; purple_input_remove(xfer->watcher); xfer->watcher = 0; @@ -1458,7 +1458,7 @@ priv = g_hash_table_lookup(xfers_data, xfer); priv->ready |= PURPLE_XFER_READY_UI; - if (0 == (priv->ready & PURPLE_XFER_READY_PRPL)) { + if (0 == (priv->ready & PURPLE_XFER_READY_PROTOCOL)) { purple_debug_misc("xfer", "UI is ready on ft %p, waiting for prpl\n", xfer); return; } @@ -1480,14 +1480,14 @@ } void -purple_xfer_prpl_ready(PurpleXfer *xfer) +purple_xfer_protocol_ready(PurpleXfer *xfer) { PurpleXferPrivData *priv; g_return_if_fail(xfer != NULL); priv = g_hash_table_lookup(xfers_data, xfer); - priv->ready |= PURPLE_XFER_READY_PRPL; + priv->ready |= PURPLE_XFER_READY_PROTOCOL; /* I don't think fwrite/fread are ever *not* ready */ if (xfer->dest_fp == NULL && 0 == (priv->ready & PURPLE_XFER_READY_UI)) {
--- a/libpurple/ft.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/ft.h Sun Aug 18 01:53:00 2013 +0530 @@ -757,7 +757,7 @@ * * @param xfer The file transfer which is ready. */ -void purple_xfer_prpl_ready(PurpleXfer *xfer); +void purple_xfer_protocol_ready(PurpleXfer *xfer); /** * Gets the thumbnail data for a transfer
--- a/libpurple/internal.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/internal.h Sun Aug 18 01:53:00 2013 +0530 @@ -98,8 +98,6 @@ #include <langinfo.h> #endif -#include <gmodule.h> - #ifdef PURPLE_PLUGINS # ifdef HAVE_DLFCN_H # include <dlfcn.h> @@ -158,6 +156,7 @@ #include "accounts.h" #include "connection.h" +#include "prefs.h" /* This is for the accounts code to notify the buddy icon code that * it's done loading. We may want to replace this with a signal. */
--- a/libpurple/keyring.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/keyring.c Sun Aug 18 01:53:00 2013 +0530 @@ -33,6 +33,7 @@ #include "debug.h" #include "internal.h" #include "dbus-maybe.h" +#include "plugins.h" struct _PurpleKeyring { @@ -1228,7 +1229,7 @@ purple_keyring_init(void) { const gchar *touse; - GList *it; + GList *plugins, *it; purple_keyring_keyrings = NULL; purple_keyring_inuse = NULL; @@ -1282,24 +1283,28 @@ purple_keyring_pref_connect(); - for (it = purple_plugins_get_all(); it != NULL; it = it->next) + plugins = purple_plugins_find_all(); + for (it = plugins; it != NULL; it = it->next) { - PurplePlugin *plugin = (PurplePlugin *)it->data; + PurplePlugin *plugin = PURPLE_PLUGIN(it->data); + PurplePluginInfo *info = purple_plugin_get_info(plugin); - if (plugin->info == NULL || plugin->info->id == NULL) + if (info == NULL || purple_plugin_info_get_id(info) == NULL) continue; - if (strncmp(plugin->info->id, "keyring-", 8) != 0) + + if (strncmp(purple_plugin_info_get_id(info), "keyring-", 8) != 0) continue; if (purple_plugin_is_loaded(plugin)) continue; - if (purple_plugin_load(plugin)) + if (purple_plugin_load(plugin, NULL)) { purple_keyring_loaded_plugins = g_list_append( purple_keyring_loaded_plugins, plugin); } } + g_list_free(plugins); if (purple_keyring_inuse == NULL) purple_debug_error("keyring", "Selected keyring failed to load\n"); @@ -1328,10 +1333,10 @@ for (it = g_list_first(purple_keyring_loaded_plugins); it != NULL; it = g_list_next(it)) { - PurplePlugin *plugin = (PurplePlugin *)it->data; + PurplePlugin *plugin = PURPLE_PLUGIN(it->data); if (g_list_find(purple_plugins_get_loaded(), plugin) == NULL) continue; - purple_plugin_unload(plugin); + purple_plugin_unload(plugin, NULL); } g_list_free(purple_keyring_loaded_plugins); purple_keyring_loaded_plugins = NULL;
--- a/libpurple/log.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/log.c Sun Aug 18 01:53:00 2013 +0530 @@ -336,18 +336,17 @@ char * purple_log_get_log_dir(PurpleLogType type, const char *name, PurpleAccount *account) { - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; - const char *prpl_name; + PurpleProtocol *protocol; + const char *protocol_name; char *acct_name; const char *target; char *dir; - prpl = purple_find_prpl(purple_account_get_protocol_id(account)); - if (!prpl) + protocol = purple_find_protocol_info(purple_account_get_protocol_id(account)); + if (!protocol) return NULL; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - prpl_name = prpl_info->list_icon(account, NULL); + + protocol_name = protocol->list_icon(account, NULL); acct_name = g_strdup(purple_escape_filename(purple_normalize(account, purple_account_get_username(account)))); @@ -362,7 +361,7 @@ target = purple_escape_filename(purple_normalize(account, name)); } - dir = g_build_filename(purple_user_dir(), "logs", prpl_name, acct_name, target, NULL); + dir = g_build_filename(purple_user_dir(), "logs", protocol_name, acct_name, target, NULL); g_free(acct_name); @@ -1104,15 +1103,13 @@ /* Find all the accounts for protocol. */ for (account_iter = purple_accounts_get_all() ; account_iter != NULL ; account_iter = account_iter->next) { - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; - prpl = purple_find_prpl(purple_account_get_protocol_id((PurpleAccount *)account_iter->data)); - if (!prpl) + protocol = purple_find_protocol_info(purple_account_get_protocol_id((PurpleAccount *)account_iter->data)); + if (!protocol) continue; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (purple_strequal(protocol_unescaped, prpl_info->list_icon((PurpleAccount *)account_iter->data, NULL))) + if (purple_strequal(protocol_unescaped, protocol->list_icon((PurpleAccount *)account_iter->data, NULL))) accounts = g_list_prepend(accounts, account_iter->data); } g_free(protocol_unescaped); @@ -1406,13 +1403,13 @@ char *date; char *header; char *escaped_from; - PurplePlugin *plugin = purple_find_prpl(purple_account_get_protocol_id(log->account)); + PurpleProtocol *protocol = + purple_find_protocol_info(purple_account_get_protocol_id(log->account)); PurpleLogCommonLoggerData *data = log->logger_data; gsize written = 0; if(!data) { - const char *prpl = - PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL); + const char *prpl = protocol->list_icon(log->account, NULL); const char *date; purple_log_common_writer(log, ".html"); @@ -1561,7 +1558,8 @@ const char *from, time_t time, const char *message) { char *date; - PurplePlugin *plugin = purple_find_prpl(purple_account_get_protocol_id(log->account)); + PurpleProtocol *protocol = + purple_find_protocol_info(purple_account_get_protocol_id(log->account)); PurpleLogCommonLoggerData *data = log->logger_data; char *stripped = NULL; @@ -1572,8 +1570,7 @@ * creating a new file there would result in empty files in the case * that you open a convo with someone, but don't say anything. */ - const char *prpl = - PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->list_icon(log->account, NULL); + const char *prpl = protocol->list_icon(log->account, NULL); purple_log_common_writer(log, ".txt"); data = log->logger_data;
--- a/libpurple/media.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/media.c Sun Aug 18 01:53:00 2013 +0530 @@ -78,7 +78,7 @@ PurpleMediaBackend *backend; gchar *conference_type; gboolean initiator; - gpointer prpl_data; + gpointer protocol_data; GHashTable *sessions; /* PurpleMediaSession table */ GList *participants; @@ -135,7 +135,7 @@ PROP_ACCOUNT, PROP_CONFERENCE_TYPE, PROP_INITIATOR, - PROP_PRPL_DATA, + PROP_PROTOCOL_DATA, }; #endif @@ -217,7 +217,7 @@ FALSE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); - g_object_class_install_property(gobject_class, PROP_PRPL_DATA, + g_object_class_install_property(gobject_class, PROP_PROTOCOL_DATA, g_param_spec_pointer("prpl-data", "gpointer", "Data the prpl plugin set on the media session.", @@ -395,8 +395,8 @@ case PROP_INITIATOR: media->priv->initiator = g_value_get_boolean(value); break; - case PROP_PRPL_DATA: - media->priv->prpl_data = g_value_get_pointer(value); + case PROP_PROTOCOL_DATA: + media->priv->protocol_data = g_value_get_pointer(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -429,8 +429,8 @@ case PROP_INITIATOR: g_value_set_boolean(value, media->priv->initiator); break; - case PROP_PRPL_DATA: - g_value_set_pointer(value, media->priv->prpl_data); + case PROP_PROTOCOL_DATA: + g_value_set_pointer(value, media->priv->protocol_data); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -589,24 +589,24 @@ } gpointer -purple_media_get_prpl_data(PurpleMedia *media) +purple_media_get_protocol_data(PurpleMedia *media) { #ifdef USE_VV - gpointer prpl_data; + gpointer protocol_data; g_return_val_if_fail(PURPLE_IS_MEDIA(media), NULL); - g_object_get(G_OBJECT(media), "prpl-data", &prpl_data, NULL); - return prpl_data; + g_object_get(G_OBJECT(media), "prpl-data", &protocol_data, NULL); + return protocol_data; #else return NULL; #endif } void -purple_media_set_prpl_data(PurpleMedia *media, gpointer prpl_data) +purple_media_set_protocol_data(PurpleMedia *media, gpointer protocol_data) { #ifdef USE_VV g_return_if_fail(PURPLE_IS_MEDIA(media)); - g_object_set(G_OBJECT(media), "prpl-data", prpl_data, NULL); + g_object_set(G_OBJECT(media), "prpl-data", protocol_data, NULL); #endif }
--- a/libpurple/media.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/media.h Sun Aug 18 01:53:00 2013 +0530 @@ -108,15 +108,15 @@ * * @return The prpl data retrieved. */ -gpointer purple_media_get_prpl_data(PurpleMedia *media); +gpointer purple_media_get_protocol_data(PurpleMedia *media); /** * Sets the prpl data on the media session. * * @param media The media session to set the prpl data on. - * @param prpl_data The data to set on the media session. + * @param protocol_data The data to set on the media session. */ -void purple_media_set_prpl_data(PurpleMedia *media, gpointer prpl_data); +void purple_media_set_protocol_data(PurpleMedia *media, gpointer protocol_data); /** * Signals an error in the media session.
--- a/libpurple/media/backend-fs2.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/media/backend-fs2.c Sun Aug 18 01:53:00 2013 +0530 @@ -1975,7 +1975,7 @@ /* check if the prpl has already specified a relay-info we need to do this to allow them to override when using non-standard TURN modes, like Google f.ex. */ - gboolean got_turn_from_prpl = FALSE; + gboolean got_turn_from_protocol = FALSE; int i; session = get_session(self, sess_id); @@ -2015,7 +2015,7 @@ for (i = 0 ; i < num_params ; i++) { if (purple_strequal(params[i].name, "relay-info")) { - got_turn_from_prpl = TRUE; + got_turn_from_protocol = TRUE; break; } } @@ -2039,7 +2039,7 @@ ++_num_params; } - if (turn_ip && !strcmp("nice", transmitter) && !got_turn_from_prpl) { + if (turn_ip && !strcmp("nice", transmitter) && !got_turn_from_protocol) { G_GNUC_BEGIN_IGNORE_DEPRECATIONS GValueArray *relay_info = g_value_array_new(0); G_GNUC_END_IGNORE_DEPRECATIONS
--- a/libpurple/mediamanager.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/mediamanager.c Sun Aug 18 01:53:00 2013 +0530 @@ -456,7 +456,7 @@ GstElement *src = gst_bin_get_by_name(GST_BIN(manager->priv->pipeline), id); if (src) { - GstElement *capsfilter = gst_bin_get_by_name(GST_BIN(src), "prpl_video_caps"); + GstElement *capsfilter = gst_bin_get_by_name(GST_BIN(src), "protocol_video_caps"); g_object_set(G_OBJECT(capsfilter), "caps", caps, NULL); } @@ -530,7 +530,7 @@ GstElement *capsfilter; videoscale = gst_element_factory_make("videoscale", NULL); - capsfilter = gst_element_factory_make("capsfilter", "prpl_video_caps"); + capsfilter = gst_element_factory_make("capsfilter", "protocol_video_caps"); g_object_set(G_OBJECT(capsfilter), "caps", purple_media_manager_get_video_caps(manager), NULL);
--- a/libpurple/notify.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/notify.h Sun Aug 18 01:53:00 2013 +0530 @@ -54,8 +54,8 @@ typedef enum { PURPLE_NOTIFY_MESSAGE = 0, /**< Message notification. */ - PURPLE_NOTIFY_EMAIL, /**< Single email notification. */ - PURPLE_NOTIFY_EMAILS, /**< Multiple email notification. */ + PURPLE_NOTIFY_EMAIL, /**< Single email notification. */ + PURPLE_NOTIFY_EMAILS, /**< Multiple email notification. */ PURPLE_NOTIFY_FORMATTED, /**< Formatted text. */ PURPLE_NOTIFY_SEARCHRESULTS, /**< Buddy search results. */ PURPLE_NOTIFY_USERINFO, /**< Formatted userinfo text. */ @@ -716,7 +716,7 @@ /*@}*/ /**************************************************************************/ -/** @name Notify Subsystem */ +/** @name Notify Subsystem */ /**************************************************************************/ /*@{*/
--- a/libpurple/plugin.c Sun Aug 18 01:52:32 2013 +0530 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1626 +0,0 @@ -/* - * 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 - */ -#define _PURPLE_PLUGIN_C_ - -#include "internal.h" - -#include "accountopt.h" -#include "core.h" -#include "dbus-maybe.h" -#include "debug.h" -#include "notify.h" -#include "prefs.h" -#include "prpl.h" -#include "request.h" -#include "signals.h" -#include "util.h" -#include "valgrind.h" -#include "version.h" - -typedef struct -{ - GHashTable *commands; - size_t command_count; - -} PurplePluginIpcInfo; - -typedef struct -{ - PurpleCallback func; - PurpleSignalMarshalFunc marshal; - - int num_params; - GType *param_types; - GType ret_type; - -} PurplePluginIpcCommand; - -static GList *search_paths = NULL; -static GList *plugins = NULL; -static GList *loaded_plugins = NULL; -static GList *protocol_plugins = NULL; -#ifdef PURPLE_PLUGINS -static GList *load_queue = NULL; -static GList *plugin_loaders = NULL; -static GList *plugins_to_disable = NULL; -#endif - -#ifdef PURPLE_PLUGINS - -static gboolean -has_file_extension(const char *filename, const char *ext) -{ - int len, extlen; - - if (filename == NULL || *filename == '\0' || ext == NULL) - return 0; - - extlen = strlen(ext); - len = strlen(filename) - extlen; - - if (len < 0) - return 0; - - return (strncmp(filename + len, ext, extlen) == 0); -} - -static gboolean -is_native(const char *filename) -{ - const char *last_period; - - last_period = strrchr(filename, '.'); - if (last_period == NULL) - return FALSE; - - return !(strcmp(last_period, ".dll") & - strcmp(last_period, ".sl") & - strcmp(last_period, ".so")); -} - -static char * -purple_plugin_get_basename(const char *filename) -{ - const char *basename; - const char *last_period; - - basename = strrchr(filename, G_DIR_SEPARATOR); - if (basename != NULL) - basename++; - else - basename = filename; - - if (is_native(basename) && - ((last_period = strrchr(basename, '.')) != NULL)) - return g_strndup(basename, (last_period - basename)); - - return g_strdup(basename); -} - -static gboolean -loader_supports_file(PurplePlugin *loader, const char *filename) -{ - GList *exts; - - for (exts = PURPLE_PLUGIN_LOADER_INFO(loader)->exts; exts != NULL; exts = exts->next) { - if (has_file_extension(filename, (char *)exts->data)) { - return TRUE; - } - } - - return FALSE; -} - -static PurplePlugin * -find_loader_for_plugin(const PurplePlugin *plugin) -{ - PurplePlugin *loader; - GList *l; - - if (plugin->path == NULL) - return NULL; - - for (l = purple_plugins_get_loaded(); l != NULL; l = l->next) { - loader = l->data; - - if (loader->info->type == PURPLE_PLUGIN_LOADER && - loader_supports_file(loader, plugin->path)) { - - return loader; - } - - loader = NULL; - } - - return NULL; -} - -#endif /* PURPLE_PLUGINS */ - -/** - * Negative if a before b, 0 if equal, positive if a after b. - */ -static gint -compare_prpl(PurplePlugin *a, PurplePlugin *b) -{ - if(PURPLE_IS_PROTOCOL_PLUGIN(a)) { - if(PURPLE_IS_PROTOCOL_PLUGIN(b)) - return strcmp(a->info->name, b->info->name); - else - return -1; - } else { - if(PURPLE_IS_PROTOCOL_PLUGIN(b)) - return 1; - else - return 0; - } -} - -PurplePlugin * -purple_plugin_new(gboolean native, const char *path) -{ - PurplePlugin *plugin; - - plugin = g_new0(PurplePlugin, 1); - - plugin->native_plugin = native; - plugin->path = g_strdup(path); - - PURPLE_DBUS_REGISTER_POINTER(plugin, PurplePlugin); - - return plugin; -} - -PurplePlugin * -purple_plugin_probe(const char *filename) -{ -#ifdef PURPLE_PLUGINS - PurplePlugin *plugin = NULL; - PurplePlugin *loader; - gpointer unpunned; - gchar *basename = NULL; - gboolean (*purple_init_plugin)(PurplePlugin *); - - purple_debug_misc("plugins", "probing %s\n", filename); - g_return_val_if_fail(filename != NULL, NULL); - - if (!g_file_test(filename, G_FILE_TEST_EXISTS)) - return NULL; - - /* If this plugin has already been probed then exit */ - basename = purple_plugin_get_basename(filename); - plugin = purple_plugins_find_with_basename(basename); - g_free(basename); - if (plugin != NULL) - { - if (purple_strequal(filename, plugin->path)) - return plugin; - else if (!purple_plugin_is_unloadable(plugin)) - { - purple_debug_warning("plugins", "Not loading %s. " - "Another plugin with the same name (%s) has already been loaded.\n", - filename, plugin->path); - return plugin; - } - else - { - /* The old plugin was a different file and it was unloadable. - * There's no guarantee that this new file with the same name - * will be loadable, but unless it fails in one of the silent - * ways and the first one didn't, it's not any worse. The user - * will still see a greyed-out plugin, which is what we want. */ - purple_plugin_destroy(plugin); - } - } - - plugin = purple_plugin_new(has_file_extension(filename, G_MODULE_SUFFIX), filename); - - if (plugin->native_plugin) { - const char *error; -#ifdef _WIN32 - /* Suppress error popups for failing to load plugins */ - UINT old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS); -#endif - - /* - * We pass G_MODULE_BIND_LOCAL here to prevent symbols from - * plugins being added to the global name space. - * - * G_MODULE_BIND_LOCAL was added in glib 2.3.3. - */ - plugin->handle = g_module_open(filename, G_MODULE_BIND_LOCAL); - - if (plugin->handle == NULL) - { - const char *error = g_module_error(); - if (error != NULL && purple_str_has_prefix(error, filename)) - { - error = error + strlen(filename); - - /* These are just so we don't crash. If we - * got this far, they should always be true. */ - if (*error == ':') - error++; - if (*error == ' ') - error++; - } - - if (error == NULL || !*error) - { - plugin->error = g_strdup(_("Unknown error")); - purple_debug_error("plugins", "%s is not loadable: Unknown error\n", - plugin->path); - } - else - { - plugin->error = g_strdup(error); - purple_debug_error("plugins", "%s is not loadable: %s\n", - plugin->path, plugin->error); - } - plugin->handle = g_module_open(filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); - - if (plugin->handle == NULL) - { -#ifdef _WIN32 - /* Restore the original error mode */ - SetErrorMode(old_error_mode); -#endif - purple_plugin_destroy(plugin); - return NULL; - } - else - { - /* We were able to load the plugin with lazy symbol binding. - * This means we're missing some symbol. Mark it as - * unloadable and keep going so we get the info to display - * to the user so they know to rebuild this plugin. */ - plugin->unloadable = TRUE; - } - } - - if (!g_module_symbol(plugin->handle, "purple_init_plugin", - &unpunned)) - { - purple_debug_error("plugins", "%s is not usable because the " - "'purple_init_plugin' symbol could not be " - "found. Does the plugin call the " - "PURPLE_INIT_PLUGIN() macro?\n", plugin->path); - - g_module_close(plugin->handle); - error = g_module_error(); - if (error != NULL) - purple_debug_error("plugins", "Error closing module %s: %s\n", - plugin->path, error); - plugin->handle = NULL; - -#ifdef _WIN32 - /* Restore the original error mode */ - SetErrorMode(old_error_mode); -#endif - purple_plugin_destroy(plugin); - return NULL; - } - purple_init_plugin = unpunned; - -#ifdef _WIN32 - /* Restore the original error mode */ - SetErrorMode(old_error_mode); -#endif - } - else { - loader = find_loader_for_plugin(plugin); - - if (loader == NULL) { - purple_plugin_destroy(plugin); - return NULL; - } - - purple_init_plugin = PURPLE_PLUGIN_LOADER_INFO(loader)->probe; - } - - if (!purple_init_plugin(plugin) || plugin->info == NULL) - { - purple_plugin_destroy(plugin); - return NULL; - } - else if (plugin->info->ui_requirement && - !purple_strequal(plugin->info->ui_requirement, purple_core_get_ui())) - { - plugin->error = g_strdup_printf(_("You are using %s, but this plugin requires %s."), - purple_core_get_ui(), plugin->info->ui_requirement); - purple_debug_error("plugins", "%s is not loadable: The UI requirement is not met. (%s)\n", plugin->path, plugin->error); - plugin->unloadable = TRUE; - return plugin; - } - - /* - * Check to make sure a plugin has defined an id. - * Not having this check caused purple_plugin_unload to - * enter an infinite loop in certain situations by passing - * purple_find_plugin_by_id a NULL value. -- ecoffey - */ - if (plugin->info->id == NULL || *plugin->info->id == '\0') - { - plugin->error = g_strdup(_("This plugin has not defined an ID.")); - purple_debug_error("plugins", "%s is not loadable: info->id is not defined.\n", plugin->path); - plugin->unloadable = TRUE; - return plugin; - } - - /* Really old plugins. */ - if (plugin->info->magic != PURPLE_PLUGIN_MAGIC) - { - if (plugin->info->magic >= 2 && plugin->info->magic <= 4) - { - struct _PurplePluginInfo2 - { - unsigned int api_version; - PurplePluginType type; - char *ui_requirement; - unsigned long flags; - GList *dependencies; - PurplePluginPriority priority; - - char *id; - char *name; - char *version; - char *summary; - char *description; - char *author; - char *homepage; - - gboolean (*load)(PurplePlugin *plugin); - gboolean (*unload)(PurplePlugin *plugin); - void (*destroy)(PurplePlugin *plugin); - - void *ui_info; - void *extra_info; - PurplePluginUiInfo *prefs_info; - GList *(*actions)(PurplePlugin *plugin, gpointer context); - } *info2 = (struct _PurplePluginInfo2 *)plugin->info; - - /* This leaks... but only for ancient plugins, so deal with it. */ - plugin->info = g_new0(PurplePluginInfo, 1); - - /* We don't really need all these to display the plugin info, but - * I'm copying them all for good measure. */ - plugin->info->magic = info2->api_version; - plugin->info->type = info2->type; - plugin->info->ui_requirement = info2->ui_requirement; - plugin->info->flags = info2->flags; - plugin->info->dependencies = info2->dependencies; - plugin->info->id = info2->id; - plugin->info->name = info2->name; - plugin->info->version = info2->version; - plugin->info->summary = info2->summary; - plugin->info->description = info2->description; - plugin->info->author = info2->author; - plugin->info->homepage = info2->homepage; - plugin->info->load = info2->load; - plugin->info->unload = info2->unload; - plugin->info->destroy = info2->destroy; - plugin->info->ui_info = info2->ui_info; - plugin->info->extra_info = info2->extra_info; - - if (info2->api_version >= 3) - plugin->info->prefs_info = info2->prefs_info; - - if (info2->api_version >= 4) - plugin->info->actions = info2->actions; - - - plugin->error = g_strdup_printf(_("Plugin magic mismatch %d (need %d)"), - plugin->info->magic, PURPLE_PLUGIN_MAGIC); - purple_debug_error("plugins", "%s is not loadable: Plugin magic mismatch %d (need %d)\n", - plugin->path, plugin->info->magic, PURPLE_PLUGIN_MAGIC); - plugin->unloadable = TRUE; - return plugin; - } - - purple_debug_error("plugins", "%s is not loadable: Plugin magic mismatch %d (need %d)\n", - plugin->path, plugin->info->magic, PURPLE_PLUGIN_MAGIC); - purple_plugin_destroy(plugin); - return NULL; - } - - if (plugin->info->major_version != PURPLE_MAJOR_VERSION || - plugin->info->minor_version > PURPLE_MINOR_VERSION) - { - plugin->error = g_strdup_printf(_("ABI version mismatch %d.%d.x (need %d.%d.x)"), - plugin->info->major_version, plugin->info->minor_version, - PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION); - purple_debug_error("plugins", "%s is not loadable: ABI version mismatch %d.%d.x (need %d.%d.x)\n", - plugin->path, plugin->info->major_version, plugin->info->minor_version, - PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION); - plugin->unloadable = TRUE; - return plugin; - } - - if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL) - { - /* If plugin is a PRPL, make sure it implements the required functions */ - if ((PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->list_icon == NULL) || - (PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->login == NULL) || - (PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->close == NULL)) - { - plugin->error = g_strdup(_("Plugin does not implement all required functions (list_icon, login and close)")); - purple_debug_error("plugins", "%s is not loadable: %s\n", - plugin->path, plugin->error); - plugin->unloadable = TRUE; - return plugin; - } - - /* For debugging, let's warn about prpl prefs. */ - if (plugin->info->prefs_info != NULL) - { - purple_debug_error("plugins", "%s has a prefs_info, but is a prpl. This is no longer supported.\n", - plugin->path); - } - } - - return plugin; -#else - return NULL; -#endif /* !PURPLE_PLUGINS */ -} - -#ifdef PURPLE_PLUGINS -static gint -compare_plugins(gconstpointer a, gconstpointer b) -{ - const PurplePlugin *plugina = a; - const PurplePlugin *pluginb = b; - - return strcmp(plugina->info->name, pluginb->info->name); -} -#endif /* PURPLE_PLUGINS */ - -gboolean -purple_plugin_load(PurplePlugin *plugin) -{ -#ifdef PURPLE_PLUGINS - GList *dep_list = NULL; - GList *l; - - g_return_val_if_fail(plugin != NULL, FALSE); - - if (purple_plugin_is_loaded(plugin)) - return TRUE; - - if (purple_plugin_is_unloadable(plugin)) - return FALSE; - - g_return_val_if_fail(plugin->error == NULL, FALSE); - - /* - * Go through the list of the plugin's dependencies. - * - * First pass: Make sure all the plugins needed are probed. - */ - for (l = plugin->info->dependencies; l != NULL; l = l->next) - { - const char *dep_name = (const char *)l->data; - PurplePlugin *dep_plugin; - - dep_plugin = purple_plugins_find_with_id(dep_name); - - if (dep_plugin == NULL) - { - char *tmp; - - tmp = g_strdup_printf(_("The required plugin %s was not found. " - "Please install this plugin and try again."), - dep_name); - - purple_notify_error(NULL, NULL, - _("Unable to load the plugin"), tmp); - g_free(tmp); - - g_list_free(dep_list); - - return FALSE; - } - - dep_list = g_list_append(dep_list, dep_plugin); - } - - /* Second pass: load all the required plugins. */ - for (l = dep_list; l != NULL; l = l->next) - { - PurplePlugin *dep_plugin = (PurplePlugin *)l->data; - - if (!purple_plugin_is_loaded(dep_plugin)) - { - if (!purple_plugin_load(dep_plugin)) - { - char *tmp; - - tmp = g_strdup_printf(_("The required plugin %s was unable to load."), - plugin->info->name); - - purple_notify_error(NULL, NULL, - _("Unable to load your plugin."), tmp); - g_free(tmp); - - g_list_free(dep_list); - - return FALSE; - } - } - } - - /* Third pass: note that other plugins are dependencies of this plugin. - * This is done separately in case we had to bail out earlier. */ - for (l = dep_list; l != NULL; l = l->next) - { - PurplePlugin *dep_plugin = (PurplePlugin *)l->data; - dep_plugin->dependent_plugins = g_list_prepend(dep_plugin->dependent_plugins, (gpointer)plugin->info->id); - } - - g_list_free(dep_list); - - if (plugin->native_plugin) - { - if (plugin->info->load != NULL && !plugin->info->load(plugin)) - return FALSE; - } - else { - PurplePlugin *loader; - PurplePluginLoaderInfo *loader_info; - - loader = find_loader_for_plugin(plugin); - - if (loader == NULL) - return FALSE; - - loader_info = PURPLE_PLUGIN_LOADER_INFO(loader); - - if (loader_info->load != NULL) - { - if (!loader_info->load(plugin)) - return FALSE; - } - } - - loaded_plugins = g_list_insert_sorted(loaded_plugins, plugin, compare_plugins); - - plugin->loaded = TRUE; - - purple_signal_emit(purple_plugins_get_handle(), "plugin-load", plugin); - - return TRUE; - -#else - return TRUE; -#endif /* !PURPLE_PLUGINS */ -} - -gboolean -purple_plugin_unload(PurplePlugin *plugin) -{ -#ifdef PURPLE_PLUGINS - GList *l; - GList *ll; - - g_return_val_if_fail(plugin != NULL, FALSE); - g_return_val_if_fail(purple_plugin_is_loaded(plugin), FALSE); - - purple_debug_info("plugins", "Unloading plugin %s\n", plugin->info->name); - - /* Unload all plugins that depend on this plugin. */ - for (l = plugin->dependent_plugins; l != NULL; l = ll) { - const char * dep_name = (const char *)l->data; - PurplePlugin *dep_plugin; - - /* Store a pointer to the next element in the list. - * This is because we'll be modifying this list in the loop. */ - ll = l->next; - - dep_plugin = purple_plugins_find_with_id(dep_name); - - if (dep_plugin != NULL && purple_plugin_is_loaded(dep_plugin)) - { - if (!purple_plugin_unload(dep_plugin)) - { - g_free(plugin->error); - plugin->error = g_strdup_printf(_("%s requires %s, but it failed to unload."), - _(plugin->info->name), - _(dep_plugin->info->name)); - return FALSE; - } - else - { -#if 0 - /* This isn't necessary. This has already been done when unloading dep_plugin. */ - plugin->dependent_plugins = g_list_delete_link(plugin->dependent_plugins, l); -#endif - } - } - } - - /* Remove this plugin from each dependency's dependent_plugins list. */ - for (l = plugin->info->dependencies; l != NULL; l = l->next) - { - const char *dep_name = (const char *)l->data; - PurplePlugin *dependency; - - dependency = purple_plugins_find_with_id(dep_name); - - if (dependency != NULL) - dependency->dependent_plugins = g_list_remove(dependency->dependent_plugins, plugin->info->id); - else - purple_debug_error("plugins", "Unable to remove from dependency list for %s\n", dep_name); - } - - if (plugin->native_plugin) { - if (plugin->info->unload && !plugin->info->unload(plugin)) - return FALSE; - - if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL) { - PurplePluginProtocolInfo *prpl_info; - GList *l; - - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); - - for (l = prpl_info->user_splits; l != NULL; l = l->next) - purple_account_user_split_destroy(l->data); - - for (l = prpl_info->protocol_options; l != NULL; l = l->next) - purple_account_option_destroy(l->data); - - if (prpl_info->user_splits != NULL) { - g_list_free(prpl_info->user_splits); - prpl_info->user_splits = NULL; - } - - if (prpl_info->protocol_options != NULL) { - g_list_free(prpl_info->protocol_options); - prpl_info->protocol_options = NULL; - } - } - } else { - PurplePlugin *loader; - PurplePluginLoaderInfo *loader_info; - - loader = find_loader_for_plugin(plugin); - - if (loader == NULL) - return FALSE; - - loader_info = PURPLE_PLUGIN_LOADER_INFO(loader); - - if (loader_info->unload && !loader_info->unload(plugin)) - return FALSE; - } - - /* cancel any pending dialogs the plugin has */ - purple_request_close_with_handle(plugin); - purple_notify_close_with_handle(plugin); - - purple_signals_disconnect_by_handle(plugin); - purple_plugin_ipc_unregister_all(plugin); - - loaded_plugins = g_list_remove(loaded_plugins, plugin); - if ((plugin->info != NULL) && PURPLE_IS_PROTOCOL_PLUGIN(plugin)) - protocol_plugins = g_list_remove(protocol_plugins, plugin); - plugins_to_disable = g_list_remove(plugins_to_disable, plugin); - plugin->loaded = FALSE; - - /* We wouldn't be anywhere near here if the plugin wasn't loaded, so - * if plugin->error is set at all, it had to be from a previous - * unload failure. It's obviously okay now. - */ - g_free(plugin->error); - plugin->error = NULL; - - purple_signal_emit(purple_plugins_get_handle(), "plugin-unload", plugin); - - purple_prefs_disconnect_by_handle(plugin); - - return TRUE; -#else - return TRUE; -#endif /* PURPLE_PLUGINS */ -} - -void -purple_plugin_disable(PurplePlugin *plugin) -{ -#ifdef PURPLE_PLUGINS - g_return_if_fail(plugin != NULL); - - if (!g_list_find(plugins_to_disable, plugin)) - plugins_to_disable = g_list_prepend(plugins_to_disable, plugin); -#endif -} - -gboolean -purple_plugin_reload(PurplePlugin *plugin) -{ -#ifdef PURPLE_PLUGINS - g_return_val_if_fail(plugin != NULL, FALSE); - g_return_val_if_fail(purple_plugin_is_loaded(plugin), FALSE); - - if (!purple_plugin_unload(plugin)) - return FALSE; - - if (!purple_plugin_load(plugin)) - return FALSE; - - return TRUE; -#else - return TRUE; -#endif /* !PURPLE_PLUGINS */ -} - -void -purple_plugin_destroy(PurplePlugin *plugin) -{ -#ifdef PURPLE_PLUGINS - g_return_if_fail(plugin != NULL); - - if (purple_plugin_is_loaded(plugin)) - purple_plugin_unload(plugin); - - plugins = g_list_remove(plugins, plugin); - - if (load_queue != NULL) - load_queue = g_list_remove(load_queue, plugin); - - /* true, this may leak a little memory if there is a major version - * mismatch, but it's a lot better than trying to free something - * we shouldn't, and crashing while trying to load an old plugin */ - if(plugin->info == NULL || plugin->info->magic != PURPLE_PLUGIN_MAGIC || - plugin->info->major_version != PURPLE_MAJOR_VERSION) - { - if(plugin->handle) - g_module_close(plugin->handle); - - g_free(plugin->path); - g_free(plugin->error); - - PURPLE_DBUS_UNREGISTER_POINTER(plugin); - - g_free(plugin); - return; - } - - if (plugin->info != NULL) - g_list_free(plugin->info->dependencies); - - if (plugin->native_plugin) - { - if (plugin->info != NULL && plugin->info->type == PURPLE_PLUGIN_LOADER) - { - PurplePluginLoaderInfo *loader_info; - GList *exts, *l, *next_l; - PurplePlugin *p2; - - loader_info = PURPLE_PLUGIN_LOADER_INFO(plugin); - - if (loader_info != NULL && loader_info->exts != NULL) - { - for (exts = PURPLE_PLUGIN_LOADER_INFO(plugin)->exts; - exts != NULL; - exts = exts->next) { - - for (l = purple_plugins_get_all(); l != NULL; l = next_l) - { - next_l = l->next; - - p2 = l->data; - - if (p2->path != NULL && - has_file_extension(p2->path, exts->data)) - { - purple_plugin_destroy(p2); - } - } - } - - g_list_free(loader_info->exts); - loader_info->exts = NULL; - } - - plugin_loaders = g_list_remove(plugin_loaders, plugin); - } - - if (plugin->info != NULL && plugin->info->destroy != NULL) - plugin->info->destroy(plugin); - - /* - * I find it extremely useful to do this when using valgrind, as - * it keeps all the plugins open, meaning that valgrind is able to - * resolve symbol names in leak traces from plugins. - */ - if (!g_getenv("PURPLE_LEAKCHECK_HELP") && !RUNNING_ON_VALGRIND) - { - if (plugin->handle != NULL) - g_module_close(plugin->handle); - } - } - else - { - PurplePlugin *loader; - PurplePluginLoaderInfo *loader_info; - - loader = find_loader_for_plugin(plugin); - - if (loader != NULL) - { - loader_info = PURPLE_PLUGIN_LOADER_INFO(loader); - - if (loader_info->destroy != NULL) - loader_info->destroy(plugin); - } - } - - g_free(plugin->path); - g_free(plugin->error); - - PURPLE_DBUS_UNREGISTER_POINTER(plugin); - - g_free(plugin); -#endif /* !PURPLE_PLUGINS */ -} - -gboolean -purple_plugin_is_loaded(const PurplePlugin *plugin) -{ - g_return_val_if_fail(plugin != NULL, FALSE); - - return plugin->loaded; -} - -gboolean -purple_plugin_is_unloadable(const PurplePlugin *plugin) -{ - g_return_val_if_fail(plugin != NULL, FALSE); - - return plugin->unloadable; -} - -const gchar * -purple_plugin_get_id(const PurplePlugin *plugin) { - g_return_val_if_fail(plugin, NULL); - g_return_val_if_fail(plugin->info, NULL); - - return plugin->info->id; -} - -const gchar * -purple_plugin_get_name(const PurplePlugin *plugin) { - g_return_val_if_fail(plugin, NULL); - g_return_val_if_fail(plugin->info, NULL); - - return _(plugin->info->name); -} - -const gchar * -purple_plugin_get_version(const PurplePlugin *plugin) { - g_return_val_if_fail(plugin, NULL); - g_return_val_if_fail(plugin->info, NULL); - - return plugin->info->version; -} - -const gchar * -purple_plugin_get_summary(const PurplePlugin *plugin) { - g_return_val_if_fail(plugin, NULL); - g_return_val_if_fail(plugin->info, NULL); - - return _(plugin->info->summary); -} - -const gchar * -purple_plugin_get_description(const PurplePlugin *plugin) { - g_return_val_if_fail(plugin, NULL); - g_return_val_if_fail(plugin->info, NULL); - - return _(plugin->info->description); -} - -const gchar * -purple_plugin_get_author(const PurplePlugin *plugin) { - g_return_val_if_fail(plugin, NULL); - g_return_val_if_fail(plugin->info, NULL); - - return _(plugin->info->author); -} - -const gchar * -purple_plugin_get_homepage(const PurplePlugin *plugin) { - g_return_val_if_fail(plugin, NULL); - g_return_val_if_fail(plugin->info, NULL); - - return plugin->info->homepage; -} - -/************************************************************************** - * Plugin IPC - **************************************************************************/ -static void -destroy_ipc_info(void *data) -{ - PurplePluginIpcCommand *ipc_command = (PurplePluginIpcCommand *)data; - - g_free(ipc_command->param_types); - g_free(ipc_command); -} - -gboolean -purple_plugin_ipc_register(PurplePlugin *plugin, const char *command, - PurpleCallback func, PurpleSignalMarshalFunc marshal, - GType ret_type, int num_params, ...) -{ - PurplePluginIpcInfo *ipc_info; - PurplePluginIpcCommand *ipc_command; - - g_return_val_if_fail(plugin != NULL, FALSE); - g_return_val_if_fail(command != NULL, FALSE); - g_return_val_if_fail(func != NULL, FALSE); - g_return_val_if_fail(marshal != NULL, FALSE); - - if (plugin->ipc_data == NULL) - { - ipc_info = plugin->ipc_data = g_new0(PurplePluginIpcInfo, 1); - ipc_info->commands = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, destroy_ipc_info); - } - else - ipc_info = (PurplePluginIpcInfo *)plugin->ipc_data; - - ipc_command = g_new0(PurplePluginIpcCommand, 1); - ipc_command->func = func; - ipc_command->marshal = marshal; - ipc_command->num_params = num_params; - ipc_command->ret_type = ret_type; - - if (num_params > 0) - { - va_list args; - int i; - - ipc_command->param_types = g_new0(GType, num_params); - - va_start(args, num_params); - - for (i = 0; i < num_params; i++) - ipc_command->param_types[i] = va_arg(args, GType); - - va_end(args); - } - - g_hash_table_replace(ipc_info->commands, g_strdup(command), ipc_command); - - ipc_info->command_count++; - - return TRUE; -} - -void -purple_plugin_ipc_unregister(PurplePlugin *plugin, const char *command) -{ - PurplePluginIpcInfo *ipc_info; - - g_return_if_fail(plugin != NULL); - g_return_if_fail(command != NULL); - - ipc_info = (PurplePluginIpcInfo *)plugin->ipc_data; - - if (ipc_info == NULL || - g_hash_table_lookup(ipc_info->commands, command) == NULL) - { - purple_debug_error("plugins", - "IPC command '%s' was not registered for plugin %s\n", - command, plugin->info->name); - return; - } - - g_hash_table_remove(ipc_info->commands, command); - - ipc_info->command_count--; - - if (ipc_info->command_count == 0) - { - g_hash_table_destroy(ipc_info->commands); - g_free(ipc_info); - - plugin->ipc_data = NULL; - } -} - -void -purple_plugin_ipc_unregister_all(PurplePlugin *plugin) -{ - PurplePluginIpcInfo *ipc_info; - - g_return_if_fail(plugin != NULL); - - if (plugin->ipc_data == NULL) - return; /* Silently ignore it. */ - - ipc_info = (PurplePluginIpcInfo *)plugin->ipc_data; - - g_hash_table_destroy(ipc_info->commands); - g_free(ipc_info); - - plugin->ipc_data = NULL; -} - -gboolean -purple_plugin_ipc_get_types(PurplePlugin *plugin, const char *command, - GType *ret_type, int *num_params, - GType **param_types) -{ - PurplePluginIpcInfo *ipc_info; - PurplePluginIpcCommand *ipc_command; - - g_return_val_if_fail(plugin != NULL, FALSE); - g_return_val_if_fail(command != NULL, FALSE); - - ipc_info = (PurplePluginIpcInfo *)plugin->ipc_data; - - if (ipc_info == NULL || - (ipc_command = g_hash_table_lookup(ipc_info->commands, - command)) == NULL) - { - purple_debug_error("plugins", - "IPC command '%s' was not registered for plugin %s\n", - command, plugin->info->name); - - return FALSE; - } - - if (num_params != NULL) - *num_params = ipc_command->num_params; - - if (param_types != NULL) - *param_types = ipc_command->param_types; - - if (ret_type != NULL) - *ret_type = ipc_command->ret_type; - - return TRUE; -} - -void * -purple_plugin_ipc_call(PurplePlugin *plugin, const char *command, - gboolean *ok, ...) -{ - PurplePluginIpcInfo *ipc_info; - PurplePluginIpcCommand *ipc_command; - va_list args; - void *ret_value; - - if (ok != NULL) - *ok = FALSE; - - g_return_val_if_fail(plugin != NULL, NULL); - g_return_val_if_fail(command != NULL, NULL); - - ipc_info = (PurplePluginIpcInfo *)plugin->ipc_data; - - if (ipc_info == NULL || - (ipc_command = g_hash_table_lookup(ipc_info->commands, - command)) == NULL) - { - purple_debug_error("plugins", - "IPC command '%s' was not registered for plugin %s\n", - command, plugin->info->name); - - return NULL; - } - - va_start(args, ok); - ipc_command->marshal(ipc_command->func, args, NULL, &ret_value); - va_end(args); - - if (ok != NULL) - *ok = TRUE; - - return ret_value; -} - -/************************************************************************** - * Plugins subsystem - **************************************************************************/ -void * -purple_plugins_get_handle(void) { - static int handle; - - return &handle; -} - -void -purple_plugins_init(void) { - void *handle = purple_plugins_get_handle(); - - purple_plugins_add_search_path(LIBDIR); - - purple_signal_register(handle, "plugin-load", - purple_marshal_VOID__POINTER, - G_TYPE_NONE, 1, PURPLE_TYPE_PLUGIN); - purple_signal_register(handle, "plugin-unload", - purple_marshal_VOID__POINTER, - G_TYPE_NONE, 1, PURPLE_TYPE_PLUGIN); -} - -void -purple_plugins_uninit(void) -{ - void *handle = purple_plugins_get_handle(); - - purple_signals_disconnect_by_handle(handle); - purple_signals_unregister_by_instance(handle); - - while (search_paths) { - g_free(search_paths->data); - search_paths = g_list_delete_link(search_paths, search_paths); - } -} - -/************************************************************************** - * Plugins API - **************************************************************************/ -void -purple_plugins_add_search_path(const char *path) -{ - g_return_if_fail(path != NULL); - - if (g_list_find_custom(search_paths, path, (GCompareFunc)strcmp)) - return; - - search_paths = g_list_append(search_paths, g_strdup(path)); -} - -GList * -purple_plugins_get_search_paths() -{ - return search_paths; -} - -void -purple_plugins_unload_all(void) -{ -#ifdef PURPLE_PLUGINS - - while (loaded_plugins != NULL) - purple_plugin_unload(loaded_plugins->data); - -#endif /* PURPLE_PLUGINS */ -} - -void -purple_plugins_unload(PurplePluginType type) -{ -#ifdef PURPLE_PLUGINS - GList *l; - - for (l = plugins; l; l = l->next) { - PurplePlugin *plugin = l->data; - if (plugin->info->type == type && purple_plugin_is_loaded(plugin)) - purple_plugin_unload(plugin); - } - -#endif /* PURPLE_PLUGINS */ -} - -void -purple_plugins_destroy_all(void) -{ -#ifdef PURPLE_PLUGINS - - while (plugins != NULL) - purple_plugin_destroy(plugins->data); - -#endif /* PURPLE_PLUGINS */ -} - -void -purple_plugins_save_loaded(const char *key) -{ -#ifdef PURPLE_PLUGINS - GList *pl; - GList *files = NULL; - - for (pl = purple_plugins_get_loaded(); pl != NULL; pl = pl->next) { - PurplePlugin *plugin = pl->data; - - if (plugin->info->type != PURPLE_PLUGIN_PROTOCOL && - plugin->info->type != PURPLE_PLUGIN_LOADER && - !g_list_find(plugins_to_disable, plugin)) { - files = g_list_append(files, plugin->path); - } - } - - purple_prefs_set_path_list(key, files); - g_list_free(files); -#endif -} - -void -purple_plugins_load_saved(const char *key) -{ -#ifdef PURPLE_PLUGINS - GList *f, *files; - - g_return_if_fail(key != NULL); - - files = purple_prefs_get_path_list(key); - - for (f = files; f; f = f->next) - { - char *filename; - char *basename; - PurplePlugin *plugin; - - if (f->data == NULL) - continue; - - filename = f->data; - - /* - * We don't know if the filename uses Windows or Unix path - * separators (because people might be sharing a prefs.xml - * file across systems), so we find the last occurrence - * of either. - */ - basename = strrchr(filename, '/'); - if ((basename == NULL) || (basename < strrchr(filename, '\\'))) - basename = strrchr(filename, '\\'); - if (basename != NULL) - basename++; - - /* Strip the extension */ - if (basename) - basename = purple_plugin_get_basename(basename); - - if (((plugin = purple_plugins_find_with_filename(filename)) != NULL) || - (basename && (plugin = purple_plugins_find_with_basename(basename)) != NULL) || - ((plugin = purple_plugin_probe(filename)) != NULL)) - { - purple_debug_info("plugins", "Loading saved plugin %s\n", - plugin->path); - purple_plugin_load(plugin); - } - else - { - purple_debug_error("plugins", "Unable to find saved plugin %s\n", - filename); - } - - g_free(basename); - - g_free(f->data); - } - - g_list_free(files); -#endif /* PURPLE_PLUGINS */ -} - - -void -purple_plugins_probe(const char *ext) -{ -#ifdef PURPLE_PLUGINS - GDir *dir; - const gchar *file; - gchar *path; - PurplePlugin *plugin; - GList *cur; - const char *search_path; - - if (!g_module_supported()) - return; - - /* Probe plugins */ - for (cur = search_paths; cur != NULL; cur = cur->next) - { - search_path = cur->data; - - dir = g_dir_open(search_path, 0, NULL); - - if (dir != NULL) - { - while ((file = g_dir_read_name(dir)) != NULL) - { - path = g_build_filename(search_path, file, NULL); - - if (ext == NULL || has_file_extension(file, ext)) - purple_plugin_probe(path); - - g_free(path); - } - - g_dir_close(dir); - } - } - - /* See if we have any plugins waiting to load */ - while (load_queue != NULL) - { - plugin = (PurplePlugin *)load_queue->data; - - load_queue = g_list_remove(load_queue, plugin); - - if (plugin == NULL || plugin->info == NULL) - continue; - - if (plugin->info->type == PURPLE_PLUGIN_LOADER) - { - /* We'll just load this right now. */ - if (!purple_plugin_load(plugin)) - { - purple_plugin_destroy(plugin); - - continue; - } - - plugin_loaders = g_list_append(plugin_loaders, plugin); - - for (cur = PURPLE_PLUGIN_LOADER_INFO(plugin)->exts; - cur != NULL; - cur = cur->next) - { - purple_plugins_probe(cur->data); - } - } - else if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL) - { - /* We'll just load this right now. */ - if (!purple_plugin_load(plugin)) - { - purple_plugin_destroy(plugin); - - continue; - } - - /* Make sure we don't load two PRPLs with the same name? */ - if (purple_find_prpl(plugin->info->id)) - { - /* Nothing to see here--move along, move along */ - purple_plugin_destroy(plugin); - - continue; - } - - protocol_plugins = g_list_insert_sorted(protocol_plugins, plugin, - (GCompareFunc)compare_prpl); - } - } -#endif /* PURPLE_PLUGINS */ -} - -gboolean -purple_plugin_register(PurplePlugin *plugin) -{ - g_return_val_if_fail(plugin != NULL, FALSE); - - /* If this plugin has been registered already then exit */ - if (g_list_find(plugins, plugin)) - return TRUE; - - /* Ensure the plugin has the requisite information */ - if (plugin->info->type == PURPLE_PLUGIN_LOADER) - { - PurplePluginLoaderInfo *loader_info; - - loader_info = PURPLE_PLUGIN_LOADER_INFO(plugin); - - if (loader_info == NULL) - { - purple_debug_error("plugins", "%s is not loadable, loader plugin missing loader_info\n", - plugin->path); - return FALSE; - } - } - else if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL) - { - PurplePluginProtocolInfo *prpl_info; - - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); - - if (prpl_info == NULL) - { - purple_debug_error("plugins", "%s is not loadable, protocol plugin missing prpl_info\n", - plugin->path); - return FALSE; - } - } - -#ifdef PURPLE_PLUGINS - /* This plugin should be probed and maybe loaded--add it to the queue */ - load_queue = g_list_append(load_queue, plugin); -#else - if (plugin->info != NULL) - { - if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL) - protocol_plugins = g_list_insert_sorted(protocol_plugins, plugin, - (GCompareFunc)compare_prpl); - if (plugin->info->load != NULL) - if (!plugin->info->load(plugin)) - return FALSE; - } -#endif - - plugins = g_list_append(plugins, plugin); - - return TRUE; -} - -gboolean -purple_plugins_enabled(void) -{ -#ifdef PURPLE_PLUGINS - return TRUE; -#else - return FALSE; -#endif -} - -PurplePlugin * -purple_plugins_find_with_name(const char *name) -{ - PurplePlugin *plugin; - GList *l; - - for (l = plugins; l != NULL; l = l->next) { - plugin = l->data; - - if (purple_strequal(plugin->info->name, name)) - return plugin; - } - - return NULL; -} - -PurplePlugin * -purple_plugins_find_with_filename(const char *filename) -{ - PurplePlugin *plugin; - GList *l; - - for (l = plugins; l != NULL; l = l->next) { - plugin = l->data; - - if (purple_strequal(plugin->path, filename)) - return plugin; - } - - return NULL; -} - -PurplePlugin * -purple_plugins_find_with_basename(const char *basename) -{ -#ifdef PURPLE_PLUGINS - PurplePlugin *plugin; - GList *l; - char *tmp; - - g_return_val_if_fail(basename != NULL, NULL); - - for (l = plugins; l != NULL; l = l->next) - { - plugin = (PurplePlugin *)l->data; - - if (plugin->path != NULL) { - tmp = purple_plugin_get_basename(plugin->path); - if (purple_strequal(tmp, basename)) - { - g_free(tmp); - return plugin; - } - g_free(tmp); - } - } - -#endif /* PURPLE_PLUGINS */ - - return NULL; -} - -PurplePlugin * -purple_plugins_find_with_id(const char *id) -{ - PurplePlugin *plugin; - GList *l; - - g_return_val_if_fail(id != NULL, NULL); - - for (l = plugins; l != NULL; l = l->next) - { - plugin = l->data; - - if (purple_strequal(plugin->info->id, id)) - return plugin; - } - - return NULL; -} - -GList * -purple_plugins_get_loaded(void) -{ - return loaded_plugins; -} - -GList * -purple_plugins_get_protocols(void) -{ - return protocol_plugins; -} - -GList * -purple_plugins_get_all(void) -{ - return plugins; -} - - -PurplePluginAction * -purple_plugin_action_new(const char* label, void (*callback)(PurplePluginAction *)) -{ - PurplePluginAction *act = g_new0(PurplePluginAction, 1); - - act->label = g_strdup(label); - act->callback = callback; - - return act; -} - -void -purple_plugin_action_free(PurplePluginAction *action) -{ - g_return_if_fail(action != NULL); - - g_free(action->label); - g_free(action); -} - -static PurplePlugin * -purple_plugin_copy(PurplePlugin *plugin) -{ - PurplePlugin *plugin_copy; - - g_return_val_if_fail(plugin != NULL, NULL); - - plugin_copy = g_new(PurplePlugin, 1); - *plugin_copy = *plugin; - - return plugin_copy; -} - -GType -purple_plugin_get_type(void) -{ - static GType type = 0; - - if (type == 0) { - type = g_boxed_type_register_static("PurplePlugin", - (GBoxedCopyFunc)purple_plugin_copy, - (GBoxedFreeFunc)g_free); - } - - return type; -}
--- a/libpurple/plugin.h Sun Aug 18 01:52:32 2013 +0530 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,675 +0,0 @@ -/** - * @file plugin.h Plugin API - * @ingroup core - * @see @ref plugin-signals - * @see @ref plugin-ids - * @see @ref plugin-i18n - */ - -/* 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 _PURPLE_PLUGIN_H_ -#define _PURPLE_PLUGIN_H_ - -#include <glib.h> -#include <gmodule.h> -#include "signals.h" - -/** Returns the GType for the PurplePlugin boxed structure */ -#define PURPLE_TYPE_PLUGIN (purple_plugin_get_type()) - -/** @copydoc _PurplePlugin */ -typedef struct _PurplePlugin PurplePlugin; -/** @copydoc _PurplePluginInfo */ -typedef struct _PurplePluginInfo PurplePluginInfo; -/** @copydoc _PurplePluginUiInfo */ -typedef struct _PurplePluginUiInfo PurplePluginUiInfo; -/** @copydoc _PurplePluginLoaderInfo */ -typedef struct _PurplePluginLoaderInfo PurplePluginLoaderInfo; - -/** @copydoc _PurplePluginAction */ -typedef struct _PurplePluginAction PurplePluginAction; - -typedef int PurplePluginPriority; /**< Plugin priority. */ - -#include "pluginpref.h" - -/** - * Plugin types. - */ -typedef enum -{ - PURPLE_PLUGIN_UNKNOWN = -1, /**< Unknown type. */ - PURPLE_PLUGIN_STANDARD = 0, /**< Standard plugin. */ - PURPLE_PLUGIN_LOADER, /**< Loader plugin. */ - PURPLE_PLUGIN_PROTOCOL /**< Protocol plugin. */ - -} PurplePluginType; - -#define PURPLE_PRIORITY_DEFAULT 0 -#define PURPLE_PRIORITY_HIGHEST 9999 -#define PURPLE_PRIORITY_LOWEST -9999 - -#define PURPLE_PLUGIN_FLAG_INVISIBLE 0x01 - -#define PURPLE_PLUGIN_MAGIC 5 /* once we hit 6.0.0 I think we can remove this */ - -/** - * Detailed information about a plugin. - * - * This is used in the version 2.0 API and up. - */ -struct _PurplePluginInfo -{ - unsigned int magic; - unsigned int major_version; - unsigned int minor_version; - PurplePluginType type; - char *ui_requirement; - unsigned long flags; - GList *dependencies; - PurplePluginPriority priority; - - const char *id; - const char *name; - const char *version; - const char *summary; - const char *description; - const char *author; - const char *homepage; - - /** - * If a plugin defines a 'load' function, and it returns FALSE, - * then the plugin will not be loaded. - */ - gboolean (*load)(PurplePlugin *plugin); - gboolean (*unload)(PurplePlugin *plugin); - void (*destroy)(PurplePlugin *plugin); - - void *ui_info; /**< Used only by UI-specific plugins to build a preference screen with a custom UI */ - void *extra_info; - PurplePluginUiInfo *prefs_info; /**< Used by any plugin to display preferences. If #ui_info has been specified, this will be ignored. */ - - /** - * This callback has a different use depending on whether this - * plugin type is PURPLE_PLUGIN_STANDARD or PURPLE_PLUGIN_PROTOCOL. - * - * If PURPLE_PLUGIN_STANDARD then the list of actions will show up - * in the Tools menu, under a submenu with the name of the plugin. - * context will be NULL. - * - * If PURPLE_PLUGIN_PROTOCOL then the list of actions will show up - * in the Accounts menu, under a submenu with the name of the - * account. context will be set to the PurpleConnection for that - * account. This callback will only be called for online accounts. - */ - GList *(*actions)(PurplePlugin *plugin, gpointer context); - - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -}; - -/** - * Extra information for loader plugins. - */ -struct _PurplePluginLoaderInfo -{ - GList *exts; - - gboolean (*probe)(PurplePlugin *plugin); - gboolean (*load)(PurplePlugin *plugin); - gboolean (*unload)(PurplePlugin *plugin); - void (*destroy)(PurplePlugin *plugin); - - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -}; - -/** - * A plugin handle. - */ -struct _PurplePlugin -{ - gboolean native_plugin; /**< Native C plugin. */ - gboolean loaded; /**< The loaded state. */ - void *handle; /**< The module handle. */ - char *path; /**< The path to the plugin. */ - PurplePluginInfo *info; /**< The plugin information. */ - char *error; - void *ipc_data; /**< IPC data. */ - void *extra; /**< Plugin-specific data. */ - gboolean unloadable; /**< Unloadable */ - GList *dependent_plugins; /**< Plugins depending on this */ - - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -}; - -#define PURPLE_PLUGIN_LOADER_INFO(plugin) \ - ((PurplePluginLoaderInfo *)(plugin)->info->extra_info) - -struct _PurplePluginUiInfo { - PurplePluginPrefFrame *(*get_plugin_pref_frame)(PurplePlugin *plugin); - - int page_num; /**< Reserved */ - PurplePluginPrefFrame *frame; /**< Reserved */ - - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -}; - -#define PURPLE_PLUGIN_HAS_PREF_FRAME(plugin) \ - ((plugin)->info != NULL && (plugin)->info->prefs_info != NULL) - -#define PURPLE_PLUGIN_UI_INFO(plugin) \ - ((PurplePluginUiInfo*)(plugin)->info->prefs_info) - - -/** - * The structure used in the actions member of PurplePluginInfo - */ -struct _PurplePluginAction { - char *label; - void (*callback)(PurplePluginAction *); - - /** set to the owning plugin */ - PurplePlugin *plugin; - - /** NULL for plugin actions menu, set to the PurpleConnection for - account actions menu */ - gpointer context; - - gpointer user_data; -}; - -#define PURPLE_PLUGIN_HAS_ACTIONS(plugin) \ - ((plugin)->info != NULL && (plugin)->info->actions != NULL) - -#define PURPLE_PLUGIN_ACTIONS(plugin, context) \ - (PURPLE_PLUGIN_HAS_ACTIONS(plugin)? \ - (plugin)->info->actions(plugin, context): NULL) - - -/** - * Handles the initialization of modules. - */ -#if !defined(PURPLE_PLUGINS) || defined(PURPLE_STATIC_PRPL) -# define _FUNC_NAME(x) purple_init_##x##_plugin -# define PURPLE_INIT_PLUGIN(pluginname, initfunc, plugininfo) \ - gboolean _FUNC_NAME(pluginname)(void);\ - gboolean _FUNC_NAME(pluginname)(void) { \ - PurplePlugin *plugin = purple_plugin_new(TRUE, NULL); \ - plugin->info = &(plugininfo); \ - initfunc((plugin)); \ - purple_plugin_load((plugin)); \ - return purple_plugin_register(plugin); \ - } -#else /* PURPLE_PLUGINS && !PURPLE_STATIC_PRPL */ -# define PURPLE_INIT_PLUGIN(pluginname, initfunc, plugininfo) \ - G_MODULE_EXPORT gboolean purple_init_plugin(PurplePlugin *plugin); \ - G_MODULE_EXPORT gboolean purple_init_plugin(PurplePlugin *plugin) { \ - plugin->info = &(plugininfo); \ - initfunc((plugin)); \ - return purple_plugin_register(plugin); \ - } -#endif - - -G_BEGIN_DECLS - -/**************************************************************************/ -/** @name Plugin API */ -/**************************************************************************/ -/*@{*/ - -/** - * Returns the GType for the PurplePlugin boxed structure. - * TODO Boxing of PurplePlugin is a temporary solution to having a GType for - * plugins. This should rather be a GObject instead of a GBoxed. - */ -GType purple_plugin_get_type(void); - -/** - * Creates a new plugin structure. - * - * @param native Whether or not the plugin is native. - * @param path The path to the plugin, or @c NULL if statically compiled. - * - * @return A new PurplePlugin structure. - */ -PurplePlugin *purple_plugin_new(gboolean native, const char *path); - -/** - * Probes a plugin, retrieving the information on it and adding it to the - * list of available plugins. - * - * @param filename The plugin's filename. - * - * @return The plugin handle. - * - * @see purple_plugin_load() - * @see purple_plugin_destroy() - */ -PurplePlugin *purple_plugin_probe(const char *filename); - -/** - * Registers a plugin and prepares it for loading. - * - * This shouldn't be called by anything but the internal module code. - * Plugins should use the PURPLE_INIT_PLUGIN() macro to register themselves - * with the core. - * - * @param plugin The plugin to register. - * - * @return @c TRUE if the plugin was registered successfully. Otherwise - * @c FALSE is returned (this happens if the plugin does not contain - * the necessary information). - */ -gboolean purple_plugin_register(PurplePlugin *plugin); - -/** - * Attempts to load a previously probed plugin. - * - * @param plugin The plugin to load. - * - * @return @c TRUE if successful, or @c FALSE otherwise. - * - * @see purple_plugin_reload() - * @see purple_plugin_unload() - */ -gboolean purple_plugin_load(PurplePlugin *plugin); - -/** - * Unloads the specified plugin. - * - * @param plugin The plugin handle. - * - * @return @c TRUE if successful, or @c FALSE otherwise. - * - * @see purple_plugin_load() - * @see purple_plugin_reload() - */ -gboolean purple_plugin_unload(PurplePlugin *plugin); - -/** - * Disable a plugin. - * - * This function adds the plugin to a list of plugins to "disable at the next - * 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. - */ -void purple_plugin_disable(PurplePlugin *plugin); - -/** - * Reloads a plugin. - * - * @param plugin The old plugin handle. - * - * @return @c TRUE if successful, or @c FALSE otherwise. - * - * @see purple_plugin_load() - * @see purple_plugin_unload() - */ -gboolean purple_plugin_reload(PurplePlugin *plugin); - -/** - * Unloads a plugin and destroys the structure from memory. - * - * @param plugin The plugin handle. - */ -void purple_plugin_destroy(PurplePlugin *plugin); - -/** - * Returns whether or not a plugin is currently loaded. - * - * @param plugin The plugin. - * - * @return @c TRUE if loaded, or @c FALSE otherwise. - */ -gboolean purple_plugin_is_loaded(const PurplePlugin *plugin); - -/** - * Returns whether or not a plugin is unloadable. - * - * If this returns @c TRUE, the plugin is guaranteed to not - * be loadable. However, a return value of @c FALSE does not - * guarantee the plugin is loadable. - * - * @param plugin The plugin. - * - * @return @c TRUE if the plugin is known to be unloadable,\ - * @c FALSE otherwise - */ -gboolean purple_plugin_is_unloadable(const PurplePlugin *plugin); - -/** - * Returns a plugin's id. - * - * @param plugin The plugin. - * - * @return The plugin's id. - */ -const gchar *purple_plugin_get_id(const PurplePlugin *plugin); - -/** - * Returns a plugin's name. - * - * @param plugin The plugin. - * - * @return THe name of the plugin, or @c NULL. - */ -const gchar *purple_plugin_get_name(const PurplePlugin *plugin); - -/** - * Returns a plugin's version. - * - * @param plugin The plugin. - * - * @return The plugin's version or @c NULL. - */ -const gchar *purple_plugin_get_version(const PurplePlugin *plugin); - -/** - * Returns a plugin's summary. - * - * @param plugin The plugin. - * - * @return The plugin's summary. - */ -const gchar *purple_plugin_get_summary(const PurplePlugin *plugin); - -/** - * Returns a plugin's description. - * - * @param plugin The plugin. - * - * @return The plugin's description. - */ -const gchar *purple_plugin_get_description(const PurplePlugin *plugin); - -/** - * Returns a plugin's author. - * - * @param plugin The plugin. - * - * @return The plugin's author. - */ -const gchar *purple_plugin_get_author(const PurplePlugin *plugin); - -/** - * Returns a plugin's homepage. - * - * @param plugin The plugin. - * - * @return The plugin's homepage. - */ -const gchar *purple_plugin_get_homepage(const PurplePlugin *plugin); - -/*@}*/ - -/**************************************************************************/ -/** @name Plugin IPC API */ -/**************************************************************************/ -/*@{*/ - -/** - * Registers an IPC command in a plugin. - * - * @param plugin The plugin to register the command with. - * @param command The name of the command. - * @param func The function to execute. - * @param marshal The marshalling function. - * @param ret_type The return type. - * @param num_params The number of parameters. - * @param ... The parameter types. - * - * @return TRUE if the function was registered successfully, or - * FALSE otherwise. - */ -gboolean purple_plugin_ipc_register(PurplePlugin *plugin, const char *command, - PurpleCallback func, - PurpleSignalMarshalFunc marshal, - GType ret_type, int num_params, ...); - -/** - * Unregisters an IPC command in a plugin. - * - * @param plugin The plugin to unregister the command from. - * @param command The name of the command. - */ -void purple_plugin_ipc_unregister(PurplePlugin *plugin, const char *command); - -/** - * Unregisters all IPC commands in a plugin. - * - * @param plugin The plugin to unregister the commands from. - */ -void purple_plugin_ipc_unregister_all(PurplePlugin *plugin); - -/** - * Returns a list of value types used for an IPC command. - * - * @param plugin The plugin. - * @param command The name of the command. - * @param ret_type The returned return type. - * @param num_params The returned number of parameters. - * @param param_types The returned list of parameter types. - * - * @return TRUE if the command was found, or FALSE otherwise. - */ -gboolean purple_plugin_ipc_get_types(PurplePlugin *plugin, const char *command, - GType *ret_type, int *num_params, - GType **param_types); - -/** - * Executes an IPC command. - * - * @param plugin The plugin to execute the command on. - * @param command The name of the command. - * @param ok TRUE if the call was successful, or FALSE otherwise. - * @param ... The parameters to pass. - * - * @return The return value, which will be NULL if the command doesn't - * return a value. - */ -void *purple_plugin_ipc_call(PurplePlugin *plugin, const char *command, - gboolean *ok, ...); - -/*@}*/ - -/**************************************************************************/ -/** @name Plugins API */ -/**************************************************************************/ -/*@{*/ - -/** - * Add a new directory to search for plugins - * - * @param path The new search path. - */ -void purple_plugins_add_search_path(const char *path); - -/** - * Returns a list of plugin search paths. - * - * @constreturn A list of searched paths. - */ -GList *purple_plugins_get_search_paths(void); - -/** - * Unloads all loaded plugins. - */ -void purple_plugins_unload_all(void); - -/** - * Unloads all plugins of a specific type. - */ -void purple_plugins_unload(PurplePluginType type); - -/** - * Destroys all registered plugins. - */ -void purple_plugins_destroy_all(void); - -/** - * Saves the list of loaded plugins to the specified preference key - * - * @param key The preference key to save the list of plugins to. - */ -void purple_plugins_save_loaded(const char *key); - -/** - * Attempts to load all the plugins in the specified preference key - * that were loaded when purple last quit. - * - * @param key The preference key containing the list of plugins. - */ -void purple_plugins_load_saved(const char *key); - -/** - * Probes for plugins in the registered module paths. - * - * @param ext The extension type to probe for, or @c NULL for all. - * - * @see purple_plugin_set_probe_path() - */ -void purple_plugins_probe(const char *ext); - -/** - * Returns whether or not plugin support is enabled. - * - * @return TRUE if plugin support is enabled, or FALSE otherwise. - */ -gboolean purple_plugins_enabled(void); - -/** - * Finds a plugin with the specified name. - * - * @param name The plugin name. - * - * @return The plugin if found, or @c NULL if not found. - */ -PurplePlugin *purple_plugins_find_with_name(const char *name); - -/** - * Finds a plugin with the specified filename (filename with a path). - * - * @param filename The plugin filename. - * - * @return The plugin if found, or @c NULL if not found. - */ -PurplePlugin *purple_plugins_find_with_filename(const char *filename); - -/** - * Finds a plugin with the specified basename (filename without a path). - * - * @param basename The plugin basename. - * - * @return The plugin if found, or @c NULL if not found. - */ -PurplePlugin *purple_plugins_find_with_basename(const char *basename); - -/** - * Finds a plugin with the specified plugin ID. - * - * @param id The plugin ID. - * - * @return The plugin if found, or @c NULL if not found. - */ -PurplePlugin *purple_plugins_find_with_id(const char *id); - -/** - * Returns a list of all loaded plugins. - * - * @constreturn A list of all loaded plugins. - */ -GList *purple_plugins_get_loaded(void); - -/** - * Returns a list of all valid protocol plugins. A protocol - * plugin is considered invalid if it does not contain the call - * to the PURPLE_INIT_PLUGIN() macro, or if it was compiled - * against an incompatable API version. - * - * @constreturn A list of all protocol plugins. - */ -GList *purple_plugins_get_protocols(void); - -/** - * Returns a list of all plugins, whether loaded or not. - * - * @constreturn A list of all plugins. - */ -GList *purple_plugins_get_all(void); - -/*@}*/ - -/**************************************************************************/ -/** @name Plugins SubSytem API */ -/**************************************************************************/ -/*@{*/ - -/** - * Returns the plugin subsystem handle. - * - * @return The plugin sybsystem handle. - */ -void *purple_plugins_get_handle(void); - -/** - * Initializes the plugin subsystem - */ -void purple_plugins_init(void); - -/** - * Uninitializes the plugin subsystem - */ -void purple_plugins_uninit(void); - -/*@}*/ - -/** - * Allocates and returns a new PurplePluginAction. - * - * @param label The description of the action to show to the user. - * @param callback The callback to call when the user selects this action. - */ -PurplePluginAction *purple_plugin_action_new(const char* label, void (*callback)(PurplePluginAction *)); - -/** - * Frees a PurplePluginAction - * - * @param action The PurplePluginAction to free. - */ -void purple_plugin_action_free(PurplePluginAction *action); - -G_END_DECLS - -#endif /* _PURPLE_PLUGIN_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/plugins.c Sun Aug 18 01:53:00 2013 +0530 @@ -0,0 +1,962 @@ +/* + * 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 + */ +#include "internal.h" + +#include "core.h" +#include "debug.h" +#include "plugins.h" + +#define PURPLE_PLUGIN_INFO_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_PLUGIN_INFO, PurplePluginInfoPrivate)) + +/** @copydoc _PurplePluginInfoPrivate */ +typedef struct _PurplePluginInfoPrivate PurplePluginInfoPrivate; + +/************************************************************************** + * Plugin info private data + **************************************************************************/ +struct _PurplePluginInfoPrivate { + char *ui_requirement; /**< ID of UI that is required to load the plugin */ + char *error; /**< Why a plugin is not loadable */ + + /** Callback that returns a list of actions the plugin can perform */ + PurplePluginGetActionsCallback get_actions; + + /** Callback that returns a preferences frame for a plugin */ + PurplePluginPrefFrameCallback get_pref_frame; + + /** TRUE if a plugin has been unloaded at least once. Load-on-query + * plugins that have been unloaded once will not be auto-loaded again. */ + gboolean unloaded; +}; + +enum +{ + PROP_0, + PROP_UI_REQUIREMENT, + PROP_GET_ACTIONS, + PROP_PREFERENCES_FRAME, + PROP_LAST +}; + +static GObjectClass *parent_class; + +/************************************************************************** + * Globals + **************************************************************************/ +#ifdef PURPLE_PLUGINS +static GList *loaded_plugins = NULL; +static GList *plugins_to_disable = NULL; +#endif + +/************************************************************************** + * Plugin API + **************************************************************************/ +gboolean +purple_plugin_load(PurplePlugin *plugin, GError **error) +{ +#ifdef PURPLE_PLUGINS + GError *err = NULL; + PurplePluginInfoPrivate *priv; + + g_return_val_if_fail(plugin != NULL, FALSE); + + if (purple_plugin_is_loaded(plugin)) + return TRUE; + + priv = PURPLE_PLUGIN_INFO_GET_PRIVATE(purple_plugin_get_info(plugin)); + + if (priv->error) { + purple_debug_error("plugins", "Failed to load plugin %s: %s", + purple_plugin_get_filename(plugin), priv->error); + + g_set_error(error, PURPLE_PLUGINS_DOMAIN, 0, + "Plugin is not loadable: %s", priv->error); + + return FALSE; + } + + if (!gplugin_plugin_manager_load_plugin(plugin, &err)) { + purple_debug_error("plugins", "Failed to load plugin %s: %s", + purple_plugin_get_filename(plugin), err->message); + + if (error) + *error = g_error_copy(err); + g_error_free(err); + + return FALSE; + } + + loaded_plugins = g_list_append(loaded_plugins, plugin); + + purple_debug_info("plugins", "Loaded plugin %s\n", + purple_plugin_get_filename(plugin)); + + purple_signal_emit(purple_plugins_get_handle(), "plugin-load", plugin); + + return TRUE; + +#else + g_set_error(error, PURPLE_PLUGINS_DOMAIN, 0, "Plugin support is disabled."); + return FALSE; +#endif /* PURPLE_PLUGINS */ +} + +gboolean +purple_plugin_unload(PurplePlugin *plugin, GError **error) +{ +#ifdef PURPLE_PLUGINS + GError *err = NULL; + PurplePluginInfoPrivate *priv; + + g_return_val_if_fail(plugin != NULL, FALSE); + + if (!purple_plugin_is_loaded(plugin)) + return TRUE; + + priv = PURPLE_PLUGIN_INFO_GET_PRIVATE(purple_plugin_get_info(plugin)); + + g_return_val_if_fail(priv != NULL, FALSE); + + purple_debug_info("plugins", "Unloading plugin %s\n", + purple_plugin_get_filename(plugin)); + + if (!gplugin_plugin_manager_unload_plugin(plugin, &err)) { + purple_debug_error("plugins", "Failed to unload plugin %s: %s", + purple_plugin_get_filename(plugin), err->message); + + if (error) + *error = g_error_copy(err); + g_error_free(err); + + return FALSE; + } + + /* cancel any pending dialogs the plugin has */ + purple_request_close_with_handle(plugin); + purple_notify_close_with_handle(plugin); + + purple_signals_disconnect_by_handle(plugin); + purple_signals_unregister_by_instance(plugin); + + priv->unloaded = TRUE; + + loaded_plugins = g_list_remove(loaded_plugins, plugin); + plugins_to_disable = g_list_remove(plugins_to_disable, plugin); + + purple_signal_emit(purple_plugins_get_handle(), "plugin-unload", plugin); + + purple_prefs_disconnect_by_handle(plugin); + + return TRUE; + +#else + g_set_error(error, PURPLE_PLUGINS_DOMAIN, 0, "Plugin support is disabled."); + return FALSE; +#endif /* PURPLE_PLUGINS */ +} + +gboolean +purple_plugin_is_loaded(const PurplePlugin *plugin) +{ +#ifdef PURPLE_PLUGINS + g_return_val_if_fail(plugin != NULL, FALSE); + + return (gplugin_plugin_get_state(plugin) == GPLUGIN_PLUGIN_STATE_LOADED); + +#else + return FALSE; +#endif +} + +const gchar * +purple_plugin_get_filename(const PurplePlugin *plugin) +{ +#ifdef PURPLE_PLUGINS + g_return_val_if_fail(plugin != NULL, NULL); + + return gplugin_plugin_get_filename(plugin); + +#else + return NULL; +#endif +} + +PurplePluginInfo * +purple_plugin_get_info(const PurplePlugin *plugin) +{ +#ifdef PURPLE_PLUGINS + GPluginPluginInfo *info; + + g_return_val_if_fail(plugin != NULL, NULL); + + info = gplugin_plugin_get_info(plugin); + g_object_unref(info); + + return PURPLE_PLUGIN_INFO(info); + +#else + return NULL; +#endif +} + +void +purple_plugin_disable(PurplePlugin *plugin) +{ +#ifdef PURPLE_PLUGINS + g_return_if_fail(plugin != NULL); + + if (!g_list_find(plugins_to_disable, plugin)) + plugins_to_disable = g_list_prepend(plugins_to_disable, plugin); +#endif +} + +GType +purple_plugin_register_type(PurplePlugin *plugin, GType parent, + const gchar *name, const GTypeInfo *info, + GTypeFlags flags) +{ +#ifdef PURPLE_PLUGINS + return gplugin_native_plugin_register_type(GPLUGIN_NATIVE_PLUGIN(plugin), + parent, name, info, flags); + +#else + return G_TYPE_INVALID; +#endif +} + +void +purple_plugin_add_interface(PurplePlugin *plugin, GType instance_type, + GType interface_type, + const GInterfaceInfo *interface_info) +{ +#ifdef PURPLE_PLUGINS + gplugin_native_plugin_add_interface(GPLUGIN_NATIVE_PLUGIN(plugin), + instance_type, interface_type, + interface_info); +#endif +} + +gboolean +purple_plugin_is_internal(const PurplePlugin *plugin) +{ +#ifdef PURPLE_PLUGINS + GPluginPluginInfo *info; + + g_return_val_if_fail(plugin != NULL, FALSE); + + info = GPLUGIN_PLUGIN_INFO(purple_plugin_get_info(plugin)); + + g_return_val_if_fail(info != NULL, FALSE); + + return (gplugin_plugin_info_get_flags(info) & + GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL); + +#else + return FALSE; +#endif +} + +GSList * +purple_plugin_get_dependent_plugins(const PurplePlugin *plugin) +{ +#ifdef PURPLE_PLUGINS +#warning TODO: Implement this when GPlugin can return dependent plugins. + return NULL; + +#else + return NULL; +#endif +} + +/************************************************************************** + * GObject code for PurplePluginInfo + **************************************************************************/ +/* GObject Property names */ +#define PROP_UI_REQUIREMENT_S "ui-requirement" +#define PROP_GET_ACTIONS_S "get-actions" +#define PROP_PREFERENCES_FRAME_S "preferences-frame" + +/* Set method for GObject properties */ +static void +purple_plugin_info_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PurplePluginInfo *info = PURPLE_PLUGIN_INFO(obj); + PurplePluginInfoPrivate *priv = PURPLE_PLUGIN_INFO_GET_PRIVATE(info); + + switch (param_id) { + case PROP_UI_REQUIREMENT: + priv->ui_requirement = g_strdup(g_value_get_string(value)); + break; + case PROP_GET_ACTIONS: + priv->get_actions = g_value_get_pointer(value); + break; + case PROP_PREFERENCES_FRAME: + priv->get_pref_frame = g_value_get_pointer(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Get method for GObject properties */ +static void +purple_plugin_info_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurplePluginInfo *info = PURPLE_PLUGIN_INFO(obj); + + switch (param_id) { + case PROP_GET_ACTIONS: + g_value_set_pointer(value, + purple_plugin_info_get_actions_callback(info)); + break; + case PROP_PREFERENCES_FRAME: + g_value_set_pointer(value, + purple_plugin_info_get_pref_frame_callback(info)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Called when done constructing */ +static void +purple_plugin_info_constructed(GObject *object) +{ + PurplePluginInfo *info = PURPLE_PLUGIN_INFO(object); + PurplePluginInfoPrivate *priv = PURPLE_PLUGIN_INFO_GET_PRIVATE(info); + const char *id = purple_plugin_info_get_id(info); + guint32 version; + + parent_class->constructed(object); + + if (id == NULL || *id == '\0') + priv->error = g_strdup(_("This plugin has not defined an ID.")); + + if (priv->ui_requirement && !purple_strequal(priv->ui_requirement, purple_core_get_ui())) + { + priv->error = g_strdup_printf(_("You are using %s, but this plugin requires %s."), + purple_core_get_ui(), priv->ui_requirement); + purple_debug_error("plugins", "%s is not loadable: The UI requirement is not met. (%s)\n", + id, priv->error); + } + + version = purple_plugin_info_get_abi_version(info); + if (PURPLE_PLUGIN_ABI_MAJOR_VERSION(version) != PURPLE_MAJOR_VERSION || + PURPLE_PLUGIN_ABI_MINOR_VERSION(version) > PURPLE_MINOR_VERSION) + { + priv->error = g_strdup_printf(_("Your libpurple version is %d.%d.x (need %d.%d.x)"), + PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, + PURPLE_PLUGIN_ABI_MAJOR_VERSION(version), + PURPLE_PLUGIN_ABI_MINOR_VERSION(version)); + purple_debug_error("plugins", "%s is not loadable: libpurple version is %d.%d.x (need %d.%d.x)\n", + id, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, + PURPLE_PLUGIN_ABI_MAJOR_VERSION(version), + PURPLE_PLUGIN_ABI_MINOR_VERSION(version)); + } +} + +/* GObject finalize function */ +static void +purple_plugin_info_finalize(GObject *object) +{ + PurplePluginInfoPrivate *priv = PURPLE_PLUGIN_INFO_GET_PRIVATE(object); + + g_free(priv->ui_requirement); + g_free(priv->error); + + parent_class->finalize(object); +} + +/* Class initializer function */ +static void purple_plugin_info_class_init(PurplePluginInfoClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + g_type_class_add_private(klass, sizeof(PurplePluginInfoPrivate)); + + obj_class->constructed = purple_plugin_info_constructed; + obj_class->finalize = purple_plugin_info_finalize; + + /* Setup properties */ + obj_class->get_property = purple_plugin_info_get_property; + obj_class->set_property = purple_plugin_info_set_property; + + g_object_class_install_property(obj_class, PROP_UI_REQUIREMENT, + g_param_spec_string(PROP_UI_REQUIREMENT_S, + "UI Requirement", + "ID of UI that is required by this plugin", NULL, + G_PARAM_WRITABLE)); + + g_object_class_install_property(obj_class, PROP_GET_ACTIONS, + g_param_spec_pointer(PROP_GET_ACTIONS_S, + "Plugin actions", + "Callback that returns list of the plugin's actions", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property(obj_class, PROP_PREFERENCES_FRAME, + g_param_spec_pointer(PROP_PREFERENCES_FRAME_S, + "Preferences frame callback", + "The callback that returns the preferences frame", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + +/************************************************************************** + * PluginInfo API + **************************************************************************/ +GType +purple_plugin_info_get_type(void) +{ + static GType type = 0; + + if (G_UNLIKELY(type == 0)) { + static const GTypeInfo info = { + .class_size = sizeof(PurplePluginInfoClass), + .class_init = (GClassInitFunc)purple_plugin_info_class_init, + .instance_size = sizeof(PurplePluginInfo), + }; + + type = g_type_register_static( +#ifdef PURPLE_PLUGINS + GPLUGIN_TYPE_PLUGIN_INFO, +#else + G_TYPE_OBJECT, +#endif + "PurplePluginInfo", &info, 0); + } + + return type; +} + +PurplePluginInfo * +purple_plugin_info_new(const char *first_property, ...) +{ + GObject *info; + va_list var_args; + + /* at least ID is required */ + if (!first_property) + return NULL; + + va_start(var_args, first_property); + info = g_object_new_valist(PURPLE_TYPE_PLUGIN_INFO, first_property, + var_args); + va_end(var_args); + + return PURPLE_PLUGIN_INFO(info); +} + +const gchar * +purple_plugin_info_get_id(const PurplePluginInfo *info) +{ +#ifdef PURPLE_PLUGINS + g_return_val_if_fail(info != NULL, NULL); + + return gplugin_plugin_info_get_id(GPLUGIN_PLUGIN_INFO(info)); + +#else + return NULL; +#endif +} + +const gchar * +purple_plugin_info_get_name(const PurplePluginInfo *info) +{ +#ifdef PURPLE_PLUGINS + g_return_val_if_fail(info != NULL, NULL); + + return gplugin_plugin_info_get_name(GPLUGIN_PLUGIN_INFO(info)); + +#else + return NULL; +#endif +} + +const gchar * +purple_plugin_info_get_version(const PurplePluginInfo *info) +{ +#ifdef PURPLE_PLUGINS + g_return_val_if_fail(info != NULL, NULL); + + return gplugin_plugin_info_get_version(GPLUGIN_PLUGIN_INFO(info)); + +#else + return NULL; +#endif +} + +const gchar * +purple_plugin_info_get_category(const PurplePluginInfo *info) +{ +#ifdef PURPLE_PLUGINS + g_return_val_if_fail(info != NULL, NULL); + + return gplugin_plugin_info_get_category(GPLUGIN_PLUGIN_INFO(info)); + +#else + return NULL; +#endif +} + +const gchar * +purple_plugin_info_get_summary(const PurplePluginInfo *info) +{ +#ifdef PURPLE_PLUGINS + g_return_val_if_fail(info != NULL, NULL); + + return gplugin_plugin_info_get_summary(GPLUGIN_PLUGIN_INFO(info)); + +#else + return NULL; +#endif +} + +const gchar * +purple_plugin_info_get_description(const PurplePluginInfo *info) +{ +#ifdef PURPLE_PLUGINS + g_return_val_if_fail(info != NULL, NULL); + + return gplugin_plugin_info_get_description(GPLUGIN_PLUGIN_INFO(info)); + +#else + return NULL; +#endif +} + +const gchar * +purple_plugin_info_get_author(const PurplePluginInfo *info) +{ +#ifdef PURPLE_PLUGINS + g_return_val_if_fail(info != NULL, NULL); + + return gplugin_plugin_info_get_author(GPLUGIN_PLUGIN_INFO(info)); + +#else + return NULL; +#endif +} + +const gchar * +purple_plugin_info_get_website(const PurplePluginInfo *info) +{ +#ifdef PURPLE_PLUGINS + g_return_val_if_fail(info != NULL, NULL); + + return gplugin_plugin_info_get_website(GPLUGIN_PLUGIN_INFO(info)); + +#else + return NULL; +#endif +} + +const gchar * +purple_plugin_info_get_icon(const PurplePluginInfo *info) +{ +#ifdef PURPLE_PLUGINS + g_return_val_if_fail(info != NULL, NULL); + + return gplugin_plugin_info_get_icon(GPLUGIN_PLUGIN_INFO(info)); + +#else + return NULL; +#endif +} + +const gchar * +purple_plugin_info_get_license(const PurplePluginInfo *info) +{ +#ifdef PURPLE_PLUGINS + g_return_val_if_fail(info != NULL, NULL); + + return gplugin_plugin_info_get_license(GPLUGIN_PLUGIN_INFO(info)); + +#else + return NULL; +#endif +} + +const gchar * +purple_plugin_info_get_license_text(const PurplePluginInfo *info) +{ +#ifdef PURPLE_PLUGINS + g_return_val_if_fail(info != NULL, NULL); + + return gplugin_plugin_info_get_license_text(GPLUGIN_PLUGIN_INFO(info)); + +#else + return NULL; +#endif +} + +const gchar * +purple_plugin_info_get_license_url(const PurplePluginInfo *info) +{ +#ifdef PURPLE_PLUGINS + g_return_val_if_fail(info != NULL, NULL); + + return gplugin_plugin_info_get_license_url(GPLUGIN_PLUGIN_INFO(info)); + +#else + return NULL; +#endif +} + +guint32 +purple_plugin_info_get_abi_version(const PurplePluginInfo *info) +{ +#ifdef PURPLE_PLUGINS + g_return_val_if_fail(info != NULL, 0); + + return gplugin_plugin_info_get_abi_version(GPLUGIN_PLUGIN_INFO(info)); + +#else + return 0; +#endif +} + +PurplePluginGetActionsCallback +purple_plugin_info_get_actions_callback(const PurplePluginInfo *info) +{ + PurplePluginInfoPrivate *priv = PURPLE_PLUGIN_INFO_GET_PRIVATE(info); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->get_actions; +} + +PurplePluginPrefFrameCallback +purple_plugin_info_get_pref_frame_callback(const PurplePluginInfo *info) +{ + PurplePluginInfoPrivate *priv = PURPLE_PLUGIN_INFO_GET_PRIVATE(info); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->get_pref_frame; +} + +const gchar * +purple_plugin_info_get_error(const PurplePluginInfo *info) +{ + PurplePluginInfoPrivate *priv = PURPLE_PLUGIN_INFO_GET_PRIVATE(info); + + g_return_val_if_fail(priv != NULL, NULL); + + return priv->error; +} + +/************************************************************************** + * PluginAction API + **************************************************************************/ +PurplePluginAction * +purple_plugin_action_new(const char* label, PurplePluginActionCallback callback) +{ + PurplePluginAction *action; + + g_return_val_if_fail(label != NULL && callback != NULL, NULL); + + action = g_new0(PurplePluginAction, 1); + + action->label = g_strdup(label); + action->callback = callback; + + return action; +} + +void +purple_plugin_action_free(PurplePluginAction *action) +{ + g_return_if_fail(action != NULL); + + g_free(action->label); + g_free(action); +} + +static PurplePluginAction * +purple_plugin_action_copy(PurplePluginAction *action) +{ + PurplePluginAction *action_copy; + + g_return_val_if_fail(action != NULL, NULL); + + action_copy = g_new(PurplePluginAction, 1); + *action_copy = *action; + + action_copy->label = g_strdup(action->label); + + return action_copy; +} + +GType +purple_plugin_action_get_type(void) +{ + static GType type = 0; + + if (G_UNLIKELY(type == 0)) { + type = g_boxed_type_register_static("PurplePluginAction", + (GBoxedCopyFunc)purple_plugin_action_copy, + (GBoxedFreeFunc)purple_plugin_action_free); + } + + return type; +} + +/************************************************************************** + * Plugins API + **************************************************************************/ +GList * +purple_plugins_find_all(void) +{ +#ifdef PURPLE_PLUGINS + GList *ret = NULL, *ids, *l; + GSList *plugins, *ll; + + ids = gplugin_plugin_manager_list_plugins(); + + for (l = ids; l; l = l->next) { + plugins = gplugin_plugin_manager_find_plugins(l->data); + for (ll = plugins; ll; ll = ll->next) + ret = g_list_append(ret, ll->data); + + gplugin_plugin_manager_free_plugin_list(plugins); + } + g_list_free(ids); + + return ret; + +#else + return NULL; +#endif +} + +GList * +purple_plugins_get_loaded(void) +{ +#ifdef PURPLE_PLUGINS + return loaded_plugins; +#else + return NULL; +#endif +} + +void +purple_plugins_add_search_path(const gchar *path) +{ +#ifdef PURPLE_PLUGINS + gplugin_plugin_manager_append_path(path); +#endif +} + +void +purple_plugins_refresh(void) +{ +#ifdef PURPLE_PLUGINS + GList *plugins, *l; + + gplugin_plugin_manager_refresh(); + + plugins = purple_plugins_find_all(); + for (l = plugins; l != NULL; l = l->next) { + PurplePlugin *plugin = PURPLE_PLUGIN(l->data); + GPluginPluginInfo *info; + PurplePluginInfoPrivate *priv; + + if (purple_plugin_is_loaded(plugin)) + continue; + + info = GPLUGIN_PLUGIN_INFO(purple_plugin_get_info(plugin)); + if (!info) + continue; + + priv = PURPLE_PLUGIN_INFO_GET_PRIVATE(info); + + if (!priv->unloaded && gplugin_plugin_info_get_flags(info) & + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY) { + purple_debug_info("plugins", "Auto-loading plugin %s\n", + purple_plugin_get_filename(plugin)); + purple_plugin_load(plugin, NULL); + } + } + + g_list_free(plugins); +#endif +} + +PurplePlugin * +purple_plugins_find_plugin(const gchar *id) +{ +#ifdef PURPLE_PLUGINS + PurplePlugin *plugin; + + g_return_val_if_fail(id != NULL && *id != '\0', NULL); + + plugin = gplugin_plugin_manager_find_plugin(id); + g_object_unref(plugin); + + return plugin; + +#else + return NULL; +#endif +} + +PurplePlugin * +purple_plugins_find_by_filename(const char *filename) +{ + GList *plugins, *l; + + g_return_val_if_fail(filename != NULL && *filename != '\0', NULL); + + plugins = purple_plugins_find_all(); + + for (l = plugins; l != NULL; l = l->next) { + PurplePlugin *plugin = PURPLE_PLUGIN(l->data); + + if (purple_strequal(purple_plugin_get_filename(plugin), filename)) { + g_list_free(plugins); + return plugin; + } + } + g_list_free(plugins); + + return NULL; +} + +void +purple_plugins_save_loaded(const char *key) +{ +#ifdef PURPLE_PLUGINS + GList *pl; + GList *files = NULL; + + g_return_if_fail(key != NULL && *key != '\0'); + + for (pl = purple_plugins_get_loaded(); pl != NULL; pl = pl->next) { + PurplePlugin *plugin = PURPLE_PLUGIN(pl->data); + GPluginPluginInfo *info = + GPLUGIN_PLUGIN_INFO(purple_plugin_get_info(plugin)); + + if (!info) + continue; + + if (gplugin_plugin_info_get_flags(info) & + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY) + continue; + + if (!g_list_find(plugins_to_disable, plugin)) + files = g_list_append(files, (gchar *)purple_plugin_get_filename(plugin)); + } + + purple_prefs_set_path_list(key, files); + g_list_free(files); +#endif +} + +void +purple_plugins_load_saved(const char *key) +{ +#ifdef PURPLE_PLUGINS + GList *l, *files; + + g_return_if_fail(key != NULL && *key != '\0'); + + files = purple_prefs_get_path_list(key); + + for (l = files; l; l = l->next) + { + char *file; + PurplePlugin *plugin; + + if (l->data == NULL) + continue; + + file = l->data; + plugin = purple_plugins_find_by_filename(file); + + if (plugin) { + purple_debug_info("plugins", "Loading saved plugin %s\n", file); + purple_plugin_load(plugin, NULL); + } else { + purple_debug_error("plugins", "Unable to find saved plugin %s\n", file); + } + + g_free(l->data); + } + + g_list_free(files); +#endif /* PURPLE_PLUGINS */ +} + +/************************************************************************** + * Plugins Subsystem API + **************************************************************************/ +void * +purple_plugins_get_handle(void) +{ + static int handle; + + return &handle; +} + +void +purple_plugins_init(void) +{ + void *handle = purple_plugins_get_handle(); + + purple_signal_register(handle, "plugin-load", + purple_marshal_VOID__POINTER, + G_TYPE_NONE, 1, PURPLE_TYPE_PLUGIN); + purple_signal_register(handle, "plugin-unload", + purple_marshal_VOID__POINTER, + G_TYPE_NONE, 1, PURPLE_TYPE_PLUGIN); + +#ifdef PURPLE_PLUGINS + gplugin_init(); + purple_plugins_add_search_path(LIBDIR); + purple_plugins_refresh(); +#endif +} + +void +purple_plugins_uninit(void) +{ + void *handle = purple_plugins_get_handle(); + +#ifdef PURPLE_PLUGINS + purple_debug_info("plugins", "Unloading all plugins\n"); + while (loaded_plugins != NULL) + purple_plugin_unload(loaded_plugins->data, NULL); +#endif + + purple_signals_disconnect_by_handle(handle); + purple_signals_unregister_by_instance(handle); + +#ifdef PURPLE_PLUGINS + gplugin_uninit(); +#endif +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/plugins.h Sun Aug 18 01:53:00 2013 +0530 @@ -0,0 +1,664 @@ +/** + * @file plugins.h Plugins API + * @ingroup core + * @see @ref plugin-signals + * @see @ref plugin-ids + * @see @ref plugin-i18n + */ + +/* 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 _PURPLE_PLUGINS_H_ +#define _PURPLE_PLUGINS_H_ + +#ifdef PURPLE_PLUGINS +#include <gplugin.h> +#include <gplugin-native.h> +#else +#include <glib.h> +#include <glib-object.h> +#endif + +#include "version.h" + +#define PURPLE_PLUGINS_DOMAIN (g_quark_from_static_string("plugins")) + +#ifdef PURPLE_PLUGINS + +#define PURPLE_TYPE_PLUGIN GPLUGIN_TYPE_PLUGIN +#define PURPLE_PLUGIN(obj) GPLUGIN_PLUGIN(obj) +#define PURPLE_PLUGIN_CLASS(klass) GPLUGIN_PLUGIN_CLASS(klass) +#define PURPLE_IS_PLUGIN(obj) GPLUGIN_IS_PLUGIN(obj) +#define PURPLE_IS_PLUGIN_CLASS(klass) GPLUGIN_IS_PLUGIN_CLASS(klass) +#define PURPLE_PLUGIN_GET_CLASS(obj) GPLUGIN_PLUGIN_GET_CLASS(obj) + +/** + * Represents a plugin handle. + * This type is an alias for GPluginPlugin. + */ +typedef GPluginPlugin PurplePlugin; + +/** + * The base class for all #PurplePlugin's. + * This type is an alias for GPluginPluginClass. + */ +typedef GPluginPluginClass PurplePluginClass; + +#else /* !defined(PURPLE_PLUGINS) */ + +#define PURPLE_TYPE_PLUGIN G_TYPE_OBJECT +#define PURPLE_PLUGIN(obj) G_OBJECT(obj) +#define PURPLE_PLUGIN_CLASS(klass) G_OBJECT_CLASS(klass) +#define PURPLE_IS_PLUGIN(obj) G_IS_OBJECT(obj) +#define PURPLE_IS_PLUGIN_CLASS(klass) G_IS_OBJECT_CLASS(klass) +#define PURPLE_PLUGIN_GET_CLASS(obj) G_OBJECT_GET_CLASS(obj) + +#define GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY 0 +#define GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL 0 + +typedef GObject PurplePlugin; +typedef GObjectClass PurplePluginClass; + +#endif /* PURPLE_PLUGINS */ + +#define PURPLE_TYPE_PLUGIN_INFO (purple_plugin_info_get_type()) +#define PURPLE_PLUGIN_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_PLUGIN_INFO, PurplePluginInfo)) +#define PURPLE_PLUGIN_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_PLUGIN_INFO, PurplePluginInfoClass)) +#define PURPLE_IS_PLUGIN_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_PLUGIN_INFO)) +#define PURPLE_IS_PLUGIN_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_PLUGIN_INFO)) +#define PURPLE_PLUGIN_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_PLUGIN_INFO, PurplePluginInfoClass)) + +/** @copydoc _PurplePluginInfo */ +typedef struct _PurplePluginInfo PurplePluginInfo; +/** @copydoc _PurplePluginInfoClass */ +typedef struct _PurplePluginInfoClass PurplePluginInfoClass; + +#define PURPLE_TYPE_PLUGIN_ACTION (purple_plugin_action_get_type()) + +/** @copydoc _PurplePluginAction */ +typedef struct _PurplePluginAction PurplePluginAction; + +#include "pluginpref.h" + +typedef void (*PurplePluginActionCallback)(PurplePluginAction *); +typedef GList *(*PurplePluginGetActionsCallback)(PurplePlugin *); +typedef PurplePluginPrefFrame *(*PurplePluginPrefFrameCallback)(PurplePlugin *); + +/** + * Holds information about a plugin. + */ +struct _PurplePluginInfo { +#ifdef PURPLE_PLUGINS + /*< private >*/ + GPluginPluginInfo parent; +#else + /*< private >*/ + GObject parent; +#endif +}; + +/** + * PurplePluginInfoClass: + * + * The base class for all #PurplePluginInfo's. + */ +struct _PurplePluginInfoClass { +#ifdef PURPLE_PLUGINS + /*< private >*/ + GPluginPluginInfoClass parent_class; +#else + /*< private >*/ + GObjectClass parent_class; +#endif + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +}; + +/** + * Represents an action that the plugin can perform. This shows up in the Tools + * menu, under a submenu with the name of the plugin. + */ +struct _PurplePluginAction { + char *label; + PurplePluginActionCallback callback; + PurplePlugin *plugin; + gpointer user_data; +}; + +/** Returns an ABI version to set in plugins using major and minor versions */ +#define PURPLE_PLUGIN_ABI_VERSION(major,minor) (0x01000000 | \ + ((major) << 16) | (minor)) + +/** Returns the major version from an ABI version */ +#define PURPLE_PLUGIN_ABI_MAJOR_VERSION(abi) ((abi >> 16) & 0xff) +/** Returns the minor version from an ABI version */ +#define PURPLE_PLUGIN_ABI_MINOR_VERSION(abi) (abi & 0xffff) + +/** + * A convenience‎ macro that returns an ABI version using PURPLE_MAJOR_VERSION + * and PURPLE_MINOR_VERSION + */ +#define PURPLE_ABI_VERSION PURPLE_PLUGIN_ABI_VERSION(PURPLE_MAJOR_VERSION, \ + PURPLE_MINOR_VERSION) + +/** + * Handles the initialization of modules. + */ +#if !defined(PURPLE_PLUGINS) || defined(PURPLE_STATIC_PROTOCOL) +#define PURPLE_PLUGIN_INIT(pluginname,pluginquery,pluginload,pluginunload) \ + PurplePluginInfo * pluginname##_plugin_query(void); \ + PurplePluginInfo * pluginname##_plugin_query(void) { \ + return pluginquery(NULL); \ + } \ + gboolean pluginname##_plugin_load(void); \ + gboolean pluginname##_plugin_load(void) { \ + GError *e = NULL; \ + gboolean loaded = pluginload(NULL, &e); \ + if (e) g_error_free(e); \ + return loaded; \ + } \ + gboolean pluginname##_plugin_unload(void); \ + gboolean pluginname##_plugin_unload(void) { \ + GError *e = NULL; \ + gboolean unloaded = pluginunload(NULL, &e); \ + if (e) g_error_free(e); \ + return unloaded; \ + } +#else /* PURPLE_PLUGINS && !PURPLE_STATIC_PROTOCOL */ +#define PURPLE_PLUGIN_INIT(pluginname,pluginquery,pluginload,pluginunload) \ + G_MODULE_EXPORT GPluginPluginInfo *gplugin_plugin_query(GError **e); \ + G_MODULE_EXPORT GPluginPluginInfo *gplugin_plugin_query(GError **e) { \ + return GPLUGIN_PLUGIN_INFO(pluginquery(e)); \ + } \ + G_MODULE_EXPORT gboolean gplugin_plugin_load(GPluginNativePlugin *p, GError **e); \ + G_MODULE_EXPORT gboolean gplugin_plugin_load(GPluginNativePlugin *p, GError **e) { \ + return pluginload(PURPLE_PLUGIN(p), e); \ + } \ + G_MODULE_EXPORT gboolean gplugin_plugin_unload(GPluginNativePlugin *p, GError **e); \ + G_MODULE_EXPORT gboolean gplugin_plugin_unload(GPluginNativePlugin *p, GError **e) { \ + return pluginunload(PURPLE_PLUGIN(p), e); \ + } +#endif + +G_BEGIN_DECLS + +/**************************************************************************/ +/** @name Plugin API */ +/**************************************************************************/ +/*@{*/ + +/** + * Attempts to load a plugin. + * + * @param plugin The plugin to load. + * @param error Return location for a #GError or @c NULL. If provided, this + * will be set to the reason if the load fails. + * + * @return @c TRUE if successful or already loaded, @c FALSE otherwise. + * + * @see purple_plugin_unload() + */ +gboolean purple_plugin_load(PurplePlugin *plugin, GError **error); + +/** + * Unloads the specified plugin. + * + * @param plugin The plugin handle. + * @param error Return location for a #GError or @c NULL. If provided, this + * will be set to the reason if the unload fails. + * + * @return @c TRUE if successful or not loaded, @c FALSE otherwise. + * + * @see purple_plugin_load() + */ +gboolean purple_plugin_unload(PurplePlugin *plugin, GError **error); + +/** + * Returns whether or not a plugin is currently loaded. + * + * @param plugin The plugin. + * + * @return @c TRUE if loaded, or @c FALSE otherwise. + */ +gboolean purple_plugin_is_loaded(const PurplePlugin *plugin); + +/** + * Returns a plugin's filename, along with the path. + * + * @param info The plugin. + * + * @return The plugin's filename. + */ +const gchar *purple_plugin_get_filename(const PurplePlugin *plugin); + +/** + * Returns a plugin's #PurplePluginInfo instance. + * + * @param info The plugin. + * + * @return The plugin's #PurplePluginInfo instance. + */ +PurplePluginInfo *purple_plugin_get_info(const PurplePlugin *plugin); + +/** + * Disable a plugin. + * + * This function adds the plugin to a list of plugins to "disable at the next + * 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. + */ +void purple_plugin_disable(PurplePlugin *plugin); + +/** + * Registers a new dynamic type. + * + * @param plugin The plugin that is registering the type. + * @param parent Type from which this type will be derived. + * @param name Name of the new type. + * @param info Information to initialize and destroy a type's classes and + * instances. + * @param flags Bitwise combination of values that determines the nature + * (e.g. abstract or not) of the type. + * + * @return The new GType, or @c G_TYPE_INVALID if registration failed. + */ +GType purple_plugin_register_type(PurplePlugin *plugin, GType parent, + const gchar *name, const GTypeInfo *info, + GTypeFlags flags); + +/** + * Adds a dynamic interface type to an instantiable type. + * + * @param plugin The plugin that is adding the interface type. + * @param instance_type The GType of the instantiable type. + * @param interface_type The GType of the interface type. + * @param interface_info Information used to manage the interface type. + */ +void purple_plugin_add_interface(PurplePlugin *plugin, GType instance_type, + GType interface_type, + const GInterfaceInfo *interface_info); + +/** + * Returns whether a plugin is an internal plugin. Internal plugins provide + * required additional functionality to the libpurple core. These plugins must + * not be shown in plugin lists. Examples of such plugins are in-tree protocol + * plugins, loaders etc. + * + * @param plugin The plugin. + * + * @return @c TRUE if the plugin is an internal plugin, @c FALSE otherwise. + */ +gboolean purple_plugin_is_internal(const PurplePlugin *plugin); + +/** + * Returns a list of plugins that depend on a particular plugin. + * + * @param plugin The plugin whose dependent plugins are returned. + * + * @constreturn The list of a plugins that depend on the specified plugin. + */ +GSList *purple_plugin_get_dependent_plugins(const PurplePlugin *plugin); + +/*@}*/ + +/**************************************************************************/ +/** @name PluginInfo API */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the GType for the PurplePluginInfo object. + */ +GType purple_plugin_info_get_type(void); + +/** + * Creates a new #PurplePluginInfo instance to be returned from + * gplugin_plugin_query() of a plugin, using the provided name/value pairs. + * + * All properties except "id" and "purple-abi" are optional. + * + * Valid property names are: \n + * "id" (string) The ID of the plugin. \n + * "name" (string) The translated name of the plugin. \n + * "version" (string) Version of the plugin. \n + * "category" (string) Primary category of the plugin. \n + * "summary" (string) Brief summary of the plugin. \n + * "description" (string) Full description of the plugin. \n + * "author" (string) Name and e-mail address of the author. + * format: First Last <user@domain.com> \n + * "website" (string) Website of the plugin. \n + * "icon" (string) Path to a plugin's icon. \n + * "license" (string) Short name of the plugin's license. This + * should either be an identifier of the + * license from http://spdx.org/licenses/ or + * "Other" for custom licenses. \n + * "license-text" (string) The text of the plugin's license, if + * unlisted on SPDX. \n + * "license-url" (string) The plugin's license URL, if unlisted on + * SPDX. \n + * "dependencies" (string) Comma-seperated list of plugin IDs required + * by the plugin. \n + * "abi-version" (guint32) The ABI version required by the plugin. \n + * "get-actions" (PurplePluginGetActionsCallback) Callback that + * returns a list of actions the plugin can + * perform. \n + * "preferences-frame" (PurplePluginPrefFrameCallback) Callback that returns + * a preferences frame for the plugin. + * + * Additionally, you can provide a "flags" property if the plugin is to be + * distributed with libpurple, the value for which should be a bitwise + * combination of: \n + * GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL: Internal plugin, not shown in lists. \n + * GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY: Auto-load on query. \n + * + * @param first_property The first property name + * @param ... The value of the first property, followed optionally by more + * name/value pairs, followed by @c NULL + * + * @return A new #PurplePluginInfo instance. + * + * @see PURPLE_PLUGIN_ABI_VERSION + * @see @ref plugin-ids + */ +PurplePluginInfo *purple_plugin_info_new(const char *first_property, ...); + +/** + * Returns a plugin's ID. + * + * @param info The plugin's info instance. + * + * @return The plugin's ID. + */ +const gchar *purple_plugin_info_get_id(const PurplePluginInfo *info); + +/** + * Returns a plugin's translated name. + * + * @param info The plugin's info instance. + * + * @return The name of the plugin, or @c NULL. + */ +const gchar *purple_plugin_info_get_name(const PurplePluginInfo *info); + +/** + * Returns a plugin's version. + * + * @param info The plugin's info instance. + * + * @return The version of the plugin, or @c NULL. + */ +const gchar *purple_plugin_info_get_version(const PurplePluginInfo *info); + +/** + * Returns a plugin's primary category. + * + * @param info The plugin's info instance. + * + * @return The primary category of the plugin, or @c NULL. + */ +const gchar *purple_plugin_info_get_category(const PurplePluginInfo *info); + +/** + * Returns a plugin's summary. + * + * @param info The plugin's info instance. + * + * @return The summary of the plugin, or @c NULL. + */ +const gchar *purple_plugin_info_get_summary(const PurplePluginInfo *info); + +/** + * Returns a plugin's description. + * + * @param info The plugin's info instance. + * + * @return The description of the plugin, or @c NULL. + */ +const gchar *purple_plugin_info_get_description(const PurplePluginInfo *info); + +/** + * Returns a plugin's author. + * + * @param info The plugin's info instance. + * + * @return The author of the plugin, or @c NULL. + */ +const gchar *purple_plugin_info_get_author(const PurplePluginInfo *info); + +/** + * Returns a plugin's website. + * + * @param info The plugin's info instance. + * + * @return The website of the plugin, or @c NULL. + */ +const gchar *purple_plugin_info_get_website(const PurplePluginInfo *info); + +/** + * Returns the path to a plugin's icon. + * + * @param info The plugin's info instance. + * + * @return The path to the plugin's icon, or @c NULL. + */ +const gchar *purple_plugin_info_get_icon(const PurplePluginInfo *info); + +/** + * Returns a short name of the plugin's license. + * + * @param info The plugin's info instance. + * + * @return The license name of the plugin, or @c NULL. + */ +const gchar *purple_plugin_info_get_license(const PurplePluginInfo *info); + +/** + * Returns the text of a plugin's license. + * + * @param info The plugin's info instance. + * + * @return The license text of the plugin, or @c NULL. + */ +const gchar *purple_plugin_info_get_license_text(const PurplePluginInfo *info); + +/** + * Returns the URL of a plugin's license. + * + * @param info The plugin's info instance. + * + * @return The license URL of the plugin, or @c NULL. + */ +const gchar *purple_plugin_info_get_license_url(const PurplePluginInfo *info); + +/** + * Returns the required purple ABI version for a plugin. + * + * @param info The plugin's info instance. + * + * @return The required purple ABI version for the plugin. + */ +guint32 purple_plugin_info_get_abi_version(const PurplePluginInfo *info); + +/** + * Returns the callback that retrieves the list of actions a plugin can perform + * at that moment. + * + * @param info The plugin info to get the callback from. + * + * @constreturn The callback that returns a list of #PurplePluginAction + * instances corresponding to the actions a plugin can perform. + */ +PurplePluginGetActionsCallback +purple_plugin_info_get_actions_callback(const PurplePluginInfo *info); + +/** + * Returns the callback that retrieves the preferences frame for a plugin. + * + * @param info The plugin info to get the callback from. + * + * @return The callback that returns the preferences frame. + */ +PurplePluginPrefFrameCallback +purple_plugin_info_get_pref_frame_callback(const PurplePluginInfo *info); + +/** + * Returns an error in the plugin info that would prevent the plugin from being + * loaded. + * + * @param info The plugin info. + * + * @return The plugin info error, or @c NULL. + */ +const gchar *purple_plugin_info_get_error(const PurplePluginInfo *info); + +/*@}*/ + +/**************************************************************************/ +/** @name PluginAction API */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the GType for the PurplePluginAction boxed structure. + */ +GType purple_plugin_action_get_type(void); + +/** + * Allocates and returns a new PurplePluginAction. Use this to add actions in a + * list in the "get-actions" callback for your plugin. + * + * @param label The description of the action to show to the user. + * @param callback The callback to call when the user selects this action. + */ +PurplePluginAction *purple_plugin_action_new(const char* label, + PurplePluginActionCallback callback); + +/** + * Frees a PurplePluginAction + * + * @param action The PurplePluginAction to free. + */ +void purple_plugin_action_free(PurplePluginAction *action); + +/*@}*/ + +/**************************************************************************/ +/** @name Plugins API */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns a list of all plugins, whether loaded or not. + * + * @return A list of all plugins. The list is owned by the caller, and must be + * g_list_free()d to avoid leaking the nodes. + */ +GList *purple_plugins_find_all(void); + +/** + * Returns a list of all loaded plugins. + * + * @constreturn A list of all loaded plugins. + */ +GList *purple_plugins_get_loaded(void); + +/** + * Add a new directory to search for plugins + * + * @param path The new search path. + */ +void purple_plugins_add_search_path(const gchar *path); + +/** + * Forces a refresh of all plugins found in the search paths, and loads plugins + * that are to be loaded on query. + * + * @see purple_plugins_add_search_path() + */ +void purple_plugins_refresh(void); + +/** + * Finds a plugin with the specified plugin ID. + * + * @param id The plugin ID. + * + * @return The plugin if found, or @c NULL if not found. + */ +PurplePlugin *purple_plugins_find_plugin(const gchar *id); + +/** + * Finds a plugin with the specified filename (filename with a path). + * + * @param filename The plugin filename. + * + * @return The plugin if found, or @c NULL if not found. + */ +PurplePlugin *purple_plugins_find_by_filename(const char *filename); + +/** + * Saves the list of loaded plugins to the specified preference key. + * Plugins that are set to load on query are not saved. + * + * @param key The preference key to save the list of plugins to. + */ +void purple_plugins_save_loaded(const char *key); + +/** + * Attempts to load all the plugins in the specified preference key + * that were loaded when purple last quit. + * + * @param key The preference key containing the list of plugins. + */ +void purple_plugins_load_saved(const char *key); + +/*@}*/ + +/**************************************************************************/ +/** @name Plugins Subsystem API */ +/**************************************************************************/ +/*@{*/ + +/** + * Returns the plugin subsystem handle. + * + * @return The plugin sybsystem handle. + */ +void *purple_plugins_get_handle(void); + +/** + * Initializes the plugin subsystem + */ +void purple_plugins_init(void); + +/** + * Uninitializes the plugin subsystem + */ +void purple_plugins_uninit(void); + +/*@}*/ + +G_END_DECLS + +#endif /* _PURPLE_PLUGINS_H_ */
--- a/libpurple/plugins/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -1,168 +1,175 @@ -DIST_SUBDIRS = mono perl ssl tcl keyrings - -if USE_PERL -PERL_DIR = perl -endif - -if USE_TCL -TCL_DIR = tcl -endif - -if ENABLE_DBUS -DBUS_LTLIB = dbus-example.la -endif - -if USE_MONO -MONO_DIR = mono -endif +DIST_SUBDIRS = ssl keyrings SUBDIRS = \ - $(MONO_DIR) \ - $(PERL_DIR) \ ssl \ - $(TCL_DIR) \ keyrings -plugindir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION) - -autoaccept_la_LDFLAGS = -module -avoid-version -buddynote_la_LDFLAGS = -module -avoid-version -ciphertest_la_LDFLAGS = -module -avoid-version -codeinline_la_LDFLAGS = -module -avoid-version -debug_example_la_LDFLAGS = -module -avoid-version -helloworld_la_LDFLAGS = -module -avoid-version -idle_la_LDFLAGS = -module -avoid-version -joinpart_la_LDFLAGS = -module -avoid-version -log_reader_la_LDFLAGS = -module -avoid-version -newline_la_LDFLAGS = -module -avoid-version -notify_example_la_LDFLAGS = -module -avoid-version -offlinemsg_la_LDFLAGS = -module -avoid-version -one_time_password_la_LDFLAGS = -module -avoid-version -pluginpref_example_la_LDFLAGS = -module -avoid-version -psychic_la_LDFLAGS = -module -avoid-version -signals_test_la_LDFLAGS = -module -avoid-version -simple_la_LDFLAGS = -module -avoid-version -statenotify_la_LDFLAGS = -module -avoid-version - -# this can't be in a conditional otherwise automake 1.4 yells -dbus_example_la_LDFLAGS = -module -avoid-version - -if PLUGINS - -plugin_LTLIBRARIES = \ - autoaccept.la \ - buddynote.la \ - idle.la \ - joinpart.la \ - log_reader.la \ - newline.la \ - offlinemsg.la \ - psychic.la \ - statenotify.la \ - $(DBUS_LTLIB) - -noinst_LTLIBRARIES = \ - ciphertest.la \ - codeinline.la \ - debug_example.la \ - helloworld.la \ - notify_example.la \ - one_time_password.la \ - pluginpref_example.la \ - signals_test.la \ - simple.la - -autoaccept_la_SOURCES = autoaccept.c -buddynote_la_SOURCES = buddynote.c -ciphertest_la_SOURCES = ciphertest.c -codeinline_la_SOURCES = codeinline.c -debug_example_la_SOURCES = debug_example.c -helloworld_la_SOURCES = helloworld.c -idle_la_SOURCES = idle.c -joinpart_la_SOURCES = joinpart.c -log_reader_la_SOURCES = log_reader.c -newline_la_SOURCES = newline.c -notify_example_la_SOURCES = notify_example.c -offlinemsg_la_SOURCES = offlinemsg.c -one_time_password_la_SOURCES = one_time_password.c -pluginpref_example_la_SOURCES = pluginpref_example.c -psychic_la_SOURCES = psychic.c -signals_test_la_SOURCES = signals-test.c -simple_la_SOURCES = simple.c -statenotify_la_SOURCES = statenotify.c - -autoaccept_la_LIBADD = $(GLIB_LIBS) -buddynote_la_LIBADD = $(GLIB_LIBS) -ciphertest_la_LIBADD = $(GLIB_LIBS) -codeinline_la_LIBADD = $(GLIB_LIBS) -idle_la_LIBADD = $(GLIB_LIBS) -joinpart_la_LIBADD = $(GLIB_LIBS) -log_reader_la_LIBADD = $(GLIB_LIBS) -newline_la_LIBADD = $(GLIB_LIBS) -notify_example_la_LIBADD = $(GLIB_LIBS) -offlinemsg_la_LIBADD = $(GLIB_LIBS) -one_time_password_la_LIBADD = $(GLIB_LIBS) -pluginpref_example_la_LIBADD = $(GLIB_LIBS) -psychic_la_LIBADD = $(GLIB_LIBS) -signals_test_la_LIBADD = $(GLIB_LIBS) -simple_la_LIBADD = $(GLIB_LIBS) -statenotify_la_LIBADD = $(GLIB_LIBS) - -if ENABLE_DBUS - -CLEANFILES = dbus-example-bindings.c -dbus_example_la_SOURCES = dbus-example.c - -dbus_example_la_LIBADD = $(GLIB_LIBS) $(DBUS_LIBS) - -.PHONY: always - -$(top_builddir)/libpurple/dbus-types.h: always - @echo -e " GEN\t$@" - @cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) - -dbus-example-bindings.c: $(top_srcdir)/libpurple/dbus-analyze-functions.py $(dbus_example_la_SOURCES) - @echo -e " GEN\t$@" - @cat $(srcdir)/$(dbus_example_la_SOURCES) | \ - $(PYTHON) $(top_srcdir)/libpurple/dbus-analyze-functions.py --export-only > $@ - -$(dbus_example_la_OBJECTS) dbus-example.so: dbus-example-bindings.c $(top_builddir)/libpurple/dbus-types.h - - -endif # ENABLE_DBUS - -endif # PLUGINS - -EXTRA_DIST = \ - Makefile.mingw \ - dbus-buddyicons-example.py \ - filectl.c \ - fortuneprofile.pl \ - ipc-test-client.c \ - ipc-test-server.c \ - startup.py - -AM_CPPFLAGS = \ - -DDATADIR=\"$(datadir)\" \ - -I$(top_srcdir)/libpurple \ - -I$(top_builddir)/libpurple \ - $(DEBUG_CFLAGS) \ - $(GLIB_CFLAGS) \ - $(PLUGIN_CFLAGS) \ - $(DBUS_CFLAGS) \ - $(NSS_CFLAGS) - -PLUGIN_LIBS = \ - $(NSS_LIBS) - +#DIST_SUBDIRS = mono perl ssl tcl keyrings +# +#if USE_PERL +#PERL_DIR = perl +#endif +# +#if USE_TCL +#TCL_DIR = tcl +#endif +# +#if ENABLE_DBUS +#DBUS_LTLIB = dbus-example.la +#endif +# +#if USE_MONO +#MONO_DIR = mono +#endif +# +#SUBDIRS = \ +# $(MONO_DIR) \ +# $(PERL_DIR) \ +# ssl \ +# $(TCL_DIR) \ +# keyrings +# +#plugindir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION) +# +#autoaccept_la_LDFLAGS = -module -avoid-version +#buddynote_la_LDFLAGS = -module -avoid-version +#ciphertest_la_LDFLAGS = -module -avoid-version +#codeinline_la_LDFLAGS = -module -avoid-version +#debug_example_la_LDFLAGS = -module -avoid-version +#helloworld_la_LDFLAGS = -module -avoid-version +#idle_la_LDFLAGS = -module -avoid-version +#joinpart_la_LDFLAGS = -module -avoid-version +#log_reader_la_LDFLAGS = -module -avoid-version +#newline_la_LDFLAGS = -module -avoid-version +#notify_example_la_LDFLAGS = -module -avoid-version +#offlinemsg_la_LDFLAGS = -module -avoid-version +#one_time_password_la_LDFLAGS = -module -avoid-version +#pluginpref_example_la_LDFLAGS = -module -avoid-version +#psychic_la_LDFLAGS = -module -avoid-version +#signals_test_la_LDFLAGS = -module -avoid-version +#simple_la_LDFLAGS = -module -avoid-version +#statenotify_la_LDFLAGS = -module -avoid-version +# +## this can't be in a conditional otherwise automake 1.4 yells +#dbus_example_la_LDFLAGS = -module -avoid-version +# +#if PLUGINS +# +#plugin_LTLIBRARIES = \ +# autoaccept.la \ +# buddynote.la \ +# idle.la \ +# joinpart.la \ +# log_reader.la \ +# newline.la \ +# offlinemsg.la \ +# psychic.la \ +# statenotify.la \ +# $(DBUS_LTLIB) +# +#noinst_LTLIBRARIES = \ +# ciphertest.la \ +# codeinline.la \ +# debug_example.la \ +# helloworld.la \ +# notify_example.la \ +# one_time_password.la \ +# pluginpref_example.la \ +# signals_test.la \ +# simple.la # -# This part allows people to build their own plugins in here. -# Yes, it's a mess. +#autoaccept_la_SOURCES = autoaccept.c +#buddynote_la_SOURCES = buddynote.c +#ciphertest_la_SOURCES = ciphertest.c +#codeinline_la_SOURCES = codeinline.c +#debug_example_la_SOURCES = debug_example.c +#helloworld_la_SOURCES = helloworld.c +#idle_la_SOURCES = idle.c +#joinpart_la_SOURCES = joinpart.c +#log_reader_la_SOURCES = log_reader.c +#newline_la_SOURCES = newline.c +#notify_example_la_SOURCES = notify_example.c +#offlinemsg_la_SOURCES = offlinemsg.c +#one_time_password_la_SOURCES = one_time_password.c +#pluginpref_example_la_SOURCES = pluginpref_example.c +#psychic_la_SOURCES = psychic.c +#signals_test_la_SOURCES = signals-test.c +#simple_la_SOURCES = simple.c +#statenotify_la_SOURCES = statenotify.c +# +#autoaccept_la_LIBADD = $(GLIB_LIBS) +#buddynote_la_LIBADD = $(GLIB_LIBS) +#ciphertest_la_LIBADD = $(GLIB_LIBS) +#codeinline_la_LIBADD = $(GLIB_LIBS) +#idle_la_LIBADD = $(GLIB_LIBS) +#joinpart_la_LIBADD = $(GLIB_LIBS) +#log_reader_la_LIBADD = $(GLIB_LIBS) +#newline_la_LIBADD = $(GLIB_LIBS) +#notify_example_la_LIBADD = $(GLIB_LIBS) +#offlinemsg_la_LIBADD = $(GLIB_LIBS) +#one_time_password_la_LIBADD = $(GLIB_LIBS) +#pluginpref_example_la_LIBADD = $(GLIB_LIBS) +#psychic_la_LIBADD = $(GLIB_LIBS) +#signals_test_la_LIBADD = $(GLIB_LIBS) +#simple_la_LIBADD = $(GLIB_LIBS) +#statenotify_la_LIBADD = $(GLIB_LIBS) +# +#if ENABLE_DBUS +# +#CLEANFILES = dbus-example-bindings.c +#dbus_example_la_SOURCES = dbus-example.c +# +#dbus_example_la_LIBADD = $(GLIB_LIBS) $(DBUS_LIBS) +# +#.PHONY: always # -SUFFIXES = .c .so -.c.so: - $(LIBTOOL) --mode=compile $(CC) -DHAVE_CONFIG_H -I$(top_builddir) $(AM_CPPFLAGS) $(CFLAGS) -c $< -o tmp$@.lo $(PLUGIN_CFLAGS) - $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o libtmp$@.la -rpath $(plugindir) tmp$@.lo $(LIBS) $(LDFLAGS) -module -avoid-version $(PLUGIN_LIBS) - @rm -f tmp$@.lo tmp$@.o libtmp$@.la - @cp .libs/libtmp$@*.so $@ - @rm -rf .libs/libtmp$@.* +#$(top_builddir)/libpurple/dbus-types.h: always +# @echo -e " GEN\t$@" +# @cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F) +# +#dbus-example-bindings.c: $(top_srcdir)/libpurple/dbus-analyze-functions.py $(dbus_example_la_SOURCES) +# @echo -e " GEN\t$@" +# @cat $(srcdir)/$(dbus_example_la_SOURCES) | \ +# $(PYTHON) $(top_srcdir)/libpurple/dbus-analyze-functions.py --export-only > $@ +# +#$(dbus_example_la_OBJECTS) dbus-example.so: dbus-example-bindings.c $(top_builddir)/libpurple/dbus-types.h +# +# +#endif # ENABLE_DBUS +# +#endif # PLUGINS +# +#EXTRA_DIST = \ +# Makefile.mingw \ +# dbus-buddyicons-example.py \ +# filectl.c \ +# fortuneprofile.pl \ +# ipc-test-client.c \ +# ipc-test-server.c \ +# startup.py +# +#AM_CPPFLAGS = \ +# -DDATADIR=\"$(datadir)\" \ +# -I$(top_srcdir)/libpurple \ +# -I$(top_builddir)/libpurple \ +# $(DEBUG_CFLAGS) \ +# $(GLIB_CFLAGS) \ +# $(GPLUGIN_CFLAGS) \ +# $(PLUGIN_CFLAGS) \ +# $(DBUS_CFLAGS) \ +# $(NSS_CFLAGS) +# +#PLUGIN_LIBS = \ +# $(NSS_LIBS) +# +## +## This part allows people to build their own plugins in here. +## Yes, it's a mess. +## +#SUFFIXES = .c .so +#.c.so: +# $(LIBTOOL) --mode=compile $(CC) -DHAVE_CONFIG_H -I$(top_builddir) $(AM_CPPFLAGS) $(CFLAGS) -c $< -o tmp$@.lo $(PLUGIN_CFLAGS) +# $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o libtmp$@.la -rpath $(plugindir) tmp$@.lo $(LIBS) $(LDFLAGS) -module -avoid-version $(PLUGIN_LIBS) +# @rm -f tmp$@.lo tmp$@.o libtmp$@.la +# @cp .libs/libtmp$@*.so $@ +# @rm -rf .libs/libtmp$@.*
--- a/libpurple/plugins/autoaccept.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/autoaccept.c Sun Aug 18 01:53:00 2013 +0530 @@ -31,7 +31,7 @@ #include <glib/gstdio.h> /* Purple headers */ -#include <plugin.h> +#include <plugins.h> #include <version.h> #include <buddylist.h>
--- a/libpurple/plugins/ciphertest.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/ciphertest.c Sun Aug 18 01:53:00 2013 +0530 @@ -33,7 +33,7 @@ #include <string.h> #include "debug.h" -#include "plugin.h" +#include "plugins.h" #include "version.h" #include "util.h"
--- a/libpurple/plugins/codeinline.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/codeinline.c Sun Aug 18 01:53:00 2013 +0530 @@ -21,7 +21,7 @@ */ #include "internal.h" -#include "plugin.h" +#include "plugins.h" #include "notify.h" #include "util.h" #include "version.h"
--- a/libpurple/plugins/dbus-example.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/dbus-example.c Sun Aug 18 01:53:00 2013 +0530 @@ -39,7 +39,7 @@ #include "buddylist.h" #include "notify.h" -#include "plugin.h" +#include "plugins.h" #include "version.h" #include <stdio.h>
--- a/libpurple/plugins/debug_example.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/debug_example.c Sun Aug 18 01:53:00 2013 +0530 @@ -48,7 +48,7 @@ * that we're including them in alphabetical order. This isn't necessary but * we do this throughout our source for consistency. */ #include "debug.h" -#include "plugin.h" +#include "plugins.h" #include "version.h" /* It's more convenient to type PLUGIN_ID all the time than it is to type
--- a/libpurple/plugins/helloworld.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/helloworld.c Sun Aug 18 01:53:00 2013 +0530 @@ -44,7 +44,7 @@ #endif #include <notify.h> -#include <plugin.h> +#include <plugins.h> #include <version.h> /* we're adding this here and assigning it in plugin_load because we need
--- a/libpurple/plugins/idle.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/idle.c Sun Aug 18 01:53:00 2013 +0530 @@ -27,7 +27,7 @@ #include "connection.h" #include "debug.h" #include "notify.h" -#include "plugin.h" +#include "plugins.h" #include "presence.h" #include "request.h" #include "server.h" @@ -53,7 +53,7 @@ { PurplePlugin *prpl; - prpl = purple_find_prpl(purple_account_get_protocol_id(account)); + prpl = purple_find_protocol_info(purple_account_get_protocol_id(account)); g_return_val_if_fail(prpl != NULL, FALSE); return (PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->set_idle != NULL);
--- a/libpurple/plugins/ipc-test-client.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/ipc-test-client.c Sun Aug 18 01:53:00 2013 +0530 @@ -20,7 +20,7 @@ */ #include "internal.h" #include "debug.h" -#include "plugin.h" +#include "plugins.h" #include "version.h" #define IPC_TEST_CLIENT_PLUGIN_ID "core-ipc-test-client"
--- a/libpurple/plugins/ipc-test-server.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/ipc-test-server.c Sun Aug 18 01:53:00 2013 +0530 @@ -22,7 +22,7 @@ #include "internal.h" #include "debug.h" -#include "plugin.h" +#include "plugins.h" #include "version.h" static int
--- a/libpurple/plugins/joinpart.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/joinpart.c Sun Aug 18 01:53:00 2013 +0530 @@ -23,7 +23,7 @@ #include "internal.h" #include "conversation.h" #include "debug.h" -#include "plugin.h" +#include "plugins.h" #include "version.h" #define JOINPART_PLUGIN_ID "core-rlaager-joinpart"
--- a/libpurple/plugins/keyrings/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/keyrings/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -72,5 +72,6 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(DEBUG_CPPFLAGS) \ $(PLUGIN_CFLAGS)
--- a/libpurple/plugins/keyrings/gnomekeyring.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/keyrings/gnomekeyring.c Sun Aug 18 01:53:00 2013 +0530 @@ -28,7 +28,7 @@ #include "account.h" #include "debug.h" #include "keyring.h" -#include "plugin.h" +#include "plugins.h" #include "version.h" #include <gnome-keyring.h> @@ -39,6 +39,7 @@ "GNOME Keyring.") #define GNOMEKEYRING_AUTHOR "Tomek Wasilczyk (tomkiewicz@cpw.pidgin.im)" #define GNOMEKEYRING_ID "keyring-gnomekeyring" +#define GNOMEKEYRING_DOMAIN (g_quark_from_static_string(GNOMEKEYRING_ID)) static PurpleKeyring *keyring_handler = NULL; static GList *request_queue = NULL; @@ -377,8 +378,26 @@ gnomekeyring_cancel(); } +static PurplePluginInfo * +plugin_query(GError **error) +{ + return purple_plugin_info_new( + "id", GNOMEKEYRING_ID, + "name", GNOMEKEYRING_NAME, + "version", DISPLAY_VERSION, + "category", N_("Keyring"), + "summary", "GNOME Keyring Plugin", + "description", GNOMEKEYRING_DESCRIPTION, + "author", GNOMEKEYRING_AUTHOR, + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL, + NULL + ); +} + static gboolean -gnomekeyring_load(PurplePlugin *plugin) +plugin_load(PurplePlugin *plugin, GError **error) { GModule *gkr_module; @@ -394,6 +413,8 @@ g_module_make_resident(gkr_module); if (!gnome_keyring_is_available()) { + g_set_error(error, GNOMEKEYRING_DOMAIN, 0, "GNOME Keyring service is " + "disabled."); purple_debug_info("keyring-gnome", "GNOME Keyring service is " "disabled\n"); return FALSE; @@ -415,9 +436,11 @@ } static gboolean -gnomekeyring_unload(PurplePlugin *plugin) +plugin_unload(PurplePlugin *plugin, GError **error) { if (purple_keyring_get_inuse() == keyring_handler) { + g_set_error(error, GNOMEKEYRING_DOMAIN, 0, "The keyring is currently " + "in use."); purple_debug_warning("keyring-gnome", "keyring in use, cannot unload\n"); return FALSE; @@ -432,36 +455,4 @@ return TRUE; } -PurplePluginInfo plugininfo = -{ - PURPLE_PLUGIN_MAGIC, /* magic */ - PURPLE_MAJOR_VERSION, /* major_version */ - PURPLE_MINOR_VERSION, /* minor_version */ - PURPLE_PLUGIN_STANDARD, /* type */ - NULL, /* ui_requirement */ - PURPLE_PLUGIN_FLAG_INVISIBLE, /* flags */ - NULL, /* dependencies */ - PURPLE_PRIORITY_DEFAULT, /* priority */ - GNOMEKEYRING_ID, /* id */ - GNOMEKEYRING_NAME, /* name */ - DISPLAY_VERSION, /* version */ - "GNOME Keyring Plugin", /* summary */ - GNOMEKEYRING_DESCRIPTION, /* description */ - GNOMEKEYRING_AUTHOR, /* author */ - PURPLE_WEBSITE, /* homepage */ - gnomekeyring_load, /* load */ - gnomekeyring_unload, /* unload */ - NULL, /* destroy */ - NULL, /* ui_info */ - NULL, /* extra_info */ - NULL, /* prefs_info */ - NULL, /* actions */ - NULL, NULL, NULL, NULL /* padding */ -}; - -static void -init_plugin(PurplePlugin *plugin) -{ -} - -PURPLE_INIT_PLUGIN(gnome_keyring, init_plugin, plugininfo) +PURPLE_PLUGIN_INIT(gnome_keyring, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/plugins/keyrings/internalkeyring.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/keyrings/internalkeyring.c Sun Aug 18 01:53:00 2013 +0530 @@ -28,7 +28,7 @@ #include "account.h" #include "debug.h" #include "keyring.h" -#include "plugin.h" +#include "plugins.h" #include "version.h" #include "ciphers/aescipher.h" @@ -40,6 +40,7 @@ "storage behaviour for libpurple.") #define INTKEYRING_AUTHOR "Tomek Wasilczyk (tomkiewicz@cpw.pidgin.im)" #define INTKEYRING_ID PURPLE_DEFAULT_KEYRING +#define INTKEYRING_DOMAIN (g_quark_from_static_string(INTKEYRING_ID)) #define INTKEYRING_VERIFY_STR "[verification-string]" #define INTKEYRING_PBKDF2_ITERATIONS 10000 @@ -954,9 +955,39 @@ return TRUE; } +static PurplePluginInfo * +plugin_query(GError **error) +{ + return purple_plugin_info_new( + "id", INTKEYRING_ID, + "name", INTKEYRING_NAME, + "version", DISPLAY_VERSION, + "category", N_("Keyring"), + "summary", "Internal Keyring Plugin", + "description", INTKEYRING_DESCRIPTION, + "author", INTKEYRING_AUTHOR, + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL, + NULL + ); +} + static gboolean -intkeyring_load(PurplePlugin *plugin) +plugin_load(PurplePlugin *plugin, GError **error) { + purple_prefs_add_none("/plugins/keyrings"); + purple_prefs_add_none("/plugins/keyrings/internal"); + purple_prefs_add_bool(INTKEYRING_PREFS "encrypt_passwords", FALSE); + purple_prefs_add_string(INTKEYRING_PREFS "encryption_method", + INTKEYRING_ENCRYPTION_METHOD); + purple_prefs_add_int(INTKEYRING_PREFS "pbkdf2_desired_iterations", + INTKEYRING_PBKDF2_ITERATIONS); + purple_prefs_add_int(INTKEYRING_PREFS "pbkdf2_iterations", + INTKEYRING_PBKDF2_ITERATIONS); + purple_prefs_add_string(INTKEYRING_PREFS "pbkdf2_salt", ""); + purple_prefs_add_string(INTKEYRING_PREFS "key_verifier", ""); + keyring_handler = purple_keyring_new(); purple_keyring_set_name(keyring_handler, _(INTKEYRING_NAME)); @@ -982,9 +1013,11 @@ } static gboolean -intkeyring_unload(PurplePlugin *plugin) +plugin_unload(PurplePlugin *plugin, GError **error) { if (purple_keyring_get_inuse() == keyring_handler) { + g_set_error(error, INTKEYRING_DOMAIN, 0, "The keyring is currently " + "in use."); purple_debug_warning("keyring-internal", "keyring in use, cannot unload\n"); return FALSE; @@ -1006,47 +1039,4 @@ return TRUE; } -PurplePluginInfo plugininfo = -{ - PURPLE_PLUGIN_MAGIC, /* magic */ - PURPLE_MAJOR_VERSION, /* major_version */ - PURPLE_MINOR_VERSION, /* minor_version */ - PURPLE_PLUGIN_STANDARD, /* type */ - NULL, /* ui_requirement */ - PURPLE_PLUGIN_FLAG_INVISIBLE, /* flags */ - NULL, /* dependencies */ - PURPLE_PRIORITY_DEFAULT, /* priority */ - INTKEYRING_ID, /* id */ - INTKEYRING_NAME, /* name */ - DISPLAY_VERSION, /* version */ - "Internal Keyring Plugin", /* summary */ - INTKEYRING_DESCRIPTION, /* description */ - INTKEYRING_AUTHOR, /* author */ - PURPLE_WEBSITE, /* homepage */ - intkeyring_load, /* load */ - intkeyring_unload, /* unload */ - NULL, /* destroy */ - NULL, /* ui_info */ - NULL, /* extra_info */ - NULL, /* prefs_info */ - NULL, /* actions */ - NULL, NULL, NULL, NULL /* padding */ -}; - -static void -init_plugin(PurplePlugin *plugin) -{ - purple_prefs_add_none("/plugins/keyrings"); - purple_prefs_add_none("/plugins/keyrings/internal"); - purple_prefs_add_bool(INTKEYRING_PREFS "encrypt_passwords", FALSE); - purple_prefs_add_string(INTKEYRING_PREFS "encryption_method", - INTKEYRING_ENCRYPTION_METHOD); - purple_prefs_add_int(INTKEYRING_PREFS "pbkdf2_desired_iterations", - INTKEYRING_PBKDF2_ITERATIONS); - purple_prefs_add_int(INTKEYRING_PREFS "pbkdf2_iterations", - INTKEYRING_PBKDF2_ITERATIONS); - purple_prefs_add_string(INTKEYRING_PREFS "pbkdf2_salt", ""); - purple_prefs_add_string(INTKEYRING_PREFS "key_verifier", ""); -} - -PURPLE_INIT_PLUGIN(internal_keyring, init_plugin, plugininfo) +PURPLE_PLUGIN_INIT(gnome_keyring, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/plugins/keyrings/kwallet.cpp Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/keyrings/kwallet.cpp Sun Aug 18 01:53:00 2013 +0530 @@ -29,7 +29,7 @@ #include "core.h" #include "debug.h" #include "keyring.h" -#include "plugin.h" +#include "plugins.h" #include "version.h" #include <QQueue> @@ -40,6 +40,7 @@ #define KWALLET_DESCRIPTION N_("This plugin will store passwords in KWallet.") #define KWALLET_AUTHOR "QuLogic (qulogic[at]pidgin.im)" #define KWALLET_ID "keyring-kwallet" +#define KWALLET_DOMAIN (g_quark_from_static_string(KWALLET_ID)) #define KWALLET_WALLET_NAME KWallet::Wallet::NetworkWallet() #define KWALLET_APP_NAME "Libpurple" @@ -488,8 +489,26 @@ return ui_name; } +static PurplePluginInfo * +plugin_query(GError **error) +{ + return purple_plugin_info_new( + "id", KWALLET_ID, + "name", KWALLET_NAME, + "version", DISPLAY_VERSION, + "category", N_("Keyring"), + "summary", "KWallet Keyring Plugin", + "description", KWALLET_DESCRIPTION, + "author", KWALLET_AUTHOR, + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL, + NULL + ); +} + static gboolean -kwallet_load(PurplePlugin *plugin) +plugin_load(PurplePlugin *plugin, GError **error) { if (!qCoreApp) { int argc = 0; @@ -498,6 +517,7 @@ } if (!kwallet_is_enabled()) { + g_set_error(error, KWALLET_DOMAIN, 0, "KWallet service is disabled."); purple_debug_info("keyring-kwallet", "KWallet service is disabled\n"); return FALSE; @@ -519,9 +539,11 @@ } static gboolean -kwallet_unload(PurplePlugin *plugin) +plugin_unload(PurplePlugin *plugin, GError **error) { if (purple_keyring_get_inuse() == keyring_handler) { + g_set_error(error, KWALLET_DOMAIN, 0, "The keyring is currently " + "in use."); purple_debug_warning("keyring-kwallet", "keyring in use, cannot unload\n"); return FALSE; @@ -543,39 +565,7 @@ return TRUE; } -PurplePluginInfo plugininfo = -{ - PURPLE_PLUGIN_MAGIC, /* magic */ - PURPLE_MAJOR_VERSION, /* major_version */ - PURPLE_MINOR_VERSION, /* minor_version */ - PURPLE_PLUGIN_STANDARD, /* type */ - NULL, /* ui_requirement */ - PURPLE_PLUGIN_FLAG_INVISIBLE, /* flags */ - NULL, /* dependencies */ - PURPLE_PRIORITY_DEFAULT, /* priority */ - KWALLET_ID, /* id */ - KWALLET_NAME, /* name */ - DISPLAY_VERSION, /* version */ - "KWallet Keyring Plugin", /* summary */ - KWALLET_DESCRIPTION, /* description */ - KWALLET_AUTHOR, /* author */ - PURPLE_WEBSITE, /* homepage */ - kwallet_load, /* load */ - kwallet_unload, /* unload */ - NULL, /* destroy */ - NULL, /* ui_info */ - NULL, /* extra_info */ - NULL, /* prefs_info */ - NULL, /* actions */ - NULL, NULL, NULL, NULL /* padding */ -}; - -static void -init_plugin(PurplePlugin *plugin) -{ -} - -PURPLE_INIT_PLUGIN(kwallet_keyring, init_plugin, plugininfo) +PURPLE_PLUGIN_INIT(gnome_keyring, plugin_query, plugin_load, plugin_unload); } /* extern "C" */
--- a/libpurple/plugins/keyrings/secretservice.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/keyrings/secretservice.c Sun Aug 18 01:53:00 2013 +0530 @@ -38,13 +38,14 @@ #include "account.h" #include "debug.h" #include "keyring.h" -#include "plugin.h" +#include "plugins.h" #include "version.h" #include <libsecret/secret.h> #define SECRETSERVICE_NAME N_("Secret Service") #define SECRETSERVICE_ID "keyring-libsecret" +#define SECRETSERVICE_DOMAIN (g_quark_from_static_string(SECRETSERVICE_ID)) static PurpleKeyring *keyring_handler = NULL; @@ -253,7 +254,7 @@ } static gboolean -ss_init(void) +ss_init(GError **error) { keyring_handler = purple_keyring_new(); @@ -281,57 +282,43 @@ /* Plugin interface */ /***********************************************/ -static gboolean -ss_load(PurplePlugin *plugin) +static PurplePluginInfo * +plugin_query(GError **error) { - return ss_init(); + return purple_plugin_info_new( + "id", SECRETSERVICE_ID, + "name", SECRETSERVICE_NAME, + "version", DISPLAY_VERSION, + "category", N_("Keyring"), + "summary", "Secret Service Plugin", + "description", N_("This plugin will store passwords in Secret Service."), + "author", "Elliott Sales de Andrade (qulogic[at]pidgin.im)", + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL, + NULL + ); } static gboolean -ss_unload(PurplePlugin *plugin) +plugin_load(PurplePlugin *plugin, GError **error) { - if (purple_keyring_get_inuse() == keyring_handler) + return ss_init(error); +} + +static gboolean +plugin_unload(PurplePlugin *plugin, GError **error) +{ + if (purple_keyring_get_inuse() == keyring_handler) { + g_set_error(error, SECRETSERVICE_DOMAIN, 0, "The keyring is currently " + "in use."); return FALSE; + } ss_uninit(); return TRUE; } -PurplePluginInfo plugininfo = -{ - PURPLE_PLUGIN_MAGIC, /* magic */ - PURPLE_MAJOR_VERSION, /* major_version */ - PURPLE_MINOR_VERSION, /* minor_version */ - PURPLE_PLUGIN_STANDARD, /* type */ - NULL, /* ui_requirement */ - PURPLE_PLUGIN_FLAG_INVISIBLE, /* flags */ - NULL, /* dependencies */ - PURPLE_PRIORITY_DEFAULT, /* priority */ - SECRETSERVICE_ID, /* id */ - SECRETSERVICE_NAME, /* name */ - DISPLAY_VERSION, /* version */ - "Secret Service Plugin", /* summary */ - N_("This plugin will store passwords in Secret Service."), /* description */ - "Elliott Sales de Andrade (qulogic[at]pidgin.im)", /* author */ - PURPLE_WEBSITE, /* homepage */ - ss_load, /* load */ - ss_unload, /* unload */ - NULL, /* destroy */ - NULL, /* ui_info */ - NULL, /* extra_info */ - NULL, /* prefs_info */ - NULL, /* actions */ - NULL, /* padding... */ - NULL, - NULL, - NULL, -}; +PURPLE_PLUGIN_INIT(gnome_keyring, plugin_query, plugin_load, plugin_unload); -static void -init_plugin(PurplePlugin *plugin) -{ -} - -PURPLE_INIT_PLUGIN(secret_service, init_plugin, plugininfo) -
--- a/libpurple/plugins/keyrings/wincred.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/keyrings/wincred.c Sun Aug 18 01:53:00 2013 +0530 @@ -27,7 +27,7 @@ #include "debug.h" #include "internal.h" #include "keyring.h" -#include "plugin.h" +#include "plugins.h" #include "version.h" #include <wincred.h> @@ -38,6 +38,7 @@ "credentials.") #define WINCRED_AUTHOR "Tomek Wasilczyk (tomkiewicz@cpw.pidgin.im)" #define WINCRED_ID "keyring-wincred" +#define WINCRED_DOMAIN (g_quark_from_static_string(WINCRED_ID)) #define WINCRED_MAX_TARGET_NAME 256 @@ -255,8 +256,26 @@ g_error_free(error); } +static PurplePluginInfo * +plugin_query(GError **error) +{ + return purple_plugin_info_new( + "id", WINCRED_ID, + "name", WINCRED_NAME, + "version", DISPLAY_VERSION, + "category", N_("Keyring"), + "summary", WINCRED_SUMMARY, + "description", WINCRED_DESCRIPTION, + "author", WINCRED_AUTHOR, + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL, + NULL + ); +} + static gboolean -wincred_load(PurplePlugin *plugin) +plugin_load(PurplePlugin *plugin, GError **error) { keyring_handler = purple_keyring_new(); @@ -271,9 +290,11 @@ } static gboolean -wincred_unload(PurplePlugin *plugin) +plugin_unload(PurplePlugin *plugin, GError **error) { if (purple_keyring_get_inuse() == keyring_handler) { + g_set_error(error, WINCRED_DOMAIN, 0, "The keyring is currently " + "in use."); purple_debug_warning("keyring-wincred", "keyring in use, cannot unload\n"); return FALSE; @@ -286,36 +307,4 @@ return TRUE; } -PurplePluginInfo plugininfo = -{ - PURPLE_PLUGIN_MAGIC, /* magic */ - PURPLE_MAJOR_VERSION, /* major_version */ - PURPLE_MINOR_VERSION, /* minor_version */ - PURPLE_PLUGIN_STANDARD, /* type */ - NULL, /* ui_requirement */ - PURPLE_PLUGIN_FLAG_INVISIBLE, /* flags */ - NULL, /* dependencies */ - PURPLE_PRIORITY_DEFAULT, /* priority */ - WINCRED_ID, /* id */ - WINCRED_NAME, /* name */ - DISPLAY_VERSION, /* version */ - WINCRED_SUMMARY, /* summary */ - WINCRED_DESCRIPTION, /* description */ - WINCRED_AUTHOR, /* author */ - PURPLE_WEBSITE, /* homepage */ - wincred_load, /* load */ - wincred_unload, /* unload */ - NULL, /* destroy */ - NULL, /* ui_info */ - NULL, /* extra_info */ - NULL, /* prefs_info */ - NULL, /* actions */ - NULL, NULL, NULL, NULL /* padding */ -}; - -static void -init_plugin(PurplePlugin *plugin) -{ -} - -PURPLE_INIT_PLUGIN(wincred_keyring, init_plugin, plugininfo) +PURPLE_PLUGIN_INIT(gnome_keyring, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/plugins/log_reader.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/log_reader.c Sun Aug 18 01:53:00 2013 +0530 @@ -4,7 +4,7 @@ #include "debug.h" #include "log.h" -#include "plugin.h" +#include "plugins.h" #include "pluginpref.h" #include "prefs.h" #include "stringref.h" @@ -67,8 +67,8 @@ GList *list = NULL; const char *logdir; PurplePlugin *plugin; - PurplePluginProtocolInfo *prpl_info; - char *prpl_name; + PurpleProtocol *protocol; + char *protocol_name; char *temp; char *path; GDir *dir; @@ -82,17 +82,17 @@ if (!logdir || !*logdir) return NULL; - plugin = purple_find_prpl(purple_account_get_protocol_id(account)); + plugin = purple_find_protocol_info(purple_account_get_protocol_id(account)); if (!plugin) return NULL; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); - if (!prpl_info->list_icon) + protocol = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); + if (!protocol->list_icon) return NULL; - prpl_name = g_ascii_strup(prpl_info->list_icon(account, NULL), -1); - - temp = g_strdup_printf("%s.%s", prpl_name, purple_account_get_username(account)); + protocol_name = g_ascii_strup(protocol->list_icon(account, NULL), -1); + + temp = g_strdup_printf("%s.%s", protocol_name, purple_account_get_username(account)); path = g_build_filename(logdir, temp, sn, NULL); g_free(temp); @@ -227,7 +227,7 @@ g_dir_close(dir); } - g_free(prpl_name); + g_free(protocol_name); g_free(path); return list; @@ -1206,8 +1206,8 @@ GList *list = NULL; const char *logdir; PurplePlugin *plugin; - PurplePluginProtocolInfo *prpl_info; - char *prpl_name; + PurpleProtocol *protocol; + char *protocol_name; const char *buddy_name; char *filename; char *path; @@ -1226,21 +1226,21 @@ if (!logdir || !*logdir) return NULL; - plugin = purple_find_prpl(purple_account_get_protocol_id(account)); + plugin = purple_find_protocol_info(purple_account_get_protocol_id(account)); if (!plugin) return NULL; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); - if (!prpl_info->list_icon) + protocol = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); + if (!protocol->list_icon) return NULL; - prpl_name = g_ascii_strup(prpl_info->list_icon(account, NULL), -1); + protocol_name = g_ascii_strup(protocol->list_icon(account, NULL), -1); buddy_name = purple_normalize(account, sn); filename = g_strdup_printf("%s.log", buddy_name); path = g_build_filename( - logdir, prpl_name, filename, NULL); + logdir, protocol_name, filename, NULL); purple_debug_info("Trillian log list", "Reading %s\n", path); /* FIXME: There's really no need to read the entire file at once. @@ -1254,7 +1254,7 @@ g_free(path); path = g_build_filename( - logdir, prpl_name, "Query", filename, NULL); + logdir, protocol_name, "Query", filename, NULL); purple_debug_info("Trillian log list", "Reading %s\n", path); if (!g_file_get_contents(path, &contents, &length, &error)) { if (error) @@ -1390,7 +1390,7 @@ } g_free(path); - g_free(prpl_name); + g_free(protocol_name); return g_list_reverse(list); } @@ -1757,7 +1757,7 @@ GList *list = NULL; const char *logdir; PurplePlugin *plugin; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; char *username; char *filename; char *path; @@ -1786,12 +1786,12 @@ if (!logdir || !*logdir) return NULL; - plugin = purple_find_prpl(purple_account_get_protocol_id(account)); + plugin = purple_find_protocol_info(purple_account_get_protocol_id(account)); if (!plugin) return NULL; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); - if (!prpl_info->list_icon) + protocol = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); + if (!protocol->list_icon) return NULL; username = g_strdup(purple_normalize(account, purple_account_get_username(account)));
--- a/libpurple/plugins/mono/loader/mono-helper.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/mono/loader/mono-helper.h Sun Aug 18 01:53:00 2013 +0530 @@ -7,7 +7,7 @@ #include <mono/metadata/assembly.h> #include <mono/metadata/debug-helpers.h> #include <mono/metadata/tokentype.h> -#include "plugin.h" +#include "plugins.h" #include "debug.h" typedef struct {
--- a/libpurple/plugins/mono/loader/mono.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/mono/loader/mono.c Sun Aug 18 01:53:00 2013 +0530 @@ -12,7 +12,7 @@ #include "internal.h" #include "debug.h" -#include "plugin.h" +#include "plugins.h" #include "version.h" #include "mono-helper.h"
--- a/libpurple/plugins/newline.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/newline.c Sun Aug 18 01:53:00 2013 +0530 @@ -22,7 +22,7 @@ #include <conversation.h> #include <debug.h> -#include <plugin.h> +#include <plugins.h> #include <signals.h> #include <util.h> #include <version.h>
--- a/libpurple/plugins/notify_example.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/notify_example.c Sun Aug 18 01:53:00 2013 +0530 @@ -47,7 +47,7 @@ #define PLUGIN_AUTHOR "John Bailey <rekkanoryo@cpw.pidgin.im>" #include <notify.h> -#include <plugin.h> +#include <plugins.h> #include <version.h> static PurplePlugin *notify_example = NULL;
--- a/libpurple/plugins/one_time_password.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/one_time_password.c Sun Aug 18 01:53:00 2013 +0530 @@ -20,7 +20,7 @@ */ #include "internal.h" #include "debug.h" -#include "plugin.h" +#include "plugins.h" #include "version.h" #include "account.h" #include "accountopt.h" @@ -56,18 +56,18 @@ plugin_load(PurplePlugin *plugin) { PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; PurpleAccountOption *option; GList *l; /* Register protocol preference. */ for (l = purple_plugins_get_protocols(); l != NULL; l = l->next) { prpl = (PurplePlugin *)l->data; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (prpl_info != NULL && !(prpl_info->options & OPT_PROTO_NO_PASSWORD)) { + protocol = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + if (protocol != NULL && !(protocol->options & OPT_PROTO_NO_PASSWORD)) { option = purple_account_option_bool_new(_("One Time Password"), PREF_NAME, FALSE); - prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); + protocol->protocol_options = g_list_append(protocol->protocol_options, option); } } @@ -82,20 +82,20 @@ plugin_unload(PurplePlugin *plugin) { PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; PurpleAccountOption *option; GList *l, *options; /* Remove protocol preference. */ for (l = purple_plugins_get_protocols(); l != NULL; l = l->next) { prpl = (PurplePlugin *)l->data; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (prpl_info != NULL && !(prpl_info->options & OPT_PROTO_NO_PASSWORD)) { - options = prpl_info->protocol_options; + protocol = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + if (protocol != NULL && !(protocol->options & OPT_PROTO_NO_PASSWORD)) { + options = protocol->protocol_options; while (options != NULL) { option = (PurpleAccountOption *) options->data; if (strcmp(PREF_NAME, purple_account_option_get_setting(option)) == 0) { - prpl_info->protocol_options = g_list_delete_link(prpl_info->protocol_options, options); + protocol->protocol_options = g_list_delete_link(protocol->protocol_options, options); purple_account_option_destroy(option); break; }
--- a/libpurple/plugins/perl/common/Cmds.xs Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/perl/common/Cmds.xs Sun Aug 18 01:53:00 2013 +0530 @@ -17,7 +17,7 @@ const_iv(FAILED), const_iv(NOT_FOUND), const_iv(WRONG_ARGS), - const_iv(WRONG_PRPL), + const_iv(WRONG_PROTOCOL), const_iv(WRONG_TYPE), }; static const constiv ret_const_iv[] = { @@ -44,7 +44,7 @@ #define const_iv(name) {#name, (IV)PURPLE_CMD_FLAG_##name} const_iv(IM), const_iv(CHAT), - const_iv(PRPL_ONLY), + const_iv(PROTOCOL_ONLY), const_iv(ALLOW_WRONG_ARGS), }; @@ -85,19 +85,19 @@ g_list_free(ll); Purple::Cmd::Id -purple_cmd_register(plugin, command, args, priority, flag, prpl_id, func, helpstr, data = 0) +purple_cmd_register(plugin, command, args, priority, flag, protocol_id, func, helpstr, data = 0) Purple::Plugin plugin const gchar *command const gchar *args Purple::Cmd::Priority priority Purple::Cmd::Flag flag - const gchar *prpl_id + const gchar *protocol_id SV *func const gchar *helpstr SV *data CODE: RETVAL = purple_perl_cmd_register(plugin, command, args, priority, flag, - prpl_id, func, helpstr, data); + protocol_id, func, helpstr, data); OUTPUT: RETVAL
--- a/libpurple/plugins/perl/common/Prpl.xs Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/perl/common/Prpl.xs Sun Aug 18 01:53:00 2013 +0530 @@ -4,26 +4,26 @@ PROTOTYPES: ENABLE Purple::Plugin -purple_find_prpl(id) +purple_find_protocol_info(id) const char *id -MODULE = Purple::Prpl PACKAGE = Purple::Prpl PREFIX = purple_prpl_ +MODULE = Purple::Prpl PACKAGE = Purple::Prpl PREFIX = purple_protocol_ PROTOTYPES: ENABLE void -purple_prpl_change_account_status(account, old_status, new_status) +purple_protocol_change_account_status(account, old_status, new_status) Purple::Account account Purple::Status old_status Purple::Status new_status void -purple_prpl_get_statuses(account, presence) +purple_protocol_get_statuses(account, presence) Purple::Account account Purple::Presence presence PREINIT: GList *l, *ll; PPCODE: - ll = purple_prpl_get_statuses(account,presence); + ll = purple_protocol_get_statuses(account,presence); for (l = ll; l != NULL; l = l->next) { XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Status"))); } @@ -32,42 +32,42 @@ g_list_free(ll); void -purple_prpl_got_account_idle(account, idle, idle_time) +purple_protocol_got_account_idle(account, idle, idle_time) Purple::Account account gboolean idle time_t idle_time void -purple_prpl_got_account_login_time(account, login_time) +purple_protocol_got_account_login_time(account, login_time) Purple::Account account time_t login_time void -purple_prpl_got_user_idle(account, name, idle, idle_time) +purple_protocol_got_user_idle(account, name, idle, idle_time) Purple::Account account const char *name gboolean idle time_t idle_time void -purple_prpl_got_user_login_time(account, name, login_time) +purple_protocol_got_user_login_time(account, name, login_time) Purple::Account account const char *name time_t login_time int -purple_prpl_send_raw(gc, str) +purple_protocol_send_raw(gc, str) Purple::Connection gc const char *str PREINIT: - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; CODE: if (!gc) RETVAL = 0; else { - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - if (prpl_info && prpl_info->send_raw != NULL) { - RETVAL = prpl_info->send_raw(gc, str, strlen(str)); + protocol = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_protocol_info(gc)); + if (protocol && protocol->send_raw != NULL) { + RETVAL = protocol->send_raw(gc, str, strlen(str)); } else { RETVAL = 0; }
--- a/libpurple/plugins/perl/common/module.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/perl/common/module.h Sun Aug 18 01:53:00 2013 +0530 @@ -55,12 +55,12 @@ #include "imgstore.h" #include "network.h" #include "notify.h" -#include "plugin.h" +#include "plugins.h" #include "pluginpref.h" #include "pounce.h" #include "prefs.h" #include "presence.h" -#include "prpl.h" +#include "protocol.h" #include "proxy.h" #include "request.h" #include "roomlist.h" @@ -203,7 +203,7 @@ typedef PurpleNotifyUserInfo * Purple__NotifyUserInfo; typedef PurpleNotifyUserInfoEntry * Purple__NotifyUserInfoEntry; -/* plugin.h */ +/* plugins.h */ typedef PurplePlugin * Purple__Plugin; typedef PurplePluginAction * Purple__Plugin__Action; typedef PurplePluginInfo * Purple__PluginInfo; @@ -233,10 +233,10 @@ typedef PurpleProxyInfo * Purple__ProxyInfo; typedef PurpleProxyType Purple__ProxyType; -/* prpl.h */ +/* protocol.h */ typedef PurpleBuddyIconSpec * Purple__Buddy__Icon__Spec; typedef PurpleIconScaleRules Purple__IconScaleRules; -typedef PurplePluginProtocolInfo * Purple__PluginProtocolInfo; +typedef PurpleProtocol * Purple__PluginProtocolInfo; typedef PurpleProtocolOptions Purple__ProtocolOptions; /* request.h */
--- a/libpurple/plugins/perl/perl-common.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/perl/perl-common.h Sun Aug 18 01:53:00 2013 +0530 @@ -20,7 +20,7 @@ #ifdef _WIN32 #undef _WIN32DEP_H_ #endif -#include "plugin.h" +#include "plugins.h" #define is_hvref(o) \ ((o) && SvROK(o) && SvRV(o) && (SvTYPE(SvRV(o)) == SVt_PVHV))
--- a/libpurple/plugins/perl/perl-handlers.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/perl/perl-handlers.c Sun Aug 18 01:53:00 2013 +0530 @@ -625,7 +625,7 @@ PurpleCmdId purple_perl_cmd_register(PurplePlugin *plugin, const gchar *command, const gchar *args, PurpleCmdPriority priority, - PurpleCmdFlag flag, const gchar *prpl_id, SV *callback, + PurpleCmdFlag flag, const gchar *protocol_id, SV *callback, const gchar *helpstr, SV *data) { PurplePerlCmdHandler *handler; @@ -633,7 +633,7 @@ handler = g_new0(PurplePerlCmdHandler, 1); handler->plugin = plugin; handler->cmd = g_strdup(command); - handler->prpl_id = g_strdup(prpl_id); + handler->protocol_id = g_strdup(protocol_id); if (callback != NULL && callback != &PL_sv_undef) handler->callback = newSVsv(callback); @@ -647,7 +647,7 @@ cmd_handlers = g_slist_append(cmd_handlers, handler); - handler->id = purple_cmd_register(command, args, priority, flag, prpl_id, + handler->id = purple_cmd_register(command, args, priority, flag, protocol_id, PURPLE_CMD_FUNC(perl_cmd_cb), helpstr, handler); @@ -667,7 +667,7 @@ SvREFCNT_dec(handler->data); g_free(handler->cmd); - g_free(handler->prpl_id); + g_free(handler->protocol_id); g_free(handler); }
--- a/libpurple/plugins/perl/perl-handlers.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/perl/perl-handlers.h Sun Aug 18 01:53:00 2013 +0530 @@ -2,7 +2,7 @@ #define _PURPLE_PERL_HANDLERS_H_ #include "cmds.h" -#include "plugin.h" +#include "plugins.h" #include "prefs.h" #include "pluginpref.h" #ifdef PURPLE_GTKPERL @@ -15,7 +15,7 @@ PurpleCmdId id; SV *callback; SV *data; - gchar *prpl_id; + gchar *protocol_id; gchar *cmd; PurplePlugin *plugin; } PurplePerlCmdHandler; @@ -73,7 +73,7 @@ PurpleCmdId purple_perl_cmd_register(PurplePlugin *plugin, const gchar *cmd, const gchar *args, PurpleCmdPriority priority, - PurpleCmdFlag flag, const gchar *prpl_id, + PurpleCmdFlag flag, const gchar *protocol_id, SV *callback, const gchar *helpstr, SV *data); void purple_perl_cmd_unregister(PurpleCmdId id); void purple_perl_cmd_clear_for_plugin(PurplePlugin *plugin);
--- a/libpurple/plugins/perl/perl.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/perl/perl.c Sun Aug 18 01:53:00 2013 +0530 @@ -90,7 +90,7 @@ #endif #include "internal.h" #include "debug.h" -#include "plugin.h" +#include "plugins.h" #include "signals.h" #include "version.h"
--- a/libpurple/plugins/pluginpref_example.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/pluginpref_example.c Sun Aug 18 01:53:00 2013 +0530 @@ -29,7 +29,7 @@ #include "internal.h" -#include "plugin.h" +#include "plugins.h" #include "pluginpref.h" #include "prefs.h" #include "version.h"
--- a/libpurple/plugins/psychic.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/psychic.c Sun Aug 18 01:53:00 2013 +0530 @@ -10,7 +10,7 @@ #include "status.h" #include "version.h" -#include "plugin.h" +#include "plugins.h" #include "pluginpref.h" #include "prefs.h"
--- a/libpurple/plugins/signals-test.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/signals-test.c Sun Aug 18 01:53:00 2013 +0530 @@ -676,7 +676,7 @@ xmlnode_set_attrib(iq, "id", id); xmlnode_set_attrib(iq, "type", "result"); - purple_signal_emit(purple_connection_get_prpl(pc), + purple_signal_emit(purple_connection_get_protocol_info(pc), "jabber-sending-xmlnode", pc, &iq); if (iq != NULL) xmlnode_free(iq);
--- a/libpurple/plugins/simple.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/simple.c Sun Aug 18 01:53:00 2013 +0530 @@ -1,6 +1,6 @@ #include "internal.h" #include "debug.h" -#include "plugin.h" +#include "plugins.h" #include "version.h" /** Plugin id : type-author-name (to guarantee uniqueness) */
--- a/libpurple/plugins/ssl/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/ssl/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -37,6 +37,7 @@ -I$(top_builddir)/libpurple \ $(DEBUG_CFLAGS) \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(PLUGIN_CFLAGS) ssl_gnutls_la_CFLAGS = $(AM_CPPFLAGS) $(GNUTLS_CFLAGS)
--- a/libpurple/plugins/ssl/ssl-gnutls.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/ssl/ssl-gnutls.c Sun Aug 18 01:53:00 2013 +0530 @@ -22,7 +22,7 @@ #include "internal.h" #include "debug.h" #include "certificate.h" -#include "plugin.h" +#include "plugins.h" #include "sslconn.h" #include "version.h" #include "util.h" @@ -1277,8 +1277,26 @@ NULL }; +static PurplePluginInfo * +plugin_query(GError **error) +{ + return purple_plugin_info_new( + "id", SSL_GNUTLS_PLUGIN_ID, + "name", N_("GNUTLS"), + "version", DISPLAY_VERSION, + "category", N_("SSL"), + "summary", N_("Provides SSL support through GNUTLS."), + "description", N_("Provides SSL support through GNUTLS."), + "author", "Christian Hammond <chipx86@gnupdate.org>", + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL, + NULL + ); +} + static gboolean -plugin_load(PurplePlugin *plugin) +plugin_load(PurplePlugin *plugin, GError **error) { if(!purple_ssl_get_ops()) { purple_ssl_set_ops(&ssl_ops); @@ -1294,7 +1312,7 @@ } static gboolean -plugin_unload(PurplePlugin *plugin) +plugin_unload(PurplePlugin *plugin, GError **error) { if(purple_ssl_get_ops() == &ssl_ops) { purple_ssl_set_ops(NULL); @@ -1305,46 +1323,4 @@ return TRUE; } -static PurplePluginInfo info = -{ - PURPLE_PLUGIN_MAGIC, - PURPLE_MAJOR_VERSION, - PURPLE_MINOR_VERSION, - PURPLE_PLUGIN_STANDARD, /**< type */ - NULL, /**< ui_requirement */ - PURPLE_PLUGIN_FLAG_INVISIBLE, /**< flags */ - NULL, /**< dependencies */ - PURPLE_PRIORITY_DEFAULT, /**< priority */ - - SSL_GNUTLS_PLUGIN_ID, /**< id */ - N_("GNUTLS"), /**< name */ - DISPLAY_VERSION, /**< version */ - /** summary */ - N_("Provides SSL support through GNUTLS."), - /** description */ - N_("Provides SSL support through GNUTLS."), - "Christian Hammond <chipx86@gnupdate.org>", - 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(ssl_gnutls, init_plugin, info) +PURPLE_PLUGIN_INIT(ssl_gnutls, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/plugins/ssl/ssl-nss.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/ssl/ssl-nss.c Sun Aug 18 01:53:00 2013 +0530 @@ -22,7 +22,7 @@ #include "internal.h" #include "debug.h" #include "certificate.h" -#include "plugin.h" +#include "plugins.h" #include "sslconn.h" #include "util.h" #include "version.h" @@ -1053,9 +1053,26 @@ NULL }; +static PurplePluginInfo * +plugin_query(GError **error) +{ + return purple_plugin_info_new( + "id", SSL_NSS_PLUGIN_ID, + "name", N_("NSS"), + "version", DISPLAY_VERSION, + "category", N_("SSL"), + "summary", N_("Provides SSL support through Mozilla NSS."), + "description", N_("Provides SSL support through Mozilla NSS."), + "author", "Christian Hammond <chipx86@gnupdate.org>", + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL, + NULL + ); +} static gboolean -plugin_load(PurplePlugin *plugin) +plugin_load(PurplePlugin *plugin, GError **error) { if (!purple_ssl_get_ops()) { purple_ssl_set_ops(&ssl_ops); @@ -1071,7 +1088,7 @@ } static gboolean -plugin_unload(PurplePlugin *plugin) +plugin_unload(PurplePlugin *plugin, GError **error) { if (purple_ssl_get_ops() == &ssl_ops) { purple_ssl_set_ops(NULL); @@ -1083,46 +1100,4 @@ return TRUE; } -static PurplePluginInfo info = -{ - PURPLE_PLUGIN_MAGIC, - PURPLE_MAJOR_VERSION, - PURPLE_MINOR_VERSION, - PURPLE_PLUGIN_STANDARD, /**< type */ - NULL, /**< ui_requirement */ - PURPLE_PLUGIN_FLAG_INVISIBLE, /**< flags */ - NULL, /**< dependencies */ - PURPLE_PRIORITY_DEFAULT, /**< priority */ - - SSL_NSS_PLUGIN_ID, /**< id */ - N_("NSS"), /**< name */ - DISPLAY_VERSION, /**< version */ - /** summary */ - N_("Provides SSL support through Mozilla NSS."), - /** description */ - N_("Provides SSL support through Mozilla NSS."), - "Christian Hammond <chipx86@gnupdate.org>", - 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(ssl_nss, init_plugin, info) +PURPLE_PLUGIN_INIT(ssl_nss, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/plugins/ssl/ssl.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/ssl/ssl.c Sun Aug 18 01:53:00 2013 +0530 @@ -21,33 +21,36 @@ */ #include "internal.h" #include "debug.h" -#include "plugin.h" +#include "plugins.h" #include "sslconn.h" #include "version.h" -#define SSL_PLUGIN_ID "core-ssl" +#define SSL_PLUGIN_ID "core-ssl" +#define SSL_PLUGIN_DOMAIN (g_quark_from_static_string(SSL_PLUGIN_ID)) static PurplePlugin *ssl_plugin = NULL; static gboolean -probe_ssl_plugins(PurplePlugin *my_plugin) +probe_ssl_plugins(PurplePlugin *my_plugin, GError **error) { PurplePlugin *plugin; - GList *l; + GList *plugins, *l; ssl_plugin = NULL; - for (l = purple_plugins_get_all(); l != NULL; l = l->next) + plugins = purple_plugins_find_all(); + + for (l = plugins; l != NULL; l = l->next) { - plugin = (PurplePlugin *)l->data; + plugin = PURPLE_PLUGIN(l->data); if (plugin == my_plugin) continue; - if (plugin->info != NULL && plugin->info->id != NULL && - strncmp(plugin->info->id, "ssl-", 4) == 0) + if (strncmp(purple_plugin_info_get_id(purple_plugin_get_info(plugin)), + "ssl-", 4) == 0) { - if (purple_plugin_is_loaded(plugin) || purple_plugin_load(plugin)) + if (purple_plugin_load(plugin, NULL)) { ssl_plugin = plugin; @@ -56,22 +59,49 @@ } } - return (ssl_plugin != NULL); + g_list_free(plugins); + + if (ssl_plugin == NULL) { + g_set_error(error, SSL_PLUGIN_DOMAIN, 0, + "Could not load a plugin that implements SSL."); + return FALSE; + } else { + return TRUE; + } +} + +static PurplePluginInfo * +plugin_query(GError **error) +{ + return purple_plugin_info_new( + "id", SSL_PLUGIN_ID, + "name", N_("SSL"), + "version", DISPLAY_VERSION, + "category", N_("SSL"), + "summary", N_("Provides a wrapper around SSL support libraries."), + "description", N_("Provides a wrapper around SSL support libraries."), + "author", "Christian Hammond <chipx86@gnupdate.org>", + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL, + NULL + ); } static gboolean -plugin_load(PurplePlugin *plugin) +plugin_load(PurplePlugin *plugin, GError **error) { - return probe_ssl_plugins(plugin); + return probe_ssl_plugins(plugin, error); } static gboolean -plugin_unload(PurplePlugin *plugin) +plugin_unload(PurplePlugin *plugin, GError **error) { if (ssl_plugin != NULL && g_list_find(purple_plugins_get_loaded(), ssl_plugin) != NULL) { - purple_plugin_unload(ssl_plugin); + if (!purple_plugin_unload(ssl_plugin, error)) + return FALSE; } ssl_plugin = NULL; @@ -79,46 +109,4 @@ return TRUE; } -static PurplePluginInfo info = -{ - PURPLE_PLUGIN_MAGIC, - PURPLE_MAJOR_VERSION, - PURPLE_MINOR_VERSION, - PURPLE_PLUGIN_STANDARD, /**< type */ - NULL, /**< ui_requirement */ - PURPLE_PLUGIN_FLAG_INVISIBLE, /**< flags */ - NULL, /**< dependencies */ - PURPLE_PRIORITY_DEFAULT, /**< priority */ - - SSL_PLUGIN_ID, /**< id */ - N_("SSL"), /**< name */ - DISPLAY_VERSION, /**< version */ - /** summary */ - N_("Provides a wrapper around SSL support libraries."), - /** description */ - N_("Provides a wrapper around SSL support libraries."), - "Christian Hammond <chipx86@gnupdate.org>", - PURPLE_WEBSITE, /**< homepage */ - - plugin_load, /**< load */ - plugin_unload, /**< unload */ - NULL, /**< destroy */ - - NULL, /**< ui_info */ - NULL, /**< extra_info */ - NULL, - NULL, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - -static void -init_plugin(PurplePlugin *plugin) -{ -} - -PURPLE_INIT_PLUGIN(ssl, init_plugin, info) +PURPLE_PLUGIN_INIT(ssl, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/plugins/statenotify.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/statenotify.c Sun Aug 18 01:53:00 2013 +0530 @@ -6,7 +6,7 @@ #include "signals.h" #include "version.h" -#include "plugin.h" +#include "plugins.h" #include "pluginpref.h" #include "prefs.h"
--- a/libpurple/plugins/tcl/tcl.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/tcl/tcl.c Sun Aug 18 01:53:00 2013 +0530 @@ -38,7 +38,7 @@ #include "internal.h" #include "connection.h" -#include "plugin.h" +#include "plugins.h" #include "signals.h" #include "debug.h" #include "util.h"
--- a/libpurple/plugins/tcl/tcl_cmd.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/tcl/tcl_cmd.c Sun Aug 18 01:53:00 2013 +0530 @@ -71,7 +71,7 @@ if ((id = purple_cmd_register(Tcl_GetString(handler->cmd), handler->args, handler->priority, - handler->flags, handler->prpl_id, + handler->flags, handler->protocol_id, PURPLE_CMD_FUNC(tcl_cmd_callback), handler->helpstr, (void *)handler)) == 0) return 0;
--- a/libpurple/plugins/tcl/tcl_cmds.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/tcl/tcl_cmds.c Sun Aug 18 01:53:00 2013 +0530 @@ -631,7 +631,7 @@ break; case CMD_CMD_REGISTER: if (objc != 9) { - Tcl_WrongNumArgs(interp, 2, objv, "cmd arglist priority flags prpl_id proc helpstr"); + Tcl_WrongNumArgs(interp, 2, objv, "cmd arglist priority flags protocol_id proc helpstr"); return TCL_ERROR; } handler = g_new0(struct tcl_cmd_handler, 1); @@ -648,7 +648,7 @@ g_free(handler); return error; } - handler->prpl_id = Tcl_GetString(objv[6]); + handler->protocol_id = Tcl_GetString(objv[6]); handler->proc = objv[7]; handler->helpstr = Tcl_GetString(objv[8]); handler->interp = interp;
--- a/libpurple/plugins/tcl/tcl_purple.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/plugins/tcl/tcl_purple.h Sun Aug 18 01:53:00 2013 +0530 @@ -27,7 +27,7 @@ #include "internal.h" #include "cmds.h" -#include "plugin.h" +#include "plugins.h" #include "stringref.h" struct tcl_signal_handler { @@ -55,7 +55,7 @@ const char *args; int priority; int flags; - const char *prpl_id; + const char *protocol_id; Tcl_Obj *proc; const char *helpstr;
--- a/libpurple/presence.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/presence.c Sun Aug 18 01:53:00 2013 +0530 @@ -553,8 +553,7 @@ { PurpleAccount *account; PurpleConnection *gc = NULL; - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; gboolean idle = purple_presence_is_idle(presence); time_t idle_time = purple_presence_get_idle_time(presence); time_t current_time = time(NULL); @@ -585,14 +584,11 @@ gc = purple_account_get_connection(account); - if(gc) - prpl = purple_connection_get_prpl(gc); + if(PURPLE_CONNECTION_IS_CONNECTED(gc)) + protocol = purple_connection_get_protocol_info(gc); - if(PURPLE_CONNECTION_IS_CONNECTED(gc) && prpl != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if (prpl_info && prpl_info->set_idle) - prpl_info->set_idle(gc, (idle ? (current_time - idle_time) : 0)); + if (protocol && protocol->set_idle) + protocol->set_idle(gc, (idle ? (current_time - idle_time) : 0)); } PurpleAccount * @@ -734,7 +730,7 @@ G_OBJECT_CLASS(presence_class)->constructed(object); PURPLE_PRESENCE_GET_PRIVATE(presence)->statuses = - purple_prpl_get_statuses(priv->account, presence); + purple_protocol_get_statuses(priv->account, presence); } /* Class initializer function */ @@ -931,7 +927,7 @@ account = purple_buddy_get_account(priv->buddy); PURPLE_PRESENCE_GET_PRIVATE(presence)->statuses = - purple_prpl_get_statuses(account, presence); + purple_protocol_get_statuses(account, presence); } /* Class initializer function */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocol.c Sun Aug 18 01:53:00 2013 +0530 @@ -0,0 +1,756 @@ +/* + * 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 + * + */ +#include "internal.h" +#include "accountopt.h" +#include "conversation.h" +#include "debug.h" +#include "network.h" +#include "notify.h" +#include "protocol.h" +#include "request.h" +#include "util.h" + +static GHashTable *protocols = NULL; + +/**************************************************************************/ +/** @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) +{ + PurpleAttentionType *attn = g_new0(PurpleAttentionType, 1); + + purple_attention_type_set_name(attn, name); + purple_attention_type_set_incoming_desc(attn, inc_desc); + purple_attention_type_set_outgoing_desc(attn, out_desc); + purple_attention_type_set_unlocalized_name(attn, ulname); + + return attn; +} + + +void +purple_attention_type_set_name(PurpleAttentionType *type, const char *name) +{ + g_return_if_fail(type != NULL); + + type->name = name; +} + +void +purple_attention_type_set_incoming_desc(PurpleAttentionType *type, const char *desc) +{ + g_return_if_fail(type != NULL); + + type->incoming_description = desc; +} + +void +purple_attention_type_set_outgoing_desc(PurpleAttentionType *type, const char *desc) +{ + g_return_if_fail(type != NULL); + + type->outgoing_description = desc; +} + +void +purple_attention_type_set_icon_name(PurpleAttentionType *type, const char *name) +{ + g_return_if_fail(type != NULL); + + type->icon_name = name; +} + +void +purple_attention_type_set_unlocalized_name(PurpleAttentionType *type, const char *ulname) +{ + g_return_if_fail(type != NULL); + + type->unlocalized_name = ulname; +} + +const char * +purple_attention_type_get_name(const PurpleAttentionType *type) +{ + g_return_val_if_fail(type != NULL, NULL); + + return type->name; +} + +const char * +purple_attention_type_get_incoming_desc(const PurpleAttentionType *type) +{ + g_return_val_if_fail(type != NULL, NULL); + + return type->incoming_description; +} + +const char * +purple_attention_type_get_outgoing_desc(const PurpleAttentionType *type) +{ + g_return_val_if_fail(type != NULL, NULL); + + return type->outgoing_description; +} + +const char * +purple_attention_type_get_icon_name(const PurpleAttentionType *type) +{ + g_return_val_if_fail(type != NULL, NULL); + + if(type->icon_name == NULL || *(type->icon_name) == '\0') + return NULL; + + return type->icon_name; +} + +const char * +purple_attention_type_get_unlocalized_name(const PurpleAttentionType *type) +{ + g_return_val_if_fail(type != NULL, NULL); + + return type->unlocalized_name; +} + +/**************************************************************************/ +/** @name Protocol Plugin API */ +/**************************************************************************/ +void +purple_protocol_got_account_idle(PurpleAccount *account, gboolean idle, + time_t idle_time) +{ + g_return_if_fail(account != NULL); + g_return_if_fail(purple_account_is_connected(account)); + + purple_presence_set_idle(purple_account_get_presence(account), + idle, idle_time); +} + +void +purple_protocol_got_account_login_time(PurpleAccount *account, time_t login_time) +{ + PurplePresence *presence; + + g_return_if_fail(account != NULL); + g_return_if_fail(purple_account_is_connected(account)); + + if (login_time == 0) + login_time = time(NULL); + + presence = purple_account_get_presence(account); + + purple_presence_set_login_time(presence, login_time); +} + +void +purple_protocol_got_account_status(PurpleAccount *account, const char *status_id, ...) +{ + PurplePresence *presence; + PurpleStatus *status; + va_list args; + + g_return_if_fail(account != NULL); + g_return_if_fail(status_id != NULL); + g_return_if_fail(purple_account_is_connected(account)); + + presence = purple_account_get_presence(account); + status = purple_presence_get_status(presence, status_id); + + g_return_if_fail(status != NULL); + + va_start(args, status_id); + purple_status_set_active_with_attrs(status, TRUE, args); + va_end(args); +} + +void +purple_protocol_got_account_actions(PurpleAccount *account) +{ + + g_return_if_fail(account != NULL); + g_return_if_fail(purple_account_is_connected(account)); + + purple_signal_emit(purple_accounts_get_handle(), "account-actions-changed", + account); +} + +void +purple_protocol_got_user_idle(PurpleAccount *account, const char *name, + gboolean idle, time_t idle_time) +{ + PurplePresence *presence; + GSList *list; + + g_return_if_fail(account != NULL); + g_return_if_fail(name != NULL); + g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account)); + + if ((list = purple_blist_find_buddies(account, name)) == NULL) + return; + + while (list) { + presence = purple_buddy_get_presence(list->data); + list = g_slist_delete_link(list, list); + purple_presence_set_idle(presence, idle, idle_time); + } +} + +void +purple_protocol_got_user_login_time(PurpleAccount *account, const char *name, + time_t login_time) +{ + GSList *list; + PurplePresence *presence; + + g_return_if_fail(account != NULL); + g_return_if_fail(name != NULL); + + if ((list = purple_blist_find_buddies(account, name)) == NULL) + return; + + if (login_time == 0) + login_time = time(NULL); + + while (list) { + PurpleBuddy *buddy = list->data; + presence = purple_buddy_get_presence(buddy); + list = g_slist_delete_link(list, list); + + if (purple_presence_get_login_time(presence) != login_time) + { + purple_presence_set_login_time(presence, login_time); + + purple_signal_emit(purple_blist_get_handle(), "buddy-got-login-time", buddy); + } + } +} + +void +purple_protocol_got_user_status(PurpleAccount *account, const char *name, + const char *status_id, ...) +{ + GSList *list, *l; + PurpleBuddy *buddy; + PurplePresence *presence; + PurpleStatus *status; + PurpleStatus *old_status; + va_list args; + + g_return_if_fail(account != NULL); + g_return_if_fail(name != NULL); + g_return_if_fail(status_id != NULL); + g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account)); + + if((list = purple_blist_find_buddies(account, name)) == NULL) + return; + + for(l = list; l != NULL; l = l->next) { + buddy = l->data; + + presence = purple_buddy_get_presence(buddy); + status = purple_presence_get_status(presence, status_id); + + if(NULL == status) + /* + * TODO: This should never happen, right? We should call + * g_warning() or something. + */ + continue; + + old_status = purple_presence_get_active_status(presence); + + va_start(args, status_id); + purple_status_set_active_with_attrs(status, TRUE, args); + va_end(args); + + purple_buddy_update_status(buddy, old_status); + } + + g_slist_free(list); + + /* The buddy is no longer online, they are therefore by definition not + * still typing to us. */ + if (!purple_status_is_online(status)) { + serv_got_typing_stopped(purple_account_get_connection(account), name); + purple_protocol_got_media_caps(account, name); + } +} + +void purple_protocol_got_user_status_deactive(PurpleAccount *account, const char *name, + const char *status_id) +{ + GSList *list, *l; + PurpleBuddy *buddy; + PurplePresence *presence; + PurpleStatus *status; + + g_return_if_fail(account != NULL); + g_return_if_fail(name != NULL); + g_return_if_fail(status_id != NULL); + g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account)); + + if((list = purple_blist_find_buddies(account, name)) == NULL) + return; + + for(l = list; l != NULL; l = l->next) { + buddy = l->data; + + presence = purple_buddy_get_presence(buddy); + status = purple_presence_get_status(presence, status_id); + + if(NULL == status) + continue; + + if (purple_status_is_active(status)) { + purple_status_set_active(status, FALSE); + purple_buddy_update_status(buddy, status); + } + } + + g_slist_free(list); +} + +static void +do_protocol_change_account_status(PurpleAccount *account, + PurpleStatus *old_status, PurpleStatus *new_status) +{ + PurpleProtocol *protocol; + + if (purple_status_is_online(new_status) && + purple_account_is_disconnected(account) && + purple_network_is_available()) + { + purple_account_connect(account); + return; + } + + if (!purple_status_is_online(new_status)) + { + if (!purple_account_is_disconnected(account)) + purple_account_disconnect(account); + /* Clear out the unsaved password if we switch to offline status */ + if (!purple_account_get_remember_password(account)) + purple_account_set_password(account, NULL, NULL, NULL); + + return; + } + + if (purple_account_is_connecting(account)) + /* + * We don't need to call the set_status PRPL function because + * the PRPL will take care of setting its status during the + * connection process. + */ + return; + + protocol = purple_find_protocol_info(purple_account_get_protocol_id(account)); + + if (protocol == NULL) + return; + + if (!purple_account_is_disconnected(account) && protocol->set_status != NULL) + { + protocol->set_status(account, new_status); + } +} + +void +purple_protocol_change_account_status(PurpleAccount *account, + PurpleStatus *old_status, PurpleStatus *new_status) +{ + g_return_if_fail(account != NULL); + g_return_if_fail(new_status != NULL); + g_return_if_fail(!purple_status_is_exclusive(new_status) || old_status != NULL); + + do_protocol_change_account_status(account, old_status, new_status); + + purple_signal_emit(purple_accounts_get_handle(), "account-status-changed", + account, old_status, new_status); +} + +GList * +purple_protocol_get_statuses(PurpleAccount *account, PurplePresence *presence) +{ + GList *statuses = NULL; + GList *l; + PurpleStatus *status; + + g_return_val_if_fail(account != NULL, NULL); + g_return_val_if_fail(presence != NULL, NULL); + + for (l = purple_account_get_status_types(account); l != NULL; l = l->next) + { + status = purple_status_new((PurpleStatusType *)l->data, presence); + statuses = g_list_prepend(statuses, status); + } + + statuses = g_list_reverse(statuses); + + return statuses; +} + +static void +purple_protocol_attention(PurpleConversation *conv, const char *who, + guint type, PurpleMessageFlags flags, time_t mtime) +{ + PurpleAccount *account = purple_conversation_get_account(conv); + purple_signal_emit(purple_conversations_get_handle(), + flags == PURPLE_MESSAGE_SEND ? "sent-attention" : "got-attention", + account, who, conv, type); +} + +void +purple_protocol_send_attention(PurpleConnection *gc, const char *who, guint type_code) +{ + PurpleAttentionType *attn; + PurpleMessageFlags flags; + PurpleProtocol *protocol; + PurpleIMConversation *im; + gboolean (*send_attention)(PurpleConnection *, const char *, guint); + PurpleBuddy *buddy; + const char *alias; + gchar *description; + time_t mtime; + + g_return_if_fail(gc != NULL); + g_return_if_fail(who != NULL); + + protocol = purple_find_protocol_info(purple_account_get_protocol_id(purple_connection_get_account(gc))); + send_attention = protocol->send_attention; + g_return_if_fail(send_attention != NULL); + + mtime = time(NULL); + + attn = purple_get_attention_type_from_code(purple_connection_get_account(gc), type_code); + + if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), who)) != NULL) + alias = purple_buddy_get_contact_alias(buddy); + else + alias = who; + + if (attn && purple_attention_type_get_outgoing_desc(attn)) { + description = g_strdup_printf(purple_attention_type_get_outgoing_desc(attn), alias); + } else { + description = g_strdup_printf(_("Requesting %s's attention..."), alias); + } + + flags = PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_NOTIFY | PURPLE_MESSAGE_SYSTEM; + + purple_debug_info("server", "serv_send_attention: sending '%s' to %s\n", + description, who); + + if (!send_attention(gc, who, type_code)) + return; + + im = purple_im_conversation_new(purple_connection_get_account(gc), who); + purple_conversation_write_message(PURPLE_CONVERSATION(im), NULL, description, flags, mtime); + purple_protocol_attention(PURPLE_CONVERSATION(im), who, type_code, PURPLE_MESSAGE_SEND, time(NULL)); + + g_free(description); +} + +static void +got_attention(PurpleConnection *gc, int id, const char *who, guint type_code) +{ + PurpleMessageFlags flags; + PurpleAttentionType *attn; + PurpleBuddy *buddy; + const char *alias; + gchar *description; + time_t mtime; + + mtime = time(NULL); + + 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; + + /* TODO: if (attn->icon_name) is non-null, use it to lookup an emoticon and display + * it next to the attention command. And if it is null, display a generic icon. */ + + if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), who)) != NULL) + alias = purple_buddy_get_contact_alias(buddy); + else + alias = who; + + if (attn && purple_attention_type_get_incoming_desc(attn)) { + description = g_strdup_printf(purple_attention_type_get_incoming_desc(attn), alias); + } else { + description = g_strdup_printf(_("%s has requested your attention!"), alias); + } + + purple_debug_info("server", "got_attention: got '%s' from %s\n", + description, who); + + if (id == -1) + serv_got_im(gc, who, description, flags, mtime); + else + serv_got_chat_in(gc, id, who, flags, description, mtime); + + /* TODO: sounds (depending on PurpleAttentionType), shaking, etc. */ + + g_free(description); +} + +void +purple_protocol_got_attention(PurpleConnection *gc, const char *who, guint type_code) +{ + PurpleConversation *conv = NULL; + PurpleAccount *account = purple_connection_get_account(gc); + + got_attention(gc, -1, who, type_code); + conv = + purple_conversations_find_with_account(who, account); + if (conv) + purple_protocol_attention(conv, who, type_code, PURPLE_MESSAGE_RECV, + time(NULL)); +} + +void +purple_protocol_got_attention_in_chat(PurpleConnection *gc, int id, const char *who, guint type_code) +{ + got_attention(gc, id, who, type_code); +} + +gboolean +purple_protocol_initiate_media(PurpleAccount *account, + const char *who, + PurpleMediaSessionType type) +{ +#ifdef USE_VV + PurpleConnection *gc = NULL; + PurpleProtocol *protocol = NULL; + + if (account) + gc = purple_account_get_connection(account); + if (gc) + protocol = purple_connection_get_protocol_info(gc); + + if (protocol && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, initiate_media)) { + /* should check that the protocol supports this media type here? */ + return protocol->initiate_media(account, who, type); + } else +#endif + return FALSE; +} + +PurpleMediaCaps +purple_protocol_get_media_caps(PurpleAccount *account, const char *who) +{ +#ifdef USE_VV + PurpleConnection *gc = NULL; + PurpleProtocol *protocol = NULL; + + if (account) + gc = purple_account_get_connection(account); + if (gc) + protocol = purple_connection_get_protocol_info(gc); + + if (protocol && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, + get_media_caps)) { + return protocol->get_media_caps(account, who); + } +#endif + return PURPLE_MEDIA_CAPS_NONE; +} + +void +purple_protocol_got_media_caps(PurpleAccount *account, const char *name) +{ +#ifdef USE_VV + GSList *list; + + g_return_if_fail(account != NULL); + g_return_if_fail(name != NULL); + + if ((list = purple_blist_find_buddies(account, name)) == NULL) + return; + + while (list) { + PurpleBuddy *buddy = list->data; + PurpleMediaCaps oldcaps = purple_buddy_get_media_caps(buddy); + PurpleMediaCaps newcaps = 0; + const gchar *bname = purple_buddy_get_name(buddy); + list = g_slist_delete_link(list, list); + + + newcaps = purple_protocol_get_media_caps(account, bname); + purple_buddy_set_media_caps(buddy, newcaps); + + if (oldcaps == newcaps) + continue; + + purple_signal_emit(purple_blist_get_handle(), + "buddy-caps-changed", buddy, + newcaps, oldcaps); + } +#endif +} + +PurpleProtocolAction * +purple_protocol_action_new(const char* label, + PurpleProtocolActionCallback callback) +{ + PurpleProtocolAction *action; + + g_return_val_if_fail(label != NULL && callback != NULL, NULL); + + action = g_new0(PurpleProtocolAction, 1); + + action->label = g_strdup(label); + action->callback = callback; + + return action; +} + +void +purple_protocol_action_free(PurpleProtocolAction *action) +{ + g_return_if_fail(action != NULL); + + g_free(action->label); + g_free(action); +} + +/************************************************************************** + * Protocols API + **************************************************************************/ +static void +purple_protocol_destroy(PurpleProtocol *protocol) +{ + GList *accounts, *l; + + accounts = purple_accounts_get_all_active(); + for (l = accounts; l != NULL; l = l->next) { + PurpleAccount *account = PURPLE_ACCOUNT(l->data); + if (purple_account_is_disconnected(account)) + continue; + + if (purple_strequal(protocol->id, purple_account_get_protocol_id(account))) + purple_account_disconnect(account); + } + + g_list_free(accounts); + + while (protocol->user_splits) { + PurpleAccountUserSplit *split = protocol->user_splits->data; + purple_account_user_split_destroy(split); + protocol->user_splits = g_list_delete_link(protocol->user_splits, + protocol->user_splits); + } + + while (protocol->protocol_options) { + PurpleAccountOption *option = protocol->protocol_options->data; + purple_account_option_destroy(option); + protocol->protocol_options = + g_list_delete_link(protocol->protocol_options, + protocol->protocol_options); + } + + purple_request_close_with_handle(protocol); + purple_notify_close_with_handle(protocol); + + purple_signals_disconnect_by_handle(protocol); + purple_signals_unregister_by_instance(protocol); + + purple_prefs_disconnect_by_handle(protocol); +} + +PurpleProtocol * +purple_find_protocol_info(const char *id) +{ + return g_hash_table_lookup(protocols, id); +} + +gboolean +purple_protocols_add(PurpleProtocol *protocol) +{ + if (purple_find_protocol_info(protocol->id)) + return FALSE; + + g_hash_table_insert(protocols, g_strdup(protocol->id), protocol); + return TRUE; +} + +gboolean purple_protocols_remove(PurpleProtocol *protocol) +{ + if (purple_find_protocol_info(protocol->id) == NULL) + return FALSE; + + g_hash_table_remove(protocols, protocol->id); + purple_protocol_destroy(protocol); + + return TRUE; +} + +GList * +purple_protocols_get_all(void) +{ + GList *ret = NULL; + PurpleProtocol *protocol; + GHashTableIter iter; + + g_hash_table_iter_init(&iter, protocols); + while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&protocol)) + ret = g_list_append(ret, protocol); + + return ret; +} + +/************************************************************************** + * Protocols Subsystem API + **************************************************************************/ +void +purple_protocols_init(void) +{ + protocols = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, + (GDestroyNotify)purple_protocol_destroy); +} + +void * +purple_protocols_get_handle(void) +{ + static int handle; + + return &handle; +} + +void +purple_protocols_uninit(void) +{ + g_hash_table_destroy(protocols); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocol.h Sun Aug 18 01:53:00 2013 +0530 @@ -0,0 +1,1055 @@ +/** + * @file protocol.h Protocol Plugin functions + * @ingroup core + */ + +/* 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 + */ + +/* this file should be all that prpls need to include. therefore, by including + * this file, they should get glib, proxy, purple_connection, prpl, etc. */ + +#ifndef _PURPLE_PROTOCOL_H_ +#define _PURPLE_PROTOCOL_H_ + +typedef struct _PurpleProtocol PurpleProtocol; + +typedef struct _PurpleProtocolAction PurpleProtocolAction; + +typedef void (*PurpleProtocolActionCallback)(PurpleProtocolAction *); + +/** Represents "nudges" and "buzzes" that you may send to a buddy to attract + * their attention (or vice-versa). + */ +typedef struct _PurpleAttentionType PurpleAttentionType; + +/**************************************************************************/ +/** @name Basic Protocol Information */ +/**************************************************************************/ + +typedef enum { + PURPLE_ICON_SCALE_DISPLAY = 0x01, /**< We scale the icon when we display it */ + PURPLE_ICON_SCALE_SEND = 0x02 /**< We scale the icon before we send it to the server */ +} PurpleIconScaleRules; + + +/** + * A description of a Buddy Icon specification. This tells Purple what kind of image file + * it should give this prpl, and what kind of image file it should expect back. + * Dimensions less than 1 should be ignored and the image not scaled. + */ +typedef struct _PurpleBuddyIconSpec PurpleBuddyIconSpec; + +/** + * A description of a file transfer thumbnail specification. + * This tells the UI if and what image formats the prpl support for file + * transfer thumbnails. + */ +typedef struct _PurpleThumbnailSpec PurpleThumbnailSpec; + +/** + * This \#define exists just to make it easier to fill out the buddy icon + * field in the prpl info struct for protocols that couldn't care less. + */ +#define NO_BUDDY_ICONS {NULL, 0, 0, 0, 0, 0, 0} + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "buddylist.h" +#include "conversations.h" +#include "ft.h" +#include "imgstore.h" +#include "media.h" +#include "notify.h" +#include "proxy.h" +#include "roomlist.h" +#include "status.h" +#include "whiteboard.h" + + +/** @copydoc PurpleBuddyIconSpec */ +struct _PurpleBuddyIconSpec { + /** This is a comma-delimited list of image formats or @c NULL if icons + * are not supported. Neither the core nor the prpl will actually + * check to see if the data it's given matches this; it's entirely up + * to the UI to do what it wants + */ + char *format; + + int min_width; /**< Minimum width of this icon */ + int min_height; /**< Minimum height of this icon */ + int max_width; /**< Maximum width of this icon */ + int max_height; /**< Maximum height of this icon */ + size_t max_filesize; /**< Maximum size in bytes */ + PurpleIconScaleRules scale_rules; /**< How to stretch this icon */ +}; + +/** Represents an entry containing information that must be supplied by the + * user when joining a chat. + */ +struct proto_chat_entry { + const char *label; /**< User-friendly name of the entry */ + const char *identifier; /**< Used by the PRPL to identify the option */ + gboolean required; /**< True if it's required */ + gboolean is_int; /**< True if the entry expects an integer */ + int min; /**< Minimum value in case of integer */ + int max; /**< Maximum value in case of integer */ + gboolean secret; /**< True if the entry is secret (password) */ +}; + +/** + * Protocol options + * + * These should all be stuff that some plugins can do and others can't. + */ +typedef enum +{ + /** + * User names are unique to a chat and are not shared between rooms. + * + * XMPP lets you choose what name you want in chats, so it shouldn't + * be pulling the aliases from the buddy list for the chat list; + * it gets annoying. + */ + OPT_PROTO_UNIQUE_CHATNAME = 0x00000004, + + /** + * Chat rooms have topics. + * + * IRC and XMPP support this. + */ + OPT_PROTO_CHAT_TOPIC = 0x00000008, + + /** + * Don't require passwords for sign-in. + * + * Zephyr doesn't require passwords, so there's no + * need for a password prompt. + */ + OPT_PROTO_NO_PASSWORD = 0x00000010, + + /** + * Notify on new mail. + * + * MSN and Yahoo notify you when you have new mail. + */ + OPT_PROTO_MAIL_CHECK = 0x00000020, + + /** + * Images in IMs. + * + * Oscar lets you send images in direct IMs. + */ + OPT_PROTO_IM_IMAGE = 0x00000040, + + /** + * Allow passwords to be optional. + * + * Passwords in IRC are optional, and are needed for certain + * functionality. + */ + OPT_PROTO_PASSWORD_OPTIONAL = 0x00000080, + + /** + * Allows font size to be specified in sane point size + * + * Probably just XMPP and Y!M + */ + OPT_PROTO_USE_POINTSIZE = 0x00000100, + + /** + * Set the Register button active even when the username has not + * been specified. + * + * Gadu-Gadu doesn't need a username to register new account (because + * usernames are assigned by the server). + */ + OPT_PROTO_REGISTER_NOSCREENNAME = 0x00000200, + + /** + * Indicates that slash commands are native to this protocol. + * Used as a hint that unknown commands should not be sent as messages. + */ + OPT_PROTO_SLASH_COMMANDS_NATIVE = 0x00000400, + + /** + * Indicates that this protocol supports sending a user-supplied message + * along with an invitation. + */ + OPT_PROTO_INVITE_MESSAGE = 0x00000800, + + /** + * Indicates that this protocol supports sending a user-supplied message + * along with an authorization acceptance. + */ + OPT_PROTO_AUTHORIZATION_GRANTED_MESSAGE = 0x00001000, + + /** + * Indicates that this protocol supports sending a user-supplied message + * along with an authorization denial. + */ + OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE = 0x00002000 + +} PurpleProtocolOptions; + +/** + * Represents an action that the protocol can perform. This shows up in the + * Accounts menu, under a submenu with the name of the account. + */ +struct _PurpleProtocolAction { + char *label; + PurpleProtocolActionCallback callback; + PurpleConnection *connection; + gpointer user_data; +}; + +/** + * A protocol plugin information structure. + * + * Every protocol plugin initializes this structure. It is the gateway + * between purple and the protocol plugin. Many of these callbacks can be + * NULL. If a callback must be implemented, it has a comment indicating so. + */ +struct _PurpleProtocol +{ + const char *id; + const char *name; + + /** + * The size of the PurpleProtocol. This should always be sizeof(PurpleProtocol). + * 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 */ + GList *protocol_options; /**< A GList of PurpleAccountOption */ + + PurpleBuddyIconSpec icon_spec; /**< The icon spec. */ + + /** + * Callback that returns the actions the protocol can perform + */ + GList *(*get_actions)(PurpleConnection *); + + /** + * Returns the base icon name for the given buddy and account. + * If buddy is NULL and the account is non-NULL, it will return the + * name to use for the account's icon. If both are NULL, it will + * return the name to use for the protocol's icon. + * + * This must be implemented. + */ + const char *(*list_icon)(PurpleAccount *account, PurpleBuddy *buddy); + + /** + * Fills the four char**'s with string identifiers for "emblems" + * that the UI will interpret and display as relevant + */ + const char *(*list_emblem)(PurpleBuddy *buddy); + + /** + * Gets a short string representing this buddy's status. This will + * be shown on the buddy list. + */ + char *(*status_text)(PurpleBuddy *buddy); + + /** + * Allows the prpl to add text to a buddy's tooltip. + */ + void (*tooltip_text)(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboolean full); + + /** + * Returns a list of #PurpleStatusType which exist for this account; + * this must be implemented, and must add at least the offline and + * online states. + */ + GList *(*status_types)(PurpleAccount *account); + + /** + * Returns a list of #PurpleMenuAction structs, which represent extra + * actions to be shown in (for example) the right-click menu for @a + * node. + */ + GList *(*blist_node_menu)(PurpleBlistNode *node); + + /** + * Returns a list of #proto_chat_entry structs, which represent + * information required by the PRPL to join a chat. libpurple will + * call join_chat along with the information filled by the user. + * + * @return A list of #proto_chat_entry structs + */ + GList *(*chat_info)(PurpleConnection *); + + /** + * Returns a hashtable which maps #proto_chat_entry struct identifiers + * to default options as strings based on chat_name. The resulting + * hashtable should be created with g_hash_table_new_full(g_str_hash, + * g_str_equal, NULL, g_free);. Use #get_chat_name if you instead need + * to extract a chat name from a hashtable. + * + * @param chat_name The chat name to be turned into components + * @return Hashtable containing the information extracted from chat_name + */ + GHashTable *(*chat_info_defaults)(PurpleConnection *, const char *chat_name); + + /* All the server-related functions */ + + /** This must be implemented. */ + void (*login)(PurpleAccount *); + + /** This must be implemented. */ + void (*close)(PurpleConnection *); + + /** + * This PRPL function should return a positive value on success. + * If the message is too big to be sent, return -E2BIG. If + * the account is not connected, return -ENOTCONN. If the + * PRPL is unable to send the message for another reason, return + * some other negative value. You can use one of the valid + * errno values, or just big something. If the message should + * not be echoed to the conversation window, return 0. + */ + int (*send_im)(PurpleConnection *, const char *who, + const char *message, + PurpleMessageFlags flags); + + void (*set_info)(PurpleConnection *, const char *info); + + /** + * @return If this protocol requires the PURPLE_IM_TYPING message to + * be sent repeatedly to signify that the user is still + * typing, then the PRPL should return the number of + * seconds to wait before sending a subsequent notification. + * Otherwise the PRPL should return 0. + */ + unsigned int (*send_typing)(PurpleConnection *, const char *name, PurpleIMTypingState state); + + /** + * Should arrange for purple_notify_userinfo() to be called with + * @a who's user info. + */ + void (*get_info)(PurpleConnection *, const char *who); + void (*set_status)(PurpleAccount *account, PurpleStatus *status); + + 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. + * + * 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. + */ + 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); + void (*add_deny)(PurpleConnection *, const char *name); + void (*rem_permit)(PurpleConnection *, const char *name); + void (*rem_deny)(PurpleConnection *, const char *name); + void (*set_permit_deny)(PurpleConnection *); + + /** + * Called when the user requests joining a chat. Should arrange for + * #serv_got_joined_chat to be called. + * + * @param components A hashtable containing information required to + * join the chat as described by the entries returned + * by #chat_info. It may also be called when accepting + * an invitation, in which case this matches the + * data parameter passed to #serv_got_chat_invite. + */ + void (*join_chat)(PurpleConnection *, GHashTable *components); + + /** + * Called when the user refuses a chat invitation. + * + * @param components A hashtable containing information required to + * join the chat as passed to #serv_got_chat_invite. + */ + void (*reject_chat)(PurpleConnection *, GHashTable *components); + + /** + * Returns a chat name based on the information in components. Use + * #chat_info_defaults if you instead need to generate a hashtable + * from a chat name. + * + * @param components A hashtable containing information about the chat. + */ + char *(*get_chat_name)(GHashTable *components); + + /** + * Invite a user to join a chat. + * + * @param id The id of the chat to invite the user to. + * @param message A message displayed to the user when the invitation + * is received. + * @param who The name of the user to send the invation to. + */ + void (*chat_invite)(PurpleConnection *, int id, + const char *message, const char *who); + /** + * Called when the user requests leaving a chat. + * + * @param id The id of the chat to leave + */ + void (*chat_leave)(PurpleConnection *, int id); + + /** + * Send a whisper to a user in a chat. + * + * @param id The id of the chat. + * @param who The name of the user to send the whisper to. + * @param message The message of the whisper. + */ + void (*chat_whisper)(PurpleConnection *, int id, + const char *who, const char *message); + + /** + * Send a message to a chat. + * This PRPL function should return a positive value on success. + * If the message is too big to be sent, return -E2BIG. If + * the account is not connected, return -ENOTCONN. If the + * PRPL is unable to send the message for another reason, return + * some other negative value. You can use one of the valid + * errno values, or just big something. + * + * @param id The id of the chat to send the message to. + * @param message The message to send to the chat. + * @param flags A bitwise OR of #PurpleMessageFlags representing + * message flags. + * @return A positive number or 0 in case of success, + * a negative error number in case of failure. + */ + int (*chat_send)(PurpleConnection *, int id, const char *message, PurpleMessageFlags flags); + + /** If implemented, this will be called regularly for this prpl's + * active connections. You'd want to do this if you need to repeatedly + * send some kind of keepalive packet to the server to avoid being + * disconnected. ("Regularly" is defined by + * <code>KEEPALIVE_INTERVAL</code> in <tt>libpurple/connection.c</tt>.) + */ + void (*keepalive)(PurpleConnection *); + + /** new user registration */ + void (*register_user)(PurpleAccount *); + + /** + * @deprecated Use #PurpleProtocol.get_info instead. + */ + void (*get_cb_info)(PurpleConnection *, int, const char *who); + + /** save/store buddy's alias on server list/roster */ + void (*alias_buddy)(PurpleConnection *, const char *who, + const char *alias); + + /** change a buddy's group on a server list/roster */ + void (*group_buddy)(PurpleConnection *, const char *who, + const char *old_group, const char *new_group); + + /** rename a group on a server list/roster */ + void (*rename_group)(PurpleConnection *, const char *old_name, + PurpleGroup *group, GList *moved_buddies); + + void (*buddy_free)(PurpleBuddy *); + + void (*convo_closed)(PurpleConnection *, const char *who); + + /** + * Convert the username @a who to its canonical form. Also checks for + * validity. + * + * For example, AIM treats "fOo BaR" and "foobar" as the same user; this + * function should return the same normalized string for both of those. + * On the other hand, both of these are invalid for protocols with + * number-based usernames, so function should return NULL in such case. + * + * @param account The account the username is related to. Can + * be NULL. + * @param who The username to convert. + * @return Normalized username, or NULL, if it's invalid. + */ + const char *(*normalize)(const PurpleAccount *account, const char *who); + + /** + * Set the buddy icon for the given connection to @a img. The prpl + * does NOT own a reference to @a img; if it needs one, it must + * #purple_imgstore_ref(@a img) itself. + */ + void (*set_buddy_icon)(PurpleConnection *, PurpleStoredImage *img); + + void (*remove_group)(PurpleConnection *gc, PurpleGroup *group); + + /** Gets the real name of a participant in a chat. For example, on + * XMPP this turns a chat room nick <tt>foo</tt> into + * <tt>room\@server/foo</tt> + * @param gc the connection on which the room is. + * @param id the ID of the chat room. + * @param who the nickname of the chat participant. + * @return the real name of the participant. This string must be + * freed by the caller. + */ + char *(*get_cb_real_name)(PurpleConnection *gc, int id, const char *who); + + void (*set_chat_topic)(PurpleConnection *gc, int id, const char *topic); + + PurpleChat *(*find_blist_chat)(PurpleAccount *account, const char *name); + + /* room listing prpl callbacks */ + PurpleRoomlist *(*roomlist_get_list)(PurpleConnection *gc); + void (*roomlist_cancel)(PurpleRoomlist *list); + void (*roomlist_expand_category)(PurpleRoomlist *list, PurpleRoomlistRoom *category); + + /* file transfer callbacks */ + gboolean (*can_receive_file)(PurpleConnection *, const char *who); + void (*send_file)(PurpleConnection *, const char *who, const char *filename); + PurpleXfer *(*new_xfer)(PurpleConnection *, const char *who); + + /** Checks whether offline messages to @a buddy are supported. + * @return @c TRUE if @a buddy can be sent messages while they are + * offline, or @c FALSE if not. + */ + gboolean (*offline_message)(const PurpleBuddy *buddy); + + PurpleWhiteboardPrplOps *whiteboard_protocol_ops; + + /** For use in plugins that may understand the underlying protocol */ + int (*send_raw)(PurpleConnection *gc, const char *buf, int len); + + /* room list serialize */ + char *(*roomlist_room_serialize)(PurpleRoomlistRoom *room); + + /** Remove the user from the server. The account can either be + * connected or disconnected. After the removal is finished, the + * connection will stay open and has to be closed! + */ + /* This is here rather than next to register_user for API compatibility + * reasons. + */ + void (*unregister_user)(PurpleAccount *, PurpleAccountUnregistrationCb cb, void *user_data); + + /* Attention API for sending & receiving zaps/nudges/buzzes etc. */ + gboolean (*send_attention)(PurpleConnection *gc, const char *username, guint type); + GList *(*get_attention_types)(PurpleAccount *acct); + + /** 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 + * table is allocated every call and MUST be unrefed by the caller. + * + * @param account The account to specify. This can be NULL. + * @return The protocol's string hash table. The hash table should be + * destroyed by the caller when it's no longer needed. + */ + GHashTable *(*get_account_text_table)(PurpleAccount *account); + + /** + * Initiate a media session with the given contact. + * + * @param account The account to initiate the media session on. + * @param who The remote user to initiate the session with. + * @param type The type of media session to initiate. + * @return TRUE if the call succeeded else FALSE. (Doesn't imply the media session or stream will be successfully created) + */ + gboolean (*initiate_media)(PurpleAccount *account, const char *who, + PurpleMediaSessionType type); + + /** + * Checks to see if the given contact supports the given type of media session. + * + * @param account The account the contact is on. + * @param who The remote user to check for media capability with. + * @return The media caps the contact supports. + */ + PurpleMediaCaps (*get_media_caps)(PurpleAccount *account, + const char *who); + + /** + * Returns an array of "PurpleMood"s, with the last one having + * "mood" set to @c NULL. + */ + PurpleMood *(*get_moods)(PurpleAccount *account); + + /** + * Set the user's "friendly name" (or alias or nickname or + * whatever term you want to call it) on the server. The + * protocol plugin should call success_cb or failure_cb + * *asynchronously* (if it knows immediately that the set will fail, + * call one of the callbacks from an idle/0-second timeout) depending + * on if the nickname is set successfully. + * + * @param gc The connection for which to set an alias + * @param alias The new server-side alias/nickname for this account, + * or NULL to unset the alias/nickname (or return it to + * a protocol-specific "default"). + * @param success_cb Callback to be called if the public alias is set + * @param failure_cb Callback to be called if setting the public alias + * fails + * @see purple_account_set_public_alias + */ + void (*set_public_alias)(PurpleConnection *gc, const char *alias, + PurpleSetPublicAliasSuccessCallback success_cb, + PurpleSetPublicAliasFailureCallback failure_cb); + /** + * Retrieve the user's "friendly name" as set on the server. + * The protocol plugin should call success_cb or failure_cb + * *asynchronously* (even if it knows immediately that the get will fail, + * call one of the callbacks from an idle/0-second timeout) depending + * on if the nickname is retrieved. + * + * @param gc The connection for which to retireve the alias + * @param success_cb Callback to be called with the retrieved alias + * @param failure_cb Callback to be called if the prpl is unable to + * retrieve the alias + * @see purple_account_get_public_alias + */ + void (*get_public_alias)(PurpleConnection *gc, + PurpleGetPublicAliasSuccessCallback success_cb, + PurpleGetPublicAliasFailureCallback failure_cb); +}; + +#define PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl, member) \ + (G_STRUCT_OFFSET(PurpleProtocol, member) < prpl->struct_size && \ + prpl->member != NULL) + +G_BEGIN_DECLS + +/**************************************************************************/ +/** @name Attention Type API */ +/**************************************************************************/ +/*@{*/ + +/** + * Creates a new #PurpleAttentionType object and sets its mandatory parameters. + * + * @param ulname A non-localized string that can be used by UIs in need of such + * non-localized strings. This should be the same as @a name, + * without localization. + * @param name A localized string that the UI may display for the event. This + * 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. + */ +PurpleAttentionType *purple_attention_type_new(const char *ulname, const char *name, + const char *inc_desc, const char *out_desc); + +/** + * Sets the displayed name of the attention-demanding event. + * + * @param type The attention type. + * @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. + */ +void purple_attention_type_set_name(PurpleAttentionType *type, const char *name); + +/** + * Sets the description of the attention-demanding event shown in conversations + * when the event is received. + * + * @param type The attention type. + * @param desc The localized description for incoming events. + */ +void purple_attention_type_set_incoming_desc(PurpleAttentionType *type, const char *desc); + +/** + * Sets the description of the attention-demanding event shown in conversations + * when the event is sent. + * + * @param type The attention type. + * @param desc The localized description for outgoing events. + */ +void purple_attention_type_set_outgoing_desc(PurpleAttentionType *type, const char *desc); + +/** + * Sets the name of the icon to display for the attention event; this is optional. + * + * @param type The attention type. + * @param name The icon's name. + * @note Icons are optional for attention events. + */ +void purple_attention_type_set_icon_name(PurpleAttentionType *type, const char *name); + +/** + * Sets the unlocalized name of the attention event; some UIs may need this, + * thus it is required. + * + * @param type The attention type. + * @param ulname The unlocalized name. This should be the same string given as + * the localized name, but without localization. + */ +void purple_attention_type_set_unlocalized_name(PurpleAttentionType *type, const char *ulname); + +/** + * Get the attention type's name as displayed by the UI. + * + * @param type The attention type. + * + * @return The name. + */ +const char *purple_attention_type_get_name(const PurpleAttentionType *type); + +/** + * Get the attention type's description shown when the event is received. + * + * @param type The attention type. + * @return The description. + */ +const char *purple_attention_type_get_incoming_desc(const PurpleAttentionType *type); + +/** + * Get the attention type's description shown when the event is sent. + * + * @param type The attention type. + * @return The description. + */ +const char *purple_attention_type_get_outgoing_desc(const PurpleAttentionType *type); + +/** + * Get the attention type's icon name. + * + * @param type The attention type. + * @return The icon name or @c NULL if unset/empty. + * @note Icons are optional for attention events. + */ +const char *purple_attention_type_get_icon_name(const PurpleAttentionType *type); + +/** + * Get the attention type's unlocalized name; this is useful for some UIs. + * + * @param type The attention type + * @return The unlocalized name. + */ +const char *purple_attention_type_get_unlocalized_name(const PurpleAttentionType *type); + +/*@}*/ + +/**************************************************************************/ +/** @name Protocol Plugin API */ +/**************************************************************************/ +/*@{*/ + +/** + * Notifies Purple that our account's idle state and time have changed. + * + * This is meant to be called from protocol plugins. + * + * @param account The account. + * @param idle The user's idle state. + * @param idle_time The user's idle time. + */ +void purple_protocol_got_account_idle(PurpleAccount *account, gboolean idle, + time_t idle_time); + +/** + * Notifies Purple of our account's log-in time. + * + * This is meant to be called from protocol plugins. + * + * @param account The account the user is on. + * @param login_time The user's log-in time. + */ +void purple_protocol_got_account_login_time(PurpleAccount *account, time_t login_time); + +/** + * Notifies Purple that our account's status has changed. + * + * This is meant to be called from protocol plugins. + * + * @param account The account the user is on. + * @param status_id The status ID. + * @param ... A NULL-terminated list of attribute IDs and values, + * beginning with the value for @a attr_id. + */ +void purple_protocol_got_account_status(PurpleAccount *account, + const char *status_id, ...) G_GNUC_NULL_TERMINATED; + +/** + * Notifies Purple that our account's actions have changed. This is only + * called after the initial connection. Emits the account-actions-changed + * signal. + * + * This is meant to be called from protocol plugins. + * + * @param account The account. + * + * @see account-actions-changed + */ +void purple_protocol_got_account_actions(PurpleAccount *account); + +/** + * Notifies Purple that a buddy's idle state and time have changed. + * + * This is meant to be called from protocol plugins. + * + * @param account The account the user is on. + * @param name The name of the buddy. + * @param idle The user's idle state. + * @param idle_time The user's idle time. This is the time at + * which the user became idle, in seconds since + * the epoch. If the PRPL does not know this value + * then it should pass 0. + */ +void purple_protocol_got_user_idle(PurpleAccount *account, const char *name, + gboolean idle, time_t idle_time); + +/** + * Notifies Purple of a buddy's log-in time. + * + * This is meant to be called from protocol plugins. + * + * @param account The account the user is on. + * @param name The name of the buddy. + * @param login_time The user's log-in time. + */ +void purple_protocol_got_user_login_time(PurpleAccount *account, const char *name, + time_t login_time); + +/** + * Notifies Purple that a buddy's status has been activated. + * + * This is meant to be called from protocol plugins. + * + * @param account The account the user is on. + * @param name The name of the buddy. + * @param status_id The status ID. + * @param ... A NULL-terminated list of attribute IDs and values, + * beginning with the value for @a attr_id. + */ +void purple_protocol_got_user_status(PurpleAccount *account, const char *name, + const char *status_id, ...) G_GNUC_NULL_TERMINATED; + +/** + * Notifies libpurple that a buddy's status has been deactivated + * + * This is meant to be called from protocol plugins. + * + * @param account The account the user is on. + * @param name The name of the buddy. + * @param status_id The status ID. + */ +void purple_protocol_got_user_status_deactive(PurpleAccount *account, const char *name, + const char *status_id); + +/** + * Informs the server that our account's status changed. + * + * @param account The account the user is on. + * @param old_status The previous status. + * @param new_status The status that was activated, or deactivated + * (in the case of independent statuses). + */ +void purple_protocol_change_account_status(PurpleAccount *account, + PurpleStatus *old_status, + PurpleStatus *new_status); + +/** + * Retrieves the list of stock status types from a prpl. + * + * @param account The account the user is on. + * @param presence The presence for which we're going to get statuses + * + * @return List of statuses + */ +GList *purple_protocol_get_statuses(PurpleAccount *account, PurplePresence *presence); + +/** + * Send an attention request message. + * + * @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 purple_protocol_send_attention(PurpleConnection *gc, const char *who, guint type_code); + +/** + * Process an incoming attention message. + * + * @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 purple_protocol_got_attention(PurpleConnection *gc, const char *who, guint type_code); + +/** + * Process an incoming attention message in a chat. + * + * @param gc The connection that received the attention message. + * @param id The chat id. + * @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 purple_protocol_got_attention_in_chat(PurpleConnection *gc, int id, const char *who, guint type_code); + +/** + * Determines if the contact supports the given media session type. + * + * @param account The account the user is on. + * @param who The name of the contact to check capabilities for. + * + * @return The media caps the contact supports. + */ +PurpleMediaCaps purple_protocol_get_media_caps(PurpleAccount *account, + const char *who); + +/** + * Initiates a media session with the given contact. + * + * @param account The account the user is on. + * @param who The name of the contact to start a session with. + * @param type The type of media session to start. + * + * @return TRUE if the call succeeded else FALSE. (Doesn't imply the media session or stream will be successfully created) + */ +gboolean purple_protocol_initiate_media(PurpleAccount *account, + const char *who, + PurpleMediaSessionType type); + +/** + * Signals that the prpl received capabilities for the given contact. + * + * This function is intended to be used only by prpls. + * + * @param account The account the user is on. + * @param who The name of the contact for which capabilities have been received. + */ +void purple_protocol_got_media_caps(PurpleAccount *account, const char *who); + +/** TODO A sanity check is needed + * Allocates and returns a new PurpleProtocolAction. Use this to add actions in + * a list in the get_actions function of the protocol. + * + * @param label The description of the action to show to the user. + * @param callback The callback to call when the user selects this action. + */ +PurpleProtocolAction *purple_protocol_action_new(const char* label, + PurpleProtocolActionCallback callback); + +/** TODO A sanity check is needed + * Frees a PurpleProtocolAction + * + * @param action The PurpleProtocolAction to free. + */ +void purple_protocol_action_free(PurpleProtocolAction *action); + +/**************************************************************************/ +/** @name Protocols API */ +/**************************************************************************/ +/*@{*/ + +/** + * Finds a protocol plugin info structure by ID. + * + * @param id The protocol's ID. + */ +PurpleProtocol *purple_find_protocol_info(const char *id); + +/** TODO A sanity check is needed + * Adds a protocol to the list of protocols. + * + * @param protocol The protocol to add. + * + * @return TRUE if the protocol was added, else FALSE. + */ +gboolean purple_protocols_add(PurpleProtocol *protocol); + +/** TODO A sanity check is needed + * Removes a protocol from the list of protocols. This will disconnect all + * connected accounts using this protocol, and free the protocol's user splits + * and protocol options. + * + * @param protocol The protocol to remove. + * + * @return TRUE if the protocol was removed, else FALSE. + */ +gboolean purple_protocols_remove(PurpleProtocol *protocol); + +/** TODO A sanity check is needed + * Returns a list of all loaded protocols. + * + * @constreturn A list of all loaded protocols. + */ +GList *purple_protocols_get_all(void); + +/*@}*/ + +/**************************************************************************/ +/** @name Protocols Subsytem API */ +/**************************************************************************/ +/*@{*/ + +/** + * Initializes the protocols subsystem. + */ +void purple_protocols_init(void); + +/** TODO Make protocols use this handle, instead of plugins handle + * Returns the protocols subsystem handle. + * + * @return The protocols subsystem handle. + */ +void *purple_protocols_get_handle(void); + +/** + * Uninitializes the protocols subsystem. + */ +void purple_protocols_uninit(void); + +/*@}*/ + +G_END_DECLS + +#endif /* _PROTOCOL_H_ */
--- a/libpurple/protocols/bonjour/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/bonjour/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -48,6 +48,7 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(DEBUG_CFLAGS) \ $(LIBXML_CFLAGS) \ - $(AVAHI_CFLAGS) \ No newline at end of file + $(AVAHI_CFLAGS)
--- a/libpurple/protocols/bonjour/bonjour.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/bonjour/bonjour.c Sun Aug 18 01:53:00 2013 +0530 @@ -35,6 +35,7 @@ #include "account.h" #include "accountopt.h" #include "debug.h" +#include "plugins.h" #include "util.h" #include "version.h" @@ -468,26 +469,18 @@ return (buddy != NULL && purple_buddy_get_protocol_data(buddy) != NULL); } -static gboolean -plugin_unload(PurplePlugin *plugin) -{ - /* These shouldn't happen here because they are allocated in _init() */ - - g_free(default_firstname); - g_free(default_lastname); +static PurpleProtocol *my_protocol = NULL; - return TRUE; -} - -static PurplePlugin *my_protocol = NULL; - -static PurplePluginProtocolInfo prpl_info = +static PurpleProtocol protocol = { - sizeof(PurplePluginProtocolInfo), /* struct_size */ + "prpl-bonjour", /* id */ + "Bonjour", /* name */ + sizeof(PurpleProtocol), /* struct_size */ OPT_PROTO_NO_PASSWORD, NULL, /* user_splits */ NULL, /* protocol_options */ {"png,gif,jpeg", 0, 0, 96, 96, 65535, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ + NULL, /* get_actions */ bonjour_list_icon, /* list_icon */ NULL, /* list_emblem */ bonjour_status_text, /* status_text */ @@ -542,7 +535,7 @@ bonjour_send_file, /* send_file */ bonjour_new_xfer, /* new_xfer */ NULL, /* offline_message */ - NULL, /* whiteboard_prpl_ops */ + NULL, /* whiteboard_protocol_ops */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ NULL, /* unregister_user */ @@ -556,49 +549,12 @@ NULL /* get_public_alias */ }; -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-bonjour", /**< id */ - "Bonjour", /**< name */ - DISPLAY_VERSION, /**< version */ - /** summary */ - N_("Bonjour Protocol Plugin"), - /** description */ - N_("Bonjour Protocol Plugin"), - NULL, /**< author */ - PURPLE_WEBSITE, /**< homepage */ - - NULL, /**< load */ - plugin_unload, /**< unload */ - NULL, /**< destroy */ - - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, /**< prefs_info */ - NULL, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - #ifdef WIN32 static gboolean _set_default_name_cb(gpointer data) { gchar *fullname = data; const char *splitpoint; - GList *tmp = prpl_info.protocol_options; + GList *tmp = protocol.protocol_options; PurpleAccountOption *option; if (!fullname) { @@ -745,8 +701,26 @@ g_free(conv); } -static void -init_plugin(PurplePlugin *plugin) +static PurplePluginInfo * +plugin_query(GError **error) +{ + return purple_plugin_info_new( + "id", "prpl-bonjour", + "name", " Bonjour", + "version", DISPLAY_VERSION, + "category", N_("Protocol"), + "summary", N_("Bonjour Protocol Plugin"), + "description", N_("Bonjour Protocol Plugin"), + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); +} + +static gboolean +plugin_load(PurplePlugin *plugin, GError **error) { PurpleAccountOption *option; @@ -754,24 +728,38 @@ /* Creating the options for the protocol */ option = purple_account_option_int_new(_("Local Port"), "port", BONJOUR_DEFAULT_PORT); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("First name"), "first", default_firstname); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("Last name"), "last", default_lastname); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("Email"), "email", ""); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("AIM Account"), "AIM", ""); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("XMPP Account"), "jid", ""); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); - my_protocol = plugin; + my_protocol = &protocol; + purple_protocols_add(my_protocol); + + return TRUE; } -PURPLE_INIT_PLUGIN(bonjour, init_plugin, info); +static gboolean +plugin_unload(PurplePlugin *plugin, GError **error) +{ + g_free(default_firstname); + g_free(default_lastname); + + purple_protocols_remove(my_protocol); + + return TRUE; +} + +PURPLE_PLUGIN_INIT(bonjour, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/bonjour/buddy.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/bonjour/buddy.c Sun Aug 18 01:53:00 2013 +0530 @@ -179,12 +179,12 @@ /* Set the user's status */ if (bonjour_buddy->msg != NULL) - purple_prpl_got_user_status(account, name, status_id, + purple_protocol_got_user_status(account, name, status_id, "message", bonjour_buddy->msg, NULL); else - purple_prpl_got_user_status(account, name, status_id, NULL); + purple_protocol_got_user_status(account, name, status_id, NULL); - purple_prpl_got_user_idle(account, name, FALSE, 0); + purple_protocol_got_user_idle(account, name, FALSE, 0); /* TODO: Because we don't save Bonjour buddies in blist.xml, * we will always have to look up the buddy icon at login time. @@ -211,7 +211,7 @@ purple_account_remove_buddy(purple_buddy_get_account(pb), pb, NULL); purple_blist_remove_buddy(pb); } else { - purple_prpl_got_user_status(purple_buddy_get_account(pb), + purple_protocol_got_user_status(purple_buddy_get_account(pb), purple_buddy_get_name(pb), "offline", NULL); bonjour_buddy_delete(purple_buddy_get_protocol_data(pb)); purple_buddy_set_protocol_data(pb, NULL);
--- a/libpurple/protocols/gg/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/gg/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -123,4 +123,5 @@ -I$(top_builddir)/libpurple \ $(INTGG_CFLAGS) \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(DEBUG_CFLAGS)
--- a/libpurple/protocols/gg/gg.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/gg/gg.c Sun Aug 18 01:53:00 2013 +0530 @@ -28,7 +28,7 @@ #include <internal.h> -#include "plugin.h" +#include "plugins.h" #include "version.h" #include "notify.h" #include "buddylist.h" @@ -146,10 +146,10 @@ /* */ -/* static void ggp_action_buddylist_save(PurplePluginAction *action) {{{ */ -static void ggp_action_buddylist_save(PurplePluginAction *action) +/* static void ggp_action_buddylist_save(PurpleProtocolAction *action) {{{ */ +static void ggp_action_buddylist_save(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *)action->context; + PurpleConnection *gc = action->connection; purple_request_file(action, _("Save buddylist..."), NULL, TRUE, G_CALLBACK(ggp_callback_buddylist_save_ok), NULL, @@ -157,9 +157,9 @@ gc); } -static void ggp_action_buddylist_load(PurplePluginAction *action) +static void ggp_action_buddylist_load(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *)action->context; + PurpleConnection *gc = action->connection; purple_request_file(action, _("Load buddylist from file..."), NULL, FALSE, @@ -776,7 +776,7 @@ } /* ---------------------------------------------------------------------- */ -/* ----- PurplePluginProtocolInfo ----------------------------------------- */ +/* ----- PurpleProtocol ----------------------------------------- */ /* ---------------------------------------------------------------------- */ static const char *ggp_list_icon(PurpleAccount *account, PurpleBuddy *buddy) @@ -1288,56 +1288,56 @@ } } -static void ggp_action_chpass(PurplePluginAction *action) +static void ggp_action_chpass(PurpleProtocolAction *action) { - ggp_account_chpass((PurpleConnection *)action->context); + ggp_account_chpass(action->connection); } -static void ggp_action_status_broadcasting(PurplePluginAction *action) +static void ggp_action_status_broadcasting(PurpleProtocolAction *action) { - ggp_status_broadcasting_dialog((PurpleConnection *)action->context); + ggp_status_broadcasting_dialog(action->connection); } -static void ggp_action_search(PurplePluginAction *action) +static void ggp_action_search(PurpleProtocolAction *action) { - ggp_pubdir_search((PurpleConnection *)action->context, NULL); + ggp_pubdir_search(action->connection, NULL); } -static void ggp_action_set_info(PurplePluginAction *action) +static void ggp_action_set_info(PurpleProtocolAction *action) { - ggp_pubdir_set_info((PurpleConnection *)action->context); + ggp_pubdir_set_info(action->connection); } -static GList *ggp_actions(PurplePlugin *plugin, gpointer context) +static GList *ggp_get_actions(PurpleConnection *gc) { GList *m = NULL; - PurplePluginAction *act; + PurpleProtocolAction *act; - act = purple_plugin_action_new(_("Change password..."), + act = purple_protocol_action_new(_("Change password..."), ggp_action_chpass); m = g_list_append(m, act); - act = purple_plugin_action_new(_("Show status only for buddies"), + act = purple_protocol_action_new(_("Show status only for buddies"), ggp_action_status_broadcasting); m = g_list_append(m, act); m = g_list_append(m, NULL); - act = purple_plugin_action_new(_("Find buddies..."), + act = purple_protocol_action_new(_("Find buddies..."), ggp_action_search); m = g_list_append(m, act); - act = purple_plugin_action_new(_("Set User Info"), + act = purple_protocol_action_new(_("Set User Info"), ggp_action_set_info); m = g_list_append(m, act); m = g_list_append(m, NULL); - act = purple_plugin_action_new(_("Save buddylist to file..."), + act = purple_protocol_action_new(_("Save buddylist to file..."), ggp_action_buddylist_save); m = g_list_append(m, act); - act = purple_plugin_action_new(_("Load buddylist from file..."), + act = purple_protocol_action_new(_("Load buddylist from file..."), ggp_action_buddylist_load); m = g_list_append(m, act); @@ -1367,13 +1367,16 @@ return table; } -static PurplePluginProtocolInfo prpl_info = +static PurpleProtocol protocol = { - sizeof(PurplePluginProtocolInfo), /* struct_size */ + "prpl-gg", /* id */ + "Gadu-Gadu", /* name */ + sizeof(PurpleProtocol), /* struct_size */ OPT_PROTO_REGISTER_NOSCREENNAME | OPT_PROTO_IM_IMAGE, NULL, /* user_splits */ NULL, /* protocol_options */ {"png", 1, 1, 200, 200, 0, PURPLE_ICON_SCALE_DISPLAY | PURPLE_ICON_SCALE_SEND}, /* icon_spec */ + ggp_get_actions, /* get_actions */ ggp_list_icon, /* list_icon */ ggp_list_emblem, /* list_emblem */ ggp_status_buddy_text, /* status_text */ @@ -1387,7 +1390,7 @@ ggp_send_im, /* send_im */ NULL, /* set_info */ ggp_send_typing, /* send_typing */ - ggp_pubdir_get_info_prpl, /* get_info */ + ggp_pubdir_get_info_protocol, /* get_info */ ggp_status_set_purplestatus, /* set_away */ NULL, /* set_idle */ NULL, /* change_passwd */ @@ -1428,7 +1431,7 @@ NULL, /* send_file */ NULL, /* new_xfer */ ggp_offline_message, /* offline_message */ - NULL, /* whiteboard_prpl_ops */ + NULL, /* whiteboard_protocol_ops */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ NULL, /* unregister_user */ @@ -1442,44 +1445,6 @@ NULL /* get_public_alias */ }; -static gboolean ggp_load(PurplePlugin *plugin); -static gboolean ggp_unload(PurplePlugin *plugin); - -static PurplePluginInfo info = { - PURPLE_PLUGIN_MAGIC, /* magic */ - PURPLE_MAJOR_VERSION, /* major_version */ - PURPLE_MINOR_VERSION, /* minor_version */ - PURPLE_PLUGIN_PROTOCOL, /* plugin type */ - NULL, /* ui_requirement */ - 0, /* flags */ - NULL, /* dependencies */ - PURPLE_PRIORITY_DEFAULT, /* priority */ - - "prpl-gg", /* id */ - "Gadu-Gadu", /* name */ - DISPLAY_VERSION, /* version */ - - N_("Gadu-Gadu Protocol Plugin"), /* summary */ - N_("Polish popular IM"), /* description */ - "boler@sourceforge.net", /* author */ - PURPLE_WEBSITE, /* homepage */ - - ggp_load, /* load */ - ggp_unload, /* unload */ - NULL, /* destroy */ - - NULL, /* ui_info */ - &prpl_info, /* extra_info */ - NULL, /* prefs_info */ - ggp_actions, /* actions */ - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - static void purple_gg_debug_handler(int level, const char * format, va_list args) { PurpleDebugLevel purple_level; char *msg = g_strdup_vprintf(format, args); @@ -1503,9 +1468,29 @@ g_free(msg); } +static PurplePluginInfo * +plugin_query(GError **error) +{ + return purple_plugin_info_new( + "id", "prpl-gg", + "name", "Gadu-Gadu", + "version", DISPLAY_VERSION, + "category", N_("Protocol"), + "summary", N_("Gadu-Gadu Protocol Plugin"), + "description", N_("Polish popular IM"), + "author", "boler@sourceforge.net", + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); +} + static PurpleAccountOption *ggp_server_option; -static void init_plugin(PurplePlugin *plugin) +static gboolean +plugin_load(PurplePlugin *plugin, GError **error) { PurpleAccountOption *option; GList *encryption_options = NULL; @@ -1514,7 +1499,7 @@ option = purple_account_option_string_new(_("GG server"), "gg_server", ""); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + protocol.protocol_options = g_list_append(protocol.protocol_options, option); ggp_server_option = option; @@ -1532,34 +1517,36 @@ option = purple_account_option_list_new(_("Connection security"), "encryption", encryption_options); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + protocol.protocol_options = g_list_append(protocol.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, + protocol.protocol_options = g_list_append(protocol.protocol_options, option); gg_debug_handler = purple_gg_debug_handler; -} -static gboolean ggp_load(PurplePlugin *plugin) -{ purple_debug_info("gg", "Loading Gadu-Gadu protocol plugin with " "libgadu %s...\n", gg_libgadu_version()); ggp_resolver_purple_setup(); ggp_servconn_setup(ggp_server_option); - + + purple_protocols_add(&protocol); + return TRUE; } -static gboolean ggp_unload(PurplePlugin *plugin) +static gboolean +plugin_unload(PurplePlugin *plugin, GError **error) { ggp_servconn_cleanup(); + purple_protocols_remove(&protocol); + return TRUE; } -PURPLE_INIT_PLUGIN(gg, init_plugin, info); +PURPLE_PLUGIN_INIT(gg, plugin_query, plugin_load, plugin_unload); /* vim: set ts=8 sts=0 sw=8 noet: */
--- a/libpurple/protocols/gg/pubdir-prpl.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/gg/pubdir-prpl.c Sun Aug 18 01:53:00 2013 +0530 @@ -66,7 +66,7 @@ static void ggp_pubdir_got_data(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, gpointer user_data); -static void ggp_pubdir_get_info_prpl_got(PurpleConnection *gc, +static void ggp_pubdir_get_info_protocol_got(PurpleConnection *gc, int records_count, const ggp_pubdir_record *records, int next_offset, void *_uin_p); @@ -350,19 +350,19 @@ ggp_pubdir_record_free(records, record_count); } -void ggp_pubdir_get_info_prpl(PurpleConnection *gc, const char *name) +void ggp_pubdir_get_info_protocol(PurpleConnection *gc, const char *name) { uin_t uin = ggp_str_to_uin(name); uin_t *uin_p = g_new0(uin_t, 1); *uin_p = uin; - purple_debug_info("gg", "ggp_pubdir_get_info_prpl: %u\n", uin); + purple_debug_info("gg", "ggp_pubdir_get_info_protocol: %u\n", uin); - ggp_pubdir_get_info(gc, uin, ggp_pubdir_get_info_prpl_got, uin_p); + ggp_pubdir_get_info(gc, uin, ggp_pubdir_get_info_protocol_got, uin_p); } -static void ggp_pubdir_get_info_prpl_got(PurpleConnection *gc, +static void ggp_pubdir_get_info_protocol_got(PurpleConnection *gc, int records_count, const ggp_pubdir_record *records, int next_offset, void *_uin_p) { @@ -375,7 +375,7 @@ if (records_count < 1) { - purple_debug_error("gg", "ggp_pubdir_get_info_prpl_got: " + purple_debug_error("gg", "ggp_pubdir_get_info_protocol_got: " "couldn't get info for %u\n", uin); purple_notify_user_info_add_pair_plaintext(info, NULL, _("Cannot get user information")); @@ -385,7 +385,7 @@ return; } - purple_debug_info("gg", "ggp_pubdir_get_info_prpl_got: %u\n", uin); + purple_debug_info("gg", "ggp_pubdir_get_info_protocol_got: %u\n", uin); g_assert(uin == record->uin); g_assert(records_count == 1); @@ -785,7 +785,7 @@ static void ggp_pubdir_search_results_info(PurpleConnection *gc, GList *row, gpointer _form) { - ggp_pubdir_get_info_prpl(gc, g_list_nth_data(row, 0)); + ggp_pubdir_get_info_protocol(gc, g_list_nth_data(row, 0)); } static void ggp_pubdir_search_results_new(PurpleConnection *gc, GList *row,
--- a/libpurple/protocols/gg/pubdir-prpl.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/gg/pubdir-prpl.h Sun Aug 18 01:53:00 2013 +0530 @@ -27,8 +27,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#ifndef _GGP_PUBDIR_PRPL_H -#define _GGP_PUBDIR_PRPL_H +#ifndef _GGP_PUBDIR_PROTOCOL_H +#define _GGP_PUBDIR_PROTOCOL_H #include <internal.h> #include <libgadu.h> @@ -62,7 +62,7 @@ void ggp_pubdir_get_info(PurpleConnection *gc, uin_t uin, ggp_pubdir_request_cb cb, void *user_data); -void ggp_pubdir_get_info_prpl(PurpleConnection *gc, const char *name); +void ggp_pubdir_get_info_protocol(PurpleConnection *gc, const char *name); void ggp_pubdir_request_buddy_alias(PurpleConnection *gc, PurpleBuddy *buddy); void ggp_pubdir_search(PurpleConnection *gc, @@ -70,4 +70,4 @@ void ggp_pubdir_set_info(PurpleConnection *gc); -#endif /* _GGP_PUBDIR_PRPL_H */ +#endif /* _GGP_PUBDIR_PROTOCOL_H */
--- a/libpurple/protocols/gg/status.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/gg/status.c Sun Aug 18 01:53:00 2013 +0530 @@ -313,7 +313,7 @@ GG_STATUS_DESCR_MAXSIZE); } - purple_prpl_got_user_status(account, + purple_protocol_got_user_status(account, purple_account_get_username(account), purple_status_get_id(status), status_msg_gg ? "message" : NULL, status_msg_gg, NULL); @@ -446,12 +446,12 @@ if (status_message) { - purple_prpl_got_user_status(account, ggp_uin_to_str(uin), + purple_protocol_got_user_status(account, ggp_uin_to_str(uin), purple_status, "message", status_message, NULL); } else { - purple_prpl_got_user_status(account, ggp_uin_to_str(uin), + purple_protocol_got_user_status(account, ggp_uin_to_str(uin), purple_status, NULL); }
--- a/libpurple/protocols/irc/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/irc/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -35,4 +35,5 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(DEBUG_CFLAGS)
--- a/libpurple/protocols/irc/irc.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/irc/irc.c Sun Aug 18 01:53:00 2013 +0530 @@ -30,8 +30,8 @@ #include "conversation.h" #include "debug.h" #include "notify.h" -#include "prpl.h" -#include "plugin.h" +#include "protocol.h" +#include "plugins.h" #include "util.h" #include "version.h" @@ -43,7 +43,7 @@ static const char *irc_blist_icon(PurpleAccount *a, PurpleBuddy *b); static GList *irc_status_types(PurpleAccount *account); -static GList *irc_actions(PurplePlugin *plugin, gpointer context); +static GList *irc_get_actions(PurpleConnection *gc); /* static GList *irc_chat_info(PurpleConnection *gc); */ static void irc_login(PurpleAccount *account); static void irc_login_cb_ssl(gpointer data, PurpleSslConnection *gsc, PurpleInputCondition cond); @@ -60,11 +60,11 @@ static gboolean irc_nick_equal(const char *nick1, const char *nick2); static void irc_buddy_free(struct irc_buddy *ib); -PurplePlugin *_irc_plugin = NULL; +PurpleProtocol *_irc_protocol = NULL; -static void irc_view_motd(PurplePluginAction *action) +static void irc_view_motd(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; struct irc_conn *irc; char *title; @@ -157,7 +157,7 @@ int ret; char *tosend= g_strdup(buf); - purple_signal_emit(_irc_plugin, "irc-sending-text", purple_account_get_connection(irc->account), &tosend); + purple_signal_emit(_irc_protocol, "irc-sending-text", purple_account_get_connection(irc->account), &tosend); if (tosend == NULL) return 0; @@ -284,12 +284,12 @@ return types; } -static GList *irc_actions(PurplePlugin *plugin, gpointer context) +static GList *irc_get_actions(PurpleConnection *gc) { GList *list = NULL; - PurplePluginAction *act = NULL; + PurpleProtocolAction *act = NULL; - act = purple_plugin_action_new(_("View MOTD"), irc_view_motd); + act = purple_protocol_action_new(_("View MOTD"), irc_view_motd); list = g_list_append(list, act); return list; @@ -614,7 +614,7 @@ ib = g_hash_table_lookup(irc->buddies, bname); if (ib != NULL) { ib->ref++; - purple_prpl_got_user_status(irc->account, bname, + purple_protocol_got_user_status(irc->account, bname, ib->online ? "available" : "offline", NULL); } else { ib = g_new0(struct irc_buddy, 1); @@ -915,14 +915,17 @@ irc_cmd_ping(irc, NULL, NULL, NULL); } -static PurplePluginProtocolInfo prpl_info = +static PurpleProtocol protocol = { - sizeof(PurplePluginProtocolInfo), /* struct_size */ + "prpl-irc", /* id */ + "IRC", /* name */ + sizeof(PurpleProtocol), /* struct_size */ OPT_PROTO_CHAT_TOPIC | OPT_PROTO_PASSWORD_OPTIONAL | OPT_PROTO_SLASH_COMMANDS_NATIVE, NULL, /* user_splits */ NULL, /* protocol_options */ NO_BUDDY_ICONS, /* icon_spec */ + irc_get_actions, /* get_actions */ irc_blist_icon, /* list_icon */ NULL, /* list_emblems */ NULL, /* status_text */ @@ -977,7 +980,7 @@ irc_dccsend_send_file, /* send_file */ irc_dccsend_new_xfer, /* new_xfer */ NULL, /* offline_message */ - NULL, /* whiteboard_prpl_ops */ + NULL, /* whiteboard_protocol_ops */ irc_send_raw, /* send_raw */ NULL, /* roomlist_room_serialize */ NULL, /* unregister_user */ @@ -991,102 +994,93 @@ NULL /* get_public_alias */ }; -static gboolean load_plugin (PurplePlugin *plugin) { - - purple_signal_register(plugin, "irc-sending-text", - purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, - PURPLE_TYPE_CONNECTION, - G_TYPE_POINTER); /* pointer to a string */ - purple_signal_register(plugin, "irc-receiving-text", - purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, - PURPLE_TYPE_CONNECTION, - G_TYPE_POINTER); /* pointer to a string */ - return TRUE; +static PurplePluginInfo * +plugin_query(GError **error) +{ + return purple_plugin_info_new( + "id", "prpl-irc", + "name", "IRC", + "version", DISPLAY_VERSION, + "category", N_("Protocol"), + "summary", N_("IRC Protocol Plugin"), + "description", N_("The IRC Protocol Plugin that Sucks Less"), + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); } - -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-irc", /**< id */ - "IRC", /**< name */ - DISPLAY_VERSION, /**< version */ - N_("IRC Protocol Plugin"), /** summary */ - N_("The IRC Protocol Plugin that Sucks Less"), /** description */ - NULL, /**< author */ - PURPLE_WEBSITE, /**< homepage */ - - load_plugin, /**< load */ - NULL, /**< unload */ - NULL, /**< destroy */ - - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, /**< prefs_info */ - irc_actions, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - -static void _init_plugin(PurplePlugin *plugin) +static gboolean +plugin_load(PurplePlugin *plugin, GError **error) { PurpleAccountUserSplit *split; PurpleAccountOption *option; split = purple_account_user_split_new(_("Server"), IRC_DEFAULT_SERVER, '@'); - prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); + protocol.user_splits = g_list_append(protocol.user_splits, split); option = purple_account_option_int_new(_("Port"), "port", IRC_DEFAULT_PORT); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("Encodings"), "encoding", IRC_DEFAULT_CHARSET); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_bool_new(_("Auto-detect incoming UTF-8"), "autodetect_utf8", IRC_DEFAULT_AUTODETECT); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("Username"), "username", ""); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("Real name"), "realname", ""); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); /* option = purple_account_option_string_new(_("Quit message"), "quitmsg", IRC_DEFAULT_QUIT); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); */ option = purple_account_option_bool_new(_("Use SSL"), "ssl", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); #ifdef HAVE_CYRUS_SASL option = purple_account_option_bool_new(_("Authenticate with SASL"), "sasl", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_bool_new( _("Allow plaintext SASL auth over unencrypted connection"), "auth_plain_in_clear", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); #endif - _irc_plugin = plugin; + _irc_protocol = &protocol; purple_prefs_remove("/plugins/prpl/irc/quitmsg"); purple_prefs_remove("/plugins/prpl/irc"); irc_register_commands(); + + purple_signal_register(_irc_protocol, "irc-sending-text", + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + PURPLE_TYPE_CONNECTION, + G_TYPE_POINTER); /* pointer to a string */ + purple_signal_register(_irc_protocol, "irc-receiving-text", + purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, + PURPLE_TYPE_CONNECTION, + G_TYPE_POINTER); /* pointer to a string */ + + purple_protocols_add(_irc_protocol); + + return TRUE; } -PURPLE_INIT_PLUGIN(irc, _init_plugin, info); +static gboolean +plugin_unload(PurplePlugin *plugin, GError **error) +{ + purple_protocols_remove(_irc_protocol); + + return TRUE; +} + +PURPLE_PLUGIN_INIT(irc, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/irc/msgs.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/irc/msgs.c Sun Aug 18 01:53:00 2013 +0530 @@ -100,8 +100,8 @@ /* If we're away then set our away message */ status = purple_account_get_active_status(irc->account); if (purple_status_type_get_primitive(purple_status_get_status_type(status)) != PURPLE_STATUS_AVAILABLE) { - PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - prpl_info->set_status(irc->account, status); + PurpleProtocol *protocol = purple_connection_get_protocol_info(gc); + protocol->set_status(irc->account, status); } /* this used to be in the core, but it's not now */ @@ -945,10 +945,10 @@ return; if (ib->online && !ib->new_online_status) { - purple_prpl_got_user_status(irc->account, name, "offline", NULL); + purple_protocol_got_user_status(irc->account, name, "offline", NULL); ib->online = FALSE; } else if (!ib->online && ib->new_online_status) { - purple_prpl_got_user_status(irc->account, name, "available", NULL); + purple_protocol_got_user_status(irc->account, name, "available", NULL); ib->online = TRUE; } }
--- a/libpurple/protocols/irc/parse.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/irc/parse.c Sun Aug 18 01:53:00 2013 +0530 @@ -44,7 +44,7 @@ "orange", "yellow", "green", "teal", "cyan", "light blue", "pink", "grey", "light grey" }; -extern PurplePlugin *_irc_plugin; +extern PurpleProtocol *_irc_protocol; /*typedef void (*IRCMsgCallback)(struct irc_conn *irc, char *from, char *name, char **args);*/ static struct _irc_msg { @@ -200,7 +200,7 @@ char *format; size_t i; - f = PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY + f = PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS; format = c->format; @@ -221,7 +221,7 @@ args[i] = '\0'; - purple_cmd_register(c->name, args, PURPLE_CMD_P_PRPL, f, "prpl-irc", + purple_cmd_register(c->name, args, PURPLE_CMD_P_PROTOCOL, f, "prpl-irc", irc_parse_purple_cmd, _(c->help), NULL); } @@ -670,7 +670,7 @@ * TODO: It should be passed as an array of bytes and a length * instead of a null terminated string. */ - purple_signal_emit(_irc_plugin, "irc-receiving-text", gc, &input); + purple_signal_emit(_irc_protocol, "irc-receiving-text", gc, &input); if (!strncmp(input, "PING ", 5)) { msg = irc_format(irc, "vv", "PONG", input + 5);
--- a/libpurple/protocols/jabber/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -133,6 +133,7 @@ -I$(top_builddir)/libpurple \ $(DEBUG_CFLAGS) \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(IDN_CFLAGS) \ $(LIBXML_CFLAGS) \ $(FARSIGHT_CFLAGS) \
--- a/libpurple/protocols/jabber/adhoccommands.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/adhoccommands.c Sun Aug 18 01:53:00 2013 +0530 @@ -269,7 +269,7 @@ } if (js->state == JABBER_STREAM_CONNECTED) - purple_prpl_got_account_actions(purple_connection_get_account(js->gc)); + purple_protocol_got_account_actions(purple_connection_get_account(js->gc)); } static void @@ -318,10 +318,10 @@ jabber_iq_send(iq); } -static void jabber_adhoc_server_execute(PurplePluginAction *action) { +static void jabber_adhoc_server_execute(PurpleProtocolAction *action) { JabberAdHocCommands *cmd = action->user_data; if(cmd) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = (PurpleConnection *) action->connection; JabberStream *js = purple_connection_get_protocol_data(gc); jabber_adhoc_execute(js, cmd); @@ -342,7 +342,7 @@ for(riter = jbr->commands; riter; riter = g_list_next(riter)) { JabberAdHocCommands *cmd = riter->data; char *cmdname = g_strdup_printf("%s (%s)",cmd->name,jbr->name); - PurplePluginAction *act = purple_plugin_action_new(cmdname, jabber_adhoc_server_execute); + PurpleProtocolAction *act = purple_protocol_action_new(cmdname, jabber_adhoc_server_execute); act->user_data = cmd; *m = g_list_append(*m, act); g_free(cmdname); @@ -354,7 +354,7 @@ /* now add server commands */ for(cmdlst = js->commands; cmdlst; cmdlst = g_list_next(cmdlst)) { JabberAdHocCommands *cmd = cmdlst->data; - PurplePluginAction *act = purple_plugin_action_new(cmd->name, jabber_adhoc_server_execute); + PurpleProtocolAction *act = purple_protocol_action_new(cmd->name, jabber_adhoc_server_execute); act->user_data = cmd; *m = g_list_append(*m, act); }
--- a/libpurple/protocols/jabber/buddy.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/buddy.c Sun Aug 18 01:53:00 2013 +0530 @@ -23,7 +23,7 @@ #include "internal.h" #include "debug.h" #include "imgstore.h" -#include "prpl.h" +#include "protocol.h" #include "notify.h" #include "request.h" #include "util.h" @@ -624,9 +624,9 @@ * string (if any) into GSLists for the (multi-entry) edit dialog and * calls the set_vcard dialog. */ -void jabber_setup_set_info(PurplePluginAction *action) +void jabber_setup_set_info(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = (PurpleConnection *) action->connection; PurpleRequestFields *fields; PurpleRequestFieldGroup *group; PurpleRequestField *field; @@ -1361,7 +1361,7 @@ if (jbr == jabber_buddy_find_resource(jb, NULL)) { - purple_prpl_got_user_idle(purple_connection_get_account(js->gc), + purple_protocol_got_user_idle(purple_connection_get_account(js->gc), buddy_name, jbr->idle, jbr->idle); } } @@ -2270,9 +2270,9 @@ jabber_iq_send(iq); } -void jabber_user_search_begin(PurplePluginAction *action) +void jabber_user_search_begin(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = (PurpleConnection *) action->connection; JabberStream *js = purple_connection_get_protocol_data(gc); const char *def_val = purple_account_get_string(purple_connection_get_account(js->gc), "user_directory", ""); if(!*def_val && js->user_directories)
--- a/libpurple/protocols/jabber/buddy.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/buddy.h Sun Aug 18 01:53:00 2013 +0530 @@ -103,11 +103,11 @@ GList *jabber_blist_node_menu(PurpleBlistNode *node); void jabber_set_info(PurpleConnection *gc, const char *info); -void jabber_setup_set_info(PurplePluginAction *action); +void jabber_setup_set_info(PurpleProtocolAction *action); void jabber_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img); void jabber_user_search(JabberStream *js, const char *directory); -void jabber_user_search_begin(PurplePluginAction *); +void jabber_user_search_begin(PurpleProtocolAction *); void jabber_buddy_remove_all_pending_buddy_info_requests(JabberStream *js);
--- a/libpurple/protocols/jabber/caps.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/caps.c Sun Aug 18 01:53:00 2013 +0530 @@ -972,8 +972,8 @@ for (node = accounts; node; node = node->next) { PurpleAccount *account = node->data; - const char *prpl_id = purple_account_get_protocol_id(account); - if (g_str_equal("prpl-jabber", prpl_id) && purple_account_is_connected(account)) { + const char *protocol_id = purple_account_get_protocol_id(account); + if (g_str_equal("prpl-jabber", protocol_id) && purple_account_is_connected(account)) { PurpleConnection *gc = purple_account_get_connection(account); jabber_presence_send(purple_connection_get_protocol_data(gc), TRUE); }
--- a/libpurple/protocols/jabber/chat.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/chat.c Sun Aug 18 01:53:00 2013 +0530 @@ -22,7 +22,7 @@ */ #include "internal.h" #include "debug.h" -#include "prpl.h" /* for proto_chat_entry */ +#include "protocol.h" /* for proto_chat_entry */ #include "notify.h" #include "request.h" #include "roomlist.h"
--- a/libpurple/protocols/jabber/google/google_presence.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/google/google_presence.c Sun Aug 18 01:53:00 2013 +0530 @@ -27,12 +27,12 @@ if (!js->googletalk) return; if (jbr->status && purple_str_has_prefix(jbr->status, "♫ ")) { - purple_prpl_got_user_status(purple_connection_get_account(js->gc), user, "tune", + purple_protocol_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(purple_connection_get_account(js->gc), user, "tune"); + purple_protocol_got_user_status_deactive(purple_connection_get_account(js->gc), user, "tune"); } }
--- a/libpurple/protocols/jabber/google/google_roster.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/google/google_roster.c Sun Aug 18 01:53:00 2013 +0530 @@ -156,7 +156,7 @@ } } - purple_prpl_got_user_status(account, who, "offline", NULL); + purple_protocol_got_user_status(account, who, "offline", NULL); } void jabber_google_roster_rem_deny(JabberStream *js, const char *who)
--- a/libpurple/protocols/jabber/google/google_session.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/google/google_session.c Sun Aug 18 01:53:00 2013 +0530 @@ -357,7 +357,7 @@ purple_connection_get_account(js->gc), "fsrtpconference", session->remote_jid, TRUE); - purple_media_set_prpl_data(session_data->media, session); + purple_media_set_protocol_data(session_data->media, session); g_signal_connect_swapped(G_OBJECT(session_data->media), "candidates-prepared", @@ -584,7 +584,7 @@ purple_connection_get_account(js->gc), "fsrtpconference", session->remote_jid, FALSE); - purple_media_set_prpl_data(session_data->media, session); + purple_media_set_protocol_data(session_data->media, session); g_signal_connect_swapped(G_OBJECT(session_data->media), "candidates-prepared", @@ -829,7 +829,7 @@ purple_connection_get_account(js->gc)); for (; iter; iter = g_list_delete_link(iter, iter)) { GoogleSession *gsession = - purple_media_get_prpl_data(iter->data); + purple_media_get_protocol_data(iter->data); if (google_session_id_equal(&(gsession->id), &id)) { session = gsession; break;
--- a/libpurple/protocols/jabber/iq.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/iq.c Sun Aug 18 01:53:00 2013 +0530 @@ -345,7 +345,7 @@ return; } - signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_prpl(js->gc), + signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_protocol_info(js->gc), "jabber-receiving-iq", js->gc, iq_type, id, from, packet)); if (signal_return) return; @@ -370,7 +370,7 @@ g_free(key); if (signal_ref > 0) { - signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_prpl(js->gc), "jabber-watched-iq", + signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_protocol_info(js->gc), "jabber-watched-iq", js->gc, iq_type, id, from, child)); if (signal_return) return;
--- a/libpurple/protocols/jabber/jabber.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/jabber.c Sun Aug 18 01:53:00 2013 +0530 @@ -37,7 +37,7 @@ #include "notify.h" #include "pluginpref.h" #include "proxy.h" -#include "prpl.h" +#include "protocol.h" #include "request.h" #include "server.h" #include "status.h" @@ -81,7 +81,7 @@ GList *jabber_features = NULL; GList *jabber_identities = NULL; -static GHashTable *jabber_cmds = NULL; /* PurplePlugin * => GSList of ids */ +static GHashTable *jabber_cmds = NULL; /* PurpleProtocol * => GSList of ids */ static gint plugin_ref = 0; @@ -332,7 +332,7 @@ const char *name; const char *xmlns; - purple_signal_emit(purple_connection_get_prpl(js->gc), "jabber-receiving-xmlnode", js->gc, packet); + purple_signal_emit(purple_connection_get_protocol_info(js->gc), "jabber-receiving-xmlnode", js->gc, packet); /* if the signal leaves us with a null packet, we're done */ if(NULL == *packet) @@ -514,7 +514,7 @@ g_free(text); } - purple_signal_emit(purple_connection_get_prpl(gc), "jabber-sending-text", gc, &data); + purple_signal_emit(purple_connection_get_protocol_info(gc), "jabber-sending-text", gc, &data); if (data == NULL) return; @@ -571,7 +571,7 @@ do_jabber_send_raw(js, data, len); } -int jabber_prpl_send_raw(PurpleConnection *gc, const char *buf, int len) +int jabber_protocol_send_raw(PurpleConnection *gc, const char *buf, int len) { JabberStream *js = purple_connection_get_protocol_data(gc); @@ -614,7 +614,7 @@ void jabber_send(JabberStream *js, xmlnode *packet) { - purple_signal_emit(purple_connection_get_prpl(js->gc), "jabber-sending-xmlnode", js->gc, &packet); + purple_signal_emit(purple_connection_get_protocol_info(js->gc), "jabber-sending-xmlnode", js->gc, &packet); } static gboolean jabber_keepalive_timeout(PurpleConnection *gc) @@ -2513,10 +2513,10 @@ jabber_iq_send(iq); } -static void jabber_password_change(PurplePluginAction *action) +static void jabber_password_change(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = (PurpleConnection *) action->connection; JabberStream *js = purple_connection_get_protocol_data(gc); PurpleRequestFields *fields; PurpleRequestFieldGroup *group; @@ -2546,28 +2546,27 @@ js); } -GList *jabber_actions(PurplePlugin *plugin, gpointer context) +GList *jabber_get_actions(PurpleConnection *gc) { - PurpleConnection *gc = (PurpleConnection *) context; JabberStream *js = purple_connection_get_protocol_data(gc); GList *m = NULL; - PurplePluginAction *act; - - act = purple_plugin_action_new(_("Set User Info..."), + PurpleProtocolAction *act; + + act = purple_protocol_action_new(_("Set User Info..."), jabber_setup_set_info); m = g_list_append(m, act); /* if (js->protocol_options & CHANGE_PASSWORD) { */ - act = purple_plugin_action_new(_("Change Password..."), + act = purple_protocol_action_new(_("Change Password..."), jabber_password_change); m = g_list_append(m, act); /* } */ - act = purple_plugin_action_new(_("Search for Users..."), + act = purple_protocol_action_new(_("Search for Users..."), jabber_user_search_begin); m = g_list_append(m, act); - purple_debug_info("jabber", "jabber_actions: have pep: %s\n", js->pep?"YES":"NO"); + purple_debug_info("jabber", "jabber_get_actions: have pep: %s\n", js->pep?"YES":"NO"); if(js->pep) jabber_pep_init_actions(&m); @@ -3597,129 +3596,129 @@ } } -static void jabber_register_commands(PurplePlugin *plugin) +static void jabber_register_commands(PurpleProtocol *protocol) { GSList *commands = NULL; PurpleCmdId id; - id = purple_cmd_register("config", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, + id = purple_cmd_register("config", "", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-jabber", jabber_cmd_chat_config, _("config: Configure a chat room."), NULL); commands = g_slist_prepend(commands, GUINT_TO_POINTER(id)); - id = purple_cmd_register("configure", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, + id = purple_cmd_register("configure", "", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-jabber", jabber_cmd_chat_config, _("configure: Configure a chat room."), NULL); commands = g_slist_prepend(commands, GUINT_TO_POINTER(id)); - id = purple_cmd_register("nick", "s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, + id = purple_cmd_register("nick", "s", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-jabber", jabber_cmd_chat_nick, _("nick <new nickname>: Change your nickname."), NULL); commands = g_slist_prepend(commands, GUINT_TO_POINTER(id)); - id = purple_cmd_register("part", "s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | + id = purple_cmd_register("part", "s", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_part, _("part [message]: Leave the room."), NULL); commands = g_slist_prepend(commands, GUINT_TO_POINTER(id)); - id = purple_cmd_register("register", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, + id = purple_cmd_register("register", "", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-jabber", jabber_cmd_chat_register, _("register: Register with a chat room."), NULL); commands = g_slist_prepend(commands, GUINT_TO_POINTER(id)); /* XXX: there needs to be a core /topic cmd, methinks */ - id = purple_cmd_register("topic", "s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | + id = purple_cmd_register("topic", "s", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_topic, _("topic [new topic]: View or change the topic."), NULL); commands = g_slist_prepend(commands, GUINT_TO_POINTER(id)); - id = purple_cmd_register("ban", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | + id = purple_cmd_register("ban", "ws", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_ban, _("ban <user> [reason]: Ban a user from the room."), NULL); commands = g_slist_prepend(commands, GUINT_TO_POINTER(id)); - id = purple_cmd_register("affiliate", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | + id = purple_cmd_register("affiliate", "ws", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_affiliate, _("affiliate <owner|admin|member|outcast|none> [nick1] [nick2] ...: Get the users with an affiliation or set users' affiliation with the room."), NULL); commands = g_slist_prepend(commands, GUINT_TO_POINTER(id)); - id = purple_cmd_register("role", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | + id = purple_cmd_register("role", "ws", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_role, _("role <moderator|participant|visitor|none> [nick1] [nick2] ...: Get the users with a role or set users' role with the room."), NULL); commands = g_slist_prepend(commands, GUINT_TO_POINTER(id)); - id = purple_cmd_register("invite", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | + id = purple_cmd_register("invite", "ws", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_invite, _("invite <user> [message]: Invite a user to the room."), NULL); commands = g_slist_prepend(commands, GUINT_TO_POINTER(id)); - id = purple_cmd_register("join", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | + id = purple_cmd_register("join", "ws", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_join, _("join: <room[@server]> [password]: Join a chat."), NULL); commands = g_slist_prepend(commands, GUINT_TO_POINTER(id)); - id = purple_cmd_register("kick", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | + id = purple_cmd_register("kick", "ws", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_chat_kick, _("kick <user> [reason]: Kick a user from the room."), NULL); commands = g_slist_prepend(commands, GUINT_TO_POINTER(id)); - id = purple_cmd_register("msg", "ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, + id = purple_cmd_register("msg", "ws", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-jabber", jabber_cmd_chat_msg, _("msg <user> <message>: Send a private message to another user."), NULL); commands = g_slist_prepend(commands, GUINT_TO_POINTER(id)); - id = purple_cmd_register("ping", "w", PURPLE_CMD_P_PRPL, + id = purple_cmd_register("ping", "w", PURPLE_CMD_P_PROTOCOL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM | - PURPLE_CMD_FLAG_PRPL_ONLY, + PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-jabber", jabber_cmd_ping, _("ping <jid>: Ping a user/component/server."), NULL); commands = g_slist_prepend(commands, GUINT_TO_POINTER(id)); - id = purple_cmd_register("buzz", "w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY | + id = purple_cmd_register("buzz", "w", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_buzz, _("buzz: Buzz a user to get their attention"), NULL); commands = g_slist_prepend(commands, GUINT_TO_POINTER(id)); - id = purple_cmd_register("mood", "ws", PURPLE_CMD_P_PRPL, + id = purple_cmd_register("mood", "ws", PURPLE_CMD_P_PROTOCOL, PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM | - PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, + PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", jabber_cmd_mood, _("mood <mood> [text]: Set current user mood"), NULL); commands = g_slist_prepend(commands, GUINT_TO_POINTER(id)); - g_hash_table_insert(jabber_cmds, plugin, commands); + g_hash_table_insert(jabber_cmds, protocol, commands); } static void cmds_free_func(gpointer value) @@ -3731,11 +3730,12 @@ } } -static void jabber_unregister_commands(PurplePlugin *plugin) +static void jabber_unregister_commands(PurpleProtocol *protocol) { - g_hash_table_remove(jabber_cmds, plugin); + g_hash_table_remove(jabber_cmds, protocol); } +#if 0 /* IPC functions */ /** @@ -3783,6 +3783,7 @@ /* send presence with new caps info for all connected accounts */ jabber_caps_broadcast_change(); } +#endif static void jabber_do_init(void) @@ -3931,15 +3932,16 @@ jabber_cmds = NULL; } -void jabber_plugin_init(PurplePlugin *plugin) +void jabber_plugin_init(PurpleProtocol *protocol) { ++plugin_ref; if (plugin_ref == 1) jabber_do_init(); - jabber_register_commands(plugin); - + jabber_register_commands(protocol); + +#if 0 /* IPC functions */ purple_plugin_ipc_register(plugin, "contact_has_feature", PURPLE_CALLBACK(jabber_ipc_contact_has_feature), purple_marshal_BOOLEAN__POINTER_POINTER_POINTER, @@ -3963,31 +3965,32 @@ G_TYPE_NONE, 2, G_TYPE_STRING, /* node */ G_TYPE_STRING); /* namespace */ - - purple_signal_register(plugin, "jabber-register-namespace-watcher", +#endif + + purple_signal_register(protocol, "jabber-register-namespace-watcher", purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, G_TYPE_STRING, /* node */ G_TYPE_STRING); /* namespace */ - purple_signal_register(plugin, "jabber-unregister-namespace-watcher", + purple_signal_register(protocol, "jabber-unregister-namespace-watcher", purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, G_TYPE_STRING, /* node */ G_TYPE_STRING); /* namespace */ - purple_signal_connect(plugin, "jabber-register-namespace-watcher", - plugin, PURPLE_CALLBACK(jabber_iq_signal_register), NULL); - purple_signal_connect(plugin, "jabber-unregister-namespace-watcher", - plugin, PURPLE_CALLBACK(jabber_iq_signal_unregister), NULL); - - - purple_signal_register(plugin, "jabber-receiving-xmlnode", + purple_signal_connect(protocol, "jabber-register-namespace-watcher", + protocol, PURPLE_CALLBACK(jabber_iq_signal_register), NULL); + purple_signal_connect(protocol, "jabber-unregister-namespace-watcher", + protocol, PURPLE_CALLBACK(jabber_iq_signal_unregister), NULL); + + + purple_signal_register(protocol, "jabber-receiving-xmlnode", purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, PURPLE_TYPE_CONNECTION, G_TYPE_POINTER); /* modifiable xmlnode */ - purple_signal_register(plugin, "jabber-sending-xmlnode", + purple_signal_register(protocol, "jabber-sending-xmlnode", purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, PURPLE_TYPE_CONNECTION, G_TYPE_POINTER); /* modifiable xmlnode */ @@ -3996,16 +3999,16 @@ * Do not remove this or the plugin will fail. Completely. You have been * warned! */ - purple_signal_connect_priority(plugin, "jabber-sending-xmlnode", - plugin, PURPLE_CALLBACK(jabber_send_signal_cb), + purple_signal_connect_priority(protocol, "jabber-sending-xmlnode", + protocol, PURPLE_CALLBACK(jabber_send_signal_cb), NULL, PURPLE_SIGNAL_PRIORITY_HIGHEST); - purple_signal_register(plugin, "jabber-sending-text", + purple_signal_register(protocol, "jabber-sending-text", purple_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, PURPLE_TYPE_CONNECTION, G_TYPE_POINTER); /* pointer to a string */ - purple_signal_register(plugin, "jabber-receiving-message", + purple_signal_register(protocol, "jabber-receiving-message", purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER_POINTER, G_TYPE_BOOLEAN, 6, PURPLE_TYPE_CONNECTION, @@ -4015,7 +4018,7 @@ G_TYPE_STRING, /* to */ PURPLE_TYPE_XMLNODE); - purple_signal_register(plugin, "jabber-receiving-iq", + purple_signal_register(protocol, "jabber-receiving-iq", purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER, G_TYPE_BOOLEAN, 5, PURPLE_TYPE_CONNECTION, @@ -4024,7 +4027,7 @@ G_TYPE_STRING, /* from */ PURPLE_TYPE_XMLNODE); - purple_signal_register(plugin, "jabber-watched-iq", + purple_signal_register(protocol, "jabber-watched-iq", purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER, G_TYPE_BOOLEAN, 5, PURPLE_TYPE_CONNECTION, @@ -4033,7 +4036,7 @@ G_TYPE_STRING, /* from */ PURPLE_TYPE_XMLNODE); /* child */ - purple_signal_register(plugin, "jabber-receiving-presence", + purple_signal_register(protocol, "jabber-receiving-presence", purple_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER, G_TYPE_BOOLEAN, 4, PURPLE_TYPE_CONNECTION, @@ -4042,14 +4045,15 @@ PURPLE_TYPE_XMLNODE); } -void jabber_plugin_uninit(PurplePlugin *plugin) +void jabber_plugin_uninit(PurpleProtocol *protocol) { g_return_if_fail(plugin_ref > 0); - purple_signals_unregister_by_instance(plugin); + purple_signals_unregister_by_instance(protocol); +#if 0 purple_plugin_ipc_unregister_all(plugin); - - jabber_unregister_commands(plugin); +#endif + jabber_unregister_commands(protocol); --plugin_ref; if (plugin_ref == 0)
--- a/libpurple/protocols/jabber/jabber.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/jabber.h Sun Aug 18 01:53:00 2013 +0530 @@ -402,8 +402,8 @@ void jabber_convo_closed(PurpleConnection *gc, const char *who); PurpleChat *jabber_find_blist_chat(PurpleAccount *account, const char *name); gboolean jabber_offline_message(const PurpleBuddy *buddy); -int jabber_prpl_send_raw(PurpleConnection *gc, const char *buf, int len); -GList *jabber_actions(PurplePlugin *plugin, gpointer context); +int jabber_protocol_send_raw(PurpleConnection *gc, const char *buf, int len); +GList *jabber_get_actions(PurpleConnection *gc); gboolean jabber_audio_enabled(JabberStream *js, const char *unused); gboolean jabber_video_enabled(JabberStream *js, const char *unused); @@ -412,7 +412,7 @@ PurpleMediaCaps jabber_get_media_caps(PurpleAccount *account, const char *who); gboolean jabber_can_receive_file(PurpleConnection *gc, const gchar *who); -void jabber_plugin_init(PurplePlugin *plugin); -void jabber_plugin_uninit(PurplePlugin *plugin); +void jabber_plugin_init(PurpleProtocol *protocol); +void jabber_plugin_uninit(PurpleProtocol *protocol); #endif /* PURPLE_JABBER_H_ */
--- a/libpurple/protocols/jabber/jingle/rtp.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/jingle/rtp.c Sun Aug 18 01:53:00 2013 +0530 @@ -215,7 +215,7 @@ for (; iter; iter = g_list_delete_link(iter, iter)) { JingleSession *media_session = - purple_media_get_prpl_data(iter->data); + purple_media_get_protocol_data(iter->data); if (media_session == session) { media = iter->data; break; @@ -425,7 +425,7 @@ return NULL; } - purple_media_set_prpl_data(media, session); + purple_media_set_protocol_data(media, session); /* connect callbacks */ g_signal_connect(G_OBJECT(media), "candidates-prepared",
--- a/libpurple/protocols/jabber/libfacebook.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/libfacebook.c Sun Aug 18 01:53:00 2013 +0530 @@ -40,6 +40,7 @@ #include "roster.h" #include "si.h" #include "message.h" +#include "plugins.h" #include "presence.h" #include "google/google.h" #include "pep.h" @@ -55,11 +56,13 @@ return "facebook"; } -static PurplePlugin *my_protocol = NULL; +static PurpleProtocol *my_protocol = NULL; -static PurplePluginProtocolInfo prpl_info = +static PurpleProtocol protocol = { - sizeof(PurplePluginProtocolInfo), /* struct_size */ + "prpl-facebook-xmpp", /* id */ + "Facebook (XMPP)", /* name */ + sizeof(PurpleProtocol), /* struct_size */ OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_MAIL_CHECK | #ifdef HAVE_CYRUS_SASL OPT_PROTO_PASSWORD_OPTIONAL | @@ -68,6 +71,7 @@ NULL, /* user_splits */ NULL, /* protocol_options */ {"png", 32, 32, 96, 96, 0, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ + jabber_get_actions, /* get_actions */ facebook_list_icon, /* list_icon */ jabber_list_emblem, /* list_emblems */ jabber_status_text, /* status_text */ @@ -122,8 +126,8 @@ NULL, /* send_file */ NULL, /* new_xfer */ jabber_offline_message, /* offline_message */ - NULL, /* whiteboard_prpl_ops */ - jabber_prpl_send_raw, /* send_raw */ + NULL, /* whiteboard_protocol_ops */ + jabber_protocol_send_raw, /* send_raw */ jabber_roomlist_room_serialize, /* roomlist_room_serialize */ NULL, /* unregister_user */ NULL, /* send_attention */ @@ -136,57 +140,6 @@ 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; @@ -219,7 +172,7 @@ if (g_ascii_strcasecmp(proto, "xmpp")) return FALSE; - acct = find_acct(purple_plugin_get_id(my_protocol), acct_id); + acct = find_acct(my_protocol->id, acct_id); if (!acct) return FALSE; @@ -251,9 +204,26 @@ return FALSE; } +static PurplePluginInfo * +plugin_query(GError **error) +{ + return purple_plugin_info_new( + "id", "prpl-facebook-xmpp", + "name", "Facebook (XMPP)", + "version", DISPLAY_VERSION, + "category", N_("Protocol"), + "summary", N_("Facebook XMPP Protocol Plugin"), + "description", N_("Facebook XMPP Protocol Plugin"), + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); +} -static void -init_plugin(PurplePlugin *plugin) +static gboolean +plugin_load(PurplePlugin *plugin, GError **error) { PurpleAccountUserSplit *split; PurpleAccountOption *option; @@ -262,11 +232,11 @@ /* 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); + protocol.user_splits = g_list_append(protocol.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); + protocol.user_splits = g_list_append(protocol.user_splits, split); #define ADD_VALUE(list, desc, v) { \ PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1); \ @@ -286,41 +256,55 @@ #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, + protocol.protocol_options = g_list_append(protocol.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, + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_int_new(_("Connect port"), "port", 5222); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + protocol.protocol_options = g_list_append(protocol.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, + protocol.protocol_options = g_list_append(protocol.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, + protocol.protocol_options = g_list_append(protocol.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, + protocol.protocol_options = g_list_append(protocol.protocol_options, option); - my_protocol = plugin; + my_protocol = &protocol; + + purple_signal_connect(purple_get_core(), "uri-handler", my_protocol, + PURPLE_CALLBACK(xmpp_uri_handler), NULL); - purple_signal_connect(purple_get_core(), "uri-handler", plugin, - PURPLE_CALLBACK(xmpp_uri_handler), NULL); + purple_protocols_add(my_protocol); + jabber_plugin_init(my_protocol); + + return TRUE; } -PURPLE_INIT_PLUGIN(facebookxmpp, init_plugin, info); +static gboolean +plugin_unload(PurplePlugin *plugin, GError **error) +{ + jabber_plugin_uninit(my_protocol); + purple_protocols_remove(my_protocol); + return TRUE; +} + +PURPLE_PLUGIN_INIT(facebookxmpp, plugin_query, plugin_load, plugin_unload); +
--- a/libpurple/protocols/jabber/libgtalk.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/libgtalk.c Sun Aug 18 01:53:00 2013 +0530 @@ -40,6 +40,7 @@ #include "roster.h" #include "si.h" #include "message.h" +#include "plugins.h" #include "presence.h" #include "google/google.h" #include "pep.h" @@ -55,11 +56,13 @@ return "google-talk"; } -static PurplePlugin *my_protocol = NULL; +static PurpleProtocol *my_protocol = NULL; -static PurplePluginProtocolInfo prpl_info = +static PurpleProtocol protocol = { - sizeof(PurplePluginProtocolInfo), /* struct_size */ + "prpl-gtalk", /* id */ + "Google Talk (XMPP)", /* name */ + sizeof(PurpleProtocol), /* struct_size */ OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_MAIL_CHECK | #ifdef HAVE_CYRUS_SASL OPT_PROTO_PASSWORD_OPTIONAL | @@ -68,6 +71,7 @@ NULL, /* user_splits */ NULL, /* protocol_options */ {"png", 32, 32, 96, 96, 0, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ + jabber_get_actions, /* get_actions */ gtalk_list_icon, /* list_icon */ jabber_list_emblem, /* list_emblems */ jabber_status_text, /* status_text */ @@ -122,8 +126,8 @@ 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 */ + NULL, /* whiteboard_protocol_ops */ + jabber_protocol_send_raw, /* send_raw */ jabber_roomlist_room_serialize, /* roomlist_room_serialize */ NULL, /* unregister_user */ jabber_send_attention, /* send_attention */ @@ -136,57 +140,6 @@ 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; @@ -219,7 +172,7 @@ if (g_ascii_strcasecmp(proto, "xmpp")) return FALSE; - acct = find_acct(purple_plugin_get_id(my_protocol), acct_id); + acct = find_acct(my_protocol->id, acct_id); if (!acct) return FALSE; @@ -251,9 +204,26 @@ return FALSE; } +static PurplePluginInfo * +plugin_query(GError **error) +{ + return purple_plugin_info_new( + "id", "prpl-gtalk", + "name", "Google Talk (XMPP)", + "version", DISPLAY_VERSION, + "category", N_("Protocol"), + "summary", N_("Google Talk Protocol Plugin"), + "description", N_("Google Talk Protocol Plugin"), + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); +} -static void -init_plugin(PurplePlugin *plugin) +static gboolean +plugin_load(PurplePlugin *plugin, GError **error) { PurpleAccountUserSplit *split; PurpleAccountOption *option; @@ -262,11 +232,11 @@ /* 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); + protocol.user_splits = g_list_append(protocol.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); + protocol.user_splits = g_list_append(protocol.user_splits, split); #define ADD_VALUE(list, desc, v) { \ PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1); \ @@ -286,22 +256,22 @@ #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, + protocol.protocol_options = g_list_append(protocol.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, + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_int_new(_("Connect port"), "port", 5222); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + protocol.protocol_options = g_list_append(protocol.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, + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("File transfer proxies"), @@ -309,26 +279,40 @@ /* 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, + protocol.protocol_options = g_list_append(protocol.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, + protocol.protocol_options = g_list_append(protocol.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, + protocol.protocol_options = g_list_append(protocol.protocol_options, option); - my_protocol = plugin; + my_protocol = &protocol; + + purple_signal_connect(purple_get_core(), "uri-handler", my_protocol, + PURPLE_CALLBACK(xmpp_uri_handler), NULL); - purple_signal_connect(purple_get_core(), "uri-handler", plugin, - PURPLE_CALLBACK(xmpp_uri_handler), NULL); + purple_protocols_add(my_protocol); + jabber_plugin_init(my_protocol); + + return TRUE; } -PURPLE_INIT_PLUGIN(gtalk, init_plugin, info); +static gboolean +plugin_unload(PurplePlugin *plugin, GError **error) +{ + jabber_plugin_uninit(my_protocol); + purple_protocols_remove(my_protocol); + return TRUE; +} + +PURPLE_PLUGIN_INIT(gtalk, plugin_query, plugin_load, plugin_unload); +
--- a/libpurple/protocols/jabber/libxmpp.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/libxmpp.c Sun Aug 18 01:53:00 2013 +0530 @@ -40,6 +40,7 @@ #include "roster.h" #include "si.h" #include "message.h" +#include "plugins.h" #include "presence.h" #include "google/google.h" #include "pep.h" @@ -49,11 +50,13 @@ #include "data.h" #include "ibb.h" -static PurplePlugin *my_protocol = NULL; +static PurpleProtocol *my_protocol = NULL; -static PurplePluginProtocolInfo prpl_info = +static PurpleProtocol protocol = { - sizeof(PurplePluginProtocolInfo), /* struct_size */ + "prpl-jabber", /* id */ + "XMPP", /* name */ + sizeof(PurpleProtocol), /* struct_size */ OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_MAIL_CHECK | #ifdef HAVE_CYRUS_SASL OPT_PROTO_PASSWORD_OPTIONAL | @@ -62,6 +65,7 @@ NULL, /* user_splits */ NULL, /* protocol_options */ {"png", 32, 32, 96, 96, 0, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ + jabber_get_actions, /* get_actions */ jabber_list_icon, /* list_icon */ jabber_list_emblem, /* list_emblems */ jabber_status_text, /* status_text */ @@ -116,8 +120,8 @@ 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 */ + NULL, /* whiteboard_protocol_ops */ + jabber_protocol_send_raw, /* send_raw */ jabber_roomlist_room_serialize, /* roomlist_room_serialize */ jabber_unregister_account, /* unregister_user */ jabber_send_attention, /* send_attention */ @@ -130,57 +134,6 @@ 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-jabber", /**< id */ - "XMPP", /**< name */ - DISPLAY_VERSION, /**< version */ - /** summary */ - N_("XMPP Protocol Plugin"), - /** description */ - N_("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; @@ -213,7 +166,7 @@ if (g_ascii_strcasecmp(proto, "xmpp")) return FALSE; - acct = find_acct(purple_plugin_get_id(my_protocol), acct_id); + acct = find_acct(my_protocol->id, acct_id); if (!acct) return FALSE; @@ -245,9 +198,26 @@ return FALSE; } +static PurplePluginInfo * +plugin_query(GError **error) +{ + return purple_plugin_info_new( + "id", "prpl-jabber", + "name", "XMPP", + "version", DISPLAY_VERSION, + "category", N_("Protocol"), + "summary", N_("XMPP Protocol Plugin"), + "description", N_("XMPP Protocol Plugin"), + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); +} -static void -init_plugin(PurplePlugin *plugin) +static gboolean +plugin_load(PurplePlugin *plugin, GError **error) { PurpleAccountUserSplit *split; PurpleAccountOption *option; @@ -256,11 +226,11 @@ /* Translators: 'domain' is used here in the context of Internet domains, e.g. pidgin.im */ split = purple_account_user_split_new(_("Domain"), NULL, '@'); purple_account_user_split_set_reverse(split, FALSE); - prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); + protocol.user_splits = g_list_append(protocol.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); + protocol.user_splits = g_list_append(protocol.user_splits, split); #define ADD_VALUE(list, desc, v) { \ PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1); \ @@ -280,22 +250,22 @@ #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, + protocol.protocol_options = g_list_append(protocol.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, + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_int_new(_("Connect port"), "port", 5222); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + protocol.protocol_options = g_list_append(protocol.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, + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("File transfer proxies"), @@ -303,28 +273,42 @@ /* 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, + protocol.protocol_options = g_list_append(protocol.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, + protocol.protocol_options = g_list_append(protocol.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, + protocol.protocol_options = g_list_append(protocol.protocol_options, option); - my_protocol = plugin; + my_protocol = &protocol; purple_prefs_remove("/plugins/prpl/jabber"); - purple_signal_connect(purple_get_core(), "uri-handler", plugin, + purple_signal_connect(purple_get_core(), "uri-handler", my_protocol, PURPLE_CALLBACK(xmpp_uri_handler), NULL); + + purple_protocols_add(my_protocol); + jabber_plugin_init(my_protocol); + + return TRUE; } +static gboolean +plugin_unload(PurplePlugin *plugin, GError **error) +{ + jabber_plugin_uninit(my_protocol); + purple_protocols_remove(my_protocol); -PURPLE_INIT_PLUGIN(jabber, init_plugin, info); + return TRUE; +} + +PURPLE_PLUGIN_INIT(jabber, plugin_query, plugin_load, plugin_unload); +
--- a/libpurple/protocols/jabber/message.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/message.c Sun Aug 18 01:53:00 2013 +0530 @@ -313,7 +313,7 @@ return; /* Do not accept buzzes from unknown people */ /* xmpp only has 1 attention type, so index is 0 */ - purple_prpl_got_attention(jm->js->gc, jm->from, 0); + purple_protocol_got_attention(jm->js->gc, jm->from, 0); } /* used internally by the functions below */ @@ -510,7 +510,7 @@ to = xmlnode_get_attrib(packet, "to"); type = xmlnode_get_attrib(packet, "type"); - signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_prpl(js->gc), + signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_protocol_info(js->gc), "jabber-receiving-message", js->gc, type, id, from, to, packet)); if (signal_return) return;
--- a/libpurple/protocols/jabber/presence.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/presence.c Sun Aug 18 01:53:00 2013 +0530 @@ -133,14 +133,14 @@ if (purple_blist_find_buddy(account, username)) { jbr = jabber_buddy_find_resource(jb, NULL); if (jbr) { - purple_prpl_got_user_status(account, username, + purple_protocol_got_user_status(account, username, jabber_buddy_state_get_status_id(jbr->state), "priority", jbr->priority, jbr->status ? "message" : NULL, jbr->status, NULL); - purple_prpl_got_user_idle(account, username, jbr->idle, jbr->idle); + purple_protocol_got_user_idle(account, username, jbr->idle, jbr->idle); } else { - purple_prpl_got_user_status(account, username, "offline", + purple_protocol_got_user_status(account, username, "offline", msg ? "message" : NULL, msg, NULL); } @@ -502,7 +502,7 @@ jbr->caps.info = info; jbr->caps.exts = exts; - purple_prpl_got_media_caps( + purple_protocol_got_media_caps( purple_connection_get_account(userdata->js->gc), userdata->from); if (info == NULL) @@ -878,17 +878,17 @@ jbr = jabber_buddy_find_resource(presence->jb, NULL); if (jbr) { jabber_google_presence_incoming(js, buddy_name, jbr); - purple_prpl_got_user_status(account, buddy_name, + purple_protocol_got_user_status(account, buddy_name, jabber_buddy_state_get_status_id(jbr->state), "priority", jbr->priority, "message", jbr->status, NULL); - purple_prpl_got_user_idle(account, buddy_name, + purple_protocol_got_user_idle(account, buddy_name, jbr->idle, jbr->idle); if (presence->nickname) serv_got_alias(js->gc, buddy_name, presence->nickname); } else { - purple_prpl_got_user_status(account, buddy_name, + purple_protocol_got_user_status(account, buddy_name, jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_UNAVAILABLE), presence->status ? "message" : NULL, presence->status, NULL); @@ -926,7 +926,7 @@ return; } - signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_prpl(js->gc), + signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_protocol_info(js->gc), "jabber-receiving-presence", js->gc, type, presence.from, packet)); if (signal_return) { goto out;
--- a/libpurple/protocols/jabber/roster.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/roster.c Sun Aug 18 01:53:00 2013 +0530 @@ -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(purple_connection_get_account(gc), who, + purple_protocol_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); }
--- a/libpurple/protocols/jabber/si.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/si.c Sun Aug 18 01:53:00 2013 +0530 @@ -1012,7 +1012,7 @@ purple_debug_info("jabber", "about to write %" G_GSIZE_FORMAT " bytes from IBB stream\n", size); purple_circular_buffer_append(jsx->ibb_buffer, data, size); - purple_xfer_prpl_ready(xfer); + purple_xfer_protocol_ready(xfer); } else { /* trying to write past size of file transfers negotiated size, reject transfer to protect against malicious behaviour */ @@ -1117,7 +1117,7 @@ purple_xfer_end(xfer); } else { /* send more... */ - purple_xfer_prpl_ready(xfer); + purple_xfer_protocol_ready(xfer); } } @@ -1128,7 +1128,7 @@ if (jabber_ibb_session_get_state(sess) == JABBER_IBB_SESSION_OPENED) { purple_xfer_start(xfer, -1, NULL, 0); - purple_xfer_prpl_ready(xfer); + purple_xfer_protocol_ready(xfer); } else { /* error */ purple_xfer_end(xfer);
--- a/libpurple/protocols/jabber/usermood.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/usermood.c Sun Aug 18 01:53:00 2013 +0530 @@ -167,12 +167,12 @@ break; } if (newmood != NULL) { - purple_prpl_got_user_status(purple_connection_get_account(js->gc), from, "mood", + purple_protocol_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(purple_connection_get_account(js->gc), from, "mood"); + purple_protocol_got_user_status_deactive(purple_connection_get_account(js->gc), from, "mood"); } g_free(moodtext); }
--- a/libpurple/protocols/jabber/usernick.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/usernick.c Sun Aug 18 01:53:00 2013 +0530 @@ -85,8 +85,8 @@ g_free(oldnickname); } -static void do_nick_set_nick(PurplePluginAction *action) { - PurpleConnection *gc = action->context; +static void do_nick_set_nick(PurpleProtocolAction *action) { + PurpleConnection *gc = action->connection; JabberStream *js = purple_connection_get_protocol_data(gc); /* since the nickname might have been changed by another resource of this account, we always have to request the old one @@ -100,6 +100,6 @@ } void jabber_nick_init_action(GList **m) { - PurplePluginAction *act = purple_plugin_action_new(_("Set Nickname..."), do_nick_set_nick); + PurpleProtocolAction *act = purple_protocol_action_new(_("Set Nickname..."), do_nick_set_nick); *m = g_list_append(*m, act); }
--- a/libpurple/protocols/jabber/usertune.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/jabber/usertune.c Sun Aug 18 01:53:00 2013 +0530 @@ -92,7 +92,7 @@ } if (valid) { - purple_prpl_got_user_status(purple_connection_get_account(js->gc), from, "tune", + purple_protocol_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(purple_connection_get_account(js->gc), from, "tune"); + purple_protocol_got_user_status_deactive(purple_connection_get_account(js->gc), from, "tune"); } g_free(tuneinfodata.artist);
--- a/libpurple/protocols/msn/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/msn/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -99,4 +99,5 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(DEBUG_CFLAGS)
--- a/libpurple/protocols/msn/contact.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/msn/contact.c Sun Aug 18 01:53:00 2013 +0530 @@ -853,8 +853,8 @@ if (mobile && user) { user->mobile = TRUE; - purple_prpl_got_user_status(session->account, user->passport, "mobile", NULL); - purple_prpl_got_user_status(session->account, user->passport, "available", NULL); + purple_protocol_got_user_status(session->account, user->passport, "mobile", NULL); + purple_protocol_got_user_status(session->account, user->passport, "available", NULL); } if (alias) purple_serv_got_private_alias(pc, passport, alias);
--- a/libpurple/protocols/msn/msg.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/msn/msg.c Sun Aug 18 01:53:00 2013 +0530 @@ -1036,12 +1036,12 @@ if (swboard->current_users > 1 || ((swboard->conv != NULL) && PURPLE_IS_CHAT_CONVERSATION(swboard->conv))) - purple_prpl_got_attention_in_chat(gc, swboard->chat_id, user, MSN_NUDGE); + purple_protocol_got_attention_in_chat(gc, swboard->chat_id, user, MSN_NUDGE); else - purple_prpl_got_attention(gc, user, MSN_NUDGE); + purple_protocol_got_attention(gc, user, MSN_NUDGE); } else { - purple_prpl_got_attention(gc, user, MSN_NUDGE); + purple_protocol_got_attention(gc, user, MSN_NUDGE); } } else if (!strcmp(id, "2")) {
--- a/libpurple/protocols/msn/msn.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/msn/msn.c Sun Aug 18 01:53:00 2013 +0530 @@ -33,7 +33,7 @@ #include "contact.h" #include "msg.h" #include "page.h" -#include "pluginpref.h" +#include "plugins.h" #include "prefs.h" #include "session.h" #include "smiley.h" @@ -41,7 +41,7 @@ #include "util.h" #include "cmds.h" #include "core.h" -#include "prpl.h" +#include "protocol.h" #include "msnutils.h" #include "version.h" @@ -163,7 +163,7 @@ username = purple_conversation_get_name(conv); - purple_prpl_send_attention(gc, username, MSN_NUDGE); + purple_protocol_send_attention(gc, username, MSN_NUDGE); return PURPLE_CMD_RET_OK; } @@ -434,13 +434,13 @@ /* -- */ static void -msn_show_set_friendly_name(PurplePluginAction *action) +msn_show_set_friendly_name(PurpleProtocolAction *action) { PurpleConnection *gc; PurpleAccount *account; char *tmp; - gc = (PurpleConnection *) action->context; + gc = action->connection; account = purple_connection_get_account(gc); tmp = g_strdup_printf(_("Set friendly name for %s."), @@ -504,7 +504,7 @@ } static void -msn_show_locations(PurplePluginAction *action) +msn_show_locations(PurpleProtocolAction *action) { PurpleConnection *pc; PurpleAccount *account; @@ -516,7 +516,7 @@ GSList *l; MsnLocationData *data; - pc = (PurpleConnection *)action->context; + pc = action->connection; account = purple_connection_get_account(pc); session = purple_connection_get_protocol_data(pc); @@ -590,7 +590,7 @@ session->enable_mpop = TRUE; msn_annotate_contact(session, "Me", "MSN.IM.MPOP", "1", NULL); - purple_prpl_got_account_actions(purple_connection_get_account(pc)); + purple_protocol_got_account_actions(purple_connection_get_account(pc)); } static void @@ -620,15 +620,15 @@ g_free(user); } - purple_prpl_got_account_actions(account); + purple_protocol_got_account_actions(account); } static void -msn_show_set_mpop(PurplePluginAction *action) +msn_show_set_mpop(PurpleProtocolAction *action) { PurpleConnection *pc; - pc = (PurpleConnection *)action->context; + pc = action->connection; purple_request_action(pc, NULL, _("Allow multiple logins?"), _("Do you want to allow or disallow connecting from " @@ -642,12 +642,12 @@ } static void -msn_show_set_home_phone(PurplePluginAction *action) +msn_show_set_home_phone(PurpleProtocolAction *action) { PurpleConnection *gc; MsnSession *session; - gc = (PurpleConnection *) action->context; + gc = action->connection; session = purple_connection_get_protocol_data(gc); purple_request_input(gc, NULL, _("Set your home phone number."), NULL, @@ -659,12 +659,12 @@ } static void -msn_show_set_work_phone(PurplePluginAction *action) +msn_show_set_work_phone(PurpleProtocolAction *action) { PurpleConnection *gc; MsnSession *session; - gc = (PurpleConnection *) action->context; + gc = action->connection; session = purple_connection_get_protocol_data(gc); purple_request_input(gc, NULL, _("Set your work phone number."), NULL, @@ -676,12 +676,12 @@ } static void -msn_show_set_mobile_phone(PurplePluginAction *action) +msn_show_set_mobile_phone(PurpleProtocolAction *action) { PurpleConnection *gc; MsnSession *session; - gc = (PurpleConnection *) action->context; + gc = action->connection; session = purple_connection_get_protocol_data(gc); purple_request_input(gc, NULL, _("Set your mobile phone number."), NULL, @@ -693,11 +693,11 @@ } static void -msn_show_set_mobile_pages(PurplePluginAction *action) +msn_show_set_mobile_pages(PurpleProtocolAction *action) { PurpleConnection *gc; - gc = (PurpleConnection *) action->context; + gc = action->connection; purple_request_action(gc, NULL, _("Allow MSN Mobile pages?"), _("Do you want to allow or disallow people on " @@ -714,9 +714,9 @@ /* QuLogic: Disabled until confirmed correct. */ #if 0 static void -msn_show_blocked_text(PurplePluginAction *action) +msn_show_blocked_text(PurpleProtocolAction *action) { - PurpleConnection *pc = (PurpleConnection *) action->context; + PurpleConnection *pc = action->connection; MsnSession *session; char *title; @@ -738,12 +738,12 @@ #endif static void -msn_show_hotmail_inbox(PurplePluginAction *action) +msn_show_hotmail_inbox(PurpleProtocolAction *action) { PurpleConnection *gc; MsnSession *session; - gc = (PurpleConnection *) action->context; + gc = action->connection; session = purple_connection_get_protocol_data(gc); if (!session->passport_info.email_enabled) { @@ -1210,66 +1210,64 @@ } static GList * -msn_actions(PurplePlugin *plugin, gpointer context) +msn_get_actions(PurpleConnection *gc) { - PurpleConnection *gc; MsnSession *session; GList *m = NULL; - PurplePluginAction *act; - - gc = (PurpleConnection *) context; + PurpleProtocolAction *act; + session = purple_connection_get_protocol_data(gc); - act = purple_plugin_action_new(_("Set Friendly Name..."), + act = purple_protocol_action_new(_("Set Friendly Name..."), msn_show_set_friendly_name); m = g_list_append(m, act); m = g_list_append(m, NULL); if (session->enable_mpop) { - act = purple_plugin_action_new(_("View Locations..."), + act = purple_protocol_action_new(_("View Locations..."), msn_show_locations); m = g_list_append(m, act); m = g_list_append(m, NULL); } - act = purple_plugin_action_new(_("Set Home Phone Number..."), + act = purple_protocol_action_new(_("Set Home Phone Number..."), msn_show_set_home_phone); m = g_list_append(m, act); - act = purple_plugin_action_new(_("Set Work Phone Number..."), + act = purple_protocol_action_new(_("Set Work Phone Number..."), msn_show_set_work_phone); m = g_list_append(m, act); - act = purple_plugin_action_new(_("Set Mobile Phone Number..."), + act = purple_protocol_action_new(_("Set Mobile Phone Number..."), msn_show_set_mobile_phone); m = g_list_append(m, act); m = g_list_append(m, NULL); #if 0 - act = purple_plugin_action_new(_("Enable/Disable Mobile Devices..."), + act = purple_protocol_action_new(_("Enable/Disable Mobile Devices..."), msn_show_set_mobile_support); m = g_list_append(m, act); #endif - act = purple_plugin_action_new(_("Allow/Disallow Multiple Logins..."), + act = purple_protocol_action_new(_("Allow/Disallow Multiple Logins..."), msn_show_set_mpop); m = g_list_append(m, act); - act = purple_plugin_action_new(_("Allow/Disallow Mobile Pages..."), + act = purple_protocol_action_new(_("Allow/Disallow Mobile Pages..."), msn_show_set_mobile_pages); m = g_list_append(m, act); /* QuLogic: Disabled until confirmed correct. */ #if 0 m = g_list_append(m, NULL); - act = purple_plugin_action_new(_("View Blocked Text..."), + act = purple_protocol_action_new(_("View Blocked Text..."), msn_show_blocked_text); m = g_list_append(m, act); #endif m = g_list_append(m, NULL); - act = purple_plugin_action_new(_("Open Hotmail Inbox"), + act = purple_protocol_action_new(_("Open Hotmail Inbox"), msn_show_hotmail_inbox); m = g_list_append(m, act); @@ -2803,22 +2801,6 @@ PROFILE_URL, name)); } -static gboolean msn_load(PurplePlugin *plugin) -{ - msn_notification_init(); - msn_switchboard_init(); - - return TRUE; -} - -static gboolean msn_unload(PurplePlugin *plugin) -{ - msn_notification_end(); - msn_switchboard_end(); - - return TRUE; -} - static PurpleAccount *find_acct(const char *prpl, const char *acct_id) { PurpleAccount *acct = NULL; @@ -2884,13 +2866,16 @@ } -static PurplePluginProtocolInfo prpl_info = +static PurpleProtocol protocol = { - sizeof(PurplePluginProtocolInfo), /* struct_size */ + "prpl-msn", /* id */ + "MSN", /* name */ + sizeof(PurpleProtocol), /* struct_size */ OPT_PROTO_MAIL_CHECK|OPT_PROTO_INVITE_MESSAGE, NULL, /* user_splits */ NULL, /* protocol_options */ {"png,gif", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_SEND}, /* icon_spec */ + msn_get_actions, /* get_actions */ msn_list_icon, /* list_icon */ msn_list_emblems, /* list_emblems */ msn_status_text, /* status_text */ @@ -2945,7 +2930,7 @@ msn_send_file, /* send_file */ msn_new_xfer, /* new_xfer */ msn_offline_message, /* offline_message */ - NULL, /* whiteboard_prpl_ops */ + NULL, /* whiteboard_protocol_ops */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ NULL, /* unregister_user */ @@ -2959,89 +2944,90 @@ msn_get_public_alias /* get_public_alias */ }; -static PurplePluginInfo info = +static PurplePluginInfo * +plugin_query(GError **error) { - 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-msn", /**< id */ - "MSN", /**< name */ - DISPLAY_VERSION, /**< version */ - N_("Windows Live Messenger Protocol Plugin"), /**< summary */ - N_("Windows Live Messenger Protocol Plugin"), /**< description */ - NULL, /**< author */ - PURPLE_WEBSITE, /**< homepage */ - - msn_load, /**< load */ - msn_unload, /**< unload */ - NULL, /**< destroy */ - - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, /**< prefs_info */ - msn_actions, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - -static void -init_plugin(PurplePlugin *plugin) + return purple_plugin_info_new( + "id", "prpl-msn", + "name", "MSN", + "version", DISPLAY_VERSION, + "category", N_("Protocol"), + "summary", N_("Windows Live Messenger Protocol Plugin"), + "description", N_("Windows Live Messenger Protocol Plugin"), + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); +} + +static gboolean +plugin_load(PurplePlugin *plugin, GError **error) { PurpleAccountOption *option; option = purple_account_option_string_new(_("Server"), "server", MSN_SERVER); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_int_new(_("Port"), "port", MSN_PORT); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_bool_new(_("Use HTTP Method"), "http_method", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("HTTP Method Server"), "http_method_server", MSN_HTTPCONN_SERVER); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_bool_new(_("Show custom smileys"), "custom_smileys", TRUE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_bool_new(_("Allow direct connections"), "direct_connect", TRUE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_bool_new(_("Allow connecting from multiple locations"), "mpop", TRUE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, + protocol.protocol_options = g_list_append(protocol.protocol_options, option); - purple_cmd_register("nudge", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY, + purple_cmd_register("nudge", "", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-msn", msn_cmd_nudge, _("nudge: nudge a user to get their attention"), NULL); purple_prefs_remove("/plugins/prpl/msn"); - purple_signal_connect(purple_get_core(), "uri-handler", plugin, + purple_signal_connect(purple_get_core(), "uri-handler", &protocol, PURPLE_CALLBACK(msn_uri_handler), NULL); + + msn_notification_init(); + msn_switchboard_init(); + + purple_protocols_add(&protocol); + + return TRUE; } -PURPLE_INIT_PLUGIN(msn, init_plugin, info); +static gboolean +plugin_unload(PurplePlugin *plugin, GError **error) +{ + msn_notification_end(); + msn_switchboard_end(); + + purple_protocols_remove(&protocol); + + return TRUE; +} + +PURPLE_PLUGIN_INIT(msn, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/msn/slplink.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/msn/slplink.c Sun Aug 18 01:53:00 2013 +0530 @@ -538,7 +538,7 @@ if (slpmsg->ft) { slpmsg->slpcall->u.incoming_data = g_byte_array_append(slpmsg->slpcall->u.incoming_data, (const guchar *)part->buffer, part->size); - purple_xfer_prpl_ready(slpmsg->slpcall->xfer); + purple_xfer_protocol_ready(slpmsg->slpcall->xfer); } else if (slpmsg->size && slpmsg->buffer) { guint64 offset = msn_p2p_info_get_offset(part->info);
--- a/libpurple/protocols/msn/slpmsg_part.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/msn/slpmsg_part.c Sun Aug 18 01:53:00 2013 +0530 @@ -190,7 +190,7 @@ if (slpmsg->slpcall->xfer && purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED) { slpmsg->slpcall->xfer_msg = slpmsg; - purple_xfer_prpl_ready(slpmsg->slpcall->xfer); + purple_xfer_protocol_ready(slpmsg->slpcall->xfer); } else msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);
--- a/libpurple/protocols/msn/user.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/msn/user.c Sun Aug 18 01:53:00 2013 +0530 @@ -130,34 +130,34 @@ offline = (user->status == NULL); if (!offline) { - purple_prpl_got_user_status(account, user->passport, user->status, + purple_protocol_got_user_status(account, user->passport, user->status, "message", user->statusline, NULL); } else { if (user->mobile) { - purple_prpl_got_user_status(account, user->passport, "mobile", NULL); - purple_prpl_got_user_status(account, user->passport, "available", NULL); + purple_protocol_got_user_status(account, user->passport, "mobile", NULL); + purple_protocol_got_user_status(account, user->passport, "available", NULL); } else { - purple_prpl_got_user_status(account, user->passport, "offline", NULL); + purple_protocol_got_user_status(account, user->passport, "offline", NULL); } } if (!offline || !user->mobile) { - purple_prpl_got_user_status_deactive(account, user->passport, "mobile"); + purple_protocol_got_user_status_deactive(account, user->passport, "mobile"); } if (!offline && user->extinfo && user->extinfo->media_type != CURRENT_MEDIA_UNKNOWN) { if (user->extinfo->media_type == CURRENT_MEDIA_MUSIC) { - purple_prpl_got_user_status(account, user->passport, "tune", + purple_protocol_got_user_status(account, user->passport, "tune", PURPLE_TUNE_ARTIST, user->extinfo->media_artist, PURPLE_TUNE_ALBUM, user->extinfo->media_album, PURPLE_TUNE_TITLE, user->extinfo->media_title, NULL); } else if (user->extinfo->media_type == CURRENT_MEDIA_GAMES) { - purple_prpl_got_user_status(account, user->passport, "tune", + purple_protocol_got_user_status(account, user->passport, "tune", "game", user->extinfo->media_title, NULL); } else if (user->extinfo->media_type == CURRENT_MEDIA_OFFICE) { - purple_prpl_got_user_status(account, user->passport, "tune", + purple_protocol_got_user_status(account, user->passport, "tune", "office", user->extinfo->media_title, NULL); } else { @@ -165,13 +165,13 @@ user->extinfo->media_type); } } else { - purple_prpl_got_user_status_deactive(account, user->passport, "tune"); + purple_protocol_got_user_status_deactive(account, user->passport, "tune"); } if (user->idle) - purple_prpl_got_user_idle(account, user->passport, TRUE, -1); + purple_protocol_got_user_idle(account, user->passport, TRUE, -1); else - purple_prpl_got_user_idle(account, user->passport, FALSE, 0); + purple_protocol_got_user_idle(account, user->passport, FALSE, 0); } void
--- a/libpurple/protocols/mxit/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/mxit/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -12,6 +12,8 @@ chunk.h \ cipher.c \ cipher.h \ + client.c \ + client.h \ filexfer.c \ filexfer.h \ formcmds.c \ @@ -26,8 +28,6 @@ mxit.h \ profile.c \ profile.h \ - protocol.c \ - protocol.h \ roster.c \ roster.h \ splashscreen.c \ @@ -60,4 +60,5 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(DEBUG_CFLAGS)
--- a/libpurple/protocols/mxit/actions.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/mxit/actions.c Sun Aug 18 01:53:00 2013 +0530 @@ -27,7 +27,7 @@ #include "debug.h" #include "request.h" -#include "protocol.h" +#include "client.h" #include "mxit.h" #include "roster.h" #include "actions.h" @@ -207,9 +207,9 @@ * * @param action The action object */ -static void mxit_profile_action( PurplePluginAction* action ) +static void mxit_profile_action( PurpleProtocolAction* action ) { - PurpleConnection* gc = (PurpleConnection*) action->context; + PurpleConnection* gc = action->connection; struct MXitSession* session = purple_connection_get_protocol_data( gc ); struct MXitProfile* profile = session->profile; @@ -382,9 +382,9 @@ * * @param action The action object */ -static void mxit_change_pin_action( PurplePluginAction* action ) +static void mxit_change_pin_action( PurpleProtocolAction* action ) { - PurpleConnection* gc = (PurpleConnection*) action->context; + PurpleConnection* gc = action->connection; PurpleRequestFields* fields = NULL; PurpleRequestFieldGroup* group = NULL; @@ -417,9 +417,9 @@ * * @param action The action object */ -static void mxit_splash_action( PurplePluginAction* action ) +static void mxit_splash_action( PurpleProtocolAction* action ) { - PurpleConnection* gc = (PurpleConnection*) action->context; + PurpleConnection* gc = action->connection; struct MXitSession* session = purple_connection_get_protocol_data( gc ); if ( splash_current( session ) != NULL ) @@ -434,7 +434,7 @@ * * @param action The action object */ -static void mxit_about_action( PurplePluginAction* action ) +static void mxit_about_action( PurpleProtocolAction* action ) { char version[256]; @@ -454,9 +454,9 @@ * * @param action The action object */ -static void mxit_suggested_friends_action( PurplePluginAction* action ) +static void mxit_suggested_friends_action( PurpleProtocolAction* action ) { - PurpleConnection* gc = (PurpleConnection*) action->context; + PurpleConnection* gc = action->connection; struct MXitSession* session = purple_connection_get_protocol_data( gc ); const char* profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME, @@ -489,9 +489,9 @@ * * @param action The action object */ -static void mxit_user_search_action( PurplePluginAction* action ) +static void mxit_user_search_action( PurpleProtocolAction* action ) { - PurpleConnection* gc = (PurpleConnection*) action->context; + PurpleConnection* gc = action->connection; purple_request_input( gc, _( "Search for user" ), _( "Search for a MXit contact" ), @@ -507,37 +507,36 @@ /*------------------------------------------------------------------------ * Associate actions with the MXit plugin. * - * @param plugin The MXit protocol plugin - * @param context The connection context (if available) + * @param gc The connection * @return The list of plugin actions */ -GList* mxit_actions( PurplePlugin* plugin, gpointer context ) +GList* mxit_get_actions( PurpleConnection *gc ) { - PurplePluginAction* action = NULL; + PurpleProtocolAction* action = NULL; GList* m = NULL; /* display / change profile */ - action = purple_plugin_action_new( _( "Change Profile..." ), mxit_profile_action ); + action = purple_protocol_action_new( _( "Change Profile..." ), mxit_profile_action ); m = g_list_append( m, action ); /* change PIN */ - action = purple_plugin_action_new( _( "Change PIN..." ), mxit_change_pin_action ); + action = purple_protocol_action_new( _( "Change PIN..." ), mxit_change_pin_action ); m = g_list_append( m, action ); /* suggested friends */ - action = purple_plugin_action_new( _( "Suggested friends..." ), mxit_suggested_friends_action ); + action = purple_protocol_action_new( _( "Suggested friends..." ), mxit_suggested_friends_action ); m = g_list_append( m, action ); /* search for contacts */ - action = purple_plugin_action_new( _( "Search for contacts..." ), mxit_user_search_action ); + action = purple_protocol_action_new( _( "Search for contacts..." ), mxit_user_search_action ); m = g_list_append( m, action ); /* display splash-screen */ - action = purple_plugin_action_new( _( "View Splash..." ), mxit_splash_action ); + action = purple_protocol_action_new( _( "View Splash..." ), mxit_splash_action ); m = g_list_append( m, action ); /* display plugin version */ - action = purple_plugin_action_new( _( "About..." ), mxit_about_action ); + action = purple_protocol_action_new( _( "About..." ), mxit_about_action ); m = g_list_append( m, action ); return m;
--- a/libpurple/protocols/mxit/actions.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/mxit/actions.h Sun Aug 18 01:53:00 2013 +0530 @@ -28,7 +28,7 @@ /* callbacks */ -GList* mxit_actions( PurplePlugin* plugin, gpointer context ); +GList* mxit_get_actions( PurpleConnection *gc ); #endif /* _MXIT_ACTIONS_H_ */
--- a/libpurple/protocols/mxit/chunk.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/mxit/chunk.c Sun Aug 18 01:53:00 2013 +0530 @@ -26,7 +26,7 @@ #include "internal.h" #include "debug.h" -#include "protocol.h" +#include "client.h" #include "mxit.h" #include "chunk.h" #include "filexfer.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/mxit/client.c Sun Aug 18 01:53:00 2013 +0530 @@ -0,0 +1,2953 @@ +/* + * MXit Protocol libPurple Plugin + * + * -- MXit client protocol implementation -- + * + * Pieter Loubser <libpurple@mxit.com> + * + * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. + * <http://www.mxitlifestyle.com> + * + * 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 "debug.h" +#include "version.h" + +#include "client.h" +#include "mxit.h" +#include "roster.h" +#include "chunk.h" +#include "filexfer.h" +#include "markup.h" +#include "multimx.h" +#include "splashscreen.h" +#include "login.h" +#include "formcmds.h" +#include "http.h" +#include "cipher.h" +#include "voicevideo.h" + + +#define MXIT_MS_OFFSET 3 + +/* configure the right record terminator char to use */ +#define CP_REC_TERM ( ( session->http ) ? CP_HTTP_REC_TERM : CP_SOCK_REC_TERM ) + + +/*------------------------------------------------------------------------ + * return the current timestamp in milliseconds + */ +gint64 mxit_now_milli( void ) +{ + GTimeVal now; + + g_get_current_time( &now ); + + return ( ( now.tv_sec * 1000 ) + ( now.tv_usec / 1000 ) ); +} + + +/*------------------------------------------------------------------------ + * Display a notification popup message to the user. + * + * @param type The type of notification: + * - info: PURPLE_NOTIFY_MSG_INFO + * - warning: PURPLE_NOTIFY_MSG_WARNING + * - error: PURPLE_NOTIFY_MSG_ERROR + * @param heading Heading text + * @param message Message text + */ +void mxit_popup( int type, const char* heading, const char* message ) +{ + /* (reference: "libpurple/notify.h") */ + purple_notify_message( NULL, type, _( MXIT_POPUP_WIN_NAME ), heading, message, NULL, NULL ); +} + + +/*------------------------------------------------------------------------ + * For compatibility with legacy clients, all usernames are sent from MXit with a domain + * appended. For MXit contacts, this domain is set to "@m". This function strips + * those fake domains. + * + * @param username The username of the contact + */ +void mxit_strip_domain( char* username ) +{ + if ( g_str_has_suffix( username, "@m" ) ) + username[ strlen( username ) - 2 ] = '\0'; +} + + +/*------------------------------------------------------------------------ + * Dump a byte buffer to the console for debugging purposes. + * + * @param buf The data + * @param len The data length + */ +void dump_bytes( struct MXitSession* session, const char* buf, int len ) +{ + char* msg = g_malloc0( len + 1 ); + int i; + + for ( i = 0; i < len; i++ ) { + char ch = buf[i]; + + if ( ch == CP_REC_TERM ) /* record terminator */ + msg[i] = '!'; + else if ( ch == CP_FLD_TERM ) /* field terminator */ + msg[i] = '^'; + else if ( ch == CP_PKT_TERM ) /* packet terminator */ + msg[i] = '@'; + else if ( ( ch < 0x20 ) || ( ch > 0x7E ) ) /* non-printable character */ + msg[i] = '_'; + else + msg[i] = ch; + } + + purple_debug_info( MXIT_PLUGIN_ID, "DUMP: '%s'\n", msg ); + + g_free( msg ); +} + + +/*------------------------------------------------------------------------ + * Determine if we have an active chat with a specific contact + * + * @param session The MXit session object + * @param who The contact name + * @return Return true if we have an active chat with the contact + */ +gboolean find_active_chat( const GList* chats, const char* who ) +{ + const GList* list = chats; + const char* chat = NULL; + + while ( list ) { + chat = (const char*) list->data; + + if ( strcmp( chat, who ) == 0 ) + return TRUE; + + list = g_list_next( list ); + } + + return FALSE; +} + + +/*======================================================================================================================== + * Low-level Packet transmission + */ + +/*------------------------------------------------------------------------ + * Remove next packet from transmission queue. + * + * @param session The MXit session object + * @return The next packet for transmission (or NULL) + */ +static struct tx_packet* pop_tx_packet( struct MXitSession* session ) +{ + struct tx_packet* packet = NULL; + + if ( session->queue.count > 0 ) { + /* dequeue the next packet */ + packet = session->queue.packets[session->queue.rd_i]; + session->queue.packets[session->queue.rd_i] = NULL; + session->queue.rd_i = ( session->queue.rd_i + 1 ) % MAX_QUEUE_SIZE; + session->queue.count--; + } + + return packet; +} + + +/*------------------------------------------------------------------------ + * Add packet to transmission queue. + * + * @param session The MXit session object + * @param packet The packet to transmit + * @return Return TRUE if packet was enqueue, or FALSE if queue is full. + */ +static gboolean push_tx_packet( struct MXitSession* session, struct tx_packet* packet ) +{ + if ( session->queue.count < MAX_QUEUE_SIZE ) { + /* enqueue packet */ + session->queue.packets[session->queue.wr_i] = packet; + session->queue.wr_i = ( session->queue.wr_i + 1 ) % MAX_QUEUE_SIZE; + session->queue.count++; + return TRUE; + } + else + return FALSE; /* queue is full */ +} + + +/*------------------------------------------------------------------------ + * Deallocate transmission packet. + * + * @param packet The packet to deallocate. + */ +static void free_tx_packet( struct tx_packet* packet ) +{ + g_free( packet->data ); + g_free( packet ); + packet = NULL; +} + + +/*------------------------------------------------------------------------ + * Flush all the packets from the tx queue and release the resources. + * + * @param session The MXit session object + */ +static void flush_queue( struct MXitSession* session ) +{ + struct tx_packet* packet; + + purple_debug_info( MXIT_PLUGIN_ID, "flushing the tx queue\n" ); + + while ( (packet = pop_tx_packet( session ) ) != NULL ) + free_tx_packet( packet ); +} + + +/*------------------------------------------------------------------------ + * TX Step 3: Write the packet data to the TCP connection. + * + * @param fd The file descriptor + * @param pktdata The packet data + * @param pktlen The length of the packet data + * @return Return -1 on error, otherwise 0 + */ +static int mxit_write_sock_packet( int fd, const char* pktdata, int pktlen ) +{ + int written; + int res; + + written = 0; + while ( written < pktlen ) { + res = write( fd, &pktdata[written], pktlen - written ); + if ( res <= 0 ) { + /* error on socket */ + if ( errno == EAGAIN ) + continue; + + purple_debug_error( MXIT_PLUGIN_ID, "Error while writing packet to MXit server (%i)\n", res ); + return -1; + } + written += res; + } + + return 0; +} + + +/** + * Callback called for handling a HTTP GET response + * + * @param http_conn http api object (see http.h) + * @param response http api object (see http.h) + * @param _session The MXit session object + */ +static void +mxit_cb_http_rx(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, + gpointer _session) +{ + struct MXitSession *session = _session; + const gchar *got_data; + size_t got_len; + + if (!purple_http_response_is_successful(response)) { + purple_debug_error(MXIT_PLUGIN_ID, "HTTP response error (%s)\n", + purple_http_response_get_error(response)); + return; + } + + /* convert the HTTP result */ + got_data = purple_http_response_get_data(response, &got_len); + memcpy(session->rx_dbuf, got_data, got_len); + session->rx_i = got_len; + + mxit_parse_packet(session); +} + + +/** + * TX Step 3: Write the packet data to the HTTP connection (GET style). + * + * @param session The MXit session object + * @param packet The packet data + */ +static void +mxit_write_http_get(struct MXitSession* session, struct tx_packet* packet) +{ + PurpleHttpRequest *req; + char *part = NULL; + + if (packet->datalen > 0) { + char *tmp; + + tmp = g_strndup(packet->data, packet->datalen); + part = g_strdup(purple_url_encode(tmp)); + g_free(tmp); + } + + req = purple_http_request_new(NULL); + purple_http_request_set_url_printf(req, "%s?%s%s", session->http_server, + purple_url_encode(packet->header), part ? part : ""); + purple_http_request_header_set(req, "User-Agent", MXIT_HTTP_USERAGENT); + purple_http_connection_set_add(session->async_http_reqs, + purple_http_request(session->con, req, mxit_cb_http_rx, + session)); + purple_http_request_unref(req); + + g_free(part); +} + + +/** + * TX Step 3: Write the packet data to the HTTP connection (POST style). + * + * @param session The MXit session object + * @param packet The packet data + */ +static void +mxit_write_http_post(struct MXitSession* session, struct tx_packet* packet) +{ + PurpleHttpRequest *req; + + /* strip off the last '&' from the header */ + packet->header[packet->headerlen - 1] = '\0'; + packet->headerlen--; + + req = purple_http_request_new(NULL); + purple_http_request_set_url_printf(req, "%s?%s", session->http_server, + purple_url_encode(packet->header)); + purple_http_request_set_method(req, "POST"); + purple_http_request_header_set(req, "User-Agent", MXIT_HTTP_USERAGENT); + purple_http_request_header_set(req, "Content-Type", + "application/octet-stream"); + purple_http_request_set_contents(req, packet->data + MXIT_MS_OFFSET, + packet->datalen - MXIT_MS_OFFSET); + purple_http_connection_set_add(session->async_http_reqs, + purple_http_request(session->con, req, mxit_cb_http_rx, + session)); + purple_http_request_unref(req); +} + + +/*------------------------------------------------------------------------ + * TX Step 2: Handle the transmission of the packet to the MXit server. + * + * @param session The MXit session object + * @param packet The packet to transmit + */ +static void mxit_send_packet( struct MXitSession* session, struct tx_packet* packet ) +{ + int res; + + if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) { + /* we are not connected so ignore all packets to be send */ + purple_debug_error( MXIT_PLUGIN_ID, "Dropping TX packet (we are not connected)\n" ); + return; + } + + purple_debug_info( MXIT_PLUGIN_ID, "Packet send CMD:%i (%i)\n", packet->cmd, packet->headerlen + packet->datalen ); +#ifdef DEBUG_PROTOCOL + dump_bytes( session, packet->header, packet->headerlen ); + dump_bytes( session, packet->data, packet->datalen ); +#endif + + if ( !session->http ) { + /* socket connection */ + char data[packet->datalen + packet->headerlen]; + int datalen; + + /* create raw data buffer */ + memcpy( data, packet->header, packet->headerlen ); + memcpy( data + packet->headerlen, packet->data, packet->datalen ); + datalen = packet->headerlen + packet->datalen; + + 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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "We have lost the connection to MXit. Please reconnect." ) ); + } + } + else { + /* http connection */ + + if ( packet->cmd == CP_CMD_MEDIA ) { + /* multimedia packets must be send with a HTTP POST */ + mxit_write_http_post( session, packet ); + } + else { + mxit_write_http_get( session, packet ); + } + } + + /* update the timestamp of the last-transmitted packet */ + session->last_tx = mxit_now_milli(); + + /* + * we need to remember that we are still waiting for the ACK from + * the server on this request + */ + session->outack = packet->cmd; + + /* free up the packet resources */ + free_tx_packet( packet ); +} + + +/*------------------------------------------------------------------------ + * TX Step 1: Create a new Tx packet and queue it for sending. + * + * @param session The MXit session object + * @param data The packet data (payload) + * @param datalen The length of the packet data + * @param cmd The MXit command for this packet + */ +static void mxit_queue_packet( struct MXitSession* session, const char* data, int datalen, int cmd ) +{ + struct tx_packet* packet; + char header[256]; + int hlen; + + /* create a packet for sending */ + packet = g_new0( struct tx_packet, 1 ); + packet->data = g_malloc0( datalen ); + packet->cmd = cmd; + packet->headerlen = 0; + + /* create generic packet header */ + hlen = g_snprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc ), CP_REC_TERM ); /* client mxitid */ + + if ( session->http ) { + /* http connection only */ + hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "s=" ); + if ( session->http_sesid > 0 ) { + hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_sesid, CP_FLD_TERM ); /* http session id */ + } + session->http_seqno++; + hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_seqno, CP_REC_TERM ); /* http request sequence id */ + } + + hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "cm=%i%c", cmd, CP_REC_TERM ); /* packet command */ + + if ( !session->http ) { + /* socket connection only */ + packet->headerlen = g_snprintf( packet->header, sizeof( packet->header ), "ln=%i%c", ( datalen + hlen ), CP_REC_TERM ); /* packet length */ + } + + /* copy the header to packet */ + memcpy( packet->header + packet->headerlen, header, hlen ); + packet->headerlen += hlen; + + /* copy payload to packet */ + if ( datalen > 0 ) + memcpy( packet->data, data, datalen ); + packet->datalen = datalen; + + + /* shortcut */ + if ( ( session->queue.count == 0 ) && ( session->outack == 0 ) ) { + /* the queue is empty and there are no outstanding acks so we can write it directly */ + mxit_send_packet( session, packet ); + } + else { + /* we need to queue this packet */ + + if ( ( packet->cmd == CP_CMD_PING ) || ( packet->cmd == CP_CMD_POLL ) ) { + /* we do NOT queue HTTP poll nor socket ping packets */ + free_tx_packet( packet ); + return; + } + + purple_debug_info( MXIT_PLUGIN_ID, "queueing packet for later sending cmd=%i\n", cmd ); + if ( !push_tx_packet( session, packet ) ) { + /* packet could not be queued for transmission */ + mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Message Send Error" ), _( "Unable to process your request at this time" ) ); + free_tx_packet( packet ); + } + } +} + + +/*------------------------------------------------------------------------ + * Manage the packet send queue (send next packet, timeout's, etc). + * + * @param session The MXit session object + */ +static void mxit_manage_queue( struct MXitSession* session ) +{ + struct tx_packet* packet = NULL; + gint64 now = mxit_now_milli(); + + if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) { + /* we are not connected, so ignore the queue */ + return; + } + else if ( session->outack > 0 ) { + /* we are still waiting for an outstanding ACK from the MXit server */ + 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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Timeout while waiting for a response from the MXit server." ) ); + } + return; + } + + /* + * the mxit server has flood detection and it prevents you from sending messages to fast. + * this is a self defense mechanism, a very annoying feature. so the client must ensure that + * it does not send messages too fast otherwise mxit will ignore the user for 30 seconds. + * this is what we are trying to avoid here.. + */ + if ( session->q_fast_timer_id == 0 ) { + /* the fast timer has not been set yet */ + if ( session->last_tx > ( now - MXIT_TX_DELAY ) ) { + /* we need to wait a little before sending the next packet, so schedule a wakeup call */ + gint64 tdiff = now - ( session->last_tx ); + guint delay = ( MXIT_TX_DELAY - tdiff ) + 9; + if ( delay <= 0 ) + delay = MXIT_TX_DELAY; + session->q_fast_timer_id = purple_timeout_add( delay, mxit_manage_queue_fast, session ); + } + else { + /* get the next packet from the queue to send */ + packet = pop_tx_packet( session ); + if ( packet != NULL ) { + /* there was a packet waiting to be sent to the server, now is the time to do something about it */ + + /* send the packet to MXit server */ + mxit_send_packet( session, packet ); + } + } + } +} + + +/*------------------------------------------------------------------------ + * Slow callback to manage the packet send queue. + * + * @param session The MXit session object + */ +gboolean mxit_manage_queue_slow( gpointer user_data ) +{ + struct MXitSession* session = (struct MXitSession*) user_data; + + mxit_manage_queue( session ); + + /* continue running */ + return TRUE; +} + + +/*------------------------------------------------------------------------ + * Fast callback to manage the packet send queue. + * + * @param session The MXit session object + */ +gboolean mxit_manage_queue_fast( gpointer user_data ) +{ + struct MXitSession* session = (struct MXitSession*) user_data; + + session->q_fast_timer_id = 0; + mxit_manage_queue( session ); + + /* stop running */ + return FALSE; +} + + +/*------------------------------------------------------------------------ + * Callback to manage HTTP server polling (HTTP connections ONLY) + * + * @param session The MXit session object + */ +gboolean mxit_manage_polling( gpointer user_data ) +{ + struct MXitSession* session = (struct MXitSession*) user_data; + gboolean poll = FALSE; + gint64 now = mxit_now_milli(); + gint64 rxdiff; + + if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) { + /* we only poll if we are actually logged in */ + return TRUE; + } + + /* calculate the time differences */ + rxdiff = now - session->last_rx; + + if ( rxdiff < MXIT_HTTP_POLL_MIN ) { + /* we received some reply a few moments ago, so reset the poll interval */ + session->http_interval = MXIT_HTTP_POLL_MIN; + } + else if ( session->http_last_poll < ( now - session->http_interval ) ) { + /* time to poll again */ + poll = TRUE; + + /* back-off some more with the polling */ + session->http_interval = session->http_interval + ( session->http_interval / 2 ); + if ( session->http_interval > MXIT_HTTP_POLL_MAX ) + session->http_interval = MXIT_HTTP_POLL_MAX; + } + + /* debugging */ + //purple_debug_info( MXIT_PLUGIN_ID, "POLL TIMER: %i (%i)\n", session->http_interval, rxdiff ); + + if ( poll ) { + /* send poll request */ + session->http_last_poll = mxit_now_milli(); + mxit_send_poll( session ); + } + + return TRUE; +} + + +/*======================================================================================================================== + * Send MXit operations. + */ + +/*------------------------------------------------------------------------ + * Send a ping/keepalive packet to MXit server. + * + * @param session The MXit session object + */ +void mxit_send_ping( struct MXitSession* session ) +{ + /* queue packet for transmission */ + mxit_queue_packet( session, NULL, 0, CP_CMD_PING ); +} + + +/*------------------------------------------------------------------------ + * Send a poll request to the HTTP server (HTTP connections ONLY). + * + * @param session The MXit session object + */ +void mxit_send_poll( struct MXitSession* session ) +{ + /* queue packet for transmission */ + mxit_queue_packet( session, NULL, 0, CP_CMD_POLL ); +} + + +/*------------------------------------------------------------------------ + * Send a logout packet to the MXit server. + * + * @param session The MXit session object + */ +void mxit_send_logout( struct MXitSession* session ) +{ + /* queue packet for transmission */ + mxit_queue_packet( session, NULL, 0, CP_CMD_LOGOUT ); +} + + +/*------------------------------------------------------------------------ + * Send a register packet to the MXit server. + * + * @param session The MXit session object + */ +void mxit_send_register( struct MXitSession* session ) +{ + struct MXitProfile* profile = session->profile; + const char* locale; + char data[CP_MAX_PACKET]; + int datalen; + char* clientVersion; + unsigned int features = MXIT_CP_FEATURES; + + 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() ) + features |= MXIT_CF_VOICE; + + /* generate client version string (eg, P-2.7.10-Y-PURPLE) */ + clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM ); + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), + "ms=%s%c%s%c%i%c%s%c" /* "ms"=password\1version\1maxreplyLen\1name\1 */ + "%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, + 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 + ); + + /* queue packet for transmission */ + mxit_queue_packet( session, data, datalen, CP_CMD_REGISTER ); + + g_free( clientVersion ); +} + + +/*------------------------------------------------------------------------ + * Send a login packet to the MXit server. + * + * @param session The MXit session object + */ +void mxit_send_login( struct MXitSession* session ) +{ + const char* splashId; + const char* locale; + char data[CP_MAX_PACKET]; + int datalen; + char* clientVersion; + unsigned int features = MXIT_CP_FEATURES; + + 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() ) + features |= MXIT_CF_VOICE; + + /* generate client version string (eg, P-2.7.10-Y-PURPLE) */ + clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM ); + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), + "ms=%s%c%s%c%i%c" /* "ms"=password\1version\1getContacts\1 */ + "%s%c%s%c%i%c" /* capabilities\1dc\1features\1 */ + "%s%c%s%c" /* dialingcode\1locale\1 */ + "%i%c%i%c%i", /* maxReplyLen\1protocolVer\1lastRosterUpdate */ + 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 + ); + + /* include "custom resource" information */ + splashId = splash_current( session ); + if ( splashId != NULL ) + datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%ccr=%s", CP_REC_TERM, splashId ); + + /* queue packet for transmission */ + mxit_queue_packet( session, data, datalen, CP_CMD_LOGIN ); + + g_free( clientVersion ); +} + + +/*------------------------------------------------------------------------ + * Send a chat message packet to the MXit server. + * + * @param session The MXit session object + * @param to The username of the recipient + * @param msg The message text + */ +void mxit_send_message( struct MXitSession* session, const char* to, const char* msg, gboolean parse_markup, gboolean is_command ) +{ + char data[CP_MAX_PACKET]; + char* markuped_msg; + int datalen; + int msgtype = ( is_command ? CP_MSGTYPE_COMMAND : CP_MSGTYPE_NORMAL ); + + /* first we need to convert the markup from libPurple to MXit format */ + if ( parse_markup ) + markuped_msg = mxit_convert_markup_tx( msg, &msgtype ); + else + markuped_msg = g_strdup( msg ); + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), + "ms=%s%c%s%c%i%c%i", /* "ms"=jid\1msg\1type\1flags */ + to, CP_FLD_TERM, markuped_msg, CP_FLD_TERM, msgtype, CP_FLD_TERM, CP_MSG_MARKUP | CP_MSG_EMOTICON + ); + + /* free the resources */ + g_free( markuped_msg ); + + /* queue packet for transmission */ + mxit_queue_packet( session, data, datalen, CP_CMD_TX_MSG ); +} + + +/*------------------------------------------------------------------------ + * Send a extended profile request packet to the MXit server. + * + * @param session The MXit session object + * @param username Username who's profile is being requested (NULL = our own) + * @param nr_attribs Number of attributes being requested + * @param attribute The names of the attributes + */ +void mxit_send_extprofile_request( struct MXitSession* session, const char* username, unsigned int nr_attrib, const char* attribute[] ) +{ + char data[CP_MAX_PACKET]; + int datalen; + unsigned int i; + + datalen = g_snprintf( data, sizeof( data ), + "ms=%s%c%i", /* "ms="mxitid\1nr_attributes */ + ( username ? username : "" ), CP_FLD_TERM, nr_attrib + ); + + /* add attributes */ + for ( i = 0; i < nr_attrib; i++ ) + datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] ); + + /* queue packet for transmission */ + mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_GET ); +} + + +/*------------------------------------------------------------------------ + * Send an update profile packet to the MXit server. + * + * @param session The MXit session object + * @param password The new password to be used for logging in (optional) + * @param nr_attrib The number of attributes + * @param attributes String containing the attribute-name, attribute-type and value (seperated by '\01') + */ +void mxit_send_extprofile_update( struct MXitSession* session, const char* password, unsigned int nr_attrib, const char* attributes ) +{ + char data[CP_MAX_PACKET]; + gchar** parts = NULL; + int datalen; + unsigned int i; + + if ( attributes ) + parts = g_strsplit( attributes, "\01", 1 + ( nr_attrib * 3 ) ); + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), + "ms=%s%c%i", /* "ms"=password\1nr_attibutes */ + ( password ) ? password : "", CP_FLD_TERM, nr_attrib + ); + + /* add attributes */ + for ( i = 1; i < nr_attrib * 3; i+=3 ) { + if ( parts == NULL || parts[i] == NULL || parts[i + 1] == NULL || parts[i + 2] == NULL ) { + purple_debug_error( MXIT_PLUGIN_ID, "Invalid profile update attributes = '%s' - nbr=%u\n", attributes, nr_attrib ); + g_strfreev( parts ); + return; + } + datalen += g_snprintf( data + datalen, sizeof( 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 */ + mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_SET ); + + /* freeup the memory */ + g_strfreev( parts ); +} + + +/*------------------------------------------------------------------------ + * Send packet to request list of suggested friends. + * + * @param session The MXit session object + * @param max Maximum number of results to return + * @param nr_attribs Number of attributes being requested + * @param attribute The names of the attributes + */ +void mxit_send_suggest_friends( struct MXitSession* session, int max, unsigned int nr_attrib, const char* attribute[] ) +{ + char data[CP_MAX_PACKET]; + int datalen; + unsigned int i; + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), + "ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */ + CP_SUGGEST_FRIENDS, CP_FLD_TERM, "", CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib ); + + /* add attributes */ + for ( i = 0; i < nr_attrib; i++ ) + datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] ); + + /* queue packet for transmission */ + mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS ); +} + + +/*------------------------------------------------------------------------ + * Send packet to perform a search for users. + * + * @param session The MXit session object + * @param max Maximum number of results to return + * @param text The search text + * @param nr_attribs Number of attributes being requested + * @param attribute The names of the attributes + */ +void mxit_send_suggest_search( struct MXitSession* session, int max, const char* text, unsigned int nr_attrib, const char* attribute[] ) +{ + char data[CP_MAX_PACKET]; + int datalen; + unsigned int i; + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), + "ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */ + CP_SUGGEST_SEARCH, CP_FLD_TERM, text, CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib ); + + /* add attributes */ + for ( i = 0; i < nr_attrib; i++ ) + datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] ); + + /* queue packet for transmission */ + mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS ); +} + + +/*------------------------------------------------------------------------ + * Send a presence update packet to the MXit server. + * + * @param session The MXit session object + * @param presence The presence (as per MXit types) + * @param statusmsg The status message (can be NULL) + */ +void mxit_send_presence( struct MXitSession* session, int presence, const char* statusmsg ) +{ + char data[CP_MAX_PACKET]; + int datalen; + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), + "ms=%i%c", /* "ms"=show\1status */ + presence, CP_FLD_TERM + ); + + /* append status message (if one is set) */ + if ( statusmsg ) + datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%s", statusmsg ); + + /* queue packet for transmission */ + mxit_queue_packet( session, data, datalen, CP_CMD_STATUS ); +} + + +/*------------------------------------------------------------------------ + * Send a mood update packet to the MXit server. + * + * @param session The MXit session object + * @param mood The mood (as per MXit types) + */ +void mxit_send_mood( struct MXitSession* session, int mood ) +{ + char data[CP_MAX_PACKET]; + int datalen; + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), + "ms=%i", /* "ms"=mood */ + mood + ); + + /* queue packet for transmission */ + mxit_queue_packet( session, data, datalen, CP_CMD_MOOD ); +} + + +/*------------------------------------------------------------------------ + * Send an invite contact packet to the MXit server. + * + * @param session The MXit session object + * @param username The username of the contact being invited + * @param mxitid Indicates the username is a MXitId. + * @param alias Our alias for the contact + * @param groupname Group in which contact should be stored. + * @param message Invite message + */ +void mxit_send_invite( struct MXitSession* session, const char* username, gboolean mxitid, const char* alias, const char* groupname, const char* message ) +{ + char data[CP_MAX_PACKET]; + int datalen; + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), + "ms=%s%c%s%c%s%c%i%c%s%c%i", /* "ms"=group \1 username \1 alias \1 type \1 msg \1 isuserid */ + groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias, + CP_FLD_TERM, MXIT_TYPE_MXIT, CP_FLD_TERM, + ( message ? message : "" ), CP_FLD_TERM, + ( mxitid ? 0 : 1 ) + ); + + /* queue packet for transmission */ + mxit_queue_packet( session, data, datalen, CP_CMD_INVITE ); +} + + +/*------------------------------------------------------------------------ + * Send a remove contact packet to the MXit server. + * + * @param session The MXit session object + * @param username The username of the contact being removed + */ +void mxit_send_remove( struct MXitSession* session, const char* username ) +{ + char data[CP_MAX_PACKET]; + int datalen; + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), + "ms=%s", /* "ms"=username */ + username + ); + + /* queue packet for transmission */ + mxit_queue_packet( session, data, datalen, CP_CMD_REMOVE ); +} + + +/*------------------------------------------------------------------------ + * Send an accept subscription (invite) packet to the MXit server. + * + * @param session The MXit session object + * @param username The username of the contact being accepted + * @param alias Our alias for the contact + */ +void mxit_send_allow_sub( struct MXitSession* session, const char* username, const char* alias ) +{ + char data[CP_MAX_PACKET]; + int datalen; + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), + "ms=%s%c%s%c%s", /* "ms"=username\1group\1alias */ + username, CP_FLD_TERM, "", CP_FLD_TERM, alias + ); + + /* queue packet for transmission */ + mxit_queue_packet( session, data, datalen, CP_CMD_ALLOW ); +} + + +/*------------------------------------------------------------------------ + * Send an deny subscription (invite) packet to the MXit server. + * + * @param session The MXit session object + * @param username The username of the contact being denied + * @param reason The message describing the reason for the rejection (can be NULL). + */ +void mxit_send_deny_sub( struct MXitSession* session, const char* username, const char* reason ) +{ + char data[CP_MAX_PACKET]; + int datalen; + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), + "ms=%s", /* "ms"=username */ + username + ); + + /* append reason (if one is set) */ + if ( reason ) + datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, reason ); + + /* queue packet for transmission */ + mxit_queue_packet( session, data, datalen, CP_CMD_DENY ); +} + + +/*------------------------------------------------------------------------ + * Send an update contact packet to the MXit server. + * + * @param session The MXit session object + * @param username The username of the contact being denied + * @param alias Our alias for the contact + * @param groupname Group in which contact should be stored. + */ +void mxit_send_update_contact( struct MXitSession* session, const char* username, const char* alias, const char* groupname ) +{ + char data[CP_MAX_PACKET]; + int datalen; + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), + "ms=%s%c%s%c%s", /* "ms"=groupname\1username\1alias */ + groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias + ); + + /* queue packet for transmission */ + mxit_queue_packet( session, data, datalen, CP_CMD_UPDATE ); +} + + +/*------------------------------------------------------------------------ + * Send a splash-screen click event packet. + * + * @param session The MXit session object + * @param splashid The identifier of the splash-screen + */ +void mxit_send_splashclick( struct MXitSession* session, const char* splashid ) +{ + char data[CP_MAX_PACKET]; + int datalen; + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), + "ms=%s", /* "ms"=splashId */ + splashid + ); + + /* queue packet for transmission */ + mxit_queue_packet( session, data, datalen, CP_CMD_SPLASHCLICK ); +} + + +/*------------------------------------------------------------------------ + * Send a message event packet. + * + * @param session The MXit session object + * @param to The username of the original sender (ie, recipient of the event) + * @param id The identifier of the event (received in message) + * @param event Identified the type of event + */ +void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event ) +{ + char data[CP_MAX_PACKET]; + int datalen; + + purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_msgevent: to=%s id=%s event=%i\n", to, id, event ); + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), + "ms=%s%c%s%c%i", /* "ms"=contactAddress \1 id \1 event */ + to, CP_FLD_TERM, id, CP_FLD_TERM, event + ); + + /* queue packet for transmission */ + mxit_queue_packet( session, data, datalen, CP_CMD_MSGEVENT ); +} + + +/*------------------------------------------------------------------------ + * Send packet to create a MultiMX room. + * + * @param session The MXit session object + * @param groupname Name of the room to create + * @param nr_usernames Number of users in initial invite + * @param usernames The usernames of the users in the initial invite + */ +void mxit_send_groupchat_create( struct MXitSession* session, const char* groupname, int nr_usernames, const char* usernames[] ) +{ + char data[CP_MAX_PACKET]; + int datalen; + int i; + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), + "ms=%s%c%i", /* "ms"=roomname\1nr_jids\1jid0\1..\1jidN */ + groupname, CP_FLD_TERM, nr_usernames + ); + + /* add usernames */ + for ( i = 0; i < nr_usernames; i++ ) + datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] ); + + /* queue packet for transmission */ + mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_CREATE ); +} + + +/*------------------------------------------------------------------------ + * Send packet to invite users to existing MultiMX room. + * + * @param session The MXit session object + * @param roomid The unique RoomID for the MultiMx room. + * @param nr_usernames Number of users being invited + * @param usernames The usernames of the users being invited + */ +void mxit_send_groupchat_invite( struct MXitSession* session, const char* roomid, int nr_usernames, const char* usernames[] ) +{ + char data[CP_MAX_PACKET]; + int datalen; + int i; + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), + "ms=%s%c%i", /* "ms"=roomid\1nr_jids\1jid0\1..\1jidN */ + roomid, CP_FLD_TERM, nr_usernames + ); + + /* add usernames */ + for ( i = 0; i < nr_usernames; i++ ) + datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] ); + + /* queue packet for transmission */ + mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_INVITE ); +} + + +/*------------------------------------------------------------------------ + * Send a "send file direct" multimedia packet. + * + * @param session The MXit session object + * @param username The username of the recipient + * @param filename The name of the file being sent + * @param buf The content of the file + * @param buflen The length of the file contents + */ +void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen ) +{ + char data[CP_MAX_PACKET]; + int datalen = 0; + gchar* chunk; + int size; + + purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %i bytes to user '%s'\n", filename, buflen, username ); + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), "ms=" ); + + /* map chunk header over data buffer */ + chunk = &data[datalen]; + + size = mxit_chunk_create_senddirect( chunk_data( chunk ), username, filename, buf, buflen ); + if ( size < 0 ) { + purple_debug_error( MXIT_PLUGIN_ID, "Error creating senddirect chunk (%i)\n", size ); + return; + } + + set_chunk_type( chunk, CP_CHUNK_DIRECT_SND ); + set_chunk_length( chunk, size ); + datalen += MXIT_CHUNK_HEADER_SIZE + size; + + /* send the byte stream to the mxit server */ + mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA ); +} + + +/*------------------------------------------------------------------------ + * Send a "reject file" multimedia packet. + * + * @param session The MXit session object + * @param fileid A unique ID that identifies this file + */ +void mxit_send_file_reject( struct MXitSession* session, const char* fileid ) +{ + char data[CP_MAX_PACKET]; + int datalen = 0; + gchar* chunk; + int size; + + purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_reject\n" ); + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), "ms=" ); + + /* map chunk header over data buffer */ + chunk = &data[datalen]; + + size = mxit_chunk_create_reject( chunk_data( chunk ), fileid ); + if ( size < 0 ) { + purple_debug_error( MXIT_PLUGIN_ID, "Error creating reject chunk (%i)\n", size ); + return; + } + + set_chunk_type( chunk, CP_CHUNK_REJECT ); + set_chunk_length( chunk, size ); + datalen += MXIT_CHUNK_HEADER_SIZE + size; + + /* send the byte stream to the mxit server */ + mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA ); +} + + +/*------------------------------------------------------------------------ + * Send a "get file" multimedia packet. + * + * @param session The MXit session object + * @param fileid A unique ID that identifies this file + * @param filesize The number of bytes to retrieve + * @param offset Offset in file at which to start retrieving + */ +void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int filesize, int offset ) +{ + char data[CP_MAX_PACKET]; + int datalen = 0; + gchar* chunk; + int size; + + purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_accept\n" ); + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), "ms=" ); + + /* map chunk header over data buffer */ + chunk = &data[datalen]; + + size = mxit_chunk_create_get( chunk_data(chunk), fileid, filesize, offset ); + if ( size < 0 ) { + purple_debug_error( MXIT_PLUGIN_ID, "Error creating getfile chunk (%i)\n", size ); + return; + } + + set_chunk_type( chunk, CP_CHUNK_GET ); + set_chunk_length( chunk, size ); + datalen += MXIT_CHUNK_HEADER_SIZE + size; + + /* send the byte stream to the mxit server */ + mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA ); +} + + +/*------------------------------------------------------------------------ + * Send a "received file" multimedia packet. + * + * @param session The MXit session object + * @param status The status of the file-transfer + */ +void mxit_send_file_received( struct MXitSession* session, const char* fileid, short status ) +{ + char data[CP_MAX_PACKET]; + int datalen = 0; + gchar* chunk; + int size; + + purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_received\n" ); + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), "ms=" ); + + /* map chunk header over data buffer */ + chunk = &data[datalen]; + + size = mxit_chunk_create_received( chunk_data(chunk), fileid, status ); + if ( size < 0 ) { + purple_debug_error( MXIT_PLUGIN_ID, "Error creating received chunk (%i)\n", size ); + return; + } + + set_chunk_type( chunk, CP_CHUNK_RECEIVED ); + set_chunk_length( chunk, size ); + datalen += MXIT_CHUNK_HEADER_SIZE + size; + + /* send the byte stream to the mxit server */ + mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA ); +} + + +/*------------------------------------------------------------------------ + * Send a "set avatar" multimedia packet. + * + * @param session The MXit session object + * @param data The avatar data + * @param buflen The length of the avatar data + */ +void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen ) +{ + char data[CP_MAX_PACKET]; + int datalen = 0; + gchar* chunk; + int size; + + purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %i bytes\n", avatarlen ); + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), "ms=" ); + + /* map chunk header over data buffer */ + chunk = &data[datalen]; + + size = mxit_chunk_create_set_avatar( chunk_data(chunk), avatar, avatarlen ); + if ( size < 0 ) { + purple_debug_error( MXIT_PLUGIN_ID, "Error creating set avatar chunk (%i)\n", size ); + return; + } + + set_chunk_type( chunk, CP_CHUNK_SET_AVATAR ); + set_chunk_length( chunk, size ); + datalen += MXIT_CHUNK_HEADER_SIZE + size; + + /* send the byte stream to the mxit server */ + mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA ); +} + + +/*------------------------------------------------------------------------ + * Send a "get avatar" multimedia packet. + * + * @param session The MXit session object + * @param mxitId The username who's avatar to request + * @param avatarId The id of the avatar image (as string) + * @param data The avatar data + * @param buflen The length of the avatar data + */ +void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const char* avatarId ) +{ + char data[CP_MAX_PACKET]; + int datalen = 0; + gchar* chunk; + int size; + + purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_avatar: %s\n", mxitId ); + + /* convert the packet to a byte stream */ + datalen = g_snprintf( data, sizeof( data ), "ms=" ); + + /* map chunk header over data buffer */ + chunk = &data[datalen]; + + size = mxit_chunk_create_get_avatar( chunk_data(chunk), mxitId, avatarId ); + if ( size < 0 ) { + purple_debug_error( MXIT_PLUGIN_ID, "Error creating get avatar chunk (%i)\n", size ); + return; + } + + set_chunk_type( chunk, CP_CHUNK_GET_AVATAR ); + set_chunk_length( chunk, size ); + datalen += MXIT_CHUNK_HEADER_SIZE + size; + + /* send the byte stream to the mxit server */ + mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA ); +} + + +/*------------------------------------------------------------------------ + * Process a login message packet. + * + * @param session The MXit session object + * @param records The packet's data records + * @param rcount The number of data records + */ +static void mxit_parse_cmd_login( struct MXitSession* session, struct record** records, int rcount ) +{ + PurpleStatus* status; + int presence; + const char* statusmsg; + 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_RELATIONSHIP, CP_PROFILE_FLAGS }; + + purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN ); + + /* we were not yet logged in so we need to complete the login sequence here */ + session->flags |= MXIT_FLAG_LOGGEDIN; + purple_connection_update_progress( session->con, _( "Successfully Logged In..." ), 3, 4 ); + purple_connection_set_state( session->con, PURPLE_CONNECTION_CONNECTED ); + + /* save extra info if this is a HTTP connection */ + if ( session->http ) { + /* save the http server to use for this session */ + g_strlcpy( session->http_server, records[1]->fields[3]->data, sizeof( session->http_server ) ); + + /* save the session id */ + session->http_sesid = atoi( records[0]->fields[0]->data ); + } + + /* extract UserId (from protocol 5.9) */ + if ( records[1]->fcount >= 9 ) + session->uid = g_strdup( records[1]->fields[8]->data ); + + /* extract VoIP server (from protocol 6.2) */ + if ( records[1]->fcount >= 11 ) + g_strlcpy( session->voip_server, records[1]->fields[10]->data, sizeof( session->voip_server ) ); + + /* display the current splash-screen */ + if ( splash_popup_enabled( session ) ) + splash_display( session ); + + /* update presence status */ + status = purple_account_get_active_status( session->acc ); + presence = mxit_convert_presence( purple_status_get_id( status ) ); + statusmsg = purple_status_get_attr_string( status, "message" ); + + if ( ( presence != MXIT_PRESENCE_ONLINE ) || ( statusmsg ) ) { + /* when logging into MXit, your default presence is online. but with the UI, one can change + * the presence to whatever. in the case where its changed to a different presence setting + * we need to send an update to the server, otherwise the user's presence will be out of + * sync between the UI and MXit. + */ + char* statusmsg1 = purple_markup_strip_html( statusmsg ); + char* statusmsg2 = g_strndup( statusmsg1, CP_MAX_STATUS_MSG ); + + mxit_send_presence( session, presence, statusmsg2 ); + + g_free( statusmsg1 ); + g_free( statusmsg2 ); + } + + /* retrieve our MXit profile */ + mxit_send_extprofile_request( session, NULL, ARRAY_SIZE( profilelist ), profilelist ); +} + + +/*------------------------------------------------------------------------ + * Process a received message packet. + * + * @param session The MXit session object + * @param records The packet's data records + * @param rcount The number of data records + */ +static void mxit_parse_cmd_message( struct MXitSession* session, struct record** records, int rcount ) +{ + struct RXMsgData* mx = NULL; + char* message = NULL; + char* sender = NULL; + int msglen = 0; + int msgflags = 0; + int msgtype = 0; + + if ( ( rcount == 1 ) || ( records[0]->fcount < 2 ) || ( records[1]->fcount == 0 ) || ( records[1]->fields[0]->len == 0 ) ) { + /* packet contains no message or an empty message */ + return; + } + + message = records[1]->fields[0]->data; + msglen = strlen( message ); + + /* strip off dummy domain */ + sender = records[0]->fields[0]->data; + mxit_strip_domain( sender ); + +#ifdef DEBUG_PROTOCOL + purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", sender ); +#endif + + /* decode message flags (if any) */ + if ( records[0]->fcount >= 5 ) + msgflags = atoi( records[0]->fields[4]->data ); + msgtype = atoi( records[0]->fields[2]->data ); + + 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_blist_find_buddy( session->acc, sender ); + if ( buddy ) + name = purple_buddy_get_alias( buddy ); + else + 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, 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( sender ); + mx->timestamp = atoi( records[0]->fields[1]->data ); + mx->got_img = FALSE; + mx->chatid = -1; + mx->img_count = 0; + + /* update list of active chats */ + if ( !find_active_chat( session->active_chats, mx->from ) ) { + session->active_chats = g_list_append( session->active_chats, g_strdup( mx->from ) ); + } + + if ( is_multimx_contact( session, mx->from ) ) { + /* this is a MultiMx chatroom message */ + multimx_message_received( mx, message, msglen, msgtype, msgflags ); + } + else { + mxit_parse_markup( mx, message, msglen, msgtype, msgflags ); + } + + /* we are now done parsing the message */ + mx->converted = TRUE; + if ( mx->img_count == 0 ) { + /* we have all the data we need for this message to be displayed now. */ + mxit_show_message( mx ); + } + else { + /* this means there are still images outstanding for this message and + * still need to wait for them before we can display the message. + * so the image received callback function will eventually display + * the message. */ + } + + /* cleanup */ + if ( msgflags & CP_MSG_TL_ENCRYPTED ) + g_free( message ); +} + + +/*------------------------------------------------------------------------ + * Process a received subscription request packet. + * + * @param session The MXit session object + * @param records The packet's data records + * @param rcount The number of data records + */ +static void mxit_parse_cmd_new_sub( struct MXitSession* session, struct record** records, int rcount ) +{ + struct contact* contact; + struct record* rec; + int i; + + purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_new_sub (%i recs)\n", rcount ); + + for ( i = 0; i < rcount; i++ ) { + rec = records[i]; + + if ( rec->fcount < 4 ) { + purple_debug_error( MXIT_PLUGIN_ID, "BAD SUBSCRIPTION RECORD! %i fields\n", rec->fcount ); + break; + } + + /* build up a new contact info struct */ + contact = g_new0( struct contact, 1 ); + + g_strlcpy( contact->username, rec->fields[0]->data, sizeof( contact->username ) ); + mxit_strip_domain( contact->username ); /* remove dummy domain */ + g_strlcpy( contact->alias, rec->fields[1]->data, sizeof( contact->alias ) ); + contact->type = atoi( rec->fields[2]->data ); + + if ( rec->fcount >= 5 ) { + /* there is a personal invite message attached */ + if ( ( rec->fields[4]->data ) && ( *rec->fields[4]->data ) ) + contact->msg = strdup( rec->fields[4]->data ); + } + + /* handle the subscription */ + if ( contact-> type == MXIT_TYPE_MULTIMX ) { /* subscription to a MultiMX room */ + char* creator = NULL; + + if ( rec->fcount >= 6 ) + creator = rec->fields[5]->data; + + multimx_invite( session, contact, creator ); + } + else + mxit_new_subscription( session, contact ); + } +} + + +/*------------------------------------------------------------------------ + * Parse the received presence value, and ensure that it is supported. + * + * @param value The received presence value. + * @return A valid presence value. + */ +static short mxit_parse_presence( const char* value ) +{ + short presence = atoi( value ); + + /* ensure that the presence value is valid */ + switch ( presence ) { + case MXIT_PRESENCE_OFFLINE : + case MXIT_PRESENCE_ONLINE : + case MXIT_PRESENCE_AWAY : + case MXIT_PRESENCE_DND : + return presence; + + default : + return MXIT_PRESENCE_ONLINE; + } +} + + +/*------------------------------------------------------------------------ + * Process a received contact update packet. + * + * @param session The MXit session object + * @param records The packet's data records + * @param rcount The number of data records + */ +static void mxit_parse_cmd_contact( struct MXitSession* session, struct record** records, int rcount ) +{ + struct contact* contact = NULL; + struct record* rec; + int i; + + purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_contact (%i recs)\n", rcount ); + + for ( i = 0; i < rcount; i++ ) { + rec = records[i]; + + if ( rec->fcount < 6 ) { + purple_debug_error( MXIT_PLUGIN_ID, "BAD CONTACT RECORD! %i fields\n", rec->fcount ); + break; + } + + /* build up a new contact info struct */ + contact = g_new0( struct contact, 1 ); + + g_strlcpy( contact->groupname, rec->fields[0]->data, sizeof( contact->groupname ) ); + g_strlcpy( contact->username, rec->fields[1]->data, sizeof( contact->username ) ); + mxit_strip_domain( contact->username ); /* remove dummy domain */ + g_strlcpy( contact->alias, rec->fields[2]->data, sizeof( contact->alias ) ); + + contact->presence = mxit_parse_presence( rec->fields[3]->data ); + contact->type = atoi( rec->fields[4]->data ); + contact->mood = atoi( rec->fields[5]->data ); + + if ( rec->fcount > 6 ) { + /* added in protocol 5.9 - flags & subtype */ + contact->flags = atoi( rec->fields[6]->data ); + contact->subtype = rec->fields[7]->data[0]; + } + if ( rec->fcount > 8 ) { + /* added in protocol 6.0 - reject message */ + contact->msg = g_strdup( rec->fields[8]->data ); + } + + /* add the contact to the buddy list */ + if ( contact-> type == MXIT_TYPE_MULTIMX ) /* contact is a MultiMX room */ + multimx_created( session, contact ); + else + mxit_update_contact( session, contact ); + } + + if ( !( session->flags & MXIT_FLAG_FIRSTROSTER ) ) { + session->flags |= MXIT_FLAG_FIRSTROSTER; + mxit_update_blist( session ); + } +} + + +/*------------------------------------------------------------------------ + * Process a received presence update packet. + * + * @param session The MXit session object + * @param records The packet's data records + * @param rcount The number of data records + */ +static void mxit_parse_cmd_presence( struct MXitSession* session, struct record** records, int rcount ) +{ + int i; + + purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_presence (%i recs)\n", rcount ); + + for ( i = 0; i < rcount; i++ ) { + struct record* rec = records[i]; + int flags = 0; + + if ( rec->fcount < 6 ) { + purple_debug_error( MXIT_PLUGIN_ID, "BAD PRESENCE RECORD! %i fields\n", rec->fcount ); + break; + } + + /* + * The format of the record is: + * contactAddressN \1 presenceN \1 moodN \1 customMoodN \1 statusMsgN \1 avatarIdN [ \1 flagsN ] + */ + mxit_strip_domain( rec->fields[0]->data ); /* contactAddress */ + + if ( rec->fcount >= 7 ) /* flags field is included */ + flags = atoi( rec->fields[6]->data ); + + mxit_update_buddy_presence( session, rec->fields[0]->data, mxit_parse_presence( rec->fields[1]->data ), atoi( rec->fields[2]->data ), + rec->fields[3]->data, rec->fields[4]->data, flags ); + mxit_update_buddy_avatar( session, rec->fields[0]->data, rec->fields[5]->data ); + } +} + + +/*------------------------------------------------------------------------ + * Process a received extended profile packet. + * + * @param session The MXit session object + * @param records The packet's data records + * @param rcount The number of data records + */ +static void mxit_parse_cmd_extprofile( struct MXitSession* session, struct record** records, int rcount ) +{ + const char* mxitId = records[0]->fields[0]->data; + struct MXitProfile* profile = NULL; + int count; + int i; + const char* avatarId = NULL; + char* statusMsg = NULL; + + purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_extprofile: profile for '%s'\n", mxitId ); + + if ( ( records[0]->fields[0]->len == 0 ) || ( session->uid && ( strcmp( session->uid, records[0]->fields[0]->data ) == 0 ) ) ) { + /* No UserId or Our UserId provided, so this must be our own profile information */ + if ( session->profile == NULL ) + session->profile = g_new0( struct MXitProfile, 1 ); + profile = session->profile; + } + else { + /* is a buddy's profile */ + profile = g_new0( struct MXitProfile, 1 ); + } + + /* set the count for attributes */ + count = atoi( records[0]->fields[1]->data ); + + for ( i = 0; i < count; i++ ) { + char* fname; + char* fvalue; + char* fstatus; + int f = ( i * 3 ) + 2; + + fname = records[0]->fields[f]->data; /* field name */ + fvalue = records[0]->fields[f + 1]->data; /* field value */ + fstatus = records[0]->fields[f + 2]->data; /* field status */ + + /* first check the status on the returned attribute */ + if ( fstatus[0] != '0' ) { + /* error: attribute requested was NOT found */ + purple_debug_error( MXIT_PLUGIN_ID, "Bad profile status on attribute '%s' \n", fname ); + continue; + } + + if ( strcmp( CP_PROFILE_BIRTHDATE, fname ) == 0 ) { + /* birthdate */ + if ( records[0]->fields[f + 1]->len > 10 ) { + fvalue[10] = '\0'; + records[0]->fields[f + 1]->len = 10; + } + memcpy( profile->birthday, fvalue, records[0]->fields[f + 1]->len ); + } + else if ( strcmp( CP_PROFILE_GENDER, fname ) == 0 ) { + /* gender */ + profile->male = ( fvalue[0] == '1' ); + } + else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) { + /* nickname */ + g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) ); + } + else if ( strcmp( CP_PROFILE_STATUS, fname ) == 0 ) { + /* status message - just keep a reference to the value */ + statusMsg = g_markup_escape_text( fvalue, -1 ); + } + else if ( strcmp( CP_PROFILE_AVATAR, fname ) == 0 ) { + /* avatar id - just keep a reference to the value */ + avatarId = fvalue; + } + else if ( strcmp( CP_PROFILE_TITLE, fname ) == 0 ) { + /* title */ + g_strlcpy( profile->title, fvalue, sizeof( profile->title ) ); + } + else if ( strcmp( CP_PROFILE_FIRSTNAME, fname ) == 0 ) { + /* first name */ + g_strlcpy( profile->firstname, fvalue, sizeof( profile->firstname ) ); + } + else if ( strcmp( CP_PROFILE_LASTNAME, fname ) == 0 ) { + /* last name */ + g_strlcpy( profile->lastname, fvalue, sizeof( profile->lastname ) ); + } + else if ( strcmp( CP_PROFILE_EMAIL, fname ) == 0 ) { + /* email address */ + g_strlcpy( profile->email, fvalue, sizeof( profile->email ) ); + } + else if ( strcmp( CP_PROFILE_MOBILENR, fname ) == 0 ) { + /* mobile number */ + g_strlcpy( profile->mobilenr, fvalue, sizeof( profile->mobilenr ) ); + } + else if ( strcmp( CP_PROFILE_REGCOUNTRY, fname ) == 0 ) { + /* registered country */ + g_strlcpy( profile->regcountry, fvalue, sizeof( profile->regcountry ) ); + } + else if ( strcmp( CP_PROFILE_FLAGS, fname ) == 0 ) { + /* profile flags */ + profile->flags = g_ascii_strtoll( fvalue, NULL, 10 ); + } + else if ( strcmp( CP_PROFILE_LASTSEEN, fname ) == 0 ) { + /* last seen online */ + profile->lastonline = g_ascii_strtoll( fvalue, NULL, 10 ); + } + else if ( strcmp( CP_PROFILE_WHEREAMI, fname ) == 0 ) { + /* where am I */ + g_strlcpy( profile->whereami, fvalue, sizeof( profile->whereami ) ); + } + else if ( strcmp( CP_PROFILE_ABOUTME, fname ) == 0) { + /* about me */ + g_strlcpy( profile->aboutme, fvalue, sizeof( profile->aboutme ) ); + } + else if ( strcmp( CP_PROFILE_RELATIONSHIP, fname ) == 0) { + /* relatinship status */ + profile->relationship = strtol( fvalue, NULL, 10 ); + } + else { + /* invalid profile attribute */ + purple_debug_error( MXIT_PLUGIN_ID, "Invalid profile attribute received '%s' \n", fname ); + } + } + + if ( profile != session->profile ) { + /* not our own profile */ + struct contact* contact = NULL; + + contact = get_mxit_invite_contact( session, mxitId ); + if ( contact ) { + /* this is an invite, so update its profile info */ + if ( ( statusMsg ) && ( *statusMsg ) ) { + /* update the status message */ + if ( contact->statusMsg ) + g_free( contact->statusMsg ); + contact->statusMsg = strdup( statusMsg ); + } + else + contact->statusMsg = NULL; + if ( contact->profile ) + g_free( contact->profile ); + contact->profile = profile; + if ( ( avatarId ) && ( *avatarId ) ) { + /* avatar must be requested for this invite before we can display it */ + mxit_get_avatar( session, mxitId, avatarId ); + if ( contact->avatarId ) + g_free( contact->avatarId ); + contact->avatarId = strdup( avatarId ); + } + else { + /* display what we have */ + contact->avatarId = NULL; + mxit_show_profile( session, mxitId, profile ); + } + } + else { + /* this is a contact */ + if ( avatarId ) + mxit_update_buddy_avatar( session, mxitId, avatarId ); + + if ( ( statusMsg ) && ( *statusMsg ) ) { + /* update the status message */ + PurpleBuddy* buddy = NULL; + + buddy = purple_blist_find_buddy( session->acc, mxitId ); + if ( buddy ) { + contact = purple_buddy_get_protocol_data( buddy ); + if ( contact ) { + if ( contact->statusMsg ) + g_free( contact->statusMsg ); + contact->statusMsg = strdup( statusMsg ); + } + } + } + + /* show the profile */ + mxit_show_profile( session, mxitId, profile ); + g_free( profile ); + } + } + + g_free( statusMsg ); +} + + +/*------------------------------------------------------------------------ + * Process a received suggest-contacts packet. + * + * @param session The MXit session object + * @param records The packet's data records + * @param rcount The number of data records + */ +static void mxit_parse_cmd_suggestcontacts( struct MXitSession* session, struct record** records, int rcount ) +{ + GList* entries = NULL; + int searchType; + int maxResults; + int count; + int i; + + /* + * searchType \1 numSuggestions \1 total \1 numAttributes \1 name0 \1 name1 \1 ... \1 nameN \0 + * userid \1 contactType \1 value0 \1 value1 ... valueN \0 + * ... + * userid \1 contactType \1 value0 \1 value1 ... valueN + */ + + /* the type of results */ + searchType = atoi( records[0]->fields[0]->data ); + + /* the maximum number of results */ + maxResults = atoi( records[0]->fields[2]->data ); + + /* set the count for attributes */ + count = atoi( records[0]->fields[3]->data ); + + for ( i = 1; i < rcount; i ++ ) { + struct record* rec = records[i]; + struct MXitProfile* profile = g_new0( struct MXitProfile, 1 ); + int j; + + g_strlcpy( profile->userid, rec->fields[0]->data, sizeof( profile->userid ) ); + // TODO: ContactType - User or Service + + for ( j = 0; j < count; j++ ) { + char* fname; + char* fvalue = ""; + + fname = records[0]->fields[4 + j]->data; /* field name */ + if ( records[i]->fcount > ( 2 + j ) ) + fvalue = records[i]->fields[2 + j]->data; /* field value */ + + purple_debug_info( MXIT_PLUGIN_ID, " %s: field='%s' value='%s'\n", profile->userid, fname, fvalue ); + + if ( strcmp( CP_PROFILE_BIRTHDATE, fname ) == 0 ) { + /* birthdate */ + g_strlcpy( profile->birthday, fvalue, sizeof( profile->birthday ) ); + } + else if ( strcmp( CP_PROFILE_FIRSTNAME, fname ) == 0 ) { + /* first name */ + g_strlcpy( profile->firstname, fvalue, sizeof( profile->firstname ) ); + } + else if ( strcmp( CP_PROFILE_LASTNAME, fname ) == 0 ) { + /* last name */ + g_strlcpy( profile->lastname, fvalue, sizeof( profile->lastname ) ); + } + else if ( strcmp( CP_PROFILE_GENDER, fname ) == 0 ) { + /* gender */ + profile->male = ( fvalue[0] == '1' ); + } + else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) { + /* nickname */ + g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) ); + } + else if ( strcmp( CP_PROFILE_WHEREAMI, fname ) == 0 ) { + /* where am I */ + g_strlcpy( profile->whereami, fvalue, sizeof( profile->whereami ) ); + } + /* ignore other attibutes */ + } + + entries = g_list_append( entries, profile ); + } + + /* display */ + mxit_show_search_results( session, searchType, maxResults, entries ); + + /* cleanup */ + g_list_foreach( entries, (GFunc)g_free, NULL ); +} + +/*------------------------------------------------------------------------ + * Process a received message event packet. + * + * @param session The MXit session object + * @param records The packet's data records + * @param rcount The number of data records + */ +static void mxit_parse_cmd_msgevent( struct MXitSession* session, struct record** records, int rcount ) +{ + int event; + + /* + * contactAddress \1 dateTime \1 id \1 event + */ + + /* strip off dummy domain */ + mxit_strip_domain( records[0]->fields[0]->data ); + + event = atoi( records[0]->fields[3]->data ); + + switch ( event ) { + case CP_MSGEVENT_TYPING : /* user is typing */ + case CP_MSGEVENT_ANGRY : /* user is typing angrily */ + serv_got_typing( session->con, records[0]->fields[0]->data, 0, PURPLE_IM_TYPING ); + break; + + case CP_MSGEVENT_STOPPED : /* user has stopped typing */ + serv_got_typing_stopped( session->con, records[0]->fields[0]->data ); + break; + + case CP_MSGEVENT_ERASING : /* user is erasing text */ + case CP_MSGEVENT_DELIVERED : /* message was delivered */ + case CP_MSGEVENT_DISPLAYED : /* message was viewed */ + /* these are currently not supported by libPurple */ + break; + + default: + purple_debug_error( MXIT_PLUGIN_ID, "Unknown message event received (%i)\n", event ); + } +} + + +/*------------------------------------------------------------------------ + * Return the length of a multimedia chunk + * + * @return The actual chunk data length in bytes + */ +static int get_chunk_len( const char* chunkdata ) +{ + int* sizeptr; + + sizeptr = (int*) &chunkdata[1]; /* we skip the first byte (type field) */ + + return ntohl( *sizeptr ); +} + + +/*------------------------------------------------------------------------ + * Process a received multimedia packet. + * + * @param session The MXit session object + * @param records The packet's data records + * @param rcount The number of data records + */ +static void mxit_parse_cmd_media( struct MXitSession* session, struct record** records, int rcount ) +{ + char type; + int size; + + type = records[0]->fields[0]->data[0]; + size = get_chunk_len( records[0]->fields[0]->data ); + + purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_media (%i records) (%i bytes)\n", rcount, size ); + + /* supported chunked data types */ + switch ( type ) { + case CP_CHUNK_CUSTOM : /* custom resource */ + { + struct cr_chunk chunk; + + /* decode the chunked data */ + memset( &chunk, 0, sizeof( struct cr_chunk ) ); + mxit_chunk_parse_cr( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ); + + purple_debug_info( MXIT_PLUGIN_ID, "chunk info id=%s handle=%s op=%i\n", chunk.id, chunk.handle, chunk.operation ); + + /* this is a splash-screen operation */ + if ( strcmp( chunk.handle, HANDLE_SPLASH2 ) == 0 ) { + if ( chunk.operation == CR_OP_UPDATE ) { /* update the splash-screen */ + struct splash_chunk *splash = chunk.resources->data; // TODO: Fix - assuming 1st resource is splash + gboolean clickable = ( g_list_length( chunk.resources ) > 1 ); // TODO: Fix - if 2 resources, then is clickable + + if ( splash != NULL ) + splash_update( session, chunk.id, splash->data, splash->datalen, clickable ); + } + else if ( chunk.operation == CR_OP_REMOVE ) /* remove the splash-screen */ + splash_remove( session ); + } + + /* cleanup custom resources */ + g_list_foreach( chunk.resources, (GFunc)g_free, NULL ); + + } + break; + + case CP_CHUNK_OFFER : /* file offer */ + { + struct offerfile_chunk chunk; + + /* decode the chunked data */ + memset( &chunk, 0, sizeof( struct offerfile_chunk ) ); + mxit_chunk_parse_offer( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ); + + /* process the offer */ + mxit_xfer_rx_offer( session, chunk.username, chunk.filename, chunk.filesize, chunk.fileid ); + } + break; + + case CP_CHUNK_GET : /* get file response */ + { + struct getfile_chunk chunk; + + /* decode the chunked data */ + memset( &chunk, 0, sizeof( struct getfile_chunk ) ); + mxit_chunk_parse_get( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ); + + /* process the getfile */ + mxit_xfer_rx_file( session, chunk.fileid, chunk.data, chunk.length ); + } + break; + + case CP_CHUNK_GET_AVATAR : /* get avatars */ + { + struct getavatar_chunk chunk; + struct contact* contact = NULL; + + /* decode the chunked data */ + memset( &chunk, 0, sizeof( struct getavatar_chunk ) ); + mxit_chunk_parse_get_avatar( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ); + + /* update avatar image */ + if ( chunk.data ) { + purple_debug_info( MXIT_PLUGIN_ID, "updating avatar for contact '%s'\n", chunk.mxitid ); + + 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_new_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 ); + } + } + } + break; + + case CP_CHUNK_SET_AVATAR : + /* this is a reply packet to a set avatar request. no action is required */ + break; + + case CP_CHUNK_DIRECT_SND : + /* this is a ack for a file send. */ + { + struct sendfile_chunk chunk; + + memset( &chunk, 0, sizeof( struct sendfile_chunk ) ); + mxit_chunk_parse_sendfile( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ); + + purple_debug_info( MXIT_PLUGIN_ID, "file-send send to '%s' [status=%i message='%s']\n", chunk.username, chunk.status, chunk.statusmsg ); + + if ( chunk.status != 0 ) /* not success */ + mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "File Send Failed" ), chunk.statusmsg ); + } + break; + + case CP_CHUNK_RECEIVED : + /* this is a ack for a file received. no action is required */ + break; + + default : + purple_debug_error( MXIT_PLUGIN_ID, "Unsupported chunked data packet type received (%i)\n", type ); + break; + } +} + + +/*------------------------------------------------------------------------ + * Handle a redirect sent from the MXit server. + * + * @param session The MXit session object + * @param url The redirect information + */ +static void mxit_perform_redirect( struct MXitSession* session, const char* url ) +{ + gchar** parts; + gchar** host; + int type; + + purple_debug_info( MXIT_PLUGIN_ID, "mxit_perform_redirect: %s\n", url ); + + /* tokenize the URL string */ + parts = g_strsplit( url, ";", 0 ); + + /* Part 1: protocol://host:port */ + host = g_strsplit( parts[0], ":", 4 ); + if ( strcmp( host[0], "socket" ) == 0 ) { + /* redirect to a MXit socket proxy */ + g_strlcpy( session->server, &host[1][2], sizeof( session->server ) ); + session->port = atoi( host[2] ); + } + else { + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Cannot perform redirect using the specified protocol" ) ); + goto redirect_fail; + } + + /* Part 2: type of redirect */ + type = atoi( parts[1] ); + if ( type == CP_REDIRECT_PERMANENT ) { + /* permanent redirect, so save new MXit server and port */ + purple_account_set_string( session->acc, MXIT_CONFIG_SERVER_ADDR, session->server ); + purple_account_set_int( session->acc, MXIT_CONFIG_SERVER_PORT, session->port ); + } + + /* Part 3: message (optional) */ + if ( parts[2] != NULL ) + purple_connection_notice( session->con, parts[2] ); + + purple_debug_info( MXIT_PLUGIN_ID, "mxit_perform_redirect: %s redirect to %s:%i\n", + ( type == CP_REDIRECT_PERMANENT ) ? "Permanent" : "Temporary", session->server, session->port ); + + /* perform the re-connect to the new MXit server */ + mxit_reconnect( session ); + +redirect_fail: + g_strfreev( parts ); + g_strfreev( host ); +} + + +/*------------------------------------------------------------------------ + * Process a success response received from the MXit server. + * + * @param session The MXit session object + * @param packet The received packet + */ +static int process_success_response( struct MXitSession* session, struct rx_packet* packet ) +{ + /* ignore ping/poll packets */ + if ( ( packet->cmd != CP_CMD_PING ) && ( packet->cmd != CP_CMD_POLL ) ) + session->last_rx = mxit_now_milli(); + + /* + * when we pass the packet records to the next level for parsing + * we minus 3 records because 1) the first record is the packet + * type 2) packet reply status 3) the last record is bogus + */ + + /* packet command */ + switch ( packet->cmd ) { + + case CP_CMD_REGISTER : + /* fall through, when registeration successful, MXit will auto login */ + case CP_CMD_LOGIN : + /* login response */ + if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) { + mxit_parse_cmd_login( session, &packet->records[2], packet->rcount - 3 ); + } + break; + + case CP_CMD_LOGOUT : + /* logout response */ + session->flags &= ~MXIT_FLAG_LOGGEDIN; + purple_account_disconnect( session->acc ); + + /* note: + * we do not prompt the user here for a reconnect, because this could be the user + * logging in with his phone. so we just disconnect the account otherwise + * mxit will start to bounce between the phone and pidgin. also could be a valid + * disconnect selected by the user. + */ + return -1; + + case CP_CMD_CONTACT : + /* contact update */ + mxit_parse_cmd_contact( session, &packet->records[2], packet->rcount - 3 ); + break; + + case CP_CMD_PRESENCE : + /* presence update */ + mxit_parse_cmd_presence( session, &packet->records[2], packet->rcount - 3 ); + break; + + case CP_CMD_RX_MSG : + /* incoming message (no bogus record) */ + mxit_parse_cmd_message( session, &packet->records[2], packet->rcount - 2 ); + break; + + case CP_CMD_NEW_SUB : + /* new subscription request */ + mxit_parse_cmd_new_sub( session, &packet->records[2], packet->rcount - 3 ); + break; + + case CP_CMD_MEDIA : + /* multi-media message */ + mxit_parse_cmd_media( session, &packet->records[2], packet->rcount - 2 ); + break; + + case CP_CMD_EXTPROFILE_GET : + /* profile update */ + mxit_parse_cmd_extprofile( session, &packet->records[2], packet->rcount - 2 ); + break; + + case CP_CMD_SUGGESTCONTACTS : + /* suggest contacts */ + mxit_parse_cmd_suggestcontacts( session, &packet->records[2], packet->rcount - 2 ); + break; + + case CP_CMD_GOT_MSGEVENT : + /* received message event */ + mxit_parse_cmd_msgevent( session, &packet->records[2], packet->rcount - 2 ); + break; + + case CP_CMD_MOOD : + /* mood update */ + case CP_CMD_UPDATE : + /* update contact information */ + case CP_CMD_ALLOW : + /* allow subscription ack */ + case CP_CMD_DENY : + /* deny subscription ack */ + case CP_CMD_INVITE : + /* invite contact ack */ + case CP_CMD_REMOVE : + /* remove contact ack */ + case CP_CMD_TX_MSG : + /* outgoing message ack */ + case CP_CMD_STATUS : + /* presence update ack */ + case CP_CMD_GRPCHAT_CREATE : + /* create groupchat */ + case CP_CMD_GRPCHAT_INVITE : + /* groupchat invite */ + case CP_CMD_PING : + /* ping reply */ + case CP_CMD_POLL : + /* HTTP poll reply */ + case CP_CMD_EXTPROFILE_SET : + /* profile update */ + // TODO: Protocol 6.2 indicates status for each attribute, and current value. + case CP_CMD_SPLASHCLICK : + /* splash-screen clickthrough */ + case CP_CMD_MSGEVENT : + /* event message */ + break; + + default : + /* unknown packet */ + purple_debug_error( MXIT_PLUGIN_ID, "Received unknown client packet (cmd = %i)\n", packet->cmd ); + } + + return 0; +} + + +/*------------------------------------------------------------------------ + * Process an error response received from the MXit server. + * + * @param session The MXit session object + * @param packet The received packet + */ +static int process_error_response( struct MXitSession* session, struct rx_packet* packet ) +{ + char errmsg[256]; + const char* errdesc; + + /* set the error description to be shown to the user */ + if ( packet->errmsg ) + errdesc = packet->errmsg; + else + errdesc = _( "An internal MXit server error occurred." ); + + purple_debug_info( MXIT_PLUGIN_ID, "Error Reply %i:%s\n", packet->errcode, errdesc ); + + if ( packet->errcode == MXIT_ERRCODE_LOGGEDOUT ) { + /* we are not currently logged in, so we need to reconnect */ + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( errdesc ) ); + } + + /* packet command */ + switch ( packet->cmd ) { + + case CP_CMD_REGISTER : + case CP_CMD_LOGIN : + if ( packet->errcode == MXIT_ERRCODE_REDIRECT ) { + mxit_perform_redirect( session, packet->errmsg ); + return 0; + } + else { + g_snprintf( errmsg, sizeof( errmsg ), _( "Login error: %s (%i)" ), errdesc, packet->errcode ); + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, errmsg ); + return -1; + } + case CP_CMD_LOGOUT : + g_snprintf( errmsg, sizeof( errmsg ), _( "Logout error: %s (%i)" ), errdesc, packet->errcode ); + 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 ) ); + break; + case CP_CMD_RX_MSG : + mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), _( errdesc ) ); + break; + case CP_CMD_TX_MSG : + mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Sending Error" ), _( errdesc ) ); + break; + case CP_CMD_STATUS : + mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Status Error" ), _( errdesc ) ); + break; + case CP_CMD_MOOD : + mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Mood Error" ), _( errdesc ) ); + break; + case CP_CMD_KICK : + /* + * the MXit server sends this packet if we were idle for too long. + * to stop the server from closing this connection we need to resend + * the login packet. + */ + mxit_send_login( session ); + break; + case CP_CMD_INVITE : + mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Invitation Error" ), _( errdesc ) ); + break; + case CP_CMD_REMOVE : + mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Removal Error" ), _( errdesc ) ); + break; + case CP_CMD_ALLOW : + case CP_CMD_DENY : + mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Subscription Error" ), _( errdesc ) ); + break; + case CP_CMD_UPDATE : + mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Update Error" ), _( errdesc ) ); + break; + case CP_CMD_MEDIA : + mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "File Transfer Error" ), _( errdesc ) ); + break; + case CP_CMD_GRPCHAT_CREATE : + mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Cannot create MultiMx room" ), _( errdesc ) ); + break; + case CP_CMD_GRPCHAT_INVITE : + mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "MultiMx Invitation Error" ), _( errdesc ) ); + break; + case CP_CMD_EXTPROFILE_GET : + case CP_CMD_EXTPROFILE_SET : + mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Profile Error" ), _( errdesc ) ); + break; + case CP_CMD_SPLASHCLICK : + case CP_CMD_MSGEVENT : + /* ignore error */ + break; + case CP_CMD_PING : + case CP_CMD_POLL : + break; + default : + mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Error" ), _( errdesc ) ); + break; + } + + return 0; +} + + +/*======================================================================================================================== + * Low-level Packet receive + */ + +#ifdef DEBUG_PROTOCOL +/*------------------------------------------------------------------------ + * Dump a received packet structure. + * + * @param p The received packet + */ +static void dump_packet( struct rx_packet* p ) +{ + struct record* r = NULL; + struct field* f = NULL; + int i; + int j; + + purple_debug_info( MXIT_PLUGIN_ID, "PACKET DUMP: (%i records)\n", p->rcount ); + + for ( i = 0; i < p->rcount; i++ ) { + r = p->records[i]; + purple_debug_info( MXIT_PLUGIN_ID, "RECORD: (%i fields)\n", r->fcount ); + + for ( j = 0; j < r->fcount; j++ ) { + f = r->fields[j]; + purple_debug_info( MXIT_PLUGIN_ID, "\tFIELD: (len=%i) '%s' \n", f->len, f->data ); + } + } +} +#endif + + +/*------------------------------------------------------------------------ + * Free up memory used by a packet structure. + * + * @param p The received packet + */ +static void free_rx_packet( struct rx_packet* p ) +{ + struct record* r = NULL; + struct field* f = NULL; + int i; + int j; + + for ( i = 0; i < p->rcount; i++ ) { + r = p->records[i]; + + for ( j = 0; j < r->fcount; j++ ) { + g_free( f ); + } + g_free( r->fields ); + g_free( r ); + } + g_free( p->records ); +} + + +/*------------------------------------------------------------------------ + * Add a new field to a record. + * + * @param r Parent record object + * @return The newly created field + */ +static struct field* add_field( struct record* r ) +{ + struct field* field; + + field = g_new0( struct field, 1 ); + + r->fields = g_realloc( r->fields, sizeof( struct field* ) * ( r->fcount + 1 ) ); + r->fields[r->fcount] = field; + r->fcount++; + + return field; +} + + +/*------------------------------------------------------------------------ + * Add a new record to a packet. + * + * @param p The packet object + * @return The newly created record + */ +static struct record* add_record( struct rx_packet* p ) +{ + struct record* rec; + + rec = g_new0( struct record, 1 ); + + p->records = g_realloc( p->records, sizeof( struct record* ) * ( p->rcount + 1 ) ); + p->records[p->rcount] = rec; + p->rcount++; + + return rec; +} + + +/*------------------------------------------------------------------------ + * Parse the received byte stream into a proper client protocol packet. + * + * @param session The MXit session object + * @return Success (0) or Failure (!0) + */ +int mxit_parse_packet( struct MXitSession* session ) +{ + struct rx_packet packet; + struct record* rec; + struct field* field; + gboolean pbreak; + unsigned int i; + int res = 0; + +#ifdef DEBUG_PROTOCOL + purple_debug_info( MXIT_PLUGIN_ID, "Received packet (%i bytes)\n", session->rx_i ); + dump_bytes( session, session->rx_dbuf, session->rx_i ); +#endif + + i = 0; + while ( i < session->rx_i ) { + + /* create first record and field */ + rec = NULL; + field = NULL; + memset( &packet, 0x00, sizeof( struct rx_packet ) ); + rec = add_record( &packet ); + pbreak = FALSE; + + /* break up the received packet into fields and records for easy parsing */ + while ( ( i < session->rx_i ) && ( !pbreak ) ) { + + switch ( session->rx_dbuf[i] ) { + case CP_SOCK_REC_TERM : + /* new record */ + if ( packet.rcount == 1 ) { + /* packet command */ + packet.cmd = atoi( packet.records[0]->fields[0]->data ); + } + else if ( packet.rcount == 2 ) { + /* special case: binary multimedia packets should not be parsed here */ + if ( packet.cmd == CP_CMD_MEDIA ) { + /* add the chunked to new record */ + rec = add_record( &packet ); + field = add_field( rec ); + field->data = &session->rx_dbuf[i + 1]; + field->len = session->rx_i - i; + /* now skip the binary data */ + res = get_chunk_len( field->data ); + /* determine if we have more packets */ + if ( res + 6 + i < session->rx_i ) { + /* we have more than one packet in this stream */ + i += res + 6; + pbreak = TRUE; + } + else { + i = session->rx_i; + } + } + } + else if ( !field ) { + field = add_field( rec ); + field->data = &session->rx_dbuf[i]; + } + session->rx_dbuf[i] = '\0'; + rec = add_record( &packet ); + field = NULL; + + break; + case CP_FLD_TERM : + /* new field */ + session->rx_dbuf[i] = '\0'; + if ( !field ) { + field = add_field( rec ); + field->data = &session->rx_dbuf[i]; + } + field = NULL; + break; + case CP_PKT_TERM : + /* packet is done! */ + session->rx_dbuf[i] = '\0'; + pbreak = TRUE; + break; + default : + /* skip non special characters */ + if ( !field ) { + field = add_field( rec ); + field->data = &session->rx_dbuf[i]; + } + field->len++; + break; + } + + i++; + } + + if ( packet.rcount < 2 ) { + /* bad packet */ + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Invalid packet received from MXit." ) ); + free_rx_packet( &packet ); + continue; + } + + session->rx_dbuf[session->rx_i] = '\0'; + packet.errcode = atoi( packet.records[1]->fields[0]->data ); + + purple_debug_info( MXIT_PLUGIN_ID, "Packet received CMD:%i (%i)\n", packet.cmd, packet.errcode ); +#ifdef DEBUG_PROTOCOL + /* debug */ + dump_packet( &packet ); +#endif + + /* reset the out ack */ + if ( session->outack == packet.cmd ) { + /* outstanding ack received from mxit server */ + session->outack = 0; + } + + /* check packet status */ + if ( packet.errcode != MXIT_ERRCODE_SUCCESS ) { + /* error reply! */ + if ( ( packet.records[1]->fcount > 1 ) && ( packet.records[1]->fields[1]->data ) ) + packet.errmsg = packet.records[1]->fields[1]->data; + else + packet.errmsg = NULL; + + res = process_error_response( session, &packet ); + } + else { + /* success reply! */ + res = process_success_response( session, &packet ); + } + + /* free up the packet resources */ + free_rx_packet( &packet ); + } + + if ( session->outack == 0 ) + mxit_manage_queue( session ); + + return res; +} + + +/*------------------------------------------------------------------------ + * Callback when data is received from the MXit server. + * + * @param user_data The MXit session object + * @param source The file-descriptor on which data was received + * @param cond Condition which caused the callback (PURPLE_INPUT_READ) + */ +void mxit_cb_rx( gpointer user_data, gint source, PurpleInputCondition cond ) +{ + struct MXitSession* session = (struct MXitSession*) user_data; + char ch; + int res; + int len; + + if ( session->rx_state == RX_STATE_RLEN ) { + /* we are reading in the packet length */ + len = read( session->fd, &ch, 1 ); + if ( len < 0 ) { + /* connection error */ + 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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x02)" ) ); + return; + } + else { + /* byte read */ + if ( ch == CP_REC_TERM ) { + /* the end of the length record found */ + 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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x03)" ) ); + } + session->rx_state = RX_STATE_DATA; + session->rx_i = 0; + } + else { + /* still part of the packet length record */ + session->rx_lbuf[session->rx_i] = ch; + session->rx_i++; + if ( session->rx_i >= sizeof( session->rx_lbuf ) ) { + /* malformed packet length record (too long) */ + purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x04)" ) ); + return; + } + } + } + } + else if ( session->rx_state == RX_STATE_DATA ) { + /* we are reading in the packet data */ + len = read( session->fd, &session->rx_dbuf[session->rx_i], session->rx_res ); + if ( len < 0 ) { + /* connection error */ + 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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x06)" ) ); + return; + } + else { + /* data read */ + session->rx_i += len; + session->rx_res -= len; + + if ( session->rx_res == 0 ) { + /* ok, so now we have read in the whole packet */ + session->rx_state = RX_STATE_PROC; + } + } + } + + if ( session->rx_state == RX_STATE_PROC ) { + /* we have a full packet, which we now need to process */ + res = mxit_parse_packet( session ); + + if ( res == 0 ) { + /* we are still logged in */ + session->rx_state = RX_STATE_RLEN; + session->rx_res = 0; + session->rx_i = 0; + } + } +} + + +/*------------------------------------------------------------------------ + * Log the user off MXit and close the connection + * + * @param session The MXit session object + */ +void mxit_close_connection( struct MXitSession* session ) +{ + purple_debug_info( MXIT_PLUGIN_ID, "mxit_close_connection\n" ); + + if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) { + /* we are already closed */ + return; + } + else if ( session->flags & MXIT_FLAG_LOGGEDIN ) { + /* we are currently logged in so we need to send a logout packet */ + if ( !session->http ) { + mxit_send_logout( session ); + } + session->flags &= ~MXIT_FLAG_LOGGEDIN; + } + session->flags &= ~MXIT_FLAG_CONNECTED; + + /* cancel all outstanding async calls */ + purple_http_connection_set_destroy(session->async_http_reqs); + session->async_http_reqs = NULL; + + /* remove the input cb function */ + if ( session->inpa ) { + purple_input_remove( session->inpa ); + session->inpa = 0; + } + + /* remove HTTP poll timer */ + if ( session->http_timer_id > 0 ) + purple_timeout_remove( session->http_timer_id ); + + /* remove slow queue manager timer */ + if ( session->q_slow_timer_id > 0 ) + purple_timeout_remove( session->q_slow_timer_id ); + + /* remove fast queue manager timer */ + if ( session->q_fast_timer_id > 0 ) + purple_timeout_remove( session->q_fast_timer_id ); + + /* remove all groupchat rooms */ + while ( session->rooms != NULL ) { + struct multimx* multimx = (struct multimx *) session->rooms->data; + + session->rooms = g_list_remove( session->rooms, multimx ); + + free( multimx ); + } + g_list_free( session->rooms ); + session->rooms = NULL; + + /* remove all rx chats names */ + while ( session->active_chats != NULL ) { + char* chat = (char*) session->active_chats->data; + + session->active_chats = g_list_remove( session->active_chats, chat ); + + g_free( chat ); + } + g_list_free( session->active_chats ); + session->active_chats = NULL; + + /* clear the internal invites */ + while ( session->invites != NULL ) { + struct contact* contact = (struct contact*) session->invites->data; + + session->invites = g_list_remove( session->invites, contact ); + + if ( contact->msg ) + g_free( contact->msg ); + if ( contact->statusMsg ) + g_free( contact->statusMsg ); + if ( contact->profile ) + g_free( contact->profile ); + g_free( contact ); + } + g_list_free( session->invites ); + session->invites = NULL; + + /* free profile information */ + if ( session->profile ) + free( session->profile ); + + /* free custom emoticons */ + mxit_free_emoticon_cache( session ); + + /* free allocated memory */ + if ( session->uid ) + g_free( session->uid ); + g_free( session->encpwd ); + session->encpwd = NULL; + + /* flush all the commands still in the queue */ + flush_queue( session ); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/mxit/client.h Sun Aug 18 01:53:00 2013 +0530 @@ -0,0 +1,352 @@ +/* + * MXit Protocol libPurple Plugin + * + * -- MXit client protocol implementation -- + * + * Pieter Loubser <libpurple@mxit.com> + * + * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. + * <http://www.mxitlifestyle.com> + * + * 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 _MXIT_PROTO_H_ +#define _MXIT_PROTO_H_ + + +/* Client protocol constants */ +#define CP_SOCK_REC_TERM '\x00' /* socket record terminator */ +#define CP_HTTP_REC_TERM '\x26' /* http record terminator '&' */ +#define CP_FLD_TERM '\x01' /* field terminator */ +#define CP_PKT_TERM '\x02' /* packet terminator */ + + +#define CP_MAX_PACKET ( 1 * 1000 * 1000 ) /* maximum client protocol packet size (1 MB) */ +#define CP_MAX_FILESIZE ( CP_MAX_PACKET - 1000 ) /* maximum file size (reserve some space for packet headers) */ +#define MXIT_EMOTICON_SIZE 18 /* icon size for custom emoticons */ +#define CP_MAX_STATUS_MSG 250 /* maximum status message length (in characters) */ + +/* Avatars */ +#define MXIT_AVATAR_SIZE 96 /* default avatar image size 96x96 */ +#define MXIT_AVATAR_TYPE "PNG" /* request avatars in this file type (only a suggestion) */ +#define MXIT_AVATAR_BITDEPT 24 /* request avatars with this bit depth (only a suggestion) */ + +/* Protocol error codes */ +#define MXIT_ERRCODE_SUCCESS 0 +#define MXIT_ERRCODE_REDIRECT 16 +#define MXIT_ERRCODE_LOGGEDOUT 42 + +/* MXit client features */ +#define MXIT_CF_NONE 0x000000 +#define MXIT_CF_FORMS 0x000001 +#define MXIT_CF_FILE_TRANSFER 0x000002 +#define MXIT_CF_CAMERA 0x000004 +#define MXIT_CF_COMMANDS 0x000008 +#define MXIT_CF_SMS 0x000010 +#define MXIT_CF_FILE_ACCESS 0x000020 +#define MXIT_CF_MIDP2 0x000040 +#define MXIT_CF_SKINS 0x000080 +#define MXIT_CF_AUDIO 0x000100 +#define MXIT_CF_ENCRYPTION 0x000200 +#define MXIT_CF_VOICE_REC 0x000400 +#define MXIT_CF_VECTOR_GFX 0x000800 +#define MXIT_CF_IMAGES 0x001000 +#define MXIT_CF_MARKUP 0x002000 +#define MXIT_CF_VIBES 0x004000 +#define MXIT_CF_SELECT_CONTACT 0x008000 +#define MXIT_CF_CUSTOM_EMO 0x010000 +#define MXIT_CF_ALERT_PROFILES 0x020000 +#define MXIT_CF_EXT_MARKUP 0x040000 +#define MXIT_CF_PLAIN_PWD 0x080000 +#define MXIT_CF_NO_GATEWAYS 0x100000 +#define MXIT_CF_NO_AVATARS 0x200000 +#define MXIT_CF_GAMING 0x400000 +#define MXIT_CF_GAMING_UPDATE 0x800000 +#define MXIT_CF_VOICE 0x1000000 +#define MXIT_CF_VIDEO 0x2000000 +#define MXIT_CF_TOUCHSCREEN 0x4000000 +#define MXIT_CF_SVC_CONNECTION 0x8000000 +#define MXIT_CF_MXML 0x10000000 +#define MXIT_CF_TYPING_NOTIFY 0x20000000 + +/* 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 | MXIT_CF_TYPING_NOTIFY ) + + +#define MXIT_PING_INTERVAL ( 5 * 60 ) /* ping the server after X seconds of being idle (5 minutes) */ +#define MXIT_ACK_TIMEOUT ( 30 ) /* timeout after waiting X seconds for an ack from the server (30 seconds) */ +#define MXIT_TX_DELAY ( 100 ) /* delay between sending consecutive packets (100 ms) */ + +/* MXit client version */ +#define MXIT_CP_DISTCODE 'P' /* client distribution code (magic, do not touch!) */ +#define MXIT_CP_ARCH "Y" /* client architecture series (Y not for Yoda but for PC-client) */ +#define MXIT_CLIENT_ID "LP" /* client ID as specified by MXit */ +#define MXIT_CP_PLATFORM "PURPLE" /* client platform */ +#define MXIT_CP_PROTO_VESION 63 /* client protocol version */ + +/* set operating system name */ +#if defined( __APPLE__ ) +#define MXIT_CP_OS "apple" +#elif defined( _WIN32 ) +#define MXIT_CP_OS "windows" +#elif defined( __linux__ ) +#define MXIT_CP_OS "linux" +#else +#define MXIT_CP_OS "unknown" +#endif + +/* Client capabilities */ +#define MXIT_CP_CAP "utf8=true;cid="MXIT_CLIENT_ID + +/* Client settings */ +#define MAX_QUEUE_SIZE ( 1 << 5 ) /* tx queue size (32 packets) */ +#define MXIT_POPUP_WIN_NAME "MXit Notification" /* popup window name */ +#define MXIT_DEFAULT_LOCALE "en" /* default locale setting */ +#define MXIT_DEFAULT_LOC "planetpurple" /* the default location for registration */ + +/* Client protocol commands */ +#define CP_CMD_LOGIN 0x0001 /* (1) login */ +#define CP_CMD_LOGOUT 0x0002 /* (2) logout */ +#define CP_CMD_CONTACT 0x0003 /* (3) get contacts */ +#define CP_CMD_UPDATE 0x0005 /* (5) update contact information */ +#define CP_CMD_INVITE 0x0006 /* (6) subscribe to new contact */ +#define CP_CMD_PRESENCE 0x0007 /* (7) get presence */ +#define CP_CMD_REMOVE 0x0008 /* (8) remove contact */ +#define CP_CMD_RX_MSG 0x0009 /* (9) get new messages */ +#define CP_CMD_TX_MSG 0x000A /* (10) send new message */ +#define CP_CMD_REGISTER 0x000B /* (11) register */ +//#define CP_CMD_PROFILE_SET 0x000C /* (12) set profile (DEPRECATED see CP_CMD_EXTPROFILE_SET) */ +#define CP_CMD_SUGGESTCONTACTS 0x000D /* (13) suggest contacts */ +#define CP_CMD_POLL 0x0011 /* (17) poll the HTTP server for an update */ +//#define CP_CMD_PROFILE_GET 0x001A /* (26) get profile (DEPRECATED see CP_CMD_EXTPROFILE_GET) */ +#define CP_CMD_MEDIA 0x001B /* (27) get multimedia message */ +#define CP_CMD_SPLASHCLICK 0x001F /* (31) splash-screen clickthrough */ +#define CP_CMD_STATUS 0x0020 /* (32) set shown presence & status */ +#define CP_CMD_MSGEVENT 0x0023 /* (35) Raise message event */ +#define CP_CMD_GOT_MSGEVENT 0x0024 /* (36) Get message event */ +#define CP_CMD_MOOD 0x0029 /* (41) set mood */ +#define CP_CMD_KICK 0x002B /* (43) login kick */ +#define CP_CMD_GRPCHAT_CREATE 0x002C /* (44) create new groupchat */ +#define CP_CMD_GRPCHAT_INVITE 0x002D /* (45) add new groupchat member */ +#define CP_CMD_NEW_SUB 0x0033 /* (51) get new subscription */ +#define CP_CMD_ALLOW 0x0034 /* (52) allow subscription */ +#define CP_CMD_DENY 0x0037 /* (55) deny subscription */ +#define CP_CMD_EXTPROFILE_GET 0x0039 /* (57) get extended profile */ +#define CP_CMD_EXTPROFILE_SET 0x003A /* (58) set extended profile */ +#define CP_CMD_PING 0x03E8 /* (1000) ping (keepalive) */ + +/* HTTP connection */ +#define MXIT_HTTP_POLL_MIN 7 /* minimum time between HTTP polls (seconds) */ +#define MXIT_HTTP_POLL_MAX ( 10 * 60 ) /* maximum time between HTTP polls (seconds) */ + +/* receiver states */ +#define RX_STATE_RLEN 0x01 /* reading packet length section */ +#define RX_STATE_DATA 0x02 /* reading packet data section */ +#define RX_STATE_PROC 0x03 /* process read data */ + +/* message flags */ +#define CP_MSG_NOTIFY_DELIVERY 0x0002 /* request delivery notification */ +#define CP_MSG_NOTIFY_READ 0x0004 /* request read notification */ +#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 */ +#define CP_MSG_FAREWELL 0x0800 /* this is a farewell message */ + +/* redirect types */ +#define CP_REDIRECT_PERMANENT 1 /* permanent redirect */ +#define CP_REDIRECT_TEMPORARY 2 /* temporary redirect */ + +/* message tx types */ +#define CP_MSGTYPE_NORMAL 0x01 /* normal message */ +#define CP_MSGTYPE_CHAT 0x02 /* chat message */ +#define CP_MSGTYPE_HEADLINE 0x03 /* headline message */ +#define CP_MSGTYPE_ERROR 0x04 /* error message */ +#define CP_MSGTYPE_GROUPCHAT 0x05 /* groupchat message */ +#define CP_MSGTYPE_FORM 0x06 /* mxit custom form */ +#define CP_MSGTYPE_COMMAND 0x07 /* mxit command */ + +/* message event types */ +#define CP_MSGEVENT_DELIVERED 0x02 /* message was delivered */ +#define CP_MSGEVENT_DISPLAYED 0x04 /* message was viewed */ +#define CP_MSGEVENT_TYPING 0x10 /* user is typing */ +#define CP_MSGEVENT_STOPPED 0x20 /* user has stopped typing */ +#define CP_MSGEVENT_ANGRY 0x40 /* user is typing angrily */ +#define CP_MSGEVENT_ERASING 0x80 /* user is erasing text */ + +/* 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) (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) */ +#define CP_PROFILE_AVATAR "avatarid" /* Avatar ID (String) */ +#define CP_PROFILE_MODIFIED "lastmodified" /* Last-Modified timestamp */ +#define CP_PROFILE_TITLE "title" /* Title (UTF8 String) */ +#define CP_PROFILE_FIRSTNAME "firstname" /* First name (UTF8 String) */ +#define CP_PROFILE_LASTNAME "lastname" /* Last name (UTF8 String) */ +#define CP_PROFILE_EMAIL "email" /* Email address (UTF8 String) */ +#define CP_PROFILE_MOBILENR "mobilenumber" /* Mobile Number (UTF8 String) */ +#define CP_PROFILE_REGCOUNTRY "registeredcountry" /* Registered Country Code (UTF8 String) */ +#define CP_PROFILE_FLAGS "flags" /* Profile flags (Bitset) */ +#define CP_PROFILE_LASTSEEN "lastseen" /* Last-Online timestamp */ +#define CP_PROFILE_WHEREAMI "whereami" /* Where am I / Where I live */ +#define CP_PROFILE_ABOUTME "aboutme" /* About me */ +#define CP_PROFILE_RELATIONSHIP "relationship" /* Relationship Status */ + +/* extended profile field types */ +#define CP_PROFILE_TYPE_BOOL 0x02 /* boolean (0 or 1) */ +#define CP_PROFILE_TYPE_SHORT 0x04 /* short (16-bit) */ +#define CP_PROFILE_TYPE_INT 0x05 /* integer (32-bit) */ +#define CP_PROFILE_TYPE_LONG 0x06 /* long (64-bit) */ +#define CP_PROFILE_TYPE_UTF8 0x0A /* UTF8 string */ +#define CP_PROFILE_TYPE_DATE 0x0B /* date-time (ISO 8601 format) */ + +/* profile flags */ +#define CP_PROF_NOT_SEARCHABLE 0x02 /* user cannot be searched for */ +#define CP_PROF_NOT_SUGGESTABLE 0x08 /* user cannot be suggested as friend */ +#define CP_PROF_DOBLOCKED 0x40 /* date-of-birth cannot be changed */ + +/* suggestion types */ +#define CP_SUGGEST_ADDRESSBOOK 0 /* address book search */ +#define CP_SUGGEST_FRIENDS 1 /* suggested friends */ +#define CP_SUGGEST_SEARCH 2 /* free-text search */ +#define CP_SUGGEST_MXITID 3 /* MXitId search */ + +/* define this to enable protocol debugging (very verbose logging) */ +#define DEBUG_PROTOCOL + + +/* ======================================================================================= */ + +struct MXitSession; + +/*------------------------------------------*/ + +struct field { + char* data; + int len; +}; + +struct record { + struct field** fields; + int fcount; +}; + +struct rx_packet { + int cmd; + int errcode; + char* errmsg; + struct record** records; + int rcount; +}; + +struct tx_packet { + int cmd; + char header[256]; + int headerlen; + char* data; + int datalen; +}; + +/*------------------------------------------*/ + + +/* + * A received message data object + */ +struct RXMsgData { + struct MXitSession* session; /* MXit session object */ + char* from; /* the sender's name */ + time_t timestamp; /* time at which the message was sent */ + GString* msg; /* newly created message converted to libPurple formatting */ + gboolean got_img; /* flag to say if this message got any images/emoticons embedded */ + short img_count; /* the amount of images/emoticons still outstanding for the message */ + int chatid; /* multimx chatroom id */ + int flags; /* libPurple conversation flags */ + gboolean converted; /* true if the message has been completely parsed and converted to libPurple markup */ + gboolean processed; /* the message has been processed completely and should be freed up */ +}; + + + +/* + * The packet transmission queue. + */ +struct tx_queue { + struct tx_packet* packets[MAX_QUEUE_SIZE]; /* array of packet pointers */ + int count; /* number of packets queued */ + int rd_i; /* queue current read index (queue offset for reading a packet) */ + int wr_i; /* queue current write index (queue offset for adding new packet) */ +}; + + +/* ======================================================================================= */ + +void mxit_popup( int type, const char* heading, const char* message ); +void mxit_strip_domain( char* username ); +gboolean find_active_chat( const GList* chats, const char* who ); + +void mxit_cb_rx( gpointer data, gint source, PurpleInputCondition cond ); +gboolean mxit_manage_queue_slow( gpointer user_data ); +gboolean mxit_manage_queue_fast( gpointer user_data ); +gboolean mxit_manage_polling( gpointer user_data ); + +void mxit_send_register( struct MXitSession* session ); +void mxit_send_login( struct MXitSession* session ); +void mxit_send_logout( struct MXitSession* session ); +void mxit_send_ping( struct MXitSession* session ); +void mxit_send_poll( struct MXitSession* session ); + +void mxit_send_presence( struct MXitSession* session, int presence, const char* statusmsg ); +void mxit_send_mood( struct MXitSession* session, int mood ); +void mxit_send_message( struct MXitSession* session, const char* to, const char* msg, gboolean parse_markup, gboolean is_command ); + +void mxit_send_extprofile_update( struct MXitSession* session, const char* password, unsigned int nr_attrib, const char* attributes ); +void mxit_send_extprofile_request( struct MXitSession* session, const char* username, unsigned int nr_attrib, const char* attribute[] ); + +void mxit_send_suggest_friends( struct MXitSession* session, int max, unsigned int nr_attrib, const char* attribute[] ); +void mxit_send_suggest_search( struct MXitSession* session, int max, const char* text, unsigned int nr_attrib, const char* attribute[] ); + +void mxit_send_invite( struct MXitSession* session, const char* username, gboolean mxitid, const char* alias, const char* groupname, const char* message ); +void mxit_send_remove( struct MXitSession* session, const char* username ); +void mxit_send_allow_sub( struct MXitSession* session, const char* username, const char* alias ); +void mxit_send_deny_sub( struct MXitSession* session, const char* username, const char* reason ); +void mxit_send_update_contact( struct MXitSession* session, const char* username, const char* alias, const char* groupname ); +void mxit_send_splashclick( struct MXitSession* session, const char* splashid ); +void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event); + +void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen ); +void mxit_send_file_reject( struct MXitSession* session, const char* fileid ); +void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int filesize, int offset ); +void mxit_send_file_received( struct MXitSession* session, const char* fileid, short status ); +void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen ); +void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const char* avatarId ); + +void mxit_send_groupchat_create( struct MXitSession* session, const char* groupname, int nr_usernames, const char* usernames[] ); +void mxit_send_groupchat_invite( struct MXitSession* session, const char* roomid, int nr_usernames, const char* usernames[] ); + +int mxit_parse_packet( struct MXitSession* session ); +void dump_bytes( struct MXitSession* session, const char* buf, int len ); +void mxit_close_connection( struct MXitSession* session ); +gint64 mxit_now_milli( void ); + + +#endif /* _MXIT_PROTO_H_ */ +
--- a/libpurple/protocols/mxit/filexfer.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/mxit/filexfer.c Sun Aug 18 01:53:00 2013 +0530 @@ -26,7 +26,7 @@ #include "internal.h" #include "debug.h" -#include "protocol.h" +#include "client.h" #include "mxit.h" #include "chunk.h" #include "filexfer.h"
--- a/libpurple/protocols/mxit/formcmds.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/mxit/formcmds.c Sun Aug 18 01:53:00 2013 +0530 @@ -28,7 +28,7 @@ #include "debug.h" #include "http.h" -#include "protocol.h" +#include "client.h" #include "mxit.h" #include "markup.h" #include "formcmds.h"
--- a/libpurple/protocols/mxit/formcmds.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/mxit/formcmds.h Sun Aug 18 01:53:00 2013 +0530 @@ -26,7 +26,7 @@ #ifndef _MXIT_FORMCMDS_H_ #define _MXIT_FORMCMDS_H_ -#include "protocol.h" +#include "client.h" int mxit_parse_command(struct RXMsgData* mx, char* message);
--- a/libpurple/protocols/mxit/login.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/mxit/login.c Sun Aug 18 01:53:00 2013 +0530 @@ -29,7 +29,7 @@ #include "request.h" #include "version.h" -#include "protocol.h" +#include "client.h" #include "mxit.h" #include "cipher.h" #include "login.h"
--- a/libpurple/protocols/mxit/markup.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/mxit/markup.c Sun Aug 18 01:53:00 2013 +0530 @@ -27,7 +27,7 @@ #include "debug.h" #include "http.h" -#include "protocol.h" +#include "client.h" #include "mxit.h" #include "markup.h" #include "chunk.h"
--- a/libpurple/protocols/mxit/multimx.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/mxit/multimx.c Sun Aug 18 01:53:00 2013 +0530 @@ -26,7 +26,7 @@ #include "internal.h" #include "debug.h" -#include "protocol.h" +#include "client.h" #include "mxit.h" #include "multimx.h" #include "markup.h"
--- a/libpurple/protocols/mxit/mxit.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/mxit/mxit.c Sun Aug 18 01:53:00 2013 +0530 @@ -26,10 +26,11 @@ #include "internal.h" #include "debug.h" #include "accountopt.h" +#include "plugins.h" #include "version.h" #include "mxit.h" -#include "protocol.h" +#include "client.h" #include "login.h" #include "roster.h" #include "chunk.h" @@ -716,8 +717,10 @@ /*========================================================================================================================*/ -static PurplePluginProtocolInfo proto_info = { - sizeof( PurplePluginProtocolInfo ), /* struct_size */ +static PurpleProtocol proto_info = { + MXIT_PLUGIN_ID, /* protocol id (must be unique) */ + MXIT_PLUGIN_NAME, /* protocol name (this will be displayed in the UI) */ + sizeof( PurpleProtocol ), /* struct_size */ OPT_PROTO_REGISTER_NOSCREENNAME | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE | OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE, /* options */ NULL, /* user_splits */ NULL, /* protocol_options */ @@ -728,6 +731,7 @@ CP_MAX_FILESIZE, /* max filesize */ PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY /* scaling rules */ }, + mxit_get_actions, /* get_actions [actions.c] */ mxit_list_icon, /* list_icon */ mxit_list_emblem, /* list_emblem */ mxit_status_text, /* status_text */ @@ -782,7 +786,7 @@ mxit_xfer_tx, /* send_file [filexfer.c */ mxit_xfer_new, /* new_xfer [filexfer.c] */ mxit_offline_message, /* offline_message */ - NULL, /* whiteboard_prpl_ops */ + NULL, /* whiteboard_protocol_ops */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ NULL, /* unregister_user */ @@ -797,48 +801,37 @@ }; -static PurplePluginInfo plugin_info = { - PURPLE_PLUGIN_MAGIC, /* purple magic, this must always be PURPLE_PLUGIN_MAGIC */ - PURPLE_MAJOR_VERSION, /* libpurple version */ - PURPLE_MINOR_VERSION, /* libpurple version */ - PURPLE_PLUGIN_PROTOCOL, /* plugin type (connecting to another network) */ - NULL, /* UI requirement (NULL for core plugin) */ - 0, /* plugin flags (zero is default) */ - NULL, /* plugin dependencies (set this value to NULL no matter what) */ - PURPLE_PRIORITY_DEFAULT, /* libpurple priority */ - - MXIT_PLUGIN_ID, /* plugin id (must be unique) */ - MXIT_PLUGIN_NAME, /* plugin name (this will be displayed in the UI) */ - DISPLAY_VERSION, /* version of the plugin */ - - MXIT_PLUGIN_SUMMARY, /* short summary of the plugin */ - MXIT_PLUGIN_DESC, /* description of the plugin (can be long) */ - MXIT_PLUGIN_EMAIL, /* plugin author name and email address */ - MXIT_PLUGIN_WWW, /* plugin website (to find new versions and reporting of bugs) */ - - NULL, /* function pointer for loading the plugin */ - NULL, /* function pointer for unloading the plugin */ - NULL, /* function pointer for destroying the plugin */ - - NULL, /* pointer to an UI-specific struct */ - &proto_info, /* pointer to either a PurplePluginLoaderInfo or PurplePluginProtocolInfo struct */ - NULL, /* pointer to a PurplePluginUiInfo struct */ - mxit_actions, /* function pointer where you can define plugin-actions */ - - /* padding */ - NULL, /* pointer reserved for future use */ - NULL, /* pointer reserved for future use */ - NULL, /* pointer reserved for future use */ - NULL /* pointer reserved for future use */ -}; +/*------------------------------------------------------------------------ + * Querying the MXit plugin. + * + * @param error Query error (if any) + */ +static PurplePluginInfo *plugin_query( GError **error ) +{ + return purple_plugin_info_new( + "id", MXIT_PLUGIN_ID, /* plugin id (must be unique) */ + "name", MXIT_PLUGIN_NAME, /* plugin name (this will be displayed in the UI) */ + "version", DISPLAY_VERSION, /* version of the plugin */ + "category", MXIT_PLUGIN_CATEGORY, /* category of the plugin */ + "summary", MXIT_PLUGIN_SUMMARY, /* short summary of the plugin */ + "description", MXIT_PLUGIN_DESC, /* description of the plugin (can be long) */ + "author", MXIT_PLUGIN_AUTHOR, /* plugin author name and email address */ + "website", MXIT_PLUGIN_WWW, /* plugin website (to find new versions and reporting of bugs) */ + "abi-version", PURPLE_ABI_VERSION, /* ABI version required by the plugin */ + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); +} /*------------------------------------------------------------------------ - * Initialising the MXit plugin. + * Loading the MXit plugin. * * @param plugin The plugin object + * @param error Load error (if any) */ -static void init_plugin( PurplePlugin* plugin ) +static gboolean plugin_load( PurplePlugin* plugin, GError **error ) { PurpleAccountOption* option; @@ -853,7 +846,25 @@ option = purple_account_option_bool_new( _( "Enable splash-screen popup" ), MXIT_CONFIG_SPLASHPOPUP, FALSE ); proto_info.protocol_options = g_list_append( proto_info.protocol_options, option ); + + purple_protocols_add( &proto_info ); + + return TRUE; } -PURPLE_INIT_PLUGIN( mxit, init_plugin, plugin_info ); +/*------------------------------------------------------------------------ + * Unloading the MXit plugin. + * + * @param plugin The plugin object + * @param error Unload error (if any) + */ +static gboolean plugin_unload( PurplePlugin* plugin, GError **error ) +{ + purple_protocols_remove( &proto_info ); + + return TRUE; +} + +PURPLE_PLUGIN_INIT( mxit, plugin_query, plugin_load, plugin_unload ); +
--- a/libpurple/protocols/mxit/mxit.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/mxit/mxit.h Sun Aug 18 01:53:00 2013 +0530 @@ -57,14 +57,15 @@ #endif -#include "protocol.h" +#include "client.h" #include "profile.h" /* Plugin details */ #define MXIT_PLUGIN_ID "prpl-loubserp-mxit" #define MXIT_PLUGIN_NAME "MXit" -#define MXIT_PLUGIN_EMAIL "Pieter Loubser <libpurple@mxit.com>" +#define MXIT_PLUGIN_CATEGORY "Protocol" +#define MXIT_PLUGIN_AUTHOR "Pieter Loubser <libpurple@mxit.com>" #define MXIT_PLUGIN_WWW "http://www.mxit.com" #define MXIT_PLUGIN_SUMMARY "MXit Protocol Plugin" #define MXIT_PLUGIN_DESC "MXit"
--- a/libpurple/protocols/mxit/protocol.c Sun Aug 18 01:52:32 2013 +0530 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2953 +0,0 @@ -/* - * MXit Protocol libPurple Plugin - * - * -- MXit client protocol implementation -- - * - * Pieter Loubser <libpurple@mxit.com> - * - * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. - * <http://www.mxitlifestyle.com> - * - * 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 "debug.h" -#include "version.h" - -#include "protocol.h" -#include "mxit.h" -#include "roster.h" -#include "chunk.h" -#include "filexfer.h" -#include "markup.h" -#include "multimx.h" -#include "splashscreen.h" -#include "login.h" -#include "formcmds.h" -#include "http.h" -#include "cipher.h" -#include "voicevideo.h" - - -#define MXIT_MS_OFFSET 3 - -/* configure the right record terminator char to use */ -#define CP_REC_TERM ( ( session->http ) ? CP_HTTP_REC_TERM : CP_SOCK_REC_TERM ) - - -/*------------------------------------------------------------------------ - * return the current timestamp in milliseconds - */ -gint64 mxit_now_milli( void ) -{ - GTimeVal now; - - g_get_current_time( &now ); - - return ( ( now.tv_sec * 1000 ) + ( now.tv_usec / 1000 ) ); -} - - -/*------------------------------------------------------------------------ - * Display a notification popup message to the user. - * - * @param type The type of notification: - * - info: PURPLE_NOTIFY_MSG_INFO - * - warning: PURPLE_NOTIFY_MSG_WARNING - * - error: PURPLE_NOTIFY_MSG_ERROR - * @param heading Heading text - * @param message Message text - */ -void mxit_popup( int type, const char* heading, const char* message ) -{ - /* (reference: "libpurple/notify.h") */ - purple_notify_message( NULL, type, _( MXIT_POPUP_WIN_NAME ), heading, message, NULL, NULL ); -} - - -/*------------------------------------------------------------------------ - * For compatibility with legacy clients, all usernames are sent from MXit with a domain - * appended. For MXit contacts, this domain is set to "@m". This function strips - * those fake domains. - * - * @param username The username of the contact - */ -void mxit_strip_domain( char* username ) -{ - if ( g_str_has_suffix( username, "@m" ) ) - username[ strlen( username ) - 2 ] = '\0'; -} - - -/*------------------------------------------------------------------------ - * Dump a byte buffer to the console for debugging purposes. - * - * @param buf The data - * @param len The data length - */ -void dump_bytes( struct MXitSession* session, const char* buf, int len ) -{ - char* msg = g_malloc0( len + 1 ); - int i; - - for ( i = 0; i < len; i++ ) { - char ch = buf[i]; - - if ( ch == CP_REC_TERM ) /* record terminator */ - msg[i] = '!'; - else if ( ch == CP_FLD_TERM ) /* field terminator */ - msg[i] = '^'; - else if ( ch == CP_PKT_TERM ) /* packet terminator */ - msg[i] = '@'; - else if ( ( ch < 0x20 ) || ( ch > 0x7E ) ) /* non-printable character */ - msg[i] = '_'; - else - msg[i] = ch; - } - - purple_debug_info( MXIT_PLUGIN_ID, "DUMP: '%s'\n", msg ); - - g_free( msg ); -} - - -/*------------------------------------------------------------------------ - * Determine if we have an active chat with a specific contact - * - * @param session The MXit session object - * @param who The contact name - * @return Return true if we have an active chat with the contact - */ -gboolean find_active_chat( const GList* chats, const char* who ) -{ - const GList* list = chats; - const char* chat = NULL; - - while ( list ) { - chat = (const char*) list->data; - - if ( strcmp( chat, who ) == 0 ) - return TRUE; - - list = g_list_next( list ); - } - - return FALSE; -} - - -/*======================================================================================================================== - * Low-level Packet transmission - */ - -/*------------------------------------------------------------------------ - * Remove next packet from transmission queue. - * - * @param session The MXit session object - * @return The next packet for transmission (or NULL) - */ -static struct tx_packet* pop_tx_packet( struct MXitSession* session ) -{ - struct tx_packet* packet = NULL; - - if ( session->queue.count > 0 ) { - /* dequeue the next packet */ - packet = session->queue.packets[session->queue.rd_i]; - session->queue.packets[session->queue.rd_i] = NULL; - session->queue.rd_i = ( session->queue.rd_i + 1 ) % MAX_QUEUE_SIZE; - session->queue.count--; - } - - return packet; -} - - -/*------------------------------------------------------------------------ - * Add packet to transmission queue. - * - * @param session The MXit session object - * @param packet The packet to transmit - * @return Return TRUE if packet was enqueue, or FALSE if queue is full. - */ -static gboolean push_tx_packet( struct MXitSession* session, struct tx_packet* packet ) -{ - if ( session->queue.count < MAX_QUEUE_SIZE ) { - /* enqueue packet */ - session->queue.packets[session->queue.wr_i] = packet; - session->queue.wr_i = ( session->queue.wr_i + 1 ) % MAX_QUEUE_SIZE; - session->queue.count++; - return TRUE; - } - else - return FALSE; /* queue is full */ -} - - -/*------------------------------------------------------------------------ - * Deallocate transmission packet. - * - * @param packet The packet to deallocate. - */ -static void free_tx_packet( struct tx_packet* packet ) -{ - g_free( packet->data ); - g_free( packet ); - packet = NULL; -} - - -/*------------------------------------------------------------------------ - * Flush all the packets from the tx queue and release the resources. - * - * @param session The MXit session object - */ -static void flush_queue( struct MXitSession* session ) -{ - struct tx_packet* packet; - - purple_debug_info( MXIT_PLUGIN_ID, "flushing the tx queue\n" ); - - while ( (packet = pop_tx_packet( session ) ) != NULL ) - free_tx_packet( packet ); -} - - -/*------------------------------------------------------------------------ - * TX Step 3: Write the packet data to the TCP connection. - * - * @param fd The file descriptor - * @param pktdata The packet data - * @param pktlen The length of the packet data - * @return Return -1 on error, otherwise 0 - */ -static int mxit_write_sock_packet( int fd, const char* pktdata, int pktlen ) -{ - int written; - int res; - - written = 0; - while ( written < pktlen ) { - res = write( fd, &pktdata[written], pktlen - written ); - if ( res <= 0 ) { - /* error on socket */ - if ( errno == EAGAIN ) - continue; - - purple_debug_error( MXIT_PLUGIN_ID, "Error while writing packet to MXit server (%i)\n", res ); - return -1; - } - written += res; - } - - return 0; -} - - -/** - * Callback called for handling a HTTP GET response - * - * @param http_conn http api object (see http.h) - * @param response http api object (see http.h) - * @param _session The MXit session object - */ -static void -mxit_cb_http_rx(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, - gpointer _session) -{ - struct MXitSession *session = _session; - const gchar *got_data; - size_t got_len; - - if (!purple_http_response_is_successful(response)) { - purple_debug_error(MXIT_PLUGIN_ID, "HTTP response error (%s)\n", - purple_http_response_get_error(response)); - return; - } - - /* convert the HTTP result */ - got_data = purple_http_response_get_data(response, &got_len); - memcpy(session->rx_dbuf, got_data, got_len); - session->rx_i = got_len; - - mxit_parse_packet(session); -} - - -/** - * TX Step 3: Write the packet data to the HTTP connection (GET style). - * - * @param session The MXit session object - * @param packet The packet data - */ -static void -mxit_write_http_get(struct MXitSession* session, struct tx_packet* packet) -{ - PurpleHttpRequest *req; - char *part = NULL; - - if (packet->datalen > 0) { - char *tmp; - - tmp = g_strndup(packet->data, packet->datalen); - part = g_strdup(purple_url_encode(tmp)); - g_free(tmp); - } - - req = purple_http_request_new(NULL); - purple_http_request_set_url_printf(req, "%s?%s%s", session->http_server, - purple_url_encode(packet->header), part ? part : ""); - purple_http_request_header_set(req, "User-Agent", MXIT_HTTP_USERAGENT); - purple_http_connection_set_add(session->async_http_reqs, - purple_http_request(session->con, req, mxit_cb_http_rx, - session)); - purple_http_request_unref(req); - - g_free(part); -} - - -/** - * TX Step 3: Write the packet data to the HTTP connection (POST style). - * - * @param session The MXit session object - * @param packet The packet data - */ -static void -mxit_write_http_post(struct MXitSession* session, struct tx_packet* packet) -{ - PurpleHttpRequest *req; - - /* strip off the last '&' from the header */ - packet->header[packet->headerlen - 1] = '\0'; - packet->headerlen--; - - req = purple_http_request_new(NULL); - purple_http_request_set_url_printf(req, "%s?%s", session->http_server, - purple_url_encode(packet->header)); - purple_http_request_set_method(req, "POST"); - purple_http_request_header_set(req, "User-Agent", MXIT_HTTP_USERAGENT); - purple_http_request_header_set(req, "Content-Type", - "application/octet-stream"); - purple_http_request_set_contents(req, packet->data + MXIT_MS_OFFSET, - packet->datalen - MXIT_MS_OFFSET); - purple_http_connection_set_add(session->async_http_reqs, - purple_http_request(session->con, req, mxit_cb_http_rx, - session)); - purple_http_request_unref(req); -} - - -/*------------------------------------------------------------------------ - * TX Step 2: Handle the transmission of the packet to the MXit server. - * - * @param session The MXit session object - * @param packet The packet to transmit - */ -static void mxit_send_packet( struct MXitSession* session, struct tx_packet* packet ) -{ - int res; - - if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) { - /* we are not connected so ignore all packets to be send */ - purple_debug_error( MXIT_PLUGIN_ID, "Dropping TX packet (we are not connected)\n" ); - return; - } - - purple_debug_info( MXIT_PLUGIN_ID, "Packet send CMD:%i (%i)\n", packet->cmd, packet->headerlen + packet->datalen ); -#ifdef DEBUG_PROTOCOL - dump_bytes( session, packet->header, packet->headerlen ); - dump_bytes( session, packet->data, packet->datalen ); -#endif - - if ( !session->http ) { - /* socket connection */ - char data[packet->datalen + packet->headerlen]; - int datalen; - - /* create raw data buffer */ - memcpy( data, packet->header, packet->headerlen ); - memcpy( data + packet->headerlen, packet->data, packet->datalen ); - datalen = packet->headerlen + packet->datalen; - - 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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "We have lost the connection to MXit. Please reconnect." ) ); - } - } - else { - /* http connection */ - - if ( packet->cmd == CP_CMD_MEDIA ) { - /* multimedia packets must be send with a HTTP POST */ - mxit_write_http_post( session, packet ); - } - else { - mxit_write_http_get( session, packet ); - } - } - - /* update the timestamp of the last-transmitted packet */ - session->last_tx = mxit_now_milli(); - - /* - * we need to remember that we are still waiting for the ACK from - * the server on this request - */ - session->outack = packet->cmd; - - /* free up the packet resources */ - free_tx_packet( packet ); -} - - -/*------------------------------------------------------------------------ - * TX Step 1: Create a new Tx packet and queue it for sending. - * - * @param session The MXit session object - * @param data The packet data (payload) - * @param datalen The length of the packet data - * @param cmd The MXit command for this packet - */ -static void mxit_queue_packet( struct MXitSession* session, const char* data, int datalen, int cmd ) -{ - struct tx_packet* packet; - char header[256]; - int hlen; - - /* create a packet for sending */ - packet = g_new0( struct tx_packet, 1 ); - packet->data = g_malloc0( datalen ); - packet->cmd = cmd; - packet->headerlen = 0; - - /* create generic packet header */ - hlen = g_snprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc ), CP_REC_TERM ); /* client mxitid */ - - if ( session->http ) { - /* http connection only */ - hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "s=" ); - if ( session->http_sesid > 0 ) { - hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_sesid, CP_FLD_TERM ); /* http session id */ - } - session->http_seqno++; - hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_seqno, CP_REC_TERM ); /* http request sequence id */ - } - - hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "cm=%i%c", cmd, CP_REC_TERM ); /* packet command */ - - if ( !session->http ) { - /* socket connection only */ - packet->headerlen = g_snprintf( packet->header, sizeof( packet->header ), "ln=%i%c", ( datalen + hlen ), CP_REC_TERM ); /* packet length */ - } - - /* copy the header to packet */ - memcpy( packet->header + packet->headerlen, header, hlen ); - packet->headerlen += hlen; - - /* copy payload to packet */ - if ( datalen > 0 ) - memcpy( packet->data, data, datalen ); - packet->datalen = datalen; - - - /* shortcut */ - if ( ( session->queue.count == 0 ) && ( session->outack == 0 ) ) { - /* the queue is empty and there are no outstanding acks so we can write it directly */ - mxit_send_packet( session, packet ); - } - else { - /* we need to queue this packet */ - - if ( ( packet->cmd == CP_CMD_PING ) || ( packet->cmd == CP_CMD_POLL ) ) { - /* we do NOT queue HTTP poll nor socket ping packets */ - free_tx_packet( packet ); - return; - } - - purple_debug_info( MXIT_PLUGIN_ID, "queueing packet for later sending cmd=%i\n", cmd ); - if ( !push_tx_packet( session, packet ) ) { - /* packet could not be queued for transmission */ - mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Message Send Error" ), _( "Unable to process your request at this time" ) ); - free_tx_packet( packet ); - } - } -} - - -/*------------------------------------------------------------------------ - * Manage the packet send queue (send next packet, timeout's, etc). - * - * @param session The MXit session object - */ -static void mxit_manage_queue( struct MXitSession* session ) -{ - struct tx_packet* packet = NULL; - gint64 now = mxit_now_milli(); - - if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) { - /* we are not connected, so ignore the queue */ - return; - } - else if ( session->outack > 0 ) { - /* we are still waiting for an outstanding ACK from the MXit server */ - 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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Timeout while waiting for a response from the MXit server." ) ); - } - return; - } - - /* - * the mxit server has flood detection and it prevents you from sending messages to fast. - * this is a self defense mechanism, a very annoying feature. so the client must ensure that - * it does not send messages too fast otherwise mxit will ignore the user for 30 seconds. - * this is what we are trying to avoid here.. - */ - if ( session->q_fast_timer_id == 0 ) { - /* the fast timer has not been set yet */ - if ( session->last_tx > ( now - MXIT_TX_DELAY ) ) { - /* we need to wait a little before sending the next packet, so schedule a wakeup call */ - gint64 tdiff = now - ( session->last_tx ); - guint delay = ( MXIT_TX_DELAY - tdiff ) + 9; - if ( delay <= 0 ) - delay = MXIT_TX_DELAY; - session->q_fast_timer_id = purple_timeout_add( delay, mxit_manage_queue_fast, session ); - } - else { - /* get the next packet from the queue to send */ - packet = pop_tx_packet( session ); - if ( packet != NULL ) { - /* there was a packet waiting to be sent to the server, now is the time to do something about it */ - - /* send the packet to MXit server */ - mxit_send_packet( session, packet ); - } - } - } -} - - -/*------------------------------------------------------------------------ - * Slow callback to manage the packet send queue. - * - * @param session The MXit session object - */ -gboolean mxit_manage_queue_slow( gpointer user_data ) -{ - struct MXitSession* session = (struct MXitSession*) user_data; - - mxit_manage_queue( session ); - - /* continue running */ - return TRUE; -} - - -/*------------------------------------------------------------------------ - * Fast callback to manage the packet send queue. - * - * @param session The MXit session object - */ -gboolean mxit_manage_queue_fast( gpointer user_data ) -{ - struct MXitSession* session = (struct MXitSession*) user_data; - - session->q_fast_timer_id = 0; - mxit_manage_queue( session ); - - /* stop running */ - return FALSE; -} - - -/*------------------------------------------------------------------------ - * Callback to manage HTTP server polling (HTTP connections ONLY) - * - * @param session The MXit session object - */ -gboolean mxit_manage_polling( gpointer user_data ) -{ - struct MXitSession* session = (struct MXitSession*) user_data; - gboolean poll = FALSE; - gint64 now = mxit_now_milli(); - gint64 rxdiff; - - if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) { - /* we only poll if we are actually logged in */ - return TRUE; - } - - /* calculate the time differences */ - rxdiff = now - session->last_rx; - - if ( rxdiff < MXIT_HTTP_POLL_MIN ) { - /* we received some reply a few moments ago, so reset the poll interval */ - session->http_interval = MXIT_HTTP_POLL_MIN; - } - else if ( session->http_last_poll < ( now - session->http_interval ) ) { - /* time to poll again */ - poll = TRUE; - - /* back-off some more with the polling */ - session->http_interval = session->http_interval + ( session->http_interval / 2 ); - if ( session->http_interval > MXIT_HTTP_POLL_MAX ) - session->http_interval = MXIT_HTTP_POLL_MAX; - } - - /* debugging */ - //purple_debug_info( MXIT_PLUGIN_ID, "POLL TIMER: %i (%i)\n", session->http_interval, rxdiff ); - - if ( poll ) { - /* send poll request */ - session->http_last_poll = mxit_now_milli(); - mxit_send_poll( session ); - } - - return TRUE; -} - - -/*======================================================================================================================== - * Send MXit operations. - */ - -/*------------------------------------------------------------------------ - * Send a ping/keepalive packet to MXit server. - * - * @param session The MXit session object - */ -void mxit_send_ping( struct MXitSession* session ) -{ - /* queue packet for transmission */ - mxit_queue_packet( session, NULL, 0, CP_CMD_PING ); -} - - -/*------------------------------------------------------------------------ - * Send a poll request to the HTTP server (HTTP connections ONLY). - * - * @param session The MXit session object - */ -void mxit_send_poll( struct MXitSession* session ) -{ - /* queue packet for transmission */ - mxit_queue_packet( session, NULL, 0, CP_CMD_POLL ); -} - - -/*------------------------------------------------------------------------ - * Send a logout packet to the MXit server. - * - * @param session The MXit session object - */ -void mxit_send_logout( struct MXitSession* session ) -{ - /* queue packet for transmission */ - mxit_queue_packet( session, NULL, 0, CP_CMD_LOGOUT ); -} - - -/*------------------------------------------------------------------------ - * Send a register packet to the MXit server. - * - * @param session The MXit session object - */ -void mxit_send_register( struct MXitSession* session ) -{ - struct MXitProfile* profile = session->profile; - const char* locale; - char data[CP_MAX_PACKET]; - int datalen; - char* clientVersion; - unsigned int features = MXIT_CP_FEATURES; - - 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() ) - features |= MXIT_CF_VOICE; - - /* generate client version string (eg, P-2.7.10-Y-PURPLE) */ - clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM ); - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), - "ms=%s%c%s%c%i%c%s%c" /* "ms"=password\1version\1maxreplyLen\1name\1 */ - "%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, - 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 - ); - - /* queue packet for transmission */ - mxit_queue_packet( session, data, datalen, CP_CMD_REGISTER ); - - g_free( clientVersion ); -} - - -/*------------------------------------------------------------------------ - * Send a login packet to the MXit server. - * - * @param session The MXit session object - */ -void mxit_send_login( struct MXitSession* session ) -{ - const char* splashId; - const char* locale; - char data[CP_MAX_PACKET]; - int datalen; - char* clientVersion; - unsigned int features = MXIT_CP_FEATURES; - - 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() ) - features |= MXIT_CF_VOICE; - - /* generate client version string (eg, P-2.7.10-Y-PURPLE) */ - clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM ); - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), - "ms=%s%c%s%c%i%c" /* "ms"=password\1version\1getContacts\1 */ - "%s%c%s%c%i%c" /* capabilities\1dc\1features\1 */ - "%s%c%s%c" /* dialingcode\1locale\1 */ - "%i%c%i%c%i", /* maxReplyLen\1protocolVer\1lastRosterUpdate */ - 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 - ); - - /* include "custom resource" information */ - splashId = splash_current( session ); - if ( splashId != NULL ) - datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%ccr=%s", CP_REC_TERM, splashId ); - - /* queue packet for transmission */ - mxit_queue_packet( session, data, datalen, CP_CMD_LOGIN ); - - g_free( clientVersion ); -} - - -/*------------------------------------------------------------------------ - * Send a chat message packet to the MXit server. - * - * @param session The MXit session object - * @param to The username of the recipient - * @param msg The message text - */ -void mxit_send_message( struct MXitSession* session, const char* to, const char* msg, gboolean parse_markup, gboolean is_command ) -{ - char data[CP_MAX_PACKET]; - char* markuped_msg; - int datalen; - int msgtype = ( is_command ? CP_MSGTYPE_COMMAND : CP_MSGTYPE_NORMAL ); - - /* first we need to convert the markup from libPurple to MXit format */ - if ( parse_markup ) - markuped_msg = mxit_convert_markup_tx( msg, &msgtype ); - else - markuped_msg = g_strdup( msg ); - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), - "ms=%s%c%s%c%i%c%i", /* "ms"=jid\1msg\1type\1flags */ - to, CP_FLD_TERM, markuped_msg, CP_FLD_TERM, msgtype, CP_FLD_TERM, CP_MSG_MARKUP | CP_MSG_EMOTICON - ); - - /* free the resources */ - g_free( markuped_msg ); - - /* queue packet for transmission */ - mxit_queue_packet( session, data, datalen, CP_CMD_TX_MSG ); -} - - -/*------------------------------------------------------------------------ - * Send a extended profile request packet to the MXit server. - * - * @param session The MXit session object - * @param username Username who's profile is being requested (NULL = our own) - * @param nr_attribs Number of attributes being requested - * @param attribute The names of the attributes - */ -void mxit_send_extprofile_request( struct MXitSession* session, const char* username, unsigned int nr_attrib, const char* attribute[] ) -{ - char data[CP_MAX_PACKET]; - int datalen; - unsigned int i; - - datalen = g_snprintf( data, sizeof( data ), - "ms=%s%c%i", /* "ms="mxitid\1nr_attributes */ - ( username ? username : "" ), CP_FLD_TERM, nr_attrib - ); - - /* add attributes */ - for ( i = 0; i < nr_attrib; i++ ) - datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] ); - - /* queue packet for transmission */ - mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_GET ); -} - - -/*------------------------------------------------------------------------ - * Send an update profile packet to the MXit server. - * - * @param session The MXit session object - * @param password The new password to be used for logging in (optional) - * @param nr_attrib The number of attributes - * @param attributes String containing the attribute-name, attribute-type and value (seperated by '\01') - */ -void mxit_send_extprofile_update( struct MXitSession* session, const char* password, unsigned int nr_attrib, const char* attributes ) -{ - char data[CP_MAX_PACKET]; - gchar** parts = NULL; - int datalen; - unsigned int i; - - if ( attributes ) - parts = g_strsplit( attributes, "\01", 1 + ( nr_attrib * 3 ) ); - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), - "ms=%s%c%i", /* "ms"=password\1nr_attibutes */ - ( password ) ? password : "", CP_FLD_TERM, nr_attrib - ); - - /* add attributes */ - for ( i = 1; i < nr_attrib * 3; i+=3 ) { - if ( parts == NULL || parts[i] == NULL || parts[i + 1] == NULL || parts[i + 2] == NULL ) { - purple_debug_error( MXIT_PLUGIN_ID, "Invalid profile update attributes = '%s' - nbr=%u\n", attributes, nr_attrib ); - g_strfreev( parts ); - return; - } - datalen += g_snprintf( data + datalen, sizeof( 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 */ - mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_SET ); - - /* freeup the memory */ - g_strfreev( parts ); -} - - -/*------------------------------------------------------------------------ - * Send packet to request list of suggested friends. - * - * @param session The MXit session object - * @param max Maximum number of results to return - * @param nr_attribs Number of attributes being requested - * @param attribute The names of the attributes - */ -void mxit_send_suggest_friends( struct MXitSession* session, int max, unsigned int nr_attrib, const char* attribute[] ) -{ - char data[CP_MAX_PACKET]; - int datalen; - unsigned int i; - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), - "ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */ - CP_SUGGEST_FRIENDS, CP_FLD_TERM, "", CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib ); - - /* add attributes */ - for ( i = 0; i < nr_attrib; i++ ) - datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] ); - - /* queue packet for transmission */ - mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS ); -} - - -/*------------------------------------------------------------------------ - * Send packet to perform a search for users. - * - * @param session The MXit session object - * @param max Maximum number of results to return - * @param text The search text - * @param nr_attribs Number of attributes being requested - * @param attribute The names of the attributes - */ -void mxit_send_suggest_search( struct MXitSession* session, int max, const char* text, unsigned int nr_attrib, const char* attribute[] ) -{ - char data[CP_MAX_PACKET]; - int datalen; - unsigned int i; - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), - "ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */ - CP_SUGGEST_SEARCH, CP_FLD_TERM, text, CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib ); - - /* add attributes */ - for ( i = 0; i < nr_attrib; i++ ) - datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] ); - - /* queue packet for transmission */ - mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS ); -} - - -/*------------------------------------------------------------------------ - * Send a presence update packet to the MXit server. - * - * @param session The MXit session object - * @param presence The presence (as per MXit types) - * @param statusmsg The status message (can be NULL) - */ -void mxit_send_presence( struct MXitSession* session, int presence, const char* statusmsg ) -{ - char data[CP_MAX_PACKET]; - int datalen; - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), - "ms=%i%c", /* "ms"=show\1status */ - presence, CP_FLD_TERM - ); - - /* append status message (if one is set) */ - if ( statusmsg ) - datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%s", statusmsg ); - - /* queue packet for transmission */ - mxit_queue_packet( session, data, datalen, CP_CMD_STATUS ); -} - - -/*------------------------------------------------------------------------ - * Send a mood update packet to the MXit server. - * - * @param session The MXit session object - * @param mood The mood (as per MXit types) - */ -void mxit_send_mood( struct MXitSession* session, int mood ) -{ - char data[CP_MAX_PACKET]; - int datalen; - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), - "ms=%i", /* "ms"=mood */ - mood - ); - - /* queue packet for transmission */ - mxit_queue_packet( session, data, datalen, CP_CMD_MOOD ); -} - - -/*------------------------------------------------------------------------ - * Send an invite contact packet to the MXit server. - * - * @param session The MXit session object - * @param username The username of the contact being invited - * @param mxitid Indicates the username is a MXitId. - * @param alias Our alias for the contact - * @param groupname Group in which contact should be stored. - * @param message Invite message - */ -void mxit_send_invite( struct MXitSession* session, const char* username, gboolean mxitid, const char* alias, const char* groupname, const char* message ) -{ - char data[CP_MAX_PACKET]; - int datalen; - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), - "ms=%s%c%s%c%s%c%i%c%s%c%i", /* "ms"=group \1 username \1 alias \1 type \1 msg \1 isuserid */ - groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias, - CP_FLD_TERM, MXIT_TYPE_MXIT, CP_FLD_TERM, - ( message ? message : "" ), CP_FLD_TERM, - ( mxitid ? 0 : 1 ) - ); - - /* queue packet for transmission */ - mxit_queue_packet( session, data, datalen, CP_CMD_INVITE ); -} - - -/*------------------------------------------------------------------------ - * Send a remove contact packet to the MXit server. - * - * @param session The MXit session object - * @param username The username of the contact being removed - */ -void mxit_send_remove( struct MXitSession* session, const char* username ) -{ - char data[CP_MAX_PACKET]; - int datalen; - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), - "ms=%s", /* "ms"=username */ - username - ); - - /* queue packet for transmission */ - mxit_queue_packet( session, data, datalen, CP_CMD_REMOVE ); -} - - -/*------------------------------------------------------------------------ - * Send an accept subscription (invite) packet to the MXit server. - * - * @param session The MXit session object - * @param username The username of the contact being accepted - * @param alias Our alias for the contact - */ -void mxit_send_allow_sub( struct MXitSession* session, const char* username, const char* alias ) -{ - char data[CP_MAX_PACKET]; - int datalen; - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), - "ms=%s%c%s%c%s", /* "ms"=username\1group\1alias */ - username, CP_FLD_TERM, "", CP_FLD_TERM, alias - ); - - /* queue packet for transmission */ - mxit_queue_packet( session, data, datalen, CP_CMD_ALLOW ); -} - - -/*------------------------------------------------------------------------ - * Send an deny subscription (invite) packet to the MXit server. - * - * @param session The MXit session object - * @param username The username of the contact being denied - * @param reason The message describing the reason for the rejection (can be NULL). - */ -void mxit_send_deny_sub( struct MXitSession* session, const char* username, const char* reason ) -{ - char data[CP_MAX_PACKET]; - int datalen; - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), - "ms=%s", /* "ms"=username */ - username - ); - - /* append reason (if one is set) */ - if ( reason ) - datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, reason ); - - /* queue packet for transmission */ - mxit_queue_packet( session, data, datalen, CP_CMD_DENY ); -} - - -/*------------------------------------------------------------------------ - * Send an update contact packet to the MXit server. - * - * @param session The MXit session object - * @param username The username of the contact being denied - * @param alias Our alias for the contact - * @param groupname Group in which contact should be stored. - */ -void mxit_send_update_contact( struct MXitSession* session, const char* username, const char* alias, const char* groupname ) -{ - char data[CP_MAX_PACKET]; - int datalen; - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), - "ms=%s%c%s%c%s", /* "ms"=groupname\1username\1alias */ - groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias - ); - - /* queue packet for transmission */ - mxit_queue_packet( session, data, datalen, CP_CMD_UPDATE ); -} - - -/*------------------------------------------------------------------------ - * Send a splash-screen click event packet. - * - * @param session The MXit session object - * @param splashid The identifier of the splash-screen - */ -void mxit_send_splashclick( struct MXitSession* session, const char* splashid ) -{ - char data[CP_MAX_PACKET]; - int datalen; - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), - "ms=%s", /* "ms"=splashId */ - splashid - ); - - /* queue packet for transmission */ - mxit_queue_packet( session, data, datalen, CP_CMD_SPLASHCLICK ); -} - - -/*------------------------------------------------------------------------ - * Send a message event packet. - * - * @param session The MXit session object - * @param to The username of the original sender (ie, recipient of the event) - * @param id The identifier of the event (received in message) - * @param event Identified the type of event - */ -void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event ) -{ - char data[CP_MAX_PACKET]; - int datalen; - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_msgevent: to=%s id=%s event=%i\n", to, id, event ); - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), - "ms=%s%c%s%c%i", /* "ms"=contactAddress \1 id \1 event */ - to, CP_FLD_TERM, id, CP_FLD_TERM, event - ); - - /* queue packet for transmission */ - mxit_queue_packet( session, data, datalen, CP_CMD_MSGEVENT ); -} - - -/*------------------------------------------------------------------------ - * Send packet to create a MultiMX room. - * - * @param session The MXit session object - * @param groupname Name of the room to create - * @param nr_usernames Number of users in initial invite - * @param usernames The usernames of the users in the initial invite - */ -void mxit_send_groupchat_create( struct MXitSession* session, const char* groupname, int nr_usernames, const char* usernames[] ) -{ - char data[CP_MAX_PACKET]; - int datalen; - int i; - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), - "ms=%s%c%i", /* "ms"=roomname\1nr_jids\1jid0\1..\1jidN */ - groupname, CP_FLD_TERM, nr_usernames - ); - - /* add usernames */ - for ( i = 0; i < nr_usernames; i++ ) - datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] ); - - /* queue packet for transmission */ - mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_CREATE ); -} - - -/*------------------------------------------------------------------------ - * Send packet to invite users to existing MultiMX room. - * - * @param session The MXit session object - * @param roomid The unique RoomID for the MultiMx room. - * @param nr_usernames Number of users being invited - * @param usernames The usernames of the users being invited - */ -void mxit_send_groupchat_invite( struct MXitSession* session, const char* roomid, int nr_usernames, const char* usernames[] ) -{ - char data[CP_MAX_PACKET]; - int datalen; - int i; - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), - "ms=%s%c%i", /* "ms"=roomid\1nr_jids\1jid0\1..\1jidN */ - roomid, CP_FLD_TERM, nr_usernames - ); - - /* add usernames */ - for ( i = 0; i < nr_usernames; i++ ) - datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] ); - - /* queue packet for transmission */ - mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_INVITE ); -} - - -/*------------------------------------------------------------------------ - * Send a "send file direct" multimedia packet. - * - * @param session The MXit session object - * @param username The username of the recipient - * @param filename The name of the file being sent - * @param buf The content of the file - * @param buflen The length of the file contents - */ -void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen ) -{ - char data[CP_MAX_PACKET]; - int datalen = 0; - gchar* chunk; - int size; - - purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %i bytes to user '%s'\n", filename, buflen, username ); - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), "ms=" ); - - /* map chunk header over data buffer */ - chunk = &data[datalen]; - - size = mxit_chunk_create_senddirect( chunk_data( chunk ), username, filename, buf, buflen ); - if ( size < 0 ) { - purple_debug_error( MXIT_PLUGIN_ID, "Error creating senddirect chunk (%i)\n", size ); - return; - } - - set_chunk_type( chunk, CP_CHUNK_DIRECT_SND ); - set_chunk_length( chunk, size ); - datalen += MXIT_CHUNK_HEADER_SIZE + size; - - /* send the byte stream to the mxit server */ - mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA ); -} - - -/*------------------------------------------------------------------------ - * Send a "reject file" multimedia packet. - * - * @param session The MXit session object - * @param fileid A unique ID that identifies this file - */ -void mxit_send_file_reject( struct MXitSession* session, const char* fileid ) -{ - char data[CP_MAX_PACKET]; - int datalen = 0; - gchar* chunk; - int size; - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_reject\n" ); - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), "ms=" ); - - /* map chunk header over data buffer */ - chunk = &data[datalen]; - - size = mxit_chunk_create_reject( chunk_data( chunk ), fileid ); - if ( size < 0 ) { - purple_debug_error( MXIT_PLUGIN_ID, "Error creating reject chunk (%i)\n", size ); - return; - } - - set_chunk_type( chunk, CP_CHUNK_REJECT ); - set_chunk_length( chunk, size ); - datalen += MXIT_CHUNK_HEADER_SIZE + size; - - /* send the byte stream to the mxit server */ - mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA ); -} - - -/*------------------------------------------------------------------------ - * Send a "get file" multimedia packet. - * - * @param session The MXit session object - * @param fileid A unique ID that identifies this file - * @param filesize The number of bytes to retrieve - * @param offset Offset in file at which to start retrieving - */ -void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int filesize, int offset ) -{ - char data[CP_MAX_PACKET]; - int datalen = 0; - gchar* chunk; - int size; - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_accept\n" ); - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), "ms=" ); - - /* map chunk header over data buffer */ - chunk = &data[datalen]; - - size = mxit_chunk_create_get( chunk_data(chunk), fileid, filesize, offset ); - if ( size < 0 ) { - purple_debug_error( MXIT_PLUGIN_ID, "Error creating getfile chunk (%i)\n", size ); - return; - } - - set_chunk_type( chunk, CP_CHUNK_GET ); - set_chunk_length( chunk, size ); - datalen += MXIT_CHUNK_HEADER_SIZE + size; - - /* send the byte stream to the mxit server */ - mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA ); -} - - -/*------------------------------------------------------------------------ - * Send a "received file" multimedia packet. - * - * @param session The MXit session object - * @param status The status of the file-transfer - */ -void mxit_send_file_received( struct MXitSession* session, const char* fileid, short status ) -{ - char data[CP_MAX_PACKET]; - int datalen = 0; - gchar* chunk; - int size; - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_received\n" ); - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), "ms=" ); - - /* map chunk header over data buffer */ - chunk = &data[datalen]; - - size = mxit_chunk_create_received( chunk_data(chunk), fileid, status ); - if ( size < 0 ) { - purple_debug_error( MXIT_PLUGIN_ID, "Error creating received chunk (%i)\n", size ); - return; - } - - set_chunk_type( chunk, CP_CHUNK_RECEIVED ); - set_chunk_length( chunk, size ); - datalen += MXIT_CHUNK_HEADER_SIZE + size; - - /* send the byte stream to the mxit server */ - mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA ); -} - - -/*------------------------------------------------------------------------ - * Send a "set avatar" multimedia packet. - * - * @param session The MXit session object - * @param data The avatar data - * @param buflen The length of the avatar data - */ -void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen ) -{ - char data[CP_MAX_PACKET]; - int datalen = 0; - gchar* chunk; - int size; - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %i bytes\n", avatarlen ); - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), "ms=" ); - - /* map chunk header over data buffer */ - chunk = &data[datalen]; - - size = mxit_chunk_create_set_avatar( chunk_data(chunk), avatar, avatarlen ); - if ( size < 0 ) { - purple_debug_error( MXIT_PLUGIN_ID, "Error creating set avatar chunk (%i)\n", size ); - return; - } - - set_chunk_type( chunk, CP_CHUNK_SET_AVATAR ); - set_chunk_length( chunk, size ); - datalen += MXIT_CHUNK_HEADER_SIZE + size; - - /* send the byte stream to the mxit server */ - mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA ); -} - - -/*------------------------------------------------------------------------ - * Send a "get avatar" multimedia packet. - * - * @param session The MXit session object - * @param mxitId The username who's avatar to request - * @param avatarId The id of the avatar image (as string) - * @param data The avatar data - * @param buflen The length of the avatar data - */ -void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const char* avatarId ) -{ - char data[CP_MAX_PACKET]; - int datalen = 0; - gchar* chunk; - int size; - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_avatar: %s\n", mxitId ); - - /* convert the packet to a byte stream */ - datalen = g_snprintf( data, sizeof( data ), "ms=" ); - - /* map chunk header over data buffer */ - chunk = &data[datalen]; - - size = mxit_chunk_create_get_avatar( chunk_data(chunk), mxitId, avatarId ); - if ( size < 0 ) { - purple_debug_error( MXIT_PLUGIN_ID, "Error creating get avatar chunk (%i)\n", size ); - return; - } - - set_chunk_type( chunk, CP_CHUNK_GET_AVATAR ); - set_chunk_length( chunk, size ); - datalen += MXIT_CHUNK_HEADER_SIZE + size; - - /* send the byte stream to the mxit server */ - mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA ); -} - - -/*------------------------------------------------------------------------ - * Process a login message packet. - * - * @param session The MXit session object - * @param records The packet's data records - * @param rcount The number of data records - */ -static void mxit_parse_cmd_login( struct MXitSession* session, struct record** records, int rcount ) -{ - PurpleStatus* status; - int presence; - const char* statusmsg; - 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_RELATIONSHIP, CP_PROFILE_FLAGS }; - - purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN ); - - /* we were not yet logged in so we need to complete the login sequence here */ - session->flags |= MXIT_FLAG_LOGGEDIN; - purple_connection_update_progress( session->con, _( "Successfully Logged In..." ), 3, 4 ); - purple_connection_set_state( session->con, PURPLE_CONNECTION_CONNECTED ); - - /* save extra info if this is a HTTP connection */ - if ( session->http ) { - /* save the http server to use for this session */ - g_strlcpy( session->http_server, records[1]->fields[3]->data, sizeof( session->http_server ) ); - - /* save the session id */ - session->http_sesid = atoi( records[0]->fields[0]->data ); - } - - /* extract UserId (from protocol 5.9) */ - if ( records[1]->fcount >= 9 ) - session->uid = g_strdup( records[1]->fields[8]->data ); - - /* extract VoIP server (from protocol 6.2) */ - if ( records[1]->fcount >= 11 ) - g_strlcpy( session->voip_server, records[1]->fields[10]->data, sizeof( session->voip_server ) ); - - /* display the current splash-screen */ - if ( splash_popup_enabled( session ) ) - splash_display( session ); - - /* update presence status */ - status = purple_account_get_active_status( session->acc ); - presence = mxit_convert_presence( purple_status_get_id( status ) ); - statusmsg = purple_status_get_attr_string( status, "message" ); - - if ( ( presence != MXIT_PRESENCE_ONLINE ) || ( statusmsg ) ) { - /* when logging into MXit, your default presence is online. but with the UI, one can change - * the presence to whatever. in the case where its changed to a different presence setting - * we need to send an update to the server, otherwise the user's presence will be out of - * sync between the UI and MXit. - */ - char* statusmsg1 = purple_markup_strip_html( statusmsg ); - char* statusmsg2 = g_strndup( statusmsg1, CP_MAX_STATUS_MSG ); - - mxit_send_presence( session, presence, statusmsg2 ); - - g_free( statusmsg1 ); - g_free( statusmsg2 ); - } - - /* retrieve our MXit profile */ - mxit_send_extprofile_request( session, NULL, ARRAY_SIZE( profilelist ), profilelist ); -} - - -/*------------------------------------------------------------------------ - * Process a received message packet. - * - * @param session The MXit session object - * @param records The packet's data records - * @param rcount The number of data records - */ -static void mxit_parse_cmd_message( struct MXitSession* session, struct record** records, int rcount ) -{ - struct RXMsgData* mx = NULL; - char* message = NULL; - char* sender = NULL; - int msglen = 0; - int msgflags = 0; - int msgtype = 0; - - if ( ( rcount == 1 ) || ( records[0]->fcount < 2 ) || ( records[1]->fcount == 0 ) || ( records[1]->fields[0]->len == 0 ) ) { - /* packet contains no message or an empty message */ - return; - } - - message = records[1]->fields[0]->data; - msglen = strlen( message ); - - /* strip off dummy domain */ - sender = records[0]->fields[0]->data; - mxit_strip_domain( sender ); - -#ifdef DEBUG_PROTOCOL - purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", sender ); -#endif - - /* decode message flags (if any) */ - if ( records[0]->fcount >= 5 ) - msgflags = atoi( records[0]->fields[4]->data ); - msgtype = atoi( records[0]->fields[2]->data ); - - 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_blist_find_buddy( session->acc, sender ); - if ( buddy ) - name = purple_buddy_get_alias( buddy ); - else - 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, 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( sender ); - mx->timestamp = atoi( records[0]->fields[1]->data ); - mx->got_img = FALSE; - mx->chatid = -1; - mx->img_count = 0; - - /* update list of active chats */ - if ( !find_active_chat( session->active_chats, mx->from ) ) { - session->active_chats = g_list_append( session->active_chats, g_strdup( mx->from ) ); - } - - if ( is_multimx_contact( session, mx->from ) ) { - /* this is a MultiMx chatroom message */ - multimx_message_received( mx, message, msglen, msgtype, msgflags ); - } - else { - mxit_parse_markup( mx, message, msglen, msgtype, msgflags ); - } - - /* we are now done parsing the message */ - mx->converted = TRUE; - if ( mx->img_count == 0 ) { - /* we have all the data we need for this message to be displayed now. */ - mxit_show_message( mx ); - } - else { - /* this means there are still images outstanding for this message and - * still need to wait for them before we can display the message. - * so the image received callback function will eventually display - * the message. */ - } - - /* cleanup */ - if ( msgflags & CP_MSG_TL_ENCRYPTED ) - g_free( message ); -} - - -/*------------------------------------------------------------------------ - * Process a received subscription request packet. - * - * @param session The MXit session object - * @param records The packet's data records - * @param rcount The number of data records - */ -static void mxit_parse_cmd_new_sub( struct MXitSession* session, struct record** records, int rcount ) -{ - struct contact* contact; - struct record* rec; - int i; - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_new_sub (%i recs)\n", rcount ); - - for ( i = 0; i < rcount; i++ ) { - rec = records[i]; - - if ( rec->fcount < 4 ) { - purple_debug_error( MXIT_PLUGIN_ID, "BAD SUBSCRIPTION RECORD! %i fields\n", rec->fcount ); - break; - } - - /* build up a new contact info struct */ - contact = g_new0( struct contact, 1 ); - - g_strlcpy( contact->username, rec->fields[0]->data, sizeof( contact->username ) ); - mxit_strip_domain( contact->username ); /* remove dummy domain */ - g_strlcpy( contact->alias, rec->fields[1]->data, sizeof( contact->alias ) ); - contact->type = atoi( rec->fields[2]->data ); - - if ( rec->fcount >= 5 ) { - /* there is a personal invite message attached */ - if ( ( rec->fields[4]->data ) && ( *rec->fields[4]->data ) ) - contact->msg = strdup( rec->fields[4]->data ); - } - - /* handle the subscription */ - if ( contact-> type == MXIT_TYPE_MULTIMX ) { /* subscription to a MultiMX room */ - char* creator = NULL; - - if ( rec->fcount >= 6 ) - creator = rec->fields[5]->data; - - multimx_invite( session, contact, creator ); - } - else - mxit_new_subscription( session, contact ); - } -} - - -/*------------------------------------------------------------------------ - * Parse the received presence value, and ensure that it is supported. - * - * @param value The received presence value. - * @return A valid presence value. - */ -static short mxit_parse_presence( const char* value ) -{ - short presence = atoi( value ); - - /* ensure that the presence value is valid */ - switch ( presence ) { - case MXIT_PRESENCE_OFFLINE : - case MXIT_PRESENCE_ONLINE : - case MXIT_PRESENCE_AWAY : - case MXIT_PRESENCE_DND : - return presence; - - default : - return MXIT_PRESENCE_ONLINE; - } -} - - -/*------------------------------------------------------------------------ - * Process a received contact update packet. - * - * @param session The MXit session object - * @param records The packet's data records - * @param rcount The number of data records - */ -static void mxit_parse_cmd_contact( struct MXitSession* session, struct record** records, int rcount ) -{ - struct contact* contact = NULL; - struct record* rec; - int i; - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_contact (%i recs)\n", rcount ); - - for ( i = 0; i < rcount; i++ ) { - rec = records[i]; - - if ( rec->fcount < 6 ) { - purple_debug_error( MXIT_PLUGIN_ID, "BAD CONTACT RECORD! %i fields\n", rec->fcount ); - break; - } - - /* build up a new contact info struct */ - contact = g_new0( struct contact, 1 ); - - g_strlcpy( contact->groupname, rec->fields[0]->data, sizeof( contact->groupname ) ); - g_strlcpy( contact->username, rec->fields[1]->data, sizeof( contact->username ) ); - mxit_strip_domain( contact->username ); /* remove dummy domain */ - g_strlcpy( contact->alias, rec->fields[2]->data, sizeof( contact->alias ) ); - - contact->presence = mxit_parse_presence( rec->fields[3]->data ); - contact->type = atoi( rec->fields[4]->data ); - contact->mood = atoi( rec->fields[5]->data ); - - if ( rec->fcount > 6 ) { - /* added in protocol 5.9 - flags & subtype */ - contact->flags = atoi( rec->fields[6]->data ); - contact->subtype = rec->fields[7]->data[0]; - } - if ( rec->fcount > 8 ) { - /* added in protocol 6.0 - reject message */ - contact->msg = g_strdup( rec->fields[8]->data ); - } - - /* add the contact to the buddy list */ - if ( contact-> type == MXIT_TYPE_MULTIMX ) /* contact is a MultiMX room */ - multimx_created( session, contact ); - else - mxit_update_contact( session, contact ); - } - - if ( !( session->flags & MXIT_FLAG_FIRSTROSTER ) ) { - session->flags |= MXIT_FLAG_FIRSTROSTER; - mxit_update_blist( session ); - } -} - - -/*------------------------------------------------------------------------ - * Process a received presence update packet. - * - * @param session The MXit session object - * @param records The packet's data records - * @param rcount The number of data records - */ -static void mxit_parse_cmd_presence( struct MXitSession* session, struct record** records, int rcount ) -{ - int i; - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_presence (%i recs)\n", rcount ); - - for ( i = 0; i < rcount; i++ ) { - struct record* rec = records[i]; - int flags = 0; - - if ( rec->fcount < 6 ) { - purple_debug_error( MXIT_PLUGIN_ID, "BAD PRESENCE RECORD! %i fields\n", rec->fcount ); - break; - } - - /* - * The format of the record is: - * contactAddressN \1 presenceN \1 moodN \1 customMoodN \1 statusMsgN \1 avatarIdN [ \1 flagsN ] - */ - mxit_strip_domain( rec->fields[0]->data ); /* contactAddress */ - - if ( rec->fcount >= 7 ) /* flags field is included */ - flags = atoi( rec->fields[6]->data ); - - mxit_update_buddy_presence( session, rec->fields[0]->data, mxit_parse_presence( rec->fields[1]->data ), atoi( rec->fields[2]->data ), - rec->fields[3]->data, rec->fields[4]->data, flags ); - mxit_update_buddy_avatar( session, rec->fields[0]->data, rec->fields[5]->data ); - } -} - - -/*------------------------------------------------------------------------ - * Process a received extended profile packet. - * - * @param session The MXit session object - * @param records The packet's data records - * @param rcount The number of data records - */ -static void mxit_parse_cmd_extprofile( struct MXitSession* session, struct record** records, int rcount ) -{ - const char* mxitId = records[0]->fields[0]->data; - struct MXitProfile* profile = NULL; - int count; - int i; - const char* avatarId = NULL; - char* statusMsg = NULL; - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_extprofile: profile for '%s'\n", mxitId ); - - if ( ( records[0]->fields[0]->len == 0 ) || ( session->uid && ( strcmp( session->uid, records[0]->fields[0]->data ) == 0 ) ) ) { - /* No UserId or Our UserId provided, so this must be our own profile information */ - if ( session->profile == NULL ) - session->profile = g_new0( struct MXitProfile, 1 ); - profile = session->profile; - } - else { - /* is a buddy's profile */ - profile = g_new0( struct MXitProfile, 1 ); - } - - /* set the count for attributes */ - count = atoi( records[0]->fields[1]->data ); - - for ( i = 0; i < count; i++ ) { - char* fname; - char* fvalue; - char* fstatus; - int f = ( i * 3 ) + 2; - - fname = records[0]->fields[f]->data; /* field name */ - fvalue = records[0]->fields[f + 1]->data; /* field value */ - fstatus = records[0]->fields[f + 2]->data; /* field status */ - - /* first check the status on the returned attribute */ - if ( fstatus[0] != '0' ) { - /* error: attribute requested was NOT found */ - purple_debug_error( MXIT_PLUGIN_ID, "Bad profile status on attribute '%s' \n", fname ); - continue; - } - - if ( strcmp( CP_PROFILE_BIRTHDATE, fname ) == 0 ) { - /* birthdate */ - if ( records[0]->fields[f + 1]->len > 10 ) { - fvalue[10] = '\0'; - records[0]->fields[f + 1]->len = 10; - } - memcpy( profile->birthday, fvalue, records[0]->fields[f + 1]->len ); - } - else if ( strcmp( CP_PROFILE_GENDER, fname ) == 0 ) { - /* gender */ - profile->male = ( fvalue[0] == '1' ); - } - else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) { - /* nickname */ - g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) ); - } - else if ( strcmp( CP_PROFILE_STATUS, fname ) == 0 ) { - /* status message - just keep a reference to the value */ - statusMsg = g_markup_escape_text( fvalue, -1 ); - } - else if ( strcmp( CP_PROFILE_AVATAR, fname ) == 0 ) { - /* avatar id - just keep a reference to the value */ - avatarId = fvalue; - } - else if ( strcmp( CP_PROFILE_TITLE, fname ) == 0 ) { - /* title */ - g_strlcpy( profile->title, fvalue, sizeof( profile->title ) ); - } - else if ( strcmp( CP_PROFILE_FIRSTNAME, fname ) == 0 ) { - /* first name */ - g_strlcpy( profile->firstname, fvalue, sizeof( profile->firstname ) ); - } - else if ( strcmp( CP_PROFILE_LASTNAME, fname ) == 0 ) { - /* last name */ - g_strlcpy( profile->lastname, fvalue, sizeof( profile->lastname ) ); - } - else if ( strcmp( CP_PROFILE_EMAIL, fname ) == 0 ) { - /* email address */ - g_strlcpy( profile->email, fvalue, sizeof( profile->email ) ); - } - else if ( strcmp( CP_PROFILE_MOBILENR, fname ) == 0 ) { - /* mobile number */ - g_strlcpy( profile->mobilenr, fvalue, sizeof( profile->mobilenr ) ); - } - else if ( strcmp( CP_PROFILE_REGCOUNTRY, fname ) == 0 ) { - /* registered country */ - g_strlcpy( profile->regcountry, fvalue, sizeof( profile->regcountry ) ); - } - else if ( strcmp( CP_PROFILE_FLAGS, fname ) == 0 ) { - /* profile flags */ - profile->flags = g_ascii_strtoll( fvalue, NULL, 10 ); - } - else if ( strcmp( CP_PROFILE_LASTSEEN, fname ) == 0 ) { - /* last seen online */ - profile->lastonline = g_ascii_strtoll( fvalue, NULL, 10 ); - } - else if ( strcmp( CP_PROFILE_WHEREAMI, fname ) == 0 ) { - /* where am I */ - g_strlcpy( profile->whereami, fvalue, sizeof( profile->whereami ) ); - } - else if ( strcmp( CP_PROFILE_ABOUTME, fname ) == 0) { - /* about me */ - g_strlcpy( profile->aboutme, fvalue, sizeof( profile->aboutme ) ); - } - else if ( strcmp( CP_PROFILE_RELATIONSHIP, fname ) == 0) { - /* relatinship status */ - profile->relationship = strtol( fvalue, NULL, 10 ); - } - else { - /* invalid profile attribute */ - purple_debug_error( MXIT_PLUGIN_ID, "Invalid profile attribute received '%s' \n", fname ); - } - } - - if ( profile != session->profile ) { - /* not our own profile */ - struct contact* contact = NULL; - - contact = get_mxit_invite_contact( session, mxitId ); - if ( contact ) { - /* this is an invite, so update its profile info */ - if ( ( statusMsg ) && ( *statusMsg ) ) { - /* update the status message */ - if ( contact->statusMsg ) - g_free( contact->statusMsg ); - contact->statusMsg = strdup( statusMsg ); - } - else - contact->statusMsg = NULL; - if ( contact->profile ) - g_free( contact->profile ); - contact->profile = profile; - if ( ( avatarId ) && ( *avatarId ) ) { - /* avatar must be requested for this invite before we can display it */ - mxit_get_avatar( session, mxitId, avatarId ); - if ( contact->avatarId ) - g_free( contact->avatarId ); - contact->avatarId = strdup( avatarId ); - } - else { - /* display what we have */ - contact->avatarId = NULL; - mxit_show_profile( session, mxitId, profile ); - } - } - else { - /* this is a contact */ - if ( avatarId ) - mxit_update_buddy_avatar( session, mxitId, avatarId ); - - if ( ( statusMsg ) && ( *statusMsg ) ) { - /* update the status message */ - PurpleBuddy* buddy = NULL; - - buddy = purple_blist_find_buddy( session->acc, mxitId ); - if ( buddy ) { - contact = purple_buddy_get_protocol_data( buddy ); - if ( contact ) { - if ( contact->statusMsg ) - g_free( contact->statusMsg ); - contact->statusMsg = strdup( statusMsg ); - } - } - } - - /* show the profile */ - mxit_show_profile( session, mxitId, profile ); - g_free( profile ); - } - } - - g_free( statusMsg ); -} - - -/*------------------------------------------------------------------------ - * Process a received suggest-contacts packet. - * - * @param session The MXit session object - * @param records The packet's data records - * @param rcount The number of data records - */ -static void mxit_parse_cmd_suggestcontacts( struct MXitSession* session, struct record** records, int rcount ) -{ - GList* entries = NULL; - int searchType; - int maxResults; - int count; - int i; - - /* - * searchType \1 numSuggestions \1 total \1 numAttributes \1 name0 \1 name1 \1 ... \1 nameN \0 - * userid \1 contactType \1 value0 \1 value1 ... valueN \0 - * ... - * userid \1 contactType \1 value0 \1 value1 ... valueN - */ - - /* the type of results */ - searchType = atoi( records[0]->fields[0]->data ); - - /* the maximum number of results */ - maxResults = atoi( records[0]->fields[2]->data ); - - /* set the count for attributes */ - count = atoi( records[0]->fields[3]->data ); - - for ( i = 1; i < rcount; i ++ ) { - struct record* rec = records[i]; - struct MXitProfile* profile = g_new0( struct MXitProfile, 1 ); - int j; - - g_strlcpy( profile->userid, rec->fields[0]->data, sizeof( profile->userid ) ); - // TODO: ContactType - User or Service - - for ( j = 0; j < count; j++ ) { - char* fname; - char* fvalue = ""; - - fname = records[0]->fields[4 + j]->data; /* field name */ - if ( records[i]->fcount > ( 2 + j ) ) - fvalue = records[i]->fields[2 + j]->data; /* field value */ - - purple_debug_info( MXIT_PLUGIN_ID, " %s: field='%s' value='%s'\n", profile->userid, fname, fvalue ); - - if ( strcmp( CP_PROFILE_BIRTHDATE, fname ) == 0 ) { - /* birthdate */ - g_strlcpy( profile->birthday, fvalue, sizeof( profile->birthday ) ); - } - else if ( strcmp( CP_PROFILE_FIRSTNAME, fname ) == 0 ) { - /* first name */ - g_strlcpy( profile->firstname, fvalue, sizeof( profile->firstname ) ); - } - else if ( strcmp( CP_PROFILE_LASTNAME, fname ) == 0 ) { - /* last name */ - g_strlcpy( profile->lastname, fvalue, sizeof( profile->lastname ) ); - } - else if ( strcmp( CP_PROFILE_GENDER, fname ) == 0 ) { - /* gender */ - profile->male = ( fvalue[0] == '1' ); - } - else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) { - /* nickname */ - g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) ); - } - else if ( strcmp( CP_PROFILE_WHEREAMI, fname ) == 0 ) { - /* where am I */ - g_strlcpy( profile->whereami, fvalue, sizeof( profile->whereami ) ); - } - /* ignore other attibutes */ - } - - entries = g_list_append( entries, profile ); - } - - /* display */ - mxit_show_search_results( session, searchType, maxResults, entries ); - - /* cleanup */ - g_list_foreach( entries, (GFunc)g_free, NULL ); -} - -/*------------------------------------------------------------------------ - * Process a received message event packet. - * - * @param session The MXit session object - * @param records The packet's data records - * @param rcount The number of data records - */ -static void mxit_parse_cmd_msgevent( struct MXitSession* session, struct record** records, int rcount ) -{ - int event; - - /* - * contactAddress \1 dateTime \1 id \1 event - */ - - /* strip off dummy domain */ - mxit_strip_domain( records[0]->fields[0]->data ); - - event = atoi( records[0]->fields[3]->data ); - - switch ( event ) { - case CP_MSGEVENT_TYPING : /* user is typing */ - case CP_MSGEVENT_ANGRY : /* user is typing angrily */ - serv_got_typing( session->con, records[0]->fields[0]->data, 0, PURPLE_IM_TYPING ); - break; - - case CP_MSGEVENT_STOPPED : /* user has stopped typing */ - serv_got_typing_stopped( session->con, records[0]->fields[0]->data ); - break; - - case CP_MSGEVENT_ERASING : /* user is erasing text */ - case CP_MSGEVENT_DELIVERED : /* message was delivered */ - case CP_MSGEVENT_DISPLAYED : /* message was viewed */ - /* these are currently not supported by libPurple */ - break; - - default: - purple_debug_error( MXIT_PLUGIN_ID, "Unknown message event received (%i)\n", event ); - } -} - - -/*------------------------------------------------------------------------ - * Return the length of a multimedia chunk - * - * @return The actual chunk data length in bytes - */ -static int get_chunk_len( const char* chunkdata ) -{ - int* sizeptr; - - sizeptr = (int*) &chunkdata[1]; /* we skip the first byte (type field) */ - - return ntohl( *sizeptr ); -} - - -/*------------------------------------------------------------------------ - * Process a received multimedia packet. - * - * @param session The MXit session object - * @param records The packet's data records - * @param rcount The number of data records - */ -static void mxit_parse_cmd_media( struct MXitSession* session, struct record** records, int rcount ) -{ - char type; - int size; - - type = records[0]->fields[0]->data[0]; - size = get_chunk_len( records[0]->fields[0]->data ); - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_media (%i records) (%i bytes)\n", rcount, size ); - - /* supported chunked data types */ - switch ( type ) { - case CP_CHUNK_CUSTOM : /* custom resource */ - { - struct cr_chunk chunk; - - /* decode the chunked data */ - memset( &chunk, 0, sizeof( struct cr_chunk ) ); - mxit_chunk_parse_cr( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ); - - purple_debug_info( MXIT_PLUGIN_ID, "chunk info id=%s handle=%s op=%i\n", chunk.id, chunk.handle, chunk.operation ); - - /* this is a splash-screen operation */ - if ( strcmp( chunk.handle, HANDLE_SPLASH2 ) == 0 ) { - if ( chunk.operation == CR_OP_UPDATE ) { /* update the splash-screen */ - struct splash_chunk *splash = chunk.resources->data; // TODO: Fix - assuming 1st resource is splash - gboolean clickable = ( g_list_length( chunk.resources ) > 1 ); // TODO: Fix - if 2 resources, then is clickable - - if ( splash != NULL ) - splash_update( session, chunk.id, splash->data, splash->datalen, clickable ); - } - else if ( chunk.operation == CR_OP_REMOVE ) /* remove the splash-screen */ - splash_remove( session ); - } - - /* cleanup custom resources */ - g_list_foreach( chunk.resources, (GFunc)g_free, NULL ); - - } - break; - - case CP_CHUNK_OFFER : /* file offer */ - { - struct offerfile_chunk chunk; - - /* decode the chunked data */ - memset( &chunk, 0, sizeof( struct offerfile_chunk ) ); - mxit_chunk_parse_offer( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ); - - /* process the offer */ - mxit_xfer_rx_offer( session, chunk.username, chunk.filename, chunk.filesize, chunk.fileid ); - } - break; - - case CP_CHUNK_GET : /* get file response */ - { - struct getfile_chunk chunk; - - /* decode the chunked data */ - memset( &chunk, 0, sizeof( struct getfile_chunk ) ); - mxit_chunk_parse_get( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ); - - /* process the getfile */ - mxit_xfer_rx_file( session, chunk.fileid, chunk.data, chunk.length ); - } - break; - - case CP_CHUNK_GET_AVATAR : /* get avatars */ - { - struct getavatar_chunk chunk; - struct contact* contact = NULL; - - /* decode the chunked data */ - memset( &chunk, 0, sizeof( struct getavatar_chunk ) ); - mxit_chunk_parse_get_avatar( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ); - - /* update avatar image */ - if ( chunk.data ) { - purple_debug_info( MXIT_PLUGIN_ID, "updating avatar for contact '%s'\n", chunk.mxitid ); - - 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_new_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 ); - } - } - } - break; - - case CP_CHUNK_SET_AVATAR : - /* this is a reply packet to a set avatar request. no action is required */ - break; - - case CP_CHUNK_DIRECT_SND : - /* this is a ack for a file send. */ - { - struct sendfile_chunk chunk; - - memset( &chunk, 0, sizeof( struct sendfile_chunk ) ); - mxit_chunk_parse_sendfile( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ); - - purple_debug_info( MXIT_PLUGIN_ID, "file-send send to '%s' [status=%i message='%s']\n", chunk.username, chunk.status, chunk.statusmsg ); - - if ( chunk.status != 0 ) /* not success */ - mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "File Send Failed" ), chunk.statusmsg ); - } - break; - - case CP_CHUNK_RECEIVED : - /* this is a ack for a file received. no action is required */ - break; - - default : - purple_debug_error( MXIT_PLUGIN_ID, "Unsupported chunked data packet type received (%i)\n", type ); - break; - } -} - - -/*------------------------------------------------------------------------ - * Handle a redirect sent from the MXit server. - * - * @param session The MXit session object - * @param url The redirect information - */ -static void mxit_perform_redirect( struct MXitSession* session, const char* url ) -{ - gchar** parts; - gchar** host; - int type; - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_perform_redirect: %s\n", url ); - - /* tokenize the URL string */ - parts = g_strsplit( url, ";", 0 ); - - /* Part 1: protocol://host:port */ - host = g_strsplit( parts[0], ":", 4 ); - if ( strcmp( host[0], "socket" ) == 0 ) { - /* redirect to a MXit socket proxy */ - g_strlcpy( session->server, &host[1][2], sizeof( session->server ) ); - session->port = atoi( host[2] ); - } - else { - purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Cannot perform redirect using the specified protocol" ) ); - goto redirect_fail; - } - - /* Part 2: type of redirect */ - type = atoi( parts[1] ); - if ( type == CP_REDIRECT_PERMANENT ) { - /* permanent redirect, so save new MXit server and port */ - purple_account_set_string( session->acc, MXIT_CONFIG_SERVER_ADDR, session->server ); - purple_account_set_int( session->acc, MXIT_CONFIG_SERVER_PORT, session->port ); - } - - /* Part 3: message (optional) */ - if ( parts[2] != NULL ) - purple_connection_notice( session->con, parts[2] ); - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_perform_redirect: %s redirect to %s:%i\n", - ( type == CP_REDIRECT_PERMANENT ) ? "Permanent" : "Temporary", session->server, session->port ); - - /* perform the re-connect to the new MXit server */ - mxit_reconnect( session ); - -redirect_fail: - g_strfreev( parts ); - g_strfreev( host ); -} - - -/*------------------------------------------------------------------------ - * Process a success response received from the MXit server. - * - * @param session The MXit session object - * @param packet The received packet - */ -static int process_success_response( struct MXitSession* session, struct rx_packet* packet ) -{ - /* ignore ping/poll packets */ - if ( ( packet->cmd != CP_CMD_PING ) && ( packet->cmd != CP_CMD_POLL ) ) - session->last_rx = mxit_now_milli(); - - /* - * when we pass the packet records to the next level for parsing - * we minus 3 records because 1) the first record is the packet - * type 2) packet reply status 3) the last record is bogus - */ - - /* packet command */ - switch ( packet->cmd ) { - - case CP_CMD_REGISTER : - /* fall through, when registeration successful, MXit will auto login */ - case CP_CMD_LOGIN : - /* login response */ - if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) { - mxit_parse_cmd_login( session, &packet->records[2], packet->rcount - 3 ); - } - break; - - case CP_CMD_LOGOUT : - /* logout response */ - session->flags &= ~MXIT_FLAG_LOGGEDIN; - purple_account_disconnect( session->acc ); - - /* note: - * we do not prompt the user here for a reconnect, because this could be the user - * logging in with his phone. so we just disconnect the account otherwise - * mxit will start to bounce between the phone and pidgin. also could be a valid - * disconnect selected by the user. - */ - return -1; - - case CP_CMD_CONTACT : - /* contact update */ - mxit_parse_cmd_contact( session, &packet->records[2], packet->rcount - 3 ); - break; - - case CP_CMD_PRESENCE : - /* presence update */ - mxit_parse_cmd_presence( session, &packet->records[2], packet->rcount - 3 ); - break; - - case CP_CMD_RX_MSG : - /* incoming message (no bogus record) */ - mxit_parse_cmd_message( session, &packet->records[2], packet->rcount - 2 ); - break; - - case CP_CMD_NEW_SUB : - /* new subscription request */ - mxit_parse_cmd_new_sub( session, &packet->records[2], packet->rcount - 3 ); - break; - - case CP_CMD_MEDIA : - /* multi-media message */ - mxit_parse_cmd_media( session, &packet->records[2], packet->rcount - 2 ); - break; - - case CP_CMD_EXTPROFILE_GET : - /* profile update */ - mxit_parse_cmd_extprofile( session, &packet->records[2], packet->rcount - 2 ); - break; - - case CP_CMD_SUGGESTCONTACTS : - /* suggest contacts */ - mxit_parse_cmd_suggestcontacts( session, &packet->records[2], packet->rcount - 2 ); - break; - - case CP_CMD_GOT_MSGEVENT : - /* received message event */ - mxit_parse_cmd_msgevent( session, &packet->records[2], packet->rcount - 2 ); - break; - - case CP_CMD_MOOD : - /* mood update */ - case CP_CMD_UPDATE : - /* update contact information */ - case CP_CMD_ALLOW : - /* allow subscription ack */ - case CP_CMD_DENY : - /* deny subscription ack */ - case CP_CMD_INVITE : - /* invite contact ack */ - case CP_CMD_REMOVE : - /* remove contact ack */ - case CP_CMD_TX_MSG : - /* outgoing message ack */ - case CP_CMD_STATUS : - /* presence update ack */ - case CP_CMD_GRPCHAT_CREATE : - /* create groupchat */ - case CP_CMD_GRPCHAT_INVITE : - /* groupchat invite */ - case CP_CMD_PING : - /* ping reply */ - case CP_CMD_POLL : - /* HTTP poll reply */ - case CP_CMD_EXTPROFILE_SET : - /* profile update */ - // TODO: Protocol 6.2 indicates status for each attribute, and current value. - case CP_CMD_SPLASHCLICK : - /* splash-screen clickthrough */ - case CP_CMD_MSGEVENT : - /* event message */ - break; - - default : - /* unknown packet */ - purple_debug_error( MXIT_PLUGIN_ID, "Received unknown client packet (cmd = %i)\n", packet->cmd ); - } - - return 0; -} - - -/*------------------------------------------------------------------------ - * Process an error response received from the MXit server. - * - * @param session The MXit session object - * @param packet The received packet - */ -static int process_error_response( struct MXitSession* session, struct rx_packet* packet ) -{ - char errmsg[256]; - const char* errdesc; - - /* set the error description to be shown to the user */ - if ( packet->errmsg ) - errdesc = packet->errmsg; - else - errdesc = _( "An internal MXit server error occurred." ); - - purple_debug_info( MXIT_PLUGIN_ID, "Error Reply %i:%s\n", packet->errcode, errdesc ); - - if ( packet->errcode == MXIT_ERRCODE_LOGGEDOUT ) { - /* we are not currently logged in, so we need to reconnect */ - purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( errdesc ) ); - } - - /* packet command */ - switch ( packet->cmd ) { - - case CP_CMD_REGISTER : - case CP_CMD_LOGIN : - if ( packet->errcode == MXIT_ERRCODE_REDIRECT ) { - mxit_perform_redirect( session, packet->errmsg ); - return 0; - } - else { - g_snprintf( errmsg, sizeof( errmsg ), _( "Login error: %s (%i)" ), errdesc, packet->errcode ); - purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, errmsg ); - return -1; - } - case CP_CMD_LOGOUT : - g_snprintf( errmsg, sizeof( errmsg ), _( "Logout error: %s (%i)" ), errdesc, packet->errcode ); - 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 ) ); - break; - case CP_CMD_RX_MSG : - mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), _( errdesc ) ); - break; - case CP_CMD_TX_MSG : - mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Sending Error" ), _( errdesc ) ); - break; - case CP_CMD_STATUS : - mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Status Error" ), _( errdesc ) ); - break; - case CP_CMD_MOOD : - mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Mood Error" ), _( errdesc ) ); - break; - case CP_CMD_KICK : - /* - * the MXit server sends this packet if we were idle for too long. - * to stop the server from closing this connection we need to resend - * the login packet. - */ - mxit_send_login( session ); - break; - case CP_CMD_INVITE : - mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Invitation Error" ), _( errdesc ) ); - break; - case CP_CMD_REMOVE : - mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Removal Error" ), _( errdesc ) ); - break; - case CP_CMD_ALLOW : - case CP_CMD_DENY : - mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Subscription Error" ), _( errdesc ) ); - break; - case CP_CMD_UPDATE : - mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Update Error" ), _( errdesc ) ); - break; - case CP_CMD_MEDIA : - mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "File Transfer Error" ), _( errdesc ) ); - break; - case CP_CMD_GRPCHAT_CREATE : - mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Cannot create MultiMx room" ), _( errdesc ) ); - break; - case CP_CMD_GRPCHAT_INVITE : - mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "MultiMx Invitation Error" ), _( errdesc ) ); - break; - case CP_CMD_EXTPROFILE_GET : - case CP_CMD_EXTPROFILE_SET : - mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Profile Error" ), _( errdesc ) ); - break; - case CP_CMD_SPLASHCLICK : - case CP_CMD_MSGEVENT : - /* ignore error */ - break; - case CP_CMD_PING : - case CP_CMD_POLL : - break; - default : - mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Error" ), _( errdesc ) ); - break; - } - - return 0; -} - - -/*======================================================================================================================== - * Low-level Packet receive - */ - -#ifdef DEBUG_PROTOCOL -/*------------------------------------------------------------------------ - * Dump a received packet structure. - * - * @param p The received packet - */ -static void dump_packet( struct rx_packet* p ) -{ - struct record* r = NULL; - struct field* f = NULL; - int i; - int j; - - purple_debug_info( MXIT_PLUGIN_ID, "PACKET DUMP: (%i records)\n", p->rcount ); - - for ( i = 0; i < p->rcount; i++ ) { - r = p->records[i]; - purple_debug_info( MXIT_PLUGIN_ID, "RECORD: (%i fields)\n", r->fcount ); - - for ( j = 0; j < r->fcount; j++ ) { - f = r->fields[j]; - purple_debug_info( MXIT_PLUGIN_ID, "\tFIELD: (len=%i) '%s' \n", f->len, f->data ); - } - } -} -#endif - - -/*------------------------------------------------------------------------ - * Free up memory used by a packet structure. - * - * @param p The received packet - */ -static void free_rx_packet( struct rx_packet* p ) -{ - struct record* r = NULL; - struct field* f = NULL; - int i; - int j; - - for ( i = 0; i < p->rcount; i++ ) { - r = p->records[i]; - - for ( j = 0; j < r->fcount; j++ ) { - g_free( f ); - } - g_free( r->fields ); - g_free( r ); - } - g_free( p->records ); -} - - -/*------------------------------------------------------------------------ - * Add a new field to a record. - * - * @param r Parent record object - * @return The newly created field - */ -static struct field* add_field( struct record* r ) -{ - struct field* field; - - field = g_new0( struct field, 1 ); - - r->fields = g_realloc( r->fields, sizeof( struct field* ) * ( r->fcount + 1 ) ); - r->fields[r->fcount] = field; - r->fcount++; - - return field; -} - - -/*------------------------------------------------------------------------ - * Add a new record to a packet. - * - * @param p The packet object - * @return The newly created record - */ -static struct record* add_record( struct rx_packet* p ) -{ - struct record* rec; - - rec = g_new0( struct record, 1 ); - - p->records = g_realloc( p->records, sizeof( struct record* ) * ( p->rcount + 1 ) ); - p->records[p->rcount] = rec; - p->rcount++; - - return rec; -} - - -/*------------------------------------------------------------------------ - * Parse the received byte stream into a proper client protocol packet. - * - * @param session The MXit session object - * @return Success (0) or Failure (!0) - */ -int mxit_parse_packet( struct MXitSession* session ) -{ - struct rx_packet packet; - struct record* rec; - struct field* field; - gboolean pbreak; - unsigned int i; - int res = 0; - -#ifdef DEBUG_PROTOCOL - purple_debug_info( MXIT_PLUGIN_ID, "Received packet (%i bytes)\n", session->rx_i ); - dump_bytes( session, session->rx_dbuf, session->rx_i ); -#endif - - i = 0; - while ( i < session->rx_i ) { - - /* create first record and field */ - rec = NULL; - field = NULL; - memset( &packet, 0x00, sizeof( struct rx_packet ) ); - rec = add_record( &packet ); - pbreak = FALSE; - - /* break up the received packet into fields and records for easy parsing */ - while ( ( i < session->rx_i ) && ( !pbreak ) ) { - - switch ( session->rx_dbuf[i] ) { - case CP_SOCK_REC_TERM : - /* new record */ - if ( packet.rcount == 1 ) { - /* packet command */ - packet.cmd = atoi( packet.records[0]->fields[0]->data ); - } - else if ( packet.rcount == 2 ) { - /* special case: binary multimedia packets should not be parsed here */ - if ( packet.cmd == CP_CMD_MEDIA ) { - /* add the chunked to new record */ - rec = add_record( &packet ); - field = add_field( rec ); - field->data = &session->rx_dbuf[i + 1]; - field->len = session->rx_i - i; - /* now skip the binary data */ - res = get_chunk_len( field->data ); - /* determine if we have more packets */ - if ( res + 6 + i < session->rx_i ) { - /* we have more than one packet in this stream */ - i += res + 6; - pbreak = TRUE; - } - else { - i = session->rx_i; - } - } - } - else if ( !field ) { - field = add_field( rec ); - field->data = &session->rx_dbuf[i]; - } - session->rx_dbuf[i] = '\0'; - rec = add_record( &packet ); - field = NULL; - - break; - case CP_FLD_TERM : - /* new field */ - session->rx_dbuf[i] = '\0'; - if ( !field ) { - field = add_field( rec ); - field->data = &session->rx_dbuf[i]; - } - field = NULL; - break; - case CP_PKT_TERM : - /* packet is done! */ - session->rx_dbuf[i] = '\0'; - pbreak = TRUE; - break; - default : - /* skip non special characters */ - if ( !field ) { - field = add_field( rec ); - field->data = &session->rx_dbuf[i]; - } - field->len++; - break; - } - - i++; - } - - if ( packet.rcount < 2 ) { - /* bad packet */ - purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Invalid packet received from MXit." ) ); - free_rx_packet( &packet ); - continue; - } - - session->rx_dbuf[session->rx_i] = '\0'; - packet.errcode = atoi( packet.records[1]->fields[0]->data ); - - purple_debug_info( MXIT_PLUGIN_ID, "Packet received CMD:%i (%i)\n", packet.cmd, packet.errcode ); -#ifdef DEBUG_PROTOCOL - /* debug */ - dump_packet( &packet ); -#endif - - /* reset the out ack */ - if ( session->outack == packet.cmd ) { - /* outstanding ack received from mxit server */ - session->outack = 0; - } - - /* check packet status */ - if ( packet.errcode != MXIT_ERRCODE_SUCCESS ) { - /* error reply! */ - if ( ( packet.records[1]->fcount > 1 ) && ( packet.records[1]->fields[1]->data ) ) - packet.errmsg = packet.records[1]->fields[1]->data; - else - packet.errmsg = NULL; - - res = process_error_response( session, &packet ); - } - else { - /* success reply! */ - res = process_success_response( session, &packet ); - } - - /* free up the packet resources */ - free_rx_packet( &packet ); - } - - if ( session->outack == 0 ) - mxit_manage_queue( session ); - - return res; -} - - -/*------------------------------------------------------------------------ - * Callback when data is received from the MXit server. - * - * @param user_data The MXit session object - * @param source The file-descriptor on which data was received - * @param cond Condition which caused the callback (PURPLE_INPUT_READ) - */ -void mxit_cb_rx( gpointer user_data, gint source, PurpleInputCondition cond ) -{ - struct MXitSession* session = (struct MXitSession*) user_data; - char ch; - int res; - int len; - - if ( session->rx_state == RX_STATE_RLEN ) { - /* we are reading in the packet length */ - len = read( session->fd, &ch, 1 ); - if ( len < 0 ) { - /* connection error */ - 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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x02)" ) ); - return; - } - else { - /* byte read */ - if ( ch == CP_REC_TERM ) { - /* the end of the length record found */ - 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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x03)" ) ); - } - session->rx_state = RX_STATE_DATA; - session->rx_i = 0; - } - else { - /* still part of the packet length record */ - session->rx_lbuf[session->rx_i] = ch; - session->rx_i++; - if ( session->rx_i >= sizeof( session->rx_lbuf ) ) { - /* malformed packet length record (too long) */ - purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x04)" ) ); - return; - } - } - } - } - else if ( session->rx_state == RX_STATE_DATA ) { - /* we are reading in the packet data */ - len = read( session->fd, &session->rx_dbuf[session->rx_i], session->rx_res ); - if ( len < 0 ) { - /* connection error */ - 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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x06)" ) ); - return; - } - else { - /* data read */ - session->rx_i += len; - session->rx_res -= len; - - if ( session->rx_res == 0 ) { - /* ok, so now we have read in the whole packet */ - session->rx_state = RX_STATE_PROC; - } - } - } - - if ( session->rx_state == RX_STATE_PROC ) { - /* we have a full packet, which we now need to process */ - res = mxit_parse_packet( session ); - - if ( res == 0 ) { - /* we are still logged in */ - session->rx_state = RX_STATE_RLEN; - session->rx_res = 0; - session->rx_i = 0; - } - } -} - - -/*------------------------------------------------------------------------ - * Log the user off MXit and close the connection - * - * @param session The MXit session object - */ -void mxit_close_connection( struct MXitSession* session ) -{ - purple_debug_info( MXIT_PLUGIN_ID, "mxit_close_connection\n" ); - - if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) { - /* we are already closed */ - return; - } - else if ( session->flags & MXIT_FLAG_LOGGEDIN ) { - /* we are currently logged in so we need to send a logout packet */ - if ( !session->http ) { - mxit_send_logout( session ); - } - session->flags &= ~MXIT_FLAG_LOGGEDIN; - } - session->flags &= ~MXIT_FLAG_CONNECTED; - - /* cancel all outstanding async calls */ - purple_http_connection_set_destroy(session->async_http_reqs); - session->async_http_reqs = NULL; - - /* remove the input cb function */ - if ( session->inpa ) { - purple_input_remove( session->inpa ); - session->inpa = 0; - } - - /* remove HTTP poll timer */ - if ( session->http_timer_id > 0 ) - purple_timeout_remove( session->http_timer_id ); - - /* remove slow queue manager timer */ - if ( session->q_slow_timer_id > 0 ) - purple_timeout_remove( session->q_slow_timer_id ); - - /* remove fast queue manager timer */ - if ( session->q_fast_timer_id > 0 ) - purple_timeout_remove( session->q_fast_timer_id ); - - /* remove all groupchat rooms */ - while ( session->rooms != NULL ) { - struct multimx* multimx = (struct multimx *) session->rooms->data; - - session->rooms = g_list_remove( session->rooms, multimx ); - - free( multimx ); - } - g_list_free( session->rooms ); - session->rooms = NULL; - - /* remove all rx chats names */ - while ( session->active_chats != NULL ) { - char* chat = (char*) session->active_chats->data; - - session->active_chats = g_list_remove( session->active_chats, chat ); - - g_free( chat ); - } - g_list_free( session->active_chats ); - session->active_chats = NULL; - - /* clear the internal invites */ - while ( session->invites != NULL ) { - struct contact* contact = (struct contact*) session->invites->data; - - session->invites = g_list_remove( session->invites, contact ); - - if ( contact->msg ) - g_free( contact->msg ); - if ( contact->statusMsg ) - g_free( contact->statusMsg ); - if ( contact->profile ) - g_free( contact->profile ); - g_free( contact ); - } - g_list_free( session->invites ); - session->invites = NULL; - - /* free profile information */ - if ( session->profile ) - free( session->profile ); - - /* free custom emoticons */ - mxit_free_emoticon_cache( session ); - - /* free allocated memory */ - if ( session->uid ) - g_free( session->uid ); - g_free( session->encpwd ); - session->encpwd = NULL; - - /* flush all the commands still in the queue */ - flush_queue( session ); -} -
--- a/libpurple/protocols/mxit/protocol.h Sun Aug 18 01:52:32 2013 +0530 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,352 +0,0 @@ -/* - * MXit Protocol libPurple Plugin - * - * -- MXit client protocol implementation -- - * - * Pieter Loubser <libpurple@mxit.com> - * - * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. - * <http://www.mxitlifestyle.com> - * - * 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 _MXIT_PROTO_H_ -#define _MXIT_PROTO_H_ - - -/* Client protocol constants */ -#define CP_SOCK_REC_TERM '\x00' /* socket record terminator */ -#define CP_HTTP_REC_TERM '\x26' /* http record terminator '&' */ -#define CP_FLD_TERM '\x01' /* field terminator */ -#define CP_PKT_TERM '\x02' /* packet terminator */ - - -#define CP_MAX_PACKET ( 1 * 1000 * 1000 ) /* maximum client protocol packet size (1 MB) */ -#define CP_MAX_FILESIZE ( CP_MAX_PACKET - 1000 ) /* maximum file size (reserve some space for packet headers) */ -#define MXIT_EMOTICON_SIZE 18 /* icon size for custom emoticons */ -#define CP_MAX_STATUS_MSG 250 /* maximum status message length (in characters) */ - -/* Avatars */ -#define MXIT_AVATAR_SIZE 96 /* default avatar image size 96x96 */ -#define MXIT_AVATAR_TYPE "PNG" /* request avatars in this file type (only a suggestion) */ -#define MXIT_AVATAR_BITDEPT 24 /* request avatars with this bit depth (only a suggestion) */ - -/* Protocol error codes */ -#define MXIT_ERRCODE_SUCCESS 0 -#define MXIT_ERRCODE_REDIRECT 16 -#define MXIT_ERRCODE_LOGGEDOUT 42 - -/* MXit client features */ -#define MXIT_CF_NONE 0x000000 -#define MXIT_CF_FORMS 0x000001 -#define MXIT_CF_FILE_TRANSFER 0x000002 -#define MXIT_CF_CAMERA 0x000004 -#define MXIT_CF_COMMANDS 0x000008 -#define MXIT_CF_SMS 0x000010 -#define MXIT_CF_FILE_ACCESS 0x000020 -#define MXIT_CF_MIDP2 0x000040 -#define MXIT_CF_SKINS 0x000080 -#define MXIT_CF_AUDIO 0x000100 -#define MXIT_CF_ENCRYPTION 0x000200 -#define MXIT_CF_VOICE_REC 0x000400 -#define MXIT_CF_VECTOR_GFX 0x000800 -#define MXIT_CF_IMAGES 0x001000 -#define MXIT_CF_MARKUP 0x002000 -#define MXIT_CF_VIBES 0x004000 -#define MXIT_CF_SELECT_CONTACT 0x008000 -#define MXIT_CF_CUSTOM_EMO 0x010000 -#define MXIT_CF_ALERT_PROFILES 0x020000 -#define MXIT_CF_EXT_MARKUP 0x040000 -#define MXIT_CF_PLAIN_PWD 0x080000 -#define MXIT_CF_NO_GATEWAYS 0x100000 -#define MXIT_CF_NO_AVATARS 0x200000 -#define MXIT_CF_GAMING 0x400000 -#define MXIT_CF_GAMING_UPDATE 0x800000 -#define MXIT_CF_VOICE 0x1000000 -#define MXIT_CF_VIDEO 0x2000000 -#define MXIT_CF_TOUCHSCREEN 0x4000000 -#define MXIT_CF_SVC_CONNECTION 0x8000000 -#define MXIT_CF_MXML 0x10000000 -#define MXIT_CF_TYPING_NOTIFY 0x20000000 - -/* 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 | MXIT_CF_TYPING_NOTIFY ) - - -#define MXIT_PING_INTERVAL ( 5 * 60 ) /* ping the server after X seconds of being idle (5 minutes) */ -#define MXIT_ACK_TIMEOUT ( 30 ) /* timeout after waiting X seconds for an ack from the server (30 seconds) */ -#define MXIT_TX_DELAY ( 100 ) /* delay between sending consecutive packets (100 ms) */ - -/* MXit client version */ -#define MXIT_CP_DISTCODE 'P' /* client distribution code (magic, do not touch!) */ -#define MXIT_CP_ARCH "Y" /* client architecture series (Y not for Yoda but for PC-client) */ -#define MXIT_CLIENT_ID "LP" /* client ID as specified by MXit */ -#define MXIT_CP_PLATFORM "PURPLE" /* client platform */ -#define MXIT_CP_PROTO_VESION 63 /* client protocol version */ - -/* set operating system name */ -#if defined( __APPLE__ ) -#define MXIT_CP_OS "apple" -#elif defined( _WIN32 ) -#define MXIT_CP_OS "windows" -#elif defined( __linux__ ) -#define MXIT_CP_OS "linux" -#else -#define MXIT_CP_OS "unknown" -#endif - -/* Client capabilities */ -#define MXIT_CP_CAP "utf8=true;cid="MXIT_CLIENT_ID - -/* Client settings */ -#define MAX_QUEUE_SIZE ( 1 << 5 ) /* tx queue size (32 packets) */ -#define MXIT_POPUP_WIN_NAME "MXit Notification" /* popup window name */ -#define MXIT_DEFAULT_LOCALE "en" /* default locale setting */ -#define MXIT_DEFAULT_LOC "planetpurple" /* the default location for registration */ - -/* Client protocol commands */ -#define CP_CMD_LOGIN 0x0001 /* (1) login */ -#define CP_CMD_LOGOUT 0x0002 /* (2) logout */ -#define CP_CMD_CONTACT 0x0003 /* (3) get contacts */ -#define CP_CMD_UPDATE 0x0005 /* (5) update contact information */ -#define CP_CMD_INVITE 0x0006 /* (6) subscribe to new contact */ -#define CP_CMD_PRESENCE 0x0007 /* (7) get presence */ -#define CP_CMD_REMOVE 0x0008 /* (8) remove contact */ -#define CP_CMD_RX_MSG 0x0009 /* (9) get new messages */ -#define CP_CMD_TX_MSG 0x000A /* (10) send new message */ -#define CP_CMD_REGISTER 0x000B /* (11) register */ -//#define CP_CMD_PROFILE_SET 0x000C /* (12) set profile (DEPRECATED see CP_CMD_EXTPROFILE_SET) */ -#define CP_CMD_SUGGESTCONTACTS 0x000D /* (13) suggest contacts */ -#define CP_CMD_POLL 0x0011 /* (17) poll the HTTP server for an update */ -//#define CP_CMD_PROFILE_GET 0x001A /* (26) get profile (DEPRECATED see CP_CMD_EXTPROFILE_GET) */ -#define CP_CMD_MEDIA 0x001B /* (27) get multimedia message */ -#define CP_CMD_SPLASHCLICK 0x001F /* (31) splash-screen clickthrough */ -#define CP_CMD_STATUS 0x0020 /* (32) set shown presence & status */ -#define CP_CMD_MSGEVENT 0x0023 /* (35) Raise message event */ -#define CP_CMD_GOT_MSGEVENT 0x0024 /* (36) Get message event */ -#define CP_CMD_MOOD 0x0029 /* (41) set mood */ -#define CP_CMD_KICK 0x002B /* (43) login kick */ -#define CP_CMD_GRPCHAT_CREATE 0x002C /* (44) create new groupchat */ -#define CP_CMD_GRPCHAT_INVITE 0x002D /* (45) add new groupchat member */ -#define CP_CMD_NEW_SUB 0x0033 /* (51) get new subscription */ -#define CP_CMD_ALLOW 0x0034 /* (52) allow subscription */ -#define CP_CMD_DENY 0x0037 /* (55) deny subscription */ -#define CP_CMD_EXTPROFILE_GET 0x0039 /* (57) get extended profile */ -#define CP_CMD_EXTPROFILE_SET 0x003A /* (58) set extended profile */ -#define CP_CMD_PING 0x03E8 /* (1000) ping (keepalive) */ - -/* HTTP connection */ -#define MXIT_HTTP_POLL_MIN 7 /* minimum time between HTTP polls (seconds) */ -#define MXIT_HTTP_POLL_MAX ( 10 * 60 ) /* maximum time between HTTP polls (seconds) */ - -/* receiver states */ -#define RX_STATE_RLEN 0x01 /* reading packet length section */ -#define RX_STATE_DATA 0x02 /* reading packet data section */ -#define RX_STATE_PROC 0x03 /* process read data */ - -/* message flags */ -#define CP_MSG_NOTIFY_DELIVERY 0x0002 /* request delivery notification */ -#define CP_MSG_NOTIFY_READ 0x0004 /* request read notification */ -#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 */ -#define CP_MSG_FAREWELL 0x0800 /* this is a farewell message */ - -/* redirect types */ -#define CP_REDIRECT_PERMANENT 1 /* permanent redirect */ -#define CP_REDIRECT_TEMPORARY 2 /* temporary redirect */ - -/* message tx types */ -#define CP_MSGTYPE_NORMAL 0x01 /* normal message */ -#define CP_MSGTYPE_CHAT 0x02 /* chat message */ -#define CP_MSGTYPE_HEADLINE 0x03 /* headline message */ -#define CP_MSGTYPE_ERROR 0x04 /* error message */ -#define CP_MSGTYPE_GROUPCHAT 0x05 /* groupchat message */ -#define CP_MSGTYPE_FORM 0x06 /* mxit custom form */ -#define CP_MSGTYPE_COMMAND 0x07 /* mxit command */ - -/* message event types */ -#define CP_MSGEVENT_DELIVERED 0x02 /* message was delivered */ -#define CP_MSGEVENT_DISPLAYED 0x04 /* message was viewed */ -#define CP_MSGEVENT_TYPING 0x10 /* user is typing */ -#define CP_MSGEVENT_STOPPED 0x20 /* user has stopped typing */ -#define CP_MSGEVENT_ANGRY 0x40 /* user is typing angrily */ -#define CP_MSGEVENT_ERASING 0x80 /* user is erasing text */ - -/* 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) (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) */ -#define CP_PROFILE_AVATAR "avatarid" /* Avatar ID (String) */ -#define CP_PROFILE_MODIFIED "lastmodified" /* Last-Modified timestamp */ -#define CP_PROFILE_TITLE "title" /* Title (UTF8 String) */ -#define CP_PROFILE_FIRSTNAME "firstname" /* First name (UTF8 String) */ -#define CP_PROFILE_LASTNAME "lastname" /* Last name (UTF8 String) */ -#define CP_PROFILE_EMAIL "email" /* Email address (UTF8 String) */ -#define CP_PROFILE_MOBILENR "mobilenumber" /* Mobile Number (UTF8 String) */ -#define CP_PROFILE_REGCOUNTRY "registeredcountry" /* Registered Country Code (UTF8 String) */ -#define CP_PROFILE_FLAGS "flags" /* Profile flags (Bitset) */ -#define CP_PROFILE_LASTSEEN "lastseen" /* Last-Online timestamp */ -#define CP_PROFILE_WHEREAMI "whereami" /* Where am I / Where I live */ -#define CP_PROFILE_ABOUTME "aboutme" /* About me */ -#define CP_PROFILE_RELATIONSHIP "relationship" /* Relationship Status */ - -/* extended profile field types */ -#define CP_PROFILE_TYPE_BOOL 0x02 /* boolean (0 or 1) */ -#define CP_PROFILE_TYPE_SHORT 0x04 /* short (16-bit) */ -#define CP_PROFILE_TYPE_INT 0x05 /* integer (32-bit) */ -#define CP_PROFILE_TYPE_LONG 0x06 /* long (64-bit) */ -#define CP_PROFILE_TYPE_UTF8 0x0A /* UTF8 string */ -#define CP_PROFILE_TYPE_DATE 0x0B /* date-time (ISO 8601 format) */ - -/* profile flags */ -#define CP_PROF_NOT_SEARCHABLE 0x02 /* user cannot be searched for */ -#define CP_PROF_NOT_SUGGESTABLE 0x08 /* user cannot be suggested as friend */ -#define CP_PROF_DOBLOCKED 0x40 /* date-of-birth cannot be changed */ - -/* suggestion types */ -#define CP_SUGGEST_ADDRESSBOOK 0 /* address book search */ -#define CP_SUGGEST_FRIENDS 1 /* suggested friends */ -#define CP_SUGGEST_SEARCH 2 /* free-text search */ -#define CP_SUGGEST_MXITID 3 /* MXitId search */ - -/* define this to enable protocol debugging (very verbose logging) */ -#define DEBUG_PROTOCOL - - -/* ======================================================================================= */ - -struct MXitSession; - -/*------------------------------------------*/ - -struct field { - char* data; - int len; -}; - -struct record { - struct field** fields; - int fcount; -}; - -struct rx_packet { - int cmd; - int errcode; - char* errmsg; - struct record** records; - int rcount; -}; - -struct tx_packet { - int cmd; - char header[256]; - int headerlen; - char* data; - int datalen; -}; - -/*------------------------------------------*/ - - -/* - * A received message data object - */ -struct RXMsgData { - struct MXitSession* session; /* MXit session object */ - char* from; /* the sender's name */ - time_t timestamp; /* time at which the message was sent */ - GString* msg; /* newly created message converted to libPurple formatting */ - gboolean got_img; /* flag to say if this message got any images/emoticons embedded */ - short img_count; /* the amount of images/emoticons still outstanding for the message */ - int chatid; /* multimx chatroom id */ - int flags; /* libPurple conversation flags */ - gboolean converted; /* true if the message has been completely parsed and converted to libPurple markup */ - gboolean processed; /* the message has been processed completely and should be freed up */ -}; - - - -/* - * The packet transmission queue. - */ -struct tx_queue { - struct tx_packet* packets[MAX_QUEUE_SIZE]; /* array of packet pointers */ - int count; /* number of packets queued */ - int rd_i; /* queue current read index (queue offset for reading a packet) */ - int wr_i; /* queue current write index (queue offset for adding new packet) */ -}; - - -/* ======================================================================================= */ - -void mxit_popup( int type, const char* heading, const char* message ); -void mxit_strip_domain( char* username ); -gboolean find_active_chat( const GList* chats, const char* who ); - -void mxit_cb_rx( gpointer data, gint source, PurpleInputCondition cond ); -gboolean mxit_manage_queue_slow( gpointer user_data ); -gboolean mxit_manage_queue_fast( gpointer user_data ); -gboolean mxit_manage_polling( gpointer user_data ); - -void mxit_send_register( struct MXitSession* session ); -void mxit_send_login( struct MXitSession* session ); -void mxit_send_logout( struct MXitSession* session ); -void mxit_send_ping( struct MXitSession* session ); -void mxit_send_poll( struct MXitSession* session ); - -void mxit_send_presence( struct MXitSession* session, int presence, const char* statusmsg ); -void mxit_send_mood( struct MXitSession* session, int mood ); -void mxit_send_message( struct MXitSession* session, const char* to, const char* msg, gboolean parse_markup, gboolean is_command ); - -void mxit_send_extprofile_update( struct MXitSession* session, const char* password, unsigned int nr_attrib, const char* attributes ); -void mxit_send_extprofile_request( struct MXitSession* session, const char* username, unsigned int nr_attrib, const char* attribute[] ); - -void mxit_send_suggest_friends( struct MXitSession* session, int max, unsigned int nr_attrib, const char* attribute[] ); -void mxit_send_suggest_search( struct MXitSession* session, int max, const char* text, unsigned int nr_attrib, const char* attribute[] ); - -void mxit_send_invite( struct MXitSession* session, const char* username, gboolean mxitid, const char* alias, const char* groupname, const char* message ); -void mxit_send_remove( struct MXitSession* session, const char* username ); -void mxit_send_allow_sub( struct MXitSession* session, const char* username, const char* alias ); -void mxit_send_deny_sub( struct MXitSession* session, const char* username, const char* reason ); -void mxit_send_update_contact( struct MXitSession* session, const char* username, const char* alias, const char* groupname ); -void mxit_send_splashclick( struct MXitSession* session, const char* splashid ); -void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event); - -void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen ); -void mxit_send_file_reject( struct MXitSession* session, const char* fileid ); -void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int filesize, int offset ); -void mxit_send_file_received( struct MXitSession* session, const char* fileid, short status ); -void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen ); -void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const char* avatarId ); - -void mxit_send_groupchat_create( struct MXitSession* session, const char* groupname, int nr_usernames, const char* usernames[] ); -void mxit_send_groupchat_invite( struct MXitSession* session, const char* roomid, int nr_usernames, const char* usernames[] ); - -int mxit_parse_packet( struct MXitSession* session ); -void dump_bytes( struct MXitSession* session, const char* buf, int len ); -void mxit_close_connection( struct MXitSession* session ); -gint64 mxit_now_milli( void ); - - -#endif /* _MXIT_PROTO_H_ */ -
--- a/libpurple/protocols/mxit/roster.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/mxit/roster.c Sun Aug 18 01:53:00 2013 +0530 @@ -26,7 +26,7 @@ #include "internal.h" #include "debug.h" -#include "protocol.h" +#include "client.h" #include "mxit.h" #include "roster.h" @@ -325,17 +325,17 @@ /* now re-instate his presence again */ if ( contact ) { - /* update the buddy's status (reference: "libpurple/prpl.h") */ + /* update the buddy's status (reference: "libpurple/protocol.h") */ if ( contact->statusMsg ) - purple_prpl_got_user_status( session->acc, newbuddy->name, mxit_statuses[contact->presence].id, "message", contact->statusMsg, NULL ); + purple_protocol_got_user_status( session->acc, newbuddy->name, mxit_statuses[contact->presence].id, "message", contact->statusMsg, NULL ); else - purple_prpl_got_user_status( session->acc, newbuddy->name, mxit_statuses[contact->presence].id, NULL ); + purple_protocol_got_user_status( session->acc, newbuddy->name, mxit_statuses[contact->presence].id, NULL ); /* update the buddy's mood */ if ( contact->mood == MXIT_MOOD_NONE ) - purple_prpl_got_user_status_deactive( session->acc, newbuddy->name, "mood" ); + purple_protocol_got_user_status_deactive( session->acc, newbuddy->name, "mood" ); else - purple_prpl_got_user_status( session->acc, newbuddy->name, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL ); + purple_protocol_got_user_status( session->acc, newbuddy->name, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL ); /* update avatar */ if ( contact->avatarId ) { @@ -422,14 +422,14 @@ else contact->avatarId = NULL; - /* update the buddy's status (reference: "libpurple/prpl.h") */ - purple_prpl_got_user_status( session->acc, contact->username, mxit_statuses[contact->presence].id, NULL ); + /* update the buddy's status (reference: "libpurple/protocol.h") */ + purple_protocol_got_user_status( session->acc, contact->username, mxit_statuses[contact->presence].id, NULL ); /* update the buddy's mood */ if ( contact->mood == MXIT_MOOD_NONE ) - purple_prpl_got_user_status_deactive( session->acc, contact->username, "mood" ); + purple_protocol_got_user_status_deactive( session->acc, contact->username, "mood" ); else - purple_prpl_got_user_status( session->acc, contact->username, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL ); + purple_protocol_got_user_status( session->acc, contact->username, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL ); } @@ -488,17 +488,17 @@ if ( ( statusMsg ) && ( statusMsg[0] != '\0' ) ) contact->statusMsg = g_markup_escape_text( statusMsg, -1 ); - /* update the buddy's status (reference: "libpurple/prpl.h") */ + /* update the buddy's status (reference: "libpurple/protocol.h") */ if ( contact->statusMsg ) - purple_prpl_got_user_status( session->acc, username, mxit_statuses[contact->presence].id, "message", contact->statusMsg, NULL ); + purple_protocol_got_user_status( session->acc, username, mxit_statuses[contact->presence].id, "message", contact->statusMsg, NULL ); else - purple_prpl_got_user_status( session->acc, username, mxit_statuses[contact->presence].id, NULL ); + purple_protocol_got_user_status( session->acc, username, mxit_statuses[contact->presence].id, NULL ); /* update the buddy's mood */ if ( contact->mood == MXIT_MOOD_NONE ) - purple_prpl_got_user_status_deactive( session->acc, username, "mood" ); + purple_protocol_got_user_status_deactive( session->acc, username, "mood" ); else - purple_prpl_got_user_status( session->acc, username, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL ); + purple_protocol_got_user_status( session->acc, username, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL ); }
--- a/libpurple/protocols/mxit/splashscreen.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/mxit/splashscreen.c Sun Aug 18 01:53:00 2013 +0530 @@ -28,7 +28,7 @@ #include "imgstore.h" #include "request.h" -#include "protocol.h" +#include "client.h" #include "mxit.h" #include "splashscreen.h"
--- a/libpurple/protocols/myspace/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/myspace/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -41,4 +41,5 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(DEBUG_CFLAGS)
--- a/libpurple/protocols/myspace/myspace.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/myspace/myspace.c Sun Aug 18 01:53:00 2013 +0530 @@ -32,8 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#define PURPLE_PLUGIN - +#include "plugins.h" #include "myspace.h" static void msim_set_status(PurpleAccount *account, PurpleStatus *status); @@ -1301,7 +1300,7 @@ PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, - MSIM_PRPL_VERSION_STRING); + MSIM_PROTOCOL_VERSION_STRING); ret = msim_send_bm(session, username, our_info, MSIM_BM_UNOFFICIAL_CLIENT); @@ -1440,14 +1439,14 @@ g_free(unrecognized_msg); } - purple_prpl_got_user_status(session->account, username, purple_primitive_get_id_from_type(purple_status_code), NULL); + purple_protocol_got_user_status(session->account, username, purple_primitive_get_id_from_type(purple_status_code), NULL); if (status_code == MSIM_STATUS_CODE_IDLE) { purple_debug_info("msim", "msim_status: got idle: %s\n", username); - purple_prpl_got_user_idle(session->account, username, TRUE, 0); + purple_protocol_got_user_idle(session->account, username, TRUE, 0); } else { /* All other statuses indicate going back to non-idle. */ - purple_prpl_got_user_idle(session->account, username, FALSE, 0); + purple_protocol_got_user_idle(session->account, username, FALSE, 0); } #ifdef MSIM_SEND_CLIENT_VERSION @@ -2919,7 +2918,7 @@ /** * Send raw data to the server, possibly with embedded NULs. * - * Used in prpl_info struct, so that plugins can have the most possible + * Used in protocol struct, so that plugins can have the most possible * control of what is sent over the connection. Inside this prpl, * msim_send_raw() is used, since it sends NUL-terminated strings (easier). * @@ -3000,10 +2999,100 @@ } /** + * Called when friends have been imported to buddy list on server. + */ +static void +msim_import_friends_cb(MsimSession *session, const MsimMessage *reply, gpointer user_data) +{ + MsimMessage *body; + gchar *completed; + + /* Check if the friends were imported successfully. */ + body = msim_msg_get_dictionary(reply, "body"); + g_return_if_fail(body != NULL); + completed = msim_msg_get_string(body, "Completed"); + msim_msg_free(body); + g_return_if_fail(completed != NULL); + if (!g_str_equal(completed, "True")) + { + purple_debug_info("msim_import_friends_cb", + "failed to import friends: %s", completed); + purple_notify_error(session->account, _("Add friends from MySpace.com"), + _("Importing friends failed"), NULL); + g_free(completed); + return; + } + g_free(completed); + + purple_debug_info("msim_import_friends_cb", + "added friends to server-side buddy list, requesting new contacts from server"); + + msim_get_contact_list(session, MSIM_CONTACT_LIST_IMPORT_ALL_FRIENDS); + + /* TODO: show, X friends have been added */ +} + +/** + * Import friends from myspace.com. + */ +static void msim_import_friends(PurpleProtocolAction *action) +{ + PurpleConnection *gc; + MsimSession *session; + gchar *group_name; + + gc = action->connection; + session = purple_connection_get_protocol_data(gc); + + group_name = "MySpace Friends"; + + g_return_if_fail(msim_send(session, + "persist", MSIM_TYPE_INTEGER, 1, + "sesskey", MSIM_TYPE_INTEGER, session->sesskey, + "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_PUT, + "dsn", MSIM_TYPE_INTEGER, MC_IMPORT_ALL_FRIENDS_DSN, + "lid", MSIM_TYPE_INTEGER, MC_IMPORT_ALL_FRIENDS_LID, + "uid", MSIM_TYPE_INTEGER, session->userid, + "rid", MSIM_TYPE_INTEGER, + msim_new_reply_callback(session, msim_import_friends_cb, NULL), + "body", MSIM_TYPE_STRING, + g_strdup_printf("GroupName=%s", group_name), + NULL)); +} + +/** + * Actions menu for account. + */ +static GList * +msim_get_actions(PurpleConnection *gc) +{ + GList *menu; + PurpleProtocolAction *act; + + menu = NULL; + +#if 0 + /* TODO: find out how */ + act = purple_protocol_action_new(_("Find people..."), msim_); + menu = g_list_append(menu, act); + + act = purple_protocol_action_new(_("Change IM name..."), NULL); + menu = g_list_append(menu, act); +#endif + + act = purple_protocol_action_new(_("Add friends from MySpace.com"), msim_import_friends); + menu = g_list_append(menu, act); + + return menu; +} + +/** * Callbacks called by Purple, to access this plugin. */ -static PurplePluginProtocolInfo prpl_info = { - sizeof(PurplePluginProtocolInfo), /* struct_size */ +static PurpleProtocol protocol = { + "prpl-myspace", /* id */ + "MySpaceIM", /* name */ + sizeof(PurpleProtocol), /* struct_size */ /* options */ OPT_PROTO_USE_POINTSIZE /* specify font size in sane point size */ | OPT_PROTO_MAIL_CHECK, @@ -3012,6 +3101,7 @@ NULL, /* user_splits */ NULL, /* protocol_options */ NO_BUDDY_ICONS, /* icon_spec - TODO: eventually should add this */ + msim_get_actions, /* get_actions */ msim_list_icon, /* list_icon */ NULL, /* list_emblems */ msim_status_text, /* status_text */ @@ -3066,7 +3156,7 @@ NULL, /* send_file */ NULL, /* new_xfer */ msim_offline_message, /* offline_message */ - NULL, /* whiteboard_prpl_ops */ + NULL, /* whiteboard_protocol_ops */ msim_send_really_raw, /* send_raw */ NULL, /* roomlist_room_serialize */ NULL, /* unregister_user */ @@ -3080,139 +3170,6 @@ NULL /* get_public_alias */ }; -/** - * Load the plugin. - */ -static gboolean -msim_load(PurplePlugin *plugin) -{ - return TRUE; -} - -/** - * Called when friends have been imported to buddy list on server. - */ -static void -msim_import_friends_cb(MsimSession *session, const MsimMessage *reply, gpointer user_data) -{ - MsimMessage *body; - gchar *completed; - - /* Check if the friends were imported successfully. */ - body = msim_msg_get_dictionary(reply, "body"); - g_return_if_fail(body != NULL); - completed = msim_msg_get_string(body, "Completed"); - msim_msg_free(body); - g_return_if_fail(completed != NULL); - if (!g_str_equal(completed, "True")) - { - purple_debug_info("msim_import_friends_cb", - "failed to import friends: %s", completed); - purple_notify_error(session->account, _("Add friends from MySpace.com"), - _("Importing friends failed"), NULL); - g_free(completed); - return; - } - g_free(completed); - - purple_debug_info("msim_import_friends_cb", - "added friends to server-side buddy list, requesting new contacts from server"); - - msim_get_contact_list(session, MSIM_CONTACT_LIST_IMPORT_ALL_FRIENDS); - - /* TODO: show, X friends have been added */ -} - -/** - * Import friends from myspace.com. - */ -static void msim_import_friends(PurplePluginAction *action) -{ - PurpleConnection *gc; - MsimSession *session; - gchar *group_name; - - gc = (PurpleConnection *)action->context; - session = purple_connection_get_protocol_data(gc); - - group_name = "MySpace Friends"; - - g_return_if_fail(msim_send(session, - "persist", MSIM_TYPE_INTEGER, 1, - "sesskey", MSIM_TYPE_INTEGER, session->sesskey, - "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_PUT, - "dsn", MSIM_TYPE_INTEGER, MC_IMPORT_ALL_FRIENDS_DSN, - "lid", MSIM_TYPE_INTEGER, MC_IMPORT_ALL_FRIENDS_LID, - "uid", MSIM_TYPE_INTEGER, session->userid, - "rid", MSIM_TYPE_INTEGER, - msim_new_reply_callback(session, msim_import_friends_cb, NULL), - "body", MSIM_TYPE_STRING, - g_strdup_printf("GroupName=%s", group_name), - NULL)); -} - -/** - * Actions menu for account. - */ -static GList * -msim_actions(PurplePlugin *plugin, gpointer context /* PurpleConnection* */) -{ - GList *menu; - PurplePluginAction *act; - - menu = NULL; - -#if 0 - /* TODO: find out how */ - act = purple_plugin_action_new(_("Find people..."), msim_); - menu = g_list_append(menu, act); - - act = purple_plugin_action_new(_("Change IM name..."), NULL); - menu = g_list_append(menu, act); -#endif - - act = purple_plugin_action_new(_("Add friends from MySpace.com"), msim_import_friends); - menu = g_list_append(menu, act); - - return menu; -} - -/** - * Based on MSN's plugin info comments. - */ -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-myspace", /**< id */ - "MySpaceIM", /**< name */ - MSIM_PRPL_VERSION_STRING, /**< version */ - /** summary */ - "MySpaceIM Protocol Plugin", - /** description */ - "MySpaceIM Protocol Plugin", - "Jeff Connelly <jeff2@soc.pidgin.im>", /**< author */ - "https://developer.pidgin.im/wiki/MySpaceIM/", /**< homepage */ - - msim_load, /**< load */ - NULL, /**< unload */ - NULL, /**< destroy */ - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, /**< prefs_info */ - msim_actions, /**< msim_actions */ - NULL, /**< reserved1 */ - NULL, /**< reserved2 */ - NULL, /**< reserved3 */ - NULL /**< reserved4 */ -}; - #ifdef MSIM_SELF_TEST /* * Test functions. @@ -3502,10 +3459,32 @@ } /** - * Initialize plugin. + * Query the plugin */ -static void -init_plugin(PurplePlugin *plugin) +static PurplePluginInfo * +plugin_query(GError **error) +{ + return purple_plugin_info_new( + "id", "prpl-myspace", + "name", "MySpaceIM", + "version", MSIM_PROTOCOL_VERSION_STRING, + "category", "Protocol", + "summary", "MySpaceIM Protocol Plugin", + "description", "MySpaceIM Protocol Plugin", + "author", "Jeff Connelly <jeff2@soc.pidgin.im>", + "website", "https://developer.pidgin.im/wiki/MySpaceIM/", + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); +} + +/** + * Load the plugin. + */ +static gboolean +plugin_load(PurplePlugin *plugin, GError **error) { #ifdef MSIM_SELF_TEST msim_test_all(); @@ -3513,45 +3492,53 @@ #endif /* MSIM_SELF_TEST */ PurpleAccountOption *option; - static gboolean initialized = FALSE; /* TODO: default to automatically try different ports. Make the user be * able to set the first port to try (like LastConnectedPort in Windows client). */ option = purple_account_option_string_new(_("Connect server"), "server", MSIM_SERVER); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_int_new(_("Connect port"), "port", MSIM_PORT); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); #ifdef MSIM_USER_WANTS_TO_CONFIGURE_STATUS_TEXT option = purple_account_option_bool_new(_("Show display name in status text"), "show_display_name", TRUE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_bool_new(_("Show headline in status text"), "show_headline", TRUE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); #endif #ifdef MSIM_USER_WANTS_TO_DISABLE_EMOTICONS option = purple_account_option_bool_new(_("Send emoticons"), "emoticons", TRUE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); #endif #ifdef MSIM_USER_REALLY_CARES_ABOUT_PRECISE_FONT_SIZES option = purple_account_option_int_new(_("Screen resolution (dots per inch)"), "dpi", MSIM_DEFAULT_DPI); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_int_new(_("Base font size (points)"), "base_font_size", MSIM_BASE_FONT_POINT_SIZE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); #endif - /* Code below only runs once. Based on oscar.c's oscar_init(). */ - if (initialized) - return; - - initialized = TRUE; - - purple_signal_connect(purple_get_core(), "uri-handler", &initialized, + purple_signal_connect(purple_get_core(), "uri-handler", &protocol, PURPLE_CALLBACK(msim_uri_handler), NULL); + + purple_protocols_add(&protocol); + + return TRUE; } -PURPLE_INIT_PLUGIN(myspace, init_plugin, info); +/** + * Unload the plugin. + */ +static gboolean +plugin_unload(PurplePlugin *plugin, GError **error) +{ + purple_protocols_remove(&protocol); + + return TRUE; +} + +PURPLE_PLUGIN_INIT(myspace, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/myspace/myspace.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/myspace/myspace.h Sun Aug 18 01:53:00 2013 +0530 @@ -39,7 +39,7 @@ #endif #include "notify.h" -#include "plugin.h" +#include "plugins.h" #include "accountopt.h" #include "version.h" #include "util.h" /* for base64 */ @@ -103,7 +103,7 @@ #define MSIM_LANGUAGE_NAME_ENGLISH "ENGLISH" /* msimprpl version string of this plugin */ -#define MSIM_PRPL_VERSION_STRING "0.18" +#define MSIM_PROTOCOL_VERSION_STRING "0.18" /* Default server */ #define MSIM_SERVER "im.myspace.akadns.net"
--- a/libpurple/protocols/myspace/user.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/myspace/user.c Sun Aug 18 01:53:00 2013 +0530 @@ -256,7 +256,7 @@ * If new_artist and new_title are NULL/empty, deactivate PURPLE_STATUS_TUNE. * * This function is useful because it lets you set the artist or title - * individually, which purple_prpl_got_user_status() doesn't do. + * individually, which purple_protocol_got_user_status() doesn't do. */ static void msim_set_artist_or_title(MsimUser *user, const char *new_artist, const char *new_title) { @@ -281,7 +281,7 @@ name = purple_buddy_get_name(user->buddy); if (!new_artist && !new_title) { - purple_prpl_got_user_status_deactive(account, name, "tune"); + purple_protocol_got_user_status_deactive(account, name, "tune"); return; } @@ -301,7 +301,7 @@ if (!new_title) new_title = prev_title; - purple_prpl_got_user_status(account, name, "tune", + purple_protocol_got_user_status(account, name, "tune", PURPLE_TUNE_TITLE, new_title, PURPLE_TUNE_ARTIST, new_artist, NULL);
--- a/libpurple/protocols/myspace/zap.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/myspace/zap.c Sun Aug 18 01:53:00 2013 +0530 @@ -179,7 +179,7 @@ zap = GPOINTER_TO_INT(zap_num_ptr); - purple_prpl_send_attention(session->gc, purple_buddy_get_name(buddy), zap); + purple_protocol_send_attention(session->gc, purple_buddy_get_name(buddy), zap); } /** Return menu, if any, for a buddy list node. */ @@ -237,7 +237,7 @@ zap = CLAMP(zap, 0, 9); - purple_prpl_got_attention(session->gc, username, zap); + purple_protocol_got_attention(session->gc, username, zap); g_free(msg_text); g_free(username);
--- a/libpurple/protocols/novell/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/novell/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -50,4 +50,5 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(DEBUG_CFLAGS) \ - $(GLIB_CFLAGS) + $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS)
--- a/libpurple/protocols/novell/novell.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/novell/novell.c Sun Aug 18 01:53:00 2013 +0530 @@ -21,7 +21,8 @@ #include "internal.h" #include "accountopt.h" #include "debug.h" -#include "prpl.h" +#include "plugins.h" +#include "protocol.h" #include "server.h" #include "nmuser.h" #include "notify.h" @@ -43,7 +44,7 @@ #define NOVELL_STATUS_TYPE_IDLE "idle" #define NOVELL_STATUS_TYPE_APPEAR_OFFLINE "appearoffline" -static PurplePlugin *my_protocol = NULL; +static PurpleProtocol *my_protocol = NULL; static gboolean _is_disconnect_error(NMERR_T err); @@ -1216,9 +1217,9 @@ } } - purple_prpl_got_user_status(account, name, status_id, + purple_protocol_got_user_status(account, name, status_id, "message", text, NULL); - purple_prpl_got_user_idle(account, name, + purple_protocol_got_user_idle(account, name, (novellstatus == NM_STATUS_AWAY_IDLE), idle); } @@ -3475,14 +3476,17 @@ _check_for_disconnect(user, rc); } -static PurplePluginProtocolInfo prpl_info = { - sizeof(PurplePluginProtocolInfo), /* struct_size */ +static PurpleProtocol protocol = { + "prpl-novell", /* id */ + "GroupWise", /* name */ + sizeof(PurpleProtocol), /* struct_size */ 0, NULL, /* user_splits */ NULL, /* protocol_options */ NO_BUDDY_ICONS, /* icon_spec */ + NULL, /* get_actions */ novell_list_icon, /* list_icon */ - NULL, /* list_emblems */ + NULL, /* list_emblems */ novell_status_text, /* status_text */ novell_tooltip_text, /* tooltip_text */ novell_status_types, /* status_types */ @@ -3535,7 +3539,7 @@ NULL, /* send_file */ NULL, /* new_xfer */ NULL, /* offline_message */ - NULL, /* whiteboard_prpl_ops */ + NULL, /* whiteboard_protocol_ops */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ NULL, /* unregister_user */ @@ -3549,55 +3553,49 @@ NULL /* get_public_alias */ }; -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-novell", /**< id */ - "GroupWise", /**< name */ - DISPLAY_VERSION, /**< version */ - /** summary */ - N_("Novell GroupWise Messenger Protocol Plugin"), - /** description */ - N_("Novell GroupWise Messenger Protocol Plugin"), - NULL, /**< author */ - PURPLE_WEBSITE, /**< homepage */ - - NULL, /**< load */ - NULL, /**< unload */ - NULL, /**< destroy */ - - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, - NULL, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - -static void -init_plugin(PurplePlugin * plugin) +static PurplePluginInfo * +plugin_query(GError **error) +{ + return purple_plugin_info_new( + "id", "prpl-novell", + "name", "GroupWise", + "version", DISPLAY_VERSION, + "category", N_("Protocol"), + "summary", N_("Novell GroupWise Messenger Protocol Plugin"), + "description", N_("Novell GroupWise Messenger Protocol Plugin"), + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); +} + +static gboolean +plugin_load(PurplePlugin *plugin, GError **error) { PurpleAccountOption *option; option = purple_account_option_string_new(_("Server address"), "server", NULL); - prpl_info.protocol_options = - g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = + g_list_append(protocol.protocol_options, option); option = purple_account_option_int_new(_("Server port"), "port", DEFAULT_PORT); - prpl_info.protocol_options = - g_list_append(prpl_info.protocol_options, option); - - my_protocol = plugin; + protocol.protocol_options = + g_list_append(protocol.protocol_options, option); + + my_protocol = &protocol; + purple_protocols_add(my_protocol); + + return TRUE; } -PURPLE_INIT_PLUGIN(novell, init_plugin, info); +static gboolean +plugin_unload(PurplePlugin *plugin, GError **error) +{ + purple_protocols_remove(my_protocol); + + return TRUE; +} + +PURPLE_PLUGIN_INIT(novell, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/null/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/null/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -20,4 +20,5 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(DEBUG_CFLAGS)
--- a/libpurple/protocols/null/nullprpl.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/null/nullprpl.c Sun Aug 18 01:53:00 2013 +0530 @@ -60,15 +60,15 @@ #include "connection.h" #include "debug.h" #include "notify.h" -#include "prpl.h" +#include "plugins.h" +#include "protocol.h" #include "roomlist.h" #include "status.h" #include "util.h" #include "version.h" - #define NULLPRPL_ID "prpl-null" -static PurplePlugin *_null_protocol = NULL; +static PurpleProtocol *_null_protocol = NULL; #define NULL_STATUS_ONLINE "online" #define NULL_STATUS_AWAY "away" @@ -86,7 +86,7 @@ /* * stores offline messages that haven't been delivered yet. maps username - * (char *) to GList * of GOfflineMessages. initialized in nullprpl_init. + * (char *) to GList * of GOfflineMessages. initialized in plugin_load. */ GHashTable* goffline_messages = NULL; @@ -171,7 +171,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(purple_connection_get_account(from), to_username, status_id, + purple_protocol_got_user_status(purple_connection_get_account(from), to_username, status_id, (message) ? "message" : NULL, message, NULL); } else { purple_debug_error("nullprpl", @@ -192,9 +192,9 @@ /* * UI callbacks */ -static void nullprpl_input_user_info(PurplePluginAction *action) +static void nullprpl_input_user_info(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *)action->context; + PurpleConnection *gc = action->connection; PurpleAccount *acct = purple_connection_get_account(gc); purple_debug_info("nullprpl", "showing 'Set User Info' dialog for %s\n", purple_account_get_username(acct)); @@ -202,20 +202,16 @@ purple_account_request_change_user_info(acct); } -/* this is set to the actions member of the PurplePluginInfo struct at the - * bottom. +/* + * prpl functions */ -static GList *nullprpl_actions(PurplePlugin *plugin, gpointer context) +static GList *nullprpl_get_actions(PurpleConnection *gc) { - PurplePluginAction *action = purple_plugin_action_new( + PurpleProtocolAction *action = purple_protocol_action_new( _("Set User Info..."), nullprpl_input_user_info); return g_list_append(NULL, action); } - -/* - * prpl functions - */ static const char *nullprpl_list_icon(PurpleAccount *acct, PurpleBuddy *buddy) { return "null"; @@ -337,7 +333,7 @@ } static GList *nullprpl_chat_info(PurpleConnection *gc) { - struct proto_chat_entry *pce; /* defined in prpl.h */ + struct proto_chat_entry *pce; /* defined in protocol.h */ purple_debug_info("nullprpl", "returning chat setting 'room'\n"); @@ -1054,15 +1050,17 @@ /* - * prpl stuff. see prpl.h for more information. + * Protocol stuff. see protocol.h for more information. */ -static PurplePluginProtocolInfo prpl_info = +static PurpleProtocol protocol = { - sizeof(PurplePluginProtocolInfo), /* struct_size */ + NULLPRPL_ID, /* id */ + "Null - Testing protocol", /* name */ + sizeof(PurpleProtocol), /* 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() */ + NULL, /* user_splits, initialized in plugin_load() */ + NULL, /* protocol_options, initialized in plugin_load() */ { /* icon_spec, a PurpleBuddyIconSpec */ "png,jpg,gif", /* format */ 0, /* min_width */ @@ -1072,6 +1070,7 @@ 10000, /* max_filesize */ PURPLE_ICON_SCALE_DISPLAY, /* scale_rules */ }, + nullprpl_get_actions, /* get_actions */ nullprpl_list_icon, /* list_icon */ NULL, /* list_emblem */ nullprpl_status_text, /* status_text */ @@ -1126,7 +1125,7 @@ NULL, /* send_file */ NULL, /* new_xfer */ nullprpl_offline_message, /* offline_message */ - NULL, /* whiteboard_prpl_ops */ + NULL, /* whiteboard_protocol_ops */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ NULL, /* unregister_user */ @@ -1140,7 +1139,29 @@ NULL /* get_public_alias */ }; -static void nullprpl_init(PurplePlugin *plugin) +static PurplePluginInfo * +plugin_query(GError **error) +{ + return purple_plugin_info_new( + "id", NULLPRPL_ID, + "name", "Null - Testing Plugin", + "version", DISPLAY_VERSION, + "category", N_("Protocol"), + "summary", N_("Null Protocol Plugin"), + "description", N_("Null Protocol Plugin"), + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + + /* If you're using this as the basis of a protocol plugin that will be + * distributed separately from libpurple, do not include these flags.*/ + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); +} + +static gboolean +plugin_load(PurplePlugin *plugin, GError **error) { /* see accountopt.h for information about user splits and protocol options */ PurpleAccountUserSplit *split = purple_account_user_split_new( @@ -1154,8 +1175,8 @@ purple_debug_info("nullprpl", "starting up\n"); - prpl_info.user_splits = g_list_append(NULL, split); - prpl_info.protocol_options = g_list_append(NULL, option); + protocol.user_splits = g_list_append(NULL, split); + protocol.protocol_options = g_list_append(NULL, option); /* register whisper chat command, /msg */ purple_cmd_register("msg", @@ -1173,42 +1194,20 @@ g_free, /* key free fn */ NULL); /* value free fn */ - _null_protocol = plugin; -} + _null_protocol = &protocol; + purple_protocols_add(_null_protocol); -static void nullprpl_destroy(PurplePlugin *plugin) { - purple_debug_info("nullprpl", "shutting down\n"); + return TRUE; } - -static PurplePluginInfo info = +static gboolean +plugin_unload(PurplePlugin *plugin, GError **error) { - PURPLE_PLUGIN_MAGIC, /* magic */ - PURPLE_MAJOR_VERSION, /* major_version */ - PURPLE_MINOR_VERSION, /* minor_version */ - PURPLE_PLUGIN_PROTOCOL, /* type */ - NULL, /* ui_requirement */ - 0, /* flags */ - NULL, /* dependencies */ - PURPLE_PRIORITY_DEFAULT, /* priority */ - NULLPRPL_ID, /* id */ - "Null - Testing Plugin", /* name */ - DISPLAY_VERSION, /* version */ - N_("Null Protocol Plugin"), /* summary */ - N_("Null Protocol Plugin"), /* description */ - NULL, /* author */ - PURPLE_WEBSITE, /* homepage */ - NULL, /* load */ - NULL, /* unload */ - nullprpl_destroy, /* destroy */ - NULL, /* ui_info */ - &prpl_info, /* extra_info */ - NULL, /* prefs_info */ - nullprpl_actions, /* actions */ - NULL, /* padding... */ - NULL, - NULL, - NULL, -}; + purple_debug_info("nullprpl", "shutting down\n"); + + purple_protocols_remove(_null_protocol); -PURPLE_INIT_PLUGIN(null, nullprpl_init, info); + return TRUE; +} + +PURPLE_PLUGIN_INIT(null, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/oscar/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/oscar/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -78,4 +78,5 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(DEBUG_CFLAGS)
--- a/libpurple/protocols/oscar/authorization.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/oscar/authorization.c Sun Aug 18 01:53:00 2013 +0530 @@ -55,10 +55,10 @@ /* Mobile users should always be online */ if (bname[0] == '+') { - purple_prpl_got_user_status(account, + purple_protocol_got_user_status(account, purple_buddy_get_name(buddy), OSCAR_STATUS_ID_AVAILABLE, NULL); - purple_prpl_got_user_status(account, + purple_protocol_got_user_status(account, purple_buddy_get_name(buddy), OSCAR_STATUS_ID_MOBILE, NULL); }
--- a/libpurple/protocols/oscar/family_icbm.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/oscar/family_icbm.c Sun Aug 18 01:53:00 2013 +0530 @@ -1727,7 +1727,7 @@ presence = purple_buddy_get_presence(buddy); status = purple_presence_get_status(presence, "mood"); if (status) { - purple_prpl_got_user_status(account, bn, + purple_protocol_got_user_status(account, bn, "mood", PURPLE_MOOD_NAME, purple_status_get_attr_string(status, PURPLE_MOOD_NAME), PURPLE_MOOD_COMMENT, unescaped_xstatus, NULL);
--- a/libpurple/protocols/oscar/family_icq.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/oscar/family_icq.c Sun Aug 18 01:53:00 2013 +0530 @@ -628,7 +628,7 @@ presence = purple_buddy_get_presence(buddy); status = purple_presence_get_active_status(presence); - purple_prpl_got_user_status(account, uin, + purple_protocol_got_user_status(account, uin, purple_status_get_id(status), "message", NULL, NULL);
--- a/libpurple/protocols/oscar/family_locate.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/oscar/family_locate.c Sun Aug 18 01:53:00 2013 +0530 @@ -929,11 +929,11 @@ mood = aim_receive_custom_icon(od, bs, length); if (mood) - purple_prpl_got_user_status(account, outinfo->bn, "mood", + purple_protocol_got_user_status(account, outinfo->bn, "mood", PURPLE_MOOD_NAME, mood, NULL); else - purple_prpl_got_user_status_deactive(account, outinfo->bn, "mood"); + purple_protocol_got_user_status_deactive(account, outinfo->bn, "mood"); } else if (type == 0x000e) { /* @@ -1093,11 +1093,11 @@ g_free(icqmood); if (mood) - purple_prpl_got_user_status(account, outinfo->bn, "mood", + purple_protocol_got_user_status(account, outinfo->bn, "mood", PURPLE_MOOD_NAME, mood, NULL); else - purple_prpl_got_user_status_deactive(account, outinfo->bn, "mood"); + purple_protocol_got_user_status_deactive(account, outinfo->bn, "mood"); } break; } @@ -1415,11 +1415,11 @@ mood = aim_receive_custom_icon(od, &cbs, tlv->length); if (mood) - purple_prpl_got_user_status(account, userinfo->bn, "mood", + purple_protocol_got_user_status(account, userinfo->bn, "mood", PURPLE_MOOD_NAME, mood, NULL); else - purple_prpl_got_user_status_deactive(account, userinfo->bn, "mood"); + purple_protocol_got_user_status_deactive(account, userinfo->bn, "mood"); } aim_tlvlist_free(tlvlist);
--- a/libpurple/protocols/oscar/libaim.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/oscar/libaim.c Sun Aug 18 01:53:00 2013 +0530 @@ -24,17 +24,22 @@ * which contains all the shared implementation code with libicq */ +#include "plugins.h" + #include "oscarcommon.h" #include "oscar.h" -static PurplePluginProtocolInfo prpl_info = +static PurpleProtocol protocol = { - sizeof(PurplePluginProtocolInfo), /* struct_size */ + "prpl-aim", /* id */ + "AIM", /* name */ + sizeof(PurpleProtocol), /* struct_size */ OPT_PROTO_MAIL_CHECK | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE | OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE, NULL, /* user_splits */ NULL, /* protocol_options */ {"gif,jpeg,bmp,ico", 0, 0, 64, 64, 7168, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ - oscar_list_icon_aim, /* list_icon */ + oscar_get_actions, /* get_actions */ + oscar_list_icon_aim, /* list_icon */ oscar_list_emblem, /* list_emblems */ oscar_status_text, /* status_text */ oscar_tooltip_text, /* tooltip_text */ @@ -88,7 +93,7 @@ oscar_send_file, /* send_file */ oscar_new_xfer, /* new_xfer */ oscar_offline_message, /* offline_message */ - NULL, /* whiteboard_prpl_ops */ + NULL, /* whiteboard_protocol_ops */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ NULL, /* unregister_user */ @@ -102,47 +107,39 @@ NULL /* get_public_alias */ }; -static PurplePluginInfo info = +static PurplePluginInfo * +plugin_query(GError **error) { - 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-aim", /**< id */ - "AIM", /**< name */ - DISPLAY_VERSION, /**< version */ - /** summary */ - N_("AIM Protocol Plugin"), - /** description */ - N_("AIM Protocol Plugin"), - NULL, /**< author */ - PURPLE_WEBSITE, /**< homepage */ - - NULL, /**< load */ - NULL, /**< unload */ - NULL, /**< destroy */ - - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, - oscar_actions, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - -static void -init_plugin(PurplePlugin *plugin) -{ - oscar_init(plugin, FALSE); + return purple_plugin_info_new( + "id", "prpl-aim", + "name", "AIM", + "version", DISPLAY_VERSION, + "category", N_("Protocol"), + "summary", N_("AIM Protocol Plugin"), + "description", N_("AIM Protocol Plugin"), + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); } -PURPLE_INIT_PLUGIN(aim, init_plugin, info); +static gboolean +plugin_load(PurplePlugin *plugin, GError **error) +{ + oscar_init(&protocol, FALSE); + purple_protocols_add(&protocol); + + return TRUE; +} + +static gboolean +plugin_unload(PurplePlugin *plugin, GError **error) +{ + purple_protocols_remove(&protocol); + + return TRUE; +} + +PURPLE_PLUGIN_INIT(aim, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/oscar/libicq.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/oscar/libicq.c Sun Aug 18 01:53:00 2013 +0530 @@ -24,6 +24,7 @@ * which contains all the shared implementation code with libaim */ +#include "plugins.h" #include "oscarcommon.h" @@ -36,14 +37,17 @@ return table; } -static PurplePluginProtocolInfo prpl_info = +static PurpleProtocol protocol = { - sizeof(PurplePluginProtocolInfo), /* struct_size */ + "prpl-icq", /* id */ + "ICQ", /* name */ + sizeof(PurpleProtocol), /* struct_size */ OPT_PROTO_MAIL_CHECK | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE | OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE, NULL, /* user_splits */ NULL, /* protocol_options */ {"gif,jpeg,bmp,ico", 0, 0, 64, 64, 7168, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ - oscar_list_icon_icq, /* list_icon */ + oscar_get_actions, /* get_actions */ + oscar_list_icon_icq, /* list_icon */ oscar_list_emblem, /* list_emblems */ oscar_status_text, /* status_text */ oscar_tooltip_text, /* tooltip_text */ @@ -97,7 +101,7 @@ oscar_send_file, /* send_file */ oscar_new_xfer, /* new_xfer */ oscar_offline_message, /* offline_message */ - NULL, /* whiteboard_prpl_ops */ + NULL, /* whiteboard_protocol_ops */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ NULL, /* unregister_user */ @@ -111,52 +115,45 @@ NULL /* get_public_alias */ }; -static PurplePluginInfo info = +static PurplePluginInfo * +plugin_query(GError **error) { - PURPLE_PLUGIN_MAGIC, - PURPLE_MAJOR_VERSION, - PURPLE_MINOR_VERSION, - PURPLE_PLUGIN_PROTOCOL, /**< type */ - NULL, /**< ui_requirement */ - 0, /**< flags */ - NULL, /**< dependencies */ - PURPLE_PRIORITY_DEFAULT, /**< priority */ + return purple_plugin_info_new( + "id", "prpl-icq", + "name", "ICQ", + "version", DISPLAY_VERSION, + "category", N_("Protocol"), + "summary", N_("ICQ Protocol Plugin"), + "description", N_("ICQ Protocol Plugin"), + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); +} - "prpl-icq", /**< id */ - "ICQ", /**< name */ - DISPLAY_VERSION, /**< version */ - /** summary */ - N_("ICQ Protocol Plugin"), - /** description */ - N_("ICQ Protocol Plugin"), - NULL, /**< author */ - PURPLE_WEBSITE, /**< homepage */ - - NULL, /**< load */ - NULL, /**< unload */ - NULL, /**< destroy */ - - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, - oscar_actions, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - -static void -init_plugin(PurplePlugin *plugin) +static gboolean +plugin_load(PurplePlugin *plugin, GError **error) { PurpleAccountOption *option; - oscar_init(plugin, TRUE); + oscar_init(&protocol, TRUE); option = purple_account_option_string_new(_("Encoding"), "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); + + purple_protocols_add(&protocol); + + return TRUE; } -PURPLE_INIT_PLUGIN(icq, init_plugin, info); +static gboolean +plugin_unload(PurplePlugin *plugin, GError **error) +{ + purple_protocols_remove(&protocol); + + return TRUE; +} + +PURPLE_PLUGIN_INIT(icq, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/oscar/oscar.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/oscar/oscar.c Sun Aug 18 01:53:00 2013 +0530 @@ -41,7 +41,7 @@ #include "imgstore.h" #include "network.h" #include "notify.h" -#include "prpl.h" +#include "protocol.h" #include "proxy.h" #include "request.h" #include "util.h" @@ -745,8 +745,8 @@ od->use_ssl = purple_ssl_is_supported() && strcmp(encryption_type, OSCAR_NO_ENCRYPTION) != 0; /* Connect to core Purple signals */ - purple_prefs_connect_callback(gc, "/purple/away/idle_reporting", idle_reporting_pref_cb, gc); - purple_prefs_connect_callback(gc, "/plugins/prpl/oscar/recent_buddies", recent_buddies_pref_cb, gc); + purple_prefs_connect_callback(purple_connection_get_protocol_info(gc), "/purple/away/idle_reporting", idle_reporting_pref_cb, gc); + purple_prefs_connect_callback(purple_connection_get_protocol_info(gc), "/plugins/prpl/oscar/recent_buddies", recent_buddies_pref_cb, gc); /* * On 2008-03-05 AOL released some documentation on the OSCAR protocol @@ -1244,9 +1244,9 @@ } if (info->flags & AIM_FLAG_WIRELESS) { - purple_prpl_got_user_status(account, info->bn, OSCAR_STATUS_ID_MOBILE, NULL); + purple_protocol_got_user_status(account, info->bn, OSCAR_STATUS_ID_MOBILE, NULL); } else { - purple_prpl_got_user_status_deactive(account, info->bn, OSCAR_STATUS_ID_MOBILE); + purple_protocol_got_user_status_deactive(account, info->bn, OSCAR_STATUS_ID_MOBILE); } message = (info->status && info->status_len > 0) @@ -1262,10 +1262,10 @@ itmsurl = g_strdup(purple_status_get_attr_string(previous_status, "itmsurl")); } purple_debug_info("oscar", "Activating status '%s' for buddy %s, message = '%s', itmsurl = '%s'\n", status_id, info->bn, message ? message : "(null)", itmsurl ? itmsurl : "(null)"); - purple_prpl_got_user_status(account, info->bn, status_id, "message", message, "itmsurl", itmsurl, NULL); + purple_protocol_got_user_status(account, info->bn, status_id, "message", message, "itmsurl", itmsurl, NULL); } else { purple_debug_info("oscar", "Activating status '%s' for buddy %s, message = '%s'\n", status_id, info->bn, message ? message : "(null)"); - purple_prpl_got_user_status(account, info->bn, status_id, "message", message, NULL); + purple_protocol_got_user_status(account, info->bn, status_id, "message", message, NULL); } g_free(message); @@ -1276,7 +1276,7 @@ signon = info->onlinesince; else if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN) signon = time(NULL) - info->sessionlen; - purple_prpl_got_user_login_time(account, info->bn, signon); + purple_protocol_got_user_login_time(account, info->bn, signon); /* Idle time stuff */ /* info->idletime is the number of minutes that this user has been idle */ @@ -1284,9 +1284,9 @@ time_idle = time(NULL) - info->idletime * 60; if (time_idle > 0) - purple_prpl_got_user_idle(account, info->bn, TRUE, time_idle); + purple_protocol_got_user_idle(account, info->bn, TRUE, time_idle); else - purple_prpl_got_user_idle(account, info->bn, FALSE, 0); + purple_protocol_got_user_idle(account, info->bn, FALSE, 0); /* Server stored icon stuff */ bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, info->bn)); @@ -1337,8 +1337,8 @@ info = va_arg(ap, aim_userinfo_t *); va_end(ap); - 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); + purple_protocol_got_user_status(account, info->bn, OSCAR_STATUS_ID_OFFLINE, NULL); + purple_protocol_got_user_status_deactive(account, info->bn, OSCAR_STATUS_ID_MOBILE); g_hash_table_remove(od->buddyinfo, purple_normalize(purple_connection_get_account(gc), info->bn)); return 1; @@ -3516,9 +3516,9 @@ /* Mobile users should always be online */ if (bname[0] == '+') { - purple_prpl_got_user_status(account, bname, + purple_protocol_got_user_status(account, bname, OSCAR_STATUS_ID_AVAILABLE, NULL); - purple_prpl_got_user_status(account, bname, + purple_protocol_got_user_status(account, bname, OSCAR_STATUS_ID_MOBILE, NULL); } } else if (aim_ssi_waitingforauth(&od->ssi.local, @@ -3835,10 +3835,10 @@ /* Mobile users should always be online */ if (curitem->name[0] == '+') { - purple_prpl_got_user_status(account, + purple_protocol_got_user_status(account, purple_buddy_get_name(b), OSCAR_STATUS_ID_AVAILABLE, NULL); - purple_prpl_got_user_status(account, + purple_protocol_got_user_status(account, purple_buddy_get_name(b), OSCAR_STATUS_ID_MOBILE, NULL); } @@ -4049,9 +4049,9 @@ /* Mobile users should always be online */ if (name[0] == '+') { - purple_prpl_got_user_status(account, + purple_protocol_got_user_status(account, name, OSCAR_STATUS_ID_AVAILABLE, NULL); - purple_prpl_got_user_status(account, + purple_protocol_got_user_status(account, name, OSCAR_STATUS_ID_MOBILE, NULL); } @@ -4989,9 +4989,9 @@ } static void -oscar_show_icq_privacy_opts(PurplePluginAction *action) +oscar_show_icq_privacy_opts(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; PurpleAccount *account = purple_connection_get_account(gc); PurpleRequestFields *fields; PurpleRequestFieldGroup *g; @@ -5021,13 +5021,13 @@ gc); } -static void oscar_confirm_account(PurplePluginAction *action) +static void oscar_confirm_account(PurpleProtocolAction *action) { PurpleConnection *gc; OscarData *od; FlapConnection *conn; - gc = (PurpleConnection *)action->context; + gc = action->connection; od = purple_connection_get_protocol_data(gc); conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN); @@ -5039,9 +5039,9 @@ } } -static void oscar_show_email(PurplePluginAction *action) +static void oscar_show_email(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; OscarData *od = purple_connection_get_protocol_data(gc); FlapConnection *conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN); @@ -5067,9 +5067,9 @@ } } -static void oscar_show_change_email(PurplePluginAction *action) +static void oscar_show_change_email(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; purple_request_input(gc, NULL, _("Change Address To:"), NULL, NULL, FALSE, FALSE, NULL, _("_OK"), G_CALLBACK(oscar_change_email), @@ -5078,9 +5078,9 @@ gc); } -static void oscar_show_awaitingauth(PurplePluginAction *action) +static void oscar_show_awaitingauth(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; OscarData *od = purple_connection_get_protocol_data(gc); PurpleAccount *account = purple_connection_get_account(gc); GSList *buddies, *filtered_buddies, *cur; @@ -5121,9 +5121,9 @@ aim_search_address(od, email); } -static void oscar_show_find_email(PurplePluginAction *action) +static void oscar_show_find_email(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; purple_request_input(gc, _("Find Buddy by Email"), _("Search for a buddy by email address"), _("Type the email address of the buddy you are " @@ -5135,39 +5135,39 @@ gc); } -static void oscar_show_set_info(PurplePluginAction *action) +static void oscar_show_set_info(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; purple_account_request_change_user_info(purple_connection_get_account(gc)); } -static void oscar_show_set_info_icqurl(PurplePluginAction *action) +static void oscar_show_set_info_icqurl(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; purple_notify_uri(gc, "http://www.icq.com/whitepages/user_details.php"); } -static void oscar_change_pass(PurplePluginAction *action) +static void oscar_change_pass(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; purple_account_request_change_password(purple_connection_get_account(gc)); } /** * Only used when connecting with the old-style BUCP login. */ -static void oscar_show_chpassurl(PurplePluginAction *action) +static void oscar_show_chpassurl(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; OscarData *od = purple_connection_get_protocol_data(gc); gchar *substituted = purple_strreplace(od->authinfo->chpassurl, "%s", purple_account_get_username(purple_connection_get_account(gc))); purple_notify_uri(gc, substituted); g_free(substituted); } -static void oscar_show_imforwardingurl(PurplePluginAction *action) +static void oscar_show_imforwardingurl(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; purple_notify_uri(gc, "http://mymobile.aol.com/dbreg/register?action=imf&clientID=1"); } @@ -5274,39 +5274,38 @@ } GList * -oscar_actions(PurplePlugin *plugin, gpointer context) +oscar_get_actions(PurpleConnection *gc) { - PurpleConnection *gc = (PurpleConnection *) context; OscarData *od = purple_connection_get_protocol_data(gc); GList *menu = NULL; - PurplePluginAction *act; - - act = purple_plugin_action_new(_("Set User Info..."), + PurpleProtocolAction *act; + + act = purple_protocol_action_new(_("Set User Info..."), oscar_show_set_info); menu = g_list_prepend(menu, act); if (od->icq) { - act = purple_plugin_action_new(_("Set User Info (web)..."), + act = purple_protocol_action_new(_("Set User Info (web)..."), oscar_show_set_info_icqurl); menu = g_list_prepend(menu, act); } - act = purple_plugin_action_new(_("Change Password..."), + act = purple_protocol_action_new(_("Change Password..."), oscar_change_pass); menu = g_list_prepend(menu, act); if (od->authinfo != NULL && od->authinfo->chpassurl != NULL) { /* This only happens when connecting with the old-style BUCP login */ - act = purple_plugin_action_new(_("Change Password (web)"), + act = purple_protocol_action_new(_("Change Password (web)"), oscar_show_chpassurl); menu = g_list_prepend(menu, act); } if (!od->icq) { - act = purple_plugin_action_new(_("Configure IM Forwarding (web)"), + act = purple_protocol_action_new(_("Configure IM Forwarding (web)"), oscar_show_imforwardingurl); menu = g_list_prepend(menu, act); } @@ -5316,41 +5315,41 @@ if (od->icq) { /* ICQ actions */ - act = purple_plugin_action_new(_("Set Privacy Options..."), + act = purple_protocol_action_new(_("Set Privacy Options..."), oscar_show_icq_privacy_opts); menu = g_list_prepend(menu, act); - act = purple_plugin_action_new(_("Show Visible List"), oscar_show_visible_list); + act = purple_protocol_action_new(_("Show Visible List"), oscar_show_visible_list); menu = g_list_prepend(menu, act); - act = purple_plugin_action_new(_("Show Invisible List"), oscar_show_invisible_list); + act = purple_protocol_action_new(_("Show Invisible List"), oscar_show_invisible_list); menu = g_list_prepend(menu, act); } else { /* AIM actions */ - act = purple_plugin_action_new(_("Confirm Account"), + act = purple_protocol_action_new(_("Confirm Account"), oscar_confirm_account); menu = g_list_prepend(menu, act); - act = purple_plugin_action_new(_("Display Currently Registered Email Address"), + act = purple_protocol_action_new(_("Display Currently Registered Email Address"), oscar_show_email); menu = g_list_prepend(menu, act); - act = purple_plugin_action_new(_("Change Currently Registered Email Address..."), + act = purple_protocol_action_new(_("Change Currently Registered Email Address..."), oscar_show_change_email); menu = g_list_prepend(menu, act); } menu = g_list_prepend(menu, NULL); - act = purple_plugin_action_new(_("Show Buddies Awaiting Authorization"), + act = purple_protocol_action_new(_("Show Buddies Awaiting Authorization"), oscar_show_awaitingauth); menu = g_list_prepend(menu, act); menu = g_list_prepend(menu, NULL); - act = purple_plugin_action_new(_("Search for Buddy by Email Address..."), + act = purple_protocol_action_new(_("Search for Buddy by Email Address..."), oscar_show_find_email); menu = g_list_prepend(menu, act); @@ -5530,9 +5529,8 @@ return FALSE; } -void oscar_init(PurplePlugin *plugin, gboolean is_icq) +void oscar_init(PurpleProtocol *protocol, gboolean is_icq) { - PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); PurpleAccountOption *option; static gboolean init = FALSE; static const gchar *encryption_keys[] = { @@ -5551,10 +5549,10 @@ int i; option = purple_account_option_string_new(_("Server"), "server", get_login_server(is_icq, TRUE)); - prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); + protocol->protocol_options = g_list_append(protocol->protocol_options, option); option = purple_account_option_int_new(_("Port"), "port", OSCAR_DEFAULT_LOGIN_PORT); - prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); + protocol->protocol_options = g_list_append(protocol->protocol_options, option); for (i = 0; encryption_keys[i]; i++) { PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1); @@ -5563,21 +5561,21 @@ encryption_options = g_list_append(encryption_options, kvp); } option = purple_account_option_list_new(_("Connection security"), "encryption", encryption_options); - prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); + protocol->protocol_options = g_list_append(protocol->protocol_options, option); option = purple_account_option_bool_new(_("Use clientLogin"), "use_clientlogin", OSCAR_DEFAULT_USE_CLIENTLOGIN); - prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); + protocol->protocol_options = g_list_append(protocol->protocol_options, option); option = purple_account_option_bool_new( _("Always use AIM/ICQ proxy server for\nfile transfers and direct IM (slower,\nbut does not reveal your IP address)"), "always_use_rv_proxy", OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY); - prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); - - if (g_str_equal(purple_plugin_get_id(plugin), "prpl-aim")) { + protocol->protocol_options = g_list_append(protocol->protocol_options, option); + + if (g_str_equal(protocol->id, "prpl-aim")) { option = purple_account_option_bool_new(_("Allow multiple simultaneous logins"), "allow_multiple_logins", OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS); - prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option); + protocol->protocol_options = g_list_append(protocol->protocol_options, option); } if (init) @@ -5593,7 +5591,7 @@ /* protocol handler */ /* TODO: figure out a good instance to use here */ - purple_signal_connect(purple_get_core(), "uri-handler", &init, + purple_signal_connect(purple_get_core(), "uri-handler", protocol, PURPLE_CALLBACK(oscar_uri_handler), NULL); }
--- a/libpurple/protocols/oscar/oscarcommon.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/oscar/oscarcommon.h Sun Aug 18 01:53:00 2013 +0530 @@ -27,7 +27,7 @@ #include "internal.h" #include "accountopt.h" -#include "prpl.h" +#include "protocol.h" #include "version.h" #include "notify.h" #include "status.h" @@ -102,5 +102,5 @@ void oscar_send_file(PurpleConnection *gc, const char *who, const char *file); PurpleXfer *oscar_new_xfer(PurpleConnection *gc, const char *who); gboolean oscar_offline_message(const PurpleBuddy *buddy); -GList *oscar_actions(PurplePlugin *plugin, gpointer context); -void oscar_init(PurplePlugin *plugin, gboolean is_icq); +GList *oscar_get_actions(PurpleConnection *gc); +void oscar_init(PurpleProtocol *protocol, gboolean is_icq);
--- a/libpurple/protocols/oscar/visibility.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/oscar/visibility.c Sun Aug 18 01:53:00 2013 +0530 @@ -86,9 +86,9 @@ } static void -show_private_list(PurplePluginAction *action, guint16 list_type, const gchar *title, const gchar *list_description, const gchar *menu_action_name) +show_private_list(PurpleProtocolAction *action, guint16 list_type, const gchar *title, const gchar *list_description, const gchar *menu_action_name) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; OscarData *od = purple_connection_get_protocol_data(gc); PurpleAccount *account = purple_connection_get_account(gc); GSList *buddies, *filtered_buddies, *cur; @@ -122,7 +122,7 @@ } void -oscar_show_visible_list(PurplePluginAction *action) +oscar_show_visible_list(PurpleProtocolAction *action) { show_private_list(action, AIM_SSI_TYPE_PERMIT, _("Visible List"), _("These buddies will see " @@ -132,7 +132,7 @@ } void -oscar_show_invisible_list(PurplePluginAction *action) +oscar_show_invisible_list(PurpleProtocolAction *action) { show_private_list(action, AIM_SSI_TYPE_DENY, _("Invisible List"), _("These buddies will always see you as offline"),
--- a/libpurple/protocols/oscar/visibility.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/oscar/visibility.h Sun Aug 18 01:53:00 2013 +0530 @@ -22,11 +22,11 @@ #define _VISIBILITY_H_ #include "oscar.h" -#include "plugin.h" +#include "plugins.h" #include "util.h" PurpleMenuAction * create_visibility_menu_item(OscarData *od, const char *bname); -void oscar_show_visible_list(PurplePluginAction *action); -void oscar_show_invisible_list(PurplePluginAction *action); +void oscar_show_visible_list(PurpleProtocolAction *action); +void oscar_show_invisible_list(PurpleProtocolAction *action); -#endif \ No newline at end of file +#endif
--- a/libpurple/protocols/sametime/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/sametime/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -32,6 +32,7 @@ -I$(top_builddir)/libpurple \ $(DEBUG_CFLAGS) \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(MEANWHILE_CFLAGS) \ -DG_LOG_DOMAIN=\"sametime\"
--- a/libpurple/protocols/sametime/sametime.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/sametime/sametime.c Sun Aug 18 01:53:00 2013 +0530 @@ -40,8 +40,8 @@ #include "imgstore.h" #include "mime.h" #include "notify.h" -#include "plugin.h" -#include "prpl.h" +#include "plugins.h" +#include "protocol.h" #include "request.h" #include "util.h" #include "version.h" @@ -71,6 +71,7 @@ /* scratch that, I just added it to the prpl options panel */ #define PLUGIN_ID "prpl-meanwhile" #define PLUGIN_NAME "Sametime" +#define PLUGIN_CATEGORY "Protocol" #define PLUGIN_SUMMARY "Sametime Protocol Plugin" #define PLUGIN_DESC "Open implementation of a Lotus Sametime client" #define PLUGIN_AUTHOR "Christopher (siege) O'Brien <siege@preoccupied.net>" @@ -78,11 +79,11 @@ /* plugin preference names */ -#define MW_PRPL_OPT_BASE "/plugins/prpl/meanwhile" -#define MW_PRPL_OPT_BLIST_ACTION MW_PRPL_OPT_BASE "/blist_action" -#define MW_PRPL_OPT_PSYCHIC MW_PRPL_OPT_BASE "/psychic" -#define MW_PRPL_OPT_FORCE_LOGIN MW_PRPL_OPT_BASE "/force_login" -#define MW_PRPL_OPT_SAVE_DYNAMIC MW_PRPL_OPT_BASE "/save_dynamic" +#define MW_PROTOCOL_OPT_BASE "/plugins/prpl/meanwhile" +#define MW_PROTOCOL_OPT_BLIST_ACTION MW_PROTOCOL_OPT_BASE "/blist_action" +#define MW_PROTOCOL_OPT_PSYCHIC MW_PROTOCOL_OPT_BASE "/psychic" +#define MW_PROTOCOL_OPT_FORCE_LOGIN MW_PROTOCOL_OPT_BASE "/force_login" +#define MW_PROTOCOL_OPT_SAVE_DYNAMIC MW_PROTOCOL_OPT_BASE "/save_dynamic" /* stages of connecting-ness */ @@ -162,7 +163,7 @@ /* testing for the above */ -#define BLIST_PREF_IS(n) (purple_prefs_get_int(MW_PRPL_OPT_BLIST_ACTION)==(n)) +#define BLIST_PREF_IS(n) (purple_prefs_get_int(MW_PROTOCOL_OPT_BLIST_ACTION)==(n)) #define BLIST_PREF_IS_LOCAL() BLIST_PREF_IS(blist_choice_LOCAL) #define BLIST_PREF_IS_MERGE() BLIST_PREF_IS(blist_choice_MERGE) #define BLIST_PREF_IS_STORE() BLIST_PREF_IS(blist_choice_STORE) @@ -197,7 +198,7 @@ /** the purple plugin data. available as purple_connection_get_protocol_data(gc) and mwSession_getClientData */ -struct mwPurplePluginData { +struct mwPurpleProtocolData { struct mwSession *session; struct mwServiceAware *srvc_aware; @@ -236,9 +237,9 @@ static void blist_export(PurpleConnection *gc, struct mwSametimeList *stlist); -static void blist_store(struct mwPurplePluginData *pd); - -static void blist_schedule(struct mwPurplePluginData *pd); +static void blist_store(struct mwPurpleProtocolData *pd); + +static void blist_schedule(struct mwPurpleProtocolData *pd); static void blist_merge(PurpleConnection *gc, struct mwSametimeList *stlist); @@ -246,19 +247,19 @@ static gboolean buddy_is_external(PurpleBuddy *b); -static void buddy_add(struct mwPurplePluginData *pd, PurpleBuddy *buddy); +static void buddy_add(struct mwPurpleProtocolData *pd, PurpleBuddy *buddy); static PurpleBuddy * buddy_ensure(PurpleConnection *gc, PurpleGroup *group, struct mwSametimeUser *stuser); -static void group_add(struct mwPurplePluginData *pd, PurpleGroup *group); +static void group_add(struct mwPurpleProtocolData *pd, PurpleGroup *group); static PurpleGroup * group_ensure(PurpleConnection *gc, struct mwSametimeGroup *stgroup); static struct mwAwareList * -list_ensure(struct mwPurplePluginData *pd, PurpleGroup *group); +list_ensure(struct mwPurpleProtocolData *pd, PurpleGroup *group); /* session functions */ @@ -272,7 +273,7 @@ /* conference functions */ static struct mwConference * -conf_find_by_id(struct mwPurplePluginData *pd, int id); +conf_find_by_id(struct mwPurpleProtocolData *pd, int id); /* conversation functions */ @@ -316,7 +317,7 @@ /** resolves a mwSession from a PurpleConnection */ static struct mwSession *gc_to_session(PurpleConnection *gc) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; g_return_val_if_fail(gc != NULL, NULL); @@ -329,7 +330,7 @@ /** resolves a PurpleConnection from a mwSession */ static PurpleConnection *session_to_gc(struct mwSession *session) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; g_return_val_if_fail(session != NULL, NULL); @@ -341,7 +342,7 @@ static void write_cb(gpointer data, gint source, PurpleInputCondition cond) { - struct mwPurplePluginData *pd = data; + struct mwPurpleProtocolData *pd = data; PurpleCircularBuffer *circ = pd->sock_buf; gsize avail; int ret; @@ -373,7 +374,7 @@ static int mw_session_io_write(struct mwSession *session, const guchar *buf, gsize len) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; gssize ret = 0; int err = 0; @@ -431,7 +432,7 @@ static void mw_session_io_close(struct mwSession *session) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; pd = mwSession_getClientData(session); g_return_if_fail(pd != NULL); @@ -487,7 +488,7 @@ PurpleConnection *gc; PurpleAccount *acct; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; guint32 idle; guint stat; const char *id; @@ -592,11 +593,11 @@ } if(aware->online) { - purple_prpl_got_user_status(acct, id, status, NULL); - purple_prpl_got_user_idle(acct, id, !!idle, (time_t) idle); + purple_protocol_got_user_status(acct, id, status, NULL); + purple_protocol_got_user_idle(acct, id, !!idle, (time_t) idle); } else { - purple_prpl_got_user_status(acct, id, MW_STATE_OFFLINE, NULL); + purple_protocol_got_user_status(acct, id, MW_STATE_OFFLINE, NULL); } } @@ -624,7 +625,7 @@ /** Ensures that an Aware List is associated with the given group, and returns that list. */ static struct mwAwareList * -list_ensure(struct mwPurplePluginData *pd, PurpleGroup *group) { +list_ensure(struct mwPurpleProtocolData *pd, PurpleGroup *group) { struct mwAwareList *list; @@ -741,7 +742,7 @@ } -static void blist_store(struct mwPurplePluginData *pd) { +static void blist_store(struct mwPurpleProtocolData *pd) { struct mwSametimeList *stlist; struct mwServiceStorage *srvc; @@ -794,7 +795,7 @@ static gboolean blist_save_cb(gpointer data) { - struct mwPurplePluginData *pd = data; + struct mwPurpleProtocolData *pd = data; blist_store(pd); pd->save_event = 0; @@ -803,7 +804,7 @@ /** schedules the buddy list to be saved to the server */ -static void blist_schedule(struct mwPurplePluginData *pd) { +static void blist_schedule(struct mwPurpleProtocolData *pd) { if(pd->save_event) return; pd->save_event = purple_timeout_add_seconds(BLIST_SAVE_SECONDS, @@ -819,7 +820,7 @@ /** Actually add a buddy to the aware service, and schedule the buddy list to be saved to the server */ -static void buddy_add(struct mwPurplePluginData *pd, +static void buddy_add(struct mwPurpleProtocolData *pd, PurpleBuddy *buddy) { struct mwAwareIdBlock idb = { mwAware_USER, (char *) purple_buddy_get_name(buddy), NULL }; @@ -848,7 +849,7 @@ static PurpleBuddy *buddy_ensure(PurpleConnection *gc, PurpleGroup *group, struct mwSametimeUser *stuser) { - struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc); + struct mwPurpleProtocolData *pd = purple_connection_get_protocol_data(gc); PurpleBuddy *buddy; PurpleAccount *acct = purple_connection_get_account(gc); @@ -878,7 +879,7 @@ /** add aware watch for a dynamic group */ -static void group_add(struct mwPurplePluginData *pd, +static void group_add(struct mwPurpleProtocolData *pd, PurpleGroup *group) { struct mwAwareIdBlock idb = { mwAware_GROUP, NULL, NULL }; @@ -1227,7 +1228,7 @@ guint32 result, struct mwStorageUnit *item, gpointer data) { - struct mwPurplePluginData *pd = data; + struct mwPurpleProtocolData *pd = data; struct mwSametimeList *stlist; struct mwGetBuffer *b; @@ -1260,7 +1261,7 @@ /** signal triggered when a conversation is opened in Purple */ static void conversation_created_cb(PurpleConversation *g_conv, - struct mwPurplePluginData *pd) { + struct mwPurpleProtocolData *pd) { /* we need to tell the IM service to negotiate features for the conversation right away, otherwise it'll wait until the first @@ -1293,7 +1294,7 @@ static void blist_menu_nab(PurpleBlistNode *node, gpointer data) { - struct mwPurplePluginData *pd = data; + struct mwPurpleProtocolData *pd = data; PurpleConnection *gc; PurpleGroup *group = (PurpleGroup *) node; @@ -1331,7 +1332,7 @@ so we use the blist-node-extended-menu signal to trigger this handler */ static void blist_node_menu_cb(PurpleBlistNode *node, - GList **menu, struct mwPurplePluginData *pd) { + GList **menu, struct mwPurpleProtocolData *pd) { const char *owner; PurpleAccount *acct; PurpleMenuAction *act; @@ -1405,7 +1406,7 @@ /** Last thing to happen from a started session */ -static void services_starting(struct mwPurplePluginData *pd) { +static void services_starting(struct mwPurpleProtocolData *pd) { PurpleConnection *gc; PurpleAccount *acct; @@ -1457,7 +1458,7 @@ static void session_loginRedirect(struct mwSession *session, const char *host) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; PurpleConnection *gc; PurpleAccount *account; guint port; @@ -1483,20 +1484,20 @@ } -static void mw_prpl_set_status(PurpleAccount *acct, PurpleStatus *status); +static void mw_protocol_set_status(PurpleAccount *acct, PurpleStatus *status); /** called from mw_session_stateChange when the session's state is mwSession_STARTED. Any finalizing of start-up stuff should go here */ -static void session_started(struct mwPurplePluginData *pd) { +static void session_started(struct mwPurpleProtocolData *pd) { PurpleStatus *status; PurpleAccount *acct; /* set out initial status */ acct = purple_connection_get_account(pd->gc); status = purple_account_get_active_status(acct); - mw_prpl_set_status(acct, status); + mw_protocol_set_status(acct, status); /* start watching for new conversations */ purple_signal_connect(purple_conversations_get_handle(), @@ -1513,7 +1514,7 @@ } -static void session_stopping(struct mwPurplePluginData *pd) { +static void session_stopping(struct mwPurpleProtocolData *pd) { /* stop watching the signals from session_started */ purple_signals_disconnect_by_handle(pd); } @@ -1522,7 +1523,7 @@ static void mw_session_stateChange(struct mwSession *session, enum mwSessionState state, gpointer info) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; PurpleConnection *gc; const char *msg = NULL; @@ -1629,7 +1630,7 @@ static void mw_session_setPrivacyInfo(struct mwSession *session) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; PurpleConnection *gc; PurpleAccount *acct; struct mwPrivacyInfo *privacy; @@ -1675,7 +1676,7 @@ static void mw_session_setUserStatus(struct mwSession *session) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; PurpleConnection *gc; struct mwAwareIdBlock idb = { mwAware_USER, NULL, NULL }; struct mwUserStatus *stat; @@ -1743,7 +1744,7 @@ /** callback triggered from purple_input_add, watches the socked for available data to be processed by the session */ static void read_cb(gpointer data, gint source, PurpleInputCondition cond) { - struct mwPurplePluginData *pd = data; + struct mwPurpleProtocolData *pd = data; int ret = 0, err = 0; g_return_if_fail(pd != NULL); @@ -1794,7 +1795,7 @@ in, and if the session logging in receives a redirect message */ static void connect_cb(gpointer data, gint source, const gchar *error_message) { - struct mwPurplePluginData *pd = data; + struct mwPurpleProtocolData *pd = data; if(source < 0) { /* connection failed */ @@ -1833,7 +1834,7 @@ struct mwLoginInfo *from, gboolean may_reply, const char *text) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; PurpleAccount *acct; PurpleIMConversation *im; PurpleBuddy *buddy; @@ -1903,7 +1904,7 @@ struct mwServiceConference *srvc; struct mwSession *session; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; PurpleConnection *gc; char *c_inviter, *c_name, *c_topic, *c_invitation; @@ -1952,7 +1953,7 @@ static struct mwConference * -conf_find_by_id(struct mwPurplePluginData *pd, int id) { +conf_find_by_id(struct mwPurpleProtocolData *pd, int id) { struct mwServiceConference *srvc = pd->srvc_conf; struct mwConference *conf = NULL; @@ -1977,7 +1978,7 @@ static void mw_conf_opened(struct mwConference *conf, GList *members) { struct mwServiceConference *srvc; struct mwSession *session; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; PurpleConnection *gc; PurpleChatConversation *g_conf; @@ -2008,7 +2009,7 @@ static void mw_conf_closed(struct mwConference *conf, guint32 reason) { struct mwServiceConference *srvc; struct mwSession *session; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; PurpleConnection *gc; const char *n = mwConference_getName(conf); @@ -2066,7 +2067,7 @@ struct mwServiceConference *srvc; struct mwSession *session; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; PurpleConnection *gc; char *esc; @@ -2167,7 +2168,7 @@ struct mwServiceFileTransfer *srvc; struct mwSession *session; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; PurpleConnection *gc; PurpleAccount *acct; const char *who; @@ -2412,7 +2413,7 @@ static PurpleIMConversation *convo_get_im(struct mwConversation *conv) { struct mwServiceIm *srvc; struct mwSession *session; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; PurpleConnection *gc; PurpleAccount *acct; @@ -2560,7 +2561,7 @@ static void mw_conversation_opened(struct mwConversation *conv) { struct mwServiceIm *srvc; struct mwSession *session; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; PurpleConnection *gc; PurpleAccount *acct; @@ -2635,7 +2636,7 @@ static void im_recv_text(struct mwConversation *conv, - struct mwPurplePluginData *pd, + struct mwPurpleProtocolData *pd, const char *msg) { struct mwIdBlock *idb; @@ -2656,7 +2657,7 @@ static void im_recv_typing(struct mwConversation *conv, - struct mwPurplePluginData *pd, + struct mwPurpleProtocolData *pd, gboolean typing) { struct mwIdBlock *idb; @@ -2668,7 +2669,7 @@ static void im_recv_html(struct mwConversation *conv, - struct mwPurplePluginData *pd, + struct mwPurpleProtocolData *pd, const char *msg) { struct mwIdBlock *idb; char *t1, *t2; @@ -2692,7 +2693,7 @@ static void im_recv_subj(struct mwConversation *conv, - struct mwPurplePluginData *pd, + struct mwPurpleProtocolData *pd, const char *subj) { /** @todo somehow indicate receipt of a conversation subject. It @@ -2721,7 +2722,7 @@ static void im_recv_mime(struct mwConversation *conv, - struct mwPurplePluginData *pd, + struct mwPurpleProtocolData *pd, const char *data) { GHashTable *img_by_cid; @@ -2860,7 +2861,7 @@ gconstpointer msg) { struct mwServiceIm *srvc; struct mwSession *session; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; srvc = mwConversation_getService(conv); session = mwService_getSession(MW_SERVICE(srvc)); @@ -2899,7 +2900,7 @@ const char *title, const char *name) { struct mwServiceIm *srvc; struct mwSession *session; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; struct mwIdBlock *idb; GHashTable *ht; @@ -2960,7 +2961,7 @@ static struct mwPlace * -place_find_by_id(struct mwPurplePluginData *pd, int id) { +place_find_by_id(struct mwPurpleProtocolData *pd, int id) { struct mwServicePlace *srvc = pd->srvc_place; struct mwPlace *place = NULL; GList *l; @@ -2983,7 +2984,7 @@ static void mw_place_opened(struct mwPlace *place) { struct mwServicePlace *srvc; struct mwSession *session; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; PurpleConnection *gc; PurpleChatConversation *gconf; @@ -3019,7 +3020,7 @@ static void mw_place_closed(struct mwPlace *place, guint32 code) { struct mwServicePlace *srvc; struct mwSession *session; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; PurpleConnection *gc; const char *n = mwPlace_getName(place); @@ -3089,7 +3090,7 @@ const char *msg) { struct mwServicePlace *srvc; struct mwSession *session; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; PurpleConnection *gc; char *esc; @@ -3144,13 +3145,13 @@ } -/** allocate and associate a mwPurplePluginData with a PurpleConnection */ -static struct mwPurplePluginData *mwPurplePluginData_new(PurpleConnection *gc) { - struct mwPurplePluginData *pd; +/** allocate and associate a mwPurpleProtocolData with a PurpleConnection */ +static struct mwPurpleProtocolData *mwPurpleProtocolData_new(PurpleConnection *gc) { + struct mwPurpleProtocolData *pd; g_return_val_if_fail(gc != NULL, NULL); - pd = g_new0(struct mwPurplePluginData, 1); + pd = g_new0(struct mwPurpleProtocolData, 1); pd->gc = gc; pd->session = mwSession_new(&mw_session_handler); pd->srvc_aware = mw_srvc_aware_new(pd->session); @@ -3181,7 +3182,7 @@ } -static void mwPurplePluginData_free(struct mwPurplePluginData *pd) { +static void mwPurpleProtocolData_free(struct mwPurpleProtocolData *pd) { g_return_if_fail(pd != NULL); purple_connection_set_protocol_data(pd->gc, NULL); @@ -3214,7 +3215,7 @@ } -static const char *mw_prpl_list_icon(PurpleAccount *a, PurpleBuddy *b) { +static const char *mw_protocol_list_icon(PurpleAccount *a, PurpleBuddy *b) { /* my little green dude is a chopped up version of the aim running guy. First, cut off the head and store someplace safe. Then, take the left-half side of the body and throw it away. Make a @@ -3230,7 +3231,7 @@ } -static const char* mw_prpl_list_emblem(PurpleBuddy *b) +static const char* mw_protocol_list_emblem(PurpleBuddy *b) { if(buddy_is_external(b)) return "external"; @@ -3239,9 +3240,9 @@ } -static char *mw_prpl_status_text(PurpleBuddy *b) { +static char *mw_protocol_status_text(PurpleBuddy *b) { PurpleConnection *gc; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; struct mwAwareIdBlock t = { mwAware_USER, (char *)purple_buddy_get_name(b), NULL }; const char *ret = NULL; @@ -3299,9 +3300,9 @@ } -static void mw_prpl_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) { +static void mw_protocol_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) { PurpleConnection *gc; - struct mwPurplePluginData *pd = NULL; + struct mwPurpleProtocolData *pd = NULL; struct mwAwareIdBlock idb = { mwAware_USER, (char *)purple_buddy_get_name(b), NULL }; const char *message = NULL; @@ -3334,7 +3335,7 @@ } } -static GList *mw_prpl_status_types(PurpleAccount *acct) +static GList *mw_protocol_status_types(PurpleAccount *acct) { GList *types = NULL; PurpleStatusType *type; @@ -3375,7 +3376,7 @@ PurpleRequestFields *fields) { PurpleAccount *acct; PurpleConnection *gc; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; struct mwServiceConference *srvc; PurpleRequestField *f; @@ -3540,7 +3541,7 @@ PurpleBuddy *buddy = (PurpleBuddy *) node; PurpleAccount *acct; PurpleConnection *gc; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; GList *l; g_return_if_fail(node != NULL); @@ -3577,7 +3578,7 @@ PurpleBuddy *buddy = (PurpleBuddy *) node; PurpleAccount *acct; PurpleConnection *gc; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; struct mwSession *session; char *rcpt_name; GList *rcpt; @@ -3608,7 +3609,7 @@ #endif -static GList *mw_prpl_blist_node_menu(PurpleBlistNode *node) { +static GList *mw_protocol_blist_node_menu(PurpleBlistNode *node) { GList *l = NULL; PurpleMenuAction *act; @@ -3636,7 +3637,7 @@ } -static GList *mw_prpl_chat_info(PurpleConnection *gc) { +static GList *mw_protocol_chat_info(PurpleConnection *gc) { GList *l = NULL; struct proto_chat_entry *pce; @@ -3649,7 +3650,7 @@ } -static GHashTable *mw_prpl_chat_info_defaults(PurpleConnection *gc, +static GHashTable *mw_protocol_chat_info_defaults(PurpleConnection *gc, const char *name) { GHashTable *table; @@ -3665,18 +3666,18 @@ } -static void mw_prpl_login(PurpleAccount *acct); - - -static void mw_prpl_login(PurpleAccount *account) { +static void mw_protocol_login(PurpleAccount *acct); + + +static void mw_protocol_login(PurpleAccount *account) { PurpleConnection *gc; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; char *user, *pass, *host; guint port; gc = purple_account_get_connection(account); - pd = mwPurplePluginData_new(gc); + pd = mwPurpleProtocolData_new(gc); /* while we do support images, the default is to not offer it */ purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_NO_IMAGES); @@ -3750,8 +3751,8 @@ } -static void mw_prpl_close(PurpleConnection *gc) { - struct mwPurplePluginData *pd; +static void mw_protocol_close(PurpleConnection *gc) { + struct mwPurpleProtocolData *pd; g_return_if_fail(gc != NULL); @@ -3778,7 +3779,7 @@ } /* clean up the rest */ - mwPurplePluginData_free(pd); + mwPurpleProtocolData_free(pd); } @@ -3950,12 +3951,12 @@ } -static int mw_prpl_send_im(PurpleConnection *gc, +static int mw_protocol_send_im(PurpleConnection *gc, const char *name, const char *message, PurpleMessageFlags flags) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; struct mwIdBlock who = { (char *) name, NULL }; struct mwConversation *conv; @@ -4024,11 +4025,11 @@ } -static unsigned int mw_prpl_send_typing(PurpleConnection *gc, +static unsigned int mw_protocol_send_typing(PurpleConnection *gc, const char *name, PurpleIMTypingState state) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; struct mwIdBlock who = { (char *) name, NULL }; struct mwConversation *conv; @@ -4117,11 +4118,11 @@ } -static void mw_prpl_get_info(PurpleConnection *gc, const char *who) { +static void mw_protocol_get_info(PurpleConnection *gc, const char *who) { struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL }; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; PurpleAccount *acct; PurpleBuddy *b; PurpleNotifyUserInfo *user_info; @@ -4190,7 +4191,7 @@ } -static void mw_prpl_set_status(PurpleAccount *acct, PurpleStatus *status) { +static void mw_protocol_set_status(PurpleAccount *acct, PurpleStatus *status) { PurpleConnection *gc; const char *state; char *message = NULL; @@ -4243,7 +4244,7 @@ } -static void mw_prpl_set_idle(PurpleConnection *gc, int t) { +static void mw_protocol_set_idle(PurpleConnection *gc, int t) { struct mwSession *session; struct mwUserStatus stat; @@ -4369,7 +4370,7 @@ BuddyAddData *data = b; PurpleBuddy *buddy = NULL; PurpleConnection *gc; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; g_return_if_fail(data != NULL); @@ -4453,12 +4454,12 @@ } -static void mw_prpl_add_buddy(PurpleConnection *gc, +static void mw_protocol_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message) { - struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc); + struct mwPurpleProtocolData *pd = purple_connection_get_protocol_data(gc); struct mwServiceResolve *srvc; GList *query; enum mwResolveFlag flags; @@ -4492,7 +4493,7 @@ static void foreach_add_buddies(PurpleGroup *group, GList *buddies, - struct mwPurplePluginData *pd) { + struct mwPurpleProtocolData *pd) { struct mwAwareList *list; list = list_ensure(pd, group); @@ -4501,12 +4502,12 @@ } -static void mw_prpl_add_buddies(PurpleConnection *gc, +static void mw_protocol_add_buddies(PurpleConnection *gc, GList *buddies, GList *groups, const char *message) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; GHashTable *group_sets; struct mwAwareIdBlock *idbs, *idb; @@ -4552,10 +4553,10 @@ } -static void mw_prpl_remove_buddy(PurpleConnection *gc, +static void mw_protocol_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; struct mwAwareIdBlock idb = { mwAware_USER, (char *)purple_buddy_get_name(buddy), NULL }; struct mwAwareList *list; @@ -4592,9 +4593,9 @@ } -static void mw_prpl_set_permit_deny(PurpleConnection *gc) { +static void mw_protocol_set_permit_deny(PurpleConnection *gc) { PurpleAccount *acct; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; struct mwSession *session; struct mwPrivacyInfo privacy = { @@ -4647,23 +4648,23 @@ } -static void mw_prpl_add_permit(PurpleConnection *gc, const char *name) { - mw_prpl_set_permit_deny(gc); -} - - -static void mw_prpl_add_deny(PurpleConnection *gc, const char *name) { - mw_prpl_set_permit_deny(gc); -} - - -static void mw_prpl_rem_permit(PurpleConnection *gc, const char *name) { - mw_prpl_set_permit_deny(gc); -} - - -static void mw_prpl_rem_deny(PurpleConnection *gc, const char *name) { - mw_prpl_set_permit_deny(gc); +static void mw_protocol_add_permit(PurpleConnection *gc, const char *name) { + mw_protocol_set_permit_deny(gc); +} + + +static void mw_protocol_add_deny(PurpleConnection *gc, const char *name) { + mw_protocol_set_permit_deny(gc); +} + + +static void mw_protocol_rem_permit(PurpleConnection *gc, const char *name) { + mw_protocol_set_permit_deny(gc); +} + + +static void mw_protocol_rem_deny(PurpleConnection *gc, const char *name) { + mw_protocol_set_permit_deny(gc); } @@ -4686,10 +4687,10 @@ } -static void mw_prpl_join_chat(PurpleConnection *gc, +static void mw_protocol_join_chat(PurpleConnection *gc, GHashTable *components) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; char *c, *t; pd = purple_connection_get_protocol_data(gc); @@ -4727,10 +4728,10 @@ } -static void mw_prpl_reject_chat(PurpleConnection *gc, +static void mw_protocol_reject_chat(PurpleConnection *gc, GHashTable *components) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; struct mwServiceConference *srvc; char *c; @@ -4751,17 +4752,17 @@ } -static char *mw_prpl_get_chat_name(GHashTable *components) { +static char *mw_protocol_get_chat_name(GHashTable *components) { return g_hash_table_lookup(components, CHAT_KEY_NAME); } -static void mw_prpl_chat_invite(PurpleConnection *gc, +static void mw_protocol_chat_invite(PurpleConnection *gc, int id, const char *invitation, const char *who) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; struct mwConference *conf; struct mwPlace *place; struct mwIdBlock idb = { (char *) who, NULL }; @@ -4784,10 +4785,10 @@ } -static void mw_prpl_chat_leave(PurpleConnection *gc, +static void mw_protocol_chat_leave(PurpleConnection *gc, int id) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; struct mwConference *conf; pd = purple_connection_get_protocol_data(gc); @@ -4807,21 +4808,21 @@ } -static void mw_prpl_chat_whisper(PurpleConnection *gc, +static void mw_protocol_chat_whisper(PurpleConnection *gc, int id, const char *who, const char *message) { - mw_prpl_send_im(gc, who, message, 0); -} - - -static int mw_prpl_chat_send(PurpleConnection *gc, + mw_protocol_send_im(gc, who, message, 0); +} + + +static int mw_protocol_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; struct mwConference *conf; char *msg; int ret; @@ -4848,7 +4849,7 @@ } -static void mw_prpl_keepalive(PurpleConnection *gc) { +static void mw_protocol_keepalive(PurpleConnection *gc) { struct mwSession *session; g_return_if_fail(gc != NULL); @@ -4860,11 +4861,11 @@ } -static void mw_prpl_alias_buddy(PurpleConnection *gc, +static void mw_protocol_alias_buddy(PurpleConnection *gc, const char *who, const char *alias) { - struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc); + struct mwPurpleProtocolData *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 @@ -4874,7 +4875,7 @@ } -static void mw_prpl_group_buddy(PurpleConnection *gc, +static void mw_protocol_group_buddy(PurpleConnection *gc, const char *who, const char *old_group, const char *new_group) { @@ -4882,7 +4883,7 @@ struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL }; GList *gl = g_list_prepend(NULL, &idb); - struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc); + struct mwPurpleProtocolData *pd = purple_connection_get_protocol_data(gc); PurpleGroup *group; struct mwAwareList *list; @@ -4903,12 +4904,12 @@ } -static void mw_prpl_rename_group(PurpleConnection *gc, +static void mw_protocol_rename_group(PurpleConnection *gc, const char *old, PurpleGroup *group, GList *buddies) { - struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc); + struct mwPurpleProtocolData *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 @@ -4921,14 +4922,14 @@ } -static void mw_prpl_buddy_free(PurpleBuddy *buddy) { +static void mw_protocol_buddy_free(PurpleBuddy *buddy) { /* I don't think we have any cleanup for buddies yet */ ; } -static void mw_prpl_convo_closed(PurpleConnection *gc, const char *who) { - struct mwPurplePluginData *pd = purple_connection_get_protocol_data(gc); +static void mw_protocol_convo_closed(PurpleConnection *gc, const char *who) { + struct mwPurpleProtocolData *pd = purple_connection_get_protocol_data(gc); struct mwServiceIm *srvc; struct mwConversation *conv; struct mwIdBlock idb = { (char *) who, NULL }; @@ -4946,7 +4947,7 @@ } -static const char *mw_prpl_normalize(const PurpleAccount *account, +static const char *mw_protocol_normalize(const PurpleAccount *account, const char *id) { /* code elsewhere assumes that the return value points to different @@ -4959,8 +4960,8 @@ } -static void mw_prpl_remove_group(PurpleConnection *gc, PurpleGroup *group) { - struct mwPurplePluginData *pd; +static void mw_protocol_remove_group(PurpleConnection *gc, PurpleGroup *group) { + struct mwPurpleProtocolData *pd; struct mwAwareList *list; pd = purple_connection_get_protocol_data(gc); @@ -4979,9 +4980,9 @@ } -static gboolean mw_prpl_can_receive_file(PurpleConnection *gc, +static gboolean mw_protocol_can_receive_file(PurpleConnection *gc, const char *who) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; struct mwServiceAware *srvc; PurpleAccount *acct; @@ -5005,7 +5006,7 @@ PurpleAccount *acct; PurpleConnection *gc; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; struct mwServiceFileTransfer *srvc; struct mwFileTransfer *ft; @@ -5068,7 +5069,7 @@ } -static PurpleXfer *mw_prpl_new_xfer(PurpleConnection *gc, const char *who) { +static PurpleXfer *mw_protocol_new_xfer(PurpleConnection *gc, const char *who) { PurpleAccount *acct; PurpleXfer *xfer; @@ -5084,10 +5085,10 @@ return xfer; } -static void mw_prpl_send_file(PurpleConnection *gc, +static void mw_protocol_send_file(PurpleConnection *gc, const char *who, const char *file) { - PurpleXfer *xfer = mw_prpl_new_xfer(gc, who); + PurpleXfer *xfer = mw_protocol_new_xfer(gc, who); if(file) { DEBUG_INFO("file != NULL\n"); @@ -5099,81 +5100,6 @@ } } - -static PurplePluginProtocolInfo mw_prpl_info = { - sizeof(PurplePluginProtocolInfo), - OPT_PROTO_IM_IMAGE, - NULL, /*< set in mw_plugin_init */ - NULL, /*< set in mw_plugin_init */ - NO_BUDDY_ICONS, - mw_prpl_list_icon, - mw_prpl_list_emblem, - mw_prpl_status_text, - mw_prpl_tooltip_text, - mw_prpl_status_types, - mw_prpl_blist_node_menu, - mw_prpl_chat_info, - mw_prpl_chat_info_defaults, - mw_prpl_login, - mw_prpl_close, - mw_prpl_send_im, - NULL, - mw_prpl_send_typing, - mw_prpl_get_info, - mw_prpl_set_status, - mw_prpl_set_idle, - NULL, - mw_prpl_add_buddy, - mw_prpl_add_buddies, - mw_prpl_remove_buddy, - NULL, - mw_prpl_add_permit, - mw_prpl_add_deny, - mw_prpl_rem_permit, - mw_prpl_rem_deny, - mw_prpl_set_permit_deny, - mw_prpl_join_chat, - mw_prpl_reject_chat, - mw_prpl_get_chat_name, - mw_prpl_chat_invite, - mw_prpl_chat_leave, - mw_prpl_chat_whisper, - mw_prpl_chat_send, - mw_prpl_keepalive, - NULL, - NULL, - mw_prpl_alias_buddy, - mw_prpl_group_buddy, - mw_prpl_rename_group, - mw_prpl_buddy_free, - mw_prpl_convo_closed, - mw_prpl_normalize, - NULL, - mw_prpl_remove_group, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - mw_prpl_can_receive_file, - mw_prpl_send_file, - mw_prpl_new_xfer, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL -}; - #if 0 static PurplePluginPrefFrame * mw_plugin_get_plugin_pref_frame(PurplePlugin *plugin) { @@ -5186,7 +5112,7 @@ purple_plugin_pref_frame_add(frame, pref); - pref = purple_plugin_pref_new_with_name(MW_PRPL_OPT_BLIST_ACTION); + pref = purple_plugin_pref_new_with_name(MW_PROTOCOL_OPT_BLIST_ACTION); purple_plugin_pref_set_label(pref, _("Buddy List Storage Mode")); purple_plugin_pref_set_type(pref, PURPLE_PLUGIN_PREF_CHOICE); @@ -5233,12 +5159,12 @@ /** prompts for a file to import blist from */ -static void st_import_action(PurplePluginAction *act) { +static void st_import_action(PurpleProtocolAction *act) { PurpleConnection *gc; PurpleAccount *account; char *title; - gc = act->context; + gc = act->connection; account = purple_connection_get_account(gc); title = g_strdup_printf(_("Import Sametime List for Account %s"), purple_account_get_username(account)); @@ -5273,12 +5199,12 @@ /** prompts for a file to export blist to */ -static void st_export_action(PurplePluginAction *act) { +static void st_export_action(PurpleProtocolAction *act) { PurpleConnection *gc; PurpleAccount *account; char *title; - gc = act->context; + gc = act->connection; account = purple_connection_get_account(gc); title = g_strdup_printf(_("Export Sametime List for Account %s"), purple_account_get_username(account)); @@ -5314,7 +5240,7 @@ } -static void remote_group_done(struct mwPurplePluginData *pd, +static void remote_group_done(struct mwPurpleProtocolData *pd, const char *id, const char *name) { PurpleConnection *gc; PurpleAccount *acct; @@ -5359,7 +5285,7 @@ } -static void remote_group_multi_cb(struct mwPurplePluginData *pd, +static void remote_group_multi_cb(struct mwPurpleProtocolData *pd, PurpleRequestFields *fields) { PurpleRequestField *f; GList *l; @@ -5380,7 +5306,7 @@ static void remote_group_multi(struct mwResolveResult *result, - struct mwPurplePluginData *pd) { + struct mwPurpleProtocolData *pd) { PurpleRequestFields *fields; PurpleRequestFieldGroup *g; @@ -5436,7 +5362,7 @@ struct mwResolveResult *res = NULL; struct mwSession *session; - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; PurpleConnection *gc; session = mwService_getSession(MW_SERVICE(srvc)); @@ -5476,7 +5402,7 @@ static void remote_group_action_cb(PurpleConnection *gc, const char *name) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; struct mwServiceResolve *srvc; GList *query; enum mwResolveFlag flags; @@ -5498,12 +5424,12 @@ } -static void remote_group_action(PurplePluginAction *act) { +static void remote_group_action(PurpleProtocolAction *act) { PurpleConnection *gc; const char *msgA; const char *msgB; - gc = act->context; + gc = act->connection; msgA = _("Notes Address Book Group"); msgB = _("Enter the name of a Notes Address Book group in the field below" @@ -5601,7 +5527,7 @@ static void search_action_cb(PurpleConnection *gc, const char *name) { - struct mwPurplePluginData *pd; + struct mwPurpleProtocolData *pd; struct mwServiceResolve *srvc; GList *query; enum mwResolveFlag flags; @@ -5623,12 +5549,12 @@ } -static void search_action(PurplePluginAction *act) { +static void search_action(PurpleProtocolAction *act) { PurpleConnection *gc; const char *msgA; const char *msgB; - gc = act->context; + gc = act->connection; msgA = _("Search for a user"); msgB = _("Enter a name or partial ID in the field below to search" @@ -5643,23 +5569,23 @@ } -static GList *mw_plugin_actions(PurplePlugin *plugin, gpointer context) { - PurplePluginAction *act; +static GList *mw_protocol_get_actions(PurpleConnection *gc) { + PurpleProtocolAction *act; GList *l = NULL; - act = purple_plugin_action_new(_("Import Sametime List..."), + act = purple_protocol_action_new(_("Import Sametime List..."), st_import_action); l = g_list_append(l, act); - act = purple_plugin_action_new(_("Export Sametime List..."), + act = purple_protocol_action_new(_("Export Sametime List..."), st_export_action); l = g_list_append(l, act); - act = purple_plugin_action_new(_("Add Notes Address Book Group..."), + act = purple_protocol_action_new(_("Add Notes Address Book Group..."), remote_group_action); l = g_list_append(l, act); - act = purple_plugin_action_new(_("User Search..."), + act = purple_protocol_action_new(_("User Search..."), search_action); l = g_list_append(l, act); @@ -5667,57 +5593,6 @@ } -static gboolean mw_plugin_load(PurplePlugin *plugin) { - return TRUE; -} - - -static gboolean mw_plugin_unload(PurplePlugin *plugin) { - return TRUE; -} - - -static void mw_plugin_destroy(PurplePlugin *plugin) { - g_log_remove_handler(G_LOG_DOMAIN, log_handler[0]); - g_log_remove_handler("meanwhile", log_handler[1]); -} - -static PurplePluginInfo mw_plugin_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 */ - - PLUGIN_ID, /**< id */ - PLUGIN_NAME, /**< name */ - DISPLAY_VERSION, /**< version */ - PLUGIN_SUMMARY, /**< summary */ - PLUGIN_DESC, /**< description */ - PLUGIN_AUTHOR, /**< author */ - PLUGIN_HOMEPAGE, /**< homepage */ - - mw_plugin_load, /**< load */ - mw_plugin_unload, /**< unload */ - mw_plugin_destroy, /**< destroy */ - - NULL, /**< ui_info */ - &mw_prpl_info, /**< extra_info */ - NULL, /**< prefs_info */ - mw_plugin_actions, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - - static void mw_log_handler(const gchar *domain, GLogLevelFlags flags, const gchar *msg, gpointer data) { @@ -5736,7 +5611,105 @@ } -static void mw_plugin_init(PurplePlugin *plugin) { +static PurpleProtocol mw_protocol = { + PLUGIN_ID, + PLUGIN_NAME, + sizeof(PurpleProtocol), + OPT_PROTO_IM_IMAGE, + NULL, /*< set in mw_plugin_init */ + NULL, /*< set in mw_plugin_init */ + NO_BUDDY_ICONS, + mw_protocol_get_actions, + mw_protocol_list_icon, + mw_protocol_list_emblem, + mw_protocol_status_text, + mw_protocol_tooltip_text, + mw_protocol_status_types, + mw_protocol_blist_node_menu, + mw_protocol_chat_info, + mw_protocol_chat_info_defaults, + mw_protocol_login, + mw_protocol_close, + mw_protocol_send_im, + NULL, + mw_protocol_send_typing, + mw_protocol_get_info, + mw_protocol_set_status, + mw_protocol_set_idle, + NULL, + mw_protocol_add_buddy, + mw_protocol_add_buddies, + mw_protocol_remove_buddy, + NULL, + mw_protocol_add_permit, + mw_protocol_add_deny, + mw_protocol_rem_permit, + mw_protocol_rem_deny, + mw_protocol_set_permit_deny, + mw_protocol_join_chat, + mw_protocol_reject_chat, + mw_protocol_get_chat_name, + mw_protocol_chat_invite, + mw_protocol_chat_leave, + mw_protocol_chat_whisper, + mw_protocol_chat_send, + mw_protocol_keepalive, + NULL, + NULL, + mw_protocol_alias_buddy, + mw_protocol_group_buddy, + mw_protocol_rename_group, + mw_protocol_buddy_free, + mw_protocol_convo_closed, + mw_protocol_normalize, + NULL, + mw_protocol_remove_group, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + mw_protocol_can_receive_file, + mw_protocol_send_file, + mw_protocol_new_xfer, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + + +static PurplePluginInfo * +plugin_query(GError **error) +{ + return purple_plugin_info_new( + "id", PLUGIN_ID, + "name", PLUGIN_NAME, + "version", DISPLAY_VERSION, + "category", PLUGIN_CATEGORY, + "summary", PLUGIN_SUMMARY, + "description", PLUGIN_DESC, + "author", PLUGIN_AUTHOR, + "website", PLUGIN_HOMEPAGE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); +} + + +static gboolean plugin_load(PurplePlugin *plugin, GError **error) { PurpleAccountUserSplit *split; PurpleAccountOption *opt; GList *l = NULL; @@ -5745,17 +5718,17 @@ G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION; /* set up the preferences */ - purple_prefs_add_none(MW_PRPL_OPT_BASE); - purple_prefs_add_int(MW_PRPL_OPT_BLIST_ACTION, BLIST_CHOICE_DEFAULT); + purple_prefs_add_none(MW_PROTOCOL_OPT_BASE); + purple_prefs_add_int(MW_PROTOCOL_OPT_BLIST_ACTION, BLIST_CHOICE_DEFAULT); /* set up account ID as user:server */ split = purple_account_user_split_new(_("Server"), MW_PLUGIN_DEFAULT_HOST, ':'); - mw_prpl_info.user_splits = g_list_append(mw_prpl_info.user_splits, split); + mw_protocol.user_splits = g_list_append(mw_protocol.user_splits, split); /* remove dead preferences */ - purple_prefs_remove(MW_PRPL_OPT_PSYCHIC); - purple_prefs_remove(MW_PRPL_OPT_SAVE_DYNAMIC); + purple_prefs_remove(MW_PROTOCOL_OPT_PSYCHIC); + purple_prefs_remove(MW_PROTOCOL_OPT_SAVE_DYNAMIC); /* port to connect to */ opt = purple_account_option_int_new(_("Port"), MW_KEY_PORT, @@ -5768,8 +5741,8 @@ gboolean b = FALSE; const char *label = _("Force login (ignore server redirects)"); - if(purple_prefs_exists(MW_PRPL_OPT_FORCE_LOGIN)) - b = purple_prefs_get_bool(MW_PRPL_OPT_FORCE_LOGIN); + if(purple_prefs_exists(MW_PROTOCOL_OPT_FORCE_LOGIN)) + b = purple_prefs_get_bool(MW_PROTOCOL_OPT_FORCE_LOGIN); opt = purple_account_option_bool_new(label, MW_KEY_FORCE, b); l = g_list_append(l, opt); @@ -5780,7 +5753,7 @@ MW_KEY_FAKE_IT, FALSE); l = g_list_append(l, opt); - mw_prpl_info.protocol_options = l; + mw_protocol.protocol_options = l; l = NULL; /* forward all our g_log messages to purple. Generally all the logging @@ -5792,9 +5765,21 @@ /* redirect meanwhile's logging to purple's */ log_handler[1] = g_log_set_handler("meanwhile", logflags, mw_log_handler, NULL); -} - - -PURPLE_INIT_PLUGIN(sametime, mw_plugin_init, mw_plugin_info); + + purple_protocols_add(&mw_protocol); + return TRUE; +} + + +static gboolean plugin_unload(PurplePlugin *plugin, GError **error) { + g_log_remove_handler(G_LOG_DOMAIN, log_handler[0]); + g_log_remove_handler("meanwhile", log_handler[1]); + + purple_protocols_remove(&mw_protocol); + return TRUE; +} + + +PURPLE_PLUGIN_INIT(sametime, plugin_query, plugin_load, plugin_unload); /* The End. */
--- a/libpurple/protocols/silc/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/silc/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -43,4 +43,5 @@ -I$(top_builddir)/libpurple \ $(DEBUG_CFLAGS) \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(SILC_CFLAGS)
--- a/libpurple/protocols/silc/buddy.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/silc/buddy.c Sun Aug 18 01:53:00 2013 +0530 @@ -731,7 +731,7 @@ _("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); + purple_protocol_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL); } static void @@ -774,7 +774,7 @@ "%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); + purple_protocol_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); if (r->public_key) @@ -1007,7 +1007,7 @@ 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); + purple_protocol_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 */
--- a/libpurple/protocols/silc/ops.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/silc/ops.c Sun Aug 18 01:53:00 2013 +0530 @@ -904,7 +904,7 @@ 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); + purple_protocol_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) || @@ -912,16 +912,16 @@ (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); + purple_protocol_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); + purple_protocol_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); + purple_protocol_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL); } } break;
--- a/libpurple/protocols/silc/silc.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/silc/silc.c Sun Aug 18 01:53:00 2013 +0530 @@ -902,9 +902,9 @@ } static void -silcpurple_attrs(PurplePluginAction *action) +silcpurple_attrs(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; SilcPurple sg = purple_connection_get_protocol_data(gc); SilcClient client = sg->client; SilcClientConnection conn = sg->conn; @@ -1069,9 +1069,9 @@ } static void -silcpurple_detach(PurplePluginAction *action) +silcpurple_detach(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; SilcPurple sg; if (!gc) @@ -1086,9 +1086,9 @@ } static void -silcpurple_view_motd(PurplePluginAction *action) +silcpurple_view_motd(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; SilcPurple sg; char *tmp; @@ -1209,9 +1209,9 @@ } static void -silcpurple_create_keypair(PurplePluginAction *action) +silcpurple_create_keypair(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; SilcPurple sg = purple_connection_get_protocol_data(gc); PurpleRequestFields *fields; PurpleRequestFieldGroup *g; @@ -1280,9 +1280,9 @@ } static void -silcpurple_change_pass(PurplePluginAction *action) +silcpurple_change_pass(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; purple_account_request_change_password(purple_connection_get_account(gc)); } @@ -1297,9 +1297,9 @@ } static void -silcpurple_show_set_info(PurplePluginAction *action) +silcpurple_show_set_info(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; purple_account_request_change_user_info(purple_connection_get_account(gc)); } @@ -1309,32 +1309,32 @@ } static GList * -silcpurple_actions(PurplePlugin *plugin, gpointer context) +silcpurple_get_actions(PurpleConnection *gc) { GList *list = NULL; - PurplePluginAction *act; + PurpleProtocolAction *act; - act = purple_plugin_action_new(_("Online Status"), + act = purple_protocol_action_new(_("Online Status"), silcpurple_attrs); list = g_list_append(list, act); - act = purple_plugin_action_new(_("Detach From Server"), + act = purple_protocol_action_new(_("Detach From Server"), silcpurple_detach); list = g_list_append(list, act); - act = purple_plugin_action_new(_("View Message of the Day"), + act = purple_protocol_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..."), + act = purple_protocol_action_new(_("Create SILC Key Pair..."), silcpurple_create_keypair); list = g_list_append(list, act); - act = purple_plugin_action_new(_("Change Password..."), + act = purple_protocol_action_new(_("Change Password..."), silcpurple_change_pass); list = g_list_append(list, act); - act = purple_plugin_action_new(_("Set User Info..."), + act = purple_protocol_action_new(_("Set User Info..."), silcpurple_show_set_info); list = g_list_append(list, act); @@ -1914,120 +1914,120 @@ static void silcpurple_register_commands(void) { - purple_cmd_register("part", "w", PURPLE_CMD_P_PRPL, + purple_cmd_register("part", "w", PURPLE_CMD_P_PROTOCOL, PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, + PURPLE_CMD_FLAG_PROTOCOL_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_register("leave", "w", PURPLE_CMD_P_PROTOCOL, PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, + PURPLE_CMD_FLAG_PROTOCOL_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_register("topic", "s", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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_register("join", "ws", PURPLE_CMD_P_PROTOCOL, PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, + PURPLE_CMD_FLAG_PROTOCOL_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_register("list", "", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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, + purple_cmd_register("whois", "w", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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, + purple_cmd_register("msg", "ws", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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_register("query", "ws", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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_register("motd", "", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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, + purple_cmd_register("detach", "", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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_register("quit", "s", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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, + purple_cmd_register("call", "s", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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_register("kill", "ws", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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, + purple_cmd_register("nick", "w", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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_register("whowas", "ww", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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_register("cmode", "wws", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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_register("cumode", "wws", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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, + purple_cmd_register("umode", "w", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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, + purple_cmd_register("oper", "s", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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_register("invite", "ws", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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_register("kick", "wws", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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_register("info", "w", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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_register("ban", "ww", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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, + purple_cmd_register("getkey", "w", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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, + purple_cmd_register("stats", "", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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, + purple_cmd_register("ping", "", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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, + purple_cmd_register("users", "w", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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_register("names", "ww", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_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 @@ -2051,15 +2051,18 @@ NULL }; -static PurplePluginProtocolInfo prpl_info = +static PurpleProtocol protocol = { - sizeof(PurplePluginProtocolInfo), /* struct_size */ + "prpl-silc", /* id */ + "SILC", /* name */ + sizeof(PurpleProtocol), /* struct_size */ OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_PASSWORD_OPTIONAL | OPT_PROTO_IM_IMAGE | OPT_PROTO_SLASH_COMMANDS_NATIVE, NULL, /* user_splits */ NULL, /* protocol_options */ {"jpeg,gif,png,bmp", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ + silcpurple_get_actions, /* get_actions */ silcpurple_list_icon, /* list_icon */ NULL, /* list_emblems */ silcpurple_status_text, /* status_text */ @@ -2114,7 +2117,7 @@ silcpurple_ftp_send_file, /* send_file */ silcpurple_ftp_new_xfer, /* new_xfer */ NULL, /* offline_message */ - &silcpurple_wb_ops, /* whiteboard_prpl_ops */ + &silcpurple_wb_ops, /* whiteboard_protocol_ops */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ NULL, /* unregister_user */ @@ -2128,42 +2131,24 @@ NULL /* get_public_alias */ }; -static PurplePluginInfo info = +static PurplePluginInfo * +plugin_query(GError **error) { - 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.1", /**< 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 -}; + return purple_plugin_info_new( + "id", "prpl-silc", + "name", "SILC", + "version", "1.1", + "category", N_("Protocol"), + "summary", N_("SILC Protocol Plugin"), + "description", N_("Secure Internet Live Conferencing (SILC) Protocol"), + "author", "Pekka Riikonen", + "website", "http://silcnet.org/", + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); +} #if 0 static SilcBool silcpurple_debug_cb(char *file, char *function, int line, @@ -2174,8 +2159,8 @@ } #endif -static void -init_plugin(PurplePlugin *plugin) +static gboolean +plugin_load(PurplePlugin *plugin, GError **error) { PurpleAccountOption *option; PurpleAccountUserSplit *split; @@ -2187,23 +2172,23 @@ silc_plugin = plugin; split = purple_account_user_split_new(_("Network"), "silcnet.org", '@'); - prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); + protocol.user_splits = g_list_append(protocol.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); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_int_new(_("Port"), "port", 706); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.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); + protocol.protocol_options = g_list_append(protocol.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); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); for (i = 0; silc_default_ciphers[i].name; i++) { kvp = g_new0(PurpleKeyValuePair, 1); @@ -2212,7 +2197,7 @@ 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); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); list = NULL; for (i = 0; silc_default_hmacs[i].name; i++) { @@ -2222,27 +2207,27 @@ 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); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_bool_new(_("Use Perfect Forward Secrecy"), "pfs", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.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); + protocol.protocol_options = g_list_append(protocol.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); + protocol.protocol_options = g_list_append(protocol.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); + protocol.protocol_options = g_list_append(protocol.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); + protocol.protocol_options = g_list_append(protocol.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); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); purple_prefs_remove("/plugins/prpl/silc"); @@ -2256,6 +2241,15 @@ silc_log_set_debug_callbacks(silcpurple_debug_cb, NULL, NULL, NULL); #endif + purple_protocols_add(&protocol); + return TRUE; } -PURPLE_INIT_PLUGIN(silc, init_plugin, info); +static gboolean +plugin_unload(PurplePlugin *plugin, GError **error) +{ + purple_protocols_remove(&protocol); + return TRUE; +} + +PURPLE_PLUGIN_INIT(silc, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/silc/silcpurple.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/silc/silcpurple.h Sun Aug 18 01:53:00 2013 +0530 @@ -29,7 +29,7 @@ #include "debug.h" #include "ft.h" #include "notify.h" -#include "prpl.h" +#include "protocol.h" #include "request.h" #include "roomlist.h" #include "server.h"
--- a/libpurple/protocols/simple/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/simple/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -33,4 +33,5 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(DEBUG_CFLAGS)
--- a/libpurple/protocols/simple/simple.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/simple/simple.c Sun Aug 18 01:53:00 2013 +0530 @@ -32,8 +32,8 @@ #include "dnsquery.h" #include "debug.h" #include "notify.h" -#include "prpl.h" -#include "plugin.h" +#include "protocol.h" +#include "plugins.h" #include "util.h" #include "version.h" #include "network.h" @@ -820,7 +820,7 @@ /* we can not subscribe -> user is offline (TODO unknown status?) */ - purple_prpl_got_user_status(sip->account, to, "offline", NULL); + purple_protocol_got_user_status(sip->account, to, "offline", NULL); g_free(to); return TRUE; } @@ -1239,7 +1239,7 @@ b->dialog = NULL; } - purple_prpl_got_user_status(sip->account, from, "offline", NULL); + purple_protocol_got_user_status(sip->account, from, "offline", NULL); break; } i++; @@ -1276,9 +1276,9 @@ if(isonline) - purple_prpl_got_user_status(sip->account, from, "available", NULL); + purple_protocol_got_user_status(sip->account, from, "available", NULL); else - purple_prpl_got_user_status(sip->account, from, "offline", NULL); + purple_protocol_got_user_status(sip->account, from, "offline", NULL); xmlnode_free(pidf); g_free(from); @@ -2046,13 +2046,16 @@ purple_connection_set_protocol_data(gc, NULL); } -static PurplePluginProtocolInfo prpl_info = +static PurpleProtocol protocol = { - sizeof(PurplePluginProtocolInfo), /* struct_size */ + "prpl-simple", /* id */ + "SIMPLE", /* name */ + sizeof(PurpleProtocol), /* struct_size */ 0, NULL, /* user_splits */ NULL, /* protocol_options */ NO_BUDDY_ICONS, /* icon_spec */ + NULL, /* get_actions */ simple_list_icon, /* list_icon */ NULL, /* list_emblems */ NULL, /* status_text */ @@ -2107,7 +2110,7 @@ NULL, /* send_file */ NULL, /* new_xfer */ NULL, /* offline_message */ - NULL, /* whiteboard_prpl_ops */ + NULL, /* whiteboard_protocol_ops */ simple_send_raw, /* send_raw */ NULL, /* roomlist_room_serialize */ NULL, /* unregister_user */ @@ -2121,66 +2124,58 @@ NULL /* get_public_alias */ }; - -static PurplePluginInfo info = +static PurplePluginInfo * +plugin_query(GError **error) { - PURPLE_PLUGIN_MAGIC, - PURPLE_MAJOR_VERSION, - PURPLE_MINOR_VERSION, - PURPLE_PLUGIN_PROTOCOL, /**< type */ - NULL, /**< ui_requirement */ - 0, /**< flags */ - NULL, /**< dependencies */ - PURPLE_PRIORITY_DEFAULT, /**< priority */ + return purple_plugin_info_new( + "id", "prpl-simple", + "name", "SIMPLE", + "version", DISPLAY_VERSION, + "category", N_("Protocol"), + "summary", N_("SIP/SIMPLE Protocol Plugin"), + "description", N_("The SIP/SIMPLE Protocol Plugin"), + "author", "Thomas Butter <butter@uni-mannheim.de>", + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); +} - "prpl-simple", /**< id */ - "SIMPLE", /**< name */ - DISPLAY_VERSION, /**< version */ - N_("SIP/SIMPLE Protocol Plugin"), /** summary */ - N_("The SIP/SIMPLE Protocol Plugin"), /** description */ - "Thomas Butter <butter@uni-mannheim.de>", /**< author */ - PURPLE_WEBSITE, /**< homepage */ - - NULL, /**< load */ - NULL, /**< unload */ - NULL, /**< destroy */ - - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, - NULL, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - -static void _init_plugin(PurplePlugin *plugin) +static gboolean plugin_load(PurplePlugin *plugin, GError **error) { PurpleAccountUserSplit *split; PurpleAccountOption *option; split = purple_account_user_split_new(_("Server"), "", '@'); - prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); + protocol.user_splits = g_list_append(protocol.user_splits, split); option = purple_account_option_bool_new(_("Publish status (note: everyone may watch you)"), "dopublish", TRUE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_int_new(_("Connect port"), "port", 0); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_bool_new(_("Use UDP"), "udp", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_bool_new(_("Use proxy"), "useproxy", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("Proxy"), "proxy", ""); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("Auth User"), "authuser", ""); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("Auth Domain"), "authdomain", ""); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); + + purple_protocols_add(&protocol); + return TRUE; } -PURPLE_INIT_PLUGIN(simple, _init_plugin, info); +static gboolean plugin_unload(PurplePlugin *plugin, GError **error) +{ + purple_protocols_remove(&protocol); + return TRUE; +} + +PURPLE_PLUGIN_INIT(simple, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/simple/simple.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/simple/simple.h Sun Aug 18 01:53:00 2013 +0530 @@ -32,7 +32,7 @@ #include "dnssrv.h" #include "network.h" #include "proxy.h" -#include "prpl.h" +#include "protocol.h" #include "sipmsg.h"
--- a/libpurple/protocols/simple/sipmsg.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/simple/sipmsg.c Sun Aug 18 01:53:00 2013 +0530 @@ -27,8 +27,8 @@ #include "conversation.h" #include "debug.h" #include "notify.h" -#include "prpl.h" -#include "plugin.h" +#include "protocol.h" +#include "plugins.h" #include "util.h" #include "version.h"
--- a/libpurple/protocols/yahoo/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/yahoo/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -57,4 +57,5 @@ -I$(top_srcdir)/libpurple \ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(DEBUG_CFLAGS)
--- a/libpurple/protocols/yahoo/libyahoo.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/yahoo/libyahoo.c Sun Aug 18 01:53:00 2013 +0530 @@ -25,6 +25,7 @@ #include <account.h> #include <core.h> +#include <plugins.h> #include "libymsg.h" #include "yahoochat.h" @@ -33,26 +34,26 @@ #include "yahoo_filexfer.h" #include "yahoo_picture.h" -static PurplePlugin *my_protocol = NULL; +static PurpleProtocol *my_protocol = NULL; static void yahoo_register_commands(void) { - purple_cmd_register("join", "s", PURPLE_CMD_P_PRPL, + purple_cmd_register("join", "s", PURPLE_CMD_P_PROTOCOL, PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PRPL_ONLY, + PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-yahoo", yahoopurple_cmd_chat_join, _("join <room>: Join a chat room on the Yahoo network"), NULL); - purple_cmd_register("list", "", PURPLE_CMD_P_PRPL, + purple_cmd_register("list", "", PURPLE_CMD_P_PROTOCOL, PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PRPL_ONLY, + PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-yahoo", yahoopurple_cmd_chat_list, _("list: List rooms on the Yahoo network"), NULL); - purple_cmd_register("buzz", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY, + purple_cmd_register("buzz", "", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-yahoo", yahoopurple_cmd_buzz, _("buzz: Buzz a user to get their attention"), NULL); - purple_cmd_register("doodle", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY, + purple_cmd_register("doodle", "", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-yahoo", yahoo_doodle_purple_cmd_start, _("doodle: Request user to start a Doodle session"), NULL); } @@ -100,7 +101,7 @@ if (g_ascii_strcasecmp(proto, "ymsgr")) return FALSE; - acct = find_acct(purple_plugin_get_id(my_protocol), acct_id); + acct = find_acct(my_protocol->id, acct_id); if (!acct) return FALSE; @@ -167,14 +168,7 @@ return table; } -static gboolean yahoo_unload_plugin(PurplePlugin *plugin) -{ - yahoo_dest_colorht(); - - return TRUE; -} - -static PurpleWhiteboardPrplOps yahoo_whiteboard_prpl_ops = +static PurpleWhiteboardPrplOps yahoo_whiteboard_protocol_ops = { yahoo_doodle_start, yahoo_doodle_end, @@ -192,13 +186,16 @@ NULL }; -static PurplePluginProtocolInfo prpl_info = +static PurpleProtocol protocol = { - sizeof(PurplePluginProtocolInfo), /* struct_size */ + "prpl-yahoo", + "Yahoo", + sizeof(PurpleProtocol), /* struct_size */ OPT_PROTO_MAIL_CHECK | OPT_PROTO_CHAT_TOPIC | OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE, NULL, /* user_splits */ NULL, /* protocol_options */ {"png,gif,jpeg", 96, 96, 96, 96, 0, PURPLE_ICON_SCALE_SEND}, + yahoo_get_actions, yahoo_list_icon, yahoo_list_emblem, yahoo_status_text, @@ -253,7 +250,7 @@ yahoo_send_file, yahoo_new_xfer, yahoo_offline_message, /* offline_message */ - &yahoo_whiteboard_prpl_ops, + &yahoo_whiteboard_protocol_ops, NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ NULL, /* unregister_user */ @@ -267,74 +264,71 @@ NULL /* get_public_alias */ }; -static PurplePluginInfo info = +static PurplePluginInfo * +plugin_query(GError **error) { - 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-yahoo", /**< id */ - "Yahoo", /**< name */ - DISPLAY_VERSION, /**< version */ - /** summary */ - N_("Yahoo! Protocol Plugin"), - /** description */ - N_("Yahoo! Protocol Plugin"), - NULL, /**< author */ - PURPLE_WEBSITE, /**< homepage */ - NULL, /**< load */ - yahoo_unload_plugin, /**< unload */ - NULL, /**< destroy */ - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, - yahoo_actions, + return purple_plugin_info_new( + "id", "prpl-yahoo", + "name", "Yahoo", + "version", DISPLAY_VERSION, + "category", N_("Protocol"), + "summary", N_("Yahoo! Protocol Plugin"), + "description", N_("Yahoo! Protocol Plugin"), + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); +} - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - -static void -init_plugin(PurplePlugin *plugin) +static gboolean +plugin_load(PurplePlugin *plugin, GError **error) { PurpleAccountOption *option; option = purple_account_option_int_new(_("Pager port"), "port", YAHOO_PAGER_PORT); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("File transfer server"), "xfer_host", YAHOO_XFER_HOST); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("Chat room locale"), "room_list_locale", YAHOO_ROOMLIST_LOCALE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("Encoding"), "local_charset", "UTF-8"); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_bool_new(_("Ignore conference and chatroom invitations"), "ignore_invites", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); #if 0 option = purple_account_option_bool_new(_("Use account proxy for HTTP and HTTPS connections"), "proxy_ssl", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("Chat room list URL"), "room_list", YAHOO_ROOMLIST_URL); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); #endif - my_protocol = plugin; + my_protocol = &protocol; yahoo_register_commands(); yahoo_init_colorht(); - purple_signal_connect(purple_get_core(), "uri-handler", plugin, + purple_signal_connect(purple_get_core(), "uri-handler", my_protocol, PURPLE_CALLBACK(yahoo_uri_handler), NULL); + + purple_protocols_add(my_protocol); + + return TRUE; } -PURPLE_INIT_PLUGIN(yahoo, init_plugin, info); +static gboolean +plugin_unload(PurplePlugin *plugin, GError **error) +{ + yahoo_dest_colorht(); + purple_protocols_remove(my_protocol); + + return TRUE; +} + +PURPLE_PLUGIN_INIT(yahoo, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/yahoo/libyahoojp.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/yahoo/libyahoojp.c Sun Aug 18 01:53:00 2013 +0530 @@ -24,6 +24,7 @@ #include "internal.h" #include <account.h> +#include <plugins.h> #include "libymsg.h" #include "yahoochat.h" @@ -34,22 +35,22 @@ static void yahoojp_register_commands(void) { - purple_cmd_register("join", "s", PURPLE_CMD_P_PRPL, + purple_cmd_register("join", "s", PURPLE_CMD_P_PROTOCOL, PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PRPL_ONLY, + PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-yahoojp", yahoopurple_cmd_chat_join, _("join <room>: Join a chat room on the Yahoo network"), NULL); - purple_cmd_register("list", "", PURPLE_CMD_P_PRPL, + purple_cmd_register("list", "", PURPLE_CMD_P_PROTOCOL, PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PRPL_ONLY, + PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-yahoojp", yahoopurple_cmd_chat_list, _("list: List rooms on the Yahoo network"), NULL); - purple_cmd_register("buzz", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY, + purple_cmd_register("buzz", "", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-yahoojp", yahoopurple_cmd_buzz, _("buzz: Buzz a user to get their attention"), NULL); - purple_cmd_register("doodle", "", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY, + purple_cmd_register("doodle", "", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-yahoojp", yahoo_doodle_purple_cmd_start, _("doodle: Request user to start a Doodle session"), NULL); } @@ -63,14 +64,7 @@ return table; } -static gboolean yahoojp_unload_plugin(PurplePlugin *plugin) -{ - yahoo_dest_colorht(); - - return TRUE; -} - -static PurpleWhiteboardPrplOps yahoo_whiteboard_prpl_ops = +static PurpleWhiteboardPrplOps yahoo_whiteboard_protocol_ops = { yahoo_doodle_start, yahoo_doodle_end, @@ -88,13 +82,16 @@ NULL }; -static PurplePluginProtocolInfo prpl_info = +static PurpleProtocol protocol = { - sizeof(PurplePluginProtocolInfo), /* struct_size */ + "prpl-yahoojp", + "Yahoo JAPAN", + sizeof(PurpleProtocol), /* struct_size */ OPT_PROTO_MAIL_CHECK | OPT_PROTO_CHAT_TOPIC | OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE, NULL, /* user_splits */ NULL, /* protocol_options */ {"png,gif,jpeg", 96, 96, 96, 96, 0, PURPLE_ICON_SCALE_SEND}, + yahoo_get_actions, yahoo_list_icon, yahoo_list_emblem, yahoo_status_text, @@ -149,7 +146,7 @@ yahoo_send_file, yahoo_new_xfer, yahoo_offline_message, /* offline_message */ - &yahoo_whiteboard_prpl_ops, + &yahoo_whiteboard_protocol_ops, NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ NULL, /* unregister_user */ @@ -165,71 +162,67 @@ NULL /* get_public_alias */ }; -static PurplePluginInfo info = +static PurplePluginInfo * +plugin_query(GError **error) { - 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-yahoojp", /**< id */ - "Yahoo JAPAN", /**< name */ - DISPLAY_VERSION, /**< version */ - /** summary */ - N_("Yahoo! JAPAN Protocol Plugin"), - /** description */ - N_("Yahoo! JAPAN Protocol Plugin"), - NULL, /**< author */ - PURPLE_WEBSITE, /**< homepage */ - NULL, /**< load */ - yahoojp_unload_plugin, /**< unload */ - NULL, /**< destroy */ - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, - yahoo_actions, + return purple_plugin_info_new( + "id", "prpl-yahoojp", + "name", "Yahoo JAPAN", + "version", DISPLAY_VERSION, + "category", N_("Protocol"), + "summary", N_("Yahoo! JAPAN Protocol Plugin"), + "description", N_("Yahoo! JAPAN Protocol Plugin"), + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); +} - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - -static void -init_plugin(PurplePlugin *plugin) +static gboolean +plugin_load(PurplePlugin *plugin, GError **error) { PurpleAccountOption *option; option = purple_account_option_int_new(_("Pager port"), "port", YAHOO_PAGER_PORT); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("File transfer server"), "xfer_host", YAHOOJP_XFER_HOST); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("Chat room locale"), "room_list_locale", YAHOOJP_ROOMLIST_LOCALE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("Encoding"), "local_charset", "UTF-8"); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_bool_new(_("Ignore conference and chatroom invitations"), "ignore_invites", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); #if 0 option = purple_account_option_bool_new(_("Use account proxy for HTTP and HTTPS connections"), "proxy_ssl", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("Chat room list URL"), "room_list", YAHOO_ROOMLIST_URL); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); #endif yahoojp_register_commands(); yahoo_init_colorht(); + + purple_protocols_add(&protocol); + return TRUE; } -PURPLE_INIT_PLUGIN(yahoojp, init_plugin, info); +static gboolean +plugin_unload(PurplePlugin *plugin, GError **error) +{ + yahoo_dest_colorht(); + purple_protocols_remove(&protocol); + return TRUE; +} + +PURPLE_PLUGIN_INIT(yahoojp, plugin_query, plugin_load, plugin_unload); +
--- a/libpurple/protocols/yahoo/libymsg.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/yahoo/libymsg.c Sun Aug 18 01:53:00 2013 +0530 @@ -33,7 +33,7 @@ #include "http.h" #include "network.h" #include "notify.h" -#include "prpl.h" +#include "protocol.h" #include "proxy.h" #include "request.h" #include "server.h" @@ -133,21 +133,21 @@ if (status) { if (f->status == YAHOO_STATUS_CUSTOM) - purple_prpl_got_user_status(purple_connection_get_account(gc), name, status, "message", + purple_protocol_got_user_status(purple_connection_get_account(gc), name, status, "message", yahoo_friend_get_status_message(f), NULL); else - purple_prpl_got_user_status(purple_connection_get_account(gc), name, status, NULL); + purple_protocol_got_user_status(purple_connection_get_account(gc), name, status, NULL); } if (f->idle != 0) - purple_prpl_got_user_idle(purple_connection_get_account(gc), name, TRUE, f->idle); + purple_protocol_got_user_idle(purple_connection_get_account(gc), name, TRUE, f->idle); else - purple_prpl_got_user_idle(purple_connection_get_account(gc), name, FALSE, 0); + purple_protocol_got_user_idle(purple_connection_get_account(gc), name, FALSE, 0); if (f->sms) - purple_prpl_got_user_status(purple_connection_get_account(gc), name, YAHOO_STATUS_TYPE_MOBILE, NULL); + purple_protocol_got_user_status(purple_connection_get_account(gc), name, YAHOO_STATUS_TYPE_MOBILE, NULL); else - purple_prpl_got_user_status_deactive(purple_connection_get_account(gc), name, YAHOO_STATUS_TYPE_MOBILE); + purple_protocol_got_user_status_deactive(purple_connection_get_account(gc), name, YAHOO_STATUS_TYPE_MOBILE); } static void yahoo_process_status(PurpleConnection *gc, struct yahoo_packet *pkt) @@ -302,8 +302,8 @@ if (f) f->status = YAHOO_STATUS_OFFLINE; if (name) { - purple_prpl_got_user_status(account, name, "offline", NULL); - purple_prpl_got_user_status_deactive(account, name, YAHOO_STATUS_TYPE_MOBILE); + purple_protocol_got_user_status(account, name, "offline", NULL); + purple_protocol_got_user_status_deactive(account, name, YAHOO_STATUS_TYPE_MOBILE); } break; } @@ -1134,7 +1134,7 @@ char *username; username = g_markup_escape_text(im->fed_from, -1); - purple_prpl_got_attention(gc, username, YAHOO_BUZZ); + purple_protocol_got_attention(gc, username, YAHOO_BUZZ); g_free(username); g_free(m); g_free(im->fed_from); @@ -1295,7 +1295,7 @@ g_free(notify_msg); g_hash_table_remove(yd->friends, who); - purple_prpl_got_user_status(purple_connection_get_account(gc), who, "offline", NULL); /* FIXME: make this set not on list status instead */ + purple_protocol_got_user_status(purple_connection_get_account(gc), who, "offline", NULL); /* FIXME: make this set not on list status instead */ /* TODO: Shouldn't we remove the buddy from our local list? */ } @@ -4134,12 +4134,12 @@ } -static void yahoo_show_inbox(PurplePluginAction *action) +static void yahoo_show_inbox(PurpleProtocolAction *action) { /* Setup a cookie that can be used by the browser */ /* XXX I have no idea how this will work with Yahoo! Japan. */ - PurpleConnection *gc = action->context; + PurpleConnection *gc = action->connection; YahooData *yd = purple_connection_get_protocol_data(gc); PurpleHttpRequest *req; PurpleHttpCookieJar *cookiejar; @@ -4160,18 +4160,18 @@ #if 0 /* XXX: it doesn't seems to work */ static void -yahoo_set_userinfo_fn(PurplePluginAction *action) +yahoo_set_userinfo_fn(PurpleProtocolAction *action) { - yahoo_set_userinfo(action->context); + yahoo_set_userinfo(action->connection); } #endif -static void yahoo_show_act_id(PurplePluginAction *action) +static void yahoo_show_act_id(PurpleProtocolAction *action) { PurpleRequestFields *fields; PurpleRequestFieldGroup *group; PurpleRequestField *field; - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = (PurpleConnection *) action->connection; YahooData *yd = purple_connection_get_protocol_data(gc); const char *name = purple_connection_get_display_name(gc); int iter; @@ -4196,9 +4196,9 @@ gc); } -static void yahoo_show_chat_goto(PurplePluginAction *action) +static void yahoo_show_chat_goto(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; purple_request_input(gc, NULL, _("Join whom in chat?"), NULL, "", FALSE, FALSE, NULL, _("OK"), G_CALLBACK(yahoo_chat_goto), @@ -4207,27 +4207,27 @@ gc); } -GList *yahoo_actions(PurplePlugin *plugin, gpointer context) { +GList *yahoo_get_actions(PurpleConnection *gc) { GList *m = NULL; - PurplePluginAction *act; + PurpleProtocolAction *act; #if 0 /* XXX: it doesn't seems to work */ - act = purple_plugin_action_new(_("Set User Info..."), + act = purple_protocol_action_new(_("Set User Info..."), yahoo_set_userinfo_fn); m = g_list_append(m, act); #endif - act = purple_plugin_action_new(_("Activate ID..."), + act = purple_protocol_action_new(_("Activate ID..."), yahoo_show_act_id); m = g_list_append(m, act); - act = purple_plugin_action_new(_("Join User in Chat..."), + act = purple_protocol_action_new(_("Join User in Chat..."), yahoo_show_chat_goto); m = g_list_append(m, act); m = g_list_append(m, NULL); - act = purple_plugin_action_new(_("Open Inbox"), + act = purple_protocol_action_new(_("Open Inbox"), yahoo_show_inbox); m = g_list_append(m, act); @@ -5054,7 +5054,7 @@ if (*args && args[0]) return PURPLE_CMD_RET_FAILED; - purple_prpl_send_attention(purple_account_get_connection(account), purple_conversation_get_name(c), YAHOO_BUZZ); + purple_protocol_send_attention(purple_account_get_connection(account), purple_conversation_get_name(c), YAHOO_BUZZ); return PURPLE_CMD_RET_OK; }
--- a/libpurple/protocols/yahoo/libymsg.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/yahoo/libymsg.h Sun Aug 18 01:53:00 2013 +0530 @@ -28,7 +28,7 @@ #include "circularbuffer.h" #include "cmds.h" #include "http.h" -#include "prpl.h" +#include "protocol.h" #include "network.h" #define YAHOO_PAGER_HOST_REQ_URL "http://vcs1.msg.yahoo.com/capacity" @@ -382,7 +382,7 @@ gboolean yahoo_send_attention(PurpleConnection *gc, const char *username, guint type); GList *yahoo_attention_types(PurpleAccount *account); -GList *yahoo_actions(PurplePlugin *plugin, gpointer context); +GList *yahoo_get_actions(PurpleConnection *gc); void yahoopurple_register_commands(void); PurpleCmdRet yahoopurple_cmd_buzz(PurpleConversation *c, const gchar *cmd, gchar **args, gchar **error, void *data);
--- a/libpurple/protocols/yahoo/util.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/yahoo/util.c Sun Aug 18 01:53:00 2013 +0530 @@ -26,7 +26,7 @@ #include "debug.h" #include "internal.h" -#include "prpl.h" +#include "protocol.h" #include "libymsg.h"
--- a/libpurple/protocols/yahoo/yahoo_doodle.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/yahoo/yahoo_doodle.c Sun Aug 18 01:53:00 2013 +0530 @@ -33,7 +33,7 @@ #include "cmds.h" #include "debug.h" #include "notify.h" -#include "prpl.h" +#include "protocol.h" #include "proxy.h" #include "request.h" #include "server.h"
--- a/libpurple/protocols/yahoo/yahoo_filexfer.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/yahoo/yahoo_filexfer.c Sun Aug 18 01:53:00 2013 +0530 @@ -25,7 +25,7 @@ #include "internal.h" #include "dnsquery.h" -#include "prpl.h" +#include "protocol.h" #include "util.h" #include "debug.h" #include "http.h"
--- a/libpurple/protocols/yahoo/yahoo_friend.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/yahoo/yahoo_friend.c Sun Aug 18 01:53:00 2013 +0530 @@ -22,7 +22,7 @@ */ #include "internal.h" -#include "prpl.h" +#include "protocol.h" #include "util.h" #include "debug.h"
--- a/libpurple/protocols/yahoo/yahoo_picture.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/yahoo/yahoo_picture.c Sun Aug 18 01:53:00 2013 +0530 @@ -28,7 +28,7 @@ #include "buddylist.h" #include "debug.h" #include "http.h" -#include "prpl.h" +#include "protocol.h" #include "proxy.h" #include "util.h"
--- a/libpurple/protocols/yahoo/yahoochat.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/yahoo/yahoochat.c Sun Aug 18 01:53:00 2013 +0530 @@ -34,7 +34,7 @@ #include "debug.h" #include "http.h" -#include "prpl.h" +#include "protocol.h" #include "conversation.h" #include "notify.h"
--- a/libpurple/protocols/yahoo/ycht.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/yahoo/ycht.c Sun Aug 18 01:53:00 2013 +0530 @@ -26,7 +26,7 @@ */ #include "internal.h" -#include "prpl.h" +#include "protocol.h" #include "notify.h" #include "account.h" #include "proxy.h"
--- a/libpurple/protocols/zephyr/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/zephyr/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -105,5 +105,6 @@ -I$(top_srcdir)/libpurple/protocols \ -DCONFDIR=\"$(sysconfdir)\" \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(KRB4_CFLAGS) \ $(DEBUG_CFLAGS)
--- a/libpurple/protocols/zephyr/zephyr.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/protocols/zephyr/zephyr.c Sun Aug 18 01:53:00 2013 +0530 @@ -31,7 +31,8 @@ #include "accountopt.h" #include "debug.h" #include "notify.h" -#include "prpl.h" +#include "plugins.h" +#include "protocol.h" #include "server.h" #include "util.h" #include "cmds.h" @@ -814,9 +815,9 @@ purple_notify_user_info_destroy(user_info); } else { if (nlocs>0) - purple_prpl_got_user_status(purple_connection_get_account(gc), b ? bname : user, "available", NULL); + purple_protocol_got_user_status(purple_connection_get_account(gc), b ? bname : user, "available", NULL); else - purple_prpl_got_user_status(purple_connection_get_account(gc), b ? bname : user, "offline", NULL); + purple_protocol_got_user_status(purple_connection_get_account(gc), b ? bname : user, "offline", NULL); } g_free(user); @@ -1199,9 +1200,9 @@ purple_notify_user_info_destroy(user_info); } else { if (nlocs>0) - purple_prpl_got_user_status(purple_connection_get_account(gc), b ? bname : user, "available", NULL); + purple_protocol_got_user_status(purple_connection_get_account(gc), b ? bname : user, "available", NULL); else - purple_prpl_got_user_status(purple_connection_get_account(gc), b ? bname : user, "offline", NULL); + purple_protocol_got_user_status(purple_connection_get_account(gc), b ? bname : user, "offline", NULL); } } else if (!g_ascii_strncasecmp(spewtype,"subscribed",10)) { @@ -1325,9 +1326,9 @@ for(i=0;i<numlocs;i++) { ZGetLocations(&locations,&one); if (nlocs>0) - purple_prpl_got_user_status(account,name,"available",NULL); + purple_protocol_got_user_status(account,name,"available",NULL); else - purple_prpl_got_user_status(account,name,"offline",NULL); + purple_protocol_got_user_status(account,name,"offline",NULL); } } #else @@ -2712,67 +2713,67 @@ static void zephyr_register_slash_commands(void) { - purple_cmd_register("msg","ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, + purple_cmd_register("msg","ws", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-zephyr", zephyr_purple_cmd_msg, _("msg <nick> <message>: Send a private message to a user"), NULL); - purple_cmd_register("zlocate","w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, + purple_cmd_register("zlocate","w", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-zephyr", zephyr_purple_cmd_zlocate, _("zlocate <nick>: Locate user"), NULL); - purple_cmd_register("zl","w", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, + purple_cmd_register("zl","w", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-zephyr", zephyr_purple_cmd_zlocate, _("zl <nick>: Locate user"), NULL); - purple_cmd_register("instance","s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, + purple_cmd_register("instance","s", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-zephyr", zephyr_purple_cmd_instance, _("instance <instance>: Set the instance to be used on this class"), NULL); - purple_cmd_register("inst","s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, + purple_cmd_register("inst","s", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-zephyr", zephyr_purple_cmd_instance, _("inst <instance>: Set the instance to be used on this class"), NULL); - purple_cmd_register("topic","s", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, + purple_cmd_register("topic","s", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-zephyr", zephyr_purple_cmd_instance, _("topic <instance>: Set the instance to be used on this class"), NULL); - purple_cmd_register("sub", "www", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, + purple_cmd_register("sub", "www", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-zephyr", zephyr_purple_cmd_joinchat_cir, _("sub <class> <instance> <recipient>: Join a new chat"), NULL); - purple_cmd_register("zi","ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, + purple_cmd_register("zi","ws", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-zephyr", zephyr_purple_cmd_zi, _("zi <instance>: Send a message to <message,<i>instance</i>,*>"), NULL); - purple_cmd_register("zci","wws",PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, + purple_cmd_register("zci","wws",PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-zephyr", zephyr_purple_cmd_zci, _("zci <class> <instance>: Send a message to <<i>class</i>,<i>instance</i>,*>"), NULL); - purple_cmd_register("zcir","wwws",PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, + purple_cmd_register("zcir","wwws",PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-zephyr", zephyr_purple_cmd_zcir, _("zcir <class> <instance> <recipient>: Send a message to <<i>class</i>,<i>instance</i>,<i>recipient</i>>"), NULL); - purple_cmd_register("zir","wws",PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, + purple_cmd_register("zir","wws",PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-zephyr", zephyr_purple_cmd_zir, _("zir <instance> <recipient>: Send a message to <MESSAGE,<i>instance</i>,<i>recipient</i>>"), NULL); - purple_cmd_register("zc","ws", PURPLE_CMD_P_PRPL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, + purple_cmd_register("zc","ws", PURPLE_CMD_P_PROTOCOL, + PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY, "prpl-zephyr", zephyr_purple_cmd_zc, _("zc <class>: Send a message to <<i>class</i>,PERSONAL,*>"), NULL); @@ -2797,17 +2798,17 @@ } -static void zephyr_action_resubscribe(PurplePluginAction *action) +static void zephyr_action_resubscribe(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; zephyr_resubscribe(gc); } -static void zephyr_action_get_subs_from_server(PurplePluginAction *action) +static void zephyr_action_get_subs_from_server(PurpleProtocolAction *action) { - PurpleConnection *gc = (PurpleConnection *) action->context; + PurpleConnection *gc = action->connection; zephyr_account *zephyr = purple_connection_get_protocol_data(gc); gchar *title; int retval, nsubs, one,i; @@ -2850,28 +2851,31 @@ } -static GList *zephyr_actions(PurplePlugin *plugin, gpointer context) +static GList *zephyr_get_actions(PurpleConnection *gc) { GList *list = NULL; - PurplePluginAction *act = NULL; - - act = purple_plugin_action_new(_("Resubscribe"), zephyr_action_resubscribe); + PurpleProtocolAction *act = NULL; + + act = purple_protocol_action_new(_("Resubscribe"), zephyr_action_resubscribe); list = g_list_append(list, act); - act = purple_plugin_action_new(_("Retrieve subscriptions from server"), zephyr_action_get_subs_from_server); + act = purple_protocol_action_new(_("Retrieve subscriptions from server"), zephyr_action_get_subs_from_server); list = g_list_append(list,act); return list; } -static PurplePlugin *my_protocol = NULL; - -static PurplePluginProtocolInfo prpl_info = { - sizeof(PurplePluginProtocolInfo), /* struct_size */ +static PurpleProtocol *my_protocol = NULL; + +static PurpleProtocol protocol = { + "prpl-zephyr", /* id */ + "Zephyr", /* name */ + sizeof(PurpleProtocol), /* struct_size */ OPT_PROTO_CHAT_TOPIC | OPT_PROTO_NO_PASSWORD, NULL, /* ??? user_splits */ NULL, /* ??? protocol_options */ NO_BUDDY_ICONS, + zephyr_get_actions, zephyr_list_icon, NULL, /* ??? list_emblems */ NULL, /* ??? status_text */ @@ -2926,7 +2930,7 @@ NULL, /* send_file */ NULL, /* new_xfer */ NULL, /* offline_message */ - NULL, /* whiteboard_prpl_ops */ + NULL, /* whiteboard_protocol_ops */ NULL, /* send_raw */ NULL, /* roomlist_room_serialize */ @@ -2941,76 +2945,66 @@ NULL /* get_public_alias */ }; -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-zephyr", /**< id */ - "Zephyr", /**< name */ - DISPLAY_VERSION, /**< version */ - /** summary */ - N_("Zephyr Protocol Plugin"), - /** description */ - N_("Zephyr Protocol Plugin"), - NULL, /**< author */ - PURPLE_WEBSITE, /**< homepage */ - - NULL, /**< load */ - NULL, /**< unload */ - NULL, /**< destroy */ - - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, - zephyr_actions, - - /* padding */ - NULL, - NULL, - NULL, - NULL -}; - -static void init_plugin(PurplePlugin * plugin) +static PurplePluginInfo *plugin_query(GError **error) +{ + return purple_plugin_info_new( + "id", "prpl-zephyr", + "name", "Zephyr", + "version", DISPLAY_VERSION, + "category", N_("Protocol"), + "summary", N_("Zephyr Protocol Plugin"), + "description", N_("Zephyr Protocol Plugin"), + "website", PURPLE_WEBSITE, + "abi-version", PURPLE_ABI_VERSION, + "flags", GPLUGIN_PLUGIN_INFO_FLAGS_INTERNAL | + GPLUGIN_PLUGIN_INFO_FLAGS_LOAD_ON_QUERY, + NULL + ); +} + +static gboolean plugin_load(PurplePlugin *plugin, GError **error) { PurpleAccountOption *option; char *tmp = get_exposure_level(); option = purple_account_option_bool_new(_("Use tzc"), "use_tzc", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("tzc command"), "tzc_command", "/usr/bin/tzc -e %s"); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_bool_new(_("Export to .anyone"), "write_anyone", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_bool_new(_("Export to .zephyr.subs"), "write_zsubs", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_bool_new(_("Import from .anyone"), "read_anyone", TRUE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_bool_new(_("Import from .zephyr.subs"), "read_zsubs", TRUE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("Realm"), "realm", ""); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("Exposure"), "exposure_level", tmp?tmp: EXPOSE_REALMVIS); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + protocol.protocol_options = g_list_append(protocol.protocol_options, option); option = purple_account_option_string_new(_("Encoding"), "encoding", ZEPHYR_FALLBACK_CHARSET); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - my_protocol = plugin; + protocol.protocol_options = g_list_append(protocol.protocol_options, option); + + my_protocol = &protocol; zephyr_register_slash_commands(); + + purple_protocols_add(my_protocol); + return TRUE; } -PURPLE_INIT_PLUGIN(zephyr, init_plugin, info); +static gboolean plugin_unload(PurplePlugin *plugin, GError **error) +{ + purple_protocols_remove(my_protocol); + return TRUE; +} + +PURPLE_PLUGIN_INIT(zephyr, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/prpl.c Sun Aug 18 01:52:32 2013 +0530 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,649 +0,0 @@ -/* - * 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 - * - */ -#include "internal.h" -#include "conversation.h" -#include "debug.h" -#include "network.h" -#include "notify.h" -#include "prpl.h" -#include "request.h" -#include "util.h" - -/**************************************************************************/ -/** @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) -{ - PurpleAttentionType *attn = g_new0(PurpleAttentionType, 1); - - purple_attention_type_set_name(attn, name); - purple_attention_type_set_incoming_desc(attn, inc_desc); - purple_attention_type_set_outgoing_desc(attn, out_desc); - purple_attention_type_set_unlocalized_name(attn, ulname); - - return attn; -} - - -void -purple_attention_type_set_name(PurpleAttentionType *type, const char *name) -{ - g_return_if_fail(type != NULL); - - type->name = name; -} - -void -purple_attention_type_set_incoming_desc(PurpleAttentionType *type, const char *desc) -{ - g_return_if_fail(type != NULL); - - type->incoming_description = desc; -} - -void -purple_attention_type_set_outgoing_desc(PurpleAttentionType *type, const char *desc) -{ - g_return_if_fail(type != NULL); - - type->outgoing_description = desc; -} - -void -purple_attention_type_set_icon_name(PurpleAttentionType *type, const char *name) -{ - g_return_if_fail(type != NULL); - - type->icon_name = name; -} - -void -purple_attention_type_set_unlocalized_name(PurpleAttentionType *type, const char *ulname) -{ - g_return_if_fail(type != NULL); - - type->unlocalized_name = ulname; -} - -const char * -purple_attention_type_get_name(const PurpleAttentionType *type) -{ - g_return_val_if_fail(type != NULL, NULL); - - return type->name; -} - -const char * -purple_attention_type_get_incoming_desc(const PurpleAttentionType *type) -{ - g_return_val_if_fail(type != NULL, NULL); - - return type->incoming_description; -} - -const char * -purple_attention_type_get_outgoing_desc(const PurpleAttentionType *type) -{ - g_return_val_if_fail(type != NULL, NULL); - - return type->outgoing_description; -} - -const char * -purple_attention_type_get_icon_name(const PurpleAttentionType *type) -{ - g_return_val_if_fail(type != NULL, NULL); - - if(type->icon_name == NULL || *(type->icon_name) == '\0') - return NULL; - - return type->icon_name; -} - -const char * -purple_attention_type_get_unlocalized_name(const PurpleAttentionType *type) -{ - g_return_val_if_fail(type != NULL, NULL); - - return type->unlocalized_name; -} - -/**************************************************************************/ -/** @name Protocol Plugin API */ -/**************************************************************************/ -void -purple_prpl_got_account_idle(PurpleAccount *account, gboolean idle, - time_t idle_time) -{ - g_return_if_fail(account != NULL); - g_return_if_fail(purple_account_is_connected(account)); - - purple_presence_set_idle(purple_account_get_presence(account), - idle, idle_time); -} - -void -purple_prpl_got_account_login_time(PurpleAccount *account, time_t login_time) -{ - PurplePresence *presence; - - g_return_if_fail(account != NULL); - g_return_if_fail(purple_account_is_connected(account)); - - if (login_time == 0) - login_time = time(NULL); - - presence = purple_account_get_presence(account); - - purple_presence_set_login_time(presence, login_time); -} - -void -purple_prpl_got_account_status(PurpleAccount *account, const char *status_id, ...) -{ - PurplePresence *presence; - PurpleStatus *status; - va_list args; - - g_return_if_fail(account != NULL); - g_return_if_fail(status_id != NULL); - g_return_if_fail(purple_account_is_connected(account)); - - presence = purple_account_get_presence(account); - status = purple_presence_get_status(presence, status_id); - - g_return_if_fail(status != NULL); - - va_start(args, status_id); - purple_status_set_active_with_attrs(status, TRUE, args); - va_end(args); -} - -void -purple_prpl_got_account_actions(PurpleAccount *account) -{ - - g_return_if_fail(account != NULL); - g_return_if_fail(purple_account_is_connected(account)); - - purple_signal_emit(purple_accounts_get_handle(), "account-actions-changed", - account); -} - -void -purple_prpl_got_user_idle(PurpleAccount *account, const char *name, - gboolean idle, time_t idle_time) -{ - PurplePresence *presence; - GSList *list; - - g_return_if_fail(account != NULL); - g_return_if_fail(name != NULL); - g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account)); - - if ((list = purple_blist_find_buddies(account, name)) == NULL) - return; - - while (list) { - presence = purple_buddy_get_presence(list->data); - list = g_slist_delete_link(list, list); - purple_presence_set_idle(presence, idle, idle_time); - } -} - -void -purple_prpl_got_user_login_time(PurpleAccount *account, const char *name, - time_t login_time) -{ - GSList *list; - PurplePresence *presence; - - g_return_if_fail(account != NULL); - g_return_if_fail(name != NULL); - - if ((list = purple_blist_find_buddies(account, name)) == NULL) - return; - - if (login_time == 0) - login_time = time(NULL); - - while (list) { - PurpleBuddy *buddy = list->data; - presence = purple_buddy_get_presence(buddy); - list = g_slist_delete_link(list, list); - - if (purple_presence_get_login_time(presence) != login_time) - { - purple_presence_set_login_time(presence, login_time); - - purple_signal_emit(purple_blist_get_handle(), "buddy-got-login-time", buddy); - } - } -} - -void -purple_prpl_got_user_status(PurpleAccount *account, const char *name, - const char *status_id, ...) -{ - GSList *list, *l; - PurpleBuddy *buddy; - PurplePresence *presence; - PurpleStatus *status; - PurpleStatus *old_status; - va_list args; - - g_return_if_fail(account != NULL); - g_return_if_fail(name != NULL); - g_return_if_fail(status_id != NULL); - g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account)); - - if((list = purple_blist_find_buddies(account, name)) == NULL) - return; - - for(l = list; l != NULL; l = l->next) { - buddy = l->data; - - presence = purple_buddy_get_presence(buddy); - status = purple_presence_get_status(presence, status_id); - - if(NULL == status) - /* - * TODO: This should never happen, right? We should call - * g_warning() or something. - */ - continue; - - old_status = purple_presence_get_active_status(presence); - - va_start(args, status_id); - purple_status_set_active_with_attrs(status, TRUE, args); - va_end(args); - - purple_buddy_update_status(buddy, old_status); - } - - g_slist_free(list); - - /* The buddy is no longer online, they are therefore by definition not - * still typing to us. */ - if (!purple_status_is_online(status)) { - serv_got_typing_stopped(purple_account_get_connection(account), name); - purple_prpl_got_media_caps(account, name); - } -} - -void purple_prpl_got_user_status_deactive(PurpleAccount *account, const char *name, - const char *status_id) -{ - GSList *list, *l; - PurpleBuddy *buddy; - PurplePresence *presence; - PurpleStatus *status; - - g_return_if_fail(account != NULL); - g_return_if_fail(name != NULL); - g_return_if_fail(status_id != NULL); - g_return_if_fail(purple_account_is_connected(account) || purple_account_is_connecting(account)); - - if((list = purple_blist_find_buddies(account, name)) == NULL) - return; - - for(l = list; l != NULL; l = l->next) { - buddy = l->data; - - presence = purple_buddy_get_presence(buddy); - status = purple_presence_get_status(presence, status_id); - - if(NULL == status) - continue; - - if (purple_status_is_active(status)) { - purple_status_set_active(status, FALSE); - purple_buddy_update_status(buddy, status); - } - } - - g_slist_free(list); -} - -static void -do_prpl_change_account_status(PurpleAccount *account, - PurpleStatus *old_status, PurpleStatus *new_status) -{ - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; - - if (purple_status_is_online(new_status) && - purple_account_is_disconnected(account) && - purple_network_is_available()) - { - purple_account_connect(account); - return; - } - - if (!purple_status_is_online(new_status)) - { - if (!purple_account_is_disconnected(account)) - purple_account_disconnect(account); - /* Clear out the unsaved password if we switch to offline status */ - if (!purple_account_get_remember_password(account)) - purple_account_set_password(account, NULL, NULL, NULL); - - return; - } - - if (purple_account_is_connecting(account)) - /* - * We don't need to call the set_status PRPL function because - * the PRPL will take care of setting its status during the - * connection process. - */ - return; - - prpl = purple_find_prpl(purple_account_get_protocol_id(account)); - - if (prpl == NULL) - return; - - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if (!purple_account_is_disconnected(account) && prpl_info->set_status != NULL) - { - prpl_info->set_status(account, new_status); - } -} - -void -purple_prpl_change_account_status(PurpleAccount *account, - PurpleStatus *old_status, PurpleStatus *new_status) -{ - g_return_if_fail(account != NULL); - g_return_if_fail(new_status != NULL); - g_return_if_fail(!purple_status_is_exclusive(new_status) || old_status != NULL); - - do_prpl_change_account_status(account, old_status, new_status); - - purple_signal_emit(purple_accounts_get_handle(), "account-status-changed", - account, old_status, new_status); -} - -GList * -purple_prpl_get_statuses(PurpleAccount *account, PurplePresence *presence) -{ - GList *statuses = NULL; - GList *l; - PurpleStatus *status; - - g_return_val_if_fail(account != NULL, NULL); - g_return_val_if_fail(presence != NULL, NULL); - - for (l = purple_account_get_status_types(account); l != NULL; l = l->next) - { - status = purple_status_new((PurpleStatusType *)l->data, presence); - statuses = g_list_prepend(statuses, status); - } - - statuses = g_list_reverse(statuses); - - return statuses; -} - -static void -purple_prpl_attention(PurpleConversation *conv, const char *who, - guint type, PurpleMessageFlags flags, time_t mtime) -{ - PurpleAccount *account = purple_conversation_get_account(conv); - purple_signal_emit(purple_conversations_get_handle(), - flags == PURPLE_MESSAGE_SEND ? "sent-attention" : "got-attention", - account, who, conv, type); -} - -void -purple_prpl_send_attention(PurpleConnection *gc, const char *who, guint type_code) -{ - PurpleAttentionType *attn; - PurpleMessageFlags flags; - PurplePlugin *prpl; - PurpleIMConversation *im; - gboolean (*send_attention)(PurpleConnection *, const char *, guint); - PurpleBuddy *buddy; - const char *alias; - gchar *description; - time_t mtime; - - g_return_if_fail(gc != NULL); - g_return_if_fail(who != NULL); - - 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(purple_connection_get_account(gc), type_code); - - if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), who)) != NULL) - alias = purple_buddy_get_contact_alias(buddy); - else - alias = who; - - if (attn && purple_attention_type_get_outgoing_desc(attn)) { - description = g_strdup_printf(purple_attention_type_get_outgoing_desc(attn), alias); - } else { - description = g_strdup_printf(_("Requesting %s's attention..."), alias); - } - - flags = PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_NOTIFY | PURPLE_MESSAGE_SYSTEM; - - purple_debug_info("server", "serv_send_attention: sending '%s' to %s\n", - description, who); - - if (!send_attention(gc, who, type_code)) - return; - - im = purple_im_conversation_new(purple_connection_get_account(gc), who); - purple_conversation_write_message(PURPLE_CONVERSATION(im), NULL, description, flags, mtime); - purple_prpl_attention(PURPLE_CONVERSATION(im), who, type_code, PURPLE_MESSAGE_SEND, time(NULL)); - - g_free(description); -} - -static void -got_attention(PurpleConnection *gc, int id, const char *who, guint type_code) -{ - PurpleMessageFlags flags; - PurpleAttentionType *attn; - PurpleBuddy *buddy; - const char *alias; - gchar *description; - time_t mtime; - - mtime = time(NULL); - - 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; - - /* TODO: if (attn->icon_name) is non-null, use it to lookup an emoticon and display - * it next to the attention command. And if it is null, display a generic icon. */ - - if ((buddy = purple_blist_find_buddy(purple_connection_get_account(gc), who)) != NULL) - alias = purple_buddy_get_contact_alias(buddy); - else - alias = who; - - if (attn && purple_attention_type_get_incoming_desc(attn)) { - description = g_strdup_printf(purple_attention_type_get_incoming_desc(attn), alias); - } else { - description = g_strdup_printf(_("%s has requested your attention!"), alias); - } - - purple_debug_info("server", "got_attention: got '%s' from %s\n", - description, who); - - if (id == -1) - serv_got_im(gc, who, description, flags, mtime); - else - serv_got_chat_in(gc, id, who, flags, description, mtime); - - /* TODO: sounds (depending on PurpleAttentionType), shaking, etc. */ - - g_free(description); -} - -void -purple_prpl_got_attention(PurpleConnection *gc, const char *who, guint type_code) -{ - PurpleConversation *conv = NULL; - PurpleAccount *account = purple_connection_get_account(gc); - - got_attention(gc, -1, who, type_code); - conv = - purple_conversations_find_with_account(who, account); - if (conv) - purple_prpl_attention(conv, who, type_code, PURPLE_MESSAGE_RECV, - time(NULL)); -} - -void -purple_prpl_got_attention_in_chat(PurpleConnection *gc, int id, const char *who, guint type_code) -{ - got_attention(gc, id, who, type_code); -} - -gboolean -purple_prpl_initiate_media(PurpleAccount *account, - const char *who, - PurpleMediaSessionType type) -{ -#ifdef USE_VV - PurpleConnection *gc = NULL; - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; - - if (account) - gc = purple_account_get_connection(account); - if (gc) - prpl = purple_connection_get_prpl(gc); - if (prpl) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, initiate_media)) { - /* should check that the protocol supports this media type here? */ - return prpl_info->initiate_media(account, who, type); - } else -#endif - return FALSE; -} - -PurpleMediaCaps -purple_prpl_get_media_caps(PurpleAccount *account, const char *who) -{ -#ifdef USE_VV - PurpleConnection *gc = NULL; - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; - - if (account) - gc = purple_account_get_connection(account); - if (gc) - prpl = purple_connection_get_prpl(gc); - if (prpl) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, - get_media_caps)) { - return prpl_info->get_media_caps(account, who); - } -#endif - return PURPLE_MEDIA_CAPS_NONE; -} - -void -purple_prpl_got_media_caps(PurpleAccount *account, const char *name) -{ -#ifdef USE_VV - GSList *list; - - g_return_if_fail(account != NULL); - g_return_if_fail(name != NULL); - - if ((list = purple_blist_find_buddies(account, name)) == NULL) - return; - - while (list) { - PurpleBuddy *buddy = list->data; - PurpleMediaCaps oldcaps = purple_buddy_get_media_caps(buddy); - PurpleMediaCaps newcaps = 0; - const gchar *bname = purple_buddy_get_name(buddy); - list = g_slist_delete_link(list, list); - - - newcaps = purple_prpl_get_media_caps(account, bname); - purple_buddy_set_media_caps(buddy, newcaps); - - if (oldcaps == newcaps) - continue; - - purple_signal_emit(purple_blist_get_handle(), - "buddy-caps-changed", buddy, - newcaps, oldcaps); - } -#endif -} - -/************************************************************************** - * Protocol Plugin Subsystem API - **************************************************************************/ - -PurplePlugin * -purple_find_prpl(const char *id) -{ - GList *l; - PurplePlugin *plugin; - - g_return_val_if_fail(id != NULL, NULL); - - for (l = purple_plugins_get_protocols(); l != NULL; l = l->next) { - plugin = (PurplePlugin *)l->data; - - if (purple_strequal(plugin->info->id, id)) - return plugin; - } - - return NULL; -}
--- a/libpurple/prpl.h Sun Aug 18 01:52:32 2013 +0530 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,974 +0,0 @@ -/** - * @file prpl.h Protocol Plugin functions - * @ingroup core - */ - -/* 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 - */ - -/* this file should be all that prpls need to include. therefore, by including - * this file, they should get glib, proxy, purple_connection, prpl, etc. */ - -#ifndef _PURPLE_PRPL_H_ -#define _PURPLE_PRPL_H_ - -typedef struct _PurplePluginProtocolInfo PurplePluginProtocolInfo; - -/** Represents "nudges" and "buzzes" that you may send to a buddy to attract - * their attention (or vice-versa). - */ -typedef struct _PurpleAttentionType PurpleAttentionType; - -/**************************************************************************/ -/** @name Basic Protocol Information */ -/**************************************************************************/ - -typedef enum { - PURPLE_ICON_SCALE_DISPLAY = 0x01, /**< We scale the icon when we display it */ - PURPLE_ICON_SCALE_SEND = 0x02 /**< We scale the icon before we send it to the server */ -} PurpleIconScaleRules; - - -/** - * A description of a Buddy Icon specification. This tells Purple what kind of image file - * it should give this prpl, and what kind of image file it should expect back. - * Dimensions less than 1 should be ignored and the image not scaled. - */ -typedef struct _PurpleBuddyIconSpec PurpleBuddyIconSpec; - -/** - * A description of a file transfer thumbnail specification. - * This tells the UI if and what image formats the prpl support for file - * transfer thumbnails. - */ -typedef struct _PurpleThumbnailSpec PurpleThumbnailSpec; - -/** - * This \#define exists just to make it easier to fill out the buddy icon - * field in the prpl info struct for protocols that couldn't care less. - */ -#define NO_BUDDY_ICONS {NULL, 0, 0, 0, 0, 0, 0} - -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include "buddylist.h" -#include "conversations.h" -#include "ft.h" -#include "imgstore.h" -#include "media.h" -#include "notify.h" -#include "proxy.h" -#include "plugin.h" -#include "roomlist.h" -#include "status.h" -#include "whiteboard.h" - - -/** @copydoc PurpleBuddyIconSpec */ -struct _PurpleBuddyIconSpec { - /** This is a comma-delimited list of image formats or @c NULL if icons - * are not supported. Neither the core nor the prpl will actually - * check to see if the data it's given matches this; it's entirely up - * to the UI to do what it wants - */ - char *format; - - int min_width; /**< Minimum width of this icon */ - int min_height; /**< Minimum height of this icon */ - int max_width; /**< Maximum width of this icon */ - int max_height; /**< Maximum height of this icon */ - size_t max_filesize; /**< Maximum size in bytes */ - PurpleIconScaleRules scale_rules; /**< How to stretch this icon */ -}; - -/** Represents an entry containing information that must be supplied by the - * user when joining a chat. - */ -struct proto_chat_entry { - const char *label; /**< User-friendly name of the entry */ - const char *identifier; /**< Used by the PRPL to identify the option */ - gboolean required; /**< True if it's required */ - gboolean is_int; /**< True if the entry expects an integer */ - int min; /**< Minimum value in case of integer */ - int max; /**< Maximum value in case of integer */ - gboolean secret; /**< True if the entry is secret (password) */ -}; - -/** - * Protocol options - * - * These should all be stuff that some plugins can do and others can't. - */ -typedef enum -{ - /** - * User names are unique to a chat and are not shared between rooms. - * - * XMPP lets you choose what name you want in chats, so it shouldn't - * be pulling the aliases from the buddy list for the chat list; - * it gets annoying. - */ - OPT_PROTO_UNIQUE_CHATNAME = 0x00000004, - - /** - * Chat rooms have topics. - * - * IRC and XMPP support this. - */ - OPT_PROTO_CHAT_TOPIC = 0x00000008, - - /** - * Don't require passwords for sign-in. - * - * Zephyr doesn't require passwords, so there's no - * need for a password prompt. - */ - OPT_PROTO_NO_PASSWORD = 0x00000010, - - /** - * Notify on new mail. - * - * MSN and Yahoo notify you when you have new mail. - */ - OPT_PROTO_MAIL_CHECK = 0x00000020, - - /** - * Images in IMs. - * - * Oscar lets you send images in direct IMs. - */ - OPT_PROTO_IM_IMAGE = 0x00000040, - - /** - * Allow passwords to be optional. - * - * Passwords in IRC are optional, and are needed for certain - * functionality. - */ - OPT_PROTO_PASSWORD_OPTIONAL = 0x00000080, - - /** - * Allows font size to be specified in sane point size - * - * Probably just XMPP and Y!M - */ - OPT_PROTO_USE_POINTSIZE = 0x00000100, - - /** - * Set the Register button active even when the username has not - * been specified. - * - * Gadu-Gadu doesn't need a username to register new account (because - * usernames are assigned by the server). - */ - OPT_PROTO_REGISTER_NOSCREENNAME = 0x00000200, - - /** - * Indicates that slash commands are native to this protocol. - * Used as a hint that unknown commands should not be sent as messages. - */ - OPT_PROTO_SLASH_COMMANDS_NATIVE = 0x00000400, - - /** - * Indicates that this protocol supports sending a user-supplied message - * along with an invitation. - */ - OPT_PROTO_INVITE_MESSAGE = 0x00000800, - - /** - * Indicates that this protocol supports sending a user-supplied message - * along with an authorization acceptance. - */ - OPT_PROTO_AUTHORIZATION_GRANTED_MESSAGE = 0x00001000, - - /** - * Indicates that this protocol supports sending a user-supplied message - * along with an authorization denial. - */ - OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE = 0x00002000 - -} PurpleProtocolOptions; - -/** - * A protocol plugin information structure. - * - * Every protocol plugin initializes this structure. It is the gateway - * between purple and the protocol plugin. Many of these callbacks can be - * NULL. If a callback must be implemented, it has a comment indicating so. - */ -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 */ - GList *protocol_options; /**< A GList of PurpleAccountOption */ - - PurpleBuddyIconSpec icon_spec; /**< The icon spec. */ - - /** - * Returns the base icon name for the given buddy and account. - * If buddy is NULL and the account is non-NULL, it will return the - * name to use for the account's icon. If both are NULL, it will - * return the name to use for the protocol's icon. - * - * This must be implemented. - */ - const char *(*list_icon)(PurpleAccount *account, PurpleBuddy *buddy); - - /** - * Fills the four char**'s with string identifiers for "emblems" - * that the UI will interpret and display as relevant - */ - const char *(*list_emblem)(PurpleBuddy *buddy); - - /** - * Gets a short string representing this buddy's status. This will - * be shown on the buddy list. - */ - char *(*status_text)(PurpleBuddy *buddy); - - /** - * Allows the prpl to add text to a buddy's tooltip. - */ - void (*tooltip_text)(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboolean full); - - /** - * Returns a list of #PurpleStatusType which exist for this account; - * this must be implemented, and must add at least the offline and - * online states. - */ - GList *(*status_types)(PurpleAccount *account); - - /** - * Returns a list of #PurpleMenuAction structs, which represent extra - * actions to be shown in (for example) the right-click menu for @a - * node. - */ - GList *(*blist_node_menu)(PurpleBlistNode *node); - - /** - * Returns a list of #proto_chat_entry structs, which represent - * information required by the PRPL to join a chat. libpurple will - * call join_chat along with the information filled by the user. - * - * @return A list of #proto_chat_entry structs - */ - GList *(*chat_info)(PurpleConnection *); - - /** - * Returns a hashtable which maps #proto_chat_entry struct identifiers - * to default options as strings based on chat_name. The resulting - * hashtable should be created with g_hash_table_new_full(g_str_hash, - * g_str_equal, NULL, g_free);. Use #get_chat_name if you instead need - * to extract a chat name from a hashtable. - * - * @param chat_name The chat name to be turned into components - * @return Hashtable containing the information extracted from chat_name - */ - GHashTable *(*chat_info_defaults)(PurpleConnection *, const char *chat_name); - - /* All the server-related functions */ - - /** This must be implemented. */ - void (*login)(PurpleAccount *); - - /** This must be implemented. */ - void (*close)(PurpleConnection *); - - /** - * This PRPL function should return a positive value on success. - * If the message is too big to be sent, return -E2BIG. If - * the account is not connected, return -ENOTCONN. If the - * PRPL is unable to send the message for another reason, return - * some other negative value. You can use one of the valid - * errno values, or just big something. If the message should - * not be echoed to the conversation window, return 0. - */ - int (*send_im)(PurpleConnection *, const char *who, - const char *message, - PurpleMessageFlags flags); - - void (*set_info)(PurpleConnection *, const char *info); - - /** - * @return If this protocol requires the PURPLE_IM_TYPING message to - * be sent repeatedly to signify that the user is still - * typing, then the PRPL should return the number of - * seconds to wait before sending a subsequent notification. - * Otherwise the PRPL should return 0. - */ - unsigned int (*send_typing)(PurpleConnection *, const char *name, PurpleIMTypingState state); - - /** - * Should arrange for purple_notify_userinfo() to be called with - * @a who's user info. - */ - void (*get_info)(PurpleConnection *, const char *who); - void (*set_status)(PurpleAccount *account, PurpleStatus *status); - - 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. - * - * 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. - */ - 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); - void (*add_deny)(PurpleConnection *, const char *name); - void (*rem_permit)(PurpleConnection *, const char *name); - void (*rem_deny)(PurpleConnection *, const char *name); - void (*set_permit_deny)(PurpleConnection *); - - /** - * Called when the user requests joining a chat. Should arrange for - * #serv_got_joined_chat to be called. - * - * @param components A hashtable containing information required to - * join the chat as described by the entries returned - * by #chat_info. It may also be called when accepting - * an invitation, in which case this matches the - * data parameter passed to #serv_got_chat_invite. - */ - void (*join_chat)(PurpleConnection *, GHashTable *components); - - /** - * Called when the user refuses a chat invitation. - * - * @param components A hashtable containing information required to - * join the chat as passed to #serv_got_chat_invite. - */ - void (*reject_chat)(PurpleConnection *, GHashTable *components); - - /** - * Returns a chat name based on the information in components. Use - * #chat_info_defaults if you instead need to generate a hashtable - * from a chat name. - * - * @param components A hashtable containing information about the chat. - */ - char *(*get_chat_name)(GHashTable *components); - - /** - * Invite a user to join a chat. - * - * @param id The id of the chat to invite the user to. - * @param message A message displayed to the user when the invitation - * is received. - * @param who The name of the user to send the invation to. - */ - void (*chat_invite)(PurpleConnection *, int id, - const char *message, const char *who); - /** - * Called when the user requests leaving a chat. - * - * @param id The id of the chat to leave - */ - void (*chat_leave)(PurpleConnection *, int id); - - /** - * Send a whisper to a user in a chat. - * - * @param id The id of the chat. - * @param who The name of the user to send the whisper to. - * @param message The message of the whisper. - */ - void (*chat_whisper)(PurpleConnection *, int id, - const char *who, const char *message); - - /** - * Send a message to a chat. - * This PRPL function should return a positive value on success. - * If the message is too big to be sent, return -E2BIG. If - * the account is not connected, return -ENOTCONN. If the - * PRPL is unable to send the message for another reason, return - * some other negative value. You can use one of the valid - * errno values, or just big something. - * - * @param id The id of the chat to send the message to. - * @param message The message to send to the chat. - * @param flags A bitwise OR of #PurpleMessageFlags representing - * message flags. - * @return A positive number or 0 in case of success, - * a negative error number in case of failure. - */ - int (*chat_send)(PurpleConnection *, int id, const char *message, PurpleMessageFlags flags); - - /** If implemented, this will be called regularly for this prpl's - * active connections. You'd want to do this if you need to repeatedly - * send some kind of keepalive packet to the server to avoid being - * disconnected. ("Regularly" is defined by - * <code>KEEPALIVE_INTERVAL</code> in <tt>libpurple/connection.c</tt>.) - */ - void (*keepalive)(PurpleConnection *); - - /** new user registration */ - void (*register_user)(PurpleAccount *); - - /** - * @deprecated Use #PurplePluginProtocolInfo.get_info instead. - */ - void (*get_cb_info)(PurpleConnection *, int, const char *who); - - /** save/store buddy's alias on server list/roster */ - void (*alias_buddy)(PurpleConnection *, const char *who, - const char *alias); - - /** change a buddy's group on a server list/roster */ - void (*group_buddy)(PurpleConnection *, const char *who, - const char *old_group, const char *new_group); - - /** rename a group on a server list/roster */ - void (*rename_group)(PurpleConnection *, const char *old_name, - PurpleGroup *group, GList *moved_buddies); - - void (*buddy_free)(PurpleBuddy *); - - void (*convo_closed)(PurpleConnection *, const char *who); - - /** - * Convert the username @a who to its canonical form. Also checks for - * validity. - * - * For example, AIM treats "fOo BaR" and "foobar" as the same user; this - * function should return the same normalized string for both of those. - * On the other hand, both of these are invalid for protocols with - * number-based usernames, so function should return NULL in such case. - * - * @param account The account the username is related to. Can - * be NULL. - * @param who The username to convert. - * @return Normalized username, or NULL, if it's invalid. - */ - const char *(*normalize)(const PurpleAccount *account, const char *who); - - /** - * Set the buddy icon for the given connection to @a img. The prpl - * does NOT own a reference to @a img; if it needs one, it must - * #purple_imgstore_ref(@a img) itself. - */ - void (*set_buddy_icon)(PurpleConnection *, PurpleStoredImage *img); - - void (*remove_group)(PurpleConnection *gc, PurpleGroup *group); - - /** Gets the real name of a participant in a chat. For example, on - * XMPP this turns a chat room nick <tt>foo</tt> into - * <tt>room\@server/foo</tt> - * @param gc the connection on which the room is. - * @param id the ID of the chat room. - * @param who the nickname of the chat participant. - * @return the real name of the participant. This string must be - * freed by the caller. - */ - char *(*get_cb_real_name)(PurpleConnection *gc, int id, const char *who); - - void (*set_chat_topic)(PurpleConnection *gc, int id, const char *topic); - - PurpleChat *(*find_blist_chat)(PurpleAccount *account, const char *name); - - /* room listing prpl callbacks */ - PurpleRoomlist *(*roomlist_get_list)(PurpleConnection *gc); - void (*roomlist_cancel)(PurpleRoomlist *list); - void (*roomlist_expand_category)(PurpleRoomlist *list, PurpleRoomlistRoom *category); - - /* file transfer callbacks */ - gboolean (*can_receive_file)(PurpleConnection *, const char *who); - void (*send_file)(PurpleConnection *, const char *who, const char *filename); - PurpleXfer *(*new_xfer)(PurpleConnection *, const char *who); - - /** Checks whether offline messages to @a buddy are supported. - * @return @c TRUE if @a buddy can be sent messages while they are - * offline, or @c FALSE if not. - */ - gboolean (*offline_message)(const PurpleBuddy *buddy); - - PurpleWhiteboardPrplOps *whiteboard_prpl_ops; - - /** For use in plugins that may understand the underlying protocol */ - int (*send_raw)(PurpleConnection *gc, const char *buf, int len); - - /* room list serialize */ - char *(*roomlist_room_serialize)(PurpleRoomlistRoom *room); - - /** Remove the user from the server. The account can either be - * connected or disconnected. After the removal is finished, the - * connection will stay open and has to be closed! - */ - /* This is here rather than next to register_user for API compatibility - * reasons. - */ - void (*unregister_user)(PurpleAccount *, PurpleAccountUnregistrationCb cb, void *user_data); - - /* Attention API for sending & receiving zaps/nudges/buzzes etc. */ - gboolean (*send_attention)(PurpleConnection *gc, const char *username, guint type); - GList *(*get_attention_types)(PurpleAccount *acct); - - /** 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 - * table is allocated every call and MUST be unrefed by the caller. - * - * @param account The account to specify. This can be NULL. - * @return The protocol's string hash table. The hash table should be - * destroyed by the caller when it's no longer needed. - */ - GHashTable *(*get_account_text_table)(PurpleAccount *account); - - /** - * Initiate a media session with the given contact. - * - * @param account The account to initiate the media session on. - * @param who The remote user to initiate the session with. - * @param type The type of media session to initiate. - * @return TRUE if the call succeeded else FALSE. (Doesn't imply the media session or stream will be successfully created) - */ - gboolean (*initiate_media)(PurpleAccount *account, const char *who, - PurpleMediaSessionType type); - - /** - * Checks to see if the given contact supports the given type of media session. - * - * @param account The account the contact is on. - * @param who The remote user to check for media capability with. - * @return The media caps the contact supports. - */ - PurpleMediaCaps (*get_media_caps)(PurpleAccount *account, - const char *who); - - /** - * Returns an array of "PurpleMood"s, with the last one having - * "mood" set to @c NULL. - */ - PurpleMood *(*get_moods)(PurpleAccount *account); - - /** - * Set the user's "friendly name" (or alias or nickname or - * whatever term you want to call it) on the server. The - * protocol plugin should call success_cb or failure_cb - * *asynchronously* (if it knows immediately that the set will fail, - * call one of the callbacks from an idle/0-second timeout) depending - * on if the nickname is set successfully. - * - * @param gc The connection for which to set an alias - * @param alias The new server-side alias/nickname for this account, - * or NULL to unset the alias/nickname (or return it to - * a protocol-specific "default"). - * @param success_cb Callback to be called if the public alias is set - * @param failure_cb Callback to be called if setting the public alias - * fails - * @see purple_account_set_public_alias - */ - void (*set_public_alias)(PurpleConnection *gc, const char *alias, - PurpleSetPublicAliasSuccessCallback success_cb, - PurpleSetPublicAliasFailureCallback failure_cb); - /** - * Retrieve the user's "friendly name" as set on the server. - * The protocol plugin should call success_cb or failure_cb - * *asynchronously* (even if it knows immediately that the get will fail, - * call one of the callbacks from an idle/0-second timeout) depending - * on if the nickname is retrieved. - * - * @param gc The connection for which to retireve the alias - * @param success_cb Callback to be called with the retrieved alias - * @param failure_cb Callback to be called if the prpl is unable to - * retrieve the alias - * @see purple_account_get_public_alias - */ - void (*get_public_alias)(PurpleConnection *gc, - PurpleGetPublicAliasSuccessCallback success_cb, - PurpleGetPublicAliasFailureCallback failure_cb); -}; - -#define PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl, member) \ - (G_STRUCT_OFFSET(PurplePluginProtocolInfo, member) < prpl->struct_size && \ - prpl->member != NULL) - - -#define PURPLE_IS_PROTOCOL_PLUGIN(plugin) \ - ((plugin)->info->type == PURPLE_PLUGIN_PROTOCOL) - -#define PURPLE_PLUGIN_PROTOCOL_INFO(plugin) \ - ((PurplePluginProtocolInfo *)(plugin)->info->extra_info) - -G_BEGIN_DECLS - -/**************************************************************************/ -/** @name Attention Type API */ -/**************************************************************************/ -/*@{*/ - -/** - * Creates a new #PurpleAttentionType object and sets its mandatory parameters. - * - * @param ulname A non-localized string that can be used by UIs in need of such - * non-localized strings. This should be the same as @a name, - * without localization. - * @param name A localized string that the UI may display for the event. This - * 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. - */ -PurpleAttentionType *purple_attention_type_new(const char *ulname, const char *name, - const char *inc_desc, const char *out_desc); - -/** - * Sets the displayed name of the attention-demanding event. - * - * @param type The attention type. - * @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. - */ -void purple_attention_type_set_name(PurpleAttentionType *type, const char *name); - -/** - * Sets the description of the attention-demanding event shown in conversations - * when the event is received. - * - * @param type The attention type. - * @param desc The localized description for incoming events. - */ -void purple_attention_type_set_incoming_desc(PurpleAttentionType *type, const char *desc); - -/** - * Sets the description of the attention-demanding event shown in conversations - * when the event is sent. - * - * @param type The attention type. - * @param desc The localized description for outgoing events. - */ -void purple_attention_type_set_outgoing_desc(PurpleAttentionType *type, const char *desc); - -/** - * Sets the name of the icon to display for the attention event; this is optional. - * - * @param type The attention type. - * @param name The icon's name. - * @note Icons are optional for attention events. - */ -void purple_attention_type_set_icon_name(PurpleAttentionType *type, const char *name); - -/** - * Sets the unlocalized name of the attention event; some UIs may need this, - * thus it is required. - * - * @param type The attention type. - * @param ulname The unlocalized name. This should be the same string given as - * the localized name, but without localization. - */ -void purple_attention_type_set_unlocalized_name(PurpleAttentionType *type, const char *ulname); - -/** - * Get the attention type's name as displayed by the UI. - * - * @param type The attention type. - * - * @return The name. - */ -const char *purple_attention_type_get_name(const PurpleAttentionType *type); - -/** - * Get the attention type's description shown when the event is received. - * - * @param type The attention type. - * @return The description. - */ -const char *purple_attention_type_get_incoming_desc(const PurpleAttentionType *type); - -/** - * Get the attention type's description shown when the event is sent. - * - * @param type The attention type. - * @return The description. - */ -const char *purple_attention_type_get_outgoing_desc(const PurpleAttentionType *type); - -/** - * Get the attention type's icon name. - * - * @param type The attention type. - * @return The icon name or @c NULL if unset/empty. - * @note Icons are optional for attention events. - */ -const char *purple_attention_type_get_icon_name(const PurpleAttentionType *type); - -/** - * Get the attention type's unlocalized name; this is useful for some UIs. - * - * @param type The attention type - * @return The unlocalized name. - */ -const char *purple_attention_type_get_unlocalized_name(const PurpleAttentionType *type); - -/*@}*/ - -/**************************************************************************/ -/** @name Protocol Plugin API */ -/**************************************************************************/ -/*@{*/ - -/** - * Notifies Purple that our account's idle state and time have changed. - * - * This is meant to be called from protocol plugins. - * - * @param account The account. - * @param idle The user's idle state. - * @param idle_time The user's idle time. - */ -void purple_prpl_got_account_idle(PurpleAccount *account, gboolean idle, - time_t idle_time); - -/** - * Notifies Purple of our account's log-in time. - * - * This is meant to be called from protocol plugins. - * - * @param account The account the user is on. - * @param login_time The user's log-in time. - */ -void purple_prpl_got_account_login_time(PurpleAccount *account, time_t login_time); - -/** - * Notifies Purple that our account's status has changed. - * - * This is meant to be called from protocol plugins. - * - * @param account The account the user is on. - * @param status_id The status ID. - * @param ... A NULL-terminated list of attribute IDs and values, - * beginning with the value for @a attr_id. - */ -void purple_prpl_got_account_status(PurpleAccount *account, - const char *status_id, ...) G_GNUC_NULL_TERMINATED; - -/** - * Notifies Purple that our account's actions have changed. This is only - * called after the initial connection. Emits the account-actions-changed - * signal. - * - * This is meant to be called from protocol plugins. - * - * @param account The account. - * - * @see account-actions-changed - */ -void purple_prpl_got_account_actions(PurpleAccount *account); - -/** - * Notifies Purple that a buddy's idle state and time have changed. - * - * This is meant to be called from protocol plugins. - * - * @param account The account the user is on. - * @param name The name of the buddy. - * @param idle The user's idle state. - * @param idle_time The user's idle time. This is the time at - * which the user became idle, in seconds since - * the epoch. If the PRPL does not know this value - * then it should pass 0. - */ -void purple_prpl_got_user_idle(PurpleAccount *account, const char *name, - gboolean idle, time_t idle_time); - -/** - * Notifies Purple of a buddy's log-in time. - * - * This is meant to be called from protocol plugins. - * - * @param account The account the user is on. - * @param name The name of the buddy. - * @param login_time The user's log-in time. - */ -void purple_prpl_got_user_login_time(PurpleAccount *account, const char *name, - time_t login_time); - -/** - * Notifies Purple that a buddy's status has been activated. - * - * This is meant to be called from protocol plugins. - * - * @param account The account the user is on. - * @param name The name of the buddy. - * @param status_id The status ID. - * @param ... A NULL-terminated list of attribute IDs and values, - * beginning with the value for @a attr_id. - */ -void purple_prpl_got_user_status(PurpleAccount *account, const char *name, - const char *status_id, ...) G_GNUC_NULL_TERMINATED; - -/** - * Notifies libpurple that a buddy's status has been deactivated - * - * This is meant to be called from protocol plugins. - * - * @param account The account the user is on. - * @param name The name of the buddy. - * @param status_id The status ID. - */ -void purple_prpl_got_user_status_deactive(PurpleAccount *account, const char *name, - const char *status_id); - -/** - * Informs the server that our account's status changed. - * - * @param account The account the user is on. - * @param old_status The previous status. - * @param new_status The status that was activated, or deactivated - * (in the case of independent statuses). - */ -void purple_prpl_change_account_status(PurpleAccount *account, - PurpleStatus *old_status, - PurpleStatus *new_status); - -/** - * Retrieves the list of stock status types from a prpl. - * - * @param account The account the user is on. - * @param presence The presence for which we're going to get statuses - * - * @return List of statuses - */ -GList *purple_prpl_get_statuses(PurpleAccount *account, PurplePresence *presence); - -/** - * Send an attention request message. - * - * @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 purple_prpl_send_attention(PurpleConnection *gc, const char *who, guint type_code); - -/** - * Process an incoming attention message. - * - * @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 purple_prpl_got_attention(PurpleConnection *gc, const char *who, guint type_code); - -/** - * Process an incoming attention message in a chat. - * - * @param gc The connection that received the attention message. - * @param id The chat id. - * @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 purple_prpl_got_attention_in_chat(PurpleConnection *gc, int id, const char *who, guint type_code); - -/** - * Determines if the contact supports the given media session type. - * - * @param account The account the user is on. - * @param who The name of the contact to check capabilities for. - * - * @return The media caps the contact supports. - */ -PurpleMediaCaps purple_prpl_get_media_caps(PurpleAccount *account, - const char *who); - -/** - * Initiates a media session with the given contact. - * - * @param account The account the user is on. - * @param who The name of the contact to start a session with. - * @param type The type of media session to start. - * - * @return TRUE if the call succeeded else FALSE. (Doesn't imply the media session or stream will be successfully created) - */ -gboolean purple_prpl_initiate_media(PurpleAccount *account, - const char *who, - PurpleMediaSessionType type); - -/** - * Signals that the prpl received capabilities for the given contact. - * - * This function is intended to be used only by prpls. - * - * @param account The account the user is on. - * @param who The name of the contact for which capabilities have been received. - */ -void purple_prpl_got_media_caps(PurpleAccount *account, const char *who); - -/*@}*/ - -/**************************************************************************/ -/** @name Protocol Plugin Subsystem API */ -/**************************************************************************/ -/*@{*/ - -/** - * Finds a protocol plugin structure of the specified type. - * - * @param id The protocol plugin; - */ -PurplePlugin *purple_find_prpl(const char *id); - -/*@}*/ - -G_END_DECLS - -#endif /* _PRPL_H_ */
--- a/libpurple/purple.h.in Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/purple.h.in Sun Aug 18 01:53:00 2013 +0530 @@ -71,13 +71,13 @@ #include <network.h> #include <notify.h> #include <ntlm.h> -#include <plugin.h> +#include <plugins.h> #include <pluginpref.h> #include <pounce.h> #include <prefs.h> #include <presence.h> #include <proxy.h> -#include <prpl.h> +#include <protocol.h> #include <request.h> #include <roomlist.h> #include <savedstatuses.h>
--- a/libpurple/roomlist.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/roomlist.c Sun Aug 18 01:53:00 2013 +0530 @@ -207,27 +207,22 @@ PurpleRoomlist *purple_roomlist_get_list(PurpleConnection *gc) { - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; g_return_val_if_fail(gc != NULL, NULL); g_return_val_if_fail(PURPLE_CONNECTION_IS_CONNECTED(gc), NULL); - prpl = purple_connection_get_prpl(gc); + protocol = purple_connection_get_protocol_info(gc); - if(prpl != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if(prpl_info && prpl_info->roomlist_get_list) - return prpl_info->roomlist_get_list(gc); + if(protocol && protocol->roomlist_get_list) + return protocol->roomlist_get_list(gc); return NULL; } void purple_roomlist_cancel_get_list(PurpleRoomlist *list) { - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; PurpleConnection *gc; g_return_if_fail(list != NULL); @@ -237,19 +232,15 @@ g_return_if_fail(gc != NULL); if(gc) - prpl = purple_connection_get_prpl(gc); + protocol = purple_connection_get_protocol_info(gc); - if(prpl) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if(prpl_info && prpl_info->roomlist_cancel) - prpl_info->roomlist_cancel(list); + if(protocol && protocol->roomlist_cancel) + protocol->roomlist_cancel(list); } void purple_roomlist_expand_category(PurpleRoomlist *list, PurpleRoomlistRoom *category) { - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; PurpleConnection *gc; g_return_if_fail(list != NULL); @@ -260,13 +251,10 @@ g_return_if_fail(gc != NULL); if(gc) - prpl = purple_connection_get_prpl(gc); + protocol = purple_connection_get_protocol_info(gc); - if(prpl) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if(prpl_info && prpl_info->roomlist_expand_category) - prpl_info->roomlist_expand_category(list, category); + if(protocol && protocol->roomlist_expand_category) + protocol->roomlist_expand_category(list, category); } GList * purple_roomlist_get_fields(PurpleRoomlist *list)
--- a/libpurple/server.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/server.c Sun Aug 18 01:53:00 2013 +0530 @@ -30,7 +30,7 @@ #include "log.h" #include "notify.h" #include "prefs.h" -#include "prpl.h" +#include "protocol.h" #include "request.h" #include "signals.h" #include "server.h" @@ -43,15 +43,13 @@ unsigned int serv_send_typing(PurpleConnection *gc, const char *name, PurpleIMTypingState state) { - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; if (gc) { - prpl = purple_connection_get_prpl(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_connection_get_protocol_info(gc); - if (prpl_info->send_typing) - return prpl_info->send_typing(gc, name, state); + if (protocol->send_typing) + return protocol->send_typing(gc, name, state); } return 0; @@ -122,26 +120,23 @@ PurpleIMConversation *im = NULL; PurpleAccount *account = NULL; PurplePresence *presence = NULL; - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; int val = -EINVAL; const gchar *auto_reply_pref = NULL; g_return_val_if_fail(gc != NULL, val); - prpl = purple_connection_get_prpl(gc); + protocol = purple_connection_get_protocol_info(gc); - g_return_val_if_fail(prpl != NULL, val); - - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + g_return_val_if_fail(protocol != NULL, val); account = purple_connection_get_account(gc); presence = purple_account_get_presence(account); im = purple_conversations_find_im_with_account(name, account); - if (prpl_info->send_im) - val = prpl_info->send_im(gc, name, message, flags); + if (protocol->send_im) + val = protocol->send_im(gc, name, message, flags); /* * XXX - If "only auto-reply when away & idle" is set, then shouldn't @@ -165,36 +160,32 @@ void serv_get_info(PurpleConnection *gc, const char *name) { - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; if (gc) { - prpl = purple_connection_get_prpl(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_connection_get_protocol_info(gc); - if (prpl_info->get_info) - prpl_info->get_info(gc, name); + if (protocol->get_info) + protocol->get_info(gc, name); } } void serv_set_info(PurpleConnection *gc, const char *info) { - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; PurpleAccount *account; if (gc) { - prpl = purple_connection_get_prpl(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_connection_get_protocol_info(gc); - if (prpl_info->set_info) { + if (protocol->set_info) { account = purple_connection_get_account(gc); if (purple_signal_emit_return_1(purple_accounts_get_handle(), "account-setting-info", account, info)) return; - prpl_info->set_info(gc, info); + protocol->set_info(gc, info); purple_signal_emit(purple_accounts_get_handle(), "account-set-info", account, info); @@ -209,8 +200,7 @@ { PurpleAccount *account; PurpleConnection *gc; - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; if (b) { account = purple_buddy_get_account(b); @@ -219,11 +209,10 @@ gc = purple_account_get_connection(account); if (gc) { - prpl = purple_connection_get_prpl(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_connection_get_protocol_info(gc); - if (prpl_info->alias_buddy) - prpl_info->alias_buddy(gc, + if (protocol->alias_buddy) + protocol->alias_buddy(gc, purple_buddy_get_name(b), purple_buddy_get_local_alias(b)); } @@ -302,16 +291,16 @@ PurpleAttentionType *purple_get_attention_type_from_code(PurpleAccount *account, guint type_code) { - PurplePlugin *prpl; + PurpleProtocol *protocol; PurpleAttentionType* attn; GList *(*get_attention_types)(PurpleAccount *); g_return_val_if_fail(account != NULL, NULL); - prpl = purple_find_prpl(purple_account_get_protocol_id(account)); + protocol = purple_find_protocol_info(purple_account_get_protocol_id(account)); /* Lookup the attention type in the protocol's attention_types list, if any. */ - get_attention_types = PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->get_attention_types; + get_attention_types = protocol->get_attention_types; if (get_attention_types) { GList *attention_types; @@ -336,8 +325,7 @@ { PurpleAccount *account; PurpleConnection *gc; - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; g_return_if_fail(b != NULL); g_return_if_fail(og != NULL); @@ -347,11 +335,10 @@ gc = purple_account_get_connection(account); if (gc) { - prpl = purple_connection_get_prpl(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_connection_get_protocol_info(gc); - if (prpl_info->group_buddy) - prpl_info->group_buddy(gc, purple_buddy_get_name(b), + if (protocol->group_buddy) + protocol->group_buddy(gc, purple_buddy_get_name(b), purple_group_get_name(og), purple_group_get_name(ng)); } @@ -359,68 +346,58 @@ void serv_add_permit(PurpleConnection *gc, const char *name) { - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; if (gc) { - prpl = purple_connection_get_prpl(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_connection_get_protocol_info(gc); - if (prpl_info->add_permit) - prpl_info->add_permit(gc, name); + if (protocol->add_permit) + protocol->add_permit(gc, name); } } void serv_add_deny(PurpleConnection *gc, const char *name) { - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; if (gc) { - prpl = purple_connection_get_prpl(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_connection_get_protocol_info(gc); - if (prpl_info->add_deny) - prpl_info->add_deny(gc, name); + if (protocol->add_deny) + protocol->add_deny(gc, name); } } void serv_rem_permit(PurpleConnection *gc, const char *name) { - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; if (gc) { - prpl = purple_connection_get_prpl(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_connection_get_protocol_info(gc); - if (prpl_info->rem_permit) - prpl_info->rem_permit(gc, name); + if (protocol->rem_permit) + protocol->rem_permit(gc, name); } } void serv_rem_deny(PurpleConnection *gc, const char *name) { - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; if (gc) { - prpl = purple_connection_get_prpl(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_connection_get_protocol_info(gc); - if (prpl_info->rem_deny) - prpl_info->rem_deny(gc, name); + if (protocol->rem_deny) + protocol->rem_deny(gc, name); } } void serv_set_permit_deny(PurpleConnection *gc) { - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; if (gc) { - prpl = purple_connection_get_prpl(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_connection_get_protocol_info(gc); /* * this is called when either you import a buddy list, and make lots @@ -428,44 +405,39 @@ * in the prefs. In either case you should probably be resetting and * resending the permit/deny info when you get this. */ - if (prpl_info->set_permit_deny) - prpl_info->set_permit_deny(gc); + if (protocol->set_permit_deny) + protocol->set_permit_deny(gc); } } void serv_join_chat(PurpleConnection *gc, GHashTable *data) { - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; if (gc) { - prpl = purple_connection_get_prpl(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_connection_get_protocol_info(gc); - if (prpl_info->join_chat) - prpl_info->join_chat(gc, data); + if (protocol->join_chat) + protocol->join_chat(gc, data); } } void serv_reject_chat(PurpleConnection *gc, GHashTable *data) { - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; if (gc) { - prpl = purple_connection_get_prpl(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_connection_get_protocol_info(gc); - if (prpl_info->reject_chat) - prpl_info->reject_chat(gc, data); + if (protocol->reject_chat) + protocol->reject_chat(gc, data); } } void serv_chat_invite(PurpleConnection *gc, int id, const char *message, const char *name) { - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; PurpleChatConversation *chat; char *buffy = message && *message ? g_strdup(message) : NULL; @@ -475,16 +447,13 @@ return; if(gc) - prpl = purple_connection_get_prpl(gc); - - if(prpl) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_connection_get_protocol_info(gc); purple_signal_emit(purple_conversations_get_handle(), "chat-inviting-user", chat, name, &buffy); - if (prpl_info && prpl_info->chat_invite) - prpl_info->chat_invite(gc, id, buffy, name); + if (protocol && protocol->chat_invite) + protocol->chat_invite(gc, id, buffy, name); purple_signal_emit(purple_conversations_get_handle(), "chat-invited-user", chat, name, buffy); @@ -499,40 +468,34 @@ */ void serv_chat_leave(PurpleConnection *gc, int id) { - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; - prpl = purple_connection_get_prpl(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_connection_get_protocol_info(gc); - if (prpl_info->chat_leave) - prpl_info->chat_leave(gc, id); + if (protocol->chat_leave) + protocol->chat_leave(gc, id); } void serv_chat_whisper(PurpleConnection *gc, int id, const char *who, const char *message) { - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; if (gc) { - prpl = purple_connection_get_prpl(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_connection_get_protocol_info(gc); - if (prpl_info->chat_whisper) - prpl_info->chat_whisper(gc, id, who, message); + if (protocol->chat_whisper) + protocol->chat_whisper(gc, id, who, message); } } int serv_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags) { - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; - prpl = purple_connection_get_prpl(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_connection_get_protocol_info(gc); - if (prpl_info->chat_send) - return prpl_info->chat_send(gc, id, message, flags); + if (protocol->chat_send) + return protocol->chat_send(gc, id, message, flags); return -EINVAL; } @@ -923,16 +886,14 @@ void serv_send_file(PurpleConnection *gc, const char *who, const char *file) { - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; if (gc) { - prpl = purple_connection_get_prpl(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_connection_get_protocol_info(gc); - if (prpl_info->send_file && - (!prpl_info->can_receive_file - || prpl_info->can_receive_file(gc, who))) - prpl_info->send_file(gc, who, file); + if (protocol->send_file && + (!protocol->can_receive_file + || protocol->can_receive_file(gc, who))) + protocol->send_file(gc, who, file); } }
--- a/libpurple/server.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/server.h Sun Aug 18 01:53:00 2013 +0530 @@ -28,7 +28,7 @@ #include "accounts.h" #include "conversations.h" -#include "prpl.h" +#include "protocol.h" G_BEGIN_DECLS
--- a/libpurple/sslconn.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/sslconn.c Sun Aug 18 01:53:00 2013 +0530 @@ -29,6 +29,7 @@ #include "certificate.h" #include "debug.h" +#include "plugins.h" #include "request.h" #include "sslconn.h" @@ -44,10 +45,10 @@ if (_ssl_initialized) return FALSE; - plugin = purple_plugins_find_with_id("core-ssl"); + plugin = purple_plugins_find_plugin("core-ssl"); - if (plugin != NULL && !purple_plugin_is_loaded(plugin)) - purple_plugin_load(plugin); + if (plugin != NULL) + purple_plugin_load(plugin, NULL); ops = purple_ssl_get_ops(); if ((ops == NULL) || (ops->init == NULL) || (ops->uninit == NULL) ||
--- a/libpurple/status.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/status.c Sun Aug 18 01:53:00 2013 +0530 @@ -559,7 +559,7 @@ PurpleAccountUiOps *ops = purple_accounts_get_ui_ops(); if (purple_account_get_enabled(account, purple_core_get_ui())) - purple_prpl_change_account_status(account, old_status, new_status); + purple_protocol_change_account_status(account, old_status, new_status); if (ops != NULL && ops->status_changed != NULL) {
--- a/libpurple/tests/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/tests/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -23,6 +23,7 @@ check_libpurple_CFLAGS=\ @CHECK_CFLAGS@ \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(DEBUG_CFLAGS) \ $(LIBXML_CFLAGS) \ -I.. \ @@ -35,6 +36,7 @@ $(top_builddir)/libpurple/protocols/yahoo/libymsg.la \ $(top_builddir)/libpurple/libpurple.la \ @CHECK_LIBS@ \ - $(GLIB_LIBS) + $(GLIB_LIBS) \ + $(GPLUGIN_LIBS) endif
--- a/libpurple/util.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/util.c Sun Aug 18 01:53:00 2013 +0530 @@ -28,7 +28,7 @@ #include "core.h" #include "debug.h" #include "notify.h" -#include "prpl.h" +#include "protocol.h" #include "prefs.h" #include "util.h" @@ -3389,15 +3389,11 @@ if (account != NULL) { - PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account)); - - if (prpl != NULL) - { - PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if (prpl_info->normalize) - ret = prpl_info->normalize(account, str); - } + PurpleProtocol *protocol = + purple_find_protocol_info(purple_account_get_protocol_id(account)); + + if (protocol != NULL && protocol->normalize) + ret = protocol->normalize(account, str); } if (ret == NULL) @@ -3437,23 +3433,20 @@ } gboolean -purple_validate(const PurplePlugin *prpl, const char *str) +purple_validate(const PurpleProtocol *protocol, const char *str) { - PurplePluginProtocolInfo *prpl_info; const char *normalized; - g_return_val_if_fail(prpl != NULL, FALSE); + g_return_val_if_fail(protocol != NULL, FALSE); g_return_val_if_fail(str != NULL, FALSE); if (str[0] == '\0') return FALSE; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - - if (!prpl_info->normalize) + if (!protocol->normalize) return TRUE; - normalized = prpl_info->normalize(NULL, str); + normalized = protocol->normalize(NULL, str); return (NULL != normalized); }
--- a/libpurple/util.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/util.h Sun Aug 18 01:53:00 2013 +0530 @@ -50,7 +50,7 @@ #include "signals.h" #include "xmlnode.h" #include "notify.h" -#include "plugin.h" +#include "protocol.h" typedef char *(*PurpleInfoFieldFormatCallback)(const char *field, size_t len); @@ -961,7 +961,7 @@ * * @return TRUE, if string is valid, otherwise FALSE. */ -gboolean purple_validate(const PurplePlugin *prpl, const char *str); +gboolean purple_validate(const PurpleProtocol *protocol, const char *str); /** * Compares two strings to see if the first contains the second as
--- a/libpurple/whiteboard.c Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/whiteboard.c Sun Aug 18 01:53:00 2013 +0530 @@ -23,7 +23,7 @@ #include "internal.h" #include "whiteboard.h" -#include "prpl.h" +#include "protocol.h" /** * A PurpleWhiteboard @@ -37,7 +37,7 @@ void *ui_data; /**< Graphical user-interface data */ void *proto_data; /**< Protocol specific data */ - PurpleWhiteboardPrplOps *prpl_ops; /**< Protocol-plugin operations */ + PurpleWhiteboardPrplOps *protocol_ops; /**< Protocol-plugin operations */ GList *draw_list; /**< List of drawing elements/deltas to send */ }; @@ -46,7 +46,7 @@ * Globals *****************************************************************************/ static PurpleWhiteboardUiOps *whiteboard_ui_ops = NULL; -/* static PurpleWhiteboardPrplOps *whiteboard_prpl_ops = NULL; */ +/* static PurpleWhiteboardPrplOps *whiteboard_protocol_ops = NULL; */ static GList *wbList = NULL; @@ -60,27 +60,26 @@ whiteboard_ui_ops = ops; } -void purple_whiteboard_set_prpl_ops(PurpleWhiteboard *wb, PurpleWhiteboardPrplOps *ops) +void purple_whiteboard_set_protocol_ops(PurpleWhiteboard *wb, PurpleWhiteboardPrplOps *ops) { - wb->prpl_ops = ops; + wb->protocol_ops = ops; } PurpleWhiteboard *purple_whiteboard_create(PurpleAccount *account, const char *who, int state) { - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; PurpleWhiteboard *wb = g_new0(PurpleWhiteboard, 1); wb->account = account; wb->state = state; wb->who = g_strdup(who); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl( - purple_account_get_connection(account))); - purple_whiteboard_set_prpl_ops(wb, prpl_info->whiteboard_prpl_ops); + protocol = purple_connection_get_protocol_info(purple_account_get_connection(account)); + purple_whiteboard_set_protocol_ops(wb, protocol->whiteboard_protocol_ops); /* Start up protocol specifics */ - if(wb->prpl_ops && wb->prpl_ops->start) - wb->prpl_ops->start(wb); + if(wb->protocol_ops && wb->protocol_ops->start) + wb->protocol_ops->start(wb); wbList = g_list_append(wbList, wb); @@ -99,8 +98,8 @@ } /* Do protocol specific session ending procedures */ - if(wb->prpl_ops && wb->prpl_ops->end) - wb->prpl_ops->end(wb); + if(wb->protocol_ops && wb->protocol_ops->end) + wb->protocol_ops->end(wb); g_free(wb->who); wbList = g_list_remove(wbList, wb); @@ -174,11 +173,11 @@ gboolean purple_whiteboard_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height) { - PurpleWhiteboardPrplOps *prpl_ops = wb->prpl_ops; + PurpleWhiteboardPrplOps *protocol_ops = wb->protocol_ops; - if (prpl_ops && prpl_ops->get_dimensions) + if (protocol_ops && protocol_ops->get_dimensions) { - prpl_ops->get_dimensions(wb, width, height); + protocol_ops->get_dimensions(wb, width, height); return TRUE; } @@ -193,10 +192,10 @@ void purple_whiteboard_send_draw_list(PurpleWhiteboard *wb, GList *list) { - PurpleWhiteboardPrplOps *prpl_ops = wb->prpl_ops; + PurpleWhiteboardPrplOps *protocol_ops = wb->protocol_ops; - if (prpl_ops && prpl_ops->send_draw_list) - prpl_ops->send_draw_list(wb, list); + if (protocol_ops && protocol_ops->send_draw_list) + protocol_ops->send_draw_list(wb, list); } void purple_whiteboard_draw_point(PurpleWhiteboard *wb, int x, int y, int color, int size) @@ -219,27 +218,27 @@ void purple_whiteboard_send_clear(PurpleWhiteboard *wb) { - PurpleWhiteboardPrplOps *prpl_ops = wb->prpl_ops; + PurpleWhiteboardPrplOps *protocol_ops = wb->protocol_ops; - if (prpl_ops && prpl_ops->clear) - prpl_ops->clear(wb); + if (protocol_ops && protocol_ops->clear) + protocol_ops->clear(wb); } void purple_whiteboard_send_brush(PurpleWhiteboard *wb, int size, int color) { - PurpleWhiteboardPrplOps *prpl_ops = wb->prpl_ops; + PurpleWhiteboardPrplOps *protocol_ops = wb->protocol_ops; - if (prpl_ops && prpl_ops->set_brush) - prpl_ops->set_brush(wb, size, color); + if (protocol_ops && protocol_ops->set_brush) + protocol_ops->set_brush(wb, size, color); } gboolean purple_whiteboard_get_brush(const PurpleWhiteboard *wb, int *size, int *color) { - PurpleWhiteboardPrplOps *prpl_ops = wb->prpl_ops; + PurpleWhiteboardPrplOps *protocol_ops = wb->protocol_ops; - if (prpl_ops && prpl_ops->get_brush) + if (protocol_ops && protocol_ops->get_brush) { - prpl_ops->get_brush(wb, size, color); + protocol_ops->get_brush(wb, size, color); return TRUE; } return FALSE;
--- a/libpurple/whiteboard.h Sun Aug 18 01:52:32 2013 +0530 +++ b/libpurple/whiteboard.h Sun Aug 18 01:53:00 2013 +0530 @@ -99,7 +99,7 @@ * @param wb The whiteboard for which to set the prpl operations * @param ops The prpl operations to set */ -void purple_whiteboard_set_prpl_ops(PurpleWhiteboard *wb, PurpleWhiteboardPrplOps *ops); +void purple_whiteboard_set_protocol_ops(PurpleWhiteboard *wb, PurpleWhiteboardPrplOps *ops); /** * Creates a whiteboard
--- a/pidgin/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -168,6 +168,7 @@ pidgin_LDADD = \ @LIBOBJS@ \ $(GLIB_LIBS) \ + $(GPLUGIN_LIBS) \ $(GCR_LIBS) \ $(DBUS_LIBS) \ $(GSTREAMER_LIBS) \ @@ -197,6 +198,7 @@ -I$(top_builddir) \ -I$(top_srcdir) \ $(GLIB_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(GCR_CFLAGS) \ $(GSTREAMER_CFLAGS) \ $(GSTVIDEO_CFLAGS) \
--- a/pidgin/gtkaccount.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkaccount.c Sun Aug 18 01:53:00 2013 +0530 @@ -32,9 +32,9 @@ #include "core.h" #include "debug.h" #include "notify.h" -#include "plugin.h" +#include "plugins.h" #include "prefs.h" -#include "prpl.h" +#include "protocol.h" #include "request.h" #include "savedstatuses.h" #include "signals.h" @@ -98,8 +98,7 @@ PurpleAccount *account; char *protocol_id; - PurplePlugin *plugin; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; PurpleProxyType new_proxy_type; @@ -203,14 +202,14 @@ pixbuf = pidgin_pixbuf_from_imgstore(dialog->icon_img); } - if (pixbuf && dialog->prpl_info && - (dialog->prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_DISPLAY)) + if (pixbuf && dialog->protocol && + (dialog->protocol->icon_spec.scale_rules & PURPLE_ICON_SCALE_DISPLAY)) { /* Scale the icon to something reasonable */ int width, height; GdkPixbuf *scale; - pidgin_buddy_icon_get_scale_size(pixbuf, &dialog->prpl_info->icon_spec, + pidgin_buddy_icon_get_scale_size(pixbuf, &dialog->protocol->icon_spec, PURPLE_ICON_SCALE_DISPLAY, &width, &height); scale = gdk_pixbuf_scale_simple(pixbuf, width, height, GDK_INTERP_BILINEAR); @@ -235,19 +234,13 @@ set_account_protocol_cb(GtkWidget *widget, const char *id, AccountPrefsDialog *dialog) { - PurplePlugin *new_plugin; - - new_plugin = purple_find_prpl(id); - - dialog->plugin = new_plugin; - - if (dialog->plugin != NULL) - { - dialog->prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(dialog->plugin); - - g_free(dialog->protocol_id); - dialog->protocol_id = g_strdup(dialog->plugin->info->id); - } + PurpleProtocol *new_protocol; + + new_protocol = purple_find_protocol_info(id); + + dialog->protocol = new_protocol; + g_free(dialog->protocol_id); + dialog->protocol_id = dialog->protocol ? g_strdup(dialog->protocol->id) : NULL; if (dialog->account != NULL) purple_account_clear_settings(dialog->account); @@ -259,13 +252,13 @@ gtk_widget_grab_focus(dialog->protocol_menu); - if (!dialog->prpl_info || !dialog->prpl_info->register_user) { + if (!dialog->protocol || !dialog->protocol->register_user) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON( dialog->register_button), FALSE); gtk_widget_hide(dialog->register_button); } else { - if (dialog->prpl_info != NULL && - (dialog->prpl_info->options & OPT_PROTO_REGISTER_NOSCREENNAME)) { + if (dialog->protocol != NULL && + (dialog->protocol->options & OPT_PROTO_REGISTER_NOSCREENNAME)) { gtk_widget_set_sensitive(dialog->register_button, TRUE); } else { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON( @@ -279,9 +272,9 @@ static void username_changed_cb(GtkEntry *entry, AccountPrefsDialog *dialog) { - gboolean opt_noscreenname = (dialog->prpl_info != NULL && - (dialog->prpl_info->options & OPT_PROTO_REGISTER_NOSCREENNAME)); - gboolean username_valid = purple_validate(dialog->plugin, + gboolean opt_noscreenname = (dialog->protocol != NULL && + (dialog->protocol->options & OPT_PROTO_REGISTER_NOSCREENNAME)); + gboolean username_valid = purple_validate(dialog->protocol, gtk_entry_get_text(entry)); if (dialog->ok_button) { @@ -310,12 +303,12 @@ GHashTable *table; const char *label; - if (!dialog->prpl_info || ! PURPLE_PROTOCOL_PLUGIN_HAS_FUNC( - dialog->prpl_info, get_account_text_table)) { + if (!dialog->protocol || ! PURPLE_PROTOCOL_PLUGIN_HAS_FUNC( + dialog->protocol, get_account_text_table)) { return FALSE; } - table = dialog->prpl_info->get_account_text_table(NULL); + table = dialog->protocol->get_account_text_table(NULL); label = g_hash_table_lookup(table, "login_label"); if(!strcmp(gtk_entry_get_text(GTK_ENTRY(widget)), label)) { @@ -338,8 +331,8 @@ GHashTable *table = NULL; const char *label = NULL; - if(PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(dialog->prpl_info, get_account_text_table)) { - table = dialog->prpl_info->get_account_text_table(NULL); + if(PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(dialog->protocol, get_account_text_table)) { + table = dialog->protocol->get_account_text_table(NULL); label = g_hash_table_lookup(table, "login_label"); if (*gtk_entry_get_text(GTK_ENTRY(widget)) == '\0') { @@ -378,7 +371,7 @@ #endif gint xsize; - table = dialog->prpl_info->get_account_text_table(NULL); + table = dialog->protocol->get_account_text_table(NULL); label = g_hash_table_lookup(table, "login_label"); text = gtk_entry_get_text(GTK_ENTRY(widget)); @@ -446,8 +439,8 @@ { int register_checked = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(dialog->register_button)); - int opt_noscreenname = (dialog->prpl_info != NULL && - (dialog->prpl_info->options & OPT_PROTO_REGISTER_NOSCREENNAME)); + int opt_noscreenname = (dialog->protocol != NULL && + (dialog->protocol->options & OPT_PROTO_REGISTER_NOSCREENNAME)); int register_noscreenname = (opt_noscreenname && register_checked); #if !GTK_CHECK_VERSION(3,2,0) @@ -484,7 +477,7 @@ if (filename != NULL) { size_t len; - gpointer data = pidgin_convert_buddy_icon(dialog->plugin, filename, &len); + gpointer data = pidgin_convert_buddy_icon(dialog->protocol, filename, &len); set_dialog_icon(dialog, data, len, g_strdup(filename)); } @@ -531,7 +524,7 @@ if ((rtmp = strchr(tmp, '\r')) || (rtmp = strchr(tmp, '\n'))) *rtmp = '\0'; - data = pidgin_convert_buddy_icon(dialog->plugin, tmp, &len); + data = pidgin_convert_buddy_icon(dialog->protocol, tmp, &len); /* This takes ownership of tmp */ set_dialog_icon(dialog, data, len, tmp); } @@ -629,11 +622,11 @@ if (dialog->account != NULL) username = g_strdup(purple_account_get_username(dialog->account)); - if (!username && dialog->prpl_info - && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(dialog->prpl_info, get_account_text_table)) { + if (!username && dialog->protocol + && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(dialog->protocol, get_account_text_table)) { GHashTable *table; const char *label; - table = dialog->prpl_info->get_account_text_table(NULL); + table = dialog->protocol->get_account_text_table(NULL); label = g_hash_table_lookup(table, "login_label"); #if GTK_CHECK_VERSION(3,2,0) @@ -656,10 +649,10 @@ G_CALLBACK(username_changed_cb), dialog); /* Do the user split thang */ - if (dialog->prpl_info == NULL) + if (dialog->protocol == NULL) user_splits = NULL; else - user_splits = dialog->prpl_info->user_splits; + user_splits = dialog->protocol->user_splits; if (dialog->user_split_entries != NULL) { g_list_free(dialog->user_split_entries); @@ -748,8 +741,8 @@ purple_account_get_remember_password(dialog->account)); } - if (dialog->prpl_info != NULL && - (dialog->prpl_info->options & OPT_PROTO_NO_PASSWORD)) { + if (dialog->protocol != NULL && + (dialog->protocol->options & OPT_PROTO_NO_PASSWORD)) { gtk_widget_hide(dialog->password_box); gtk_widget_hide(dialog->remember_pass_check); @@ -848,11 +841,11 @@ gtk_box_pack_start(GTK_BOX(hbox2), button, FALSE, FALSE, 0); gtk_widget_show(button); - if (dialog->prpl_info != NULL) { - if (!(dialog->prpl_info->options & OPT_PROTO_MAIL_CHECK)) + if (dialog->protocol != NULL) { + if (!(dialog->protocol->options & OPT_PROTO_MAIL_CHECK)) gtk_widget_hide(dialog->new_mail_check); - if (dialog->prpl_info->icon_spec.format == NULL) { + if (dialog->protocol->icon_spec.format == NULL) { gtk_widget_hide(dialog->icon_check); gtk_widget_hide(dialog->icon_hbox); } @@ -887,9 +880,9 @@ } #if 0 - if (!dialog->prpl_info || - (!(dialog->prpl_info->options & OPT_PROTO_MAIL_CHECK) && - (dialog->prpl_info->icon_spec.format == NULL))) { + if (!dialog->protocol || + (!(dialog->protocol->options & OPT_PROTO_MAIL_CHECK) && + (dialog->protocol->icon_spec.format == NULL))) { /* Nothing to see :( aww. */ gtk_widget_hide(dialog->user_frame); @@ -929,8 +922,8 @@ dialog->protocol_opt_entries = g_list_delete_link(dialog->protocol_opt_entries, dialog->protocol_opt_entries); } - if (dialog->prpl_info == NULL || - dialog->prpl_info->protocol_options == NULL) + if (dialog->protocol == NULL || + dialog->protocol->protocol_options == NULL) return; account = dialog->account; @@ -942,7 +935,7 @@ gtk_label_new_with_mnemonic(_("Ad_vanced")), 1); gtk_widget_show(vbox); - for (l = dialog->prpl_info->protocol_options; l != NULL; l = l->next) + for (l = dialog->protocol->protocol_options; l != NULL; l = l->next) { option = (PurpleAccountOption *)l->data; @@ -1329,7 +1322,7 @@ add_voice_options(AccountPrefsDialog *dialog) { #ifdef USE_VV - if (!dialog->prpl_info || !PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(dialog->prpl_info, initiate_media)) { + if (!dialog->protocol || !PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(dialog->protocol, initiate_media)) { if (dialog->voice_frame) { gtk_widget_destroy(dialog->voice_frame); dialog->voice_frame = NULL; @@ -1431,9 +1424,9 @@ /* Build the username string. */ username = g_strdup(gtk_entry_get_text(GTK_ENTRY(dialog->username_entry))); - if (dialog->prpl_info != NULL) + if (dialog->protocol != NULL) { - for (l = dialog->prpl_info->user_splits, + for (l = dialog->protocol->user_splits, l2 = dialog->user_split_entries; l != NULL && l2 != NULL; l = l->next, l2 = l2->next) @@ -1494,7 +1487,7 @@ purple_account_set_private_alias(account, NULL); /* Buddy Icon */ - if (dialog->prpl_info != NULL && dialog->prpl_info->icon_spec.format != NULL) + if (dialog->protocol != NULL && dialog->protocol->icon_spec.format != NULL) { const char *filename; @@ -1524,7 +1517,7 @@ else if ((filename = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon")) && icon_change) { size_t len; - gpointer data = pidgin_convert_buddy_icon(dialog->plugin, filename, &len); + gpointer data = pidgin_convert_buddy_icon(dialog->protocol, filename, &len); purple_account_set_buddy_icon_path(account, filename); purple_buddy_icons_set_account_icon(account, data, len); } @@ -1540,7 +1533,7 @@ purple_account_set_remember_password(account, remember); /* Check Mail */ - if (dialog->prpl_info && dialog->prpl_info->options & OPT_PROTO_MAIL_CHECK) + if (dialog->protocol && dialog->protocol->options & OPT_PROTO_MAIL_CHECK) purple_account_set_check_mail(account, gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(dialog->new_mail_check))); @@ -1563,7 +1556,7 @@ g_free(username); /* Add the protocol settings */ - if (dialog->prpl_info) { + if (dialog->protocol) { ProtocolOptEntry *opt_entry; GtkTreeIter iter; char *value2; @@ -1732,10 +1725,10 @@ dialog->sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); if (dialog->account == NULL) { - /* Select the first prpl in the list*/ - GList *prpl_list = purple_plugins_get_protocols(); - if (prpl_list != NULL) - dialog->protocol_id = g_strdup(((PurplePlugin *) prpl_list->data)->info->id); + /* Select the first protocol in the list*/ + GList *protocol_list = purple_protocols_get_all(); + if (protocol_list != NULL) + dialog->protocol_id = g_strdup(((PurpleProtocol *) protocol_list->data)->id); } else { @@ -1743,8 +1736,12 @@ g_strdup(purple_account_get_protocol_id(dialog->account)); } - if ((dialog->plugin = purple_find_prpl(dialog->protocol_id)) != NULL) - dialog->prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(dialog->plugin); + /* TODO if no protocols are loaded, this should inform the user that + protocols need to be loaded instead of just doing nothing */ + if (!dialog->protocol_id) + return; + + dialog->protocol = purple_find_protocol_info(dialog->protocol_id); dialog->window = win = pidgin_create_dialog((type == PIDGIN_ADD_ACCOUNT_DIALOG) ? _("Add Account") : _("Modify Account"), PIDGIN_HIG_BOX_SPACE, "account", FALSE); @@ -1779,7 +1776,7 @@ if (dialog->account == NULL) gtk_widget_set_sensitive(button, FALSE); - if (!dialog->prpl_info || !dialog->prpl_info->register_user) + if (!dialog->protocol || !dialog->protocol->register_user) gtk_widget_hide(button); /* Setup the page with 'Advanced' (protocol options). */ @@ -1854,7 +1851,7 @@ if (gtk_tree_model_iter_nth_child(model, &iter, NULL, index)) { - pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM); + pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_MEDIUM); if ((pixbuf != NULL) && purple_account_is_disconnected(account)) gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE); @@ -2243,17 +2240,14 @@ { GdkPixbuf *pixbuf, *buddyicon = NULL; PurpleStoredImage *img = NULL; - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info = NULL; - - pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM); + PurpleProtocol *protocol = NULL; + + pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_MEDIUM); if ((pixbuf != NULL) && purple_account_is_disconnected(account)) gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE); - prpl = purple_find_prpl(purple_account_get_protocol_id(account)); - if (prpl != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (prpl_info != NULL && prpl_info->icon_spec.format != NULL) { + protocol = purple_find_protocol_info(purple_account_get_protocol_id(account)); + if (protocol != NULL && protocol->icon_spec.format != NULL) { if (purple_account_get_bool(account, "use-global-buddyicon", TRUE)) { if (global_buddyicon != NULL) buddyicon = g_object_ref(G_OBJECT(global_buddyicon)); @@ -2712,14 +2706,12 @@ authorize_reason_cb(struct auth_request *ar) { const char *protocol_id; - PurplePlugin *plugin; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; protocol_id = purple_account_get_protocol_id(ar->account); - if ((plugin = purple_find_prpl(protocol_id)) != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); - - if (prpl_info && (prpl_info->options & OPT_PROTO_AUTHORIZATION_GRANTED_MESSAGE)) { + protocol = purple_find_protocol_info(protocol_id); + + if (protocol && (protocol->options & OPT_PROTO_AUTHORIZATION_GRANTED_MESSAGE)) { /* Duplicate information because ar is freed by closing minidialog */ struct auth_request *aa = g_new0(struct auth_request, 1); aa->auth_cb = ar->auth_cb; @@ -2757,14 +2749,12 @@ deny_reason_cb(struct auth_request *ar) { const char *protocol_id; - PurplePlugin *plugin; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; protocol_id = purple_account_get_protocol_id(ar->account); - if ((plugin = purple_find_prpl(protocol_id)) != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); - - if (prpl_info && (prpl_info->options & OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE)) { + protocol = purple_find_protocol_info(protocol_id); + + if (protocol && (protocol->options & OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE)) { /* Duplicate information because ar is freed by closing minidialog */ struct auth_request *aa = g_new0(struct auth_request, 1); aa->auth_cb = ar->auth_cb; @@ -2820,7 +2810,7 @@ PurpleConnection *gc; GtkWidget *alert; PidginMiniDialog *dialog; - GdkPixbuf *prpl_icon; + GdkPixbuf *protocol_icon; struct auth_request *aa; const char *our_name; gboolean have_valid_alias; @@ -2859,7 +2849,7 @@ g_free(escaped_our_name); g_free(escaped_message); - prpl_icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); + protocol_icon = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL); aa = g_new0(struct auth_request, 1); aa->auth_cb = auth_cb; @@ -2871,7 +2861,7 @@ aa->add_buddy_after_auth = !on_list; alert = pidgin_make_mini_dialog_with_custom_icon( - gc, prpl_icon, + gc, protocol_icon, _("Authorize buddy?"), NULL, aa, _("Authorize"), authorize_reason_cb, _("Deny"), deny_reason_cb,
--- a/pidgin/gtkblist.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkblist.c Sun Aug 18 01:53:00 2013 +0530 @@ -32,9 +32,9 @@ #include "core.h" #include "debug.h" #include "notify.h" -#include "prpl.h" +#include "protocol.h" #include "prefs.h" -#include "plugin.h" +#include "plugins.h" #include "request.h" #include "signals.h" #include "pidginstock.h" @@ -322,7 +322,7 @@ #ifdef USE_VV static void gtk_blist_menu_audio_call_cb(GtkWidget *w, PurpleBuddy *b) { - purple_prpl_initiate_media(purple_buddy_get_account(b), + purple_protocol_initiate_media(purple_buddy_get_account(b), purple_buddy_get_name(b), PURPLE_MEDIA_AUDIO); } @@ -330,13 +330,13 @@ { /* if the buddy supports both audio and video, start a combined call, otherwise start a pure video session */ - if (purple_prpl_get_media_caps(purple_buddy_get_account(b), + if (purple_protocol_get_media_caps(purple_buddy_get_account(b), purple_buddy_get_name(b)) & PURPLE_MEDIA_CAPS_AUDIO_VIDEO) { - purple_prpl_initiate_media(purple_buddy_get_account(b), + purple_protocol_initiate_media(purple_buddy_get_account(b), purple_buddy_get_name(b), PURPLE_MEDIA_AUDIO | PURPLE_MEDIA_VIDEO); } else { - purple_prpl_initiate_media(purple_buddy_get_account(b), + purple_protocol_initiate_media(purple_buddy_get_account(b), purple_buddy_get_name(b), PURPLE_MEDIA_VIDEO); } } @@ -384,18 +384,18 @@ { PurpleAccount *account; PurpleConversation *conv; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; GHashTable *components; const char *name; char *chat_name; account = purple_chat_get_account(chat); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account))); + protocol = purple_find_protocol_info(purple_account_get_protocol_id(account)); components = purple_chat_get_components(chat); - if (prpl_info && prpl_info->get_chat_name) - chat_name = prpl_info->get_chat_name(components); + if (protocol && protocol->get_chat_name) + chat_name = protocol->get_chat_name(components); else chat_name = NULL; @@ -671,7 +671,7 @@ purple_request_fields_add_group(fields, group); gc = purple_account_get_connection(purple_chat_get_account(chat)); - parts = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->chat_info(gc); + parts = purple_connection_get_protocol_info(gc)->chat_info(gc); for (iter = parts; iter; iter = iter->next) { pce = iter->data; @@ -748,12 +748,12 @@ account = purple_buddy_get_account(b); } else if (PURPLE_IS_CHAT(node)) { PurpleChat *c = PURPLE_CHAT(node); - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; type = PURPLE_LOG_CHAT; account = purple_chat_get_account(c); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_find_prpl(purple_account_get_protocol_id(account))); - if (prpl_info && prpl_info->get_chat_name) { - name = prpl_info->get_chat_name(purple_chat_get_components(c)); + protocol = purple_find_protocol_info(purple_account_get_protocol_id(account)); + if (protocol && protocol->get_chat_name) { + name = protocol->get_chat_name(purple_chat_get_components(c)); } } else if (PURPLE_IS_CONTACT(node)) { pidgin_log_show_contact(PURPLE_CONTACT(node)); @@ -888,7 +888,7 @@ static void set_sensitive_if_input_chat_cb(GtkWidget *entry, gpointer user_data) { - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; PurpleConnection *gc; PidginChatData *data; GList *tmp; @@ -912,8 +912,8 @@ 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(purple_connection_get_prpl(gc)) : NULL; - sensitive = (prpl_info != NULL && prpl_info->roomlist_get_list != NULL); + protocol = (gc != NULL) ? purple_connection_get_protocol_info(gc) : NULL; + sensitive = (protocol != NULL && protocol->roomlist_get_list != NULL); gtk_dialog_set_response_sensitive(GTK_DIALOG(data->rq_data.window), 1, sensitive); } @@ -921,16 +921,16 @@ static void set_sensitive_if_input_buddy_cb(GtkWidget *entry, gpointer user_data) { - PurplePlugin *prpl; + PurpleProtocol *protocol; PidginAddBuddyData *data = user_data; const char *text; - prpl = purple_find_prpl(purple_account_get_protocol_id( + protocol = purple_find_protocol_info(purple_account_get_protocol_id( data->rq_data.account)); text = gtk_entry_get_text(GTK_ENTRY(entry)); gtk_dialog_set_response_sensitive(GTK_DIALOG(data->rq_data.window), - GTK_RESPONSE_OK, purple_validate(prpl, text)); + GTK_RESPONSE_OK, purple_validate(protocol, text)); } static void @@ -946,14 +946,14 @@ chat_account_filter_func(PurpleAccount *account) { PurpleConnection *gc = purple_account_get_connection(account); - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; if (gc == NULL) return FALSE; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - - return (prpl_info->chat_info != NULL); + protocol = purple_connection_get_protocol_info(gc); + + return (protocol->chat_info != NULL); } gboolean @@ -1042,7 +1042,7 @@ rebuild_chat_entries(PidginChatData *data, const char *default_chat_name) { PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; GList *list = NULL, *tmp; GHashTable *defaults = NULL; struct proto_chat_entry *pce; @@ -1051,18 +1051,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)); + protocol = purple_connection_get_protocol_info(gc); gtk_container_foreach(GTK_CONTAINER(data->rq_data.vbox), (GtkCallback)gtk_widget_destroy, NULL); g_list_free(data->entries); data->entries = NULL; - 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); + if (protocol->chat_info != NULL) + list = protocol->chat_info(gc); + + if (protocol->chat_info_defaults != NULL) + defaults = protocol->chat_info_defaults(gc, default_chat_name); for (tmp = list; tmp; tmp = tmp->next) { @@ -1426,12 +1426,12 @@ PurpleBlistNode *node) { GList *l, *ll; - PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - - if(!prpl_info || !prpl_info->blist_node_menu) + PurpleProtocol *protocol = purple_connection_get_protocol_info(gc); + + if(!protocol || !protocol->blist_node_menu) return; - for(l = ll = prpl_info->blist_node_menu(node); l; l = l->next) { + for(l = ll = protocol->blist_node_menu(node); l; l = l->next) { PurpleMenuAction *act = (PurpleMenuAction *) l->data; pidgin_append_menu_action(menu, act, node); } @@ -1482,7 +1482,7 @@ pidgin_blist_make_buddy_menu(GtkWidget *menu, PurpleBuddy *buddy, gboolean sub) { PurpleAccount *account = NULL; PurpleConnection *pc = NULL; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; PurpleContact *contact; PurpleBlistNode *node; gboolean contact_expanded = FALSE; @@ -1492,7 +1492,7 @@ account = purple_buddy_get_account(buddy); pc = purple_account_get_connection(account); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(pc)); + protocol = purple_connection_get_protocol_info(pc); node = PURPLE_BLIST_NODE(buddy); @@ -1502,7 +1502,7 @@ contact_expanded = node->contact_expanded; } - if (prpl_info && prpl_info->get_info) { + if (protocol && protocol->get_info) { pidgin_new_item_from_stock(menu, _("Get _Info"), PIDGIN_STOCK_TOOLBAR_USER_INFO, G_CALLBACK(gtk_blist_menu_info_cb), buddy, 0, 0, NULL); } @@ -1510,10 +1510,10 @@ G_CALLBACK(gtk_blist_menu_im_cb), buddy, 0, 0, NULL); #ifdef USE_VV - if (prpl_info && prpl_info->get_media_caps) { + if (protocol && protocol->get_media_caps) { PurpleAccount *account = purple_buddy_get_account(buddy); const gchar *who = purple_buddy_get_name(buddy); - PurpleMediaCaps caps = purple_prpl_get_media_caps(account, who); + PurpleMediaCaps caps = purple_protocol_get_media_caps(account, who); if (caps & PURPLE_MEDIA_CAPS_AUDIO) { pidgin_new_item_from_stock(menu, _("_Audio Call"), PIDGIN_STOCK_TOOLBAR_AUDIO_CALL, @@ -1532,9 +1532,9 @@ #endif - if (prpl_info && prpl_info->send_file) { - if (!prpl_info->can_receive_file || - prpl_info->can_receive_file(purple_account_get_connection(purple_buddy_get_account(buddy)), purple_buddy_get_name(buddy))) + if (protocol && protocol->send_file) { + if (!protocol->can_receive_file || + protocol->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, @@ -1859,7 +1859,7 @@ continue; 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); + buf = pidgin_create_protocol_icon(purple_buddy_get_account(buddy), PIDGIN_PROTOCOL_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), @@ -1941,8 +1941,7 @@ PurpleBlistNode *node; GtkTreeIter iter; GtkTreeSelection *sel; - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; struct _pidgin_blist_node *gtknode; gboolean handled = FALSE; @@ -1975,11 +1974,9 @@ else b = (PurpleBuddy *)node; - 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) + protocol = purple_find_protocol_info(purple_account_get_protocol_id(purple_buddy_get_account(b))); + + if (protocol && protocol->get_info) pidgin_retrieve_user_info(purple_account_get_connection(purple_buddy_get_account(b)), purple_buddy_get_name(b)); handled = TRUE; } @@ -2104,7 +2101,7 @@ } static void -add_buddies_from_vcard(const char *prpl_id, PurpleGroup *group, GList *list, +add_buddies_from_vcard(const char *protocol_id, PurpleGroup *group, GList *list, const char *alias) { GList *l; @@ -2119,7 +2116,7 @@ gc = (PurpleConnection *)l->data; account = purple_connection_get_account(gc); - if (!strcmp(purple_account_get_protocol_id(account), prpl_id)) + if (!strcmp(purple_account_get_protocol_id(account), protocol_id)) break; account = NULL; @@ -2318,7 +2315,7 @@ } protocol = - PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->list_icon(purple_buddy_get_account(buddy), + purple_connection_get_protocol_info(gc)->list_icon(purple_buddy_get_account(buddy), buddy); str = g_string_new(NULL); @@ -2672,7 +2669,7 @@ PurpleAccount *account = NULL; PurpleContact *contact = NULL; PurpleStoredImage *custom_img; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; gint orig_width, orig_height, scale_width, scale_height; if (PURPLE_IS_CONTACT(node)) { @@ -2695,7 +2692,7 @@ } if(account && purple_account_get_connection(account)) { - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(purple_account_get_connection(account))); + protocol = purple_connection_get_protocol_info(purple_account_get_connection(account)); } #if 0 @@ -2771,8 +2768,8 @@ scale_width = orig_width = gdk_pixbuf_get_width(buf); scale_height = orig_height = gdk_pixbuf_get_height(buf); - if (prpl_info && prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_DISPLAY) - purple_buddy_icon_get_scale_size(&prpl_info->icon_spec, &scale_width, &scale_height); + if (protocol && protocol->icon_spec.scale_rules & PURPLE_ICON_SCALE_DISPLAY) + purple_buddy_icon_get_scale_size(&protocol->icon_spec, &scale_width, &scale_height); if (scaled || scale_height > 200 || scale_width > 200) { GdkPixbuf *tmpbuf; @@ -2837,14 +2834,14 @@ #define TOOLTIP_BORDER 12 #define SMALL_SPACE 6 #define LARGE_SPACE 12 -#define PRPL_SIZE 16 +#define PROTOCOL_SIZE 16 struct tooltip_data { PangoLayout *layout; PangoLayout *name_layout; - GdkPixbuf *prpl_icon; + GdkPixbuf *protocol_icon; GdkPixbuf *status_icon; GdkPixbuf *avatar; - gboolean avatar_is_prpl_icon; + gboolean avatar_is_protocol_icon; int avatar_width; int avatar_height; int name_height; @@ -2875,8 +2872,8 @@ static struct tooltip_data * create_tip_for_account(PurpleAccount *account) { struct tooltip_data *td = g_new0(struct tooltip_data, 1); - td->status_icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); - /* Yes, status_icon, not prpl_icon */ + td->status_icon = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL); + /* Yes, status_icon, not protocol_icon */ if (purple_account_is_disconnected(account)) gdk_pixbuf_saturate_and_pixelate(td->status_icon, td->status_icon, 0.0, FALSE); td->layout = create_pango_layout(purple_account_get_username(account), &td->width, &td->height); @@ -2900,7 +2897,7 @@ td->status_icon = pidgin_blist_get_status_icon(node, PIDGIN_STATUS_ICON_LARGE); td->avatar = pidgin_blist_get_buddy_icon(node, !full, FALSE); if (account != NULL) { - td->prpl_icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); + td->protocol_icon = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL); } tooltip_text = pidgin_get_tooltip_text(node, full); if (tooltip_text && *tooltip_text) { @@ -2924,12 +2921,12 @@ g_free(tmp); td->name_layout = create_pango_layout(node_name, &td->name_width, &td->name_height); - td->name_width += SMALL_SPACE + PRPL_SIZE; - td->name_height = MAX(td->name_height, PRPL_SIZE + SMALL_SPACE); + td->name_width += SMALL_SPACE + PROTOCOL_SIZE; + td->name_height = MAX(td->name_height, PROTOCOL_SIZE + SMALL_SPACE); #if 0 /* PRPL Icon as avatar */ if(!td->avatar && full) { - td->avatar = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_LARGE); - td->avatar_is_prpl_icon = TRUE; + td->avatar = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_LARGE); + td->avatar_is_protocol_icon = TRUE; } #endif @@ -2955,7 +2952,7 @@ int max_text_width; int max_avatar_width; GList *l; - int prpl_col = 0; + int protocol_col = 0; GtkTextDirection dir = gtk_widget_get_direction(widget); int status_size = 0; @@ -2985,9 +2982,9 @@ max_width = TOOLTIP_BORDER + status_size + SMALL_SPACE + max_text_width + SMALL_SPACE + max_avatar_width + TOOLTIP_BORDER; if (dir == GTK_TEXT_DIR_RTL) - prpl_col = TOOLTIP_BORDER + max_avatar_width + SMALL_SPACE; + protocol_col = TOOLTIP_BORDER + max_avatar_width + SMALL_SPACE; else - prpl_col = TOOLTIP_BORDER + status_size + SMALL_SPACE + max_text_width - PRPL_SIZE; + protocol_col = TOOLTIP_BORDER + status_size + SMALL_SPACE + max_text_width - PROTOCOL_SIZE; current_height = 12; for(l = gtkblist->tooltipdata; l; l = l->next) @@ -3054,10 +3051,10 @@ } } - if (!td->avatar_is_prpl_icon && td->prpl_icon) { - gdk_cairo_set_source_pixbuf(cr, td->prpl_icon, prpl_col, + if (!td->avatar_is_protocol_icon && td->protocol_icon) { + gdk_cairo_set_source_pixbuf(cr, td->protocol_icon, protocol_col, current_height + - (td->name_height - PRPL_SIZE) / 2); + (td->name_height - PROTOCOL_SIZE) / 2); cairo_paint(cr); } @@ -3131,8 +3128,8 @@ g_object_unref(td->avatar); if(td->status_icon) g_object_unref(td->status_icon); - if(td->prpl_icon) - g_object_unref(td->prpl_icon); + if(td->protocol_icon) + g_object_unref(td->protocol_icon); if (td->layout) g_object_unref(td->layout); if (td->name_layout) @@ -3521,14 +3518,13 @@ PurpleConnection *gc = purple_account_get_connection(account); if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOODS) { - PurplePluginProtocolInfo *prpl_info = - PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + PurpleProtocol *protocol = purple_connection_get_protocol_info(gc); PurpleMood *mood = NULL; /* PURPLE_CONNECTION_FLAG_SUPPORT_MOODS would not be set if the prpl doesn't * have get_moods, so using PURPLE_PROTOCOL_PLUGIN_HAS_FUNC isn't necessary * here */ - for (mood = prpl_info->get_moods(account) ; + for (mood = protocol->get_moods(account) ; mood->mood != NULL ; mood++) { int mood_count = GPOINTER_TO_INT(g_hash_table_lookup(mood_counts, mood->mood)); @@ -3607,7 +3603,7 @@ PurpleRequestFieldGroup *g; PurpleRequestField *f; PurpleConnection *gc = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; PurpleMood *mood; PurpleMood *global_moods = get_global_moods(); @@ -3615,8 +3611,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(purple_connection_get_prpl(gc) != NULL); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + g_return_if_fail(purple_connection_get_protocol_info(gc) != NULL); + protocol = purple_connection_get_protocol_info(gc); current_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME); } else { current_mood = get_global_mood_status(); @@ -3632,8 +3628,8 @@ /* TODO: rlaager wants this sorted. */ /* TODO: darkrain wants it sorted post-translation */ - if (account && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods)) - mood = prpl_info->get_moods(account); + if (account && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, get_moods)) + mood = protocol->get_moods(account); else mood = global_moods; for ( ; mood->mood != NULL ; mood++) { @@ -3804,8 +3800,7 @@ static char *pidgin_get_tooltip_text(PurpleBlistNode *node, gboolean full) { GString *str = g_string_new(""); - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; char *tmp; if (PURPLE_IS_CHAT(node)) @@ -3819,8 +3814,7 @@ PidginBlistNode *bnode = purple_blist_node_get_ui_data(node); chat = (PurpleChat *)node; - prpl = purple_find_prpl(purple_account_get_protocol_id(purple_chat_get_account(chat))); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_find_protocol_info(purple_account_get_protocol_id(purple_chat_get_account(chat))); connections = purple_connections_get_all(); if (connections && connections->next) @@ -3834,8 +3828,8 @@ conv = PURPLE_CHAT_CONVERSATION(bnode->conv.conv); } else { char *chat_name; - if (prpl_info && prpl_info->get_chat_name) - chat_name = prpl_info->get_chat_name(purple_chat_get_components(chat)); + if (protocol && protocol->get_chat_name) + chat_name = protocol->get_chat_name(purple_chat_get_components(chat)); else chat_name = g_strdup(purple_chat_get_name(chat)); @@ -3848,7 +3842,7 @@ g_string_append_printf(str, _("\n<b>Occupants:</b> %d"), g_list_length(purple_chat_conversation_get_users(conv))); - if (prpl_info && (prpl_info->options & OPT_PROTO_CHAT_TOPIC)) { + if (protocol && (protocol->options & OPT_PROTO_CHAT_TOPIC)) { const char *chattopic = purple_chat_conversation_get_topic(conv); char *topic = chattopic ? g_markup_escape_text(chattopic, -1) : NULL; g_string_append_printf(str, _("\n<b>Topic:</b> %s"), topic ? topic : _("(no topic set)")); @@ -3856,8 +3850,8 @@ } } - if (prpl_info && prpl_info->chat_info != NULL) - cur = prpl_info->chat_info(purple_account_get_connection(purple_chat_get_account(chat))); + if (protocol && protocol->chat_info != NULL) + cur = protocol->chat_info(purple_account_get_connection(purple_chat_get_account(chat))); else cur = NULL; @@ -3908,8 +3902,7 @@ c = purple_buddy_get_contact(b); } - prpl = purple_find_prpl(purple_account_get_protocol_id(purple_buddy_get_account(b))); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + protocol = purple_find_protocol_info(purple_account_get_protocol_id(purple_buddy_get_account(b))); presence = purple_buddy_get_presence(b); user_info = purple_notify_user_info_new(); @@ -4018,10 +4011,10 @@ } if (purple_account_is_connected(purple_buddy_get_account(b)) && - prpl_info && prpl_info->tooltip_text) + protocol && protocol->tooltip_text) { /* Additional text from the PRPL */ - prpl_info->tooltip_text(b, user_info, full); + protocol->tooltip_text(b, user_info, full); } /* These are Easter Eggs. Patches to remove them will be rejected. */ @@ -4108,8 +4101,7 @@ { PurpleBuddy *buddy = NULL; struct _pidgin_blist_node *gtknode = purple_blist_node_get_ui_data(node); - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; const char *name = NULL; char *filename, *path; PurplePresence *p = NULL; @@ -4133,7 +4125,7 @@ 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(purple_buddy_get_account((PurpleBuddy*)node), PIDGIN_PRPL_ICON_SMALL); + return pidgin_create_protocol_icon(purple_buddy_get_account((PurpleBuddy*)node), PIDGIN_PROTOCOL_ICON_SMALL); } } else { return NULL; @@ -4177,13 +4169,12 @@ return _pidgin_blist_get_cached_emblem(path); } - prpl = purple_find_prpl(purple_account_get_protocol_id(purple_buddy_get_account(buddy))); - if (!prpl) + protocol = purple_find_protocol_info(purple_account_get_protocol_id(purple_buddy_get_account(buddy))); + if (!protocol) return NULL; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (prpl_info && prpl_info->list_emblem) - name = prpl_info->list_emblem(buddy); + if (protocol->list_emblem) + name = protocol->list_emblem(buddy); if (name == NULL) { PurpleStatus *status; @@ -4238,15 +4229,15 @@ if(buddy || chat) { PurpleAccount *account; - PurplePlugin *prpl; + PurpleProtocol *protocol; if(buddy) account = purple_buddy_get_account(buddy); else account = purple_chat_get_account(chat); - prpl = purple_find_prpl(purple_account_get_protocol_id(account)); - if(!prpl) + protocol = purple_find_protocol_info(purple_account_get_protocol_id(account)); + if(!protocol) return NULL; } @@ -4329,8 +4320,7 @@ { const char *name, *name_color, *name_font, *status_color, *status_font; char *text = NULL; - PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; PurpleContact *contact; PurplePresence *presence; struct _pidgin_blist_node *gtkcontactnode = NULL; @@ -4379,13 +4369,10 @@ if (!aliased || biglist) { /* Status Info */ - 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 && purple_account_get_connection(purple_buddy_get_account(b))) { - char *tmp = prpl_info->status_text(b); + protocol = purple_find_protocol_info(purple_account_get_protocol_id(purple_buddy_get_account(b))); + + if (protocol && protocol->status_text && purple_account_get_connection(purple_buddy_get_account(b))) { + char *tmp = protocol->status_text(b); const char *end; if(tmp && !g_utf8_validate(tmp, -1, &end)) { @@ -5183,13 +5170,13 @@ } static void -pack_prpl_icon_start(GtkWidget *box, +pack_protocol_icon_start(GtkWidget *box, PurpleAccount *account) { GdkPixbuf *pixbuf; GtkWidget *image; - pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); + pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL); if (pixbuf != NULL) { image = gtk_image_new_from_pixbuf(pixbuf); g_object_unref(pixbuf); @@ -5449,7 +5436,7 @@ hbox = gtk_hbox_new(FALSE, 6); g_object_set_data(G_OBJECT(hbox), OBJECT_DATA_KEY_ACCOUNT, account); - pack_prpl_icon_start(hbox, account); + pack_protocol_icon_start(hbox, account); label = gtk_label_new(NULL); markup = g_strdup_printf("<span size=\"smaller\">%s</span>", username); @@ -6689,7 +6676,7 @@ static void buddy_node(PurpleBuddy *buddy, GtkTreeIter *iter, PurpleBlistNode *node) { PurplePresence *presence = purple_buddy_get_presence(buddy); - GdkPixbuf *status, *avatar, *emblem, *prpl_icon; + GdkPixbuf *status, *avatar, *emblem, *protocol_icon; GdkColor *color = NULL; char *mark; char *idle = NULL; @@ -6758,7 +6745,7 @@ } } - prpl_icon = pidgin_create_prpl_icon(purple_buddy_get_account(buddy), PIDGIN_PRPL_ICON_SMALL); + protocol_icon = pidgin_create_protocol_icon(purple_buddy_get_account(buddy), PIDGIN_PROTOCOL_ICON_SMALL); if (theme != NULL) color = pidgin_blist_theme_get_contact_color(theme); @@ -6773,7 +6760,7 @@ BUDDY_ICON_VISIBLE_COLUMN, biglist, EMBLEM_COLUMN, emblem, EMBLEM_VISIBLE_COLUMN, (emblem != NULL), - PROTOCOL_ICON_COLUMN, prpl_icon, + PROTOCOL_ICON_COLUMN, protocol_icon, PROTOCOL_ICON_VISIBLE_COLUMN, purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons"), BGCOLOR_COLUMN, color, CONTACT_EXPANDER_COLUMN, NULL, @@ -6789,8 +6776,8 @@ g_object_unref(status); if(avatar) g_object_unref(avatar); - if(prpl_icon) - g_object_unref(prpl_icon); + if(protocol_icon) + g_object_unref(protocol_icon); } /* This is a variation on the original gtk_blist_update_contact. Here we @@ -6939,7 +6926,7 @@ if(purple_account_is_connected(purple_chat_get_account(chat))) { GtkTreeIter iter; - GdkPixbuf *status, *avatar, *emblem, *prpl_icon; + GdkPixbuf *status, *avatar, *emblem, *protocol_icon; const gchar *color, *font; gchar *mark, *tmp; gboolean showicons = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"); @@ -7001,7 +6988,7 @@ g_free(mark); mark = tmp; - prpl_icon = pidgin_create_prpl_icon(purple_chat_get_account(chat), PIDGIN_PRPL_ICON_SMALL); + protocol_icon = pidgin_create_protocol_icon(purple_chat_get_account(chat), PIDGIN_PROTOCOL_ICON_SMALL); if (theme != NULL) bgcolor = pidgin_blist_theme_get_contact_color(theme); @@ -7013,7 +7000,7 @@ BUDDY_ICON_VISIBLE_COLUMN, showicons, EMBLEM_COLUMN, emblem, EMBLEM_VISIBLE_COLUMN, emblem != NULL, - PROTOCOL_ICON_COLUMN, prpl_icon, + PROTOCOL_ICON_COLUMN, protocol_icon, PROTOCOL_ICON_VISIBLE_COLUMN, purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons"), NAME_COLUMN, mark, BGCOLOR_COLUMN, bgcolor, @@ -7027,8 +7014,8 @@ g_object_unref(status); if(avatar) g_object_unref(avatar); - if(prpl_icon) - g_object_unref(prpl_icon); + if(protocol_icon) + g_object_unref(protocol_icon); } else { pidgin_blist_hide_node(list, node, TRUE); @@ -7166,8 +7153,7 @@ PidginAddBuddyData *data) { PurpleConnection *pc = NULL; - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; gboolean invite_enabled = TRUE; /* Save our account */ @@ -7176,10 +7162,8 @@ if (account) pc = purple_account_get_connection(account); if (pc) - prpl = purple_connection_get_prpl(pc); - if (prpl) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (prpl_info && !(prpl_info->options & OPT_PROTO_INVITE_MESSAGE)) + protocol = purple_connection_get_protocol_info(pc); + if (protocol && !(protocol->options & OPT_PROTO_INVITE_MESSAGE)) invite_enabled = FALSE; gtk_widget_set_sensitive(data->entry_for_invite, invite_enabled); @@ -7429,13 +7413,13 @@ GList *l; PurpleConnection *gc; GtkBox *vbox; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; if (account != NULL) { gc = purple_account_get_connection(account); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - - if (prpl_info->join_chat == NULL) { + protocol = purple_connection_get_protocol_info(gc); + + if (protocol->join_chat == NULL) { purple_notify_error(gc, NULL, _("This protocol does not support chat rooms."), NULL); return; } @@ -7443,9 +7427,9 @@ /* Find an account with chat capabilities */ for (l = purple_connections_get_all(); l != NULL; l = l->next) { gc = (PurpleConnection *)l->data; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - - if (prpl_info->join_chat != NULL) { + protocol = purple_connection_get_protocol_info(gc); + + if (protocol->join_chat != NULL) { account = purple_connection_get_account(gc); break; } @@ -8124,21 +8108,24 @@ static void build_plugin_actions(GtkActionGroup *action_group, GString *ui, char *parent, - PurplePlugin *plugin, gpointer context) + PurplePlugin *plugin) { GtkAction *menuaction; + PurplePluginGetActionsCallback get_actions; PurplePluginAction *action = NULL; GList *actions, *l; char *name; int count = 0; - actions = PURPLE_PLUGIN_ACTIONS(plugin, context); + get_actions = + purple_plugin_info_get_actions_callback(purple_plugin_get_info(plugin)); + + actions = get_actions(plugin); for (l = actions; l != NULL; l = l->next) { if (l->data) { action = (PurplePluginAction *)l->data; action->plugin = plugin; - action->context = context; name = g_strdup_printf("%s-action-%d", parent, count++); menuaction = gtk_action_new(name, action->label, NULL, NULL); @@ -8186,6 +8173,13 @@ purple_account_set_enabled(account, PIDGIN_UI, FALSE); } +static void +protocol_act(GtkWidget *obj, PurpleProtocolAction *pam) +{ + if (pam && pam->callback) + pam->callback(pam); +} + void pidgin_blist_update_accounts_menu(void) { @@ -8234,7 +8228,7 @@ menuitem = gtk_image_menu_item_new_with_label(buf); g_free(buf); - pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); + pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL); if (pixbuf != NULL) { if (!purple_account_is_connected(account)) gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE); @@ -8267,8 +8261,7 @@ PurpleConnection *gc = NULL; PurpleAccount *account = NULL; GdkPixbuf *pixbuf = NULL; - PurplePlugin *plugin = NULL; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; account = accounts->data; @@ -8281,7 +8274,7 @@ accel_path_buf = g_strconcat("<Actions>/AccountActions/", buf, NULL); g_free(buf); - pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); + pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL); if (pixbuf != NULL) { if (!purple_account_is_connected(account)) gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, @@ -8308,13 +8301,13 @@ pidgin_separator(submenu); gc = purple_account_get_connection(account); - 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) && + protocol = gc && PURPLE_CONNECTION_IS_CONNECTED(gc) ? + purple_connection_get_protocol_info(gc) : NULL; + + if (protocol && + (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, get_moods) || + PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, get_actions))) { + if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, get_moods) && (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOODS)) { if (purple_account_get_status(account, "mood")) { @@ -8325,29 +8318,28 @@ } } - if (PURPLE_PLUGIN_HAS_ACTIONS(plugin)) { + if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, get_actions)) { GtkWidget *menuitem; - PurplePluginAction *action = NULL; + PurpleProtocolAction *action = NULL; GList *actions, *l; - actions = PURPLE_PLUGIN_ACTIONS(plugin, gc); + actions = protocol->get_actions(gc); for (l = actions; l != NULL; l = l->next) { if (l->data) { - action = (PurplePluginAction *) l->data; - action->plugin = plugin; - action->context = gc; + action = (PurpleProtocolAction *) l->data; + action->connection = 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", + G_CALLBACK(protocol_act), action); + g_object_set_data_full(G_OBJECT(menuitem), "protocol_action", action, - (GDestroyNotify)purple_plugin_action_free); + (GDestroyNotify)purple_protocol_action_free); gtk_widget_show(menuitem); } else @@ -8380,6 +8372,7 @@ pidgin_blist_update_plugin_actions(void) { PurplePlugin *plugin = NULL; + PurplePluginInfo *info; GList *l; GtkAction *action; @@ -8408,19 +8401,17 @@ char *name; plugin = (PurplePlugin *)l->data; - - if (PURPLE_IS_PROTOCOL_PLUGIN(plugin)) - continue; - - if (!PURPLE_PLUGIN_HAS_ACTIONS(plugin)) + info = purple_plugin_get_info(plugin); + + if (!purple_plugin_info_get_actions_callback(info)) continue; name = g_strdup_printf("plugin%d", count); - action = gtk_action_new(name, plugin->info->name, NULL, NULL); + action = gtk_action_new(name, purple_plugin_info_get_name(info), NULL, NULL); gtk_action_group_add_action(plugins_action_group, action); g_string_append_printf(plugins_ui, "<menu action='%s'>", name); - build_plugin_actions(plugins_action_group, plugins_ui, name, plugin, NULL); + build_plugin_actions(plugins_action_group, plugins_ui, name, plugin); g_string_append(plugins_ui, "</menu>"); count++;
--- a/pidgin/gtkconv-theme-loader.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkconv-theme-loader.c Sun Aug 18 01:53:00 2013 +0530 @@ -26,6 +26,7 @@ #include "xmlnode.h" #include "debug.h" +#include "prefs.h" /***************************************************************************** * Conversation Theme Builder
--- a/pidgin/gtkconv.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkconv.c Sun Aug 18 01:53:00 2013 +0530 @@ -43,7 +43,8 @@ #include "imgstore.h" #include "log.h" #include "notify.h" -#include "prpl.h" +#include "plugins.h" +#include "protocol.h" #include "request.h" #include "theme-loader.h" #include "theme-manager.h" @@ -186,7 +187,7 @@ static GList *busy_list = NULL; static GList *xa_list = NULL; static GList *offline_list = NULL; -static GHashTable *prpl_lists = NULL; +static GHashTable *protocol_lists = NULL; static PurpleTheme *default_conv_theme = NULL; @@ -384,7 +385,9 @@ const GList *plugins = purple_plugins_get_loaded(); if (plugins) { for (; plugins; plugins = plugins->next) { - str = g_string_append(str, purple_plugin_get_name(plugins->data)); + PurplePluginInfo *info = purple_plugin_get_info(PURPLE_PLUGIN(plugins->data)); + str = g_string_append(str, purple_plugin_info_get_name(info)); + if (plugins->next) str = g_string_append(str, ", "); } @@ -552,13 +555,13 @@ break; case PURPLE_CMD_STATUS_NOT_FOUND: { - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; PurpleConnection *gc; 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)) { + protocol = purple_connection_get_protocol_info(gc); + + if ((protocol != NULL) && (protocol->options & OPT_PROTO_SLASH_COMMANDS_NATIVE)) { char *spaceslash; /* If the first word in the entered text has a '/' in it, then the user @@ -595,7 +598,7 @@ PURPLE_MESSAGE_NO_LOG, time(NULL)); retval = TRUE; break; - case PURPLE_CMD_STATUS_WRONG_PRPL: + case PURPLE_CMD_STATUS_WRONG_PROTOCOL: purple_conversation_write(conv, "", _("That command doesn't work on this protocol."), PURPLE_MESSAGE_NO_LOG, time(NULL)); retval = TRUE; @@ -1184,7 +1187,7 @@ PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win); PurpleAccount *account = purple_conversation_get_account(conv); - purple_prpl_initiate_media(account, + purple_protocol_initiate_media(account, purple_conversation_get_name(conv), action == win->menu.audio_call ? PURPLE_MEDIA_AUDIO : action == win->menu.video_call ? PURPLE_MEDIA_VIDEO : @@ -1217,7 +1220,7 @@ 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_protocol_send_attention(purple_conversation_get_connection(conv), purple_conversation_get_name(conv), index); } } @@ -1474,7 +1477,7 @@ PurpleConversation *conv = gtkconv->active_conv; PurpleAccount *account; PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; gchar *real_who = NULL; account = purple_conversation_get_account(conv); @@ -1483,10 +1486,10 @@ gc = purple_account_get_connection(account); g_return_if_fail(gc != NULL); - 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, + protocol = purple_connection_get_protocol_info(gc); + + if (protocol && protocol->get_cb_real_name) + real_who = protocol->get_cb_real_name(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv)), who); if(!who && !real_who) @@ -1529,7 +1532,7 @@ static void menu_chat_send_file_cb(GtkWidget *w, PidginConversation *gtkconv) { - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; PurpleConversation *conv = gtkconv->active_conv; const char *who = g_object_get_data(G_OBJECT(w), "user_data"); PurpleConnection *gc = purple_conversation_get_connection(conv); @@ -1537,10 +1540,10 @@ g_return_if_fail(gc != NULL); - 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, + protocol = purple_connection_get_protocol_info(gc); + + if (protocol && protocol->get_cb_real_name) + real_who = protocol->get_cb_real_name(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv)), who); serv_send_file(gc, real_who ? real_who : who, NULL); @@ -1628,7 +1631,7 @@ create_chat_menu(PurpleChatConversation *chat, const char *who, PurpleConnection *gc) { static GtkWidget *menu = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; PurpleConversation *conv = PURPLE_CONVERSATION(chat); PurpleAccount *account = purple_conversation_get_account(conv); gboolean is_me = FALSE; @@ -1636,7 +1639,7 @@ PurpleBuddy *buddy = NULL; if (gc != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + protocol = purple_connection_get_protocol_info(gc); /* * If a menu already exists, destroy it before creating a new one, @@ -1660,7 +1663,7 @@ g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free); - if (prpl_info && prpl_info->send_file) + if (protocol && protocol->send_file) { gboolean can_receive_file = TRUE; @@ -1668,14 +1671,14 @@ PIDGIN_STOCK_TOOLBAR_SEND_FILE, G_CALLBACK(menu_chat_send_file_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL); - if (gc == NULL || prpl_info == NULL) + if (gc == NULL || protocol == NULL) can_receive_file = FALSE; else { gchar *real_who = NULL; - if (prpl_info->get_cb_real_name) - real_who = prpl_info->get_cb_real_name(gc, + if (protocol->get_cb_real_name) + real_who = protocol->get_cb_real_name(gc, purple_chat_conversation_get_id(chat), who); - if (!(!prpl_info->can_receive_file || prpl_info->can_receive_file(gc, real_who ? real_who : who))) + if (!(!protocol->can_receive_file || protocol->can_receive_file(gc, real_who ? real_who : who))) can_receive_file = FALSE; g_free(real_who); } @@ -1700,7 +1703,7 @@ g_object_set_data_full(G_OBJECT(button), "user_data", g_strdup(who), g_free); } - if (prpl_info && (prpl_info->get_info || prpl_info->get_cb_info)) { + if (protocol && (protocol->get_info || protocol->get_cb_info)) { button = pidgin_new_item_from_stock(menu, _("Info"), PIDGIN_STOCK_TOOLBAR_USER_INFO, G_CALLBACK(menu_chat_info_cb), PIDGIN_CONVERSATION(conv), 0, 0, NULL); @@ -1710,7 +1713,7 @@ 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 (!is_me && protocol && !(protocol->options & OPT_PROTO_UNIQUE_CHATNAME)) { if ((buddy = purple_blist_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); @@ -2450,21 +2453,21 @@ * A bunch of buddy icon functions **************************************************************************/ -static GList *get_prpl_icon_list(PurpleAccount *account) +static GList *get_protocol_icon_list(PurpleAccount *account) { GList *l = NULL; - PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account)); - PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - const char *prplname = prpl_info->list_icon(account, NULL); - l = g_hash_table_lookup(prpl_lists, prplname); + PurpleProtocol *protocol = + purple_find_protocol_info(purple_account_get_protocol_id(account)); + const char *prplname = protocol->list_icon(account, NULL); + l = g_hash_table_lookup(protocol_lists, prplname); if (l) return l; - l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_LARGE)); - l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM)); - l = g_list_prepend(l, pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL)); - - g_hash_table_insert(prpl_lists, g_strdup(prplname), l); + l = g_list_prepend(l, pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_LARGE)); + l = g_list_prepend(l, pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_MEDIUM)); + l = g_list_prepend(l, pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL)); + + g_hash_table_insert(protocol_lists, g_strdup(prplname), l); return l; } @@ -2501,7 +2504,7 @@ } } - return get_prpl_icon_list(account); + return get_protocol_icon_list(account); } static const char * @@ -2622,7 +2625,7 @@ g_object_unref(emblem); if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons")) { - emblem = pidgin_create_prpl_icon(purple_conversation_get_account(gtkconv->active_conv), PIDGIN_PRPL_ICON_SMALL); + emblem = pidgin_create_protocol_icon(purple_conversation_get_account(gtkconv->active_conv), PIDGIN_PROTOCOL_ICON_SMALL); } else { emblem = NULL; } @@ -3269,11 +3272,11 @@ 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)); - PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + PurpleProtocol *protocol = + purple_find_protocol_info(purple_account_get_protocol_id(account)); if (purple_account_get_connection(account) != NULL && - PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, chat_info_defaults)) { - components = prpl_info->chat_info_defaults(purple_account_get_connection(account), + PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, chat_info_defaults)) { + components = protocol->chat_info_defaults(purple_account_get_connection(account), purple_conversation_get_name(conv)); } else { components = g_hash_table_new_full(g_str_hash, g_str_equal, @@ -3359,7 +3362,7 @@ */ if (account != NULL && PURPLE_IS_IM_CONVERSATION(conv)) { PurpleMediaCaps caps = - purple_prpl_get_media_caps(account, + purple_protocol_get_media_caps(account, purple_conversation_get_name(conv)); gtk_action_set_sensitive(win->menu.audio_call, @@ -3391,8 +3394,7 @@ GtkWidget *menu; PurpleConversation *conv; PurpleConnection *pc; - PurplePlugin *prpl = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; GList *list; conv = pidgin_conv_window_get_active_conversation(win); @@ -3407,12 +3409,10 @@ 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)); + protocol = purple_connection_get_protocol_info(pc); + + if (protocol && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, get_attention_types)) { + list = protocol->get_attention_types(purple_connection_get_account(pc)); /* Multiple attention types */ if (list && list->next) { @@ -3922,7 +3922,7 @@ gchar *text; /* Create a pixmap for the protocol icon. */ - pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); + pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL); /* Now convert it to GtkImage */ if (pixbuf == NULL) @@ -4128,7 +4128,7 @@ PurpleConversation *conv; PidginChatPane *gtkchat; PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; GtkTreeModel *tm; GtkListStore *ls; GtkTreePath *newpath; @@ -4150,7 +4150,7 @@ gtkchat = gtkconv->u.chat; gc = purple_conversation_get_connection(conv); - if (!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)))) + if (!gc || !(protocol = purple_connection_get_protocol_info(gc))) return; tm = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); @@ -4455,7 +4455,7 @@ static void topic_callback(GtkWidget *w, PidginConversation *gtkconv) { - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; PurpleConnection *gc; PurpleConversation *conv = gtkconv->active_conv; PidginChatPane *gtkchat; @@ -4464,10 +4464,10 @@ gc = purple_conversation_get_connection(conv); - if(!gc || !(prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)))) + if(!gc || !(protocol = purple_connection_get_protocol_info(gc))) return; - if(prpl_info->set_chat_topic == NULL) + if(protocol->set_chat_topic == NULL) return; gtkconv = PIDGIN_CONVERSATION(conv); @@ -4485,7 +4485,7 @@ else gtk_entry_set_text(GTK_ENTRY(gtkchat->topic_text), ""); - prpl_info->set_chat_topic(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv)), + protocol->set_chat_topic(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv)), new_topic); g_free(new_topic); @@ -4535,7 +4535,7 @@ } static void -update_chat_alias(PurpleBuddy *buddy, PurpleChatConversation *chat, PurpleConnection *gc, PurplePluginProtocolInfo *prpl_info) +update_chat_alias(PurpleBuddy *buddy, PurpleChatConversation *chat, PurpleConnection *gc, PurpleProtocol *protocol) { PidginConversation *gtkconv = PIDGIN_CONVERSATION(PURPLE_CONVERSATION(chat)); PurpleAccount *account = purple_conversation_get_account(PURPLE_CONVERSATION(chat)); @@ -4599,7 +4599,7 @@ blist_node_aliased_cb(PurpleBlistNode *node, const char *old_alias, PurpleChatConversation *chat) { PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; PurpleConversation *conv = PURPLE_CONVERSATION(chat); g_return_if_fail(node != NULL); @@ -4607,10 +4607,10 @@ gc = purple_conversation_get_connection(conv); g_return_if_fail(gc != NULL); - 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) + g_return_if_fail(purple_connection_get_protocol_info(gc) != NULL); + protocol = purple_connection_get_protocol_info(gc); + + if (protocol->options & OPT_PROTO_UNIQUE_CHATNAME) return; if (PURPLE_IS_CONTACT(node)) @@ -4622,11 +4622,11 @@ if(!PURPLE_IS_BUDDY(bnode)) continue; - update_chat_alias((PurpleBuddy *)bnode, chat, gc, prpl_info); + update_chat_alias((PurpleBuddy *)bnode, chat, gc, protocol); } } else if (PURPLE_IS_BUDDY(node)) - update_chat_alias((PurpleBuddy *)node, chat, gc, prpl_info); + update_chat_alias((PurpleBuddy *)node, chat, gc, protocol); else if (PURPLE_IS_CHAT(node) && purple_conversation_get_account(conv) == purple_chat_get_account((PurpleChat*)node)) { @@ -4832,8 +4832,8 @@ { PurpleConversation *conv = gtkconv->active_conv; 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) + PurpleProtocol *protocol = purple_connection_get_protocol_info(gc); + if (protocol->options & OPT_PROTO_CHAT_TOPIC) { GtkWidget *hbox, *label; PidginChatPane *gtkchat = gtkconv->u.chat; @@ -4847,7 +4847,7 @@ gtkchat->topic_text = gtk_entry_new(); gtk_widget_set_size_request(gtkchat->topic_text, -1, BUDDYICON_SIZE_MIN); - if(prpl_info->set_chat_topic == NULL) { + if(protocol->set_chat_topic == NULL) { gtk_editable_set_editable(GTK_EDITABLE(gtkchat->topic_text), FALSE); } else { g_signal_connect(G_OBJECT(gtkchat->topic_text), "activate", @@ -4869,7 +4869,7 @@ GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkconv->u.chat->list)); PurpleConversation *conv = gtkconv->active_conv; PurpleBlistNode *node; - PurplePluginProtocolInfo *prpl_info; + PurpleProtocol *protocol; PurpleAccount *account = purple_conversation_get_account(conv); char *who = NULL; @@ -4881,9 +4881,9 @@ gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &who, -1); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(purple_account_get_connection(account))); + protocol = purple_connection_get_protocol_info(purple_account_get_connection(account)); node = (PurpleBlistNode*)(purple_blist_find_buddy(purple_conversation_get_account(conv), who)); - if (node && prpl_info && (prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) + if (node && protocol && (protocol->options & OPT_PROTO_UNIQUE_CHATNAME)) pidgin_blist_draw_tooltip(node, gtkconv->infopane); g_free(who); @@ -5513,7 +5513,7 @@ PurpleIMConversation *im; PurpleAccount *convaccount = purple_conversation_get_account(conv); PurpleConnection *gc = purple_account_get_connection(convaccount); - PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)) : NULL; + PurpleProtocol *protocol = gc ? purple_connection_get_protocol_info(gc) : NULL; const guchar *data = gtk_selection_data_get_data(sd); if (info == PIDGIN_DRAG_BLIST_NODE) @@ -5540,7 +5540,7 @@ * invite him to the chat. */ if (PURPLE_IS_CHAT_CONVERSATION(conv) && - prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, chat_invite) && + protocol && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, chat_invite) && strcmp(purple_account_get_protocol_id(convaccount), purple_account_get_protocol_id(buddyaccount)) == 0) { purple_chat_conversation_invite_user(PURPLE_CHAT_CONVERSATION(conv), buddyname, NULL, TRUE); @@ -5577,13 +5577,13 @@ } else if (info == PIDGIN_DRAG_IM_CONTACT) { - char *protocol = NULL; + char *protocol_id = NULL; char *username = NULL; PurpleAccount *account; PidginConversation *gtkconv; if (pidgin_parse_x_im_contact((const char *) data, FALSE, &account, - &protocol, &username, NULL)) + &protocol_id, &username, NULL)) { if (account == NULL) { @@ -5596,8 +5596,8 @@ * invite him to the chat. */ if (PURPLE_IS_CHAT_CONVERSATION(conv) && - prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, chat_invite) && - strcmp(purple_account_get_protocol_id(convaccount), protocol) == 0) { + protocol && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(protocol, chat_invite) && + strcmp(purple_account_get_protocol_id(convaccount), protocol_id) == 0) { purple_chat_conversation_invite_user(PURPLE_CHAT_CONVERSATION(conv), username, NULL, TRUE); } else { im = purple_im_conversation_new(account, username); @@ -5611,7 +5611,7 @@ } g_free(username); - g_free(protocol); + g_free(protocol_id); gtk_drag_finish(dc, TRUE, gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t); @@ -6527,7 +6527,7 @@ 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(purple_conversation_get_account(conv))))->options & + if (purple_find_protocol_info(purple_account_get_protocol_id(purple_conversation_get_account(conv)))->options & OPT_PROTO_USE_POINTSIZE) { gtk_font_options |= GTK_IMHTML_USE_POINTSIZE; } @@ -7127,7 +7127,7 @@ PidginWindow *win; PurpleConversation *conv = gtkconv->active_conv; PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; GdkPixbuf *window_icon = NULL; GtkWebViewButtons buttons; PurpleAccount *account; @@ -7137,7 +7137,7 @@ account = purple_conversation_get_account(conv); if (gc != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + protocol = purple_connection_get_protocol_info(gc); if (win->menu.send_to != NULL) update_send_to_selection(win); @@ -7234,7 +7234,7 @@ buttons = GTK_WEBVIEW_SMILEY | GTK_WEBVIEW_IMAGE; } - if (!(prpl_info->options & OPT_PROTO_IM_IMAGE) + if (!(protocol->options & OPT_PROTO_IM_IMAGE) && !(features & PURPLE_CONNECTION_FLAG_NO_IMAGES)) { features |= PURPLE_CONNECTION_FLAG_NO_IMAGES; purple_conversation_set_features(conv, features); @@ -7255,27 +7255,27 @@ /* Deal with menu items */ 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.get_info, (protocol->get_info != NULL)); + gtk_action_set_sensitive(win->menu.invite, (protocol->chat_invite != NULL)); gtk_action_set_sensitive(win->menu.insert_link, (features & PURPLE_CONNECTION_FLAG_HTML)); gtk_action_set_sensitive(win->menu.insert_image, !(features & PURPLE_CONNECTION_FLAG_NO_IMAGES)); if (PURPLE_IS_IM_CONVERSATION(conv)) { - 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.add, (protocol->add_buddy != NULL)); + gtk_action_set_sensitive(win->menu.remove, (protocol->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_action_set_sensitive(win->menu.get_attention, (prpl_info->send_attention != NULL)); + (protocol->send_file != NULL && (!protocol->can_receive_file || + protocol->can_receive_file(gc, purple_conversation_get_name(conv))))); + gtk_action_set_sensitive(win->menu.get_attention, (protocol->send_attention != NULL)); gtk_action_set_sensitive(win->menu.alias, (account != NULL) && (purple_blist_find_buddy(account, purple_conversation_get_name(conv)) != NULL)); } else { - 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.add, (protocol->join_chat != NULL)); + gtk_action_set_sensitive(win->menu.remove, (protocol->join_chat != NULL)); gtk_action_set_sensitive(win->menu.alias, (account != NULL) && (purple_blist_find_chat(account, purple_conversation_get_name(conv)) != NULL)); @@ -8186,10 +8186,10 @@ GHashTable *comps = NULL; PurpleChat *chat = purple_blist_find_chat(purple_conversation_get_account(conv), purple_conversation_get_name(conv)); if (chat == NULL) { - PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + PurpleProtocol *protocol = purple_connection_get_protocol_info(gc); - if (prpl_info->chat_info_defaults != NULL) - comps = prpl_info->chat_info_defaults(gc, purple_conversation_get_name(conv)); + if (protocol->chat_info_defaults != NULL) + comps = protocol->chat_info_defaults(gc, purple_conversation_get_name(conv)); } else { comps = purple_chat_get_components(chat); } @@ -8868,7 +8868,7 @@ #include "imgstore.h" #include "log.h" #include "notify.h" -#include "prpl.h" +#include "protocol.h" #include "request.h" #include "util.h" @@ -9740,12 +9740,12 @@ text = purple_buddy_get_contact_alias(buddy); } else { PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; gc = purple_conversation_get_connection(conv); if (gc != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - if (prpl_info && prpl_info->set_chat_topic == NULL) + protocol = purple_connection_get_protocol_info(gc); + if (protocol && protocol->set_chat_topic == NULL) /* This protocol doesn't support setting the chat room topic */ return FALSE; @@ -9870,7 +9870,7 @@ xa_list = make_status_icon_list(PIDGIN_STOCK_STATUS_XA, w); offline_list = make_status_icon_list(PIDGIN_STOCK_STATUS_OFFLINE, w); away_list = make_status_icon_list(PIDGIN_STOCK_STATUS_AWAY, w); - prpl_lists = g_hash_table_new(g_str_hash, g_str_equal); + protocol_lists = g_hash_table_new(g_str_hash, g_str_equal); } static void
--- a/pidgin/gtkdialogs.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkdialogs.c Sun Aug 18 01:53:00 2013 +0530 @@ -31,8 +31,8 @@ #include "debug.h" #include "notify.h" -#include "plugin.h" -#include "prpl.h" +#include "plugins.h" +#include "protocol.h" #include "request.h" #include "util.h" #include "core.h" @@ -686,12 +686,12 @@ g_string_append(str, "<dt>Network Security Services (NSS):</dt><dd>Disabled</dd>"); #endif - if (purple_plugins_find_with_id("core-perl") != NULL) + if (purple_plugins_find_plugin("core-perl") != NULL) g_string_append(str, "<dt>Perl:</dt><dd>Enabled</dd>"); else g_string_append(str, "<dt>Perl:</dt><dd>Disabled</dd>"); - if (purple_plugins_find_with_id("core-tcl") != NULL) { + if (purple_plugins_find_plugin("core-tcl") != NULL) { g_string_append(str, "<dt>Tcl:</dt><dd>Enabled</dd>"); #ifdef HAVE_TK g_string_append(str, "<dt>Tk:</dt><dd>Enabled</dd>"); @@ -828,47 +828,58 @@ void pidgin_dialogs_plugins_info(void) { GString *str; - GList *l = NULL; + GList *plugins, *l = NULL; PurplePlugin *plugin = NULL; + PurplePluginInfo *info; char *title = g_strdup_printf(_("%s Plugin Information"), PIDGIN_NAME); char *pname = NULL, *pauthor = NULL; - const char *pver, *pwebsite, *pid; - gboolean ploaded, punloadable; + const char *pver, *plicense, *pwebsite, *pid; + gboolean ploaded, ploadable; static GtkWidget *plugins_info = NULL; str = g_string_sized_new(4096); g_string_append_printf(str, "<h2>%s</h2><dl>", _("Plugin Information")); - for(l = purple_plugins_get_all(); l; l = l->next) { - plugin = (PurplePlugin *)l->data; + plugins = purple_plugins_find_all(); + + for(l = plugins; l; l = l->next) { + plugin = PURPLE_PLUGIN(l->data); + info = purple_plugin_get_info(plugin); - pname = g_markup_escape_text(purple_plugin_get_name(plugin), -1); - if ((pauthor = (char *)purple_plugin_get_author(plugin)) != NULL) + pname = g_markup_escape_text(purple_plugin_info_get_name(info), -1); + if ((pauthor = (char *)purple_plugin_info_get_author(info)) != 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); - punloadable = purple_plugin_is_unloadable(plugin); + pver = purple_plugin_info_get_version(info); + plicense = purple_plugin_info_get_license(info); + pwebsite = purple_plugin_info_get_website(info); + pid = purple_plugin_info_get_id(info); + ploadable = !purple_plugin_info_get_error(info); ploaded = purple_plugin_is_loaded(plugin); g_string_append_printf(str, "<dt>%s</dt><dd>" "<b>Author:</b> %s<br/>" "<b>Version:</b> %s<br/>" + "<b>License:</b> %s<br/>" "<b>Website:</b> %s<br/>" "<b>ID String:</b> %s<br/>" "<b>Loadable:</b> %s<br/>" "<b>Loaded:</b> %s" "</dd><br/>", - pname, pauthor ? pauthor : "(null)", - pver, pwebsite, pid, - punloadable ? "<span style=\"color: #FF0000;\"><b>No</b></span>" : "Yes", - ploaded ? "Yes" : "No"); + pname ? pname : "", + pauthor ? pauthor : "", + pver ? pver : "", + plicense ? plicense : "", + pwebsite ? pwebsite : "", + pid, + ploadable ? "Yes" : "<span style=\"color: #FF0000;\"><b>No</b></span>", + ploaded ? "Yes" : "No"); g_free(pname); g_free(pauthor); } + g_list_free(plugins); g_string_append(str, "</dl>"); @@ -896,15 +907,15 @@ { PurpleRequestFields *fields = _fields; PurpleAccount *account; - PurplePlugin *prpl; + PurpleProtocol *protocol; const char *username; gboolean valid; account = purple_request_fields_get_account(fields, "account"); - prpl = purple_find_prpl(purple_account_get_protocol_id(account)); + protocol = purple_find_protocol_info(purple_account_get_protocol_id(account)); username = purple_request_fields_get_string(fields, "screenname"); - valid = purple_validate(prpl, username); + valid = purple_validate(protocol, username); if (errmsg && !valid) *errmsg = g_strdup(_("Invalid username"));
--- a/pidgin/gtkdocklet.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkdocklet.c Sun Aug 18 01:53:00 2013 +0530 @@ -260,8 +260,8 @@ while(c != NULL) { PurpleConnection *gc = c->data; - PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - if (prpl_info != NULL && prpl_info->chat_info != NULL) + PurpleProtocol *protocol = purple_connection_get_protocol_info(gc); + if (protocol != NULL && protocol->chat_info != NULL) return TRUE; c = c->next; } @@ -297,7 +297,7 @@ docklet_signed_on_cb(PurpleConnection *gc) { if (!enable_join_chat) { - if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->chat_info != NULL) + if (purple_connection_get_protocol_info(gc)->chat_info != NULL) enable_join_chat = TRUE; } docklet_update_status(); @@ -307,7 +307,7 @@ docklet_signed_off_cb(PurpleConnection *gc) { if (enable_join_chat) { - if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->chat_info != NULL) + if (purple_connection_get_protocol_info(gc)->chat_info != NULL) enable_join_chat = online_account_supports_chat(); } docklet_update_status(); @@ -623,7 +623,6 @@ } - static void plugin_act(GtkWidget *widget, PurplePluginAction *pam) { @@ -632,14 +631,16 @@ } static void -build_plugin_actions(GtkWidget *menu, PurplePlugin *plugin, - gpointer context) +build_plugin_actions(GtkWidget *menu, PurplePlugin *plugin) { GtkWidget *menuitem; + PurplePluginGetActionsCallback get_actions; PurplePluginAction *action = NULL; GList *actions, *l; - actions = PURPLE_PLUGIN_ACTIONS(plugin, context); + get_actions = + purple_plugin_info_get_actions_callback(purple_plugin_get_info(plugin)); + actions = get_actions(plugin); for (l = actions; l != NULL; l = l->next) { @@ -647,7 +648,6 @@ { 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); @@ -672,6 +672,7 @@ { GtkWidget *menuitem, *submenu; PurplePlugin *plugin = NULL; + PurplePluginInfo *info; GList *l; int c = 0; @@ -679,21 +680,20 @@ /* Add a submenu for each plugin with custom actions */ for (l = purple_plugins_get_loaded(); l; l = l->next) { - plugin = (PurplePlugin *) l->data; + plugin = PURPLE_PLUGIN(l->data); + info = purple_plugin_get_info(plugin); - if (PURPLE_IS_PROTOCOL_PLUGIN(plugin)) + if (!purple_plugin_info_get_actions_callback(info)) continue; - if (!PURPLE_PLUGIN_HAS_ACTIONS(plugin)) - continue; - - menuitem = gtk_image_menu_item_new_with_label(_(plugin->info->name)); + menuitem = + gtk_image_menu_item_new_with_label(_(purple_plugin_info_get_name(info))); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); submenu = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); - build_plugin_actions(submenu, plugin, NULL); + build_plugin_actions(submenu, plugin); c++; }
--- a/pidgin/gtkft.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkft.c Sun Aug 18 01:53:00 2013 +0530 @@ -29,7 +29,7 @@ #include "debug.h" #include "notify.h" #include "ft.h" -#include "prpl.h" +#include "protocol.h" #include "util.h" #include "gtkft.h"
--- a/pidgin/gtkimhtmltoolbar.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkimhtmltoolbar.c Sun Aug 18 01:53:00 2013 +0530 @@ -927,7 +927,7 @@ 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); + purple_protocol_send_attention(gc, who, 0); gtk_widget_grab_focus(toolbar->imhtml); } @@ -1593,14 +1593,14 @@ PurpleConversation *conv) { PurpleConnection *gc = purple_conversation_get_connection(conv); - PurplePlugin *prpl = purple_connection_get_prpl(gc); + PurpleProtocol *protocol = purple_connection_get_protocol_info(gc); 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(toolbar->attention, - conv && prpl && PURPLE_IS_IM_CONVERSATION(conv) && - PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->send_attention != NULL); + conv && protocol && PURPLE_IS_IM_CONVERSATION(conv) && + protocol->send_attention != NULL); }
--- a/pidgin/gtklog.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtklog.c Sun Aug 18 01:53:00 2013 +0530 @@ -689,7 +689,7 @@ PidginLogViewer *lv = NULL; const char *name = buddyname; char *title; - GdkPixbuf *prpl_icon; + GdkPixbuf *protocol_icon; g_return_if_fail(account != NULL); g_return_if_fail(buddyname != NULL); @@ -727,14 +727,14 @@ title = g_strdup_printf(_("Conversations with %s"), name); } - prpl_icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM); + protocol_icon = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_MEDIUM); display_log_viewer(ht, purple_log_get_logs(type, buddyname, account), - title, gtk_image_new_from_pixbuf(prpl_icon), + title, gtk_image_new_from_pixbuf(protocol_icon), purple_log_get_total_size(type, buddyname, account)); - if (prpl_icon) - g_object_unref(prpl_icon); + if (protocol_icon) + g_object_unref(protocol_icon); g_free(title); } @@ -822,7 +822,7 @@ for(accounts = purple_accounts_get_all(); accounts != NULL; accounts = accounts->next) { PurpleAccount *account = (PurpleAccount *)accounts->data; - if(purple_find_prpl(purple_account_get_protocol_id(account)) == NULL) + if(purple_find_protocol_info(purple_account_get_protocol_id(account)) == NULL) continue; logs = g_list_concat(purple_log_get_system_logs(account), logs);
--- a/pidgin/gtkmain.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkmain.c Sun Aug 18 01:53:00 2013 +0530 @@ -35,7 +35,7 @@ #include "network.h" #include "notify.h" #include "prefs.h" -#include "prpl.h" +#include "protocol.h" #include "pounce.h" #include "sound.h" #include "status.h" @@ -757,17 +757,6 @@ purple_core_set_ui_ops(pidgin_core_get_ui_ops()); purple_eventloop_set_ui_ops(pidgin_eventloop_get_ui_ops()); - /* - * Set plugin search directories. Give priority to the plugins - * in user's home directory. - */ - search_path = g_build_filename(purple_user_dir(), "plugins", NULL); - if (!g_stat(search_path, &st)) - g_mkdir(search_path, S_IRUSR | S_IWUSR | S_IXUSR); - purple_plugins_add_search_path(search_path); - g_free(search_path); - purple_plugins_add_search_path(LIBDIR); - if (!purple_core_init(PIDGIN_UI)) { fprintf(stderr, "Initialization of the libpurple core failed. Dumping core.\n" @@ -778,6 +767,15 @@ abort(); } + search_path = g_build_filename(purple_user_dir(), "plugins", NULL); + if (!g_stat(search_path, &st)) + g_mkdir(search_path, S_IRUSR | S_IWUSR | S_IXUSR); + purple_plugins_add_search_path(search_path); + g_free(search_path); + + purple_plugins_add_search_path(LIBDIR); + purple_plugins_refresh(); + if (opt_si && !purple_core_ensure_single_instance()) { #ifdef HAVE_DBUS DBusConnection *conn = purple_dbus_get_connection();
--- a/pidgin/gtknotify.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtknotify.c Sun Aug 18 01:53:00 2013 +0530 @@ -674,7 +674,7 @@ if (clear) return NULL; - icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM); + icon = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_MEDIUM); if (new_n) { data = g_new0(PidginNotifyMailData, 1); @@ -931,7 +931,7 @@ gtk_list_store_clear(data->model); - pixbuf = pidgin_create_prpl_icon(purple_connection_get_account(gc), PIDGIN_PRPL_ICON_SMALL); + pixbuf = pidgin_create_protocol_icon(purple_connection_get_account(gc), PIDGIN_PROTOCOL_ICON_SMALL); for (row = results->rows; row != NULL; row = row->next) { @@ -1460,7 +1460,7 @@ if (pounce_dialog == NULL) pounce_dialog = pidgin_create_notification_dialog(PIDGIN_NOTIFY_POUNCE); - icon = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); + icon = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL); pounce_data = g_new(PidginNotifyPounceData, 1);
--- a/pidgin/gtkplugin.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkplugin.c Sun Aug 18 01:53:00 2013 +0530 @@ -37,10 +37,25 @@ #include "gtk3compat.h" +#define PIDGIN_PLUGIN_INFO_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), PIDGIN_TYPE_PLUGIN_INFO, PidginPluginInfoPrivate)) + #define PIDGIN_RESPONSE_CONFIGURE 98121 +typedef struct +{ + PidginPluginConfigFrame get_config_frame; +} PidginPluginInfoPrivate; + +enum +{ + PROP_0, + PROP_PIDGIN_CONFIG_FRAME, + PROP_LAST +}; + static void plugin_toggled_stage_two(PurplePlugin *plug, GtkTreeModel *model, - GtkTreeIter *iter, gboolean unload); + GtkTreeIter *iter, GError *error, gboolean unload); static GtkWidget *expander = NULL; static GtkWidget *plugin_dialog = NULL; @@ -56,47 +71,155 @@ static GtkWidget *pref_button = NULL; static GHashTable *plugin_pref_dialogs = NULL; +/* Set method for GObject properties */ +static void +pidgin_plugin_info_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *pspec) +{ + PidginPluginInfoPrivate *priv = PIDGIN_PLUGIN_INFO_GET_PRIVATE(obj); + + switch (param_id) { + case PROP_PIDGIN_CONFIG_FRAME: + priv->get_config_frame = g_value_get_pointer(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Get method for GObject properties */ +static void +pidgin_plugin_info_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PidginPluginInfoPrivate *priv = PIDGIN_PLUGIN_INFO_GET_PRIVATE(obj); + + switch (param_id) { + case PROP_PIDGIN_CONFIG_FRAME: + g_value_set_pointer(value, priv->get_config_frame); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +/* Class initializer function */ +static void pidgin_plugin_info_class_init(PidginPluginInfoClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + g_type_class_add_private(klass, sizeof(PidginPluginInfoPrivate)); + + /* Setup properties */ + obj_class->get_property = pidgin_plugin_info_get_property; + obj_class->set_property = pidgin_plugin_info_set_property; + + g_object_class_install_property(obj_class, PROP_PIDGIN_CONFIG_FRAME, + g_param_spec_pointer("pidgin-config-frame", + "Pidgin configuration frame callback", + "Callback that returns a GTK configuration frame", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + +GType +pidgin_plugin_info_get_type(void) +{ + static GType type = 0; + + if (G_UNLIKELY(type == 0)) { + static const GTypeInfo info = { + .class_size = sizeof(PidginPluginInfoClass), + .class_init = (GClassInitFunc)pidgin_plugin_info_class_init, + .instance_size = sizeof(PidginPluginInfo), + }; + + type = g_type_register_static(PURPLE_TYPE_PLUGIN_INFO, + "PidginPluginInfo", &info, 0); + } + + return type; +} + +PidginPluginInfo * +pidgin_plugin_info_new(const char *first_property, ...) +{ + GObject *info; + va_list var_args; + + /* at least ID is required */ + if (!first_property) + return NULL; + + va_start(var_args, first_property); + info = g_object_new_valist(PIDGIN_TYPE_PLUGIN_INFO, first_property, + var_args); + va_end(var_args); + + g_object_set(info, "ui-requirement", PIDGIN_UI, NULL); + + return PIDGIN_PLUGIN_INFO(info); +} + GtkWidget * pidgin_plugin_get_config_frame(PurplePlugin *plugin) { GtkWidget *config = NULL; + PurplePluginInfo *info; + PidginPluginInfoPrivate *priv = NULL; g_return_val_if_fail(plugin != NULL, NULL); - if (PIDGIN_IS_PIDGIN_PLUGIN(plugin) && plugin->info->ui_info - && PIDGIN_PLUGIN_UI_INFO(plugin)->get_config_frame) - { - PidginPluginUiInfo *ui_info; + info = purple_plugin_get_info(plugin); + if (PIDGIN_IS_PLUGIN_INFO(info)) + priv = PIDGIN_PLUGIN_INFO_GET_PRIVATE(info); - ui_info = PIDGIN_PLUGIN_UI_INFO(plugin); + if (priv && priv->get_config_frame) + { + config = priv->get_config_frame(plugin); - config = ui_info->get_config_frame(plugin); - - if (plugin->info->prefs_info - && plugin->info->prefs_info->get_plugin_pref_frame) + if (purple_plugin_info_get_pref_frame_callback(info)) { purple_debug_warning("gtkplugin", "Plugin %s contains both, ui_info and " "prefs_info preferences; prefs_info will be " - "ignored.", plugin->info->name); + "ignored.", + purple_plugin_info_get_name(info)); } } - - if (config == NULL && plugin->info->prefs_info - && plugin->info->prefs_info->get_plugin_pref_frame) + else if (purple_plugin_info_get_pref_frame_callback(info)) { PurplePluginPrefFrame *frame; + PurplePluginPrefFrameCallback get_pref_frame = + purple_plugin_info_get_pref_frame_callback(info); - frame = plugin->info->prefs_info->get_plugin_pref_frame(plugin); + frame = get_pref_frame(plugin); config = pidgin_plugin_pref_create_frame(frame); - - plugin->info->prefs_info->frame = frame; } return config; } +static gboolean +pidgin_plugin_has_config_frame(PurplePlugin *plugin) +{ + PurplePluginInfo *info = purple_plugin_get_info(plugin); + PidginPluginInfoPrivate *priv = NULL; + gboolean ret; + + g_return_val_if_fail(plugin != NULL, FALSE); + + if (PIDGIN_IS_PLUGIN_INFO(info)) + priv = PIDGIN_PLUGIN_INFO_GET_PRIVATE(info); + + ret = ((priv && priv->get_config_frame) || + purple_plugin_info_get_pref_frame_callback(info)); + + return ret; +} + void pidgin_plugins_save(void) { @@ -108,44 +231,38 @@ { GtkListStore *ls = GTK_LIST_STORE(data); GtkTreeIter iter; - GList *probes; + GList *plugins, *l; PurplePlugin *plug; + PurplePluginInfo *info; gtk_list_store_clear(ls); - purple_plugins_probe(G_MODULE_SUFFIX); + purple_plugins_refresh(); - for (probes = purple_plugins_get_all(); - probes != NULL; - probes = probes->next) + plugins = purple_plugins_find_all(); + + for (l = plugins; l != NULL; l = l->next) { char *name; char *version; char *summary; char *desc; - plug = probes->data; + plug = PURPLE_PLUGIN(l->data); + info = purple_plugin_get_info(plug); - if (plug->info->type == PURPLE_PLUGIN_LOADER) { - GList *cur; - for (cur = PURPLE_PLUGIN_LOADER_INFO(plug)->exts; cur != NULL; - cur = cur->next) - purple_plugins_probe(cur->data); + if (purple_plugin_is_internal(plug)) continue; - } else if (plug->info->type != PURPLE_PLUGIN_STANDARD || - (plug->info->flags & PURPLE_PLUGIN_FLAG_INVISIBLE)) { - continue; - } gtk_list_store_append (ls, &iter); - if (plug->info->name) { - name = g_markup_escape_text(_(plug->info->name), -1); + if (purple_plugin_info_get_name(info)) { + name = g_markup_escape_text(_(purple_plugin_info_get_name(info)), -1); } else { - char *tmp = g_path_get_basename(plug->path); + char *tmp = g_path_get_basename(purple_plugin_get_filename(plug)); name = g_markup_escape_text(tmp, -1); g_free(tmp); } - version = g_markup_escape_text(purple_plugin_get_version(plug), -1); - summary = g_markup_escape_text(purple_plugin_get_summary(plug), -1); + version = g_markup_escape_text(purple_plugin_info_get_version(info), -1); + summary = g_markup_escape_text(purple_plugin_info_get_summary(info), -1); desc = g_strdup_printf("<b>%s</b> %s\n%s", name, version, @@ -158,10 +275,11 @@ 0, purple_plugin_is_loaded(plug), 1, desc, 2, plug, - 3, purple_plugin_is_unloadable(plug), -1); g_free(desc); } + + g_list_free(plugins); } static void plugin_loading_common(PurplePlugin *plugin, GtkTreeView *view, gboolean loaded) @@ -190,11 +308,7 @@ if (plug == plugin) { gtk_widget_set_sensitive(pref_button, - loaded - && ((PIDGIN_IS_PIDGIN_PLUGIN(plug) && plug->info->ui_info - && PIDGIN_PLUGIN_UI_INFO(plug)->get_config_frame) - || (plug->info->prefs_info - && plug->info->prefs_info->get_plugin_pref_frame))); + loaded && pidgin_plugin_has_config_frame(plug)); } } @@ -227,11 +341,6 @@ } gtk_widget_destroy(d); - if (plug->info->prefs_info && plug->info->prefs_info->frame) { - purple_plugin_pref_frame_destroy(plug->info->prefs_info->frame); - plug->info->prefs_info->frame = NULL; - } - break; } } @@ -242,7 +351,7 @@ GtkTreeModel *model = (GtkTreeModel *)data[1]; GtkTreeIter *iter = (GtkTreeIter *)data[2]; - plugin_toggled_stage_two(plugin, model, iter, TRUE); + plugin_toggled_stage_two(plugin, model, iter, NULL, TRUE); g_free(data); } @@ -253,25 +362,19 @@ GtkTreeIter *iter = g_new(GtkTreeIter, 1); GtkTreePath *path = gtk_tree_path_new_from_string(pth); PurplePlugin *plug; + GError *error = NULL; GtkWidget *dialog = NULL; gtk_tree_model_get_iter(model, iter, path); gtk_tree_path_free(path); gtk_tree_model_get(model, iter, 2, &plug, -1); - /* Apparently, GTK+ won't honor the sensitive flag on cell renderers for booleans. */ - if (purple_plugin_is_unloadable(plug)) - { - g_free(iter); - return; - } - if (!purple_plugin_is_loaded(plug)) { pidgin_set_cursor(plugin_dialog, GDK_WATCH); - purple_plugin_load(plug); - plugin_toggled_stage_two(plug, model, iter, FALSE); + purple_plugin_load(plug, &error); + plugin_toggled_stage_two(plug, model, iter, error, FALSE); pidgin_clear_cursor(plugin_dialog); } @@ -281,19 +384,22 @@ (dialog = g_hash_table_lookup(plugin_pref_dialogs, plug))) pref_dialog_response_cb(dialog, GTK_RESPONSE_DELETE_EVENT, plug); - if (plug->dependent_plugins != NULL) + if (purple_plugin_get_dependent_plugins(plug) != NULL) { GString *tmp = g_string_new(_("The following plugins will be unloaded.")); - GList *l; + GSList *l; gpointer *cb_data; - for (l = plug->dependent_plugins ; l != NULL ; l = l->next) + for (l = purple_plugin_get_dependent_plugins(plug); l != NULL ; l = l->next) { const char *dep_name = (const char *)l->data; - PurplePlugin *dep_plugin = purple_plugins_find_with_id(dep_name); + PurplePlugin *dep_plugin = purple_plugins_find_plugin(dep_name); + PurplePluginInfo *dep_info; + g_return_if_fail(dep_plugin != NULL); - g_string_append_printf(tmp, "\n\t%s\n", purple_plugin_get_name(dep_plugin)); + dep_info = purple_plugin_get_info(dep_plugin); + g_string_append_printf(tmp, "\n\t%s\n", purple_plugin_info_get_name(dep_info)); } cb_data = g_new(gpointer, 3); @@ -311,31 +417,26 @@ g_string_free(tmp, TRUE); } else - plugin_toggled_stage_two(plug, model, iter, TRUE); + plugin_toggled_stage_two(plug, model, iter, NULL, TRUE); } } -static void plugin_toggled_stage_two(PurplePlugin *plug, GtkTreeModel *model, GtkTreeIter *iter, gboolean unload) +static void plugin_toggled_stage_two(PurplePlugin *plug, GtkTreeModel *model, GtkTreeIter *iter, GError *error, gboolean unload) { + PurplePluginInfo *info = purple_plugin_get_info(plug); + if (unload) { pidgin_set_cursor(plugin_dialog, GDK_WATCH); - if (!purple_plugin_unload(plug)) + if (!purple_plugin_unload(plug, &error)) { const char *primary = _("Could not unload plugin"); const char *reload = _("The plugin could not be unloaded now, but will be disabled at the next startup."); - if (!plug->error) - { - purple_notify_warning(NULL, NULL, primary, reload); - } - else - { - char *tmp = g_strdup_printf("%s\n\n%s", reload, plug->error); - purple_notify_warning(NULL, NULL, primary, tmp); - g_free(tmp); - } + char *tmp = g_strdup_printf("%s\n\n%s", reload, error->message); + purple_notify_warning(NULL, NULL, primary, tmp); + g_free(tmp); purple_plugin_disable(plug); } @@ -344,22 +445,19 @@ } gtk_widget_set_sensitive(pref_button, - purple_plugin_is_loaded(plug) - && ((PIDGIN_IS_PIDGIN_PLUGIN(plug) && plug->info->ui_info - && PIDGIN_PLUGIN_UI_INFO(plug)->get_config_frame) - || (plug->info->prefs_info - && plug->info->prefs_info->get_plugin_pref_frame))); + purple_plugin_is_loaded(plug) && pidgin_plugin_has_config_frame(plug)); - if (plug->error != NULL) + if (error != NULL) { - gchar *name = g_markup_escape_text(purple_plugin_get_name(plug), -1); + gchar *name = g_markup_escape_text(purple_plugin_info_get_name(info), -1); - gchar *error = g_markup_escape_text(plug->error, -1); + gchar *disp_error = g_markup_escape_text(error->message, -1); gchar *text; text = g_strdup_printf( "<b>%s</b> %s\n<span weight=\"bold\" color=\"red\"%s</span>", - purple_plugin_get_name(plug), purple_plugin_get_version(plug), error); + purple_plugin_info_get_name(info), + purple_plugin_info_get_version(info), disp_error); gtk_list_store_set(GTK_LIST_STORE (model), iter, 1, text, -1); @@ -367,12 +465,14 @@ text = g_strdup_printf( "<span weight=\"bold\" color=\"red\">%s</span>", - error); + disp_error); gtk_label_set_markup(plugin_error, text); g_free(text); - g_free(error); + g_free(disp_error); g_free(name); + + g_error_free(error); } gtk_list_store_set(GTK_LIST_STORE (model), iter, @@ -404,6 +504,7 @@ GtkTreeIter iter; GValue val; PurplePlugin *plug; + PurplePluginInfo *info; if (!gtk_tree_selection_get_selected (sel, &model, &iter)) { @@ -421,9 +522,10 @@ val.g_type = 0; gtk_tree_model_get_value (model, &iter, 2, &val); plug = g_value_get_pointer(&val); + info = purple_plugin_get_info(plug); - name = g_markup_escape_text(purple_plugin_get_name(plug), -1); - version = g_markup_escape_text(purple_plugin_get_version(plug), -1); + name = g_markup_escape_text(purple_plugin_info_get_name(info), -1); + version = g_markup_escape_text(purple_plugin_info_get_version(info), -1); buf = g_strdup_printf( "<span size=\"larger\" weight=\"bold\">%s</span> " "<span size=\"smaller\">%s</span>", @@ -433,12 +535,13 @@ g_free(version); g_free(buf); - gtk_text_buffer_set_text(plugin_desc, purple_plugin_get_description(plug), -1); - gtk_label_set_text(plugin_author, purple_plugin_get_author(plug)); - gtk_label_set_text(plugin_filename, plug->path); + gtk_text_buffer_set_text(plugin_desc, purple_plugin_info_get_description(info), -1); + gtk_label_set_text(plugin_author, purple_plugin_info_get_author(info)); + gtk_label_set_text(plugin_filename, purple_plugin_get_filename(plug)); g_free(plugin_website_uri); - plugin_website_uri = g_strdup(purple_plugin_get_homepage(plug)); + plugin_website_uri = g_strdup(purple_plugin_info_get_website(info)); + if (plugin_website_uri) { tmp = g_markup_escape_text(plugin_website_uri, -1); @@ -453,13 +556,13 @@ gtk_label_set_text(plugin_website, NULL); } - if (plug->error == NULL) + if (purple_plugin_info_get_error(info) == NULL) { gtk_label_set_text(plugin_error, NULL); } else { - tmp = g_markup_escape_text(plug->error, -1); + tmp = g_markup_escape_text(purple_plugin_info_get_error(info), -1); buf = g_strdup_printf( _("<span foreground=\"red\" weight=\"bold\">" "Error: %s\n" @@ -472,11 +575,7 @@ } gtk_widget_set_sensitive(pref_button, - purple_plugin_is_loaded(plug) - && ((PIDGIN_IS_PIDGIN_PLUGIN(plug) && plug->info->ui_info - && PIDGIN_PLUGIN_UI_INFO(plug)->get_config_frame) - || (plug->info->prefs_info - && plug->info->prefs_info->get_plugin_pref_frame))); + purple_plugin_is_loaded(plug) && pidgin_plugin_has_config_frame(plug)); /* Make sure the selected plugin is still visible */ g_idle_add(ensure_plugin_visible, sel); @@ -531,9 +630,11 @@ g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(pref_dialog_response_cb), plug); gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), box); gtk_window_set_role(GTK_WINDOW(dialog), "plugin_config"); - gtk_window_set_title(GTK_WINDOW(dialog), _(purple_plugin_get_name(plug))); + gtk_window_set_title(GTK_WINDOW(dialog), + _(purple_plugin_info_get_name(purple_plugin_get_info(plug)))); gtk_widget_show_all(dialog); g_value_unset(&val); + break; } } @@ -583,6 +684,7 @@ GtkTreeIter iter; GtkTreeView *treeview = GTK_TREE_VIEW(data); PurplePlugin *plugin = NULL; + PurplePluginInfo *info; GtkTreeModel *model = gtk_tree_view_get_model(treeview); PangoLayout *layout; int width, height; @@ -592,11 +694,12 @@ return FALSE; gtk_tree_model_get(model, &iter, 2, &plugin, -1); + info = purple_plugin_get_info(plugin); markup = g_strdup_printf("<span size='x-large' weight='bold'>%s</span>\n<b>%s:</b> %s\n<b>%s:</b> %s", - name = g_markup_escape_text(purple_plugin_get_name(plugin), -1), - _("Description"), desc = g_markup_escape_text(purple_plugin_get_description(plugin), -1), - _("Author"), author = g_markup_escape_text(purple_plugin_get_author(plugin), -1)); + name = g_markup_escape_text(purple_plugin_info_get_name(info), -1), + _("Description"), desc = g_markup_escape_text(purple_plugin_info_get_description(info), -1), + _("Author"), author = g_markup_escape_text(purple_plugin_info_get_author(info), -1)); layout = gtk_widget_create_pango_layout(tipwindow, NULL); pango_layout_set_markup(layout, markup, -1); @@ -734,7 +837,7 @@ gtk_widget_set_sensitive(pref_button, FALSE); gtk_window_set_role(GTK_WINDOW(plugin_dialog), "plugins"); - ls = gtk_list_store_new(4, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN); + ls = gtk_list_store_new(3, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_POINTER); gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(ls), 1, GTK_SORT_ASCENDING);
--- a/pidgin/gtkplugin.h Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkplugin.h Sun Aug 18 01:53:00 2013 +0530 @@ -27,36 +27,71 @@ #define _PIDGINPLUGIN_H_ #include "pidgin.h" -#include "plugin.h" +#include "plugins.h" -typedef struct _PidginPluginUiInfo PidginPluginUiInfo; +#define PIDGIN_TYPE_PLUGIN_INFO (pidgin_plugin_info_get_type()) +#define PIDGIN_PLUGIN_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PIDGIN_TYPE_PLUGIN_INFO, PidginPluginInfo)) +#define PIDGIN_PLUGIN_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PIDGIN_TYPE_PLUGIN_INFO, PidginPluginInfoClass)) +#define PIDGIN_IS_PLUGIN_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PIDGIN_TYPE_PLUGIN_INFO)) +#define PIDGIN_IS_PLUGIN_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PIDGIN_TYPE_PLUGIN_INFO)) +#define PIDGIN_PLUGIN_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PIDGIN_TYPE_PLUGIN_INFO, PidginPluginInfoClass)) + +/** @copydoc _PidginPluginInfo */ +typedef struct _PidginPluginInfo PidginPluginInfo; +/** @copydoc _PidginPluginInfoClass */ +typedef struct _PidginPluginInfoClass PidginPluginInfoClass; + +typedef GtkWidget *(*PidginPluginConfigFrame)(PurplePlugin *); /** - * A GTK+ UI structure for plugins. + * Extends #PurplePluginInfo to hold UI information for pidgin. */ -struct _PidginPluginUiInfo -{ - GtkWidget *(*get_config_frame)(PurplePlugin *plugin); +struct _PidginPluginInfo { + /*< private >*/ + PurplePluginInfo parent; +}; - int page_num; /**< Reserved */ +/** + * PidginPluginInfoClass: + * + * The base class for all #PidginPluginInfo's. + */ +struct _PidginPluginInfoClass { + /*< private >*/ + PurplePluginInfoClass parent_class; - /* padding */ void (*_pidgin_reserved1)(void); void (*_pidgin_reserved2)(void); void (*_pidgin_reserved3)(void); void (*_pidgin_reserved4)(void); }; -#define PIDGIN_PLUGIN_TYPE PIDGIN_UI +G_BEGIN_DECLS + +/** + * Returns the GType for the PidginPluginInfo object. + */ +GType pidgin_plugin_info_get_type(void); -#define PIDGIN_IS_PIDGIN_PLUGIN(plugin) \ - ((plugin)->info != NULL && (plugin)->info->ui_info != NULL && \ - !strcmp((plugin)->info->ui_requirement, PIDGIN_PLUGIN_TYPE)) - -#define PIDGIN_PLUGIN_UI_INFO(plugin) \ - ((PidginPluginUiInfo *)(plugin)->info->ui_info) - -G_BEGIN_DECLS +/** + * Creates a new #PidginPluginInfo instance to be returned from + * gplugin_plugin_query() of a pidgin plugin, using the provided name/value + * pairs. + * + * See purple_plugin_info_new() for a list of available property names. + * Additionally, you can provide the property "pidgin-config-frame", + * which should be a callback that returns a GtkWidget for the plugin's + * configuration (see PidginPluginConfigFrame). + * + * @param first_property The first property name + * @param ... The value of the first property, followed optionally by more + * name/value pairs, followed by @c NULL + * + * @return A new #PidginPluginInfo instance. + * + * @see purple_plugin_info_new() + */ +PidginPluginInfo *pidgin_plugin_info_new(const char *first_property, ...); /** * Returns the configuration frame widget for a GTK+ plugin, if one
--- a/pidgin/gtkpounce.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkpounce.c Sun Aug 18 01:53:00 2013 +0530 @@ -30,7 +30,7 @@ #include "account.h" #include "conversation.h" #include "debug.h" -#include "prpl.h" +#include "protocol.h" #include "request.h" #include "server.h" #include "sound.h" @@ -203,7 +203,7 @@ account = purple_pounce_get_pouncer(pounce); - pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM); + pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_MEDIUM); pouncer = purple_account_get_username(account); pouncee = purple_pounce_get_pouncee(pounce);
--- a/pidgin/gtkprefs.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkprefs.c Sun Aug 18 01:53:00 2013 +0530 @@ -34,7 +34,7 @@ #include "notify.h" #include "prefs.h" #include "proxy.h" -#include "prpl.h" +#include "protocol.h" #include "request.h" #include "savedstatuses.h" #include "sound.h"
--- a/pidgin/gtkrequest.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkrequest.c Sun Aug 18 01:53:00 2013 +0530 @@ -99,7 +99,7 @@ if (!account) return; - pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); + pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL); image = gtk_image_new_from_pixbuf(pixbuf); g_object_unref(G_OBJECT(pixbuf));
--- a/pidgin/gtkroomlist.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkroomlist.c Sun Aug 18 01:53:00 2013 +0530 @@ -230,13 +230,13 @@ char *name; PurpleAccount *account = purple_roomlist_get_account(info->list); PurpleConnection *gc = purple_account_get_connection(account); - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; if(gc != NULL) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + protocol = purple_connection_get_protocol_info(gc); - if(prpl_info != NULL && prpl_info->roomlist_room_serialize) - name = prpl_info->roomlist_room_serialize(info->room); + if(protocol != NULL && protocol->roomlist_room_serialize) + name = protocol->roomlist_room_serialize(info->room); else name = g_strdup(purple_roomlist_room_get_name(info->room)); @@ -537,12 +537,12 @@ static gboolean account_filter_func(PurpleAccount *account) { PurpleConnection *conn = purple_account_get_connection(account); - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; if (conn && PURPLE_CONNECTION_IS_CONNECTED(conn)) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(conn)); + protocol = purple_connection_get_protocol_info(conn); - return (prpl_info && prpl_info->roomlist_get_list != NULL); + return (protocol && protocol->roomlist_get_list != NULL); } gboolean
--- a/pidgin/gtksavedstatuses.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtksavedstatuses.c Sun Aug 18 01:53:00 2013 +0530 @@ -1002,7 +1002,7 @@ const char *id = NULL, *name = NULL, *message = NULL; PurpleStatusPrimitive prim = PURPLE_STATUS_UNSET; - pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM); + pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_MEDIUM); if ((pixbuf != NULL) && !purple_account_is_connected(account)) { gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
--- a/pidgin/gtkstatusbox.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkstatusbox.c Sun Aug 18 01:53:00 2013 +0530 @@ -494,12 +494,10 @@ case PROP_ICON_SEL: if (g_value_get_boolean(value)) { if (statusbox->account) { - PurplePlugin *plug = purple_plugins_find_with_id(purple_account_get_protocol_id(statusbox->account)); - if (plug) { - PurplePluginProtocolInfo *prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plug); - if (prplinfo && prplinfo->icon_spec.format != NULL) - setup_icon_box(statusbox); - } + PurpleProtocol *protocol = + purple_find_protocol_info(purple_account_get_protocol_id(statusbox->account)); + if (protocol && protocol->icon_spec.format != NULL) + setup_icon_box(statusbox); } else { setup_icon_box(statusbox); } @@ -715,7 +713,7 @@ text = g_strdup_printf("%s - <span size=\"smaller\" color=\"%s\">%s</span>", purple_account_get_username(status_box->account), aa_color, secondary ? secondary : primary); - emblem = pidgin_create_prpl_icon(status_box->account, PIDGIN_PRPL_ICON_SMALL); + emblem = pidgin_create_protocol_icon(status_box->account, PIDGIN_PROTOCOL_ICON_SMALL); } else if (secondary != NULL) { text = g_strdup_printf("%s<span size=\"smaller\" color=\"%s\"> - %s</span>", primary, aa_color, secondary); @@ -1452,44 +1450,40 @@ PurpleStoredImage *img = NULL; if (box->account) { - PurplePlugin *plug = purple_find_prpl(purple_account_get_protocol_id(box->account)); - if (plug) { - PurplePluginProtocolInfo *prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plug); - if (prplinfo && prplinfo->icon_spec.format) { - gpointer data = NULL; - size_t len = 0; - if (filename) - data = pidgin_convert_buddy_icon(plug, filename, &len); - img = purple_buddy_icons_set_account_icon(box->account, data, len); - if (img) - /* - * set_account_icon doesn't give us a reference, but we - * unref one below (for the other code path) - */ - purple_imgstore_ref(img); - - purple_account_set_buddy_icon_path(box->account, filename); - - purple_account_set_bool(box->account, "use-global-buddyicon", (filename != NULL)); - } + PurpleProtocol *protocol = + purple_find_protocol_info(purple_account_get_protocol_id(box->account)); + if (protocol && protocol->icon_spec.format) { + gpointer data = NULL; + size_t len = 0; + if (filename) + data = pidgin_convert_buddy_icon(protocol, filename, &len); + img = purple_buddy_icons_set_account_icon(box->account, data, len); + if (img) + /* + * set_account_icon doesn't give us a reference, but we + * unref one below (for the other code path) + */ + purple_imgstore_ref(img); + + purple_account_set_buddy_icon_path(box->account, filename); + + purple_account_set_bool(box->account, "use-global-buddyicon", (filename != NULL)); } } else { GList *accounts; for (accounts = purple_accounts_get_all(); accounts != NULL; accounts = accounts->next) { PurpleAccount *account = accounts->data; - PurplePlugin *plug = purple_find_prpl(purple_account_get_protocol_id(account)); - if (plug) { - PurplePluginProtocolInfo *prplinfo = PURPLE_PLUGIN_PROTOCOL_INFO(plug); - if (prplinfo != NULL && - purple_account_get_bool(account, "use-global-buddyicon", TRUE) && - prplinfo->icon_spec.format) { - gpointer data = NULL; - size_t len = 0; - if (filename) - data = pidgin_convert_buddy_icon(plug, filename, &len); - purple_buddy_icons_set_account_icon(account, data, len); - purple_account_set_buddy_icon_path(account, filename); - } + PurpleProtocol *protocol = + purple_find_protocol_info(purple_account_get_protocol_id(account)); + if (protocol != NULL && + purple_account_get_bool(account, "use-global-buddyicon", TRUE) && + protocol->icon_spec.format) { + gpointer data = NULL; + size_t len = 0; + if (filename) + data = pidgin_convert_buddy_icon(protocol, filename, &len); + purple_buddy_icons_set_account_icon(account, data, len); + purple_account_set_buddy_icon_path(account, filename); } }
--- a/pidgin/gtkthemes.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkthemes.c Sun Aug 18 01:53:00 2013 +0530 @@ -25,7 +25,7 @@ #include "conversation.h" #include "debug.h" -#include "prpl.h" +#include "protocol.h" #include "util.h" #include "gtkconv.h" @@ -396,7 +396,7 @@ } GSList *pidgin_themes_get_proto_smileys(const char *id) { - PurplePlugin *proto; + PurpleProtocol *protocol; struct smiley_list *list, *def; if ((current_smiley_theme == NULL) || (current_smiley_theme->list == NULL)) @@ -407,12 +407,12 @@ if (id == NULL) return def->smileys; - proto = purple_find_prpl(id); + protocol = purple_find_protocol_info(id); while (list) { if (!strcmp(list->sml, "default")) def = list; - else if (proto && !strcmp(proto->info->name, list->sml)) + else if (protocol && !strcmp(protocol->name, list->sml)) break; list = list->next;
--- a/pidgin/gtkutils.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkutils.c Sun Aug 18 01:53:00 2013 +0530 @@ -49,7 +49,7 @@ #include "imgstore.h" #include "notify.h" #include "prefs.h" -#include "prpl.h" +#include "protocol.h" #include "request.h" #include "signals.h" #include "sound.h" @@ -549,19 +549,17 @@ } static GdkPixbuf * -pidgin_create_prpl_icon_from_prpl(PurplePlugin *prpl, PidginPrplIconSize size, PurpleAccount *account) +pidgin_create_protocol_icon_from_protocol(PurpleProtocol *protocol, PidginPrplIconSize size, PurpleAccount *account) { - PurplePluginProtocolInfo *prpl_info; const char *protoname = NULL; char *tmp; char *filename = NULL; GdkPixbuf *pixbuf; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (prpl_info->list_icon == NULL) + if (protocol->list_icon == NULL) return NULL; - protoname = prpl_info->list_icon(account, NULL); + protoname = protocol->list_icon(account, NULL); if (protoname == NULL) return NULL; @@ -572,8 +570,8 @@ tmp = g_strconcat(protoname, ".png", NULL); filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", - size == PIDGIN_PRPL_ICON_SMALL ? "16" : - size == PIDGIN_PRPL_ICON_MEDIUM ? "22" : "48", + size == PIDGIN_PROTOCOL_ICON_SMALL ? "16" : + size == PIDGIN_PROTOCOL_ICON_MEDIUM ? "22" : "48", tmp, NULL); g_free(tmp); @@ -626,7 +624,7 @@ create_protocols_menu(const char *default_proto_id) { AopMenu *aop_menu = NULL; - PurplePlugin *plugin; + PurpleProtocol *protocol; GdkPixbuf *pixbuf = NULL; GtkTreeIter iter; GtkListStore *ls; @@ -639,25 +637,25 @@ aop_menu->default_item = 0; aop_menu->model = GTK_TREE_MODEL(ls); - for (p = purple_plugins_get_protocols(), i = 0; + for (p = purple_protocols_get_all(), i = 0; p != NULL; p = p->next, i++) { - plugin = (PurplePlugin *)p->data; - - pixbuf = pidgin_create_prpl_icon_from_prpl(plugin, PIDGIN_PRPL_ICON_SMALL, NULL); + protocol = (PurpleProtocol *)p->data; + + pixbuf = pidgin_create_protocol_icon_from_protocol(protocol, PIDGIN_PROTOCOL_ICON_SMALL, NULL); 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, + AOP_NAME_COLUMN, protocol->name, + AOP_DATA_COLUMN, protocol->id, -1); if (pixbuf) g_object_unref(pixbuf); - if (default_proto_id != NULL && !strcmp(plugin->info->id, default_proto_id)) + if (default_proto_id != NULL && !strcmp(protocol->id, default_proto_id)) aop_menu->default_item = i; } @@ -722,7 +720,7 @@ continue; } - pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); + pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL); if (pixbuf) { if (purple_account_is_disconnected(account) && show_all && @@ -911,24 +909,24 @@ void pidgin_retrieve_user_info_in_chat(PurpleConnection *conn, const char *name, int chat) { char *who = NULL; - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; if (chat < 0) { pidgin_retrieve_user_info(conn, name); return; } - 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) { + protocol = purple_connection_get_protocol_info(conn); + if (protocol != NULL && protocol->get_cb_real_name) + who = protocol->get_cb_real_name(conn, chat, name); + if (protocol == NULL || protocol->get_cb_info == NULL) { pidgin_retrieve_user_info(conn, who ? who : name); g_free(who); return; } show_retrieveing_info(conn, who ? who : name); - prpl_info->get_cb_info(conn, chat, name); + protocol->get_cb_info(conn, chat, name); g_free(who); } @@ -937,9 +935,9 @@ PurpleAccount **ret_account, char **ret_protocol, char **ret_username, char **ret_alias) { - char *protocol = NULL; - char *username = NULL; - char *alias = NULL; + char *protocol_id = NULL; + char *username = NULL; + char *alias = NULL; char *str; char *s; gboolean valid; @@ -988,18 +986,18 @@ if (!g_ascii_strcasecmp(key, "X-IM-Username:")) username = g_strdup(value); else if (!g_ascii_strcasecmp(key, "X-IM-Protocol:")) - protocol = g_strdup(value); + protocol_id = g_strdup(value); else if (!g_ascii_strcasecmp(key, "X-IM-Alias:")) alias = g_strdup(value); } } - if (username != NULL && protocol != NULL) + if (username != NULL && protocol_id != NULL) { valid = TRUE; *ret_username = username; - *ret_protocol = protocol; + *ret_protocol = protocol_id; if (ret_alias != NULL) *ret_alias = alias; @@ -1020,76 +1018,70 @@ for (l = list; l != NULL; l = l->next) { PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info = NULL; - PurplePlugin *plugin; + PurpleProtocol *protocol = NULL; if (all_accounts) { account = (PurpleAccount *)l->data; - plugin = purple_plugins_find_with_id( + protocol = purple_find_protocol_info( purple_account_get_protocol_id(account)); - if (plugin == NULL) + if (protocol == NULL) { account = NULL; continue; } - - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); } else { gc = (PurpleConnection *)l->data; account = purple_connection_get_account(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + protocol = purple_connection_get_protocol_info(gc); } - protoname = prpl_info->list_icon(account, NULL); - - if (!strcmp(protoname, protocol)) + protoname = protocol->list_icon(account, NULL); + + if (!strcmp(protoname, protocol_id)) break; account = NULL; } /* Special case for AIM and ICQ */ - if (account == NULL && (!strcmp(protocol, "aim") || - !strcmp(protocol, "icq"))) + if (account == NULL && (!strcmp(protocol_id, "aim") || + !strcmp(protocol_id, "icq"))) { for (l = list; l != NULL; l = l->next) { PurpleConnection *gc; - PurplePluginProtocolInfo *prpl_info = NULL; - PurplePlugin *plugin; + PurpleProtocol *protocol = NULL; if (all_accounts) { account = (PurpleAccount *)l->data; - plugin = purple_plugins_find_with_id( + protocol = purple_find_protocol_info( purple_account_get_protocol_id(account)); - if (plugin == NULL) + if (protocol == NULL) { account = NULL; continue; } - - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); } else { gc = (PurpleConnection *)l->data; account = purple_connection_get_account(gc); - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + protocol = purple_connection_get_protocol_info(gc); } - protoname = prpl_info->list_icon(account, NULL); + protoname = protocol->list_icon(account, NULL); if (!strcmp(protoname, "aim") || !strcmp(protoname, "icq")) break; @@ -1106,7 +1098,7 @@ valid = FALSE; g_free(username); - g_free(protocol); + g_free(protocol_id); g_free(alias); } @@ -1446,7 +1438,7 @@ GdkPixbuf *pb; GList *files = purple_uri_list_extract_filenames((const gchar *) gtk_selection_data_get_data(sd)); PurpleConnection *gc = purple_account_get_connection(account); - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; #ifndef _WIN32 PurpleDesktopItem *item; #endif @@ -1495,14 +1487,14 @@ data->account = account; if (gc) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); - - if (prpl_info && prpl_info->options & OPT_PROTO_IM_IMAGE) + protocol = purple_connection_get_protocol_info(gc); + + if (protocol && protocol->options & OPT_PROTO_IM_IMAGE) im = TRUE; - if (prpl_info && prpl_info->can_receive_file) - ft = prpl_info->can_receive_file(gc, who); - else if (prpl_info && prpl_info->send_file) + if (protocol && protocol->can_receive_file) + ft = protocol->can_receive_file(gc, who); + else if (protocol && protocol->send_file) ft = TRUE; if (im && ft) @@ -1694,16 +1686,16 @@ } GdkPixbuf * -pidgin_create_prpl_icon(PurpleAccount *account, PidginPrplIconSize size) +pidgin_create_protocol_icon(PurpleAccount *account, PidginPrplIconSize size) { - PurplePlugin *prpl; + PurpleProtocol *protocol; g_return_val_if_fail(account != NULL, NULL); - prpl = purple_find_prpl(purple_account_get_protocol_id(account)); - if (prpl == NULL) + protocol = purple_find_protocol_info(purple_account_get_protocol_id(account)); + if (protocol == NULL) return NULL; - return pidgin_create_prpl_icon_from_prpl(prpl, size, account); + return pidgin_create_protocol_icon_from_protocol(protocol, size, account); } static void @@ -2266,14 +2258,13 @@ } gpointer -pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path, size_t *len) +pidgin_convert_buddy_icon(PurpleProtocol *protocol, const char *path, size_t *len) { - PurplePluginProtocolInfo *prpl_info; PurpleBuddyIconSpec *spec; int orig_width, orig_height, new_width, new_height; GdkPixbufFormat *format; char **pixbuf_formats; - char **prpl_formats; + char **protocol_formats; GError *error = NULL; gchar *contents; gsize length; @@ -2282,8 +2273,7 @@ int i; gchar *tmp; - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); - spec = &prpl_info->icon_spec; + spec = &protocol->icon_spec; g_return_val_if_fail(spec->format != NULL, NULL); format = gdk_pixbuf_get_file_info(path, &orig_width, &orig_height); @@ -2293,9 +2283,9 @@ } pixbuf_formats = gdk_pixbuf_format_get_extensions(format); - prpl_formats = g_strsplit(spec->format, ",", 0); - - if (str_array_match(pixbuf_formats, prpl_formats) && /* This is an acceptable format AND */ + protocol_formats = g_strsplit(spec->format, ",", 0); + + if (str_array_match(pixbuf_formats, protocol_formats) && /* This is an acceptable format AND */ (!(spec->scale_rules & PURPLE_ICON_SCALE_SEND) || /* The prpl doesn't scale before it sends OR */ (spec->min_width <= orig_width && spec->max_width >= orig_width && spec->min_height <= orig_height && spec->max_height >= orig_height))) /* The icon is the correct size */ @@ -2305,7 +2295,7 @@ if (!g_file_get_contents(path, &contents, &length, &error)) { purple_debug_warning("buddyicon", "Could not get file contents " "of %s: %s\n", path, error->message); - g_strfreev(prpl_formats); + g_strfreev(protocol_formats); return NULL; } @@ -2314,7 +2304,7 @@ constraints. Great! Return it without making any changes. */ if (len) *len = length; - g_strfreev(prpl_formats); + g_strfreev(protocol_formats); return contents; } @@ -2330,7 +2320,7 @@ purple_debug_warning("buddyicon", "Could not open icon '%s' for " "conversion: %s\n", path, error->message); g_error_free(error); - g_strfreev(prpl_formats); + g_strfreev(protocol_formats); return NULL; } original = g_object_ref(G_OBJECT(pixbuf)); @@ -2351,31 +2341,31 @@ scale_factor = 1; do { - for (i = 0; prpl_formats[i]; i++) { + for (i = 0; protocol_formats[i]; i++) { int quality = 100; do { const char *key = NULL; const char *value = NULL; gchar tmp_buf[4]; - purple_debug_info("buddyicon", "Converting buddy icon to %s\n", prpl_formats[i]); - - if (g_str_equal(prpl_formats[i], "png")) { + purple_debug_info("buddyicon", "Converting buddy icon to %s\n", protocol_formats[i]); + + if (g_str_equal(protocol_formats[i], "png")) { key = "compression"; value = "9"; - } else if (g_str_equal(prpl_formats[i], "jpeg")) { + } else if (g_str_equal(protocol_formats[i], "jpeg")) { sprintf(tmp_buf, "%u", quality); key = "quality"; value = tmp_buf; } if (!gdk_pixbuf_save_to_buffer(pixbuf, &contents, &length, - prpl_formats[i], &error, key, value, NULL)) + protocol_formats[i], &error, key, value, NULL)) { /* The NULL checking of error is necessary due to this bug: * http://bugzilla.gnome.org/show_bug.cgi?id=405539 */ purple_debug_warning("buddyicon", - "Could not convert to %s: %s\n", prpl_formats[i], + "Could not convert to %s: %s\n", protocol_formats[i], (error && error->message) ? error->message : "Unknown error"); g_error_free(error); error = NULL; @@ -2393,10 +2383,10 @@ "%dx%d to %dx%d, format=%s, quality=%u, " "filesize=%" G_GSIZE_FORMAT "\n", orig_width, orig_height, new_width, new_height, - prpl_formats[i], quality, length); + protocol_formats[i], quality, length); if (len) *len = length; - g_strfreev(prpl_formats); + g_strfreev(protocol_formats); g_object_unref(G_OBJECT(pixbuf)); g_object_unref(G_OBJECT(original)); return contents; @@ -2404,7 +2394,7 @@ g_free(contents); - if (!g_str_equal(prpl_formats[i], "jpeg")) { + if (!g_str_equal(protocol_formats[i], "jpeg")) { /* File size was too big and we can't lower the quality, so skip to the next image type. */ break; @@ -2424,12 +2414,12 @@ g_object_unref(G_OBJECT(pixbuf)); pixbuf = gdk_pixbuf_scale_simple(original, new_width, new_height, GDK_INTERP_HYPER); } while ((new_width > 10 || new_height > 10) && new_width > spec->min_width && new_height > spec->min_height); - g_strfreev(prpl_formats); + g_strfreev(protocol_formats); g_object_unref(G_OBJECT(pixbuf)); g_object_unref(G_OBJECT(original)); tmp = g_strdup_printf(_("The file '%s' is too large for %s. Please try a smaller image.\n"), - path, plugin->info->name); + path, protocol->name); purple_notify_error(NULL, _("Icon Error"), _("Could not set icon"), tmp); g_free(tmp);
--- a/pidgin/gtkutils.h Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkutils.h Sun Aug 18 01:53:00 2013 +0530 @@ -28,7 +28,7 @@ #include "gtkconv.h" #include "pidgin.h" -#include "prpl.h" +#include "protocol.h" #include "util.h" typedef enum @@ -49,9 +49,9 @@ typedef enum { - PIDGIN_PRPL_ICON_SMALL, - PIDGIN_PRPL_ICON_MEDIUM, - PIDGIN_PRPL_ICON_LARGE + PIDGIN_PROTOCOL_ICON_SMALL, + PIDGIN_PROTOCOL_ICON_MEDIUM, + PIDGIN_PROTOCOL_ICON_LARGE } PidginPrplIconSize; #ifndef _WIN32 @@ -514,7 +514,7 @@ * to allocate the image buffer, or the image file * contained invalid data. */ -GdkPixbuf *pidgin_create_prpl_icon(PurpleAccount *account, PidginPrplIconSize size); +GdkPixbuf *pidgin_create_protocol_icon(PurpleAccount *account, PidginPrplIconSize size); /** * Creates a status icon for a given primitve @@ -593,13 +593,13 @@ /** * Converts a buddy icon to the required size and format * - * @param plugin The prpl to convert the icon + * @param protocol The prpl to convert the icon * @param path The path of a file to convert * @param len If not @c NULL, the length of the returned data will be set here. * * @return The converted image data, or @c NULL if an error occurred. */ -gpointer pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path, size_t *len); +gpointer pidgin_convert_buddy_icon(PurpleProtocol *protocol, const char *path, size_t *len); /** * Converts "->" and "<-" in strings to Unicode arrow characters, for use in referencing
--- a/pidgin/gtkwebviewtoolbar.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkwebviewtoolbar.c Sun Aug 18 01:53:00 2013 +0530 @@ -979,7 +979,7 @@ const gchar *who = purple_conversation_get_name(conv); PurpleConnection *gc = purple_conversation_get_connection(conv); - purple_prpl_send_attention(gc, who, 0); + purple_protocol_send_attention(gc, who, 0); gtk_widget_grab_focus(toolbar->webview); } @@ -1625,15 +1625,15 @@ { GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar); PurpleConnection *gc = purple_conversation_get_connection(conv); - PurplePlugin *prpl = purple_connection_get_prpl(gc); + PurpleProtocol *protocol = purple_connection_get_protocol_info(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_action_set_sensitive(priv->attention, - conv && prpl && PURPLE_IS_IM_CONVERSATION(conv) && - PURPLE_PLUGIN_PROTOCOL_INFO(prpl)->send_attention != NULL); + conv && protocol && PURPLE_IS_IM_CONVERSATION(conv) && + protocol->send_attention != NULL); gtk_action_set_sensitive(priv->smiley, (gboolean)pidgin_themes_get_proto_smileys(priv->sml));
--- a/pidgin/gtkwhiteboard.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/gtkwhiteboard.c Sun Aug 18 01:53:00 2013 +0530 @@ -330,7 +330,7 @@ /* * Whiteboard start button on conversation window (move this code to gtkconv? - * and use new prpl_info member?) + * and use new protocol member?) */ #if 0 static void pidginwhiteboard_button_start_press(GtkButton *button, gpointer data)
--- a/pidgin/plugins/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -1,142 +1,143 @@ -DIST_SUBDIRS = cap disco gestures gevolution musicmessaging perl ticker - -if BUILD_GEVOLUTION -GEVOLUTION_DIR = gevolution -endif - -if ENABLE_DBUS -MUSICMESSAGING_DIR = musicmessaging -endif - -if ENABLE_CAP -CAP_DIR = cap -endif - -if USE_PERL -PERL_DIR = perl -endif - -if ENABLE_GESTURES -GESTURE_DIR = gestures -endif - -SUBDIRS = \ - $(CAP_DIR) \ - $(GESTURE_DIR) \ - $(GEVOLUTION_DIR) \ - $(MUSICMESSAGING_DIR) \ - $(PERL_DIR) \ - disco \ - ticker - -plugindir = $(libdir)/pidgin - -convcolors_la_LDFLAGS = -module -avoid-version -contact_priority_la_LDFLAGS = -module -avoid-version -extplacement_la_LDFLAGS = -module -avoid-version -gtk_signals_test_la_LDFLAGS = -module -avoid-version -gtkbuddynote_la_LDFLAGS = -module -avoid-version -history_la_LDFLAGS = -module -avoid-version -iconaway_la_LDFLAGS = -module -avoid-version -markerline_la_LDFLAGS = -module -avoid-version -notify_la_LDFLAGS = -module -avoid-version -pidginrc_la_LDFLAGS = -module -avoid-version -relnot_la_LDFLAGS = -module -avoid-version -sendbutton_la_LDFLAGS = -module -avoid-version -spellchk_la_LDFLAGS = -module -avoid-version -themeedit_la_LDFLAGS = -module -avoid-version -webkit_la_LDFLAGS = -module -avoid-version -xmppconsole_la_LDFLAGS = -module -avoid-version - -if PLUGINS - -plugin_LTLIBRARIES = \ - convcolors.la \ - extplacement.la \ - gtkbuddynote.la \ - history.la \ - iconaway.la \ - markerline.la \ - notify.la \ - pidginrc.la \ - relnot.la \ - sendbutton.la \ - spellchk.la \ - themeedit.la \ - webkit.la \ - xmppconsole.la - -noinst_LTLIBRARIES = \ - contact_priority.la \ - gtk_signals_test.la - -convcolors_la_SOURCES = convcolors.c -contact_priority_la_SOURCES = contact_priority.c -extplacement_la_SOURCES = extplacement.c -gtk_signals_test_la_SOURCES = gtk-signals-test.c -gtkbuddynote_la_SOURCES = gtkbuddynote.c -history_la_SOURCES = history.c -iconaway_la_SOURCES = iconaway.c -markerline_la_SOURCES = markerline.c -notify_la_SOURCES = notify.c -pidginrc_la_SOURCES = pidginrc.c -relnot_la_SOURCES = relnot.c -sendbutton_la_SOURCES = sendbutton.c -spellchk_la_SOURCES = spellchk.c -themeedit_la_SOURCES = themeedit.c themeedit-icon.c themeedit-icon.h -webkit_la_SOURCES = webkit.c -xmppconsole_la_SOURCES = xmppconsole.c - -convcolors_la_LIBADD = $(GTK_LIBS) -contact_priority_la_LIBADD = $(GTK_LIBS) -extplacement_la_LIBADD = $(GTK_LIBS) -gtk_signals_test_la_LIBADD = $(GTK_LIBS) -gtkbuddynote_la_LIBADD = $(GTK_LIBS) -history_la_LIBADD = $(GTK_LIBS) -iconaway_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) -webkit_la_LIBADD = $(GTK_LIBS) $(WEBKIT_LIBS) -xmppconsole_la_LIBADD = $(GTK_LIBS) - -endif # PLUGINS - -EXTRA_DIST = \ - Makefile.mingw \ - mailchk.c \ - pidgininc.c \ - raw.c \ - win32/transparency/Makefile.mingw \ - win32/transparency/win2ktrans.c \ - win32/winprefs/gtkappbar.c \ - win32/winprefs/gtkappbar.h \ - win32/winprefs/Makefile.mingw \ - win32/winprefs/winprefs.c - -AM_CPPFLAGS = \ - -DDATADIR=\"$(datadir)\" \ - -I$(top_builddir)/libpurple \ - -I$(top_srcdir)/libpurple \ - -I$(top_srcdir)/pidgin \ - $(DEBUG_CFLAGS) \ - $(GTK_CFLAGS) \ - $(WEBKIT_CFLAGS) \ - $(GSTREAMER_CFLAGS) \ - $(PLUGIN_CFLAGS) - +#DIST_SUBDIRS = cap disco gestures gevolution musicmessaging perl ticker +# +#if BUILD_GEVOLUTION +#GEVOLUTION_DIR = gevolution +#endif +# +#if ENABLE_DBUS +#MUSICMESSAGING_DIR = musicmessaging +#endif +# +#if ENABLE_CAP +#CAP_DIR = cap +#endif +# +#if USE_PERL +#PERL_DIR = perl +#endif +# +#if ENABLE_GESTURES +#GESTURE_DIR = gestures +#endif +# +#SUBDIRS = \ +# $(CAP_DIR) \ +# $(GESTURE_DIR) \ +# $(GEVOLUTION_DIR) \ +# $(MUSICMESSAGING_DIR) \ +# $(PERL_DIR) \ +# disco \ +# ticker +# +#plugindir = $(libdir)/pidgin +# +#convcolors_la_LDFLAGS = -module -avoid-version +#contact_priority_la_LDFLAGS = -module -avoid-version +#extplacement_la_LDFLAGS = -module -avoid-version +#gtk_signals_test_la_LDFLAGS = -module -avoid-version +#gtkbuddynote_la_LDFLAGS = -module -avoid-version +#history_la_LDFLAGS = -module -avoid-version +#iconaway_la_LDFLAGS = -module -avoid-version +#markerline_la_LDFLAGS = -module -avoid-version +#notify_la_LDFLAGS = -module -avoid-version +#pidginrc_la_LDFLAGS = -module -avoid-version +#relnot_la_LDFLAGS = -module -avoid-version +#sendbutton_la_LDFLAGS = -module -avoid-version +#spellchk_la_LDFLAGS = -module -avoid-version +#themeedit_la_LDFLAGS = -module -avoid-version +#webkit_la_LDFLAGS = -module -avoid-version +#xmppconsole_la_LDFLAGS = -module -avoid-version +# +#if PLUGINS +# +#plugin_LTLIBRARIES = \ +# convcolors.la \ +# extplacement.la \ +# gtkbuddynote.la \ +# history.la \ +# iconaway.la \ +# markerline.la \ +# notify.la \ +# pidginrc.la \ +# relnot.la \ +# sendbutton.la \ +# spellchk.la \ +# themeedit.la \ +# webkit.la \ +# xmppconsole.la +# +#noinst_LTLIBRARIES = \ +# contact_priority.la \ +# gtk_signals_test.la # -# This part allows people to build their own plugins in here. -# Yes, it's a mess. +#convcolors_la_SOURCES = convcolors.c +#contact_priority_la_SOURCES = contact_priority.c +#extplacement_la_SOURCES = extplacement.c +#gtk_signals_test_la_SOURCES = gtk-signals-test.c +#gtkbuddynote_la_SOURCES = gtkbuddynote.c +#history_la_SOURCES = history.c +#iconaway_la_SOURCES = iconaway.c +#markerline_la_SOURCES = markerline.c +#notify_la_SOURCES = notify.c +#pidginrc_la_SOURCES = pidginrc.c +#relnot_la_SOURCES = relnot.c +#sendbutton_la_SOURCES = sendbutton.c +#spellchk_la_SOURCES = spellchk.c +#themeedit_la_SOURCES = themeedit.c themeedit-icon.c themeedit-icon.h +#webkit_la_SOURCES = webkit.c +#xmppconsole_la_SOURCES = xmppconsole.c +# +#convcolors_la_LIBADD = $(GTK_LIBS) +#contact_priority_la_LIBADD = $(GTK_LIBS) +#extplacement_la_LIBADD = $(GTK_LIBS) +#gtk_signals_test_la_LIBADD = $(GTK_LIBS) +#gtkbuddynote_la_LIBADD = $(GTK_LIBS) +#history_la_LIBADD = $(GTK_LIBS) +#iconaway_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) +#webkit_la_LIBADD = $(GTK_LIBS) $(WEBKIT_LIBS) +#xmppconsole_la_LIBADD = $(GTK_LIBS) +# +#endif # PLUGINS # -SUFFIXES = .c .so -.c.so: - $(LIBTOOL) --mode=compile $(CC) -DHAVE_CONFIG_H -I$(top_builddir) $(AM_CPPFLAGS) $(CFLAGS) -c $< -o tmp$@.lo $(PLUGIN_CFLAGS) - $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o libtmp$@.la -rpath $(plugindir) tmp$@.lo $(LIBS) $(LDFLAGS) -module -avoid-version $(PLUGIN_LIBS) - @rm -f tmp$@.lo tmp$@.o libtmp$@.la - @cp .libs/libtmp$@*.so $@ - @rm -rf .libs/libtmp$@.* +#EXTRA_DIST = \ +# Makefile.mingw \ +# mailchk.c \ +# pidgininc.c \ +# raw.c \ +# win32/transparency/Makefile.mingw \ +# win32/transparency/win2ktrans.c \ +# win32/winprefs/gtkappbar.c \ +# win32/winprefs/gtkappbar.h \ +# win32/winprefs/Makefile.mingw \ +# win32/winprefs/winprefs.c +# +#AM_CPPFLAGS = \ +# -DDATADIR=\"$(datadir)\" \ +# -I$(top_builddir)/libpurple \ +# -I$(top_srcdir)/libpurple \ +# -I$(top_srcdir)/pidgin \ +# $(DEBUG_CFLAGS) \ +# $(GTK_CFLAGS) \ +# $(GPLUGIN_CFLAGS) \ +# $(WEBKIT_CFLAGS) \ +# $(GSTREAMER_CFLAGS) \ +# $(PLUGIN_CFLAGS) +# +## +## This part allows people to build their own plugins in here. +## Yes, it's a mess. +## +#SUFFIXES = .c .so +#.c.so: +# $(LIBTOOL) --mode=compile $(CC) -DHAVE_CONFIG_H -I$(top_builddir) $(AM_CPPFLAGS) $(CFLAGS) -c $< -o tmp$@.lo $(PLUGIN_CFLAGS) +# $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o libtmp$@.la -rpath $(plugindir) tmp$@.lo $(LIBS) $(LDFLAGS) -module -avoid-version $(PLUGIN_LIBS) +# @rm -f tmp$@.lo tmp$@.o libtmp$@.la +# @cp .libs/libtmp$@*.so $@ +# @rm -rf .libs/libtmp$@.*
--- a/pidgin/plugins/cap/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/cap/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -24,6 +24,7 @@ -I$(top_srcdir)/pidgin \ $(DEBUG_CFLAGS) \ $(GTK_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(SQLITE3_CFLAGS) EXTRA_DIST = Makefile.mingw
--- a/pidgin/plugins/crazychat/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/crazychat/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -36,6 +36,7 @@ -I$(top_builddir)/libpurple \ -I$(top_srcdir)/pidgin \ $(GTK_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(GTKGLEXT_CFLAGS) \ $(DEBUG_CPPFLAGS) \ $(DEBUG_CFLAGS) \
--- a/pidgin/plugins/crazychat/cc_pidgin_plugin.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/crazychat/cc_pidgin_plugin.c Sun Aug 18 01:53:00 2013 +0530 @@ -2,7 +2,7 @@ #include <assert.h> #include "internal.h" -#include "plugin.h" +#include "plugins.h" #include "gtkplugin.h" #include "gtkblist.h" #include "gtkutils.h"
--- a/pidgin/plugins/disco/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/disco/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -25,4 +25,5 @@ -I$(top_builddir)/libpurple \ -I$(top_srcdir)/pidgin \ $(DEBUG_CFLAGS) \ - $(GTK_CFLAGS) + $(GTK_CFLAGS) \ + $(GPLUGIN_CFLAGS)
--- a/pidgin/plugins/disco/xmppdisco.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/disco/xmppdisco.c Sun Aug 18 01:53:00 2013 +0530 @@ -128,7 +128,7 @@ g_hash_table_remove(iq_callbacks, id); if (g_hash_table_size(iq_callbacks) == 0) { - PurplePlugin *prpl = purple_connection_get_prpl(pc); + PurplePlugin *prpl = purple_connection_get_protocol_info(pc); iq_listening = FALSE; purple_signal_disconnect(prpl, "jabber-receiving-iq", my_plugin, PURPLE_CALLBACK(xmpp_iq_received)); @@ -178,7 +178,7 @@ /* Steals id */ xmpp_iq_register_callback(pc, id, cbdata, cb); - purple_signal_emit(purple_connection_get_prpl(pc), "jabber-sending-xmlnode", + purple_signal_emit(purple_connection_get_protocol_info(pc), "jabber-sending-xmlnode", pc, &iq); if (iq != NULL) xmlnode_free(iq); @@ -204,7 +204,7 @@ /* Steals id */ xmpp_iq_register_callback(pc, id, cbdata, cb); - purple_signal_emit(purple_connection_get_prpl(pc), "jabber-sending-xmlnode", + purple_signal_emit(purple_connection_get_protocol_info(pc), "jabber-sending-xmlnode", pc, &iq); if (iq != NULL) xmlnode_free(iq); @@ -578,7 +578,7 @@ query = xmlnode_new_child(iq, "query"); xmlnode_set_namespace(query, NS_REGISTER); - purple_signal_emit(purple_connection_get_prpl(service->list->pc), + purple_signal_emit(purple_connection_get_protocol_info(service->list->pc), "jabber-sending-xmlnode", service->list->pc, &iq); if (iq != NULL) xmlnode_free(iq); @@ -617,12 +617,12 @@ static gboolean plugin_load(PurplePlugin *plugin) { - PurplePlugin *xmpp_prpl; + PurplePlugin *xmpp_protocol; my_plugin = plugin; - xmpp_prpl = purple_plugins_find_with_id(XMPP_PLUGIN_ID); - if (NULL == xmpp_prpl) + xmpp_protocol = purple_plugins_find_with_id(XMPP_PLUGIN_ID); + if (NULL == xmpp_protocol) return FALSE; purple_signal_connect(purple_connections_get_handle(), "signing-off",
--- a/pidgin/plugins/disco/xmppdisco.h Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/disco/xmppdisco.h Sun Aug 18 01:53:00 2013 +0530 @@ -32,7 +32,7 @@ #define NS_MUC "http://jabber.org/protocol/muc" #define NS_REGISTER "jabber:iq:register" -#include "plugin.h" +#include "plugins.h" extern PurplePlugin *my_plugin; /**
--- a/pidgin/plugins/gestures/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/gestures/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -23,4 +23,5 @@ -I$(top_builddir)/libpurple \ -I$(top_srcdir)/pidgin \ $(DEBUG_CFLAGS) \ - $(GTK_CFLAGS) + $(GTK_CFLAGS) \ + $(GPLUGIN_CFLAGS)
--- a/pidgin/plugins/gevolution/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/gevolution/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -26,4 +26,5 @@ -I$(top_srcdir)/pidgin \ $(EVOLUTION_ADDRESSBOOK_CFLAGS) \ $(DEBUG_CFLAGS) \ - $(GTK_CFLAGS) + $(GTK_CFLAGS) \ + $(GPLUGIN_CFLAGS)
--- a/pidgin/plugins/gevolution/add_buddy_dialog.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/gevolution/add_buddy_dialog.c Sun Aug 18 01:53:00 2013 +0530 @@ -32,7 +32,7 @@ enum { COLUMN_NAME, - COLUMN_PRPL_ICON, + COLUMN_PROTOCOL_ICON, COLUMN_USERNAME, COLUMN_DATA, NUM_COLUMNS @@ -147,7 +147,7 @@ renderer = gtk_cell_renderer_pixbuf_new(); gtk_tree_view_column_pack_start(column, renderer, FALSE); gtk_tree_view_column_add_attribute(column, renderer, - "pixbuf", COLUMN_PRPL_ICON); + "pixbuf", COLUMN_PROTOCOL_ICON); /* Account name */ renderer = gtk_cell_renderer_text_new(); @@ -183,7 +183,7 @@ if (account == NULL) return; - pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); + pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL); for (l = list; l != NULL; l = l->next) { @@ -199,7 +199,7 @@ gtk_list_store_set(dialog->model, &iter, COLUMN_NAME, name, - COLUMN_PRPL_ICON, pixbuf, + COLUMN_PROTOCOL_ICON, pixbuf, COLUMN_USERNAME, account_name, COLUMN_DATA, contact, -1); @@ -602,13 +602,13 @@ GdkPixbuf *pixbuf; GtkTreeIter iter; - pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); + pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL); gtk_list_store_append(dialog->model, &iter); gtk_list_store_set(dialog->model, &iter, COLUMN_NAME, name, - COLUMN_PRPL_ICON, pixbuf, + COLUMN_PROTOCOL_ICON, pixbuf, COLUMN_DATA, contact, COLUMN_USERNAME, screenname, -1);
--- a/pidgin/plugins/gevolution/assoc-buddy.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/gevolution/assoc-buddy.c Sun Aug 18 01:53:00 2013 +0530 @@ -134,7 +134,7 @@ { EBook *book; EBookQuery *query; - const char *prpl_id; + const char *protocol_id; gboolean status; GList *cards, *c; GError *err = NULL; @@ -188,7 +188,7 @@ return; } - prpl_id = purple_account_get_protocol_id(dialog->buddy->account); + protocol_id = purple_account_get_protocol_id(dialog->buddy->account); for (c = cards; c != NULL; c = c->next) { @@ -207,7 +207,7 @@ -1); /* See if this user has the buddy in its list. */ - protocol_field = gevo_prpl_get_field(dialog->buddy->account, + protocol_field = gevo_protocol_get_field(dialog->buddy->account, dialog->buddy); if (protocol_field > 0) @@ -289,7 +289,7 @@ COLUMN_DATA, &contact, -1); - protocol_field = gevo_prpl_get_field(dialog->buddy->account, dialog->buddy); + protocol_field = gevo_protocol_get_field(dialog->buddy->account, dialog->buddy); if (protocol_field == 0) return; /* XXX */
--- a/pidgin/plugins/gevolution/eds-utils.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/gevolution/eds-utils.c Sun Aug 18 01:53:00 2013 +0530 @@ -177,7 +177,7 @@ EBookQuery *full_query; GSList *groups, *g; EContact *result; - EContactField protocol_field = gevo_prpl_get_field(buddy->account, buddy); + EContactField protocol_field = gevo_protocol_get_field(buddy->account, buddy); if (protocol_field == 0) return NULL;
--- a/pidgin/plugins/gevolution/gevo-util.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/gevolution/gevo-util.c Sun Aug 18 01:53:00 2013 +0530 @@ -90,7 +90,7 @@ } EContactField -gevo_prpl_get_field(PurpleAccount *account, PurpleBuddy *buddy) +gevo_protocol_get_field(PurpleAccount *account, PurpleBuddy *buddy) { EContactField protocol_field = 0; const char *protocol_id; @@ -118,9 +118,9 @@ } gboolean -gevo_prpl_is_supported(PurpleAccount *account, PurpleBuddy *buddy) +gevo_protocol_is_supported(PurpleAccount *account, PurpleBuddy *buddy) { - return (gevo_prpl_get_field(account, buddy) != 0); + return (gevo_protocol_get_field(account, buddy) != 0); } gboolean @@ -168,14 +168,14 @@ if (mail == NULL) { PurpleAccount *account = purple_buddy_get_account(buddy); - const char *prpl_id = purple_account_get_protocol_id(account); + const char *protocol_id = purple_account_get_protocol_id(account); - if (!strcmp(prpl_id, "prpl-msn")) + if (!strcmp(protocol_id, "prpl-msn")) { mail = g_strdup(purple_normalize(account, purple_buddy_get_name(buddy))); } - else if (!strcmp(prpl_id, "prpl-yahoo")) + else if (!strcmp(protocol_id, "prpl-yahoo")) { mail = g_strdup_printf("%s@yahoo.com", purple_normalize(account,
--- a/pidgin/plugins/gevolution/gevolution.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/gevolution/gevolution.c Sun Aug 18 01:53:00 2013 +0530 @@ -76,7 +76,7 @@ static void update_ims_from_contact(EContact *contact, const char *name, - const char *prpl_id, EContactField field) + const char *protocol_id, EContactField field) { GList *ims = e_contact_get(contact, field); GList *l, *l2; @@ -90,7 +90,7 @@ PurpleAccount *account = purple_connection_get_account(gc); char *me; - if (strcmp(purple_account_get_protocol_id(account), prpl_id)) + if (strcmp(purple_account_get_protocol_id(account), protocol_id)) continue; if (!purple_account_get_bool(account, "gevo-autoadd", FALSE)) @@ -274,7 +274,7 @@ buddy = PURPLE_BUDDY(node); account = purple_buddy_get_account(buddy); - if (!gevo_prpl_is_supported(account, buddy)) + if (!gevo_protocol_is_supported(account, buddy)) return; contact = gevo_search_buddy_in_contacts(buddy, NULL); @@ -489,7 +489,7 @@ gtk_list_store_append(model, &iter); - pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); + pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL); if ((pixbuf != NULL) && (!purple_account_is_connected(account))) gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
--- a/pidgin/plugins/gevolution/gevolution.h Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/gevolution/gevolution.h Sun Aug 18 01:53:00 2013 +0530 @@ -121,8 +121,8 @@ const char *screenname, const char *alias); GList *gevo_get_groups(void); -EContactField gevo_prpl_get_field(PurpleAccount *account, PurpleBuddy *buddy); -gboolean gevo_prpl_is_supported(PurpleAccount *account, PurpleBuddy *buddy); +EContactField gevo_protocol_get_field(PurpleAccount *account, PurpleBuddy *buddy); +gboolean gevo_protocol_is_supported(PurpleAccount *account, PurpleBuddy *buddy); gboolean gevo_load_addressbook(const gchar *uri, EBook **book, GError **error); char *gevo_get_email_for_buddy(PurpleBuddy *buddy);
--- a/pidgin/plugins/musicmessaging/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/musicmessaging/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -43,4 +43,5 @@ -I$(top_srcdir)/pidgin \ $(DEBUG_CFLAGS) \ $(GTK_CFLAGS) \ + $(GPLUGIN_CFLAGS) \ $(DBUS_CFLAGS)
--- a/pidgin/plugins/pidgininc.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/pidgininc.c Sun Aug 18 01:53:00 2013 +0530 @@ -1,5 +1,5 @@ #include "internal.h" -#include "plugin.h" +#include "plugins.h" #include "account.h" #include "connection.h"
--- a/pidgin/plugins/raw.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/raw.c Sun Aug 18 01:53:00 2013 +0530 @@ -26,7 +26,7 @@ #include "conversation.h" #include "debug.h" -#include "prpl.h" +#include "protocol.h" #include "version.h" #include "gtkplugin.h" @@ -59,7 +59,7 @@ { const char *txt; PurpleConnection *gc; - const char *prpl_id; + const char *protocol_id; if (account == NULL) return; @@ -68,11 +68,11 @@ txt = gtk_entry_get_text(entry); - prpl_id = purple_account_get_protocol_id(account); + protocol_id = purple_account_get_protocol_id(account); - purple_debug_misc("raw", "prpl_id = %s\n", prpl_id); + purple_debug_misc("raw", "protocol_id = %s\n", protocol_id); - if (strcmp(prpl_id, "prpl-toc") == 0) { + if (strcmp(protocol_id, "prpl-toc") == 0) { int *a = (int *)gc->proto_data; unsigned short seqno = htons(a[1]++ & 0xffff); unsigned short len = htons(strlen(txt) + 1); @@ -82,23 +82,23 @@ write(*a, txt, ntohs(len)); purple_debug(PURPLE_DEBUG_MISC, "raw", "TOC C: %s\n", txt); - } else if (strcmp(prpl_id, "prpl-msn") == 0) { + } else if (strcmp(protocol_id, "prpl-msn") == 0) { MsnSession *session = gc->proto_data; char buf[strlen(txt) + 3]; g_snprintf(buf, sizeof(buf), "%s\r\n", txt); msn_servconn_write(session->notification->servconn, buf, strlen(buf)); - } else if (strcmp(prpl_id, "prpl-irc") == 0) { + } else if (strcmp(protocol_id, "prpl-irc") == 0) { write(*(int *)gc->proto_data, txt, strlen(txt)); write(*(int *)gc->proto_data, "\r\n", 2); purple_debug(PURPLE_DEBUG_MISC, "raw", "IRC C: %s\n", txt); - } else if (strcmp(prpl_id, "prpl-jabber") == 0) { + } else if (strcmp(protocol_id, "prpl-jabber") == 0) { jabber_send_raw((JabberStream *)gc->proto_data, txt, -1); } else { - purple_debug_error("raw", "Unknown protocol ID %s\n", prpl_id); + purple_debug_error("raw", "Unknown protocol ID %s\n", protocol_id); } gtk_entry_set_text(entry, "");
--- a/pidgin/plugins/ticker/Makefile.am Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/ticker/Makefile.am Sun Aug 18 01:53:00 2013 +0530 @@ -24,4 +24,5 @@ -I$(top_builddir)/libpurple \ -I$(top_srcdir)/pidgin \ $(DEBUG_CFLAGS) \ - $(GTK_CFLAGS) + $(GTK_CFLAGS) \ + $(GPLUGIN_CFLAGS)
--- a/pidgin/plugins/ticker/ticker.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/ticker/ticker.c Sun Aug 18 01:53:00 2013 +0530 @@ -30,7 +30,7 @@ #include "buddylist.h" #include "conversation.h" #include "debug.h" -#include "prpl.h" +#include "protocol.h" #include "signals.h" #include "version.h"
--- a/pidgin/plugins/xmppconsole.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/plugins/xmppconsole.c Sun Aug 18 01:53:00 2013 +0530 @@ -22,7 +22,7 @@ #include "internal.h" #include "gtkplugin.h" #include "version.h" -#include "prpl.h" +#include "protocol.h" #include "xmlnode.h" #include "gtkimhtml.h" @@ -194,7 +194,7 @@ static gboolean message_send_cb(GtkWidget *widget, GdkEventKey *event, gpointer p) { - PurplePluginProtocolInfo *prpl_info = NULL; + PurpleProtocol *protocol = NULL; PurpleConnection *gc; gchar *text; @@ -204,12 +204,12 @@ gc = console->gc; if (gc) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)); + protocol = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_protocol_info(gc)); text = gtk_webview_get_body_text(GTK_WEBVIEW(widget)); - if (prpl_info && prpl_info->send_raw != NULL) - prpl_info->send_raw(gc, text, strlen(text)); + if (protocol && protocol->send_raw != NULL) + protocol->send_raw(gc, text, strlen(text)); g_free(text); gtk_webview_load_html_string(GTK_WEBVIEW(console->entry), ""); @@ -711,7 +711,7 @@ { PurplePlugin *jabber; - jabber = purple_find_prpl("prpl-jabber"); + jabber = purple_find_protocol_info("prpl-jabber"); if (!jabber) return FALSE;
--- a/pidgin/smileyparser.c Sun Aug 18 01:52:32 2013 +0530 +++ b/pidgin/smileyparser.c Sun Aug 18 01:53:00 2013 +0530 @@ -138,9 +138,9 @@ const char *proto_name = "default"; if (proto_id != NULL) { - PurplePlugin *proto; - proto = purple_find_prpl(proto_id); - proto_name = proto->info->name; + PurpleProtocol *protocol; + protocol = purple_find_protocol_info(proto_id); + proto_name = protocol->name; } /* unnecessarily slow, but lets manage for now. */