Mercurial > pidgin.yaz
annotate src/dbus-server.c @ 13925:60f39c405dff
[gaim-migrate @ 16442]
It is currently possible for yourself to not show up in your own
buddy list at signon with Jabber. To reproduce:
1. Sign on and add yourself to your buddy list
2. Sign off and exit Gaim
3. Delete your blist.xml
4. Sign on
The same bug would also appear when signing into your Jabber
account using Gaim for the first time.
Normally this works because the Jabber PRPL fakes showing your status
whenever jabber_presence_send() is called. However, the call to
jabber_presence_send() can happen BEFORE we receive the roster from the
server (it usually does, I think) so the PRPL tries to set the status
for yourself, but your GaimBuddy node doesn't exist yet.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Thu, 06 Jul 2006 08:24:26 +0000 |
parents | fd708f52defd |
children | 2d6f7ac4b6f2 |
rev | line source |
---|---|
11055 | 1 /* |
2 * gaim | |
3 * | |
4 * Gaim is the legal property of its developers, whose names are too numerous | |
5 * to list here. Please refer to the COPYRIGHT file distributed with this | |
6 * source distribution. | |
7 * | |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License | |
19 * along with this program; if not, write to the Free Software | |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 * | |
22 */ | |
23 | |
11146 | 24 #define DBUS_API_SUBJECT_TO_CHANGE |
25 | |
11055 | 26 #include <stdio.h> |
27 #include <stdlib.h> | |
28 #include <string.h> | |
29 | |
30 #include "account.h" | |
11067 | 31 #include "blist.h" |
32 #include "conversation.h" | |
11055 | 33 #include "dbus-gaim.h" |
34 #include "dbus-server.h" | |
11146 | 35 #include "dbus-useful.h" |
11171 | 36 #include "dbus-bindings.h" |
11055 | 37 #include "debug.h" |
38 #include "core.h" | |
13761
ec858948d292
[gaim-migrate @ 16173]
Richard Laager <rlaager@wiktel.com>
parents:
13759
diff
changeset
|
39 #include "savedstatuses.h" |
11067 | 40 #include "value.h" |
11055 | 41 |
11080 | 42 |
11067 | 43 /**************************************************************************/ |
11171 | 44 /** @name Gaim DBUS pointer registration mechanism */ |
11080 | 45 /**************************************************************************/ |
11055 | 46 |
11171 | 47 /* |
48 Here we include the list of #GAIM_DBUS_DEFINE_TYPE statements for | |
49 all structs defined in gaim. This file has been generated by the | |
50 #dbus-analize-types.py script. | |
51 */ | |
11055 | 52 |
11171 | 53 #include "dbus-types.c" |
11055 | 54 |
11171 | 55 /* The following three hashtables map are used to translate between |
56 pointers (nodes) and the corresponding handles (ids). */ | |
57 | |
58 static GHashTable *map_node_id; | |
59 static GHashTable *map_id_node; | |
60 static GHashTable *map_id_type; | |
11080 | 61 |
62 | |
11171 | 63 /* This function initializes the pointer-id traslation system. It |
64 creates the three above hashtables and defines parents of some types. | |
65 */ | |
66 void gaim_dbus_init_ids(void) { | |
67 map_id_node = g_hash_table_new (g_direct_hash, g_direct_equal); | |
68 map_id_type = g_hash_table_new (g_direct_hash, g_direct_equal); | |
69 map_node_id = g_hash_table_new (g_direct_hash, g_direct_equal); | |
70 | |
71 GAIM_DBUS_TYPE(GaimBuddy)->parent = GAIM_DBUS_TYPE(GaimBlistNode); | |
72 GAIM_DBUS_TYPE(GaimContact)->parent = GAIM_DBUS_TYPE(GaimBlistNode); | |
73 GAIM_DBUS_TYPE(GaimChat)->parent = GAIM_DBUS_TYPE(GaimBlistNode); | |
74 GAIM_DBUS_TYPE(GaimGroup)->parent = GAIM_DBUS_TYPE(GaimBlistNode); | |
75 } | |
76 | |
77 void gaim_dbus_register_pointer(gpointer node, GaimDBusType *type) | |
78 { | |
79 static gint last_id = 0; | |
80 | |
11291 | 81 g_return_if_fail(map_node_id); |
82 g_return_if_fail(g_hash_table_lookup(map_node_id, node) == NULL); | |
11171 | 83 |
84 last_id++; | |
85 g_hash_table_insert(map_node_id, node, GINT_TO_POINTER(last_id)); | |
86 g_hash_table_insert(map_id_node, GINT_TO_POINTER(last_id), node); | |
87 g_hash_table_insert(map_id_type, GINT_TO_POINTER(last_id), type); | |
88 } | |
89 | |
90 void gaim_dbus_unregister_pointer(gpointer node) { | |
91 gpointer id = g_hash_table_lookup(map_node_id, node); | |
92 | |
93 g_hash_table_remove(map_node_id, node); | |
94 g_hash_table_remove(map_id_node, GINT_TO_POINTER(id)); | |
95 g_hash_table_remove(map_id_type, GINT_TO_POINTER(id)); | |
96 } | |
11055 | 97 |
11171 | 98 gint gaim_dbus_pointer_to_id(gpointer node) { |
99 gint id = GPOINTER_TO_INT(g_hash_table_lookup(map_node_id, node)); | |
13759 | 100 if ((id == 0) && (node != NULL)) |
101 { | |
102 gaim_debug_warning("dbus", | |
103 "Need to register an object with the dbus subsystem.\n"); | |
13763
fd708f52defd
[gaim-migrate @ 16175]
Richard Laager <rlaager@wiktel.com>
parents:
13761
diff
changeset
|
104 g_return_val_if_reached(0); |
13759 | 105 } |
11171 | 106 return id; |
107 } | |
108 | |
109 gpointer gaim_dbus_id_to_pointer(gint id, GaimDBusType *type) { | |
110 GaimDBusType *objtype = | |
111 (GaimDBusType*) g_hash_table_lookup(map_id_type, | |
112 GINT_TO_POINTER(id)); | |
113 | |
114 while (objtype != type && objtype != NULL) | |
115 objtype = objtype->parent; | |
116 | |
117 if (objtype == type) | |
118 return g_hash_table_lookup(map_id_node, GINT_TO_POINTER(id)); | |
119 else | |
120 return NULL; | |
121 } | |
122 | |
123 gint gaim_dbus_pointer_to_id_error(gpointer ptr, DBusError *error) | |
124 { | |
125 gint id = gaim_dbus_pointer_to_id(ptr); | |
11055 | 126 |
11171 | 127 if (ptr != NULL && id == 0) |
13220
ac5bc9a7b603
[gaim-migrate @ 15584]
Richard Laager <rlaager@wiktel.com>
parents:
13134
diff
changeset
|
128 dbus_set_error(error, "net.sf.gaim.ObjectNotFound", |
11171 | 129 "The return object is not mapped (this is a Gaim error)"); |
130 | |
131 return id; | |
132 } | |
133 | |
134 gpointer gaim_dbus_id_to_pointer_error(gint id, GaimDBusType *type, | |
135 const char *typename, DBusError *error) | |
136 { | |
137 gpointer ptr = gaim_dbus_id_to_pointer(id, type); | |
11055 | 138 |
11171 | 139 if (ptr == NULL && id != 0) |
13220
ac5bc9a7b603
[gaim-migrate @ 15584]
Richard Laager <rlaager@wiktel.com>
parents:
13134
diff
changeset
|
140 dbus_set_error(error, "net.sf.gaim.InvalidHandle", |
11171 | 141 "%s object with ID = %i not found", typename, id); |
142 | |
143 return ptr; | |
144 } | |
11187 | 145 |
146 | |
147 /**************************************************************************/ | |
148 /** @name Modified versions of some DBus functions */ | |
149 /**************************************************************************/ | |
150 | |
151 dbus_bool_t | |
152 gaim_dbus_message_get_args (DBusMessage *message, | |
11277 | 153 DBusError *error, |
154 int first_arg_type, | |
155 ...) | |
11187 | 156 { |
157 dbus_bool_t retval; | |
158 va_list var_args; | |
159 | |
160 va_start (var_args, first_arg_type); | |
161 retval = gaim_dbus_message_get_args_valist (message, error, first_arg_type, var_args); | |
162 va_end (var_args); | |
163 | |
164 return retval; | |
165 } | |
166 | |
167 dbus_bool_t | |
168 gaim_dbus_message_get_args_valist (DBusMessage *message, | |
169 DBusError *error, | |
170 int first_arg_type, | |
171 va_list var_args) | |
172 { | |
173 DBusMessageIter iter; | |
174 | |
175 dbus_message_iter_init (message, &iter); | |
176 return gaim_dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args); | |
177 } | |
178 | |
179 dbus_bool_t | |
180 gaim_dbus_message_iter_get_args(DBusMessageIter *iter, | |
181 DBusError *error, | |
182 int first_arg_type, | |
183 ...) | |
184 { | |
185 dbus_bool_t retval; | |
186 va_list var_args; | |
187 | |
188 va_start (var_args, first_arg_type); | |
189 retval = gaim_dbus_message_iter_get_args_valist(iter, error, first_arg_type, var_args); | |
190 va_end (var_args); | |
191 | |
192 return retval; | |
193 } | |
194 | |
195 #define TYPE_IS_CONTAINER(typecode) \ | |
196 ((typecode) == DBUS_TYPE_STRUCT || \ | |
197 (typecode) == DBUS_TYPE_DICT_ENTRY || \ | |
198 (typecode) == DBUS_TYPE_VARIANT || \ | |
199 (typecode) == DBUS_TYPE_ARRAY) | |
200 | |
201 | |
202 dbus_bool_t | |
203 gaim_dbus_message_iter_get_args_valist (DBusMessageIter *iter, | |
204 DBusError *error, | |
205 int first_arg_type, | |
206 va_list var_args) | |
207 { | |
208 int spec_type, msg_type, i; | |
209 | |
210 spec_type = first_arg_type; | |
211 | |
212 for(i=0; spec_type != DBUS_TYPE_INVALID; i++) { | |
213 msg_type = dbus_message_iter_get_arg_type (iter); | |
214 | |
215 if (msg_type != spec_type) { | |
216 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, | |
217 "Argument %d is specified to be of type \"%i\", but " | |
218 "is actually of type \"%i\"\n", i, | |
219 spec_type, msg_type); | |
220 return FALSE; | |
221 } | |
222 | |
223 if (!TYPE_IS_CONTAINER(spec_type)) { | |
224 gpointer ptr; | |
225 ptr = va_arg (var_args, gpointer); | |
226 dbus_message_iter_get_basic(iter, ptr); | |
227 } | |
228 else { | |
229 DBusMessageIter *sub; | |
230 sub = va_arg (var_args, DBusMessageIter*); | |
231 dbus_message_iter_recurse(iter, sub); | |
232 g_print("subiter %i:%i\n", (int) sub, * (int*) sub); | |
233 break; /* for testing only! */ | |
234 } | |
11171 | 235 |
11187 | 236 spec_type = va_arg (var_args, int); |
237 if (!dbus_message_iter_next(iter) && spec_type != DBUS_TYPE_INVALID) { | |
238 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, | |
239 "Message has only %d arguments, but more were expected", i); | |
240 return FALSE; | |
241 } | |
242 } | |
243 return TRUE; | |
244 } | |
245 | |
246 | |
247 | |
11171 | 248 /**************************************************************************/ |
249 /** @name Useful functions */ | |
250 /**************************************************************************/ | |
11146 | 251 |
11171 | 252 const char* empty_to_null(const char *str) { |
11146 | 253 if (str == NULL || str[0] == 0) |
254 return NULL; | |
255 else | |
256 return str; | |
257 } | |
258 | |
11171 | 259 const char* null_to_empty(const char *s) { |
11080 | 260 if (s) |
261 return s; | |
262 else | |
263 return ""; | |
11055 | 264 } |
265 | |
11171 | 266 dbus_int32_t* gaim_dbusify_GList(GList *list, gboolean free_memory, |
267 dbus_int32_t *len) | |
268 { | |
269 dbus_int32_t *array; | |
270 int i; | |
271 GList *elem; | |
11055 | 272 |
11171 | 273 *len = g_list_length(list); |
274 array = g_new0(dbus_int32_t, g_list_length(list)); | |
275 for(i = 0, elem = list; elem != NULL; elem = elem->next, i++) | |
276 array[i] = gaim_dbus_pointer_to_id(elem->data); | |
277 | |
278 if (free_memory) | |
279 g_list_free(list); | |
280 | |
281 return array; | |
11080 | 282 } |
11055 | 283 |
11171 | 284 dbus_int32_t* gaim_dbusify_GSList(GSList *list, gboolean free_memory, |
285 dbus_int32_t *len) | |
286 { | |
287 dbus_int32_t *array; | |
11146 | 288 int i; |
11171 | 289 GSList *elem; |
11146 | 290 |
11171 | 291 *len = g_slist_length(list); |
292 array = g_new0(dbus_int32_t, g_slist_length(list)); | |
293 for(i = 0, elem = list; elem != NULL; elem = elem->next, i++) | |
294 array[i] = gaim_dbus_pointer_to_id(elem->data); | |
11067 | 295 |
11171 | 296 if (free_memory) |
297 g_slist_free(list); | |
11080 | 298 |
11171 | 299 return array; |
11067 | 300 } |
301 | |
11187 | 302 gpointer* gaim_GList_to_array(GList *list, gboolean free_memory, |
303 dbus_int32_t *len) | |
304 { | |
305 gpointer *array; | |
306 int i; | |
307 GList *elem; | |
308 | |
309 *len = g_list_length(list); | |
310 array = g_new0(gpointer, g_list_length(list)); | |
311 for(i = 0, elem = list; elem != NULL; elem = elem->next, i++) | |
312 array[i] = elem->data; | |
313 | |
314 if (free_memory) | |
315 g_list_free(list); | |
316 | |
317 return array; | |
318 } | |
319 | |
320 gpointer* gaim_GSList_to_array(GSList *list, gboolean free_memory, | |
321 dbus_int32_t *len) | |
322 { | |
323 gpointer *array; | |
324 int i; | |
325 GSList *elem; | |
326 | |
327 *len = g_slist_length(list); | |
328 array = g_new0(gpointer, g_slist_length(list)); | |
329 for(i = 0, elem = list; elem != NULL; elem = elem->next, i++) | |
330 array[i] = elem->data; | |
331 | |
332 if (free_memory) | |
333 g_slist_free(list); | |
334 | |
335 return array; | |
336 } | |
337 | |
338 GHashTable *gaim_dbus_iter_hash_table(DBusMessageIter *iter, DBusError *error) { | |
339 GHashTable *hash; | |
340 | |
341 /* we do not need to destroy strings because they are part of the message */ | |
342 hash = g_hash_table_new(g_str_hash, g_str_equal); | |
343 | |
344 do { | |
345 char *key, *value; | |
346 DBusMessageIter subiter; | |
347 | |
348 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) | |
349 goto error; /* With all due respect to Dijkstra, | |
350 this goto is for exception | |
351 handling, and it is ok because it | |
352 avoids duplication of the code | |
353 responsible for destroying the hash | |
354 table. Exceptional instructions | |
355 for exceptional situations. */ | |
356 | |
357 dbus_message_iter_recurse(iter, &subiter); | |
358 if (!gaim_dbus_message_iter_get_args(&subiter, error, | |
359 DBUS_TYPE_STRING, &key, | |
360 DBUS_TYPE_STRING, &value, | |
361 DBUS_TYPE_INVALID)) | |
362 goto error; /* same here */ | |
363 | |
364 g_hash_table_insert(hash, key, value); | |
365 } while (dbus_message_iter_next(iter)); | |
366 | |
367 return hash; | |
368 | |
369 error: | |
370 g_hash_table_destroy(hash); | |
371 return NULL; | |
372 } | |
373 | |
11171 | 374 /**************************************************************/ |
375 /* DBus bindings ... */ | |
376 /**************************************************************/ | |
377 | |
378 static DBusConnection *gaim_dbus_connection; | |
379 | |
380 DBusConnection *gaim_dbus_get_connection(void) { | |
381 return gaim_dbus_connection; | |
382 } | |
383 | |
384 #include "dbus-bindings.c" | |
385 | |
386 void *gaim_dbus_get_handle(void) { | |
387 static int handle; | |
388 | |
389 return &handle; | |
11067 | 390 } |
391 | |
11171 | 392 static gboolean |
393 gaim_dbus_dispatch_cb(DBusConnection *connection, | |
394 DBusMessage *message, | |
395 void *user_data) | |
396 { | |
397 const char *name; | |
398 GaimDBusBinding *bindings; | |
399 int i; | |
400 | |
401 bindings = (GaimDBusBinding*) user_data; | |
402 | |
11175 | 403 if (!dbus_message_has_path(message, DBUS_PATH_GAIM)) |
11171 | 404 return FALSE; |
405 | |
406 name = dbus_message_get_member(message); | |
407 | |
11175 | 408 if (name == NULL) |
409 return FALSE; | |
410 | |
411 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL) | |
11171 | 412 return FALSE; |
413 | |
414 for(i=0; bindings[i].name; i++) | |
415 if (!strcmp(name, bindings[i].name)) { | |
416 DBusMessage *reply; | |
417 DBusError error; | |
418 | |
419 dbus_error_init(&error); | |
420 | |
421 reply = bindings[i].handler(message, &error); | |
422 | |
423 if (reply == NULL && dbus_error_is_set(&error)) | |
424 reply = dbus_message_new_error (message, | |
425 error.name, | |
426 error.message); | |
427 | |
428 if (reply != NULL) { | |
429 dbus_connection_send (connection, reply, NULL); | |
430 dbus_message_unref(reply); | |
431 } | |
432 | |
433 return TRUE; /* return reply! */ | |
434 } | |
435 | |
436 return FALSE; | |
11067 | 437 } |
11146 | 438 |
11175 | 439 |
440 static const char *gettext(const char **ptr) { | |
441 const char *text = *ptr; | |
442 *ptr += strlen(text) + 1; | |
443 return text; | |
444 } | |
445 | |
446 static void | |
447 gaim_dbus_introspect_cb(GList **bindings_list, void *bindings) { | |
448 *bindings_list = g_list_prepend(*bindings_list, bindings); | |
449 } | |
450 | |
451 static DBusMessage *gaim_dbus_introspect(DBusMessage *message) | |
452 { | |
453 DBusMessage *reply; | |
454 GString *str; | |
455 GList *bindings_list, *node; | |
456 | |
457 str = g_string_sized_new(0x1000); /* fixme: why this size? */ | |
458 | |
459 g_string_append(str, "<!DOCTYPE node PUBLIC '-//freedesktop//DTD D-BUS Object Introspection 1.0//EN' 'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>\n"); | |
460 g_string_append_printf(str, "<node name='%s'>\n", DBUS_PATH_GAIM); | |
461 g_string_append_printf(str, "<interface name='%s'>\n", DBUS_INTERFACE_GAIM); | |
462 | |
463 bindings_list = NULL; | |
464 gaim_signal_emit(gaim_dbus_get_handle(), "dbus-introspect", &bindings_list); | |
465 | |
466 for(node = bindings_list; node; node = node->next) { | |
467 GaimDBusBinding *bindings; | |
468 int i; | |
469 | |
470 bindings = (GaimDBusBinding*) node->data; | |
471 | |
472 for(i=0; bindings[i].name; i++) { | |
473 const char *text; | |
474 | |
475 g_string_append_printf(str, "<method name='%s'>\n", bindings[i].name); | |
476 | |
477 text = bindings[i].parameters; | |
478 while (*text) { | |
479 const char *name, *direction, *type; | |
480 | |
481 direction = gettext(&text); | |
482 type = gettext(&text); | |
483 name = gettext(&text); | |
484 | |
11187 | 485 g_string_append_printf(str, |
486 "<arg name='%s' type='%s' direction='%s'/>\n", | |
487 name, type, direction); | |
11175 | 488 } |
489 g_string_append(str, "</method>\n"); | |
490 } | |
491 } | |
492 | |
493 g_string_append(str, "</interface>\n</node>\n"); | |
494 | |
495 reply = dbus_message_new_method_return (message); | |
496 dbus_message_append_args(reply, DBUS_TYPE_STRING, &(str->str), | |
497 DBUS_TYPE_INVALID); | |
498 g_string_free(str, TRUE); | |
499 g_list_free(bindings_list); | |
500 | |
501 return reply; | |
502 | |
503 } | |
504 | |
11171 | 505 static DBusHandlerResult gaim_dbus_dispatch(DBusConnection *connection, |
506 DBusMessage *message, | |
507 void *user_data) | |
508 { | |
509 if (gaim_signal_emit_return_1(gaim_dbus_get_handle(), | |
510 "dbus-method-called", | |
511 connection, message)) | |
512 return DBUS_HANDLER_RESULT_HANDLED; | |
11175 | 513 |
514 if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL && | |
515 dbus_message_has_path(message, DBUS_PATH_GAIM) && | |
516 dbus_message_has_interface(message, DBUS_INTERFACE_INTROSPECTABLE) && | |
517 dbus_message_has_member(message, "Introspect")) | |
518 { | |
519 DBusMessage *reply; | |
520 reply = gaim_dbus_introspect(message); | |
521 dbus_connection_send (connection, reply, NULL); | |
522 dbus_message_unref(reply); | |
523 return DBUS_HANDLER_RESULT_HANDLED; | |
524 } | |
525 | |
526 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; | |
11067 | 527 } |
11171 | 528 |
529 void gaim_dbus_register_bindings(void *handle, GaimDBusBinding *bindings) { | |
530 gaim_signal_connect(gaim_dbus_get_handle(), "dbus-method-called", | |
531 handle, | |
532 GAIM_CALLBACK(gaim_dbus_dispatch_cb), | |
533 bindings); | |
11175 | 534 gaim_signal_connect(gaim_dbus_get_handle(), "dbus-introspect", |
535 handle, | |
536 GAIM_CALLBACK(gaim_dbus_introspect_cb), | |
537 bindings); | |
11171 | 538 } |
11146 | 539 |
540 | |
11171 | 541 |
12627 | 542 static gboolean gaim_dbus_dispatch_init(void) |
11171 | 543 { |
12627 | 544 static DBusObjectPathVTable vtable = {NULL, &gaim_dbus_dispatch, NULL, NULL, NULL, NULL}; |
11171 | 545 |
546 DBusError error; | |
547 int result; | |
548 | |
549 dbus_error_init (&error); | |
550 gaim_dbus_connection = dbus_bus_get (DBUS_BUS_STARTER, &error); | |
11146 | 551 |
11171 | 552 if (gaim_dbus_connection == NULL) { |
553 gaim_debug_error("dbus", "Failed to get connection\n"); | |
554 dbus_error_free(&error); | |
555 return FALSE; | |
556 } | |
557 | |
558 if (!dbus_connection_register_object_path (gaim_dbus_connection, | |
559 DBUS_PATH_GAIM, &vtable, NULL)) | |
560 { | |
561 gaim_debug_error("dbus", "Failed to get name: %s\n", error.name); | |
562 dbus_error_free(&error); | |
563 return FALSE; | |
564 } | |
565 | |
11146 | 566 |
11171 | 567 result = dbus_bus_request_name (gaim_dbus_connection, DBUS_SERVICE_GAIM, |
568 0, &error); | |
569 | |
570 if (dbus_error_is_set (&error)) { | |
571 dbus_connection_unref(gaim_dbus_connection); | |
572 dbus_error_free(&error); | |
11903 | 573 gaim_dbus_connection = NULL; |
11171 | 574 gaim_debug_error("dbus", "Failed to get serv name: %s\n", error.name); |
575 return FALSE; | |
576 } | |
577 | |
578 dbus_connection_setup_with_g_main(gaim_dbus_connection, NULL); | |
11146 | 579 |
11171 | 580 gaim_debug_misc ("dbus", "okkk\n"); |
581 | |
582 gaim_signal_register(gaim_dbus_get_handle(), "dbus-method-called", | |
583 gaim_marshal_BOOLEAN__POINTER_POINTER, | |
584 gaim_value_new(GAIM_TYPE_BOOLEAN), 2, | |
585 gaim_value_new(GAIM_TYPE_POINTER), | |
586 gaim_value_new(GAIM_TYPE_POINTER)); | |
587 | |
11175 | 588 gaim_signal_register(gaim_dbus_get_handle(), "dbus-introspect", |
589 gaim_marshal_VOID__POINTER, NULL, 1, | |
590 gaim_value_new_outgoing(GAIM_TYPE_POINTER)); | |
591 | |
11171 | 592 GAIM_DBUS_REGISTER_BINDINGS(gaim_dbus_get_handle()); |
593 | |
594 return TRUE; | |
595 } | |
596 | |
11146 | 597 |
598 | |
599 /**************************************************************************/ | |
600 /** @name Signals */ | |
601 /**************************************************************************/ | |
602 | |
603 | |
604 | |
605 static char *gaim_dbus_convert_signal_name(const char *gaim_name) | |
606 { | |
607 int gaim_index, g_index; | |
608 char *g_name = g_new(char, strlen(gaim_name)+1); | |
609 gboolean capitalize_next = TRUE; | |
610 | |
611 for(gaim_index = g_index = 0; gaim_name[gaim_index]; gaim_index++) | |
612 if (gaim_name[gaim_index] != '-' && gaim_name[gaim_index] != '_') { | |
613 if (capitalize_next) | |
614 g_name[g_index++] = g_ascii_toupper(gaim_name[gaim_index]); | |
615 else | |
616 g_name[g_index++] = gaim_name[gaim_index]; | |
617 capitalize_next = FALSE; | |
618 } else | |
619 capitalize_next = TRUE; | |
620 g_name[g_index] = 0; | |
621 | |
622 return g_name; | |
623 } | |
624 | |
625 #define my_arg(type) (ptr != NULL ? * ((type *)ptr) : va_arg(data, type)) | |
626 | |
627 static void gaim_dbus_message_append_gaim_values(DBusMessageIter *iter, | |
628 int number, | |
629 GaimValue **gaim_values, | |
630 va_list data) | |
631 { | |
632 int i; | |
633 | |
634 for(i=0; i<number; i++) { | |
635 const char *str; | |
636 int id; | |
637 gint xint; | |
638 guint xuint; | |
639 gboolean xboolean; | |
640 gpointer ptr = NULL; | |
641 if (gaim_value_is_outgoing(gaim_values[i])) { | |
642 ptr = my_arg(gpointer); | |
11291 | 643 g_return_if_fail(ptr); |
11146 | 644 } |
645 | |
646 switch(gaim_values[i]->type) { | |
647 case GAIM_TYPE_INT: | |
648 xint = my_arg(gint); | |
649 dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &xint); | |
650 break; | |
651 case GAIM_TYPE_UINT: | |
652 xuint = my_arg(guint); | |
653 dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &xuint); | |
654 break; | |
655 case GAIM_TYPE_BOOLEAN: | |
656 xboolean = my_arg(gboolean); | |
657 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &xboolean); | |
658 break; | |
659 case GAIM_TYPE_STRING: | |
660 str = null_to_empty(my_arg(char*)); | |
661 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &str); | |
662 break; | |
663 case GAIM_TYPE_SUBTYPE: /* registered pointers only! */ | |
664 case GAIM_TYPE_POINTER: | |
13134
b2d838b7eb00
[gaim-migrate @ 15496]
Richard Laager <rlaager@wiktel.com>
parents:
12627
diff
changeset
|
665 case GAIM_TYPE_OBJECT: |
b2d838b7eb00
[gaim-migrate @ 15496]
Richard Laager <rlaager@wiktel.com>
parents:
12627
diff
changeset
|
666 case GAIM_TYPE_BOXED: |
11146 | 667 id = gaim_dbus_pointer_to_id(my_arg(gpointer)); |
13134
b2d838b7eb00
[gaim-migrate @ 15496]
Richard Laager <rlaager@wiktel.com>
parents:
12627
diff
changeset
|
668 dbus_message_iter_append_basic(iter, (sizeof(void *) == 4) ? DBUS_TYPE_UINT32 : DBUS_TYPE_UINT64, &id); |
11146 | 669 break; |
670 default: /* no conversion implemented */ | |
11291 | 671 g_return_if_reached(); |
11146 | 672 } |
673 } | |
674 } | |
675 | |
676 #undef my_arg | |
677 | |
11903 | 678 void gaim_dbus_signal_emit_gaim(const char *name, int num_values, |
11146 | 679 GaimValue **values, va_list vargs) |
680 { | |
681 DBusMessage *signal; | |
682 DBusMessageIter iter; | |
683 char *newname; | |
684 | |
11903 | 685 #if 0 /* this is noisy with no dbus connection */ |
11171 | 686 g_return_if_fail(gaim_dbus_connection); |
11903 | 687 #else |
688 if (gaim_dbus_connection == NULL) | |
689 return; | |
690 #endif | |
691 | |
11146 | 692 |
11277 | 693 /* The test below is a hack that prevents our "dbus-method-called" |
694 signal from being propagated to dbus. What we really need is a | |
695 flag for each signal that states whether this signal is to be | |
696 dbus-propagated or not. */ | |
697 if (!strcmp(name, "dbus-method-called")) | |
698 return; | |
699 | |
11146 | 700 newname = gaim_dbus_convert_signal_name(name); |
701 signal = dbus_message_new_signal(DBUS_PATH_GAIM, DBUS_INTERFACE_GAIM, newname); | |
702 dbus_message_iter_init_append(signal, &iter); | |
703 | |
704 gaim_dbus_message_append_gaim_values(&iter, num_values, values, vargs); | |
705 | |
11171 | 706 dbus_connection_send(gaim_dbus_connection, signal, NULL); |
11146 | 707 |
708 g_free(newname); | |
709 dbus_message_unref(signal); | |
710 } | |
711 | |
712 | |
11080 | 713 |
714 | |
715 | |
716 | |
717 gboolean gaim_dbus_init(void) | |
718 { | |
11171 | 719 gaim_dbus_init_ids(); |
720 return gaim_dbus_dispatch_init() ; | |
11080 | 721 } |
11146 | 722 |
723 |