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