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