]> git.0d.be Git - empathy.git/blob - libempathy/empathy-log-store-empathy.c
Updated Polish translation
[empathy.git] / libempathy / empathy-log-store-empathy.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: Xavier Claessens <xclaesse@gmail.com>
22  *          Jonny Lamb <jonny.lamb@collabora.co.uk>
23  */
24
25 #include <config.h>
26
27 #include <string.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <glib/gstdio.h>
31
32 #include <telepathy-glib/account-manager.h>
33 #include <telepathy-glib/util.h>
34 #include <telepathy-glib/defs.h>
35
36 #include "empathy-log-store.h"
37 #include "empathy-log-store-empathy.h"
38 #include "empathy-log-manager.h"
39 #include "empathy-contact.h"
40 #include "empathy-time.h"
41 #include "empathy-utils.h"
42
43 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
44 #include "empathy-debug.h"
45
46 #define LOG_DIR_CREATE_MODE       (S_IRUSR | S_IWUSR | S_IXUSR)
47 #define LOG_FILE_CREATE_MODE      (S_IRUSR | S_IWUSR)
48 #define LOG_DIR_CHATROOMS         "chatrooms"
49 #define LOG_FILENAME_SUFFIX       ".log"
50 #define LOG_TIME_FORMAT_FULL      "%Y%m%dT%H:%M:%S"
51 #define LOG_TIME_FORMAT           "%Y%m%d"
52 #define LOG_HEADER \
53     "<?xml version='1.0' encoding='utf-8'?>\n" \
54     "<?xml-stylesheet type=\"text/xsl\" href=\"empathy-log.xsl\"?>\n" \
55     "<log>\n"
56
57 #define LOG_FOOTER \
58     "</log>\n"
59
60
61 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyLogStoreEmpathy)
62 typedef struct
63 {
64   gchar *basedir;
65   gchar *name;
66   TpAccountManager *account_manager;
67 } EmpathyLogStoreEmpathyPriv;
68
69 static void log_store_iface_init (gpointer g_iface,gpointer iface_data);
70
71 G_DEFINE_TYPE_WITH_CODE (EmpathyLogStoreEmpathy, empathy_log_store_empathy,
72     G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (EMPATHY_TYPE_LOG_STORE,
73       log_store_iface_init));
74
75 static void
76 log_store_empathy_finalize (GObject *object)
77 {
78   EmpathyLogStoreEmpathy *self = EMPATHY_LOG_STORE_EMPATHY (object);
79   EmpathyLogStoreEmpathyPriv *priv = GET_PRIV (self);
80
81   g_object_unref (priv->account_manager);
82   g_free (priv->basedir);
83   g_free (priv->name);
84 }
85
86 static void
87 empathy_log_store_empathy_class_init (EmpathyLogStoreEmpathyClass *klass)
88 {
89   GObjectClass *object_class = G_OBJECT_CLASS (klass);
90
91   object_class->finalize = log_store_empathy_finalize;
92
93   g_type_class_add_private (object_class, sizeof (EmpathyLogStoreEmpathyPriv));
94 }
95
96 static void
97 empathy_log_store_empathy_init (EmpathyLogStoreEmpathy *self)
98 {
99   EmpathyLogStoreEmpathyPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
100       EMPATHY_TYPE_LOG_STORE_EMPATHY, EmpathyLogStoreEmpathyPriv);
101
102   self->priv = priv;
103
104   priv->basedir = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (),
105     PACKAGE_NAME, "logs", NULL);
106
107   priv->name = g_strdup ("Empathy");
108   priv->account_manager = tp_account_manager_dup ();
109 }
110
111 static gchar *
112 log_store_account_to_dirname (TpAccount *account)
113 {
114   const gchar *name;
115
116   name = tp_proxy_get_object_path (account);
117   if (g_str_has_prefix (name, TP_ACCOUNT_OBJECT_PATH_BASE))
118     name += strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
119
120   return g_strdelimit (g_strdup (name), "/", '_');
121 }
122
123
124 static gchar *
125 log_store_empathy_get_dir (EmpathyLogStore *self,
126                            TpAccount *account,
127                            const gchar *chat_id,
128                            gboolean chatroom)
129 {
130   gchar *basedir;
131   gchar *escaped;
132   EmpathyLogStoreEmpathyPriv *priv;
133
134   priv = GET_PRIV (self);
135
136   escaped = log_store_account_to_dirname (account);
137
138   if (chatroom)
139     basedir = g_build_path (G_DIR_SEPARATOR_S, priv->basedir, escaped,
140         LOG_DIR_CHATROOMS, chat_id, NULL);
141   else
142     basedir = g_build_path (G_DIR_SEPARATOR_S, priv->basedir,
143         escaped, chat_id, NULL);
144
145   g_free (escaped);
146
147   return basedir;
148 }
149
150 static gchar *
151 log_store_empathy_get_timestamp_filename (void)
152 {
153   time_t t;
154   gchar *time_str;
155   gchar *filename;
156
157   t = empathy_time_get_current ();
158   time_str = empathy_time_to_string_local (t, LOG_TIME_FORMAT);
159   filename = g_strconcat (time_str, LOG_FILENAME_SUFFIX, NULL);
160
161   g_free (time_str);
162
163   return filename;
164 }
165
166 static gchar *
167 log_store_empathy_get_timestamp_from_message (EmpathyMessage *message)
168 {
169   time_t t;
170
171   t = empathy_message_get_timestamp (message);
172
173   /* We keep the timestamps in the messages as UTC. */
174   return empathy_time_to_string_utc (t, LOG_TIME_FORMAT_FULL);
175 }
176
177 static gchar *
178 log_store_empathy_get_filename (EmpathyLogStore *self,
179                                 TpAccount *account,
180                                 const gchar *chat_id,
181                                 gboolean chatroom)
182 {
183   gchar *basedir;
184   gchar *timestamp;
185   gchar *filename;
186
187   basedir = log_store_empathy_get_dir (self, account, chat_id, chatroom);
188   timestamp = log_store_empathy_get_timestamp_filename ();
189   filename = g_build_filename (basedir, timestamp, NULL);
190
191   g_free (basedir);
192   g_free (timestamp);
193
194   return filename;
195 }
196
197 static gboolean
198 log_store_empathy_add_message (EmpathyLogStore *self,
199                                const gchar *chat_id,
200                                gboolean chatroom,
201                                EmpathyMessage *message,
202                                GError **error)
203 {
204   FILE *file;
205   TpAccount *account;
206   EmpathyContact *sender;
207   const gchar *body_str;
208   const gchar *str;
209   EmpathyAvatar *avatar;
210   gchar *avatar_token = NULL;
211   gchar *filename;
212   gchar *basedir;
213   gchar *body;
214   gchar *timestamp;
215   gchar *contact_name;
216   gchar *contact_id;
217   TpChannelTextMessageType msg_type;
218
219   g_return_val_if_fail (EMPATHY_IS_LOG_STORE (self), FALSE);
220   g_return_val_if_fail (chat_id != NULL, FALSE);
221   g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
222
223   sender = empathy_message_get_sender (message);
224   account = empathy_contact_get_account (sender);
225   body_str = empathy_message_get_body (message);
226   msg_type = empathy_message_get_tptype (message);
227
228   if (EMP_STR_EMPTY (body_str))
229     return FALSE;
230
231   filename = log_store_empathy_get_filename (self, account, chat_id, chatroom);
232   basedir = g_path_get_dirname (filename);
233   if (!g_file_test (basedir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
234     {
235       DEBUG ("Creating directory:'%s'", basedir);
236       g_mkdir_with_parents (basedir, LOG_DIR_CREATE_MODE);
237     }
238   g_free (basedir);
239
240   DEBUG ("Adding message: '%s' to file: '%s'", body_str, filename);
241
242   if (!g_file_test (filename, G_FILE_TEST_EXISTS))
243     {
244       file = g_fopen (filename, "w+");
245       if (file != NULL)
246         g_fprintf (file, LOG_HEADER);
247
248       g_chmod (filename, LOG_FILE_CREATE_MODE);
249     }
250   else
251     {
252       file = g_fopen (filename, "r+");
253       if (file != NULL)
254         fseek (file, - strlen (LOG_FOOTER), SEEK_END);
255     }
256
257   body = g_markup_escape_text (body_str, -1);
258   timestamp = log_store_empathy_get_timestamp_from_message (message);
259
260   str = empathy_contact_get_name (sender);
261   contact_name = g_markup_escape_text (str, -1);
262
263   str = empathy_contact_get_id (sender);
264   contact_id = g_markup_escape_text (str, -1);
265
266   avatar = empathy_contact_get_avatar (sender);
267   if (avatar != NULL)
268     avatar_token = g_markup_escape_text (avatar->token, -1);
269
270   g_fprintf (file,
271        "<message time='%s' cm_id='%d' id='%s' name='%s' token='%s' isuser='%s' type='%s'>"
272        "%s</message>\n" LOG_FOOTER, timestamp,
273        empathy_message_get_id (message),
274        contact_id, contact_name,
275        avatar_token ? avatar_token : "",
276        empathy_contact_is_user (sender) ? "true" : "false",
277        empathy_message_type_to_str (msg_type), body);
278
279   fclose (file);
280   g_free (filename);
281   g_free (contact_id);
282   g_free (contact_name);
283   g_free (timestamp);
284   g_free (body);
285   g_free (avatar_token);
286
287   return TRUE;
288 }
289
290 static gboolean
291 log_store_empathy_exists (EmpathyLogStore *self,
292                           TpAccount *account,
293                           const gchar *chat_id,
294                           gboolean chatroom)
295 {
296   gchar *dir;
297   gboolean exists;
298
299   dir = log_store_empathy_get_dir (self, account, chat_id, chatroom);
300   exists = g_file_test (dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR);
301   g_free (dir);
302
303   return exists;
304 }
305
306 static GList *
307 log_store_empathy_get_dates (EmpathyLogStore *self,
308                              TpAccount *account,
309                              const gchar *chat_id,
310                              gboolean chatroom)
311 {
312   GList *dates = NULL;
313   gchar *date;
314   gchar *directory;
315   GDir *dir;
316   const gchar *filename;
317   const gchar *p;
318
319   g_return_val_if_fail (EMPATHY_IS_LOG_STORE (self), NULL);
320   g_return_val_if_fail (chat_id != NULL, NULL);
321
322   directory = log_store_empathy_get_dir (self, account, chat_id, chatroom);
323   dir = g_dir_open (directory, 0, NULL);
324   if (!dir)
325     {
326       DEBUG ("Could not open directory:'%s'", directory);
327       g_free (directory);
328       return NULL;
329     }
330
331   DEBUG ("Collating a list of dates in:'%s'", directory);
332
333   while ((filename = g_dir_read_name (dir)) != NULL)
334     {
335       if (!g_str_has_suffix (filename, LOG_FILENAME_SUFFIX))
336         continue;
337
338       p = strstr (filename, LOG_FILENAME_SUFFIX);
339       date = g_strndup (filename, p - filename);
340
341       if (!date)
342         continue;
343
344       if (!g_regex_match_simple ("\\d{8}", date, 0, 0))
345         continue;
346
347       dates = g_list_insert_sorted (dates, date, (GCompareFunc) strcmp);
348     }
349
350   g_free (directory);
351   g_dir_close (dir);
352
353   DEBUG ("Parsed %d dates", g_list_length (dates));
354
355   return dates;
356 }
357
358 static gchar *
359 log_store_empathy_get_filename_for_date (EmpathyLogStore *self,
360                                          TpAccount *account,
361                                          const gchar *chat_id,
362                                          gboolean chatroom,
363                                          const gchar *date)
364 {
365   gchar *basedir;
366   gchar *timestamp;
367   gchar *filename;
368
369   basedir = log_store_empathy_get_dir (self, account, chat_id, chatroom);
370   timestamp = g_strconcat (date, LOG_FILENAME_SUFFIX, NULL);
371   filename = g_build_filename (basedir, timestamp, NULL);
372
373   g_free (basedir);
374   g_free (timestamp);
375
376   return filename;
377 }
378
379 static EmpathyLogSearchHit *
380 log_store_empathy_search_hit_new (EmpathyLogStore *self,
381                                   const gchar *filename)
382 {
383   EmpathyLogStoreEmpathyPriv *priv = GET_PRIV (self);
384   EmpathyLogSearchHit *hit;
385   gchar *account_name;
386   const gchar *end;
387   gchar **strv;
388   guint len;
389   GList *accounts, *l;
390
391   if (!g_str_has_suffix (filename, LOG_FILENAME_SUFFIX))
392     return NULL;
393
394   strv = g_strsplit (filename, G_DIR_SEPARATOR_S, -1);
395   len = g_strv_length (strv);
396
397   hit = g_slice_new0 (EmpathyLogSearchHit);
398
399   end = strstr (strv[len-1], LOG_FILENAME_SUFFIX);
400   hit->date = g_strndup (strv[len-1], end - strv[len-1]);
401   hit->chat_id = g_strdup (strv[len-2]);
402   hit->is_chatroom = (strcmp (strv[len-3], LOG_DIR_CHATROOMS) == 0);
403
404   if (hit->is_chatroom)
405     account_name = strv[len-4];
406   else
407     account_name = strv[len-3];
408
409   /* FIXME: This assumes the account manager is prepared, but the
410    * synchronous API forces this. See bug #599189. */
411   accounts = tp_account_manager_get_valid_accounts (priv->account_manager);
412
413   for (l = accounts; l != NULL; l = g_list_next (l))
414     {
415       TpAccount *account = TP_ACCOUNT (l->data);
416       gchar *name;
417
418       name = log_store_account_to_dirname (account);
419       if (!tp_strdiff (name, account_name))
420         {
421           g_assert (hit->account == NULL);
422           hit->account = account;
423           g_object_ref (account);
424         }
425       g_free (name);
426     }
427   g_list_free (accounts);
428
429   hit->filename = g_strdup (filename);
430
431   g_strfreev (strv);
432
433   return hit;
434 }
435
436 static GList *
437 log_store_empathy_get_messages_for_file (EmpathyLogStore *self,
438                                          TpAccount *account,
439                                          const gchar *filename)
440 {
441   GList *messages = NULL;
442   xmlParserCtxtPtr ctxt;
443   xmlDocPtr doc;
444   xmlNodePtr log_node;
445   xmlNodePtr node;
446
447   g_return_val_if_fail (EMPATHY_IS_LOG_STORE (self), NULL);
448   g_return_val_if_fail (filename != NULL, NULL);
449
450   DEBUG ("Attempting to parse filename:'%s'...", filename);
451
452   if (!g_file_test (filename, G_FILE_TEST_EXISTS))
453     {
454       DEBUG ("Filename:'%s' does not exist", filename);
455       return NULL;
456     }
457
458   /* Create parser. */
459   ctxt = xmlNewParserCtxt ();
460
461   /* Parse and validate the file. */
462   doc = xmlCtxtReadFile (ctxt, filename, NULL, 0);
463   if (!doc)
464     {
465       g_warning ("Failed to parse file:'%s'", filename);
466       xmlFreeParserCtxt (ctxt);
467       return NULL;
468     }
469
470   /* The root node, presets. */
471   log_node = xmlDocGetRootElement (doc);
472   if (!log_node)
473     {
474       xmlFreeDoc (doc);
475       xmlFreeParserCtxt (ctxt);
476       return NULL;
477     }
478
479   /* Now get the messages. */
480   for (node = log_node->children; node; node = node->next)
481     {
482       EmpathyMessage *message;
483       EmpathyContact *sender;
484       gchar *time_;
485       time_t t;
486       gchar *sender_id;
487       gchar *sender_name;
488       gchar *sender_avatar_token;
489       gchar *body;
490       gchar *is_user_str;
491       gboolean is_user = FALSE;
492       gchar *msg_type_str;
493       gchar *cm_id_str;
494       guint cm_id;
495       TpChannelTextMessageType msg_type = TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
496
497       if (strcmp ((const gchar *) node->name, "message") != 0)
498         continue;
499
500       body = (gchar *) xmlNodeGetContent (node);
501       time_ = (gchar *) xmlGetProp (node, (const xmlChar *) "time");
502       sender_id = (gchar *) xmlGetProp (node, (const xmlChar *) "id");
503       sender_name = (gchar *) xmlGetProp (node, (const xmlChar *) "name");
504       sender_avatar_token = (gchar *) xmlGetProp (node,
505           (const xmlChar *) "token");
506       is_user_str = (gchar *) xmlGetProp (node, (const xmlChar *) "isuser");
507       msg_type_str = (gchar *) xmlGetProp (node, (const xmlChar *) "type");
508       cm_id_str = (gchar *) xmlGetProp (node, (const xmlChar *) "cm_id");
509
510       if (is_user_str)
511         is_user = strcmp (is_user_str, "true") == 0;
512
513       if (msg_type_str)
514         msg_type = empathy_message_type_from_str (msg_type_str);
515
516       if (cm_id_str)
517         cm_id = atoi (cm_id_str);
518
519       t = empathy_time_parse (time_);
520
521       sender = empathy_contact_new_for_log (account, sender_id, sender_name,
522                                             is_user);
523
524       if (!EMP_STR_EMPTY (sender_avatar_token))
525         empathy_contact_load_avatar_cache (sender,
526             sender_avatar_token);
527
528       message = empathy_message_new (body);
529       empathy_message_set_sender (message, sender);
530       empathy_message_set_timestamp (message, t);
531       empathy_message_set_tptype (message, msg_type);
532       empathy_message_set_is_backlog (message, TRUE);
533
534       if (cm_id_str)
535         empathy_message_set_id (message, cm_id);
536
537       messages = g_list_append (messages, message);
538
539       g_object_unref (sender);
540       xmlFree (time_);
541       xmlFree (sender_id);
542       xmlFree (sender_name);
543       xmlFree (body);
544       xmlFree (is_user_str);
545       xmlFree (msg_type_str);
546       xmlFree (cm_id_str);
547       xmlFree (sender_avatar_token);
548     }
549
550   DEBUG ("Parsed %d messages", g_list_length (messages));
551
552   xmlFreeDoc (doc);
553   xmlFreeParserCtxt (ctxt);
554
555   return messages;
556 }
557
558 static GList *
559 log_store_empathy_get_all_files (EmpathyLogStore *self,
560                                  const gchar *dir)
561 {
562   GDir *gdir;
563   GList *files = NULL;
564   const gchar *name;
565   const gchar *basedir;
566   EmpathyLogStoreEmpathyPriv *priv;
567
568   priv = GET_PRIV (self);
569
570   basedir = dir ? dir : priv->basedir;
571
572   gdir = g_dir_open (basedir, 0, NULL);
573   if (!gdir)
574     return NULL;
575
576   while ((name = g_dir_read_name (gdir)) != NULL)
577     {
578       gchar *filename;
579
580       filename = g_build_filename (basedir, name, NULL);
581       if (g_str_has_suffix (filename, LOG_FILENAME_SUFFIX))
582         {
583           files = g_list_prepend (files, filename);
584           continue;
585         }
586
587       if (g_file_test (filename, G_FILE_TEST_IS_DIR))
588         {
589           /* Recursively get all log files */
590           files = g_list_concat (files,
591               log_store_empathy_get_all_files (self, filename));
592         }
593
594       g_free (filename);
595     }
596
597   g_dir_close (gdir);
598
599   return files;
600 }
601
602 static GList *
603 log_store_empathy_search_new (EmpathyLogStore *self,
604                               const gchar *text)
605 {
606   GList *files, *l;
607   GList *hits = NULL;
608   gchar *text_casefold;
609
610   g_return_val_if_fail (EMPATHY_IS_LOG_STORE (self), NULL);
611   g_return_val_if_fail (!EMP_STR_EMPTY (text), NULL);
612
613   text_casefold = g_utf8_casefold (text, -1);
614
615   files = log_store_empathy_get_all_files (self, NULL);
616   DEBUG ("Found %d log files in total", g_list_length (files));
617
618   for (l = files; l; l = g_list_next (l))
619     {
620       gchar *filename;
621       GMappedFile *file;
622       gsize length;
623       gchar *contents;
624       gchar *contents_casefold;
625
626       filename = l->data;
627
628       file = g_mapped_file_new (filename, FALSE, NULL);
629       if (!file)
630         continue;
631
632       length = g_mapped_file_get_length (file);
633       contents = g_mapped_file_get_contents (file);
634       contents_casefold = g_utf8_casefold (contents, length);
635
636       g_mapped_file_unref (file);
637
638       if (strstr (contents_casefold, text_casefold))
639         {
640           EmpathyLogSearchHit *hit;
641
642           hit = log_store_empathy_search_hit_new (self, filename);
643
644           if (hit)
645             {
646               hits = g_list_prepend (hits, hit);
647               DEBUG ("Found text:'%s' in file:'%s' on date:'%s'",
648                   text, hit->filename, hit->date);
649             }
650         }
651
652       g_free (contents_casefold);
653       g_free (filename);
654     }
655
656   g_list_free (files);
657   g_free (text_casefold);
658
659   return hits;
660 }
661
662 static GList *
663 log_store_empathy_get_chats_for_dir (EmpathyLogStore *self,
664                                      const gchar *dir,
665                                      gboolean is_chatroom)
666 {
667   GDir *gdir;
668   GList *hits = NULL;
669   const gchar *name;
670   GError *error = NULL;
671
672   gdir = g_dir_open (dir, 0, &error);
673   if (!gdir)
674     {
675       DEBUG ("Failed to open directory: %s, error: %s", dir, error->message);
676       g_error_free (error);
677       return NULL;
678     }
679
680   while ((name = g_dir_read_name (gdir)) != NULL)
681     {
682       EmpathyLogSearchHit *hit;
683
684       if (!is_chatroom && strcmp (name, LOG_DIR_CHATROOMS) == 0)
685         {
686           gchar *filename = g_build_filename (dir, name, NULL);
687           hits = g_list_concat (hits, log_store_empathy_get_chats_for_dir (
688                 self, filename, TRUE));
689           g_free (filename);
690           continue;
691         }
692       hit = g_slice_new0 (EmpathyLogSearchHit);
693       hit->chat_id = g_strdup (name);
694       hit->is_chatroom = is_chatroom;
695
696       hits = g_list_prepend (hits, hit);
697     }
698
699   g_dir_close (gdir);
700
701   return hits;
702 }
703
704
705 static GList *
706 log_store_empathy_get_messages_for_date (EmpathyLogStore *self,
707                                          TpAccount *account,
708                                          const gchar *chat_id,
709                                          gboolean chatroom,
710                                          const gchar *date)
711 {
712   gchar *filename;
713   GList *messages;
714
715   g_return_val_if_fail (EMPATHY_IS_LOG_STORE (self), NULL);
716   g_return_val_if_fail (chat_id != NULL, NULL);
717   g_return_val_if_fail (account != NULL, NULL);
718
719   filename = log_store_empathy_get_filename_for_date (self, account,
720       chat_id, chatroom, date);
721   messages = log_store_empathy_get_messages_for_file (self, account,
722     filename);
723   g_free (filename);
724
725   return messages;
726 }
727
728 static GList *
729 log_store_empathy_get_chats (EmpathyLogStore *self,
730                               TpAccount *account)
731 {
732   gchar *dir;
733   GList *hits;
734   EmpathyLogStoreEmpathyPriv *priv;
735
736   priv = GET_PRIV (self);
737
738   dir = log_store_empathy_get_dir (self, account, NULL, FALSE);
739
740   hits = log_store_empathy_get_chats_for_dir (self, dir, FALSE);
741
742   g_free (dir);
743
744   return hits;
745 }
746
747 static const gchar *
748 log_store_empathy_get_name (EmpathyLogStore *self)
749 {
750   EmpathyLogStoreEmpathyPriv *priv = GET_PRIV (self);
751
752   return priv->name;
753 }
754
755 static GList *
756 log_store_empathy_get_filtered_messages (EmpathyLogStore *self,
757                                          TpAccount *account,
758                                          const gchar *chat_id,
759                                          gboolean chatroom,
760                                          guint num_messages,
761                                          EmpathyLogMessageFilter filter,
762                                          gpointer user_data)
763 {
764   GList *dates, *l, *messages = NULL;
765   guint i = 0;
766
767   dates = log_store_empathy_get_dates (self, account, chat_id, chatroom);
768
769   for (l = g_list_last (dates); l && i < num_messages; l = g_list_previous (l))
770     {
771       GList *new_messages, *n, *next;
772
773       /* FIXME: We should really restrict the message parsing to get only
774        * the newest num_messages. */
775       new_messages = log_store_empathy_get_messages_for_date (self, account,
776           chat_id, chatroom, l->data);
777
778       n = new_messages;
779       while (n != NULL)
780         {
781           next = g_list_next (n);
782           if (!filter (n->data, user_data))
783             {
784               g_object_unref (n->data);
785               new_messages = g_list_delete_link (new_messages, n);
786             }
787           else
788             {
789               i++;
790             }
791           n = next;
792         }
793       messages = g_list_concat (messages, new_messages);
794     }
795
796   g_list_foreach (dates, (GFunc) g_free, NULL);
797   g_list_free (dates);
798
799   return messages;
800 }
801
802 static void
803 log_store_iface_init (gpointer g_iface,
804                       gpointer iface_data)
805 {
806   EmpathyLogStoreInterface *iface = (EmpathyLogStoreInterface *) g_iface;
807
808   iface->get_name = log_store_empathy_get_name;
809   iface->exists = log_store_empathy_exists;
810   iface->add_message = log_store_empathy_add_message;
811   iface->get_dates = log_store_empathy_get_dates;
812   iface->get_messages_for_date = log_store_empathy_get_messages_for_date;
813   iface->get_chats = log_store_empathy_get_chats;
814   iface->search_new = log_store_empathy_search_new;
815   iface->ack_message = NULL;
816   iface->get_filtered_messages = log_store_empathy_get_filtered_messages;
817 }