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