dovecot-2.2: lib-imap: Replaced last traces of imap_quote*() wit...
dovecot at dovecot.org
dovecot at dovecot.org
Wed Oct 24 11:30:22 EEST 2012
details: http://hg.dovecot.org/dovecot-2.2/rev/b89dae6aead4
changeset: 15250:b89dae6aead4
user: Timo Sirainen <tss at iki.fi>
date: Wed Oct 24 11:30:09 2012 +0300
description:
lib-imap: Replaced last traces of imap_quote*() with imap_append_string_for_humans()
Also the imap_append_*string() functions now decide whether to use
quoted-string or literal based on the output string length (if both would
work).
diffstat:
src/lib-imap/imap-envelope.c | 21 ++-
src/lib-imap/imap-quote.c | 260 ++++++++++++++++++++++--------------------
src/lib-imap/imap-quote.h | 20 +--
3 files changed, 158 insertions(+), 143 deletions(-)
diffs (truncated from 368 to 300 lines):
diff -r c849ae6603f2 -r b89dae6aead4 src/lib-imap/imap-envelope.c
--- a/src/lib-imap/imap-envelope.c Wed Oct 24 11:28:38 2012 +0300
+++ b/src/lib-imap/imap-envelope.c Wed Oct 24 11:30:09 2012 +0300
@@ -147,18 +147,18 @@
*addr_p = message_address_parse(pool, hdr->full_value,
hdr->full_value_len,
(unsigned int)-1, TRUE);
- } else if (str_p != NULL) {
+ } else if (str_p != NULL) T_BEGIN {
+ string_t *str = t_str_new(128);
+
if (str_p != &d->subject) {
- string_t *str = t_str_new(128);
-
imap_append_string(str,
t_strndup(hdr->full_value, hdr->full_value_len));
- *str_p = p_strdup(pool, str_c(str));
} else {
- *str_p = imap_quote(pool, hdr->full_value,
- hdr->full_value_len, TRUE);
+ imap_append_string_for_humans(str,
+ hdr->full_value, hdr->full_value_len);
}
- }
+ *str_p = p_strdup(pool, str_c(str));
+ } T_END;
}
static void imap_write_address(string_t *str, struct message_address *addr)
@@ -171,7 +171,12 @@
str_append_c(str, '(');
while (addr != NULL) {
str_append_c(str, '(');
- imap_quote_append_string(str, addr->name, TRUE);
+ if (addr->name == NULL)
+ str_append(str, "NIL");
+ else {
+ imap_append_string_for_humans(str,
+ (const void *)addr->name, strlen(addr->name));
+ }
str_append_c(str, ' ');
imap_append_nstring(str, addr->route);
str_append_c(str, ' ');
diff -r c849ae6603f2 -r b89dae6aead4 src/lib-imap/imap-quote.c
--- a/src/lib-imap/imap-quote.c Wed Oct 24 11:28:38 2012 +0300
+++ b/src/lib-imap/imap-quote.c Wed Oct 24 11:30:09 2012 +0300
@@ -5,124 +5,15 @@
#include "imap-arg.h"
#include "imap-quote.h"
-void imap_quote_append(string_t *str, const unsigned char *value,
- size_t value_len, bool fix_text)
-{
- size_t i, extra = 0;
- bool last_lwsp = TRUE, literal = FALSE, modify = FALSE;
-
- if (value == NULL) {
- str_append(str, "NIL");
- return;
- }
-
- if (value_len == (size_t)-1)
- value_len = strlen((const char *) value);
-
- for (i = 0; i < value_len; i++) {
- switch (value[i]) {
- case 0:
- /* it's converted to 8bit char */
- literal = TRUE;
- last_lwsp = FALSE;
- modify = TRUE;
- break;
- case '\t':
- modify = TRUE;
- /* fall through */
- case ' ':
- if (last_lwsp && fix_text) {
- modify = TRUE;
- extra++;
- }
- last_lwsp = TRUE;
- break;
- case 13:
- case 10:
- if (!fix_text)
- literal = TRUE;
- extra++;
- modify = TRUE;
- break;
- default:
- if ((value[i] & 0x80) != 0 ||
- value[i] == '"' || value[i] == '\\')
- literal = TRUE;
- last_lwsp = FALSE;
- }
- }
-
- if (!fix_text) {
- extra = 0;
- modify = FALSE;
- }
-
- if (!literal) {
- /* no 8bit chars or imapspecials, return as "string" */
- str_append_c(str, '"');
- } else {
- /* return as literal */
- str_printfa(str, "{%"PRIuSIZE_T"}\r\n", value_len - extra);
- }
-
- if (!modify)
- str_append_n(str, value, value_len);
- else {
- last_lwsp = TRUE;
- for (i = 0; i < value_len; i++) {
- switch (value[i]) {
- case 0:
- str_append_c(str, 128);
- last_lwsp = FALSE;
- break;
- case ' ':
- case '\t':
- if (!last_lwsp)
- str_append_c(str, ' ');
- last_lwsp = TRUE;
- break;
- case 13:
- case 10:
- break;
- default:
- last_lwsp = FALSE;
- str_append_c(str, value[i]);
- break;
- }
- }
- }
-
- if (!literal)
- str_append_c(str, '"');
-}
-
-static const char *
-imap_quote_internal(pool_t pool, const unsigned char *value,
- size_t value_len, bool fix_text)
-{
- string_t *str;
-
- str = t_str_new(value_len + MAX_INT_STRLEN + 5);
- imap_quote_append(str, value, value_len, fix_text);
- return pool->datastack_pool ? str_c(str) :
- p_strndup(pool, str_data(str), str_len(str));
-}
-
-const char *imap_quote(pool_t pool, const unsigned char *value,
- size_t value_len, bool fix_text)
-{
- const char *ret;
-
- if (value == NULL)
- return "NIL";
-
- if (pool->datastack_pool)
- ret = imap_quote_internal(pool, value, value_len, fix_text);
- else T_BEGIN {
- ret = imap_quote_internal(pool, value, value_len, fix_text);
- } T_END;
- return ret;
-}
+/* If we have quoted-specials (<">, <\>) in a string, the minimum quoted-string
+ overhead is 3 bytes ("\") while the minimum literal overhead is 5 bytes
+ ("{n}\r\n"). But the literal overhead also depends on the string size. If
+ the string length is less than 10, literal catches up to quoted-string after
+ 3 quoted-specials. If the string length is 10..99, it catches up after 4
+ quoted-specials, and so on. We'll assume that the string lengths are usually
+ in double digits, so we'll switch to literals after seeing 4
+ quoted-specials. */
+#define QUOTED_MAX_ESCAPE_CHARS 4
void imap_append_string(string_t *dest, const char *src)
{
@@ -149,9 +40,52 @@
str_append(dest, src);
}
+static void
+imap_append_literal(string_t *dest, const char *src, unsigned int pos)
+{
+ unsigned int full_len = pos + strlen(src+pos);
+
+ str_printfa(dest, "{%u}\r\n", full_len);
+ buffer_append(dest, src, full_len);
+}
+
void imap_append_nstring(string_t *dest, const char *src)
{
- imap_quote_append_string(dest, src, FALSE);
+ unsigned int i, escape_count = 0;
+
+ if (src == NULL) {
+ str_append(dest, "NIL");
+ return;
+ }
+
+ /* first check if we can (or want to) write this as quoted or
+ as literal.
+
+ quoted-specials = DQUOTE / "\"
+ QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> /
+ "\" quoted-specials
+ TEXT-CHAR = <any CHAR except CR and LF>
+ */
+ for (i = 0; src[i] != '\0'; i++) {
+ switch (src[i]) {
+ case '"':
+ case '\\':
+ if (escape_count++ < QUOTED_MAX_ESCAPE_CHARS)
+ break;
+ /* fall through */
+ case 13:
+ case 10:
+ imap_append_literal(dest, src, i);
+ return;
+ default:
+ if ((unsigned char)src[i] >= 0x80) {
+ imap_append_literal(dest, src, i);
+ return;
+ }
+ break;
+ }
+ }
+ imap_append_quoted(dest, src);
}
void imap_append_quoted(string_t *dest, const char *src)
@@ -159,8 +93,8 @@
str_append_c(dest, '"');
for (; *src != '\0'; src++) {
switch (*src) {
- case '\r':
- case '\n':
+ case 13:
+ case 10:
/* not allowed */
break;
case '"':
@@ -180,3 +114,87 @@
}
str_append_c(dest, '"');
}
+
+void imap_append_string_for_humans(string_t *dest,
+ const unsigned char *src, size_t size)
+{
+ size_t i, pos, remove_count = 0;
+ bool last_lwsp = TRUE, modify = FALSE;
+
+ /* first check if there is anything to change */
+ for (i = 0; i < size; i++) {
+ switch (src[i]) {
+ case 0:
+ /* convert NUL to #0x80 */
+ last_lwsp = FALSE;
+ modify = TRUE;
+ break;
+ case '\t':
+ modify = TRUE;
+ /* fall through */
+ case ' ':
+ if (last_lwsp) {
+ modify = TRUE;
+ remove_count++;
+ }
+ last_lwsp = TRUE;
+ break;
+ case 13:
+ case 10:
+ remove_count++;
+ modify = TRUE;
+ break;
+ case '"':
+ case '\\':
+ modify = TRUE;
+ last_lwsp = FALSE;
+ break;
+ default:
+ if ((src[i] & 0x80) != 0)
+ modify = TRUE;
+ last_lwsp = FALSE;
+ break;
+ }
+ }
+ if (last_lwsp) {
+ modify = TRUE;
+ remove_count++;
+ }
+ if (!modify) {
+ /* fast path: we can simply write it as quoted string
+ without any escaping */
+ str_append_c(dest, '"');
+ str_append_n(dest, src, size);
More information about the dovecot-cvs
mailing list