Mercurial > dovecot > core-2.2
view src/lib-mail/quoted-printable.c @ 17130:add8c00fb3cc
Updated copyright notices to include year 2014.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 04 Feb 2014 16:23:22 -0500 |
parents | 6821794943a5 |
children | 3009a1a6f6d5 |
line wrap: on
line source
/* Copyright (c) 2002-2014 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "buffer.h" #include "hex-binary.h" #include "quoted-printable.h" #define QP_IS_TRAILING_SPACE(c) \ ((c) == ' ' || (c) == '\t') static int qp_is_end_of_line(const unsigned char *src, size_t *src_pos, size_t size) { size_t i = *src_pos; i_assert(src[i] == '='); for (i++; i < size; i++) { if (QP_IS_TRAILING_SPACE(src[i]) || src[i] == '\r') continue; if (src[i] != '\n') return 0; *src_pos = i; return 1; } return -1; } static int quoted_printable_decode_full(const unsigned char *src, size_t src_size, size_t *src_pos_r, buffer_t *dest, bool eof) { char hexbuf[3]; size_t src_pos, pos, next; bool errors = FALSE; int ret; hexbuf[2] = '\0'; next = 0; for (src_pos = 0; src_pos < src_size; src_pos++) { if (src[src_pos] != '=' && src[src_pos] != '\n') continue; if (src[src_pos] == '\n') { /* drop trailing whitespace */ pos = src_pos; if (pos > 0 && src[pos-1] == '\r') pos--; while (pos > 0 && QP_IS_TRAILING_SPACE(src[pos-1])) pos--; buffer_append(dest, src + next, pos - next); next = src_pos+1; buffer_append_c(dest, '\r'); buffer_append_c(dest, '\n'); continue; } /* '=' */ buffer_append(dest, src + next, src_pos - next); next = src_pos; if ((ret = qp_is_end_of_line(src, &src_pos, src_size)) > 0) { /* =[whitespace][\r]\n */ next = src_pos+1; continue; } if (ret < 0) { /* '=' was followed only by whitespace */ break; } if (src_pos+2 >= src_size) { /* '=' was followed by non-whitespace */ if (eof) errors = TRUE; break; } /* =<hex> */ hexbuf[0] = src[src_pos+1]; hexbuf[1] = src[src_pos+2]; if (hex_to_binary(hexbuf, dest) == 0) { src_pos += 2; next = src_pos + 1; } else { /* non-hex data, show as-is */ errors = TRUE; next = src_pos; } } if (src_pos == src_size) { /* add everything but trailing spaces */ if (src_pos > 0 && src[src_pos-1] == '\r') src_pos--; while (src_pos > 0 && QP_IS_TRAILING_SPACE(src[src_pos-1])) src_pos--; buffer_append(dest, src + next, src_pos - next); next = src_pos; } *src_pos_r = next; return errors ? -1 : 0; } int quoted_printable_decode(const unsigned char *src, size_t src_size, size_t *src_pos_r, buffer_t *dest) { return quoted_printable_decode_full(src, src_size, src_pos_r, dest, FALSE); } int quoted_printable_decode_final(const unsigned char *src, size_t src_size, size_t *src_pos_r, buffer_t *dest) { return quoted_printable_decode_full(src, src_size, src_pos_r, dest, TRUE); } int quoted_printable_q_decode(const unsigned char *src, size_t src_size, buffer_t *dest) { char hexbuf[3]; size_t src_pos, next; bool errors = FALSE; hexbuf[2] = '\0'; next = 0; for (src_pos = 0; src_pos < src_size; src_pos++) { if (src[src_pos] != '_' && src[src_pos] != '=') continue; buffer_append(dest, src + next, src_pos - next); next = src_pos; if (src[src_pos] == '_') { buffer_append_c(dest, ' '); next++; continue; } if (src_pos+2 >= src_size) break; /* =<hex> */ hexbuf[0] = src[src_pos+1]; hexbuf[1] = src[src_pos+2]; if (hex_to_binary(hexbuf, dest) == 0) { src_pos += 2; next = src_pos+1; } else { /* non-hex data, show as-is */ errors = TRUE; next = src_pos; } } buffer_append(dest, src + next, src_size - next); return errors ? -1 : 0; }