/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "buffer.h"
#include "istream.h"
#include "str.h"
#include "message-part-data.h"
#include "message-parser.h"
#include "rfc822-parser.h"
#include "rfc2231-parser.h"
#include "imap-parser.h"
#include "imap-quote.h"
#include "imap-envelope.h"
#include "imap-bodystructure.h"
"NIL NIL NIL NIL)"
/*
* IMAP BODY/BODYSTRUCTURE write
*/
static void
bool default_charset)
{
unsigned int i;
bool seen_charset;
if (!default_charset && params_count == 0) {
return;
}
for (i = 0; i < params_count; i++) {
if (i > 0)
if (default_charset &&
seen_charset = TRUE;
}
if (default_charset && !seen_charset) {
if (i > 0)
}
}
static void
{
}
}
static void
{
else {
}
else {
lang++;
lang++;
}
}
}
{
else {
/* no parts in multipart message,
that's not allowed. write a single
if (!extended)
else
}
else
if (!extended)
return;
/* BODYSTRUCTURE data */
}
{
bool text;
} else {
/* "content type" "subtype" */
} else {
}
else {
if (text)
else
}
}
/* ("content type param key" "value" ...) */
else
if (text) {
/* text/.. contains line count */
}
if (!extended)
return;
/* BODYSTRUCTURE data */
/* "md5" ("content disposition" ("disposition" "params"))
("body" "language" "params") "location" */
}
{
else
}
/*
* IMAP BODYSTRUCTURE parsing
*/
static int
{
unsigned int list_count, i;
return 0;
}
} else {
return -1;
for (i = 0; i < list_count; i++) {
return -1;
}
}
return 0;
}
static int
unsigned int *count_r)
{
return 0;
}
return -1;
if ((list_count % 2) != 0)
return -1;
for (i = 0; i < params_count; i++) {
return -1;
return -1;
}
*count_r = params_count;
return 0;
}
static int
const char **error_r)
{
return 0;
args++;
*error_r = "Invalid content-disposition list";
return -1;
} else {
if (!imap_arg_get_nstring
*error_r = "Invalid content-disposition";
return -1;
}
&data->content_disposition_params_count) < 0) {
*error_r = "Invalid content-disposition params";
return -1;
}
args++;
}
return 0;
*error_r = "Invalid content-language";
return -1;
}
return 0;
if (!imap_arg_get_nstring
*error_r = "Invalid content-location";
return -1;
}
return 0;
}
int
struct message_part **_part,
const char **error_r)
{
unsigned int lines;
/* parsing with pre-existing message_part tree */
} else {
/* parsing message_part tree from BODYSTRUCTURE as well */
parsing_tree = TRUE;
}
if (!parsing_tree) {
.content_type = "text",
.content_subtype = "plain",
.content_transfer_encoding = "7bit"
};
.data = &dummy_part_data,
};
/* no parts in multipart message,
that's not allowed. expect a single
*error_r = "message_part hierarchy "
"doesn't match BODYSTRUCTURE";
return -1;
}
&dummy_partp, error_r) < 0)
return -1;
child_part = NULL;
args++;
} else {
child_part == NULL) {
*error_r = "message_part hierarchy "
"doesn't match BODYSTRUCTURE";
return -1;
}
&child_part, error_r) < 0)
return -1;
args++;
}
}
if (multipart) {
if (child_part != NULL) {
*error_r = "message_part hierarchy "
"doesn't match BODYSTRUCTURE";
return -1;
}
*error_r = "message_part multipart flag "
"doesn't match BODYSTRUCTURE";
return -1;
}
} else {
child_part_p, error_r) < 0)
return -1;
args++;
}
if (multipart) {
}
}
if (multipart) {
*error_r = "Invalid multipart content-type";
return -1;
}
return 0;
&data->content_type_params_count) < 0) {
*error_r = "Invalid content params";
return -1;
}
}
/* "content type" "subtype" */
*error_r = "Invalid content-type";
return -1;
}
args += 2;
if (!parsing_tree) {
#if 0
/* Disabled for now. Earlier Dovecot versions handled broken
Content-Type headers by writing them as "text" "plain" to
BODYSTRUCTURE reply, but the message_part didn't have
MESSAGE_PART_FLAG_TEXT. */
*error_r = "message_part text flag "
"doesn't match BODYSTRUCTURE";
return -1;
}
#endif
if (message_rfc822 !=
"doesn't match BODYSTRUCTURE";
return -1;
}
} else {
if (text)
if (message_rfc822)
}
/* ("content type param key" "value" ...) | NIL */
&data->content_type_params_count) < 0) {
*error_r = "Invalid content params";
return -1;
}
/* "content id" "content description" "transfer encoding" size */
*error_r = "Invalid content-id";
return -1;
}
*error_r = "Invalid content-description";
return -1;
}
*error_r = "Invalid content-transfer-encoding";
return -1;
}
*error_r = "Invalid size field";
return -1;
}
if (!parsing_tree) {
*error_r = "message_part virtual_size doesn't match "
"size in BODYSTRUCTURE";
return -1;
}
} else {
}
if (text) {
*error_r = "Invalid lines field";
return -1;
}
} else if (message_rfc822) {
if (!parsing_tree) {
}
*error_r = "Child bodystructure list expected";
return -1;
}
return -1;
if (parsing_tree) {
}
*error_r = "Envelope list expected";
return -1;
}
("Invalid envelope list: %s", error);
return -1;
}
args += 2;
*error_r = "Invalid lines field";
return -1;
}
} else {
lines = 0;
}
if (!parsing_tree) {
*error_r = "message_part lines "
"doesn't match lines in BODYSTRUCTURE";
return -1;
}
} else {
}
return 0;
*error_r = "Invalid content-md5";
return -1;
}
}
const char **error_r)
{
int ret;
(void)i_stream_read(input);
if (ret < 0) {
} else if (ret == 0) {
*error_r = "Empty bodystructure";
ret = -1;
} else {
T_BEGIN {
if (ret < 0)
} T_END;
if (ret < 0) {
}
}
return ret;
}
const char **error_r)
{
}
/*
* IMAP BODYSTRUCTURE to BODY conversion
*/
{
const char *cstr;
return FALSE;
case IMAP_ARG_NIL:
break;
case IMAP_ARG_ATOM:
break;
case IMAP_ARG_STRING:
/* NOTE: we're parsing with no-unescape flag,
so don't double-escape it here */
break;
case IMAP_ARG_LITERAL: {
break;
}
default:
i_unreached();
return FALSE;
}
return TRUE;
}
static void
bool toplevel)
{
/* don't do any typechecking, just write it out */
while (!IMAP_ARG_IS_EOL(args)) {
/* everything is either nstring or list */
i_unreached();
}
}
args++;
}
}
static void
{
}
{
int i;
return -1;
args++;
}
if (multipart) {
/* next is subtype of Content-Type. rest is skipped. */
*error_r = "Invalid multipart content-type";
return -1;
}
return 0;
}
/* "content type" "subtype" */
*error_r = "Invalid content-type";
return -1;
}
i_unreached();
i_unreached();
args += 2;
/* ("content type param key" "value" ...) | NIL */
while (!IMAP_ARG_IS_EOL(subargs)) {
*error_r = "Invalid content param key";
return -1;
}
*error_r = "Invalid content param value";
return -1;
}
subargs += 2;
if (IMAP_ARG_IS_EOL(subargs))
break;
}
} else {
return -1;
}
args++;
/* "content id" "content description" "transfer encoding" size */
for (i = 0; i < 4; i++, args++) {
*error_r = "nstring expected";
return -1;
}
}
if (text) {
*error_r = "Text lines expected";
return -1;
}
} else if (message_rfc822) {
*error_r = "Envelope list expected";
return -1;
}
*error_r = "Child bodystructure list expected";
return -1;
}
return -1;
*error_r = "Text lines expected";
return -1;
}
}
return 0;
}
{
int ret;
(void)i_stream_read(input);
if (ret < 0) {
} else if (ret == 0) {
*error_r = "Empty bodystructure";
ret = -1;
} else {
}
return ret;
}