1 /* dbus-client.c - HexChat command-line options for D-Bus
2  * Copyright (C) 2006 Claessens Xavier
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  *
18  * Claessens Xavier
19  * xclaesse@gmail.com
20  */
21 
22 #include "config.h"
23 
24 #include "dbus-client.h"
25 #include <stdlib.h>
26 #include <gio/gio.h>
27 #include "hexchat.h"
28 #include "hexchatc.h"
29 
30 #define DBUS_REMOTE_PATH "/org/hexchat/Remote"
31 #define DBUS_REMOTE_INTERFACE "org.hexchat.plugin"
32 
33 #define DBUS_SERVICE_DBUS "org.freedesktop.DBus"
34 #define DBUS_PATH_DBUS "/org/freedesktop/DBus"
35 #define DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
36 
37 static void
write_error(char * message,GError ** error)38 write_error (char *message, GError **error)
39 {
40 	if (error == NULL || *error == NULL) {
41 		return;
42 	}
43 	g_printerr ("%s: %s\n", message, (*error)->message);
44 	g_clear_error (error);
45 }
46 
47 static inline GVariant *
new_param_variant(const char * arg)48 new_param_variant (const char *arg)
49 {
50 	GVariant * const args[1] = {
51 		g_variant_new_string (arg)
52 	};
53 	return g_variant_new_tuple (args, 1);
54 }
55 
56 void
hexchat_remote(void)57 hexchat_remote (void)
58 /* TODO: dbus_g_connection_unref (connection) are commented because it makes
59  * dbus to crash. Fixed in dbus >=0.70 ?!?
60  * https://launchpad.net/distros/ubuntu/+source/dbus/+bug/54375
61  */
62 {
63 	GDBusConnection *connection;
64 	GDBusProxy *dbus = NULL;
65 	GVariant *ret;
66 	GDBusProxy *remote_object = NULL;
67 	gboolean hexchat_running;
68 	GError *error = NULL;
69 	char *command = NULL;
70 	int i;
71 
72 	/* if there is nothing to do, return now. */
73 	if (!arg_existing || !(arg_url || arg_urls || arg_command)) {
74 		return;
75 	}
76 
77 	arg_dont_autoconnect = TRUE;
78 
79 	connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
80 	if (!connection)
81 	{
82 		write_error (_("Couldn't connect to session bus"), &error);
83 		return;
84 	}
85 
86 	/* Checks if HexChat is already running */
87 	dbus = g_dbus_proxy_new_sync (connection,
88 								  G_DBUS_PROXY_FLAGS_NONE,
89 								  NULL,
90 								  DBUS_SERVICE_DBUS,
91 								  DBUS_PATH_DBUS,
92 								  DBUS_INTERFACE_DBUS,
93 								  NULL,
94 								  &error);
95 
96 	ret = g_dbus_proxy_call_sync (dbus, "NameHasOwner",
97 								 new_param_variant (DBUS_SERVICE),
98 								 G_DBUS_CALL_FLAGS_NONE,
99 								 -1,
100 								 NULL,
101 								 &error);
102 	if (!ret)
103 	{
104 		write_error (_("Failed to complete NameHasOwner"), &error);
105 		hexchat_running = FALSE;
106 	}
107 	else
108 	{
109 		GVariant *child = g_variant_get_child_value (ret, 0);
110 		hexchat_running = g_variant_get_boolean (child);
111 		g_variant_unref (ret);
112 		g_variant_unref (child);
113 	}
114 	g_object_unref (dbus);
115 
116 	if (!hexchat_running) {
117 		g_object_unref (connection);
118 		return;
119 	}
120 
121 	remote_object = g_dbus_proxy_new_sync (connection,
122 								  G_DBUS_PROXY_FLAGS_NONE,
123 								  NULL,
124 								  DBUS_SERVICE,
125 								  DBUS_REMOTE_PATH,
126 								  DBUS_REMOTE_INTERFACE,
127 								  NULL,
128 								  &error);
129 
130 	if (!remote_object)
131 	{
132 		write_error("Failed to connect to HexChat", &error);
133 		g_object_unref (connection);
134 		exit (0);
135 	}
136 
137 	if (arg_url) {
138 		command = g_strdup_printf ("url %s", arg_url);
139 	} else if (arg_command) {
140 		command = g_strdup (arg_command);
141 	}
142 
143 	if (command)
144 	{
145 		g_dbus_proxy_call_sync (remote_object, "Command",
146 								new_param_variant (command),
147 								G_DBUS_CALL_FLAGS_NONE,
148 								-1,
149 								NULL,
150 								&error);
151 
152 		if (error)
153 			write_error (_("Failed to complete Command"), &error);
154 		g_free (command);
155 	}
156 
157 	if (arg_urls)
158 	{
159 		for (i = 0; i < g_strv_length(arg_urls); i++)
160 		{
161 			command = g_strdup_printf ("url %s", arg_urls[i]);
162 
163 			g_dbus_proxy_call_sync (remote_object, "Command",
164 									new_param_variant (command),
165 									G_DBUS_CALL_FLAGS_NONE,
166 									-1,
167 									NULL,
168 									&error);
169 			if (error)
170 				write_error (_("Failed to complete Command"), &error);
171 			g_free (command);
172 		}
173 		g_strfreev (arg_urls);
174 	}
175 
176 	g_object_unref (remote_object);
177 	g_object_unref (connection);
178 	exit (0);
179 }
180