aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2025-06-02 10:42:59 +0000
committerWerner Koch <[email protected]>2025-06-02 10:42:59 +0000
commite6463d7fe097b39c9e8952ef9f5758fa0ee0e4bd (patch)
tree38222b8338276d8de0b92130dd43b003ec46754c
parentgpg-mail-tube: Support templates. (diff)
downloadgnupg-e6463d7fe097b39c9e8952ef9f5758fa0ee0e4bd.tar.gz
gnupg-e6463d7fe097b39c9e8952ef9f5758fa0ee0e4bd.zip
wks: Use templates for the server responses.
* common/helpfile.c (gnupg_get_template): Add arg locale_override and adjust all callers. * tools/wks-receive.c (struct receive_ctx_s): Add field ct_language. (get_language): New. (new_part): Call it. (wks_receive): Pass language to the result callback. * tools/gpg-wks-client.c (short_locale): New. (main): Get and store the current locale. (command_create): Fix a glitch for the Posteo hack. Insert the locale into the confirmation request. (send_confirmation_response): Ditto. * tools/gpg-wks-server.c (struct server_ctx_s): Add field language. (only_ascii): New. (struct my_subst_vars_s, my_subst_vars_cb, my_subst_vars): New. (send_confirmation_request): Use a template. (send_congratulation_message): Ditto. (check_and_publish): Pss ctx to send_congratulation_message. (command_receive_cb): Add arg language. * doc/wks-utils.txt, doc/wks-utils.de.txt: New. * doc/Makefile.am (helpfiles): Add them. -- GnuPG-bug-id: 7381 Note that the subject is not yet translated or templated due to a missing header encoding function.
-rw-r--r--common/helpfile.c22
-rw-r--r--common/t-helpfile.c2
-rw-r--r--common/util.h2
-rw-r--r--doc/Makefile.am3
-rw-r--r--doc/wks-utils.de.txt73
-rw-r--r--doc/wks-utils.txt71
-rw-r--r--doc/wks.texi9
-rw-r--r--tools/gpg-mail-tube.c5
-rw-r--r--tools/gpg-wks-client.c70
-rw-r--r--tools/gpg-wks-server.c184
-rw-r--r--tools/gpg-wks.h1
-rw-r--r--tools/wks-receive.c39
12 files changed, 406 insertions, 75 deletions
diff --git a/common/helpfile.c b/common/helpfile.c
index 956ec2516..240562794 100644
--- a/common/helpfile.c
+++ b/common/helpfile.c
@@ -234,21 +234,25 @@ findkey_locale (const char *domain, const char *key, const char *locname,
intervening lines (except for comment lines) lead to the same help
text. Lines following the key lines make up the actual template texts.
*/
-
char *
-gnupg_get_template (const char *domain, const char *key, unsigned int flags)
+gnupg_get_template (const char *domain, const char *key, unsigned int flags,
+ const char *override_locale)
{
- static const char *locname;
+ static const char *locname_buffer;
+ const char *locname;
char *result;
- if (!locname)
+ if (override_locale && *override_locale)
+ locname = override_locale;
+ else if (!locname_buffer)
{
char *buffer, *p;
int count = 0;
const char *s = gnupg_messages_locale_name ();
+
buffer = xtrystrdup (s);
if (!buffer)
- locname = "";
+ locname_buffer = "";
else
{
for (p = buffer; *p; p++)
@@ -259,9 +263,12 @@ gnupg_get_template (const char *domain, const char *key, unsigned int flags)
if (count++)
*p = 0; /* Also cut at an underscore in the territory. */
}
- locname = buffer;
+ locname_buffer = buffer;
}
+ locname = locname_buffer;
}
+ else
+ locname = locname_buffer;
if (!key || !*key)
return NULL;
@@ -293,5 +300,6 @@ char *
gnupg_get_help_string (const char *key, int only_current)
{
return gnupg_get_template ("help", key,
- only_current? GET_TEMPLATE_CURRENT_LOCALE : 0);
+ only_current? GET_TEMPLATE_CURRENT_LOCALE : 0,
+ NULL);
}
diff --git a/common/t-helpfile.c b/common/t-helpfile.c
index adb69ba2d..d1e7f547d 100644
--- a/common/t-helpfile.c
+++ b/common/t-helpfile.c
@@ -66,7 +66,7 @@ main (int argc, char **argv)
}
- result = gnupg_get_template (argv[0], argv[1], flags);
+ result = gnupg_get_template (argv[0], argv[1], flags, NULL);
if (!result)
{
fprintf (stderr,
diff --git a/common/util.h b/common/util.h
index ce1dc37d8..b81664c3e 100644
--- a/common/util.h
+++ b/common/util.h
@@ -303,7 +303,7 @@ void gnupg_rl_initialize (void);
#define GET_TEMPLATE_CRLF 4 /* Use CR+LF. */
char *gnupg_get_template (const char *domain, const char *key,
- unsigned int flags);
+ unsigned int flags, const char *override_locale);
char *gnupg_get_help_string (const char *key, int only_current_locale);
/*-- localename.c --*/
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 6d52de830..1e4c6fb64 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -34,7 +34,8 @@ helpfiles = help.txt help.be.txt help.ca.txt help.cs.txt \
help.ja.txt help.nb.txt help.pl.txt help.pt.txt \
help.pt_BR.txt help.ro.txt help.ru.txt help.sk.txt \
help.sv.txt help.tr.txt help.zh_CN.txt help.zh_TW.txt \
- mail-tube.txt mail-tube.de.txt
+ mail-tube.txt mail-tube.de.txt \
+ wks-utils.txt wks-utils.de.txt
EXTRA_DIST = samplekeys.asc mksamplekeys com-certs.pem \
gnupg-logo.pdf gnupg-logo.png gnupg-logo-tr.png \
diff --git a/doc/wks-utils.de.txt b/doc/wks-utils.de.txt
new file mode 100644
index 000000000..02f768476
--- /dev/null
+++ b/doc/wks-utils.de.txt
@@ -0,0 +1,73 @@
+# wks-utils.txt - gpg-wks-server/-client strings (de) -*- default-generic -*-
+# Written in 2025 by g10 Code GmbH
+#
+# To the extent possible under law, the author(s) have dedicated all
+# copyright and related and neighboring rights to this text to the
+# public domain worldwide. This text is distributed without any
+# warranty. You should have received a copy of the CC0 Public Domain
+# Dedication along with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>.
+# SPDX-License-Identifier: CC0-1.0
+#
+# Note that this template file needs to be UTF-8 encoded. When looking
+# for a template item, GnuPG scans the help files in the following order
+# (assuming a standard Unix layout):
+#
+# /etc/gnupg/TEMPLATE.LL_TT.txt
+# /etc/gnupg/TEMPLATE.LL.txt
+# /etc/gnupg/TEMPLATE.txt
+# /usr/share/gnupg/TEMPLATE.LL_TT.txt
+# /usr/share/gnupg/TEMPLATE.LL.txt
+# /usr/share/gnupg/TEMPLATE.txt
+#
+# Here TEMPLATE denotes the name of the template (e.g. "mail-tube"),
+# LL_TT denotes the full name of the current locale with the territory
+# (.e.g. "de_DE"), LL denotes just the locale name (e.g. "de"). The
+# first matching item is returned. To put a dot or a hash mark at the
+# beginning of a text line, it needs to be prefixed with a dot and a
+# space. A single dot may be used to terminated an entry. Depending
+# on the template type certain variables (${NAME}) are expanded.
+# Check the man page of the respective tool.
+
+.server.confirm.body
+
+Diese Nachricht wurde auf Ihre Anforderung gesendet, Ihren Schlüssel
+zu veröffentlichen. Falls Sie solch eine Anforderung nicht gesendet
+haben, so ignorieren Sie bitte diese Nachricht.
+
+[English: This message has been send to confirm your request
+ to publish your key. If you did not request a key
+ publication, simply ignore this message.]
+
+Viele Mail Software ist in der Lage diese Art von Nachrichten
+automatisch zu verarbeiten. In diesem Fall sollten Sie diesen Text
+auch nicht sehen. Falls doch so ist Ihre Mailsoftware veraltet und
+kann mit dieser Nachricht nichts anfangen. Unter
+
+ https://gnupg.org/faq/wkd.html
+
+finden Sie eine Erklärung, wie Sie solche Nachrichten anderweitig
+verarbeiten können.
+
+
+${sigdelim}
+Weitere Informationen zu GnuPG finden Sie hier: https://gnupg.org
+
+.
+
+.server.publish.congrats
+Hallo!
+
+Der Schlüssel für Ihre Mailadresse '${address}' wurde soeben vom
+Web Key Directory akzeptiert. Je nach Konfiguration Ihres Providers kann
+es bis zu 15 Minuten dauern, bis er öffentlich sichtbar wird.
+
+Viele Grüße von Ihrem
+
+ Schlüsselveröffentlichungsdienst
+
+
+${sigdelim}
+Weitere Informationen zu GnuPG finden Sie hier: https://gnupg.org
+
+.
diff --git a/doc/wks-utils.txt b/doc/wks-utils.txt
new file mode 100644
index 000000000..012e46da6
--- /dev/null
+++ b/doc/wks-utils.txt
@@ -0,0 +1,71 @@
+# wks-utils.txt - gpg-wks-server/-client strings (en) -*- default-generic -*-
+# Written in 2025 by g10 Code GmbH
+#
+# To the extent possible under law, the author(s) have dedicated all
+# copyright and related and neighboring rights to this text to the
+# public domain worldwide. This text is distributed without any
+# warranty. You should have received a copy of the CC0 Public Domain
+# Dedication along with this software. If not, see
+# <https://creativecommons.org/publicdomain/zero/1.0/>.
+# SPDX-License-Identifier: CC0-1.0
+#
+# Note that this template file needs to be UTF-8 encoded. When looking
+# for a template item, GnuPG scans the help files in the following order
+# (assuming a standard Unix layout):
+#
+# /etc/gnupg/TEMPLATE.LL_TT.txt
+# /etc/gnupg/TEMPLATE.LL.txt
+# /etc/gnupg/TEMPLATE.txt
+# /usr/share/gnupg/TEMPLATE.LL_TT.txt
+# /usr/share/gnupg/TEMPLATE.LL.txt
+# /usr/share/gnupg/TEMPLATE.txt
+#
+# Here TEMPLATE denotes the name of the template (e.g. "mail-tube"),
+# LL_TT denotes the full name of the current locale with the territory
+# (.e.g. "de_DE"), LL denotes just the locale name (e.g. "de"). The
+# first matching item is returned. To put a dot or a hash mark at the
+# beginning of a text line, it needs to be prefixed with a dot and a
+# space. A single dot may be used to terminated an entry. Depending
+# on the template type certain variables (${NAME}) are expanded.
+# Check the man page of the respective tool.
+
+.server.confirm.body
+This message has been send to confirm your request
+to publish your key. If you did not request a key
+publication, simply ignore this message.
+
+Most mail software can handle this kind of message
+automatically and thus you would not have seen this
+message. It seems that your client does not fully
+support this service. The web page
+
+ https://gnupg.org/faq/wkd.html
+
+explains how you can process this message anyway in
+a few manual steps.
+
+
+${sigdelim}
+For information on GnuPG see: https://gnupg.org
+
+.
+
+.server.publish.congrats
+Hello!
+
+The key for your address '${address}' has been published
+and can now be retrieved from the Web Key Directory.
+
+For more information on this system see:
+
+ https://gnupg.org/faq/wkd.html
+
+Best regards
+
+ GnuPG Key Publisher
+
+
+${sigdelim}
+For information on GnuPG see: https://gnupg.org
+
+.
diff --git a/doc/wks.texi b/doc/wks.texi
index bfdd069f2..a47bdfa92 100644
--- a/doc/wks.texi
+++ b/doc/wks.texi
@@ -358,6 +358,15 @@ use option @option{-q}.
The command @option{--revoke-key} is not yet functional.
+This tool needs to insert strings into the mails which can be
+configured using a plain text file. The installed default files for
+English (@file{wks-utils.txt}) and German (@file{wks-utils.de.txt})
+can be copied to the system configuration directory and changed to
+local needs. Environment variables in these texts are expanded, the
+variable ``sigdelim'' is replaced by two dashes and a blank, the
+variable ``address'' is replaced by the mail address of the key to be
+published.
+
@mansect options
@noindent
diff --git a/tools/gpg-mail-tube.c b/tools/gpg-mail-tube.c
index 7c3c6d0e3..c672651de 100644
--- a/tools/gpg-mail-tube.c
+++ b/tools/gpg-mail-tube.c
@@ -371,7 +371,7 @@ main (int argc, char **argv)
}
-/* Return true if TSRING has only ascii chacrterst or is NULL. */
+/* Return true if STRING has only ascii characters or is NULL. */
static int
only_ascii (const char *string)
{
@@ -571,7 +571,8 @@ mail_tube_encrypt (estream_t fpin, strlist_t recipients)
ct_is_text? "encrypted-file-attached"
: "encrypted-mail-attached",
(GET_TEMPLATE_SUBST_ENVVARS
- | GET_TEMPLATE_CRLF));
+ | GET_TEMPLATE_CRLF),
+ NULL);
if (templ && !only_ascii (templ))
{
charset = "utf-8";
diff --git a/tools/gpg-wks-client.c b/tools/gpg-wks-client.c
index ef11a4e3e..2d037faef 100644
--- a/tools/gpg-wks-client.c
+++ b/tools/gpg-wks-client.c
@@ -155,6 +155,8 @@ const char *fake_submission_addr;
static char **blacklist_array;
static size_t blacklist_array_len;
+/* The current locale in the short form (e.g. "de" instead of "de_DE") */
+static char *short_locale;
static void wrong_args (const char *t1, const char *t2) GPGRT_ATTR_NORETURN;
static void add_blacklist (const char *fname);
@@ -168,7 +170,9 @@ static gpg_error_t encrypt_response (estream_t *r_output, estream_t input,
const char *fingerprint);
static gpg_error_t read_confirmation_request (estream_t msg);
static gpg_error_t command_receive_cb (void *opaque,
- const char *mediatype, estream_t fp,
+ const char *mediatype,
+ const char *language,
+ estream_t fp,
unsigned int flags);
static gpg_error_t command_mirror (char *domain[]);
@@ -374,6 +378,20 @@ main (int argc, char **argv)
!opt.no_autostart);
+ /* Get the short form of the current locale. */
+ {
+ const char *locname = gnupg_messages_locale_name ();
+ char *p;
+
+ if (locname && *locname && strcmp (locname, "C"))
+ {
+ short_locale = xstrdup (locname);
+ if ((p = strpbrk (short_locale, "_.@/")))
+ *p = 0;
+ gpgrt_annotate_leaked_object (short_locale);
+ }
+ }
+
/* Check that the top directory exists. */
if (cmd == aInstallKey || cmd == aRemoveKey || cmd == aMirror)
{
@@ -1338,16 +1356,32 @@ command_create (const char *fingerprint, const char *userid)
}
}
+ /* Hack to support posteo but let them disable this by setting the
+ * new policy-version flag. */
+ if (policy->protocol_version < 3
+ && !ascii_strcasecmp (domain, "posteo.de"))
+ {
+ log_info ("Warning: Using draft-1 method for domain '%s'\n", domain);
+ no_encrypt = 1;
+ posteo_hack = 1;
+ }
+
/* Now put the armor around the key. */
{
estream_t newkey;
+ char *prefix;
+
+ prefix = xstrconcat
+ ("Content-Type: application/pgp-keys\n",
+ short_locale && *short_locale? "Content-Language: " : "",
+ short_locale && *short_locale? short_locale : "",
+ short_locale && *short_locale? "\n" : "",
+ "\n", NULL);
es_rewind (key);
- err = wks_armor_key (&newkey, key,
- no_encrypt? NULL
- /* */ : ("Content-Type: application/pgp-keys\n"
- "\n"));
+ err = wks_armor_key (&newkey, key, no_encrypt? NULL : prefix);
+ xfree (prefix);
if (err)
{
log_error ("error armoring key: %s\n", gpg_strerror (err));
@@ -1357,16 +1391,6 @@ command_create (const char *fingerprint, const char *userid)
key = newkey;
}
- /* Hack to support posteo but let them disable this by setting the
- * new policy-version flag. */
- if (policy->protocol_version < 3
- && !ascii_strcasecmp (domain, "posteo.de"))
- {
- log_info ("Warning: Using draft-1 method for domain '%s'\n", domain);
- no_encrypt = 1;
- posteo_hack = 1;
- }
-
/* Encrypt the key part. */
if (!no_encrypt)
{
@@ -1415,8 +1439,10 @@ command_create (const char *fingerprint, const char *userid)
goto leave;
}
- err = mime_maker_add_header (mime, "Content-type",
+ err = mime_maker_add_header (mime, "Content-Type",
"application/pgp-keys");
+ if (!err && short_locale && *short_locale)
+ err = mime_maker_add_header (mime, "Content-Language", short_locale);
if (err)
goto leave;
@@ -1596,10 +1622,11 @@ send_confirmation_response (const char *sender, const char *address,
* only our client will see it. */
if (encrypt)
{
- es_fputs ("Content-Type: application/vnd.gnupg.wks\n"
- "Content-Transfer-Encoding: 8bit\n"
- "\n",
- body);
+ es_fprintf (body,
+ "Content-Type: application/vnd.gnupg.wks\n"
+ "Content-Transfer-Encoding: 8bit\n"
+ "Content-Language: %s\n"
+ "\n", (short_locale && *short_locale)? short_locale : "en");
}
es_fprintf (body, ("type: confirmation-response\n"
@@ -1858,12 +1885,13 @@ read_confirmation_request (estream_t msg)
/* Called from the MIME receiver to process the plain text data in MSG. */
static gpg_error_t
-command_receive_cb (void *opaque, const char *mediatype,
+command_receive_cb (void *opaque, const char *mediatype, const char *language,
estream_t msg, unsigned int flags)
{
gpg_error_t err;
(void)opaque;
+ (void)language;
(void)flags;
if (!strcmp (mediatype, "application/vnd.gnupg.wks"))
diff --git a/tools/gpg-wks-server.c b/tools/gpg-wks-server.c
index 31de67618..0e216cec6 100644
--- a/tools/gpg-wks-server.c
+++ b/tools/gpg-wks-server.c
@@ -142,6 +142,7 @@ struct server_ctx_s
{
char *fpr;
uidinfo_list_t mboxes; /* List with addr-specs taken from the UIDs. */
+ char *language; /* Requested language. */
unsigned int draft_version_2:1; /* Client supports the draft 2. */
};
typedef struct server_ctx_s *server_ctx_t;
@@ -157,7 +158,9 @@ static int opt_with_file;
static gpg_error_t get_domain_list (strlist_t *r_list);
static gpg_error_t command_receive_cb (void *opaque,
- const char *mediatype, estream_t fp,
+ const char *mediatype,
+ const char *language,
+ estream_t fp,
unsigned int flags);
static gpg_error_t command_list_domains (void);
static gpg_error_t command_revoke_key (const char *mailaddr);
@@ -432,6 +435,54 @@ main (int argc, char **argv)
}
+/* Return true if STRING has only ascii characters or is NULL. */
+static int
+only_ascii (const char *string)
+{
+ if (string)
+ for ( ; *string; string++)
+ if ((*string & 0x80))
+ return 0;
+ return 1;
+}
+
+
+struct my_subst_vars_s
+{
+ const char *address;
+};
+
+
+/* Helper for my_subst_vars. */
+static const char *
+my_subst_vars_cb (void *cookie, const char *name)
+{
+ struct my_subst_vars_s *parm = cookie;
+ const char *s;
+
+ if (name && !strcmp (name, "sigdelim"))
+ s = "-- ";
+ else if (name && !strcmp (name, "address"))
+ s = parm->address;
+ else /* Assume envvar. */
+ s = getenv (name);
+ return s? s : "";
+}
+
+
+/* Substitute all envvars in TEMPL and the var $address my the value
+ * of MBOX. Return a a new malloced string or NULL. */
+static char *
+my_subst_vars (server_ctx_t ctx, const char *templ, const char *mbox)
+{
+ struct my_subst_vars_s parm;
+
+ (void)ctx;
+ parm.address = mbox;
+ return substitute_vars (templ, my_subst_vars_cb, &parm);
+}
+
+
/* Take the key in KEYFILE and write it to OUTFILE in binary encoding.
* If ADDRSPEC is given only matching user IDs are included in the
* output. */
@@ -991,6 +1042,9 @@ send_confirmation_request (server_ctx_t ctx,
char *from_buffer = NULL;
const char *from;
strlist_t sl;
+ char *templ = NULL;
+ char *p;
+ const char *cttype, *ctencode;
from = from_buffer = get_submission_address (mbox);
if (!from)
@@ -1123,25 +1177,48 @@ send_confirmation_request (server_ctx_t ctx,
goto leave;
partid = mime_maker_get_partid (mime);
- err = mime_maker_add_header (mime, "Content-Type", "text/plain");
+ templ = gnupg_get_template ("wks-utils", "server.confirm.body",
+ 0, ctx->language);
+ if (templ)
+ {
+ p = my_subst_vars (ctx, templ, mbox);
+ xfree (templ);
+ templ = p;
+ }
+
+ if (templ && !only_ascii (templ))
+ {
+ cttype = "text/plain; charset=utf-8";
+ ctencode = "quoted-printable";
+ p = mime_maker_qp_encode (templ);
+ if (!p)
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("QP encoding failed: %s\n", gpg_strerror (err));
+ goto leave;
+ }
+ xfree (templ);
+ templ = p;
+ }
+ else
+ {
+ cttype = "text/plain";
+ ctencode = NULL;
+ }
+
+ err = mime_maker_add_header (mime, "Content-Type", cttype);
+ if (err)
+ goto leave;
+ if (ctencode)
+ err = mime_maker_add_header (mime,
+ "Content-Transfer-Encoding", ctencode);
if (err)
goto leave;
- err = mime_maker_add_body
- (mime,
+ err = mime_maker_add_body (mime, templ? templ :
"This message has been send to confirm your request\n"
"to publish your key. If you did not request a key\n"
- "publication, simply ignore this message.\n"
- "\n"
- "Most mail software can handle this kind of message\n"
- "automatically and thus you would not have seen this\n"
- "message. It seems that your client does not fully\n"
- "support this service. The web page\n"
- "\n"
- " https://gnupg.org/faq/wkd.html\n"
- "\n"
- "explains how you can process this message anyway in\n"
- "a few manual steps.\n");
+ "publication, simply ignore this message.\n");
if (err)
goto leave;
@@ -1180,6 +1257,7 @@ send_confirmation_request (server_ctx_t ctx,
err = wks_send_mime (mime);
leave:
+ xfree (templ);
mime_maker_release (mime);
es_fclose (signature);
es_fclose (signeddata);
@@ -1285,7 +1363,8 @@ process_new_key (server_ctx_t ctx, estream_t key)
/* Send a message to tell the user at MBOX that their key has been
* published. FNAME the name of the file with the key. */
static gpg_error_t
-send_congratulation_message (const char *mbox, const char *keyfile)
+send_congratulation_message (server_ctx_t ctx,
+ const char *mbox, const char *keyfile)
{
gpg_error_t err;
estream_t body = NULL;
@@ -1294,6 +1373,9 @@ send_congratulation_message (const char *mbox, const char *keyfile)
char *from_buffer = NULL;
const char *from;
strlist_t sl;
+ char *templ = NULL;
+ char *p;
+ const char *charset, *ctencode;
from = from_buffer = get_submission_address (mbox);
if (!from)
@@ -1315,28 +1397,47 @@ send_congratulation_message (const char *mbox, const char *keyfile)
log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
goto leave;
}
- /* It is fine to use 8 bit encoding because that is encrypted and
- * only our client will see it. */
- es_fputs ("Content-Type: text/plain; charset=utf-8\n"
- "Content-Transfer-Encoding: 8bit\n"
- "\n",
- body);
-
- es_fprintf (body,
- "Hello!\n\n"
- "The key for your address '%s' has been published\n"
- "and can now be retrieved from the Web Key Directory.\n"
- "\n"
- "For more information on this system see:\n"
- "\n"
- " https://gnupg.org/faq/wkd.html\n"
- "\n"
- "Best regards\n"
- "\n"
- " GnuPG Key Publisher\n\n\n"
- "-- \n"
- "For information on GnuPG see: %s\n",
- mbox, "https://gnupg.org");
+
+ templ = gnupg_get_template ("wks-utils", "server.publish.congrats",
+ 0, ctx->language);
+ if (templ)
+ {
+ p = my_subst_vars (ctx, templ, mbox);
+ xfree (templ);
+ templ = p;
+ }
+
+ if (templ && !only_ascii (templ))
+ {
+ charset = "utf-8";
+ ctencode = "Content-Transfer-Encoding: quoted-printable\n";
+ p = mime_maker_qp_encode (templ);
+ if (!p)
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("QP encoding failed: %s\n", gpg_strerror (err));
+ goto leave;
+ }
+ xfree (templ);
+ templ = p;
+ }
+ else
+ {
+ charset = "us-ascii";
+ ctencode = "";
+ }
+
+
+ es_fprintf (body, "Content-Type: text/plain; charset=%s\n%s\n",
+ charset, ctencode);
+
+ if (templ)
+ es_fputs (templ, body);
+ else
+ es_fprintf (body, "Hello!\n\n"
+ "The key for your address '%s' has been published\n"
+ "and can now be retrieved from the Web Key Directory.\n",
+ mbox);
es_rewind (body);
err = encrypt_stream (&bodyenc, body, keyfile);
@@ -1399,6 +1500,7 @@ send_congratulation_message (const char *mbox, const char *keyfile)
err = wks_send_mime (mime);
leave:
+ xfree (templ);
mime_maker_release (mime);
es_fclose (bodyenc);
es_fclose (body);
@@ -1516,7 +1618,7 @@ check_and_publish (server_ctx_t ctx, const char *address, const char *nonce)
fnewname, gpg_strerror (gpg_err_code_from_syserror()));
log_info ("key %s published for '%s'\n", ctx->fpr, address);
- send_congratulation_message (address, fnewname);
+ send_congratulation_message (ctx, address, fnewname);
/* Try to publish as DANE record if the DANE directory exists. */
xfree (fname);
@@ -1645,7 +1747,7 @@ process_confirmation_response (server_ctx_t ctx, estream_t msg)
/* Called from the MIME receiver to process the plain text data in MSG . */
static gpg_error_t
-command_receive_cb (void *opaque, const char *mediatype,
+command_receive_cb (void *opaque, const char *mediatype, const char *language,
estream_t msg, unsigned int flags)
{
gpg_error_t err;
@@ -1656,6 +1758,8 @@ command_receive_cb (void *opaque, const char *mediatype,
memset (&ctx, 0, sizeof ctx);
if ((flags & WKS_RECEIVE_DRAFT2))
ctx.draft_version_2 = 1;
+ if (language)
+ ctx.language = xtrystrdup (language);
if (!strcmp (mediatype, "application/pgp-keys"))
err = process_new_key (&ctx, msg);
diff --git a/tools/gpg-wks.h b/tools/gpg-wks.h
index 0601d48fe..3049aaa9d 100644
--- a/tools/gpg-wks.h
+++ b/tools/gpg-wks.h
@@ -127,6 +127,7 @@ gpg_error_t wks_cmd_print_wkd_url (const char *userid);
gpg_error_t wks_receive (estream_t fp,
gpg_error_t (*result_cb)(void *opaque,
const char *mediatype,
+ const char *language,
estream_t data,
unsigned int flags),
void *cb_data);
diff --git a/tools/wks-receive.c b/tools/wks-receive.c
index ecd8cafe3..6bc1318cc 100644
--- a/tools/wks-receive.c
+++ b/tools/wks-receive.c
@@ -50,6 +50,7 @@ struct receive_ctx_s
estream_t signature;
estream_t key_data;
estream_t wkd_data;
+ char *ct_language; /* The short locale of the conent or NULL. */
unsigned int collect_key_data:1;
unsigned int collect_wkd_data:1;
unsigned int draft_version_2:1; /* This is a draft version 2 request. */
@@ -288,6 +289,34 @@ t2body (void *cookie, int level)
}
+/* Get the Content-Language from the curent MIME header and store it
+ * in CTX. */
+static void
+get_language (receive_ctx_t ctx)
+{
+ rfc822parse_t msg;
+ char *value, *p;
+ size_t valueoff;
+
+ msg = mime_parser_rfc822parser (ctx->parser);
+ if (msg)
+ {
+ value = rfc822parse_get_field (msg, "Content-Language",
+ -1, &valueoff);
+ if (value)
+ {
+ xfree (ctx->ct_language);
+ ctx->ct_language = xtrystrdup (value+valueoff);
+ /* Take only the first short language. */
+ if (ctx->ct_language
+ && (p = strpbrk (ctx->ct_language, " \t,_.@/")))
+ *p = 0;
+ rfc822_free (value);
+ }
+ }
+}
+
+
static gpg_error_t
new_part (void *cookie, const char *mediatype, const char *mediasubtype)
{
@@ -308,6 +337,7 @@ new_part (void *cookie, const char *mediatype, const char *mediasubtype)
}
else
{
+ get_language (ctx);
ctx->key_data = es_fopenmem (0, "w+b");
if (!ctx->key_data)
{
@@ -333,6 +363,7 @@ new_part (void *cookie, const char *mediatype, const char *mediasubtype)
}
else
{
+ get_language (ctx);
ctx->wkd_data = es_fopenmem (0, "w+b");
if (!ctx->wkd_data)
{
@@ -410,6 +441,7 @@ gpg_error_t
wks_receive (estream_t fp,
gpg_error_t (*result_cb)(void *opaque,
const char *mediatype,
+ const char *language,
estream_t data,
unsigned int flags),
void *cb_data)
@@ -482,6 +514,8 @@ wks_receive (estream_t fp,
if (DBG_MIME)
{
es_rewind (ctx->key_data);
+ if (ctx->ct_language)
+ log_debug ("Language: '%s'\n", ctx->ct_language);
log_debug ("Key: '");
log_printf ("\n");
while ((c = es_getc (ctx->key_data)) != EOF)
@@ -492,7 +526,7 @@ wks_receive (estream_t fp,
{
es_rewind (ctx->key_data);
err = result_cb (cb_data, "application/pgp-keys",
- ctx->key_data, flags);
+ ctx->ct_language, ctx->key_data, flags);
if (err)
goto leave;
}
@@ -512,7 +546,7 @@ wks_receive (estream_t fp,
{
es_rewind (ctx->wkd_data);
err = result_cb (cb_data, "application/vnd.gnupg.wks",
- ctx->wkd_data, flags);
+ ctx->ct_language, ctx->wkd_data, flags);
if (err)
goto leave;
}
@@ -529,6 +563,7 @@ wks_receive (estream_t fp,
es_fclose (ctx->signature);
es_fclose (ctx->key_data);
es_fclose (ctx->wkd_data);
+ xfree (ctx->ct_language);
xfree (ctx);
return err;
}