pidgin/pidgin

301b7d002cf1
Parents 91aacfd62b5f
Children a9b4409be267
Move purple plugins into their own subdirectories

Not sure if the trip though reviewboard will preserve the moves, so you might have to that yourself manually.

Testing Done:
Compile only.

Reviewed at https://reviews.imfreedom.org/r/1738/
--- a/libpurple/plugins/autoaccept.c Sun Sep 11 02:09:40 2022 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,340 +0,0 @@
-/*
- * Autoaccept - Auto-accept file transfers from selected users
- * Copyright (C) 2006
- *
- * 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 <glib/gi18n-lib.h>
-
-#define PLUGIN_ID "core-plugin_pack-autoaccept"
-#define PLUGIN_NAME N_("Autoaccept")
-#define PLUGIN_CATEGORY N_("Utility")
-#define PLUGIN_STATIC_NAME Autoaccept
-#define PLUGIN_SUMMARY N_("Auto-accept file transfer requests from selected users.")
-#define PLUGIN_DESCRIPTION N_("Auto-accept file transfer requests from selected users.")
-#define PLUGIN_AUTHORS {"Sadrul H Chowdhury <sadrul@users.sourceforge.net>", NULL}
-
-/* System headers */
-#include <glib.h>
-#include <glib/gstdio.h>
-
-#include <gplugin.h>
-#include <gplugin-native.h>
-
-#include <purple.h>
-
-#define PREF_PREFIX "/plugins/core/" PLUGIN_ID
-#define PREF_PATH PREF_PREFIX "/path"
-#define PREF_STRANGER PREF_PREFIX "/stranger"
-#define PREF_NOTIFY PREF_PREFIX "/notify"
-#define PREF_NEWDIR PREF_PREFIX "/newdir"
-#define PREF_ESCAPE PREF_PREFIX "/escape"
-
-#define PREF_STRANGER_OLD PREF_PREFIX "/reject_stranger"
-
-typedef enum
-{
- FT_ASK,
- FT_ACCEPT,
- FT_REJECT
-} AutoAcceptSetting;
-
-static gboolean
-ensure_path_exists(const char *dir)
-{
- if (!g_file_test(dir, G_FILE_TEST_IS_DIR))
- {
- if (g_mkdir_with_parents(dir, S_IRUSR | S_IWUSR | S_IXUSR)) {
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-static void
-auto_accept_complete_cb(PurpleXfer *xfer, G_GNUC_UNUSED GParamSpec *pspec,
- G_GNUC_UNUSED gpointer data)
-{
- PurpleConversationManager *manager = NULL;
-
- if (purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_DONE) {
- return;
- }
-
- manager = purple_conversation_manager_get_default();
-
- if(purple_prefs_get_bool(PREF_NOTIFY) &&
- !purple_conversation_manager_find_im(manager,
- purple_xfer_get_account(xfer),
- purple_xfer_get_remote_user(xfer)))
- {
- char *message = g_strdup_printf(_("Autoaccepted file transfer of \"%s\" from \"%s\" completed."),
- purple_xfer_get_filename(xfer), purple_xfer_get_remote_user(xfer));
- purple_notify_info(NULL, _("Autoaccept complete"), message,
- NULL, purple_request_cpar_from_account(
- purple_xfer_get_account(xfer)));
- g_free(message);
- }
-}
-
-static void
-file_recv_request_cb(PurpleXfer *xfer, gpointer handle)
-{
- PurpleAccount *account;
- PurpleBlistNode *node;
- const char *pref;
- char *filename;
- char *dirname;
-
- int accept_setting;
-
- account = purple_xfer_get_account(xfer);
- node = PURPLE_BLIST_NODE(purple_blist_find_buddy(account, purple_xfer_get_remote_user(xfer)));
-
- /* If person is on buddy list, use the buddy setting; otherwise, use the
- stranger setting. */
- if (node) {
- node = purple_blist_node_get_parent(node);
- g_return_if_fail(PURPLE_IS_CONTACT(node));
- accept_setting = purple_blist_node_get_int(node, "autoaccept");
- } else {
- accept_setting = purple_prefs_get_int(PREF_STRANGER);
- }
-
- switch (accept_setting)
- {
- case FT_ASK:
- break;
- case FT_ACCEPT:
- pref = purple_prefs_get_string(PREF_PATH);
- if (ensure_path_exists(pref))
- {
- int count = 1;
- const char *escape;
- gchar **name_and_ext;
- const gchar *name;
- gchar *ext;
-
- if (purple_prefs_get_bool(PREF_NEWDIR))
- dirname = g_build_filename(pref, purple_normalize(account, purple_xfer_get_remote_user(xfer)), NULL);
- else
- dirname = g_build_filename(pref, NULL);
-
- if (!ensure_path_exists(dirname))
- {
- g_free(dirname);
- break;
- }
-
- /* Escape filename (if escaping is turned on) */
- if (purple_prefs_get_bool(PREF_ESCAPE)) {
- escape = purple_escape_filename(purple_xfer_get_filename(xfer));
- } else {
- escape = purple_xfer_get_filename(xfer);
- }
- filename = g_build_filename(dirname, escape, NULL);
-
- /* Split at the first dot, to avoid uniquifying "foo.tar.gz" to "foo.tar-2.gz" */
- name_and_ext = g_strsplit(escape, ".", 2);
- name = name_and_ext[0];
- if (name == NULL) {
- g_strfreev(name_and_ext);
- g_return_if_reached();
- }
- if (name_and_ext[1] != NULL) {
- /* g_strsplit does not include the separator in each chunk. */
- ext = g_strdup_printf(".%s", name_and_ext[1]);
- } else {
- ext = g_strdup("");
- }
-
- /* Make sure the file doesn't exist. Do we want some better checking than this? */
- /* FIXME: There is a race here: if the newly uniquified file name gets created between
- * this g_file_test and the transfer starting, the file created in the meantime
- * will be clobbered. But it's not at all straightforward to fix.
- */
- while (g_file_test(filename, G_FILE_TEST_EXISTS)) {
- char *file = g_strdup_printf("%s-%d%s", name, count++, ext);
- g_free(filename);
- filename = g_build_filename(dirname, file, NULL);
- g_free(file);
- }
-
- purple_xfer_request_accepted(xfer, filename);
-
- g_strfreev(name_and_ext);
- g_free(ext);
- g_free(dirname);
- g_free(filename);
- }
-
- g_signal_connect(xfer, "notify::status",
- G_CALLBACK(auto_accept_complete_cb), NULL);
- break;
- case FT_REJECT:
- purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_LOCAL);
- break;
- }
-}
-
-static void
-save_cb(PurpleBlistNode *node, int choice)
-{
- if (PURPLE_IS_BUDDY(node))
- node = purple_blist_node_get_parent(node);
- g_return_if_fail(PURPLE_IS_CONTACT(node));
- purple_blist_node_set_int(node, "autoaccept", choice);
-}
-
-static void
-set_auto_accept_settings(PurpleBlistNode *node, gpointer plugin)
-{
- char *message;
-
- if (PURPLE_IS_BUDDY(node))
- node = purple_blist_node_get_parent(node);
- g_return_if_fail(PURPLE_IS_CONTACT(node));
-
- message = g_strdup_printf(_("When a file-transfer request arrives from %s"),
- purple_contact_get_alias(PURPLE_CONTACT(node)));
- purple_request_choice(plugin, _("Set Autoaccept Setting"), message,
- NULL, GINT_TO_POINTER(purple_blist_node_get_int(node, "autoaccept")),
- _("_Save"), G_CALLBACK(save_cb),
- _("_Cancel"), NULL,
- NULL, node,
- _("Ask"), GINT_TO_POINTER(FT_ASK),
- _("Auto Accept"), GINT_TO_POINTER(FT_ACCEPT),
- _("Auto Reject"), GINT_TO_POINTER(FT_REJECT),
- NULL);
- g_free(message);
-}
-
-static void
-context_menu(PurpleBlistNode *node, GList **menu, gpointer plugin)
-{
- PurpleActionMenu *action;
-
- if (!PURPLE_IS_BUDDY(node) && !PURPLE_IS_CONTACT(node) &&
- !purple_blist_node_is_transient(node))
- return;
-
- action = purple_action_menu_new(_("Autoaccept File Transfers..."),
- G_CALLBACK(set_auto_accept_settings), plugin, NULL);
- (*menu) = g_list_prepend(*menu, action);
-}
-
-static PurplePluginPrefFrame *
-get_plugin_pref_frame(PurplePlugin *plugin)
-{
- PurplePluginPrefFrame *frame;
- PurplePluginPref *pref;
-
- frame = purple_plugin_pref_frame_new();
-
- /* XXX: Is there a better way than this? There really should be. */
- pref = purple_plugin_pref_new_with_name_and_label(PREF_PATH, _("Path to save the files in\n"
- "(Please provide the full path)"));
- purple_plugin_pref_frame_add(frame, pref);
-
- pref = purple_plugin_pref_new_with_name_and_label(PREF_STRANGER,
- _("When a file-transfer request arrives from a user who is\n"
- "*not* on your buddy list:"));
- purple_plugin_pref_set_pref_type(pref, PURPLE_PLUGIN_PREF_CHOICE);
- purple_plugin_pref_add_choice(pref, _("Ask"), GINT_TO_POINTER(FT_ASK));
- purple_plugin_pref_add_choice(pref, _("Auto Accept"), GINT_TO_POINTER(FT_ACCEPT));
- purple_plugin_pref_add_choice(pref, _("Auto Reject"), GINT_TO_POINTER(FT_REJECT));
- purple_plugin_pref_frame_add(frame, pref);
-
- pref = purple_plugin_pref_new_with_name_and_label(PREF_NOTIFY,
- _("Notify with a popup when an autoaccepted file transfer is complete\n"
- "(only when there's no conversation with the sender)"));
- purple_plugin_pref_frame_add(frame, pref);
-
- pref = purple_plugin_pref_new_with_name_and_label(PREF_NEWDIR,
- _("Create a new directory for each user"));
- purple_plugin_pref_frame_add(frame, pref);
-
- pref = purple_plugin_pref_new_with_name_and_label(PREF_ESCAPE,
- _("Escape the filenames"));
- purple_plugin_pref_frame_add(frame, pref);
-
- return frame;
-}
-
-static GPluginPluginInfo *
-auto_accept_query(GError **error)
-{
- const gchar * const authors[] = PLUGIN_AUTHORS;
-
- return purple_plugin_info_new(
- "id", PLUGIN_ID,
- "name", PLUGIN_NAME,
- "version", DISPLAY_VERSION,
- "category", PLUGIN_CATEGORY,
- "summary", PLUGIN_SUMMARY,
- "description", PLUGIN_DESCRIPTION,
- "authors", authors,
- "website", PURPLE_WEBSITE,
- "abi-version", PURPLE_ABI_VERSION,
- "pref-frame-cb", get_plugin_pref_frame,
- NULL
- );
-}
-
-static gboolean
-auto_accept_load(GPluginPlugin *plugin, GError **error)
-{
- char *dirname;
-
- dirname = g_build_filename(g_get_user_special_dir(G_USER_DIRECTORY_DOWNLOAD), "autoaccept", NULL);
- purple_prefs_add_none(PREF_PREFIX);
- purple_prefs_add_string(PREF_PATH, dirname);
- purple_prefs_add_bool(PREF_NOTIFY, TRUE);
- purple_prefs_add_bool(PREF_NEWDIR, TRUE);
- purple_prefs_add_bool(PREF_ESCAPE, TRUE);
- g_free(dirname);
-
- /* migrate the old pref (we should only care if the plugin is actually *used*) */
- /*
- * TODO: We should eventually call purple_prefs_remove(PREFS_STRANGER_OLD)
- * to clean up after ourselves, but we don't want to do it yet
- * so that we don't break users who share a .purple directory
- * between old libpurple clients and new libpurple clients.
- * --Mark Doliner, 2011-01-03
- */
- if (!purple_prefs_exists(PREF_STRANGER)) {
- if (purple_prefs_exists(PREF_STRANGER_OLD) && purple_prefs_get_bool(PREF_STRANGER_OLD))
- purple_prefs_add_int(PREF_STRANGER, FT_REJECT);
- else
- purple_prefs_set_int(PREF_STRANGER, FT_ASK);
- }
-
- purple_signal_connect(purple_xfers_get_handle(), "file-recv-request", plugin,
- G_CALLBACK(file_recv_request_cb), plugin);
- purple_signal_connect(purple_blist_get_handle(), "blist-node-extended-menu", plugin,
- G_CALLBACK(context_menu), plugin);
- return TRUE;
-}
-
-static gboolean
-auto_accept_unload(GPluginPlugin *plugin, gboolean shutdown, GError **error)
-{
- return TRUE;
-}
-
-GPLUGIN_NATIVE_PLUGIN_DECLARE(auto_accept)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/autoaccept/autoaccept.c Mon Sep 12 04:49:23 2022 -0500
@@ -0,0 +1,340 @@
+/*
+ * Autoaccept - Auto-accept file transfers from selected users
+ * Copyright (C) 2006
+ *
+ * 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 <glib/gi18n-lib.h>
+
+#define PLUGIN_ID "core-plugin_pack-autoaccept"
+#define PLUGIN_NAME N_("Autoaccept")
+#define PLUGIN_CATEGORY N_("Utility")
+#define PLUGIN_STATIC_NAME Autoaccept
+#define PLUGIN_SUMMARY N_("Auto-accept file transfer requests from selected users.")
+#define PLUGIN_DESCRIPTION N_("Auto-accept file transfer requests from selected users.")
+#define PLUGIN_AUTHORS {"Sadrul H Chowdhury <sadrul@users.sourceforge.net>", NULL}
+
+/* System headers */
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include <gplugin.h>
+#include <gplugin-native.h>
+
+#include <purple.h>
+
+#define PREF_PREFIX "/plugins/core/" PLUGIN_ID
+#define PREF_PATH PREF_PREFIX "/path"
+#define PREF_STRANGER PREF_PREFIX "/stranger"
+#define PREF_NOTIFY PREF_PREFIX "/notify"
+#define PREF_NEWDIR PREF_PREFIX "/newdir"
+#define PREF_ESCAPE PREF_PREFIX "/escape"
+
+#define PREF_STRANGER_OLD PREF_PREFIX "/reject_stranger"
+
+typedef enum
+{
+ FT_ASK,
+ FT_ACCEPT,
+ FT_REJECT
+} AutoAcceptSetting;
+
+static gboolean
+ensure_path_exists(const char *dir)
+{
+ if (!g_file_test(dir, G_FILE_TEST_IS_DIR))
+ {
+ if (g_mkdir_with_parents(dir, S_IRUSR | S_IWUSR | S_IXUSR)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+auto_accept_complete_cb(PurpleXfer *xfer, G_GNUC_UNUSED GParamSpec *pspec,
+ G_GNUC_UNUSED gpointer data)
+{
+ PurpleConversationManager *manager = NULL;
+
+ if (purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_DONE) {
+ return;
+ }
+
+ manager = purple_conversation_manager_get_default();
+
+ if(purple_prefs_get_bool(PREF_NOTIFY) &&
+ !purple_conversation_manager_find_im(manager,
+ purple_xfer_get_account(xfer),
+ purple_xfer_get_remote_user(xfer)))
+ {
+ char *message = g_strdup_printf(_("Autoaccepted file transfer of \"%s\" from \"%s\" completed."),
+ purple_xfer_get_filename(xfer), purple_xfer_get_remote_user(xfer));
+ purple_notify_info(NULL, _("Autoaccept complete"), message,
+ NULL, purple_request_cpar_from_account(
+ purple_xfer_get_account(xfer)));
+ g_free(message);
+ }
+}
+
+static void
+file_recv_request_cb(PurpleXfer *xfer, gpointer handle)
+{
+ PurpleAccount *account;
+ PurpleBlistNode *node;
+ const char *pref;
+ char *filename;
+ char *dirname;
+
+ int accept_setting;
+
+ account = purple_xfer_get_account(xfer);
+ node = PURPLE_BLIST_NODE(purple_blist_find_buddy(account, purple_xfer_get_remote_user(xfer)));
+
+ /* If person is on buddy list, use the buddy setting; otherwise, use the
+ stranger setting. */
+ if (node) {
+ node = purple_blist_node_get_parent(node);
+ g_return_if_fail(PURPLE_IS_CONTACT(node));
+ accept_setting = purple_blist_node_get_int(node, "autoaccept");
+ } else {
+ accept_setting = purple_prefs_get_int(PREF_STRANGER);
+ }
+
+ switch (accept_setting)
+ {
+ case FT_ASK:
+ break;
+ case FT_ACCEPT:
+ pref = purple_prefs_get_string(PREF_PATH);
+ if (ensure_path_exists(pref))
+ {
+ int count = 1;
+ const char *escape;
+ gchar **name_and_ext;
+ const gchar *name;
+ gchar *ext;
+
+ if (purple_prefs_get_bool(PREF_NEWDIR))
+ dirname = g_build_filename(pref, purple_normalize(account, purple_xfer_get_remote_user(xfer)), NULL);
+ else
+ dirname = g_build_filename(pref, NULL);
+
+ if (!ensure_path_exists(dirname))
+ {
+ g_free(dirname);
+ break;
+ }
+
+ /* Escape filename (if escaping is turned on) */
+ if (purple_prefs_get_bool(PREF_ESCAPE)) {
+ escape = purple_escape_filename(purple_xfer_get_filename(xfer));
+ } else {
+ escape = purple_xfer_get_filename(xfer);
+ }
+ filename = g_build_filename(dirname, escape, NULL);
+
+ /* Split at the first dot, to avoid uniquifying "foo.tar.gz" to "foo.tar-2.gz" */
+ name_and_ext = g_strsplit(escape, ".", 2);
+ name = name_and_ext[0];
+ if (name == NULL) {
+ g_strfreev(name_and_ext);
+ g_return_if_reached();
+ }
+ if (name_and_ext[1] != NULL) {
+ /* g_strsplit does not include the separator in each chunk. */
+ ext = g_strdup_printf(".%s", name_and_ext[1]);
+ } else {
+ ext = g_strdup("");
+ }
+
+ /* Make sure the file doesn't exist. Do we want some better checking than this? */
+ /* FIXME: There is a race here: if the newly uniquified file name gets created between
+ * this g_file_test and the transfer starting, the file created in the meantime
+ * will be clobbered. But it's not at all straightforward to fix.
+ */
+ while (g_file_test(filename, G_FILE_TEST_EXISTS)) {
+ char *file = g_strdup_printf("%s-%d%s", name, count++, ext);
+ g_free(filename);
+ filename = g_build_filename(dirname, file, NULL);
+ g_free(file);
+ }
+
+ purple_xfer_request_accepted(xfer, filename);
+
+ g_strfreev(name_and_ext);
+ g_free(ext);
+ g_free(dirname);
+ g_free(filename);
+ }
+
+ g_signal_connect(xfer, "notify::status",
+ G_CALLBACK(auto_accept_complete_cb), NULL);
+ break;
+ case FT_REJECT:
+ purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_LOCAL);
+ break;
+ }
+}
+
+static void
+save_cb(PurpleBlistNode *node, int choice)
+{
+ if (PURPLE_IS_BUDDY(node))
+ node = purple_blist_node_get_parent(node);
+ g_return_if_fail(PURPLE_IS_CONTACT(node));
+ purple_blist_node_set_int(node, "autoaccept", choice);
+}
+
+static void
+set_auto_accept_settings(PurpleBlistNode *node, gpointer plugin)
+{
+ char *message;
+
+ if (PURPLE_IS_BUDDY(node))
+ node = purple_blist_node_get_parent(node);
+ g_return_if_fail(PURPLE_IS_CONTACT(node));
+
+ message = g_strdup_printf(_("When a file-transfer request arrives from %s"),
+ purple_contact_get_alias(PURPLE_CONTACT(node)));
+ purple_request_choice(plugin, _("Set Autoaccept Setting"), message,
+ NULL, GINT_TO_POINTER(purple_blist_node_get_int(node, "autoaccept")),
+ _("_Save"), G_CALLBACK(save_cb),
+ _("_Cancel"), NULL,
+ NULL, node,
+ _("Ask"), GINT_TO_POINTER(FT_ASK),
+ _("Auto Accept"), GINT_TO_POINTER(FT_ACCEPT),
+ _("Auto Reject"), GINT_TO_POINTER(FT_REJECT),
+ NULL);
+ g_free(message);
+}
+
+static void
+context_menu(PurpleBlistNode *node, GList **menu, gpointer plugin)
+{
+ PurpleActionMenu *action;
+
+ if (!PURPLE_IS_BUDDY(node) && !PURPLE_IS_CONTACT(node) &&
+ !purple_blist_node_is_transient(node))
+ return;
+
+ action = purple_action_menu_new(_("Autoaccept File Transfers..."),
+ G_CALLBACK(set_auto_accept_settings), plugin, NULL);
+ (*menu) = g_list_prepend(*menu, action);
+}
+
+static PurplePluginPrefFrame *
+get_plugin_pref_frame(PurplePlugin *plugin)
+{
+ PurplePluginPrefFrame *frame;
+ PurplePluginPref *pref;
+
+ frame = purple_plugin_pref_frame_new();
+
+ /* XXX: Is there a better way than this? There really should be. */
+ pref = purple_plugin_pref_new_with_name_and_label(PREF_PATH, _("Path to save the files in\n"
+ "(Please provide the full path)"));
+ purple_plugin_pref_frame_add(frame, pref);
+
+ pref = purple_plugin_pref_new_with_name_and_label(PREF_STRANGER,
+ _("When a file-transfer request arrives from a user who is\n"
+ "*not* on your buddy list:"));
+ purple_plugin_pref_set_pref_type(pref, PURPLE_PLUGIN_PREF_CHOICE);
+ purple_plugin_pref_add_choice(pref, _("Ask"), GINT_TO_POINTER(FT_ASK));
+ purple_plugin_pref_add_choice(pref, _("Auto Accept"), GINT_TO_POINTER(FT_ACCEPT));
+ purple_plugin_pref_add_choice(pref, _("Auto Reject"), GINT_TO_POINTER(FT_REJECT));
+ purple_plugin_pref_frame_add(frame, pref);
+
+ pref = purple_plugin_pref_new_with_name_and_label(PREF_NOTIFY,
+ _("Notify with a popup when an autoaccepted file transfer is complete\n"
+ "(only when there's no conversation with the sender)"));
+ purple_plugin_pref_frame_add(frame, pref);
+
+ pref = purple_plugin_pref_new_with_name_and_label(PREF_NEWDIR,
+ _("Create a new directory for each user"));
+ purple_plugin_pref_frame_add(frame, pref);
+
+ pref = purple_plugin_pref_new_with_name_and_label(PREF_ESCAPE,
+ _("Escape the filenames"));
+ purple_plugin_pref_frame_add(frame, pref);
+
+ return frame;
+}
+
+static GPluginPluginInfo *
+auto_accept_query(GError **error)
+{
+ const gchar * const authors[] = PLUGIN_AUTHORS;
+
+ return purple_plugin_info_new(
+ "id", PLUGIN_ID,
+ "name", PLUGIN_NAME,
+ "version", DISPLAY_VERSION,
+ "category", PLUGIN_CATEGORY,
+ "summary", PLUGIN_SUMMARY,
+ "description", PLUGIN_DESCRIPTION,
+ "authors", authors,
+ "website", PURPLE_WEBSITE,
+ "abi-version", PURPLE_ABI_VERSION,
+ "pref-frame-cb", get_plugin_pref_frame,
+ NULL
+ );
+}
+
+static gboolean
+auto_accept_load(GPluginPlugin *plugin, GError **error)
+{
+ char *dirname;
+
+ dirname = g_build_filename(g_get_user_special_dir(G_USER_DIRECTORY_DOWNLOAD), "autoaccept", NULL);
+ purple_prefs_add_none(PREF_PREFIX);
+ purple_prefs_add_string(PREF_PATH, dirname);
+ purple_prefs_add_bool(PREF_NOTIFY, TRUE);
+ purple_prefs_add_bool(PREF_NEWDIR, TRUE);
+ purple_prefs_add_bool(PREF_ESCAPE, TRUE);
+ g_free(dirname);
+
+ /* migrate the old pref (we should only care if the plugin is actually *used*) */
+ /*
+ * TODO: We should eventually call purple_prefs_remove(PREFS_STRANGER_OLD)
+ * to clean up after ourselves, but we don't want to do it yet
+ * so that we don't break users who share a .purple directory
+ * between old libpurple clients and new libpurple clients.
+ * --Mark Doliner, 2011-01-03
+ */
+ if (!purple_prefs_exists(PREF_STRANGER)) {
+ if (purple_prefs_exists(PREF_STRANGER_OLD) && purple_prefs_get_bool(PREF_STRANGER_OLD))
+ purple_prefs_add_int(PREF_STRANGER, FT_REJECT);
+ else
+ purple_prefs_set_int(PREF_STRANGER, FT_ASK);
+ }
+
+ purple_signal_connect(purple_xfers_get_handle(), "file-recv-request", plugin,
+ G_CALLBACK(file_recv_request_cb), plugin);
+ purple_signal_connect(purple_blist_get_handle(), "blist-node-extended-menu", plugin,
+ G_CALLBACK(context_menu), plugin);
+ return TRUE;
+}
+
+static gboolean
+auto_accept_unload(GPluginPlugin *plugin, gboolean shutdown, GError **error)
+{
+ return TRUE;
+}
+
+GPLUGIN_NATIVE_PLUGIN_DECLARE(auto_accept)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/autoaccept/meson.build Mon Sep 12 04:49:23 2022 -0500
@@ -0,0 +1,7 @@
+autoaccept = library('autoaccept', 'autoaccept.c',
+ c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="PurplePlugin-AutoAccept"'],
+ dependencies : [libpurple_dep, glib],
+ name_prefix : '',
+ install : true, install_dir : PURPLE_PLUGINDIR)
+
+devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir())
--- a/libpurple/plugins/buddynote.c Sun Sep 11 02:09:40 2022 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/*
- * BuddyNote - Store notes on particular buddies
- * Copyright (C) 2004 Stu Tomlinson <stu@nosnilmot.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 <glib/gi18n-lib.h>
-
-#include <gplugin.h>
-#include <gplugin-native.h>
-
-#include <purple.h>
-
-static void
-dont_do_it_cb(PurpleBlistNode *node, const char *note)
-{
-}
-
-static void
-do_it_cb(PurpleBlistNode *node, const char *note)
-{
- purple_blist_node_set_string(node, "notes", note);
-}
-
-static void
-buddynote_edit_cb(PurpleBlistNode *node, gpointer data)
-{
- const char *note;
-
- note = purple_blist_node_get_string(node, "notes");
-
- purple_request_input(node, _("Notes"),
- _("Enter your notes below..."),
- NULL,
- note, TRUE, FALSE, "html",
- _("Save"), G_CALLBACK(do_it_cb),
- _("Cancel"), G_CALLBACK(dont_do_it_cb),
- NULL, node);
-}
-
-static void
-buddynote_extended_menu_cb(PurpleBlistNode *node, GList **m)
-{
- PurpleActionMenu *bna = NULL;
-
- if (purple_blist_node_is_transient(node))
- return;
-
- *m = g_list_append(*m, bna);
- bna = purple_action_menu_new(_("Edit Notes..."), G_CALLBACK(buddynote_edit_cb), NULL, NULL);
- *m = g_list_append(*m, bna);
-}
-
-static GPluginPluginInfo *
-buddy_note_query(GError **error)
-{
- const gchar * const authors[] = {
- "Stu Tomlinson <stu@nosnilmot.com>",
- NULL
- };
-
- return purple_plugin_info_new(
- "id", "core-plugin_pack-buddynote",
- "name", N_("Buddy Notes"),
- "version", DISPLAY_VERSION,
- "category", N_("Utility"),
- "summary", N_("Store notes on particular buddies."),
- "description", N_("Adds the option to store notes for buddies on your "
- "buddy list."),
- "authors", authors,
- "website", PURPLE_WEBSITE,
- "abi-version", PURPLE_ABI_VERSION,
- NULL
- );
-}
-
-static gboolean
-buddy_note_load(GPluginPlugin *plugin, GError **error)
-{
-
- purple_signal_connect(purple_blist_get_handle(), "blist-node-extended-menu",
- plugin, G_CALLBACK(buddynote_extended_menu_cb), NULL);
-
- return TRUE;
-}
-
-static gboolean
-buddy_note_unload(GPluginPlugin *plugin, gboolean shutdown, GError **error)
-{
- return TRUE;
-}
-
-GPLUGIN_NATIVE_PLUGIN_DECLARE(buddy_note)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/buddynote/buddynote.c Mon Sep 12 04:49:23 2022 -0500
@@ -0,0 +1,105 @@
+/*
+ * BuddyNote - Store notes on particular buddies
+ * Copyright (C) 2004 Stu Tomlinson <stu@nosnilmot.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 <glib/gi18n-lib.h>
+
+#include <gplugin.h>
+#include <gplugin-native.h>
+
+#include <purple.h>
+
+static void
+dont_do_it_cb(PurpleBlistNode *node, const char *note)
+{
+}
+
+static void
+do_it_cb(PurpleBlistNode *node, const char *note)
+{
+ purple_blist_node_set_string(node, "notes", note);
+}
+
+static void
+buddynote_edit_cb(PurpleBlistNode *node, gpointer data)
+{
+ const char *note;
+
+ note = purple_blist_node_get_string(node, "notes");
+
+ purple_request_input(node, _("Notes"),
+ _("Enter your notes below..."),
+ NULL,
+ note, TRUE, FALSE, "html",
+ _("Save"), G_CALLBACK(do_it_cb),
+ _("Cancel"), G_CALLBACK(dont_do_it_cb),
+ NULL, node);
+}
+
+static void
+buddynote_extended_menu_cb(PurpleBlistNode *node, GList **m)
+{
+ PurpleActionMenu *bna = NULL;
+
+ if (purple_blist_node_is_transient(node))
+ return;
+
+ *m = g_list_append(*m, bna);
+ bna = purple_action_menu_new(_("Edit Notes..."), G_CALLBACK(buddynote_edit_cb), NULL, NULL);
+ *m = g_list_append(*m, bna);
+}
+
+static GPluginPluginInfo *
+buddy_note_query(GError **error)
+{
+ const gchar * const authors[] = {
+ "Stu Tomlinson <stu@nosnilmot.com>",
+ NULL
+ };
+
+ return purple_plugin_info_new(
+ "id", "core-plugin_pack-buddynote",
+ "name", N_("Buddy Notes"),
+ "version", DISPLAY_VERSION,
+ "category", N_("Utility"),
+ "summary", N_("Store notes on particular buddies."),
+ "description", N_("Adds the option to store notes for buddies on your "
+ "buddy list."),
+ "authors", authors,
+ "website", PURPLE_WEBSITE,
+ "abi-version", PURPLE_ABI_VERSION,
+ NULL
+ );
+}
+
+static gboolean
+buddy_note_load(GPluginPlugin *plugin, GError **error)
+{
+
+ purple_signal_connect(purple_blist_get_handle(), "blist-node-extended-menu",
+ plugin, G_CALLBACK(buddynote_extended_menu_cb), NULL);
+
+ return TRUE;
+}
+
+static gboolean
+buddy_note_unload(GPluginPlugin *plugin, gboolean shutdown, GError **error)
+{
+ return TRUE;
+}
+
+GPLUGIN_NATIVE_PLUGIN_DECLARE(buddy_note)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/buddynote/meson.build Mon Sep 12 04:49:23 2022 -0500
@@ -0,0 +1,7 @@
+buddynote = library('buddynote', 'buddynote.c',
+ c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="PurplePlugin-BuddyNote"'],
+ dependencies : [libpurple_dep],
+ name_prefix : '',
+ install : true, install_dir : PURPLE_PLUGINDIR)
+
+devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir())
--- a/libpurple/plugins/idle.c Sun Sep 11 02:09:40 2022 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,332 +0,0 @@
-/*
- * idle.c - I'dle Mak'er plugin for Purple
- *
- * This file is part of 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 <glib/gi18n-lib.h>
-
-#include <gplugin.h>
-#include <gplugin-native.h>
-
-#include <purple.h>
-
-/* This plugin no longer depends on gtk */
-#define IDLE_PLUGIN_ID "core-idle"
-
-static GList *idled_accts = NULL;
-
-static gboolean
-unidle_filter(PurpleAccount *acct)
-{
- if (g_list_find(idled_accts, acct))
- return TRUE;
-
- return FALSE;
-}
-
-static gboolean
-idleable_filter(PurpleAccount *account)
-{
- PurpleProtocol *protocol;
-
- protocol = purple_account_get_protocol(account);
- g_return_val_if_fail(protocol != NULL, FALSE);
-
- return PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER, set_idle);
-}
-
-static void
-set_idle_time(PurpleAccount *acct, int mins_idle)
-{
- time_t t;
- PurpleConnection *gc = purple_account_get_connection(acct);
- PurplePresence *presence = purple_account_get_presence(acct);
-
- if (!gc)
- return;
-
- purple_debug_info("idle",
- "setting idle time for %s to %d\n",
- purple_account_get_username(acct), mins_idle);
-
- if (mins_idle)
- t = time(NULL) - (60 * mins_idle); /* subtract seconds idle from current time */
- else
- t = 0; /* time idle is irrelevant */
-
- purple_presence_set_idle(presence, mins_idle ? TRUE : FALSE, t);
-}
-
-static void
-idle_action_ok(void *ignored, PurpleRequestFields *fields)
-{
- int tm = purple_request_fields_get_integer(fields, "mins");
- PurpleAccount *acct = purple_request_fields_get_account(fields, "acct");
-
- /* only add the account to the GList if it's not already been idled */
- if (!unidle_filter(acct))
- {
- purple_debug_misc("idle",
- "%s hasn't been idled yet; adding to list.\n",
- purple_account_get_username(acct));
- idled_accts = g_list_append(idled_accts, acct);
- }
-
- set_idle_time(acct, tm);
-}
-
-static void
-idle_all_action_ok(void *ignored, PurpleRequestFields *fields)
-{
- PurpleAccountManager *manager = NULL;
- PurpleAccount *acct = NULL;
- GList *list, *iter;
- int tm = purple_request_fields_get_integer(fields, "mins");
-
- manager = purple_account_manager_get_default();
- list = purple_account_manager_get_enabled(manager);
- for(iter = list; iter; iter = iter->next) {
- acct = (PurpleAccount *)(iter->data);
-
- if(acct && idleable_filter(acct)) {
- purple_debug_misc("idle", "Idling %s.\n",
- purple_account_get_username(acct));
-
- set_idle_time(acct, tm);
-
- if(!g_list_find(idled_accts, acct))
- idled_accts = g_list_append(idled_accts, acct);
- }
- }
-
- g_list_free(list);
-}
-
-static void
-unidle_action_ok(void *ignored, PurpleRequestFields *fields)
-{
- PurpleAccount *acct = purple_request_fields_get_account(fields, "acct");
-
- set_idle_time(acct, 0); /* unidle the account */
-
- /* once the account has been unidled it shouldn't be in the list */
- idled_accts = g_list_remove(idled_accts, acct);
-}
-
-static void
-signing_off_cb(PurpleConnection *gc, void *data)
-{
- PurpleAccount *account;
-
- account = purple_connection_get_account(gc);
- idled_accts = g_list_remove(idled_accts, account);
-}
-
-/******************************************************************************
- * Actions
- *****************************************************************************/
-static void
-purple_idle_set_account_idle_time(G_GNUC_UNUSED GSimpleAction *action,
- G_GNUC_UNUSED GVariant *parameter,
- gpointer data)
-{
- /* Use the super fancy request API */
-
- PurpleRequestFields *request;
- PurpleRequestFieldGroup *group;
- PurpleRequestField *field;
-
- group = purple_request_field_group_new(NULL);
-
- field = purple_request_field_account_new("acct", _("Account"), NULL);
- purple_request_field_account_set_filter(field, idleable_filter);
- purple_request_field_account_set_show_all(field, FALSE);
- purple_request_field_group_add_field(group, field);
-
- field = purple_request_field_int_new("mins", _("Minutes"), 10, 0, 9999);
- purple_request_field_group_add_field(group, field);
-
- request = purple_request_fields_new();
- purple_request_fields_add_group(request, group);
-
- purple_request_fields(data,
- N_("I'dle Mak'er"),
- _("Set Account Idle Time"),
- NULL,
- request,
- _("_Set"), G_CALLBACK(idle_action_ok),
- _("_Cancel"), NULL,
- NULL, NULL);
-}
-
-static void
-purple_idle_unset_account_idle_time(G_GNUC_UNUSED GSimpleAction *action,
- G_GNUC_UNUSED GVariant *parameter,
- gpointer data)
-{
- PurpleRequestFields *request;
- PurpleRequestFieldGroup *group;
- PurpleRequestField *field;
-
- if (idled_accts == NULL)
- {
- purple_notify_info(NULL, NULL, _("None of your accounts are idle."), NULL, NULL);
- return;
- }
-
- group = purple_request_field_group_new(NULL);
-
- field = purple_request_field_account_new("acct", _("Account"), NULL);
- purple_request_field_account_set_filter(field, unidle_filter);
- purple_request_field_account_set_show_all(field, FALSE);
- purple_request_field_group_add_field(group, field);
-
- request = purple_request_fields_new();
- purple_request_fields_add_group(request, group);
-
- purple_request_fields(data,
- N_("I'dle Mak'er"),
- _("Unset Account Idle Time"),
- NULL,
- request,
- _("_Unset"), G_CALLBACK(unidle_action_ok),
- _("_Cancel"), NULL,
- NULL, NULL);
-}
-
-static void
-purple_idle_set_all_accounts_idle_time(G_GNUC_UNUSED GSimpleAction *action,
- G_GNUC_UNUSED GVariant *parameter,
- gpointer data)
-{
- PurpleRequestFields *request;
- PurpleRequestFieldGroup *group;
- PurpleRequestField *field;
-
- group = purple_request_field_group_new(NULL);
-
- field = purple_request_field_int_new("mins", _("Minutes"), 10, 0, 9999);
- purple_request_field_group_add_field(group, field);
-
- request = purple_request_fields_new();
- purple_request_fields_add_group(request, group);
-
- purple_request_fields(data,
- N_("I'dle Mak'er"),
- _("Set Idle Time for All Accounts"),
- NULL,
- request,
- _("_Set"), G_CALLBACK(idle_all_action_ok),
- _("_Cancel"), NULL,
- NULL, NULL);
-}
-
-static void
-purple_idle_unset_all_accounts_idle_time(G_GNUC_UNUSED GSimpleAction *action,
- G_GNUC_UNUSED GVariant *parameter,
- G_GNUC_UNUSED gpointer data)
-{
- /* freeing the list here will cause segfaults if the user idles an account
- * after the list is freed */
- g_list_foreach(idled_accts, (GFunc)set_idle_time, GINT_TO_POINTER(0));
- g_list_free(idled_accts);
- idled_accts = NULL;
-}
-
-/******************************************************************************
- * GPlugin Exports
- *****************************************************************************/
-static GPluginPluginInfo *
-idle_query(GError **error)
-{
- GSimpleActionGroup *group = NULL;
- GActionEntry entries[] = {
- {
- .name = "set-account-idle-time",
- .activate = purple_idle_set_account_idle_time,
- }, {
- .name = "unset-account-idle-time",
- .activate = purple_idle_unset_account_idle_time,
- }, {
- .name = "set-all-accounts-idle-time",
- .activate = purple_idle_set_all_accounts_idle_time,
- }, {
- .name = "unset-all-accounts-idle-time",
- .activate = purple_idle_unset_all_accounts_idle_time,
- }
- };
- GMenu *menu = NULL;
- const gchar * const authors[] = {
- "Eric Warmenhoven <eric@warmenhoven.org>",
- NULL
- };
-
- group = g_simple_action_group_new();
- g_action_map_add_action_entries(G_ACTION_MAP(group), entries,
- G_N_ELEMENTS(entries), NULL);
-
- menu = g_menu_new();
- g_menu_append(menu, _("Set Account Idle Time"), "set-account-idle-time");
- g_menu_append(menu, _("Unset Account Idle Time"),
- "unset-account-idle-time");
- g_menu_append(menu, _("Set Idle Time for All Accounts"),
- "set-all-accounts-idle-time");
- g_menu_append(menu, _("Unset Idle Time for All Idled Accounts"),
- "unset-all-accounts-idle-time");
-
- return purple_plugin_info_new(
- "id", IDLE_PLUGIN_ID,
- /* This is a cultural reference. Dy'er Mak'er is a song by Led Zeppelin.
- If that doesn't translate well into your language, drop the 's before translating. */
- "name", N_("I'dle Mak'er"),
- "version", DISPLAY_VERSION,
- "category", N_("Utility"),
- "summary", N_("Allows you to hand-configure how long you've been idle"),
- "description", N_("Allows you to hand-configure how long you've been idle"),
- "authors", authors,
- "website", PURPLE_WEBSITE,
- "abi-version", PURPLE_ABI_VERSION,
- "action-group", group,
- "action-menu", menu,
- NULL
- );
-}
-
-static gboolean
-idle_load(GPluginPlugin *plugin, GError **error)
-{
- purple_signal_connect(purple_connections_get_handle(), "signing-off",
- plugin,
- G_CALLBACK(signing_off_cb), NULL);
-
- return TRUE;
-}
-
-static gboolean
-idle_unload(GPluginPlugin *plugin, gboolean shutdown, GError **error)
-{
- purple_idle_unset_all_accounts_idle_time(NULL, NULL, NULL);
-
- return TRUE;
-}
-
-GPLUGIN_NATIVE_PLUGIN_DECLARE(idle);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/idle/idle.c Mon Sep 12 04:49:23 2022 -0500
@@ -0,0 +1,332 @@
+/*
+ * idle.c - I'dle Mak'er plugin for Purple
+ *
+ * This file is part of 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 <glib/gi18n-lib.h>
+
+#include <gplugin.h>
+#include <gplugin-native.h>
+
+#include <purple.h>
+
+/* This plugin no longer depends on gtk */
+#define IDLE_PLUGIN_ID "core-idle"
+
+static GList *idled_accts = NULL;
+
+static gboolean
+unidle_filter(PurpleAccount *acct)
+{
+ if (g_list_find(idled_accts, acct))
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean
+idleable_filter(PurpleAccount *account)
+{
+ PurpleProtocol *protocol;
+
+ protocol = purple_account_get_protocol(account);
+ g_return_val_if_fail(protocol != NULL, FALSE);
+
+ return PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER, set_idle);
+}
+
+static void
+set_idle_time(PurpleAccount *acct, int mins_idle)
+{
+ time_t t;
+ PurpleConnection *gc = purple_account_get_connection(acct);
+ PurplePresence *presence = purple_account_get_presence(acct);
+
+ if (!gc)
+ return;
+
+ purple_debug_info("idle",
+ "setting idle time for %s to %d\n",
+ purple_account_get_username(acct), mins_idle);
+
+ if (mins_idle)
+ t = time(NULL) - (60 * mins_idle); /* subtract seconds idle from current time */
+ else
+ t = 0; /* time idle is irrelevant */
+
+ purple_presence_set_idle(presence, mins_idle ? TRUE : FALSE, t);
+}
+
+static void
+idle_action_ok(void *ignored, PurpleRequestFields *fields)
+{
+ int tm = purple_request_fields_get_integer(fields, "mins");
+ PurpleAccount *acct = purple_request_fields_get_account(fields, "acct");
+
+ /* only add the account to the GList if it's not already been idled */
+ if (!unidle_filter(acct))
+ {
+ purple_debug_misc("idle",
+ "%s hasn't been idled yet; adding to list.\n",
+ purple_account_get_username(acct));
+ idled_accts = g_list_append(idled_accts, acct);
+ }
+
+ set_idle_time(acct, tm);
+}
+
+static void
+idle_all_action_ok(void *ignored, PurpleRequestFields *fields)
+{
+ PurpleAccountManager *manager = NULL;
+ PurpleAccount *acct = NULL;
+ GList *list, *iter;
+ int tm = purple_request_fields_get_integer(fields, "mins");
+
+ manager = purple_account_manager_get_default();
+ list = purple_account_manager_get_enabled(manager);
+ for(iter = list; iter; iter = iter->next) {
+ acct = (PurpleAccount *)(iter->data);
+
+ if(acct && idleable_filter(acct)) {
+ purple_debug_misc("idle", "Idling %s.\n",
+ purple_account_get_username(acct));
+
+ set_idle_time(acct, tm);
+
+ if(!g_list_find(idled_accts, acct))
+ idled_accts = g_list_append(idled_accts, acct);
+ }
+ }
+
+ g_list_free(list);
+}
+
+static void
+unidle_action_ok(void *ignored, PurpleRequestFields *fields)
+{
+ PurpleAccount *acct = purple_request_fields_get_account(fields, "acct");
+
+ set_idle_time(acct, 0); /* unidle the account */
+
+ /* once the account has been unidled it shouldn't be in the list */
+ idled_accts = g_list_remove(idled_accts, acct);
+}
+
+static void
+signing_off_cb(PurpleConnection *gc, void *data)
+{
+ PurpleAccount *account;
+
+ account = purple_connection_get_account(gc);
+ idled_accts = g_list_remove(idled_accts, account);
+}
+
+/******************************************************************************
+ * Actions
+ *****************************************************************************/
+static void
+purple_idle_set_account_idle_time(G_GNUC_UNUSED GSimpleAction *action,
+ G_GNUC_UNUSED GVariant *parameter,
+ gpointer data)
+{
+ /* Use the super fancy request API */
+
+ PurpleRequestFields *request;
+ PurpleRequestFieldGroup *group;
+ PurpleRequestField *field;
+
+ group = purple_request_field_group_new(NULL);
+
+ field = purple_request_field_account_new("acct", _("Account"), NULL);
+ purple_request_field_account_set_filter(field, idleable_filter);
+ purple_request_field_account_set_show_all(field, FALSE);
+ purple_request_field_group_add_field(group, field);
+
+ field = purple_request_field_int_new("mins", _("Minutes"), 10, 0, 9999);
+ purple_request_field_group_add_field(group, field);
+
+ request = purple_request_fields_new();
+ purple_request_fields_add_group(request, group);
+
+ purple_request_fields(data,
+ N_("I'dle Mak'er"),
+ _("Set Account Idle Time"),
+ NULL,
+ request,
+ _("_Set"), G_CALLBACK(idle_action_ok),
+ _("_Cancel"), NULL,
+ NULL, NULL);
+}
+
+static void
+purple_idle_unset_account_idle_time(G_GNUC_UNUSED GSimpleAction *action,
+ G_GNUC_UNUSED GVariant *parameter,
+ gpointer data)
+{
+ PurpleRequestFields *request;
+ PurpleRequestFieldGroup *group;
+ PurpleRequestField *field;
+
+ if (idled_accts == NULL)
+ {
+ purple_notify_info(NULL, NULL, _("None of your accounts are idle."), NULL, NULL);
+ return;
+ }
+
+ group = purple_request_field_group_new(NULL);
+
+ field = purple_request_field_account_new("acct", _("Account"), NULL);
+ purple_request_field_account_set_filter(field, unidle_filter);
+ purple_request_field_account_set_show_all(field, FALSE);
+ purple_request_field_group_add_field(group, field);
+
+ request = purple_request_fields_new();
+ purple_request_fields_add_group(request, group);
+
+ purple_request_fields(data,
+ N_("I'dle Mak'er"),
+ _("Unset Account Idle Time"),
+ NULL,
+ request,
+ _("_Unset"), G_CALLBACK(unidle_action_ok),
+ _("_Cancel"), NULL,
+ NULL, NULL);
+}
+
+static void
+purple_idle_set_all_accounts_idle_time(G_GNUC_UNUSED GSimpleAction *action,
+ G_GNUC_UNUSED GVariant *parameter,
+ gpointer data)
+{
+ PurpleRequestFields *request;
+ PurpleRequestFieldGroup *group;
+ PurpleRequestField *field;
+
+ group = purple_request_field_group_new(NULL);
+
+ field = purple_request_field_int_new("mins", _("Minutes"), 10, 0, 9999);
+ purple_request_field_group_add_field(group, field);
+
+ request = purple_request_fields_new();
+ purple_request_fields_add_group(request, group);
+
+ purple_request_fields(data,
+ N_("I'dle Mak'er"),
+ _("Set Idle Time for All Accounts"),
+ NULL,
+ request,
+ _("_Set"), G_CALLBACK(idle_all_action_ok),
+ _("_Cancel"), NULL,
+ NULL, NULL);
+}
+
+static void
+purple_idle_unset_all_accounts_idle_time(G_GNUC_UNUSED GSimpleAction *action,
+ G_GNUC_UNUSED GVariant *parameter,
+ G_GNUC_UNUSED gpointer data)
+{
+ /* freeing the list here will cause segfaults if the user idles an account
+ * after the list is freed */
+ g_list_foreach(idled_accts, (GFunc)set_idle_time, GINT_TO_POINTER(0));
+ g_list_free(idled_accts);
+ idled_accts = NULL;
+}
+
+/******************************************************************************
+ * GPlugin Exports
+ *****************************************************************************/
+static GPluginPluginInfo *
+idle_query(GError **error)
+{
+ GSimpleActionGroup *group = NULL;
+ GActionEntry entries[] = {
+ {
+ .name = "set-account-idle-time",
+ .activate = purple_idle_set_account_idle_time,
+ }, {
+ .name = "unset-account-idle-time",
+ .activate = purple_idle_unset_account_idle_time,
+ }, {
+ .name = "set-all-accounts-idle-time",
+ .activate = purple_idle_set_all_accounts_idle_time,
+ }, {
+ .name = "unset-all-accounts-idle-time",
+ .activate = purple_idle_unset_all_accounts_idle_time,
+ }
+ };
+ GMenu *menu = NULL;
+ const gchar * const authors[] = {
+ "Eric Warmenhoven <eric@warmenhoven.org>",
+ NULL
+ };
+
+ group = g_simple_action_group_new();
+ g_action_map_add_action_entries(G_ACTION_MAP(group), entries,
+ G_N_ELEMENTS(entries), NULL);
+
+ menu = g_menu_new();
+ g_menu_append(menu, _("Set Account Idle Time"), "set-account-idle-time");
+ g_menu_append(menu, _("Unset Account Idle Time"),
+ "unset-account-idle-time");
+ g_menu_append(menu, _("Set Idle Time for All Accounts"),
+ "set-all-accounts-idle-time");
+ g_menu_append(menu, _("Unset Idle Time for All Idled Accounts"),
+ "unset-all-accounts-idle-time");
+
+ return purple_plugin_info_new(
+ "id", IDLE_PLUGIN_ID,
+ /* This is a cultural reference. Dy'er Mak'er is a song by Led Zeppelin.
+ If that doesn't translate well into your language, drop the 's before translating. */
+ "name", N_("I'dle Mak'er"),
+ "version", DISPLAY_VERSION,
+ "category", N_("Utility"),
+ "summary", N_("Allows you to hand-configure how long you've been idle"),
+ "description", N_("Allows you to hand-configure how long you've been idle"),
+ "authors", authors,
+ "website", PURPLE_WEBSITE,
+ "abi-version", PURPLE_ABI_VERSION,
+ "action-group", group,
+ "action-menu", menu,
+ NULL
+ );
+}
+
+static gboolean
+idle_load(GPluginPlugin *plugin, GError **error)
+{
+ purple_signal_connect(purple_connections_get_handle(), "signing-off",
+ plugin,
+ G_CALLBACK(signing_off_cb), NULL);
+
+ return TRUE;
+}
+
+static gboolean
+idle_unload(GPluginPlugin *plugin, gboolean shutdown, GError **error)
+{
+ purple_idle_unset_all_accounts_idle_time(NULL, NULL, NULL);
+
+ return TRUE;
+}
+
+GPLUGIN_NATIVE_PLUGIN_DECLARE(idle);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/idle/meson.build Mon Sep 12 04:49:23 2022 -0500
@@ -0,0 +1,7 @@
+idle = library('idle', 'idle.c',
+ c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="PurplePlugin-Idle"'],
+ dependencies : [libpurple_dep],
+ name_prefix : '',
+ install : true, install_dir : PURPLE_PLUGINDIR)
+
+devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir())
--- a/libpurple/plugins/joinpart.c Sun Sep 11 02:09:40 2022 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,281 +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 <glib/gi18n-lib.h>
-
-#include <gplugin.h>
-#include <gplugin-native.h>
-
-#include <purple.h>
-
-#define JOINPART_PLUGIN_ID "core-rlaager-joinpart"
-
-
-/* Preferences */
-
-/* The number of minutes before a person is considered
- * to have stopped being part of active conversation. */
-#define DELAY_PREF "/plugins/core/joinpart/delay"
-#define DELAY_DEFAULT 10
-
-/* The number of people that must be in a room for this
- * plugin to have any effect */
-#define THRESHOLD_PREF "/plugins/core/joinpart/threshold"
-#define THRESHOLD_DEFAULT 20
-
-/* Hide buddies */
-#define HIDE_BUDDIES_PREF "/plugins/core/joinpart/hide_buddies"
-#define HIDE_BUDDIES_DEFAULT FALSE
-
-struct joinpart_key
-{
- PurpleConversation *conv;
- char *user;
-};
-
-static guint joinpart_key_hash(const struct joinpart_key *key)
-{
- g_return_val_if_fail(key != NULL, 0);
-
- return g_direct_hash(key->conv) + g_str_hash(key->user);
-}
-
-static gboolean joinpart_key_equal(const struct joinpart_key *a, const struct joinpart_key *b)
-{
- if (a == NULL)
- return (b == NULL);
- else if (b == NULL)
- return FALSE;
-
- return (a->conv == b->conv) && purple_strequal(a->user, b->user);
-}
-
-static void joinpart_key_destroy(struct joinpart_key *key)
-{
- g_return_if_fail(key != NULL);
-
- g_free(key->user);
- g_free(key);
-}
-
-static gboolean should_hide_notice(PurpleConversation *conv, const char *name,
- GHashTable *users)
-{
- PurpleChatConversation *chat;
- guint threshold;
- struct joinpart_key key;
- time_t *last_said;
-
- g_return_val_if_fail(conv != NULL, FALSE);
- g_return_val_if_fail(PURPLE_IS_CHAT_CONVERSATION(conv), FALSE);
-
- /* If the room is small, don't bother. */
- chat = PURPLE_CHAT_CONVERSATION(conv);
- threshold = purple_prefs_get_int(THRESHOLD_PREF);
- if (purple_chat_conversation_get_users_count(chat) < threshold)
- return FALSE;
-
- if (!purple_prefs_get_bool(HIDE_BUDDIES_PREF) &&
- purple_blist_find_buddy(purple_conversation_get_account(conv), name))
- return FALSE;
-
- /* Only show the notice if the user has spoken recently. */
- key.conv = conv;
- key.user = (gchar *)name;
- last_said = g_hash_table_lookup(users, &key);
- if (last_said != NULL)
- {
- int delay = purple_prefs_get_int(DELAY_PREF);
- if (delay > 0 && (*last_said + (delay * 60)) >= time(NULL))
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean chat_user_leaving_cb(PurpleConversation *conv, const char *name,
- const char *reason, GHashTable *users)
-{
- return should_hide_notice(conv, name, users);
-}
-
-static gboolean chat_user_joining_cb(PurpleConversation *conv, const char *name,
- PurpleChatUserFlags flags,
- GHashTable *users)
-{
- return should_hide_notice(conv, name, users);
-}
-
-static void received_chat_msg_cb(PurpleAccount *account, char *sender,
- char *message, PurpleConversation *conv,
- PurpleMessageFlags flags, GHashTable *users)
-{
- struct joinpart_key key;
- time_t *last_said;
-
- /* Most of the time, we'll already have tracked the user,
- * so we avoid memory allocation here. */
- key.conv = conv;
- key.user = sender;
- last_said = g_hash_table_lookup(users, &key);
- if (last_said != NULL)
- {
- /* They just said something, so update the time. */
- time(last_said);
- }
- else
- {
- struct joinpart_key *key2;
-
- key2 = g_new(struct joinpart_key, 1);
- key2->conv = conv;
- key2->user = g_strdup(sender);
-
- last_said = g_new(time_t, 1);
- time(last_said);
-
- g_hash_table_insert(users, key2, last_said);
- }
-}
-
-static gboolean check_expire_time(struct joinpart_key *key,
- time_t *last_said, time_t *limit)
-{
- purple_debug_info("joinpart", "Removing key for %s\n", key->user);
- return (*last_said < *limit);
-}
-
-static gboolean clean_users_hash(GHashTable *users)
-{
- int delay = purple_prefs_get_int(DELAY_PREF);
- time_t limit = time(NULL) - (60 * delay);
-
- g_hash_table_foreach_remove(users, (GHRFunc)check_expire_time, &limit);
-
- return TRUE;
-}
-
-static PurplePluginPrefFrame *
-get_plugin_pref_frame(PurplePlugin *plugin)
-{
- PurplePluginPrefFrame *frame;
- PurplePluginPref *ppref;
-
- g_return_val_if_fail(plugin != NULL, FALSE);
-
- frame = purple_plugin_pref_frame_new();
-
- ppref = purple_plugin_pref_new_with_label(_("Hide Joins/Parts"));
- purple_plugin_pref_frame_add(frame, ppref);
-
- ppref = purple_plugin_pref_new_with_name_and_label(THRESHOLD_PREF,
- /* Translators: Followed by an input request a number of people */
- _("For rooms with more than this many people"));
- purple_plugin_pref_set_bounds(ppref, 0, 1000);
- purple_plugin_pref_frame_add(frame, ppref);
-
- ppref = purple_plugin_pref_new_with_name_and_label(DELAY_PREF,
- _("If user has not spoken in this many minutes"));
- purple_plugin_pref_set_bounds(ppref, 0, 8 * 60); /* 8 Hours */
- purple_plugin_pref_frame_add(frame, ppref);
-
- ppref = purple_plugin_pref_new_with_name_and_label(HIDE_BUDDIES_PREF,
- _("Apply hiding rules to buddies"));
- purple_plugin_pref_frame_add(frame, ppref);
-
- return frame;
-}
-
-static GPluginPluginInfo *
-join_part_query(GError **error)
-{
- const gchar * const authors[] = {
- "Richard Laager <rlaager@pidgin.im>",
- NULL
- };
-
- return purple_plugin_info_new(
- "id", JOINPART_PLUGIN_ID,
- "name", N_("Join/Part Hiding"),
- "version", DISPLAY_VERSION,
- "category", N_("User interface"),
- "summary", N_("Hides extraneous join/part messages."),
- "description", N_("This plugin hides join/part messages in "
- "large rooms, except for those users actively "
- "taking part in a conversation."),
- "authors", authors,
- "website", PURPLE_WEBSITE,
- "abi-version", PURPLE_ABI_VERSION,
- "pref-frame-cb", get_plugin_pref_frame,
- NULL
- );
-}
-
-static gboolean
-join_part_load(GPluginPlugin *plugin, GError **error)
-{
- void *conv_handle;
- GHashTable *users;
- guint id;
-
- purple_prefs_add_none("/plugins/core/joinpart");
-
- purple_prefs_add_int(DELAY_PREF, DELAY_DEFAULT);
- purple_prefs_add_int(THRESHOLD_PREF, THRESHOLD_DEFAULT);
- purple_prefs_add_bool(HIDE_BUDDIES_PREF, HIDE_BUDDIES_DEFAULT);
-
- users = g_hash_table_new_full((GHashFunc)joinpart_key_hash,
- (GEqualFunc)joinpart_key_equal,
- (GDestroyNotify)joinpart_key_destroy,
- g_free);
-
- conv_handle = purple_conversations_get_handle();
- purple_signal_connect(conv_handle, "chat-user-joining", plugin,
- G_CALLBACK(chat_user_joining_cb), users);
- purple_signal_connect(conv_handle, "chat-user-leaving", plugin,
- G_CALLBACK(chat_user_leaving_cb), users);
- purple_signal_connect(conv_handle, "received-chat-msg", plugin,
- G_CALLBACK(received_chat_msg_cb), users);
-
- /* Cleanup every 5 minutes */
- id = g_timeout_add_seconds(60 * 5, (GSourceFunc)clean_users_hash, users);
-
- g_object_set_data(G_OBJECT(plugin), "users", users);
- g_object_set_data(G_OBJECT(plugin), "id", GUINT_TO_POINTER(id));
-
- return TRUE;
-}
-
-static gboolean
-join_part_unload(GPluginPlugin *plugin, gboolean shutdown, GError **error)
-{
- /* Destroy the hash table. The core plugin code will
- * disconnect the signals, and since Purple is single-threaded,
- * we don't have to worry one will be called after this. */
- g_hash_table_destroy((GHashTable *)g_object_get_data(G_OBJECT(plugin), "users"));
-
- g_source_remove(GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(plugin), "id")));
-
- return TRUE;
-}
-
-GPLUGIN_NATIVE_PLUGIN_DECLARE(join_part)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/joinpart/joinpart.c Mon Sep 12 04:49:23 2022 -0500
@@ -0,0 +1,281 @@
+/**
+ * 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 <glib/gi18n-lib.h>
+
+#include <gplugin.h>
+#include <gplugin-native.h>
+
+#include <purple.h>
+
+#define JOINPART_PLUGIN_ID "core-rlaager-joinpart"
+
+
+/* Preferences */
+
+/* The number of minutes before a person is considered
+ * to have stopped being part of active conversation. */
+#define DELAY_PREF "/plugins/core/joinpart/delay"
+#define DELAY_DEFAULT 10
+
+/* The number of people that must be in a room for this
+ * plugin to have any effect */
+#define THRESHOLD_PREF "/plugins/core/joinpart/threshold"
+#define THRESHOLD_DEFAULT 20
+
+/* Hide buddies */
+#define HIDE_BUDDIES_PREF "/plugins/core/joinpart/hide_buddies"
+#define HIDE_BUDDIES_DEFAULT FALSE
+
+struct joinpart_key
+{
+ PurpleConversation *conv;
+ char *user;
+};
+
+static guint joinpart_key_hash(const struct joinpart_key *key)
+{
+ g_return_val_if_fail(key != NULL, 0);
+
+ return g_direct_hash(key->conv) + g_str_hash(key->user);
+}
+
+static gboolean joinpart_key_equal(const struct joinpart_key *a, const struct joinpart_key *b)
+{
+ if (a == NULL)
+ return (b == NULL);
+ else if (b == NULL)
+ return FALSE;
+
+ return (a->conv == b->conv) && purple_strequal(a->user, b->user);
+}
+
+static void joinpart_key_destroy(struct joinpart_key *key)
+{
+ g_return_if_fail(key != NULL);
+
+ g_free(key->user);
+ g_free(key);
+}
+
+static gboolean should_hide_notice(PurpleConversation *conv, const char *name,
+ GHashTable *users)
+{
+ PurpleChatConversation *chat;
+ guint threshold;
+ struct joinpart_key key;
+ time_t *last_said;
+
+ g_return_val_if_fail(conv != NULL, FALSE);
+ g_return_val_if_fail(PURPLE_IS_CHAT_CONVERSATION(conv), FALSE);
+
+ /* If the room is small, don't bother. */
+ chat = PURPLE_CHAT_CONVERSATION(conv);
+ threshold = purple_prefs_get_int(THRESHOLD_PREF);
+ if (purple_chat_conversation_get_users_count(chat) < threshold)
+ return FALSE;
+
+ if (!purple_prefs_get_bool(HIDE_BUDDIES_PREF) &&
+ purple_blist_find_buddy(purple_conversation_get_account(conv), name))
+ return FALSE;
+
+ /* Only show the notice if the user has spoken recently. */
+ key.conv = conv;
+ key.user = (gchar *)name;
+ last_said = g_hash_table_lookup(users, &key);
+ if (last_said != NULL)
+ {
+ int delay = purple_prefs_get_int(DELAY_PREF);
+ if (delay > 0 && (*last_said + (delay * 60)) >= time(NULL))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean chat_user_leaving_cb(PurpleConversation *conv, const char *name,
+ const char *reason, GHashTable *users)
+{
+ return should_hide_notice(conv, name, users);
+}
+
+static gboolean chat_user_joining_cb(PurpleConversation *conv, const char *name,
+ PurpleChatUserFlags flags,
+ GHashTable *users)
+{
+ return should_hide_notice(conv, name, users);
+}
+
+static void received_chat_msg_cb(PurpleAccount *account, char *sender,
+ char *message, PurpleConversation *conv,
+ PurpleMessageFlags flags, GHashTable *users)
+{
+ struct joinpart_key key;
+ time_t *last_said;
+
+ /* Most of the time, we'll already have tracked the user,
+ * so we avoid memory allocation here. */
+ key.conv = conv;
+ key.user = sender;
+ last_said = g_hash_table_lookup(users, &key);
+ if (last_said != NULL)
+ {
+ /* They just said something, so update the time. */
+ time(last_said);
+ }
+ else
+ {
+ struct joinpart_key *key2;
+
+ key2 = g_new(struct joinpart_key, 1);
+ key2->conv = conv;
+ key2->user = g_strdup(sender);
+
+ last_said = g_new(time_t, 1);
+ time(last_said);
+
+ g_hash_table_insert(users, key2, last_said);
+ }
+}
+
+static gboolean check_expire_time(struct joinpart_key *key,
+ time_t *last_said, time_t *limit)
+{
+ purple_debug_info("joinpart", "Removing key for %s\n", key->user);
+ return (*last_said < *limit);
+}
+
+static gboolean clean_users_hash(GHashTable *users)
+{
+ int delay = purple_prefs_get_int(DELAY_PREF);
+ time_t limit = time(NULL) - (60 * delay);
+
+ g_hash_table_foreach_remove(users, (GHRFunc)check_expire_time, &limit);
+
+ return TRUE;
+}
+
+static PurplePluginPrefFrame *
+get_plugin_pref_frame(PurplePlugin *plugin)
+{
+ PurplePluginPrefFrame *frame;
+ PurplePluginPref *ppref;
+
+ g_return_val_if_fail(plugin != NULL, FALSE);
+
+ frame = purple_plugin_pref_frame_new();
+
+ ppref = purple_plugin_pref_new_with_label(_("Hide Joins/Parts"));
+ purple_plugin_pref_frame_add(frame, ppref);
+
+ ppref = purple_plugin_pref_new_with_name_and_label(THRESHOLD_PREF,
+ /* Translators: Followed by an input request a number of people */
+ _("For rooms with more than this many people"));
+ purple_plugin_pref_set_bounds(ppref, 0, 1000);
+ purple_plugin_pref_frame_add(frame, ppref);
+
+ ppref = purple_plugin_pref_new_with_name_and_label(DELAY_PREF,
+ _("If user has not spoken in this many minutes"));
+ purple_plugin_pref_set_bounds(ppref, 0, 8 * 60); /* 8 Hours */
+ purple_plugin_pref_frame_add(frame, ppref);
+
+ ppref = purple_plugin_pref_new_with_name_and_label(HIDE_BUDDIES_PREF,
+ _("Apply hiding rules to buddies"));
+ purple_plugin_pref_frame_add(frame, ppref);
+
+ return frame;
+}
+
+static GPluginPluginInfo *
+join_part_query(GError **error)
+{
+ const gchar * const authors[] = {
+ "Richard Laager <rlaager@pidgin.im>",
+ NULL
+ };
+
+ return purple_plugin_info_new(
+ "id", JOINPART_PLUGIN_ID,
+ "name", N_("Join/Part Hiding"),
+ "version", DISPLAY_VERSION,
+ "category", N_("User interface"),
+ "summary", N_("Hides extraneous join/part messages."),
+ "description", N_("This plugin hides join/part messages in "
+ "large rooms, except for those users actively "
+ "taking part in a conversation."),
+ "authors", authors,
+ "website", PURPLE_WEBSITE,
+ "abi-version", PURPLE_ABI_VERSION,
+ "pref-frame-cb", get_plugin_pref_frame,
+ NULL
+ );
+}
+
+static gboolean
+join_part_load(GPluginPlugin *plugin, GError **error)
+{
+ void *conv_handle;
+ GHashTable *users;
+ guint id;
+
+ purple_prefs_add_none("/plugins/core/joinpart");
+
+ purple_prefs_add_int(DELAY_PREF, DELAY_DEFAULT);
+ purple_prefs_add_int(THRESHOLD_PREF, THRESHOLD_DEFAULT);
+ purple_prefs_add_bool(HIDE_BUDDIES_PREF, HIDE_BUDDIES_DEFAULT);
+
+ users = g_hash_table_new_full((GHashFunc)joinpart_key_hash,
+ (GEqualFunc)joinpart_key_equal,
+ (GDestroyNotify)joinpart_key_destroy,
+ g_free);
+
+ conv_handle = purple_conversations_get_handle();
+ purple_signal_connect(conv_handle, "chat-user-joining", plugin,
+ G_CALLBACK(chat_user_joining_cb), users);
+ purple_signal_connect(conv_handle, "chat-user-leaving", plugin,
+ G_CALLBACK(chat_user_leaving_cb), users);
+ purple_signal_connect(conv_handle, "received-chat-msg", plugin,
+ G_CALLBACK(received_chat_msg_cb), users);
+
+ /* Cleanup every 5 minutes */
+ id = g_timeout_add_seconds(60 * 5, (GSourceFunc)clean_users_hash, users);
+
+ g_object_set_data(G_OBJECT(plugin), "users", users);
+ g_object_set_data(G_OBJECT(plugin), "id", GUINT_TO_POINTER(id));
+
+ return TRUE;
+}
+
+static gboolean
+join_part_unload(GPluginPlugin *plugin, gboolean shutdown, GError **error)
+{
+ /* Destroy the hash table. The core plugin code will
+ * disconnect the signals, and since Purple is single-threaded,
+ * we don't have to worry one will be called after this. */
+ g_hash_table_destroy((GHashTable *)g_object_get_data(G_OBJECT(plugin), "users"));
+
+ g_source_remove(GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(plugin), "id")));
+
+ return TRUE;
+}
+
+GPLUGIN_NATIVE_PLUGIN_DECLARE(join_part)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/joinpart/meson.build Mon Sep 12 04:49:23 2022 -0500
@@ -0,0 +1,7 @@
+joinpart = library('joinpart', 'joinpart.c',
+ c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="PurplePlugin-JoinPart"'],
+ dependencies : [libpurple_dep],
+ name_prefix : '',
+ install : true, install_dir : PURPLE_PLUGINDIR)
+
+devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir())
--- a/libpurple/plugins/meson.build Sun Sep 11 02:09:40 2022 -0500
+++ b/libpurple/plugins/meson.build Mon Sep 12 04:49:23 2022 -0500
@@ -1,49 +1,12 @@
+subdir('autoaccept')
+subdir('buddynote')
+subdir('idle')
+subdir('joinpart')
subdir('keychain-access')
subdir('kwallet')
subdir('libsecret')
subdir('notification-sound')
+subdir('psychic')
+subdir('purple-toast')
+subdir('statenotify')
subdir('wincred')
-
-autoaccept = library('autoaccept', 'autoaccept.c',
- c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="PurplePlugin-AutoAccept"'],
- dependencies : [libpurple_dep, glib],
- name_prefix : '',
- install : true, install_dir : PURPLE_PLUGINDIR)
-
-buddynote = library('buddynote', 'buddynote.c',
- c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="PurplePlugin-BuddyNote"'],
- dependencies : [libpurple_dep],
- name_prefix : '',
- install : true, install_dir : PURPLE_PLUGINDIR)
-
-idle = library('idle', 'idle.c',
- c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="PurplePlugin-Idle"'],
- dependencies : [libpurple_dep],
- name_prefix : '',
- install : true, install_dir : PURPLE_PLUGINDIR)
-
-joinpart = library('joinpart', 'joinpart.c',
- c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="PurplePlugin-JoinPart"'],
- dependencies : [libpurple_dep],
- name_prefix : '',
- install : true, install_dir : PURPLE_PLUGINDIR)
-
-psychic = library('psychic', 'psychic.c',
- c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="PurplePlugin-Psychic"'],
- dependencies : [libpurple_dep],
- name_prefix : '',
- install : true, install_dir : PURPLE_PLUGINDIR)
-
-statenotify = library('statenotify', 'statenotify.c',
- c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="PurplePlugin-StateNotify"'],
- dependencies : [libpurple_dep],
- name_prefix : '',
- install : true, install_dir : PURPLE_PLUGINDIR)
-
-purple_toast = library('purple-toast', 'purple-toast.c',
- c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="PurplePlugin-Toast"'],
- dependencies : [libpurple_dep],
- name_prefix: '',
- install : true, install_dir : PURPLE_PLUGINDIR)
-
-devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir())
--- a/libpurple/plugins/psychic.c Sun Sep 11 02:09:40 2022 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,167 +0,0 @@
-/*
- * 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 <glib/gi18n-lib.h>
-
-#include <gplugin.h>
-#include <gplugin-native.h>
-
-#include <purple.h>
-
-#define PLUGIN_ID "core-psychic"
-#define PLUGIN_NAME N_("Psychic Mode")
-#define PLUGIN_CATEGORY N_("Utility")
-#define PLUGIN_SUMMARY N_("Psychic mode for incoming conversation")
-#define PLUGIN_DESC N_("Causes conversation windows to appear as other" \
- " users begin to message you. This works for" \
- " AIM, ICQ, XMPP, and Sametime")
-#define PLUGIN_AUTHORS { "Christopher O'Brien <siege@preoccupied.net>", NULL }
-
-
-#define PREFS_BASE "/plugins/core/psychic"
-#define PREF_BUDDIES PREFS_BASE "/buddies_only"
-#define PREF_NOTICE PREFS_BASE "/show_notice"
-#define PREF_STATUS PREFS_BASE "/activate_online"
-#define PREF_RAISE PREFS_BASE "/raise_conv"
-
-
-static void
-buddy_typing_cb(PurpleAccount *acct, const char *name, void *data) {
- PurpleConversation *im;
- PurpleConversationManager *manager;
-
- if(purple_prefs_get_bool(PREF_STATUS) &&
- ! purple_status_is_available(purple_account_get_active_status(acct))) {
- purple_debug_info("psychic", "not available, doing nothing\n");
- return;
- }
-
- if(purple_prefs_get_bool(PREF_BUDDIES) &&
- ! purple_blist_find_buddy(acct, name)) {
- purple_debug_info("psychic", "not in blist, doing nothing\n");
- return;
- }
-
- if(FALSE == purple_account_privacy_check(acct, name)) {
- purple_debug_info("psychic", "user %s is blocked\n", name);
- return;
- }
-
- manager = purple_conversation_manager_get_default();
- im = purple_conversation_manager_find_im(manager, acct, name);
- if(! im) {
- purple_debug_info("psychic", "no previous conversation exists\n");
- im = purple_im_conversation_new(acct, name);
-
- if(purple_prefs_get_bool(PREF_RAISE)) {
- purple_conversation_present(im);
- }
-
- if(purple_prefs_get_bool(PREF_NOTICE)) {
-
- /* This is a quote from Star Wars. You should probably not
- translate it literally. If you can't find a fitting cultural
- reference in your language, consider translating something
- like this instead: "You feel a new message coming." */
- purple_conversation_write_system_message(im,
- _("You feel a disturbance in the force..."),
- PURPLE_MESSAGE_NO_LOG | PURPLE_MESSAGE_ACTIVE_ONLY);
- }
-
- /* Necessary because we may be creating a new conversation window. */
- purple_im_conversation_set_typing_state(PURPLE_IM_CONVERSATION(im),
- PURPLE_IM_TYPING);
- }
-}
-
-
-static PurplePluginPrefFrame *
-get_plugin_pref_frame(PurplePlugin *plugin) {
-
- PurplePluginPrefFrame *frame;
- PurplePluginPref *pref;
-
- frame = purple_plugin_pref_frame_new();
-
- pref = purple_plugin_pref_new_with_name(PREF_BUDDIES);
- purple_plugin_pref_set_label(pref, _("Only enable for users on"
- " the buddy list"));
- purple_plugin_pref_frame_add(frame, pref);
-
- pref = purple_plugin_pref_new_with_name(PREF_STATUS);
- purple_plugin_pref_set_label(pref, _("Disable when away"));
- purple_plugin_pref_frame_add(frame, pref);
-
- pref = purple_plugin_pref_new_with_name(PREF_NOTICE);
- purple_plugin_pref_set_label(pref, _("Display notification message in"
- " conversations"));
- purple_plugin_pref_frame_add(frame, pref);
-
- pref = purple_plugin_pref_new_with_name(PREF_RAISE);
- purple_plugin_pref_set_label(pref, _("Raise psychic conversations"));
- purple_plugin_pref_frame_add(frame, pref);
-
- return frame;
-}
-
-
-static GPluginPluginInfo *
-psychic_query(GError **error) {
- const gchar * const authors[] = PLUGIN_AUTHORS;
-
- return purple_plugin_info_new(
- "id", PLUGIN_ID,
- "name", PLUGIN_NAME,
- "version", DISPLAY_VERSION,
- "category", PLUGIN_CATEGORY,
- "summary", PLUGIN_SUMMARY,
- "description", PLUGIN_DESC,
- "authors", authors,
- "website", PURPLE_WEBSITE,
- "abi-version", PURPLE_ABI_VERSION,
- "pref-frame-cb", get_plugin_pref_frame,
- NULL
- );
-}
-
-
-static gboolean
-psychic_load(GPluginPlugin *plugin, GError **error) {
-
- void *convs_handle;
-
- purple_prefs_add_none(PREFS_BASE);
- purple_prefs_add_bool(PREF_BUDDIES, FALSE);
- purple_prefs_add_bool(PREF_NOTICE, TRUE);
- purple_prefs_add_bool(PREF_STATUS, TRUE);
-
- convs_handle = purple_conversations_get_handle();
-
- purple_signal_connect(convs_handle, "buddy-typing", plugin,
- G_CALLBACK(buddy_typing_cb), NULL);
-
- return TRUE;
-}
-
-
-static gboolean
-psychic_unload(GPluginPlugin *plugin, gboolean shutdown, GError **error) {
-
- return TRUE;
-}
-
-GPLUGIN_NATIVE_PLUGIN_DECLARE(psychic)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/psychic/meson.build Mon Sep 12 04:49:23 2022 -0500
@@ -0,0 +1,7 @@
+psychic = library('psychic', 'psychic.c',
+ c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="PurplePlugin-Psychic"'],
+ dependencies : [libpurple_dep],
+ name_prefix : '',
+ install : true, install_dir : PURPLE_PLUGINDIR)
+
+devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir())
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/psychic/psychic.c Mon Sep 12 04:49:23 2022 -0500
@@ -0,0 +1,167 @@
+/*
+ * 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 <glib/gi18n-lib.h>
+
+#include <gplugin.h>
+#include <gplugin-native.h>
+
+#include <purple.h>
+
+#define PLUGIN_ID "core-psychic"
+#define PLUGIN_NAME N_("Psychic Mode")
+#define PLUGIN_CATEGORY N_("Utility")
+#define PLUGIN_SUMMARY N_("Psychic mode for incoming conversation")
+#define PLUGIN_DESC N_("Causes conversation windows to appear as other" \
+ " users begin to message you. This works for" \
+ " AIM, ICQ, XMPP, and Sametime")
+#define PLUGIN_AUTHORS { "Christopher O'Brien <siege@preoccupied.net>", NULL }
+
+
+#define PREFS_BASE "/plugins/core/psychic"
+#define PREF_BUDDIES PREFS_BASE "/buddies_only"
+#define PREF_NOTICE PREFS_BASE "/show_notice"
+#define PREF_STATUS PREFS_BASE "/activate_online"
+#define PREF_RAISE PREFS_BASE "/raise_conv"
+
+
+static void
+buddy_typing_cb(PurpleAccount *acct, const char *name, void *data) {
+ PurpleConversation *im;
+ PurpleConversationManager *manager;
+
+ if(purple_prefs_get_bool(PREF_STATUS) &&
+ ! purple_status_is_available(purple_account_get_active_status(acct))) {
+ purple_debug_info("psychic", "not available, doing nothing\n");
+ return;
+ }
+
+ if(purple_prefs_get_bool(PREF_BUDDIES) &&
+ ! purple_blist_find_buddy(acct, name)) {
+ purple_debug_info("psychic", "not in blist, doing nothing\n");
+ return;
+ }
+
+ if(FALSE == purple_account_privacy_check(acct, name)) {
+ purple_debug_info("psychic", "user %s is blocked\n", name);
+ return;
+ }
+
+ manager = purple_conversation_manager_get_default();
+ im = purple_conversation_manager_find_im(manager, acct, name);
+ if(! im) {
+ purple_debug_info("psychic", "no previous conversation exists\n");
+ im = purple_im_conversation_new(acct, name);
+
+ if(purple_prefs_get_bool(PREF_RAISE)) {
+ purple_conversation_present(im);
+ }
+
+ if(purple_prefs_get_bool(PREF_NOTICE)) {
+
+ /* This is a quote from Star Wars. You should probably not
+ translate it literally. If you can't find a fitting cultural
+ reference in your language, consider translating something
+ like this instead: "You feel a new message coming." */
+ purple_conversation_write_system_message(im,
+ _("You feel a disturbance in the force..."),
+ PURPLE_MESSAGE_NO_LOG | PURPLE_MESSAGE_ACTIVE_ONLY);
+ }
+
+ /* Necessary because we may be creating a new conversation window. */
+ purple_im_conversation_set_typing_state(PURPLE_IM_CONVERSATION(im),
+ PURPLE_IM_TYPING);
+ }
+}
+
+
+static PurplePluginPrefFrame *
+get_plugin_pref_frame(PurplePlugin *plugin) {
+
+ PurplePluginPrefFrame *frame;
+ PurplePluginPref *pref;
+
+ frame = purple_plugin_pref_frame_new();
+
+ pref = purple_plugin_pref_new_with_name(PREF_BUDDIES);
+ purple_plugin_pref_set_label(pref, _("Only enable for users on"
+ " the buddy list"));
+ purple_plugin_pref_frame_add(frame, pref);
+
+ pref = purple_plugin_pref_new_with_name(PREF_STATUS);
+ purple_plugin_pref_set_label(pref, _("Disable when away"));
+ purple_plugin_pref_frame_add(frame, pref);
+
+ pref = purple_plugin_pref_new_with_name(PREF_NOTICE);
+ purple_plugin_pref_set_label(pref, _("Display notification message in"
+ " conversations"));
+ purple_plugin_pref_frame_add(frame, pref);
+
+ pref = purple_plugin_pref_new_with_name(PREF_RAISE);
+ purple_plugin_pref_set_label(pref, _("Raise psychic conversations"));
+ purple_plugin_pref_frame_add(frame, pref);
+
+ return frame;
+}
+
+
+static GPluginPluginInfo *
+psychic_query(GError **error) {
+ const gchar * const authors[] = PLUGIN_AUTHORS;
+
+ return purple_plugin_info_new(
+ "id", PLUGIN_ID,
+ "name", PLUGIN_NAME,
+ "version", DISPLAY_VERSION,
+ "category", PLUGIN_CATEGORY,
+ "summary", PLUGIN_SUMMARY,
+ "description", PLUGIN_DESC,
+ "authors", authors,
+ "website", PURPLE_WEBSITE,
+ "abi-version", PURPLE_ABI_VERSION,
+ "pref-frame-cb", get_plugin_pref_frame,
+ NULL
+ );
+}
+
+
+static gboolean
+psychic_load(GPluginPlugin *plugin, GError **error) {
+
+ void *convs_handle;
+
+ purple_prefs_add_none(PREFS_BASE);
+ purple_prefs_add_bool(PREF_BUDDIES, FALSE);
+ purple_prefs_add_bool(PREF_NOTICE, TRUE);
+ purple_prefs_add_bool(PREF_STATUS, TRUE);
+
+ convs_handle = purple_conversations_get_handle();
+
+ purple_signal_connect(convs_handle, "buddy-typing", plugin,
+ G_CALLBACK(buddy_typing_cb), NULL);
+
+ return TRUE;
+}
+
+
+static gboolean
+psychic_unload(GPluginPlugin *plugin, gboolean shutdown, GError **error) {
+
+ return TRUE;
+}
+
+GPLUGIN_NATIVE_PLUGIN_DECLARE(psychic)
--- a/libpurple/plugins/purple-toast.c Sun Sep 11 02:09:40 2022 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,239 +0,0 @@
-/* pidgin
- *
- * Pidgin is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-#include <glib.h>
-#include <gmodule.h>
-
-#include <gplugin.h>
-#include <gplugin-native.h>
-
-#include <purple.h>
-
-/******************************************************************************
- * Helpers
- *****************************************************************************/
-static GApplication *
-purple_toast_get_application(void) {
- static GApplication *application = NULL;
-
- if(G_UNLIKELY(application == NULL)) {
- application = g_application_get_default();
-
- if(application == NULL) {
- application = g_application_new(NULL, G_APPLICATION_FLAGS_NONE);
- g_application_register(application, NULL, NULL);
- }
- }
-
- return application;
-}
-
-static void
-purple_toast_show_notification(const gchar *title,
- const gchar *body,
- GIcon *icon)
-{
- GNotification *notification = g_notification_new(title);
- gchar *stripped = purple_markup_strip_html(body);
-
- g_notification_set_body(notification, stripped);
- g_free(stripped);
-
- if(G_IS_ICON(icon)) {
- g_notification_set_icon(notification, icon);
- }
-
- g_application_send_notification(purple_toast_get_application(),
- NULL,
- notification);
-
- g_object_unref(G_OBJECT(notification));
-}
-
-static GIcon *
-purple_toast_find_icon(PurpleAccount *account,
- PurpleBuddy *buddy,
- const gchar *sender)
-{
- GIcon *icon = NULL;
-
- if(PURPLE_IS_BUDDY(buddy)) {
- PurpleBuddyIcon *buddy_icon = purple_buddy_get_icon(buddy);
-
- if(buddy_icon) {
- const gchar *filename = NULL;
-
- filename = purple_buddy_icon_get_full_path(buddy_icon);
- if(filename != NULL) {
- GFile *file = g_file_new_for_path(filename);
-
- icon = g_file_icon_new(file);
-
- g_object_unref(file);
- }
- }
- } else {
- PurpleImage *image = NULL;
- const gchar *path = NULL;
-
- image = purple_buddy_icons_find_account_icon(account);
- if(PURPLE_IS_IMAGE(image)) {
- path = purple_image_get_path(image);
-
- if(path) {
- GFile *file = g_file_new_for_path(path);
-
- icon = g_file_icon_new(file);
-
- g_object_unref(G_OBJECT(file));
- }
- g_object_unref(G_OBJECT(image));
- }
- }
-
- /* We should probably have a fallback, but we need a libpurple or
- * pidgin icon or something to make that happen.
- */
-
- return icon;
-}
-
-/******************************************************************************
- * Callbacks
- *****************************************************************************/
-static void
-purple_toast_im_message_received(PurpleAccount *account,
- const gchar *sender,
- const gchar *message,
- PurpleConversation *conv,
- PurpleMessageFlags flags,
- gpointer data)
-{
- PurpleBuddy *buddy = NULL;
- GIcon *icon = NULL;
- const gchar *title = NULL;
-
- buddy = purple_blist_find_buddy(account, sender);
- title = PURPLE_IS_BUDDY(buddy) ? purple_buddy_get_alias(buddy) : sender;
- icon = purple_toast_find_icon(account, buddy, sender);
-
- purple_toast_show_notification(title, message, icon);
-
- if(G_IS_ICON(icon)) {
- g_object_unref(G_OBJECT(icon));
- }
-}
-
-static void
-purple_toast_chat_message_received(PurpleAccount *account,
- gchar *sender,
- gchar *message,
- PurpleConversation *conv,
- PurpleMessageFlags flags,
- gpointer data)
-{
- PurpleBuddy *buddy = NULL;
- GIcon *icon = NULL;
- gchar *title = NULL;
- const gchar *chat_name = NULL, *from = NULL;
-
- /* figure out the title */
- chat_name = purple_conversation_get_name(PURPLE_CONVERSATION(conv));
- if(chat_name) {
- PurpleChat *chat = purple_blist_find_chat(account, chat_name);
-
- if(chat) {
- chat_name = purple_chat_get_name(chat);
- }
- }
-
- from = sender;
- buddy = purple_blist_find_buddy(account, sender);
- if(PURPLE_IS_BUDDY(buddy)) {
- from = purple_buddy_get_alias(buddy);
- }
-
- title = g_strdup_printf("%s : %s", chat_name, from);
-
- /* figure out the icon */
- icon = purple_toast_find_icon(account, buddy, sender);
-
- /* show the notification */
- purple_toast_show_notification(title, message, icon);
-
- /* clean up our memory */
- g_free(title);
-
- if(G_IS_ICON(icon)) {
- g_object_unref(G_OBJECT(icon));
- }
-}
-
-/******************************************************************************
- * Plugin Exports
- *****************************************************************************/
-static GPluginPluginInfo *
-purple_toast_query(G_GNUC_UNUSED GError **error) {
- const gchar * const authors[] = {
- "Gary Kramlich <grim@reaperworld.com>",
- NULL
- };
-
- return purple_plugin_info_new(
- "id", "purple/toast",
- "abi-version", PURPLE_ABI_VERSION,
- "name", "Purple Toast",
- "version", "0.0.1",
- "summary", "Toast notifications",
- "authors", authors,
- NULL
- );
-}
-
-static gboolean
-purple_toast_load(GPluginPlugin *plugin, G_GNUC_UNUSED GError **error) {
- gpointer conv_handle = purple_conversations_get_handle();
-
- purple_signal_connect(conv_handle,
- "received-im-msg",
- plugin,
- G_CALLBACK(purple_toast_im_message_received),
- NULL
- );
-
- purple_signal_connect(conv_handle,
- "received-chat-msg",
- plugin,
- G_CALLBACK(purple_toast_chat_message_received),
- NULL
- );
-
- return TRUE;
-}
-
-static gboolean
-purple_toast_unload(G_GNUC_UNUSED GPluginPlugin *plugin,
- G_GNUC_UNUSED gboolean shutdown,
- G_GNUC_UNUSED GError **error)
-{
- return TRUE;
-}
-
-GPLUGIN_NATIVE_PLUGIN_DECLARE(purple_toast)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/purple-toast/meson.build Mon Sep 12 04:49:23 2022 -0500
@@ -0,0 +1,7 @@
+purple_toast = library('purple-toast', 'purple-toast.c',
+ c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="PurplePlugin-Toast"'],
+ dependencies : [libpurple_dep],
+ name_prefix: '',
+ install : true, install_dir : PURPLE_PLUGINDIR)
+
+devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir())
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/purple-toast/purple-toast.c Mon Sep 12 04:49:23 2022 -0500
@@ -0,0 +1,239 @@
+/* pidgin
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+#include <glib.h>
+#include <gmodule.h>
+
+#include <gplugin.h>
+#include <gplugin-native.h>
+
+#include <purple.h>
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static GApplication *
+purple_toast_get_application(void) {
+ static GApplication *application = NULL;
+
+ if(G_UNLIKELY(application == NULL)) {
+ application = g_application_get_default();
+
+ if(application == NULL) {
+ application = g_application_new(NULL, G_APPLICATION_FLAGS_NONE);
+ g_application_register(application, NULL, NULL);
+ }
+ }
+
+ return application;
+}
+
+static void
+purple_toast_show_notification(const gchar *title,
+ const gchar *body,
+ GIcon *icon)
+{
+ GNotification *notification = g_notification_new(title);
+ gchar *stripped = purple_markup_strip_html(body);
+
+ g_notification_set_body(notification, stripped);
+ g_free(stripped);
+
+ if(G_IS_ICON(icon)) {
+ g_notification_set_icon(notification, icon);
+ }
+
+ g_application_send_notification(purple_toast_get_application(),
+ NULL,
+ notification);
+
+ g_object_unref(G_OBJECT(notification));
+}
+
+static GIcon *
+purple_toast_find_icon(PurpleAccount *account,
+ PurpleBuddy *buddy,
+ const gchar *sender)
+{
+ GIcon *icon = NULL;
+
+ if(PURPLE_IS_BUDDY(buddy)) {
+ PurpleBuddyIcon *buddy_icon = purple_buddy_get_icon(buddy);
+
+ if(buddy_icon) {
+ const gchar *filename = NULL;
+
+ filename = purple_buddy_icon_get_full_path(buddy_icon);
+ if(filename != NULL) {
+ GFile *file = g_file_new_for_path(filename);
+
+ icon = g_file_icon_new(file);
+
+ g_object_unref(file);
+ }
+ }
+ } else {
+ PurpleImage *image = NULL;
+ const gchar *path = NULL;
+
+ image = purple_buddy_icons_find_account_icon(account);
+ if(PURPLE_IS_IMAGE(image)) {
+ path = purple_image_get_path(image);
+
+ if(path) {
+ GFile *file = g_file_new_for_path(path);
+
+ icon = g_file_icon_new(file);
+
+ g_object_unref(G_OBJECT(file));
+ }
+ g_object_unref(G_OBJECT(image));
+ }
+ }
+
+ /* We should probably have a fallback, but we need a libpurple or
+ * pidgin icon or something to make that happen.
+ */
+
+ return icon;
+}
+
+/******************************************************************************
+ * Callbacks
+ *****************************************************************************/
+static void
+purple_toast_im_message_received(PurpleAccount *account,
+ const gchar *sender,
+ const gchar *message,
+ PurpleConversation *conv,
+ PurpleMessageFlags flags,
+ gpointer data)
+{
+ PurpleBuddy *buddy = NULL;
+ GIcon *icon = NULL;
+ const gchar *title = NULL;
+
+ buddy = purple_blist_find_buddy(account, sender);
+ title = PURPLE_IS_BUDDY(buddy) ? purple_buddy_get_alias(buddy) : sender;
+ icon = purple_toast_find_icon(account, buddy, sender);
+
+ purple_toast_show_notification(title, message, icon);
+
+ if(G_IS_ICON(icon)) {
+ g_object_unref(G_OBJECT(icon));
+ }
+}
+
+static void
+purple_toast_chat_message_received(PurpleAccount *account,
+ gchar *sender,
+ gchar *message,
+ PurpleConversation *conv,
+ PurpleMessageFlags flags,
+ gpointer data)
+{
+ PurpleBuddy *buddy = NULL;
+ GIcon *icon = NULL;
+ gchar *title = NULL;
+ const gchar *chat_name = NULL, *from = NULL;
+
+ /* figure out the title */
+ chat_name = purple_conversation_get_name(PURPLE_CONVERSATION(conv));
+ if(chat_name) {
+ PurpleChat *chat = purple_blist_find_chat(account, chat_name);
+
+ if(chat) {
+ chat_name = purple_chat_get_name(chat);
+ }
+ }
+
+ from = sender;
+ buddy = purple_blist_find_buddy(account, sender);
+ if(PURPLE_IS_BUDDY(buddy)) {
+ from = purple_buddy_get_alias(buddy);
+ }
+
+ title = g_strdup_printf("%s : %s", chat_name, from);
+
+ /* figure out the icon */
+ icon = purple_toast_find_icon(account, buddy, sender);
+
+ /* show the notification */
+ purple_toast_show_notification(title, message, icon);
+
+ /* clean up our memory */
+ g_free(title);
+
+ if(G_IS_ICON(icon)) {
+ g_object_unref(G_OBJECT(icon));
+ }
+}
+
+/******************************************************************************
+ * Plugin Exports
+ *****************************************************************************/
+static GPluginPluginInfo *
+purple_toast_query(G_GNUC_UNUSED GError **error) {
+ const gchar * const authors[] = {
+ "Gary Kramlich <grim@reaperworld.com>",
+ NULL
+ };
+
+ return purple_plugin_info_new(
+ "id", "purple/toast",
+ "abi-version", PURPLE_ABI_VERSION,
+ "name", "Purple Toast",
+ "version", "0.0.1",
+ "summary", "Toast notifications",
+ "authors", authors,
+ NULL
+ );
+}
+
+static gboolean
+purple_toast_load(GPluginPlugin *plugin, G_GNUC_UNUSED GError **error) {
+ gpointer conv_handle = purple_conversations_get_handle();
+
+ purple_signal_connect(conv_handle,
+ "received-im-msg",
+ plugin,
+ G_CALLBACK(purple_toast_im_message_received),
+ NULL
+ );
+
+ purple_signal_connect(conv_handle,
+ "received-chat-msg",
+ plugin,
+ G_CALLBACK(purple_toast_chat_message_received),
+ NULL
+ );
+
+ return TRUE;
+}
+
+static gboolean
+purple_toast_unload(G_GNUC_UNUSED GPluginPlugin *plugin,
+ G_GNUC_UNUSED gboolean shutdown,
+ G_GNUC_UNUSED GError **error)
+{
+ return TRUE;
+}
+
+GPLUGIN_NATIVE_PLUGIN_DECLARE(purple_toast)
--- a/libpurple/plugins/statenotify.c Sun Sep 11 02:09:40 2022 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-/*
- * 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 <glib/gi18n-lib.h>
-
-#include <gplugin.h>
-#include <gplugin-native.h>
-
-#include <purple.h>
-
-#define STATENOTIFY_PLUGIN_ID "core-statenotify"
-
-static void
-write_status(PurpleBuddy *buddy, const char *message)
-{
- PurpleAccount *account = NULL;
- PurpleConversation *im;
- PurpleConversationManager *manager;
- const char *who;
- char buf[256];
- char *escaped;
- const gchar *buddy_name = NULL;
-
- account = purple_buddy_get_account(buddy);
- buddy_name = purple_buddy_get_name(buddy);
-
- manager = purple_conversation_manager_get_default();
- im = purple_conversation_manager_find_im(manager, account, buddy_name);
-
- if (im == NULL)
- return;
-
- /* Prevent duplicate notifications for buddies in multiple groups */
- if (buddy != purple_blist_find_buddy(account, buddy_name))
- return;
-
- who = purple_buddy_get_alias(buddy);
- escaped = g_markup_escape_text(who, -1);
-
- g_snprintf(buf, sizeof(buf), message, escaped);
- g_free(escaped);
-
- purple_conversation_write_system_message(im, buf,
- PURPLE_MESSAGE_ACTIVE_ONLY | PURPLE_MESSAGE_NO_LINKIFY);
-}
-
-static void
-buddy_status_changed_cb(PurpleBuddy *buddy, PurpleStatus *old_status,
- PurpleStatus *status, void *data)
-{
- gboolean available, old_available;
-
- if (!purple_status_is_exclusive(status) ||
- !purple_status_is_exclusive(old_status))
- return;
-
- available = purple_status_is_available(status);
- old_available = purple_status_is_available(old_status);
-
- if (purple_prefs_get_bool("/plugins/core/statenotify/notify_away")) {
- if (available && !old_available)
- write_status(buddy, _("%s is no longer away."));
- else if (!available && old_available)
- write_status(buddy, _("%s has gone away."));
- }
-}
-
-static void
-buddy_idle_changed_cb(PurpleBuddy *buddy, gboolean old_idle, gboolean idle,
- void *data)
-{
- if (purple_prefs_get_bool("/plugins/core/statenotify/notify_idle")) {
- if (idle && !old_idle) {
- write_status(buddy, _("%s has become idle."));
- } else if (!idle && old_idle) {
- write_status(buddy, _("%s is no longer idle."));
- }
- }
-}
-
-static void
-buddy_signon_cb(PurpleBuddy *buddy, void *data)
-{
- if (purple_prefs_get_bool("/plugins/core/statenotify/notify_signon"))
- write_status(buddy, _("%s has signed on."));
-}
-
-static void
-buddy_signoff_cb(PurpleBuddy *buddy, void *data)
-{
- if (purple_prefs_get_bool("/plugins/core/statenotify/notify_signon"))
- write_status(buddy, _("%s has signed off."));
-}
-
-static PurplePluginPrefFrame *
-get_plugin_pref_frame(PurplePlugin *plugin)
-{
- PurplePluginPrefFrame *frame;
- PurplePluginPref *ppref;
-
- frame = purple_plugin_pref_frame_new();
-
- ppref = purple_plugin_pref_new_with_label(_("Notify When"));
- purple_plugin_pref_frame_add(frame, ppref);
-
- ppref = purple_plugin_pref_new_with_name_and_label("/plugins/core/statenotify/notify_away", _("Buddy Goes _Away"));
- purple_plugin_pref_frame_add(frame, ppref);
-
- ppref = purple_plugin_pref_new_with_name_and_label("/plugins/core/statenotify/notify_idle", _("Buddy Goes _Idle"));
- purple_plugin_pref_frame_add(frame, ppref);
-
- ppref = purple_plugin_pref_new_with_name_and_label("/plugins/core/statenotify/notify_signon", _("Buddy _Signs On/Off"));
- purple_plugin_pref_frame_add(frame, ppref);
-
- return frame;
-}
-
-static GPluginPluginInfo *
-state_notify_query(GError **error)
-{
- const gchar * const authors[] = {
- "Christian Hammond <chipx86@gnupdate.org>",
- NULL
- };
-
- return purple_plugin_info_new(
- "id", STATENOTIFY_PLUGIN_ID,
- "name", N_("Buddy State Notification"),
- "version", DISPLAY_VERSION,
- "category", N_("Notification"),
- "summary", N_("Notifies in a conversation window when a "
- "buddy goes or returns from away or idle."),
- "description", N_("Notifies in a conversation window when a "
- "buddy goes or returns from away or idle."),
- "authors", authors,
- "website", PURPLE_WEBSITE,
- "abi-version", PURPLE_ABI_VERSION,
- "pref-frame-cb", get_plugin_pref_frame,
- NULL
- );
-}
-
-static gboolean
-state_notify_load(GPluginPlugin *plugin, GError **error)
-{
- void *blist_handle = purple_blist_get_handle();
-
- purple_prefs_add_none("/plugins/core/statenotify");
- purple_prefs_add_bool("/plugins/core/statenotify/notify_away", TRUE);
- purple_prefs_add_bool("/plugins/core/statenotify/notify_idle", TRUE);
- purple_prefs_add_bool("/plugins/core/statenotify/notify_signon", TRUE);
-
- purple_signal_connect(blist_handle, "buddy-status-changed", plugin,
- G_CALLBACK(buddy_status_changed_cb), NULL);
- purple_signal_connect(blist_handle, "buddy-idle-changed", plugin,
- G_CALLBACK(buddy_idle_changed_cb), NULL);
- purple_signal_connect(blist_handle, "buddy-signed-on", plugin,
- G_CALLBACK(buddy_signon_cb), NULL);
- purple_signal_connect(blist_handle, "buddy-signed-off", plugin,
- G_CALLBACK(buddy_signoff_cb), NULL);
-
- return TRUE;
-}
-
-static gboolean
-state_notify_unload(GPluginPlugin *plugin, gboolean shutdown, GError **error)
-{
- return TRUE;
-}
-
-GPLUGIN_NATIVE_PLUGIN_DECLARE(state_notify)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/statenotify/meson.build Mon Sep 12 04:49:23 2022 -0500
@@ -0,0 +1,7 @@
+statenotify = library('statenotify', 'statenotify.c',
+ c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="PurplePlugin-StateNotify"'],
+ dependencies : [libpurple_dep],
+ name_prefix : '',
+ install : true, install_dir : PURPLE_PLUGINDIR)
+
+devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir())
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/plugins/statenotify/statenotify.c Mon Sep 12 04:49:23 2022 -0500
@@ -0,0 +1,185 @@
+/*
+ * 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 <glib/gi18n-lib.h>
+
+#include <gplugin.h>
+#include <gplugin-native.h>
+
+#include <purple.h>
+
+#define STATENOTIFY_PLUGIN_ID "core-statenotify"
+
+static void
+write_status(PurpleBuddy *buddy, const char *message)
+{
+ PurpleAccount *account = NULL;
+ PurpleConversation *im;
+ PurpleConversationManager *manager;
+ const char *who;
+ char buf[256];
+ char *escaped;
+ const gchar *buddy_name = NULL;
+
+ account = purple_buddy_get_account(buddy);
+ buddy_name = purple_buddy_get_name(buddy);
+
+ manager = purple_conversation_manager_get_default();
+ im = purple_conversation_manager_find_im(manager, account, buddy_name);
+
+ if (im == NULL)
+ return;
+
+ /* Prevent duplicate notifications for buddies in multiple groups */
+ if (buddy != purple_blist_find_buddy(account, buddy_name))
+ return;
+
+ who = purple_buddy_get_alias(buddy);
+ escaped = g_markup_escape_text(who, -1);
+
+ g_snprintf(buf, sizeof(buf), message, escaped);
+ g_free(escaped);
+
+ purple_conversation_write_system_message(im, buf,
+ PURPLE_MESSAGE_ACTIVE_ONLY | PURPLE_MESSAGE_NO_LINKIFY);
+}
+
+static void
+buddy_status_changed_cb(PurpleBuddy *buddy, PurpleStatus *old_status,
+ PurpleStatus *status, void *data)
+{
+ gboolean available, old_available;
+
+ if (!purple_status_is_exclusive(status) ||
+ !purple_status_is_exclusive(old_status))
+ return;
+
+ available = purple_status_is_available(status);
+ old_available = purple_status_is_available(old_status);
+
+ if (purple_prefs_get_bool("/plugins/core/statenotify/notify_away")) {
+ if (available && !old_available)
+ write_status(buddy, _("%s is no longer away."));
+ else if (!available && old_available)
+ write_status(buddy, _("%s has gone away."));
+ }
+}
+
+static void
+buddy_idle_changed_cb(PurpleBuddy *buddy, gboolean old_idle, gboolean idle,
+ void *data)
+{
+ if (purple_prefs_get_bool("/plugins/core/statenotify/notify_idle")) {
+ if (idle && !old_idle) {
+ write_status(buddy, _("%s has become idle."));
+ } else if (!idle && old_idle) {
+ write_status(buddy, _("%s is no longer idle."));
+ }
+ }
+}
+
+static void
+buddy_signon_cb(PurpleBuddy *buddy, void *data)
+{
+ if (purple_prefs_get_bool("/plugins/core/statenotify/notify_signon"))
+ write_status(buddy, _("%s has signed on."));
+}
+
+static void
+buddy_signoff_cb(PurpleBuddy *buddy, void *data)
+{
+ if (purple_prefs_get_bool("/plugins/core/statenotify/notify_signon"))
+ write_status(buddy, _("%s has signed off."));
+}
+
+static PurplePluginPrefFrame *
+get_plugin_pref_frame(PurplePlugin *plugin)
+{
+ PurplePluginPrefFrame *frame;
+ PurplePluginPref *ppref;
+
+ frame = purple_plugin_pref_frame_new();
+
+ ppref = purple_plugin_pref_new_with_label(_("Notify When"));
+ purple_plugin_pref_frame_add(frame, ppref);
+
+ ppref = purple_plugin_pref_new_with_name_and_label("/plugins/core/statenotify/notify_away", _("Buddy Goes _Away"));
+ purple_plugin_pref_frame_add(frame, ppref);
+
+ ppref = purple_plugin_pref_new_with_name_and_label("/plugins/core/statenotify/notify_idle", _("Buddy Goes _Idle"));
+ purple_plugin_pref_frame_add(frame, ppref);
+
+ ppref = purple_plugin_pref_new_with_name_and_label("/plugins/core/statenotify/notify_signon", _("Buddy _Signs On/Off"));
+ purple_plugin_pref_frame_add(frame, ppref);
+
+ return frame;
+}
+
+static GPluginPluginInfo *
+state_notify_query(GError **error)
+{
+ const gchar * const authors[] = {
+ "Christian Hammond <chipx86@gnupdate.org>",
+ NULL
+ };
+
+ return purple_plugin_info_new(
+ "id", STATENOTIFY_PLUGIN_ID,
+ "name", N_("Buddy State Notification"),
+ "version", DISPLAY_VERSION,
+ "category", N_("Notification"),
+ "summary", N_("Notifies in a conversation window when a "
+ "buddy goes or returns from away or idle."),
+ "description", N_("Notifies in a conversation window when a "
+ "buddy goes or returns from away or idle."),
+ "authors", authors,
+ "website", PURPLE_WEBSITE,
+ "abi-version", PURPLE_ABI_VERSION,
+ "pref-frame-cb", get_plugin_pref_frame,
+ NULL
+ );
+}
+
+static gboolean
+state_notify_load(GPluginPlugin *plugin, GError **error)
+{
+ void *blist_handle = purple_blist_get_handle();
+
+ purple_prefs_add_none("/plugins/core/statenotify");
+ purple_prefs_add_bool("/plugins/core/statenotify/notify_away", TRUE);
+ purple_prefs_add_bool("/plugins/core/statenotify/notify_idle", TRUE);
+ purple_prefs_add_bool("/plugins/core/statenotify/notify_signon", TRUE);
+
+ purple_signal_connect(blist_handle, "buddy-status-changed", plugin,
+ G_CALLBACK(buddy_status_changed_cb), NULL);
+ purple_signal_connect(blist_handle, "buddy-idle-changed", plugin,
+ G_CALLBACK(buddy_idle_changed_cb), NULL);
+ purple_signal_connect(blist_handle, "buddy-signed-on", plugin,
+ G_CALLBACK(buddy_signon_cb), NULL);
+ purple_signal_connect(blist_handle, "buddy-signed-off", plugin,
+ G_CALLBACK(buddy_signoff_cb), NULL);
+
+ return TRUE;
+}
+
+static gboolean
+state_notify_unload(GPluginPlugin *plugin, gboolean shutdown, GError **error)
+{
+ return TRUE;
+}
+
+GPLUGIN_NATIVE_PLUGIN_DECLARE(state_notify)