mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-31 06:05:37 +00:00
postfix-2.3-20051226
This commit is contained in:
committed by
Viktor Dukhovni
parent
51da02abb8
commit
bb0be7749b
@@ -11660,6 +11660,23 @@ Apologies for any names omitted.
|
||||
Bugfix: 20051219 "postconf -A" produced "postconf -a" output.
|
||||
Andreas Winkelmann.
|
||||
|
||||
20051225
|
||||
|
||||
Bugfix: the regexp map cleverly avoided scanning constant
|
||||
lookup results for non-existent $number expressions, but
|
||||
failed to subject those results to the necessary $$ -> $
|
||||
replacement. Files: util/dict_regexp.c.
|
||||
|
||||
Performance: the pcre map did not optimize constant lookup
|
||||
results; they were always scanned for non-existent $number
|
||||
expressions. File: util/dict_pcre.c.
|
||||
|
||||
This round of edits eliminates architectural differences
|
||||
between the pcre and regexp table implementations. The
|
||||
remaining difference is that regexp tables still support
|
||||
the obsolete "/pattern1/!/pattern2/ action" syntax, for
|
||||
backwards compatibility with Postfix 2.0 and earlier.
|
||||
|
||||
Open problems:
|
||||
|
||||
"postsuper -r" no longer resets the message arrival time,
|
||||
@@ -11670,11 +11687,6 @@ Open problems:
|
||||
Is it safe to cache a connection after it has been used for
|
||||
more than some number of address verification probes?
|
||||
|
||||
Access map actions such as FILTER and REDIRECT don't work
|
||||
in smtpd_end_of_data_restrictions (or anything else that
|
||||
generates additional queue file records after the message
|
||||
content is stored).
|
||||
|
||||
Try to recognize that Resent- headers appear in blocks,
|
||||
newest block first. But don't break on incorrect header
|
||||
block organization.
|
||||
|
@@ -10,7 +10,9 @@ delivery notifications.
|
||||
|
||||
Specifically, DSN support gives an email sender the ability to specify:
|
||||
|
||||
* What notifications are sent: success, failure, delay, or none.
|
||||
* What notifications are sent: success, failure, delay, or none. Normally,
|
||||
Postfix informs the sender only mail when delivery is delayed or when
|
||||
delivery fails.
|
||||
|
||||
* What content is returned in case of failure: only the message headers, or
|
||||
the full message.
|
||||
@@ -37,9 +39,11 @@ Unfortunately, disallowing "success" notification requests requires disallowing
|
||||
other DSN requests as well. The RFCs do not offer the option to negotiate
|
||||
feature subsets.
|
||||
|
||||
This is not as bad as it sounds. Remote senders with DSN support will still be
|
||||
informed that their mail reached your Postfix gateway successfully; they just
|
||||
will not get successful delivery notices from your internal systems.
|
||||
This is not as bad as it sounds. When you turn off DSN for remote inbound mail,
|
||||
remote senders with DSN support will still be informed that their mail reached
|
||||
your Postfix gateway successfully; they just will not get successful delivery
|
||||
notices from your internal systems. Remote senders lose very little: they can
|
||||
no longer specify how Postfix should report delayed or failed delivery.
|
||||
|
||||
Use the smtpd_discard_ehlo_keyword_address_maps feature if you wish to allow
|
||||
DSN requests from trusted clients but not from random strangers (see below for
|
||||
|
@@ -221,33 +221,27 @@
|
||||
# transport(5) table to direct mail to the discard(8)
|
||||
# service.
|
||||
#
|
||||
# Note: this action does not work in Postfix 2.2
|
||||
# smtpd_end_of_data_restrictions.
|
||||
#
|
||||
# This feature is available in Postfix 2.0 and later.
|
||||
#
|
||||
# DUNNO Pretend that the lookup key was not found. This
|
||||
# prevents Postfix from trying substrings of the
|
||||
# lookup key (such as a subdomain name, or a network
|
||||
# DUNNO Pretend that the lookup key was not found. This
|
||||
# prevents Postfix from trying substrings of the
|
||||
# lookup key (such as a subdomain name, or a network
|
||||
# address subnetwork).
|
||||
#
|
||||
# This feature is available in Postfix 2.0 and later.
|
||||
#
|
||||
# FILTER transport:destination
|
||||
# After the message is queued, send the entire mes-
|
||||
# After the message is queued, send the entire mes-
|
||||
# sage through the specified external content filter.
|
||||
# The transport:destination syntax is described in
|
||||
# the transport(5) manual page. More information
|
||||
# about external content filters is in the Postfix
|
||||
# The transport:destination syntax is described in
|
||||
# the transport(5) manual page. More information
|
||||
# about external content filters is in the Postfix
|
||||
# FILTER_README file.
|
||||
#
|
||||
# Note: this action overrides the main.cf con-
|
||||
# Note: this action overrides the main.cf con-
|
||||
# tent_filter setting, and currently affects all
|
||||
# recipients of the message.
|
||||
#
|
||||
# Note: this action does not work in Postfix 2.2
|
||||
# smtpd_end_of_data_restrictions.
|
||||
#
|
||||
# This feature is available in Postfix 2.0 and later.
|
||||
#
|
||||
# HOLD optional text...
|
||||
@@ -268,37 +262,31 @@
|
||||
# Note: this action currently affects all recipients
|
||||
# of the message.
|
||||
#
|
||||
# Note: this action does not work in Postfix 2.2
|
||||
# smtpd_end_of_data_restrictions.
|
||||
#
|
||||
# This feature is available in Postfix 2.0 and later.
|
||||
#
|
||||
# PREPEND headername: headervalue
|
||||
# Prepend the specified message header to the mes-
|
||||
# Prepend the specified message header to the mes-
|
||||
# sage. When this action is used multiple times, the
|
||||
# first prepended header appears before the second
|
||||
# first prepended header appears before the second
|
||||
# etc. prepended header.
|
||||
#
|
||||
# Note: this action does not support multi-line mes-
|
||||
# Note: this action does not support multi-line mes-
|
||||
# sage headers.
|
||||
#
|
||||
# Note: this action must be used before the message
|
||||
# content is received; it cannot be used in
|
||||
# Note: this action must be used before the message
|
||||
# content is received; it cannot be used in
|
||||
# smtpd_end_of_data_restrictions.
|
||||
#
|
||||
# This feature is available in Postfix 2.1 and later.
|
||||
#
|
||||
# REDIRECT user@domain
|
||||
# After the message is queued, send the message to
|
||||
# After the message is queued, send the message to
|
||||
# the specified address instead of the intended
|
||||
# recipient(s).
|
||||
#
|
||||
# Note: this action overrides the FILTER action, and
|
||||
# Note: this action overrides the FILTER action, and
|
||||
# currently affects all recipients of the message.
|
||||
#
|
||||
# Note: this action does not work in Postfix 2.2
|
||||
# smtpd_end_of_data_restrictions.
|
||||
#
|
||||
# This feature is available in Postfix 2.1 and later.
|
||||
#
|
||||
# WARN optional text...
|
||||
|
@@ -30,7 +30,8 @@ specify: </p>
|
||||
<ul>
|
||||
|
||||
<li> <p> What notifications are sent: success, failure, delay, or
|
||||
none. </p>
|
||||
none. Normally, Postfix informs the sender only mail when delivery
|
||||
is delayed or when delivery fails. </p>
|
||||
|
||||
<li> <p> What content is returned in case of failure: only the
|
||||
message headers, or the full message. </p>
|
||||
@@ -68,10 +69,12 @@ internal infrastructure than desirable. Unfortunately, disallowing
|
||||
requests as well. The RFCs do not offer the option to negotiate
|
||||
feature subsets. </p>
|
||||
|
||||
<p> This is not as bad as it sounds. Remote senders with DSN support
|
||||
will still be informed that their mail reached your Postfix gateway
|
||||
successfully; they just will not get successful delivery notices
|
||||
from your internal systems. </p>
|
||||
<p> This is not as bad as it sounds. When you turn off DSN for
|
||||
remote inbound mail, remote senders with DSN support will still be
|
||||
informed that their mail reached your Postfix gateway successfully;
|
||||
they just will not get successful delivery notices from your internal
|
||||
systems. Remote senders lose very little: they can no longer specify
|
||||
how Postfix should report delayed or failed delivery. </p>
|
||||
|
||||
<p> Use the <a href="postconf.5.html#smtpd_discard_ehlo_keyword_address_maps">smtpd_discard_ehlo_keyword_address_maps</a> feature if you
|
||||
wish to allow DSN requests from trusted clients but not from random
|
||||
|
@@ -227,33 +227,27 @@ ACCESS(5) ACCESS(5)
|
||||
<a href="transport.5.html">transport(5)</a> table to direct mail to the <a href="discard.8.html">discard(8)</a>
|
||||
service.
|
||||
|
||||
Note: this action does not work in Postfix 2.2
|
||||
<b><a href="postconf.5.html#smtpd_end_of_data_restrictions">smtpd_end_of_data_restrictions</a></b>.
|
||||
|
||||
This feature is available in Postfix 2.0 and later.
|
||||
|
||||
<b>DUNNO</b> Pretend that the lookup key was not found. This
|
||||
prevents Postfix from trying substrings of the
|
||||
lookup key (such as a subdomain name, or a network
|
||||
<b>DUNNO</b> Pretend that the lookup key was not found. This
|
||||
prevents Postfix from trying substrings of the
|
||||
lookup key (such as a subdomain name, or a network
|
||||
address subnetwork).
|
||||
|
||||
This feature is available in Postfix 2.0 and later.
|
||||
|
||||
<b>FILTER</b> <i>transport:destination</i>
|
||||
After the message is queued, send the entire mes-
|
||||
After the message is queued, send the entire mes-
|
||||
sage through the specified external content filter.
|
||||
The <i>transport:destination</i> syntax is described in
|
||||
the <a href="transport.5.html"><b>transport</b>(5)</a> manual page. More information
|
||||
about external content filters is in the Postfix
|
||||
The <i>transport:destination</i> syntax is described in
|
||||
the <a href="transport.5.html"><b>transport</b>(5)</a> manual page. More information
|
||||
about external content filters is in the Postfix
|
||||
<a href="FILTER_README.html">FILTER_README</a> file.
|
||||
|
||||
Note: this action overrides the <b>main.cf <a href="postconf.5.html#content_filter">con</a>-</b>
|
||||
Note: this action overrides the <b>main.cf <a href="postconf.5.html#content_filter">con</a>-</b>
|
||||
<b><a href="postconf.5.html#content_filter">tent_filter</a></b> setting, and currently affects all
|
||||
recipients of the message.
|
||||
|
||||
Note: this action does not work in Postfix 2.2
|
||||
<b><a href="postconf.5.html#smtpd_end_of_data_restrictions">smtpd_end_of_data_restrictions</a></b>.
|
||||
|
||||
This feature is available in Postfix 2.0 and later.
|
||||
|
||||
<b>HOLD</b> <i>optional text...</i>
|
||||
@@ -274,37 +268,31 @@ ACCESS(5) ACCESS(5)
|
||||
Note: this action currently affects all recipients
|
||||
of the message.
|
||||
|
||||
Note: this action does not work in Postfix 2.2
|
||||
<b><a href="postconf.5.html#smtpd_end_of_data_restrictions">smtpd_end_of_data_restrictions</a></b>.
|
||||
|
||||
This feature is available in Postfix 2.0 and later.
|
||||
|
||||
<b>PREPEND</b> <i>headername: headervalue</i>
|
||||
Prepend the specified message header to the mes-
|
||||
Prepend the specified message header to the mes-
|
||||
sage. When this action is used multiple times, the
|
||||
first prepended header appears before the second
|
||||
first prepended header appears before the second
|
||||
etc. prepended header.
|
||||
|
||||
Note: this action does not support multi-line mes-
|
||||
Note: this action does not support multi-line mes-
|
||||
sage headers.
|
||||
|
||||
Note: this action must be used before the message
|
||||
content is received; it cannot be used in
|
||||
Note: this action must be used before the message
|
||||
content is received; it cannot be used in
|
||||
<b><a href="postconf.5.html#smtpd_end_of_data_restrictions">smtpd_end_of_data_restrictions</a></b>.
|
||||
|
||||
This feature is available in Postfix 2.1 and later.
|
||||
|
||||
<b>REDIRECT</b> <i>user@domain</i>
|
||||
After the message is queued, send the message to
|
||||
After the message is queued, send the message to
|
||||
the specified address instead of the intended
|
||||
recipient(s).
|
||||
|
||||
Note: this action overrides the FILTER action, and
|
||||
Note: this action overrides the FILTER action, and
|
||||
currently affects all recipients of the message.
|
||||
|
||||
Note: this action does not work in Postfix 2.2
|
||||
<b><a href="postconf.5.html#smtpd_end_of_data_restrictions">smtpd_end_of_data_restrictions</a></b>.
|
||||
|
||||
This feature is available in Postfix 2.1 and later.
|
||||
|
||||
<b>WARN</b> <i>optional text...</i>
|
||||
|
@@ -50,112 +50,120 @@ PCRE_TABLE(5) PCRE_TABLE(5)
|
||||
Note: do not prepend whitespace to patterns inside
|
||||
<b>if</b>..<b>endif</b>.
|
||||
|
||||
This feature is available in Postfix 2.1 and later.
|
||||
|
||||
<b>if !/</b><i>pattern</i><b>/</b><i>flags</i>
|
||||
|
||||
<b>endif</b> Match the input string against the patterns between
|
||||
<b>if</b> and <b>endif</b>, if and only if the input string does
|
||||
<b>if</b> and <b>endif</b>, if and only if the input string does
|
||||
<b>not</b> match <i>pattern</i>. The <b>if</b>..<b>endif</b> can nest.
|
||||
|
||||
Note: do not prepend whitespace to patterns inside
|
||||
<b>if</b>..<b>endif</b>.
|
||||
|
||||
This feature is available in Postfix 2.1 and later.
|
||||
|
||||
blank lines and comments
|
||||
Empty lines and whitespace-only lines are ignored,
|
||||
as are lines whose first non-whitespace character
|
||||
Empty lines and whitespace-only lines are ignored,
|
||||
as are lines whose first non-whitespace character
|
||||
is a `#'.
|
||||
|
||||
multi-line text
|
||||
A logical line starts with non-whitespace text. A
|
||||
line that starts with whitespace continues a logi-
|
||||
A logical line starts with non-whitespace text. A
|
||||
line that starts with whitespace continues a logi-
|
||||
cal line.
|
||||
|
||||
Each pattern is a perl-like regular expression. The
|
||||
expression delimiter can be any character, except white-
|
||||
space or characters that have special meaning (tradition-
|
||||
ally the forward slash is used). The regular expression
|
||||
expression delimiter can be any character, except white-
|
||||
space or characters that have special meaning (tradition-
|
||||
ally the forward slash is used). The regular expression
|
||||
can contain whitespace.
|
||||
|
||||
By default, matching is case-insensitive, and newlines are
|
||||
not treated as special characters. The behavior is con-
|
||||
trolled by flags, which are toggled by appending one or
|
||||
not treated as special characters. The behavior is con-
|
||||
trolled by flags, which are toggled by appending one or
|
||||
more of the following characters after the pattern:
|
||||
|
||||
<b>i</b> (default: on)
|
||||
Toggles the case sensitivity flag. By default,
|
||||
Toggles the case sensitivity flag. By default,
|
||||
matching is case insensitive.
|
||||
|
||||
<b>m</b> (default: off)
|
||||
Toggles the PCRE_MULTILINE flag. When this flag is
|
||||
on, the <b>^</b> and <b>$</b> metacharacters match immediately
|
||||
after and immediately before a newline character,
|
||||
respectively, in addition to matching at the start
|
||||
Toggles the PCRE_MULTILINE flag. When this flag is
|
||||
on, the <b>^</b> and <b>$</b> metacharacters match immediately
|
||||
after and immediately before a newline character,
|
||||
respectively, in addition to matching at the start
|
||||
and end of the subject string.
|
||||
|
||||
<b>s</b> (default: on)
|
||||
Toggles the PCRE_DOTALL flag. When this flag is on,
|
||||
the <b>.</b> metacharacter matches the newline character.
|
||||
With Postfix versions prior to 2.0, The flag is off
|
||||
by default, which is inconvenient for multi-line
|
||||
by default, which is inconvenient for multi-line
|
||||
message header matching.
|
||||
|
||||
<b>x</b> (default: off)
|
||||
Toggles the pcre extended flag. When this flag is
|
||||
on, whitespace in the pattern (other than in a
|
||||
Toggles the pcre extended flag. When this flag is
|
||||
on, whitespace in the pattern (other than in a
|
||||
character class) and characters between a <b>#</b> outside
|
||||
a character class and the next newline character
|
||||
are ignored. An escaping backslash can be used to
|
||||
include a whitespace or <b>#</b> character as part of the
|
||||
a character class and the next newline character
|
||||
are ignored. An escaping backslash can be used to
|
||||
include a whitespace or <b>#</b> character as part of the
|
||||
pattern.
|
||||
|
||||
<b>A</b> (default: off)
|
||||
Toggles the PCRE_ANCHORED flag. When this flag is
|
||||
on, the pattern is forced to be "anchored", that
|
||||
Toggles the PCRE_ANCHORED flag. When this flag is
|
||||
on, the pattern is forced to be "anchored", that
|
||||
is, it is constrained to match only at the start of
|
||||
the string which is being searched (the "subject
|
||||
string"). This effect can also be achieved by
|
||||
the string which is being searched (the "subject
|
||||
string"). This effect can also be achieved by
|
||||
appropriate constructs in the pattern itself.
|
||||
|
||||
<b>E</b> (default: off)
|
||||
Toggles the PCRE_DOLLAR_ENDONLY flag. When this
|
||||
flag is on, a <b>$</b> metacharacter in the pattern
|
||||
matches only at the end of the subject string.
|
||||
Without this flag, a dollar also matches immedi-
|
||||
Toggles the PCRE_DOLLAR_ENDONLY flag. When this
|
||||
flag is on, a <b>$</b> metacharacter in the pattern
|
||||
matches only at the end of the subject string.
|
||||
Without this flag, a dollar also matches immedi-
|
||||
ately before the final character if it is a newline
|
||||
character (but not before any other newline charac-
|
||||
ters). This flag is ignored if PCRE_MULTILINE flag
|
||||
ters). This flag is ignored if PCRE_MULTILINE flag
|
||||
is set.
|
||||
|
||||
<b>U</b> (default: off)
|
||||
Toggles the ungreedy matching flag. When this flag
|
||||
is on, the pattern matching engine inverts the
|
||||
"greediness" of the quantifiers so that they are
|
||||
not greedy by default, but become greedy if fol-
|
||||
lowed by "?". This flag can also set by a (?U)
|
||||
is on, the pattern matching engine inverts the
|
||||
"greediness" of the quantifiers so that they are
|
||||
not greedy by default, but become greedy if fol-
|
||||
lowed by "?". This flag can also set by a (?U)
|
||||
modifier within the pattern.
|
||||
|
||||
<b>X</b> (default: off)
|
||||
Toggles the PCRE_EXTRA flag. When this flag is on,
|
||||
any backslash in a pattern that is followed by a
|
||||
any backslash in a pattern that is followed by a
|
||||
letter that has no special meaning causes an error,
|
||||
thus reserving these combinations for future expan-
|
||||
sion.
|
||||
|
||||
<b>SEARCH ORDER</b>
|
||||
Patterns are applied in the order as specified in the ta-
|
||||
ble, until a pattern is found that matches the input
|
||||
Patterns are applied in the order as specified in the ta-
|
||||
ble, until a pattern is found that matches the input
|
||||
string.
|
||||
|
||||
Each pattern is applied to the entire input string.
|
||||
Depending on the application, that string is an entire
|
||||
Each pattern is applied to the entire input string.
|
||||
Depending on the application, that string is an entire
|
||||
client hostname, an entire client IP address, or an entire
|
||||
mail address. Thus, no parent domain or parent network
|
||||
search is done, and <i>user@domain</i> mail addresses are not
|
||||
broken up into their <i>user</i> and <i>domain</i> constituent parts,
|
||||
mail address. Thus, no parent domain or parent network
|
||||
search is done, and <i>user@domain</i> mail addresses are not
|
||||
broken up into their <i>user</i> and <i>domain</i> constituent parts,
|
||||
nor is <i>user+foo</i> broken up into <i>user</i> and <i>foo</i>.
|
||||
|
||||
<b>TEXT SUBSTITUTION</b>
|
||||
Substitution of substrings from the matched expression
|
||||
into the result string is possible using the conventional
|
||||
perl syntax ($1, $2, etc.). The macros in the result
|
||||
string may need to be written as ${n} or $(n) if they
|
||||
aren't followed by whitespace.
|
||||
Substitution of substrings from the matched expression
|
||||
into the result string is possible using the conventional
|
||||
perl syntax ($1, $2, etc.); specify $$ to produce a $
|
||||
character as output. The macros in the result string may
|
||||
need to be written as ${n} or $(n) if they aren't followed
|
||||
by whitespace.
|
||||
|
||||
Note: since negated patterns (those preceded by <b>!</b>) return
|
||||
a result when the expression does not match, substitutions
|
||||
|
@@ -50,11 +50,19 @@ REGEXP_TABLE(5) REGEXP_TABLE(5)
|
||||
Note: do not prepend whitespace to patterns inside
|
||||
<b>if</b>..<b>endif</b>.
|
||||
|
||||
This feature is available in Postfix 2.1 and later.
|
||||
|
||||
<b>if !/</b><i>pattern</i><b>/</b><i>flags</i>
|
||||
|
||||
<b>endif</b> Match the input string against the patterns between
|
||||
<b>if</b> and <b>endif</b>, if and only if that same input string
|
||||
does <b>not</b> match <i>pattern</i>. The <b>if</b>..<b>endif</b> can nest.
|
||||
does <b>not</b> match <i>pattern</i>. The <b>if</b>..<b>endif</b> can nest.
|
||||
matches <i>pattern</i>. The <b>if</b>..<b>endif</b> can nest.
|
||||
|
||||
Note: do not prepend whitespace to patterns inside
|
||||
<b>if</b>..<b>endif</b>.
|
||||
|
||||
This feature is available in Postfix 2.1 and later.
|
||||
|
||||
blank lines and comments
|
||||
Empty lines and whitespace-only lines are ignored,
|
||||
@@ -113,11 +121,12 @@ REGEXP_TABLE(5) REGEXP_TABLE(5)
|
||||
|
||||
<b>TEXT SUBSTITUTION</b>
|
||||
Substitution of substrings from the matched expression
|
||||
into the result string is possible using $1, $2, etc.. The
|
||||
macros in the result string may need to be written as ${n}
|
||||
or $(n) if they aren't followed by whitespace.
|
||||
into the result string is possible using $1, $2, etc.;
|
||||
specify $$ to produce a $ character as output. The macros
|
||||
in the result string may need to be written as ${n} or
|
||||
$(n) if they aren't followed by whitespace.
|
||||
|
||||
Note: since negated patterns (those preceded by <b>!</b>) return
|
||||
Note: since negated patterns (those preceded by <b>!</b>) return
|
||||
a result when the expression does not match, substitutions
|
||||
are not available for negated patterns.
|
||||
|
||||
|
@@ -212,9 +212,6 @@ Note: this action currently affects all recipients of the message.
|
||||
To discard only one recipient without discarding the entire message,
|
||||
use the transport(5) table to direct mail to the discard(8) service.
|
||||
.sp
|
||||
Note: this action does not work in Postfix 2.2
|
||||
\fBsmtpd_end_of_data_restrictions\fR.
|
||||
.sp
|
||||
This feature is available in Postfix 2.0 and later.
|
||||
.IP \fBDUNNO\fR
|
||||
Pretend that the lookup key was not found. This
|
||||
@@ -232,9 +229,6 @@ about external content filters is in the Postfix FILTER_README file.
|
||||
Note: this action overrides the \fBmain.cf content_filter\fR setting,
|
||||
and currently affects all recipients of the message.
|
||||
.sp
|
||||
Note: this action does not work in Postfix 2.2
|
||||
\fBsmtpd_end_of_data_restrictions\fR.
|
||||
.sp
|
||||
This feature is available in Postfix 2.0 and later.
|
||||
.IP "\fBHOLD \fIoptional text...\fR"
|
||||
Place the message on the \fBhold\fR queue, where it will sit
|
||||
@@ -252,9 +246,6 @@ or \fB$bounce_queue_lifetime\fR, or longer.
|
||||
.sp
|
||||
Note: this action currently affects all recipients of the message.
|
||||
.sp
|
||||
Note: this action does not work in Postfix 2.2
|
||||
\fBsmtpd_end_of_data_restrictions\fR.
|
||||
.sp
|
||||
This feature is available in Postfix 2.0 and later.
|
||||
.IP "\fBPREPEND \fIheadername: headervalue\fR"
|
||||
Prepend the specified message header to the message.
|
||||
@@ -274,9 +265,6 @@ address instead of the intended recipient(s).
|
||||
Note: this action overrides the FILTER action, and currently affects
|
||||
all recipients of the message.
|
||||
.sp
|
||||
Note: this action does not work in Postfix 2.2
|
||||
\fBsmtpd_end_of_data_restrictions\fR.
|
||||
.sp
|
||||
This feature is available in Postfix 2.1 and later.
|
||||
.IP "\fBWARN \fIoptional text...\fR
|
||||
Log a warning with the optional text, together with client information
|
||||
|
@@ -48,11 +48,18 @@ and \fBendif\fR, if and only if the input string also matches
|
||||
.sp
|
||||
Note: do not prepend whitespace to patterns inside
|
||||
\fBif\fR..\fBendif\fR.
|
||||
.sp
|
||||
This feature is available in Postfix 2.1 and later.
|
||||
.IP "\fBif !/\fIpattern\fB/\fIflags\fR"
|
||||
.IP "\fBendif\fR"
|
||||
Match the input string against the patterns between \fBif\fR
|
||||
and \fBendif\fR, if and only if the input string does \fBnot\fR
|
||||
match \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
|
||||
.sp
|
||||
Note: do not prepend whitespace to patterns inside
|
||||
\fBif\fR..\fBendif\fR.
|
||||
.sp
|
||||
This feature is available in Postfix 2.1 and later.
|
||||
.IP "blank lines and comments"
|
||||
Empty lines and whitespace-only lines are ignored, as
|
||||
are lines whose first non-whitespace character is a `#'.
|
||||
@@ -137,7 +144,8 @@ broken up into \fIuser\fR and \fIfoo\fR.
|
||||
.ad
|
||||
.fi
|
||||
Substitution of substrings from the matched expression into the result
|
||||
string is possible using the conventional perl syntax ($1, $2, etc.).
|
||||
string is possible using the conventional perl syntax ($1, $2, etc.);
|
||||
specify $$ to produce a $ character as output.
|
||||
The macros in the result string may need to be written as ${n}
|
||||
or $(n) if they aren't followed by whitespace.
|
||||
|
||||
|
@@ -48,11 +48,19 @@ matches \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
|
||||
.sp
|
||||
Note: do not prepend whitespace to patterns inside
|
||||
\fBif\fR..\fBendif\fR.
|
||||
.sp
|
||||
This feature is available in Postfix 2.1 and later.
|
||||
.IP "\fBif !/\fIpattern\fB/\fIflags\fR"
|
||||
.IP "\fBendif\fR"
|
||||
Match the input string against the patterns between \fBif\fR
|
||||
and \fBendif\fR, if and only if that same input string does
|
||||
\fBnot\fR match \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
|
||||
matches \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
|
||||
.sp
|
||||
Note: do not prepend whitespace to patterns inside
|
||||
\fBif\fR..\fBendif\fR.
|
||||
.sp
|
||||
This feature is available in Postfix 2.1 and later.
|
||||
.IP "blank lines and comments"
|
||||
Empty lines and whitespace-only lines are ignored, as
|
||||
are lines whose first non-whitespace character is a `#'.
|
||||
@@ -105,7 +113,9 @@ broken up into \fIuser\fR and \fIfoo\fR.
|
||||
.ad
|
||||
.fi
|
||||
Substitution of substrings from the matched expression into the result
|
||||
string is possible using $1, $2, etc.. The macros in the result string
|
||||
string is possible using $1, $2, etc.;
|
||||
specify $$ to produce a $ character as output.
|
||||
The macros in the result string
|
||||
may need to be written as ${n} or $(n) if they aren't followed
|
||||
by whitespace.
|
||||
|
||||
|
@@ -30,7 +30,8 @@ specify: </p>
|
||||
<ul>
|
||||
|
||||
<li> <p> What notifications are sent: success, failure, delay, or
|
||||
none. </p>
|
||||
none. Normally, Postfix informs the sender only mail when delivery
|
||||
is delayed or when delivery fails. </p>
|
||||
|
||||
<li> <p> What content is returned in case of failure: only the
|
||||
message headers, or the full message. </p>
|
||||
@@ -68,10 +69,12 @@ internal infrastructure than desirable. Unfortunately, disallowing
|
||||
requests as well. The RFCs do not offer the option to negotiate
|
||||
feature subsets. </p>
|
||||
|
||||
<p> This is not as bad as it sounds. Remote senders with DSN support
|
||||
will still be informed that their mail reached your Postfix gateway
|
||||
successfully; they just will not get successful delivery notices
|
||||
from your internal systems. </p>
|
||||
<p> This is not as bad as it sounds. When you turn off DSN for
|
||||
remote inbound mail, remote senders with DSN support will still be
|
||||
informed that their mail reached your Postfix gateway successfully;
|
||||
they just will not get successful delivery notices from your internal
|
||||
systems. Remote senders lose very little: they can no longer specify
|
||||
how Postfix should report delayed or failed delivery. </p>
|
||||
|
||||
<p> Use the smtpd_discard_ehlo_keyword_address_maps feature if you
|
||||
wish to allow DSN requests from trusted clients but not from random
|
||||
|
@@ -219,9 +219,6 @@
|
||||
# To discard only one recipient without discarding the entire message,
|
||||
# use the transport(5) table to direct mail to the discard(8) service.
|
||||
# .sp
|
||||
# Note: this action does not work in Postfix 2.2
|
||||
# \fBsmtpd_end_of_data_restrictions\fR.
|
||||
# .sp
|
||||
# This feature is available in Postfix 2.0 and later.
|
||||
# .IP \fBDUNNO\fR
|
||||
# Pretend that the lookup key was not found. This
|
||||
@@ -239,9 +236,6 @@
|
||||
# Note: this action overrides the \fBmain.cf content_filter\fR setting,
|
||||
# and currently affects all recipients of the message.
|
||||
# .sp
|
||||
# Note: this action does not work in Postfix 2.2
|
||||
# \fBsmtpd_end_of_data_restrictions\fR.
|
||||
# .sp
|
||||
# This feature is available in Postfix 2.0 and later.
|
||||
# .IP "\fBHOLD \fIoptional text...\fR"
|
||||
# Place the message on the \fBhold\fR queue, where it will sit
|
||||
@@ -259,9 +253,6 @@
|
||||
# .sp
|
||||
# Note: this action currently affects all recipients of the message.
|
||||
# .sp
|
||||
# Note: this action does not work in Postfix 2.2
|
||||
# \fBsmtpd_end_of_data_restrictions\fR.
|
||||
# .sp
|
||||
# This feature is available in Postfix 2.0 and later.
|
||||
# .IP "\fBPREPEND \fIheadername: headervalue\fR"
|
||||
# Prepend the specified message header to the message.
|
||||
@@ -281,9 +272,6 @@
|
||||
# Note: this action overrides the FILTER action, and currently affects
|
||||
# all recipients of the message.
|
||||
# .sp
|
||||
# Note: this action does not work in Postfix 2.2
|
||||
# \fBsmtpd_end_of_data_restrictions\fR.
|
||||
# .sp
|
||||
# This feature is available in Postfix 2.1 and later.
|
||||
# .IP "\fBWARN \fIoptional text...\fR
|
||||
# Log a warning with the optional text, together with client information
|
||||
|
@@ -40,11 +40,18 @@
|
||||
# .sp
|
||||
# Note: do not prepend whitespace to patterns inside
|
||||
# \fBif\fR..\fBendif\fR.
|
||||
# .sp
|
||||
# This feature is available in Postfix 2.1 and later.
|
||||
# .IP "\fBif !/\fIpattern\fB/\fIflags\fR"
|
||||
# .IP "\fBendif\fR"
|
||||
# Match the input string against the patterns between \fBif\fR
|
||||
# and \fBendif\fR, if and only if the input string does \fBnot\fR
|
||||
# match \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
|
||||
# .sp
|
||||
# Note: do not prepend whitespace to patterns inside
|
||||
# \fBif\fR..\fBendif\fR.
|
||||
# .sp
|
||||
# This feature is available in Postfix 2.1 and later.
|
||||
# .IP "blank lines and comments"
|
||||
# Empty lines and whitespace-only lines are ignored, as
|
||||
# are lines whose first non-whitespace character is a `#'.
|
||||
@@ -125,7 +132,8 @@
|
||||
# .ad
|
||||
# .fi
|
||||
# Substitution of substrings from the matched expression into the result
|
||||
# string is possible using the conventional perl syntax ($1, $2, etc.).
|
||||
# string is possible using the conventional perl syntax ($1, $2, etc.);
|
||||
# specify $$ to produce a $ character as output.
|
||||
# The macros in the result string may need to be written as ${n}
|
||||
# or $(n) if they aren't followed by whitespace.
|
||||
#
|
||||
|
@@ -40,11 +40,19 @@
|
||||
# .sp
|
||||
# Note: do not prepend whitespace to patterns inside
|
||||
# \fBif\fR..\fBendif\fR.
|
||||
# .sp
|
||||
# This feature is available in Postfix 2.1 and later.
|
||||
# .IP "\fBif !/\fIpattern\fB/\fIflags\fR"
|
||||
# .IP "\fBendif\fR"
|
||||
# Match the input string against the patterns between \fBif\fR
|
||||
# and \fBendif\fR, if and only if that same input string does
|
||||
# \fBnot\fR match \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
|
||||
# matches \fIpattern\fR. The \fBif\fR..\fBendif\fR can nest.
|
||||
# .sp
|
||||
# Note: do not prepend whitespace to patterns inside
|
||||
# \fBif\fR..\fBendif\fR.
|
||||
# .sp
|
||||
# This feature is available in Postfix 2.1 and later.
|
||||
# .IP "blank lines and comments"
|
||||
# Empty lines and whitespace-only lines are ignored, as
|
||||
# are lines whose first non-whitespace character is a `#'.
|
||||
@@ -93,7 +101,9 @@
|
||||
# .ad
|
||||
# .fi
|
||||
# Substitution of substrings from the matched expression into the result
|
||||
# string is possible using $1, $2, etc.. The macros in the result string
|
||||
# string is possible using $1, $2, etc.;
|
||||
# specify $$ to produce a $ character as output.
|
||||
# The macros in the result string
|
||||
# may need to be written as ${n} or $(n) if they aren't followed
|
||||
# by whitespace.
|
||||
#
|
||||
|
@@ -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 "20051223"
|
||||
#define MAIL_RELEASE_DATE "20051226"
|
||||
#define MAIL_VERSION_NUMBER "2.3"
|
||||
|
||||
#ifdef SNAPSHOT
|
||||
|
@@ -40,7 +40,7 @@ typedef struct DICT {
|
||||
time_t mtime; /* mod time at open */
|
||||
} DICT;
|
||||
|
||||
extern DICT *dict_alloc(const char *, const char *, int);
|
||||
extern DICT *dict_alloc(const char *, const char *, ssize_t);
|
||||
extern void dict_free(DICT *);
|
||||
|
||||
extern DICT *dict_debug(DICT *);
|
||||
|
@@ -9,7 +9,7 @@
|
||||
/* DICT *dict_alloc(dict_type, dict_name, size)
|
||||
/* const char *dict_type;
|
||||
/* const char *dict_name;
|
||||
/* int size;
|
||||
/* ssize_t size;
|
||||
/*
|
||||
/* void dict_free(dict)
|
||||
/* DICT *ptr;
|
||||
@@ -105,7 +105,7 @@ static void dict_default_close(DICT *dict)
|
||||
|
||||
/* dict_alloc - allocate dictionary object, initialize super-class */
|
||||
|
||||
DICT *dict_alloc(const char *dict_type, const char *dict_name, int size)
|
||||
DICT *dict_alloc(const char *dict_type, const char *dict_name, ssize_t size)
|
||||
{
|
||||
DICT *dict = (DICT *) mymalloc(size);
|
||||
|
||||
|
@@ -101,6 +101,7 @@ typedef struct {
|
||||
pcre_extra *hints; /* hints to speed pattern execution */
|
||||
char *replacement; /* replacement string */
|
||||
int match; /* positive or negative match */
|
||||
size_t max_sub; /* largest $number in replacement */
|
||||
} DICT_PCRE_MATCH_RULE;
|
||||
|
||||
typedef struct {
|
||||
@@ -116,6 +117,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
DICT dict; /* generic members */
|
||||
DICT_PCRE_RULE *head;
|
||||
VSTRING *expansion_buf; /* lookup result */
|
||||
} DICT_PCRE;
|
||||
|
||||
static int dict_pcre_init = 0; /* flag need to init pcre library */
|
||||
@@ -124,9 +126,8 @@ static int dict_pcre_init = 0; /* flag need to init pcre library */
|
||||
* Context for $number expansion callback.
|
||||
*/
|
||||
typedef struct {
|
||||
const char *mapname; /* source dict name */
|
||||
int lineno; /* source file line number */
|
||||
VSTRING *expansion_buf; /* target string buffer */
|
||||
DICT_PCRE *dict_pcre; /* the dictionary handle */
|
||||
DICT_PCRE_MATCH_RULE *match_rule; /* the rule we matched */
|
||||
const char *lookup_string; /* string against which we match */
|
||||
int offsets[PCRE_MAX_CAPTURE * 3]; /* Cut substrings */
|
||||
int matches; /* Count of cuts */
|
||||
@@ -138,8 +139,8 @@ typedef struct {
|
||||
typedef struct {
|
||||
const char *mapname; /* name of regexp map */
|
||||
int lineno; /* where in file */
|
||||
int flags; /* dict_flags */
|
||||
size_t max_sub; /* Largest $n seen */
|
||||
char *literal; /* constant result, $$ -> $ */
|
||||
} DICT_PCRE_PRESCAN_CONTEXT;
|
||||
|
||||
/*
|
||||
@@ -162,6 +163,8 @@ typedef struct {
|
||||
static int dict_pcre_expand(int type, VSTRING *buf, char *ptr)
|
||||
{
|
||||
DICT_PCRE_EXPAND_CONTEXT *ctxt = (DICT_PCRE_EXPAND_CONTEXT *) ptr;
|
||||
DICT_PCRE_MATCH_RULE *match_rule = ctxt->match_rule;
|
||||
DICT_PCRE *dict_pcre = ctxt->dict_pcre;
|
||||
const char *pp;
|
||||
int n;
|
||||
int ret;
|
||||
@@ -176,16 +179,16 @@ static int dict_pcre_expand(int type, VSTRING *buf, char *ptr)
|
||||
if (ret < 0) {
|
||||
if (ret == PCRE_ERROR_NOSUBSTRING)
|
||||
msg_fatal("regexp %s, line %d: replace index out of range",
|
||||
ctxt->mapname, ctxt->lineno);
|
||||
dict_pcre->dict.name, match_rule->rule.lineno);
|
||||
else
|
||||
msg_fatal("regexp %s, line %d: pcre_get_substring error: %d",
|
||||
ctxt->mapname, ctxt->lineno, ret);
|
||||
dict_pcre->dict.name, match_rule->rule.lineno, ret);
|
||||
}
|
||||
if (*pp == 0) {
|
||||
myfree((char *) pp);
|
||||
return (MAC_PARSE_UNDEF);
|
||||
}
|
||||
vstring_strcat(ctxt->expansion_buf, pp);
|
||||
vstring_strcat(dict_pcre->expansion_buf, pp);
|
||||
myfree((char *) pp);
|
||||
return (MAC_PARSE_OK);
|
||||
}
|
||||
@@ -194,7 +197,7 @@ static int dict_pcre_expand(int type, VSTRING *buf, char *ptr)
|
||||
* Straight text - duplicate with no substitution.
|
||||
*/
|
||||
else {
|
||||
vstring_strcat(ctxt->expansion_buf, vstring_str(buf));
|
||||
vstring_strcat(dict_pcre->expansion_buf, vstring_str(buf));
|
||||
return (MAC_PARSE_OK);
|
||||
}
|
||||
}
|
||||
@@ -252,7 +255,6 @@ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string)
|
||||
DICT_PCRE_MATCH_RULE *match_rule;
|
||||
int lookup_len = strlen(lookup_string);
|
||||
DICT_PCRE_EXPAND_CONTEXT ctxt;
|
||||
static VSTRING *expansion_buf;
|
||||
int nesting = 0;
|
||||
|
||||
dict_errno = 0;
|
||||
@@ -292,28 +294,31 @@ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string)
|
||||
continue; /* pcre_exec failed */
|
||||
}
|
||||
|
||||
/* Negative rules can't have any substitutions */
|
||||
if (!match_rule->match)
|
||||
/*
|
||||
* Skip $number substitutions when the replacement text contains
|
||||
* no $number strings, as learned during the compile time
|
||||
* pre-scan. The pre-scan already replaced $$ by $.
|
||||
*/
|
||||
if (match_rule->max_sub == 0)
|
||||
return match_rule->replacement;
|
||||
|
||||
/*
|
||||
* We've got a match. Perform substitution on replacement string.
|
||||
*/
|
||||
if (expansion_buf == 0)
|
||||
expansion_buf = vstring_alloc(10);
|
||||
VSTRING_RESET(expansion_buf);
|
||||
ctxt.expansion_buf = expansion_buf;
|
||||
if (dict_pcre->expansion_buf == 0)
|
||||
dict_pcre->expansion_buf = vstring_alloc(10);
|
||||
VSTRING_RESET(dict_pcre->expansion_buf);
|
||||
ctxt.dict_pcre = dict_pcre;
|
||||
ctxt.match_rule = match_rule;
|
||||
ctxt.lookup_string = lookup_string;
|
||||
ctxt.mapname = dict->name;
|
||||
ctxt.lineno = rule->lineno;
|
||||
|
||||
if (mac_parse(match_rule->replacement, dict_pcre_expand,
|
||||
(char *) &ctxt) & MAC_PARSE_ERROR)
|
||||
msg_fatal("pcre map %s, line %d: bad replacement syntax",
|
||||
dict->name, rule->lineno);
|
||||
|
||||
VSTRING_TERMINATE(expansion_buf);
|
||||
return (vstring_str(expansion_buf));
|
||||
VSTRING_TERMINATE(dict_pcre->expansion_buf);
|
||||
return (vstring_str(dict_pcre->expansion_buf));
|
||||
|
||||
/*
|
||||
* Conditional. XXX We provide space for matched substring info
|
||||
@@ -392,6 +397,8 @@ static void dict_pcre_close(DICT *dict)
|
||||
}
|
||||
myfree((char *) rule);
|
||||
}
|
||||
if (dict_pcre->expansion_buf)
|
||||
vstring_free(dict_pcre->expansion_buf);
|
||||
dict_free(dict);
|
||||
}
|
||||
|
||||
@@ -493,12 +500,15 @@ static int dict_pcre_prescan(int type, VSTRING *buf, char *context)
|
||||
DICT_PCRE_PRESCAN_CONTEXT *ctxt = (DICT_PCRE_PRESCAN_CONTEXT *) context;
|
||||
size_t n;
|
||||
|
||||
/*
|
||||
* Keep a copy of literal text (with $$ already replaced by $) if and
|
||||
* only if the replacement text contains no $number expression. This way
|
||||
* we can avoid having to scan the replacement text at lookup time.
|
||||
*/
|
||||
if (type == MAC_PARSE_VARNAME) {
|
||||
if (ctxt->flags & DICT_FLAG_NO_REGSUB) {
|
||||
msg_warn("pcre map %s, line %d: "
|
||||
"regular expression substitution is not allowed",
|
||||
ctxt->mapname, ctxt->lineno);
|
||||
return (MAC_PARSE_ERROR);
|
||||
if (ctxt->literal) {
|
||||
myfree(ctxt->literal);
|
||||
ctxt->literal = 0;
|
||||
}
|
||||
if (!alldig(vstring_str(buf))) {
|
||||
msg_warn("pcre map %s, line %d: non-numeric replacement index \"%s\"",
|
||||
@@ -513,6 +523,11 @@ static int dict_pcre_prescan(int type, VSTRING *buf, char *context)
|
||||
}
|
||||
if (n > ctxt->max_sub)
|
||||
ctxt->max_sub = n;
|
||||
} else if (type == MAC_PARSE_LITERAL && ctxt->max_sub == 0) {
|
||||
if (ctxt->literal)
|
||||
msg_panic("pcre map %s, line %d: multiple literals but no $number",
|
||||
ctxt->mapname, ctxt->lineno);
|
||||
ctxt->literal = mystrdup(vstring_str(buf));
|
||||
}
|
||||
return (MAC_PARSE_OK);
|
||||
}
|
||||
@@ -599,14 +614,23 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno,
|
||||
*/
|
||||
prescan_context.mapname = mapname;
|
||||
prescan_context.lineno = lineno;
|
||||
prescan_context.flags = dict_flags;
|
||||
prescan_context.max_sub = 0;
|
||||
prescan_context.literal = 0;
|
||||
|
||||
/*
|
||||
* The optimizer will eliminate code duplication and/or dead code.
|
||||
*/
|
||||
#define CREATE_MATCHOP_ERROR_RETURN(rval) do { \
|
||||
if (prescan_context.literal) \
|
||||
myfree(prescan_context.literal); \
|
||||
return (rval); \
|
||||
} while (0)
|
||||
|
||||
if (mac_parse(p, dict_pcre_prescan, (char *) &prescan_context)
|
||||
& MAC_PARSE_ERROR) {
|
||||
msg_warn("pcre map %s, line %d: bad replacement syntax: "
|
||||
"skipping this rule", mapname, lineno);
|
||||
return (0);
|
||||
CREATE_MATCHOP_ERROR_RETURN(0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -615,14 +639,20 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno,
|
||||
if (prescan_context.max_sub > 0 && regexp.match == 0) {
|
||||
msg_warn("pcre map %s, line %d: $number found in negative match "
|
||||
"replacement text: skipping this rule", mapname, lineno);
|
||||
return (0);
|
||||
CREATE_MATCHOP_ERROR_RETURN(0);
|
||||
}
|
||||
if (prescan_context.max_sub > 0 && (dict_flags & DICT_FLAG_NO_REGSUB)) {
|
||||
msg_warn("pcre map %s, line %d: "
|
||||
"regular expression substitution is not allowed: "
|
||||
"skipping this rule", mapname, lineno);
|
||||
CREATE_MATCHOP_ERROR_RETURN(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compile the pattern.
|
||||
*/
|
||||
if (dict_pcre_compile(mapname, lineno, ®exp, &engine) == 0)
|
||||
return (0);
|
||||
CREATE_MATCHOP_ERROR_RETURN(0);
|
||||
|
||||
/*
|
||||
* Save the result.
|
||||
@@ -631,7 +661,11 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno,
|
||||
dict_pcre_rule_alloc(DICT_PCRE_OP_MATCH, nesting, lineno,
|
||||
sizeof(DICT_PCRE_MATCH_RULE));
|
||||
match_rule->match = regexp.match;
|
||||
match_rule->replacement = mystrdup(p);
|
||||
match_rule->max_sub = prescan_context.max_sub;
|
||||
if (prescan_context.literal)
|
||||
match_rule->replacement = prescan_context.literal;
|
||||
else
|
||||
match_rule->replacement = mystrdup(p);
|
||||
match_rule->pattern = engine.pattern;
|
||||
match_rule->hints = engine.hints;
|
||||
return ((DICT_PCRE_RULE *) match_rule);
|
||||
@@ -747,6 +781,7 @@ DICT *dict_pcre_open(const char *mapname, int unused_flags, int dict_flags)
|
||||
dict_pcre->dict.close = dict_pcre_close;
|
||||
dict_pcre->dict.flags = dict_flags | DICT_FLAG_PATTERN;
|
||||
dict_pcre->head = 0;
|
||||
dict_pcre->expansion_buf = 0;
|
||||
|
||||
if (dict_pcre_init == 0) {
|
||||
pcre_malloc = (void *(*) (size_t)) mymalloc;
|
||||
|
@@ -110,6 +110,7 @@ typedef struct {
|
||||
DICT dict; /* generic members */
|
||||
regmatch_t *pmatch; /* matched substring info */
|
||||
DICT_REGEXP_RULE *head; /* first rule */
|
||||
VSTRING *expansion_buf; /* lookup result */
|
||||
} DICT_REGEXP;
|
||||
|
||||
/*
|
||||
@@ -122,10 +123,9 @@ typedef struct {
|
||||
* Context for $number expansion callback.
|
||||
*/
|
||||
typedef struct {
|
||||
DICT_REGEXP *dict_regexp; /* the dictionary entry */
|
||||
DICT_REGEXP *dict_regexp; /* the dictionary handle */
|
||||
DICT_REGEXP_MATCH_RULE *match_rule; /* the rule we matched */
|
||||
const char *lookup_string; /* matched text */
|
||||
VSTRING *expansion_buf; /* buffer for $number expansion */
|
||||
} DICT_REGEXP_EXPAND_CONTEXT;
|
||||
|
||||
/*
|
||||
@@ -135,6 +135,7 @@ typedef struct {
|
||||
const char *mapname; /* name of regexp map */
|
||||
int lineno; /* where in file */
|
||||
size_t max_sub; /* largest $number seen */
|
||||
char *literal; /* constant result, $$ -> $ */
|
||||
} DICT_REGEXP_PRESCAN_CONTEXT;
|
||||
|
||||
/*
|
||||
@@ -168,7 +169,7 @@ static int dict_regexp_expand(int type, VSTRING *buf, char *ptr)
|
||||
pmatch = dict_regexp->pmatch + n;
|
||||
if (pmatch->rm_so < 0 || pmatch->rm_so == pmatch->rm_eo)
|
||||
return (MAC_PARSE_UNDEF); /* empty or not matched */
|
||||
vstring_strncat(ctxt->expansion_buf,
|
||||
vstring_strncat(dict_regexp->expansion_buf,
|
||||
ctxt->lookup_string + pmatch->rm_so,
|
||||
pmatch->rm_eo - pmatch->rm_so);
|
||||
return (MAC_PARSE_OK);
|
||||
@@ -178,7 +179,7 @@ static int dict_regexp_expand(int type, VSTRING *buf, char *ptr)
|
||||
* Straight text - duplicate with no substitution.
|
||||
*/
|
||||
else {
|
||||
vstring_strcat(ctxt->expansion_buf, vstring_str(buf));
|
||||
vstring_strcat(dict_regexp->expansion_buf, vstring_str(buf));
|
||||
return (MAC_PARSE_OK);
|
||||
}
|
||||
}
|
||||
@@ -212,7 +213,6 @@ static const char *dict_regexp_lookup(DICT *dict, const char *lookup_string)
|
||||
DICT_REGEXP_IF_RULE *if_rule;
|
||||
DICT_REGEXP_MATCH_RULE *match_rule;
|
||||
DICT_REGEXP_EXPAND_CONTEXT expand_context;
|
||||
static VSTRING *expansion_buf;
|
||||
int error;
|
||||
int nesting = 0;
|
||||
|
||||
@@ -256,7 +256,8 @@ static const char *dict_regexp_lookup(DICT *dict, const char *lookup_string)
|
||||
|
||||
/*
|
||||
* Skip $number substitutions when the replacement text contains
|
||||
* no $number strings (as learned during the pre-scan).
|
||||
* no $number strings, as learned during the compile time
|
||||
* pre-scan. The pre-scan already replaced $$ by $.
|
||||
*/
|
||||
if (match_rule->max_sub == 0)
|
||||
return (match_rule->replacement);
|
||||
@@ -267,10 +268,9 @@ static const char *dict_regexp_lookup(DICT *dict, const char *lookup_string)
|
||||
* expansion errors at this point mean something impossible has
|
||||
* happened.
|
||||
*/
|
||||
if (!expansion_buf)
|
||||
expansion_buf = vstring_alloc(10);
|
||||
VSTRING_RESET(expansion_buf);
|
||||
expand_context.expansion_buf = expansion_buf;
|
||||
if (!dict_regexp->expansion_buf)
|
||||
dict_regexp->expansion_buf = vstring_alloc(10);
|
||||
VSTRING_RESET(dict_regexp->expansion_buf);
|
||||
expand_context.lookup_string = lookup_string;
|
||||
expand_context.match_rule = match_rule;
|
||||
expand_context.dict_regexp = dict_regexp;
|
||||
@@ -279,8 +279,8 @@ static const char *dict_regexp_lookup(DICT *dict, const char *lookup_string)
|
||||
(char *) &expand_context) & MAC_PARSE_ERROR)
|
||||
msg_panic("regexp map %s, line %d: bad replacement syntax",
|
||||
dict->name, rule->lineno);
|
||||
VSTRING_TERMINATE(expansion_buf);
|
||||
return (vstring_str(expansion_buf));
|
||||
VSTRING_TERMINATE(dict_regexp->expansion_buf);
|
||||
return (vstring_str(dict_regexp->expansion_buf));
|
||||
|
||||
/*
|
||||
* Conditional.
|
||||
@@ -349,6 +349,8 @@ static void dict_regexp_close(DICT *dict)
|
||||
}
|
||||
if (dict_regexp->pmatch)
|
||||
myfree((char *) dict_regexp->pmatch);
|
||||
if (dict_regexp->expansion_buf)
|
||||
vstring_free(dict_regexp->expansion_buf);
|
||||
dict_free(dict);
|
||||
}
|
||||
|
||||
@@ -467,15 +469,34 @@ static int dict_regexp_prescan(int type, VSTRING *buf, char *context)
|
||||
DICT_REGEXP_PRESCAN_CONTEXT *ctxt = (DICT_REGEXP_PRESCAN_CONTEXT *) context;
|
||||
size_t n;
|
||||
|
||||
/*
|
||||
* Keep a copy of literal text (with $$ already replaced by $) if and
|
||||
* only if the replacement text contains no $number expression. This way
|
||||
* we can avoid having to scan the replacement text at lookup time.
|
||||
*/
|
||||
if (type == MAC_PARSE_VARNAME) {
|
||||
if (ctxt->literal) {
|
||||
myfree(ctxt->literal);
|
||||
ctxt->literal = 0;
|
||||
}
|
||||
if (!alldig(vstring_str(buf))) {
|
||||
msg_warn("regexp map %s, line %d: non-numeric replacement index \"%s\"",
|
||||
ctxt->mapname, ctxt->lineno, vstring_str(buf));
|
||||
return (MAC_PARSE_ERROR);
|
||||
}
|
||||
n = atoi(vstring_str(buf));
|
||||
if (n < 1) {
|
||||
msg_warn("regexp map %s, line %d: out-of-range replacement index \"%s\"",
|
||||
ctxt->mapname, ctxt->lineno, vstring_str(buf));
|
||||
return (MAC_PARSE_ERROR);
|
||||
}
|
||||
if (n > ctxt->max_sub)
|
||||
ctxt->max_sub = n;
|
||||
} else if (type == MAC_PARSE_LITERAL && ctxt->max_sub == 0) {
|
||||
if (ctxt->literal)
|
||||
msg_panic("regexp map %s, line %d: multiple literals but no $number",
|
||||
ctxt->mapname, ctxt->lineno);
|
||||
ctxt->literal = mystrdup(vstring_str(buf));
|
||||
}
|
||||
return (MAC_PARSE_OK);
|
||||
}
|
||||
@@ -532,7 +553,7 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno,
|
||||
DICT_REGEXP_PATTERN first_pat;
|
||||
DICT_REGEXP_PATTERN second_pat;
|
||||
DICT_REGEXP_PRESCAN_CONTEXT prescan_context;
|
||||
regex_t *first_exp;
|
||||
regex_t *first_exp = 0;
|
||||
regex_t *second_exp;
|
||||
DICT_REGEXP_MATCH_RULE *match_rule;
|
||||
|
||||
@@ -563,12 +584,26 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno,
|
||||
prescan_context.mapname = mapname;
|
||||
prescan_context.lineno = lineno;
|
||||
prescan_context.max_sub = 0;
|
||||
prescan_context.literal = 0;
|
||||
|
||||
/*
|
||||
* The optimizer will eliminate code duplication and/or dead code.
|
||||
*/
|
||||
#define CREATE_MATCHOP_ERROR_RETURN(rval) do { \
|
||||
if (first_exp) { \
|
||||
regfree(first_exp); \
|
||||
myfree((char *) first_exp); \
|
||||
} \
|
||||
if (prescan_context.literal) \
|
||||
myfree(prescan_context.literal); \
|
||||
return (rval); \
|
||||
} while (0)
|
||||
|
||||
if (mac_parse(p, dict_regexp_prescan, (char *) &prescan_context)
|
||||
& MAC_PARSE_ERROR) {
|
||||
msg_warn("regexp map %s, line %d: bad replacement syntax: "
|
||||
"skipping this rule", mapname, lineno);
|
||||
return (0);
|
||||
CREATE_MATCHOP_ERROR_RETURN(0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -577,36 +612,33 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno,
|
||||
* result string, or when the highest numbered substring is less than
|
||||
* the total number of () subpatterns.
|
||||
*/
|
||||
#define FREE_EXPR_AND_RETURN(expr, rval) \
|
||||
{ regfree(expr); myfree((char *) (expr)); return (rval); }
|
||||
|
||||
if (prescan_context.max_sub == 0 || first_pat.match == 0) {
|
||||
if (prescan_context.max_sub == 0)
|
||||
first_pat.options |= REG_NOSUB;
|
||||
} else if (dict_flags & DICT_FLAG_NO_REGSUB) {
|
||||
if (prescan_context.max_sub > 0 && first_pat.match == 0) {
|
||||
msg_warn("regexp map %s, line %d: $number found in negative match "
|
||||
"replacement text: skipping this rule", mapname, lineno);
|
||||
CREATE_MATCHOP_ERROR_RETURN(0);
|
||||
}
|
||||
if (prescan_context.max_sub > 0 && (dict_flags & DICT_FLAG_NO_REGSUB)) {
|
||||
msg_warn("regexp map %s, line %d: "
|
||||
"regular expression substitution is not allowed: "
|
||||
"skipping this rule", mapname, lineno);
|
||||
return (0);
|
||||
CREATE_MATCHOP_ERROR_RETURN(0);
|
||||
}
|
||||
if ((first_exp = dict_regexp_compile_pat(mapname, lineno,
|
||||
&first_pat)) == 0)
|
||||
return (0);
|
||||
if (prescan_context.max_sub > 0 && first_pat.match == 0) {
|
||||
msg_warn("regexp map %s, line %d: $number found in negative match replacement text: "
|
||||
"skipping this rule", mapname, lineno);
|
||||
FREE_EXPR_AND_RETURN(first_exp, 0);
|
||||
}
|
||||
CREATE_MATCHOP_ERROR_RETURN(0);
|
||||
if (prescan_context.max_sub > first_exp->re_nsub) {
|
||||
msg_warn("regexp map %s, line %d: out of range replacement index \"%d\": "
|
||||
"skipping this rule", mapname, lineno,
|
||||
(int) prescan_context.max_sub);
|
||||
FREE_EXPR_AND_RETURN(first_exp, 0);
|
||||
CREATE_MATCHOP_ERROR_RETURN(0);
|
||||
}
|
||||
if (second_pat.regexp != 0) {
|
||||
second_pat.options |= REG_NOSUB;
|
||||
if ((second_exp = dict_regexp_compile_pat(mapname, lineno,
|
||||
&second_pat)) == 0)
|
||||
FREE_EXPR_AND_RETURN(first_exp, 0);
|
||||
CREATE_MATCHOP_ERROR_RETURN(0);
|
||||
} else {
|
||||
second_exp = 0;
|
||||
}
|
||||
@@ -615,11 +647,13 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno,
|
||||
sizeof(DICT_REGEXP_MATCH_RULE));
|
||||
match_rule->first_exp = first_exp;
|
||||
match_rule->first_match = first_pat.match;
|
||||
match_rule->max_sub =
|
||||
(prescan_context.max_sub > 0 ? prescan_context.max_sub + 1 : 0);
|
||||
match_rule->max_sub = prescan_context.max_sub;
|
||||
match_rule->second_exp = second_exp;
|
||||
match_rule->second_match = second_pat.match;
|
||||
match_rule->replacement = mystrdup(p);
|
||||
if (prescan_context.literal)
|
||||
match_rule->replacement = prescan_context.literal;
|
||||
else
|
||||
match_rule->replacement = mystrdup(p);
|
||||
return ((DICT_REGEXP_RULE *) match_rule);
|
||||
}
|
||||
|
||||
@@ -706,6 +740,7 @@ DICT *dict_regexp_open(const char *mapname, int unused_flags, int dict_flags)
|
||||
dict_regexp->dict.flags = dict_flags | DICT_FLAG_PATTERN;
|
||||
dict_regexp->head = 0;
|
||||
dict_regexp->pmatch = 0;
|
||||
dict_regexp->expansion_buf = 0;
|
||||
|
||||
/*
|
||||
* Parse the regexp table.
|
||||
|
@@ -4,20 +4,37 @@
|
||||
./dict_open: warning: regexp map dict_regexp.map, line 10: out of range replacement index "5": skipping this rule
|
||||
./dict_open: warning: regexp map dict_regexp.map, line 17: $number found in negative match replacement text: skipping this rule
|
||||
./dict_open: warning: regexp map dict_regexp.map, line 22: no regexp: skipping this rule
|
||||
> get true
|
||||
true: not found
|
||||
> get true1
|
||||
true1=1
|
||||
> get true2
|
||||
true2: not found
|
||||
> get truefalse2
|
||||
truefalse2=2
|
||||
> get 3
|
||||
3: not found
|
||||
> get true3
|
||||
true3=3
|
||||
> get c
|
||||
c=
|
||||
> get d
|
||||
d: not found
|
||||
> get ab
|
||||
ab: not found
|
||||
> get aa
|
||||
aa=a!b
|
||||
> get 1235
|
||||
1235=(1)(2)(3)
|
||||
> get 1234
|
||||
1234=(1)(2)(3)(4)
|
||||
> get 123
|
||||
123=(1)(2)(3)
|
||||
> get bar/find
|
||||
bar/find: not found
|
||||
> get bar/whynot
|
||||
bar/whynot=Don't have a liquor license
|
||||
> get bar/elbereth
|
||||
bar/elbereth=(elbereth)
|
||||
> get say/elbereth
|
||||
say/elbereth: not found
|
||||
|
@@ -550,6 +550,7 @@ int sockaddr_to_hostaddr(const struct sockaddr * sa, SOCKADDR_SIZE salen,
|
||||
if (hostaddr != 0) {
|
||||
if (inet_ntop(AF_INET, (void *) &(SOCK_ADDR_IN_ADDR(sa)),
|
||||
hostaddr->buf, sizeof(hostaddr->buf)) == 0)
|
||||
errno = ENOSPC;
|
||||
return (EAI_SYSTEM);
|
||||
}
|
||||
if (portnum != 0) {
|
||||
|
@@ -300,7 +300,7 @@ XSASL_CLIENT *xsasl_cyrus_client_create(XSASL_CLIENT_IMPL *unused_impl,
|
||||
int sasl_status;
|
||||
|
||||
/*
|
||||
* The optimizer will eliminate duplication and/or dead code.
|
||||
* The optimizer will eliminate code duplication and/or dead code.
|
||||
*/
|
||||
#define XSASL_CYRUS_CLIENT_CREATE_ERROR_RETURN(x) \
|
||||
do { \
|
||||
|
@@ -262,7 +262,7 @@ static XSASL_SERVER *xsasl_cyrus_server_create(XSASL_SERVER_IMPL *unused_impl,
|
||||
myname, service, realm ? realm : "(null)");
|
||||
|
||||
/*
|
||||
* The optimizer will eliminate duplication and/or dead code.
|
||||
* The optimizer will eliminate code duplication and/or dead code.
|
||||
*/
|
||||
#define XSASL_CYRUS_SERVER_CREATE_ERROR_RETURN(x) \
|
||||
do { \
|
||||
|
Reference in New Issue
Block a user