str_append(str, NVL(data->message_id, "NIL"));
}
-static bool imap_address_arg_append(const struct imap_arg *arg, string_t *str,
- bool *in_group, bool *begin_group)
-{
- const struct imap_arg *list_args;
- unsigned int list_count;
- const char *args[4];
- int i;
-
- if (!imap_arg_get_list_full(arg, &list_args, &list_count))
- return FALSE;
-
- /* we require 4 arguments, strings or NILs */
- if (list_count < 4)
- return FALSE;
-
- for (i = 0; i < 4; i++) {
- if (!imap_arg_get_nstring(&list_args[i], &args[i]))
- return FALSE;
- }
-
- if (*in_group && args[0] == NULL && args[1] == NULL &&
- args[2] == NULL && args[3] == NULL) {
- /* end of group */
- str_append_c(str, ';');
- *in_group = FALSE;
- *begin_group = FALSE;
- return TRUE;
- }
-
- if (str_len(str) > 0 && !*begin_group)
- str_append(str, ", ");
-
- if (!*in_group && args[0] == NULL && args[1] == NULL &&
- args[2] != NULL && args[3] == NULL) {
- /* beginning of group */
- str_append(str, args[2]);
- str_append(str, ": ");
- *in_group = TRUE;
- *begin_group = TRUE;
- return TRUE;
- }
- *begin_group = FALSE;
-
- /* a) mailbox@domain
- b) name <@route:mailbox@domain> */
- if (args[0] == NULL && args[1] == NULL) {
- if (args[2] != NULL)
- str_append(str, args[2]);
- if (args[3] != NULL) {
- str_append_c(str, '@');
- str_append(str, args[3]);
- }
- } else {
- if (args[0] != NULL) {
- str_append(str, args[0]);
- str_append_c(str, ' ');
- }
-
- str_append_c(str, '<');
- if (args[1] != NULL) {
- str_append_c(str, '@');
- str_append(str, args[1]);
- str_append_c(str, ':');
- }
- if (args[2] != NULL)
- str_append(str, args[2]);
- if (args[3] != NULL) {
- str_append_c(str, '@');
- str_append(str, args[3]);
- }
- str_append_c(str, '>');
- }
- return TRUE;
-}
-
-static const char *imap_envelope_parse_address(const struct imap_arg *arg)
-{
- const struct imap_arg *list_args;
- string_t *str;
- bool in_group;
- bool begin_group;
-
- if (!imap_arg_get_list(arg, &list_args))
- return NULL;
-
- in_group = FALSE;
- begin_group = FALSE;
- str = t_str_new(128);
-
- for (; !IMAP_ARG_IS_EOL(list_args); list_args++) {
- if (!imap_address_arg_append(list_args, str, &in_group, &begin_group))
- return NULL;
- }
-
- return str_c(str);
-}
-
-static const char *imap_envelope_parse_first_mailbox(const struct imap_arg *arg)
-{
- const struct imap_arg *list_args;
- const char *str;
- unsigned int list_count;
-
- /* ((...)(...) ...) */
- if (!imap_arg_get_list(arg, &list_args))
- return NULL;
- if (IMAP_ARG_IS_EOL(list_args))
- return "";
-
- /* (name route mailbox domain) */
- if (!imap_arg_get_list_full(arg, &list_args, &list_count) ||
- list_count != 4)
- return NULL;
- if (!imap_arg_get_nstring(&list_args[2], &str))
- return NULL;
- return t_strdup(str);
-}
-
-static bool
-imap_envelope_parse_arg(const struct imap_arg *arg,
- enum imap_envelope_field field,
- const char *envelope,
- enum imap_envelope_result_type result_type,
- const char **result)
-{
- const char *value = NULL;
-
- if (arg->type == IMAP_ARG_NIL) {
- *result = NULL;
- return TRUE;
- }
-
- switch (result_type) {
- case IMAP_ENVELOPE_RESULT_TYPE_STRING:
- if (field >= IMAP_ENVELOPE_FROM && field <= IMAP_ENVELOPE_BCC)
- value = imap_envelope_parse_address(arg);
- else {
- if (imap_arg_get_nstring(arg, &value))
- value = t_strdup(value);
- }
- break;
- case IMAP_ENVELOPE_RESULT_TYPE_FIRST_MAILBOX:
- i_assert(field >= IMAP_ENVELOPE_FROM &&
- field <= IMAP_ENVELOPE_BCC);
- value = imap_envelope_parse_first_mailbox(arg);
- break;
- }
-
- *result = value;
- if (value != NULL)
- return TRUE;
- else {
- i_error("Invalid field %u in IMAP envelope: %s",
- field, envelope);
- return FALSE;
- }
-}
-
-bool imap_envelope_parse(const char *envelope, enum imap_envelope_field field,
- enum imap_envelope_result_type result_type,
- const char **result)
-{
- struct istream *input;
- struct imap_parser *parser;
- const struct imap_arg *args;
- int args_count;
- bool ret;
-
- i_assert(field < IMAP_ENVELOPE_FIELDS);
-
- input = i_stream_create_from_data(envelope, strlen(envelope));
- parser = imap_parser_create(input, NULL, (size_t)-1);
-
- (void)i_stream_read(input);
- args_count = imap_parser_read_args(parser, field+1, 0, &args);
- if (args_count > (int)field) {
- ret = imap_envelope_parse_arg(&args[field], field,
- envelope, result_type, result);
- } else {
- i_error("Error parsing IMAP envelope: %s", envelope);
- *result = NULL;
- ret = FALSE;
- }
-
- imap_parser_unref(&parser);
- i_stream_destroy(&input);
- return ret;
-}