message-header-decode.c revision b516a7812b9acc04522869fead3aa6d2787dcdc6
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2002-2011 Dovecot authors, see the included COPYING file */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainenmessage_header_decode_encoded(const unsigned char *data, size_t size,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen buffer_t *decodebuf, unsigned int *charsetlen_r)
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen unsigned int num = 0;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen /* data should contain "charset?encoding?text?=" */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen for (i = 0; i < size; i++) {
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen /* invalid block */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen quoted_printable_q_decode(data + start_pos[1] + 1,
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainen /* contains invalid data. show what we got so far. */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen /* unknown encoding */
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainenstatic bool is_only_lwsp(const unsigned char *data, unsigned int size)
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen unsigned int i;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen for (i = 0; i < size; i++) {
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainenvoid message_header_decode(const unsigned char *data, size_t size,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen unsigned int charsetlen = 0;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen /* =?charset?Q|B?text?= */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen /* encoded string beginning */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen !is_only_lwsp(data+start_pos, pos-start_pos)) {
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen /* send the unencoded data so far */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if (!callback(data + start_pos, pos - start_pos,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen decodebuf = buffer_create_dynamic(default_pool,
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen ret = message_header_decode_encoded(data + pos, size - pos,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen /* decodebuf contains <charset> NUL <text> */
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (!callback(CONST_PTR_OFFSET(decodebuf->data,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen (void)callback(data + start_pos, size - start_pos,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainendecode_utf8_callback(const unsigned char *data, size_t size,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen /* one call with charset=NULL means nothing changed */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if (charset == NULL || charset_is_utf8(charset)) {
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen /* ASCII / UTF-8 */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen (void)uni_utf8_to_decomposed_titlecase(data, size,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if (uni_utf8_get_valid_data(data, size, ctx->dest))
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen flags = ctx->dtcase ? CHARSET_FLAG_DECOMP_TITLECASE : 0;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if (charset_to_utf8_begin(charset, flags, &t) < 0) {
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen /* data probably still contains some valid ASCII characters.
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen append them. */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if (uni_utf8_get_valid_data(data, size, ctx->dest))
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen /* ignore any errors */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen (void)charset_to_utf8(t, data, &size, ctx->dest);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainenbool message_header_decode_utf8(const unsigned char *data, size_t size,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen message_header_decode(data, size, decode_utf8_callback, &ctx);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen return ctx.changed || (dest->used - used != size);