]> git.0d.be Git - empathy.git/blob - libempathy/empathy-log-manager.c
Add MSN setting UI. Fixes bug #443162 (Cosimo Cecchi).
[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) 2007 Collabora Ltd.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  * 
20  * Authors: Xavier Claessens <xclaesse@gmail.com>
21  */
22
23 #include <config.h>
24
25 #include <string.h>
26 #include <stdio.h>
27 #include <glib/gstdio.h>
28
29 #include "empathy-log-manager.h"
30 #include "empathy-contact.h"
31 #include "empathy-time.h"
32 #include "empathy-debug.h"
33 #include "empathy-utils.h"
34
35 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
36                        EMPATHY_TYPE_LOG_MANAGER, EmpathyLogManagerPriv))
37
38 #define DEBUG_DOMAIN "LogManager"
39
40 #define LOG_DIR_CREATE_MODE       (S_IRUSR | S_IWUSR | S_IXUSR)
41 #define LOG_FILE_CREATE_MODE      (S_IRUSR | S_IWUSR)
42 #define LOG_DIR_CHATROOMS         "chatrooms"
43 #define LOG_FILENAME_SUFFIX       ".log"
44 #define LOG_TIME_FORMAT_FULL      "%Y%m%dT%H:%M:%S"
45 #define LOG_TIME_FORMAT           "%Y%m%d"
46 #define LOG_HEADER \
47     "<?xml version='1.0' encoding='utf-8'?>\n" \
48     "<?xml-stylesheet type=\"text/xsl\" href=\"empathy-log.xsl\"?>\n" \
49     "<log>\n"
50
51 #define LOG_FOOTER \
52     "</log>\n"
53
54 struct _EmpathyLogManagerPriv {
55         gchar *basedir;
56 };
57
58 static void                 empathy_log_manager_class_init         (EmpathyLogManagerClass *klass);
59 static void                 empathy_log_manager_init               (EmpathyLogManager      *manager);
60 static void                 log_manager_finalize                   (GObject                *object);
61 static const gchar *        log_manager_get_basedir                (EmpathyLogManager      *manager);
62 static GList *              log_manager_get_all_files              (EmpathyLogManager      *manager,
63                                                                     const gchar            *dir);
64 static GList *              log_manager_get_chats                  (EmpathyLogManager      *manager,
65                                                                     const gchar            *dir,
66                                                                     gboolean                is_chatroom);
67 static gchar *              log_manager_get_dir                    (EmpathyLogManager      *manager,
68                                                                     McAccount              *account,
69                                                                     const gchar            *chat_id,
70                                                                     gboolean                chatroom);
71 static gchar *              log_manager_get_filename               (EmpathyLogManager      *manager,
72                                                                     McAccount              *account,
73                                                                     const gchar            *chat_id,
74                                                                     gboolean                chatroom);
75 static gchar *              log_manager_get_filename_for_date      (EmpathyLogManager      *manager,
76                                                                     McAccount              *account,
77                                                                     const gchar            *chat_id,
78                                                                     gboolean                chatroom,
79                                                                     const gchar            *date);
80 static gchar *              log_manager_get_timestamp_filename     (void);
81 static gchar *              log_manager_get_timestamp_from_message (EmpathyMessage          *message);
82 static EmpathyLogSearchHit *log_manager_search_hit_new             (EmpathyLogManager      *manager,
83                                                                     const gchar            *filename);
84 static void                 log_manager_search_hit_free            (EmpathyLogSearchHit    *hit);
85
86 G_DEFINE_TYPE (EmpathyLogManager, empathy_log_manager, G_TYPE_OBJECT);
87
88 static void
89 empathy_log_manager_class_init (EmpathyLogManagerClass *klass)
90 {
91         GObjectClass *object_class = G_OBJECT_CLASS (klass);
92
93         object_class->finalize = log_manager_finalize;
94
95         g_type_class_add_private (object_class, sizeof (EmpathyLogManagerPriv));
96 }
97
98 static void
99 empathy_log_manager_init (EmpathyLogManager *manager)
100 {
101 }
102
103 static void
104 log_manager_finalize (GObject *object)
105 {
106         EmpathyLogManagerPriv *priv;
107
108         priv = GET_PRIV (object);
109
110         g_free (priv->basedir);
111 }
112
113 EmpathyLogManager *
114 empathy_log_manager_new (void)
115 {
116         static EmpathyLogManager *manager = NULL;
117
118         if (!manager) {
119                 manager = g_object_new (EMPATHY_TYPE_LOG_MANAGER, NULL);
120                 g_object_add_weak_pointer (G_OBJECT (manager), (gpointer) &manager);
121         } else {
122                 g_object_ref (manager);
123         }
124
125         return manager;
126 }
127
128 void
129 empathy_log_manager_add_message (EmpathyLogManager *manager,
130                                  const gchar       *chat_id,
131                                  gboolean           chatroom,
132                                  EmpathyMessage     *message)
133 {
134         FILE          *file;
135         McAccount     *account;
136         EmpathyContact *sender;
137         const gchar   *body_str;
138         const gchar   *str;
139         gchar         *filename;
140         gchar         *basedir;
141         gchar         *body;
142         gchar         *timestamp;
143         gchar         *contact_name;
144         gchar         *contact_id;
145
146         g_return_if_fail (EMPATHY_IS_LOG_MANAGER (manager));
147         g_return_if_fail (chat_id != NULL);
148         g_return_if_fail (EMPATHY_IS_MESSAGE (message));
149
150         sender = empathy_message_get_sender (message);
151         account = empathy_contact_get_account (sender);
152         body_str = empathy_message_get_body (message);
153
154         if (G_STR_EMPTY (body_str)) {
155                 return;
156         }
157
158         filename = log_manager_get_filename (manager, account, chat_id, chatroom);
159         basedir = g_path_get_dirname (filename);
160         if (!g_file_test (basedir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
161                 empathy_debug (DEBUG_DOMAIN, "Creating directory:'%s'", basedir);
162
163                 g_mkdir_with_parents (basedir, LOG_DIR_CREATE_MODE);
164         }
165         g_free (basedir);
166
167         empathy_debug (DEBUG_DOMAIN, "Adding message: '%s' to file: '%s'",
168                       body_str, filename);
169
170         if (!g_file_test (filename, G_FILE_TEST_EXISTS)) {
171                 file = g_fopen (filename, "w+");
172                 if (file) {
173                         g_fprintf (file, LOG_HEADER);
174                 }
175                 g_chmod (filename, LOG_FILE_CREATE_MODE);
176         } else {
177                 file = g_fopen (filename, "r+");
178                 if (file) {
179                         fseek (file, - strlen (LOG_FOOTER), SEEK_END);
180                 }
181         }
182
183         body = g_markup_escape_text (body_str, -1);
184         timestamp = log_manager_get_timestamp_from_message (message);
185
186         str = empathy_contact_get_name (sender);
187         contact_name = g_markup_escape_text (str, -1);
188
189         str = empathy_contact_get_id (sender);
190         contact_id = g_markup_escape_text (str, -1);
191
192         g_fprintf (file,
193                    "<message time='%s' id='%s' name='%s' isuser='%s'>%s</message>\n" LOG_FOOTER,
194                    timestamp,
195                    contact_id,
196                    contact_name,
197                    empathy_contact_is_user (sender) ? "true" : "false",
198                    body);
199
200         fclose (file);
201         g_free (filename);
202         g_free (contact_id);
203         g_free (contact_name);
204         g_free (timestamp);
205         g_free (body);
206 }
207
208 gboolean
209 empathy_log_manager_exists (EmpathyLogManager *manager,
210                             McAccount         *account,
211                             const gchar       *chat_id,
212                             gboolean           chatroom)
213 {
214         gchar    *dir;
215         gboolean  exists;
216
217         dir = log_manager_get_dir (manager, account, chat_id, chatroom);
218         exists = g_file_test (dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR);
219         g_free (dir);
220
221         return exists;
222 }
223
224 GList *
225 empathy_log_manager_get_dates (EmpathyLogManager *manager,
226                                McAccount         *account,
227                                const gchar       *chat_id,
228                                gboolean           chatroom)
229 {
230         GList       *dates = NULL;
231         gchar       *date;
232         gchar       *directory;
233         GDir        *dir;
234         const gchar *filename;
235         const gchar *p;
236
237         g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), NULL);
238         g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
239         g_return_val_if_fail (chat_id != NULL, NULL);
240
241         directory = log_manager_get_dir (manager, account, chat_id, chatroom);
242         dir = g_dir_open (directory, 0, NULL);
243         if (!dir) {
244                 empathy_debug (DEBUG_DOMAIN, "Could not open directory:'%s'", directory);
245                 g_free (directory);
246                 return NULL;
247         }
248
249         empathy_debug (DEBUG_DOMAIN, "Collating a list of dates in:'%s'", directory);
250
251         while ((filename = g_dir_read_name (dir)) != NULL) {
252                 if (!g_str_has_suffix (filename, LOG_FILENAME_SUFFIX)) {
253                         continue;
254                 }
255
256                 p = strstr (filename, LOG_FILENAME_SUFFIX);
257                 date = g_strndup (filename, p - filename);
258                 if (!date) {
259                         continue;
260                 }
261
262                 dates = g_list_insert_sorted (dates, date, (GCompareFunc) strcmp);
263         }
264
265         g_free (directory);
266         g_dir_close (dir);
267
268         empathy_debug (DEBUG_DOMAIN, "Parsed %d dates", g_list_length (dates));
269
270         return dates;
271 }
272
273 GList *
274 empathy_log_manager_get_messages_for_file (EmpathyLogManager *manager,
275                                            const gchar       *filename)
276 {
277         GList               *messages = NULL;
278         xmlParserCtxtPtr     ctxt;
279         xmlDocPtr            doc;
280         xmlNodePtr           log_node;
281         xmlNodePtr           node;
282         EmpathyLogSearchHit *hit;
283         McAccount           *account;
284
285         g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), NULL);
286         g_return_val_if_fail (filename != NULL, NULL);
287
288         empathy_debug (DEBUG_DOMAIN, "Attempting to parse filename:'%s'...", filename);
289
290         if (!g_file_test (filename, G_FILE_TEST_EXISTS)) {
291                 empathy_debug (DEBUG_DOMAIN, "Filename:'%s' does not exist", filename);
292                 return NULL;
293         }
294
295         /* Get the account from the filename */
296         hit = log_manager_search_hit_new (manager, filename);
297         account = g_object_ref (hit->account);
298         log_manager_search_hit_free (hit);
299
300         /* Create parser. */
301         ctxt = xmlNewParserCtxt ();
302
303         /* Parse and validate the file. */
304         doc = xmlCtxtReadFile (ctxt, filename, NULL, 0);
305         if (!doc) {
306                 g_warning ("Failed to parse file:'%s'", filename);
307                 xmlFreeParserCtxt (ctxt);
308                 return NULL;
309         }
310
311         /* The root node, presets. */
312         log_node = xmlDocGetRootElement (doc);
313         if (!log_node) {
314                 xmlFreeDoc (doc);
315                 xmlFreeParserCtxt (ctxt);
316                 return NULL;
317         }
318
319         /* Now get the messages. */
320         for (node = log_node->children; node; node = node->next) {
321                 EmpathyMessage *message;
322                 EmpathyContact *sender;
323                 gchar         *time;
324                 EmpathyTime     t;
325                 gchar         *sender_id;
326                 gchar         *sender_name;
327                 gchar         *body;
328                 gchar         *is_user_str;
329                 gboolean       is_user = FALSE;
330
331                 if (strcmp (node->name, "message") != 0) {
332                         continue;
333                 }
334
335                 body = xmlNodeGetContent (node);
336                 time = xmlGetProp (node, "time");
337                 sender_id = xmlGetProp (node, "id");
338                 sender_name = xmlGetProp (node, "name");
339                 is_user_str = xmlGetProp (node, "isuser");
340
341                 if (is_user_str) {
342                         is_user = strcmp (is_user_str, "true") == 0;
343                 }
344
345                 t = empathy_time_parse (time);
346
347                 sender = empathy_contact_new_full (account, sender_id, sender_name);
348                 empathy_contact_set_is_user (sender, is_user);
349                 message = empathy_message_new (body);
350                 empathy_message_set_sender (message, sender);
351                 empathy_message_set_timestamp (message, t);
352
353                 messages = g_list_append (messages, message);
354
355                 g_object_unref (sender);
356                 xmlFree (time);
357                 xmlFree (sender_id);
358                 xmlFree (sender_name);
359                 xmlFree (body);
360         }
361
362         empathy_debug (DEBUG_DOMAIN, "Parsed %d messages", g_list_length (messages));
363
364         xmlFreeDoc (doc);
365         xmlFreeParserCtxt (ctxt);
366
367         return messages;
368 }
369
370 GList *
371 empathy_log_manager_get_messages_for_date (EmpathyLogManager *manager,
372                                            McAccount         *account,
373                                            const gchar       *chat_id,
374                                            gboolean           chatroom,
375                                            const gchar       *date)
376 {
377         gchar *filename;
378         GList *messages;
379
380         g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), NULL);
381         g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
382         g_return_val_if_fail (chat_id != NULL, NULL);
383
384         filename = log_manager_get_filename_for_date (manager, account, chat_id, chatroom, date);
385         messages = empathy_log_manager_get_messages_for_file (manager, filename);
386         g_free (filename);
387
388         return messages;
389 }
390
391 GList *
392 empathy_log_manager_get_last_messages (EmpathyLogManager *manager,
393                                        McAccount         *account,
394                                        const gchar       *chat_id,
395                                        gboolean           chatroom)
396 {
397         GList *messages = NULL;
398         GList *dates;
399         GList *l;
400
401         g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), NULL);
402         g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
403         g_return_val_if_fail (chat_id != NULL, NULL);
404
405         dates = empathy_log_manager_get_dates (manager, account, chat_id, chatroom);
406
407         l = g_list_last (dates);
408         if (l) {
409                 messages = empathy_log_manager_get_messages_for_date (manager,
410                                                                       account,
411                                                                       chat_id,
412                                                                       chatroom,
413                                                                       l->data);
414         }
415
416         g_list_foreach (dates, (GFunc) g_free, NULL);
417         g_list_free (dates);
418
419         return messages;
420 }
421
422 GList *
423 empathy_log_manager_get_chats (EmpathyLogManager *manager,
424                                McAccount         *account)
425 {
426         const gchar *basedir;
427         gchar       *dir;
428
429         basedir = log_manager_get_basedir (manager);
430         dir = g_build_filename (basedir,
431                                 mc_account_get_unique_name (account),
432                                 NULL);
433
434         return log_manager_get_chats (manager, dir, FALSE);
435 }
436
437 GList *
438 empathy_log_manager_search_new (EmpathyLogManager *manager,
439                                 const gchar       *text)
440 {
441         GList *files, *l;
442         GList *hits = NULL;
443         gchar *text_casefold;
444
445         g_return_val_if_fail (EMPATHY_IS_LOG_MANAGER (manager), NULL);
446         g_return_val_if_fail (!G_STR_EMPTY (text), NULL);
447
448         text_casefold = g_utf8_casefold (text, -1);
449
450         files = log_manager_get_all_files (manager, NULL);
451         empathy_debug (DEBUG_DOMAIN, "Found %d log files in total",
452                       g_list_length (files));
453
454         for (l = files; l; l = l->next) {
455                 gchar       *filename;
456                 GMappedFile *file;
457                 gsize        length;
458                 gchar       *contents;
459                 gchar       *contents_casefold;
460
461                 filename = l->data;
462
463                 file = g_mapped_file_new (filename, FALSE, NULL);
464                 if (!file) {
465                         continue;
466                 }
467
468                 length = g_mapped_file_get_length (file);
469                 contents = g_mapped_file_get_contents (file);
470                 contents_casefold = g_utf8_casefold (contents, length);
471
472                 g_mapped_file_free (file);
473
474                 if (strstr (contents_casefold, text_casefold)) {
475                         EmpathyLogSearchHit *hit;
476
477                         hit = log_manager_search_hit_new (manager, filename);
478
479                         if (hit) {
480                                 hits = g_list_prepend (hits, hit);
481                                 empathy_debug (DEBUG_DOMAIN, 
482                                               "Found text:'%s' in file:'%s' on date:'%s'...",
483                                               text, hit->filename, hit->date);
484                         }
485                 }
486
487                 g_free (contents_casefold);
488                 g_free (filename);
489         }
490         g_list_free (files);
491
492         g_free (text_casefold);
493
494         return hits;
495 }
496
497 void
498 empathy_log_manager_search_free (GList *hits)
499 {
500         GList *l;
501
502         for (l = hits; l; l = l->next) {
503                 log_manager_search_hit_free (l->data);
504         }
505         
506         g_list_free (hits);
507 }
508
509 /* Format is just date, 20061201. */
510 gchar *
511 empathy_log_manager_get_date_readable (const gchar *date)
512 {
513         EmpathyTime t;
514
515         t = empathy_time_parse (date);
516
517         return empathy_time_to_string_local (t, "%a %d %b %Y");
518 }
519
520 static const gchar *
521 log_manager_get_basedir (EmpathyLogManager *manager)
522 {
523         EmpathyLogManagerPriv *priv;    
524
525         priv = GET_PRIV (manager);
526
527         if (priv->basedir) {
528                 return priv->basedir;
529         }
530
531         priv->basedir = g_build_path (G_DIR_SEPARATOR_S,
532                                       g_get_home_dir (),
533                                       ".gnome2",
534                                       PACKAGE_NAME,
535                                       "logs",
536                                       NULL);
537
538         return priv->basedir;
539 }
540
541 static GList *
542 log_manager_get_all_files (EmpathyLogManager *manager,
543                            const gchar       *dir)
544 {
545         GDir        *gdir;
546         GList       *files = NULL;
547         const gchar *name;
548         
549         if (!dir) {
550                 dir = log_manager_get_basedir (manager);
551         }
552
553         gdir = g_dir_open (dir, 0, NULL);
554         if (!gdir) {
555                 return NULL;
556         }
557
558         while ((name = g_dir_read_name (gdir)) != NULL) {
559                 gchar *filename;
560
561                 filename = g_build_filename (dir, name, NULL);
562                 if (g_str_has_suffix (filename, LOG_FILENAME_SUFFIX)) {
563                         files = g_list_prepend (files, filename);
564                         continue;
565                 }
566
567                 if (g_file_test (filename, G_FILE_TEST_IS_DIR)) {
568                         /* Recursively get all log files */
569                         files = g_list_concat (files, log_manager_get_all_files (manager, filename));
570                 }
571                 g_free (filename);
572         }
573
574         g_dir_close (gdir);
575
576         return files;
577 }
578
579 static GList *
580 log_manager_get_chats (EmpathyLogManager *manager,
581                        const gchar       *dir,
582                        gboolean           is_chatroom)
583 {
584         GDir        *gdir;
585         GList       *hits = NULL;
586         const gchar *name;
587
588         gdir = g_dir_open (dir, 0, NULL);
589         if (!gdir) {
590                 return NULL;
591         }
592
593         while ((name = g_dir_read_name (gdir)) != NULL) {
594                 EmpathyLogSearchHit *hit;
595                 gchar *filename;
596
597                 filename = g_build_filename (dir, name, NULL);
598                 if (strcmp (name, LOG_DIR_CHATROOMS) == 0) {
599                         hits = g_list_concat (hits, log_manager_get_chats (manager, filename, TRUE));
600                         g_free (filename);
601                         continue;
602                 }
603
604                 hit = g_slice_new0 (EmpathyLogSearchHit);
605                 hit->chat_id = g_strdup (name);
606                 hit->is_chatroom = is_chatroom;
607
608                 hits = g_list_prepend (hits, hit);
609         }
610
611         g_dir_close (gdir);
612
613         return hits;
614 }
615
616 static gchar *
617 log_manager_get_dir (EmpathyLogManager *manager,
618                      McAccount         *account,
619                      const gchar       *chat_id,
620                      gboolean           chatroom)
621 {
622         const gchar *account_id;
623         gchar       *basedir;
624         gchar       *str;
625
626         account_id = mc_account_get_unique_name (account);
627         basedir = 
628         str = g_build_path (G_DIR_SEPARATOR_S,
629                             log_manager_get_basedir (manager),
630                             account_id,
631                             chat_id,
632                             NULL);
633
634         if (chatroom) {
635                 basedir = g_build_path (G_DIR_SEPARATOR_S,
636                                         str,
637                                         LOG_DIR_CHATROOMS,
638                                         NULL);
639                 g_free (str);
640         } else {
641                 basedir = str;
642         }
643
644         return basedir;
645 }
646
647 static gchar *
648 log_manager_get_filename (EmpathyLogManager *manager,
649                           McAccount         *account,
650                           const gchar       *chat_id,
651                           gboolean           chatroom)
652 {
653         gchar *basedir;
654         gchar *timestamp;
655         gchar *filename;
656
657         basedir = log_manager_get_dir (manager, account, chat_id, chatroom);
658         timestamp = log_manager_get_timestamp_filename ();
659         filename = g_build_filename (basedir, timestamp, NULL);
660
661         g_free (basedir);
662         g_free (timestamp);
663
664         return filename;
665 }
666
667 static gchar *
668 log_manager_get_filename_for_date (EmpathyLogManager *manager,
669                                    McAccount         *account,
670                                    const gchar       *chat_id,
671                                    gboolean           chatroom,
672                                    const gchar       *date)
673 {
674         gchar *basedir;
675         gchar *timestamp;
676         gchar *filename;
677
678         basedir = log_manager_get_dir (manager, account, chat_id, chatroom);
679         timestamp = g_strconcat (date, LOG_FILENAME_SUFFIX, NULL);
680         filename = g_build_filename (basedir, timestamp, NULL);
681
682         g_free (basedir);
683         g_free (timestamp);
684
685         return filename;
686 }
687
688 static gchar *
689 log_manager_get_timestamp_filename (void)
690 {
691         EmpathyTime  t;
692         gchar      *time_str;
693         gchar      *filename;
694
695         t = empathy_time_get_current ();
696         time_str = empathy_time_to_string_local (t, LOG_TIME_FORMAT);
697         filename = g_strconcat (time_str, LOG_FILENAME_SUFFIX, NULL);
698
699         g_free (time_str);
700
701         return filename;
702 }
703
704 static gchar *
705 log_manager_get_timestamp_from_message (EmpathyMessage *message)
706 {
707         EmpathyTime t;
708
709         t = empathy_message_get_timestamp (message);
710
711         /* We keep the timestamps in the messages as UTC. */
712         return empathy_time_to_string_utc (t, LOG_TIME_FORMAT_FULL);
713 }
714
715 static EmpathyLogSearchHit *
716 log_manager_search_hit_new (EmpathyLogManager *manager,
717                             const gchar       *filename)
718 {
719         EmpathyLogSearchHit  *hit;
720         const gchar          *account_name;
721         const gchar          *end;
722         gchar               **strv;
723         guint                 len;
724
725         if (!g_str_has_suffix (filename, LOG_FILENAME_SUFFIX)) {
726                 return NULL;
727         }
728
729         strv = g_strsplit (filename, G_DIR_SEPARATOR_S, -1);
730         len = g_strv_length (strv);
731
732         hit = g_slice_new0 (EmpathyLogSearchHit);
733
734         end = strstr (strv[len-1], LOG_FILENAME_SUFFIX);
735         hit->date = g_strndup (strv[len-1], end - strv[len-1]);
736         hit->chat_id = g_strdup (strv[len-2]);
737         hit->is_chatroom = (strcmp (strv[len-3], LOG_DIR_CHATROOMS) == 0);
738         if (hit->is_chatroom) {
739                 account_name = strv[len-4];
740         } else {
741                 account_name = strv[len-3];
742         }
743         hit->account = mc_account_lookup (account_name);
744         hit->filename = g_strdup (filename);
745
746         g_strfreev (strv);
747
748         return hit;
749 }
750
751 static void
752 log_manager_search_hit_free (EmpathyLogSearchHit *hit)
753 {
754         if (hit->account) {
755                 g_object_unref (hit->account);
756         }
757
758         g_free (hit->date);
759         g_free (hit->filename);
760         g_free (hit->chat_id);
761
762         g_slice_free (EmpathyLogSearchHit, hit);
763 }