Пример #1
0
int rfc822_parse_phrase(struct rfc822_parser_context *ctx, string_t *str)
{
    int ret;

    /*
       phrase     = 1*word / obs-phrase
       word       = atom / quoted-string
       obs-phrase = word *(word / "." / CFWS)
    */

    if (ctx->data == ctx->end)
        return 0;
    if (*ctx->data == '.')
        return -1;

    for (;;) {
        if (*ctx->data == '"')
            ret = rfc822_parse_quoted_string(ctx, str);
        else
            ret = rfc822_parse_atom_or_dot(ctx, str);

        if (ret <= 0)
            return ret;

        if (!IS_ATEXT(*ctx->data) && *ctx->data != '"'
                && *ctx->data != '.')
            break;
        str_append_c(str, ' ');
    }
    return rfc822_skip_lwsp(ctx);
}
Пример #2
0
static void test_rfc822_parse_quoted_string(void)
{
	static const struct {
		const char *input, *output;
		int ret;
	} tests[] = {
		{ "\"", "", -1 },
		{ "\"\"", "", 0 },
		{ "\"foo\"", "foo", 0 },
		{ "\"\"foo", "", 1 },
		{ "\"\"\"", "", 1 },
		{ "\"\\\"\"", "\"", 0 },
		{ "\"\\\\\"", "\\", 0 },
		{ "\"\\\\foo\\\\foo\\\\\"", "\\foo\\foo\\", 0 }
	};
	struct rfc822_parser_context parser;
	string_t *str = t_str_new(64);
	unsigned int i = 0;

	test_begin("rfc822 parse quoted string");
	for (i = 0; i < N_ELEMENTS(tests); i++) {
		rfc822_parser_init(&parser, (const void *)tests[i].input,
				   strlen(tests[i].input), NULL);
		test_assert_idx(rfc822_parse_quoted_string(&parser, str) == tests[i].ret, i);
		test_assert_idx(tests[i].ret < 0 ||
				strcmp(tests[i].output, str_c(str)) == 0, i);
		str_truncate(str, 0);
	}
	test_end();
}
int rfc822_parse_content_param(struct rfc822_parser_context *ctx,
			       const char **key_r, const char **value_r)
{
	string_t *tmp;
	size_t value_pos;
	int ret;

	/* .. := *(";" parameter)
	   parameter := attribute "=" value
	   attribute := token
	   value := token / quoted-string
	*/
	*key_r = NULL;
	*value_r = NULL;

	if (ctx->data == ctx->end)
		return 0;
	if (*ctx->data != ';')
		return -1;
	ctx->data++;

	if (rfc822_skip_lwsp(ctx) <= 0)
		return -1;

	tmp = t_str_new(64);
	if (rfc822_parse_mime_token(ctx, tmp) <= 0)
		return -1;
	str_append_c(tmp, '\0');
	value_pos = str_len(tmp);

	if (*ctx->data != '=')
		return -1;
	ctx->data++;

	if ((ret = rfc822_skip_lwsp(ctx)) <= 0) {
		/* broken / no value */
	} else if (*ctx->data == '"') {
		ret = rfc822_parse_quoted_string(ctx, tmp);
		(void)str_unescape(str_c_modifiable(tmp) + value_pos);
	} else if (ctx->data != ctx->end && *ctx->data == '=') {
		/* workaround for broken input:
		   name==?utf-8?b?...?= */
		while (ctx->data != ctx->end && *ctx->data != ';' &&
		       *ctx->data != ' ' && *ctx->data != '\t' &&
		       *ctx->data != '\r' && *ctx->data != '\n') {
			str_append_c(tmp, *ctx->data);
			ctx->data++;
		}
	} else {
		ret = rfc822_parse_mime_token(ctx, tmp);
	}

	*key_r = str_c(tmp);
	*value_r = *key_r + value_pos;
	return ret < 0 ? -1 : 1;
}