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