[dovecot-cvs] dovecot/src/lib-mail message-header-decode.c, 1.9, 1.10
tss at dovecot.org
tss at dovecot.org
Wed Apr 4 08:39:15 EEST 2007
Update of /var/lib/cvs/dovecot/src/lib-mail
In directory talvi:/tmp/cvs-serv18597
Modified Files:
message-header-decode.c
Log Message:
Rewrite/cleanup
Index: message-header-decode.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-mail/message-header-decode.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- message-header-decode.c 3 Apr 2007 13:55:08 -0000 1.9
+++ message-header-decode.c 4 Apr 2007 05:39:13 -0000 1.10
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Timo Sirainen */
+/* Copyright (C) 2002-2007 Timo Sirainen */
#include "lib.h"
#include "base64.h"
@@ -6,116 +6,110 @@
#include "quoted-printable.h"
#include "message-header-decode.h"
-static bool split_encoded(const unsigned char *data, size_t *size_p,
- const char **charset, const char **encoding,
- const unsigned char **text, size_t *text_size_r)
-{
- size_t size, pos, textpos;
-
- size = *size_p;
-
- /* get charset */
- for (pos = 0; pos < size && data[pos] != '?'; pos++) ;
- if (data[pos] != '?') return FALSE;
- *charset = t_strndup(data, pos);
-
- /* get encoding */
- pos++;
- if (pos+2 >= size || data[pos+1] != '?')
- return FALSE;
-
- if (data[pos] == 'Q' || data[pos] == 'q')
- *encoding = "Q";
- else if (data[pos] == 'B' || data[pos] == 'b')
- *encoding = "B";
- else
- return FALSE;
-
- /* get text */
- pos += 2;
- textpos = pos;
- while (pos < size && data[pos] != '?') pos++;
- if (data[pos] != '?' || pos+1 >= size || data[pos+1] != '=')
- return FALSE;
-
- *text = data + textpos;
- *text_size_r = pos - textpos;
- *size_p = pos+2;
- return TRUE;
-}
-
-static bool
-message_header_decode_encoded(const unsigned char *data, size_t *size,
- message_header_decode_callback_t *callback,
- void *context)
+static size_t
+message_header_decode_encoded(const unsigned char *data, size_t size,
+ buffer_t *decodebuf, unsigned int *charsetlen_r)
{
- const unsigned char *text;
- const char *charset, *encoding;
- buffer_t *decodebuf;
- size_t text_size;
- int ret;
-
- t_push();
+#define QCOUNT 3
+ unsigned int num = 0;
+ size_t i, start_pos[QCOUNT];
- /* first split the string charset?encoding?text?= */
- if (!split_encoded(data, size, &charset, &encoding,
- &text, &text_size)) {
- t_pop();
- return TRUE;
+ /* data should contain "charset?encoding?text?=" */
+ for (i = 0; i < size; i++) {
+ if (data[i] == '?') {
+ start_pos[num++] = i;
+ if (num == QCOUNT)
+ break;
+ }
+ }
+ if (i == size || data[i+1] != '=') {
+ /* invalid block */
+ return 0;
}
- decodebuf = buffer_create_static_hard(pool_datastack_create(),
- text_size);
+ buffer_append(decodebuf, data, start_pos[0]);
+ buffer_append_c(decodebuf, '\0');
+ *charsetlen_r = decodebuf->used;
- if (*encoding == 'Q')
- quoted_printable_decode(text, text_size, NULL, decodebuf);
- else {
- if (base64_decode(text, text_size, NULL, decodebuf) < 0) {
- /* corrupted encoding */
- t_pop();
- return TRUE;
+ switch (data[start_pos[0]+1]) {
+ case 'q':
+ case 'Q':
+ quoted_printable_decode(data + start_pos[1] + 1,
+ start_pos[2] - start_pos[1] - 1,
+ NULL, decodebuf);
+ break;
+ case 'b':
+ case 'B':
+ if (base64_decode(data + start_pos[1] + 1,
+ start_pos[2] - start_pos[1] - 1,
+ NULL, decodebuf) < 0) {
+ /* contains invalid data. show what we got so far. */
}
+ break;
+ default:
+ /* unknown encoding */
+ return 0;
}
- ret = decodebuf->used == 0 ? FALSE :
- callback(decodebuf->data, decodebuf->used, charset, context);
-
- t_pop();
- return ret;
+ return start_pos[2] + 2;
}
void message_header_decode(const unsigned char *data, size_t size,
message_header_decode_callback_t *callback,
void *context)
{
- size_t pos, start_pos, subsize;
+ buffer_t *decodebuf = NULL;
+ unsigned int charsetlen = 0;
+ size_t pos, start_pos;
+ /* =?charset?Q|B?text?= */
+ t_push();
start_pos = pos = 0;
- while (pos < size) {
- if (data[pos] == '=' && pos+1 < size && data[pos+1] == '?') {
- /* encoded string beginning */
- if (pos != start_pos) {
- /* send the unencoded data so far */
- if (!callback(data + start_pos, pos - start_pos,
- NULL, context))
- return;
- }
+ for (pos = 0; pos + 1 < size; ) {
+ if (data[pos] != '=' || data[pos+1] != '?') {
+ pos++;
+ continue;
+ }
- pos += 2;
- subsize = size - pos;
- if (!message_header_decode_encoded(data + pos, &subsize,
- callback, context))
- return;
+ /* encoded string beginning */
+ if (pos != start_pos) {
+ /* send the unencoded data so far */
+ if (!callback(data + start_pos, pos - start_pos,
+ NULL, context)) {
+ start_pos = size;
+ break;
+ }
+ }
- pos += subsize;
- start_pos = pos;
+ if (decodebuf == NULL) {
+ decodebuf =
+ buffer_create_dynamic(pool_datastack_create(),
+ size - pos);
} else {
- pos++;
+ buffer_set_used_size(decodebuf, 0);
}
+
+ pos += 2;
+ pos += message_header_decode_encoded(data + pos, size - pos,
+ decodebuf, &charsetlen);
+
+ if (decodebuf->used > charsetlen) {
+ /* decodebuf contains <charset> NUL <text> */
+ if (!callback(CONST_PTR_OFFSET(decodebuf->data,
+ charsetlen),
+ decodebuf->used - charsetlen,
+ decodebuf->data, context)) {
+ start_pos = size;
+ break;
+ }
+ }
+
+ start_pos = pos;
}
- if (size > start_pos) {
+ if (size != start_pos) {
(void)callback(data + start_pos, size - start_pos,
NULL, context);
}
+ t_pop();
}
More information about the dovecot-cvs
mailing list