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