]> git.0d.be Git - empathy.git/blob - libempathy/empathy-log-manager.c
Added checks to the arguments of empathy_message_equal.
[empathy.git] / libempathy / empathy-log-manager.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., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  * Authors: Xavier Claessens <xclaesse@gmail.com>
22  */
23
24 #include <config.h>
25
26 #include <string.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <glib/gstdio.h>
30
31 #include <telepathy-glib/util.h>
32
33 #include "empathy-log-manager.h"
34 #include "empathy-log-store-empathy.h"
35 #include "empathy-log-store.h"
36 #include "empathy-tp-chat.h"
37 #include "empathy-utils.h"
38
39 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
40 #include "empathy-debug.h"
41
42 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyLogManager)
43 typedef struct
44 {
45   GList *stores;
46 } EmpathyLogManagerPriv;
47
48 G_DEFINE_TYPE (EmpathyLogManager, empathy_log_manager, G_TYPE_OBJECT);
49
50 static EmpathyLogManager * manager_singleton = NULL;
51
52 static void
53 log_manager_finalize (GObject *object)
54 {
55   EmpathyLogManagerPriv *priv;
56   GList *l;
57
58   priv = GET_PRIV (object);
59
60   for (l = priv->stores; l; l = l->next)
61     {
62       EmpathyLogStore *store = (EmpathyLogStore *) l->data;
63       g_object_unref (store);
64     }
65
66   g_list_free (priv->stores);
67 }
68
69 static GObject *
70 log_manager_constructor (GType type,
71                          guint n_props,
72                          GObjectConstructParam *props)
73 {
74   GObject *retval;
75   EmpathyLogManagerPriv *priv;
76
77   if (manager_singleton)
78     {
79       retval = g_object_ref (manager_singleton);
80     }
81   else
82     {
83       retval = G_OBJECT_CLASS (empathy_log_manager_parent_class)->constructor
84           (type, n_props, props);
85
86       manager_singleton = EMPATHY_LOG_MANAGER (retval);
87       g_object_add_weak_pointer (retval, (gpointer *) &manager_singleton);
88
89       priv = GET_PRIV (manager_singleton);
90
91       priv->stores = g_list_append (priv->stores,
92           g_object_new (EMPATHY_TYPE_LOG_STORE_EMPATHY, NULL));
93     }
94
95   return retval;
96 }
97
98 static void
99 empathy_log_manager_class_init (EmpathyLogManagerClass *klass)
100 {
101   GObjectClass *object_class = G_OBJECT_CLASS (klass);
102
103   object_class->constructor = log_manager_constructor;
104   object_class->finalize = log_manager_finalize;
105
106   g_type_class_add_private (object_class, sizeof (EmpathyLogManagerPriv));
107 }
108
109 static void
110 empathy_log_manager_init (EmpathyLogManager *manager)
111 {
112   EmpathyLogManagerPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
113       EMPATHY_TYPE_LOG_MANAGER, EmpathyLogManagerPriv);
114
115   manager->priv = priv;
116 }
117
118 EmpathyLogManager *
119 empathy_log_manager_dup_singleton (void)
120 {
121   return g_object_new (EMPATHY_TYPE_LOG_MANAGER, NULL);
122 }
123
124 gboolean
125 empathy_log_manager_add_message (EmpathyLogManager *manager,
126                                  const gchar *chat_id,
127                                  gboolean chatroom,
128                                  EmpathyMessage *message,
129                                  GError **error)
130 {
131   EmpathyLogManagerPriv *priv;
132   GList *l;
133   gboolean out = FALSE;
134   gboolean found = FALSE;
135
136   /* TODO: When multiple log stores appear with add_message implementations
137    * make this customisable. */
138   const gchar *add_store = "Empathy";
139
140   g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), FALSE);
141   g_return_val_if_fail (chat_id != NULL, FALSE);
142   g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
143
144   priv = GET_PRIV (manager);
145
146   for (l = priv->stores; l; l = l->next)
147     {
148       if (!tp_strdiff (empathy_log_store_get_name (
149               EMPATHY_LOG_STORE (l->data)), add_store))
150         {
151           out = empathy_log_store_add_message (EMPATHY_LOG_STORE (l->data),
152               chat_id, chatroom, message, error);
153           found = TRUE;
154           break;
155         }
156     }
157
158   if (!found)
159     DEBUG ("Failed to find chosen log store to write to.");
160
161   return out;
162 }
163
164 gboolean
165 empathy_log_manager_exists (EmpathyLogManager *manager,
166                             McAccount *account,
167                             const gchar *chat_id,
168                             gboolean chatroom)
169 {
170   GList *l;
171   EmpathyLogManagerPriv *priv;
172
173   g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), FALSE);
174   g_return_val_if_fail (MC_IS_ACCOUNT (account), FALSE);
175   g_return_val_if_fail (chat_id != NULL, FALSE);
176
177   priv = GET_PRIV (manager);
178
179   for (l = priv->stores; l; l = l->next)
180     {
181       if (empathy_log_store_exists (EMPATHY_LOG_STORE (l->data),
182             account, chat_id, chatroom))
183         return TRUE;
184     }
185
186   return FALSE;
187 }
188
189 static void
190 log_manager_get_dates_foreach (gpointer data,
191                                gpointer user_data)
192 {
193   /* g_list_first is needed in case an older date was last inserted */
194   GList *orig = g_list_first (user_data);
195
196   if (g_list_find_custom (orig, data, (GCompareFunc) strcmp))
197     orig = g_list_insert_sorted (orig, g_strdup (data), (GCompareFunc) strcmp);
198 }
199
200 GList *
201 empathy_log_manager_get_dates (EmpathyLogManager *manager,
202                                McAccount *account,
203                                const gchar *chat_id,
204                                gboolean chatroom)
205 {
206   GList *l, *out = NULL;
207   EmpathyLogManagerPriv *priv;
208
209   g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), NULL);
210   g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
211   g_return_val_if_fail (chat_id != NULL, NULL);
212
213   priv = GET_PRIV (manager);
214
215   for (l = priv->stores; l; l = l->next)
216     {
217       EmpathyLogStore *store = EMPATHY_LOG_STORE (l->data);
218
219       if (!out)
220         out = empathy_log_store_get_dates (store, account, chat_id, chatroom);
221       else
222         {
223           GList *new = empathy_log_store_get_dates (store, account, chat_id,
224               chatroom);
225           g_list_foreach (new, log_manager_get_dates_foreach, out);
226
227           g_list_foreach (new, (GFunc) g_free, NULL);
228           g_list_free (new);
229
230           /* Similar reason for using g_list_first here as before */
231           out = g_list_first (out);
232         }
233     }
234
235   return out;
236 }
237
238 GList *
239 empathy_log_manager_get_messages_for_date (EmpathyLogManager *manager,
240                                            McAccount *account,
241                                            const gchar *chat_id,
242                                            gboolean chatroom,
243                                            const gchar *date)
244 {
245   GList *l, *out = NULL;
246   EmpathyLogManagerPriv *priv;
247
248   g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), NULL);
249   g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
250   g_return_val_if_fail (chat_id != NULL, NULL);
251
252   priv = GET_PRIV (manager);
253
254   for (l = priv->stores; l; l = l->next)
255     {
256       EmpathyLogStore *store = EMPATHY_LOG_STORE (l->data);
257
258       out = g_list_concat (out, empathy_log_store_get_messages_for_date (
259           store, account, chat_id, chatroom, date));
260     }
261
262   return out;
263 }
264
265 GList *
266 empathy_log_manager_get_last_messages (EmpathyLogManager *manager,
267                                        McAccount *account,
268                                        const gchar *chat_id,
269                                        gboolean chatroom)
270 {
271   GList *messages = NULL;
272   GList *dates;
273   GList *l;
274
275   g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), NULL);
276   g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
277   g_return_val_if_fail (chat_id != NULL, NULL);
278
279   dates = empathy_log_manager_get_dates (manager, account, chat_id, chatroom);
280
281   l = g_list_last (dates);
282   if (l)
283     {
284       messages = empathy_log_manager_get_messages_for_date (manager, account,
285         chat_id, chatroom, l->data);
286
287       /* The latest date will always be today as messages are logged immediately. */
288       l = g_list_previous (l);
289       if (l)
290         {
291           messages = g_list_concat (messages, empathy_log_manager_get_messages_for_date (
292             manager, account, chat_id, chatroom, l->data));
293         }
294     }
295
296   g_list_foreach (dates, (GFunc) g_free, NULL);
297   g_list_free (dates);
298
299   return messages;
300 }
301
302 GList *
303 empathy_log_manager_get_chats (EmpathyLogManager *manager,
304                                McAccount *account)
305 {
306   GList *l, *out = NULL;
307   EmpathyLogManagerPriv *priv;
308
309   g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), NULL);
310   g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
311
312   priv = GET_PRIV (manager);
313
314   for (l = priv->stores; l; l = l->next)
315     {
316       EmpathyLogStore *store = EMPATHY_LOG_STORE (l->data);
317
318       out = g_list_concat (out,
319           empathy_log_store_get_chats (store, account));
320     }
321
322   return out;
323 }
324
325 GList *
326 empathy_log_manager_search_new (EmpathyLogManager *manager,
327                                 const gchar *text)
328 {
329   GList *l, *out = NULL;
330   EmpathyLogManagerPriv *priv;
331
332   g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), NULL);
333   g_return_val_if_fail (!EMP_STR_EMPTY (text), NULL);
334
335   priv = GET_PRIV (manager);
336
337   for (l = priv->stores; l; l = l->next)
338     {
339       EmpathyLogStore *store = EMPATHY_LOG_STORE (l->data);
340
341       out = g_list_concat (out,
342           empathy_log_store_search_new (store, text));
343     }
344
345   return out;
346 }
347
348 void
349 empathy_log_manager_search_hit_free (EmpathyLogSearchHit *hit)
350 {
351   if (hit->account)
352     g_object_unref (hit->account);
353
354   g_free (hit->date);
355   g_free (hit->filename);
356   g_free (hit->chat_id);
357
358   g_slice_free (EmpathyLogSearchHit, hit);
359 }
360
361 void
362 empathy_log_manager_search_free (GList *hits)
363 {
364   GList *l;
365
366   for (l = hits; l; l = l->next)
367     {
368       empathy_log_manager_search_hit_free (l->data);
369     }
370
371   g_list_free (hits);
372 }
373
374 /* Format is just date, 20061201. */
375 gchar *
376 empathy_log_manager_get_date_readable (const gchar *date)
377 {
378   time_t t;
379
380   t = empathy_time_parse (date);
381
382   return empathy_time_to_string_local (t, "%a %d %b %Y");
383 }
384
385 static void
386 log_manager_chat_received_message_cb (EmpathyTpChat *tp_chat,
387                                       EmpathyMessage *message,
388                                       EmpathyLogManager *log_manager)
389 {
390   GError *error = NULL;
391   TpHandleType handle_type;
392   TpChannel *channel;
393
394   channel = empathy_tp_chat_get_channel (tp_chat);
395   tp_channel_get_handle (channel, &handle_type);
396
397   if (!empathy_log_manager_add_message (log_manager,
398         tp_channel_get_identifier (channel),
399         handle_type == TP_HANDLE_TYPE_ROOM,
400         message, &error))
401     {
402       DEBUG ("Failed to write message: %s",
403           error ? error->message : "No error message");
404
405       if (error)
406         g_error_free (error);
407     }
408 }
409
410 static void
411 log_manager_dispatcher_observe_cb (EmpathyDispatcher *dispatcher,
412                                    EmpathyDispatchOperation *operation,
413                                    EmpathyLogManager *log_manager)
414 {
415   GQuark channel_type;
416
417   channel_type = empathy_dispatch_operation_get_channel_type_id (operation);
418
419   if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_TEXT)
420     {
421       EmpathyTpChat *tp_chat;
422
423       tp_chat = EMPATHY_TP_CHAT (
424           empathy_dispatch_operation_get_channel_wrapper (operation));
425
426       g_signal_connect (tp_chat, "message-received",
427           G_CALLBACK (log_manager_chat_received_message_cb), log_manager);
428     }
429 }
430
431
432 void
433 empathy_log_manager_observe (EmpathyLogManager *log_manager,
434                              EmpathyDispatcher *dispatcher)
435 {
436   g_signal_connect (dispatcher, "observe",
437       G_CALLBACK (log_manager_dispatcher_observe_cb), log_manager);
438 }