Adapt migration for files
[pidgin-git.git] / libpurple / core.c
blob53ced2bad6e790f381f237186fd3df1abc451265
1 /* purple
3 * Purple is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
5 * source distribution.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
21 #include "internal.h"
22 #include "cipher.h"
23 #include "cmds.h"
24 #include "connection.h"
25 #include "conversation.h"
26 #include "core.h"
27 #include "debug.h"
28 #include "xfer.h"
29 #include "glibcompat.h"
30 #include "http.h"
31 #include "idle.h"
32 #include "image-store.h"
33 #include "keyring.h"
34 #include "message.h"
35 #include "network.h"
36 #include "notify.h"
37 #include "plugins.h"
38 #include "pounce.h"
39 #include "prefs.h"
40 #include "proxy.h"
41 #include "savedstatuses.h"
42 #include "signals.h"
43 #include "smiley-custom.h"
44 #include "smiley-parser.h"
45 #include "smiley-theme.h"
46 #include "sound.h"
47 #include "sound-theme-loader.h"
48 #include "sslconn.h"
49 #include "status.h"
50 #include "stun.h"
51 #include "theme-manager.h"
52 #include "util.h"
54 #ifdef HAVE_DBUS
55 # ifndef DBUS_API_SUBJECT_TO_CHANGE
56 # define DBUS_API_SUBJECT_TO_CHANGE
57 # endif
58 # include <dbus/dbus.h>
59 # include "dbus-purple.h"
60 # include "dbus-server.h"
61 # include "dbus-bindings.h"
62 #endif
64 struct PurpleCore
66 char *ui;
68 void *reserved;
71 static PurpleCoreUiOps *_ops = NULL;
72 static PurpleCore *_core = NULL;
74 STATIC_PROTO_LOAD
75 STATIC_PROTO_UNLOAD
77 static void
78 purple_core_print_version(void)
80 GHashTable *ui_info = purple_core_get_ui_info();
81 const gchar *ui_name;
82 const gchar *ui_version;
83 gchar *ui_full_name = NULL;
85 ui_name = ui_info ? g_hash_table_lookup(ui_info, "name") : NULL;
86 ui_version = ui_info ? g_hash_table_lookup(ui_info, "version") : NULL;
88 if (ui_name) {
89 ui_full_name = g_strdup_printf("%s%s%s", ui_name,
90 ui_version ? " " : "", ui_version);
93 purple_debug_info("main", "Launching %s%slibpurple %s",
94 ui_full_name ? ui_full_name : "",
95 ui_full_name ? " with " : "",
96 purple_core_get_version());
100 gboolean
101 purple_core_init(const char *ui)
103 PurpleCoreUiOps *ops;
104 PurpleCore *core;
106 g_return_val_if_fail(ui != NULL, FALSE);
107 g_return_val_if_fail(purple_get_core() == NULL, FALSE);
109 #ifdef ENABLE_NLS
110 bindtextdomain(PACKAGE, PURPLE_LOCALEDIR);
111 #endif
112 #ifdef _WIN32
113 wpurple_init();
114 #endif
116 _core = core = g_new0(PurpleCore, 1);
117 core->ui = g_strdup(ui);
118 core->reserved = NULL;
120 ops = purple_core_get_ui_ops();
122 /* The signals subsystem is important and should be first. */
123 purple_signals_init();
125 purple_util_init();
127 purple_signal_register(core, "uri-handler",
128 purple_marshal_BOOLEAN__POINTER_POINTER_POINTER,
129 G_TYPE_BOOLEAN, 3,
130 G_TYPE_STRING, /* Protocol */
131 G_TYPE_STRING, /* Command */
132 G_TYPE_POINTER); /* Parameters (GHashTable *) */
134 purple_signal_register(core, "quitting", purple_marshal_VOID, G_TYPE_NONE,
136 purple_signal_register(core, "core-initialized", purple_marshal_VOID,
137 G_TYPE_NONE, 0);
139 purple_core_print_version();
141 /* The prefs subsystem needs to be initialized before static protocols
142 * for protocol prefs to work. */
143 purple_prefs_init();
145 purple_debug_init();
147 if (ops != NULL)
149 if (ops->ui_prefs_init != NULL)
150 ops->ui_prefs_init();
152 if (ops->debug_ui_init != NULL)
153 ops->debug_ui_init();
156 #ifdef HAVE_DBUS
157 purple_dbus_init();
158 #endif
160 purple_cmds_init();
161 purple_protocols_init();
163 /* Load all static protocols. */
164 static_proto_load();
166 /* Since plugins get probed so early we should probably initialize their
167 * subsystem right away too.
169 purple_plugins_init();
171 purple_keyring_init(); /* before accounts */
172 purple_theme_manager_init();
174 /* The buddy icon code uses the image store, so init it early. */
175 _purple_image_store_init();
177 /* Accounts use status, buddy icons and connection signals, so
178 * initialize these before accounts
180 purple_statuses_init();
181 purple_buddy_icons_init();
182 purple_connections_init();
184 purple_accounts_init();
185 purple_savedstatuses_init();
186 purple_notify_init();
187 _purple_message_init();
188 purple_conversations_init();
189 purple_blist_init();
190 purple_log_init();
191 purple_network_init();
192 purple_pounces_init();
193 _purple_socket_init();
194 purple_proxy_init();
195 purple_sound_init();
196 purple_stun_init();
197 purple_xfers_init();
198 purple_idle_init();
199 purple_http_init();
200 _purple_smiley_custom_init();
201 _purple_smiley_parser_init();
204 * Call this early on to try to auto-detect our IP address and
205 * hopefully save some time later.
207 purple_network_get_my_ip(-1);
209 if (ops != NULL && ops->ui_init != NULL)
210 ops->ui_init();
212 /* The UI may have registered some theme types, so refresh them */
213 purple_theme_manager_refresh();
215 /* Load the buddy list after UI init */
216 purple_blist_boot();
218 purple_signal_emit(purple_get_core(), "core-initialized");
220 return TRUE;
223 void
224 purple_core_quit(void)
226 PurpleCoreUiOps *ops;
227 PurpleCore *core = purple_get_core();
229 g_return_if_fail(core != NULL);
231 /* The self destruct sequence has been initiated */
232 purple_signal_emit(purple_get_core(), "quitting");
234 /* Transmission ends */
235 purple_connections_disconnect_all();
237 /* Save .xml files, remove signals, etc. */
238 _purple_smiley_theme_uninit();
239 _purple_smiley_custom_uninit();
240 _purple_smiley_parser_uninit();
241 purple_http_uninit();
242 purple_idle_uninit();
243 purple_pounces_uninit();
244 purple_conversations_uninit();
245 purple_blist_uninit();
246 purple_notify_uninit();
247 purple_connections_uninit();
248 purple_buddy_icons_uninit();
249 purple_savedstatuses_uninit();
250 purple_statuses_uninit();
251 purple_accounts_uninit();
252 purple_keyring_uninit(); /* after accounts */
253 purple_sound_uninit();
254 purple_theme_manager_uninit();
255 purple_xfers_uninit();
256 purple_proxy_uninit();
257 _purple_socket_uninit();
258 _purple_image_store_uninit();
259 purple_network_uninit();
261 ops = purple_core_get_ui_ops();
262 if (ops != NULL && ops->quit != NULL)
263 ops->quit();
265 /* Everything after prefs_uninit must not try to read any prefs */
266 purple_prefs_uninit();
267 purple_plugins_uninit();
269 static_proto_unload();
270 purple_protocols_uninit();
272 #ifdef HAVE_DBUS
273 purple_dbus_uninit();
274 #endif
276 purple_cmds_uninit();
277 purple_log_uninit();
278 _purple_message_uninit();
279 /* Everything after util_uninit cannot try to write things to the
280 * confdir nor use purple_escape_js
282 purple_util_uninit();
284 purple_signals_uninit();
286 g_free(core->ui);
287 g_free(core);
289 #ifdef _WIN32
290 wpurple_cleanup();
291 #endif
293 _core = NULL;
296 gboolean
297 purple_core_quit_cb(gpointer unused)
299 purple_core_quit();
301 return FALSE;
304 const char *
305 purple_core_get_version(void)
307 return VERSION;
310 const char *
311 purple_core_get_ui(void)
313 PurpleCore *core = purple_get_core();
315 g_return_val_if_fail(core != NULL, NULL);
317 return core->ui;
320 PurpleCore *
321 purple_get_core(void)
323 return _core;
326 static PurpleCoreUiOps *
327 purple_core_ui_ops_copy(PurpleCoreUiOps *ops)
329 PurpleCoreUiOps *ops_new;
331 g_return_val_if_fail(ops != NULL, NULL);
333 ops_new = g_new(PurpleCoreUiOps, 1);
334 *ops_new = *ops;
336 return ops_new;
339 GType
340 purple_core_ui_ops_get_type(void)
342 static GType type = 0;
344 if (type == 0) {
345 type = g_boxed_type_register_static("PurpleCoreUiOps",
346 (GBoxedCopyFunc)purple_core_ui_ops_copy,
347 (GBoxedFreeFunc)g_free);
350 return type;
353 void
354 purple_core_set_ui_ops(PurpleCoreUiOps *ops)
356 _ops = ops;
359 PurpleCoreUiOps *
360 purple_core_get_ui_ops(void)
362 return _ops;
365 #ifdef HAVE_DBUS
366 static char *purple_dbus_owner_user_dir(void)
368 DBusMessage *msg = NULL, *reply = NULL;
369 DBusConnection *dbus_connection = NULL;
370 DBusError dbus_error;
371 char *remote_user_dir = NULL;
373 if ((dbus_connection = purple_dbus_get_connection()) == NULL)
374 return NULL;
376 if ((msg = dbus_message_new_method_call(PURPLE_DBUS_SERVICE, PURPLE_DBUS_PATH, PURPLE_DBUS_INTERFACE, "PurpleUserDir")) == NULL)
377 return NULL;
379 dbus_error_init(&dbus_error);
380 reply = dbus_connection_send_with_reply_and_block(dbus_connection, msg, 5000, &dbus_error);
381 dbus_message_unref(msg);
382 dbus_error_free(&dbus_error);
384 if (reply)
386 dbus_error_init(&dbus_error);
387 dbus_message_get_args(reply, &dbus_error, DBUS_TYPE_STRING, &remote_user_dir, DBUS_TYPE_INVALID);
388 remote_user_dir = g_strdup(remote_user_dir);
389 dbus_error_free(&dbus_error);
390 dbus_message_unref(reply);
393 return remote_user_dir;
396 #endif /* HAVE_DBUS */
398 gboolean
399 purple_core_ensure_single_instance()
401 gboolean is_single_instance = TRUE;
402 #ifdef HAVE_DBUS
403 /* in the future, other mechanisms might have already set this to FALSE */
404 if (is_single_instance)
406 if (!purple_dbus_is_owner())
408 const char *user_dir = purple_user_dir();
409 char *dbus_owner_user_dir = purple_dbus_owner_user_dir();
411 is_single_instance = !purple_strequal(dbus_owner_user_dir, user_dir);
412 g_free(dbus_owner_user_dir);
415 #endif /* HAVE_DBUS */
417 return is_single_instance;
420 GHashTable* purple_core_get_ui_info() {
421 PurpleCoreUiOps *ops = purple_core_get_ui_ops();
423 if(NULL == ops || NULL == ops->get_ui_info)
424 return NULL;
426 return ops->get_ui_info();