]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.12-20150112-nonprod
authorWietse Venema <wietse@porcupine.org>
Mon, 12 Jan 2015 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Tue, 13 Jan 2015 02:15:57 +0000 (21:15 -0500)
18 files changed:
postfix/HISTORY
postfix/README_FILES/SMTPUTF8_README
postfix/WISHLIST
postfix/html/SMTPUTF8_README.html
postfix/proto/SMTPUTF8_README.html
postfix/src/global/Makefile.in
postfix/src/global/addr_match_list.c
postfix/src/global/domain_list.c
postfix/src/global/mail_version.h
postfix/src/global/namadr_list.c
postfix/src/global/string_list.c
postfix/src/util/casefold.c
postfix/src/util/dict.h
postfix/src/util/dict_utf8.c
postfix/src/util/match_list.c
postfix/src/util/match_list.h
postfix/src/util/match_ops.c
postfix/src/util/stringops.h

index 9871221caac736cc42ebb7a39ad40eb3a1e57bfa..6126f4ba91a03a6c847af5c4a822132f584a0b7e 100644 (file)
@@ -21326,7 +21326,7 @@ Apologies for any names omitted.
        mysql_table(5), pgsql_table(5) and sqlite_table(5),
        virtual_alias_domains, virtual_mailbox_domains.
 
-20140111
+20150111
 
        Cleanup: simplified the interposition layer that adds UTF-8
        support to Postfix lookup tables. Files: util/dict_utf8.c.
@@ -21345,3 +21345,14 @@ Apologies for any names omitted.
        smtpd_tls_session_cache_database, transport_maps,
        virtual_alias_maps, virtual_gid_maps, virtual_mailbox_maps,
        virtual_uid_maps.
+
+20150112
+
+       Support for UTF-8 casefolding in match_lists. Instead of
+       using strcasecmp(), casefold all string constant patterns
+       during initialization, and casefold a search string at the
+       beginning of the search, and use strcmp() for comparison.
+       Files: util/casefold.c util/dict.h, util/dict_utf8.c,
+       util/match_list.c, util/match_list.h, util/match_ops.c,
+       util/stringops.h, global/addr_match_list.c, global/domain_list.c,
+       global/namadr_list.c, global/string_list.c.
index 8dc081a1f0decea6d2cadd631dc3550d641d69cf..f03b3a0d8b958cd43e2c8dbd6ab4b9f47fc63a55 100644 (file)
@@ -218,13 +218,6 @@ name or email address in mydestination, relay_domains, access maps,
 transport_maps, etc., and when maintaining tables with the postmap(1) and
 postalias(1) commands.
 
-N\bNo\bo c\bca\bas\bse\be-\b-i\bin\bns\bse\ben\bns\bsi\bit\bti\biv\bve\be m\bma\bat\btc\bch\bhi\bin\bng\bg o\bof\bf n\bno\bon\bn-\b-A\bAS\bSC\bCI\bII\bI s\bst\btr\bri\bin\bng\bg p\bpa\bat\btt\bte\ber\brn\bns\bs i\bin\bn m\bma\bat\btc\bch\bhl\bli\bis\bst\bts\bs.\b.
-
-Postfix currently does not yet implement case-insensitive string comparison for
-non-ASCII string patterns in list features such as mydestination,
-relay_domains, etc. For now, use "inline:{string}" instead of "string". This
-limitation will be removed before the stable release.
-
 C\bCo\bom\bmp\bpa\bat\bti\bib\bbi\bil\bli\bit\bty\by w\bwi\bit\bth\bh p\bpr\bre\be-\b-S\bSM\bMT\bTP\bPU\bUT\bTF\bF8\b8 e\ben\bnv\bvi\bir\bro\bon\bnm\bme\ben\bnt\bts\bs
 
 M\bMa\bai\bil\bli\bin\bng\bg l\bli\bis\bst\bts\bs w\bwi\bit\bth\bh U\bUT\bTF\bF-\b-8\b8 a\ban\bnd\bd n\bno\bon\bn-\b-U\bUT\bTF\bF-\b-8\b8 s\bsu\bub\bbs\bsc\bcr\bri\bib\bbe\ber\brs\bs
index a8f3b85b9cf7a4ec1510f64957899ba0bdc88ea6..26f80b1d10217c6f9acc7855f55c7afae5b5d12d 100644 (file)
@@ -8,6 +8,8 @@ Wish list:
 
        Things to do after the stable release:
 
+       Add context argument for better match_list diagnostics.
+
        Expose UTF8 flag in server_acl API. Some applications such
        as postscreen don't need UTF8 support.
 
index 33c101be7e92d6fb1462059e74e79075a679a86c..546b9c4a85321b731f8494430c84b64db77d3c05 100644 (file)
@@ -298,14 +298,6 @@ domain name or email address in <a href="postconf.5.html#mydestination">mydestin
 maps, <a href="postconf.5.html#transport_maps">transport_maps</a>, etc., and when maintaining tables with the
 <a href="postmap.1.html">postmap(1)</a> and <a href="postalias.1.html">postalias(1)</a> commands. </p>
 
-<h3> No case-insensitive matching of non-ASCII string patterns in matchlists. </h3>
-
-<p> Postfix currently does not yet implement case-insensitive string
-comparison for non-ASCII string patterns in list features such as
-<a href="postconf.5.html#mydestination">mydestination</a>, <a href="postconf.5.html#relay_domains">relay_domains</a>, etc. For now, use "<a href="DATABASE_README.html#types">inline</a>:{string}"
-instead of "string". This limitation will be removed before the
-stable release.  </p>
-
 <h2> <a name="compatibility">Compatibility with pre-SMTPUTF8
 environments</a> </h2>
 
index 9461ea6b5ad93f56730a7b1e5ccc667187849ef0..40f594b4e7b6d3c4a7db518bba5789733ff63be2 100644 (file)
@@ -298,14 +298,6 @@ domain name or email address in mydestination, relay_domains, access
 maps, transport_maps, etc., and when maintaining tables with the
 postmap(1) and postalias(1) commands. </p>
 
-<h3> No case-insensitive matching of non-ASCII string patterns in matchlists. </h3>
-
-<p> Postfix currently does not yet implement case-insensitive string
-comparison for non-ASCII string patterns in list features such as
-mydestination, relay_domains, etc. For now, use "inline:{string}"
-instead of "string". This limitation will be removed before the
-stable release.  </p>
-
 <h2> <a name="compatibility">Compatibility with pre-SMTPUTF8
 environments</a> </h2>
 
index e994fb9f54fdc949e27ba9a414cf1cf4dd57664c..ab6b8a1ec25d47158332bcf7d948a5ca0c75f113 100644 (file)
@@ -688,8 +688,11 @@ abounce.o: mail_proto.h
 abounce.o: msg_stats.h
 abounce.o: recipient_list.h
 addr_match_list.o: ../../include/argv.h
+addr_match_list.o: ../../include/check_arg.h
 addr_match_list.o: ../../include/match_list.h
 addr_match_list.o: ../../include/sys_defs.h
+addr_match_list.o: ../../include/vbuf.h
+addr_match_list.o: ../../include/vstring.h
 addr_match_list.o: addr_match_list.c
 addr_match_list.o: addr_match_list.h
 anvil_clnt.o: ../../include/attr.h
@@ -878,9 +881,12 @@ db_common.o: db_common.c
 db_common.o: db_common.h
 db_common.o: string_list.h
 debug_peer.o: ../../include/argv.h
+debug_peer.o: ../../include/check_arg.h
 debug_peer.o: ../../include/match_list.h
 debug_peer.o: ../../include/msg.h
 debug_peer.o: ../../include/sys_defs.h
+debug_peer.o: ../../include/vbuf.h
+debug_peer.o: ../../include/vstring.h
 debug_peer.o: debug_peer.c
 debug_peer.o: debug_peer.h
 debug_peer.o: mail_params.h
@@ -1107,8 +1113,11 @@ dict_sqlite.o: dict_sqlite.c
 dict_sqlite.o: dict_sqlite.h
 dict_sqlite.o: string_list.h
 domain_list.o: ../../include/argv.h
+domain_list.o: ../../include/check_arg.h
 domain_list.o: ../../include/match_list.h
 domain_list.o: ../../include/sys_defs.h
+domain_list.o: ../../include/vbuf.h
+domain_list.o: ../../include/vstring.h
 domain_list.o: domain_list.c
 domain_list.o: domain_list.h
 dot_lockfile.o: ../../include/check_arg.h
@@ -1842,8 +1851,11 @@ mark_corrupt.o: mark_corrupt.h
 mark_corrupt.o: msg_stats.h
 mark_corrupt.o: recipient_list.h
 match_parent_style.o: ../../include/argv.h
+match_parent_style.o: ../../include/check_arg.h
 match_parent_style.o: ../../include/match_list.h
 match_parent_style.o: ../../include/sys_defs.h
+match_parent_style.o: ../../include/vbuf.h
+match_parent_style.o: ../../include/vstring.h
 match_parent_style.o: mail_params.h
 match_parent_style.o: match_parent_style.c
 match_parent_style.o: match_parent_style.h
@@ -2090,8 +2102,11 @@ mypwd.o: ../../include/sys_defs.h
 mypwd.o: mypwd.c
 mypwd.o: mypwd.h
 namadr_list.o: ../../include/argv.h
+namadr_list.o: ../../include/check_arg.h
 namadr_list.o: ../../include/match_list.h
 namadr_list.o: ../../include/sys_defs.h
+namadr_list.o: ../../include/vbuf.h
+namadr_list.o: ../../include/vstring.h
 namadr_list.o: namadr_list.c
 namadr_list.o: namadr_list.h
 off_cvt.o: ../../include/check_arg.h
@@ -2491,8 +2506,11 @@ stream2rec.o: rec_type.h
 stream2rec.o: record.h
 stream2rec.o: stream2rec.c
 string_list.o: ../../include/argv.h
+string_list.o: ../../include/check_arg.h
 string_list.o: ../../include/match_list.h
 string_list.o: ../../include/sys_defs.h
+string_list.o: ../../include/vbuf.h
+string_list.o: ../../include/vstring.h
 string_list.o: string_list.c
 string_list.o: string_list.h
 strip_addr.o: ../../include/mymalloc.h
index 946cf4ae3b6ac6a9a835c693240427b743100f75..fdc95d012a8d664492b4cf28635205aaa3ff6e50 100644 (file)
@@ -88,6 +88,7 @@
 #include <vstream.h>
 #include <vstring_vstream.h>
 #include <msg_vstream.h>
+#include <stringops.h>                 /* util_utf8_enable */
 
 static void usage(char *progname)
 {
@@ -113,6 +114,8 @@ int     main(int argc, char **argv)
     }
     if (argc != optind + 2)
        usage(argv[0]);
+    dict_allow_surrogate = 1;
+    util_utf8_enable = 1;
     list = addr_match_list_init(MATCH_FLAG_PARENT | MATCH_FLAG_RETURN, argv[optind]);
     addr = argv[optind + 1];
     if (strcmp(addr, "-") == 0) {
index 8433caaf76ce4a8d409bc3a3eb2eace666cb2ac0..c64f4de38a8d38a0647a691ab8159813e2c92b8f 100644 (file)
@@ -88,6 +88,7 @@
 #include <unistd.h>
 #include <vstream.h>
 #include <msg_vstream.h>
+#include <stringops.h>                 /* util_utf8_enable */
 
 static void usage(char *progname)
 {
@@ -113,6 +114,8 @@ int     main(int argc, char **argv)
     }
     if (argc != optind + 2)
        usage(argv[0]);
+    dict_allow_surrogate = 1;
+    util_utf8_enable = 1;
     list = domain_list_init(MATCH_FLAG_PARENT | MATCH_FLAG_RETURN, argv[optind]);
     host = argv[optind + 1];
     vstream_printf("%s: %s\n", host, domain_list_match(list, host) ?
index 27ad964d2931a9efad39a466d4e9c740f0380944..c97ed8e8747325e4c3134e7d6cec7c9b8f677871 100644 (file)
@@ -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      "20150111"
+#define MAIL_RELEASE_DATE      "20150112"
 #define MAIL_VERSION_NUMBER    "2.12"
 
 #ifdef SNAPSHOT
index fc7f681ed239706f3c7b950faddd049eca589212..eebfa68db8a29f21b5d6c1c3a8f52e5805b827ea 100644 (file)
@@ -95,6 +95,7 @@
 #include <vstream.h>
 #include <msg_vstream.h>
 #include <dict.h>
+#include <stringops.h>                 /* util_utf8_enable */
 
 static void usage(char *progname)
 {
@@ -122,6 +123,7 @@ int     main(int argc, char **argv)
     if (argc != optind + 3)
        usage(argv[0]);
     dict_allow_surrogate = 1;
+    util_utf8_enable = 1;
     list = namadr_list_init(MATCH_FLAG_PARENT | MATCH_FLAG_RETURN, argv[optind]);
     host = argv[optind + 1];
     addr = argv[optind + 2];
index a24e4e179da534db2f5d3dd428a1fa505d6222bb..b5dda32e838f5388a20b068cf286025462739413 100644 (file)
@@ -81,6 +81,7 @@
 #include <vstream.h>
 #include <vstring.h>
 #include <msg_vstream.h>
+#include <stringops.h>                 /* util_utf8_enable */
 
 static void usage(char *progname)
 {
@@ -106,6 +107,8 @@ int     main(int argc, char **argv)
     }
     if (argc != optind + 2)
        usage(argv[0]);
+    dict_allow_surrogate = 1;
+    util_utf8_enable = 1;
     list = string_list_init(MATCH_FLAG_RETURN, argv[optind]);
     string = argv[optind + 1];
     vstream_printf("%s: %s\n", string, string_list_match(list, string) ?
index ed4b493a6578b9f1e9241ddde512793345a40baf..99acf757220f55c926eaf5c31599ef902a07a23a 100644 (file)
@@ -7,6 +7,7 @@
 /*     #include <stringops.h>
 /*
 /*     char    *casefold(
+/*     int     utf8_request,
 /*     VSTRING *src,
 /*     const char *src,
 /*     CONST_CHAR_STAR *err)
@@ -29,6 +30,8 @@
 /*     range), not even when running inside an empty chroot jail.
 /*
 /*     Arguments:
+/* .IP utf8_request
+/*     Perform UTF-8 case folding.
 /* .IP src
 /*     Null-terminated input string.
 /* .IP dest
@@ -69,7 +72,8 @@
 
 /* casefold - casefold an UTF-8 string */
 
-char   *casefold(VSTRING *dest, const char *src, CONST_CHAR_STAR *err)
+char   *casefold(int utf8_req, VSTRING *dest, const char *src,
+                        CONST_CHAR_STAR *err)
 {
 #ifdef NO_EAI
 
@@ -91,7 +95,7 @@ char   *casefold(VSTRING *dest, const char *src, CONST_CHAR_STAR *err)
     /*
      * All-ASCII input.
      */
-    if (allascii(src)) {
+    if (utf8_req == 0 || allascii(src)) {
        vstring_strcpy(dest, src);
        return (lowercase(STR(dest)));
     }
@@ -183,14 +187,14 @@ int     main(int argc, char **argv)
     char   *conv_res;
     const char *fold_err;
     char   *cmd;
-    int     codepoint, first, last;
+    int     codepoint, first, last, utf8_req;
 
     if (setlocale(LC_ALL, "C") == 0)
        msg_fatal("setlocale(LC_ALL, C) failed: %m");
 
     msg_vstream_init(argv[0], VSTREAM_ERR);
 
-    util_utf8_enable = 1;
+    utf8_req = util_utf8_enable = 1;
 
     VSTRING_SPACE(buffer, 256);                        /* chroot pathname */
 
@@ -207,7 +211,7 @@ int     main(int argc, char **argv)
         * Null-terminated string.
         */
        if (strcmp(cmd, "fold") == 0) {
-           if ((conv_res = casefold(dest, bp, &fold_err)) != 0)
+           if ((conv_res = casefold(utf8_req, dest, bp, &fold_err)) != 0)
                msg_info("\"%s\" ->fold \"%s\"", bp, conv_res);
            else
                msg_warn("cannot casefold \"%s\": %s", bp, fold_err);
@@ -229,7 +233,7 @@ int     main(int argc, char **argv)
                        msg_info("U+%X -> %s", codepoint, STR(buffer));
                    if (valid_utf8_string(STR(buffer), LEN(buffer)) == 0)
                        msg_fatal("bad utf-8 encoding for U+%X", codepoint);
-                   if (casefold(dest, STR(buffer), &fold_err) == 0)
+                   if (casefold(utf8_req, dest, STR(buffer), &fold_err) == 0)
                        msg_warn("casefold error for U+%X: %s",
                                 codepoint, fold_err);
                }
index b86bad8ace2000d1db0cc295ea9bfb84293ee61f..0c3c464a60739188f6b1a9857e7eb640c91614d9 100644 (file)
@@ -269,6 +269,7 @@ extern DICT *PRINTFLIKE(5, 6) dict_surrogate(const char *, const char *, int, in
   * This name is reserved for matchlist error handling.
   */
 #define DICT_TYPE_NOFILE       "non-existent"
+#define DICT_TYPE_NOUTF8       "non-UTF-8"
 
  /*
   * Duplicated from vstream(3). This should probably be abstracted out.
index eecabf68a42966c67f31e1531c6b6e415111d452..9a6c7b68d9bc8c8b3895fd5d8ee2224117caa801 100644 (file)
@@ -34,9 +34,7 @@
 /*     configuration error.
 /*
 /*     The dict_utf8_check* functions may be invoked to perform
-/*     UTF-8 validity checks when util_utf8_enable is non-zero and
-/*     DICT_FLAG_UTF8_ENABLE is set. Otherwise both functions
-/*     always report success.
+/*     UTF-8 validity checks when util_utf8_enable is non-zero.
 /*
 /*     dict_utf8_check_fold() optionally folds a string, and checks
 /*     it for UTF-8 validity. The result is the possibly-folded
@@ -130,7 +128,8 @@ char   *dict_utf8_check_fold(DICT *dict, const char *string,
                           DICT_FLAG_FOLD_FIX : DICT_FLAG_FOLD_MUL)) {
        if (dict->fold_buf == 0)
            dict->fold_buf = vstring_alloc(10);
-       return (casefold(dict->fold_buf, string, err));
+       return (casefold(dict->flags & DICT_FLAG_UTF8_ACTIVE,
+                        dict->fold_buf, string, err));
     }
 
     /*
@@ -278,14 +277,20 @@ static int dict_utf8_delete(DICT *dict, const char *key)
 
 DICT   *dict_utf8_activate(DICT *dict)
 {
+    const char myname[] = "dict_utf8_activate";
     DICT_UTF8_BACKUP *backup;
 
     /*
      * Sanity check.
      */
+    if (util_utf8_enable == 0)
+       msg_panic("%s: Unicode support is not available", myname);
+    if ((dict->flags & DICT_FLAG_UTF8_REQUEST) == 0)
+       msg_panic("%s: %s:%s does not request Unicode support",
+                 myname, dict->type, dict->name);
     if (dict->flags & DICT_FLAG_UTF8_ACTIVE)
-       msg_panic("dict_utf8_activate: %s:%s is already encapsulated",
-                 dict->type, dict->name);
+       msg_panic("%s: %s:%s Unicode support is already activated",
+                 myname, dict->type, dict->name);
 
     /*
      * Unlike dict_debug(3) we do not put a proxy dict object in front of the
index 9626562119108e333a585da1a416bca8d70a4a0b..f0a3f90ab8bc67781ea1aac83955c45e35f32a7f 100644 (file)
@@ -20,7 +20,8 @@
 /*     MATCH_LIST *list;
 /* DESCRIPTION
 /*     This module implements a framework for tests for list membership.
-/*     The actual tests are done by user-supplied functions.
+/*     The actual tests are done by user-supplied functions. With
+/*     util_utf8_enable non-zero, string comparison supports UTF-8.
 /*
 /*     Patterns are separated by whitespace and/or commas. A pattern
 /*     is either a string, a file name (in which case the contents
@@ -94,7 +95,8 @@
 
 /* match_list_parse - parse buffer, destroy buffer */
 
-static ARGV *match_list_parse(ARGV *list, char *string, int init_match)
+static ARGV *match_list_parse(MATCH_LIST *match_list, ARGV *pat_list,
+                                     char *string, int init_match)
 {
     const char *myname = "match_list_parse";
     VSTRING *buf = vstring_alloc(10);
@@ -105,15 +107,23 @@ static ARGV *match_list_parse(ARGV *list, char *string, int init_match)
     char   *item;
     char   *map_type_name_flags;
     int     match;
+    const char *utf8_err;
 
+    /*
+     * No DICT_FLAG_FOLD_FIX here, because we casefold the search string at
+     * the beginning of a search. String constant patterns are casefolded
+     * during match_list initialization.
+     */
 #define OPEN_FLAGS     O_RDONLY
-#define DICT_FLAGS     (DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX \
-                       | DICT_FLAG_UTF8_REQUEST)
+#define DICT_FLAGS     (DICT_FLAG_LOCK | DICT_FLAG_UTF8_REQUEST)
 #define STR(x)         vstring_str(x)
 
     /*
      * /filename contents are expanded in-line. To support !/filename we
      * prepend the negation operator to each item from the file.
+     * 
+     * If there is an error, implement graceful degradation by inserting a
+     * pseudo table whose lookups fail with a warning message.
      */
     while ((start = mystrtokq(&bp, delim, CHARS_BRACE)) != 0) {
        if (*start == '#') {
@@ -128,17 +138,17 @@ static ARGV *match_list_parse(ARGV *list, char *string, int init_match)
        if (*item == '/') {                     /* /file/name */
            if ((fp = vstream_fopen(item, O_RDONLY, 0)) == 0) {
                vstring_sprintf(buf, "%s:%s", DICT_TYPE_NOFILE, item);
-               /* XXX Should increment existing map refcount. */
                if (dict_handle(STR(buf)) == 0)
                    dict_register(STR(buf),
                                  dict_surrogate(DICT_TYPE_NOFILE, item,
                                                 OPEN_FLAGS, DICT_FLAGS,
                                                 "open file %s: %m", item));
-               argv_add(list, STR(buf), (char *) 0);
+               argv_add(pat_list, STR(buf), (char *) 0);
            } else {
                while (vstring_fgets(buf, fp))
                    if (vstring_str(buf)[0] != '#')
-                       list = match_list_parse(list, vstring_str(buf), match);
+                       pat_list = match_list_parse(match_list, pat_list,
+                                                   vstring_str(buf), match);
                if (vstream_fclose(fp))
                    msg_fatal("%s: read file %s: %m", myname, item);
            }
@@ -146,18 +156,28 @@ static ARGV *match_list_parse(ARGV *list, char *string, int init_match)
            vstring_sprintf(buf, "%s%s(%o,%s)", match ? "" : "!",
                            item, OPEN_FLAGS, dict_flags_str(DICT_FLAGS));
            map_type_name_flags = STR(buf) + (match == 0);
-           /* XXX Should increment existing map refcount. */
            if (dict_handle(map_type_name_flags) == 0)
                dict_register(map_type_name_flags,
                              dict_open(item, OPEN_FLAGS, DICT_FLAGS));
-           argv_add(list, STR(buf), (char *) 0);
+           argv_add(pat_list, STR(buf), (char *) 0);
        } else {                                /* other pattern */
-           argv_add(list, match ? item :
-                    STR(vstring_sprintf(buf, "!%s", item)), (char *) 0);
+           if (casefold(util_utf8_enable, match_list->fold_buf, match ?
+                        item : STR(vstring_sprintf(buf, "!%s", item)),
+                        &utf8_err) == 0) {
+               vstring_sprintf(match_list->fold_buf, "%s:%s",
+                               DICT_TYPE_NOUTF8, item);
+               if (dict_handle(STR(match_list->fold_buf)) == 0)
+                   dict_register(STR(match_list->fold_buf),
+                                 dict_surrogate(DICT_TYPE_NOFILE, item,
+                                                OPEN_FLAGS, DICT_FLAGS,
+                                                "casefold error: %s",
+                                                utf8_err));
+           }
+           argv_add(pat_list, STR(match_list->fold_buf), (char *) 0);
        }
     }
     vstring_free(buf);
-    return (list);
+    return (pat_list);
 }
 
 /* match_list_init - initialize pattern list */
@@ -184,11 +204,13 @@ MATCH_LIST *match_list_init(int flags, const char *patterns, int match_count,...
        list->match_func[i] = va_arg(ap, MATCH_LIST_FN);
     va_end(ap);
     list->error = 0;
+    list->fold_buf = vstring_alloc(20);
 
 #define DO_MATCH       1
 
     saved_patterns = mystrdup(patterns);
-    list->patterns = match_list_parse(argv_alloc(1), saved_patterns, DO_MATCH);
+    list->patterns = match_list_parse(list, argv_alloc(1), saved_patterns,
+                                     DO_MATCH);
     argv_terminate(list->patterns);
     myfree(saved_patterns);
     return (list);
@@ -204,6 +226,7 @@ int     match_list_match(MATCH_LIST *list,...)
     int     match;
     int     i;
     va_list ap;
+    const char *utf8_err;
 
     /*
      * Iterate over all patterns in the list, stop at the first match.
@@ -217,11 +240,18 @@ int     match_list_match(MATCH_LIST *list,...)
     for (cpp = list->patterns->argv; (pat = *cpp) != 0; cpp++) {
        for (match = 1; *pat == '!'; pat++)
            match = !match;
-       for (i = 0; i < list->match_count; i++)
-           if (list->match_func[i] (list, list->match_args[i], pat))
+       for (i = 0; i < list->match_count; i++) {
+           if (casefold(util_utf8_enable, list->fold_buf,
+                        list->match_args[i], &utf8_err) == 0) {
+               msg_warn("%s: casefold error for \"%s\": %s",
+                        myname, list->match_args[i], utf8_err);
+               continue;
+           }
+           if (list->match_func[i] (list, STR(list->fold_buf), pat))
                return (match);
            else if (list->error != 0)
                return (0);
+       }
     }
     if (msg_verbose)
        for (i = 0; i < list->match_count; i++)
@@ -237,5 +267,6 @@ void    match_list_free(MATCH_LIST *list)
     argv_free(list->patterns);
     myfree((void *) list->match_func);
     myfree((void *) list->match_args);
+    vstring_free(list->fold_buf);
     myfree((void *) list);
 }
index d51b6e831f50916c0af362efeea8731cdd782e93..c08475cd3c670ee6ff413356de2a56c8869cb695 100644 (file)
@@ -15,6 +15,7 @@
   * Utility library.
   */
 #include <argv.h>
+#include <vstring.h>
 
  /*
   * External interface.
@@ -29,6 +30,7 @@ struct MATCH_LIST {
     int     match_count;               /* match function/argument count */
     MATCH_LIST_FN *match_func;         /* match functions */
     const char **match_args;           /* match arguments */
+    VSTRING *fold_buf;                 /* case-folded pattern string */
     int     error;                     /* last operation */
 };
 
index f978d2629b80597828b028e5eabfa576017ac97b..f49b13865a6868ecce5ba35efd429e0eb2d24989 100644 (file)
@@ -132,9 +132,10 @@ int     match_string(MATCH_LIST *list, const char *string, const char *pattern)
     }
 
     /*
-     * Try an exact string match.
+     * Try an exact string match. Note that the string and pattern are
+     * already casefolded.
      */
-    if (strcasecmp(string, pattern) == 0) {
+    if (strcmp(string, pattern) == 0) {
        return (1);
     }
 
@@ -189,23 +190,25 @@ int     match_hostname(MATCH_LIST *list, const char *name, const char *pattern)
     }
 
     /*
-     * Try an exact match with the host name.
+     * Try an exact match with the host name. Note that the name and the
+     * pattern are already casefolded.
      */
-    if (strcasecmp(name, pattern) == 0) {
+    if (strcmp(name, pattern) == 0) {
        return (1);
     }
 
     /*
-     * See if the pattern is a parent domain of the hostname.
+     * See if the pattern is a parent domain of the hostname. Note that the
+     * name and the pattern are already casefolded.
      */
     else {
        if (list->flags & MATCH_FLAG_PARENT) {
            pd = name + strlen(name) - strlen(pattern);
-           if (pd > name && pd[-1] == '.' && strcasecmp(pd, pattern) == 0)
+           if (pd > name && pd[-1] == '.' && strcmp(pd, pattern) == 0)
                return (1);
        } else if (pattern[0] == '.') {
            pd = name + strlen(name) - strlen(pattern);
-           if (pd > name && strcasecmp(pd, pattern) == 0)
+           if (pd > name && strcmp(pd, pattern) == 0)
                return (1);
        }
     }
@@ -247,15 +250,16 @@ int     match_hostaddr(MATCH_LIST *list, const char *addr, const char *pattern)
     }
 
     /*
-     * Try an exact match with the host address.
+     * Try an exact match with the host address. Note that the address and
+     * pattern are already casefolded.
      */
     if (pattern[0] != '[') {
-       if (strcasecmp(addr, pattern) == 0)
+       if (strcmp(addr, pattern) == 0)
            return (1);
     } else {
        size_t  addr_len = strlen(addr);
 
-       if (strncasecmp(addr, pattern + 1, addr_len) == 0
+       if (strncmp(addr, pattern + 1, addr_len) == 0
            && strcmp(pattern + 1 + addr_len, "]") == 0)
            return (1);
     }
@@ -271,7 +275,7 @@ int     match_hostaddr(MATCH_LIST *list, const char *addr, const char *pattern)
      * - Don't bother unless the pattern is either an IPv6 address or net/mask.
      * 
      * We can safely skip IPv4 address patterns because their form is
-     * unambiguous and they did not match in the strcasecmp() calls above.
+     * unambiguous and they did not match in the strcmp() calls above.
      * 
      * XXX We MUST skip (parent) domain names, which may appear in NAMADR_LIST
      * input, to avoid triggering false cidr_match_parse() errors.
index cac9eca55fe8ed5a9a13c46a9162bea1c645d59f..52938ca307951136bda35bd9ed64160919443a62 100644 (file)
@@ -23,7 +23,7 @@ extern int util_utf8_enable;
 extern char *printable(char *, int);
 extern char *neuter(char *, const char *, int);
 extern char *lowercase(char *);
-extern char *casefold(VSTRING *, const char *, CONST_CHAR_STAR *);
+extern char *casefold(int, VSTRING *, const char *, CONST_CHAR_STAR *);
 extern char *uppercase(char *);
 extern char *skipblanks(const char *);
 extern char *trimblanks(char *, ssize_t);