]> git.0d.be Git - empathy.git/blob - libempathy/empathy-utils.c
Merge branch 'empathy-account'
[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 (EMPATHY_IS_ACCOUNT (key), 0);
234
235         return g_str_hash (empathy_account_get_unique_name (EMPATHY_ACCOUNT (key)));
236 }
237
238 gboolean
239 empathy_account_equal (gconstpointer a,
240                        gconstpointer b)
241 {
242   return a == b;
243 }
244
245 MissionControl *
246 empathy_mission_control_dup_singleton (void)
247 {
248         static MissionControl *mc = NULL;
249
250         if (!mc) {
251                 mc = mission_control_new (tp_get_bus ());
252                 g_object_add_weak_pointer (G_OBJECT (mc), (gpointer) &mc);
253         } else {
254                 g_object_ref (mc);
255         }
256
257         return mc;
258 }
259
260 const gchar *
261 empathy_presence_get_default_message (TpConnectionPresenceType presence)
262 {
263         switch (presence) {
264         case TP_CONNECTION_PRESENCE_TYPE_AVAILABLE:
265                 return _("Available");
266         case TP_CONNECTION_PRESENCE_TYPE_BUSY:
267                 return _("Busy");
268         case TP_CONNECTION_PRESENCE_TYPE_AWAY:
269         case TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY:
270                 return _("Away");
271         case TP_CONNECTION_PRESENCE_TYPE_HIDDEN:
272                 return _("Hidden");
273         case TP_CONNECTION_PRESENCE_TYPE_OFFLINE:
274                 return _("Offline");
275         case TP_CONNECTION_PRESENCE_TYPE_UNSET:
276         case TP_CONNECTION_PRESENCE_TYPE_UNKNOWN:
277         case TP_CONNECTION_PRESENCE_TYPE_ERROR:
278                 return NULL;
279         }
280
281         return NULL;
282 }
283
284 const gchar *
285 empathy_presence_to_str (TpConnectionPresenceType presence)
286 {
287         int i;
288
289         for (i = 0 ; presence_types[i].name != NULL; i++)
290                 if (presence == presence_types[i].type)
291                         return presence_types[i].name;
292
293         return NULL;
294 }
295
296 TpConnectionPresenceType
297 empathy_presence_from_str (const gchar *str)
298 {
299         int i;
300
301         for (i = 0 ; presence_types[i].name != NULL; i++)
302                 if (!tp_strdiff (str, presence_types[i].name))
303                         return presence_types[i].type;
304
305         return TP_CONNECTION_PRESENCE_TYPE_UNSET;
306 }
307
308 gchar *
309 empathy_file_lookup (const gchar *filename, const gchar *subdir)
310 {
311         gchar *path;
312
313         if (!subdir) {
314                 subdir = ".";
315         }
316
317         path = g_build_filename (g_getenv ("EMPATHY_SRCDIR"), subdir, filename, NULL);
318         if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
319                 g_free (path);
320                 path = g_build_filename (DATADIR, "empathy", filename, NULL);
321         }
322
323         return path;
324 }
325
326 guint
327 empathy_proxy_hash (gconstpointer key)
328 {
329         TpProxy      *proxy = TP_PROXY (key);
330         TpProxyClass *proxy_class = TP_PROXY_GET_CLASS (key);
331
332         g_return_val_if_fail (TP_IS_PROXY (proxy), 0);
333         g_return_val_if_fail (proxy_class->must_have_unique_name, 0);
334
335         return g_str_hash (proxy->object_path) ^ g_str_hash (proxy->bus_name);
336 }
337
338 gboolean
339 empathy_proxy_equal (gconstpointer a,
340                      gconstpointer b)
341 {
342         TpProxy *proxy_a = TP_PROXY (a);
343         TpProxy *proxy_b = TP_PROXY (b);
344         TpProxyClass *proxy_a_class = TP_PROXY_GET_CLASS (a);
345         TpProxyClass *proxy_b_class = TP_PROXY_GET_CLASS (b);
346
347         g_return_val_if_fail (TP_IS_PROXY (proxy_a), FALSE);
348         g_return_val_if_fail (TP_IS_PROXY (proxy_b), FALSE);
349         g_return_val_if_fail (proxy_a_class->must_have_unique_name, 0);
350         g_return_val_if_fail (proxy_b_class->must_have_unique_name, 0);
351
352         return g_str_equal (proxy_a->object_path, proxy_b->object_path) &&
353                g_str_equal (proxy_a->bus_name, proxy_b->bus_name);
354 }
355
356 gboolean
357 empathy_check_available_state (void)
358 {
359         TpConnectionPresenceType presence;
360         EmpathyIdle *idle;
361
362         idle = empathy_idle_dup_singleton ();
363         presence = empathy_idle_get_state (idle);
364         g_object_unref (idle);
365
366         if (presence != TP_CONNECTION_PRESENCE_TYPE_AVAILABLE &&
367                 presence != TP_CONNECTION_PRESENCE_TYPE_UNSET) {
368                 return FALSE;
369         }
370
371         return TRUE;
372 }
373
374 gint
375 empathy_uint_compare (gconstpointer a,
376                       gconstpointer b)
377 {
378         return *(guint *) a - *(guint *) b;
379 }
380