line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Copyrights 2001-2023 by [Mark Overmeer]. |
2
|
|
|
|
|
|
|
# For other contributors see ChangeLog. |
3
|
|
|
|
|
|
|
# See the manual pages for details on the licensing terms. |
4
|
|
|
|
|
|
|
# Pod stripped from pm file by OODoc 2.03. |
5
|
|
|
|
|
|
|
# This code is part of distribution Mail-Box. Meta-POD processed with |
6
|
|
|
|
|
|
|
# OODoc into POD and HTML manual-pages. See README.md |
7
|
|
|
|
|
|
|
# Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
package Mail::Box::Search; |
10
|
2
|
|
|
2
|
|
17
|
use vars '$VERSION'; |
|
2
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
139
|
|
11
|
|
|
|
|
|
|
$VERSION = '3.010'; |
12
|
|
|
|
|
|
|
|
13
|
2
|
|
|
2
|
|
11
|
use base 'Mail::Reporter'; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
187
|
|
14
|
|
|
|
|
|
|
|
15
|
2
|
|
|
2
|
|
12
|
use strict; |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
36
|
|
16
|
2
|
|
|
2
|
|
10
|
use warnings; |
|
2
|
|
|
|
|
11
|
|
|
2
|
|
|
|
|
84
|
|
17
|
|
|
|
|
|
|
|
18
|
2
|
|
|
2
|
|
49
|
use Carp; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
2445
|
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
sub init($) |
22
|
12
|
|
|
12
|
0
|
37
|
{ my ($self, $args) = @_; |
23
|
|
|
|
|
|
|
|
24
|
12
|
|
|
|
|
41
|
$self->SUPER::init($args); |
25
|
|
|
|
|
|
|
|
26
|
12
|
|
50
|
|
|
159
|
my $in = $args->{in} || 'BODY'; |
27
|
12
|
50
|
|
|
|
87
|
@$self{ qw/MBS_check_head MBS_check_body/ } |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
28
|
|
|
|
|
|
|
= $in eq 'BODY' ? (0,1) |
29
|
|
|
|
|
|
|
: $in eq 'HEAD' ? (1,0) |
30
|
|
|
|
|
|
|
: $in eq 'MESSAGE' ? (1,1) |
31
|
|
|
|
|
|
|
: ($self->log(ERROR => "Search in BODY, HEAD or MESSAGE not $in."), return); |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
$self->log(ERROR => "Cannot search in header."), return |
34
|
12
|
50
|
66
|
|
|
81
|
if $self->{MBS_check_head} && !$self->can('inHead'); |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
$self->log(ERROR => "Cannot search in body."), return |
37
|
12
|
50
|
66
|
|
|
112
|
if $self->{MBS_check_body} && !$self->can('inBody'); |
38
|
|
|
|
|
|
|
|
39
|
12
|
|
|
|
|
35
|
my $deliver = $args->{deliver}; |
40
|
|
|
|
|
|
|
$self->{MBS_deliver} |
41
|
518
|
|
|
518
|
|
1140
|
= ref $deliver eq 'CODE' ? sub { $deliver->($self, $_[0]) } |
42
|
|
|
|
|
|
|
: !defined $deliver ? undef |
43
|
|
|
|
|
|
|
: $deliver eq 'DELETE' |
44
|
0
|
|
|
0
|
|
0
|
? sub {$_[0]->{part}->toplevel->label(deleted => 1)} |
45
|
12
|
0
|
|
|
|
69
|
: $self->log(ERROR => "Don't know how to deliver results in $deliver."); |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
46
|
|
|
|
|
|
|
|
47
|
12
|
|
50
|
|
|
56
|
my $logic = $args->{logical} || 'REPLACE'; |
48
|
12
|
|
|
|
|
57
|
$self->{MBS_negative} = $logic =~ s/\s*NOT\s*$//; |
49
|
12
|
|
|
|
|
29
|
$self->{MBS_logical} = $logic; |
50
|
|
|
|
|
|
|
|
51
|
12
|
|
|
|
|
85
|
$self->{MBS_label} = $args->{label}; |
52
|
12
|
|
100
|
|
|
56
|
$self->{MBS_binaries} = $args->{binaries} || 0; |
53
|
12
|
|
100
|
|
|
49
|
$self->{MBS_limit} = $args->{limit} || 0; |
54
|
12
|
|
50
|
|
|
42
|
$self->{MBS_decode} = $args->{decode} || 1; |
55
|
12
|
|
|
|
|
32
|
$self->{MBS_no_deleted} = not $args->{deleted}; |
56
|
12
|
50
|
|
|
|
32
|
$self->{MBS_delayed} = defined $args->{delayed} ? $args->{delayed} : 1; |
57
|
|
|
|
|
|
|
$self->{MBS_multiparts} |
58
|
12
|
100
|
|
|
|
37
|
= defined $args->{multiparts} ? $args->{multiparts} : 1; |
59
|
|
|
|
|
|
|
|
60
|
12
|
|
|
|
|
30
|
$self; |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
#------------------------------------------- |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
sub search(@) |
67
|
14
|
|
|
14
|
1
|
39
|
{ my ($self, $object) = @_; |
68
|
|
|
|
|
|
|
|
69
|
14
|
|
|
|
|
26
|
my $label = $self->{MBS_label}; |
70
|
14
|
|
|
|
|
29
|
my $limit = $self->{MBS_limit}; |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
my @messages |
73
|
14
|
50
|
|
|
|
165
|
= ref $object eq 'ARRAY' ? @$object |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
74
|
|
|
|
|
|
|
: $object->isa('Mail::Box') ? $object->messages |
75
|
|
|
|
|
|
|
: $object->isa('Mail::Message') ? ($object) |
76
|
|
|
|
|
|
|
: $object->isa('Mail::Box::Thread::Node') ? $object->threadMessages |
77
|
|
|
|
|
|
|
: croak "Expect messages to search, not $object."; |
78
|
|
|
|
|
|
|
|
79
|
14
|
|
|
|
|
36
|
my $take = 0; |
80
|
14
|
100
|
100
|
|
|
132
|
if($limit < 0) { $take = -$limit; @messages = reverse @messages } |
|
1
|
50
|
|
|
|
3
|
|
|
1
|
100
|
|
|
|
2
|
|
81
|
0
|
|
|
|
|
0
|
elsif($limit > 0) { $take = $limit } |
82
|
1
|
|
|
|
|
4
|
elsif(!defined $label && !wantarray && !$self->{MBS_deliver}) {$take = 1 } |
83
|
|
|
|
|
|
|
|
84
|
14
|
|
|
|
|
32
|
my $logic = $self->{MBS_logical}; |
85
|
14
|
|
|
|
|
22
|
my @selected; |
86
|
14
|
|
|
|
|
23
|
my $count = 0; |
87
|
|
|
|
|
|
|
|
88
|
14
|
|
|
|
|
30
|
foreach my $message (@messages) |
89
|
376
|
100
|
100
|
|
|
1553
|
{ next if $self->{MBS_no_deleted} && $message->isDeleted; |
90
|
343
|
50
|
33
|
|
|
918
|
next unless $self->{MBS_delayed} || !$message->isDelayed; |
91
|
|
|
|
|
|
|
|
92
|
343
|
50
|
|
|
|
711
|
my $set = defined $label ? $message->label($label) : 0; |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
my $selected |
95
|
|
|
|
|
|
|
= $set && $logic eq 'OR' ? 1 |
96
|
|
|
|
|
|
|
: !$set && $logic eq 'AND' ? 0 |
97
|
343
|
50
|
33
|
|
|
1775
|
: $self->{MBS_negative} ? ! $self->searchPart($message) |
|
|
50
|
33
|
|
|
|
|
|
|
50
|
|
|
|
|
|
98
|
|
|
|
|
|
|
: $self->searchPart($message); |
99
|
|
|
|
|
|
|
|
100
|
343
|
50
|
|
|
|
892
|
$message->label($label => $selected) if defined $label; |
101
|
343
|
100
|
|
|
|
770
|
if($selected) |
102
|
167
|
|
|
|
|
287
|
{ push @selected, $message; |
103
|
167
|
|
|
|
|
219
|
$count++; |
104
|
167
|
100
|
100
|
|
|
526
|
last if $take && $count == $take; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
14
|
100
|
|
|
|
204
|
$limit < 0 ? reverse @selected : @selected; |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
#------------------------------------------- |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
sub searchPart($) |
116
|
376
|
|
|
376
|
1
|
751
|
{ my ($self, $part) = @_; |
117
|
|
|
|
|
|
|
|
118
|
376
|
|
|
|
|
533
|
my $matched = 0; |
119
|
|
|
|
|
|
|
$matched = $self->inHead($part, $part->head) |
120
|
376
|
100
|
|
|
|
1027
|
if $self->{MBS_check_head}; |
121
|
|
|
|
|
|
|
|
122
|
376
|
100
|
|
|
|
873
|
return $matched unless $self->{MBS_check_body}; |
123
|
335
|
50
|
66
|
|
|
745
|
return $matched if $matched && !$self->{MBS_deliver}; |
124
|
|
|
|
|
|
|
|
125
|
335
|
|
|
|
|
901
|
my $body = $part->body; |
126
|
335
|
|
|
|
|
1903
|
my @bodies; |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
# Handle multipart parts. |
129
|
|
|
|
|
|
|
|
130
|
335
|
100
|
|
|
|
1301
|
if($body->isMultipart) |
|
|
50
|
|
|
|
|
|
131
|
25
|
100
|
|
|
|
73
|
{ return $matched unless $self->{MBS_multiparts}; |
132
|
24
|
|
|
|
|
66
|
my $no_delayed = not $self->{MBS_delayed}; |
133
|
24
|
|
|
|
|
84
|
@bodies = ($body->preamble, $body->epilogue); |
134
|
|
|
|
|
|
|
|
135
|
24
|
|
|
|
|
319
|
foreach my $piece ($body->parts) |
136
|
33
|
50
|
|
|
|
236
|
{ next unless defined $piece; |
137
|
33
|
50
|
33
|
|
|
87
|
next if $no_delayed && $piece->isDelayed; |
138
|
|
|
|
|
|
|
|
139
|
33
|
|
|
|
|
88
|
$matched += $self->searchPart($piece); |
140
|
33
|
50
|
66
|
|
|
178
|
return $matched if $matched && !$self->{MBS_deliver}; |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
elsif($body->isNested) |
144
|
0
|
0
|
|
|
|
0
|
{ return $matched unless $self->{MBS_multiparts}; |
145
|
0
|
|
|
|
|
0
|
$matched += $self->searchPart($body->nested); |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
else |
148
|
310
|
|
|
|
|
731
|
{ @bodies = ($body); |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
# Handle normal bodies. |
152
|
|
|
|
|
|
|
|
153
|
334
|
|
|
|
|
673
|
foreach (@bodies) |
154
|
358
|
100
|
|
|
|
745
|
{ next unless defined $_; |
155
|
349
|
100
|
100
|
|
|
1195
|
next if !$self->{MBS_binaries} && $_->isBinary; |
156
|
326
|
50
|
|
|
|
101748
|
my $body = $self->{MBS_decode} ? $_->decoded : $_; |
157
|
326
|
|
|
|
|
313686
|
my $inbody = $self->inBody($part, $body); |
158
|
326
|
|
|
|
|
937
|
$matched += $inbody; |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
334
|
|
|
|
|
6817
|
$matched; |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
#------------------------------------------- |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
|
167
|
0
|
|
|
0
|
1
|
|
sub inHead(@) {shift->notImplemented} |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
#------------------------------------------- |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
|
172
|
0
|
|
|
0
|
1
|
|
sub inBody(@) {shift->notImplemented} |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
#------------------------------------------- |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
|
177
|
0
|
|
|
0
|
1
|
|
sub printMatch($) {shift->notImplemented} |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
#------------------------------------------- |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
1; |