Escape regexp characters in patterns unless specifically requested otherwise
authorJamie Cameron <jcameron@webmin.com>
Tue, 29 Mar 2011 21:08:33 +0000 (14:08 -0700)
committerJamie Cameron <jcameron@webmin.com>
Tue, 29 Mar 2011 21:08:33 +0000 (14:08 -0700)
https://www.virtualmin.com/node/17692

filter/CHANGELOG
filter/edit.cgi
filter/filter-lib.pl
filter/lang/en
filter/save.cgi

index a64f716..83d3bd1 100644 (file)
@@ -32,3 +32,4 @@ Quick autoreply and forward setup pages now only show un-conditional rules.
 Added option to select the character set of automatic reply messages.
 ---- Changes since 1.460 ----
 Added a checkbox (on by default) to not forward bounce emails, which can cause mail loops.
+Text for rules that match on headers is now automatically escaped unless the new "Regular expression" box is checked, which makes creation of simple substring matching rules easier for users.
index fefc3e5..ed9f017 100755 (executable)
@@ -72,6 +72,22 @@ elsif ($filter->{'condvalue'} =~ /^(.*)\.\*$/ ||
        $condvalue = $1;
        $condmode = 0;
        }
+if ($condvalue =~ /^[a-zA-Z0-9_ ]*$/) {
+       # Contains no special chars, so not a regexp
+       $regexp = 0;
+       }
+else {
+       # Has special chars .. but if they are all escaped, then not a regexp
+       $condre = $condvalue;
+       $condre =~ s/\\./x/g;
+       if ($condre =~ /^[a-zA-Z0-9_ ]*$/) {
+               $condvalue =~ s/\\(.)/$1/g;
+               $regexp = 0;
+               }
+       else {
+               $regexp = 1;
+               }
+       }
 print &ui_table_row(
        &ui_oneradio("cmode", 4, $text{'edit_cmode4'}, $cmode == 4),
        &text('edit_cheader2',
@@ -89,7 +105,8 @@ print &ui_table_row(
                           [ 1, $text{'edit_modecont'} ],
                           [ 2, $text{'edit_modeend'} ] ]),
              &ui_textbox("condvalue", $condvalue, 40, 0, undef,
-                         "onFocus='form.cmode[3].checked = true'")),
+                         "onFocus='form.cmode[3].checked = true'")." ".
+             &ui_checkbox("condregexp", 1, $text{'edit_regexp'}, $regexp)),
        undef, \@tds);
 
 # Smaller
index 944d702..6d86968 100755 (executable)
@@ -502,19 +502,19 @@ elsif ($f->{'condheader'}) {
        if ($f->{'condvalue'} =~ /^\.\*(.*)\$$/) {
                $cond = &text('index_cheader2',
                        "<tt>".&html_escape($f->{'condheader'})."</tt>",
-                       "<tt>".&html_escape($1)."</tt>");
+                       "<tt>".&html_escape(&prettify_regexp("$1"))."</tt>");
                }
        elsif ($f->{'condvalue'} =~ /^\.\*(.*)\.\*$/ ||
               $f->{'condvalue'} =~ /^\.\*(.*)$/) {
                $cond = &text('index_cheader1',
                        "<tt>".&html_escape($f->{'condheader'})."</tt>",
-                       "<tt>".&html_escape($1)."</tt>");
+                       "<tt>".&html_escape(&prettify_regexp("$1"))."</tt>");
                }
        elsif ($f->{'condvalue'} =~ /^(.*)\.\*$/ ||
               $f->{'condvalue'} =~ /^(.*)$/) {
                $cond = &text('index_cheader0',
                        "<tt>".&html_escape($f->{'condheader'})."</tt>",
-                       "<tt>".&html_escape($1)."</tt>");
+                       "<tt>".&html_escape(&prettify_regexp("$1"))."</tt>");
                }
        }
 elsif ($f->{'condtype'} eq '<' || $f->{'condtype'} eq '>') {
@@ -534,6 +534,19 @@ else {
 return wantarray ? ( $cond, $lastalways ) : $cond;
 }
 
+# prettify_regexp(string)
+# If a string contains only \ quoted special characters, remove the \s
+sub prettify_regexp
+{
+my ($str) = @_;
+my $re = $str;
+$re =~ s/\\./x/g;
+if ($re =~ /^[a-zA-Z0-9_ ]*$/) {
+       $str =~ s/\\(.)/$1/g;
+       }
+return $str;
+}
+
 # describe_action(&filter, &folder, [homedir])
 # Returns a human-readable description for the delivery action for some folder
 sub describe_action
index 35bdb08..1b32539 100644 (file)
@@ -15,6 +15,7 @@ index_cheader2=Header $1 must end with $2
 edit_modestart=starts with
 edit_modecont=contains
 edit_modeend=ends with
+edit_regexp=Regular expression?
 index_cre=Headers match $1
 index_cre2=Body matches $1
 index_calways=Always
index bba54c9..8cccb44 100755 (executable)
@@ -49,6 +49,10 @@ else {
                $filter->{'condheader'} = $in{'condmenu'} || $in{'condheader'};
                $filter->{'condheader'} =~ /^[a-zA-Z0-9\-]+$/ ||
                        &error($text{'save_econdheader'});
+               if (!$in{'condregexp'} &&
+                   $in{'condvalue'} !~ /^[a-zA-Z0-9_ ]+$/) {
+                       $in{'condvalue'} = quotemeta($in{'condvalue'});
+                       }
                if ($in{'condmode'} == 0) {
                        $filter->{'condvalue'} = $in{'condvalue'};
                        }