]> git.0d.be Git - empathy.git/blob - libempathy/empathy-utils.c
Merge branch 'debugger'
[empathy.git] / libempathy / empathy-utils.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2003-2007 Imendio AB
4  * Copyright (C) 2007-2008 Collabora Ltd.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public
17  * License along with this program; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA  02110-1301  USA
20  *
21  * Authors: Richard Hult <richard@imendio.com>
22  *          Martyn Russell <martyn@imendio.com>
23  *          Xavier Claessens <xclaesse@gmail.com>
24  */
25
26 #include "config.h"
27
28 #include <string.h>
29 #include <time.h>
30 #include <sys/types.h>
31
32 #include <glib/gi18n-lib.h>
33
34 #include <libxml/uri.h>
35 #include <telepathy-glib/connection.h>
36 #include <telepathy-glib/channel.h>
37 #include <telepathy-glib/dbus.h>
38 #include <telepathy-glib/util.h>
39
40 #include "empathy-utils.h"
41 #include "empathy-contact-manager.h"
42 #include "empathy-dispatcher.h"
43 #include "empathy-dispatch-operation.h"
44 #include "empathy-idle.h"
45 #include "empathy-tp-call.h"
46
47 #include <extensions/extensions.h>
48
49 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
50 #include "empathy-debug.h"
51
52 /* Translation between presence types and string */
53 static struct {
54         gchar *name;
55         TpConnectionPresenceType type;
56 } presence_types[] = {
57         { "available", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE },
58         { "busy",      TP_CONNECTION_PRESENCE_TYPE_BUSY },
59         { "away",      TP_CONNECTION_PRESENCE_TYPE_AWAY },
60         { "ext_away",  TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY },
61         { "hidden",    TP_CONNECTION_PRESENCE_TYPE_HIDDEN },
62         { "offline",   TP_CONNECTION_PRESENCE_TYPE_OFFLINE },
63         { "unset",     TP_CONNECTION_PRESENCE_TYPE_UNSET },
64         { "unknown",   TP_CONNECTION_PRESENCE_TYPE_UNKNOWN },
65         { "error",     TP_CONNECTION_PRESENCE_TYPE_ERROR },
66         /* alternative names */
67         { "dnd",      TP_CONNECTION_PRESENCE_TYPE_BUSY },
68         { "brb",      TP_CONNECTION_PRESENCE_TYPE_AWAY },
69         { "xa",       TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY },
70         { NULL, },
71 };
72
73
74
75 void
76 empathy_init (void)
77 {
78         static gboolean initialized = FALSE;
79
80         if (initialized)
81                 return;
82
83         g_type_init ();
84
85         /* Setup gettext */
86         bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
87         bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
88
89         /* Setup debug output for empathy and telepathy-glib */
90         if (g_getenv ("EMPATHY_TIMING") != NULL) {
91                 g_log_set_default_handler (tp_debug_timestamped_log_handler, NULL);
92         }
93         empathy_debug_set_flags (g_getenv ("EMPATHY_DEBUG"));
94         tp_debug_divert_messages (g_getenv ("EMPATHY_LOGFILE"));
95
96         emp_cli_init ();
97
98         initialized = TRUE;
99 }
100
101 gchar *
102 empathy_substring (const gchar *str,
103                   gint         start,
104                   gint         end)
105 {
106         return g_strndup (str + start, end - start);
107 }
108
109 gint
110 empathy_strcasecmp (const gchar *s1,
111                    const gchar *s2)
112 {
113         return empathy_strncasecmp (s1, s2, -1);
114 }
115
116 gint
117 empathy_strncasecmp (const gchar *s1,
118                     const gchar *s2,
119                     gsize        n)
120 {
121         gchar *u1, *u2;
122         gint   ret_val;
123
124         u1 = g_utf8_casefold (s1, n);
125         u2 = g_utf8_casefold (s2, n);
126
127         ret_val = g_utf8_collate (u1, u2);
128         g_free (u1);
129         g_free (u2);
130
131         return ret_val;
132 }
133
134 gboolean
135 empathy_xml_validate (xmlDoc      *doc,
136                      const gchar *dtd_filename)
137 {
138         gchar        *path, *escaped;
139         xmlValidCtxt  cvp;
140         xmlDtd       *dtd;
141         gboolean      ret;
142
143         path = g_build_filename (g_getenv ("EMPATHY_SRCDIR"), "libempathy",
144                                  dtd_filename, NULL);
145         if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
146                 g_free (path);
147                 path = g_build_filename (DATADIR, "empathy", dtd_filename, NULL);
148         }
149         DEBUG ("Loading dtd file %s", path);
150
151         /* The list of valid chars is taken from libxml. */
152         escaped = xmlURIEscapeStr (path, ":@&=+$,/?;");
153         g_free (path);
154
155         memset (&cvp, 0, sizeof (cvp));
156         dtd = xmlParseDTD (NULL, escaped);
157         ret = xmlValidateDtd (&cvp, doc, dtd);
158
159         xmlFree (escaped);
160         xmlFreeDtd (dtd);
161
162         return ret;
163 }
164
165 xmlNodePtr
166 empathy_xml_node_get_child (xmlNodePtr   node,
167                            const gchar *child_name)
168 {
169         xmlNodePtr l;
170
171         g_return_val_if_fail (node != NULL, NULL);
172         g_return_val_if_fail (child_name != NULL, NULL);
173
174         for (l = node->children; l; l = l->next) {
175                 if (l->name && strcmp (l->name, child_name) == 0) {
176                         return l;
177                 }
178         }
179
180         return NULL;
181 }
182
183 xmlChar *
184 empathy_xml_node_get_child_content (xmlNodePtr   node,
185                                    const gchar *child_name)
186 {
187         xmlNodePtr l;
188
189         g_return_val_if_fail (node != NULL, NULL);
190         g_return_val_if_fail (child_name != NULL, NULL);
191
192         l = empathy_xml_node_get_child (node, child_name);
193         if (l) {
194                 return xmlNodeGetContent (l);
195         }
196
197         return NULL;
198 }
199
200 xmlNodePtr
201 empathy_xml_node_find_child_prop_value (xmlNodePtr   node,
202                                        const gchar *prop_name,
203                                        const gchar *prop_value)
204 {
205         xmlNodePtr l;
206         xmlNodePtr found = NULL;
207
208         g_return_val_if_fail (node != NULL, NULL);
209         g_return_val_if_fail (prop_name != NULL, NULL);
210         g_return_val_if_fail (prop_value != NULL, NULL);
211
212         for (l = node->children; l && !found; l = l->next) {
213                 xmlChar *prop;
214
215                 if (!xmlHasProp (l, prop_name)) {
216                         continue;
217                 }
218
219                 prop = xmlGetProp (l, prop_name);
220                 if (prop && strcmp (prop, prop_value) == 0) {
221                         found = l;
222                 }
223
224                 xmlFree (prop);
225         }
226
227         return found;
228 }
229
230 guint
231 empathy_account_hash (gconstpointer key)
232 {
233         g_return_val_if_fail (MC_IS_ACCOUNT (key), 0);
234
235         return g_str_hash (mc_account_get_unique_name (MC_ACCOUNT (key)));
236 }
237
238 gboolean
239 empathy_account_equal (gconstpointer a,
240                        gconstpointer b)
241 {
242         const gchar *name_a;
243         const gchar *name_b;
244
245         g_return_val_if_fail (MC_IS_ACCOUNT (a), FALSE);
246         g_return_val_if_fail (MC_IS_ACCOUNT (b), FALSE);
247
248         name_a = mc_account_get_unique_name (MC_ACCOUNT (a));
249         name_b = mc_account_get_unique_name (MC_ACCOUNT (b));
250
251         return g_str_equal (name_a, name_b);
252 }
253
254 MissionControl *
255 empathy_mission_control_dup_singleton (void)
256 {
257         static MissionControl *mc = NULL;
258
259         if (!mc) {
260                 mc = mission_control_new (tp_get_bus ());
261                 g_object_add_weak_pointer (G_OBJECT (mc), (gpointer) &mc);
262         } else {
263                 g_object_ref (mc);
264         }
265
266         return mc;
267 }
268
269 const gchar *
270 empathy_presence_get_default_message (TpConnectionPresenceType presence)
271 {
272         switch (presence) {
273         case TP_CONNECTION_PRESENCE_TYPE_AVAILABLE:
274                 return _("Available");
275         case TP_CONNECTION_PRESENCE_TYPE_BUSY:
276                 return _("Busy");
277         case TP_CONNECTION_PRESENCE_TYPE_AWAY:
278         case TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY:
279                 return _("Away");
280         case TP_CONNECTION_PRESENCE_TYPE_HIDDEN:
281                 return _("Hidden");
282         case TP_CONNECTION_PRESENCE_TYPE_OFFLINE:
283                 return _("Offline");
284         case TP_CONNECTION_PRESENCE_TYPE_UNSET:
285         case TP_CONNECTION_PRESENCE_TYPE_UNKNOWN:
286         case TP_CONNECTION_PRESENCE_TYPE_ERROR:
287                 return NULL;
288         }
289
290         return NULL;
291 }
292
293 const gchar *
294 empathy_presence_to_str (TpConnectionPresenceType presence)
295 {
296         int i;
297
298         for (i = 0 ; presence_types[i].name != NULL; i++)
299                 if (presence == presence_types[i].type)
300                         return presence_types[i].name;
301
302         return NULL;
303 }
304
305 TpConnectionPresenceType
306 empathy_presence_from_str (const gchar *str)
307 {
308         int i;
309
310         for (i = 0 ; presence_types[i].name != NULL; i++)
311                 if (!tp_strdiff (str, presence_types[i].name))
312                         return presence_types[i].type;
313
314         return TP_CONNECTION_PRESENCE_TYPE_UNSET;
315 }
316
317 gchar *
318 empathy_file_lookup (const gchar *filename, const gchar *subdir)
319 {
320         gchar *path;
321
322         if (!subdir) {
323                 subdir = ".";
324         }
325
326         path = g_build_filename (g_getenv ("EMPATHY_SRCDIR"), subdir, filename, NULL);
327         if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
328                 g_free (path);
329                 path = g_build_filename (DATADIR, "empathy", filename, NULL);
330         }
331
332         return path;
333 }
334
335 guint
336 empathy_proxy_hash (gconstpointer key)
337 {
338         TpProxy      *proxy = TP_PROXY (key);
339         TpProxyClass *proxy_class = TP_PROXY_GET_CLASS (key);
340
341         g_return_val_if_fail (TP_IS_PROXY (proxy), 0);
342         g_return_val_if_fail (proxy_class->must_have_unique_name, 0);
343
344         return g_str_hash (proxy->object_path) ^ g_str_hash (proxy->bus_name);
345 }
346
347 gboolean
348 empathy_proxy_equal (gconstpointer a,
349                      gconstpointer b)
350 {
351         TpProxy *proxy_a = TP_PROXY (a);
352         TpProxy *proxy_b = TP_PROXY (b);
353         TpProxyClass *proxy_a_class = TP_PROXY_GET_CLASS (a);
354         TpProxyClass *proxy_b_class = TP_PROXY_GET_CLASS (b);
355
356         g_return_val_if_fail (TP_IS_PROXY (proxy_a), FALSE);
357         g_return_val_if_fail (TP_IS_PROXY (proxy_b), FALSE);
358         g_return_val_if_fail (proxy_a_class->must_have_unique_name, 0);
359         g_return_val_if_fail (proxy_b_class->must_have_unique_name, 0);
360
361         return g_str_equal (proxy_a->object_path, proxy_b->object_path) &&
362                g_str_equal (proxy_a->bus_name, proxy_b->bus_name);
363 }
364
365 gboolean
366 empathy_check_available_state (void)
367 {
368         TpConnectionPresenceType presence;
369         EmpathyIdle *idle;
370
371         idle = empathy_idle_dup_singleton ();
372         presence = empathy_idle_get_state (idle);
373         g_object_unref (idle);
374
375         if (presence != TP_CONNECTION_PRESENCE_TYPE_AVAILABLE &&
376                 presence != TP_CONNECTION_PRESENCE_TYPE_UNSET) {
377                 return FALSE;
378         }
379
380         return TRUE;
381 }
382
383 gint
384 empathy_uint_compare (gconstpointer a,
385                       gconstpointer b)
386 {
387         return *(guint *) a - *(guint *) b;
388 }
389