mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-22 18:07:41 +00:00
postfix-2.8-20100618
This commit is contained in:
parent
fef3bc167b
commit
2cee07704f
@ -15846,8 +15846,12 @@ Apologies for any names omitted.
|
||||
Feature: read-only sqlite support based on code by Axel
|
||||
Steiner and documentation by Jesus Garcia Crespo. Files:
|
||||
conf/postfix-files, mantools/postlink, proto/DATABASE_README.html,
|
||||
proto/Makefile.in, proto/INSTALL.html, proto/SASL_README.html,
|
||||
proto/mysql_table, proto/pgsql_table, proto/sqlite_table,
|
||||
proto/SQLITE_README.html, global/Makefile.in, global/mail_dict.c,
|
||||
global/dict_sqlite.c, global/dict_sqlite.h, postconf/postconf.c,
|
||||
postfix/postfix.c.
|
||||
proto/Makefile.in, proto/INSTALL.html, proto/mysql_table,
|
||||
proto/pgsql_table, proto/sqlite_table, proto/SQLITE_README.html,
|
||||
global/Makefile.in, global/mail_dict.c, global/dict_sqlite.c,
|
||||
global/dict_sqlite.h, postconf/postconf.c, postfix/postfix.c.
|
||||
|
||||
20100618
|
||||
|
||||
Cleanup: SQLite read-only driver and documentation. Files:
|
||||
global/dict_sqlite.c, proto/mysql_table, proto/SQLITE_README.html.
|
||||
|
@ -54,7 +54,7 @@ map type in <a href="postconf.5.html">main.cf</a> like this: </p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
<a href="postconf.5.html#alias_maps">alias_maps</a> = sqlite:/etc/postfix/sqlite-aliases.cf
|
||||
<a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="mysql_table.5.html">sqlite</a>:/etc/postfix/sqlite-aliases.cf
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
|
@ -10,9 +10,9 @@ SQLITE_TABLE(5) SQLITE_TABLE(5)
|
||||
sqlite_table - Postfix SQLite configuration
|
||||
|
||||
<b>SYNOPSIS</b>
|
||||
<b>postmap -q "</b><i>string</i><b>" sqlite:/etc/postfix/filename</b>
|
||||
<b>postmap -q "</b><i>string</i><b>" <a href="mysql_table.5.html">sqlite</a>:/etc/postfix/filename</b>
|
||||
|
||||
<b>postmap -q - sqlite:/etc/postfix/</b><i>filename</i> <<i>inputfile</i>
|
||||
<b>postmap -q - <a href="mysql_table.5.html">sqlite</a>:/etc/postfix/</b><i>filename</i> <<i>inputfile</i>
|
||||
|
||||
<b>DESCRIPTION</b>
|
||||
The Postfix mail system uses optional tables for address
|
||||
@ -20,9 +20,9 @@ SQLITE_TABLE(5) SQLITE_TABLE(5)
|
||||
or <b>db</b> format.
|
||||
|
||||
Alternatively, lookup tables can be specified as SQLite
|
||||
databases. In order to use SQLite lookups, define a
|
||||
databases. In order to use SQLite lookups, define an
|
||||
SQLite source as a lookup table in <a href="postconf.5.html">main.cf</a>, for example:
|
||||
<a href="postconf.5.html#alias_maps">alias_maps</a> = sqlite:/etc/sqlite-aliases.cf
|
||||
<a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="mysql_table.5.html">sqlite</a>:/etc/sqlite-aliases.cf
|
||||
|
||||
The file /etc/postfix/sqlite-aliases.cf has the same for-
|
||||
mat as the Postfix <a href="postconf.5.html">main.cf</a> file, and can specify the
|
||||
@ -35,7 +35,7 @@ SQLITE_TABLE(5) SQLITE_TABLE(5)
|
||||
with a slash or a dot. The SQLite parameters will then be
|
||||
accessible as the name you've given the source in its def-
|
||||
inition, an underscore, and the name of the parameter.
|
||||
For example, if the map is specified as "sqlite:<i>sqlite-</i>
|
||||
For example, if the map is specified as "<a href="mysql_table.5.html">sqlite</a>:<i>sqlite-</i>
|
||||
<i>name</i>", the parameter "query" below would be defined in
|
||||
<a href="postconf.5.html">main.cf</a> as "<i>sqlitename</i>_query".
|
||||
|
||||
@ -269,7 +269,7 @@ SQLITE_TABLE(5) SQLITE_TABLE(5)
|
||||
|
||||
<b>README FILES</b>
|
||||
<a href="DATABASE_README.html">DATABASE_README</a>, Postfix lookup table overview
|
||||
<a href="SQLITE_README.html">SQLITE_README</a>, Postfix SQLITE driver
|
||||
<a href="SQLITE_README.html">SQLITE_README</a>, Postfix SQLITE howto
|
||||
|
||||
<b>LICENSE</b>
|
||||
The Secure Mailer license must be distributed with this
|
||||
|
@ -19,7 +19,7 @@ rewriting or mail routing. These tables are usually in
|
||||
\fBdbm\fR or \fBdb\fR format.
|
||||
|
||||
Alternatively, lookup tables can be specified as SQLite databases.
|
||||
In order to use SQLite lookups, define a SQLite source as a lookup
|
||||
In order to use SQLite lookups, define an SQLite source as a lookup
|
||||
table in main.cf, for example:
|
||||
.nf
|
||||
alias_maps = sqlite:/etc/sqlite-aliases.cf
|
||||
@ -286,7 +286,7 @@ Use "\fBpostconf readme_directory\fR" or
|
||||
.na
|
||||
.nf
|
||||
DATABASE_README, Postfix lookup table overview
|
||||
SQLITE_README, Postfix SQLITE driver
|
||||
SQLITE_README, Postfix SQLITE howto
|
||||
.SH "LICENSE"
|
||||
.na
|
||||
.nf
|
||||
|
@ -979,6 +979,7 @@ while (<>) {
|
||||
s/\b(nisplus):/<a href="nisplus_table.5.html">$1<\/a>:/g;
|
||||
s/\b(ldap):/<a href="ldap_table.5.html">$1<\/a>:/g;
|
||||
s/\b(regexp):/<a href="regexp_table.5.html">$1<\/a>:/g;
|
||||
s/\b(sqlite):/<a href="mysql_table.5.html">$1<\/a>:/g;
|
||||
s/\b(tcp):/<a href="tcp_table.5.html">$1<\/a>:/g;
|
||||
|
||||
# Do nice links for smtp:host:port etc.
|
||||
|
@ -13,7 +13,7 @@
|
||||
# \fBdbm\fR or \fBdb\fR format.
|
||||
#
|
||||
# Alternatively, lookup tables can be specified as SQLite databases.
|
||||
# In order to use SQLite lookups, define a SQLite source as a lookup
|
||||
# In order to use SQLite lookups, define an SQLite source as a lookup
|
||||
# table in main.cf, for example:
|
||||
# .nf
|
||||
# alias_maps = sqlite:/etc/sqlite-aliases.cf
|
||||
@ -268,7 +268,7 @@
|
||||
# .na
|
||||
# .nf
|
||||
# DATABASE_README, Postfix lookup table overview
|
||||
# SQLITE_README, Postfix SQLITE driver
|
||||
# SQLITE_README, Postfix SQLITE howto
|
||||
# LICENSE
|
||||
# .ad
|
||||
# .fi
|
||||
|
@ -100,19 +100,19 @@
|
||||
/* "vmailer" and password "passwd" then the configuration file
|
||||
/* should read:
|
||||
/* .PP
|
||||
/* \fIuser\fR = \fBvmailer\fR
|
||||
/* user = vmailer
|
||||
/* .br
|
||||
/* \fIpassword\fR = \fBpasswd\fR
|
||||
/* password = passwd
|
||||
/* .br
|
||||
/* \fIdbname\fR = \fBvmailer_info\fR
|
||||
/* dbname = vmailer_info
|
||||
/* .br
|
||||
/* \fItable\fR = \fBaliases\fR
|
||||
/* table = aliases
|
||||
/* .br
|
||||
/* \fIselect_field\fR = \fBforw_addr\fR
|
||||
/* select_field = forw_addr
|
||||
/* .br
|
||||
/* \fIwhere_field\fR = \fBalias\fR
|
||||
/* where_field = alias
|
||||
/* .br
|
||||
/* \fIhosts\fR = \fBhost1.some.domain\fR \fBhost2.some.domain\fR
|
||||
/* hosts = host1.some.domain\fR \fBhost2.some.domain
|
||||
/* .IP additional_conditions
|
||||
/* Backward compatibility when \fIquery\fR is not set, additional
|
||||
/* conditions to the WHERE clause.
|
||||
@ -127,19 +127,19 @@
|
||||
/* "vmailer" and password "passwd" then the configuration file
|
||||
/* should read:
|
||||
/* .PP
|
||||
/* \fIuser\fR = \fBvmailer\fR
|
||||
/* user = vmailer
|
||||
/* .br
|
||||
/* \fIpassword\fR = \fBpasswd\fR
|
||||
/* password = passwd
|
||||
/* .br
|
||||
/* \fIdbname\fR = \fBvmailer_info\fR
|
||||
/* dbname = vmailer_info
|
||||
/* .br
|
||||
/* \fItable\fR = \fBaliases\fR
|
||||
/* table = aliases
|
||||
/* .br
|
||||
/* \fIselect_field\fR = \fBforw_addr\fR
|
||||
/* select_field = forw_addr
|
||||
/* .br
|
||||
/* \fIwhere_field\fR = \fBalias\fR
|
||||
/* where_field = alias
|
||||
/* .br
|
||||
/* \fIhosts\fR = \fBhost1.some.domain\fR \fBhost2.some.domain\fR
|
||||
/* hosts = host1.some.domain\fR \fBhost2.some.domain
|
||||
/* .PP
|
||||
/* SEE ALSO
|
||||
/* dict(3) generic dictionary manager
|
||||
|
@ -103,19 +103,19 @@
|
||||
/* "postfix" and password "passwd" then the configuration file
|
||||
/* should read:
|
||||
/* .PP
|
||||
/* \fIuser\fR = \fBpostfix\fR
|
||||
/* user = postfix
|
||||
/* .br
|
||||
/* \fIpassword\fR = \fBpasswd\fR
|
||||
/* password = passwd
|
||||
/* .br
|
||||
/* \fIdbname\fR = \fBpostfix_info\fR
|
||||
/* dbname = postfix_info
|
||||
/* .br
|
||||
/* \fItable\fR = \fBaliases\fR
|
||||
/* table = aliases
|
||||
/* .br
|
||||
/* \fIselect_field\fR = \fBforw_addr\fR
|
||||
/* select_field = forw_addr
|
||||
/* .br
|
||||
/* \fIwhere_field\fR = \fBalias\fR
|
||||
/* where_field = alias
|
||||
/* .br
|
||||
/* \fIhosts\fR = \fBhost1.some.domain\fR \fBhost2.some.domain\fR
|
||||
/* hosts = host1.some.domain\fR \fBhost2.some.domain
|
||||
/* .PP
|
||||
/* SEE ALSO
|
||||
/* dict(3) generic dictionary manager
|
||||
|
@ -14,7 +14,7 @@
|
||||
/* dict_sqlite_open() creates a dictionary of type 'sqlite'.
|
||||
/* This dictionary is an interface for the postfix key->value
|
||||
/* mappings to SQLite. The result is a pointer to the installed
|
||||
/* dictionary, or a null pointer in case of problems.
|
||||
/* dictionary.
|
||||
/* .PP
|
||||
/* Arguments:
|
||||
/* .IP name
|
||||
@ -39,7 +39,7 @@
|
||||
/* .IP dbpath
|
||||
/* Path to SQLite database
|
||||
/* .IP query
|
||||
/* Query template, before the query is actually issued, variable
|
||||
/* Query template. Before the query is actually issued, variable
|
||||
/* substitutions are performed. See sqlite_table(5) for details.
|
||||
/* .IP result_format
|
||||
/* The format used to expand results from queries. Substitutions
|
||||
@ -101,16 +101,16 @@ typedef struct {
|
||||
|
||||
/* dict_sqlite_quote - escape SQL metacharacters in input string */
|
||||
|
||||
static void dict_sqlite_quote(DICT *dict, const char *name, VSTRING *result)
|
||||
static void dict_sqlite_quote(DICT *dict, const char *raw_text, VSTRING *result)
|
||||
{
|
||||
char *q;
|
||||
char *quoted_text;
|
||||
|
||||
q = sqlite3_mprintf("%q", name);
|
||||
quoted_text = sqlite3_mprintf("%q", raw_text);
|
||||
/* Fix 20100616 */
|
||||
if (q == 0)
|
||||
if (quoted_text == 0)
|
||||
msg_fatal("dict_sqlite_quote: out of memory");
|
||||
vstring_strcat(result, q);
|
||||
sqlite3_free(q);
|
||||
vstring_strcat(result, raw_text);
|
||||
sqlite3_free(quoted_text);
|
||||
}
|
||||
|
||||
/* dict_sqlite_close - close the database */
|
||||
@ -142,11 +142,11 @@ static const char *dict_sqlite_lookup(DICT *dict, const char *name)
|
||||
{
|
||||
const char *myname = "dict_sqlite_lookup";
|
||||
DICT_SQLITE *dict_sqlite = (DICT_SQLITE *) dict;
|
||||
sqlite3_stmt *sql;
|
||||
const char *zErrMsg;
|
||||
sqlite3_stmt *sql_stmt;
|
||||
const char *query_remainder;
|
||||
static VSTRING *query;
|
||||
static VSTRING *result;
|
||||
const char *r;
|
||||
const char *retval;
|
||||
int expansion = 0;
|
||||
int status;
|
||||
|
||||
@ -161,17 +161,17 @@ static const char *dict_sqlite_lookup(DICT *dict, const char *name)
|
||||
}
|
||||
|
||||
/*
|
||||
* Optionally fold the key.
|
||||
* Optionally fold the key. Folding may be enabled on on-the-fly.
|
||||
*/
|
||||
if (dict->flags & DICT_FLAG_FOLD_FIX) {
|
||||
if (dict->fold_buf == 0)
|
||||
dict->fold_buf = vstring_alloc(10);
|
||||
dict->fold_buf = vstring_alloc(100);
|
||||
vstring_strcpy(dict->fold_buf, name);
|
||||
name = lowercase(vstring_str(dict->fold_buf));
|
||||
}
|
||||
|
||||
/*
|
||||
* Domain filter for email address lookups.
|
||||
* Apply the optional domain filter for email address lookups.
|
||||
*/
|
||||
if (db_common_check_domain(dict_sqlite->ctx, name) == 0) {
|
||||
if (msg_verbose)
|
||||
@ -201,75 +201,95 @@ static const char *dict_sqlite_lookup(DICT *dict, const char *name)
|
||||
myname, dict_sqlite->parser->name, vstring_str(query));
|
||||
|
||||
if (sqlite3_prepare_v2(dict_sqlite->db, vstring_str(query), -1,
|
||||
&sql, &zErrMsg) != SQLITE_OK) {
|
||||
&sql_stmt, &query_remainder) != SQLITE_OK)
|
||||
msg_fatal("%s: %s: SQL prepare failed: %s\n",
|
||||
myname, dict_sqlite->parser->name,
|
||||
sqlite3_errmsg(dict_sqlite->db));
|
||||
}
|
||||
|
||||
if (*query_remainder && msg_verbose)
|
||||
msg_info("%s: %s: Ignoring text at end of query: %s",
|
||||
myname, dict_sqlite->parser->name, query_remainder);
|
||||
|
||||
/*
|
||||
* Retrieve and expand the result(s).
|
||||
*/
|
||||
INIT_VSTR(result, 10);
|
||||
while ((status = sqlite3_step(sql)) == SQLITE_ROW) {
|
||||
while ((status = sqlite3_step(sql_stmt)) != SQLITE_DONE) {
|
||||
if (status == SQLITE_ROW) {
|
||||
if (db_common_expand(dict_sqlite->ctx, dict_sqlite->result_format,
|
||||
(char *) sqlite3_column_text(sql, 0),
|
||||
(char *) sqlite3_column_text(sql_stmt, 0),
|
||||
name, result, 0)
|
||||
&& dict_sqlite->expansion_limit > 0
|
||||
&& ++expansion > dict_sqlite->expansion_limit) {
|
||||
msg_warn("%s: %s: Expansion limit exceeded for key: '%s'",
|
||||
msg_warn("%s: %s: Expansion limit exceeded for key '%s'",
|
||||
myname, dict_sqlite->parser->name, name);
|
||||
dict_errno = DICT_ERR_RETRY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix 20100616 */
|
||||
if (status != SQLITE_ROW && status != SQLITE_DONE) {
|
||||
msg_warn("%s: %s: sql step for %s; %s\n",
|
||||
else {
|
||||
msg_warn("%s: %s: SQL step failed for query '%s': %s\n",
|
||||
myname, dict_sqlite->parser->name,
|
||||
vstring_str(query), sqlite3_errmsg(dict_sqlite->db));
|
||||
dict_errno = DICT_ERR_RETRY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up.
|
||||
*/
|
||||
if (sqlite3_finalize(sql))
|
||||
msg_fatal("%s: %s: SQL finalize for %s; %s\n",
|
||||
if (sqlite3_finalize(sql_stmt))
|
||||
msg_fatal("%s: %s: SQL finalize failed for query '%s': %s\n",
|
||||
myname, dict_sqlite->parser->name,
|
||||
vstring_str(query), sqlite3_errmsg(dict_sqlite->db));
|
||||
|
||||
r = vstring_str(result);
|
||||
return ((dict_errno == 0 && *r) ? r : 0);
|
||||
return ((dict_errno == 0 && *(retval = vstring_str(result)) != 0) ?
|
||||
retval : 0);
|
||||
}
|
||||
|
||||
/* sqlite_parse_config - parse sqlite configuration file */
|
||||
|
||||
static void sqlite_parse_config(DICT_SQLITE *dict_sqlite, const char *sqlitecf)
|
||||
{
|
||||
CFG_PARSER *p;
|
||||
VSTRING *buf;
|
||||
|
||||
p = dict_sqlite->parser = cfg_parser_alloc(sqlitecf);
|
||||
dict_sqlite->dbpath = cfg_get_str(p, "dbpath", "", 1, 0);
|
||||
dict_sqlite->result_format = cfg_get_str(p, "result_format", "%s", 1, 0);
|
||||
|
||||
if ((dict_sqlite->query = cfg_get_str(p, "query", NULL, 0, 0)) == 0) {
|
||||
buf = vstring_alloc(64);
|
||||
db_common_sql_build_query(buf, p);
|
||||
/*
|
||||
* Parse the primary configuration parameters, and emulate the legacy
|
||||
* query interface if necessary. This simplifies migration from one SQL
|
||||
* database type to another.
|
||||
*/
|
||||
dict_sqlite->parser = cfg_parser_alloc(sqlitecf);
|
||||
dict_sqlite->dbpath = cfg_get_str(dict_sqlite->parser, "dbpath", "", 1, 0);
|
||||
dict_sqlite->query = cfg_get_str(dict_sqlite->parser, "query", NULL, 0, 0);
|
||||
if (dict_sqlite->query == 0) {
|
||||
buf = vstring_alloc(100);
|
||||
db_common_sql_build_query(buf, dict_sqlite->parser);
|
||||
dict_sqlite->query = vstring_export(buf);
|
||||
}
|
||||
dict_sqlite->expansion_limit = cfg_get_int(p, "expansion_limit", 0, 0, 0);
|
||||
dict_sqlite->result_format =
|
||||
cfg_get_str(dict_sqlite->parser, "result_format", "%s", 1, 0);
|
||||
dict_sqlite->expansion_limit =
|
||||
cfg_get_int(dict_sqlite->parser, "expansion_limit", 0, 0, 0);
|
||||
|
||||
/*
|
||||
* Parse the query / result templates and the optional domain filter.
|
||||
*/
|
||||
dict_sqlite->ctx = 0;
|
||||
|
||||
(void) db_common_parse(&dict_sqlite->dict, &dict_sqlite->ctx, dict_sqlite->query, 1);
|
||||
(void) db_common_parse(&dict_sqlite->dict, &dict_sqlite->ctx,
|
||||
dict_sqlite->query, 1);
|
||||
(void) db_common_parse(0, &dict_sqlite->ctx, dict_sqlite->result_format, 0);
|
||||
db_common_parse_domain(dict_sqlite->parser, dict_sqlite->ctx);
|
||||
|
||||
db_common_parse_domain(p, dict_sqlite->ctx);
|
||||
|
||||
if (dict_sqlite->dict.flags & DICT_FLAG_FOLD_FIX)
|
||||
dict_sqlite->dict.fold_buf = vstring_alloc(10);
|
||||
/*
|
||||
* Maps that use substring keys should only be used with the full input
|
||||
* key.
|
||||
*/
|
||||
if (db_common_dict_partial(dict_sqlite->ctx))
|
||||
dict_sqlite->dict.flags |= DICT_FLAG_PATTERN;
|
||||
else
|
||||
dict_sqlite->dict.flags |= DICT_FLAG_FIXED;
|
||||
}
|
||||
|
||||
/* dict_sqlite_open - open sqlite database */
|
||||
@ -290,13 +310,13 @@ DICT *dict_sqlite_open(const char *name, int open_flags, int dict_flags)
|
||||
dict_sqlite->dict.lookup = dict_sqlite_lookup;
|
||||
dict_sqlite->dict.close = dict_sqlite_close;
|
||||
dict_sqlite->dict.flags = dict_flags;
|
||||
dict_sqlite->dict.flags |= DICT_FLAG_FIXED;
|
||||
|
||||
sqlite_parse_config(dict_sqlite, name);
|
||||
|
||||
if (sqlite3_open(dict_sqlite->dbpath, &dict_sqlite->db)) {
|
||||
msg_fatal("Can't open database: %s\n", sqlite3_errmsg(dict_sqlite->db));
|
||||
sqlite3_close(dict_sqlite->db);
|
||||
}
|
||||
if (sqlite3_open(dict_sqlite->dbpath, &dict_sqlite->db))
|
||||
msg_fatal("%s:%s: Can't open database: %s\n",
|
||||
DICT_TYPE_SQLITE, name, sqlite3_errmsg(dict_sqlite->db));
|
||||
|
||||
return (DICT_DEBUG (&dict_sqlite->dict));
|
||||
}
|
||||
|
||||
|
@ -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 "20100617"
|
||||
#define MAIL_RELEASE_DATE "20100618"
|
||||
#define MAIL_VERSION_NUMBER "2.8"
|
||||
|
||||
#ifdef SNAPSHOT
|
||||
|
Loading…
x
Reference in New Issue
Block a user