index-fetch-section.c revision a3ea111cfdbfd4f32baeb0bd7f1d72568c60a023
/* Copyright (C) 2002 Timo Sirainen */
#include "lib.h"
#include "str.h"
#include "istream.h"
#include "ostream.h"
#include "message-send.h"
#include "index-storage.h"
#include "index-fetch.h"
#include <ctype.h>
#include <unistd.h>
typedef struct {
const char *const *fields;
int (*match_func) (const char *const *, const unsigned char *, size_t);
/* For FETCH[HEADER.FIELDS*] we need to modify the header data before sending
it. We can either save it in memory and then send it, or we can parse it
twice, first calculating the size and then send it. This value specifies
the maximum amount of memory we allow to allocate before using
double-parsing. */
{
/* no IMAP_CACHE_MESSAGE_BODY_SIZE, so that we don't
uselessly check it when we want to read partial data */
return IMAP_CACHE_MESSAGE_OPEN;
}
/* error */
return 0;
}
/* fetch BODY[] or BODY[TEXT] */
{
const char *str;
int cr_skipped;
i_error("Couldn't get BODY[] for UID %u (index %s)",
return FALSE;
}
return FALSE;
if (cr_skipped)
size.virtual_size++;
}
static const char **get_fields_array(const char *fields)
{
const char **field_list, **field;
while (*fields == ' ')
fields++;
if (*fields == '(')
fields++;
/* array ends at ")" element */
}
return field_list;
}
static int header_match(const char *const *fields,
{
const unsigned char *name_start, *name_end;
const char *field;
if (size == 0)
return FALSE;
name_start = name;
if (*field == '\0')
continue;
/* field has been uppercased long time ago while
parsing FETCH command */
break;
field++;
if (*field == '\0') {
return TRUE;
break;
}
}
}
return FALSE;
}
static int header_match_not(const char *const *fields,
{
}
{
return TRUE;
return TRUE;
return FALSE;
}
{
return TRUE;
}
}
}
return FALSE;
}
}
const unsigned char *value __attr_unused__,
void *context)
{
/* see if we want this field. */
return;
/* add the field, inserting CRs when needed. FIXME: is this too
kludgy? we assume name continues with ": value". but otherwise
we wouldn't reply with correct LWSP between ":". */
field_start = name;
for (p = field_start; p != field_end; p++) {
if (*p == '\r')
cr = p;
/* missing CR */
(size_t) (p-field_start)))
return;
return;
field_start = p+1;
}
}
if (field_start != field_end) {
return;
}
}
{
/* Mime-Version + Content-* fields */
} else {
/* invalid section given by user - FIXME: tell user about it */
return FALSE;
}
/* FIXME: The blank line must not be filtered, says RFC. However, we
shouldn't add it if it wasn't there in the first place. Not very
easy to know currently so we'll just do it always, it'll be present
in all sane messages anyway.. */
return TRUE;
}
/* fetch wanted headers from given data */
{
const char *str;
int failed;
/* HEADER, MIME, HEADER.FIELDS (list), HEADER.FIELDS.NOT (list) */
/* all headers */
return FALSE;
}
/* partial headers - copy the wanted fields into memory, inserting
missing CRs on the way. If the header is too large, calculate
the size first and then send the data directly to output stream. */
t_push();
/* first pass, we need at least the size */
} else {
}
if (!failed) {
}
if (!failed) {
/* second pass, write the data to output stream */
if (!failed &&
} else {
}
}
t_pop();
return !failed;
}
/* fetch BODY[HEADER...] */
const char *prefix)
{
return FALSE;
}
/* Find MessagePart for section (eg. 1.3.4) */
const char **section)
{
const char *path;
unsigned int num;
/* get part number */
num = 0;
return NULL;
path++;
}
if (*path == '.')
path++;
/* find the part */
} else {
/* only 1 allowed with non-multipart messages */
if (num != 1)
return NULL;
}
}
}
return part;
}
/* fetch BODY[1.2] or BODY[1.2.TEXT] */
{
const char *str;
return FALSE;
/* jump to beginning of wanted data */
return FALSE;
/* FIXME: potential performance problem with big messages:
FETCH BODY[1]<100000..1024>, hopefully no clients do this */
}
/* fetch BODY[1.2.MIME|HEADER...] */
const char *prefix)
{
return FALSE;
}
const char *prefix)
{
const char *section;
return FALSE;
return FALSE;
}
{
const char *prefix;
}
/* FIXME: point the error to user */
return FALSE;
}