]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-imap: Add imap_write_args_for_human()
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 4 Apr 2017 12:58:15 +0000 (15:58 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 6 Apr 2017 17:22:41 +0000 (20:22 +0300)
src/lib-imap/imap-util.c
src/lib-imap/imap-util.h

index f4bd9dae1f68c118b1a42d34c0a8bbb8916adee9..3e38d10180e538ca5554f55284986957d79ab983 100644 (file)
@@ -4,6 +4,7 @@
 #include "array.h"
 #include "str.h"
 #include "strescape.h"
+#include "unichar.h"
 #include "mail-types.h"
 #include "imap-parser.h"
 #include "imap-util.h"
@@ -119,6 +120,73 @@ void imap_write_args(string_t *dest, const struct imap_arg *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, "<%"PRIuSIZE_T" 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;
index 2813dbce93c24f2ef83f53b1a61040ac20540f35..07f8af3903f6a99f33339b260c3169d4e1479c51 100644 (file)
@@ -16,6 +16,10 @@ enum mail_flags imap_parse_system_flag(const char *str);
 void imap_write_seq_range(string_t *dest, const ARRAY_TYPE(seq_range) *array);
 /* Write IMAP args to given string. The string is mainly useful for humans. */
 void imap_write_args(string_t *dest, const struct imap_arg *args);
+/* Write IMAP args in a human-readable format to given string (e.g. for
+   logging). The output is a single valid UTF-8 line without control
+   characters. Multi-line literals are replaced with a generic placeholder. */
+void imap_write_args_for_human(string_t *dest, const struct imap_arg *args);
 /* Like imap_write_args(), but return the string allocated from data stack. */
 const char *imap_args_to_str(const struct imap_arg *args);