Commit e992a9db authored by Pascal Terjan's avatar Pascal Terjan Committed by Bastien Nocera

Use dbus API in pidgin plugin

And drop pidgin_plugin which is no longer needed
Signed-off-by: 's avatarPascal Terjan <pterjan@linuxfr.org>

https://bugzilla.gnome.org/show_bug.cgi?id=597039
parent 9f3bc7d7
if HAVE_PIDGIN
PIDGIN_PLUGIN_DIR=pidgin_plugin
endif
if HAVE_EVOLUTION
EVOLUTION_PLUGIN_DIR=evolution
endif
SUBDIRS = src $(GAIM_PLUGIN_DIR) $(PIDGIN_PLUGIN_DIR) $(EVOLUTION_PLUGIN_DIR) docs po
SUBDIRS = src $(EVOLUTION_PLUGIN_DIR) docs po
DIST_SUBDIRS = pidgin_plugin evolution src po
DIST_SUBDIRS = evolution src po
man_MANS = nautilus-sendto.1
......
......@@ -33,7 +33,6 @@ GLIB_REQUIRED=2.6.0
GTK_REQUIRED=2.12
EBOOK_REQUIRED=1.5.3
GCONF_REQUIRED=2.13.0
PIDGIN_REQUIRED=2.0.0
NAUTILUS_EXTENSION=2.13.3
DBUS_REQUIRED=1.0
DBUS_GLIB_REQUIRED=0.60
......@@ -45,7 +44,6 @@ AC_SUBST(GLIB_REQUIRED)
AC_SUBST(GTK_REQUIRED)
AC_SUBST(GCONF_REQUIRED)
AC_SUBST(EBOOK_REQUIRED)
AC_SUBST(PIDGIN_REQUIRED)
AC_SUBST(NAUTILUS_EXTENSION)
AC_SUBST(BLUETOOTH_REQUIRED)
AC_SUBST(DBUS_REQUIRED)
......@@ -200,20 +198,10 @@ for plugin in ${used_plugins}; do
fi
;;
pidgin)
PKG_CHECK_MODULES(PIDGIN, pidgin >= $PIDGIN_REQUIRED purple >= $PIDGIN_REQUIRED,
[
PIDGIN_LIBDIR=`pkg-config --variable=libdir purple`
PIDGIN_DATADIR=`pkg-config --variable=datadir purple`
AC_SUBST(PIDGIN_LIBDIR)
AC_SUBST(PIDGIN_DATADIR)
enable_pidgin=yes
],
[
enable_pidgin=no
]
)
PKG_CHECK_MODULES(PIDGIN, dbus-glib-1 >= $DBUS_GLIB_REQUIRED,
enable_pidgin=yes, enable_pidgin=no)
if test "${enable_pidgin}" != "yes" ; then
plugin_error_or_ignore "you need pidgin and libpurple installed for the pidgin plugin"
plugin_error_or_ignore "you need dbus-glib to build the pidgin plugin"
add_plugin="0"
fi
;;
......@@ -296,7 +284,6 @@ docs/Makefile
docs/nautilus-sendto/Makefile
docs/nautilus-sendto/version.xml
evolution/Makefile
pidgin_plugin/Makefile
po/Makefile.in
])
......
plugindir = $(libdir)/pidgin
plugin_LTLIBRARIES = nautilus.la
nautilus_la_SOURCES = nautilus-sendto-plugin.c
nautilus_la_LIBADD = $(PIDGIN_LIBS)
nautilus_la_LDFLAGS = -module -avoid-version -no-undefined
AM_CPPFLAGS = \
-DLIBDIR=\"$(PIDGIN_LIBDIR)/pidgin/\" \
-DDATADIR=\"$(PIDGIN_DATADIR)\" \
$(NAUTILUS_SENDTO_CFLAGS) \
$(PIDGIN_CFLAGS) \
$(WARN_CFLAGS)
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2004 Roberto Majadas
*
* 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 av.
*
* 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 02110-1301 USA.
*
* Author: Roberto Majadas <roberto.majadas@openshine.com>
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifndef PURPLE_PLUGINS
#define PURPLE_PLUGINS
#endif
#include <glib.h>
#include <glib/gstdio.h>
#include <glib/gi18n.h>
#include <errno.h>
#include "conversation.h"
#include "core.h"
#include "debug.h"
#include "prpl.h"
#include "notify.h"
#include "eventloop.h"
#include "gtkft.h"
#include "server.h"
#include "gtkplugin.h"
#include "pidgin.h"
#include "version.h"
#include "prefs.h"
#define PLUGIN_HOME ".gnome2/nautilus-sendto"
#define B_ONLINE "pidgin_buddies_online"
#define SAVE_TIMEOUT 5000
static guint take_spool_files_handler;
static gboolean taking_files;
static GString *buddies_str = NULL;
static char *
get_buddies_path (void)
{
return g_build_filename (g_get_home_dir(), PLUGIN_HOME, B_ONLINE, NULL);
}
static void
get_online_buddies (PurpleBlistNode *node, GString *str){
PurpleBlistNode *aux;
if (node == NULL)
return;
for (aux = node ; aux != NULL ;aux = aux->next) {
if (PURPLE_BLIST_NODE_IS_BUDDY(aux)){
PurpleBuddy *buddy;
buddy = (PurpleBuddy*)aux;
if (PURPLE_BUDDY_IS_ONLINE(buddy)){
char *alias;
if (buddy->alias == NULL){
if (buddy->server_alias == NULL){
alias = g_strdup (buddy->name);
}else{
alias = g_strdup (buddy->server_alias);
}
}else{
alias = g_strdup (buddy->alias);
}
g_string_append_printf (str,"%s\n%s\n%s\n%s\n",
buddy->account->username,
buddy->name,
alias,
buddy->account->protocol_id);
g_free (alias);
}
} else {
get_online_buddies (aux->child, str);
}
}
}
static void
save_online_buddies (PurpleBuddy *buddy, gpointer data)
{
PurpleBuddyList *blist;
GString *str;
char *fd_name;
fd_name = get_buddies_path ();
blist = purple_get_blist();
str = g_string_new ("---\n");
get_online_buddies (blist->root, str);
str = g_string_append (str, "---\n");
if (!g_string_equal (buddies_str, str)) {
GError *err = NULL;
if (g_file_set_contents (fd_name, str->str, str->len, &err) == FALSE) {
purple_debug_info ("nautilus", "couldn't save '%s': %s\n", fd_name, err->message);
g_error_free (err);
g_string_free (str, TRUE);
} else {
purple_debug_info ("nautilus", "saved blist online\n");
g_string_free (buddies_str, TRUE);
buddies_str = str;
}
} else {
g_string_free (str, TRUE);
purple_debug_info ("nautilus", "don't save blist online. No change\n");
}
g_free (fd_name);
}
static gboolean
init_plugin_stuff (void)
{
char *spool_tmp;
gboolean retval;
spool_tmp = g_build_filename (g_get_home_dir(), PLUGIN_HOME, "spool", "tmp", NULL);
if (g_mkdir_with_parents (spool_tmp, 0755) < 0) {
int error = errno;
g_warning ("Failed to create '%s': %s", spool_tmp, g_strerror (error));
retval = FALSE;
} else {
retval = TRUE;
}
g_free (spool_tmp);
return retval;
}
static void
send_file (GString *username, GString *cname,
GString *protocol, GString *file)
{
PurpleAccount *account;
account = purple_accounts_find (username->str, protocol->str);
if (account == NULL)
return;
serv_send_file (account->gc, cname->str, file->str);
}
static void
process_file (const char *file)
{
GIOChannel *io;
GString *username;
GString *cname;
GString *protocol;
GString *file_to_send;
username = g_string_new ("");
cname = g_string_new ("");
protocol = g_string_new ("");
file_to_send = g_string_new ("");
io = g_io_channel_new_file (file,"r",NULL);
if (io == NULL)
return;
purple_debug_info ("nautilus","Open spool file : %s\n",file);
g_io_channel_read_line_string (io, username, NULL, NULL);
username = g_string_truncate (username, username->len - 1);
g_io_channel_read_line_string (io, cname, NULL, NULL);
cname = g_string_truncate (cname, cname->len - 1);
g_io_channel_read_line_string (io, protocol, NULL, NULL);
protocol = g_string_truncate (protocol, protocol->len - 1);
while (G_IO_STATUS_EOF != g_io_channel_read_line_string (io,file_to_send, NULL, NULL)) {
if (file_to_send->len <=1)
continue;
file_to_send = g_string_truncate (file_to_send,
file_to_send->len - 1);
send_file (username, cname,
protocol, file_to_send);
}
g_string_free (username, TRUE);
g_string_free (cname, TRUE);
g_string_free (protocol, TRUE);
g_string_free (file_to_send, TRUE);
g_io_channel_shutdown (io, TRUE, NULL);
remove (file);
}
static int
take_spool_files (gpointer user_data)
{
char *plugin_spool;
if (taking_files == FALSE)
{
GDir *dir;
GError *err = NULL;
taking_files = TRUE;
plugin_spool = g_build_filename (g_get_home_dir(), PLUGIN_HOME, "spool", NULL);
dir = g_dir_open (plugin_spool, 0, &err);
g_free (plugin_spool);
if (dir == NULL) {
purple_debug_info ("nautilus","Can't open the spool dir: %s\n", err->message);
g_error_free (err);
} else {
const char *filename;
filename = g_dir_read_name (dir);
while (filename) {
char *file;
if (g_str_equal (filename, "tmp")) {
filename = g_dir_read_name (dir);
continue;
}
file = g_build_filename (g_get_home_dir(),
PLUGIN_HOME, "spool",
filename, NULL);
process_file (file);
g_free (file);
filename = g_dir_read_name (dir);
}
g_dir_close (dir);
}
taking_files = FALSE;
}
return TRUE;
}
static gboolean
plugin_load (PurplePlugin *plugin)
{
void *blist_handle;
if (init_plugin_stuff () == FALSE)
return FALSE;
buddies_str = g_string_new ("");
blist_handle = purple_blist_get_handle();
purple_signal_connect (blist_handle, "buddy-signed-on",
plugin, (PurpleCallback) save_online_buddies,
NULL);
purple_signal_connect (blist_handle, "buddy-signed-off",
plugin, (PurpleCallback) save_online_buddies,
NULL);
taking_files = FALSE;
take_spool_files_handler = purple_timeout_add_seconds (3, (GSourceFunc) take_spool_files, NULL);
/* And save a list already */
save_online_buddies (NULL, NULL);
return TRUE;
}
static gboolean
plugin_unload (PurplePlugin *plugin)
{
void *blist_handle;
char *fd_name;
blist_handle = purple_blist_get_handle();
purple_signal_disconnect (blist_handle, "buddy-signed-on",
plugin, (PurpleCallback) save_online_buddies);
purple_signal_disconnect (blist_handle, "buddy-signed-off",
plugin, (PurpleCallback) save_online_buddies);
fd_name = get_buddies_path ();
purple_timeout_remove (take_spool_files_handler);
g_unlink (fd_name);
g_free (fd_name);
g_string_free (buddies_str, TRUE);
buddies_str = NULL;
purple_debug_info ("nautilus", "Stop nautilus plugin\n");
return TRUE;
}
static gboolean
force_load_once (gpointer data)
{
PurplePlugin *plugin = (PurplePlugin *)data;
if (!purple_prefs_get_bool ("/plugins/gtk/nautilus/auto_loaded")) {
purple_debug_info ("nautilus", "Force loading nautilus plugin\n");
purple_plugin_load (plugin);
purple_plugins_save_loaded (PIDGIN_PREFS_ROOT "/plugins/loaded");
purple_prefs_set_bool ("/plugins/gtk/nautilus/auto_loaded", TRUE);
}
return FALSE;
}
static void
init_plugin(PurplePlugin *plugin)
{
purple_prefs_add_none ("/plugins/gtk/nautilus");
purple_prefs_add_bool ("/plugins/gtk/nautilus/auto_loaded", FALSE);
g_idle_add(force_load_once, plugin);
}
static PurplePluginInfo info = {
PURPLE_PLUGIN_MAGIC, /* api version */
PURPLE_MAJOR_VERSION,
PURPLE_MINOR_VERSION,
PURPLE_PLUGIN_STANDARD, /* type */
PIDGIN_PLUGIN_TYPE, /* ui requirement */
PURPLE_PRIORITY_DEFAULT, /* flags */
NULL, /* dependencies */
PURPLE_PRIORITY_DEFAULT, /* priority */
"gtk-nautilus", /* id */
N_("Nautilus Integration"), /* name */
"0.8", /* version */
N_("Provides integration with Nautilus"), /* summary */
N_("Provides integration with Nautilus"), /* description */
"Roberto Majadas <roberto.majadas@openshine.com>", /* author */
"www.gnome.org", /* homepage */
plugin_load, /* load */
plugin_unload, /* unload */
NULL, /* destroy */
NULL, /* ui info */
NULL, /* extra info */
NULL /* actions info */
};
PURPLE_INIT_PLUGIN(nautilus, init_plugin, info)
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
/*
* pidgin.c
* pidgin plugin for nautilus-sendto
*
* Copyright (C) 2004 Roberto Majadas
* Copyright (C) 2009 Pascal Terjan
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
......@@ -22,159 +26,239 @@
*/
#include "config.h"
#include <string.h>
#include <glib/gi18n-lib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include "nautilus-sendto-plugin.h"
#define OBJ_PATH "/im/pidgin/purple/PurpleObject"
#define INTERFACE "im.pidgin.purple.PurpleInterface"
#define SERVICE "im.pidgin.purple.PurpleService"
static DBusGProxy *proxy = NULL;
static GHashTable *contact_hash = NULL;
static gchar *blist_online = NULL;
typedef struct _ContactData {
char *username;
char *cname;
int account;
int id;
char *name;
char *alias;
char *prt;
} ContactData;
enum {
COL_ICON,
COL_ALIAS,
NUM_COLS
};
/*
* Print appropriate warnings when dbus raised error
* on queries
*/
static void
handle_dbus_exception(GError *error)
{
if (error == NULL) {
g_warning("[Pidgin] unable to parse result");
return;
}
else if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION) {
g_warning ("[Pidgin] caught remote method exception %s: %s",
dbus_g_error_get_name (error),
error->message);
}
g_error_free (error);
}
static gboolean
init (NstPlugin *plugin)
{
DBusGConnection *connection;
GError *error;
GArray *accounts;
g_print ("Init pidgin plugin\n");
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
blist_online = g_build_path ("/", g_get_home_dir(),
".gnome2/nautilus-sendto/pidgin_buddies_online",
NULL);
if (!g_file_test (blist_online, G_FILE_TEST_EXISTS)) {
g_free (blist_online);
blist_online = NULL;
error = NULL;
connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
if(error != NULL) {
g_warning("[Pidgin] unable to get session bus, error was:\n %s", error->message);
g_error_free(error);
return FALSE;
}
proxy = dbus_g_proxy_new_for_name(connection,
SERVICE,
OBJ_PATH,
INTERFACE);
dbus_g_connection_unref(connection);
if (proxy == NULL)
return FALSE;
error = NULL;
if (!dbus_g_proxy_call (proxy, "PurpleAccountsGetAllActive", &error, G_TYPE_INVALID,
DBUS_TYPE_G_INT_ARRAY, &accounts, G_TYPE_INVALID)) {
g_object_unref(proxy);
g_error_free(error);
return FALSE;
}
g_array_free(accounts, TRUE);
return TRUE;
}
static GdkPixbuf *
get_buddy_icon(int id)
{
GError *error;
GdkPixbuf *pixbuf = NULL;
gchar *path = NULL;
int icon;
error=NULL;
if (!dbus_g_proxy_call (proxy, "PurpleBuddyGetIcon", &error,
G_TYPE_INT, id,
G_TYPE_INVALID,
G_TYPE_INT, &icon, G_TYPE_INVALID)) {
handle_dbus_exception(error);
}
if (icon) {
if (!dbus_g_proxy_call (proxy, "PurpleBuddyIconGetFullPath", &error,
G_TYPE_INT, icon,
G_TYPE_INVALID,
G_TYPE_STRING, &path, G_TYPE_INVALID)) {
handle_dbus_exception(error);
}
//FIXME Get the size from somewhere
pixbuf = gdk_pixbuf_new_from_file_at_scale(path, 24, 24, TRUE, NULL);
}
return pixbuf;
}
static void
add_pidgin_contacts_to_model (GtkTreeStore *store,
GtkTreeIter *iter,
GtkTreeIter *parent)
{
GdkPixbuf *msn, *jabber, *yahoo, *aim, *icq, *bonjour;
GError *error;
GArray *contacts_list;
GArray *accounts;
int i, j;
GdkPixbuf *icon;
GtkIconTheme *it;
GIOChannel *io;
gsize terminator_pos;
GHashTableIter hiter;
GPtrArray *contacts_group;
ContactData *dat;
GValue val = {0,};
io = g_io_channel_new_file (blist_online, "r", NULL);
if (io == NULL)
if(proxy == NULL)
return;
error = NULL;
if (!dbus_g_proxy_call (proxy, "PurpleAccountsGetAllActive", &error, G_TYPE_INVALID,
DBUS_TYPE_G_INT_ARRAY,
&accounts, G_TYPE_INVALID)) {
handle_dbus_exception(error);
return;
}
contact_hash = g_hash_table_new (g_str_hash, g_str_equal);
gchar *tmp;
g_io_channel_read_line (io, &tmp, NULL, NULL, NULL);
g_free(tmp);
while (1){
dat = g_new0 (ContactData, 1);
if (g_io_channel_read_line (io, &dat->username, NULL, &terminator_pos,
NULL) == G_IO_STATUS_EOF)
break;
dat->username[terminator_pos] = '\0';
if (g_io_channel_read_line (io, &dat->cname, NULL, &terminator_pos,
NULL) == G_IO_STATUS_EOF)
break;
dat->cname[terminator_pos] = '\0';
if (g_io_channel_read_line (io, &dat->alias, NULL, &terminator_pos,
NULL) == G_IO_STATUS_EOF)
break;
dat->alias[terminator_pos] = '\0';
if (g_io_channel_read_line (io, &dat->prt, NULL, &terminator_pos,
NULL) == G_IO_STATUS_EOF)
break;
dat->prt[terminator_pos] = '\0';
contacts_group = g_hash_table_lookup (contact_hash, dat->alias);
if (contacts_group == NULL){
GPtrArray *new_group = g_ptr_array_new ();
g_ptr_array_add (new_group, dat);
g_hash_table_insert (contact_hash, dat->alias, new_group);
} else {
g_ptr_array_add (contacts_group, dat);
for(i = 0; i < accounts->len; i++) {
int account = g_array_index(accounts, int, i);
error = NULL;
if (!dbus_g_proxy_call (proxy, "PurpleFindBuddies", &error,
G_TYPE_INT, account,
G_TYPE_STRING, NULL,
G_TYPE_INVALID,
DBUS_TYPE_G_INT_ARRAY, &contacts_list, G_TYPE_INVALID)) {
handle_dbus_exception(error);
continue;
}
}
for(j = 0; j < contacts_list->len ; j++) {
int id = g_array_index(contacts_list, int, j);
int online;
error = NULL;
if (!dbus_g_proxy_call (proxy, "PurpleBuddyIsOnline", &error,
G_TYPE_INT, id,
G_TYPE_INVALID,
G_TYPE_INT, &online, G_TYPE_INVALID)) {
handle_dbus_exception(error);
continue;
}
if (!online)
continue;
dat = g_new0 (ContactData, 1);
dat->account = account;
dat->id = id;
error = NULL;
if (!dbus_g_proxy_call (proxy, "PurpleBuddyGetName", &error,
G_TYPE_INT, id,
G_TYPE_INVALID,
G_TYPE_STRING, &dat->name, G_TYPE_INVALID)) {
handle_dbus_exception(error);
g_free(dat);
continue;
}
if (!dbus_g_proxy_call (proxy, "PurpleBuddyGetAlias", &error,
G_TYPE_INT, id,
G_TYPE_INVALID,
G_TYPE_STRING, &dat->alias, G_TYPE_INVALID)) {
handle_dbus_exception(error);
}
g_io_channel_shutdown (io, TRUE, NULL);
it = gtk_icon_theme_get_default ();
msn = gtk_icon_theme_load_icon (it, "im-msn", 16,
GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
jabber = gtk_icon_theme_load_icon (it, "im-jabber", 16,
GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
yahoo = gtk_icon_theme_load_icon (it, "im-yahoo", 16,
GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
aim = gtk_icon_theme_load_icon (it, "im-aim", 16,
GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
icq = gtk_icon_theme_load_icon (it, "im-icq", 16,
GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
bonjour = gtk_icon_theme_load_icon (it, "network-wired", 16,
GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
contacts_group = g_hash_table_lookup (contact_hash, dat->alias);
if (contacts_group == NULL){
GPtrArray *new_group = g_ptr_array_new ();
g_ptr_array_add (new_group, dat);
g_hash_table_insert (contact_hash, dat->alias, new_group);
} else {
g_ptr_array_add (contacts_group, dat);
}
}
g_array_free(contacts_list, TRUE);
}
g_array_free (accounts, TRUE);
g_hash_table_iter_init (&hiter, contact_hash);
while (g_hash_table_iter_next (&hiter, NULL, (gpointer)&contacts_group)) {
GString *alias_e;
gint accounts;
dat = g_ptr_array_index (contacts_group, 0);
alias_e = g_string_new (dat->alias);
if (alias_e->len > 30){
alias_e = g_string_truncate (alias_e, 30);
alias_e = g_string_append (alias_e, "...");