2026-01-05 23:12:38 -07:00
|
|
|
/* dbus-plugin.c - zoitechat plugin for remote access using D-Bus
|
2011-02-24 04:14:30 +01:00
|
|
|
* Copyright (C) 2006 Claessens Xavier
|
|
|
|
|
*
|
|
|
|
|
* 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
|
2012-12-23 11:36:54 -08:00
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
2011-02-24 04:14:30 +01:00
|
|
|
*
|
|
|
|
|
* Claessens Xavier
|
|
|
|
|
* xclaesse@gmail.com
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
2026-04-27 11:04:04 -06:00
|
|
|
#include <gio/gio.h>
|
2011-02-24 04:14:30 +01:00
|
|
|
#include <glib/gi18n.h>
|
2026-01-05 23:12:38 -07:00
|
|
|
#include "zoitechat-plugin.h"
|
2014-07-19 13:36:13 +10:00
|
|
|
#include "dbus-plugin.h"
|
2011-02-24 04:14:30 +01:00
|
|
|
|
|
|
|
|
#define PNAME _("remote access")
|
|
|
|
|
#define PDESC _("plugin for remote access using DBUS")
|
|
|
|
|
#define PVERSION ""
|
|
|
|
|
|
2026-01-05 23:12:38 -07:00
|
|
|
#define DBUS_OBJECT_PATH "/org/zoitechat"
|
2026-04-27 11:04:04 -06:00
|
|
|
#define DBUS_INTERFACE_CONNECTION "org.zoitechat.connection"
|
|
|
|
|
#define DBUS_INTERFACE_PLUGIN "org.zoitechat.plugin"
|
|
|
|
|
#define DBUS_SERVICE_DBUS "org.freedesktop.DBus"
|
|
|
|
|
#define DBUS_PATH_DBUS "/org/freedesktop/DBus"
|
|
|
|
|
#define DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
|
|
|
|
|
|
|
|
|
|
static const char introspection_xml[] =
|
|
|
|
|
"<node>"
|
|
|
|
|
" <interface name='org.zoitechat.connection'>"
|
|
|
|
|
" <method name='Connect'>"
|
|
|
|
|
" <arg type='s' name='filename' direction='in'/>"
|
|
|
|
|
" <arg type='s' name='name' direction='in'/>"
|
|
|
|
|
" <arg type='s' name='desc' direction='in'/>"
|
|
|
|
|
" <arg type='s' name='version' direction='in'/>"
|
|
|
|
|
" <arg type='s' name='path' direction='out'/>"
|
|
|
|
|
" </method>"
|
|
|
|
|
" <method name='Disconnect'/>"
|
|
|
|
|
" </interface>"
|
|
|
|
|
" <interface name='org.zoitechat.plugin'>"
|
|
|
|
|
" <method name='Command'><arg type='s' direction='in'/></method>"
|
|
|
|
|
" <method name='Print'><arg type='s' direction='in'/></method>"
|
|
|
|
|
" <method name='FindContext'><arg type='s' direction='in'/><arg type='s' direction='in'/><arg type='u' direction='out'/></method>"
|
|
|
|
|
" <method name='GetContext'><arg type='u' direction='out'/></method>"
|
|
|
|
|
" <method name='SetContext'><arg type='u' direction='in'/><arg type='b' direction='out'/></method>"
|
|
|
|
|
" <method name='GetInfo'><arg type='s' direction='in'/><arg type='s' direction='out'/></method>"
|
|
|
|
|
" <method name='GetPrefs'><arg type='s' direction='in'/><arg type='i' direction='out'/><arg type='s' direction='out'/><arg type='i' direction='out'/></method>"
|
|
|
|
|
" <method name='HookCommand'><arg type='s' direction='in'/><arg type='i' direction='in'/><arg type='s' direction='in'/><arg type='i' direction='in'/><arg type='u' direction='out'/></method>"
|
|
|
|
|
" <method name='HookServer'><arg type='s' direction='in'/><arg type='i' direction='in'/><arg type='i' direction='in'/><arg type='u' direction='out'/></method>"
|
|
|
|
|
" <method name='HookPrint'><arg type='s' direction='in'/><arg type='i' direction='in'/><arg type='i' direction='in'/><arg type='u' direction='out'/></method>"
|
|
|
|
|
" <method name='Unhook'><arg type='u' direction='in'/></method>"
|
|
|
|
|
" <method name='ListGet'><arg type='s' direction='in'/><arg type='u' direction='out'/></method>"
|
|
|
|
|
" <method name='ListNext'><arg type='u' direction='in'/><arg type='b' direction='out'/></method>"
|
|
|
|
|
" <method name='ListStr'><arg type='u' direction='in'/><arg type='s' direction='in'/><arg type='s' direction='out'/></method>"
|
|
|
|
|
" <method name='ListInt'><arg type='u' direction='in'/><arg type='s' direction='in'/><arg type='i' direction='out'/></method>"
|
|
|
|
|
" <method name='ListTime'><arg type='u' direction='in'/><arg type='s' direction='in'/><arg type='t' direction='out'/></method>"
|
|
|
|
|
" <method name='ListFields'><arg type='s' direction='in'/><arg type='as' direction='out'/></method>"
|
|
|
|
|
" <method name='ListFree'><arg type='u' direction='in'/></method>"
|
|
|
|
|
" <method name='EmitPrint'><arg type='s' direction='in'/><arg type='as' direction='in'/><arg type='b' direction='out'/></method>"
|
|
|
|
|
" <method name='Nickcmp'><arg type='s' direction='in'/><arg type='s' direction='in'/><arg type='i' direction='out'/></method>"
|
|
|
|
|
" <method name='Strip'><arg type='s' direction='in'/><arg type='i' direction='in'/><arg type='i' direction='in'/><arg type='s' direction='out'/></method>"
|
|
|
|
|
" <method name='SendModes'><arg type='as' direction='in'/><arg type='i' direction='in'/><arg type='y' direction='in'/><arg type='y' direction='in'/></method>"
|
|
|
|
|
" <signal name='CommandSignal'><arg type='as'/><arg type='as'/><arg type='u'/><arg type='u'/></signal>"
|
|
|
|
|
" <signal name='ServerSignal'><arg type='as'/><arg type='as'/><arg type='u'/><arg type='u'/></signal>"
|
|
|
|
|
" <signal name='PrintSignal'><arg type='as'/><arg type='u'/><arg type='u'/></signal>"
|
|
|
|
|
" <signal name='UnloadSignal'/>"
|
|
|
|
|
" </interface>"
|
|
|
|
|
"</node>";
|
2011-02-24 04:14:30 +01:00
|
|
|
|
2026-01-05 23:12:38 -07:00
|
|
|
static zoitechat_plugin *ph;
|
2026-04-27 11:04:04 -06:00
|
|
|
static guint last_context_id;
|
|
|
|
|
static GList *contexts;
|
|
|
|
|
static GHashTable *clients;
|
|
|
|
|
static GDBusConnection *connection;
|
|
|
|
|
static GDBusNodeInfo *introspection_data;
|
|
|
|
|
static guint name_owner_subscription;
|
|
|
|
|
static guint object_count;
|
2011-02-24 04:14:30 +01:00
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
typedef struct
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
|
|
|
|
guint id;
|
|
|
|
|
int return_value;
|
2026-01-05 23:12:38 -07:00
|
|
|
zoitechat_hook *hook;
|
2026-04-27 11:04:04 -06:00
|
|
|
struct _RemoteObject *obj;
|
2011-02-24 04:14:30 +01:00
|
|
|
} HookInfo;
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
guint id;
|
2026-01-05 23:12:38 -07:00
|
|
|
zoitechat_context *context;
|
2011-02-24 04:14:30 +01:00
|
|
|
} ContextInfo;
|
|
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
typedef struct _RemoteObject
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
guint registration_id;
|
|
|
|
|
guint last_hook_id;
|
|
|
|
|
guint last_list_id;
|
|
|
|
|
zoitechat_context *context;
|
|
|
|
|
char *dbus_path;
|
|
|
|
|
char *filename;
|
|
|
|
|
void *handle;
|
|
|
|
|
GHashTable *hooks;
|
|
|
|
|
GHashTable *lists;
|
|
|
|
|
} RemoteObject;
|
2011-02-24 04:14:30 +01:00
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
static char **build_list (char *word[]);
|
|
|
|
|
static guint context_list_find_id (zoitechat_context *context);
|
|
|
|
|
static zoitechat_context *context_list_find_context (guint id);
|
|
|
|
|
static gboolean emit_signal (RemoteObject *obj, const char *name, GVariant *params);
|
|
|
|
|
static const GDBusInterfaceVTable connection_vtable;
|
2011-02-24 04:14:30 +01:00
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
hook_info_destroy (gpointer data)
|
|
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
HookInfo *info = (HookInfo *)data;
|
2011-02-24 04:14:30 +01:00
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
if (!info)
|
2011-02-24 04:14:30 +01:00
|
|
|
return;
|
2026-04-27 11:04:04 -06:00
|
|
|
|
2026-01-05 23:12:38 -07:00
|
|
|
zoitechat_unhook (ph, info->hook);
|
2011-02-24 04:14:30 +01:00
|
|
|
g_free (info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
list_info_destroy (gpointer data)
|
|
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
zoitechat_list_free (ph, (zoitechat_list *)data);
|
2011-02-24 04:14:30 +01:00
|
|
|
}
|
|
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
static RemoteObject *
|
|
|
|
|
remote_object_new (const char *path)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
RemoteObject *obj = g_new0 (RemoteObject, 1);
|
2011-02-24 04:14:30 +01:00
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
obj->hooks = g_hash_table_new_full (g_int_hash, g_int_equal, NULL, hook_info_destroy);
|
|
|
|
|
obj->lists = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, list_info_destroy);
|
|
|
|
|
obj->dbus_path = g_strdup (path);
|
2026-01-05 23:12:38 -07:00
|
|
|
obj->context = zoitechat_get_context (ph);
|
2011-02-24 04:14:30 +01:00
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
return obj;
|
2011-02-24 04:14:30 +01:00
|
|
|
}
|
|
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
static void
|
|
|
|
|
remote_object_free (RemoteObject *obj)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
if (!obj)
|
|
|
|
|
return;
|
2011-02-24 04:14:30 +01:00
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
if (connection && obj->registration_id)
|
|
|
|
|
g_dbus_connection_unregister_object (connection, obj->registration_id);
|
|
|
|
|
g_hash_table_destroy (obj->lists);
|
|
|
|
|
g_hash_table_destroy (obj->hooks);
|
|
|
|
|
g_free (obj->dbus_path);
|
|
|
|
|
g_free (obj->filename);
|
|
|
|
|
if (obj->handle)
|
|
|
|
|
zoitechat_plugingui_remove (ph, obj->handle);
|
|
|
|
|
g_free (obj);
|
2011-02-24 04:14:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_command (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
const char *command)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
if (zoitechat_set_context (ph, obj->context))
|
2026-01-05 23:12:38 -07:00
|
|
|
zoitechat_command (ph, command);
|
2011-02-24 04:14:30 +01:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_print (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
const char *text)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
if (zoitechat_set_context (ph, obj->context))
|
2026-01-05 23:12:38 -07:00
|
|
|
zoitechat_print (ph, text);
|
2011-02-24 04:14:30 +01:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_find_context (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
const char *server,
|
|
|
|
|
const char *channel,
|
|
|
|
|
guint *ret_id)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-01-05 23:12:38 -07:00
|
|
|
zoitechat_context *context;
|
2011-02-24 04:14:30 +01:00
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
if (*server == '\0')
|
2011-02-24 04:14:30 +01:00
|
|
|
server = NULL;
|
2026-04-27 11:04:04 -06:00
|
|
|
if (*channel == '\0')
|
2011-02-24 04:14:30 +01:00
|
|
|
channel = NULL;
|
2026-01-05 23:12:38 -07:00
|
|
|
context = zoitechat_find_context (ph, server, channel);
|
2011-02-24 04:14:30 +01:00
|
|
|
*ret_id = context_list_find_id (context);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_get_context (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
guint *ret_id)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
|
|
|
|
*ret_id = context_list_find_id (obj->context);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_set_context (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
guint id,
|
|
|
|
|
gboolean *ret)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
zoitechat_context *context = context_list_find_context (id);
|
|
|
|
|
|
|
|
|
|
if (!context)
|
|
|
|
|
{
|
2011-02-24 04:14:30 +01:00
|
|
|
*ret = FALSE;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2026-04-27 11:04:04 -06:00
|
|
|
|
2011-02-24 04:14:30 +01:00
|
|
|
obj->context = context;
|
|
|
|
|
*ret = TRUE;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_get_info (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
const char *id,
|
|
|
|
|
char **ret_info)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
if (!zoitechat_set_context (ph, obj->context) || g_str_equal (id, "win_ptr"))
|
|
|
|
|
{
|
2011-02-24 04:14:30 +01:00
|
|
|
*ret_info = NULL;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2026-04-27 11:04:04 -06:00
|
|
|
|
2026-01-05 23:12:38 -07:00
|
|
|
*ret_info = g_strdup (zoitechat_get_info (ph, id));
|
2011-02-24 04:14:30 +01:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_get_prefs (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
const char *name,
|
|
|
|
|
int *ret_type,
|
|
|
|
|
char **ret_str,
|
|
|
|
|
int *ret_int)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
|
|
|
|
const char *str;
|
|
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
if (!zoitechat_set_context (ph, obj->context))
|
|
|
|
|
{
|
2011-02-24 04:14:30 +01:00
|
|
|
*ret_type = 0;
|
2026-04-27 11:04:04 -06:00
|
|
|
*ret_str = NULL;
|
|
|
|
|
*ret_int = 0;
|
2011-02-24 04:14:30 +01:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
2026-04-27 11:04:04 -06:00
|
|
|
|
2026-01-05 23:12:38 -07:00
|
|
|
*ret_type = zoitechat_get_prefs (ph, name, &str, ret_int);
|
2011-02-24 04:14:30 +01:00
|
|
|
*ret_str = g_strdup (str);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
server_hook_cb (char *word[],
|
|
|
|
|
char *word_eol[],
|
|
|
|
|
void *userdata)
|
|
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
HookInfo *info = (HookInfo *)userdata;
|
|
|
|
|
char **arg1 = build_list (word + 1);
|
|
|
|
|
char **arg2 = build_list (word_eol + 1);
|
|
|
|
|
guint context_id;
|
|
|
|
|
GVariant *params;
|
2011-02-24 04:14:30 +01:00
|
|
|
|
2026-01-05 23:12:38 -07:00
|
|
|
info->obj->context = zoitechat_get_context (ph);
|
2026-04-27 11:04:04 -06:00
|
|
|
context_id = context_list_find_id (info->obj->context);
|
|
|
|
|
params = g_variant_new ("(^as^asuu)", arg1 ? arg1 : (char *[]){ NULL }, arg2 ? arg2 : (char *[]){ NULL }, info->id, context_id);
|
|
|
|
|
emit_signal (info->obj, "ServerSignal", params);
|
2011-02-24 04:14:30 +01:00
|
|
|
g_strfreev (arg1);
|
|
|
|
|
g_strfreev (arg2);
|
|
|
|
|
return info->return_value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
command_hook_cb (char *word[],
|
|
|
|
|
char *word_eol[],
|
|
|
|
|
void *userdata)
|
|
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
HookInfo *info = (HookInfo *)userdata;
|
|
|
|
|
char **arg1 = build_list (word + 1);
|
|
|
|
|
char **arg2 = build_list (word_eol + 1);
|
|
|
|
|
guint context_id;
|
|
|
|
|
GVariant *params;
|
2011-02-24 04:14:30 +01:00
|
|
|
|
2026-01-05 23:12:38 -07:00
|
|
|
info->obj->context = zoitechat_get_context (ph);
|
2026-04-27 11:04:04 -06:00
|
|
|
context_id = context_list_find_id (info->obj->context);
|
|
|
|
|
params = g_variant_new ("(^as^asuu)", arg1 ? arg1 : (char *[]){ NULL }, arg2 ? arg2 : (char *[]){ NULL }, info->id, context_id);
|
|
|
|
|
emit_signal (info->obj, "CommandSignal", params);
|
2011-02-24 04:14:30 +01:00
|
|
|
g_strfreev (arg1);
|
|
|
|
|
g_strfreev (arg2);
|
|
|
|
|
return info->return_value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
print_hook_cb (char *word[],
|
|
|
|
|
void *userdata)
|
|
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
HookInfo *info = (HookInfo *)userdata;
|
|
|
|
|
char **arg1 = build_list (word + 1);
|
|
|
|
|
guint context_id;
|
|
|
|
|
GVariant *params;
|
2011-02-24 04:14:30 +01:00
|
|
|
|
2026-01-05 23:12:38 -07:00
|
|
|
info->obj->context = zoitechat_get_context (ph);
|
2026-04-27 11:04:04 -06:00
|
|
|
context_id = context_list_find_id (info->obj->context);
|
|
|
|
|
params = g_variant_new ("(^asuu)", arg1 ? arg1 : (char *[]){ NULL }, info->id, context_id);
|
|
|
|
|
emit_signal (info->obj, "PrintSignal", params);
|
2011-02-24 04:14:30 +01:00
|
|
|
g_strfreev (arg1);
|
|
|
|
|
return info->return_value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_hook_command (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
const char *name,
|
|
|
|
|
int priority,
|
|
|
|
|
const char *help_text,
|
|
|
|
|
int return_value,
|
|
|
|
|
guint *ret_id)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
HookInfo *info = g_new0 (HookInfo, 1);
|
2011-02-24 04:14:30 +01:00
|
|
|
|
|
|
|
|
info->obj = obj;
|
|
|
|
|
info->return_value = return_value;
|
|
|
|
|
info->id = ++obj->last_hook_id;
|
2026-04-27 11:04:04 -06:00
|
|
|
info->hook = zoitechat_hook_command (ph, name, priority, command_hook_cb, help_text, info);
|
2011-02-24 04:14:30 +01:00
|
|
|
g_hash_table_insert (obj->hooks, &info->id, info);
|
|
|
|
|
*ret_id = info->id;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_hook_server (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
const char *name,
|
|
|
|
|
int priority,
|
|
|
|
|
int return_value,
|
|
|
|
|
guint *ret_id)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
HookInfo *info = g_new0 (HookInfo, 1);
|
2011-02-24 04:14:30 +01:00
|
|
|
|
|
|
|
|
info->obj = obj;
|
|
|
|
|
info->return_value = return_value;
|
|
|
|
|
info->id = ++obj->last_hook_id;
|
2026-04-27 11:04:04 -06:00
|
|
|
info->hook = zoitechat_hook_server (ph, name, priority, server_hook_cb, info);
|
2011-02-24 04:14:30 +01:00
|
|
|
g_hash_table_insert (obj->hooks, &info->id, info);
|
|
|
|
|
*ret_id = info->id;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_hook_print (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
const char *name,
|
|
|
|
|
int priority,
|
|
|
|
|
int return_value,
|
|
|
|
|
guint *ret_id)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
HookInfo *info = g_new0 (HookInfo, 1);
|
2011-02-24 04:14:30 +01:00
|
|
|
|
|
|
|
|
info->obj = obj;
|
|
|
|
|
info->return_value = return_value;
|
|
|
|
|
info->id = ++obj->last_hook_id;
|
2026-04-27 11:04:04 -06:00
|
|
|
info->hook = zoitechat_hook_print (ph, name, priority, print_hook_cb, info);
|
2011-02-24 04:14:30 +01:00
|
|
|
g_hash_table_insert (obj->hooks, &info->id, info);
|
|
|
|
|
*ret_id = info->id;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_unhook (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
guint id)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
|
|
|
|
g_hash_table_remove (obj->hooks, &id);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_list_get (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
const char *name,
|
|
|
|
|
guint *ret_id)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-01-05 23:12:38 -07:00
|
|
|
zoitechat_list *xlist;
|
2011-02-24 04:14:30 +01:00
|
|
|
guint *id;
|
|
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
if (!zoitechat_set_context (ph, obj->context))
|
|
|
|
|
{
|
2011-02-24 04:14:30 +01:00
|
|
|
*ret_id = 0;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2026-04-27 11:04:04 -06:00
|
|
|
|
2026-01-05 23:12:38 -07:00
|
|
|
xlist = zoitechat_list_get (ph, name);
|
2026-04-27 11:04:04 -06:00
|
|
|
if (!xlist)
|
|
|
|
|
{
|
2011-02-24 04:14:30 +01:00
|
|
|
*ret_id = 0;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2026-04-27 11:04:04 -06:00
|
|
|
|
2011-02-24 04:14:30 +01:00
|
|
|
id = g_new (guint, 1);
|
|
|
|
|
*id = ++obj->last_list_id;
|
|
|
|
|
*ret_id = *id;
|
2026-04-27 11:04:04 -06:00
|
|
|
g_hash_table_insert (obj->lists, id, xlist);
|
2011-02-24 04:14:30 +01:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2026-04-27 11:04:04 -06:00
|
|
|
remote_object_list_next (RemoteObject *obj,
|
|
|
|
|
guint id,
|
|
|
|
|
gboolean *ret)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
zoitechat_list *xlist = g_hash_table_lookup (obj->lists, &id);
|
|
|
|
|
|
|
|
|
|
if (!xlist)
|
|
|
|
|
{
|
2011-02-24 04:14:30 +01:00
|
|
|
*ret = FALSE;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
*ret = zoitechat_list_next (ph, xlist);
|
2011-02-24 04:14:30 +01:00
|
|
|
return TRUE;
|
2026-04-27 11:04:04 -06:00
|
|
|
}
|
2011-02-24 04:14:30 +01:00
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_list_str (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
guint id,
|
|
|
|
|
const char *name,
|
|
|
|
|
char **ret_str)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
zoitechat_list *xlist = g_hash_table_lookup (obj->lists, &id);
|
|
|
|
|
|
|
|
|
|
if (xlist == NULL && !zoitechat_set_context (ph, obj->context))
|
|
|
|
|
{
|
2011-02-24 04:14:30 +01:00
|
|
|
*ret_str = NULL;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2026-04-27 11:04:04 -06:00
|
|
|
|
|
|
|
|
if (g_str_equal (name, "context"))
|
|
|
|
|
{
|
2011-02-24 04:14:30 +01:00
|
|
|
*ret_str = NULL;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
*ret_str = g_strdup (zoitechat_list_str (ph, xlist, name));
|
2011-02-24 04:14:30 +01:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_list_int (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
guint id,
|
|
|
|
|
const char *name,
|
|
|
|
|
int *ret_int)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
zoitechat_list *xlist = g_hash_table_lookup (obj->lists, &id);
|
|
|
|
|
|
|
|
|
|
if (xlist == NULL && !zoitechat_set_context (ph, obj->context))
|
|
|
|
|
{
|
2011-02-24 04:14:30 +01:00
|
|
|
*ret_int = -1;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2026-04-27 11:04:04 -06:00
|
|
|
|
|
|
|
|
if (g_str_equal (name, "context"))
|
|
|
|
|
{
|
|
|
|
|
zoitechat_context *context = (zoitechat_context *)zoitechat_list_str (ph, xlist, name);
|
2011-02-24 04:14:30 +01:00
|
|
|
*ret_int = context_list_find_id (context);
|
|
|
|
|
}
|
2026-04-27 11:04:04 -06:00
|
|
|
else
|
|
|
|
|
*ret_int = zoitechat_list_int (ph, xlist, name);
|
2011-02-24 04:14:30 +01:00
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_list_time (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
guint id,
|
|
|
|
|
const char *name,
|
|
|
|
|
guint64 *ret_time)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
zoitechat_list *xlist = g_hash_table_lookup (obj->lists, &id);
|
|
|
|
|
|
|
|
|
|
if (!xlist)
|
|
|
|
|
{
|
|
|
|
|
*ret_time = (guint64)-1;
|
2011-02-24 04:14:30 +01:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
2026-04-27 11:04:04 -06:00
|
|
|
|
2026-01-05 23:12:38 -07:00
|
|
|
*ret_time = zoitechat_list_time (ph, xlist, name);
|
2011-02-24 04:14:30 +01:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2026-04-27 11:04:04 -06:00
|
|
|
remote_object_list_fields (const char *name,
|
|
|
|
|
char ***ret)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
*ret = g_strdupv ((char **)zoitechat_list_fields (ph, name));
|
|
|
|
|
if (*ret == NULL)
|
|
|
|
|
*ret = g_new0 (char *, 1);
|
2011-02-24 04:14:30 +01:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_list_free (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
guint id)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
|
|
|
|
g_hash_table_remove (obj->lists, &id);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_emit_print (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
const char *event_name,
|
|
|
|
|
const char *args[],
|
|
|
|
|
gboolean *ret)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
const char *argv[4] = { NULL, NULL, NULL, NULL };
|
2011-02-24 04:14:30 +01:00
|
|
|
int i;
|
2026-04-27 11:04:04 -06:00
|
|
|
|
|
|
|
|
for (i = 0; i < 4 && args[i] != NULL; i++)
|
2011-02-24 04:14:30 +01:00
|
|
|
argv[i] = args[i];
|
|
|
|
|
|
2026-01-05 23:12:38 -07:00
|
|
|
*ret = zoitechat_set_context (ph, obj->context);
|
2026-04-27 11:04:04 -06:00
|
|
|
if (*ret)
|
|
|
|
|
*ret = zoitechat_emit_print (ph, event_name, argv[0], argv[1], argv[2], argv[3]);
|
2011-02-24 04:14:30 +01:00
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_nickcmp (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
const char *nick1,
|
|
|
|
|
const char *nick2,
|
|
|
|
|
int *ret)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-01-05 23:12:38 -07:00
|
|
|
zoitechat_set_context (ph, obj->context);
|
|
|
|
|
*ret = zoitechat_nickcmp (ph, nick1, nick2);
|
2011-02-24 04:14:30 +01:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2026-04-27 11:04:04 -06:00
|
|
|
remote_object_strip (const char *str,
|
|
|
|
|
int len,
|
|
|
|
|
int flag,
|
|
|
|
|
char **ret_str)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-01-05 23:12:38 -07:00
|
|
|
*ret_str = zoitechat_strip (ph, str, len, flag);
|
2011-02-24 04:14:30 +01:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
remote_object_send_modes (RemoteObject *obj,
|
2026-04-27 11:04:04 -06:00
|
|
|
const char *targets[],
|
|
|
|
|
int modes_per_line,
|
|
|
|
|
char sign,
|
|
|
|
|
char mode)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
if (zoitechat_set_context (ph, obj->context))
|
|
|
|
|
{
|
2026-01-05 23:12:38 -07:00
|
|
|
zoitechat_send_modes (ph, targets,
|
2026-04-27 11:04:04 -06:00
|
|
|
g_strv_length ((char **)targets),
|
|
|
|
|
modes_per_line,
|
|
|
|
|
sign,
|
|
|
|
|
mode);
|
2011-02-24 04:14:30 +01:00
|
|
|
}
|
2026-04-27 11:04:04 -06:00
|
|
|
|
2011-02-24 04:14:30 +01:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
static gboolean
|
|
|
|
|
emit_signal (RemoteObject *obj, const char *name, GVariant *params)
|
|
|
|
|
{
|
|
|
|
|
if (!connection)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
return g_dbus_connection_emit_signal (connection,
|
|
|
|
|
NULL,
|
|
|
|
|
obj->dbus_path,
|
|
|
|
|
DBUS_INTERFACE_PLUGIN,
|
|
|
|
|
name,
|
|
|
|
|
params,
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
clients_find_path_foreach (gpointer key,
|
|
|
|
|
gpointer value,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
RemoteObject *obj = value;
|
|
|
|
|
return g_str_equal (obj->dbus_path, (const char *)user_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static RemoteObject *
|
|
|
|
|
find_remote_by_path (const char *object_path)
|
|
|
|
|
{
|
|
|
|
|
if (g_str_equal (object_path, DBUS_OBJECT_PATH "/Remote"))
|
|
|
|
|
return g_hash_table_lookup (clients, "__root__");
|
|
|
|
|
|
|
|
|
|
return g_hash_table_find (clients, clients_find_path_foreach, (gpointer)object_path);
|
|
|
|
|
}
|
2011-02-24 04:14:30 +01:00
|
|
|
|
|
|
|
|
static void
|
2026-04-27 11:04:04 -06:00
|
|
|
method_call_cb (GDBusConnection *conn,
|
|
|
|
|
const gchar *sender,
|
|
|
|
|
const gchar *object_path,
|
|
|
|
|
const gchar *interface_name,
|
|
|
|
|
const gchar *method_name,
|
|
|
|
|
GVariant *parameters,
|
|
|
|
|
GDBusMethodInvocation *invocation,
|
|
|
|
|
gpointer user_data)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
RemoteObject *obj;
|
|
|
|
|
|
|
|
|
|
if (g_str_equal (interface_name, DBUS_INTERFACE_CONNECTION))
|
|
|
|
|
{
|
|
|
|
|
if (g_str_equal (method_name, "Connect"))
|
|
|
|
|
{
|
|
|
|
|
const char *filename;
|
|
|
|
|
const char *name;
|
|
|
|
|
const char *desc;
|
|
|
|
|
const char *version;
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
char *path;
|
|
|
|
|
gchar count_buffer[15];
|
|
|
|
|
|
|
|
|
|
g_variant_get (parameters, "(&s&s&s&s)", &filename, &name, &desc, &version);
|
|
|
|
|
obj = g_hash_table_lookup (clients, sender);
|
|
|
|
|
if (obj)
|
|
|
|
|
{
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", obj->dbus_path));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_snprintf (count_buffer, sizeof count_buffer, "%u", object_count++);
|
|
|
|
|
path = g_build_filename (DBUS_OBJECT_PATH, count_buffer, NULL);
|
|
|
|
|
obj = remote_object_new (path);
|
|
|
|
|
obj->filename = g_path_get_basename (filename);
|
|
|
|
|
obj->handle = zoitechat_plugingui_add (ph, obj->filename, name, desc, version, NULL);
|
|
|
|
|
obj->registration_id = g_dbus_connection_register_object (
|
|
|
|
|
conn,
|
|
|
|
|
obj->dbus_path,
|
|
|
|
|
introspection_data->interfaces[1],
|
|
|
|
|
&connection_vtable,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
&error);
|
|
|
|
|
if (!obj->registration_id)
|
|
|
|
|
{
|
|
|
|
|
g_dbus_method_invocation_return_dbus_error (invocation, "org.zoitechat.Error", error->message);
|
|
|
|
|
g_error_free (error);
|
|
|
|
|
remote_object_free (obj);
|
|
|
|
|
g_free (path);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
g_hash_table_insert (clients, g_strdup (sender), obj);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", obj->dbus_path));
|
|
|
|
|
g_free (path);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (g_str_equal (method_name, "Disconnect"))
|
|
|
|
|
{
|
|
|
|
|
g_hash_table_remove (clients, sender);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
obj = find_remote_by_path (object_path);
|
|
|
|
|
if (!obj)
|
|
|
|
|
{
|
|
|
|
|
g_dbus_method_invocation_return_dbus_error (invocation, "org.zoitechat.Error", "No such object");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (g_str_equal (method_name, "Command"))
|
|
|
|
|
{
|
|
|
|
|
const char *command;
|
|
|
|
|
g_variant_get (parameters, "(&s)", &command);
|
|
|
|
|
remote_object_command (obj, command);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "Print"))
|
|
|
|
|
{
|
|
|
|
|
const char *text;
|
|
|
|
|
g_variant_get (parameters, "(&s)", &text);
|
|
|
|
|
remote_object_print (obj, text);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "FindContext"))
|
|
|
|
|
{
|
|
|
|
|
const char *server;
|
|
|
|
|
const char *channel;
|
|
|
|
|
guint id;
|
|
|
|
|
g_variant_get (parameters, "(&s&s)", &server, &channel);
|
|
|
|
|
remote_object_find_context (obj, server, channel, &id);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", id));
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "GetContext"))
|
|
|
|
|
{
|
|
|
|
|
guint id;
|
|
|
|
|
remote_object_get_context (obj, &id);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", id));
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "SetContext"))
|
|
|
|
|
{
|
|
|
|
|
guint id;
|
|
|
|
|
gboolean ret;
|
|
|
|
|
g_variant_get (parameters, "(u)", &id);
|
|
|
|
|
remote_object_set_context (obj, id, &ret);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret));
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "GetInfo"))
|
|
|
|
|
{
|
|
|
|
|
const char *id;
|
|
|
|
|
char *ret_info;
|
|
|
|
|
g_variant_get (parameters, "(&s)", &id);
|
|
|
|
|
remote_object_get_info (obj, id, &ret_info);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", ret_info ? ret_info : ""));
|
|
|
|
|
g_free (ret_info);
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "GetPrefs"))
|
|
|
|
|
{
|
|
|
|
|
const char *name;
|
|
|
|
|
int ret_type;
|
|
|
|
|
char *ret_str;
|
|
|
|
|
int ret_int;
|
|
|
|
|
g_variant_get (parameters, "(&s)", &name);
|
|
|
|
|
remote_object_get_prefs (obj, name, &ret_type, &ret_str, &ret_int);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(isi)", ret_type, ret_str ? ret_str : "", ret_int));
|
|
|
|
|
g_free (ret_str);
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "HookCommand"))
|
|
|
|
|
{
|
|
|
|
|
const char *name;
|
|
|
|
|
int priority;
|
|
|
|
|
const char *help;
|
|
|
|
|
int rv;
|
|
|
|
|
guint id;
|
|
|
|
|
g_variant_get (parameters, "(&si&si)", &name, &priority, &help, &rv);
|
|
|
|
|
remote_object_hook_command (obj, name, priority, help, rv, &id);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", id));
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "HookServer"))
|
|
|
|
|
{
|
|
|
|
|
const char *name;
|
|
|
|
|
int priority;
|
|
|
|
|
int rv;
|
|
|
|
|
guint id;
|
|
|
|
|
g_variant_get (parameters, "(&sii)", &name, &priority, &rv);
|
|
|
|
|
remote_object_hook_server (obj, name, priority, rv, &id);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", id));
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "HookPrint"))
|
|
|
|
|
{
|
|
|
|
|
const char *name;
|
|
|
|
|
int priority;
|
|
|
|
|
int rv;
|
|
|
|
|
guint id;
|
|
|
|
|
g_variant_get (parameters, "(&sii)", &name, &priority, &rv);
|
|
|
|
|
remote_object_hook_print (obj, name, priority, rv, &id);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", id));
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "Unhook"))
|
|
|
|
|
{
|
|
|
|
|
guint id;
|
|
|
|
|
g_variant_get (parameters, "(u)", &id);
|
|
|
|
|
remote_object_unhook (obj, id);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
|
2011-02-24 04:14:30 +01:00
|
|
|
}
|
2026-04-27 11:04:04 -06:00
|
|
|
else if (g_str_equal (method_name, "ListGet"))
|
|
|
|
|
{
|
|
|
|
|
const char *name;
|
|
|
|
|
guint id;
|
|
|
|
|
g_variant_get (parameters, "(&s)", &name);
|
|
|
|
|
remote_object_list_get (obj, name, &id);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(u)", id));
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "ListNext"))
|
|
|
|
|
{
|
|
|
|
|
guint id;
|
|
|
|
|
gboolean ret;
|
|
|
|
|
g_variant_get (parameters, "(u)", &id);
|
|
|
|
|
remote_object_list_next (obj, id, &ret);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret));
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "ListStr"))
|
|
|
|
|
{
|
|
|
|
|
guint id;
|
|
|
|
|
const char *name;
|
|
|
|
|
char *ret_str;
|
|
|
|
|
g_variant_get (parameters, "(u&s)", &id, &name);
|
|
|
|
|
remote_object_list_str (obj, id, name, &ret_str);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", ret_str ? ret_str : ""));
|
|
|
|
|
g_free (ret_str);
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "ListInt"))
|
|
|
|
|
{
|
|
|
|
|
guint id;
|
|
|
|
|
const char *name;
|
|
|
|
|
int ret;
|
|
|
|
|
g_variant_get (parameters, "(u&s)", &id, &name);
|
|
|
|
|
remote_object_list_int (obj, id, name, &ret);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(i)", ret));
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "ListTime"))
|
|
|
|
|
{
|
|
|
|
|
guint id;
|
|
|
|
|
const char *name;
|
|
|
|
|
guint64 ret;
|
|
|
|
|
g_variant_get (parameters, "(u&s)", &id, &name);
|
|
|
|
|
remote_object_list_time (obj, id, name, &ret);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(t)", ret));
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "ListFields"))
|
|
|
|
|
{
|
|
|
|
|
const char *name;
|
|
|
|
|
char **ret;
|
|
|
|
|
g_variant_get (parameters, "(&s)", &name);
|
|
|
|
|
remote_object_list_fields (name, &ret);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(^as)", ret));
|
|
|
|
|
g_strfreev (ret);
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "ListFree"))
|
|
|
|
|
{
|
|
|
|
|
guint id;
|
|
|
|
|
g_variant_get (parameters, "(u)", &id);
|
|
|
|
|
remote_object_list_free (obj, id);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "EmitPrint"))
|
|
|
|
|
{
|
|
|
|
|
const char *event_name;
|
|
|
|
|
GVariant *args;
|
|
|
|
|
char **strv;
|
|
|
|
|
gboolean ret;
|
|
|
|
|
g_variant_get (parameters, "(&s@as)", &event_name, &args);
|
|
|
|
|
strv = g_variant_dup_strv (args, NULL);
|
|
|
|
|
remote_object_emit_print (obj, event_name, (const char **)strv, &ret);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret));
|
|
|
|
|
g_strfreev (strv);
|
|
|
|
|
g_variant_unref (args);
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "Nickcmp"))
|
|
|
|
|
{
|
|
|
|
|
const char *n1;
|
|
|
|
|
const char *n2;
|
|
|
|
|
int ret;
|
|
|
|
|
g_variant_get (parameters, "(&s&s)", &n1, &n2);
|
|
|
|
|
remote_object_nickcmp (obj, n1, n2, &ret);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(i)", ret));
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "Strip"))
|
|
|
|
|
{
|
|
|
|
|
const char *str;
|
|
|
|
|
int len;
|
|
|
|
|
int flag;
|
|
|
|
|
char *ret;
|
|
|
|
|
g_variant_get (parameters, "(&sii)", &str, &len, &flag);
|
|
|
|
|
remote_object_strip (str, len, flag, &ret);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", ret ? ret : ""));
|
|
|
|
|
g_free (ret);
|
|
|
|
|
}
|
|
|
|
|
else if (g_str_equal (method_name, "SendModes"))
|
|
|
|
|
{
|
|
|
|
|
GVariant *targets;
|
|
|
|
|
char **strv;
|
|
|
|
|
int modes_per_line;
|
|
|
|
|
guchar sign;
|
|
|
|
|
guchar mode;
|
|
|
|
|
g_variant_get (parameters, "(@asiyy)", &targets, &modes_per_line, &sign, &mode);
|
|
|
|
|
strv = g_variant_dup_strv (targets, NULL);
|
|
|
|
|
remote_object_send_modes (obj, (const char **)strv, modes_per_line, (char)sign, (char)mode);
|
|
|
|
|
g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
|
|
|
|
|
g_strfreev (strv);
|
|
|
|
|
g_variant_unref (targets);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
g_dbus_method_invocation_return_dbus_error (invocation, "org.zoitechat.Error", "Unknown method");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const GDBusInterfaceVTable connection_vtable = {
|
|
|
|
|
method_call_cb,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
name_owner_changed_cb (GDBusConnection *conn,
|
|
|
|
|
const gchar *sender_name,
|
|
|
|
|
const gchar *object_path,
|
|
|
|
|
const gchar *interface_name,
|
|
|
|
|
const gchar *signal_name,
|
|
|
|
|
GVariant *parameters,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
const char *name;
|
|
|
|
|
const char *old_owner;
|
|
|
|
|
const char *new_owner;
|
|
|
|
|
|
|
|
|
|
g_variant_get (parameters, "(&s&s&s)", &name, &old_owner, &new_owner);
|
|
|
|
|
if (*new_owner == '\0')
|
|
|
|
|
g_hash_table_remove (clients, name);
|
2011-02-24 04:14:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
init_dbus (void)
|
|
|
|
|
{
|
|
|
|
|
GError *error = NULL;
|
2026-04-27 11:04:04 -06:00
|
|
|
GVariant *request_name_result;
|
|
|
|
|
RemoteObject *root_remote;
|
|
|
|
|
guint registration_id;
|
|
|
|
|
|
|
|
|
|
connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
|
|
|
|
if (!connection)
|
|
|
|
|
{
|
|
|
|
|
zoitechat_printf (ph, _("Couldn't connect to session bus: %s\n"), error->message);
|
2011-02-24 04:14:30 +01:00
|
|
|
g_error_free (error);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, &error);
|
|
|
|
|
if (!introspection_data)
|
|
|
|
|
{
|
|
|
|
|
zoitechat_printf (ph, _("Couldn't parse DBus introspection data: %s\n"), error->message);
|
2011-02-24 04:14:30 +01:00
|
|
|
g_error_free (error);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
request_name_result = g_dbus_connection_call_sync (
|
|
|
|
|
connection,
|
|
|
|
|
DBUS_SERVICE_DBUS,
|
|
|
|
|
DBUS_PATH_DBUS,
|
|
|
|
|
DBUS_INTERFACE_DBUS,
|
|
|
|
|
"RequestName",
|
|
|
|
|
g_variant_new ("(su)", DBUS_SERVICE, 1u),
|
|
|
|
|
G_VARIANT_TYPE ("(u)"),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
NULL,
|
|
|
|
|
&error);
|
|
|
|
|
if (!request_name_result)
|
|
|
|
|
{
|
|
|
|
|
zoitechat_printf (ph, _("Failed to acquire %s: %s\n"), DBUS_SERVICE, error->message);
|
|
|
|
|
g_error_free (error);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
g_variant_unref (request_name_result);
|
|
|
|
|
|
|
|
|
|
registration_id = g_dbus_connection_register_object (
|
|
|
|
|
connection,
|
|
|
|
|
DBUS_OBJECT_PATH,
|
|
|
|
|
introspection_data->interfaces[0],
|
|
|
|
|
&connection_vtable,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
&error);
|
|
|
|
|
if (!registration_id)
|
|
|
|
|
{
|
|
|
|
|
zoitechat_printf (ph, _("Failed to register %s: %s\n"), DBUS_OBJECT_PATH, error->message);
|
|
|
|
|
g_error_free (error);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2011-02-24 04:14:30 +01:00
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
root_remote = remote_object_new (DBUS_OBJECT_PATH "/Remote");
|
|
|
|
|
root_remote->registration_id = g_dbus_connection_register_object (
|
|
|
|
|
connection,
|
|
|
|
|
root_remote->dbus_path,
|
|
|
|
|
introspection_data->interfaces[1],
|
|
|
|
|
&connection_vtable,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
&error);
|
|
|
|
|
if (!root_remote->registration_id)
|
|
|
|
|
{
|
|
|
|
|
zoitechat_printf (ph, _("Failed to register %s: %s\n"), root_remote->dbus_path, error->message);
|
|
|
|
|
g_error_free (error);
|
|
|
|
|
remote_object_free (root_remote);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
g_hash_table_insert (clients, g_strdup ("__root__"), root_remote);
|
|
|
|
|
|
|
|
|
|
name_owner_subscription = g_dbus_connection_signal_subscribe (
|
|
|
|
|
connection,
|
|
|
|
|
DBUS_SERVICE_DBUS,
|
|
|
|
|
DBUS_INTERFACE_DBUS,
|
|
|
|
|
"NameOwnerChanged",
|
|
|
|
|
DBUS_PATH_DBUS,
|
|
|
|
|
NULL,
|
|
|
|
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
|
|
|
|
name_owner_changed_cb,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL);
|
2011-02-24 04:14:30 +01:00
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
static char **
|
2011-02-24 04:14:30 +01:00
|
|
|
build_list (char *word[])
|
|
|
|
|
{
|
|
|
|
|
guint i;
|
|
|
|
|
guint num = 0;
|
|
|
|
|
char **result;
|
|
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
if (!word)
|
2011-02-24 04:14:30 +01:00
|
|
|
return NULL;
|
2026-04-27 11:04:04 -06:00
|
|
|
|
|
|
|
|
while (word[num] && word[num][0])
|
2011-02-24 04:14:30 +01:00
|
|
|
num++;
|
2026-04-27 11:04:04 -06:00
|
|
|
|
|
|
|
|
result = g_new0 (char *, num + 1);
|
|
|
|
|
for (i = 0; i < num; i++)
|
2011-02-24 04:14:30 +01:00
|
|
|
result[i] = g_strdup (word[i]);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static guint
|
2026-01-05 23:12:38 -07:00
|
|
|
context_list_find_id (zoitechat_context *context)
|
2011-02-24 04:14:30 +01:00
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
GList *l;
|
2011-02-24 04:14:30 +01:00
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
for (l = contexts; l != NULL; l = l->next)
|
|
|
|
|
{
|
|
|
|
|
if (((ContextInfo *)l->data)->context == context)
|
|
|
|
|
return ((ContextInfo *)l->data)->id;
|
2011-02-24 04:14:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
static zoitechat_context *
|
2011-02-24 04:14:30 +01:00
|
|
|
context_list_find_context (guint id)
|
|
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
GList *l;
|
2011-02-24 04:14:30 +01:00
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
for (l = contexts; l != NULL; l = l->next)
|
|
|
|
|
{
|
|
|
|
|
if (((ContextInfo *)l->data)->id == id)
|
|
|
|
|
return ((ContextInfo *)l->data)->context;
|
2011-02-24 04:14:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
open_context_cb (char *word[],
|
|
|
|
|
void *userdata)
|
|
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
ContextInfo *info = g_new0 (ContextInfo, 1);
|
|
|
|
|
|
2011-02-24 04:14:30 +01:00
|
|
|
info->id = ++last_context_id;
|
2026-01-05 23:12:38 -07:00
|
|
|
info->context = zoitechat_get_context (ph);
|
2011-02-24 04:14:30 +01:00
|
|
|
contexts = g_list_prepend (contexts, info);
|
2026-01-25 16:13:47 -07:00
|
|
|
return ZOITECHAT_EAT_NONE;
|
2011-02-24 04:14:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
close_context_cb (char *word[],
|
|
|
|
|
void *userdata)
|
|
|
|
|
{
|
|
|
|
|
GList *l;
|
2026-01-05 23:12:38 -07:00
|
|
|
zoitechat_context *context = zoitechat_get_context (ph);
|
2011-02-24 04:14:30 +01:00
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
for (l = contexts; l != NULL; l = l->next)
|
|
|
|
|
{
|
|
|
|
|
if (((ContextInfo *)l->data)->context == context)
|
|
|
|
|
{
|
2011-02-24 04:14:30 +01:00
|
|
|
g_free (l->data);
|
|
|
|
|
contexts = g_list_delete_link (contexts, l);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-25 16:13:47 -07:00
|
|
|
return ZOITECHAT_EAT_NONE;
|
2011-02-24 04:14:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
clients_find_filename_foreach (gpointer key,
|
|
|
|
|
gpointer value,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
RemoteObject *obj = value;
|
|
|
|
|
return g_str_equal (obj->filename, (char *)user_data);
|
2011-02-24 04:14:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
unload_plugin_cb (char *word[], char *word_eol[], void *userdata)
|
|
|
|
|
{
|
2026-04-27 11:04:04 -06:00
|
|
|
RemoteObject *obj = g_hash_table_find (clients, clients_find_filename_foreach, word[2]);
|
|
|
|
|
|
|
|
|
|
if (obj != NULL)
|
|
|
|
|
{
|
|
|
|
|
emit_signal (obj, "UnloadSignal", g_variant_new ("()"));
|
2026-01-25 16:13:47 -07:00
|
|
|
return ZOITECHAT_EAT_ALL;
|
2011-02-24 04:14:30 +01:00
|
|
|
}
|
2026-04-27 11:04:04 -06:00
|
|
|
|
2026-01-25 16:13:47 -07:00
|
|
|
return ZOITECHAT_EAT_NONE;
|
2011-02-24 04:14:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2026-01-05 23:12:38 -07:00
|
|
|
dbus_plugin_init (zoitechat_plugin *plugin_handle,
|
2011-02-24 04:14:30 +01:00
|
|
|
char **plugin_name,
|
|
|
|
|
char **plugin_desc,
|
|
|
|
|
char **plugin_version,
|
|
|
|
|
char *arg)
|
|
|
|
|
{
|
|
|
|
|
ph = plugin_handle;
|
|
|
|
|
*plugin_name = PNAME;
|
|
|
|
|
*plugin_desc = PDESC;
|
|
|
|
|
*plugin_version = PVERSION;
|
|
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
clients = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)remote_object_free);
|
2011-02-24 04:14:30 +01:00
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
if (init_dbus ())
|
|
|
|
|
{
|
|
|
|
|
zoitechat_hook_print (ph, "Open Context", ZOITECHAT_PRI_NORM, open_context_cb, NULL);
|
|
|
|
|
zoitechat_hook_print (ph, "Close Context", ZOITECHAT_PRI_NORM, close_context_cb, NULL);
|
|
|
|
|
zoitechat_hook_command (ph, "unload", ZOITECHAT_PRI_HIGHEST, unload_plugin_cb, NULL, NULL);
|
2011-02-24 04:14:30 +01:00
|
|
|
}
|
|
|
|
|
|
2026-04-27 11:04:04 -06:00
|
|
|
return TRUE;
|
2011-02-24 04:14:30 +01:00
|
|
|
}
|