/* $Id: fmail.h,v 1.49 2004/01/02 03:54:01 fesnel Exp $ */
/*******************************************************************************
 *   This program is part of a library used by the Archimedes email client     * 
 *                                                                             *
 *   Copyright : (C) 1995-1998 Gennady B. Sorokopud (gena@NetVision.net.il)    *
 *               (C) 1995 Ugen. J. S. Antsilevich (ugen@latte.worldbank.org)   *
 *               (C) 1998-2004 by the Archimedes Project                       *
 *                   http://sourceforge.net/projects/archimedes                *
 *                                                                             *
 *             --------------------------------------------                    *
 *                                                                             *
 *   This program is free software; you can redistribute it and/or modify      *
 *   it under the terms of the GNU Library General Public License as published *
 *   by the Free Software Foundation; either version 2 of the License, or      *
 *   (at your option) any later version.                                       *
 *                                                                             *
 *   This program is distributed in the hope that it will be useful,           *
 *   but WITHOUT ANY WARRANTY, without even the implied warranty of            *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
 *   GNU Library General Public License for more details.                      *
 *                                                                             *
 *   You should have received a copy of the GNU Library 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 _FMAIL_H
	#define _FMAIL_H

	using namespace std;

	#ifdef DMALLOC
			#include <dmalloc.h>
	#endif

	#ifdef HAVE_LOCALE_H
		#include <locale.h>
	#endif

	#include <glib.h>

	//#include <gettext.h>

	#if defined(__linux__) && defined(__alpha__)
		#define _linuxalpha_
	#endif

	#if HAVE_CONFIG_H
		#include <config.h>
	#endif

	#include <iostream>
	#include <fstream>
	#include <list>
	#include <map>
	#include <string>
	#include <vector>

	#include <stdio.h>
	#include <stdlib.h>

	#if HAVE_UNISTD_H
		#include <sys/types.h>
		#include <unistd.h>
	#endif

	#if STDC_HEADERS || defined(HAVE_STDARG_H)
		#if HAVE_STDARG_H
			#include <stdarg.h>
		#endif
	#else
		#if HAVE_VARARGS_H
			#include <varargs.h>
		#endif
	#endif

	#if STDC_HEADERS
		#include <string.h>
		#ifndef bzero
			#define bzero(s, n) memset ((s), 0, (n))
		#endif
	#else
		#ifndef HAVE_STRCHR
			#define strchr index
			#define strrchr rindex
		#endif
char *strchr (), *strrchr ();
		#ifndef HAVE_MEMCPY
			#define memcpy(d, s, n) bcopy ((s), (d), (n))
		#endif
	#endif

	#ifndef HAVE_MEMMOVE
		#define memmove(d, s, n) bcopy ((s), (d), (n))
	#endif

	#ifndef HAVE_STRTOUL
		#define strtoul(nptr,endptr,base) abs(strtol(nptr,endptr,base))
	#endif

	#if TIME_WITH_SYS_TIME
		#include <sys/time.h>
		#include <time.h>
	#else
		#if HAVE_SYS_TIME_H
			#include <sys/time.h>
		#else
			#include <time.h>
		#endif
	#endif

	#ifdef HAVE_SYS_WAIT_H
		#include <sys/wait.h>
	#endif
	#ifndef WEXITSTATUS
		#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
	#endif
	#ifndef WIFEXITED
		#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
	#endif

	#ifdef HAVE_DIRENT_H
		#include <dirent.h>
		#define NAMLEN(dirent) strlen((dirent)->d_name)
	#else
		#define dirent direct
		#define NAMLEN(dirent) (dirent)->d_namlen
		#ifdef HAVE_SYS_NDIR_H
			#include <sys/ndir.h>
		#endif
		#ifdef HAVE_SYS_DIR_H
			#include <sys/dir.h>
		#endif
		#ifdef HAVE_NDIR_H
			#include <ndir.h>
		#endif
	#endif

	#ifdef HAVE_SYS_FILE_H
		#include <sys/file.h>
	#endif

	#ifdef HAVE_SYS_STAT_H
		#include <sys/stat.h>
	#endif

	#include <sys/mman.h>
	#undef MIN
	#undef MAX
	#include <sys/param.h>
	#include <fcntl.h>

	#ifdef HAVE_SIGNAL_H
		#include <signal.h>
	#endif

	#ifdef  HAVE_ERRNO_H
		#include <errno.h>
	#endif

	#include <sys/socket.h>
	#include <netinet/in.h>
	#include <arpa/inet.h>
	#include <netdb.h>

	#if !defined(errno)
extern int errno;
	#endif

	#if !defined(environ)
extern char **environ;
	#endif

/* All the Stuff os/2 does not have */
	#ifdef __EMX__
		#define lstat stat
		#define getwd(s) _getcwd2(s,MAXPATHLEN)
		#define chdir(s) _chdir2(s)
		#define S_ISLNK(mode) (0)
		#define S_ISBLK(mode) (0)
		#define symlink(t,s) (0)
		#define readlink(s,t,l) (strcpy(t,s),strlen(t))
		#define mkfifo(p,m) (0)
		#define mknod(p,m,d) (0)
	#endif

	#ifdef HAVE_MMAP
		#define MMAP_MSG
	#endif

	#ifdef HAVE_REGCOMP
		#include <regex.h>
	#else
		#include "../regex/regex.h"
	#endif

	#if defined(HAVE_PATHS_H) && !defined(__EMX__)
		#include <paths.h>
	#endif

	#ifdef  HAVE_LOCALE_H
		#include <locale.h>
	#endif

/* structures to be defined later */
struct _mail_msg;
struct _mail_folder;
struct _mime_msg;
struct _retrieve_src;
struct _spool_src;
struct _pop_src;
struct _imap_src;
struct _smtp_auth_src;

/* stuff from util.c */
	#ifndef HAVE_UTIMES
extern int utimes(const char *, const struct timeval *);
	#endif

extern int     do_move (char *, char *);
extern int     fastcopy (char *, char *, struct stat *);

	#ifndef HAVE_UNSETENV
extern void    Unsetenv (char *);
	#endif

char *strcasestr(register const char *s, register const char *find, int scase);

	#ifndef HAVE_SNPRINTF
extern int snprintf(char *, size_t, const char *, ...);
	#endif

	#ifndef HAVE_VSNPRINTF
extern int vsnprintf(char *, size_t, const char *, va_list);
	#endif

	#define MAX_FIELD_NAME_LEN  32  /* limit of field name length in mail header */
	#define MAX_FIELDS_IN_HDR   256  /* maximum fields in msg header */
	#define MAX_FIELD_LEN       998 /* limit on length of field */
	#define MAX_SPLIT_FIELD_LEN 32768   /* limit on length of splitted field */
	#define MAX_ADDR_IN_FIELD   1024    /* limit on max recipients in field */
	#define FLD_BREAK       80  /* line length limit in field */
	#define MAX_FOLD_NAME_LEN   255 /* maximal length of folder name */
	#define MAX_MH_FOLD_NAME_LEN    64  /* maximal length of folder name (MH) */
	#define MAX_IMAP_FOLD_NAME_LEN  255 /*maximal length of folder name (IMAP)*/
	#define STATUS_FIELD        "XFMstatus" /* name of status field in mail header */
	#define STATUS_FIELD_LEN    9   /* length of stat. field name */
	#define XFRECEIPT       "X-XFmail-Return-To"    /* confirm reading field */
	#define XUIDL           "X-UIDL"    /* uid on POP server */
	#define MAX_NESTLEVEL       16  /* maximal nesting level for subfold. */
    #define MAX_SUBFOLDERS      256  /* maximal number of subfolders */
	//#define MAX_HIDDEN_FOLDERS  8   /* maximal number of hidden folders */
	#define MAX_MSG_LEN     3072000 /* maximal message length (3Mb) */
	#define MAX_HEADER_LEN      (MAX_FIELDS_IN_HDR * MAX_FIELD_LEN / 4) /* limit on header length */
	#define MAP_HEADER_LEN      2048    /* regular header is not bigger then 2k */
	#define MMAP_INCR       1024    /* increment mmapped part by this value */
	#define MAX_INSFILE_SIZE    65535   /* limit on inserted file size (warning only) */
	#define MAX_INSFILE_LINE    127 /* limit on inserted file line size */
	#define MAX_RECP_NUM        1024    /* limit on recipients number */
	#define MAX_MCAP_SIZE       127 /* limit on number of mailcap entries */
	#define MAX_CHARSETS        64  /* limit on number of MIME charsets */
	#define MAX_EXTRA_HEADERS   16  /* limit on number of extra header
						fields */
	#define MAX_FCC_LEN     255 /* limit on length of Fcc list */
	#define MAX_FOLDER_ALIAS_NAME   32  /* max. length of folder alias name */
	#define MAX_HOST        128 /* host name length limit  */
	#define MAX_PREVIEW_SIZE    65535   /* preview no more than this */
	#define MAX_PREVIEW_LINES   2048    /* preview no more than this */
	#define MAX_CHARSET_NAME    24  /* limit on charset name length */
	#define SOCKET_TIMEOUT      300 /* data transfer timeout */
	#define RESOLV_TIMEOUT      60  /* DNS timeout */

	#define REPLY_ORGMSG        "XF-OrgMsg" /* pointer to original message */
/* <folder>;<uid;<validity> */
	#define FWD_ORGMSG      "XF-FwdOrgMsg" /* pointer to original message */
	#define BOUNCE_ORGMSG       "XF-BncOrgMsg" /* pointer to original message */
	#define SOURCE_FIELD        "XF-Source" /* where the message was retrieved
									from */
	#define MAX_USERNAME_LEN 255  /* maximum length of username for
					 POP/IMAP/SMTP account authentication */

	#define MAX_PASSWD_LEN 255   /* maximum length of paswwd for
					 POP/IMAP/SMTP account authentication 
								 (see also a similarsetting in gpasswd.h
				 that is not yet set by the define here)
				 */

/************* various formatting options ****************/
	#define NEAT_SPACED_INDENTS  1 /* put in space after indent if there
								are no prior indents */
	#define REFORMAT_CONTINOUS_LINES 1 /* enable reformatting of continous
							  (without spaces) lines */
	#define REFORMAT_ENABLE 1      /* enable reformatting
			  (only for conventional/existing fromatting method) */
	#define SMART_FORMAT    1      /* this option is still to be used
				when I get round to writing some code for it */
	#define INDENT_CHARS    ">:#|"     /* indentation characters */
/**********************************************************/

	#define TRASH       "trash"     /* trash folder */
	#define INBOX       "inbox"     /* incoming mailbox folder */
	#define OUTBOX      "outbox"    /* outgoing mail folder */
	#define SENTMAIL    "sent_mail" /* mail that was successfully sent */
	#define DRAFT       "draft"     /* draft folder */
	#define TEMPLATE    "template"  /* template folder */
	#define FTEMP       ".ftemp"    /* temporary folder */
	#define FIMAP       ".imap"     /* IMAP folder */
	#define FMBOX       ".mbox"     /* MBOX folder */

	#ifndef _PATH_SENDMAIL
		#ifdef _CONF_PATH_SENDMAIL
			#define _PATH_SENDMAIL  _CONF_PATH_SENDMAIL
		#endif
	#endif

	#ifndef _PATH_SENDMAIL
		#if defined(sun) || defined(SVR4) || defined(sgi)
			#define _PATH_SENDMAIL  "/usr/lib/sendmail"
		#else
			#define _PATH_SENDMAIL  "/usr/sbin/sendmail"
		#endif
	#endif

	#ifndef        _PATH_LPR
		#ifdef  _PATH_LP
			#define _PATH_LPR   _PATH_LP
			#define _PRINT_LP
		#endif
	#endif

	#ifndef        _PATH_LPR
		#if defined(sun)
			#define _PATH_LPR    "/usr/ucb/lpr"
		#else
			#if defined(SVR4) || defined(sgi) || defined(hpux)
				#define _PATH_LPR   "/usr/bin/lp"
				#define _PRINT_LP
			#else
				#define     _PATH_LPR       "/usr/bin/lpr"
			#endif
		#endif
	#endif

	#ifndef _PATH_MAILDIR
		#ifdef _CONF_PATH_MAILDIR
			#define _PATH_MAILDIR   _CONF_PATH_MAILDIR
		#endif
	#endif

	#ifndef _PATH_MAILDIR
		#if defined(sun) && !defined(SVR4)
			#define _PATH_MAILDIR   "/usr/mail"
		#else
			#ifdef SVR4
				#define _PATH_MAILDIR  "/var/mail"
			#else
				#define _PATH_MAILDIR   "/usr/spool/mail"
			#endif
		#endif
	#endif

	#ifndef _PATH_PGP
		#define _PATH_PGP  "/usr/local/bin/pgp"
	#endif

	#ifndef _PATH_ISPELL
		#define _PATH_ISPELL  "/usr/bin/ispell"
	#endif

	#define NO_SORT     0x00

/* message sort types */
	#define BY_SNT_TIME 0x01
	#define BY_RCV_TIME 0x02
	#define BY_SUBJECT  0x03
	#define BY_AUTHOR   0x04
	#define BY_FLAGS    0x05
	#define BY_SIZE     0x06
	#define BY_RECIPIENT    0x07
	#define BY_UID      0x08    /* internal */
	#define BY_MSG_UID  0x09

/* folder sort types  */
	#define BY_NAME     0x01
	#define BY_PRIOR    0x02
	#define BY_MSGNUM   0x03
	#define BY_UNREAD   0x04

/* sort order (modifiers) */
	#define MSG_ASCEND  0x10
	#define MSG_DESCEND 0x20
	#define MSG_THREAD  0x40
	#define FLD_SORTED  0x40

/* search options (flags) */
	#define S_CASE      0x01    /* search is case insensitive */

extern vector<struct _mail_folder *> mailbox;
extern vector<struct _mail_folder *> hidden_mailbox;

/* pointers to system folders */
extern struct _mail_folder *trash, *inbox, *outbox, *sentm, *draft, *mftemplate, *ftemp, *fmbox;
/* path of mail directory ( usually ~/Mail) */
extern char mailbox_path[255];
extern char *months[12];
extern char *shorthfields[];

/* offline work */
extern u_int offline;

/* sort criteria */
extern u_int sort_type;
extern u_int folder_sort;

/* headers to be stripped when sending mail */
extern char *stripheaders[];

/* linked address list */

typedef struct _mail_addr {
	int num;        /* number of addresses in list */
	char *addr;     /* mail address like: user@host */
	char *name;     /* name (if exists) like: John B. Smith */
	char *comment;      /* comment (if exists) like: (The WiZaRd) */
	char *pgpid;        /* PGP Id */
	struct _mail_addr *next_addr;   /* next address in group */
} mail_addr;

/* newsgroups */
typedef struct _news_addr {
	char *name;     /* newsgroup name */
	char *descr;        /* newsgroup description (NULL if none) */
	struct _news_addr *next;/* next newsgroup in list */
} newsgroup;

/* structure of field in message header */

typedef struct _head_field {
	int num_fields;     /* number of fields in header */
	char f_name[MAX_FIELD_NAME_LEN];    /* field name */
	char *f_line;       /* field contents */
	struct _head_field *next_head_field;    /* pointer to the next field */
} head_field;

/* header of mail message */

typedef struct _msg_header {
	u_int header_len;   /* header lenght in bytes */
	/* standard address fields */
	mail_addr *From;    /* From address */
	mail_addr *To;      /* To address list */
	mail_addr *Sender;  /* Sender address */
	mail_addr *Cc;      /* Cc address list */
	mail_addr *Bcc;     /* Bcc address list */
	newsgroup *News;    /* Newsgroups list */
	char *Fcc;      /* Fcc folder list */
	char *Subject;      /* subject */
	time_t snt_time;    /* time when the message was sent */
	time_t rcv_time;    /* time when the message was received */
	int flags;      /* message flags (from file) */
	head_field *other_fields;
} msg_header;

/* mail message */

typedef int (*msg_delete) (struct _mail_msg *);             /* delete message*/
typedef int (*msg_print) (struct _mail_msg *, FILE *, int); /* print message */
typedef int (*msg_print_body) (struct _mail_msg *, FILE *); /* print body    */
/* get text      */
typedef int (*msg_get_text) (struct _mail_msg *, struct _mime_msg *);
typedef void (*msg_free_text) (struct _mail_msg *); /* free message text */
typedef char *(*msg_get_file) (struct _mail_msg *); /* get message file  */
typedef int (*msg_update) (struct _mail_msg *);     /* update message    */
typedef int (*msg_get_header) (struct _mail_msg *); /* get full header   */
typedef unsigned long (*msg_validity) (struct _mail_msg *); /* get validity number */
typedef int (*msg_refresh) (struct _mail_msg *); /* refresh message from server/disk */

typedef struct _mail_msg {
	u_long  msg_len;    /* length of message (including header) */
	msg_header *header; /* message header */
	char *msg_body;     /* message text */
	u_long msg_body_len;    /* length of text in memory */
	long num;        /* message file number */
	long uid;       /* message UID */
	long real_uid;  /* message UID: same as above for MH folders real UID for mbox */
	int flags;      /* message status (stored in message header) */
	#define SIGNED      0x00000001  /* message has signature attached */
	#define UNREAD      0x00000002  /* unread message */
	#define NOT_SENT    0x00000004  /* message waits for sending */
	#define MARKED      0x00000008  /* message is marked */
	#define URGENT1     0x00000010  /* urgent bit 1 */
	#define URGENT2     0x00000020  /* urgent bit 2 */
	/* 00 - normal    (3)   */
	/* 01 - low       (5)   */
	/* 10 - high      (2)   */
	/* 11 - very high (1)   */
	#define M_TEMP      0x00000080  /* temporary message */
	#define H_ONLY      0x00000100  /* header only */
	#define ANSWERED    0x00000200  /* answered message */
	#define FORWARDED   0x00000400  /* forwarded message */
	#define PGP_SIGNED  0x00000800  /* PGP signed message */
	#define PGP_ENCRYPTED   0x00001000  /* PGP encrypted message */
	#define M_SFAILED   0x00002000  /* could not send this message */
	#define M_DONTEXPIRE    0x00004000  /* don't expire this message */
	/* special header flags */
	#define M_HSHORT    0x40000000  /* identifies short header */
	#define M_TESTFLAG  0x80000000  /* test flag. never set */
	int type;       /* message type */
	#define M_MH        0x0001      /* local MH-style message */
	#define M_IMAP      0x0002      /* remote (IMAP) message  */
	#define M_NEWS      0x0004      /* News article. Not supported yet*/
	#define M_MBOX      0x0008      /* Unix mailbox. */
	int status;     /* message status */
	#define LOCKED      0x00000001 /* message is locked by viewer/editor */
	#define DELETED     0x00000002 /* message marked to be removed */
	#define MOVED       0x00000004 /* message moved to another folder */
	#define COPIED      0x00800008 /* message copied to another folder */
	#define CHANGED     0x00000010 /* message was changed */
	#define S_THREAD    0x00000020 /* thread start */
	#define RECENT      0x00000040 /* recently retrieved */
	#define DELPERM     0x00000080 /* permanently deleted */
	#define MARKTMP     0x00000100 /* temporarily marked */
	#define MSGNEW      0x00000200 /* new message */
	#define H_SHORT     0x00000400 /* short header */
	#define NOTINCOMING 0x00000800 /* not incoming, used by rules */
	#define MMODIFIED   0x00001000 /* modified in this session */
	#define MREFRESH    0x00002000 /* refresh from server */
	#define MNOREFRESH  0x00004000 /* don't refresh from server */
	#define MOUTGOING   0x00008000 /* outgoing message */
	#define MNOTEXISTS  0x00010000 /* does not exists anymore */
	#define MTOOBIG     0x00020000 /* message is to big, just keep it */
	#define C_DELIVERY  0x00040000 /* confirm message delivery */
	#define C_READ      0x00080000 /* confirm message read */
	#define IMAPDELETED 0x00100000 /* marked as deleted on IMAP server */
	#define MTOUS       0x00200000 /* sent directly to the user */
	#define MFROMUS     0x00400000 /* sent by the user */
	struct _mail_folder *folder; /* pointer to folder of message */
	struct _mail_msg *next; /* pointer to next message in folder */
	struct _mail_msg *ref;  /* pointer to referenced message in folder */
	struct _mime_msg *mime; /* pointer to mime structure */
	int     refs;   /* depth of refererences */
	int     data;   /* type of data in pdata */
	#define MSG_DAT_EMPTY   0x00    /* pdata is empty */
	#define MSG_DAT_ORIG    0x01    /* pointer to original message */
	#define MSG_DAT_ENCAP   0x02    /* pointer to encapsulating message */
	void        *pdata; /* pointer to misc data */

	msg_delete  mdelete;
	msg_print   print;
	msg_print_body  print_body;
	msg_get_text    get_text;
	msg_get_header  get_header;
	msg_free_text   free_text;
	msg_get_file    get_file;
	msg_update  update;
	msg_validity    validity;
	msg_refresh refresh;
} mail_msg;

/* mail folder */

typedef void (*fld_search_cb) (struct _mail_folder *, long); /* search callback */
typedef char * (*fld_name) (struct _mail_folder *); /* get folder name     */
typedef int (*fld_open) (struct _mail_folder *, int flags); /* open folder */
typedef int (*fld_rescan) (struct _mail_folder *); /* rescan folder    */
typedef void (*fld_close) (struct _mail_folder *);  /* close folder    */
typedef void (*fld_empty) (struct _mail_folder *);  /* empty folder    */
typedef int (*fld_delete) (struct _mail_folder *);  /* delete folder   */
typedef void (*fld_update) (struct _mail_folder *); /* update folder   */
typedef int (*fld_rename) (struct _mail_folder *, char *); /* rename folder */
typedef int (*fld_move) (struct _mail_msg *, struct _mail_folder *); /* move message to folder */
typedef struct _mail_msg * (*fld_copy) (struct _mail_msg *, struct _mail_folder *); /* copy message to folder */
typedef int (*fld_search) (struct _mail_folder *, char *, char *,int, fld_search_cb); /* search in folder */
typedef long (*fld_uid) (struct _mail_folder *);
typedef struct _mail_msg * (*fld_getmsg) (struct _mail_folder *, long uid); /* return message with specified UID */
typedef int (*fld_refresh) (struct _mail_folder *); /* refresh folder */
typedef int (*fld_expunge) (struct _mail_folder *); /* expunge folder */

typedef struct _mail_folder {
	char fold_path[255];    /* path of folder directory */
	char *sname;        /* short name (usualy derived from path) */
	char *descr;        /* short description */
	unsigned long num_msg;      /* number of messages in the folder */
	unsigned long unread_num;   /* number of unread messages in the folder */
	char    hdelim;     /* hierarchy delimiter */
	struct _mail_msg *messages; /* pointer to messages */
	int sort;       /* sort (-1 - default)         */
	int color;      /* color (-1 - default)        */
	int expire;     /* expire old messages (<= 0 don't expire) */
	struct _mail_addr *From;/* default From: address */
	struct _mail_addr *To;	/* default To: address */
	long uid;       /* unique id */
	void *cache;        /* cache info */
	void *spec;     /* type-specific info */
	struct _mail_folder *pfold; /* parent folder */
	struct _mail_folder **subfold;  /* subfolders, if any */
	int level;      /* nesting level */
	int type;       /* folder type */
	#define F_MH    0x0001  /* local MH-style folder */
	#define F_IMAP  0x0002  /* remote (IMAP) folder. */
	#define F_NEWS  0x0004  /* NEWS folder. Not supported yet */
	#define F_MBOX  0x0008  /* local Unix mailbox    */
	int flags;      /* folder flags (permanent) */
	#define FMARKED 0x0001  /* marked */
	#define FNCOUNT 0x0002  /* don't count unread messages in this folder */
	#define CACHED  0x0004  /* cached folder */
	#define FNTRASH 0x0008  /* line NOTRASH but not a trash folder */
	#define FSHRECP 0x0010  /* show recipient instead of sender */
	#define FCHECK  0x0020  /* check the folder periodically */
	#define FEXPND  0x0040  /* show all subfolders */
	#define FRKEEP  0x0080  /* keep reply in the same folder */
	#define FNVALD  0x0100  /* don't validate cached messages */
	int status;     /* folder status */
	#define SYSTEM  0x00000001   /* system folder , can not be deleted or renamed */
	#define SORTED  0x00000002   /* messages are sorted */
	#define OPENED  0x00000004   /* folder is opened */
	#define SEARCH  0x00000008   /* folder contains messages marked during search */
	#define FRONLY  0x00000010   /* read only folder */
	#define NOINFR  0x00000020   /* no inferiors (subfolders) */
	#define FHIDDN  0x00000040   /* hidden folder */
	#define NOTRASH 0x00000080   /* don't move messages to trash */
	#define FRESCAN 0x00000100   /* folder contents has changed, update required */
	#define FSHORTH 0x00000200   /* parse only part of message headers */
	#define FMRKTMP 0x00000400   /* marked temporarily */
	#define FUNREAD 0x00000800   /* only unread messages are opened */
	#define FREMOTE 0x00001000   /* remote (IMAP, NEWS, etc...) folder */
	#define FLOCKED 0x00002000   /* locked folder (MBOX) */
	#define FREWRTE 0x00004000   /* needs to be rewritten (MBOX) */
	#define FNOCLSE 0x00008000   /* don't close (don't discard messages) */
	#define FDUMMY  0x00010000   /* dummy folder, can not be manipulated */
	#define FSKIP   0x00020000   /* skip (don't show) the folder */
	#define FRECNT  0x00040000   /* contains recently retrieved messages */
	#define FALIAS  0x00080000   /* sname is an alias */
	#define FNSCAN  0x00100000   /* don't rescan folder */
	#define FEXPNG  0x00200000   /* EXPUNGE when deselection/closing (IMAP) */
	#define FNOMOD  0x00400000   /* don't modify (ask if modify) */
	#define FTOP    0x00800000   /* top folder of the hierarchy */
	#define FSUBS   0x01000000   /* subscribed folder */
	/* folder manipulation functions */
	fld_name    name;
	fld_open    open;
	fld_rescan  rescan;
	fld_close   close;
	fld_empty   empty;
	fld_delete  fdelete;
	fld_update  update;
	fld_rename  rename;
	fld_move    move;
	fld_copy    copy;
	fld_search  search;
	fld_uid     getuid;
	fld_getmsg  getmsg;
	fld_refresh refresh;
	fld_expunge expunge;
} mail_folder;

/* how to open folder */
	#define FOPEN_UNREAD    0x01    /* unread messages only */
	#define FOPEN_NOCACHE   0x02    /* don't use cache      */
	#define FOPEN_CRCACHE   0x04    /* create the cache     */
	#define FOPEN_NOCLOSE   0x08    /* don't close already opened folder */

/* hash table entry */
typedef struct _ht {
	struct _mail_msg *msg;
	char *id;
	int next;
} ht_t;

/* flag structure */
typedef struct _flag {
	int mask;  /* and mask to apply */
	int result;    /* result after applying the mask */
	char name[16]; /* flag name */
} flag;

/* incorporate mail rule data structure */
typedef struct _xf_rule {
	char name[16];      /* rule name */
	char fmatch[MAX_FIELD_NAME_LEN]; /* field to look in the mail header */
	char tmatch[255];   /* text to match in the field (regexp) */
	char data[64];      /* misc data */
	u_int action;       /* what to do with the message */
	#define R_DISCARD   0x01    /* delete it */
	#define R_MOVE      0x02    /* move to folder specified in data */
	#define R_FORWARD   0x03    /* forward to address specified in data */
	#define R_VACATION  0x04    /* reply with vacation messages */
	#define R_RESEND    0x05    /* resend message */
	#define R_EXECUTE   0x06    /* execute program/script with message */
	#define RULE_MAXACTION  0x06

	u_int flags;        /* special flags */
	#define CASE_I      0x0001  /* case insensitive ( only on regexp ) */
	#define R_VAC_KEEP  0x0002  /* don't delete message */
	#define R_SAVE_ADDR 0x0004  /* save addresses in address book */
	#define R_MARK_READ 0x0008  /* mark matching message as read */
	#define R_SILENT    0x0010  /* don't count if incoming message */
	#define R_NINCOMING 0x0020  /* apply by special request */
	#define R_LOG       0x0040  /* log when matches */
	#define R_OUTGOING  0x0080  /* outgoing rule */
	#define R_EMODIFY   0x0100  /* allow external program to modify msg. */

	#ifdef HAVE_REGCOMP
	regex_t rx;     /* compiled regular expression */
	#endif
} xf_rule;

/* rules functions */

/* load rules database from file */
/* returns 0 on success and -1 on error */
int load_rules( );

/* saves rules database to file */
/* returns 0 on success and -1 on error */
int save_rules( );

/* initialize rule structure */
void init_rule(struct _xf_rule *rule);

/* check if msg matches <rule> */
/* returns 1 if match is successfull and 0 if not */
int match_rule(struct _mail_msg *msg, struct _xf_rule *rule);

/* check msg against all rules and act accordingly */
/* if delay > 0 all operations are delayed */
/* returns -1 on exit, 0 on success, and 1 on success */
/* if the message should not be counted as incoming */
int apply_rule(struct _mail_msg *msg, int delay);

/* update rules after a folder rename */
void rule_rename_folder(struct _mail_folder *newfolder, char *oldname);

/* return array location matching rule name */
int rule_by_name(char *rname);

int cleanup_rules();
/* --------------- */

/* mmap stuff */
	#ifdef MMAP_MSG

/* ftell analog for mmapped message */
long mmtell(FILE *stream);

/* fseek analog for mmapped message */
int mmseek(FILE *stream ,long offset, int whence);

/* fgets analog for mmapped message */
char *mmgets(char *str, size_t size, FILE *stream);

		#define msg_tell    mmtell
		#define msg_seek    mmseek
		#define msg_gets    mmgets

extern char *mmsg;      /* mmapped message */
extern long mmpos;              /* position in msg */
extern long mmlen;              /* length of mmapped block */
extern long mmmax;      /* max. length of mmaped part (for autoincrement) */
extern long mmofft;     /* offset from beginning of the message */
extern int  mmapfd;     /* mmaped file descriptor */

	#else

		#define msg_tell    ftell
		#define msg_seek    fseek
		#define msg_gets    fgets

	#endif

/* cache stuff */

	#define CACHE_DIR   ".cache"    /* directory with cached messages */
	#define CACHE_MAGIC 0x7f7f0005  /* cache file magic identifier */

/* initialize cache */
int init_cache();

/* close folder's cache */
void close_cache(struct _mail_folder *folder);

/* delete cache file */
void delete_cache(struct _mail_folder *folder);

/* rename cache file */
void rename_cache(struct _mail_folder *folder, char *oldsname);

/* returns 1 if cache file exists and not-empty , and 0 otherwise */
int exists_cache(struct _mail_folder *folder);

/* put message into cache. returns -1 on error and 0 on success */
int cache_msg(struct _mail_msg *msg);

/* retrieve message from cache */
struct _mail_msg *msg_cache(struct _mail_folder *folder, long uid);

/* delete message from cache */
void msg_cache_del(struct _mail_msg *msg);

/* delete message with uid from cache */
void msg_cache_deluid(struct _mail_folder *folder, long uid);
/* ----------- */

/* MIME stuff  */

/* field names */

	#define MIME_C_TYPE "Content-Type"
	#define MIME_C_ENCR "Content-Transfer-Encoding"
	#define MIME_C_DESCR    "Content-Description"
	#define MIME_C_ID   "Content-ID"
	#define MIME_C_LENGTH   "Content-Length"
	#define MIME_C_DISP "Content-Disposition"
	#define MIME_VERSION    "MIME-Version"

	#define MIME_VERS_SUPP  10  /* supported MIME version */

/* encodings */
	#define CE_NONE     0x00    /* No encoding */
	#define CE_7BIT     0x01    /* 7 bit ASCII text */
	#define CE_QPRT     0x02    /* quoted-printable encoding */
	#define CE_BASE64   0x03    /* base64 encoding */
	#define CE_8BIT     0x04    /* 8 bit ASCII text */
	#define CE_BINARY   0x05    /* binary information */
	#define CE_UNSUPPORTED  0xff    /* unsupported encoding */

/* encoding function. Should be called with NULL as a string to initalize */
/* and for finish encoding , int parameter represents length of encoding */
/* buffer */
/* returns encoded ASCII string */
typedef char * (*fn_encode) (char *, int);

/* Decoding function. Should be called with NULL as a string to initialize */
/* and for finish decoding , int * parameter returns length of the decoding */
/* buffer */
/* returns decoded binary buffer */
typedef char * (*fn_decode) (char *, int *);

/* Base64 encoding/decoding */
char *base64_encode(char *str, int len);
char *base64_decode(char *str, int *len);

/* Quoted-printable encoding/decoding */
char *qprt_encode(char *str, int len);
char *qprt_decode(char *str, int *len);

/* Dumb encoding/decoding. Used for binary , unsupported and when there is */
/* no encoding at all */
char *dumb_encode(char *str, int len);
char *dumb_decode(char *str, int *len);

/* 7bit encoding/decoding */
/* Encoding strips 8's bit and breaks long lines */
/* Decoding does nothing */
char *sevenbit_encode(char *str, int len);
char *sevenbit_decode(char *str, int *len);

/* 8bit encoding/decoding */
/* Encoding breaks long lines , decoding does nothing */
char *eightbit_encode(char *str, int len);
char *eightbit_decode(char *str, int *len);

typedef struct _mime_encoding {
	u_int c_trans_enc;      /* Content-transfer-encoding */
	char *encoding_name;        /* name of the method in the ce field */
	fn_encode ce_enc;       /* encoding function */
	fn_decode ce_dec;       /* decoding function */
	u_int str_len;          /* max string length */
} mime_encoding;

/* supported character sets */
/* need to be defined in mime.c charset table */

	#define US_ASCII    0x00
	#define ISO_8859_1  0x01
	#define ISO_8859_2  0x02
	#define ISO_8859_3  0x03
	#define ISO_8859_4  0x04
	#define ISO_8859_5  0x05
	#define ISO_8859_6  0x06
	#define ISO_8859_7  0x07
	#define ISO_8859_8  0x08
	#define ISO_8859_9  0x09
	#define ISO_8859_10 0x0a
	#define ISO_8859_13 0x0d
    #define ISO_8859_14 0x0e
    #define ISO_8859_15 0x0f
    #define KOI8R       0x10
	#define CHAR_UNKNOWN    0xff

typedef char * (*charset_encode) (char *);
typedef char * (*charset_decode) (char *);

typedef struct _mime_charset {
	u_int charset_code;     /* Code of the charset */
	char *charset_name;     /* Name of the charset */
	char *charset_descr;        /* Description of the charset */
	charset_decode decode;      /* Decode function     */
	charset_encode encode;      /* Encode function     */
	u_int flags;            /* special flags       */
	#define CHARSET_FIXED   0x01        /* can not be deleted */
} mime_charset;

struct _mime_mailcap;

typedef struct _mime_msg {
	long m_start;           /* start offset */
	long m_end;         /* end offset */
	char *src_info;         /* source info (file name) */

	u_int mime_vers;        /* MIME version */

	struct _mime_mailcap  *mailcap; /* pointer to mailcap */
	struct _mime_encoding *encoding;/* pointer to encoding structure */
	struct _mime_charset  *charset; /* pointer to charset structure */

	char *c_id;         /* Content-ID */
	char *c_descr;          /* Contet-Description */
	long c_len;         /* Content-Length */

	struct _head_field *m_fields;   /* MIME fields */
	struct _mime_msg *mime_next;    /* next mime header (if multipart) */
	char *boundary;         /* Boundary (if multipart) */

	u_int flags;            /* MIME flags */
	#define PREAMBLE    0x0001      /* multipart preamble */
	#define EPILOG      0x0002      /* multipart epilog */
	#define ATTACHMENT  0x0004      /* multipart attachment */
	/* modifiers */
	#define TEXT_PART   0x0008      /* visible part in multipart */
	#define MSG_BODY    0x0010      /* takes all message body */
	#define FILE_TEMP   0x0020      /* attached file should be removed */
	#define PGP_PART    0x0040      /* part encoded with PGP */
	#define LOCK_PART   0x0080      /* part locked by viewer */
	#define DELETE_PART 0x0100      /* part to be deleted */
} mime_msg;

typedef int (*mcap_view) (struct _mail_msg *, struct _mime_msg *);
typedef int (*mcap_print) (struct _mail_msg *, struct _mime_msg *);
typedef int (*mcap_process) (struct _mail_msg *, struct _mime_msg *);

/* Supported Content-types */

	#define CTYPE_DEFAULT       0x00    /* Always matches */
	#define CTYPE_TEXT      0x01    /* text */
	#define CTYPE_MULTIPART     0x02    /* multipart */
	#define CTYPE_MESSAGE       0x03    /* message */
	#define CTYPE_APPLICATION   0x04    /* application */
	#define CTYPE_IMAGE     0x05    /* image */
	#define CTYPE_VIDEO     0x06    /* video */
	#define CTYPE_AUDIO     0x07    /* audio */
	#define CTYPE_EXTERNAL      0xfe    /* external type */
	#define CTYPE_UNSUPPORTED   0xff    /* unsupported */

/* Supported Content-subtypes */
	#define CSUBTYPE_DEFAULT    0x00    /* Always matches */
/* text */
	#define CSUBTYPE_PLAIN      0x01    /* plain */
	#define CSUBTYPE_RTF        0x02    /* richtext */
	#define CSUBTYPE_HTML       0x03    /* richtext */
/* multiparts */
	#define CSUBTYPE_MIXED      0x04    /* mixed */
	#define CSUBTYPE_ALTERNATIVE    0x05    /* alternative */
	#define CSUBTYPE_DIGEST     0x06    /* digest */
	#define CSUBTYPE_PARALLEL   0x07    /* parallel */
	#define CSUBTYPE_REPORT     0x08    /* report */
	#define CSUBTYPE_ENCRYPTED  0x09    /* encrypted */
	#define CSUBTYPE_SIGNED     0x0a    /* signed */
/* message */
	#define CSUBTYPE_RFC822     0x0b    /* rfc822 */
	#define CSUBTYPE_PARTIAL    0x0c    /* partial */
	#define CSUBTYPE_EXTBODY    0x0d    /* external-body */
/* application */
	#define CSUBTYPE_OSTREAM    0x0e    /* octet-stream */
	#define CSUBTYPE_PSCRIPT    0x0f    /* PostScript */
	#define CSUBTYPE_PGP        0x10    /* PGP */
	#define CSUBTYPE_PGPSIG     0x11    /* PGP signed */
	#define CSUBTYPE_PGPENC     0x12    /* PGP encrypted */
	#define CSUBTYPE_PGPKEYS    0x13    /* PGP keys */
/* image */
	#define CSUBTYPE_GIF        0x14    /* gif */
	#define CSUBTYPE_JPEG       0x15    /* jpeg */
/* audio */
	#define CSUBTYPE_BASIC      0x16    /* basic */
/* video */
	#define CSUBTYPE_MPEG       0x17    /* mpeg */

	#define CSUBTYPE_EXTERNAL   0xfe    /* external subtype */
	#define CSUBTYPE_UNSUPPORTED    0xff    /* unsupported */

typedef struct _mime_mailcap {
	u_int   type_code;      /* type code */
	char    type_text[16];      /* type name */
	u_int   subtype_code;       /* subtype code */
	char    subtype_text[16];   /* subtype name */

	mcap_view   view;       /* view function */
	mcap_print  print;      /* print function */
	mcap_process    process;    /* process function */

	char    *ext_mcap;      /* any external info */
	char    ext[5];         /* default file extension */
	u_int   encode;         /* default encoding type */
} mime_mailcap;

/* MIME variables */

extern struct _mime_mailcap  mailcap[];       /* system mailcap */
extern struct _mime_encoding supp_encodings[]; /* supported encodings */
extern struct _mime_charset  supp_charsets[];  /* supported charsets */
extern const char sevenbit_chars[]; /* characters<32 that are allowed in 7bit */

extern u_int    def_charset;            /* default character set */
extern u_int    def_encoding;           /* default MIME encoding */

	#define DEFAULT_MAILCAP         0x00        /* pointer to text/plain      */
	#define HTML_MAILCAP        0x02        /* pointer to text/html       */
	#define MULTIPART_MAILCAP       0x04        /* pointer to multipart/mixed */
	#define MULTIPART_ENCRYPTED     0x09        /* pointer to multipart/encrypted */
	#define MULTIPART_SIGNED        0x0a        /* pointer to multipart/signed*/
	#define MESSAGE_MAILCAP     0x0c        /* pointer to message/rfc822  */
	#define BINARY_MAILCAP      0x10        /* pointer to application/octet-stream */
	#define PGP_MAILCAP     0x12        /* pointer to application/pgp */
	#define PGPSIG_MAILCAP      0x13        /* pointer to application/pgp-signed */
	#define PGPENC_MAILCAP      0x14        /* pointer to application/pgp-encrypted */
	#define PGPKEYS_MAILCAP     0x15        /* pointer to application/pgp-keys */

	#define TEXT_ENCODING           0x01        /* pointer to 7bit */
	#define QPRT_ENCODING           0x02        /* pointer to quoted-printable*/
	#define BINARY_ENCODING     0x03        /* pointer to BASE64 */
	#define DEFAULT_ENCODING        0x04        /* pointer to 8bit   */
	#define NO_ENCODING     0x05        /* pointer to binary */
	#define UNSUPPORTED_ENCODING    0x06

	#define DEFAULT_CHARSET         0x00        /* pointer to us-ascii        */
	#define BINARY_CHARSET      0x01        /* pointer to ISO8859-1 */
	#define UNSUPPORTED_CHARSET     0x15

/* MIME functions */

/* extract parameter pname from specific field */
/* returns NULL if such parameter does not exists */
char *get_fld_param(struct _head_field *fld, char *pname);

/* returns version number of MIME protocol used */
u_int get_mime_version(struct _mail_msg *msg);

/* returns 1 if msg is a MIME message and 0 otherwise */
int is_mime(struct _mail_msg *msg);

/* returns 1 is msg has Content-Type field other then text/plain */
int is_mime_msg(struct _mail_msg *msg);

/* returns pointer to mailcap entry with specified type and subtype */
/* if exact == 0 then check wildcard entries and return new mcap */
/* if exact == 1 then check for exact match only and return new mcap */
/* if exact == 2 then check for wildcard entries and return mcap from
  the mailcap table */
/* returns NULL if such entry does not exists */
struct _mime_mailcap *find_mailcap(char *type, char *subtype, int exact);

/* creates new mailcap structure and copies contents of mcap into it */
/* returns NULL is there was not enough memory */
struct _mime_mailcap *copy_mailcap(struct _mime_mailcap *mcap);

/* add mcap structure to table of supported MIME types */
void add_mailcap(struct _mime_mailcap *mcap);

/* load mime types from file */
void load_mailcap();

/* save mime types to file */
void save_mailcap();

/* returns mailcap entry for msg or for mime structure */
/* NULL if it does not exists */
struct _mime_mailcap *get_mailcap_entry(struct _mail_msg *msg, struct _mime_msg *mime);

/* free memory taken by mime structure */
void discard_mime(struct _mime_msg *mime);

/* free memory taken by mailcap structure */
void discard_mcap(struct _mime_mailcap *mcap);

/* searches for field with name str */
/* returns NULL if search failed */
struct _head_field *find_mime_field(struct _mime_msg *mime, char *str);

/* Add field to mime structure */
void add_mime_field(struct _mime_msg *mime, char *name, char *str);

/* Replace field in mime structure */
void replace_mime_field(struct _mime_msg *mime, char *name, char *str);

/* return encoding type either from msg or from mime structure */
/* returns NULL on error or if encoding method is unknown */
struct _mime_encoding *get_mime_encoding(struct _mail_msg *msg, struct _mime_msg *mime);

/* return charset type either from msg or from mime structure */
/* returns NULL on error or if charset is unknown */
struct _mime_charset *get_mime_charset(struct _mail_msg *msg, struct _mime_msg *mime);

/* returns > 0 if ch_name is an alias to already existing charset */
/* and 0 if not. Returns -1 if specified charset does not exists */
/* if it returns > 0 then the return value is index of main charset */
/* + 1 */
int is_charset_alias(char *ch_name);

/* return the character set code given the name
 * return -1 on failure
 */
int charset_code_from_name(char *ch_name);

/* return the character set name given the code.
 * return NULL on failure.
 */
const char *charset_name_from_code(int code);

/* return the character set description, given the code.
 * return NULL on failure.
 */
const char *charset_descr_from_code(int code);

/* add new charset. ch_name - charset name, ch_descr - short description */
/* if ch_code < 0 then new charset will be added , otherwise */
/* an alias to existing charset with code ch_code will be added */
/* returns -1 on errror and 0 on success */
int add_charset(char *ch_name, char *ch_descr, int ch_code);

/* delete charset. ch_name - charset name */
/* returns -1 on errror and 0 on success */
int del_charset(char *ch_name);

/* scan message for MIME attachments */
void mime_scan(struct _mail_msg *msg);

/* debug function */
void print_mime(struct _mime_msg *mime);

/* check if str is a boundary for multipart message */
/* returns 0 if not 1 if it's usuall boundary 2 if it's final boundary */
int is_boundary(char *boundary, char *str);

/* scan one attachment in multipart */
struct _mime_msg *scan_part(char *boundary, FILE *mfd);

/* parse multipart MIME attachment */
int process_multipart(struct _mail_msg *msg, struct _mime_msg *mime);

/* return 1 if mime is a conventional unencoded text message */
int is_mime_text(struct _mime_msg *mime);

/* encode 3 or less characters using base64 encoding */
/* returns NULL on error */
/* len specified how many characters should be encoded */
char *base64_encode_3(char *triplet, int len);

/* decode 4 characters encoded using base64 encryption */
/* return NULL on error */
/* len contains how many characters was decoded */
char *base64_decode_4(char *four, int *len);

/* Save mime part of msg into file. If file is NULL function will */
/* prompt for file name. Returns -1 on error and 0 on success */
int save_part(struct _mail_msg *msg, struct _mime_msg *mime,char *file, u_int flags);
/* possible flags */
	#define SAVEPART_HEADER 0x01    /* save with header */
	#define SAVEPART_APPEND 0x02    /* append to file if it exists */
	#define SAVEPART_CRLF   0x04    /* terminate lines with CRLF */
	#define SAVEPART_CHFILE 0x08    /* ask for filename only if can not find one */
/* in this case file is a directory to save */
	#define SAVEPART_FHDR   0x10    /* save with full message header */
	#define SAVEPART_RAW    0x20    /* don't decode message */

/* view mime part using either internal or external viewer */
/* returns -1 on error and 0 on success */
int view_part(struct _mail_msg *msg, struct _mime_msg *mime);

/* get textual part of the message */
/* returns NULL on error */
struct _mime_msg *get_text_part(struct _mail_msg *msg);

/* get textual part of the message (even encrypted) */
/* returns NULL on error */
struct _mime_msg *get_any_text_part(struct _mail_msg *msg);

/* print header of mime part */
void print_mime_header(struct _mime_msg *mime, FILE *mfd);

/* print combined mime and message header */
void print_mime_msg_header(struct _mime_msg *mime, struct _mail_msg *msg, FILE *mfd);

/* print/view text parts of mime message */
int text_view(struct _mail_msg *msg, struct _mime_msg *mime);
int text_print(struct _mail_msg *msg, struct _mime_msg *mime);

/* view rfc822 */
int msg_view(struct _mail_msg *msg, struct _mime_msg *mime);

/* if mime represents a rfc822 message, extract it and return pointer to it */
struct _mail_msg *get_mime_msg(struct _mail_msg *msg, struct _mime_msg *mime);

/* view digest (and any multipart actually) */
int digest_view(struct _mail_msg *msg, struct _mime_msg *mime);

/* play audio/basic */
int mime_play(struct _mail_msg *msg, struct _mime_msg *mime);

/* view application/pgp */
int pgp_view(struct _mail_msg *msg, struct _mime_msg *mime);

/* view application/pgp-signature */
int pgpsig_view(struct _mail_msg *msg, struct _mime_msg *mime);

/* view application/pgp-encrypted */
int pgpenc_view(struct _mail_msg *msg, struct _mime_msg *mime);

/* view application/pgp-keys */
int pgpkeys_view(struct _mail_msg *msg, struct _mime_msg *mime);

/* Create empty MIME structure */
/* returns NULL if malloc failed */
struct _mime_msg *create_mime();

/* write mime attachment into file */
int write_part(struct _mime_msg *mime, struct _mail_msg *msg, FILE *mfd);

/* write new MIME message instead of msg */
/* returns -1 on error and 0 on success */
int update_mime(struct _mail_msg *msg);

/* assemble and view message/partial */
int assemble_partial(struct _mail_msg *msg, struct _mime_msg *mime);

/* displays and/or if possible retrieves body of message/external-body */
int view_external(struct _mail_msg *msg, struct _mime_msg *mime);

/* decode string according to rfc1522. Returns pointer to decoded */
/* string if it was successfully decoded or NULL if error  */
/* occured or no decoding was required, charset will point to character set */
/* of the message */
char *rfc1522_decode(char *string, int *charset);

/* encodes non-ASCII string according to rfc1522. If charset and/or encoding */
/* are -1 defaults are used. If error occured or string is pure ASCII        */
/* then string itself is returned.                                           */
char *rfc1522_encode(char *string, int charset, int encoding);

/* set descritpion for attachment */
void set_mime_descr(struct _mime_msg *msg, char *descr);

/* returns name of attached file */
/* returns NULL if name can not be extracted */
char *get_mime_fname(struct _mime_msg *mime);

/* returns size of attached file */
/* returns 0 if size can not be extracted */
u_long get_mime_fsize(struct _mime_msg *mime);

/* returns line with full description of supplied mime structure */
char *get_mime_line(int mnum, struct _mail_msg *msg, struct _mime_msg *mime);

/* attach file to msg. mcap is attachment type, if it's NULL then   */
/* application/octet-stream is choosed. encoding is encoding type.  */
/* if -1 then base64 is used. Returns either pointer to new mime    */
/* structure in case of ATT_NOUPDATE or pointer to message mime     */
/* structure otherwise. NULL is returned if error occured           */
struct _mime_msg *attach_file(struct _mail_msg *msg, char *file, struct _mime_mailcap *mcap, int encoding, int flags);

/* attachment flags */
	#define ATT_NOFLAGS 0x00
	#define ATT_NOUPDATE    0x01    /* don't update message */
	#define ATT_NODISPINFO  0x02    /* don't include Contents-Disposition */
	#define ATT_NOFILEINFO  0x04    /* don't include information about the attached file Content-Type */

/* ----------- END of MIME stuff ------------------------------------------- */

/* removes beginning/ending spaces from str */
/* warning: str is modified */
char *rem_tr_space(char *str);

/* removes beginning/ending spaces and quotes from str */
/* warning: str is modified */
char *rem_tr_spacequotes(char *str);

/* returns next word (either quoted or separated by spaces) from the string */
/* *str will point to the next word. warning: str is modified */
char *get_quoted_str(char **str);

/* remove \n (and \r if exists) at the end of string */
/* returns 1 if newline was stripped and 0 if not    */
int strip_newline(char *str);

/* replace all % in string with %% so it can be safely be used in vsprintf */
char *strip_percent(char *str);

/* return name of temporary file */
char *get_temp_file(char *base);

/* replaces all non-printable characters in str to _ */
/* returns 1 if str was modified and 0 otherwise */
int graph_str(char *str);

/* returns number of the months with name at the beginning of str */
/* returns -1 if str is not a valid month name */
int get_month(char *str);

/* returns number of the weekday with name at the beginning of str */
/* returns -1 if str is not a valid weekday name */
int get_day(const char *str);

/* returns offset of timezone from GMT in seconds */
/* returns -1 if timezone is not known */
int get_tz_offt(char *tzname);

/* get difference in seconds between GMT and local TZ */
int get_date_offt();

/* return date in ARPA format */
char *get_arpa_date(time_t t);

/* parses string with date ( mail format ) and returns time in time_t val */
time_t get_date(const char *str);

/* return GMT offset of specified date string */
int parse_offt(const char *str);

/* parse mail address. returns NULL if error or linked list of addresses */
/* if ok */
struct _mail_addr *get_address(const char *str, int flags);
	#define ADDR_IGNORE_COMMAS  0x01    /* treat commas as part of address */
	#define ADDR_GET_FIRST      0x02    /* parse only first address in list */

/* parse Newsgroups list */
struct _news_addr *get_news_addr(char *str);

/* checks if given e-mail address is actually a newsgroup */
/* if strict > 0 only addresses started with #news. are considered newsgroups */
int is_newsgroup_addr(struct _mail_addr *addr, int strict);

/* returns list of newsgroups located in provided mail address list */
/* if strict > 0 only addresses started with #news. are considered newsgroups */
struct _news_addr *expand_news_addr_list(struct _mail_addr *addr, int strict);

/* prints signature file into stream file if signature attachment */
/* is enabled */
void add_signature(struct _mail_msg *msg, FILE *file, int forceattach);

/* adds signature to tfile */
void add_signature_to_msg(struct _mail_msg *msg, char *tfile);

/* adds contents of file to the end of tfile */
/* offt specfies where in the text file should be inserted */
/* if separators is no 0, header and footer lines are added */
void add_file_to_msg(char *tfile, char *file, u_long offt, int separators);

/* include text of original message in reply */
/* if type == 0 each line is prefixed */
/* the text is inserted at offset <offt> */
void insert_orig(char *tfile, struct _mail_msg *msg, int type, u_long offt);

/* extracts the text of the message and puts in file */
/* performs PGP decoding if needed. returns NULL on error */
/* returned filename should be freed, and file unlinked */
char *get_reply_text(struct _mail_msg *msg);

/* reformat included text. ifd, ofd are input/output file descriptors */
/* include indicates how the text should be formatted */
void format_reply_text(struct _mail_msg *msg, FILE *ifd, FILE *ofd,int include);

/* if the message requires reading confirmation returns pointer to */
/* the field which contains address to send the confirmation to    */
/* returns NULL otherwise */
struct _head_field *need_read_confirm(struct _mail_msg *msg);

/* delete notification request from message header */
void delete_read_confirm(struct _mail_msg *msg);

/* send read confirmation message */
void read_confirm(struct _mail_msg *msg);

/* generate reply to msg , if to_all == 0 reply to sender only */
/* to_all == 1 include all according to settings */
/* to_all == 2 include all unconditionally       */
/* if rtextbuf is not NULL then it contains text to be included */
/* returns NULL on error */
struct _mail_msg *get_reply_msg(struct _mail_msg *msg , char *rtextbuf, int to_all);

/* generate forward message, fwdtext specifies the text to be forwarded */
/* (can be NULL). Returns NULL on error. */
struct _mail_msg *get_fwd_msg(struct _mail_msg *msg, char *fwdtext);

/* generate "vacation" message from msg and vacation file */
/* returns NULL on error */
struct _mail_msg *get_vac_msg(struct _mail_msg *msg, char *vfile);

/* returns address with field name <aname> (To, Cc, ...) */
/* returns NULL if such address does not exists */
struct _mail_addr *get_addr_by_name(struct _mail_msg *msg, char *aname);

/* returns character representation of person specified in address */
char *get_addr_line(struct _mail_addr *addr);

/* returns character representation of mail address addr */
char *get_addr_addr(struct _mail_addr *addr);

/* returns full character representation of mail address addr */
char *get_full_addr_line(struct _mail_addr *addr);

/* returns short representation of addr */
char *get_short_addr_line(struct _mail_addr *addr);

/* returns full character representation of mail address addr */
/* takes care of rfc1522 encoding. Charset will return pointer */
/* to appropriate charset structure if exists */
char *get_charset_addr_line(char *prefix,struct _mail_addr *addr, int *charset);

/* parse line in mail header . Always return allocated field structure */
struct _head_field *get_field(const char *str);

/* parse one field in open message file. The field can be split across */
/* multiple lines. Returns NULL on error.                              */
struct _head_field *get_folded_field(FILE *ffd);

/* finds field with name str in header of message msg */
/* returns pointer to found field or NULL if not found */
struct _head_field *find_field(struct _mail_msg *msg, char *str);

/* same as above, but never preloads header into memory */
struct _head_field *find_field_noload(struct _mail_msg *msg, char *str);

/* finds last field in the list with name <str> */
/* returns pointer to found field or NULL if not found */
struct _head_field *find_last_field(struct _mail_msg *msg, char *str);

/* returns text contents of field str in message msg */
/* returns NULL if field str does not exists */
/* returned value of fr indicates how deallocate memory */
char *get_field_content(struct _mail_msg *msg, char *str , int *fr);

/* deallocate memory allocated by get_field_content */
void free_field_content(struct _mail_msg *msg, char *p, int fr);

/* delete field in msg */
void delete_field(struct _mail_msg *msg, struct _head_field *field);

/* delete all fields with specified name */
void delete_all_fields(struct _mail_msg *msg, char *name);

/* add field name and contents str to header of message msg */
void add_field(struct _mail_msg *msg, char *name, char *str);

/* make a copy of field */
/* return NULL on error */
struct _head_field *copy_field(struct _head_field *field);

/* make a copy of field chain */
/* return NULL on error */
struct _head_field *copy_field_chain(struct _head_field *field);

/* replace contents of field name with str */
/* if field does not exists the function acts as add_field */
void replace_field(struct _mail_msg *msg, char *name, char *str);
/* same as above, but never preloads header into memory */
void replace_field_noload(struct _mail_msg *msg, char *name, char *str);

/* convert special fields in msg header to flags */
void convert_fields(struct _mail_msg *msg);

/* parses whole message header. Always returns allocated mail header */
/* structure. mfd is open file descriptor of mail file  */
/* eoh == 0 means that end-of-header was not reached */
/* if H_SHORT set in flags then only short header is parsed */
struct _msg_header *get_msg_header(FILE *mfd, int flags, int *eoh);

/* opens mail message num and parses it */
/* return NULL if error occured */
struct _mail_msg *get_message(long num, struct _mail_folder *folder);

/* allocate and copy message header structure */
struct _msg_header *copy_message_header(struct _msg_header *header);

/* allocate and copy message structure */
struct _mail_msg *copy_msg(struct _mail_msg *msg);

/* copy msg to another folder and return pointer to it */
/* returns NULL on error */
struct _mail_msg *copy_to_folder(struct _mail_msg *msg, struct _mail_folder *fld);

/* compare two messages. */
int compare_msgs(struct _mail_msg **msg1,struct _mail_msg **msg2);

/* compare two folders. */
int compare_folders(struct _mail_folder **folder1, struct _mail_folder **folder2);

/* sort folder by specific criteria */
void sort_folder(struct _mail_folder *folder);

/* sort mailbox's folders */
void sort_folders();

/* search for text in all messages located in folder       */
/* all found messages become marked                        */
/* returns number of messages that contains specified text */
/* or -1 if error ocurred                                  */
int find_text(struct _mail_folder *folder, char *text, char *where, int flags, fld_search_cb callback);

/* append folder to appropriate folder list */
int append_folder(struct _mail_folder *folder, int hidden);

/* remove folder from appropriate folder list */
int remove_folder(struct _mail_folder *folder);

/* allocate new folder structure. return NULL on error */
struct _mail_folder *alloc_folder();

/* allocate new message structure. return NULL on error */
struct _mail_msg *alloc_message();

/* create new message in folder. return NULL on error */
struct _mail_msg *create_message(struct _mail_folder *folder);

/* get new message number in folder */
long get_new_name(struct _mail_folder *folder);

/* returns message file name */
char *get_msg_file(struct _mail_msg *msg);

/* make folder local (MH-style) */
void local_folder(struct _mail_folder *folder);

/* create dummy folder */
void dummy_folder(struct _mail_folder *folder);

/* make message local (MH-style) */
void local_message(struct _mail_msg *msg);

/* open mail folder.  Returns -1 if error occured */
int open_folder(struct _mail_folder *folder, int flags);

/* create new folder with name. If folder is not null make new folder */
/* its subfolder. Returns NULL on error and pointer to new folder    */
/* on success */
struct _mail_folder *create_mh_folder(struct _mail_folder *folder, char *name);

/* rescans mail folder. Returns -1 if error occured */
/* and 0 otherwise */
int rescan_folder(struct _mail_folder *folder);

/* check folder for new messages and retrieve them if the folder is opened */
/* returns -1 on error 0 if there are no new messages and 1 if new */
/* messages was found */
int refresh_folder(struct _mail_folder *folder);

/* expunge deleted messages in folder */
/* returns 0 on success and -1 on error */
int expunge_folder(struct _mail_folder *folder);

/* Close folder. All memory allocated for messages is freed */
void close_folder(struct _mail_folder *folder);

/* deallocated memory taken by message header */
void discard_message_header(struct _mail_msg *msg);

/* deallocated memory taken by message msg */
void discard_message(struct _mail_msg *msg);

/* deallocated memory taken by addr */
void discard_address(struct _mail_addr *addr);

/* deallocated memory taken by addr */
void discard_news_address(struct _news_addr *addr);

/* deallocated memory taken by folder */
void discard_folder(struct _mail_folder *folder);

/* creates new addr structure and copies contents of addr to it */
struct _mail_addr *copy_address(struct _mail_addr *addr);
struct _news_addr *copy_news_address(struct _news_addr *addr);

/* duplicates contents of whole address chain addr and returns pointer */
/* to it */
struct _mail_addr *copy_address_chain(struct _mail_addr *addr);
struct _news_addr *copy_news_address_chain(struct _news_addr *addr);

/* get text of message from disk */
/* if mime is specified only this part is being retrieved */
/* returns 0 on success */
int get_message_text(struct _mail_msg *msg, struct _mime_msg *mime);

/* returns OS's pagesize. needed for calculating offset for mmap */
int xfmail_getpagesize();

/* read full message header into memory if only part of it was parsed */
/* returns -1 on error and 0 on success */
int get_message_header(struct _mail_msg *msg);

/* get validity number of MH message */
unsigned long get_message_validity(struct _mail_msg *msg);

/* refresh message from disk/server */
/* returns -1 on error and 0 on success */
int refresh_message(struct _mail_msg *msg);

/* frees (unmaps) memory allocated for message text */
void free_message_text(struct _mail_msg *msg);

/* check if field fld should be stripped when sending message */
int strip_when_send(struct _head_field *fld);

/* print message with header to stream file */
/* if send - do not print STATUS and Sender fields and encode header*/
int print_message(struct _mail_msg *msg,  FILE *file, int send);

/* returns printer command line */
char *get_print_command(char *file);

/* send message msg to printer */
void lpr_message(struct _mail_msg *msg);

/* print mail address to stream file */
/* if charset == -2 the addresses and subject will not be encoded with */
/* rfc1522, if charset == -1 the default charset during encoding will */
/* be used, otherwise charset is an index in supp_charsets[] array */
void print_addr(struct _mail_addr *addr, char *str, FILE *file, int charset);

/* print newsgroups list to stream file */
void print_news_addr(struct _news_addr *addr, char *str, FILE *file);

/* print message header to stream file */
void print_message_header(struct _mail_msg *msg,  FILE *file);

/* print field to stream file */
void print_header_field(struct _head_field *fld,  FILE *file, int encode);

/* print message text to stream file */
int print_message_body(struct _mail_msg *msg,  FILE *file);

/* send message msg, return 0 on success */
int send_message(struct _mail_msg *msg);

/* send message msg using sendmail, return 0 on success */
int sendmail_send_message(struct _mail_msg *msg);

/* send message msg using POP, return 0 on success */
int pop_send_message(struct _pop_src *pop, struct _mail_msg *msg);

/* send message msg using smtp */
void * smtp_send_message(void * arg);

/* send message msg using nntp, return 0 on success */
/* and -1 on error */
int nntp_send_message(struct _mail_msg *msg);

/* send msg to the sock m_out */
/* returns -1 on error */
int smtp_message(struct _mail_msg *msg, FILE *m_out);

/* update message access and modification times according to UNREAD flag */
void touch_message(struct _mail_msg *msg);

/* evaluates length of message and its header and stores */
/* this values in the mail structure */
void update_message_length(struct _mail_msg *msg);

/* Update STATUS field of mail message on disk */
void update_message_status(struct _mail_msg *msg);

/* updates text of the message */
/* returns -1 on error and 0 on success */
int update_message_text(struct _mail_msg *msg , char *text);

/* places contents of file (- stdin) into message body */
/* returns -1 on error and 0 on success */
int set_message_text(struct _mail_msg *msg , char *file);

/* replace the whole message (including header) with contents of given file */
/* (- stdin). returns -1 on error and 0 on success */
int set_message_file(struct _mail_msg *msg , char *file);

/* Updates and saves message on disk */
/* returns -1 on error and 0 on success */
int update_message(struct _mail_msg *msg);

/* Update folder messages */
void update_folder(struct _mail_folder *folder);

/* scans all folders in a mailbox, uses default mailbox if it's not specified */
/* creates mailbox if it does not exists. initializes mailbox */
/* and folder_num variables. returns -1 on errror 0 on success  */
/* creates inbox/outbox/trash folders if does not exists */
/* if noscan > 0 only system folders are created */
int open_all_folders(char *mailbox, int noscan);

/* closes all folders and frees all memory allocated for them */
void close_all_folders();
void discard_all_folders();

/* incorporate messages from spool file according to rules */
/* returns number of messages actually incorporated or -1 on error */
/* notify returns number of message which require sound/visual */
/* notification */
long mbox_inc_mail(struct _retrieve_src *source, long *notify);

/* incorporate messages from POP server according to rules */
/* returns number of messages actually incorporated or -1 on error */
/* notify returns number of message which require sound/visual */
/* notification */
long pop_inc(struct _retrieve_src *source, long *notify);

/* retrieve message body from POP server if previosly only header */
/* was retrieved. Returns -1 on error and 0 on success */
int pop_getfull_msg(struct _pop_src *pop, struct _mail_msg *msg);

/* delete message on the server if previously only header was retrieved */
/* Returns -1 on error and 0 on success */
int pop_delmsg_by_uidl(struct _pop_src *pop, struct _mail_msg *msg);

/* initialize POP server connection (connect and log in) */
/* Returns -1 on error and 0 on success */
int pop_init(struct _pop_src *pop);

/* close connection to POP server */
void pop_end(struct _pop_src *pop);

/* connects to remote host and returns socket file descriptor       */
/* hostname - remote host name (IP or DNS name) - default localhost */
/* service - service name or port number - default pop3             */
/* protocol - protocol name - default tcp(others are not supported) */
int host_connect(char *hostname, char *service, char *protocol);

/* disconnect from host. */
/* sock is a pointer to a connection socket */
void host_disconnect(int sock);

/* returns appropriate hostent for given hostname */
/* could be DNS name or IP address                */
extern "C" struct hostent *gethostbystring(char *host);

/* get string from file descriptor iop        */
/* result is stored in str                    */
/* returns NULL on error and string on success*/
/* if len < 0 then string is allocated , but  */
/* not more then abs(len) bytes               */
char * getline(char *str, int len, FILE *iop);

/* get len bytes from iop followed by CRLF      */
/* if ofile is not NULL output everything to it */
/* otherwise store result in str                */
/* returns -1 on error and 0 on success         */
int getdata(char *str, long len, FILE *iop, FILE *ofile);

/* send string str to stream associated with file descriptor */
/* iop. Returns -1 on error.                                 */
int putline(char *str, FILE *iop);

/* put len bytes from string s or file ifile to socket iop */
/* otput is followed by CRLF                               */
/* returns -1 on error and 0 on success                    */
int putdata(char *str, int len, FILE *iop, FILE *ifile);

/* returns name of given mail folder */
char *get_folder_name(struct _mail_folder *folder);

/* returns short name of given mail folder */
char *get_folder_short_name(struct _mail_folder *folder);

/* returns full name of given mail folder */
char *get_folder_full_name(struct _mail_folder *folder);

/* unique short name */
char *get_folder_unique_name(struct _mail_folder *folder);

/* returns pointer to a folder with given name , NULL if such */
/* folder does not exists */
struct _mail_folder *get_folder_by_name(char *name);

/* returns pointer to MH folder with given name , NULL if such */
/* folder does not exists */
struct _mail_folder *get_mh_folder_by_name(char *name);

/* returns pointer to MH folder with given path , NULL if such */
/* folder does not exists */
struct _mail_folder *get_mh_folder_by_path(char *path);

/* move message to specified folder */
int move_to_folder(struct _mail_msg *msg, struct _mail_folder *folder);

/* remove message from folder's linked list */
/* return 1 if message was found and removed and 0 otherwise */
int unlink_message(struct _mail_msg *msg);

/* delete message msg from memory and disk */
/* return -1 on error and 0 on success */
int delete_message(struct _mail_msg *msg);

/* delete all message in folder */
void empty_folder(struct _mail_folder *folder );

/* removes folder and all messages in it from memory and from disk */
/* returns -1 on error and 0 on success */
int delete_folder(struct _mail_folder *folder);

/* renames folder to name */
/* returns -1 on error , 0 on success */
int rename_folder(struct _mail_folder *folder , char *name);

/* extracts directory name from path */
char *dir_path(char *path);

/* extracts file name from path */
char *name_path(const char *path);

/* returns index of folder in mailbox, 0 if not found */
int get_folder_index(struct _mail_folder *folder);
int get_folder_index_noskip(struct _mail_folder *folder);

/* returns pointer to folder with index index */
struct _mail_folder *get_folder_by_index(int index);
struct _mail_folder *get_folder_by_index_noskip(int index);

/* returns index of message in folder, 0 if not found */
long get_msg_index(struct _mail_folder *folder , struct _mail_msg *msg);

/* returns pointer to message in folder folder with index index */
struct _mail_msg *get_msg_by_index(struct _mail_folder *folder, long index);

/* returns pointer to message in folder folder with specific uid */
struct _mail_msg *get_msg_by_uid(struct _mail_folder *folder, long uid);

/* returns message with closest smaller uid then <muid> */
/* returns NULL if message with such uid does not exists */
struct _mail_msg *get_smaller_uid(struct _mail_folder *folder, long muid);

/* returns message with closest larger uid then <muid> */
/* returns NULL if message with such uid does not exists */
struct _mail_msg *get_larger_uid(struct _mail_folder *folder, long muid);

/* obtain the biggest message UID in folder */
long get_max_uid(struct _mail_folder *folder);

/* expands string str according to % directives and contents of message msg */
/* length of str should be sufficient to contain all the expanded string */
void expand_str(struct _mail_msg *msg, char *str);

/* set message flags according to Status field in header */
void set_flags_by_status(struct _mail_msg *msg);

/* set Status field in header according to the message flags */
void set_status_by_flags(struct _mail_msg *msg);

/* checks if c represents one of iso-8859-8 hebrew characters */
int ishebrew(u_int c);

/* converts str according to hebrew rules (right to left) */
char *hebrew_conv(char *str);

/* calculate real message len replacing CR with CRLF */
long calc_msg_len(struct _mail_msg *msg);

/* count total number of recipients in To,Cc and Bcc fields */
int count_recipients(struct _mail_msg *msg);

/* ------- IMAP stuff ------------ */

/* connect to IMAP server and initialize all folders */
/* returns -1 on error and 0 on success */
int imap_init(struct _imap_src *imap);

/* disconnect from IMAP server */
void imap_close(struct _imap_src *imap, int bygui);

/* returns 1 if connection to IMAP server exists and 0 otherwise */
int imap_isconnected(struct _imap_src *imap);

/* returns number of established IMAP connections */
int imap_connected();

/* find IMAP folder by full name */
/* returns pointer to folder if found and NULL if not */
struct _mail_folder *find_imap_folder(struct _imap_src *imap, char *name);

/* find IMAP folder by name */
/* returns pointer to folder if found and NULL if not */
struct _mail_folder *find_imap_folder_by_name(struct _imap_src *imap, char *name);

/* return path of IMAP folder */
/* returns NULL if path does not exists */
char *get_imap_folder_path(struct _imap_src *imap, struct _mail_folder *folder);

/* returns short name of IMAP folder */
char *get_imap_folder_short_name(struct _imap_src *imap, struct _mail_folder *folder);

/* mark folder as IMAP */
void imap_folder(struct _imap_src *imap, struct _mail_folder *folder);

/* mark message as IMAP */
void imap_message(struct _imap_src *imap, struct _mail_msg *message);

/* delete all IMAP folders and free all memory used by them and thei messages */
/* all locked messages are being relocated to FTEMP */
void discard_imap_folders(struct _imap_src *imap);

/* create new IMAP folder with given name */
/* returns pointer to new folder on success and NULL on error */
struct _mail_folder *create_imap_folder(struct _imap_src *imap, struct _mail_folder *folder,char *name);

/* inactivity timer callback */
void imap_timer_cb();

/* retrieve mail from IMAP */
/* notify returns number of message which require sound/visual */
/* notification */
long imap_inc(struct _retrieve_src *source, long *notify);

/* EXPUNGE messages in given IMAP folder (if needed) */
int imap_folder_expunge(struct _mail_folder *folder);

/* save all folders from connected servers */
void save_imap_folders();

/* close connection to all servers */
void imap_close_all(int bygui);

/* returns IMAP connection structure for specific account (if connected) */
/* if name is NULL then any IMAP account with established connection */
/* is returned */
struct _imap_src *get_imap_connection(char *name);

/* ------------------------------------- */

/* returns first found unread msg */
struct _mail_msg *get_unread_msg();

/* returns total number of unread messages in all folders */
unsigned long get_total_unread();

/* returns id of folder , -1 on error */
long get_mh_folder_uid(struct _mail_folder *folder);

/* load folder configuration, if ffile != NULL it's used as file */
/* extension (after -). Returns -1 on error and 0 on success.    */
int load_folders_conf(char *ffile);

/* save folder configuration, if ffile != NULL it's used as file   */
/* extension (after -). If ftype > 0 only folders of this type are */
/* saved. Returns -1 on error and 0 on success.                    */
int save_folders_conf(char *ffile, int ftype);

/* get string which represents message's location */
/* returns NULL on error */
char *get_msg_url(struct _mail_msg *msg);

/* returns message with location <url> */
/* returns NULL on error */
struct _mail_msg *get_msg_by_url(char *url);

/* checks if some messages in opened folder need to be expired */
/* and performs expiration. Returns -1 on erro and number of expired */
/* messages on success */
int expire_msgs(struct _mail_folder *folder);

/* set sent/receive dates of the message */
/* dates are set only if they are > 0 */
void set_msg_date(struct _mail_msg *msg, time_t rdate, time_t sdate);

/* checks if given header field has any special meeaning */
/* (i.e. handled internally by XFMail */
/* returns 1 if yes and 0 if not */
int is_spechdr(struct _head_field *hf);

/* returns string which represents message priority */
char *get_msg_priority_name(struct _mail_msg *msg);

/* returns number which represents message priority */
int get_msg_priority(struct _mail_msg *msg);

/* set X-Priority and Priority headers according to message flags*/
void set_priority_by_flags(struct _mail_msg *msg);

/* set priority flags accordinf to X-Priority and Priority headers */
void set_priority_by_headers(struct _mail_msg *msg);

/* returns pointer to the folder which is being used for storing */
/* files of the message of specified type */
struct _mail_folder *get_file_folder(struct _mail_msg *msg);

/* returns 1 if addr matches one of our own e-mail addresses */
int addr_is_us(struct _mail_msg *msg, struct _mail_addr *addr);

/* set MTOUS/MFROMUS on all messages in folder which are sent */
/* directly from/to us */
void mark_to_us(struct _mail_folder *folder);

/* remove all messages marked as non-existent from folder's message list */
void remove_nonexistent(struct _mail_folder *folder);

/* pipe message to shell command */
/* returns 0 on success and -1 on failure */
int pipe_msg(struct _mail_msg *msg, char *command);

/* update paths of subfolders if path of parent folder has been changed */
void update_cfold_path(struct _mail_folder *folder);

/* add folder to Fcc list. Return -1 on error and 0 on success */
int add_fcc_list(struct _msg_header *msgh, struct _mail_folder *folder);

/* return folder pointed by fptr from Fcc list */
/* Returns -1 on error and 0 on success */
int del_fcc_list(struct _mail_msg *msg, char *fptr);

/* returns next folder from Fcc list */
/* returns NULL if Fcc list is empty or we've reached the end of the list */
char *scan_fcc_list(struct _mail_msg *msg, char *fptr);

/* parse and append supplied comma-separated Fcc list */
void parse_fcc_list(struct _msg_header *msgh, char *fcclist);

/* print Fcc list in header format */
void print_fcc_list(struct _mail_msg *msg, FILE *fcc);

/* copy message to folders according to Fcc list */
/* returns -1 on error and 0 on success */
int process_fcc_list(struct _mail_msg *msg);

typedef struct _url_spec {
	int url_s, url_e;
	struct _url_spec *next;
} url_spec;

/* highlight (find) all URLs in supplied string */
/* returns linked list of found URLs or NULL of none were found */
struct _url_spec *highlight_urls(char *str);

/* ------------------------------- */

/* ------- MBOX stuff ------------ */
typedef struct _mbox_spec {
	FILE    *ffd;           /* folder file descriptor */
	size_t  fsize;          /* latest size */
	char    mode[3];        /* open mode   */
} mbox_spec;

extern int locking; /* locking method */
	#define MBOX_DOT_LOCK       0x01    /* use <spool>.lock */
	#define MBOX_KERNEL_LOCK    0x02    /* use flock() or lockf() */

	#define REALENGTH   "X-Real-Length" /* store real lenght in this field */
	#define FROMLINE    "X-From-Line"   /* store original From line here */

/* make folder local (MBOX-style) */
void mbox_folder(struct _mail_folder *folder);

/* make message local (MBOX-style) */
void mbox_message(struct _mail_msg *msg);

/* create MBOX folder */
struct _mail_folder *create_mbox_folder(struct _mail_folder *pfolder, char *name);

/* returns folder with specific path. returns NULL if not found */
struct _mail_folder *get_mbox_folder_by_path(char *path);

/* deallocate memory taken by folder's spec structure */
void free_mbox_spec(struct _mail_folder *folder);

/* check if str is a correct From line */
/* returns message time or 0 if str is not valid From line */
/* if retpath and retpathlen are supplied, return path is returned */
time_t is_from(char *str, char *retpath, int retpathlen);

/* ------------------------------- */

/* ----- netsed folders stuff ---- */

/* create linked tree of folders */
int create_folder_tree();

/* append folder to folder tree */
int append_folder_tree(struct _mail_folder *folder);

/* remove folder from the folder tree */
int remove_subfold(struct _mail_folder *folder);

/* increase by 1 nesting level of given folder and its subtree */
int increase_level(struct _mail_folder *folder);

/* derease by 1 nesting level of given folder and its subtree */
int reduce_level(struct _mail_folder *folder);

/* find place in subfolders array where given folder appears in */
/* its parent's folder */
int find_subfold_ind(struct _mail_folder *folder);

/* add child as a subfolder of parent */
int add_subfold(struct _mail_folder *parent, struct _mail_folder *child);

/* returns 0  if folder1 is a parent of folder2, returns -1 otherwise */
int is_parent(struct _mail_folder *folder1, struct _mail_folder *folder2);

/* returns 0  if folder1 is a parent of folder2 in an existing folder tree */
/* returns -1 otherwise */
int is_tree_parent(const struct _mail_folder *folder1, const struct _mail_folder *folder2);

/* returns the topmost ancestor of specific folder */
/* returns NULL if folder has not ancestors */
const struct _mail_folder *get_ancestor(const struct _mail_folder *folder);

/* finds two ancestors of folder1 and folder2 which have the same father */
/* returns -1 on error, 0 if the ancestors were found - in this case */
/* folder1 and folder2 points to those ancestors , */
/* 1 if folder1 is a father of folder2, 2 if folder2 is a father of folder1 */
int find_ancestors(const struct _mail_folder **folder1, const struct _mail_folder **folder2);

/* expand (collapse) folder tree, if all > 0, all subtrees will be */
/* expanded (collapsed) as well. returns -1 on error and 0 on success */
void expand_tree(struct _mail_folder *folder, int all);
void collapse_tree(struct _mail_folder *folder, int all);
int expand_collapse_tree(struct _mail_folder *folder, int all);

/* ------------------------------- */

/* ---- multisource retrieve ---- */

/* retrieve mail */
typedef long (*get_mail) (struct _retrieve_src *, long *notify);
/* free spec structure in _retrieve_src */
typedef void (*free_rsrc) (struct _retrieve_src *);
/* initialize spec structure in _retrieve_src */
typedef void (*init_rsrc) (struct _retrieve_src *);
/* load spec structure from file */
typedef int (*load_rsrc) (struct _retrieve_src *, FILE *);
/* save spec strucutre to file */
typedef int (*save_rsrc) (struct _retrieve_src *, FILE *);

typedef struct _retrieve_src {
	char name[32];      /* source name */
	int flags;
	#define RSRC_DISABLED   0x01    /* source disabled */
	#define RSRC_MARKREAD   0x02    /* mark all retrieved messages as read */
	#define RSRC_NONOTIFY   0x04    /* don't notify */
	#define RSRC_SAVEADDR   0x08    /* save addresses from retrieved messages */
	#define RSRC_NOTIMER    0x10    /* don't retrieve if invoked by timer */
	#define RSRC_DOWNLOAD   0x20    /* Auto Download for Preview Pane */
	int type;
	#define RSRC_SPOOL  0x01    /* spool file */
	#define RSRC_POP    0x02    /* POP server */
	#define RSRC_IMAP   0x04    /* IMAP server */
	void *spec;
	/* functions */
	get_mail retrieve;
	free_rsrc free;
	init_rsrc init;
	load_rsrc load;
	save_rsrc save;
} retrieve_src;

extern list<struct _retrieve_src> retrieve_srcs;	/* list of sources */

typedef struct _spool_src {
	char path[MAXPATHLEN];
	int flags;
	#define SSRC_TRUNCATE   0x01        /* truncate spool after retrieving */
	#define SSRC_REWRITE    0x02        /* rewrite periodically */
} spool_src;

	#define MAX_UIDL    71  /* max. length of UID string        */
	#define MAX_POP_UIDS    3000    /* maxmimal number of UID's in file */

/* cache data structure */
typedef struct _uidl {
	char uidlstr[MAX_UIDL]; /* message unique ID */
	long mnum;     /* message number on the server */
	u_long mlen;        /* message length as reported by LIST */
	struct _uidl *next; /* next cache entry */
	u_int flags;        /* special flags */
	#define POP_DELETED 0x01    /* message has been deleted in this session */
	#define POP_LENGTH  0x02    /* message length is stored in mlen */
} uidl;

typedef struct _pop_src {
	char name[32];				/* XXX: source name */
	char hostname[MAX_HOST];    /* host to connect */
	char service[16];       /* port number or service name */
	#define POP_MAX_USERNAME_LEN MAX_USERNAME_LEN
	char username[POP_MAX_USERNAME_LEN + 1];      /* username */
	#define POP_MAX_PASSWD_LEN MAX_PASSWD_LEN
	char password[POP_MAX_PASSWD_LEN + 1];      /* password */
	long maxmsg;            /* don't retrieve longer messages */
	int flags;
	#define PSRC_POP2   0x0001      /* use POP2 */
	#define PSRC_DELETE 0x0002      /* delete messages from server */
	#define PSRC_DMARK  0x0004      /* don't mark retrieve */
	#define PSRC_STOREPWD   0x0008      /* store password */
	#define PSRC_LOGSESSION 0x0010      /* log session */
	#define PSRC_GETHEADER  0x0020      /* get only header of big message */
	#define PSRC_SKIPBIG    0x0040      /* skip big message */
	#define PSRC_CHECKUID   0x0080      /* check if retrieved by UID */
	#define PSRC_CHECKSTAT  0x0100      /* check if retrieved by status */
	#define PSRC_STATHEADER 0x0200      /* get status from header */
	#define PSRC_STATXLST   0x0400      /* get status from XLST */
	#define PSRC_APOP   0x0800      /* use APOP */
	/* run-time variables */
	int popsock;            /* communication socket */
	FILE *pop_in;           /* incoming data */
	FILE *pop_out;          /* outgoing data */
	struct _uidl *uidlcache;    /* cache of UIDs and lengths */
	int nouidl;         /* set if UIDL is not supported */
	unsigned long num_msgs;           /* number of messages on server */
	char *pop_uids[MAX_POP_UIDS];   /* array to store POP UID numbers */
	int uidfirst;           /* first element in the array */
	#define PSRC_RESPONSE_LEN	512
	char response[PSRC_RESPONSE_LEN];     /* server response */
} pop_src;

typedef struct _imap_src {
	char name[32];				/* XXX: source name */
	char hostname[MAX_HOST];    /* host to connect */
	char service[16];       /* port number or service name */
	#define IMAP_MAX_USERNAME_LEN MAX_USERNAME_LEN
	char username[IMAP_MAX_USERNAME_LEN + 1];      /* username */
	#define IMAP_MAX_PASSWD_LEN MAX_PASSWD_LEN
	char password[IMAP_MAX_PASSWD_LEN + 1];      /* password */
	char list[128];         /* hierarchies to list */
	int flags;
	#define ISRC_AUTOCON    0x001        /* autoconnect at startup */
	#define ISRC_STOREPWD   0x002        /* store password */
	#define ISRC_LOGSESSION 0x004        /* log session */
	#define ISRC_TRASH  0x008        /* use trash */
	#define ISRC_CACHE  0x010        /* cache between sessions */
	#define ISRC_NOEXPUNGE  0x020        /* no autoexpunge */
	#define ISRC_RETRIEVE   0x040        /* retrieve mail from this server */
	#define ISRC_SSL     0x080 /* use SSL */
	#define ISRC_SQUOTES	0x100	/* use single (') quotes to delimit
									 * quoted strings */
	
	/* run-time variables */
	int imapsock;           /* communication socket */
	FILE *imap_in;          /* incoming data */
	FILE *imap_out;         /* outgoing data */
	int icap;           /* server capabilities */
	int icauth;         /* server auth capabilities */
	int istate;         /* server state */
	char *response;         /* server response */
	struct _mail_folder *ifold; /* selected folder */
	struct _mail_folder *iinbox;    /* INBOX folder */
	struct _mail_folder *itrash;    /* TRASH folder */
	struct _mail_folder *svfold;    /* saved folder */
	struct _mail_folder *fimap; /* MH storage folder */
	struct _mail_msg *imsg;     /* current message */
	long *search_res;     /* search results */
	long uid;            /* UID */
	int lflags;         /* flags for LIST/LSUB folders */
	int conninprogress;     /* connect in progress */
	char *plist;            /* parenthized list */
	char *elem;         /* element of parenthized list */
	time_t lastcom;         /* when last command was sent */
	#if defined(SASL) && defined(PROT_STDIO)    /* protected stdio */
	struct protstream *pout;
	struct protstream *pin;
	#endif
} imap_src;

/* mark source as spool, POP , IMAP, or SMTP_AUTH */
void spool_source(struct _retrieve_src *src);
void pop_source(struct _retrieve_src *src);
void imap_source(struct _retrieve_src *src);

#define DEFAULT_SMTP_PORT "25"

#define MAX_SMTP_ACCOUNTS    16  /* limit to number of smtp accounts */
extern struct _smtp_account smtp_accounts[];    /* list of smtp accounts */


typedef struct _smtp_account {
	char name[32];              /* smtp  account name */
	char hostname[MAX_HOST+1];    /* host to connect to */
	char service[16];           /* host port number or service name */
	char src_name[32];      /* source account supplying username+password */  
	#define SMTP_MAX_USERNAME_LEN MAX_USERNAME_LEN
	char username[SMTP_MAX_USERNAME_LEN + 1];      /* username */
	#define SMTP_MAX_PASSWD_LEN MAX_PASSWD_LEN
	char password[SMTP_MAX_PASSWD_LEN + 1];      /* password */
	int flags;  
	#define SMTP_DISABLED     0x01   /* disable smtp account  */
	#define SMTP_AUTH         0x02   /* use authenticated smtp protocol */
	#define SMTP_AUTH_SRC     0x04   /* use authentication from source acct  */
	#define SMTP_STOREPWD     0x08   /* store password */
} Smtp_Account;

/* initializes smtp account configuration */
void  init_smtp_acct( struct _smtp_account *);
/* loads smtp account configururation from a file */
int load_smtp_acct(struct _smtp_account *, FILE *);
/* saves smtp account configururation to a file */
int save_smtp_acct(struct _smtp_account *, FILE *);

void findreplace(string & haystack, string needle, string newtext);

/* retrieves username and password from source account */
int get_src_info( char * , char *, char *);

/* ------------------------------- */
/* Take care of msg that is sent based on the given result code from the send */
void send_message_finalizer(struct _mail_msg *msg, int code);
/* ------------------------------- */
#endif /* _FMAIL_H */





