1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-06-12 18:11:03 +02:00

tools: Add a quoted-printable encoding function.

* tools/mime-maker.c (mime_maker_qp_encode): New.
* tools/t-mime-maker.c: New.
* tools/Makefile.am (TESTS): New.
(module_tests): Add the first test.
This commit is contained in:
Werner Koch 2025-05-30 12:15:37 +02:00
parent 8d837279bc
commit 61514f7cd8
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
4 changed files with 227 additions and 2 deletions

View File

@ -51,6 +51,12 @@ gpg-wks-client-w32info.o : gpg-wks-client.w32-manifest \
endif
if DISABLE_TESTS
TESTS =
else
TESTS = $(module_tests)
endif
AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) $(LIBASSUAN_CFLAGS)
sbin_SCRIPTS = addgnupghome applygnupgdefaults
@ -76,7 +82,7 @@ if !HAVE_W32_SYSTEM
libexec_PROGRAMS += gpg-auth
endif
noinst_PROGRAMS = clean-sat make-dns-cert
noinst_PROGRAMS = clean-sat make-dns-cert $(module_tests)
if BUILD_GPGTAR
bin_PROGRAMS += gpgtar
@ -216,6 +222,24 @@ gpg_auth_LDADD = $(common_libs) \
$(GPG_ERROR_LIBS) \
$(LIBINTL) $(NETLIBS) $(LIBICONV)
#
# Module tests
#
module_tests = t-mime-maker
t_extra_src =
t_common_cflags = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) $(INCICONV)
t_common_ldadd = $(libcommon) \
$(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \
$(LIBINTL) $(LIBICONV)
t_mime_maker_SOURCES = t-mime-maker.c \
rfc822parse.c rfc822parse.h \
mime-maker.c mime-maker.h $(t_extra_src)
t_mime_maker_LDADD = $(t_common_ldadd)
# Instead of a symlink we install a simple wrapper script for the new
# gpg-wks-client location. We assume bin is a sibling of libexec.
install-exec-local:

View File

@ -1,5 +1,5 @@
/* mime-maker.c - Create MIME structures
* Copyright (C) 2016 g10 Code GmbH
* Copyright (C) 2016, 2025 g10 Code GmbH
* Copyright (C) 2016 Bundesamt für Sicherheit in der Informationstechnik
*
* This file is part of GnuPG.
@ -16,6 +16,7 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include <config.h>
@ -348,6 +349,89 @@ add_header (part_t part, const char *name, const char *value)
}
/* Return a new string which is QP encoded. Also encodes the F in a
* leading "From " and a line with a single dot. Return NULL and sets
* ERRNO on error. */
char *
mime_maker_qp_encode (const char *string)
{
/* Check whether the current character is followed by a line ending.
* The end of the string also considered a line ending. */
#define nextislf(a) (*a && ((a[1] == '\r' && a[2] == '\n') \
|| a[1] == '\n' || !a[1]))
#define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
char *buffer, *p;
const unsigned char *s;
int lastwaslf;
size_t n;
/* Count the required length. */
for (lastwaslf=1, n=0, s = string; *s; s++)
{
if (*s == '.' && nextislf (s))
{
n += 3;
}
else if (!strncmp (s, "From ", 5))
{
n += 3 + 4;
s += 4;
}
else if (*s == '=')
{
n += 3;
}
else if (strchr ("\r\n\t", *s) || (*s >= 0x20 && *s <= 0x7e))
n++;
else
n += 3;
}
n++;
/* Now encode. */
p = buffer = xtrymalloc (n);
if (!buffer)
return NULL;
for (lastwaslf=1, s = string; *s; s++)
{
if (lastwaslf && *s == '.' && nextislf (s))
{
*p++ = '=';
*p++ = '2';
*p++ = 'E';
}
else if (lastwaslf && !strncmp (s, "From ", 5))
{
memcpy (p, "=46rom ", 7);
p += 7;
s += 4;
}
else if (*s == '=')
{
*p++ = '=';
*p++ = '3';
*p++ = 'D';
}
else if (strchr ("\r\n\t", *s) || (*s >= 0x20 && *s <= 0x7e))
*p++ = *s;
else
{
*p++ = '=';
*p++ = tohex ((*s>>4)&15);
*p++ = tohex (*s&15);
}
lastwaslf = (*s == '\n');
}
*p = 0;
return buffer;
#undef tohex
#undef nextislf
}
/* Add a header with NAME and VALUE to the current mail. A LF in the
* VALUE will be handled automagically. If NULL is used for VALUE it
* is expected that the NAME has the format "NAME=VALUE" and VALUE is

View File

@ -31,6 +31,7 @@ void mime_maker_set_verbose (mime_maker_t ctx, int level);
void mime_maker_dump_tree (mime_maker_t ctx);
char *mime_maker_qp_encode (const char *string);
gpg_error_t mime_maker_add_header (mime_maker_t ctx,
const char *name, const char *value);
gpg_error_t mime_maker_add_body (mime_maker_t ctx, const char *string);

116
tools/t-mime-maker.c Normal file
View File

@ -0,0 +1,116 @@
/* t-mime-maker.c - Module test for mime-maker.c
* Copyright (C) 2025 g10 Code GmbH
*
* This file is part of GnuPG.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "../common/util.h"
#include "../common/init.h"
#include "mime-maker.h"
static int verbose;
static void
test_qp_encode (void)
{
static struct
{
const char *plain;
const char *encoded;
} samples[] =
{
{ "",
""
},{
"From someone\n"
" I received this mail\n",
"=46rom someone\n"
" I received this mail\n"
},{
" From someone\n",
" From someone\n"
},{
"Foo\n"
".\n",
"Foo\n"
"=2E\n"
},{
"Foo\n"
".",
"Foo\n"
"=2E"
},{
"Hello ÄÖܧäöüß my dear umlauts",
"Hello =C3=84=C3=96=C3=9C=C2=A7=C3=A4=C3=B6=C3=BC=C3=9F "
"my dear umlauts"
},{
"👀\t",
"=F0=9F=91=80\t=E2=92=B6"
}
};
int idx;
char *result;
int oops = 0;
for (idx=0; idx < DIM (samples); idx++)
{
result = mime_maker_qp_encode (samples[idx].plain);
if (!result)
{
log_error ("%s:test %d: error: %s\n",
__func__, idx, strerror (errno));
exit (1);
}
if (strcmp (samples[idx].encoded, result))
{
log_error ("%s:test %d: error\nwant ===>%s<===\n got ===>%s<===\n",
__func__, idx, samples[idx].plain, result);
oops = 1;
}
}
if (oops)
exit (1);
}
int
main (int argc, char **argv)
{
log_set_prefix ("t-mime-maker", GPGRT_LOG_WITH_PREFIX);
init_common_subsystems (&argc, &argv);
if (argc)
{ argc--; argv++; }
if (argc && !strcmp (argv[0], "--verbose"))
{
verbose = 1;
argc--; argv++;
}
test_qp_encode ();
return 0;
}