@@ -137,8 +137,13 @@ private function mail_user_filter_get_rule($page_form) {
137137 $ content = '' ;
138138 $ content .= '### BEGIN FILTER_ID: ' .$ page_form ->id ."\n" ;
139139
140- //$content .= 'require ["fileinto", "regex", "vacation"];'."\n";
141-
140+ if ($ page_form ->dataRecord ["source " ] == 'Header ' ) {
141+ $ parts = explode (': ' ,trim ($ page_form ->dataRecord ["searchterm " ]));
142+ $ page_form ->dataRecord ["source " ] = trim (array_shift ($ parts ));
143+ $ page_form ->dataRecord ["searchterm " ] = trim (implode (': ' ,$ parts ));
144+ unset($ parts );
145+ }
146+
142147 if ($ page_form ->dataRecord ["op " ] == 'domain ' ) {
143148 $ content .= 'if address :domain :is " ' .strtolower ($ page_form ->dataRecord ["source " ]).'" " ' .$ page_form ->dataRecord ["searchterm " ].'" { ' ."\n" ;
144149 } elseif ($ page_form ->dataRecord ["op " ] == 'localpart ' ) {
@@ -152,33 +157,50 @@ private function mail_user_filter_get_rule($page_form) {
152157 $ content .= 'if size :over ' .intval ($ page_form ->dataRecord ["searchterm " ]).$ unit .' { ' ."\n" ;
153158 } else {
154159
155- if ($ page_form ->dataRecord ["source " ] == 'Header ' ) {
156- $ parts = explode (': ' ,trim ($ page_form ->dataRecord ["searchterm " ]));
157- $ page_form ->dataRecord ["source " ] = trim ($ parts [0 ]);
158- unset($ parts [0 ]);
159- $ page_form ->dataRecord ["searchterm " ] = trim (implode (': ' ,$ parts ));
160- unset($ parts );
161- }
160+ $ content .= 'if header :regex " ' .strtolower ($ page_form ->dataRecord ["source " ]).'" [" ' ;
161+
162+ # special chars in sieve regex must be escaped with double-backslash
163+ if ($ page_form ->dataRecord ["op " ] == 'regex ' ) {
164+ # if providing a regex, special chars must already be quoted as intended;
165+ # we will simply try to check for an obviously unquoted double-quote and handle that.
166+ $ patterns = array ( '/([^ \\\\]{2})"/ ' , '/([^ \\\\]) \\\\"/ ' );
167+ $ replace = array ( '${1} \\\\\\\\" ' , '${1} \\\\\\\\" ' );
168+ $ searchterm = preg_replace ( $ patterns , $ replace , $ page_form ->dataRecord ["searchterm " ] );
169+ } else {
170+ $ sieve_regex_escape = array (
171+ '\\' => '\\\\\\' ,
172+ '+ ' => '\\\\+ ' ,
173+ '* ' => '\\\\* ' ,
174+ '? ' => '\\\\? ' ,
175+ '[ ' => '\\\\[ ' ,
176+ '^ ' => '\\\\^ ' ,
177+ '] ' => '\\\\] ' ,
178+ '$ ' => '\\\\$ ' ,
179+ '( ' => '\\\\( ' ,
180+ ') ' => '\\\\) ' ,
181+ '{ ' => '\\\\{ ' ,
182+ '} ' => '\\\\} ' ,
183+ '| ' => '\\\\| ' ,
184+ '. ' => '\\\\. ' ,
185+ # these (from preg_quote) should not be needed
186+ #'=' => '\\\\=',
187+ #'!' => '\\\\!',
188+ #'<' => '\\\\<',
189+ #'>' => '\\\\>',
190+ #':' => '\\\\:',
191+ #'-' => '\\\\-',
192+ #'#' => '\\\\#',
193+ );
194+ $ searchterm = strtr ( $ page_form ->dataRecord ["searchterm " ], $ sieve_regex_escape );
162195
163- $ content .= 'if header :regex [" ' .strtolower ($ page_form ->dataRecord ["source " ]).'"] [" ' ;
164-
165- $ searchterm = preg_quote ($ page_form ->dataRecord ["searchterm " ]);
166- $ searchterm = str_replace (
167- array (
168- '" ' ,
169- '\\[ ' ,
170- '\\] '
171- ),
172- array (
173- '\\" ' ,
174- '\\\\[ ' ,
175- '\\\\] '
176- ), $ searchterm );
196+ }
177197
178198 if ($ page_form ->dataRecord ["op " ] == 'contains ' ) {
179199 $ content .= ".* " .$ searchterm ;
180200 } elseif ($ page_form ->dataRecord ["op " ] == 'is ' ) {
181201 $ content .= "^ " .$ searchterm ."$ " ;
202+ } elseif ($ page_form ->dataRecord ["op " ] == 'regex ' ) {
203+ $ content .= $ searchterm ;
182204 } elseif ($ page_form ->dataRecord ["op " ] == 'begins ' ) {
183205 $ content .= "^ " .$ searchterm ."" ;
184206 } elseif ($ page_form ->dataRecord ["op " ] == 'ends ' ) {
0 commit comments