/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
#include "imap-common.h"
#include "buffer.h"
#include "str.h"
#include "strescape.h"
#include "istream.h"
#include "ostream.h"
#include "istream-header-filter.h"
#include "message-parser.h"
#include "mail-storage-private.h"
#include "imap-quote.h"
#include "imap-parser.h"
#include "imap-msgpart.h"
#include "imap-fetch.h"
#include <ctype.h>
#include <unistd.h>
struct imap_fetch_body_data {
};
const char **disconnect_reason_r)
{
*disconnect_reason_r = "Mail expunged while it was being FETCHed";
return;
}
}
"read(%s) failed: %s (FETCH %s)",
*disconnect_reason_r = "FETCH read() failed";
}
{
if (body->binary_size)
else
}
}
const struct imap_fetch_body_data *body,
{
else
else
return str;
}
{
const char *disconnect_reason;
}
switch (res) {
/* Input stream gave less data than expected */
"read(%s): FETCH %s got too little data: "
return -1;
}
return 1;
i_unreached();
return 0;
return -1;
/* client disconnected */
return -1;
}
i_unreached();
}
static const char *
{
else
}
}
const struct imap_msgpart *msgpart)
{
if (!imap_msgpart_contains_body(msgpart)) {
} else {
}
}
struct imap_fetch_body_data *body)
{
return 1;
}
return -1;
}
struct imap_fetch_body_data *body)
{
return 1;
}
return -1;
else
return -1;
return 1;
}
/* Parse next digits in string into integer. Returns -1 if the integer
becomes too big and wraps. */
{
return str_parse_uoff(*p, value, p);
}
static int
{
const char *value;
size_t i;
for (i = 0; i < args_count; i++) {
"Header list contains non-strings";
return -1;
}
if (i != 0)
else
}
return 0;
}
const char *p, const char **error_r)
{
if (*p == '\0')
return 0;
/* <start.end> */
if (*p != '<') {
*error_r = "Unexpected data after ']'";
return -1;
}
p++;
/* wrapped */
*error_r = "Too big partial start";
return -1;
}
if (*p == '.') {
p++;
/* wrapped */
*error_r = "Too big partial end";
return -1;
}
}
if (*p != '>') {
*error_r = "Missing '>' in partial";
return -1;
}
if (p[1] != '\0') {
*error_r = "Unexpected data after '>'";
return -1;
}
return 0;
}
{
unsigned int list_count;
p += 5;
else
if (*p != '[') {
return FALSE;
}
/* BODY[HEADER.FIELDS.. (headers list)] */
str[0] != ']') {
return FALSE;
}
list_args, list_count) < 0)
return FALSE;
p = str+1;
} else {
/* no headers list */
if (p == NULL) {
return FALSE;
}
p++;
}
return FALSE;
}
"Invalid BODY[..] parameter: %s", error);
return FALSE;
}
/* update the section name for the imap_fetch_add_handler() */
return TRUE;
}
{
unsigned int list_count;
/* fetch decoded size of the section */
p += 5;
p += 5;
} else {
}
if (*p != '[') {
return FALSE;
}
/* BINARY[HEADER.FIELDS.. (headers list)] */
str[0] != ']') {
return FALSE;
}
list_args, list_count) < 0)
return FALSE;
p = str+1;
} else {
/* no headers list */
if (p == NULL) {
return FALSE;
}
p++;
}
return FALSE;
}
if (!body->binary_size) {
"Invalid BINARY[..] parameter: %s", error);
return FALSE;
}
}
/* update the section name for the imap_fetch_add_handler() */
if (body->binary_size) {
} else {
}
return TRUE;
}
static int ATTR_NULL(3)
void *context ATTR_UNUSED)
{
return -1;
return 1;
}
static int
{
int ret;
if (ret < 0)
return -1;
return 0;
}
static int ATTR_NULL(3)
void *context ATTR_UNUSED)
{
const char *str;
msgpart = imap_msgpart_full();
return -1;
}
}
static int ATTR_NULL(3)
{
const char *str;
return -1;
}
}
static int ATTR_NULL(3)
void *context ATTR_UNUSED)
{
const char *str;
msgpart = imap_msgpart_body();
return -1;
}
}
{
fetch_rfc822, NULL);
return TRUE;
}
return TRUE;
}
return TRUE;
}
return TRUE;
}
return FALSE;
}
static int ATTR_NULL(3)
void *context)
{
enum mail_lookup_abort temp_lookup_abort = lazy ? MAIL_LOOKUP_ABORT_NOT_IN_CACHE : mail->lookup_abort;
const char *snippet;
int ret;
if (ret == 0) {
/* got it => nothing to do */
snippet++; /* skip over snippet version byte */
/* actual error => bail */
return -1;
} else if (lazy) {
/* not in cache && lazy => give up */
return 1;
} else {
/*
* not in cache && !lazy => someone higher up set
* MAIL_LOOKUP_ABORT_NOT_IN_CACHE and so even though we got
* a non-lazy request we failed the cache lookup.
*
* This is not an error, but since the scenario is
* sufficiently convoluted this else branch serves to
* document it.
*/
return 1;
}
return 1;
}
{
unsigned int list_count;
bool lazy;
unsigned int i;
for (i = 0; i < list_count; i++) {
const char *str;
return FALSE;
}
/* nothing to do */
} else {
str);
return FALSE;
}
}
}
return TRUE;
}