/*
* Copyright (C) 2004 Thomas Glanzmann <sithglan@stud.uni-erlangen.de>
* Copyright (C) 2004 Tobias Werth <sitowert@stud.uni-erlangen.de>
* Copyright (C) 2004 Brian Fundakowski Feldman <green@FreeBSD.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#if HAVE_GDBM
#include <gdbm.h>
#elif HAVE_DB4
#include <db.h>
#endif
#include <errno.h>
#include <fcntl.h>
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include "mutt.h"
#ifdef USE_IMAP
#include "message.h"
#endif
#include "mime.h"
#include "mx.h"
#include "lib.h"
#include "md5.h"
#if HAVE_GDBM
static struct header_cache
{
GDBM_FILE db;
char *folder;
unsigned int crc;
} HEADER_CACHE;
#elif HAVE_DB4
static struct header_cache
{
DB_ENV *env;
DB *db;
unsigned int crc;
int fd;
char lockfile[_POSIX_PATH_MAX];
} HEADER_CACHE;
#endif
typedef union
{
struct timeval timeval;
unsigned long uid_validity;
} validate;
static void *
lazy_malloc(size_t siz)
{
if (0 < siz && siz < 4096)
siz = 4096;
return safe_malloc(siz);
}
static void
lazy_realloc(void *ptr, size_t siz)
{
void **p = (void **) ptr;
if (p != NULL && 0 < siz && siz < 4096)
return;
safe_realloc(ptr, siz);
}
static unsigned char *
dump_int(unsigned int i, unsigned char *d, int *off)
{
lazy_realloc(&d, *off + sizeof (int));
memcpy(d + *off, &i, sizeof (int));
(*off) += sizeof (int);
return d;
}
static void
restore_int(unsigned int *i, const unsigned char *d, int *off)
{
memcpy(i, d + *off, sizeof (int));
(*off) += sizeof (int);
}
static unsigned char *
dump_char(char *c, unsigned char *d, int *off)
{
unsigned int size;
if (c == NULL)
{
size = 0;
d = dump_int(size, d, off);
return d;
}
size = mutt_strlen(c) + 1;
d = dump_int(size, d, off);
lazy_realloc(&d, *off + size);
memcpy(d + *off, c, size);
*off += size;
return d;
}
static unsigned char *
dump_char_size(char *c, unsigned char *d, int *off, ssize_t size)
{
if (c == NULL)
{
size = 0;
d = dump_int(size, d, off);
return d;
}
d = dump_int(size, d, off);
lazy_realloc(&d, *off + size);
memcpy(d + *off, c, size);
*off += size;
return d;
}
static void
restore_char(char **c, const unsigned char *d, int *off)
{
unsigned int size;
restore_int(&size, d, off);
if (size == 0)
{
*c = NULL;
return;
}
*c = safe_malloc(size);
memcpy(*c, d + *off, size);
*off += size;
}
static unsigned char *
dump_address(ADDRESS * a, unsigned char *d, int *off)
{
unsigned int counter = 0;
unsigned int start_off = *off;
d = dump_int(0xdeadbeef, d, off);
while (a)
{
#ifdef EXACT_ADDRESS
d = dump_char(a->val, d, off);
#endif
d = dump_char(a->personal, d, off);
d = dump_char