Index: lib/Mail/SpamAssassin/Conf.pm =================================================================== --- lib/Mail/SpamAssassin/Conf.pm (revision 592615) +++ lib/Mail/SpamAssassin/Conf.pm (working copy) @@ -54,13 +54,14 @@ B if the C<#> character is to be used as part of a rule or configuration option, it must be escaped with a backslash. i.e.: C<\#> -Whitespace in the files is not significant, but please note that starting a -line with whitespace is deprecated, as we reserve its use for multi-line rule -definitions, at some point in the future. +Whitespace in the files is not significant. Multi-line settings are +supported via putting a C<\> at the very end of a line; the next +non-empty line (a line containing something other than whitespace) +will be added to the end of the continued line, with the continuing +line's leading whitespace stripped. The continuing line can also end +in a C<\>, in which case it too will be continued by the next +non-empty line. -Currently, each rule or configuration setting must fit on one-line; multi-line -settings are not supported yet. - File and directory paths can use C<~> to refer to the user's home directory, but no other shell-style path extensions such as globing or C<~user/> are supported. Index: lib/Mail/SpamAssassin/Conf/Parser.pm =================================================================== --- lib/Mail/SpamAssassin/Conf/Parser.pm (revision 592615) +++ lib/Mail/SpamAssassin/Conf/Parser.pm (working copy) @@ -249,6 +249,36 @@ while (defined ($line = shift @conf_lines)) { local ($1); # bug 3838: prevent random taint flagging of $1 + # Line continuation via having a '\' at the end of a line; leading + # whitespace of continuing line is ignored. Empty lines are + # discarded, with the first non-empty line following the continued + # line being used to continue it, but comments are not discarded. + while ($line =~ /\\$/) { + my $cont; + unless (defined ($cont = shift @conf_lines)) { + die "config: line '$line' in file $self->{currentfile} ends in \\, " . + "but is last element in \@conf_lines"; + } + + next if ($cont =~ /^\s*$/); + $line =~ s/\\$//; + + if ($cont =~ /^file start /) { + $cont =~ s/^file start //; + die "config: line '$line' in file $self->{currentfile} ends in \\ " . + "and continues into the start of file $cont; impossible."; + } + elsif ($cont =~ /^file end /) { + warn "config: line '$line' in file $self->{currentfile} ends in \\, " . + "but is last line in the file"; + unshift(@conf_lines, $cont); + unshift(@conf_lines, ""); + last; + } + $cont =~ s/^\s*//g; + $line .= $cont; + } + # bug 5545: used to support testing rules in the ruleqa system if ($keepmetadata && $line =~ /^\#testrules/) { $self->{file_scoped_attrs}->{testrules}++;