aboutsummaryrefslogblamecommitdiffstats
path: root/camel/providers/nntp/camel-nntp-summary.c
blob: dad88b6ca42e800e3e9a5942e18c2034596f0f16 (plain) (tree)


























                                                                           

















































































































































                                                                                                                       




































































                                                                                         










                                                                        


                   























                                                                                           


















































































                                                                                             










                                                                 





















                                                                              
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-nntp-utils.c : summary support for nntp groups. */

/* 
 * Author : Chris Toshok <toshok@helixcode.com> 
 *
 * Copyright (C) 2000 Helix Code .

 * 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 "camel-exception.h"
#include "camel-nntp-folder.h"
#include "camel-nntp-summary.h"
#include "md5-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>
#include <netinet/in.h>

static CamelFolderSummaryClass *parent_class = NULL;

static int count_messages (CamelFolderSummary *summary);
static int count_subfolders (CamelFolderSummary *summary);
static GPtrArray *get_subfolder_info (CamelFolderSummary *summary,
                      int first, int count);
static GPtrArray *get_message_info (CamelFolderSummary *summary,
                    int first, int count);
static void finalize (GtkObject *object);

static void
camel_nntp_summary_class_init (CamelNNTPSummaryClass *camel_nntp_summary_class)
{
    GtkObjectClass *gtk_object_class =
        GTK_OBJECT_CLASS (camel_nntp_summary_class);
    CamelFolderSummaryClass *camel_folder_summary_class =
        CAMEL_FOLDER_SUMMARY_CLASS (camel_nntp_summary_class);

    parent_class = gtk_type_class (camel_folder_summary_get_type ());

    /* virtual method override */
    camel_folder_summary_class->count_messages = count_messages;
    camel_folder_summary_class->count_subfolders = count_subfolders;
    camel_folder_summary_class->get_subfolder_info = get_subfolder_info;
    camel_folder_summary_class->get_message_info = get_message_info;

    gtk_object_class->finalize = finalize;
}


GtkType
camel_nntp_summary_get_type (void)
{
    static GtkType camel_nntp_summary_type = 0;

    if (!camel_nntp_summary_type) {
        GtkTypeInfo camel_nntp_summary_info =   
        {
            "CamelNNTPSummary",
            sizeof (CamelNNTPSummary),
            sizeof (CamelNNTPSummaryClass),
            (GtkClassInitFunc) camel_nntp_summary_class_init,
            (GtkObjectInitFunc) NULL,
                /* reserved_1 */ NULL,
                /* reserved_2 */ NULL,
            (GtkClassInitFunc) NULL,
        };

        camel_nntp_summary_type = gtk_type_unique (camel_folder_summary_get_type (), &camel_nntp_summary_info);
    }

    return camel_nntp_summary_type;
}

static void
finalize (GtkObject *object)
{
    CamelNNTPSummary *summary = CAMEL_NNTP_SUMMARY (object);
    CamelNNTPSummaryInformation *info;
    int i;

    for (i = 0; i < summary->message_info->len; i++) {
        info = &(((CamelNNTPSummaryInformation *)summary->message_info->data)[i]);
        g_free (info->headers.subject);
        g_free (info->headers.sender);
        g_free (info->headers.to);
        g_free (info->headers.sent_date);
        g_free (info->headers.received_date);
        g_free (info->headers.uid);
    }
    g_array_free (summary->message_info, TRUE);     

    GTK_OBJECT_CLASS (parent_class)->finalize (object);
}   

static int
count_messages (CamelFolderSummary *summary)
{
    return CAMEL_NNTP_SUMMARY (summary)->nb_message;
}

static int
count_subfolders (CamelFolderSummary *summary)
{
    return 0;
}

static GPtrArray *
get_subfolder_info (CamelFolderSummary *summary, int first, int count)
{
    return NULL;
}

static GPtrArray *
get_message_info (CamelFolderSummary *summary, int first, int count)
{
    CamelNNTPSummary *nntp_summary = CAMEL_NNTP_SUMMARY (summary);
    CamelNNTPSummaryInformation *info;
    GPtrArray *arr;

    /* XXX bounds check */

    arr = g_ptr_array_new ();
    for (; count; count--) {
        info = &((CamelNNTPSummaryInformation *)nntp_summary->message_info->data)[first++];
        g_ptr_array_add (arr, info);
    }

    return arr;
}

/**
 * camel_nntp_summary_save:
 * @summary: 
 * @filename: 
 * @ex: 
 * 
 * save the summary into a file 
 **/
void 
camel_nntp_summary_save (CamelNNTPSummary *summary, const gchar *filename,
             CamelException *ex)
{
    CamelNNTPSummaryInformation *msg_info;
    guint cur_msg;
    guint field_length;
    gint fd;
    gint write_result; /* XXX use this */
    guint32 data;

    fd = open (filename, O_WRONLY | O_CREAT | O_TRUNC,
           S_IRUSR | S_IWUSR);
    if (fd == -1) {
        camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION,
                      "could not create the nntp summary "
                      "file\n\t%s\nFull error is : %s\n",
                      filename,
                      strerror (errno));
        return;
    }

    /* We write the file out in network byte order, not because
     * that makes sense, but because it's easy.
     */

    data = htonl (CAMEL_NNTP_SUMMARY_VERSION);
    write (fd, &data, sizeof (data));

    data = htonl (summary->nb_message);
    write (fd, &data, sizeof (data));

    for (cur_msg = 0; cur_msg < summary->nb_message; cur_msg++) {
        msg_info = (CamelNNTPSummaryInformation *)
            (summary->message_info->data) + cur_msg;

        /* Write meta-info. */
        data = htonl (msg_info->size);
        write (fd, &data, sizeof (data));
        write (fd, &msg_info->status, 1);

        /* Write subject. */
        if (msg_info->headers.subject)
            field_length = strlen (msg_info->headers.subject);
        else
            field_length = 0;
        data = htonl (field_length);
        write (fd, &data, sizeof (data));
        if (msg_info->headers.subject)
            write (fd, msg_info->headers.subject, field_length);

        /* Write sender. */
        if (msg_info->headers.sender)
            field_length = strlen (msg_info->headers.sender);
        else
            field_length = 0;
        data = htonl (field_length);
        write (fd, &data, sizeof (data));
        if (msg_info->headers.sender)
            write (fd, msg_info->headers.sender, field_length);

        /* Write sent date. */
        if (msg_info->headers.sent_date)
            field_length = strlen (msg_info->headers.sent_date);
        else
            field_length = 0;
        data = htonl (field_length);
        write (fd, &data, sizeof (data));
        if (msg_info->headers.sent_date)
            write (fd, msg_info->headers.sent_date, field_length);

        /* Write received date. */
        if (msg_info->headers.received_date)
            field_length = strlen (msg_info->headers.received_date);
        else
            field_length = 0;
        data = htonl (field_length);
        write (fd, &data, sizeof (data));
        if (msg_info->headers.received_date)
            write (fd, msg_info->headers.received_date, field_length);

        /* Write uid date. */
        if (msg_info->headers.uid)
            field_length = strlen (msg_info->headers.uid);
        else
            field_length = 0;
        data = htonl (field_length);
        write (fd, &data, sizeof (data));
        if (msg_info->headers.uid)
            write (fd, msg_info->headers.uid, field_length);

    }

    close (fd);
}



/**
 * camel_nntp_summary_load:
 * @filename: 
 * @ex: 
 * 
 * load the summary from a file 
 * 
 * Return value: 
 **/
CamelNNTPSummary *
camel_nntp_summary_load (const gchar *newsgroup, const gchar *filename, CamelException *ex)
{
    CamelNNTPSummaryInformation *msg_info;
    guint cur_msg;
    guint field_length;
    gint fd;
    CamelNNTPSummary *summary;
    gint read_result;
    guint32 data;

    fd = open (filename, O_RDONLY);
    if (fd == -1) {
        camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION,
                      "could not open the nntp summary file\n"
                      "\t%s\nFull error is : %s\n",
                      filename, strerror (errno));
        return NULL;
    }

    /* Verify version number. */
    read (fd, &data, sizeof(data));
    data = ntohl (data);

    if (data != CAMEL_NNTP_SUMMARY_VERSION) {
        camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_SUMMARY_INVALID,
                      "This folder summary was written by "
                      "%s version of this software.",
                      data < CAMEL_NNTP_SUMMARY_VERSION ?
                      "an older" : "a newer");
        return NULL;
    }

    summary = CAMEL_NNTP_SUMMARY (gtk_object_new (camel_nntp_summary_get_type (), NULL));

    read (fd, &data, sizeof(data));
    summary->nb_message = ntohl (data);

    summary->message_info =
        g_array_new (FALSE, FALSE,
                 sizeof (CamelNNTPSummaryInformation));
    g_array_set_size (summary->message_info, summary->nb_message);

    for (cur_msg = 0; cur_msg < summary->nb_message; cur_msg++)  {
        msg_info = (CamelNNTPSummaryInformation *)
            (summary->message_info->data) + cur_msg;

        /* Read the meta-info. */
        read (fd, &data, sizeof(data));
        msg_info->size = ntohl (data);
        read (fd, &msg_info->status, 1);

        /* Read the subject. */
        read (fd, &field_length, sizeof (field_length));
        field_length = ntohl (field_length);
        if (field_length > 0) {         
            msg_info->headers.subject =
                g_new0 (gchar, field_length + 1);
            read (fd, msg_info->headers.subject, field_length);
        } else 
            msg_info->headers.subject = NULL;
        
        /* Read the sender. */
        read (fd, &field_length, sizeof (field_length));
        field_length = ntohl (field_length);
        if (field_length > 0) {         
            msg_info->headers.sender =
                g_new0 (gchar, field_length + 1);
            read (fd, msg_info->headers.sender, field_length);
        } else 
            msg_info->headers.sender = NULL;

        msg_info->headers.to = g_strdup (newsgroup);

        /* Read the sent date field. */
        read (fd, &field_length, sizeof (field_length));
        field_length = ntohl (field_length);
        if (field_length > 0) {         
            msg_info->headers.sent_date =
                g_new0 (gchar, field_length + 1);
            read (fd, msg_info->headers.sent_date, field_length);
        } else 
            msg_info->headers.sent_date = NULL;

        /* Read the received date field. */
        read (fd, &field_length, sizeof (field_length));
        field_length = ntohl (field_length);
        if (field_length > 0) {         
            msg_info->headers.received_date =
                g_new0 (gchar, field_length + 1);
            read (fd, msg_info->headers.received_date,
                  field_length);
        } else 
            msg_info->headers.received_date = NULL;

        /* Read the uid field. */
        read (fd, &field_length, sizeof (field_length));
        field_length = ntohl (field_length);
        if (field_length > 0) {         
            msg_info->headers.uid =
                g_new0 (gchar, field_length + 1);
            read (fd, msg_info->headers.uid,
                  field_length);
        } else 
            msg_info->headers.uid = NULL;
    }       

    close (fd);
    return summary;
}


/**
 * camel_nntp_summary_append_entries:
 * @summary: 
 * @entries: 
 * 
 * append an entry to a summary
 **/
void
camel_nntp_summary_append_entries (CamelNNTPSummary *summary, GArray *entries)
{

    summary->message_info = g_array_append_vals (summary->message_info,
                             entries->data,
                             entries->len);
}