From: Baptiste Daroussin Date: Wed, 8 Jan 2025 10:42:45 +0000 (+0100) Subject: decode_qp: add Q format support and reuse the function X-Git-Tag: RELEASE_1_5_0~2 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=687e325749cb52eebefde483688dd5fa9e980d42;p=thirdparty%2Fmlmmj.git decode_qp: add Q format support and reuse the function decode rfc2047's Q format using the strgen's decode_qp this reduces code duplication --- diff --git a/include/strgen.h b/include/strgen.h index 8f63a670..3fac0820 100644 --- a/include/strgen.h +++ b/include/strgen.h @@ -35,7 +35,7 @@ char *mydirname(const char *path); const char *mybasename(const char *path); char *genmsgid(const char *fqdn); char *gendatestr(void); -char *decode_qp(const char *qpstr); +char *decode_qp(const char *qpstr, bool qformat); bool splitlistaddr(const char *listaddr, char **listname, const char **listfqdn); #endif /* STRGEN_H */ diff --git a/src/do_all_the_voodoo_here.c b/src/do_all_the_voodoo_here.c index 2e58e178..3ba56da7 100644 --- a/src/do_all_the_voodoo_here.c +++ b/src/do_all_the_voodoo_here.c @@ -128,7 +128,7 @@ int do_all_the_voodoo_here(int infd, int outfd, int hdrfd, int footfd, if(prefix) { if(strncasecmp(hdrline, "Subject:", 8) == 0) { subject_present = 1; - unqp = decode_qp(hdrline + 8); + unqp = decode_qp(hdrline + 8, false); if(strstr(hdrline + 8, prefix) == NULL && strstr(unqp, prefix) == NULL) { dprintf(outfd, "Subject: %s%s\n", prefix, hdrline + 8); diff --git a/src/strgen.c b/src/strgen.c index d0e5a858..14418c76 100644 --- a/src/strgen.c +++ b/src/strgen.c @@ -190,7 +190,7 @@ decode_char(const char *s) } char * -decode_qp(const char *qpstr) +decode_qp(const char *qpstr, bool qformat) { char *buffer = NULL; size_t size = 0; @@ -224,6 +224,12 @@ decode_qp(const char *qpstr) fputc(decode_char(qpstr), bufp); qpstr += 2; break; + case '_': + if (qformat) { + fputc(0x20, bufp); + break; + } + /* FALLTHROUGH */ default: fputc(*qpstr, bufp); break; diff --git a/src/unistr.c b/src/unistr.c index 2984cc2c..c5fce3d7 100644 --- a/src/unistr.c +++ b/src/unistr.c @@ -35,6 +35,7 @@ #include "mlmmj.h" #include "xmalloc.h" #include "unistr.h" +#include "strgen.h" #include "log_error.h" /* This is allocated on the stack, so it can't be too big. */ @@ -266,40 +267,11 @@ char *unistr_to_utf8(const unistr *str) } -static int hexval(char ch) +static void +decode_quoted_print(char *str, char **binary, size_t *bin_len) { - ch = tolower(ch); - - if ((ch >= 'a') && (ch <= 'f')) { - return 10 + ch - 'a'; - } - - if ((ch >= '0') && (ch <= '9')) { - return ch - '0'; - } - - return 0; -} - - -static void decode_qp(char *str, char **binary, size_t *bin_len) -{ - int i; - - /* decoded string will never be longer, and we don't include a NUL */ - *binary = xmalloc(strlen(str)); - *bin_len = 0; - - for (i=0; str[i]; i++) { - if ((str[i] == '=') && isxdigit(str[i+1]) && isxdigit(str[i+2])) { - (*binary)[(*bin_len)++] = (hexval(str[i+1]) << 4) + hexval(str[i+2]); - i += 2; - } else if (str[i] == '_') { - (*binary)[(*bin_len)++] = 0x20; - } else { - (*binary)[(*bin_len)++] = str[i]; - } - } + *binary = decode_qp(str, true); + *bin_len = strlen(*binary); } @@ -407,7 +379,7 @@ static int header_decode_word(char *wsp, char *word, unistr *ret) } if (tolower(encoding[0]) == 'q') { - decode_qp(string, &binary, &bin_len); + decode_quoted_print(string, &binary, &bin_len); } else if (tolower(encoding[0]) == 'b') { decode_base64(string, &binary, &bin_len); } else { diff --git a/tests/mlmmj.c b/tests/mlmmj.c index 670b0df6..ac8a15b3 100644 --- a/tests/mlmmj.c +++ b/tests/mlmmj.c @@ -683,16 +683,17 @@ ATF_TC_BODY(strtotimet, tc) ATF_TC_BODY(decode_qp, tc) { - ATF_REQUIRE_STREQ(decode_qp("="), "="); - ATF_REQUIRE_STREQ(decode_qp("=\ra"), "=\ra"); - ATF_REQUIRE_STREQ(decode_qp("=\r\na"), "a"); - ATF_REQUIRE_STREQ(decode_qp("=\na"), "a"); - ATF_REQUIRE_STREQ(decode_qp("This is a subject"), "This is a subject"); - ATF_REQUIRE_STREQ(decode_qp("This= is a subject"), "This= is a subject"); - ATF_REQUIRE_STREQ(decode_qp("This=2 is a subject"), "This=2 is a subject"); - ATF_REQUIRE_STREQ(decode_qp("This=23 is a subject"), "This# is a subject"); - ATF_REQUIRE_STREQ(decode_qp("This=3D is a subject"), "This= is a subject"); - ATF_REQUIRE_STREQ(decode_qp("This_ is a subject"), "This_ is a subject"); + ATF_REQUIRE_STREQ(decode_qp("=", false), "="); + ATF_REQUIRE_STREQ(decode_qp("=\ra", false), "=\ra"); + ATF_REQUIRE_STREQ(decode_qp("=\r\na", false), "a"); + ATF_REQUIRE_STREQ(decode_qp("=\na", false), "a"); + ATF_REQUIRE_STREQ(decode_qp("This is a subject", false), "This is a subject"); + ATF_REQUIRE_STREQ(decode_qp("This= is a subject", false), "This= is a subject"); + ATF_REQUIRE_STREQ(decode_qp("This=2 is a subject", false), "This=2 is a subject"); + ATF_REQUIRE_STREQ(decode_qp("This=23 is a subject", false), "This# is a subject"); + ATF_REQUIRE_STREQ(decode_qp("This=3D is a subject", false), "This= is a subject"); + ATF_REQUIRE_STREQ(decode_qp("This_ is a subject", false), "This_ is a subject"); + ATF_REQUIRE_STREQ(decode_qp("This_ is a subject", true), "This is a subject"); } ATF_TC_BODY(parse_lastdigest, tc)