[Commits] Makefile.am NONE 1.1.2.1 carray.c NONE 1.1.2.1 carray.h NONE 1.1.2.1 chash.c NONE 1.1.2.1 chash.h NONE 1.1.2.1 clist.c NONE 1.1.2.1 clist.h NONE 1.1.2.1 mailimf.c NONE 1.1.2.1 mailimf.h NONE 1.1.2.1 mailimf_types.c NONE 1.1.2.1 mailimf_types.h NONE 1.1.2.1 mailimf_types_helper.c NONE 1.1.2.1 mailimf_types_helper.h NONE 1.1.2.1 mailimf_write.c NONE 1.1.2.1 mailimf_write.h NONE 1.1.2.1 maillock.c NONE 1.1.2.1 maillock.h NONE 1.1.2.1 mailmbox.c NONE 1.1.2.1 mailmbox.h NONE 1.1.2.1 mailmbox_folder.c NONE 1.1.2.1 mailmbox_folder.h NONE 1.1.2.1 mailmbox_gtk.deps NONE 1.1.2.1 mailmbox_parse.c NONE 1.1.2.1 mailmbox_parse.h NONE 1.1.2.1 mailmbox_types.c NONE 1.1.2.1 mailmbox_types.h NONE 1.1.2.1 mmapstring.c NONE 1.1.2.1 mmapstring.h NONE 1.1.2.1 placeholder.txt 1.1.2.1 NONE plugin.c NONE 1.1.2.1 plugin_gtk.c NONE 1.1.2.1 plugin_gtk.h NONE 1.1.2.1

colin at claws-mail.org colin at claws-mail.org
Sun Feb 17 22:22:00 CET 2013


Update of /home/claws-mail/claws/src/plugins/mailmbox
In directory srv:/tmp/cvs-serv7104/src/plugins/mailmbox

Added Files:
      Tag: gtk2
	Makefile.am carray.c carray.h chash.c chash.h clist.c clist.h 
	mailimf.c mailimf.h mailimf_types.c mailimf_types.h 
	mailimf_types_helper.c mailimf_types_helper.h mailimf_write.c 
	mailimf_write.h maillock.c maillock.h mailmbox.c mailmbox.h 
	mailmbox_folder.c mailmbox_folder.h mailmbox_gtk.deps 
	mailmbox_parse.c mailmbox_parse.h mailmbox_types.c 
	mailmbox_types.h mmapstring.c mmapstring.h plugin.c 
	plugin_gtk.c plugin_gtk.h 
Removed Files:
      Tag: gtk2
	placeholder.txt 
Log Message:
2013-02-17 [colin]	3.9.0cvs75

	* src/plugins/Makefile.am
	* src/plugins/archive/Makefile.am
	* src/plugins/clamd/Makefile.am
	* src/plugins/clamd/clamav_plugin.c
	* src/plugins/clamd/clamav_plugin.h
	* src/plugins/clamd/clamav_plugin_gtk.c
	* src/plugins/clamd/placeholder.txt
	* src/plugins/clamd/libclamd/Makefile.am
	* src/plugins/clamd/libclamd/clamd-plugin.c
	* src/plugins/clamd/libclamd/clamd-plugin.h
	* src/plugins/fetchinfo/Makefile.am
	* src/plugins/fetchinfo/fetchinfo_plugin.c
	* src/plugins/fetchinfo/fetchinfo_plugin.h
	* src/plugins/fetchinfo/fetchinfo_plugin_gtk.c
	* src/plugins/fetchinfo/placeholder.txt
	* src/plugins/gdata/Makefile.am
	* src/plugins/gdata/cm_gdata_contacts.c
	* src/plugins/gdata/cm_gdata_contacts.h
	* src/plugins/gdata/cm_gdata_prefs.c
	* src/plugins/gdata/cm_gdata_prefs.h
	* src/plugins/gdata/gdata_plugin.c
	* src/plugins/gdata/gdata_plugin.h
	* src/plugins/gdata/placeholder.txt
	* src/plugins/geolocation/placeholder.txt
	* src/plugins/gtkhtml2_viewer/placeholder.txt
	* src/plugins/mailmbox/Makefile.am
	* src/plugins/mailmbox/carray.c
	* src/plugins/mailmbox/carray.h
	* src/plugins/mailmbox/chash.c
	* src/plugins/mailmbox/chash.h
	* src/plugins/mailmbox/clist.c
	* src/plugins/mailmbox/clist.h
	* src/plugins/mailmbox/mailimf.c
	* src/plugins/mailmbox/mailimf.h
	* src/plugins/mailmbox/mailimf_types.c
	* src/plugins/mailmbox/mailimf_types.h
	* src/plugins/mailmbox/mailimf_types_helper.c
	* src/plugins/mailmbox/mailimf_types_helper.h
	* src/plugins/mailmbox/mailimf_write.c
	* src/plugins/mailmbox/mailimf_write.h
	* src/plugins/mailmbox/maillock.c
	* src/plugins/mailmbox/maillock.h
	* src/plugins/mailmbox/mailmbox.c
	* src/plugins/mailmbox/mailmbox.h
	* src/plugins/mailmbox/mailmbox_folder.c
	* src/plugins/mailmbox/mailmbox_folder.h
	* src/plugins/mailmbox/mailmbox_gtk.deps
	* src/plugins/mailmbox/mailmbox_parse.c
	* src/plugins/mailmbox/mailmbox_parse.h
	* src/plugins/mailmbox/mailmbox_types.c
	* src/plugins/mailmbox/mailmbox_types.h
	* src/plugins/mailmbox/mmapstring.c
	* src/plugins/mailmbox/mmapstring.h
	* src/plugins/mailmbox/placeholder.txt
	* src/plugins/mailmbox/plugin.c
	* src/plugins/mailmbox/plugin_gtk.c
	* src/plugins/mailmbox/plugin_gtk.h
	* src/plugins/newmail/Makefile.am
	* src/plugins/newmail/newmail.c
	* src/plugins/newmail/placeholder.txt
	* src/plugins/notification/Makefile.am
	* src/plugins/notification/claws.def
	* src/plugins/notification/notification_banner.c
	* src/plugins/notification/notification_banner.h
	* src/plugins/notification/notification_command.c
	* src/plugins/notification/notification_command.h
	* src/plugins/notification/notification_core.c
	* src/plugins/notification/notification_core.h
	* src/plugins/notification/notification_foldercheck.c
	* src/plugins/notification/notification_foldercheck.h
	* src/plugins/notification/notification_hotkeys.c
	* src/plugins/notification/notification_hotkeys.h
	* src/plugins/notification/notification_indicator.c
	* src/plugins/notification/notification_indicator.h
	* src/plugins/notification/notification_lcdproc.c
	* src/plugins/notification/notification_lcdproc.h
	* src/plugins/notification/notification_pixbuf.c
	* src/plugins/notification/notification_pixbuf.h
	* src/plugins/notification/notification_plugin.c
	* src/plugins/notification/notification_plugin.h
	* src/plugins/notification/notification_popup.c
	* src/plugins/notification/notification_popup.h
	* src/plugins/notification/notification_prefs.c
	* src/plugins/notification/notification_prefs.h
	* src/plugins/notification/notification_trayicon.c
	* src/plugins/notification/notification_trayicon.h
	* src/plugins/notification/placeholder.txt
	* src/plugins/notification/plugin.def
	* src/plugins/notification/raw_claws_mail_logo_64x64.h
	* src/plugins/notification/version.rc
	* src/plugins/pdf_viewer/Makefile.am
	* src/plugins/pdf_viewer/doc_index.xpm
	* src/plugins/pdf_viewer/doc_index_close.xpm
	* src/plugins/pdf_viewer/doc_info.xpm
	* src/plugins/pdf_viewer/first_arrow.xpm
	* src/plugins/pdf_viewer/last_arrow.xpm
	* src/plugins/pdf_viewer/left_arrow.xpm
	* src/plugins/pdf_viewer/placeholder.txt
	* src/plugins/pdf_viewer/poppler_viewer.c
	* src/plugins/pdf_viewer/poppler_viewer.h
	* src/plugins/pdf_viewer/right_arrow.xpm
	* src/plugins/pdf_viewer/rotate_left.xpm
	* src/plugins/pdf_viewer/rotate_right.xpm
	* src/plugins/pdf_viewer/zoom_fit.xpm
	* src/plugins/pdf_viewer/zoom_in.xpm
	* src/plugins/pdf_viewer/zoom_out.xpm
	* src/plugins/pdf_viewer/zoom_width.xpm
	* src/plugins/perl/Makefile.am
	* src/plugins/perl/perl_gtk.c
	* src/plugins/perl/perl_gtk.h
	* src/plugins/perl/perl_plugin.c
	* src/plugins/perl/perl_plugin.h
	* src/plugins/perl/placeholder.txt
	* src/plugins/python/Makefile.am
	* src/plugins/python/clawsmailmodule.c
	* src/plugins/python/clawsmailmodule.h
	* src/plugins/python/composewindowtype.c
	* src/plugins/python/composewindowtype.h
	* src/plugins/python/foldertype.c
	* src/plugins/python/foldertype.h
	* src/plugins/python/messageinfotype.c
	* src/plugins/python/messageinfotype.h
	* src/plugins/python/nodetype.c
	* src/plugins/python/nodetype.h
	* src/plugins/python/placeholder.txt
	* src/plugins/python/python-hooks.c
	* src/plugins/python/python-hooks.h
	* src/plugins/python/python-shell.c
	* src/plugins/python/python-shell.h
	* src/plugins/python/python_plugin.c
	* src/plugins/vcalendar/Makefile.in
		Add some plugins (clamd, fetchinfo, gdata, mailmbox, newmail,
		notification, pdf_viewer, perl, python). Notification not yet
		enabled because it has too much autoconf switches for my taste.

--- NEW FILE: mailimf_types.h ---
/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001 - 2003 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */


/*
 * $Id: mailimf_types.h,v 1.1.2.1 2013-02-17 21:21:57 colin Exp $
 */

#ifndef MAILIMF_TYPES_H

#define MAILIMF_TYPES_H

#ifdef __cplusplus
extern "C" {
#endif

#include "clist.h"
#include <sys/types.h>

/*
  IMPORTANT NOTE:
  
  All allocation functions will take as argument allocated data
  and will store these data in the structure they will allocate.
  Data should be persistant during all the use of the structure
  and will be freed by the free function of the structure

  allocation functions will return NULL on failure
*/

/*
  mailimf_date_time is a date
  
  - day is the day of month (1 to 31)

  - month (1 to 12)

  - year (4 digits)

  - hour (0 to 23)

  - min (0 to 59)

  - sec (0 to 59)

  - zone (this is the decimal value that we can read, for example:
    for "-0200", the value is -200)
*/

struct mailimf_date_time {
  int dt_day;
  int dt_month;
  int dt_year;
  int dt_hour;
  int dt_min;
  int dt_sec;
  int dt_zone;
};

struct mailimf_date_time *
mailimf_date_time_new(int dt_day, int dt_month, int dt_year,
    int dt_hour, int dt_min, int dt_sec, int dt_zone);

void mailimf_date_time_free(struct mailimf_date_time * date_time);



/* this is the type of address */

enum {
  MAILIMF_ADDRESS_ERROR,   /* on parse error */
  MAILIMF_ADDRESS_MAILBOX, /* if this is a mailbox (mailbox at domain) */
  MAILIMF_ADDRESS_GROUP,   /* if this is a group
                              (group_name: address1 at domain1,
                                  address2 at domain2; ) */
};

/*
  mailimf_address is an address

  - type can be MAILIMF_ADDRESS_MAILBOX or MAILIMF_ADDRESS_GROUP

  - mailbox is a mailbox if type is MAILIMF_ADDRESS_MAILBOX

  - group is a group if type is MAILIMF_ADDRESS_GROUP
*/

struct mailimf_address {
  int ad_type;
  union {
    struct mailimf_mailbox * ad_mailbox; /* can be NULL */
    struct mailimf_group * ad_group;     /* can be NULL */
  } ad_data;
};


struct mailimf_address *
mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox,
    struct mailimf_group * ad_group);

void mailimf_address_free(struct mailimf_address * address);



/*
  mailimf_mailbox is a mailbox

  - display_name is the name that will be displayed for this mailbox,
    for example 'name' in '"name" <mailbox at domain>,
    should be allocated with malloc()
  
  - addr_spec is the mailbox, for example 'mailbox at domain'
    in '"name" <mailbox at domain>, should be allocated with malloc()
*/

struct mailimf_mailbox {
  char * mb_display_name; /* can be NULL */
  char * mb_addr_spec;    /* != NULL */
};

struct mailimf_mailbox *
mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec);

void mailimf_mailbox_free(struct mailimf_mailbox * mailbox);



/*
  mailimf_group is a group

  - display_name is the name that will be displayed for this group,
    for example 'group_name' in
    'group_name: address1 at domain1, address2 at domain2;', should be allocated
    with malloc()

  - mb_list is a list of mailboxes
*/

struct mailimf_group {
  char * grp_display_name; /* != NULL */
  struct mailimf_mailbox_list * grp_mb_list; /* can be NULL */
};

struct mailimf_group *
mailimf_group_new(char * grp_display_name,
    struct mailimf_mailbox_list * grp_mb_list);

void mailimf_group_free(struct mailimf_group * group);



/*
  mailimf_mailbox_list is a list of mailboxes

  - list is a list of mailboxes
*/

struct mailimf_mailbox_list {
  clist * mb_list; /* list of (struct mailimf_mailbox *) */
     /* != NULL */
};

struct mailimf_mailbox_list *
mailimf_mailbox_list_new(clist * mb_list);

void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list);



/*
  mailimf_address_list is a list of addresses

  - list is a list of addresses
*/

struct mailimf_address_list {
  clist * ad_list; /* list of (struct mailimf_address *) */
     /* != NULL */
};

struct mailimf_address_list *
mailimf_address_list_new(clist * ad_list);

void mailimf_address_list_free(struct mailimf_address_list * addr_list);





/*
  mailimf_body is the text part of a message
  
  - text is the beginning of the text part, it is a substring
    of an other string

  - size is the size of the text part
*/

struct mailimf_body {
  const char * bd_text; /* != NULL */
  size_t bd_size;
};

struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size);

void mailimf_body_free(struct mailimf_body * body);




/*
  mailimf_message is the content of the message

  - fields is the header fields of the message
  
  - body is the text part of the message
*/

struct mailimf_message {
  struct mailimf_fields * msg_fields; /* != NULL */
  struct mailimf_body * msg_body;     /* != NULL */
};

struct mailimf_message *
mailimf_message_new(struct mailimf_fields * msg_fields,
    struct mailimf_body * msg_body);

void mailimf_message_free(struct mailimf_message * message);




/*
  mailimf_fields is a list of header fields

  - list is a list of header fields
*/

struct mailimf_fields {
  clist * fld_list; /* list of (struct mailimf_field *) */
                /* != NULL */
};

struct mailimf_fields * mailimf_fields_new(clist * fld_list);

void mailimf_fields_free(struct mailimf_fields * fields);



/* this is a type of field */

enum {
  MAILIMF_FIELD_NONE,           /* on parse error */
  MAILIMF_FIELD_RETURN_PATH,    /* Return-Path */
  MAILIMF_FIELD_RESENT_DATE,    /* Resent-Date */
  MAILIMF_FIELD_RESENT_FROM,    /* Resent-From */
  MAILIMF_FIELD_RESENT_SENDER,  /* Resent-Sender */
  MAILIMF_FIELD_RESENT_TO,      /* Resent-To */
  MAILIMF_FIELD_RESENT_CC,      /* Resent-Cc */
  MAILIMF_FIELD_RESENT_BCC,     /* Resent-Bcc */
  MAILIMF_FIELD_RESENT_MSG_ID,  /* Resent-Message-ID */
  MAILIMF_FIELD_ORIG_DATE,      /* Date */
  MAILIMF_FIELD_FROM,           /* From */
  MAILIMF_FIELD_SENDER,         /* Sender */
  MAILIMF_FIELD_REPLY_TO,       /* Reply-To */
  MAILIMF_FIELD_TO,             /* To */
  MAILIMF_FIELD_CC,             /* Cc */
  MAILIMF_FIELD_BCC,            /* Bcc */
  MAILIMF_FIELD_MESSAGE_ID,     /* Message-ID */
  MAILIMF_FIELD_IN_REPLY_TO,    /* In-Reply-To */
  MAILIMF_FIELD_REFERENCES,     /* References */
  MAILIMF_FIELD_SUBJECT,        /* Subject */
  MAILIMF_FIELD_COMMENTS,       /* Comments */
  MAILIMF_FIELD_KEYWORDS,       /* Keywords */
  MAILIMF_FIELD_OPTIONAL_FIELD, /* other field */
};

/*
  mailimf_field is a field

  - type is the type of the field

  - return_path is the parsed content of the Return-Path field if type is
    MAILIMF_FIELD_RETURN_PATH

  - resent_date is the parsed content of the Resent-Date field if type is
    MAILIMF_FIELD_RESENT_DATE

  - resent_from is the parsed content of the Resent-From field

  - resent_sender is the parsed content of the Resent-Sender field

  - resent_to is the parsed content of the Resent-To field

  - resent_cc is the parsed content of the Resent-Cc field

  - resent_bcc is the parsed content of the Resent-Bcc field

  - resent_msg_id is the parsed content of the Resent-Message-ID field

  - orig_date is the parsed content of the Date field

  - from is the parsed content of the From field

  - sender is the parsed content of the Sender field

  - reply_to is the parsed content of the Reply-To field

  - to is the parsed content of the To field

  - cc is the parsed content of the Cc field

  - bcc is the parsed content of the Bcc field

  - message_id is the parsed content of the Message-ID field

  - in_reply_to is the parsed content of the In-Reply-To field

  - references is the parsed content of the References field

  - subject is the content of the Subject field

  - comments is the content of the Comments field

  - keywords is the parsed content of the Keywords field

  - optional_field is an other field and is not parsed
*/

#define LIBETPAN_MAILIMF_FIELD_UNION

struct mailimf_field {
  int fld_type;
  union {
    struct mailimf_return * fld_return_path;              /* can be NULL */
    struct mailimf_orig_date * fld_resent_date;    /* can be NULL */
    struct mailimf_from * fld_resent_from;         /* can be NULL */
    struct mailimf_sender * fld_resent_sender;     /* can be NULL */
    struct mailimf_to * fld_resent_to;             /* can be NULL */
    struct mailimf_cc * fld_resent_cc;             /* can be NULL */
    struct mailimf_bcc * fld_resent_bcc;           /* can be NULL */
    struct mailimf_message_id * fld_resent_msg_id; /* can be NULL */
    struct mailimf_orig_date * fld_orig_date;             /* can be NULL */
    struct mailimf_from * fld_from;                       /* can be NULL */
    struct mailimf_sender * fld_sender;                   /* can be NULL */
    struct mailimf_reply_to * fld_reply_to;               /* can be NULL */
    struct mailimf_to * fld_to;                           /* can be NULL */
    struct mailimf_cc * fld_cc;                           /* can be NULL */
    struct mailimf_bcc * fld_bcc;                         /* can be NULL */
    struct mailimf_message_id * fld_message_id;           /* can be NULL */
    struct mailimf_in_reply_to * fld_in_reply_to;         /* can be NULL */
    struct mailimf_references * fld_references;           /* can be NULL */
    struct mailimf_subject * fld_subject;                 /* can be NULL */
    struct mailimf_comments * fld_comments;               /* can be NULL */
    struct mailimf_keywords * fld_keywords;               /* can be NULL */
    struct mailimf_optional_field * fld_optional_field;   /* can be NULL */
  } fld_data;
};

struct mailimf_field *
mailimf_field_new(int fld_type,
    struct mailimf_return * fld_return_path,
    struct mailimf_orig_date * fld_resent_date,
    struct mailimf_from * fld_resent_from,
    struct mailimf_sender * fld_resent_sender,
    struct mailimf_to * fld_resent_to,
    struct mailimf_cc * fld_resent_cc,
    struct mailimf_bcc * fld_resent_bcc,
    struct mailimf_message_id * fld_resent_msg_id,
    struct mailimf_orig_date * fld_orig_date,
    struct mailimf_from * fld_from,
    struct mailimf_sender * fld_sender,
    struct mailimf_reply_to * fld_reply_to,
    struct mailimf_to * fld_to,
    struct mailimf_cc * fld_cc,
    struct mailimf_bcc * fld_bcc,
    struct mailimf_message_id * fld_message_id,
    struct mailimf_in_reply_to * fld_in_reply_to,
    struct mailimf_references * fld_references,
    struct mailimf_subject * fld_subject,
    struct mailimf_comments * fld_comments,
    struct mailimf_keywords * fld_keywords,
    struct mailimf_optional_field * fld_optional_field);

void mailimf_field_free(struct mailimf_field * field);



/*
  mailimf_orig_date is the parsed Date field

  - date_time is the parsed date
*/

struct mailimf_orig_date {
  struct mailimf_date_time * dt_date_time; /* != NULL */
};

struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time *
    dt_date_time);

void mailimf_orig_date_free(struct mailimf_orig_date * orig_date);




/*
  mailimf_from is the parsed From field

  - mb_list is the parsed mailbox list
*/

struct mailimf_from {
  struct mailimf_mailbox_list * frm_mb_list; /* != NULL */
};

struct mailimf_from *
mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list);

void mailimf_from_free(struct mailimf_from * from);



/*
  mailimf_sender is the parsed Sender field

  - mb is the parsed mailbox
*/

struct mailimf_sender {
  struct mailimf_mailbox * snd_mb; /* != NULL */
};

struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb);

void mailimf_sender_free(struct mailimf_sender * sender);




/*
  mailimf_reply_to is the parsed Reply-To field

  - addr_list is the parsed address list
 */

struct mailimf_reply_to {
  struct mailimf_address_list * rt_addr_list; /* != NULL */
};

struct mailimf_reply_to *
mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list);

void mailimf_reply_to_free(struct mailimf_reply_to * reply_to);




/*
  mailimf_to is the parsed To field
  
  - addr_list is the parsed address list
*/

struct mailimf_to {
  struct mailimf_address_list * to_addr_list; /* != NULL */
};

struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list);

void mailimf_to_free(struct mailimf_to * to);




/*
  mailimf_cc is the parsed Cc field

  - addr_list is the parsed addres list
*/

struct mailimf_cc {
  struct mailimf_address_list * cc_addr_list; /* != NULL */
};

struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list);

void mailimf_cc_free(struct mailimf_cc * cc);




/*
  mailimf_bcc is the parsed Bcc field

  - addr_list is the parsed addres list
*/

struct mailimf_bcc {
  struct mailimf_address_list * bcc_addr_list; /* can be NULL */
};

struct mailimf_bcc *
mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list);

void mailimf_bcc_free(struct mailimf_bcc * bcc);



/*
  mailimf_message_id is the parsed Message-ID field
  
  - value is the message identifier
*/

struct mailimf_message_id {
  char * mid_value; /* != NULL */
};

struct mailimf_message_id * mailimf_message_id_new(char * mid_value);

void mailimf_message_id_free(struct mailimf_message_id * message_id);




/*
  mailimf_in_reply_to is the parsed In-Reply-To field

  - msg_id_list is the list of message identifers
*/

struct mailimf_in_reply_to {
  clist * mid_list; /* list of (char *) */
       /* != NULL */
};

struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list);

void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to);



/*
  mailimf_references is the parsed References field

  - msg_id_list is the list of message identifiers
 */

struct mailimf_references {
  clist * mid_list; /* list of (char *) */
       /* != NULL */
};

struct mailimf_references * mailimf_references_new(clist * mid_list);

void mailimf_references_free(struct mailimf_references * references);



/*
  mailimf_subject is the parsed Subject field
  
  - value is the value of the field
*/

struct mailimf_subject {
  char * sbj_value; /* != NULL */
};

struct mailimf_subject * mailimf_subject_new(char * sbj_value);

void mailimf_subject_free(struct mailimf_subject * subject);


/*
  mailimf_comments is the parsed Comments field

  - value is the value of the field
*/

struct mailimf_comments {
  char * cm_value; /* != NULL */
};

struct mailimf_comments * mailimf_comments_new(char * cm_value);

void mailimf_comments_free(struct mailimf_comments * comments);


/*
  mailimf_keywords is the parsed Keywords field

  - list is the list of keywords
*/

struct mailimf_keywords {
  clist * kw_list; /* list of (char *) */
       /* != NULL */
};

struct mailimf_keywords * mailimf_keywords_new(clist * kw_list);

void mailimf_keywords_free(struct mailimf_keywords * keywords);


/*
  mailimf_return is the parsed Return-Path field

  - path is the parsed value of Return-Path
*/

struct mailimf_return {
  struct mailimf_path * ret_path; /* != NULL */
};

struct mailimf_return *
mailimf_return_new(struct mailimf_path * ret_path);

void mailimf_return_free(struct mailimf_return * return_path);


/*
  mailimf_path is the parsed value of Return-Path

  - addr_spec is a mailbox
*/

struct mailimf_path {
  char * pt_addr_spec; /* can be NULL */
};

struct mailimf_path * mailimf_path_new(char * pt_addr_spec);

void mailimf_path_free(struct mailimf_path * path);


/*
  mailimf_optional_field is a non-parsed field

  - name is the name of the field

  - value is the value of the field
*/

struct mailimf_optional_field {
  char * fld_name;  /* != NULL */
  char * fld_value; /* != NULL */
};

struct mailimf_optional_field *
mailimf_optional_field_new(char * fld_name, char * fld_value);

void mailimf_optional_field_free(struct mailimf_optional_field * opt_field);


/*
  mailimf_fields is the native structure that IMF module will use,
  this module will provide an easier structure to use when parsing fields.

  mailimf_single_fields is an easier structure to get parsed fields,
  rather than iteration over the list of fields

  - orig_date is the parsed "Date" field

  - from is the parsed "From" field
  
  - sender is the parsed "Sender "field

  - reply_to is the parsed "Reply-To" field
  
  - to is the parsed "To" field

  - cc is the parsed "Cc" field

  - bcc is the parsed "Bcc" field

  - message_id is the parsed "Message-ID" field

  - in_reply_to is the parsed "In-Reply-To" field

  - references is the parsed "References" field

  - subject is the parsed "Subject" field
  
  - comments is the parsed "Comments" field

  - keywords is the parsed "Keywords" field
*/

struct mailimf_single_fields {
  struct mailimf_orig_date * fld_orig_date;      /* can be NULL */
  struct mailimf_from * fld_from;                /* can be NULL */
  struct mailimf_sender * fld_sender;            /* can be NULL */
  struct mailimf_reply_to * fld_reply_to;        /* can be NULL */
  struct mailimf_to * fld_to;                    /* can be NULL */
  struct mailimf_cc * fld_cc;                    /* can be NULL */
  struct mailimf_bcc * fld_bcc;                  /* can be NULL */
  struct mailimf_message_id * fld_message_id;    /* can be NULL */
  struct mailimf_in_reply_to * fld_in_reply_to;  /* can be NULL */
  struct mailimf_references * fld_references;    /* can be NULL */
  struct mailimf_subject * fld_subject;          /* can be NULL */
  struct mailimf_comments * fld_comments;        /* can be NULL */
  struct mailimf_keywords * fld_keywords;        /* can be NULL */
};






/* internal use */

void mailimf_atom_free(char * atom);

void mailimf_dot_atom_free(char * dot_atom);

void mailimf_dot_atom_text_free(char * dot_atom);

void mailimf_quoted_string_free(char * quoted_string);

void mailimf_word_free(char * word);

void mailimf_phrase_free(char * phrase);

void mailimf_unstructured_free(char * unstructured);

void mailimf_angle_addr_free(char * angle_addr);

void mailimf_display_name_free(char * display_name);

void mailimf_addr_spec_free(char * addr_spec);

void mailimf_local_part_free(char * local_part);

void mailimf_domain_free(char * domain);

void mailimf_domain_literal_free(char * domain);

void mailimf_msg_id_free(char * msg_id);

void mailimf_id_left_free(char * id_left);

void mailimf_id_right_free(char * id_right);

void mailimf_no_fold_quote_free(char * nfq);

void mailimf_no_fold_literal_free(char * nfl);

void mailimf_field_name_free(char * field_name);



/* these are the possible returned error codes */

enum {
  MAILIMF_NO_ERROR = 0,
  MAILIMF_ERROR_PARSE,
  MAILIMF_ERROR_MEMORY,
  MAILIMF_ERROR_INVAL,
  MAILIMF_ERROR_FILE,
};


#ifdef __cplusplus
}
#endif

#endif

--- NEW FILE: mailmbox_types.c ---
/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001, 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: mailmbox_types.c,v 1.1.2.1 2013-02-17 21:21:58 colin Exp $
 */

#include "mailmbox_types.h"

#include <string.h>
#include <stdlib.h>

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif

/* *********************************************************************** */

int claws_mailmbox_msg_info_update(struct claws_mailmbox_folder * folder,
			     size_t msg_start, size_t msg_start_len,
			     size_t msg_headers, size_t msg_headers_len,
			     size_t msg_body, size_t msg_body_len,
			     size_t msg_size, size_t msg_padding,
			     uint32_t msg_uid)
{
  struct claws_mailmbox_msg_info * info;
  int res;
  chashdatum key;
  chashdatum data;
  int r;
  
  key.data = &msg_uid;
  key.len = sizeof(msg_uid);
  r = chash_get(folder->mb_hash, &key, &data);
  if (r < 0) {
    unsigned int index;

    info = claws_mailmbox_msg_info_new(msg_start, msg_start_len,
        msg_headers, msg_headers_len,
        msg_body, msg_body_len, msg_size, msg_padding, msg_uid);
    if (info == NULL) {
      res = MAILMBOX_ERROR_MEMORY;
      goto err;
    }

    r = carray_add(folder->mb_tab, info, &index);
    if (r < 0) {
      claws_mailmbox_msg_info_free(info);
      res = MAILMBOX_ERROR_MEMORY;
      goto err;
    }

    if (msg_uid != 0) {
      chashdatum key;
      chashdatum data;
      
      key.data = &msg_uid;
      key.len = sizeof(msg_uid);
      data.data = info;
      data.len = 0;
      
      r = chash_set(folder->mb_hash, &key, &data, NULL);
      if (r < 0) {
	claws_mailmbox_msg_info_free(info);
	carray_delete(folder->mb_tab, index);
	res = MAILMBOX_ERROR_MEMORY;
	goto err;
      }
    }
    
    info->msg_index = index;
  }
  else {
    info = data.data;
    
    info->msg_start = msg_start;
    info->msg_start_len = msg_start_len;
    info->msg_headers = msg_headers;
    info->msg_headers_len = msg_headers_len;
    info->msg_body = msg_body;
    info->msg_body_len = msg_body_len;
    info->msg_size = msg_size;
    info->msg_padding = msg_padding;
  }

  return MAILMBOX_NO_ERROR;

 err:
  return res;
}


struct claws_mailmbox_msg_info *
claws_mailmbox_msg_info_new(size_t msg_start, size_t msg_start_len,
		      size_t msg_headers, size_t msg_headers_len,
		      size_t msg_body, size_t msg_body_len,
		      size_t msg_size, size_t msg_padding,
		      uint32_t msg_uid)
{
  struct claws_mailmbox_msg_info * info;

  info = malloc(sizeof(* info));
  if (info == NULL)
    return NULL;

  info->msg_index = 0;
  info->msg_uid = msg_uid;
  if (msg_uid != 0)
    info->msg_written_uid = TRUE;
  else
    info->msg_written_uid = FALSE;
  info->msg_deleted = FALSE;

  info->msg_start = msg_start;
  info->msg_start_len = msg_start_len;

  info->msg_headers = msg_headers;
  info->msg_headers_len = msg_headers_len;

  info->msg_body = msg_body;
  info->msg_body_len = msg_body_len;

  info->msg_size = msg_size;

  info->msg_padding = msg_padding;

  return info;
}

void claws_mailmbox_msg_info_free(struct claws_mailmbox_msg_info * info)
{
  free(info);
}


/* append info */

struct claws_mailmbox_append_info *
claws_mailmbox_append_info_new(const char * ai_message, size_t ai_size)
{
  struct claws_mailmbox_append_info * info;

  info = malloc(sizeof(* info));
  if (info == NULL)
    return NULL;

  info->ai_message = ai_message;
  info->ai_size = ai_size;

  return info;
}

void claws_mailmbox_append_info_free(struct claws_mailmbox_append_info * info)
{
  free(info);
}

struct claws_mailmbox_folder * claws_mailmbox_folder_new(const char * mb_filename)
{
  struct claws_mailmbox_folder * folder;

  folder = malloc(sizeof(* folder));
  if (folder == NULL)
    goto err;

  strncpy(folder->mb_filename, mb_filename, PATH_MAX);

  folder->mb_mtime = (time_t) -1;

  folder->mb_fd = -1;
  folder->mb_read_only = TRUE;
  folder->mb_no_uid = TRUE;

  folder->mb_changed = FALSE;
  folder->mb_deleted_count = 0;
  
  folder->mb_mapping = NULL;
  folder->mb_mapping_size = 0;

  folder->mb_written_uid = 0;
  folder->mb_max_uid = 0;

  folder->mb_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
  if (folder->mb_hash == NULL)
    goto free;
  
  folder->mb_tab = carray_new(128);
  if (folder->mb_tab == NULL)
    goto free_hash;

  return folder;

 free_hash:
  chash_free(folder->mb_hash);
 free:
  free(folder);
 err:
  return NULL;
}

void claws_mailmbox_folder_free(struct claws_mailmbox_folder * folder)
{
  unsigned int i;

  for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) {
    struct claws_mailmbox_msg_info * info;

    info = carray_get(folder->mb_tab, i);
    if (info != NULL)
      claws_mailmbox_msg_info_free(info);
  }

  carray_free(folder->mb_tab);
  
  chash_free(folder->mb_hash);

  free(folder);
}

--- NEW FILE: mailmbox_types.h ---
/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001, 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: mailmbox_types.h,v 1.1.2.1 2013-02-17 21:21:58 colin Exp $
 */

#ifndef MAILMBOX_TYPES_H

#define MAILMBOX_TYPES_H

#ifdef __cplusplus
extern "C" {
#endif

#include <sys/types.h>
#include <limits.h>

#include "mailimf.h"
#include "carray.h"
#include "chash.h"

enum {
  MAILMBOX_NO_ERROR = 0,
  MAILMBOX_ERROR_PARSE,
  MAILMBOX_ERROR_INVAL,
  MAILMBOX_ERROR_FILE_NOT_FOUND,
  MAILMBOX_ERROR_MEMORY,
  MAILMBOX_ERROR_TEMPORARY_FILE,
  MAILMBOX_ERROR_FILE,
  MAILMBOX_ERROR_MSG_NOT_FOUND,
  MAILMBOX_ERROR_READONLY,
};


struct claws_mailmbox_folder {
  char mb_filename[PATH_MAX];

  time_t mb_mtime;

  int mb_fd;
  int mb_read_only;
  int mb_no_uid;

  int mb_changed;
  unsigned int mb_deleted_count;
  
  char * mb_mapping;
  size_t mb_mapping_size;

  uint32_t mb_written_uid;
  uint32_t mb_max_uid;

  chash * mb_hash;
  carray * mb_tab;
};

struct claws_mailmbox_folder * claws_mailmbox_folder_new(const char * mb_filename);
void claws_mailmbox_folder_free(struct claws_mailmbox_folder * folder);


struct claws_mailmbox_msg_info {
  unsigned int msg_index;
  uint32_t msg_uid;
  int msg_written_uid;
  int msg_deleted;

  size_t msg_start;
  size_t msg_start_len;

  size_t msg_headers;
  size_t msg_headers_len;

  size_t msg_body;
  size_t msg_body_len;

  size_t msg_size;

  size_t msg_padding;
};


int claws_mailmbox_msg_info_update(struct claws_mailmbox_folder * folder,
			     size_t msg_start, size_t msg_start_len,
			     size_t msg_headers, size_t msg_headers_len,
			     size_t msg_body, size_t msg_body_len,
			     size_t msg_size, size_t msg_padding,
			     uint32_t msg_uid);

struct claws_mailmbox_msg_info *
claws_mailmbox_msg_info_new(size_t msg_start, size_t msg_start_len,
		      size_t msg_headers, size_t msg_headers_len,
		      size_t msg_body, size_t msg_body_len,
		      size_t msg_size, size_t msg_padding,
		      uint32_t msg_uid);

void claws_mailmbox_msg_info_free(struct claws_mailmbox_msg_info * info);

struct claws_mailmbox_append_info {
  const char * ai_message;
  size_t ai_size;
};

struct claws_mailmbox_append_info *
claws_mailmbox_append_info_new(const char * ai_message, size_t ai_size);

void claws_mailmbox_append_info_free(struct claws_mailmbox_append_info * info);

#ifdef __cplusplus
}
#endif

#endif

--- NEW FILE: mailimf_types.c ---
/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001, 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: mailimf_types.c,v 1.1.2.1 2013-02-17 21:21:57 colin Exp $
 */

#include "mailimf_types.h"
#include "mmapstring.h"
#include <stdlib.h>

void mailimf_atom_free(char * atom)
{
  free(atom);
}

void mailimf_dot_atom_free(char * dot_atom)
{
  free(dot_atom);
}

void mailimf_dot_atom_text_free(char * dot_atom)
{
  free(dot_atom);
}

void mailimf_quoted_string_free(char * quoted_string)
{
  free(quoted_string);
}

void mailimf_word_free(char * word)
{
  free(word);
}

void mailimf_phrase_free(char * phrase)
{
  free(phrase);
}

void mailimf_unstructured_free(char * unstructured)
{
  free(unstructured);
}


struct mailimf_date_time *
mailimf_date_time_new(int dt_day, int dt_month, int dt_year,
    int dt_hour, int dt_min, int dt_sec, int dt_zone)
{
  struct mailimf_date_time * date_time;

  date_time = malloc(sizeof(* date_time));
  if (date_time == NULL)
    return NULL;

  date_time->dt_day = dt_day;
  date_time->dt_month = dt_month;
  date_time->dt_year = dt_year;
  date_time->dt_hour = dt_hour;
  date_time->dt_min = dt_min;
  date_time->dt_sec = dt_sec;
  date_time->dt_zone = dt_zone;

  return date_time;
}


void mailimf_date_time_free(struct mailimf_date_time * date_time)
{
  free(date_time);
}




struct mailimf_address *
mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox,
    struct mailimf_group * ad_group)
{
  struct mailimf_address * address;

  address = malloc(sizeof(* address));
  if (address == NULL)
    return NULL;

  address->ad_type = ad_type;
  switch (ad_type) {
  case MAILIMF_ADDRESS_MAILBOX:
    address->ad_data.ad_mailbox = ad_mailbox;
    break;
  case MAILIMF_ADDRESS_GROUP:
    address->ad_data.ad_group = ad_group;
    break;
  }

  return address;
}

void mailimf_address_free(struct mailimf_address * address)
{
  switch (address->ad_type) {
  case MAILIMF_ADDRESS_MAILBOX:
    mailimf_mailbox_free(address->ad_data.ad_mailbox);
    break;
  case MAILIMF_ADDRESS_GROUP:
    mailimf_group_free(address->ad_data.ad_group);
  }
  free(address);
}

struct mailimf_mailbox *
mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec)
{
  struct mailimf_mailbox * mb;

  mb = malloc(sizeof(* mb));
  if (mb == NULL)
    return NULL;

  mb->mb_display_name = mb_display_name;
  mb->mb_addr_spec = mb_addr_spec;

  return mb;
}

void mailimf_mailbox_free(struct mailimf_mailbox * mailbox)
{
  if (mailbox->mb_display_name != NULL)
    mailimf_display_name_free(mailbox->mb_display_name);
  mailimf_addr_spec_free(mailbox->mb_addr_spec);
  free(mailbox);
}


void mailimf_angle_addr_free(char * angle_addr)
{
  free(angle_addr);
}


struct mailimf_group *
mailimf_group_new(char * grp_display_name,
    struct mailimf_mailbox_list * grp_mb_list)
{
  struct mailimf_group * group;

  group = malloc(sizeof(* group));
  if (group == NULL)
    return NULL;

  group->grp_display_name = grp_display_name;
  group->grp_mb_list = grp_mb_list;
  
  return group;
}

void mailimf_group_free(struct mailimf_group * group)
{
  if (group->grp_mb_list)
    mailimf_mailbox_list_free(group->grp_mb_list);
  mailimf_display_name_free(group->grp_display_name);
  free(group);
}

void mailimf_display_name_free(char * display_name)
{
  mailimf_phrase_free(display_name);
}


struct mailimf_mailbox_list *
mailimf_mailbox_list_new(clist * mb_list)
{
  struct mailimf_mailbox_list * mbl;

  mbl = malloc(sizeof(* mbl));
  if (mbl == NULL)
    return NULL;

  mbl->mb_list = mb_list;

  return mbl;
}

void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list)
{
  clist_foreach(mb_list->mb_list, (clist_func) mailimf_mailbox_free, NULL);
  clist_free(mb_list->mb_list);
  free(mb_list);
}



struct mailimf_address_list *
mailimf_address_list_new(clist * ad_list)
{
  struct mailimf_address_list * addr_list;

  addr_list = malloc(sizeof(* addr_list));
  if (addr_list == NULL)
    return NULL;

  addr_list->ad_list = ad_list;

  return addr_list;
}

void mailimf_address_list_free(struct mailimf_address_list * addr_list)
{
  clist_foreach(addr_list->ad_list, (clist_func) mailimf_address_free, NULL);
  clist_free(addr_list->ad_list);
  free(addr_list);
}


void mailimf_addr_spec_free(char * addr_spec)
{
  free(addr_spec);
}

void mailimf_local_part_free(char * local_part)
{
  free(local_part);
}

void mailimf_domain_free(char * domain)
{
  free(domain);
}

void mailimf_domain_literal_free(char * domain_literal)
{
  free(domain_literal);
}



struct mailimf_message * 
mailimf_message_new(struct mailimf_fields * msg_fields,
    struct mailimf_body * msg_body)
{
  struct mailimf_message * message;
  
  message = malloc(sizeof(* message));
  if (message == NULL)
    return NULL;

  message->msg_fields = msg_fields;
  message->msg_body = msg_body;

  return message;
}

void mailimf_message_free(struct mailimf_message * message)
{
  mailimf_body_free(message->msg_body);
  mailimf_fields_free(message->msg_fields);
  free(message);
}


struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size)
{
  struct mailimf_body * body;

  body = malloc(sizeof(* body));
  if (body == NULL)
    return NULL;
  body->bd_text = bd_text;
  body->bd_size = bd_size;

  return body;
}

void mailimf_body_free(struct mailimf_body * body)
{
  free(body);
}



struct mailimf_field *
mailimf_field_new(int fld_type,
    struct mailimf_return * fld_return_path,
    struct mailimf_orig_date * fld_resent_date,
    struct mailimf_from * fld_resent_from,
    struct mailimf_sender * fld_resent_sender,
    struct mailimf_to * fld_resent_to,
    struct mailimf_cc * fld_resent_cc,
    struct mailimf_bcc * fld_resent_bcc,
    struct mailimf_message_id * fld_resent_msg_id,
    struct mailimf_orig_date * fld_orig_date,
    struct mailimf_from * fld_from,
    struct mailimf_sender * fld_sender,
    struct mailimf_reply_to * fld_reply_to,
    struct mailimf_to * fld_to,
    struct mailimf_cc * fld_cc,
    struct mailimf_bcc * fld_bcc,
    struct mailimf_message_id * fld_message_id,
    struct mailimf_in_reply_to * fld_in_reply_to,
    struct mailimf_references * fld_references,
    struct mailimf_subject * fld_subject,
    struct mailimf_comments * fld_comments,
    struct mailimf_keywords * fld_keywords,
    struct mailimf_optional_field * fld_optional_field)
{
  struct mailimf_field * field;

  field = malloc(sizeof(* field));
  if (field == NULL)
    return NULL;

  field->fld_type = fld_type;
  switch (fld_type) {
  case MAILIMF_FIELD_RETURN_PATH:
    field->fld_data.fld_return_path = fld_return_path;
    break;
  case MAILIMF_FIELD_RESENT_DATE:
    field->fld_data.fld_resent_date = fld_resent_date;
    break;
  case MAILIMF_FIELD_RESENT_FROM:
    field->fld_data.fld_resent_from = fld_resent_from;
    break;
  case MAILIMF_FIELD_RESENT_SENDER:
    field->fld_data.fld_resent_sender = fld_resent_sender;
    break;
  case MAILIMF_FIELD_RESENT_TO:
    field->fld_data.fld_resent_to = fld_resent_to;
    break;
  case MAILIMF_FIELD_RESENT_CC:
    field->fld_data.fld_resent_cc = fld_resent_cc;
    break;
  case MAILIMF_FIELD_RESENT_BCC:
    field->fld_data.fld_resent_bcc = fld_resent_bcc;
    break;
  case MAILIMF_FIELD_RESENT_MSG_ID:
    field->fld_data.fld_resent_msg_id = fld_resent_msg_id;
    break;
  case MAILIMF_FIELD_ORIG_DATE:
    field->fld_data.fld_orig_date = fld_orig_date;
    break;
  case MAILIMF_FIELD_FROM:
    field->fld_data.fld_from = fld_from;
    break;
  case MAILIMF_FIELD_SENDER:
    field->fld_data.fld_sender = fld_sender;
    break;
  case MAILIMF_FIELD_REPLY_TO:
    field->fld_data.fld_reply_to = fld_reply_to;
    break;
  case MAILIMF_FIELD_TO:
    field->fld_data.fld_to = fld_to;
    break;
  case MAILIMF_FIELD_CC:
    field->fld_data.fld_cc = fld_cc;
    break;
  case MAILIMF_FIELD_BCC:
    field->fld_data.fld_bcc = fld_bcc;
    break;
  case MAILIMF_FIELD_MESSAGE_ID:
    field->fld_data.fld_message_id = fld_message_id;
    break;
  case MAILIMF_FIELD_IN_REPLY_TO:
    field->fld_data.fld_in_reply_to = fld_in_reply_to;
    break;
  case MAILIMF_FIELD_REFERENCES:
    field->fld_data.fld_references = fld_references;
    break;
  case MAILIMF_FIELD_SUBJECT:
    field->fld_data.fld_subject = fld_subject;
    break;
  case MAILIMF_FIELD_COMMENTS:
    field->fld_data.fld_comments = fld_comments;
    break;
  case MAILIMF_FIELD_KEYWORDS:
    field->fld_data.fld_keywords = fld_keywords;
    break;
  case MAILIMF_FIELD_OPTIONAL_FIELD:
    field->fld_data.fld_optional_field = fld_optional_field;
    break;
  }
  
  return field;
}

void mailimf_field_free(struct mailimf_field * field)
{
  switch (field->fld_type) {
  case MAILIMF_FIELD_RETURN_PATH:
    mailimf_return_free(field->fld_data.fld_return_path);
    break;
  case MAILIMF_FIELD_RESENT_DATE:
    mailimf_orig_date_free(field->fld_data.fld_resent_date);
    break;
  case MAILIMF_FIELD_RESENT_FROM:
    mailimf_from_free(field->fld_data.fld_resent_from);
    break;
  case MAILIMF_FIELD_RESENT_SENDER:
    mailimf_sender_free(field->fld_data.fld_resent_sender);
    break;
  case MAILIMF_FIELD_RESENT_TO:
    mailimf_to_free(field->fld_data.fld_resent_to);
    break;
  case MAILIMF_FIELD_RESENT_CC:
    mailimf_cc_free(field->fld_data.fld_resent_cc);
    break;
  case MAILIMF_FIELD_RESENT_BCC:
    mailimf_bcc_free(field->fld_data.fld_resent_bcc);
    break;
  case MAILIMF_FIELD_RESENT_MSG_ID:
    mailimf_message_id_free(field->fld_data.fld_resent_msg_id);
    break;
  case MAILIMF_FIELD_ORIG_DATE:
    mailimf_orig_date_free(field->fld_data.fld_orig_date);
    break;
  case MAILIMF_FIELD_FROM:
    mailimf_from_free(field->fld_data.fld_from);
    break;
  case MAILIMF_FIELD_SENDER:
    mailimf_sender_free(field->fld_data.fld_sender);
    break;
  case MAILIMF_FIELD_REPLY_TO:
    mailimf_reply_to_free(field->fld_data.fld_reply_to);
    break;
  case MAILIMF_FIELD_TO:
    mailimf_to_free(field->fld_data.fld_to);
    break;
  case MAILIMF_FIELD_CC:
    mailimf_cc_free(field->fld_data.fld_cc);
    break;
  case MAILIMF_FIELD_BCC:
    mailimf_bcc_free(field->fld_data.fld_bcc);
    break;
  case MAILIMF_FIELD_MESSAGE_ID:
    mailimf_message_id_free(field->fld_data.fld_message_id);
    break;
  case MAILIMF_FIELD_IN_REPLY_TO:
    mailimf_in_reply_to_free(field->fld_data.fld_in_reply_to);
    break;
  case MAILIMF_FIELD_REFERENCES:
    mailimf_references_free(field->fld_data.fld_references);
    break;
  case MAILIMF_FIELD_SUBJECT:
    mailimf_subject_free(field->fld_data.fld_subject);
    break;
  case MAILIMF_FIELD_COMMENTS:
    mailimf_comments_free(field->fld_data.fld_comments);
    break;
  case MAILIMF_FIELD_KEYWORDS:
    mailimf_keywords_free(field->fld_data.fld_keywords);
    break;
  case MAILIMF_FIELD_OPTIONAL_FIELD:
    mailimf_optional_field_free(field->fld_data.fld_optional_field);
    break;
  }
  
  free(field);
}

struct mailimf_fields * mailimf_fields_new(clist * fld_list)
{
  struct mailimf_fields * fields;

  fields = malloc(sizeof(* fields));
  if (fields == NULL)
    return NULL;

  fields->fld_list = fld_list;

  return fields;
}

void mailimf_fields_free(struct mailimf_fields * fields)
{
  if (fields->fld_list != NULL) {
    clist_foreach(fields->fld_list, (clist_func) mailimf_field_free, NULL);
    clist_free(fields->fld_list);
  }
  free(fields);
}


struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time *
    dt_date_time)
{
  struct mailimf_orig_date * orig_date;

  orig_date = malloc(sizeof(* orig_date));
  if (orig_date == NULL)
    return NULL;

  orig_date->dt_date_time = dt_date_time;

  return orig_date;
}

void mailimf_orig_date_free(struct mailimf_orig_date * orig_date)
{
  if (orig_date->dt_date_time != NULL)
    mailimf_date_time_free(orig_date->dt_date_time);
  free(orig_date);
}

struct mailimf_from *
mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list)
{
  struct mailimf_from * from;

  from = malloc(sizeof(* from));
  if (from == NULL)
    return NULL;
  
  from->frm_mb_list = frm_mb_list;

  return from;
}

void mailimf_from_free(struct mailimf_from * from)
{
  if (from->frm_mb_list != NULL)
    mailimf_mailbox_list_free(from->frm_mb_list);
  free(from);
}

struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb)
{
  struct mailimf_sender * sender;

  sender = malloc(sizeof(* sender));
  if (sender == NULL)
    return NULL;

  sender->snd_mb = snd_mb;

  return sender;
}

void mailimf_sender_free(struct mailimf_sender * sender)
{
  if (sender->snd_mb != NULL)
    mailimf_mailbox_free(sender->snd_mb);
  free(sender);
}

struct mailimf_reply_to *
mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list)
{
  struct mailimf_reply_to * reply_to;

  reply_to = malloc(sizeof(* reply_to));
  if (reply_to == NULL)
    return NULL;

  reply_to->rt_addr_list = rt_addr_list;

  return reply_to;
}

void mailimf_reply_to_free(struct mailimf_reply_to * reply_to)
{
  if (reply_to->rt_addr_list != NULL)
    mailimf_address_list_free(reply_to->rt_addr_list);
  free(reply_to);
}

struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list)
{
  struct mailimf_to * to;

  to = malloc(sizeof(* to));
  if (to == NULL)
    return NULL;

  to->to_addr_list = to_addr_list;

  return to;
}

void mailimf_to_free(struct mailimf_to * to)
{
  if (to->to_addr_list != NULL)
    mailimf_address_list_free(to->to_addr_list);
  free(to);
}

struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list)
{
  struct mailimf_cc * cc;

  cc = malloc(sizeof(* cc));
  if (cc == NULL)
    return NULL;

  cc->cc_addr_list = cc_addr_list;

  return cc;
}

void mailimf_cc_free(struct mailimf_cc * cc)
{
  if (cc->cc_addr_list != NULL)
    mailimf_address_list_free(cc->cc_addr_list);
  free(cc);
}

struct mailimf_bcc *
mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list)
{
  struct mailimf_bcc * bcc;

  bcc = malloc(sizeof(* bcc));
  if (bcc == NULL)
    return NULL;

  bcc->bcc_addr_list = bcc_addr_list;

  return bcc;
}

void mailimf_bcc_free(struct mailimf_bcc * bcc)
{
  if (bcc->bcc_addr_list != NULL)
    mailimf_address_list_free(bcc->bcc_addr_list);
  free(bcc);
}

struct mailimf_message_id * mailimf_message_id_new(char * mid_value)
{
  struct mailimf_message_id * message_id;

  message_id = malloc(sizeof(* message_id));
  if (message_id == NULL)
    return NULL;

  message_id->mid_value = mid_value;

  return message_id;
}

void mailimf_message_id_free(struct mailimf_message_id * message_id)
{
  if (message_id->mid_value != NULL)
    mailimf_msg_id_free(message_id->mid_value);
  free(message_id);
}

struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list)
{
  struct mailimf_in_reply_to * in_reply_to;

  in_reply_to = malloc(sizeof(* in_reply_to));
  if (in_reply_to == NULL)
    return NULL;

  in_reply_to->mid_list = mid_list;

  return in_reply_to;
}

void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to)
{
  clist_foreach(in_reply_to->mid_list,
		(clist_func) mailimf_msg_id_free, NULL);
  clist_free(in_reply_to->mid_list);
  free(in_reply_to);
}

struct mailimf_references * mailimf_references_new(clist * mid_list)
{
  struct mailimf_references * ref;

  ref = malloc(sizeof(* ref));
  if (ref == NULL)
    return NULL;

  ref->mid_list = mid_list;

  return ref;
}

void mailimf_references_free(struct mailimf_references * references)
{
  clist_foreach(references->mid_list,
      (clist_func) mailimf_msg_id_free, NULL);
  clist_free(references->mid_list);
  free(references);
}

void mailimf_msg_id_free(char * msg_id)
{
  free(msg_id);
}

void mailimf_id_left_free(char * id_left)
{
  free(id_left);
}

void mailimf_id_right_free(char * id_right)
{
  free(id_right);
}

void mailimf_no_fold_quote_free(char * nfq)
{
  free(nfq);
}

void mailimf_no_fold_literal_free(char * nfl)
{
  free(nfl);
}

struct mailimf_subject * mailimf_subject_new(char * sbj_value)
{
  struct mailimf_subject * subject;

  subject = malloc(sizeof(* subject));
  if (subject == NULL)
    return NULL;

  subject->sbj_value = sbj_value;

  return subject;
}

void mailimf_subject_free(struct mailimf_subject * subject)
{
  mailimf_unstructured_free(subject->sbj_value);
  free(subject);
}

struct mailimf_comments * mailimf_comments_new(char * cm_value)
{
  struct mailimf_comments * comments;

  comments = malloc(sizeof(* comments));
  if (comments == NULL)
    return NULL;

  comments->cm_value = cm_value;

  return comments;
}

void mailimf_comments_free(struct mailimf_comments * comments)
{
  mailimf_unstructured_free(comments->cm_value);
  free(comments);
}

struct mailimf_keywords * mailimf_keywords_new(clist * kw_list)
{
  struct mailimf_keywords * keywords;

  keywords = malloc(sizeof(* keywords));
  if (keywords == NULL)
    return NULL;

  keywords->kw_list = kw_list;
  
  return keywords;
}

void mailimf_keywords_free(struct mailimf_keywords * keywords)
{
  clist_foreach(keywords->kw_list, (clist_func) mailimf_phrase_free, NULL);
  clist_free(keywords->kw_list);
  free(keywords);
}

struct mailimf_return *
mailimf_return_new(struct mailimf_path * ret_path)
{
  struct mailimf_return * return_path;

  return_path = malloc(sizeof(* return_path));
  if (return_path == NULL)
    return NULL;

  return_path->ret_path = ret_path;

  return return_path;
}

void mailimf_return_free(struct mailimf_return * return_path)
{
  mailimf_path_free(return_path->ret_path);
  free(return_path);
}


struct mailimf_path * mailimf_path_new(char * pt_addr_spec)
{
  struct mailimf_path * path;

  path = malloc(sizeof(* path));
  if (path == NULL)
    return NULL;

  path->pt_addr_spec = pt_addr_spec;

  return path;
}

void mailimf_path_free(struct mailimf_path * path)
{
  if (path->pt_addr_spec != NULL)
    mailimf_addr_spec_free(path->pt_addr_spec);
  free(path);
}

struct mailimf_optional_field *
mailimf_optional_field_new(char * fld_name, char * fld_value)
{
  struct mailimf_optional_field * opt_field;

  opt_field = malloc(sizeof(* opt_field));
  if (opt_field == NULL)
    return NULL;
  
  opt_field->fld_name = fld_name;
  opt_field->fld_value = fld_value;

  return opt_field;
}

void mailimf_optional_field_free(struct mailimf_optional_field * opt_field)
{
  mailimf_field_name_free(opt_field->fld_name);
  mailimf_unstructured_free(opt_field->fld_value);
  free(opt_field);
}

void mailimf_field_name_free(char * field_name)
{
  free(field_name);
}

--- placeholder.txt DELETED ---

--- NEW FILE: mailimf.h ---
/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001, 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: mailimf.h,v 1.1.2.1 2013-02-17 21:21:57 colin Exp $
 */

#ifndef MAILIMF_H

#define MAILIMF_H

#ifdef __cplusplus
extern "C" {
#endif

#include "mailimf_types.h"
#include "mailimf_write.h"
#include "mailimf_types_helper.h"

#include <inttypes.h>
#include <sys/types.h>

/*
  mailimf_message_parse will parse the given message
  
  @param message this is a string containing the message content
  @param length this is the size of the given string
  @param index this is a pointer to the start of the message in
    the given string, (* index) is modified to point at the end
    of the parsed data
  @param result the result of the parse operation is stored in
    (* result)

  @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
*/

int mailimf_message_parse(const char * message, size_t length,
			  size_t * index,
			  struct mailimf_message ** result);

/*
  mailimf_body_parse will parse the given text part of a message
  
  @param message this is a string containing the message text part
  @param length this is the size of the given string
  @param index this is a pointer to the start of the message text part in
    the given string, (* index) is modified to point at the end
    of the parsed data
  @param result the result of the parse operation is stored in
    (* result)

  @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
*/

int mailimf_body_parse(const char * message, size_t length,
		       size_t * index,
		       struct mailimf_body ** result);

/*
  mailimf_fields_parse will parse the given header fields
  
  @param message this is a string containing the header fields
  @param length this is the size of the given string
  @param index this is a pointer to the start of the header fields in
    the given string, (* index) is modified to point at the end
    of the parsed data
  @param result the result of the parse operation is stored in
    (* result)

  @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
*/

int mailimf_fields_parse(const char * message, size_t length,
			 size_t * index,
			 struct mailimf_fields ** result);

/*
  mailimf_mailbox_list_parse will parse the given mailbox list
  
  @param message this is a string containing the mailbox list
  @param length this is the size of the given string
  @param index this is a pointer to the start of the mailbox list in
    the given string, (* index) is modified to point at the end
    of the parsed data
  @param result the result of the parse operation is stored in
    (* result)

  @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
*/

int
mailimf_mailbox_list_parse(const char * message, size_t length,
			   size_t * index,
			   struct mailimf_mailbox_list ** result);

/*
  mailimf_address_list_parse will parse the given address list
  
  @param message this is a string containing the address list
  @param length this is the size of the given string
  @param index this is a pointer to the start of the address list in
    the given string, (* index) is modified to point at the end
    of the parsed data
  @param result the result of the parse operation is stored in
    (* result)

  @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
*/

int
mailimf_address_list_parse(const char * message, size_t length,
			   size_t * index,
			   struct mailimf_address_list ** result);

/*
  mailimf_address_parse will parse the given address
  
  @param message this is a string containing the address
  @param length this is the size of the given string
  @param index this is a pointer to the start of the address in
    the given string, (* index) is modified to point at the end
    of the parsed data
  @param result the result of the parse operation is stored in
    (* result)

  @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
*/

int mailimf_address_parse(const char * message, size_t length,
			  size_t * index,
			  struct mailimf_address ** result);

/*
  mailimf_mailbox_parse will parse the given address
  
  @param message this is a string containing the mailbox
  @param length this is the size of the given string
  @param index this is a pointer to the start of the mailbox in
    the given string, (* index) is modified to point at the end
    of the parsed data
  @param result the result of the parse operation is stored in
    (* result)

  @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
*/

int mailimf_mailbox_parse(const char * message, size_t length,
			  size_t * index,
			  struct mailimf_mailbox ** result);

/*
  mailimf_date_time_parse will parse the given RFC 2822 date
  
  @param message this is a string containing the date
  @param length this is the size of the given string
  @param index this is a pointer to the start of the date in
    the given string, (* index) is modified to point at the end
    of the parsed data
  @param result the result of the parse operation is stored in
    (* result)

  @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
*/

int mailimf_date_time_parse(const char * message, size_t length,
			    size_t * index,
			    struct mailimf_date_time ** result);

/*
  mailimf_envelope_fields_parse will parse the given fields (Date,
  From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To,
  References and Subject)
  
  @param message this is a string containing the header fields
  @param length this is the size of the given string
  @param index this is a pointer to the start of the header fields in
    the given string, (* index) is modified to point at the end
    of the parsed data
  @param result the result of the parse operation is stored in
    (* result)

  @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
*/

int mailimf_envelope_fields_parse(const char * message, size_t length,
				  size_t * index,
				  struct mailimf_fields ** result);

/*
  mailimf_ignore_field_parse will skip the given field
  
  @param message this is a string containing the header field
  @param length this is the size of the given string
  @param index this is a pointer to the start of the header field in
    the given string, (* index) is modified to point at the end
    of the parsed data

  @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
*/


int mailimf_ignore_field_parse(const char * message, size_t length,
			       size_t * index);

/*
  mailimf_envelope_fields will parse the given fields (Date,
  From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To,
  References and Subject), other fields will be added as optional
  fields.
  
  @param message this is a string containing the header fields
  @param length this is the size of the given string
  @param index this is a pointer to the start of the header fields in
    the given string, (* index) is modified to point at the end
    of the parsed data
  @param result the result of the parse operation is stored in
    (* result)

  @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
*/


int
mailimf_envelope_and_optional_fields_parse(const char * message, size_t length,
					   size_t * index,
					   struct mailimf_fields ** result);

/*
  mailimf_envelope_fields will parse the given fields as optional
  fields.
  
  @param message this is a string containing the header fields
  @param length this is the size of the given string
  @param index this is a pointer to the start of the header fields in
    the given string, (* index) is modified to point at the end
    of the parsed data
  @param result the result of the parse operation is stored in
    (* result)

  @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error
*/

int
mailimf_optional_fields_parse(const char * message, size_t length,
			      size_t * index,
			      struct mailimf_fields ** result);


/* internal use, exported for MIME */

int mailimf_fws_parse(const char * message, size_t length, size_t * index);

int mailimf_cfws_parse(const char * message, size_t length,
		       size_t * index);

int mailimf_char_parse(const char * message, size_t length,
		       size_t * index, char token);

int mailimf_unstrict_char_parse(const char * message, size_t length,
				size_t * index, char token);

int mailimf_crlf_parse(const char * message, size_t length, size_t * index);

int
mailimf_custom_string_parse(const char * message, size_t length,
			    size_t * index, char ** result,
			    int (* is_custom_char)(char));

int
mailimf_token_case_insensitive_len_parse(const char * message, size_t length,
					 size_t * index, char * token,
					 size_t token_length);

#define mailimf_token_case_insensitive_parse(message, length, index, token) \
    mailimf_token_case_insensitive_len_parse(message, length, index, token, \
					     sizeof(token) - 1)

int mailimf_quoted_string_parse(const char * message, size_t length,
				size_t * index, char ** result);

int
mailimf_number_parse(const char * message, size_t length,
		     size_t * index, uint32_t * result);

int mailimf_msg_id_parse(const char * message, size_t length,
			 size_t * index,
			 char ** result);

int mailimf_msg_id_list_parse(const char * message, size_t length,
			      size_t * index, clist ** result);

int mailimf_word_parse(const char * message, size_t length,
		       size_t * index, char ** result);

int mailimf_atom_parse(const char * message, size_t length,
		       size_t * index, char ** result);

int mailimf_fws_atom_parse(const char * message, size_t length,
			   size_t * index, char ** result);

int mailimf_fws_word_parse(const char * message, size_t length,
			   size_t * index, char ** result);

int mailimf_fws_quoted_string_parse(const char * message, size_t length,
				    size_t * index, char ** result);

/* exported for IMAP */

int mailimf_references_parse(const char * message, size_t length,
			     size_t * index,
			     struct mailimf_references ** result);

#ifdef __cplusplus
}
#endif

#endif

--- NEW FILE: mailimf.c ---
/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001, 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
[...7546 lines suppressed...]

  fields = mailimf_fields_new(list);
  if (fields == NULL) {
    res = MAILIMF_ERROR_MEMORY;
    goto free;
  }

  * result = fields;
  * index = cur_token;

  return MAILIMF_NO_ERROR;

 free:
  if (list != NULL) {
    clist_foreach(list, (clist_func) mailimf_field_free, NULL);
    clist_free(list);
  }
 err:
  return res;
}

--- NEW FILE: mailimf_types_helper.c ---
/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001, 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
[...1597 lines suppressed...]
  opt_field = mailimf_optional_field_new(name, value);
  if (opt_field == NULL)
    goto err;

  field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD,
      NULL, NULL, NULL, NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL,
      NULL, NULL, NULL, NULL,
      NULL, NULL, opt_field);
  if (field == NULL)
    goto free_opt_field;

  return field;
  
 free_opt_field:
  mailimf_optional_field_free(opt_field);
 err:
  return NULL;
}

--- NEW FILE: chash.c ---

/*
 * libEtPan! -- a mail stuff library
 *
 * chash - Implements generic hash tables.
 *
 * Copyright (c) 1999-2000, Gaël Roualland <gael.roualland at iname.com>
 * interface changes - 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: chash.c,v 1.1.2.1 2013-02-17 21:21:57 colin Exp $
 */

#include <stdlib.h>
#include <string.h>

#include "chash.h"

/* This defines the maximum (average) number of entries per bucket.
   The hash is resized everytime inserting an entry makes the
   average go over that value. */
#define CHASH_MAXDEPTH    3

static inline unsigned int chash_func(const char * key, unsigned int len) {
#if 0
  register unsigned int c = 0, t;
  register const char * k = key;
  
  while (len--) {
    c += (c << 4) + *k++;
    if ((t = c & 0xF0000000)) {
      c ^= t >> 24;
      c ^= t;
    }
  }
  return c;
#endif
  register unsigned int c = 5381;
  register const char * k = key;
  
  while (len--) {
    c = ((c << 5) + c) + *k++;
  }
  
  return c;
}

static inline char * chash_dup(const void * data, unsigned int len)
{
  void * r;

  r = (char *) malloc(len);
  if (!r)
    return NULL;
  memcpy(r, data, len);
  return r;
}

chash * chash_new(unsigned int size, int flags)
{
  chash * h;

  h = (chash *) malloc(sizeof(chash));
  if (h == NULL)
    return NULL;

  h->count = 0;
  h->cells = (struct chashcell **) calloc(size, sizeof(struct chashcell *));
  if (h->cells == NULL) {
    free(h);
    return NULL;
  }
  h->size = size;
  h->copykey = flags & CHASH_COPYKEY;
  h->copyvalue = flags & CHASH_COPYVALUE;
  
  return h;
}

int chash_get(chash * hash,
	      chashdatum * key, chashdatum * result)
{
  unsigned int func;
  chashiter * iter;
  
  func = chash_func(key->data, key->len);

  /* look for the key in existing cells */
  iter = hash->cells[func % hash->size];
  while (iter) {
    if (iter->key.len == key->len && iter->func == func
	&& !memcmp(iter->key.data, key->data, key->len)) {
      * result = iter->value; /* found */

      return 0;
    }
    iter = iter->next;
  }

  return -1;
}

int chash_set(chash * hash,
	      chashdatum * key,
	      chashdatum * value,
	      chashdatum * oldvalue)
{
  unsigned int func, indx;
  chashiter * iter, * cell;
  int r;

  if (hash->count > hash->size * CHASH_MAXDEPTH) {
    r = chash_resize(hash, (hash->count / CHASH_MAXDEPTH) * 2 + 1);
    if (r < 0)
      goto err;
  }

  func = chash_func(key->data, key->len);
  indx = func % hash->size;

  /* look for the key in existing cells */
  iter = hash->cells[indx];
  while (iter) {
    if (iter->key.len == key->len && iter->func == func
	&& !memcmp(iter->key.data, key->data, key->len)) {
      /* found, replacing entry */
      if (hash->copyvalue) {
	char * data;

	data = chash_dup(value->data, value->len);
	if (data == NULL)
	  goto err;

	free(iter->value.data);
	iter->value.data = data;
	iter->value.len = value->len;
      } else {
	if (oldvalue != NULL) {
	  oldvalue->data = iter->value.data;
	  oldvalue->len = iter->value.len;
	}
	iter->value.data = value->data;
	iter->value.len = value->len;
      }
      if (!hash->copykey)
	iter->key.data = key->data;

      if (oldvalue != NULL) {
	oldvalue->data = value->data;
	oldvalue->len = value->len;
      }

      return 0;
    }
    iter = iter->next;
  }
  
  if (oldvalue != NULL) {
    oldvalue->data = NULL;
    oldvalue->len = 0;
  }
  
  /* not found, adding entry */
  cell = (struct chashcell *) malloc(sizeof(struct chashcell));
  if (cell == NULL)
    goto err;

  if (hash->copykey) {
    cell->key.data = chash_dup(key->data, key->len);
    if (cell->key.data == NULL)
      goto free;
  }
  else
    cell->key.data = key->data;

  cell->key.len = key->len;
  if (hash->copyvalue) {
    cell->value.data = chash_dup(value->data, value->len);
    if (cell->value.data == NULL)
      goto free_key_data;
  }
  else
    cell->value.data = value->data;

  cell->value.len = value->len;
  cell->func = func;
  cell->next = hash->cells[indx];
  hash->cells[indx] = cell;
  hash->count++;

  return 0;
  
 free_key_data:
  if (hash->copykey)
    free(cell->key.data);
 free:
  free(cell);
 err:
  return -1;
}

int chash_delete(chash * hash, chashdatum * key, chashdatum * oldvalue)
{
  /*  chashdatum result = { NULL, TRUE }; */
  unsigned int func, indx;
  chashiter * iter, * old;

  /*  
  if (!keylen)
    keylen = strlen(key) + 1;  
  */

  func = chash_func(key->data, key->len);
  indx = func % hash->size;

  /* look for the key in existing cells */
  old = NULL;
  iter = hash->cells[indx];
  while (iter) {
    if (iter->key.len == key->len && iter->func == func
	&& !memcmp(iter->key.data, key->data, key->len)) {
      /* found, deleting */
      if (old)
	old->next = iter->next;
      else
	hash->cells[indx] = iter->next;
      if (hash->copykey)
	free(iter->key.data);
      if (hash->copyvalue)
	free(iter->value.data);
      else {
	if (oldvalue != NULL) {
	  oldvalue->data = iter->value.data;
	  oldvalue->len = iter->value.len;
	}
      }
      free(iter);
      hash->count--;
      return 0;
    }
    old = iter;
    iter = iter->next;
  }

  return -1; /* not found */
}

void chash_free(chash * hash) {
  unsigned int indx;
  chashiter * iter, * next;

  /* browse the hash table */
  for(indx = 0; indx < hash->size; indx++) {
    iter = hash->cells[indx];
    while (iter) {
      next = iter->next;
      if (hash->copykey)
	free(iter->key.data);
      if (hash->copyvalue)
	free(iter->value.data);
      free(iter);
      iter = next;
    }
  }
  free(hash->cells);
  free(hash);
}

void chash_clear(chash * hash) {
  unsigned int indx;
  chashiter * iter, * next;

  /* browse the hash table */
  for(indx = 0; indx < hash->size; indx++) {
    iter = hash->cells[indx];
    while (iter) {
      next = iter->next;
      if (hash->copykey)
	free(iter->key.data);
      if (hash->copyvalue)
	free(iter->value.data);
      free(iter);
      iter = next;
    }
  }
  memset(hash->cells, 0, hash->size * sizeof(* hash->cells));
  hash->count = 0;
}

chashiter * chash_begin(chash * hash) {
  chashiter * iter;
  unsigned int indx = 0;
  
  iter = hash->cells[0];
  while(!iter) {
    indx++;
    if (indx >= hash->size)
      return NULL;
    iter = hash->cells[indx];
  }
  return iter;
}

chashiter * chash_next(chash * hash, chashiter * iter) {
  unsigned int indx;

  if (!iter)
    return NULL;

  indx = iter->func % hash->size;
  iter = iter->next;

  while(!iter) {
    indx++;
    if (indx >= hash->size)
      return NULL;
    iter = hash->cells[indx];
  }
  return iter;
}

int chash_resize(chash * hash, unsigned int size)
{
  struct chashcell ** cells;
  unsigned int indx, nindx;
  chashiter * iter, * next;
  
  if (hash->size == size)
    return 0;

  cells = (struct chashcell **) calloc(size, sizeof(struct chashcell *));
  if (!cells)
    return -1;

  /* browse initial hash and copy items in second hash */
  for(indx = 0; indx < hash->size; indx++) {
    iter = hash->cells[indx];
    while (iter) {
      next = iter->next;
      nindx = iter->func % size;
      iter->next = cells[nindx];
      cells[nindx] = iter;
      iter = next;
    }
  }
  free(hash->cells);
  hash->size = size;
  hash->cells = cells;

  return 0;
}

#ifdef NO_MACROS
int chash_count(chash * hash) {
  return hash->count;
}

int chash_size(chash * hash) {
  return hash->size;
}

void chash_value(chashiter * iter, chashdatum * result) {
  * result = iter->value;
}

void chash_key(chashiter * iter, chashdatum * result) {
  * result = iter->key;
}
#endif

--- NEW FILE: mailmbox.c ---
/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001, 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
[...1434 lines suppressed...]

/*
  when MBOX is DONE

  - check for changes

  - unmap the file
  - close file
*/

void claws_mailmbox_done(struct claws_mailmbox_folder * folder)
{
  if (!folder->mb_read_only)
    claws_mailmbox_expunge(folder);
  
  claws_mailmbox_unmap(folder);
  claws_mailmbox_close(folder);

  claws_mailmbox_folder_free(folder);
}

--- NEW FILE: mailmbox_parse.h ---
/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001, 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: mailmbox_parse.h,v 1.1.2.1 2013-02-17 21:21:58 colin Exp $
 */

#ifndef MAILMBOX_PARSE_H

#define MAILMBOX_PARSE_H

#ifdef __cplusplus
extern "C" {
#endif

#include "mailmbox_types.h"

int claws_mailmbox_parse(struct claws_mailmbox_folder * folder);

int
claws_mailmbox_parse_additionnal(struct claws_mailmbox_folder * folder,
			   size_t * index);

#ifdef __cplusplus
}
#endif

#endif

--- NEW FILE: mailimf_types_helper.h ---
/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001, 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: mailimf_types_helper.h,v 1.1.2.1 2013-02-17 21:21:57 colin Exp $
 */

#ifndef MAILIMF_TYPES_HELPER

#define MAILIMF_TYPES_HELPER

#ifdef __cplusplus
extern "C" {
#endif

#include "mailimf_types.h"

/*
  IMPORTANT NOTE:
  
  All allocation functions will take as argument allocated data
  and will store these data in the structure they will allocate.
  Data should be persistant during all the use of the structure
  and will be freed by the free function of the structure

  allocation functions will return NULL on failure
*/

/*
  mailimf_mailbox_list_new_empty creates an empty list of mailboxes
*/

struct mailimf_mailbox_list *
mailimf_mailbox_list_new_empty();

/*
  mailimf_mailbox_list_add adds a mailbox to the list of mailboxes

  @return MAILIMF_NO_ERROR will be returned on success,
  other code will be returned otherwise
*/

int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list,
			     struct mailimf_mailbox * mb);

/*
  mailimf_mailbox_list_add_parse parse the given string
  into a mailimf_mailbox structure and adds it to the list of mailboxes

  @return MAILIMF_NO_ERROR will be returned on success,
  other code will be returned otherwise
*/

int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list,
				   char * mb_str);

/*
  mailimf_mailbox creates a mailimf_mailbox structure with the given
  arguments and adds it to the list of mailboxes

  - display_name is the name that will be displayed for this mailbox,
    for example 'name' in '"name" <mailbox at domain>,
    should be allocated with malloc()
  
  - address is the mailbox, for example 'mailbox at domain'
    in '"name" <mailbox at domain>, should be allocated with malloc()

  @return MAILIMF_NO_ERROR will be returned on success,
  other code will be returned otherwise
*/

int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list,
				char * display_name, char * address);

/*
  mailimf_address_list_new_empty creates an empty list of addresses
*/

struct mailimf_address_list *
mailimf_address_list_new_empty();

/*
  mailimf_address_list_add adds a mailbox to the list of addresses

  @return MAILIMF_NO_ERROR will be returned on success,
  other code will be returned otherwise
*/

int mailimf_address_list_add(struct mailimf_address_list * address_list,
			     struct mailimf_address * addr);

/*
  mailimf_address_list_add_parse parse the given string
  into a mailimf_address structure and adds it to the list of addresses

  @return MAILIMF_NO_ERROR will be returned on success,
  other code will be returned otherwise
*/

int mailimf_address_list_add_parse(struct mailimf_address_list * address_list,
				   char * addr_str);

/*
  mailimf_address_list_add_mb creates a mailbox mailimf_address
  with the given arguments and adds it to the list of addresses

  - display_name is the name that will be displayed for this mailbox,
    for example 'name' in '"name" <mailbox at domain>,
    should be allocated with malloc()
  
  - address is the mailbox, for example 'mailbox at domain'
    in '"name" <mailbox at domain>, should be allocated with malloc()

  @return MAILIMF_NO_ERROR will be returned on success,
  other code will be returned otherwise
*/

int mailimf_address_list_add_mb(struct mailimf_address_list * address_list,
				char * display_name, char * address);

/*
  mailimf_resent_fields_add_data adds a set of resent fields in the
  given mailimf_fields structure.
  
  if you don't want a given field in the set to be added in the list
  of fields, you can give NULL as argument

  @param resent_msg_id sould be allocated with malloc()

  @return MAILIMF_NO_ERROR will be returned on success,
  other code will be returned otherwise
*/

int
mailimf_resent_fields_add_data(struct mailimf_fields * fields,
    struct mailimf_date_time * resent_date,
    struct mailimf_mailbox_list * resent_from,
    struct mailimf_mailbox * resent_sender,
    struct mailimf_address_list * resent_to,
    struct mailimf_address_list * resent_cc,
    struct mailimf_address_list * resent_bcc,
    char * resent_msg_id);

/*
  mailimf_resent_fields_new_with_data_all creates a new mailimf_fields
  structure with a set of resent fields

  if you don't want a given field in the set to be added in the list
  of fields, you can give NULL as argument

  @param resent_msg_id sould be allocated with malloc()

  @return MAILIMF_NO_ERROR will be returned on success,
  other code will be returned otherwise
*/

struct mailimf_fields *
mailimf_resent_fields_new_with_data_all(struct mailimf_date_time *
    resent_date, struct mailimf_mailbox_list * resent_from,
    struct mailimf_mailbox * resent_sender,
    struct mailimf_address_list * resent_to,
    struct mailimf_address_list * resent_cc,
    struct mailimf_address_list * resent_bcc,
    char * resent_msg_id);

/*
  mailimf_resent_fields_new_with_data_all creates a new mailimf_fields
  structure with a set of resent fields.
  Resent-Date and Resent-Message-ID fields will be generated for you.

  if you don't want a given field in the set to be added in the list
  of fields, you can give NULL as argument

  @return MAILIMF_NO_ERROR will be returned on success,
  other code will be returned otherwise
*/

struct mailimf_fields *
mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from,
    struct mailimf_mailbox * sender,
    struct mailimf_address_list * to,
    struct mailimf_address_list * cc,
    struct mailimf_address_list * bcc);

/*
  this function creates a new mailimf_fields structure with no fields
*/

struct mailimf_fields *
mailimf_fields_new_empty(void);


/*
  this function adds a field to the mailimf_fields structure

  @return MAILIMF_NO_ERROR will be returned on success,
  other code will be returned otherwise
*/

int mailimf_fields_add(struct mailimf_fields * fields,
		       struct mailimf_field * field);


/*
  mailimf_fields_add_data adds a set of fields in the
  given mailimf_fields structure.
  
  if you don't want a given field in the set to be added in the list
  of fields, you can give NULL as argument

  @param msg_id sould be allocated with malloc()
  @param subject should be allocated with malloc()
  @param in_reply_to each elements of this list should be allocated
    with malloc()
  @param references each elements of this list should be allocated
    with malloc()

  @return MAILIMF_NO_ERROR will be returned on success,
  other code will be returned otherwise
*/

int mailimf_fields_add_data(struct mailimf_fields * fields,
			    struct mailimf_date_time * date,
			    struct mailimf_mailbox_list * from,
			    struct mailimf_mailbox * sender,
			    struct mailimf_address_list * reply_to,
			    struct mailimf_address_list * to,
			    struct mailimf_address_list * cc,
			    struct mailimf_address_list * bcc,
			    char * msg_id,
			    clist * in_reply_to,
			    clist * references,
			    char * subject);

/*
  mailimf_fields_new_with_data_all creates a new mailimf_fields
  structure with a set of fields

  if you don't want a given field in the set to be added in the list
  of fields, you can give NULL as argument

  @param message_id sould be allocated with malloc()
  @param subject should be allocated with malloc()
  @param in_reply_to each elements of this list should be allocated
    with malloc()
  @param references each elements of this list should be allocated
    with malloc()

  @return MAILIMF_NO_ERROR will be returned on success,
  other code will be returned otherwise
*/

struct mailimf_fields *
mailimf_fields_new_with_data_all(struct mailimf_date_time * date,
				 struct mailimf_mailbox_list * from,
				 struct mailimf_mailbox * sender,
				 struct mailimf_address_list * reply_to,
				 struct mailimf_address_list * to,
				 struct mailimf_address_list * cc,
				 struct mailimf_address_list * bcc,
				 char * message_id,
				 clist * in_reply_to,
				 clist * references,
				 char * subject);

/*
  mailimf_fields_new_with_data creates a new mailimf_fields
  structure with a set of fields
  Date and Message-ID fields will be generated for you.

  if you don't want a given field in the set to be added in the list
  of fields, you can give NULL as argument

  @param subject should be allocated with malloc()
  @param in_reply_to each elements of this list should be allocated
    with malloc()
  @param references each elements of this list should be allocated
    with malloc()

  @return MAILIMF_NO_ERROR will be returned on success,
  other code will be returned otherwise
*/

struct mailimf_fields *
mailimf_fields_new_with_data(struct mailimf_mailbox_list * from,
			     struct mailimf_mailbox * sender,
			     struct mailimf_address_list * reply_to,
			     struct mailimf_address_list * to,
			     struct mailimf_address_list * cc,
			     struct mailimf_address_list * bcc,
			     clist * in_reply_to,
			     clist * references,
			     char * subject);

/*
  this function returns an allocated message identifier to
  use in a Message-ID or Resent-Message-ID field
*/

char * mailimf_get_message_id(void);

/*
  this function returns a mailimf_date_time structure to
  use in a Date or Resent-Date field
*/

struct mailimf_date_time * mailimf_get_current_date(void);


/*
  mailimf_single_fields_init fills a mailimf_single_fields structure
  with the content of a mailimf_fields structure
*/

void mailimf_single_fields_init(struct mailimf_single_fields * single_fields,
                                struct mailimf_fields * fields);

/*
  mailimf_single_fields_new creates a new mailimf_single_fields and
  fills the structure with mailimf_fields
*/

struct mailimf_single_fields *
mailimf_single_fields_new(struct mailimf_fields * fields);

void mailimf_single_fields_free(struct mailimf_single_fields *
                                single_fields);

/*
  mailimf_field_new_custom creates a new field of type optional

  @param name should be allocated with malloc()
  @param value should be allocated with malloc()
*/

struct mailimf_field * mailimf_field_new_custom(char * name, char * value);

#ifdef __cplusplus
}
#endif

#endif

--- NEW FILE: mailmbox_parse.c ---
/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001, 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: mailmbox_parse.c,v 1.1.2.1 2013-02-17 21:21:58 colin Exp $
 */

#include "mailmbox_parse.h"

#include "mailmbox.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>

#define UID_HEADER "X-LibEtPan-UID:"

#include "utils.h"

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif

enum {
  UNSTRUCTURED_START,
  UNSTRUCTURED_CR,
  UNSTRUCTURED_LF,
  UNSTRUCTURED_WSP,
  UNSTRUCTURED_OUT
};

static inline int
claws_mailmbox_fields_parse(char * str, size_t length,
		      size_t * index,
		      uint32_t * puid,
		      size_t * phlen)
{
  size_t cur_token;
  int r;
  size_t hlen;
  size_t uid;
  int end;

  cur_token = * index;

  end = FALSE;
  uid = 0;
  while (!end) {
    size_t begin;

    begin = cur_token;

    r = mailimf_ignore_field_parse(str, length, &cur_token);
    switch (r) {
    case MAILIMF_NO_ERROR:
      if (str[begin] == 'X') {

	if (strncasecmp(str + begin, UID_HEADER, strlen(UID_HEADER)) == 0) {
	  begin += strlen(UID_HEADER);

	  while (str[begin] == ' ')
	    begin ++;
	  
	  uid = strtoul(str + begin, NULL, 10);
	}
      }
      
      break;
    case MAILIMF_ERROR_PARSE:
    default:
      end = TRUE;
      break;
    }
  }

  hlen = cur_token - * index;

  * phlen = hlen;
  * puid = uid;
  * index = cur_token;

  return MAILMBOX_NO_ERROR;
}

enum {
  IN_MAIL,
  FIRST_CR,
  FIRST_LF,
  SECOND_CR,
  SECOND_LF,
  PARSING_F,
  PARSING_R,
  PARSING_O,
  PARSING_M,
  OUT_MAIL
};




static inline int
claws_mailmbox_single_parse(char * str, size_t length,
		      size_t * index,
		      size_t * pstart,
		      size_t * pstart_len,
		      size_t * pheaders,
		      size_t * pheaders_len,
		      size_t * pbody,
		      size_t * pbody_len,
		      size_t * psize,
		      size_t * ppadding,
		      uint32_t * puid)
{
  size_t cur_token;
  size_t start;
  size_t start_len;
  size_t headers;
  size_t headers_len;
  size_t body;
  size_t end;
  size_t next;
  size_t message_length;
  uint32_t uid;
  int r;
#if 0
  int in_mail_data;
#endif
#if 0
  size_t begin;
#endif

  int state;

  cur_token = * index;

  if (cur_token >= length)
    return MAILMBOX_ERROR_PARSE;

  start = cur_token;
  start_len = 0;
  headers = cur_token;

  if (cur_token + 5 < length) {
    if (strncmp(str + cur_token, "From ", 5) == 0) {
      cur_token += 5;
      while (str[cur_token] != '\n') {
        cur_token ++;
        if (cur_token >= length)
          break;
      }
      if (cur_token < length) {
        cur_token ++;
        headers = cur_token;
        start_len = headers - start;
      }
    }
  }

  next = length;

  r = claws_mailmbox_fields_parse(str, length, &cur_token,
			    &uid, &headers_len);
  if (r != MAILMBOX_NO_ERROR)
    return r;

  /* save position */
#if 0
  begin = cur_token;
#endif
  
  mailimf_crlf_parse(str, length, &cur_token);

#if 0
  if (str[cur_token] == 'F') {
    printf("start !\n");
    printf("%50.50s\n", str + cur_token);
    getchar();
  }
#endif
  
  body = cur_token;

  /* restore position */
  /*  cur_token = begin; */

  state = FIRST_LF;

  end = length;

#if 0
  in_mail_data = 0;
#endif
  while (state != OUT_MAIL) {

    if (cur_token >= length) {
      if (state == IN_MAIL)
	end = length;
      next = length;
      break;
    }

    switch(state) {
    case IN_MAIL:
      switch(str[cur_token]) {
      case '\r':
        state = FIRST_CR;
        break;
      case '\n':
        state = FIRST_LF;
        break;
      case 'F':
        if (cur_token == body) {
          end = cur_token;
          next = cur_token;
          state = PARSING_F;
        }
        break;
#if 0
      default:
        in_mail_data = 1;
        break;
#endif
      }
      break;
      
    case FIRST_CR:
      end = cur_token;
      switch(str[cur_token]) {
      case '\r':
        state = SECOND_CR;
        break;
      case '\n':
        state = FIRST_LF;
        break;
      default:
        state = IN_MAIL;
#if 0
        in_mail_data = 1;
#endif
        break;
      }
      break;
      
    case FIRST_LF:
      end = cur_token;
      switch(str[cur_token]) {
      case '\r':
        state = SECOND_CR;
        break;
      case '\n':
        state = SECOND_LF;
        break;
      default:
        state = IN_MAIL;
#if 0
        in_mail_data = 1;
#endif
        break;
      }
      break;
      
    case SECOND_CR:
      switch(str[cur_token]) {
        case '\r':
          end = cur_token;
          break;
        case '\n':
          state = SECOND_LF;
          break;
        case 'F':
          next = cur_token;
          state = PARSING_F;
          break;
        default:
          state = IN_MAIL;
#if 0
          in_mail_data = 1;
#endif
          break;
      }
      break;

    case SECOND_LF:
      switch(str[cur_token]) {
        case '\r':
          state = SECOND_CR;
          break;
        case '\n':
          end = cur_token;
          break;
        case 'F':
          next = cur_token;
          state = PARSING_F;
          break;
        default:
          state = IN_MAIL;
#if 0
          in_mail_data = 1;
#endif
          break;
      }
      break;
      
    case PARSING_F:
      switch(str[cur_token]) {
        case 'r':
          state = PARSING_R;
          break;
        default:
          state = IN_MAIL;
#if 0
          in_mail_data = 1;
#endif
          break;
      }
      break;
      
    case PARSING_R:
      switch(str[cur_token]) {
        case 'o':
          state = PARSING_O;
          break;
        default:
          state = IN_MAIL;
#if 0
          in_mail_data = 1;
#endif
          break;
      }
      break;
      
    case PARSING_O:
      switch(str[cur_token]) {
        case 'm':
          state = PARSING_M;
          break;
        default:
          state = IN_MAIL;
#if 0
          in_mail_data = 1;
#endif
          break;
      }
      break;

    case PARSING_M:
      switch(str[cur_token]) {
        case ' ':
          state = OUT_MAIL;
          break;
      default:
          state = IN_MAIL;
          break;
      }
      break;
    }
    
    cur_token ++;
  }

  message_length = end - start;

  * pstart = start;
  * pstart_len = start_len;
  * pheaders = headers;
  * pheaders_len = headers_len;
  * pbody = body;
  * pbody_len = end - body;
  * psize = message_length;
  * ppadding = next - end;
  * puid = uid;

  * index = next;

  return MAILMBOX_NO_ERROR;
}


int
claws_mailmbox_parse_additionnal(struct claws_mailmbox_folder * folder,
			   size_t * index)
{
  size_t cur_token;

  size_t start;
  size_t start_len;
  size_t headers;
  size_t headers_len;
  size_t body;
  size_t body_len;
  size_t size;
  size_t padding;
  uint32_t uid;
  int r;
  int res;

  uint32_t max_uid;
  uint32_t first_index;
  unsigned int i;
  unsigned int j;

  cur_token = * index;

  /* remove temporary UID that we will parse */

  first_index = carray_count(folder->mb_tab);

  for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) {
    struct claws_mailmbox_msg_info * info;
    
    info = carray_get(folder->mb_tab, i);

    if (info->msg_start < cur_token) {
      continue;
    }

    if (!info->msg_written_uid) {
      chashdatum key;
      
      key.data = &info->msg_uid;
      key.len = sizeof(info->msg_uid);
      
      chash_delete(folder->mb_hash, &key, NULL);
      carray_delete_fast(folder->mb_tab, i);
      claws_mailmbox_msg_info_free(info);
      if (i < first_index)
	first_index = i;
    }
  }

  /* make a sequence in the table */

  max_uid = folder->mb_written_uid;

  i = 0;
  j = 0;
  while (i < carray_count(folder->mb_tab)) {
    struct claws_mailmbox_msg_info * info;
    
    info = carray_get(folder->mb_tab, i);
    if (info != NULL) {
      carray_set(folder->mb_tab, j, info);

      if (info->msg_uid > max_uid)
	max_uid = info->msg_uid;

      info->msg_index = j;
      j ++;
    }
    i ++;
  }
  carray_set_size(folder->mb_tab, j);

  /* parse content */

  first_index = j;

  while (1) {
    struct claws_mailmbox_msg_info * info;
    chashdatum key;
    chashdatum data;
    
    r = claws_mailmbox_single_parse(folder->mb_mapping, folder->mb_mapping_size,
			      &cur_token,
			      &start, &start_len,
			      &headers, &headers_len,
			      &body, &body_len,
			      &size, &padding, &uid);
    if (r == MAILMBOX_NO_ERROR) {
      /* do nothing */
    }
    else if (r == MAILMBOX_ERROR_PARSE) {
      break;
    } else {
      res = r;
      goto err;
    }
    
    key.data = &uid;
    key.len = sizeof(uid);
    
    r = chash_get(folder->mb_hash, &key, &data);
    if (r == 0) {
      info = data.data;
      
      if (!info->msg_written_uid) {
	/* some new mail has been written and override an
	   existing temporary UID */
        
	chash_delete(folder->mb_hash, &key, NULL);
	info->msg_uid = 0;

	if (info->msg_index < first_index)
	  first_index = info->msg_index;
      }
      else
        uid = 0;
    }

    if (uid > max_uid)
      max_uid = uid;

    r = claws_mailmbox_msg_info_update(folder,
				 start, start_len, headers, headers_len,
				 body, body_len, size, padding, uid);
    if (r != MAILMBOX_NO_ERROR) {
      debug_print("claws_mailmbox_msg_info_update failed with %d\n", r);
      res = r;
      goto err;
    }
  }

  * index = cur_token;

  folder->mb_written_uid = max_uid;

  /* attribute uid */

  for(i = first_index ; i < carray_count(folder->mb_tab) ; i ++) {
    struct claws_mailmbox_msg_info * info;
    chashdatum key;
    chashdatum data;

    info = carray_get(folder->mb_tab, i);

    if (info->msg_uid != 0) {
      continue;
    }

    max_uid ++;
    info->msg_uid = max_uid;
    
    key.data = &info->msg_uid;
    key.len = sizeof(info->msg_uid);
    data.data = info;
    data.len = 0;
    
    r = chash_set(folder->mb_hash, &key, &data, NULL);
    if (r < 0) {
      debug_print("chash_set failed with %d\n", r);
      res = MAILMBOX_ERROR_MEMORY;
      goto err;
    }
  }

  folder->mb_max_uid = max_uid;

  return MAILMBOX_NO_ERROR;

 err:
  return res;
}

static void flush_uid(struct claws_mailmbox_folder * folder)
{
  unsigned int i;
  
  for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) {
    struct claws_mailmbox_msg_info * info;
    
    info = carray_get(folder->mb_tab, i);
    if (info != NULL)
      claws_mailmbox_msg_info_free(info);
  }
  
  chash_clear(folder->mb_hash);
  carray_set_size(folder->mb_tab, 0);
}

int claws_mailmbox_parse(struct claws_mailmbox_folder * folder)
{
  int r;
  int res;
  size_t cur_token;

  flush_uid(folder);
  
  cur_token = 0;

  r = claws_mailmbox_parse_additionnal(folder, &cur_token);

  if (r != MAILMBOX_NO_ERROR) {
    res = r;
    goto err;
  }

  return MAILMBOX_NO_ERROR;

 err:
  return res;
}

--- NEW FILE: mailmbox.h ---
/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001, 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: mailmbox.h,v 1.1.2.1 2013-02-17 21:21:57 colin Exp $
 */

#ifndef MAILMBOX_H

#define MAILMBOX_H

#ifdef __cplusplus
extern "C" {
#endif

#include "mailmbox_types.h"

int
claws_mailmbox_append_message_list(struct claws_mailmbox_folder * folder,
			     carray * append_tab);

int
claws_mailmbox_append_message(struct claws_mailmbox_folder * folder,
			const char * data, size_t len);

int claws_mailmbox_fetch_msg(struct claws_mailmbox_folder * folder,
		       uint32_t num, const char ** result,
		       size_t * result_len);

int claws_mailmbox_fetch_msg_headers(struct claws_mailmbox_folder * folder,
			       uint32_t num, const char ** result,
			       size_t * result_len);

void claws_mailmbox_fetch_result_free(char * msg);

int claws_mailmbox_copy_msg_list(struct claws_mailmbox_folder * dest_folder,
			   struct claws_mailmbox_folder * src_folder,
			   carray * tab);

int claws_mailmbox_copy_msg(struct claws_mailmbox_folder * dest_folder,
		      struct claws_mailmbox_folder * src_folder,
		      uint32_t uid);

int claws_mailmbox_expunge(struct claws_mailmbox_folder * folder);

int claws_mailmbox_delete_msg(struct claws_mailmbox_folder * folder, uint32_t uid);

int claws_mailmbox_init(const char * filename,
		  int force_readonly,
		  int force_no_uid,
		  uint32_t default_written_uid,
		  struct claws_mailmbox_folder ** result_folder);

void claws_mailmbox_done(struct claws_mailmbox_folder * folder);

/* low-level access primitives */

int claws_mailmbox_write_lock(struct claws_mailmbox_folder * folder);

int claws_mailmbox_write_unlock(struct claws_mailmbox_folder * folder);

int claws_mailmbox_read_lock(struct claws_mailmbox_folder * folder);

int claws_mailmbox_read_unlock(struct claws_mailmbox_folder * folder);


/* memory map */

int claws_mailmbox_map(struct claws_mailmbox_folder * folder);

void claws_mailmbox_unmap(struct claws_mailmbox_folder * folder);

void claws_mailmbox_sync(struct claws_mailmbox_folder * folder);


/* open & close file */

int claws_mailmbox_open(struct claws_mailmbox_folder * folder);

void claws_mailmbox_close(struct claws_mailmbox_folder * folder);


/* validate cache */

int claws_mailmbox_validate_write_lock(struct claws_mailmbox_folder * folder);

int claws_mailmbox_validate_read_lock(struct claws_mailmbox_folder * folder);


/* fetch message */

int claws_mailmbox_fetch_msg_no_lock(struct claws_mailmbox_folder * folder,
			       uint32_t num, const char ** result,
			       size_t * result_len);

int claws_mailmbox_fetch_msg_headers_no_lock(struct claws_mailmbox_folder * folder,
				       uint32_t num, const char ** result,
				       size_t * result_len);

/* append message */

int
claws_mailmbox_append_message_list_no_lock(struct claws_mailmbox_folder * folder,
				     carray * append_tab);

int claws_mailmbox_expunge_no_lock(struct claws_mailmbox_folder * folder);

#ifdef __cplusplus
}
#endif

#endif

--- NEW FILE: chash.h ---

/*
 * libEtPan! -- a mail stuff library
 *
 * chash - Implements generic hash tables.
 *
 * Copyright (c) 1999-2000, Gaël Roualland <gael.roualland at iname.com>
 * interface changes - 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: chash.h,v 1.1.2.1 2013-02-17 21:21:57 colin Exp $
 */

#ifndef CHASH_H
#define CHASH_H

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
  void * data;
  unsigned int len;
} chashdatum;

struct chash {
  unsigned int size;
  unsigned int count;
  int copyvalue;
  int copykey;
  struct chashcell ** cells; 
};

typedef struct chash chash;

struct chashcell {
  unsigned int func;
  chashdatum key;
  chashdatum value;
  struct chashcell * next;
};

typedef struct chashcell chashiter;

#define CHASH_COPYNONE    0
#define CHASH_COPYKEY     1
#define CHASH_COPYVALUE   2
#define CHASH_COPYALL     (CHASH_COPYKEY | CHASH_COPYVALUE)

#define CHASH_DEFAULTSIZE 13
  
/* Allocates a new (empty) hash using this initial size and the given flags,
   specifying which data should be copied in the hash.
    CHASH_COPYNONE  : Keys/Values are not copied.
    CHASH_COPYKEY   : Keys are dupped and freed as needed in the hash.
    CHASH_COPYVALUE : Values are dupped and freed as needed in the hash.
    CHASH_COPYALL   : Both keys and values are dupped in the hash.
 */
chash * chash_new(unsigned int size, int flags);

/* Frees a hash */
void chash_free(chash * hash);

/* Removes all elements from a hash */
void chash_clear(chash * hash);

/* Adds an entry in the hash table.
   Length can be 0 if key/value are strings.
   If an entry already exists for this key, it is replaced, and its value
   is returned. Otherwise, the data pointer will be NULL and the length
   field be set to TRUE or FALSe to indicate success or failure. */
int chash_set(chash * hash,
	      chashdatum * key,
	      chashdatum * value,
	      chashdatum * oldvalue);

/* Retrieves the data associated to the key if it is found in the hash table.
   The data pointer and the length will be NULL if not found*/
int chash_get(chash * hash,
	      chashdatum * key, chashdatum * result);

/* Removes the entry associated to this key if it is found in the hash table,
   and returns its contents if not dupped (otherwise, pointer will be NULL
   and len TRUE). If entry is not found both pointer and len will be NULL. */
int chash_delete(chash * hash,
		 chashdatum * key,
		 chashdatum * oldvalue);

/* Resizes the hash table to the passed size. */
int chash_resize(chash * hash, unsigned int size);

/* Returns an iterator to the first non-empty entry of the hash table */
chashiter * chash_begin(chash * hash);

/* Returns the next non-empty entry of the hash table */
chashiter * chash_next(chash * hash, chashiter * iter);

/* Some of the following routines can be implemented as macros to
   be faster. If you don't want it, define NO_MACROS */
#ifdef NO_MACROS
/* Returns the size of the hash table */
unsigned int          chash_size(chash * hash);

/* Returns the number of entries in the hash table */
unsigned int          chash_count(chash * hash);

/* Returns the key part of the entry pointed by the iterator */
void chash_key(chashiter * iter, chashdatum * result);

/* Returns the value part of the entry pointed by the iterator */
void chash_value(chashiter * iter, chashdatum * result);

#else
static inline unsigned int chash_size(chash * hash)
{
  return hash->size;
}

static inline unsigned int chash_count(chash * hash)
{
  return hash->count;
}

static inline void chash_key(chashiter * iter, chashdatum * result)
{
  * result = iter->key;
}

static inline void chash_value(chashiter * iter, chashdatum * result)
{
  * result = iter->value;
}

#endif

#ifdef __cplusplus
}
#endif

#endif

--- NEW FILE: plugin_gtk.c ---
/*
 * mailmbox Plugin -- mbox support for Sylpheed
 * Copyright (C) 2003-2005 Christoph Hohmann, 
 *			   Hoa v. Dinh, 
 *			   Alfons Hoogervorst
 *
 * 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 3 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.
 */


#ifdef HAVE_CONFIG_H
#  include "config.h"
#  include "claws-features.h"
#endif

#include <glib.h>
#include <glib/gi18n.h>

#include <gtk/gtk.h>

#include "plugin.h"
#include "folder.h"
#include "mailmbox_folder.h"
#include "mainwindow.h"
#include "folderview.h"
#include "inputdialog.h"
#include "foldersel.h"
#include "alertpanel.h"
#include "main.h"
#include "menu.h"
#include "account.h"
#include "prefs_actions.h"
#include "summaryview.h"
#include "folder_item_prefs.h"

static void add_mailbox(GtkAction *action, gpointer callback_data);
static void new_folder_cb(GtkAction *action, gpointer data);
static void delete_folder_cb(GtkAction *action, gpointer data);
static void rename_folder_cb(GtkAction *action, gpointer data);
static void move_folder_cb(GtkAction *action, gpointer data);
static void copy_folder_cb(GtkAction *action, gpointer data);
static void update_tree_cb(GtkAction *action, gpointer data);
static void remove_mailbox_cb(GtkAction *action, gpointer data);

static GtkActionEntry claws_mailmbox_popup_entries[] = 
{
	{"FolderViewPopup/CreateNewFolder",	NULL, N_("Create _new folder..."), NULL, NULL, G_CALLBACK(new_folder_cb) },
	{"FolderViewPopup/RenameFolder",	NULL, N_("_Rename folder..."), NULL, NULL, G_CALLBACK(rename_folder_cb) },
	{"FolderViewPopup/MoveFolder",		NULL, N_("M_ove folder..."), NULL, NULL, G_CALLBACK(move_folder_cb) },
	{"FolderViewPopup/CopyFolder",		NULL, N_("Cop_y folder..."), NULL, NULL, G_CALLBACK(copy_folder_cb) },
	{"FolderViewPopup/DeleteFolder",	NULL, N_("_Delete folder..."), NULL, NULL, G_CALLBACK(delete_folder_cb) },
	{"FolderViewPopup/CheckNewMessages",	NULL, N_("_Check for new messages"), NULL, NULL, G_CALLBACK(update_tree_cb) }, /*0*/
	{"FolderViewPopup/CheckNewFolders",	NULL, N_("C_heck for new folders"), NULL, NULL, G_CALLBACK(update_tree_cb) }, /*1*/
	{"FolderViewPopup/RebuildTree",		NULL, N_("R_ebuild folder tree"), NULL, NULL, G_CALLBACK(update_tree_cb) }, /*2*/
	{"FolderViewPopup/RemoveMailbox",	NULL, N_("Remove _mailbox..."), NULL, NULL, G_CALLBACK(remove_mailbox_cb) },
};			
static void set_sensitivity(GtkUIManager *ui_manager, FolderItem *item);
static void add_menuitems(GtkUIManager *ui_manager, FolderItem *item);

static FolderViewPopup claws_mailmbox_popup =
{
	"mailmbox",
	"<MailmboxFolder>",
	claws_mailmbox_popup_entries,
	G_N_ELEMENTS(claws_mailmbox_popup_entries),
	NULL, 0,
	NULL, 0, 0, NULL,
	add_menuitems,
	set_sensitivity
};

static GtkActionEntry mainwindow_add_mailbox[] = {{
	"File/AddMailbox/Mbox",
	NULL, N_("mbox (etPan!)..."), NULL, NULL, G_CALLBACK(add_mailbox)
}};

static guint main_menu_id = 0;

gint plugin_gtk_init(gchar **error)
{
	MainWindow *mainwin = mainwindow_get_mainwindow();

	folderview_register_popup(&claws_mailmbox_popup);

	gtk_action_group_add_actions(mainwin->action_group, mainwindow_add_mailbox,
			1, (gpointer)mainwin);
	MENUITEM_ADDUI_ID_MANAGER(mainwin->ui_manager, "/Menu/File/AddMailbox", "Mbox", 
			  "File/AddMailbox/Mbox", GTK_UI_MANAGER_MENUITEM,
			  main_menu_id)

	return 0;
}

void plugin_gtk_done(void)
{
	MainWindow *mainwin = mainwindow_get_mainwindow();
	
	if (mainwin == NULL || claws_is_exiting())
		return;

	folderview_unregister_popup(&claws_mailmbox_popup);

	MENUITEM_REMUI_MANAGER(mainwin->ui_manager,mainwin->action_group, "File/AddMailbox/RSSyl", main_menu_id);
	main_menu_id = 0;
}

static void add_menuitems(GtkUIManager *ui_manager, FolderItem *item)
{
	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "CreateNewFolder", "FolderViewPopup/CreateNewFolder", GTK_UI_MANAGER_MENUITEM)
	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorMbox1", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RenameFolder", "FolderViewPopup/RenameFolder", GTK_UI_MANAGER_MENUITEM)
	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "MoveFolder", "FolderViewPopup/MoveFolder", GTK_UI_MANAGER_MENUITEM)
	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "CopyFolder", "FolderViewPopup/CopyFolder", GTK_UI_MANAGER_MENUITEM)
	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorMbox2", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "DeleteFolder", "FolderViewPopup/DeleteFolder", GTK_UI_MANAGER_MENUITEM)
	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorMbox3", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "CheckNewMessages", "FolderViewPopup/CheckNewMessages", GTK_UI_MANAGER_MENUITEM)
	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "CheckNewFolders", "FolderViewPopup/CheckNewFolders", GTK_UI_MANAGER_MENUITEM)
	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RebuildTree", "FolderViewPopup/RebuildTree", GTK_UI_MANAGER_MENUITEM)
	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorMbox4", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "RemoveMailbox", "FolderViewPopup/RemoveMailbox", GTK_UI_MANAGER_MENUITEM)
	MENUITEM_ADDUI_MANAGER(ui_manager, "/Popup/FolderViewPopup", "SeparatorMbox5", "FolderViewPopup/---", GTK_UI_MANAGER_SEPARATOR)
}

static void set_sensitivity(GtkUIManager *ui_manager, FolderItem *item)
{
	gboolean folder_is_normal = 
			item != NULL &&
			item->stype == F_NORMAL &&
			!folder_has_parent_of_type(item, F_OUTBOX) &&
			!folder_has_parent_of_type(item, F_DRAFT) &&
			!folder_has_parent_of_type(item, F_QUEUE) &&
			!folder_has_parent_of_type(item, F_TRASH);
#define SET_SENS(name, sens) \
	cm_menu_set_sensitive_full(ui_manager, "Popup/"name, sens)

	SET_SENS("FolderViewPopup/CreateNewFolder",   item->stype != F_INBOX);
	SET_SENS("FolderViewPopup/RenameFolder",       item->stype == F_NORMAL && folder_item_parent(item) != NULL);
	SET_SENS("FolderViewPopup/MoveFolder", 	    folder_is_normal && folder_item_parent(item) != NULL);
	SET_SENS("FolderViewPopup/DeleteFolder", 	    item->stype == F_NORMAL && folder_item_parent(item) != NULL);

	SET_SENS("FolderViewPopup/CheckNewMessages", folder_item_parent(item) == NULL);
	SET_SENS("FolderViewPopup/CheckNewFolders",  folder_item_parent(item) == NULL);
	SET_SENS("FolderViewPopup/RebuildTree",    folder_item_parent(item) == NULL);

	SET_SENS("FolderViewPopup/RemoveMailbox",         folder_item_parent(item) == NULL);

#undef SET_SENS
}

#define DO_ACTION(name, act)	{ if (!strcmp(a_name, name)) act; }

static void update_tree_cb(GtkAction *action, gpointer data)
{
	FolderView *folderview = (FolderView *)data;
	FolderItem *item;
	const gchar *a_name = gtk_action_get_name(action);

	item = folderview_get_selected_item(folderview);
	g_return_if_fail(item != NULL);

	summary_show(folderview->summaryview, NULL);

	g_return_if_fail(item->folder != NULL);

	DO_ACTION("FolderViewPopup/CheckNewMessages", folderview_check_new(item->folder));
	DO_ACTION("FolderViewPopup/CheckNewFolders", folderview_rescan_tree(item->folder, FALSE));
	DO_ACTION("FolderViewPopup/RebuildTree", folderview_rescan_tree(item->folder, TRUE));
}

static void add_mailbox(GtkAction *action, gpointer callback_data)
{
	MainWindow *mainwin = (MainWindow *) callback_data;
	gchar *path, *basename;
	Folder *folder;

	path = input_dialog(_("Add mailbox"),
			    _("Input the location of mailbox.\n"
			      "If the existing mailbox is specified, it will be\n"
			      "scanned automatically."),
			    "Mail");
	if (!path) return;
	if (folder_find_from_path(path)) {
		alertpanel_error(_("The mailbox `%s' already exists."), path);
		g_free(path);
		return;
	}
	basename = g_path_get_basename(path);
	folder = folder_new(folder_get_class_from_string("mailmbox"), 
			    !strcmp(path, "Mail") ? _("Mailbox") : basename,
			    path);
	g_free(basename);			    
	g_free(path);


	if (folder->klass->create_tree(folder) < 0) {
		alertpanel_error(_("Creation of the mailbox failed.\n"
				   "Maybe some files already exist, or you don't have the permission to write there."));
		folder_destroy(folder);
		return;
	}

	folder_add(folder);
	folder_scan_tree(folder, TRUE);

	folderview_set(mainwin->folderview);

	return;
}

static void new_folder_cb(GtkAction *action, gpointer data)
{
	FolderView *folderview = (FolderView *)data;
	GtkCMCTree *ctree = GTK_CMCTREE(folderview->ctree);
	FolderItem *item;
	FolderItem *new_item;
	gchar *new_folder;
	gchar *name;
	gchar *p;

	if (!folderview->selected) return;

	item = gtk_cmctree_node_get_row_data(ctree, folderview->selected);
	g_return_if_fail(item != NULL);
	g_return_if_fail(item->folder != NULL);

	new_folder = input_dialog(_("New folder"),
				  _("Input the name of new folder:"),
				  _("NewFolder"));
	if (!new_folder) return;
	AUTORELEASE_STR(new_folder, {g_free(new_folder); return;});

	p = strchr(new_folder, G_DIR_SEPARATOR);
	if (p == NULL)
		p = strchr(new_folder, '.');
	if (p) {
		alertpanel_error(_("`%c' can't be included in folder name."),
				 p[0]);
		return;
	}

	name = trim_string(new_folder, 32);
	AUTORELEASE_STR(name, {g_free(name); return;});

	/* find whether the directory already exists */
	p = g_strconcat(item->path ? item->path : "", ".", new_folder, NULL);
	if (folder_find_child_item_by_name(item, p)) {
		g_free(p);
		alertpanel_error(_("The folder `%s' already exists."), name);
		return;
	}
	g_free(p);

	new_item = folder_create_folder(item, new_folder);
	if (!new_item) {
		alertpanel_error(_("Can't create the folder `%s'."), name);
		return;
	}

	folder_write_list();
}

static void remove_mailbox_cb(GtkAction *action, gpointer data)
{
	FolderView *folderview = (FolderView *)data;
	FolderItem *item;
	gchar *name;
	gchar *message;
	AlertValue avalue;

	item = folderview_get_selected_item(folderview);
	g_return_if_fail(item != NULL);
	g_return_if_fail(item->folder != NULL);
	if (folder_item_parent(item)) return;

	name = trim_string(item->folder->name, 32);
	message = g_strdup_printf
		(_("Really remove the mailbox `%s' ?\n"
		   "(The messages are NOT deleted from the disk)"), name);
	avalue = alertpanel_full(_("Remove mailbox"), message,
				 GTK_STOCK_CANCEL, _("_Remove"), NULL, FALSE,
				 NULL, ALERT_WARNING, G_ALERTDEFAULT);
	g_free(message);
	g_free(name);
	if (avalue != G_ALERTALTERNATE) return;

	folderview_unselect(folderview);
	summary_clear_all(folderview->summaryview);

	folder_destroy(item->folder);
}

static void delete_folder_cb(GtkAction *action, gpointer data)
{
	FolderView *folderview = (FolderView *)data;
	GtkCMCTree *ctree = GTK_CMCTREE(folderview->ctree);
	FolderItem *item;
	gchar *message, *name;
	AlertValue avalue;
	gchar *old_path;
	gchar *old_id;

	item = folderview_get_selected_item(folderview);
	g_return_if_fail(item != NULL);
	g_return_if_fail(item->path != NULL);
	g_return_if_fail(item->folder != NULL);

	name = trim_string(item->name, 32);
	AUTORELEASE_STR(name, {g_free(name); return;});
	message = g_strdup_printf
		(_("All folder(s) and message(s) under `%s' will be deleted.\n"
		   "Do you really want to delete?"), name);
	avalue = alertpanel_full(_("Delete folder"), message,
				 GTK_STOCK_CANCEL, GTK_STOCK_DELETE, NULL, FALSE,
				 NULL, ALERT_NOTICE, G_ALERTDEFAULT);
	g_free(message);
	if (avalue != G_ALERTALTERNATE) return;

	Xstrdup_a(old_path, item->path, return);
	old_id = folder_item_get_identifier(item);

	if (folderview->opened == folderview->selected ||
	    gtk_cmctree_is_ancestor(ctree,
				  folderview->selected,
				  folderview->opened)) {
		summary_clear_all(folderview->summaryview);
		folderview->opened = NULL;
	}

	if (item->folder->klass->remove_folder(item->folder, item) < 0) {
		alertpanel_error(_("Can't remove the folder `%s'."), name);
		if (folderview->opened == folderview->selected)
			summary_show(folderview->summaryview,
				     folderview->summaryview->folder_item);
		g_free(old_id);
		return;
	}

	folder_write_list();

	prefs_filtering_delete_path(old_id);
	g_free(old_id);

}

static void move_folder_cb(GtkAction *action, gpointer data)
{
	FolderView *folderview = (FolderView *)data;
	FolderItem *from_folder = NULL, *to_folder = NULL;

	from_folder = folderview_get_selected_item(folderview);
	if (!from_folder || from_folder->folder->klass != claws_mailmbox_get_class())
		return;

	to_folder = foldersel_folder_sel(from_folder->folder, FOLDER_SEL_MOVE, NULL, FALSE);
	if (!to_folder)
		return;

	folderview_move_folder(folderview, from_folder, to_folder, 0);
}

static void copy_folder_cb(GtkAction *action, gpointer data)
{
	FolderView *folderview = (FolderView *)data;
	FolderItem *from_folder = NULL, *to_folder = NULL;

	from_folder = folderview_get_selected_item(folderview);
	if (!from_folder || from_folder->folder->klass != claws_mailmbox_get_class())
		return;

	to_folder = foldersel_folder_sel(from_folder->folder, FOLDER_SEL_MOVE, NULL, FALSE);
	if (!to_folder)
		return;

	folderview_move_folder(folderview, from_folder, to_folder, 1);
}

static void rename_folder_cb(GtkAction *action, gpointer data)
{
	FolderView *folderview = (FolderView *)data;
	FolderItem *item, *parent;
	gchar *new_folder;
	gchar *name;
	gchar *message;
	gchar *old_path;
	gchar *old_id;
	gchar *new_id;
	gchar *p;

	item = folderview_get_selected_item(folderview);
	g_return_if_fail(item != NULL);
	g_return_if_fail(item->path != NULL);
	g_return_if_fail(item->folder != NULL);

	name = trim_string(item->name, 32);
	message = g_strdup_printf(_("Input new name for `%s':"), name);
	new_folder = input_dialog(_("Rename folder"), message, item->name);
	g_free(message);
	g_free(name);
	if (!new_folder) return;
	AUTORELEASE_STR(new_folder, {g_free(new_folder); return;});

	p = strchr(new_folder, G_DIR_SEPARATOR);
	if (p == NULL)
		p = strchr(new_folder, '.');
	if (p) {
		alertpanel_error(_("`%c' can't be included in folder name."),
				 p[0]);
		return;
	}

	parent = folder_item_parent(item);
	p = g_strconcat(parent->path ? parent->path : "", ".", new_folder, NULL);
	if (folder_find_child_item_by_name(parent, p)) {
		name = trim_string(new_folder, 32);
		alertpanel_error(_("The folder `%s' already exists."), name);
		g_free(name);
		return;
	}

	Xstrdup_a(old_path, item->path, {g_free(new_folder); return;});

	old_id = folder_item_get_identifier(item);

	if (folder_item_rename(item, new_folder) < 0) {
		alertpanel_error(_("The folder could not be renamed.\n"
				   "The new folder name is not allowed."));
		g_free(old_id);
		return;
	}

	new_id = folder_item_get_identifier(item);
	prefs_filtering_rename_path(old_id, new_id);
	account_rename_path(old_id, new_id);
	prefs_actions_rename_path(old_id, new_id);

	g_free(old_id);
	g_free(new_id);

	folder_item_prefs_save_config_recursive(item);
	folder_write_list();
}


--- NEW FILE: Makefile.am ---
plugindir = $(pkglibdir)/plugins
plugin_LTLIBRARIES = mailmbox.la

## Mailmbox folder plugin

mailmbox_la_SOURCES = \
	plugin.c plugin_gtk.c \
	carray.c carray.h \
	chash.c chash.h \
	clist.c clist.h \
	mailimf.c mailimf.h \
	mailimf_types.c mailimf_types.h \
	mailimf_types_helper.c mailimf_types_helper.h \
	mailimf_write.c mailimf_write.h \
	maillock.c maillock.h \
	mailmbox.c mailmbox.h \
	mailmbox_folder.c mailmbox_folder.h \
	mailmbox_parse.c mailmbox_parse.h \
	mailmbox_types.c mailmbox_types.h \
	mmapstring.c mmapstring.h \
	plugin_gtk.h

mailmbox_la_LDFLAGS = \
	-avoid-version -module

mailmbox_la_LIBADD = \
	$(GTK_LIBS)

mailmbox_la_CPPFLAGS = \
	$(CLAWS_MAIL_CFLAGS) \
	$(GLIB_CFLAGS) \
	$(GTK_CFLAGS)

AM_CPPFLAGS = \
	$(CLAWS_MAIL_CFLAGS) \
	$(GLIB_CFLAGS) \
	$(GTK_CFLAGS)

INCLUDES = \
	-I$(top_srcdir)/src \
	-I$(top_srcdir)/src/common \
	-I$(top_srcdir)/src/gtk

--- NEW FILE: mailimf_write.c ---
/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001, 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
[...1982 lines suppressed...]
    return r;

  r = mailimf_string_write(f, col,
      message_id->mid_value, strlen(message_id->mid_value));
  if (r != MAILIMF_NO_ERROR)
    return r;

  r = mailimf_string_write(f, col, ">", 1);
  if (r != MAILIMF_NO_ERROR)
    return r;

  r = mailimf_string_write(f, col, "\r\n", 2);
  if (r != MAILIMF_NO_ERROR)
    return r;
#if 0
  * col = 0;
#endif

  return MAILIMF_NO_ERROR;
}

--- NEW FILE: mailmbox_gtk.deps ---
mailmbox

--- NEW FILE: plugin_gtk.h ---
/*
 * mailmbox Plugin -- mbox support for Sylpheed
 * Copyright (C) 2003-2005 Christoph Hohmann, 
 *			   Hoa v. Dinh, 
 *			   Alfons Hoogervorst
 *
 * 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 3 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.
 */

#ifndef __PLUGIN_GTK_H__
#define __PLUGIN_GTK_H__

#include <glib.h>

gint plugin_gtk_init(gchar **error);
void plugin_gtk_done(void);

#endif

--- NEW FILE: mailimf_write.h ---
/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001, 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: mailimf_write.h,v 1.1.2.1 2013-02-17 21:21:57 colin Exp $
 */

#ifndef MAILIMF_WRITE_H

#define MAILIMF_WRITE_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>
#include "mailimf_types.h"

/*
  mailimf_string_write writes a string to a given stream
  
  @param f is the stream
  @param col (* col) is the column number where we will start to
    write the text, the ending column will be stored in (* col)
  @param str is the string to write
*/

int mailimf_string_write(FILE * f, int * col,
    const char * str, size_t length);


/*
  mailimf_fields_write writes the fields to a given stream
  
  @param f is the stream
  @param col (* col) is the column number where we will start to
    write the text, the ending column will be stored in (* col)
  @param fields is the fields to write
*/

int mailimf_fields_write(FILE * f, int * col,
    struct mailimf_fields * fields);


/*
  mailimf_envelope_fields_write writes only some fields to a given stream
  
  @param f is the stream
  @param col (* col) is the column number where we will start to
    write the text, the ending column will be stored in (* col)
  @param fields is the fields to write
*/

int mailimf_envelope_fields_write(FILE * f, int * col,
    struct mailimf_fields * fields);


/*
  mailimf_field_write writes a field to a given stream
  
  @param f is the stream
  @param col (* col) is the column number where we will start to
    write the text, the ending column will be stored in (* col)
  @param field is the field to write
*/

int mailimf_field_write(FILE * f, int * col,
    struct mailimf_field * field);

/*
  mailimf_quoted_string_write writes a string that is quoted
  to a given stream
  
  @param f is the stream
  @param col (* col) is the column number where we will start to
    write the text, the ending column will be stored in (* col)
  @param string is the string to quote and write
*/

int mailimf_quoted_string_write(FILE * f, int * col,
    const char * string, size_t len);

int mailimf_address_list_write(FILE * f, int * col,
    struct mailimf_address_list * addr_list);

int mailimf_mailbox_list_write(FILE * f, int * col,
    struct mailimf_mailbox_list * mb_list);

/*
  mailimf_header_string_write writes a header value and fold the header
    if needed.
  
  @param f is the stream
  @param col (* col) is the column number where we will start to
    write the text, the ending column will be stored in (* col)
  @param str is the string to write
*/

int mailimf_header_string_write(FILE * f, int * col,
    const char * str, size_t length);

#ifdef __cplusplus
}
#endif

#endif

--- NEW FILE: maillock.c ---
/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001, 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id $
 */

#include "maillock.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <string.h>

/* ********************************************************************** */

/* lock primitives */

/* the lock code is modified from the dot lock file code from mail.local.c */

/*
			     SENDMAIL LICENSE

The following license terms and conditions apply, unless a different
license is obtained from Sendmail, Inc., 6425 Christie Ave, Fourth Floor,
Emeryville, CA 94608, or by electronic mail at license at sendmail.com.

License Terms:

Use, Modification and Redistribution (including distribution of any
modified or derived work) in source and binary forms is permitted only if
each of the following conditions is met:

1. Redistributions qualify as "freeware" or "Open Source Software" under
   one of the following terms:

   (a) Redistributions are made at no charge beyond the reasonable cost of
       materials and delivery.

   (b) Redistributions are accompanied by a copy of the Source Code or by an
       irrevocable offer to provide a copy of the Source Code for up to three
       years at the cost of materials and delivery.  Such redistributions
       must allow further use, modification, and redistribution of the Source
       Code under substantially the same terms as this license.  For the
       purposes of redistribution "Source Code" means the complete compilable
       and linkable source code of sendmail including all modifications.

2. Redistributions of source code must retain the copyright notices as they
   appear in each source code file, these license terms, and the
   disclaimer/limitation of liability set forth as paragraph 6 below.

3. Redistributions in binary form must reproduce the Copyright Notice,
   these license terms, and the disclaimer/limitation of liability set
   forth as paragraph 6 below, in the documentation and/or other materials
   provided with the distribution.  For the purposes of binary distribution
   the "Copyright Notice" refers to the following language:
   "Copyright (c) 1998-2002 Sendmail, Inc.  All rights reserved."

4. Neither the name of Sendmail, Inc. nor the University of California nor
   the names of their contributors may be used to endorse or promote
   products derived from this software without specific prior written
   permission.  The name "sendmail" is a trademark of Sendmail, Inc.

5. All redistributions must comply with the conditions imposed by the
   University of California on certain embedded code, whose copyright
   notice and conditions for redistribution are as follows:

   (a) Copyright (c) 1988, 1993 The Regents of the University of
       California.  All rights reserved.

   (b) Redistribution and use in source and binary forms, with or without
       modification, are permitted provided that the following conditions
       are met:

      (i)   Redistributions of source code must retain the above copyright
            notice, this list of conditions and the following disclaimer.

      (ii)  Redistributions in binary form must reproduce the above
            copyright notice, this list of conditions and the following
            disclaimer in the documentation and/or other materials provided
            with the distribution.

      (iii) Neither the name of the University nor the names of its
            contributors may be used to endorse or promote products derived
            from this software without specific prior written permission.

6. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY
   SENDMAIL, INC. AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
   NO EVENT SHALL SENDMAIL, INC., THE REGENTS OF THE UNIVERSITY OF
   CALIFORNIA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/

/*
  TODO : lock, prefer fcntl() over flock()
         AND use dotlock code above
*/

#define LOCKTO_RM	300	/* timeout for stale lockfile removal */
#define LOCKTO_GLOB	400	/* global timeout for lockfile creation */

static int lock_common(const char * filename, int fd, short locktype)
{
  char lockfilename[PATH_MAX];
  struct flock lock;
  /* dot lock file */
  int statfailed = 0;
  time_t start;
  int r;
  int res;

  lock.l_start = 0;
  lock.l_len = 0;
  lock.l_pid = getpid();
  lock.l_type = locktype;
  lock.l_whence = SEEK_SET;

  r = fcntl(fd, F_SETLKW, &lock);
  if (r < 0) {
    /* WARNING POSIX lock could not be applied */
  }

  /* dot lock file */

  if (strlen(filename) + 6 > PATH_MAX) {
    res = -1;
    goto unlock;
  }

  snprintf(lockfilename, PATH_MAX, "%s.lock", filename);

  time(&start);
  while (1) {
    int fd;
    struct stat st;
    time_t now;
    
    /* global timeout */
    time(&now);
    if (now > start + LOCKTO_GLOB) {
      res = -1;
      goto unlock;
    }

    fd = open(lockfilename, O_WRONLY|O_EXCL|O_CREAT, 0);
    if (fd >= 0) {
      /* defeat lock checking programs which test pid */
      write(fd, "0", 2);
      close(fd);
      break;
    }
    
    /* libEtPan! - adds a delay of 5 seconds between each tries */
    sleep(5);
    
    if (stat(lockfilename, &st) < 0) {
      if (statfailed++ > 5) {
	res = -1;
	goto unlock;
      }
      continue;
    }
    statfailed = 0;
    time(&now);

    if (now < st.st_ctime + LOCKTO_RM)
      continue;
    
    /* try to remove stale lockfile */
    if (unlink(lockfilename) < 0) {
      res = -1;
      goto unlock;
    }

    /*
      libEtPan! - removes this delay of 5 seconds,
       maybe it was misplaced ?
    */
#if 0
    sleep(5);
#endif
  }

  return 0;

 unlock:
  lock.l_start = 0;
  lock.l_len = 0;
  lock.l_pid = getpid();
  lock.l_type = F_UNLCK;
  lock.l_whence = SEEK_SET;

  r = fcntl(fd, F_SETLK, &lock);
  if (r < 0) {
    /* WARNING POSIX lock could not be applied */
  }
  return res;
}

static int unlock_common(const char * filename, int fd)
{
  char lockfilename[PATH_MAX];
  struct flock lock;
  int r;

  if (strlen(filename) + 6 > PATH_MAX)
    return -1;

  snprintf(lockfilename, PATH_MAX, "%s.lock", filename);

  unlink(lockfilename);

  lock.l_start = 0;
  lock.l_len = 0;
  lock.l_pid = getpid();
  lock.l_type = F_UNLCK;
  lock.l_whence = SEEK_SET;

  r = fcntl(fd, F_SETLK, &lock);
  if (r < 0) {
    /* WARNING POSIX lock could not be applied */
  }

  return 0;
}

int maillock_read_lock(const char * filename, int fd)
{
  return lock_common(filename, fd, F_RDLCK);
}

int maillock_read_unlock(const char * filename, int fd)
{
  return unlock_common(filename, fd);
}

int maillock_write_lock(const char * filename, int fd)
{
  return lock_common(filename, fd, F_WRLCK);
}

int maillock_write_unlock(const char * filename, int fd)
{
  return unlock_common(filename, fd);
}

--- NEW FILE: carray.h ---

/*
 * libEtPan! -- a mail stuff library
 *
 * carray - Implements simple dynamic pointer arrays
 *
 * Copyright (c) 1999-2000, Gaël Roualland <gael.roualland at iname.com>
 * interface changes - 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: carray.h,v 1.1.2.1 2013-02-17 21:21:57 colin Exp $
 */

#ifndef CARRAY_H
#define CARRAY_H

#ifdef __cplusplus
extern "C" {
#endif

#include <inttypes.h>

struct carray_s {
  void ** array;
  unsigned int len;
  unsigned int max;
};

typedef struct carray_s carray;

/* Creates a new array of pointers, with initsize preallocated cells */
carray *   carray_new(unsigned int initsize);

/* Adds the pointer to data in the array.
   Returns the index of the pointer in the array or -1 on error */
int       carray_add(carray * array, void * data, unsigned int * index);

int carray_set_size(carray * array, unsigned int new_size);

/* Removes the cell at this index position. Returns TRUE on success.
   Order of elements in the array IS changed. */
int       carray_delete(carray * array, unsigned int indx);

/* Removes the cell at this index position. Returns TRUE on success.
   Order of elements in the array IS not changed. */
int       carray_delete_slow(carray * array, unsigned int indx);

/* remove without decreasing the size of the array */
int carray_delete_fast(carray * array, unsigned int indx);

/* Some of the following routines can be implemented as macros to
   be faster. If you don't want it, define NO_MACROS */
#ifdef NO_MACROS

/* Returns the array itself */
void **   carray_data(carray);

/* Returns the number of elements in the array */
int       carray_count(carray);

/* Returns the contents of one cell */
void *    carray_get(carray array, unsigned int indx);

/* Sets the contents of one cell */
void      carray_set(carray array, unsigned int indx, void * value);

#else

#if 0
#define   carray_data(a)         (a->array)
#define   carray_count(a)        (a->len)
#define   carray_get(a, indx)    (a->array[indx])
#define   carray_set(a, indx, v) do { a->array[indx]=v; } while(0)
#endif

static inline void ** carray_data(carray * array) {
  return array->array;
}

static inline unsigned int carray_count(carray * array) {
  return array->len;
}

static inline void * carray_get(carray * array, unsigned int indx) {
  return array->array[indx];
}

static inline void carray_set(carray * array,
    unsigned int indx, void * value) {
  array->array[indx] = value;
}
#endif

void carray_free(carray * array);

#ifdef __cplusplus
}
#endif

#endif

--- NEW FILE: clist.c ---

/*
 * libEtPan! -- a mail stuff library
 *
 * clist - Implements simple generic double-linked pointer lists
 *
 * Copyright (c) 1999-2000, Gaël Roualland <gael.roualland at iname.com>
 * interface changes - 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: clist.c,v 1.1.2.1 2013-02-17 21:21:57 colin Exp $
 */

#include <stdlib.h>
#include "clist.h"

clist * clist_new() {
  clist * lst;
  
  lst = (clist *) malloc(sizeof(clist));
  if (!lst) return NULL;
  
  lst->first = lst->last = NULL;
  lst->count = 0;
  
  return lst;
}

void clist_free(clist * lst) {
  clistcell * l1, * l2;

  l1 = lst->first;
  while (l1) {
    l2 = l1->next;
    free(l1);
    l1 = l2;
  }

  free(lst);
}

#ifdef NO_MACROS
int clist_isempty(clist * lst) {
  return ((lst->first==lst->last) && (lst->last==NULL));
}

clistiter * clist_begin(clist * lst) {
  return lst->first;
}

clistiter * clist_end(clist * lst) {
  return lst->last;
}

clistiter * clist_next(clistiter * iter) {
  if (iter)
    return iter->next;
  else
    return NULL;
}

clistiter * clist_previous(clistiter * iter) {
  if (iter)
    return iter->previous;
  else
    return NULL;
}

void * clist_content(clistiter * iter) {
  if (iter)
    return iter->data;
  else
    return NULL;
}

int clist_count(clist * lst) {
  return lst->count;
}

int clist_prepend(clist * lst, void * data) {
  return clist_insert_before(lst, lst->first, data);
}

int clist_append(clist * lst, void * data) {
  return clist_insert_after(lst, lst->last, data);
}
#endif

int clist_insert_before(clist * lst, clistiter * iter, void * data) {
  clistcell * c;

  c = (clistcell *) malloc(sizeof(clistcell));
  if (!c) return -1;

  c->data = data;
  lst->count++;
  
  if (clist_isempty(lst)) {
    c->previous = c->next = NULL;
    lst->first = lst->last = c;
    return 0;
  }
  
  if (!iter) {
    c->previous = lst->last;
    c->previous->next = c;
    c->next = NULL;
    lst->last = c;
    return 0;
  }

  c->previous = iter->previous;
  c->next = iter;
  c->next->previous = c;
  if (c->previous)
    c->previous->next = c;
  else
    lst->first = c;

  return 0;
}

int clist_insert_after(clist * lst, clistiter * iter, void * data) {
  clistcell * c;

  c = (clistcell *) malloc(sizeof(clistcell));
  if (!c) return -1;

  c->data = data;
  lst->count++;
  
  if (clist_isempty(lst)) {
    c->previous = c->next = NULL;
    lst->first = lst->last = c;
    return 0;
  }
  
  if (!iter) {
    c->previous = lst->last;
    c->previous->next = c;
    c->next = NULL;
    lst->last = c;
    return 0;
  }

  c->previous = iter;
  c->next = iter->next;
  if (c->next)
    c->next->previous = c;
  else
    lst->last = c;
  c->previous->next = c;

  return 0;
}

clistiter * clist_delete(clist * lst, clistiter * iter) {
  clistiter * ret;
  
  if (!iter) return NULL;

  if (iter->previous) 
    iter->previous->next = iter->next;
  else
    lst->first = iter->next;

  if (iter->next) {
    iter->next->previous = iter->previous;
    ret = iter->next;
  }  else {
    lst->last = iter->previous;
    ret = NULL;
  }

  free(iter);
  lst->count--;
  
  return ret;
}



void clist_foreach(clist * lst, clist_func func, void * data)
{
  clistiter * cur;

  for(cur = clist_begin(lst) ; cur != NULL ; cur = cur->next)
    func(cur->data, data);
}

void clist_concat(clist * dest, clist * src)
{
  if (src->first == NULL) {
    /* do nothing */
  }
  else if (dest->last == NULL) {
    dest->first = src->first;
    dest->last = src->last;
  }
  else {
    dest->last->next = src->first;
    src->first->previous = dest->last;
    dest->last = src->last;
  }
  
  dest->count += src->count;
  src->last = src->first = NULL;
}

static inline clistiter * internal_clist_nth(clist * lst, int index)
{
  clistiter * cur;

  cur = clist_begin(lst);
  while ((index > 0) && (cur != NULL)) {
    cur = cur->next;
    index --;
  }

  if (cur == NULL)
    return NULL;

  return cur;
}

void * clist_nth_data(clist * lst, int index)
{
  clistiter * cur;

  cur = internal_clist_nth(lst, index);
  if (cur == NULL)
    return NULL;
  
  return cur->data;
}

clistiter * clist_nth(clist * lst, int index)
{
  return internal_clist_nth(lst, index);
}

--- NEW FILE: maillock.h ---
/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001, 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: maillock.h,v 1.1.2.1 2013-02-17 21:21:57 colin Exp $
 */

#ifndef MAILLOCK_H

#define MAILLOCK_H

#ifdef __cplusplus
extern "C" {
#endif

int maillock_read_lock(const char * filename, int fd);
int maillock_read_unlock(const char * filename, int fd);
int maillock_write_lock(const char * filename, int fd);
int maillock_write_unlock(const char * filename, int fd);

#ifdef __cplusplus
}
#endif

#endif

--- NEW FILE: plugin.c ---
/*
 * mailmbox Plugin -- mbox support for Sylpheed
 * Copyright (C) 2003 Christoph Hohmann
 * Copyright (C) 2003-2005 Hoa v. Dinh, Alfons Hoogervorst
 *
 * 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 3 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.
 */


#ifdef HAVE_CONFIG_H
#  include "config.h"
#  include "claws-features.h"
#endif

#include <glib.h>
#include <glib/gi18n.h>
#include "plugin.h"
#include "folder.h"
#include "mailmbox_folder.h"
#include "common/version.h"
#include "plugin_gtk.h"
#include "plugin.h"
#include "main.h"

gint plugin_init(gchar **error)
{
	if (!check_plugin_version(MAKE_NUMERIC_VERSION(3,8,1,46),
				VERSION_NUMERIC, "Mailmbox", error))
		return -1;

	folder_register_class(claws_mailmbox_get_class());
	plugin_gtk_init(error);
	return 0;
}

gboolean plugin_done(void)
{
	plugin_gtk_done();
	if (!claws_is_exiting())
		folder_unregister_class(claws_mailmbox_get_class());
	return TRUE;
}

const gchar *plugin_name(void)
{
	return _("mailmbox folder (etPan!)");
}

const gchar *plugin_desc(void)
{
	return _("This is a plugin to handle mailboxes in mbox format.");
}

const gchar *plugin_type(void)
{
	return "GTK2";
}

const gchar *plugin_licence(void)
{
		return "GPL3+";
}

const gchar *plugin_version(void)
{
	return VERSION;
}

struct PluginFeature *plugin_provides(void)
{
	static struct PluginFeature features[] = 
		{ {PLUGIN_FOLDERCLASS, N_("MBOX")},
		  {PLUGIN_NOTHING, NULL}};
	return features;
}

--- NEW FILE: clist.h ---

/*
 * libEtPan! -- a mail stuff library
 *
 * clist - Implements simple generic double-linked pointer lists
 *
 * Copyright (c) 1999-2000, Gaël Roualland <gael.roualland at iname.com>
 * interface changes - 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: clist.h,v 1.1.2.1 2013-02-17 21:21:57 colin Exp $
 */

#ifndef CLIST_H
#define CLIST_H

#ifdef __cplusplus
extern "C" {
#endif

typedef struct clistcell_s {
  void * data;
  struct clistcell_s * previous;
  struct clistcell_s * next;
} clistcell;

struct clist_s {
  clistcell * first;
  clistcell * last;
  int count;
};

typedef struct clist_s clist;
typedef clistcell clistiter;

/* Allocate a new pointer list */
clist *      clist_new();

/* Destroys a list. Data pointed by data pointers is NOT freed. */
void        clist_free(clist *);

/* Some of the following routines can be implemented as macros to
   be faster. If you don't want it, define NO_MACROS */
#ifdef NO_MACROS

/* Returns TRUE if list is empty */
int         clist_isempty(clist *);

/* Returns the number of elements in the list */
int         clist_count(clist *);

/* Returns an iterator to the first element of the list */
clistiter *   clist_begin(clist *);

/* Returns an iterator to the last element of the list */
clistiter *   clist_end(clist *);

/* Returns an iterator to the next element of the list */
clistiter *   clist_next(clistiter *);

/* Returns an iterator to the previous element of the list */
clistiter *   clist_previous(clistiter *);

/* Returns the data pointer of this element of the list */
void*       clist_content(clistiter *);

/* Inserts this data pointer at the beginning of the list */
int         clist_prepend(clist *, void *);

/* Inserts this data pointer at the end of the list */
int         clist_append(clist *, void *);
#else
#define     clist_isempty(lst)             ((lst->first==lst->last) && (lst->last==NULL))
#define     clist_count(lst)               (lst->count)
#define     clist_begin(lst)               (lst->first)
#define     clist_end(lst)                 (lst->last)
#define     clist_next(iter)               (iter ? iter->next : NULL)
#define     clist_previous(iter)           (iter ? iter->previous : NULL)
#define     clist_content(iter)            (iter ? iter->data : NULL)
#define     clist_prepend(lst, data)  (clist_insert_before(lst, lst->first, data))
#define     clist_append(lst, data)   (clist_insert_after(lst, lst->last, data))
#endif

/* Inserts this data pointer before the element pointed by the iterator */
int         clist_insert_before(clist *, clistiter *, void *);

/* Inserts this data pointer after the element pointed by the iterator */
int         clist_insert_after(clist *, clistiter *, void *);

/* Deletes the element pointed by the iterator.
   Returns an iterator to the next element. */
clistiter *   clist_delete(clist *, clistiter *);

typedef void (* clist_func)(void *, void *);

void clist_foreach(clist * lst, clist_func func, void * data);

void clist_concat(clist * dest, clist * src);

void * clist_nth_data(clist * lst, int index);

clistiter * clist_nth(clist * lst, int index);

#ifdef __cplusplus
}
#endif

#endif

--- NEW FILE: carray.c ---

/*
 * libEtPan! -- a mail stuff library
 *
 * carray - Implements simple dynamic pointer arrays
 *
 * Copyright (c) 1999-2000, Gaël Roualland <gael.roualland at iname.com>
 * interface changes - 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: carray.c,v 1.1.2.1 2013-02-17 21:21:57 colin Exp $
 */

#include <stdlib.h>
#include <string.h>
#include "carray.h"

carray * carray_new(unsigned int initsize) {
  carray * array;

  array = (carray *) malloc(sizeof(carray));
  if (!array) return NULL;

  array->len = 0;
  array->max = initsize;
  array->array = (void **) malloc(sizeof(void *) * initsize);
  if (!array->array) {
    free(array);
    return NULL;
  }
  return array;
}

int carray_add(carray * array, void * data, unsigned int * index) {
  int r;
  
  r = carray_set_size(array, array->len + 1);
  if (r < 0)
    return r;

  array->array[array->len - 1] = data;
  if (index != NULL)
    * index = array->len - 1;

  return 0;
}

int carray_set_size(carray * array, unsigned int new_size)
{
  if (new_size > array->max) {
    unsigned int n = array->max * 2;
    void * new;

    while (n <= new_size)
      n *= 2;

    new = (void **) realloc(array->array, sizeof(void *) * n);
    if (!new)
      return -1;
    array->array = new;
    array->max = n;
  }
  array->len = new_size;

  return 0;
}

int carray_delete_fast(carray * array, unsigned int indx) {
  if (indx >= array->len)
    return -1;

  array->array[indx] = NULL;

  return 0;
}

int carray_delete(carray * array, unsigned int indx) {
  if (indx >= array->len)
    return -1;

  if (indx != --array->len)
    array->array[indx] = array->array[array->len];
  return 0;
}

int carray_delete_slow(carray * array, unsigned int indx) {
  if (indx >= array->len)
    return -1;

  if (indx != --array->len) 
    memmove(array->array + indx, array->array + indx + 1,
	    (array->len - indx) * sizeof(void *));
  return 0;
}

#ifdef NO_MACROS
void ** carray_data(carray * array) {
  return array->array;
}

unsigned int carray_count(carray * array) {
  return array->len;
}

void * carray_get(carray * array, unsigned int indx) {
  return array->array[indx];
}

void carray_set(carray * array, unsigned int indx, void * value) {
  array->array[indx] = value;
}
#endif

void carray_free(carray * array) {
  free(array->array);
  free(array);
}

--- NEW FILE: mmapstring.h ---
/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001, 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: mmapstring.h,v 1.1.2.1 2013-02-17 21:21:58 colin Exp $
 */

#ifndef __MMAP_STRING_H__

#define __MMAP_STRING_H__

#include <sys/types.h>

#ifdef __cplusplus
extern "C" {
#endif

/*
#define TMPDIR "/tmp"
*/

typedef struct _MMAPString MMAPString;

struct _MMAPString
{
  char * str;
  size_t len;    
  size_t allocated_len;
  int fd;
  size_t mmapped_size;
  /*
  char * old_non_mmapped_str;
  */
};

/* configure location of mmaped files */

void mmap_string_set_tmpdir(char * directory);

/* Strings
 */

MMAPString * mmap_string_new (const char * init);

MMAPString * mmap_string_new_len (const char * init,
				  size_t len);   

MMAPString * mmap_string_sized_new (size_t dfl_size);

void mmap_string_free (MMAPString * string);

MMAPString * mmap_string_assign (MMAPString * string,
				 const char * rval);

MMAPString * mmap_string_truncate (MMAPString *string,
				   size_t len);    

MMAPString * mmap_string_set_size (MMAPString * string,
				   size_t len);

MMAPString * mmap_string_insert_len (MMAPString * string,
				     size_t pos,   
				     const char * val,
				     size_t len);  

MMAPString * mmap_string_append (MMAPString * string,
				 const char * val);

MMAPString * mmap_string_append_len (MMAPString * string,
				     const char * val,
				     size_t len);  

MMAPString * mmap_string_append_c (MMAPString * string,
				   char c);

MMAPString * mmap_string_prepend (MMAPString * string,
				  const char * val);

MMAPString * mmap_string_prepend_c (MMAPString * string,
				    char c);

MMAPString * mmap_string_prepend_len (MMAPString * string,
				      const char * val,
				      size_t len);  

MMAPString * mmap_string_insert (MMAPString * string,
				 size_t pos,
				 const char * val);

MMAPString * mmap_string_insert_c (MMAPString *string,
				   size_t pos,
				   char c);

MMAPString * mmap_string_erase(MMAPString * string,
			       size_t pos,    
			       size_t len);   

void mmap_string_set_ceil(size_t ceil);

int mmap_string_ref(MMAPString * string);
int mmap_string_unref(char * str);

#ifdef __cplusplus
}
#endif


#endif /* __MMAP_STRING_H__ */

--- NEW FILE: mmapstring.c ---
/*
 * libEtPan! -- a mail stuff library
 *
 * Copyright (C) 2001, 2002 - DINH Viet Hoa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the libEtPan! project nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * $Id: mmapstring.c,v 1.1.2.1 2013-02-17 21:21:58 colin Exp $
 */

#include "mmapstring.h"

#include "chash.h"

#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <pthread.h>
#include <limits.h>

#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))

#define MMAP_STRING_DEFAULT_CEIL (8 * 1024 * 1024)

#define DEFAULT_TMP_PATH "/tmp"

static char tmpdir[PATH_MAX] = DEFAULT_TMP_PATH;

static size_t mmap_string_ceil = MMAP_STRING_DEFAULT_CEIL;

/* MMAPString references */

static pthread_mutex_t mmapstring_lock = PTHREAD_MUTEX_INITIALIZER;
static chash * mmapstring_hashtable = NULL;

static void mmapstring_hashtable_init()
{
  mmapstring_hashtable = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
}

void mmap_string_set_tmpdir(char * directory)
{
  strncpy(tmpdir, directory, PATH_MAX);
  tmpdir[PATH_MAX - 1] = 0;
}


int mmap_string_ref(MMAPString * string)
{
  chash * ht;
  int r;
  chashdatum key;
  chashdatum data;
  
  pthread_mutex_lock(&mmapstring_lock);
  if (mmapstring_hashtable == NULL) {
    mmapstring_hashtable_init();
  }
  ht = mmapstring_hashtable;
  
  if (ht == NULL) {
    pthread_mutex_unlock(&mmapstring_lock);
    return -1;
  }
  
  key.data = &string->str;
  key.len = sizeof(string->str);
  data.data = string;
  data.len = 0;
  
  r = chash_set(mmapstring_hashtable, &key, &data, NULL);
  pthread_mutex_unlock(&mmapstring_lock);
  
  if (r < 0)
    return r;

  return 0;
}

int mmap_string_unref(char * str)
{
  MMAPString * string;
  chash * ht;
  chashdatum key;
  chashdatum data;
  int r;

  pthread_mutex_lock(&mmapstring_lock);
  ht = mmapstring_hashtable;
  
  if (ht == NULL) {
    pthread_mutex_unlock(&mmapstring_lock);
    return -1;
  }
  
  key.data = &str;
  key.len = sizeof(str);

  r = chash_get(ht, &key, &data);
  if (r < 0)
    string = NULL;
  else
    string = data.data;
  
  if (string != NULL) {
    chash_delete(ht, &key, NULL);
    if (chash_count(ht) == 0) {
      chash_free(ht);
      mmapstring_hashtable = NULL;
    }
  }
  
  pthread_mutex_unlock(&mmapstring_lock);

  if (string != NULL) {
    mmap_string_free(string);
    return 0;
  }
  else
    return -1;
}



/* MMAPString */

#define MY_MAXSIZE ((size_t) -1)

static inline size_t
nearest_power (size_t base, size_t num)    
{
  if (num > MY_MAXSIZE / 2) {
    return MY_MAXSIZE;
  }
  else {
    size_t n = base;
    
    while (n < num)
      n <<= 1;
    
    return n;
  }
}

void mmap_string_set_ceil(size_t ceil)
{
  mmap_string_ceil = ceil;
}

/* Strings.
 */

static MMAPString * mmap_string_realloc_file(MMAPString * string)
{
  char * data;

  if (string->fd == -1) {
    char tmpfilename[PATH_MAX];
    int fd;

    * tmpfilename = 0;
    strcat(tmpfilename, tmpdir);
    strcat(tmpfilename, "/libetpan-mmapstring-XXXXXX");

    fd = mkstemp(tmpfilename);
    if (fd == -1)
      return NULL;

    if (unlink(tmpfilename) == -1) {
      close(fd);
      return NULL;
    }

    if (ftruncate(fd, string->allocated_len) == -1) {
      close(fd);
      return NULL;
    }

    data = mmap(NULL, string->allocated_len, PROT_WRITE | PROT_READ,
		MAP_SHARED, fd, 0);

    if (data == MAP_FAILED) {
      close(fd);
      return NULL;
    }

    if (string->str != NULL)
      memcpy(data, string->str, string->len + 1);

    string->fd = fd;
    string->mmapped_size = string->allocated_len;
    free(string->str);
    string->str = data;
  }
  else {
    if (munmap(string->str, string->mmapped_size) == -1)
      return NULL;

    if (ftruncate(string->fd, string->allocated_len) == -1)
      return NULL;
    
    data = mmap(NULL, string->allocated_len, PROT_WRITE | PROT_READ,
		MAP_SHARED, string->fd, 0);

    if (data == MAP_FAILED)
      return NULL;

    string->mmapped_size = string->allocated_len;
    string->str = data;
  }
  
  return string;
}

static MMAPString * mmap_string_realloc_memory(MMAPString * string)
{
  char * tmp;

  tmp =  realloc (string->str, string->allocated_len);
  
  if (tmp == NULL)
    string = NULL;
  else
    string->str = tmp;

  return string;
}

static MMAPString *
mmap_string_maybe_expand (MMAPString* string,
			  size_t len) 
{
  if (string->len + len >= string->allocated_len)
    {
      size_t old_size;
      MMAPString * newstring;

      old_size = string->allocated_len;

      string->allocated_len = nearest_power (1, string->len + len + 1);
      
#ifndef MMAP_UNAVAILABLE
      if (string->allocated_len > mmap_string_ceil)
	newstring = mmap_string_realloc_file(string);
      else {
#endif
	newstring = mmap_string_realloc_memory(string);
#ifndef MMAP_UNAVAILABLE
	if (newstring == NULL)
	  newstring = mmap_string_realloc_file(string);
      }
#endif

      if (newstring == NULL)
	string->allocated_len = old_size;
    }

  return string;
}

MMAPString*
mmap_string_sized_new (size_t dfl_size)
{
  MMAPString *string;
 
  string = malloc(sizeof(* string));
  if (string == NULL)
    return NULL;

  string->allocated_len = 0;
  string->len   = 0;
  string->str   = NULL;
  string->fd    = -1;
  string->mmapped_size = 0;

  if (mmap_string_maybe_expand (string, MAX (dfl_size, 2)) == NULL)
    return NULL;

  string->str[0] = 0;

  return string;
}

MMAPString*
mmap_string_new (const char *init)
{
  MMAPString *string;

  string = mmap_string_sized_new (init ? strlen (init) + 2 : 2);
  if (string == NULL)
    return NULL;

  if (init)
    mmap_string_append (string, init);

  return string;
}

MMAPString*
mmap_string_new_len (const char *init,
		     size_t len)    
{
  MMAPString *string;

  if (len <= 0)
    return mmap_string_new (init);
  else
    {
      string = mmap_string_sized_new (len);
      
      if (init)
        mmap_string_append_len (string, init, len);
      
      return string;
    }
}

void
mmap_string_free (MMAPString *string)
{
  if (string == NULL)
    return;

  if (string->fd != -1) {
    munmap(string->str, string->mmapped_size);
    close(string->fd);
  }
  else {
    free (string->str);
  }
  free(string);
}

MMAPString*
mmap_string_assign (MMAPString     *string,
		    const char *rval)
{
  mmap_string_truncate (string, 0);
  if (mmap_string_append (string, rval) == NULL)
    return NULL;

  return string;
}

MMAPString*
mmap_string_truncate (MMAPString *string,
		      size_t    len)    
{
  string->len = MIN (len, string->len);
  string->str[string->len] = 0;

  return string;
}

/**
 * mmap_string_set_size:
 * @string: a #MMAPString
 * @len: the new length
 * 
 * Sets the length of a #MMAPString. If the length is less than
 * the current length, the string will be truncated. If the
 * length is greater than the current length, the contents
 * of the newly added area are undefined. (However, as
 * always, string->str[string->len] will be a nul byte.) 
 * 
 * Return value: @string
 **/
MMAPString*
mmap_string_set_size (MMAPString *string,
		      size_t    len)    
{
  if (len >= string->allocated_len)
    if (mmap_string_maybe_expand (string, len - string->len) == NULL)
      return NULL;
  
  string->len = len;
  string->str[len] = 0;

  return string;
}

/*
static int in_mapped_zone(MMAPString * string, char * val)
{
  return (val >= string->str) && (val < string->str + string->mmapped_size);
}
*/

MMAPString*
mmap_string_insert_len (MMAPString     *string,
			size_t       pos,    
			const char *val,
			size_t       len)    
{
  if (mmap_string_maybe_expand (string, len) == NULL)
    return NULL;
    
  if (pos < string->len)
    memmove (string->str + pos + len, string->str + pos, string->len - pos);

  /* insert the new string */
  memmove (string->str + pos, val, len);

  string->len += len;

  string->str[string->len] = 0;

  return string;
}

MMAPString*
mmap_string_append (MMAPString     *string,
		    const char *val)
{  
  return mmap_string_insert_len (string, string->len, val, strlen(val));
}

MMAPString*
mmap_string_append_len (MMAPString	 *string,
			const char *val,
			size_t       len)    
{
  return mmap_string_insert_len (string, string->len, val, len);
}

MMAPString*
mmap_string_append_c (MMAPString *string,
		      char    c)
{
  return mmap_string_insert_c (string, string->len, c);
}

MMAPString*
mmap_string_prepend (MMAPString     *string,
		     const char *val)
{
  return mmap_string_insert_len (string, 0, val, strlen(val));
}

MMAPString*
mmap_string_prepend_len (MMAPString	  *string,
			 const char *val,
			 size_t       len)    
{
  return mmap_string_insert_len (string, 0, val, len);
}

MMAPString*
mmap_string_prepend_c (MMAPString *string,
		       char    c)
{  
  return mmap_string_insert_c (string, 0, c);
}

MMAPString*
mmap_string_insert (MMAPString     *string,
		    size_t       pos,    
		    const char *val)
{
  return mmap_string_insert_len (string, pos, val, strlen(val));
}

MMAPString*
mmap_string_insert_c (MMAPString *string,
		      size_t   pos,    
		      char    c)
{
  if (mmap_string_maybe_expand (string, 1) == NULL)
    return NULL;
  
  /* If not just an append, move the old stuff */
  if (pos < string->len)
    memmove (string->str + pos + 1, string->str + pos, string->len - pos);

  string->str[pos] = c;

  string->len += 1;

  string->str[string->len] = 0;

  return string;
}

MMAPString*
mmap_string_erase (MMAPString *string,
		   size_t    pos,    
		   size_t    len)    
{
  if ((pos + len) < string->len)
    memmove (string->str + pos, string->str + pos + len,
	     string->len - (pos + len));
  
  string->len -= len;
  
  string->str[string->len] = 0;

  return string;
}

--- NEW FILE: mailmbox_folder.c ---
/*
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
 * Copyright (C) 1999-2003 Hiroyuki Yamamoto
 *
 * 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 3 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.
 */

[...1103 lines suppressed...]

        if (folder->name == NULL)
                return NULL;

        folderpath = quote_mailbox(folder->name);
        if (folderpath == NULL)	 
    		return NULL;
        itempath = quote_mailbox(item->path);
        if (itempath == NULL) {
                free(folderpath);
    		return NULL;
        }
        path = g_strconcat(get_cache_dir(),
            G_DIR_SEPARATOR_S, folderpath,
            G_DIR_SEPARATOR_S, itempath, NULL);	 
        free(itempath);
        free(folderpath);
        
	return path;
}

--- NEW FILE: mailmbox_folder.h ---
/*
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
 * Copyright (C) 1999-2003 Hiroyuki Yamamoto
 *
 * 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 3 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.
 */

#ifndef __MAILMBOX_FOLDER_H__
#define __MAILMBOX_FOLDER_H__

#include <glib.h>

#include "folder.h"
#include "localfolder.h"

typedef struct _MAILMBOXFolder	MAILMBOXFolder;

#define MAILMBOX_FOLDER(obj)		((MAILMBOXFolder *)obj)

struct _MAILMBOXFolder
{
	LocalFolder lfolder;
};

FolderClass *claws_mailmbox_get_class	(void);

#endif /* __MH_H__ */



More information about the Commits mailing list