char translation_buf[MAX_TRANSLATION_BUF_SIZE];
unsigned int translation_size;
- char encoding_buf[MAX_ENCODING_BUF_SIZE];
- unsigned int encoding_size;
+ buffer_t *encoding_buf;
char *content_charset;
enum content_type content_type;
ctx->flags = flags;
ctx->buf = buffer_create_dynamic(default_pool, 8192);
ctx->buf2 = buffer_create_dynamic(default_pool, 8192);
+ ctx->encoding_buf = buffer_create_dynamic(default_pool, 128);
return ctx;
}
if (ctx->charset_trans != NULL)
charset_to_utf8_end(&ctx->charset_trans);
+ buffer_free(&ctx->encoding_buf);
buffer_free(&ctx->buf);
buffer_free(&ctx->buf2);
i_free(ctx->charset_trans_charset);
struct message_block *input,
struct message_block *output)
{
- unsigned char new_buf[MAX_ENCODING_BUF_SIZE+1];
const unsigned char *data = NULL;
- size_t pos, size = 0, skip = 0;
+ size_t pos, size = 0;
int ret;
- if (ctx->encoding_size != 0) {
+ if (ctx->encoding_buf->used != 0) {
/* @UNSAFE */
- memcpy(new_buf, ctx->encoding_buf, ctx->encoding_size);
- skip = sizeof(new_buf) - ctx->encoding_size;
- if (skip > input->size)
- skip = input->size;
- memcpy(new_buf + ctx->encoding_size, input->data, skip);
+ buffer_append(ctx->encoding_buf, input->data, input->size);
}
switch (ctx->content_type) {
break;
case CONTENT_TYPE_QP:
buffer_set_used_size(ctx->buf, 0);
- if (ctx->encoding_size != 0) {
- quoted_printable_decode(new_buf,
- ctx->encoding_size + skip,
+ if (ctx->encoding_buf->used != 0) {
+ quoted_printable_decode(ctx->encoding_buf->data,
+ ctx->encoding_buf->used,
+ &pos, ctx->buf);
+ } else {
+ quoted_printable_decode(input->data, input->size,
&pos, ctx->buf);
- i_assert(pos >= ctx->encoding_size);
- skip = pos - ctx->encoding_size;
}
-
- quoted_printable_decode(input->data + skip, input->size - skip,
- &pos, ctx->buf);
- pos += skip;
data = ctx->buf->data;
size = ctx->buf->used;
break;
case CONTENT_TYPE_BASE64:
buffer_set_used_size(ctx->buf, 0);
- if (ctx->encoding_size != 0) {
- if (base64_decode(new_buf, ctx->encoding_size + skip,
- &pos, ctx->buf) < 0) {
- /* corrupted base64 data, don't bother with
- the rest of it */
- return FALSE;
- }
- i_assert(pos >= ctx->encoding_size);
- skip = pos - ctx->encoding_size;
+ if (ctx->encoding_buf->used != 0) {
+ ret = base64_decode(ctx->encoding_buf->data,
+ ctx->encoding_buf->used,
+ &pos, ctx->buf);
+ } else {
+ ret = base64_decode(input->data, input->size,
+ &pos, ctx->buf);
}
- ret = base64_decode(input->data + skip, input->size - skip,
- &pos, ctx->buf);
if (ret < 0) {
/* corrupted base64 data, don't bother with
the rest of it */
}
if (ret == 0) {
/* end of base64 input */
- pos = input->size - skip;
+ pos = input->size;
+ buffer_set_used_size(ctx->encoding_buf, 0);
}
- pos += skip;
data = ctx->buf->data;
size = ctx->buf->used;
break;
}
- if (pos != input->size) {
- /* @UNSAFE */
- i_assert(pos < input->size);
- ctx->encoding_size = input->size - pos;
- i_assert(ctx->encoding_size <= sizeof(ctx->encoding_buf));
- memcpy(ctx->encoding_buf, input->data + pos,
- ctx->encoding_size);
- } else {
- ctx->encoding_size = 0;
+ if (ctx->encoding_buf->used != 0)
+ buffer_delete(ctx->encoding_buf, 0, pos);
+ else if (pos != input->size) {
+ buffer_append(ctx->encoding_buf,
+ input->data + pos, input->size - pos);
}
if (ctx->binary_input) {
i_free_and_null(ctx->content_charset);
ctx->content_type = CONTENT_TYPE_BINARY;
ctx->charset_utf8 = TRUE;
- ctx->encoding_size = 0;
+ buffer_set_used_size(ctx->encoding_buf, 0);
}
--- /dev/null
+/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "buffer.h"
+#include "charset-utf8.h"
+#include "quoted-printable.h"
+#include "message-parser.h"
+#include "message-header-decode.h"
+#include "message-decoder.h"
+#include "test-common.h"
+
+bool message_header_decode_utf8(const unsigned char *data, size_t size,
+ buffer_t *dest, bool dtcase ATTR_UNUSED)
+{
+ buffer_append(dest, data, size);
+ return FALSE;
+}
+
+void quoted_printable_decode(const unsigned char *src, size_t src_size,
+ size_t *src_pos_r, buffer_t *dest)
+{
+ while (src_size > 0 && src[src_size-1] == ' ')
+ src_size--;
+ buffer_append(dest, src, src_size);
+ *src_pos_r = src_size;
+}
+
+int charset_to_utf8_begin(const char *charset ATTR_UNUSED,
+ enum charset_flags flags ATTR_UNUSED,
+ struct charset_translation **t_r)
+{
+ *t_r = NULL;
+ return 0;
+}
+void charset_to_utf8_end(struct charset_translation **t ATTR_UNUSED) { }
+bool charset_is_utf8(const char *charset ATTR_UNUSED) { return TRUE; }
+
+enum charset_result
+charset_to_utf8(struct charset_translation *t ATTR_UNUSED,
+ const unsigned char *src, size_t *src_size, buffer_t *dest)
+{
+ buffer_append(dest, src, *src_size);
+ return CHARSET_RET_OK;
+}
+
+static void test_message_decoder(void)
+{
+ struct message_decoder_context *ctx;
+ struct message_part part;
+ struct message_header_line hdr;
+ struct message_block input, output;
+
+ test_begin("message decoder");
+
+ memset(&part, 0, sizeof(part));
+ memset(&input, 0, sizeof(input));
+ memset(&output, 0, sizeof(output));
+ input.part = ∂
+
+ ctx = message_decoder_init(0);
+
+ hdr.name = "Content-Transfer-Encoding";
+ hdr.name_len = strlen(hdr.name);
+ hdr.full_value = (const void *)"quoted-printable";
+ hdr.full_value_len = strlen((const char *)hdr.full_value);
+ input.hdr = &hdr;
+ test_assert(message_decoder_decode_next_block(ctx, &input, &output));
+
+ input.hdr = NULL;
+ test_assert(message_decoder_decode_next_block(ctx, &input, &output));
+
+ input.hdr = NULL;
+ test_assert(message_decoder_decode_next_block(ctx, &input, &output));
+
+ input.data = (const void *)"foo ";
+ input.size = strlen((const char *)input.data);
+ test_assert(message_decoder_decode_next_block(ctx, &input, &output));
+ test_assert(output.size == 3);
+ test_assert(memcmp(output.data, "foo", 3) == 0);
+
+ input.data = (const void *)"bar";
+ input.size = strlen((const char *)input.data);
+ test_assert(message_decoder_decode_next_block(ctx, &input, &output));
+ test_assert(output.size == 14);
+ test_assert(memcmp(output.data, " bar", 14) == 0);
+
+ message_decoder_deinit(&ctx);
+
+ test_end();
+}
+
+int main(void)
+{
+ static void (*test_functions[])(void) = {
+ test_message_decoder,
+ NULL
+ };
+ return test_run(test_functions);
+}