aboutsummaryrefslogblamecommitdiffstats
path: root/camel/providers/MH/mh-summary.c
blob: 5a964696e05c6ab56c80c1e0b1a50cf45751f6e2 (plain) (tree)

































































































































































































































































































                                                                                                           
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/* 
 *
 * Copyright (C) 1999 Bertrand Guiheneuf <Bertrand.Guiheneuf@aful.org> .
 *
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU General Public License as 
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 */


#include <config.h> 

#include "mh-uid.h"
#include "camel-log.h"
#include "camel-stream.h"
#include "camel-stream-fs.h"
#include "camel-stream-buffered-fs.h"
#include "gmime-utils.h"
#include "mh-utils.h"

#include <sys/stat.h> 
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

void 
mh_generate_summary (CamelFolder *folder)
{
    CamelMhFolder *mh_folder = CAMEL_MH_FOLDER (folder);
    CamelFolderSummary *summary;
    CamelMessageInfo *message_info;
    CamelFolderInfo *subfolder_info;
    CamelStream *message_stream;
    guint file_number;
    gchar *message_fullpath;
    gchar *directory_path;
    GArray *header_array;
    MhUidCouple *uid_couple;
    Rfc822Header *cur_header;
    int i;
    int n_file;
    GArray *uid_array;

    CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::generate_summary entering \n");

    g_assert (folder);

    directory_path = mh_folder->directory_path;
    if (!directory_path) {
        CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::generate_summary folder has no directory path\n");
        return;
    }

    summary = camel_folder_summary_new ();
    folder->summary = summary;

    uid_array = mh_folder->uid_array;
    
    if (!uid_array) {
        CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::generate_summary "
                      "no uid list, that probably means there is "
                      "no message in this folder, exiting \n");
        return;
    }
    uid_couple = (MhUidCouple *)uid_array->data;

    for (n_file=0; n_file<uid_array->len; n_file++) {

        file_number = uid_couple->file_number;

        message_info = g_new0 (CamelMessageInfo, 1);
        message_info->uid = g_new0 (guchar, 17);
        strncpy (message_info->uid, uid_couple->uid, 16);


        message_fullpath = g_strdup_printf ("%s/%d", directory_path, file_number);
        message_stream = camel_stream_buffered_fs_new_with_name (message_fullpath, 
                                     CAMEL_STREAM_BUFFERED_FS_READ);
        if (!message_stream) {
            CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::generate_summary "
                          "could not open %d for reading\n", message_fullpath);
            g_free (message_fullpath);
            return;
        }
        g_free (message_fullpath);
        
        header_array = get_header_array_from_stream (message_stream);
        gtk_object_unref (GTK_OBJECT (message_stream));
        
        for (i=0; i<header_array->len; i++) {
            cur_header = (Rfc822Header *)header_array->data + i;
            if (!g_strcasecmp (cur_header->name, "subject")) {
                message_info->subject = cur_header->value;
                g_free (cur_header->name);
            } else if (!g_strcasecmp (cur_header->name, "sender")) {
                message_info->date = cur_header->value;
                g_free (cur_header->name);
            } else if (!g_strcasecmp (cur_header->name, "date")) {
                message_info->date = cur_header->value;
                g_free (cur_header->name);
            } else {
                g_free (cur_header->name);
                g_free (cur_header->value);
            }
        }       
        g_array_free (header_array, TRUE);

        summary->message_info_list = g_list_append (summary->message_info_list, message_info);

        /* next message in the uid list */
        uid_couple++;
    }   
    CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::generate_summary leaving \n");

}


void 
mh_save_summary (CamelMhFolder *mh_folder)
{
    GArray *uid_array;
    MhUidCouple *first_uid_couple;
    CamelFolderSummary *summary;
    GList *msg_info_list;
    CamelMessageInfo *msg_info;
    gchar *directory_path = mh_folder->directory_path;
    gchar *summary_file_path;
    gint fd;
    gint i;
    gint field_lgth;
    
    CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::save_summary entering \n");

    summary = CAMEL_FOLDER (mh_folder)->summary;
    if (!summary) return;
    
    summary_file_path = g_strdup_printf ("%s/%s", directory_path, ".camel-summary");
    CAMEL_LOG_FULL_DEBUG ("In the process of writing %s\n", summary_file_path);
    fd = open (summary_file_path, O_WRONLY | O_CREAT );
    
    if (!fd) {
        CAMEL_LOG_FULL_DEBUG ("could not open file %s for writing. Exiting.\n", summary_file_path);
        g_free (summary_file_path);
        return;
    }
    g_free (summary_file_path);

    msg_info_list = summary->message_info_list;
    while (msg_info_list) {
        msg_info = msg_info_list->data;
        /* write subject */
        field_lgth = msg_info->subject ? strlen (msg_info->subject) : 0;
        write (fd, &field_lgth, sizeof (gint));
        if (field_lgth)
            write (fd, msg_info->subject, field_lgth);

        /* write uid */
        field_lgth = msg_info->uid ? strlen (msg_info->uid) : 0;
        write (fd, &field_lgth, sizeof (gint));
        if (field_lgth)
            write (fd, msg_info->uid, field_lgth);

        /* write date */
        field_lgth = msg_info->date ? strlen (msg_info->date) : 0;
        write (fd, &field_lgth, sizeof (gint));
        if (field_lgth)
            write (fd, msg_info->date, field_lgth);

        /* write sender */
        field_lgth = msg_info->sender ? strlen (msg_info->sender) : 0;
        write (fd, &field_lgth, sizeof (gint));
        if (field_lgth)
            write (fd, msg_info->sender, field_lgth);

        msg_info_list = msg_info_list->next;
        
    }
            
    close (fd);

    CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::save_summary leaving \n");
        
}





gint
mh_load_summary (CamelMhFolder *mh_folder)
{
    GArray *uid_array;
    MhUidCouple *first_uid_couple;
    CamelFolderSummary *summary;
    CamelMessageInfo *msg_info;
    gchar *directory_path = mh_folder->directory_path;
    gchar *summary_file_path;
    gint fd;
    gint i;
    gint field_lgth;
    gboolean file_eof;
    gint stat_error;
    struct stat stat_buf;

    summary = CAMEL_FOLDER (mh_folder)->summary;
    if (summary) return 1; /* should we regenerate it ? */
    
    summary_file_path = g_strdup_printf ("%s/%s", directory_path, ".camel-summary");
    CAMEL_LOG_FULL_DEBUG ("In the process of reading %s\n", summary_file_path);
    fd = open (summary_file_path, O_RDONLY);
    /* tests if file exists */
    stat_error = stat (summary_file_path, &stat_buf);

    if (!((stat_error != -1) && S_ISREG (stat_buf.st_mode))) {      
        CAMEL_LOG_FULL_DEBUG ("could not open file %s for reading. Exiting.\n", summary_file_path);
        g_free (summary_file_path);
        return -1;
    }
    g_free (summary_file_path);
    
    for (;;)  {
        /* read subject */
        file_eof = (read (fd, &field_lgth, sizeof (gint)) <= 0);
        if (file_eof) break;
        
        
        /* allcate a summary if needed */
        if (!summary) 
            summary = camel_folder_summary_new ();
        /* allocate a message info struct */
        msg_info = g_new0 (CamelMessageInfo, 1);    
    
        if (!file_eof && (field_lgth > 0)) {            
            msg_info->subject = g_new0 (gchar, field_lgth + 1);
            read (fd, msg_info->subject, field_lgth);
        } else 
            msg_info->subject = NULL;
        
        /* read uid */
        if (!file_eof) file_eof = (read (fd, &field_lgth, sizeof (gint)) <= 0);
        if (!file_eof && (field_lgth > 0)) {        
            msg_info->uid = g_new0 (gchar, field_lgth + 1);
            read (fd, msg_info->uid, field_lgth);
        } else 
            msg_info->uid = NULL;
        
        /* read date */
        if (!file_eof) file_eof = (read (fd, &field_lgth, sizeof (gint)) <= 0);
        if (!file_eof && (field_lgth > 0)) {            
            msg_info->date = g_new0 (gchar, field_lgth + 1);
            read (fd, msg_info->date, field_lgth);
        } else 
            msg_info->date = NULL;
        
        /* read sender */
        if (!file_eof) file_eof = (read (fd, &field_lgth, sizeof (gint)) <= 0);
        if (!file_eof && (field_lgth > 0)) {            
            msg_info->sender = g_new0 (gchar, field_lgth + 1);
            read (fd, msg_info->sender, field_lgth);
        } else 
            msg_info->sender = NULL;

        summary->message_info_list = g_list_prepend (summary->message_info_list, 
                                 msg_info);
    }       
    
    CAMEL_FOLDER (mh_folder)->summary = summary;
            
    close (fd);
    return 1;
}