]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.3-20050922
authorWietse Venema <wietse@porcupine.org>
Thu, 22 Sep 2005 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:31:28 +0000 (06:31 +0000)
postfix/HISTORY
postfix/src/bounce/bounce_notify_util.c
postfix/src/global/db_common.c
postfix/src/global/db_common.h
postfix/src/global/dict_ldap.c
postfix/src/global/dict_mysql.c
postfix/src/global/dict_pgsql.c
postfix/src/global/mail_version.h
postfix/src/tls/tls_verify.c

index 8c9da4bb88509f85d7384100842f75181ad665f1..d88540f36294a9a47622103ece0b1014d9607050 100644 (file)
@@ -11124,6 +11124,17 @@ Apologies for any names omitted.
        Files: tls_client.c, tls_server.c, tls_session.c, tls_misc.c,
        tls_verify.c.
        
+20050922
+
+       Bugfix: the *SQL clients did not uniformly choose the
+       database host from the available pool of servers due to an
+       off-by-one error, so that the "last" available server was
+       not selected. Leandro Santi. Files: dict_mysql.c, dict_pgsql.c.
+
+       Update: common code factored out into db_common.c, and
+       adoption of Liviu Daia's connection aware MySQL quoting.
+       Files: dict_ldap.c, dict_mysql.c, dict_pgsql.c, db_common.c.
+
 Open problems:
 
        Look for systems with XPG basename() declared in <libgen.h>,
index ae42a3e1869a63c6389a40dbcb0d5fa222e11295..1b5d70bf3eb7428298a7c430eb6947a861f4ac34 100644 (file)
@@ -505,7 +505,7 @@ int     bounce_boilerplate(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
                          var_max_queue_time / 86400.0);
     } else if (bounce_info->report_type == BOUNCE_REPORT_SUCCESS) {
        post_mail_fputs(bounce,
-                       "Your message was sucessfully delivered to the destination(s) listed");
+                       "Your message was successfully delivered to the destination(s) listed");
        post_mail_fputs(bounce,
                        "below. In the case of delivery to mailbox you will receive no further");
        post_mail_fputs(bounce,
index 1522711d92ffd14a56e23962d1208579d0166842..b5ab21e6b5ee660b0776842e86ad5daba164289f 100644 (file)
 #define        DB_COMMON_KEY_USER      (1 << 1)        /* Need lookup key localpart */
 #define        DB_COMMON_VALUE_DOMAIN  (1 << 2)        /* Need result domain */
 #define        DB_COMMON_VALUE_USER    (1 << 3)        /* Need result localpart */
+#define        DB_COMMON_KEY_PARTIAL   (1 << 4)        /* Key uses input substrings */
 
 typedef struct {
     DICT    *dict;
+    STRING_LIST *domain;
     int      flags;
     int      nparts;
 } DB_COMMON_CTX;
@@ -172,6 +174,7 @@ int db_common_parse(DICT *dict, void **ctxPtr, const char *format, int query)
     if (ctx == 0) {
        ctx = (DB_COMMON_CTX *)(*ctxPtr = mymalloc(sizeof *ctx));
        ctx->dict = dict;
+       ctx->domain = 0;
        ctx->flags = 0;
        ctx->nparts = 0;
     }
@@ -182,20 +185,22 @@ int db_common_parse(DICT *dict, void **ctxPtr, const char *format, int query)
            case '%':
                break;
            case 'u':
-               ctx->flags |=
-                   query ? DB_COMMON_KEY_USER : DB_COMMON_VALUE_USER;
+               ctx->flags |= 
+                   query ? DB_COMMON_KEY_USER | DB_COMMON_KEY_PARTIAL
+                         : DB_COMMON_VALUE_USER;
                dynamic = 1;
                break;
            case 'd':
-               ctx->flags |=
-                   query ? DB_COMMON_KEY_DOMAIN : DB_COMMON_VALUE_DOMAIN;
+               ctx->flags |= 
+                   query ? DB_COMMON_KEY_DOMAIN | DB_COMMON_KEY_PARTIAL
+                         : DB_COMMON_VALUE_DOMAIN;
                dynamic = 1;
                break;
            case 's': case 'S':
                dynamic = 1;
                break;
            case 'U':
-               ctx->flags |= DB_COMMON_KEY_USER;
+               ctx->flags |= DB_COMMON_KEY_PARTIAL | DB_COMMON_KEY_USER;
                dynamic = 1;
                break;
            case '1': case '2': case '3': case '4': case '5':
@@ -204,7 +209,7 @@ int db_common_parse(DICT *dict, void **ctxPtr, const char *format, int query)
                    ctx->nparts = *cp - '0';
                /* FALLTHROUGH */
            case 'D':
-               ctx->flags |= DB_COMMON_KEY_DOMAIN;
+               ctx->flags |= DB_COMMON_KEY_PARTIAL | DB_COMMON_KEY_DOMAIN;
                dynamic = 1;
                break;
            default:
@@ -214,10 +219,49 @@ int db_common_parse(DICT *dict, void **ctxPtr, const char *format, int query)
     return dynamic;
 }
 
+/* db_common_parse_domain - parse domain matchlist*/
+
+void db_common_parse_domain(CFG_PARSER *parser, void *ctxPtr)
+{
+    DB_COMMON_CTX *ctx = (DB_COMMON_CTX *)ctxPtr;
+    char   *domainlist;
+    char   *myname = "db_common_parse_domain";
+
+    domainlist = cfg_get_str(parser, "domain", "", 0, 0);
+    if (*domainlist) {
+       ctx->domain = string_list_init(MATCH_FLAG_NONE, domainlist);
+       if (ctx->domain == 0)
+           /*
+            * The "domain" optimization skips input keys that may in fact
+            * have unwanted matches in the database, so failure to create
+            * the match list is fatal.
+            */
+           msg_fatal("%s: %s: domain match list creation using '%s' failed",
+                     myname, parser->name, domainlist);
+    }
+    myfree(domainlist);
+}
+
+/* db_common_dict_partial - Does query use partial lookup keys? */
+
+int db_common_dict_partial(void *ctxPtr)
+{
+#if 0  /* Breaks recipient_delimiter */
+    DB_COMMON_CTX *ctx = (DB_COMMON_CTX *)ctxPtr;
+
+    return (ctx->domain || ctx->flags & DB_COMMON_KEY_PARTIAL);
+#endif
+    return (0);
+}
+
 /* db_common_free_ctx - free parse context */
 
 void db_common_free_ctx(void *ctxPtr)
 {
+    DB_COMMON_CTX *ctx = (DB_COMMON_CTX *)ctxPtr;
+
+    if (ctx->domain)
+       string_list_free(ctx->domain);
     myfree((char *)ctxPtr);
 }
 
@@ -401,16 +445,17 @@ int db_common_expand(void *ctxArg, const char *format, const char *value,
 
 /* db_common_check_domain - check domain list */
 
-int db_common_check_domain(STRING_LIST *domain_list, const char *addr)
+int db_common_check_domain(void *ctxPtr, const char *addr)
 {
+    DB_COMMON_CTX *ctx = (DB_COMMON_CTX *)ctxPtr;
     char   *domain;
 
-    if (domain_list) {
+    if (ctx->domain) {
        if ((domain = strrchr(addr, '@')) != NULL)
            ++domain;
        if (domain == NULL || domain == addr + 1)
            return (0);
-       if (match_list_match(domain_list, domain) == 0)
+       if (match_list_match(ctx->domain, domain) == 0)
            return (0);
     }
     return (1);
index 73c466136118dde0fef3a21a6ffe9bb780d97821..ce7adc1e134a9d3086c7ffcd7e860bc0d1566ece 100644 (file)
 typedef void (*db_quote_callback_t)(DICT *, const char *, VSTRING *);
 
 extern int db_common_parse(DICT *, void **, const char *, int);
-extern void db_common_free_ctx(void *);
+extern void db_common_parse_domain(CFG_PARSER *, void *);
+extern int db_common_dict_partial(void *);
 extern int db_common_expand(void *, const char *, const char *,
                            const char *, VSTRING *, db_quote_callback_t);
-extern int db_common_check_domain(STRING_LIST *, const char *);
+extern int db_common_check_domain(void *, const char *);
+extern void db_common_free_ctx(void *);
 extern void db_common_sql_build_query(VSTRING *query, CFG_PARSER *parser);
 
 /* LICENSE
index 6e8a4f752105073399070ac1c003f9c649685aa2..24daf2972dd111d0fc2a0575e58f18d1eb1f16c8 100644 (file)
@@ -216,7 +216,6 @@ typedef struct {
     CFG_PARSER *parser;                        /* common parameter parser */
     char   *query;                     /* db_common_expand() query */
     char   *result_format;             /* db_common_expand() result_format */
-    STRING_LIST *domain;               /* restrict queries to these domains */
     void   *ctx;                       /* db_common_parse() context */
     int     dynamic_base;              /* Search base has substitutions? */
     int     expansion_limit;
@@ -908,7 +907,7 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
      * addresses in domains on the list. This can significantly reduce the
      * load on the LDAP server.
      */
-    if (db_common_check_domain(dict_ldap->domain, name) == 0) {
+    if (db_common_check_domain(dict_ldap->ctx, name) == 0) {
        if (msg_verbose)
            msg_info("%s: Skipping lookup of '%s'", myname, name);
        return (0);
@@ -1126,8 +1125,6 @@ static void dict_ldap_close(DICT *dict)
     cfg_parser_free(dict_ldap->parser);
     myfree(dict_ldap->server_host);
     myfree(dict_ldap->search_base);
-    if (dict_ldap->domain)
-       string_list_free(dict_ldap->domain);
     myfree(dict_ldap->query);
     if (dict_ldap->result_format)
         myfree(dict_ldap->result_format);
@@ -1157,7 +1154,6 @@ DICT   *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
     char   *s;
     char   *h;
     char   *server_host;
-    char   *domainlist;
     char   *scope;
     char   *attr;
     int     tmp;
@@ -1169,7 +1165,7 @@ DICT   *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
                                         sizeof(*dict_ldap));
     dict_ldap->dict.lookup = dict_ldap_lookup;
     dict_ldap->dict.close = dict_ldap_close;
-    dict_ldap->dict.flags = dict_flags | DICT_FLAG_FIXED;
+    dict_ldap->dict.flags = dict_flags;
 
     dict_ldap->ld = NULL;
     dict_ldap->parser = cfg_parser_alloc(ldapsource);
@@ -1285,22 +1281,6 @@ DICT   *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
     dict_ldap->search_base = cfg_get_str(dict_ldap->parser, "search_base",
                                         "", 0, 0);
 
-    domainlist = cfg_get_str(dict_ldap->parser, "domain", "", 0, 0);
-    if (*domainlist) {
-       dict_ldap->domain = string_list_init(MATCH_FLAG_NONE, domainlist);
-       if (dict_ldap->domain == NULL)
-           /*
-            * The "domain" optimization skips input keys that may in fact
-            * have unwanted matches in the database, so failure to create
-            * the match list is fatal.
-            */
-           msg_fatal("%s: %s: domain match list creation using '%s' failed",
-                     myname, ldapsource, domainlist);
-    } else {
-       dict_ldap->domain = NULL;
-    }
-    myfree(domainlist);
-
     /*
      * get configured value of "timeout"; default to 10 seconds
      * 
@@ -1337,6 +1317,16 @@ DICT   *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
                 myname, ldapsource, dict_ldap->query);
     }
     (void) db_common_parse(0, &dict_ldap->ctx, dict_ldap->result_format, 0);
+    db_common_parse_domain(dict_ldap->parser, dict_ldap->ctx);
+
+    /*
+     * Maps that use substring keys should only be used with the full
+     * input key.
+     */
+    if (db_common_dict_partial(dict_ldap->ctx))
+       dict_ldap->dict.flags |= DICT_FLAG_PATTERN;
+    else
+       dict_ldap->dict.flags |= DICT_FLAG_FIXED;
 
     attr = cfg_get_str(dict_ldap->parser, "result_attribute",
                       "maildrop", 0, 0);
index e16d22933e46148c0de92400c7d86049341535d5..62dbf38b32363a83ed44b01375403cecf0ee4b36 100644 (file)
@@ -216,7 +216,6 @@ typedef struct {
     CFG_PARSER *parser;
     char   *query;
     char   *result_format;
-    STRING_LIST *domain;   
     void   *ctx;
     int     expansion_limit;
     char   *username;
@@ -224,6 +223,9 @@ typedef struct {
     char   *dbname;
     ARGV   *hosts;
     PLMYSQL *pldb;
+#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
+    HOST   *active_host;
+#endif
 } DICT_MYSQL;
 
 #define STATACTIVE                     (1<<0)
@@ -239,7 +241,8 @@ typedef struct {
 
 /* internal function declarations */
 static PLMYSQL *plmysql_init(ARGV *);
-static MYSQL_RES *plmysql_query(PLMYSQL *, const char *, char *, char *, char *);
+static MYSQL_RES *plmysql_query(DICT_MYSQL *, const char *, VSTRING *, char *,
+                               char *, char *);
 static void plmysql_dealloc(PLMYSQL *);
 static void plmysql_close_host(HOST *);
 static void plmysql_down_host(HOST *);
@@ -266,16 +269,14 @@ static void dict_mysql_quote(DICT *dict, const char *name, VSTRING *result)
        msg_panic("dict_mysql_quote: integer overflow in 2*%d+1", len);
     VSTRING_SPACE(result, buflen);
 
-    /*
-     * XXX Too expensive to find out which connection is still open at
-     * this point. Grrr!
-     */
-#if 0 && defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
-    mysql_real_escape_string(dict_mysql->pldb->db_hosts[i].db,
-                            vstring_end(result), name, len);
-#else
-    mysql_escape_string(vstring_end(result), name, len);
+#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
+    if (dict_mysql->active_host)
+       mysql_real_escape_string(dict_mysql->active_host->db,
+                                vstring_end(result), name, len);
+    else
 #endif
+       mysql_escape_string(vstring_end(result), name, len);
+
     VSTRING_SKIP(result);
 }
 
@@ -295,15 +296,16 @@ static const char *dict_mysql_lookup(DICT *dict, const char *name)
     int     numrows;
     int     expansion;
     const char *r;
+    db_quote_callback_t quote_func = dict_mysql_quote;
 
     dict_errno = 0;
     
     /*
      * If there is a domain list for this map, then only search for
      * addresses in domains on the list. This can significantly reduce
-     * the load on the server. Do not try "@domain" keys.
+     * the load on the server.
      */
-    if (db_common_check_domain(dict_mysql->domain, name) == 0) {
+    if (db_common_check_domain(dict_mysql->ctx, name) == 0) {
         if (msg_verbose)
            msg_info("%s: Skipping lookup of '%s'", myname, name);
         return (0);
@@ -320,13 +322,21 @@ static const char *dict_mysql_lookup(DICT *dict, const char *name)
 
     /*
      * Suppress the lookup if the query expansion is empty
+     *
+     * This initial expansion is outside the context of any
+     * specific host connection, we just want to check the
+     * key pre-requisites, so when quoting happens separately
+     * for each connection, we don't bother with quoting...
      */
+#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
+    quote_func = 0;
+#endif
     if (!db_common_expand(dict_mysql->ctx, dict_mysql->query,
-                         name, 0, query, dict_mysql_quote))
+                         name, 0, query, quote_func))
         return (0);
     
     /* do the query - set dict_errno & cleanup if there's an error */
-    if ((query_res = plmysql_query(pldb, vstring_str(query),
+    if ((query_res = plmysql_query(dict_mysql, name, query,
                                   dict_mysql->dbname,
                                   dict_mysql->username,
                                   dict_mysql->password)) == 0) {
@@ -393,16 +403,12 @@ static HOST *dict_mysql_find_host(PLMYSQL *PLDB, unsigned stat, unsigned type)
     }
 
     if (count) {
-       /*
-        * Calling myrand() can deplete the random pool.
-        * Don't rely on the optimizer to weed out the call
-        * when count == 1.
-        */
-       idx = (count > 1) ? 1 + (count - 1) * (double) myrand() / RAND_MAX : 1;
+       idx = (count > 1) ?
+           1 + count * (double) myrand() / (1.0 + RAND_MAX) : 1;
 
        for (i = 0; i < PLDB->len_hosts; i++) {
            if (dict_mysql_check_stat(PLDB->db_hosts[i], stat, type, t) &&
-                                     --idx == 0)
+               --idx == 0)
                return PLDB->db_hosts[i];
        }
     }
@@ -466,17 +472,33 @@ static void dict_mysql_event(int unused_event, char *context)
  *                     close unnecessary active connections
  */
 
-static MYSQL_RES *plmysql_query(PLMYSQL *PLDB,
-                                       const char *query,
+static MYSQL_RES *plmysql_query(DICT_MYSQL *dict_mysql,
+                                       const char *name,
+                                       VSTRING *query,
                                        char *dbname,
                                        char *username,
                                        char *password)
 {
+    PLMYSQL *PLDB = dict_mysql->pldb;
     HOST   *host;
     MYSQL_RES *res = 0;
 
     while ((host = dict_mysql_get_active(PLDB, dbname, username, password)) != NULL) {
-       if (!(mysql_query(host->db, query))) {
+
+#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
+       /*
+        * The active host is used to escape strings in the
+        * context of the active connection's character encoding.
+        */
+       dict_mysql->active_host = host;
+       VSTRING_RESET(query);
+       VSTRING_TERMINATE(query);
+       db_common_expand(dict_mysql->ctx, dict_mysql->query,
+                        name, 0, query, dict_mysql_quote);
+       dict_mysql->active_host = 0;
+#endif
+
+       if (!(mysql_query(host->db, vstring_str(query)))) {
            if ((res = mysql_store_result(host->db)) == 0) {
                msg_warn("mysql query failed: %s", mysql_error(host->db));
                plmysql_down_host(host);
@@ -553,7 +575,6 @@ static void mysql_parse_config(DICT_MYSQL *dict_mysql, const char *mysqlcf)
     VSTRING *buf;
     int     i;
     char   *hosts;
-    char   *domain;
     
     p = dict_mysql->parser = cfg_parser_alloc(mysqlcf);
     dict_mysql->username = cfg_get_str(p, "user", "", 0, 0);
@@ -584,21 +605,16 @@ static void mysql_parse_config(DICT_MYSQL *dict_mysql, const char *mysqlcf)
     (void) db_common_parse(&dict_mysql->dict, &dict_mysql->ctx,
                           dict_mysql->query, 1);
     (void) db_common_parse(0, &dict_mysql->ctx, dict_mysql->result_format, 0);
+    db_common_parse_domain(p, dict_mysql->ctx);
 
-    domain = cfg_get_str(p, "domain", "", 0, 0);
-    if (*domain) {
-        if (!(dict_mysql->domain = string_list_init(MATCH_FLAG_NONE, domain)))
-           /*
-            * The "domain" optimization skips input keys that may in fact
-            * have unwanted matches in the database, so failure to create
-            * the match list is fatal.
-            */
-           msg_fatal("%s: %s: domain match list creation using '%s' failed",
-                     myname, mysqlcf, domain);
-    }
+    /*
+     * Maps that use substring keys should only be used with the full
+     * input key.
+     */
+    if (db_common_dict_partial(dict_mysql->ctx))
+       dict_mysql->dict.flags |= DICT_FLAG_PATTERN;
     else
-        dict_mysql->domain = 0;
-    myfree(domain);
+       dict_mysql->dict.flags |= DICT_FLAG_FIXED;
 
     hosts = cfg_get_str(p, "hosts", "", 0, 0);
 
@@ -630,8 +646,11 @@ DICT   *dict_mysql_open(const char *name, int open_flags, int dict_flags)
                                           sizeof(DICT_MYSQL));
     dict_mysql->dict.lookup = dict_mysql_lookup;
     dict_mysql->dict.close = dict_mysql_close;
-    dict_mysql->dict.flags = dict_flags | DICT_FLAG_FIXED;
+    dict_mysql->dict.flags = dict_flags;
     mysql_parse_config(dict_mysql, name);
+#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
+    dict_mysql->active_host = 0;
+#endif
     dict_mysql->pldb = plmysql_init(dict_mysql->hosts);
     if (dict_mysql->pldb == NULL)
        msg_fatal("couldn't intialize pldb!\n");
@@ -717,8 +736,6 @@ static void dict_mysql_close(DICT *dict)
     myfree(dict_mysql->dbname);
     myfree(dict_mysql->query);
     myfree(dict_mysql->result_format);
-    if (dict_mysql->domain)
-        string_list_free(dict_mysql->domain);
     if (dict_mysql->hosts)
        argv_free(dict_mysql->hosts);
     if (dict_mysql->ctx)
index 025cb6b376af97317fe64406c539eb8f6e1ce6cc..976168eba7079373346aae1b1bc8b60523348bdc 100644 (file)
@@ -208,7 +208,6 @@ typedef struct {
     CFG_PARSER *parser;
     char   *query;
     char   *result_format;
-    STRING_LIST *domain;
     void   *ctx;
     int     expansion_limit;
     char   *username;
@@ -306,9 +305,9 @@ static const char *dict_pgsql_lookup(DICT *dict, const char *name)
     /*
      * If there is a domain list for this map, then only search for
      * addresses in domains on the list. This can significantly reduce
-     * the load on the server. Do not try "@domain" keys.
+     * the load on the server.
      */
-    if (db_common_check_domain(dict_pgsql->domain, name) == 0) {
+    if (db_common_check_domain(dict_pgsql->ctx, name) == 0) {
         if (msg_verbose)
            msg_info("%s: Skipping lookup of '%s'", myname, name);
         return (0);
@@ -388,16 +387,12 @@ static HOST *dict_pgsql_find_host(PLPGSQL *PLDB, unsigned stat, unsigned type)
     }
 
     if (count) {
-       /*
-        * Calling myrand() can deplete the random pool.
-        * Don't rely on the optimizer to weed out the call
-        * when count == 1.
-        */
-       idx = (count > 1) ? 1 + (count - 1) * (double) myrand() / RAND_MAX : 1;
+       idx = (count > 1) ?
+           1 + count * (double) myrand() / (1.0 + RAND_MAX) : 1;
 
        for (i = 0; i < PLDB->len_hosts; i++) {
            if (dict_pgsql_check_stat(PLDB->db_hosts[i], stat, type, t) &&
-                                     --idx == 0)
+               --idx == 0)
                return PLDB->db_hosts[i];
        }
     }
@@ -545,7 +540,6 @@ static void pgsql_parse_config(DICT_PGSQL *dict_pgsql, const char *pgsqlcf)
     char   *hosts;
     VSTRING *query;
     char   *select_function;
-    char   *domain;
 
     p = dict_pgsql->parser = cfg_parser_alloc(pgsqlcf);
     dict_pgsql->username = cfg_get_str(p, "user", "", 0, 0);
@@ -581,21 +575,16 @@ static void pgsql_parse_config(DICT_PGSQL *dict_pgsql, const char *pgsqlcf)
     (void) db_common_parse(&dict_pgsql->dict, &dict_pgsql->ctx,
                           dict_pgsql->query, 1);
     (void) db_common_parse(0, &dict_pgsql->ctx, dict_pgsql->result_format, 0);
+    db_common_parse_domain(p, dict_pgsql->ctx);
 
-    domain = cfg_get_str(p, "domain", "", 0, 0);
-    if (*domain) {
-        if (!(dict_pgsql->domain = string_list_init(MATCH_FLAG_NONE, domain)))
-           /*
-            * The "domain" optimization skips input keys that may in fact
-            * have unwanted matches in the database, so failure to create
-            * the match list is fatal.
-            */
-           msg_fatal("%s: %s: domain match list creation using '%s' failed",
-                     myname, pgsqlcf, domain);
-    }
+    /*
+     * Maps that use substring keys should only be used with the full
+     * input key.
+     */
+    if (db_common_dict_partial(dict_pgsql->ctx))
+       dict_pgsql->dict.flags |= DICT_FLAG_PATTERN;
     else
-        dict_pgsql->domain = 0;
-    myfree(domain);
+       dict_pgsql->dict.flags |= DICT_FLAG_FIXED;
 
     hosts = cfg_get_str(p, "hosts", "", 0, 0);
 
@@ -624,9 +613,9 @@ DICT   *dict_pgsql_open(const char *name, int open_flags, int dict_flags)
                                           sizeof(DICT_PGSQL));
     dict_pgsql->dict.lookup = dict_pgsql_lookup;
     dict_pgsql->dict.close = dict_pgsql_close;
+    dict_pgsql->dict.flags = dict_flags;
     pgsql_parse_config(dict_pgsql, name);
     dict_pgsql->pldb = plpgsql_init(dict_pgsql->hosts);
-    dict_pgsql->dict.flags = dict_flags | DICT_FLAG_FIXED;
     if (dict_pgsql->pldb == NULL)
        msg_fatal("couldn't intialize pldb!\n");
     return &dict_pgsql->dict;
@@ -698,8 +687,6 @@ static void dict_pgsql_close(DICT *dict)
     myfree(dict_pgsql->dbname);
     myfree(dict_pgsql->query);
     myfree(dict_pgsql->result_format);
-    if (dict_pgsql->domain)
-        string_list_free(dict_pgsql->domain);
     if (dict_pgsql->hosts)
        argv_free(dict_pgsql->hosts);
     if (dict_pgsql->ctx)
index 72a3f5a0121e44a9c0374b70805ae5d0034587b6..55236fe8477422ca732fd010d1fa3825179e71d5 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      "20050920"
+#define MAIL_RELEASE_DATE      "20050922"
 #define MAIL_VERSION_NUMBER    "2.3"
 
 #ifdef SNAPSHOT
index 2580ff21ca232d9859b58c24ed53121f972ce7e1..4471da58e68e874579cb4956d81c3561cc070848 100644 (file)
@@ -242,7 +242,7 @@ char   *tls_peer_CN(X509 *peercert)
     return (cn);
 }
 
-/* tls_text_name - extract issuer common name from certificate */
+/* tls_issuer_CN - extract issuer common name from certificate */
 
 char   *tls_issuer_CN(X509 *peer)
 {