line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Net::Sieve::Script; |
2
|
5
|
|
|
5
|
|
267527
|
use strict; |
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
133
|
|
3
|
5
|
|
|
5
|
|
26
|
use warnings; |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
162
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
BEGIN { |
6
|
5
|
|
|
5
|
|
23
|
use Exporter (); |
|
5
|
|
|
|
|
12
|
|
|
5
|
|
|
|
|
99
|
|
7
|
5
|
|
|
5
|
|
24
|
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); |
|
5
|
|
|
|
|
16
|
|
|
5
|
|
|
|
|
479
|
|
8
|
5
|
|
|
5
|
|
16
|
$VERSION = '0.09'; |
9
|
5
|
|
|
|
|
52
|
@ISA = qw(Exporter); |
10
|
|
|
|
|
|
|
#Give a hoot don't pollute, do not export more than needed by default |
11
|
5
|
|
|
|
|
14
|
@EXPORT = qw(_strip); |
12
|
5
|
|
|
|
|
8
|
@EXPORT_OK = qw(_strip); |
13
|
5
|
|
|
|
|
102
|
%EXPORT_TAGS = (); |
14
|
|
|
|
|
|
|
} |
15
|
|
|
|
|
|
|
|
16
|
5
|
|
|
5
|
|
27
|
use base qw(Class::Accessor::Fast); |
|
5
|
|
|
|
|
8
|
|
|
5
|
|
|
|
|
1470
|
|
17
|
5
|
|
|
5
|
|
11672
|
use Net::Sieve::Script::Rule; |
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
22
|
|
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=head1 NAME |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
Net::Sieve::Script - Parse and write sieve scripts |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=head1 SYNOPSIS |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
use Net::Sieve::Script; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
my $test_script = 'require "fileinto"; |
28
|
|
|
|
|
|
|
# Place all these in the "Test" folder |
29
|
|
|
|
|
|
|
if header :contains "Subject" "[Test]" { |
30
|
|
|
|
|
|
|
fileinto "Test"; |
31
|
|
|
|
|
|
|
}'; |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
my $script = Net::Sieve::Script->new ($test_script); |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
print "OK" if ( $script->parsing_ok ) ; |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
print $script->write_script; |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
or |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
my $script = Net::Sieve::Script->new(); |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
my $cond = Net::Sieve::Script::Condition->new('header'); |
44
|
|
|
|
|
|
|
$cond->match_type(':contains'); |
45
|
|
|
|
|
|
|
$cond->header_list('"Subject"'); |
46
|
|
|
|
|
|
|
$cond->key_list('"Re: Test2"'); |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
my $actions = 'fileinto "INBOX.test"; stop;'; |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
my $rule = Net::Sieve::Script::Rule->new(); |
51
|
|
|
|
|
|
|
$rule->add_condition($cond); |
52
|
|
|
|
|
|
|
$rule->add_action($actions); |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
$script->add_rule($rule); |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
print $script->write_script; |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
=head1 DESCRIPTION |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
Manage sieve script |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
Read and parse file script, make L, L, L objects |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
Write sieve script |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
Support RFC 5228 - sieve base |
69
|
|
|
|
|
|
|
RFC 5231 - relationnal |
70
|
|
|
|
|
|
|
RFC 5230 - vacation |
71
|
|
|
|
|
|
|
Draft regex |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
missing |
74
|
|
|
|
|
|
|
5229 variables |
75
|
|
|
|
|
|
|
5232 imapflags |
76
|
|
|
|
|
|
|
5233 subaddress |
77
|
|
|
|
|
|
|
5235 spamtest |
78
|
|
|
|
|
|
|
notify draft |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
=cut |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
__PACKAGE__->mk_accessors(qw(raw rules require max_priority)); |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
=head1 CONSTRUCTOR |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
=head2 new |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
Argument : optional text script |
89
|
|
|
|
|
|
|
Purpose : if param, put script in raw, parse script |
90
|
|
|
|
|
|
|
Return : main Script object |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
Accessors : |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
->raw() : read or set original text script |
95
|
|
|
|
|
|
|
->require() : require part of script |
96
|
|
|
|
|
|
|
->rules() : array of rules |
97
|
|
|
|
|
|
|
->max_priority() : last rule id |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
=cut |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
sub new |
102
|
|
|
|
|
|
|
{ |
103
|
8
|
|
|
8
|
1
|
2330
|
my ($class, $param) = @_; |
104
|
|
|
|
|
|
|
|
105
|
8
|
|
33
|
|
|
45
|
my $self = bless ({}, ref ($class) || $class); |
106
|
8
|
|
|
|
|
22
|
my @LISTS = qw((\[.*?\]|".*?")); |
107
|
|
|
|
|
|
|
|
108
|
8
|
100
|
|
|
|
18
|
if ($param) { |
109
|
2
|
|
|
|
|
9
|
$self->raw($param); |
110
|
2
|
100
|
|
|
|
71
|
$self->require($1) if ( $param =~ m/require @LISTS;/si ); |
111
|
2
|
|
|
|
|
12
|
$self->read_rules(); |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# break if more than 50 rules |
115
|
8
|
50
|
66
|
|
|
27
|
die "50 rules does not sound reasonable !" |
116
|
|
|
|
|
|
|
if ( $self->max_priority() && $self->max_priority() >= 50 ); |
117
|
|
|
|
|
|
|
|
118
|
8
|
|
|
|
|
93
|
return $self; |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
=head1 METHODS |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=head2 parsing_ok |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
return 1 on raw parsing success |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=cut |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
sub parsing_ok |
130
|
|
|
|
|
|
|
{ |
131
|
1
|
|
|
1
|
1
|
4
|
my $self = shift; |
132
|
|
|
|
|
|
|
|
133
|
1
|
|
|
|
|
1
|
return ( $self->_strip eq _strip($self->write_script) ); |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=head2 write_script |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
Purpose : write full script, require and rules parts |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
Return : set current require, |
141
|
|
|
|
|
|
|
return rules ordered by priority in text format |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=cut |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub write_script { |
146
|
7
|
|
|
7
|
1
|
475
|
my $self = shift; |
147
|
7
|
|
|
|
|
9
|
my $text; |
148
|
7
|
|
|
|
|
11
|
my %require = (); |
149
|
|
|
|
|
|
|
|
150
|
7
|
|
|
|
|
10
|
foreach my $rule ( sort { $a->priority() <=> $b->priority() } @{$self->rules()} ) { |
|
17
|
|
|
|
|
76
|
|
|
7
|
|
|
|
|
13
|
|
151
|
16
|
|
|
|
|
62
|
$text .= $rule->write."\n"; |
152
|
16
|
|
|
|
|
103
|
foreach my $req ($rule->require()) { |
153
|
16
|
100
|
|
|
|
86
|
$require{$req->[0]} = 1 if defined $req->[0]; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
#TODO keep original require if current is include, for test parsing |
158
|
7
|
|
|
|
|
12
|
my $require_line; |
159
|
|
|
|
|
|
|
my $count; |
160
|
7
|
|
|
|
|
20
|
foreach my $req (sort keys %require) { |
161
|
9
|
50
|
|
|
|
18
|
next if(!$req); |
162
|
9
|
|
|
|
|
20
|
$require_line .= ', "'.$req.'"'; |
163
|
9
|
|
|
|
|
11
|
$count++; |
164
|
|
|
|
|
|
|
}; |
165
|
7
|
|
|
|
|
25
|
$require_line =~ s/^, //; |
166
|
7
|
100
|
|
|
|
17
|
$require_line = '['.$require_line.']' if ($count > 1); |
167
|
|
|
|
|
|
|
|
168
|
7
|
|
|
|
|
18
|
$self->require($require_line); |
169
|
|
|
|
|
|
|
|
170
|
7
|
50
|
|
|
|
36
|
$require_line = "require $require_line;\n" if $require_line; |
171
|
|
|
|
|
|
|
|
172
|
7
|
|
|
|
|
29
|
return $require_line.$text; |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=head2 equals |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
$object->equals($test_object): return 1 if $object and $test_object are equals |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=cut |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
sub equals { |
182
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
183
|
0
|
|
|
|
|
0
|
my $object = shift; |
184
|
|
|
|
|
|
|
|
185
|
0
|
0
|
|
|
|
0
|
return 0 unless (defined $object); |
186
|
0
|
0
|
|
|
|
0
|
return 0 unless ($object->isa('Net::Sieve::Script')); |
187
|
|
|
|
|
|
|
|
188
|
0
|
|
|
|
|
0
|
my @accessors = qw( require ); |
189
|
|
|
|
|
|
|
|
190
|
0
|
|
|
|
|
0
|
foreach my $accessor ( @accessors ) { |
191
|
0
|
|
|
|
|
0
|
my $myvalue = $self->$accessor; |
192
|
0
|
|
|
|
|
0
|
my $theirvalue = $object->$accessor; |
193
|
0
|
0
|
|
|
|
0
|
if (defined $myvalue) { |
194
|
0
|
0
|
|
|
|
0
|
return 0 unless (defined $theirvalue); |
195
|
0
|
0
|
|
|
|
0
|
return 0 unless ($myvalue eq $theirvalue); |
196
|
|
|
|
|
|
|
} else { |
197
|
0
|
0
|
|
|
|
0
|
return 0 if (defined $theirvalue); |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
|
201
|
0
|
0
|
|
|
|
0
|
if (defined $self->rules) { |
202
|
0
|
|
|
|
|
0
|
my @myrules = sort { $a->priority() <=> $b->priority() } @{$self->rules()}; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
203
|
0
|
|
|
|
|
0
|
my @theirrules = sort { $a->priority() <=> $b->priority() } @{$object->rules()} ; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
204
|
0
|
0
|
|
|
|
0
|
return 0 unless ($#myrules == $#theirrules); |
205
|
|
|
|
|
|
|
|
206
|
0
|
0
|
|
|
|
0
|
unless ($#myrules == -1) { |
207
|
0
|
|
|
|
|
0
|
foreach my $index (0..$#myrules) { |
208
|
0
|
|
|
|
|
0
|
my $myrule = $myrules[$index]; |
209
|
0
|
|
|
|
|
0
|
my $theirrule = $theirrules[$index]; |
210
|
0
|
0
|
|
|
|
0
|
if (defined ($myrule)) { |
211
|
0
|
0
|
|
|
|
0
|
return 0 unless ($myrule->isa( |
212
|
|
|
|
|
|
|
'Net::Sieve::Script::Rule')); |
213
|
0
|
0
|
|
|
|
0
|
return 0 unless ($myrule->equals($theirrule)); |
214
|
|
|
|
|
|
|
} else { |
215
|
0
|
0
|
|
|
|
0
|
return 0 if (defined ($theirrule)); |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
} else { |
221
|
0
|
0
|
|
|
|
0
|
return 0 if (defined ($object->rules)); |
222
|
|
|
|
|
|
|
} |
223
|
0
|
|
|
|
|
0
|
return 1; |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
=head2 read_rules |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
$script->read_rules() : read rules from raw |
230
|
|
|
|
|
|
|
$script->read_rules($some_text) : parse text rules |
231
|
|
|
|
|
|
|
use of read_rules set $script->rules() |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
Return 1 on success |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=cut |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
sub read_rules |
238
|
|
|
|
|
|
|
{ |
239
|
6
|
|
|
6
|
1
|
1604
|
my $self = shift; |
240
|
6
|
|
66
|
|
|
22
|
my $text_rules = shift || $self->raw(); |
241
|
|
|
|
|
|
|
|
242
|
6
|
|
|
|
|
26
|
my @LISTS = qw((\[.*?\]|".*?")); |
243
|
|
|
|
|
|
|
|
244
|
6
|
100
|
|
|
|
92
|
$self->require($1) if ( $text_rules =~ m/require @LISTS;/si ); |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
#read rules from raw or from $text_rules if set |
247
|
6
|
|
|
|
|
34
|
my $script_raw = $self->_strip($text_rules); |
248
|
|
|
|
|
|
|
|
249
|
6
|
|
|
|
|
9
|
my @Rules; |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
# for simple vacation RFC 5230 |
252
|
6
|
100
|
|
|
|
15
|
if ($script_raw =~m/^(vacation .*)$/) { |
253
|
1
|
|
|
|
|
7
|
push @Rules, Net::Sieve::Script::Rule->new(ctrl => 'vacation',block => $1,order =>1) |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
|
256
|
6
|
|
|
|
|
6
|
my $order; |
257
|
6
|
|
|
|
|
34
|
while ($script_raw =~m/(if|else|elsif) (.*?)\{(.*?)}([\s;]?)/isg) { |
258
|
13
|
|
|
|
|
30
|
my $ctrl = lc($1); |
259
|
13
|
|
|
|
|
24
|
my $test_list = $2; |
260
|
13
|
|
|
|
|
24
|
my $block = $3; |
261
|
|
|
|
|
|
|
|
262
|
13
|
|
|
|
|
14
|
++$order; |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
# break if more than 50 rules |
265
|
13
|
50
|
|
|
|
22
|
die "50 rules does not sound reasonable !" |
266
|
|
|
|
|
|
|
if ( $order >= 50 ); |
267
|
|
|
|
|
|
|
|
268
|
13
|
|
|
|
|
31
|
my $pRule = Net::Sieve::Script::Rule->new ( |
269
|
|
|
|
|
|
|
ctrl => $ctrl, |
270
|
|
|
|
|
|
|
test_list => $test_list, |
271
|
|
|
|
|
|
|
block => $block, |
272
|
|
|
|
|
|
|
order => $order |
273
|
|
|
|
|
|
|
); |
274
|
|
|
|
|
|
|
|
275
|
13
|
|
|
|
|
91
|
push @Rules, $pRule; |
276
|
|
|
|
|
|
|
}; |
277
|
|
|
|
|
|
|
|
278
|
6
|
|
|
|
|
25
|
$self->rules(\@Rules); |
279
|
6
|
|
|
|
|
73
|
$self->max_priority($order); |
280
|
|
|
|
|
|
|
|
281
|
6
|
|
|
|
|
31
|
return 1; |
282
|
|
|
|
|
|
|
} |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
=head2 find_rule |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
Return L pointer find by priority |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
Return 0 on error, 1 on not find |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
=cut |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
sub find_rule |
293
|
|
|
|
|
|
|
{ |
294
|
13
|
|
|
13
|
1
|
277
|
my $self = shift; |
295
|
13
|
|
|
|
|
11
|
my $priority = shift; |
296
|
13
|
100
|
100
|
|
|
22
|
return 0 if $priority > $self->max_priority || $priority <= 0; |
297
|
11
|
50
|
|
|
|
64
|
return 0 if not defined $self->rules; |
298
|
|
|
|
|
|
|
|
299
|
11
|
|
|
|
|
36
|
foreach my $rule (@{$self->rules}) { |
|
11
|
|
|
|
|
15
|
|
300
|
28
|
100
|
|
|
|
87
|
return $rule if ($rule->priority == $priority ); |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
|
303
|
0
|
|
|
|
|
0
|
return 1; |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
=head2 swap_rules |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
Swap priorities, |
309
|
|
|
|
|
|
|
now don't take care of if/else/elsif |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
Return 1 on success, 0 on error |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
=cut |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
sub swap_rules |
316
|
|
|
|
|
|
|
{ |
317
|
4
|
|
|
4
|
1
|
8
|
my $self = shift; |
318
|
4
|
|
|
|
|
5
|
my $swap1 = shift; |
319
|
4
|
|
|
|
|
6
|
my $swap2 = shift; |
320
|
|
|
|
|
|
|
|
321
|
4
|
100
|
|
|
|
12
|
return 0 if $swap1 == $swap2; |
322
|
|
|
|
|
|
|
|
323
|
3
|
|
|
|
|
7
|
my $pr1 = $self->find_rule($swap1); |
324
|
3
|
|
|
|
|
14
|
my $pr2 = $self->find_rule($swap2); |
325
|
|
|
|
|
|
|
|
326
|
3
|
100
|
|
|
|
17
|
return 0 if ref($pr1) ne 'Net::Sieve::Script::Rule'; |
327
|
2
|
100
|
|
|
|
7
|
return 0 if ref($pr2) ne 'Net::Sieve::Script::Rule'; |
328
|
|
|
|
|
|
|
|
329
|
1
|
|
|
|
|
2
|
my $mem_pr2 = $pr2->priority(); |
330
|
1
|
|
|
|
|
5
|
$pr2->priority($pr1->priority()); |
331
|
1
|
|
|
|
|
37
|
$pr1->priority($mem_pr2); |
332
|
|
|
|
|
|
|
|
333
|
1
|
|
|
|
|
7
|
return 1; |
334
|
|
|
|
|
|
|
} |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
=head2 reorder_rules |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
Reorder rules with a list of number, start with 1, and with blanck separator. Useful for ajax sort functions. |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
Thank you jeanne for your help in brain storming. |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
Return 1 on success, 0 on error |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
=cut |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
sub reorder_rules |
347
|
|
|
|
|
|
|
{ |
348
|
5
|
|
|
5
|
1
|
233
|
my $self = shift; |
349
|
5
|
|
|
|
|
8
|
my $list = shift; |
350
|
|
|
|
|
|
|
|
351
|
5
|
100
|
|
|
|
15
|
return 0 if ( ! $list ); |
352
|
|
|
|
|
|
|
|
353
|
4
|
|
|
|
|
14
|
my @swap = split ' ',$list; |
354
|
|
|
|
|
|
|
|
355
|
4
|
50
|
|
|
|
12
|
return 0 if ( ! scalar @swap ); |
356
|
4
|
100
|
|
|
|
10
|
return 0 if ( scalar @swap != $self->max_priority ); |
357
|
|
|
|
|
|
|
|
358
|
1
|
|
|
|
|
5
|
my @new_ordered_rules; |
359
|
1
|
|
|
|
|
2
|
foreach my $swap ( @swap ) { |
360
|
4
|
50
|
|
|
|
11
|
if ($swap =~ m/\d+/) { |
361
|
4
|
|
|
|
|
8
|
my $rule = $self->find_rule($swap); |
362
|
4
|
|
|
|
|
17
|
push @new_ordered_rules, $rule; |
363
|
|
|
|
|
|
|
} |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
|
366
|
1
|
|
|
|
|
2
|
my $i=1; |
367
|
1
|
|
|
|
|
2
|
foreach my $rule (@new_ordered_rules) { |
368
|
4
|
|
|
|
|
6
|
$rule->priority($i); |
369
|
4
|
|
|
|
|
14
|
$i++; |
370
|
|
|
|
|
|
|
}; |
371
|
|
|
|
|
|
|
|
372
|
1
|
|
|
|
|
4
|
return 1; |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
=head2 delete_rule |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
Delete rule and change priority, delete rule take care for 'if' test |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
if deleted is 'if' |
380
|
|
|
|
|
|
|
delete next if next is 'else' |
381
|
|
|
|
|
|
|
change next in 'if' next is 'elsif' |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
Return : 1 on success, 0 on error |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
=cut |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
sub delete_rule |
388
|
|
|
|
|
|
|
{ |
389
|
9
|
|
|
9
|
1
|
1608
|
my $self = shift; |
390
|
9
|
|
|
|
|
12
|
my $id = shift; |
391
|
9
|
|
|
|
|
13
|
my $deleted = 0; |
392
|
9
|
50
|
|
|
|
20
|
my @Rules = defined $self->rules?@{$self->rules}:(); |
|
9
|
|
|
|
|
47
|
|
393
|
9
|
|
|
|
|
38
|
my @NewRules = (); |
394
|
9
|
|
|
|
|
12
|
my $order = 0; |
395
|
|
|
|
|
|
|
|
396
|
9
|
|
|
|
|
24
|
for ( my $i = 0; $i < scalar(@Rules); $i++ ) { |
397
|
27
|
|
|
|
|
56
|
my $rule = $Rules[$i]; |
398
|
27
|
|
|
|
|
33
|
my $next=$i+1; |
399
|
27
|
100
|
|
|
|
45
|
if ($rule->priority == $id) { |
400
|
8
|
|
|
|
|
30
|
$deleted = 1; |
401
|
8
|
100
|
100
|
|
|
28
|
if ( defined $Rules[$next] && $rule->alternate eq 'if') { |
402
|
6
|
100
|
|
|
|
41
|
$Rules[$next]->alternate('if') |
403
|
|
|
|
|
|
|
if ($Rules[$next]->alternate eq 'elsif' ); |
404
|
|
|
|
|
|
|
|
405
|
6
|
100
|
|
|
|
37
|
if ($Rules[$next]->alternate eq 'else' ) { |
406
|
2
|
|
|
|
|
11
|
$i++; |
407
|
2
|
|
|
|
|
7
|
$rule = $Rules[$i]; |
408
|
|
|
|
|
|
|
} |
409
|
|
|
|
|
|
|
} |
410
|
|
|
|
|
|
|
} |
411
|
|
|
|
|
|
|
else { |
412
|
19
|
|
|
|
|
69
|
++$order; |
413
|
19
|
|
|
|
|
34
|
$rule->priority($order); |
414
|
19
|
|
|
|
|
102
|
push @NewRules, $rule; |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
} |
417
|
|
|
|
|
|
|
|
418
|
9
|
|
|
|
|
26
|
$self->max_priority($order); |
419
|
9
|
|
|
|
|
49
|
$self->rules(\@NewRules); |
420
|
|
|
|
|
|
|
|
421
|
9
|
|
|
|
|
73
|
return $deleted; |
422
|
|
|
|
|
|
|
} |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
=head2 add_rule |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
Purpose : add a rule in end of script |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
Return : priority on success, 0 on error |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
Argument : Net::Sieve::Script::Rule object |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
=cut |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
sub add_rule |
435
|
|
|
|
|
|
|
{ |
436
|
18
|
|
|
18
|
1
|
510
|
my $self = shift; |
437
|
18
|
|
|
|
|
21
|
my $rule = shift; |
438
|
|
|
|
|
|
|
|
439
|
18
|
100
|
|
|
|
43
|
return 0 if ref($rule) ne 'Net::Sieve::Script::Rule'; |
440
|
|
|
|
|
|
|
|
441
|
17
|
|
|
|
|
33
|
my $order = $self->max_priority(); |
442
|
17
|
100
|
|
|
|
73
|
my @Rules = defined $self->rules?@{$self->rules}:(); |
|
13
|
|
|
|
|
53
|
|
443
|
|
|
|
|
|
|
|
444
|
17
|
|
|
|
|
68
|
++$order; |
445
|
17
|
|
|
|
|
33
|
$rule->priority($order); |
446
|
17
|
|
|
|
|
73
|
push @Rules, $rule; |
447
|
|
|
|
|
|
|
|
448
|
17
|
|
|
|
|
32
|
$self->max_priority($order); |
449
|
17
|
|
|
|
|
80
|
$self->rules(\@Rules); |
450
|
|
|
|
|
|
|
|
451
|
17
|
|
|
|
|
111
|
return $order; |
452
|
|
|
|
|
|
|
} |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
# private and exported tool _strip |
455
|
|
|
|
|
|
|
# strip a string or strip raw |
456
|
|
|
|
|
|
|
# return a string |
457
|
|
|
|
|
|
|
# usefull for parsing or tests |
458
|
|
|
|
|
|
|
# |
459
|
|
|
|
|
|
|
# default remove require line or set $keep_require |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
sub _strip { |
462
|
50
|
|
|
50
|
|
1000
|
my ( $self, $script_raw, $keep_require ) = @_; |
463
|
|
|
|
|
|
|
|
464
|
50
|
100
|
|
|
|
89
|
if ( ref($self) eq 'Net::Sieve::Script' ) { |
465
|
11
|
100
|
|
|
|
22
|
$script_raw = $self->raw() if (! $script_raw ); |
466
|
|
|
|
|
|
|
} else { |
467
|
39
|
|
|
|
|
44
|
$script_raw = $self; |
468
|
|
|
|
|
|
|
} |
469
|
|
|
|
|
|
|
|
470
|
50
|
|
|
|
|
133
|
$script_raw =~ s/\#.*//g; # hash-comment |
471
|
50
|
|
|
|
|
65
|
$script_raw =~ s!/\*.*.\*/!!g; # bracket-comment |
472
|
50
|
|
|
|
|
55
|
$script_raw =~ s/\t/ /g; # remove tabs |
473
|
50
|
|
|
|
|
101
|
$script_raw =~ s/\(/ \( /g; # add white-space around ( |
474
|
50
|
|
|
|
|
101
|
$script_raw =~ s/\)/ \) /g; # add white-space around ) |
475
|
|
|
|
|
|
|
#$script_raw =~ s/\s+\[/ \[ /g; # add white-space around [ |
476
|
|
|
|
|
|
|
#$script_raw =~ s/\]\s+/ \] /g; # add white-space around ] |
477
|
50
|
|
|
|
|
99
|
$script_raw =~ s/\]\s*,/\],/g; # add white-space around ] |
478
|
50
|
|
|
|
|
223
|
$script_raw =~ s/"\s*,/", /g; # add white-space after , in list |
479
|
50
|
|
|
|
|
121
|
$script_raw =~ s/"\s+;/";/g; # remove white-space between " and ; |
480
|
50
|
|
|
|
|
486
|
$script_raw =~ s/\s+/ /g; # remove doubs white-space |
481
|
50
|
|
|
|
|
90
|
$script_raw =~ s/^\s+//; # trim |
482
|
50
|
|
|
|
|
207
|
$script_raw =~ s/\s+$//; #trim |
483
|
|
|
|
|
|
|
|
484
|
50
|
50
|
|
|
|
163
|
$script_raw =~ s/require.*?["\]];\s+//sgi if (!$keep_require); #remove require |
485
|
|
|
|
|
|
|
|
486
|
50
|
|
|
|
|
141
|
return $script_raw; |
487
|
|
|
|
|
|
|
} |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
=head1 BUGS |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
Rewrite a hand made script will lose comments. Verify parsing success with parsing_ok method before write a new script. |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
=head1 SUPPORT |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
Please report any bugs or feature requests to "bug-net-sieve-script at rt.cpan.org", or through the web interface at L. |
496
|
|
|
|
|
|
|
I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
=head1 AUTHOR |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
Yves Agostini - |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
=head1 COPYRIGHT |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
Copyright 2017 Yves Agostini - |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
This program is free software; you can redistribute |
509
|
|
|
|
|
|
|
it and/or modify it under the same terms as Perl itself. |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
The full text of the license can be found in the |
512
|
|
|
|
|
|
|
LICENSE file included with this module. |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
=head1 SEE ALSO |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
L |
518
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
=cut |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
1; |
522
|
|
|
|
|
|
|
# The preceding line will help the module return a true value |
523
|
|
|
|
|
|
|
|