bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
c7e60c7a4052db86fa90147a52d613d00f720c45Timo Sirainen
c7e60c7a4052db86fa90147a52d613d00f720c45Timo Sirainen#include "lib.h"
def516ea503a60f20d510c14d5070b7ff5bbddf4Timo Sirainen#include "buffer.h"
c7e60c7a4052db86fa90147a52d613d00f720c45Timo Sirainen#include "hex-binary.h"
c7e60c7a4052db86fa90147a52d613d00f720c45Timo Sirainen#include "quoted-printable.h"
c7e60c7a4052db86fa90147a52d613d00f720c45Timo Sirainen
e4f1a5fdad77884e1de516521504c15dc936fa9dTimo Sirainenint quoted_printable_q_decode(const unsigned char *src, size_t src_size,
e4f1a5fdad77884e1de516521504c15dc936fa9dTimo Sirainen buffer_t *dest)
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen{
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen char hexbuf[3];
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen size_t src_pos, next;
e4f1a5fdad77884e1de516521504c15dc936fa9dTimo Sirainen bool errors = FALSE;
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen hexbuf[2] = '\0';
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen next = 0;
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen for (src_pos = 0; src_pos < src_size; src_pos++) {
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen if (src[src_pos] != '_' && src[src_pos] != '=')
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen continue;
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen buffer_append(dest, src + next, src_pos - next);
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen next = src_pos;
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen if (src[src_pos] == '_') {
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen buffer_append_c(dest, ' ');
9882f82ad44ddee334081956e14118813651295fTimo Sirainen next++;
9882f82ad44ddee334081956e14118813651295fTimo Sirainen continue;
9882f82ad44ddee334081956e14118813651295fTimo Sirainen }
9882f82ad44ddee334081956e14118813651295fTimo Sirainen
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen if (src_pos+2 >= src_size)
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen break;
1a1fcdbe27a8cee9a4c453a6b2f625a5be572a32Timo Sirainen
9882f82ad44ddee334081956e14118813651295fTimo Sirainen /* =<hex> */
9882f82ad44ddee334081956e14118813651295fTimo Sirainen hexbuf[0] = src[src_pos+1];
9882f82ad44ddee334081956e14118813651295fTimo Sirainen hexbuf[1] = src[src_pos+2];
9882f82ad44ddee334081956e14118813651295fTimo Sirainen
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen if (hex_to_binary(hexbuf, dest) == 0) {
9882f82ad44ddee334081956e14118813651295fTimo Sirainen src_pos += 2;
def516ea503a60f20d510c14d5070b7ff5bbddf4Timo Sirainen next = src_pos+1;
def516ea503a60f20d510c14d5070b7ff5bbddf4Timo Sirainen } else {
9882f82ad44ddee334081956e14118813651295fTimo Sirainen /* non-hex data, show as-is */
e4f1a5fdad77884e1de516521504c15dc936fa9dTimo Sirainen errors = TRUE;
9882f82ad44ddee334081956e14118813651295fTimo Sirainen next = src_pos;
c7e60c7a4052db86fa90147a52d613d00f720c45Timo Sirainen }
c7e60c7a4052db86fa90147a52d613d00f720c45Timo Sirainen }
847aeef259d42e2f14cf126699e28291e6e1fb53Timo Sirainen buffer_append(dest, src + next, src_size - next);
e4f1a5fdad77884e1de516521504c15dc936fa9dTimo Sirainen return errors ? -1 : 0;
c7e60c7a4052db86fa90147a52d613d00f720c45Timo Sirainen}