imap-msgpart.c revision 39aaa66444f0450942e7a762f635863c432541f6
/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "istream.h"
#include "istream-crlf.h"
#include "istream-nonuls.h"
#include "istream-header-filter.h"
#include "message-parser.h"
#include "mail-storage-private.h"
#include "mail-namespace.h"
#include "imap-parser.h"
#include "imap-msgpart.h"
enum fetch_type {
};
struct imap_msgpart {
/* "" for root, otherwise e.g. "1.2.3". the .MIME, .HEADER, etc.
suffix not included */
const char *section_number;
enum fetch_type fetch_type;
/* HEADER.FIELDS[.NOT] (list of headers) */
struct mailbox_header_lookup_ctx *header_ctx;
const char *const *headers;
/* which part of the message part to fetch (default: 0..(uoff_t)-1) */
};
struct imap_msgpart_open_ctx {
/* from matching message_part, set after opening: */
struct message_size mime_hdr_size;
struct message_size mime_body_size;
};
{
struct imap_msgpart *msgpart;
return msgpart;
}
struct imap_msgpart *imap_msgpart_full(void)
{
return imap_msgpart_type(FETCH_FULL);
}
struct imap_msgpart *imap_msgpart_header(void)
{
return imap_msgpart_type(FETCH_HEADER);
}
struct imap_msgpart *imap_msgpart_body(void)
{
return imap_msgpart_type(FETCH_BODY);
}
static struct message_part *
{
const char *path;
unsigned int num;
/* get part number, we have already verified its validity */
num = 0;
path++;
}
if (*path == '.')
path++;
/* find the part */
} else {
/* only 1 allowed with non-multipart messages */
if (num != 1)
}
body part */
}
}
return part;
}
static int
{
struct imap_parser *parser;
unsigned int list_count;
unsigned int i;
int result = 0;
list_count > 0) {
const char *value;
for (i = 0; i < list_count; i++) {
result = -1;
break;
}
}
} else {
result = -1;
}
/* istream-header-filter requires headers to be sorted */
return result;
}
static int
struct imap_msgpart *msgpart,
const char *header_list)
{
/* HEADER.FIELDS (list), HEADER.FIELDS.NOT (list) */
&fields) < 0)
return -1;
return 0;
}
struct imap_msgpart **msgpart_r)
{
struct imap_msgpart *msgpart;
unsigned int i;
bool next_digit;
int ret;
/* get the section number */
next_digit = TRUE;
for (i = 0; section[i] != '\0'; i++) {
next_digit = FALSE;
next_digit = TRUE;
} else {
break;
}
}
if (i == 0) {
/* [], [HEADER], etc. */
} else if (section[i] == '\0') {
/* [1.2.3] */
pool_unref(&pool);
return -1;
}
section = "";
} else {
/* [1.2.3.MIME], [1.2.3.HEADER], etc */
pool_unref(&pool);
return -1;
}
section += i;
}
if (*section == '\0') {
return 0;
}
/* message body */
/* header */
ret = 0;
section+14);
section+18);
} else {
ret = -1;
}
if (ret < 0) {
return -1;
}
/* we may be able to get this from cache, don't give a
wanted_fields hint */
else
}
return 0;
}
{
}
{
}
{
return msgpart->partial_offset;
}
{
return msgpart->wanted_fields;
}
static int
const struct imap_msgpart *msgpart,
struct message_size *hdr_size_r,
struct imap_msgpart_open_result *result_r)
{
bool has_nuls;
} else {
}
return -1;
}
i_stream_seek(input, 0);
return 0;
}
static void
{
int ret;
if (ret < 0)
return;
break;
/* skip header */
/* skip body */
} else {
/* maybe we have a child and can skip using it? */
}
}
}
static struct istream *
const struct imap_msgpart *msgpart)
{
const unsigned char *data;
if (virtual_skip == 0) {
/* no need to seek */
/* use cache */
} else {
/* can't use cache, but maybe we can skip faster using the
message parts. */
}
if (!mail->has_no_nuls) {
}
input = crlf_input;
if ((msgpart->partial_offset != 0 ||
/* update cache */
if (data[0] == '\n') {
/* the physical_pos points to virtual CRLF, but
virtual_pos already skipped CR. that can't work,
so seek back the virtual CR */
cache->virtual_pos--;
}
}
return input;
}
static void
const struct message_size *part_size,
struct imap_msgpart_open_result *result)
{
/* input is already seeked to the beginning of the wanted data */
/* can't seek past the MIME part */
return;
}
/* input has CRLF linefeeds, we can quickly seek to
wanted position */
} else {
/* input has LF linefeeds. it can be slow to seek to wanted
position, so try to do caching whenever possible */
msgpart);
}
/* limit output to specified number of bytes */
} else {
/* send all bytes */
}
}
struct imap_msgpart_open_result *result_r)
{
uoff_t physical_pos = 0;
/* find the MIME part */
return -1;
else {
}
}
/* MIME part not found. return an empty stream. */
return 0;
}
return -1;
} else switch (msgpart->fetch_type) {
case FETCH_FULL:
/* fetch the whole message */
return -1;
break;
case FETCH_MIME:
i_unreached();
case FETCH_HEADER:
case FETCH_HEADER_FIELDS_NOT:
/* fetch the message's header */
return -1;
break;
case FETCH_HEADER_FIELDS:
/* try to lookup the headers from cache */
&input) < 0)
return -1;
result_r->size_field = 0;
break;
case FETCH_BODY:
/* fetch the message's body */
return -1;
break;
}
/* return specific headers */
return -1;
return 0;
}
switch (msgpart->fetch_type) {
case FETCH_FULL:
/* fall through */
case FETCH_MIME:
case FETCH_HEADER:
break;
case FETCH_HEADER_FIELDS:
case FETCH_HEADER_FIELDS_NOT:
i_unreached();
case FETCH_BODY:
break;
}
return 0;
}