struct mail *mail;
struct fts_backend_update_context *update_ctx;
- char *content_type, *content_disposition;
+ char *content_type, *content_type_params, *content_disposition;
struct fts_parser *body_parser;
buffer_t *word_buf, *pending_input;
T_BEGIN {
content_type = t_str_new(64);
(void)rfc822_parse_content_type(&parser, content_type);
+ /* Parse the mime-type only... */
ctx->content_type = str_lcase(i_strdup(str_c(content_type)));
+ /* ... then store the remainder of the line - which may contain RFC2231
+ parameters - without parsing it because not all backends need them. In
+ the backends that need them further parsing can be implemented. */
+ ctx->content_type_params = i_strdup((const char *)parser.data);
} T_END;
rfc822_parser_deinit(&parser);
}
key.part = part;
i_zero(&parser_context);
- parser_context.content_type = ctx->content_type != NULL ?
- ctx->content_type : "text/plain";
+ if (ctx->content_type != NULL) {
+ parser_context.content_type = ctx->content_type;
+ parser_context.content_type_params = ctx->content_type_params;
+ } else {
+ parser_context.content_type = "text/plain";
+ parser_context.content_type_params = "";
+ }
+
if (str_begins_with(parser_context.content_type, "multipart/")) {
/* multiparts are never indexed, only their contents */
return FALSE;
fts_backend_update_unset_build_key(update_ctx);
prev_part = raw_block.part;
i_free_and_null(ctx.content_type);
+ i_free_and_null(ctx.content_type_params);
i_free_and_null(ctx.content_disposition);
if (raw_block.size != 0) {
index_mail_set_message_parts_corrupted(mail, error);
message_decoder_deinit(&decoder);
i_free(ctx.content_type);
+ i_free(ctx.content_type_params);
i_free(ctx.content_disposition);
buffer_free(&ctx.word_buf);
buffer_free(&ctx.pending_input);
return FALSE;
}
-static void parse_content_disposition(const char *content_disposition,
- const char **filename_r)
+static bool get_param_and_free_parser(struct rfc822_parser_context *parser,
+ const char *key, const char **value_r)
{
- struct rfc822_parser_context parser;
const char *const *results;
- string_t *str;
+ *value_r = NULL;
+ rfc2231_parse(parser, &results);
+ for (; *results != NULL; results += 2) {
+ if (strcasecmp(results[0], key) == 0) {
+ *value_r = results[1];
+ break;
+ }
+ }
+ rfc822_parser_deinit(parser);
+ return *value_r != NULL;
+}
- *filename_r = NULL;
+static struct rfc822_parser_context init_content_parser(const char *content)
+{
+ struct rfc822_parser_context parser;
+ rfc822_parser_init(&parser, (const unsigned char *)content, strlen(content), NULL);
+ rfc822_skip_lwsp(&parser);
+ return parser;
+}
- if (content_disposition == NULL)
- return;
+/* We receive Content-Disposition parameters as `mimetype; param; param; ...` */
+static bool get_cd_filename(const char *content, const char **filename_r)
+{
+ if (content == NULL)
+ return FALSE;
- rfc822_parser_init(&parser, (const unsigned char *)content_disposition,
- strlen(content_disposition), NULL);
- rfc822_skip_lwsp(&parser);
+ struct rfc822_parser_context parser = init_content_parser(content);
/* type; param; param; .. */
- str = t_str_new(32);
+ string_t *str = t_str_new(32);
if (rfc822_parse_mime_token(&parser, str) < 0) {
rfc822_parser_deinit(&parser);
- return;
+ return FALSE;
}
- rfc2231_parse(&parser, &results);
- for (; *results != NULL; results += 2) {
- if (strcasecmp(results[0], "filename") == 0) {
- *filename_r = results[1];
- break;
- }
- }
- rfc822_parser_deinit(&parser);
+ return get_param_and_free_parser(&parser, "filename", filename_r);
+}
+
+/* We receive Content-Type parameters as `; param; param; ...` */
+static bool get_ct_filename(const char *content, const char **filename_r)
+{
+ if (content == NULL)
+ return FALSE;
+ struct rfc822_parser_context parser = init_content_parser(content);
+ return get_param_and_free_parser(&parser, "name", filename_r);
}
static struct fts_parser *
const char *filename, *path, *cmd;
int fd;
- parse_content_disposition(parser_context->content_disposition, &filename);
+ if (!get_cd_filename(parser_context->content_disposition, &filename))
+ (void)get_ct_filename(parser_context->content_type_params, &filename);
+
if (!script_support_content(parser_context, filename))
return NULL;