From a646b55ae09513a5295484c711d0a720d31d8217 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Mon, 9 May 2022 00:00:00 -0500 Subject: [PATCH] postfix-3.8-20220509 --- postfix/HISTORY | 7 +++++ postfix/WISHLIST | 4 --- postfix/html/pgsql_table.5.html | 9 ++++++ postfix/man/man5/pgsql_table.5 | 10 ++++++ postfix/proto/pgsql_table | 10 ++++++ postfix/proto/stop | 2 ++ postfix/src/global/dict_pgsql.c | 51 ++++++++++++------------------- postfix/src/global/mail_version.h | 2 +- 8 files changed, 58 insertions(+), 37 deletions(-) diff --git a/postfix/HISTORY b/postfix/HISTORY index 3da460d7d..14ed05def 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -26495,3 +26495,10 @@ Apologies for any names omitted. Documentation: added POSTLOG_SERVICE and POSTLOG_HOSTNAME to the import_environment description. File: proto/postconf.proto. + +20220509 + + Cleanup: the pgsql: client encoding is now configurable + with the "encoding" configuration file attribute. The default + is "UTF8". Previously the encoding was hard-coded as "LATIN1". + Files: global/dict_pgsql,c, proto/pgsql_table. diff --git a/postfix/WISHLIST b/postfix/WISHLIST index d0c3589c4..79b1da7d6 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -30,10 +30,6 @@ Wish list: expectations when different reply patterns have different weights. We need a compatibility_level feature to correct this. - In the pgsql: client, make the client encoding configurable - with a sensible default (UTF8). This code is implemented - and needs to be tested. - FILTER_README needs some text on multi-instance implementations, and existing multi-instance references need to be updated. diff --git a/postfix/html/pgsql_table.5.html b/postfix/html/pgsql_table.5.html index 89a200bf1..1acc49417 100644 --- a/postfix/html/pgsql_table.5.html +++ b/postfix/html/pgsql_table.5.html @@ -65,6 +65,15 @@ PGSQL_TABLE(5) PGSQL_TABLE(5) dbname The database name on the servers. Example: dbname = customer_database + encoding + The encoding used by the database client. The default setting + is: + encoding = UTF8 + Historically, the database client was hard coded to use LATIN1 + in an attempt to disable multibyte character support. + + This feature is available in Postfix 3.8 and later. + query The SQL query template used to search the database, where %s is a substitute for the address Postfix is trying to resolve, e.g. query = SELECT replacement FROM aliases WHERE mailbox = '%s' diff --git a/postfix/man/man5/pgsql_table.5 b/postfix/man/man5/pgsql_table.5 index 150115245..a0ccddc3e 100644 --- a/postfix/man/man5/pgsql_table.5 +++ b/postfix/man/man5/pgsql_table.5 @@ -83,6 +83,16 @@ The database name on the servers. Example: .nf dbname = customer_database .fi +.IP "\fBencoding\fR" +The encoding used by the database client. The default setting +is: +.nf + encoding = UTF8 +.fi +Historically, the database client was hard coded to use +LATIN1 in an attempt to disable multibyte character support. + +This feature is available in Postfix 3.8 and later. .IP "\fBquery\fR" The SQL query template used to search the database, where \fB%s\fR is a substitute for the address Postfix is trying to resolve, diff --git a/postfix/proto/pgsql_table b/postfix/proto/pgsql_table index f5d96833c..05cd2c6cf 100644 --- a/postfix/proto/pgsql_table +++ b/postfix/proto/pgsql_table @@ -73,6 +73,16 @@ # .nf # dbname = customer_database # .fi +# .IP "\fBencoding\fR" +# The encoding used by the database client. The default setting +# is: +# .nf +# encoding = UTF8 +# .fi +# Historically, the database client was hard coded to use +# LATIN1 in an attempt to disable multibyte character support. +# +# This feature is available in Postfix 3.8 and later. # .IP "\fBquery\fR" # The SQL query template used to search the database, where \fB%s\fR # is a substitute for the address Postfix is trying to resolve, diff --git a/postfix/proto/stop b/postfix/proto/stop index 0189e961a..d8ae00828 100644 --- a/postfix/proto/stop +++ b/postfix/proto/stop @@ -1563,3 +1563,5 @@ postlogd proxied raf fnvz +hc +mkmap diff --git a/postfix/src/global/dict_pgsql.c b/postfix/src/global/dict_pgsql.c index 8eac25606..f44a29ad0 100644 --- a/postfix/src/global/dict_pgsql.c +++ b/postfix/src/global/dict_pgsql.c @@ -54,6 +54,9 @@ /* Password for the above. /* .IP dbname /* Name of the database. +/* .IP "encoding (default: UTF8) +/* Client encoding, Postfix 3.8 and later. Previously this was +/* hard-coded as LATIN1. /* .IP query /* Query template. If not defined a default query template is constructed /* from the legacy \fIselect_function\fR or failing that the \fItable\fR, @@ -210,6 +213,7 @@ typedef struct { char *username; char *password; char *dbname; + char *encoding; char *table; ARGV *hosts; PLPGSQL *pldb; @@ -223,11 +227,11 @@ typedef struct { /* internal function declarations */ static PLPGSQL *plpgsql_init(ARGV *); static PGSQL_RES *plpgsql_query(DICT_PGSQL *, const char *, VSTRING *, char *, - char *, char *); + char *, char *, char *); static void plpgsql_dealloc(PLPGSQL *); static void plpgsql_close_host(HOST *); static void plpgsql_down_host(HOST *); -static void plpgsql_connect_single(HOST *, char *, char *, char *); +static void plpgsql_connect_single(HOST *, char *, char *, char *, char *); static const char *dict_pgsql_lookup(DICT *, const char *); DICT *dict_pgsql_open(const char *, int, int); static void dict_pgsql_close(DICT *); @@ -348,7 +352,6 @@ static const char *dict_pgsql_lookup(DICT *dict, const char *name) /* * Don't frustrate future attempts to make Postfix UTF-8 transparent. */ -#ifdef SNAPSHOT if ((dict->flags & DICT_FLAG_UTF8_ACTIVE) == 0 && !valid_utf8_string(name, strlen(name))) { if (msg_verbose) @@ -356,7 +359,6 @@ static const char *dict_pgsql_lookup(DICT *dict, const char *name) myname, dict_pgsql->parser->name, name); return (0); } -#endif /* * Optionally fold the key. @@ -396,6 +398,7 @@ static const char *dict_pgsql_lookup(DICT *dict, const char *name) /* do the query - set dict->error & cleanup if there's an error */ if ((query_res = plpgsql_query(dict_pgsql, name, query, dict_pgsql->dbname, + dict_pgsql->encoding, dict_pgsql->username, dict_pgsql->password)) == 0) { dict->error = DICT_ERR_RETRY; @@ -473,7 +476,7 @@ static HOST *dict_pgsql_find_host(PLPGSQL *PLDB, unsigned stat, unsigned type) /* dict_pgsql_get_active - get an active connection */ -static HOST *dict_pgsql_get_active(PLPGSQL *PLDB, char *dbname, +static HOST *dict_pgsql_get_active(PLPGSQL *PLDB, char *dbname, char *encoding, char *username, char *password) { const char *myname = "dict_pgsql_get_active"; @@ -505,7 +508,7 @@ static HOST *dict_pgsql_get_active(PLPGSQL *PLDB, char *dbname, if (msg_verbose) msg_info("%s: attempting to connect to host %s", myname, host->hostname); - plpgsql_connect_single(host, dbname, username, password); + plpgsql_connect_single(host, dbname, encoding, username, password); if (host->stat == STATACTIVE) return host; } @@ -535,6 +538,7 @@ static PGSQL_RES *plpgsql_query(DICT_PGSQL *dict_pgsql, const char *name, VSTRING *query, char *dbname, + char *encoding, char *username, char *password) { @@ -543,7 +547,7 @@ static PGSQL_RES *plpgsql_query(DICT_PGSQL *dict_pgsql, PGSQL_RES *res = 0; ExecStatusType status; - while ((host = dict_pgsql_get_active(PLDB, dbname, username, password)) != NULL) { + while ((host = dict_pgsql_get_active(PLDB, dbname, encoding, username, password)) != NULL) { /* * The active host is used to escape strings in the context of the @@ -638,7 +642,7 @@ static PGSQL_RES *plpgsql_query(DICT_PGSQL *dict_pgsql, * used to reconnect to a single database when one is down or none is * connected yet. Log all errors and set the stat field of host accordingly */ -static void plpgsql_connect_single(HOST *host, char *dbname, char *username, char *password) +static void plpgsql_connect_single(HOST *host, char *dbname, char *encoding, char *username, char *password) { if (host->type == TYPECONNSTRING) { host->db = PQconnectdb(host->name); @@ -652,34 +656,15 @@ static void plpgsql_connect_single(HOST *host, char *dbname, char *username, cha plpgsql_down_host(host); return; } - if (msg_verbose) - msg_info("dict_pgsql: successful connection to host %s", - host->hostname); - - /* - * The only legitimate encodings for Internet mail are ASCII and UTF-8. - */ -#ifdef SNAPSHOT - if (PQsetClientEncoding(host->db, "UTF8") != 0) { - msg_warn("dict_pgsql: cannot set the encoding to UTF8, skipping %s", - host->hostname); + if (PQsetClientEncoding(host->db, encoding) != 0) { + msg_warn("dict_pgsql: cannot set the encoding to %s, skipping %s", + encoding, host->hostname); plpgsql_down_host(host); return; } -#else - - /* - * XXX Postfix does not send multi-byte characters. The following piece - * of code is an explicit statement of this fact, and the database server - * should not accept multi-byte information after this point. - */ - if (PQsetClientEncoding(host->db, "LATIN1") != 0) { - msg_warn("dict_pgsql: cannot set the encoding to LATIN1, skipping %s", + if (msg_verbose) + msg_info("dict_pgsql: successful connection to host %s", host->hostname); - plpgsql_down_host(host); - return; - } -#endif /* Success. */ host->stat = STATACTIVE; } @@ -721,6 +706,7 @@ static void pgsql_parse_config(DICT_PGSQL *dict_pgsql, const char *pgsqlcf) dict_pgsql->username = cfg_get_str(p, "user", "", 0, 0); dict_pgsql->password = cfg_get_str(p, "password", "", 0, 0); dict_pgsql->dbname = cfg_get_str(p, "dbname", "", 1, 0); + dict_pgsql->encoding = cfg_get_str(p, "encoding", "UTF8", 1, 0); dict_pgsql->result_format = cfg_get_str(p, "result_format", "%s", 1, 0); /* @@ -892,6 +878,7 @@ static void dict_pgsql_close(DICT *dict) myfree(dict_pgsql->username); myfree(dict_pgsql->password); myfree(dict_pgsql->dbname); + myfree(dict_pgsql->encoding); myfree(dict_pgsql->query); myfree(dict_pgsql->result_format); if (dict_pgsql->hosts) diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 567892093..5c902b790 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20220507" +#define MAIL_RELEASE_DATE "20220509" #define MAIL_VERSION_NUMBER "3.8" #ifdef SNAPSHOT -- 2.47.3