imap-message-cache.c revision 907035872354e895a0c4431e1e42cd21d456f3ea
/* Copyright (C) 2002 Timo Sirainen */
#include "lib.h"
#include "istream.h"
#include "mmap-util.h"
#include "message-parser.h"
#include "message-part-serialize.h"
#include "message-size.h"
#include "imap-bodystructure.h"
#include "imap-envelope.h"
#include "imap-message-cache.h"
#include <unistd.h>
/* It's not very useful to cache lots of messages, as they're mostly wanted
just once. The biggest reason for this cache to exist is to get just the
latest message. */
#define MAX_CACHED_MESSAGES 16
#define DEFAULT_MESSAGE_POOL_SIZE 4096
typedef struct _CachedMessage CachedMessage;
struct _CachedMessage {
unsigned int uid;
char *cached_body;
char *cached_bodystructure;
char *cached_envelope;
};
struct _ImapMessageCache {
int messages_count;
void *context;
};
{
return cache;
}
{
}
{
}
}
{
}
{
cache->messages_count++;
else {
/* remove the last message from cache */
}
return msg;
}
unsigned int uid)
{
break;
}
/* not found, add it */
/* move it to first in list */
} else {
}
return msg;
}
void *context)
{
/* parse envelope headers if we're at the root message part */
}
}
{
/* need to rewind */
cache->open_stream =
}
return FALSE;
return TRUE;
}
{
}
}
/* Caches the fields for given message if possible */
{
const char *value;
int failed;
t_push();
if ((fields & IMAP_CACHE_BODYSTRUCTURE) &&
TRUE);
}
}
/* we can generate it from cached BODYSTRUCTURE.
do it only if the file isn't open already, since
this takes more CPU than parsing message headers. */
value);
}
}
FALSE);
}
}
imap_msgcache_get_stream(cache, 0)) {
/* envelope isn't parsed yet, do it. header
size is calculated anyway so save it */
MessageSize, 1);
}
msg);
}
}
}
if ((fields & IMAP_CACHE_VIRTUAL_SIZE) &&
}
/* we don't have body size. and since we're already going
to scan the whole message body, we might as well build
the MessagePart. FIXME: this slows down things when it's
not needed, do we really want to? */
}
if (fields & IMAP_CACHE_MESSAGE_PART) {
/* we need to parse the message */
if ((fields & IMAP_CACHE_ENVELOPE) &&
/* we need envelope too, fill the info
while parsing headers */
} else {
}
}
}
}
/* easy, get it from root part */
MessageSize, 1);
}
} else {
/* need to do some light parsing */
if (imap_msgcache_get_stream(cache, 0)) {
} else {
}
}
}
if ((fields & IMAP_CACHE_VIRTUAL_SIZE) &&
else {
}
}
if (fields & IMAP_CACHE_MESSAGE_OPEN) {
/* this isn't needed for anything else than pre-opening the
mail and seeing if it fails. */
}
if ((fields & IMAP_CACHE_INTERNALDATE) &&
/* keep this last, since we may get it when mail file is
opened. */
msg->internal_date =
}
t_pop();
return !failed;
}
{
}
/* physical size == virtual size */
}
/* physical size == virtual size */
}
}
{
}
}
{
switch (field) {
case IMAP_CACHE_BODY:
return msg->cached_body;
case IMAP_CACHE_BODYSTRUCTURE:
return msg->cached_bodystructure;
case IMAP_CACHE_ENVELOPE:
return msg->cached_envelope;
default:
i_unreached();
}
return NULL;
}
{
}
{
}
{
}
{
return FALSE;
}
return FALSE;
}
return FALSE;
}
return TRUE;
}
int *cr_skipped)
{
int last_cr;
/* see if we can use the existing partial */
else {
}
/* get_body_size() sees \n first, counting it as \r\n */
}
if (*cr_skipped) {
/* extra virtual \r counted, drop it */
dest->virtual_size--;
}
if (last_cr != 0) {
/* we'll see \n as first character next time, so make sure
we don't count the (virtual) \r twice. */
if (last_cr == 1)
partial->physical_size--;
partial->virtual_size--;
}
return physical_skip;
}
{
int size_got;
*cr_skipped = FALSE;
return FALSE;
}
/* see if we can do this easily */
if (virtual_skip == 0) {
return FALSE;
}
if (get_header)
if (max_virtual_size >= full_size) {
if (get_header)
}
}
if (size_got) {
} else {
if (!imap_msgcache_get_stream(cache, 0))
return FALSE;
if (!get_header)
size, cr_skipped);
}
/* seek to wanted position */
return FALSE;
return TRUE;
}
{
if (!imap_msgcache_get_stream(cache, 0))
return FALSE;
return TRUE;
}