diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib-imap/imap-util.c | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/src/lib-imap/imap-util.c b/src/lib-imap/imap-util.c new file mode 100644 index 0000000..dc1ae24 --- /dev/null +++ b/src/lib-imap/imap-util.c @@ -0,0 +1,202 @@ +/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" +#include "str.h" +#include "strescape.h" +#include "unichar.h" +#include "mail-types.h" +#include "imap-parser.h" +#include "imap-util.h" + +void imap_write_flags(string_t *dest, enum mail_flags flags, + const char *const *keywords) +{ + size_t size; + + size = str_len(dest); + if ((flags & MAIL_ANSWERED) != 0) + str_append(dest, "\\Answered "); + if ((flags & MAIL_FLAGGED) != 0) + str_append(dest, "\\Flagged "); + if ((flags & MAIL_DELETED) != 0) + str_append(dest, "\\Deleted "); + if ((flags & MAIL_SEEN) != 0) + str_append(dest, "\\Seen "); + if ((flags & MAIL_DRAFT) != 0) + str_append(dest, "\\Draft "); + if ((flags & MAIL_RECENT) != 0) + str_append(dest, "\\Recent "); + + if (keywords != NULL) { + /* we have keywords too */ + while (*keywords != NULL) { + str_append(dest, *keywords); + str_append_c(dest, ' '); + keywords++; + } + } + + if (str_len(dest) != size) + str_truncate(dest, str_len(dest)-1); +} + +enum mail_flags imap_parse_system_flag(const char *str) +{ + if (strcasecmp(str, "\\Answered") == 0) + return MAIL_ANSWERED; + else if (strcasecmp(str, "\\Flagged") == 0) + return MAIL_FLAGGED; + else if (strcasecmp(str, "\\Deleted") == 0) + return MAIL_DELETED; + else if (strcasecmp(str, "\\Seen") == 0) + return MAIL_SEEN; + else if (strcasecmp(str, "\\Draft") == 0) + return MAIL_DRAFT; + else if (strcasecmp(str, "\\Recent") == 0) + return MAIL_RECENT; + else + return 0; +} + +void imap_write_seq_range(string_t *dest, const ARRAY_TYPE(seq_range) *array) +{ + const struct seq_range *range; + unsigned int i, count; + + range = array_get(array, &count); + for (i = 0; i < count; i++) { + if (i > 0) + str_append_c(dest, ','); + str_printfa(dest, "%u", range[i].seq1); + if (range[i].seq1 != range[i].seq2) + str_printfa(dest, ":%u", range[i].seq2); + } +} + +void imap_write_arg(string_t *dest, const struct imap_arg *arg) +{ + switch (arg->type) { + case IMAP_ARG_NIL: + str_append(dest, "NIL"); + break; + case IMAP_ARG_ATOM: + str_append(dest, imap_arg_as_astring(arg)); + break; + case IMAP_ARG_STRING: { + const char *strarg = imap_arg_as_astring(arg); + str_append_c(dest, '"'); + str_append_escaped(dest, strarg, strlen(strarg)); + str_append_c(dest, '"'); + break; + } + case IMAP_ARG_LITERAL: { + const char *strarg = imap_arg_as_astring(arg); + str_printfa(dest, "{%zu}\r\n", + strlen(strarg)); + str_append(dest, strarg); + break; + } + case IMAP_ARG_LIST: + str_append_c(dest, '('); + imap_write_args(dest, imap_arg_as_list(arg)); + str_append_c(dest, ')'); + break; + case IMAP_ARG_LITERAL_SIZE: + case IMAP_ARG_LITERAL_SIZE_NONSYNC: + str_printfa(dest, "<%"PRIuUOFF_T" byte literal>", + imap_arg_as_literal_size(arg)); + break; + case IMAP_ARG_EOL: + i_unreached(); + } +} + +void imap_write_args(string_t *dest, const struct imap_arg *args) +{ + bool first = TRUE; + + for (; !IMAP_ARG_IS_EOL(args); args++) { + if (first) + first = FALSE; + else + str_append_c(dest, ' '); + imap_write_arg(dest, args); + } +} + +static void imap_human_args_fix_control_chars(char *str) +{ + size_t i; + + for (i = 0; str[i] != '\0'; i++) { + if (str[i] < 0x20 || str[i] == 0x7f) + str[i] = '?'; + } +} + +void imap_write_args_for_human(string_t *dest, const struct imap_arg *args) +{ + bool first = TRUE; + + for (; !IMAP_ARG_IS_EOL(args); args++) { + if (first) + first = FALSE; + else + str_append_c(dest, ' '); + + switch (args->type) { + case IMAP_ARG_NIL: + str_append(dest, "NIL"); + break; + case IMAP_ARG_ATOM: + /* atom has only printable us-ascii chars */ + str_append(dest, imap_arg_as_astring(args)); + break; + case IMAP_ARG_STRING: + case IMAP_ARG_LITERAL: { + const char *strarg = imap_arg_as_astring(args); + + if (strpbrk(strarg, "\r\n") != NULL) { + str_printfa(dest, "<%zu byte multi-line literal>", + strlen(strarg)); + break; + } + strarg = str_escape(strarg); + + str_append_c(dest, '"'); + size_t start_pos = str_len(dest); + /* append only valid UTF-8 chars */ + if (uni_utf8_get_valid_data((const unsigned char *)strarg, + strlen(strarg), dest)) + str_append(dest, strarg); + /* replace all control chars */ + imap_human_args_fix_control_chars( + str_c_modifiable(dest) + start_pos); + str_append_c(dest, '"'); + break; + } + case IMAP_ARG_LIST: + str_append_c(dest, '('); + imap_write_args_for_human(dest, imap_arg_as_list(args)); + str_append_c(dest, ')'); + break; + case IMAP_ARG_LITERAL_SIZE: + case IMAP_ARG_LITERAL_SIZE_NONSYNC: + str_printfa(dest, "<%"PRIuUOFF_T" byte literal>", + imap_arg_as_literal_size(args)); + break; + case IMAP_ARG_EOL: + i_unreached(); + } + } +} + +const char *imap_args_to_str(const struct imap_arg *args) +{ + string_t *str; + + str = t_str_new(128); + imap_write_args(str, args); + return str_c(str); +} |