imap-bodystructure.c revision b674bd911aaab7e8b1a77c106a0b5bccb603439f
/* Copyright (c) 2002-2017 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"
#define EMPTY_BODYSTRUCTURE "(\"text\" \"plain\" " \
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
}
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 */
const struct message_part_data *child_data;
}
if (!extended)
return;
/* BODYSTRUCTURE data */
/* "md5" ("content disposition" ("disposition" "params"))
("body" "language" "params") "location" */
}
{
else
}
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)
{
struct message_part_param *params;
unsigned int list_count, params_count, i;
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;
}
static int
struct message_part *part,
const char **error_r)
{
struct message_part_data *data;
struct message_part *child_part;
unsigned int lines;
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 = "Invalid multipart content-type";
return -1;
}
return 0;
&data->content_type_params_count) < 0) {
*error_r = "Invalid content params";
return -1;
}
}
*error_r = "message_part multipart flag doesn't match BODYSTRUCTURE";
return -1;
}
/* "content type" "subtype" */
*error_r = "Invalid content-type";
return -1;
}
args += 2;
#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
return -1;
}
/* ("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;
}
*error_r = "message_part virtual_size doesn't match "
"size in BODYSTRUCTURE";
return -1;
}
if (text) {
*error_r = "Invalid lines field";
return -1;
}
} else if (message_rfc822) {
*error_r = "Child bodystructure list expected";
return -1;
}
return -1;
*error_r = "Envelope list expected";
return -1;
}
("Invalid envelope list: %s", error);
return -1;
}
args += 2;
*error_r = "Invalid lines field";
return -1;
}
} else {
}
*error_r = "message_part lines "
"doesn't match lines in BODYSTRUCTURE";
return -1;
}
return 0;
*error_r = "Invalid content-md5";
return -1;
}
}
int imap_bodystructure_parse(const char *bodystructure,
const char **error_r)
{
struct imap_parser *parser;
char *error;
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 *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 imap_body_parse_from_bodystructure(const char *bodystructure,
{
struct imap_parser *parser;
int ret;
(void)i_stream_read(input);
if (ret < 0) {
} else if (ret == 0) {
*error_r = "Empty bodystructure";
ret = -1;
} else {
}
return ret;
}