2 # Create, update or delete a filter
4 require './filter-lib.pl';
5 &foreign_require("mailbox", "mailbox-lib.pl");
9 # Find existing filter object
10 &lock_file($procmail::procmailrc);
11 @filters = &list_filters();
13 ($filter) = grep { $_->{'index'} == $in{'idx'} } @filters;
16 $filter = { 'index' => scalar(@filters) };
21 &delete_filter($filter);
24 # Validate and store inputs
25 &error_setup($text{'save_err'});
27 # Parse condition first
28 delete($filter->{'condspam'});
29 delete($filter->{'condlevel'});
30 delete($filter->{'condheader'});
31 delete($filter->{'condtype'});
32 delete($filter->{'cond'});
33 $filter->{'body'} = 0;
34 if ($in{'cmode'} == 0) {
35 # Always enabled, so nothing to set!
37 elsif ($in{'cmode'} == 5) {
38 # Match if spamassassin has set header
39 $filter->{'condspam'} = 1;
41 elsif ($in{'cmode'} == 6) {
43 $in{'condlevel'} =~ /^[1-9]\d*$/ ||
44 &error($text{'save_econdlevel'});
45 $filter->{'condlevel'} = $in{'condlevel'};
47 elsif ($in{'cmode'} == 4) {
49 $filter->{'condheader'} = $in{'condmenu'} || $in{'condheader'};
50 $filter->{'condheader'} =~ /^[a-zA-Z0-9\-]+$/ ||
51 &error($text{'save_econdheader'});
52 if (!$in{'condregexp'} &&
53 $in{'condvalue'} !~ /^[a-zA-Z0-9_ ]+$/) {
54 $in{'condvalue'} = quotemeta($in{'condvalue'});
56 if ($in{'condmode'} == 0) {
57 $filter->{'condvalue'} = $in{'condvalue'};
59 elsif ($in{'condmode'} == 1) {
60 $filter->{'condvalue'} = ".*".$in{'condvalue'}.".*";
63 $filter->{'condvalue'} = ".*".$in{'condvalue'}."\$";
66 elsif ($in{'cmode'} == 3) {
67 # Smaller than some size
68 $in{'condsmall'} =~ /^\d+$/ || &error($text{'save_esmall'});
69 $filter->{'cond'} = $in{'condsmall'}*$in{'condsmall_units'};
70 $filter->{'condtype'} = '<';
72 elsif ($in{'cmode'} == 2) {
73 # Larger than some size
74 $in{'condlarge'} =~ /^\d+$/ || &error($text{'save_elarge'});
75 $filter->{'cond'} = $in{'condlarge'}*$in{'condlarge_units'};
76 $filter->{'condtype'} = '>';
78 elsif ($in{'cmode'} == 1) {
80 $in{'cond'} || &error($text{'save_econd'});
81 $filter->{'cond'} = $in{'cond'};
82 $filter->{'body'} = $in{'body'};
85 # Parse action section
86 delete($filter->{'actionreply'});
87 delete($filter->{'actionspam'});
88 delete($filter->{'actionthrow'});
89 delete($filter->{'actiondefault'});
90 delete($filter->{'actionreply'});
91 delete($filter->{'actiontype'});
92 delete($filter->{'continue'});
93 if ($in{'amode'} == 3) {
95 $filter->{'actiondefault'} = 1;
97 elsif ($in{'amode'} == 5) {
99 $filter->{'actionspam'} = 1;
101 elsif ($in{'amode'} == 4) {
103 $filter->{'actionthrow'} = 1;
105 elsif ($in{'amode'} == 1) {
106 # Forward to an address
107 $in{'forward'} =~ /\S/ || &error($text{'save_eforward'});
108 $in{'forward'} =~ s/^\s+//;
109 $in{'forward'} =~ s/\s+$//;
110 $in{'forward'} =~ s/\s+/,/g;
111 $filter->{'action'} = $in{'forward'};
112 $filter->{'actiontype'} = '!';
113 $filter->{'nobounce'} = $in{'nobounce'};
115 elsif ($in{'amode'} == 0) {
116 # Write to a folder or file
117 @folders = &mailbox::list_folders();
119 $folder = &mailbox::find_named_folder($in{'folder'},
121 $file = $folder->{'file'};
124 $in{'file'} =~ /\S/ || &error($text{'save_efile'});
127 $file =~ s/^\Q$remote_user_info[7]\/\E/\$HOME\//;
128 $filter->{'action'} = $file;
129 if ($folder->{'type'} == 1 ||
130 $folder->{'type'} == 4 && -d $folder->{'file'}) {
131 # Maildir has to end with /
132 $filter->{'action'} .= '/';
135 elsif ($in{'amode'} == 6) {
137 $filter->{'actionreply'} = 1;
138 $in{'reply'} =~ /\S/ || &error($text{'save_ereply'});
139 $in{'reply'} =~ s/\r//g;
140 $filter->{'reply'}->{'autotext'} = $in{'reply'};
141 $filter->{'reply'}->{'from'} =
142 &mailbox::get_preferred_from_address();
143 $idx = defined($filter->{'index'}) ? $filter->{'index'}
145 $filter->{'reply'}->{'autoreply'} ||=
146 "$remote_user_info[7]/autoreply.$idx.txt";
147 if ($config{'reply_force'}) {
149 $min = $config{'reply_min'} || 60;
150 $filter->{'reply'}->{'period'} = $min*60;
151 $filter->{'reply'}->{'replies'} ||=
152 "$user_module_config_directory/replies";
154 elsif ($in{'period_def'}) {
155 # No autoreply period
156 delete($filter->{'reply'}->{'replies'});
157 delete($filter->{'reply'}->{'period'});
160 # Set reply period and tracking file
161 $in{'period'} =~ /^\d+$/ ||
162 &error($text{'save_eperiod'});
163 if ($config{'reply_min'} &&
164 $in{'period'} < $config{'reply_min'}) {
165 &error(&text('save_eperiodmin',
166 $config{'reply_min'}));
168 $filter->{'reply'}->{'period'} = $in{'period'}*60;
169 $filter->{'reply'}->{'replies'} ||=
170 "$user_module_config_directory/replies";
172 # Save autoreply start and end
173 foreach $p ('start', 'end') {
174 local ($s, $m, $h) = $p eq 'start' ? (0, 0, 0) :
177 $tm = timelocal($s, $m, $h, $in{'d'.$p},
178 $in{'m'.$p}-1, $in{'y'.$p}-1900);
179 $tm || &error($text{'save_e'.$p});
180 $filter->{'reply'}->{'autoreply_'.$p} = $tm;
183 delete($filter->{'reply'}->{'autoreply_'.$p});
187 if ($in{'charset_def'}) {
188 delete($filter->{'reply'}->{'charset'});
191 $in{'charset'} =~ /^[a-z0-9\.\-\_]+$/i ||
192 error($text{'save_echarset'});
193 $filter->{'reply'}->{'charset'} = $in{'charset'};
196 elsif ($in{'amode'} == 7) {
197 # Create a new folder for saving (always in Maildir format)
198 $in{'newfolder'} =~ /\S/ || &error($text{'save_enewfolder'});
199 $in{'newfolder'} !~ /^\// && $in{'newfolder'} !~ /\.\./ ||
200 &error($text{'save_enewfolder2'});
201 ($clash) = grep { $_->{'name'} eq $in{'newfolder'} }
203 $clash && &error($text{'save_enewfolder3'});
204 $folder = { 'name' => $in{'newfolder'},
207 &mailbox::save_folder($folder);
208 $filter->{'action'} = $folder->{'file'}."/";
209 $filter->{'action'} =~ s/^\Q$remote_user_info[7]\/\E/\$HOME\//;
211 $filter->{'continue'} = $in{'continue'};
215 &create_filter($filter);
218 &modify_filter($filter);
221 &unlock_file($procmail::procmailrc);