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