| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# $Id: DCCIf.pm,v 1.4 2004/02/11 14:36:48 matt Exp $ |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package Net::DCCIf; |
|
4
|
1
|
|
|
1
|
|
6779
|
use strict; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
36
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
791
|
use IO::Socket; |
|
|
1
|
|
|
|
|
33392
|
|
|
|
1
|
|
|
|
|
5
|
|
|
7
|
1
|
|
|
1
|
|
493
|
use Socket qw(:crlf inet_ntoa); |
|
|
1
|
|
|
|
|
7
|
|
|
|
1
|
|
|
|
|
303
|
|
|
8
|
1
|
|
|
1
|
|
1060
|
use Fatal qw(open close); |
|
|
1
|
|
|
|
|
17068
|
|
|
|
1
|
|
|
|
|
8
|
|
|
9
|
1
|
|
|
1
|
|
1083
|
use Symbol qw(gensym); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
67
|
|
|
10
|
|
|
|
|
|
|
|
|
11
|
1
|
|
|
1
|
|
5
|
use vars qw($VERSION); |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
1755
|
|
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
$VERSION = '0.02'; |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
my %result_map = ( |
|
16
|
|
|
|
|
|
|
A => 'Accept', |
|
17
|
|
|
|
|
|
|
R => 'Reject', |
|
18
|
|
|
|
|
|
|
S => 'Accept Some', |
|
19
|
|
|
|
|
|
|
T => 'Temporary Failure', |
|
20
|
|
|
|
|
|
|
); |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
sub new { |
|
23
|
0
|
|
|
0
|
1
|
|
my $class = shift; |
|
24
|
|
|
|
|
|
|
|
|
25
|
0
|
|
|
|
|
|
return bless {}, $class; |
|
26
|
|
|
|
|
|
|
} |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
sub connect { |
|
29
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
|
30
|
0
|
|
|
|
|
|
my %opts = @_; |
|
31
|
|
|
|
|
|
|
|
|
32
|
0
|
|
|
|
|
|
%$self = (); # clear out self in case its being re-used. |
|
33
|
|
|
|
|
|
|
|
|
34
|
0
|
|
0
|
|
|
|
$opts{homedir} ||= $self->{homedir} || '/var/dcc'; |
|
|
|
|
0
|
|
|
|
|
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# this slightly odd logic copied from the original dccif.pl |
|
37
|
0
|
0
|
|
|
|
|
if ($opts{clnt_addr}) { |
|
|
|
0
|
|
|
|
|
|
|
38
|
0
|
0
|
|
|
|
|
inet_aton($opts{clnt_addr}) || die "Client address lookup failed: $!"; |
|
39
|
|
|
|
|
|
|
} |
|
40
|
|
|
|
|
|
|
elsif ($opts{clnt_name}) { |
|
41
|
0
|
|
0
|
|
|
|
$opts{clnt_addr} = inet_ntoa(scalar(gethostbyname($opts{clnt_name}))) |
|
42
|
|
|
|
|
|
|
|| die "Cannot resolve domain name $opts{clnt_name}: $!"; |
|
43
|
|
|
|
|
|
|
} |
|
44
|
|
|
|
|
|
|
else { |
|
45
|
0
|
|
|
|
|
|
$opts{clnt_name} = ''; |
|
46
|
|
|
|
|
|
|
} |
|
47
|
|
|
|
|
|
|
|
|
48
|
0
|
|
0
|
|
|
|
my $server = IO::Socket::UNIX->new( |
|
49
|
|
|
|
|
|
|
Type => SOCK_STREAM, |
|
50
|
|
|
|
|
|
|
Peer => "$opts{homedir}/dccifd", |
|
51
|
|
|
|
|
|
|
) || die "Socket connect failed ($opts{homedir}/dccifd): $!"; |
|
52
|
|
|
|
|
|
|
|
|
53
|
0
|
|
|
|
|
|
$self->{server} = $server; |
|
54
|
0
|
|
|
|
|
|
$self->{homedir} = $opts{homedir}; |
|
55
|
|
|
|
|
|
|
|
|
56
|
0
|
|
|
|
|
|
my @options; |
|
57
|
0
|
0
|
|
|
|
|
if ($opts{known_spam}) { |
|
58
|
0
|
|
|
|
|
|
push @options, "spam"; |
|
59
|
|
|
|
|
|
|
} |
|
60
|
0
|
0
|
|
|
|
|
if ($opts{output_body}) { |
|
61
|
0
|
|
|
|
|
|
push @options, "body"; |
|
62
|
|
|
|
|
|
|
} |
|
63
|
0
|
0
|
|
|
|
|
if ($opts{output_header}) { |
|
64
|
0
|
|
|
|
|
|
push @options, "header"; |
|
65
|
|
|
|
|
|
|
} |
|
66
|
0
|
0
|
|
|
|
|
if ($opts{query_only}) { |
|
67
|
0
|
|
|
|
|
|
push @options, "query"; |
|
68
|
|
|
|
|
|
|
} |
|
69
|
|
|
|
|
|
|
|
|
70
|
0
|
|
|
|
|
|
$self->send("opts", join(" ", @options), LF); |
|
71
|
|
|
|
|
|
|
|
|
72
|
0
|
|
|
|
|
|
$self->send("clnt helo env_from", |
|
73
|
|
|
|
|
|
|
$opts{clnt_addr}, CR, $opts{clnt_name}, LF, |
|
74
|
|
|
|
|
|
|
$opts{helo}, LF, |
|
75
|
|
|
|
|
|
|
$opts{env_from}, LF, |
|
76
|
|
|
|
|
|
|
); |
|
77
|
|
|
|
|
|
|
|
|
78
|
0
|
0
|
|
|
|
|
if (!ref($opts{env_to})) { |
|
79
|
0
|
0
|
|
|
|
|
$opts{env_to} = $opts{env_to} ? [$opts{env_to}] : []; |
|
80
|
|
|
|
|
|
|
} |
|
81
|
|
|
|
|
|
|
|
|
82
|
0
|
|
|
|
|
|
$self->{env_to} = $opts{env_to}; |
|
83
|
|
|
|
|
|
|
|
|
84
|
0
|
|
|
|
|
|
foreach my $env_to (@{$opts{env_to}}) { |
|
|
0
|
|
|
|
|
|
|
|
85
|
0
|
|
|
|
|
|
$self->send("env_to", $env_to, LF); |
|
86
|
|
|
|
|
|
|
} |
|
87
|
|
|
|
|
|
|
|
|
88
|
0
|
|
|
|
|
|
$self->send("end of env_tos", LF); |
|
89
|
|
|
|
|
|
|
|
|
90
|
0
|
|
|
|
|
|
return $self; |
|
91
|
|
|
|
|
|
|
} |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub dcc_file { |
|
94
|
0
|
|
|
0
|
1
|
|
my ($self, $file) = @_; |
|
95
|
|
|
|
|
|
|
|
|
96
|
0
|
|
|
|
|
|
my $fh = gensym(); |
|
97
|
0
|
|
|
|
|
|
open($fh, $file); |
|
98
|
|
|
|
|
|
|
|
|
99
|
0
|
|
|
|
|
|
return $self->dcc_fh($fh); |
|
100
|
|
|
|
|
|
|
} |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
sub dcc_fh { |
|
103
|
0
|
|
|
0
|
1
|
|
my ($self, $fh) = @_; |
|
104
|
|
|
|
|
|
|
|
|
105
|
0
|
|
|
|
|
|
my $buf; |
|
106
|
0
|
|
|
|
|
|
while (1) { |
|
107
|
0
|
|
|
|
|
|
my $i = sysread($fh, $buf, 8192); |
|
108
|
0
|
0
|
|
|
|
|
die "sysread file handle failed: $!" unless defined($i); |
|
109
|
0
|
0
|
|
|
|
|
last unless $i; |
|
110
|
0
|
|
|
|
|
|
$self->send("body", $buf); |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
|
|
113
|
0
|
|
|
|
|
|
return $self->get_results(); |
|
114
|
|
|
|
|
|
|
} |
|
115
|
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
sub send { |
|
117
|
0
|
|
|
0
|
1
|
|
my ($self, $type, @data) = @_; |
|
118
|
|
|
|
|
|
|
# warn("send $type:", join('', @data)) if $type ne 'body'; |
|
119
|
0
|
0
|
|
|
|
|
$self->{server}->syswrite(join('', @data)) || die "socket write failed at $type: $!"; |
|
120
|
|
|
|
|
|
|
} |
|
121
|
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
sub get_results { |
|
123
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
|
124
|
|
|
|
|
|
|
|
|
125
|
0
|
0
|
|
|
|
|
if ($self->{results}) { |
|
126
|
0
|
|
|
|
|
|
return @{$self->{results}}; |
|
|
0
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
} |
|
128
|
|
|
|
|
|
|
|
|
129
|
0
|
0
|
|
|
|
|
$self->{server}->shutdown(1) || die "socket shutdown failed: $!"; |
|
130
|
0
|
|
0
|
|
|
|
my $result = $self->{server}->getline || die "socket read failed: $!"; |
|
131
|
0
|
|
0
|
|
|
|
my $oks = $self->{server}->getline || die "socket read failed: $!"; |
|
132
|
0
|
|
|
|
|
|
chomp($result); chomp($oks); |
|
|
0
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
|
|
134
|
0
|
|
|
|
|
|
$result = $result_map{$result}; |
|
135
|
0
|
|
|
|
|
|
my @ok_map; |
|
136
|
0
|
|
|
|
|
|
foreach my $env_to (@{$self->{env_to}}) { |
|
|
0
|
|
|
|
|
|
|
|
137
|
0
|
|
|
|
|
|
my $val = substr($oks, 0, 1, ''); |
|
138
|
0
|
|
|
|
|
|
push @ok_map, $env_to, $result_map{$val}; |
|
139
|
|
|
|
|
|
|
} |
|
140
|
|
|
|
|
|
|
|
|
141
|
0
|
|
|
|
|
|
$self->{results} = [ $result, @ok_map ]; |
|
142
|
0
|
|
|
|
|
|
return( $result, @ok_map ); |
|
143
|
|
|
|
|
|
|
} |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub get_output { |
|
146
|
0
|
|
|
0
|
1
|
|
my ($self, %opts) = @_; |
|
147
|
|
|
|
|
|
|
|
|
148
|
0
|
|
|
|
|
|
my $output_fh = $opts{output_fh}; |
|
149
|
0
|
0
|
|
|
|
|
if (!$output_fh) { |
|
150
|
0
|
0
|
|
|
|
|
if ($opts{output_file}) { |
|
151
|
0
|
|
|
|
|
|
$output_fh = gensym(); |
|
152
|
0
|
|
|
|
|
|
open($output_fh, ">" . $self->{output_file}); |
|
153
|
|
|
|
|
|
|
} |
|
154
|
|
|
|
|
|
|
} |
|
155
|
|
|
|
|
|
|
|
|
156
|
0
|
|
|
|
|
|
my $ret = ''; |
|
157
|
0
|
|
|
|
|
|
my $buf; |
|
158
|
0
|
|
|
|
|
|
while (1) { |
|
159
|
0
|
|
|
|
|
|
my $i = $self->{server}->read($buf, 8192); |
|
160
|
0
|
0
|
|
|
|
|
die "read socket failed: $!" unless defined($i); |
|
161
|
0
|
0
|
|
|
|
|
last unless $i; |
|
162
|
0
|
0
|
|
|
|
|
if ($output_fh) { |
|
163
|
0
|
0
|
|
|
|
|
print $output_fh ($buf) or die "write output filehandle failed: $!"; |
|
164
|
|
|
|
|
|
|
} |
|
165
|
|
|
|
|
|
|
else { |
|
166
|
0
|
|
|
|
|
|
$ret .= $buf; |
|
167
|
|
|
|
|
|
|
} |
|
168
|
|
|
|
|
|
|
} |
|
169
|
|
|
|
|
|
|
|
|
170
|
0
|
|
|
|
|
|
return $ret; |
|
171
|
|
|
|
|
|
|
} |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
sub disconnect { |
|
174
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
|
175
|
0
|
|
|
|
|
|
delete $self->{server}; |
|
176
|
|
|
|
|
|
|
} |
|
177
|
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
1; |
|
179
|
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=head1 NAME |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
Net::DCCIf - Interface to the DCC daemon |
|
183
|
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
my $dcc = Net::DCCIf->new(); |
|
187
|
|
|
|
|
|
|
$dcc->connect(); |
|
188
|
|
|
|
|
|
|
my ($results, $oks) = $dcc->dcc_file("test.eml"); |
|
189
|
|
|
|
|
|
|
$dcc->disconnect(); |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
This module is a simple interface to the Distributed Checksum Clearinghouse |
|
194
|
|
|
|
|
|
|
daemon (dccifd). It is a simpler replacement for the F script that |
|
195
|
|
|
|
|
|
|
dcc ships with, making usage more perlish (though probably at the expense of |
|
196
|
|
|
|
|
|
|
a slight performance drop). |
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=head1 API |
|
199
|
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
The API is intentionally simple. Hopefully it allows enough flexibility to |
|
201
|
|
|
|
|
|
|
support everything needed, however if not there may be some advantages to |
|
202
|
|
|
|
|
|
|
sticking with F from the DCC distribution. |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=head2 C<< Net::DCCIf->new() >> |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
This constructs a new Net::DCCIf object. It takes no options, and will always |
|
207
|
|
|
|
|
|
|
return a valid object unless there is an out of memory error. |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
=head2 C<< $dcc->connect(%options) >> |
|
210
|
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
Attempt to connect to the local unix domain socket. By default this domain |
|
212
|
|
|
|
|
|
|
socket is expected to be at F, however you can override |
|
213
|
|
|
|
|
|
|
this with the C option. If the connection fails for any reason |
|
214
|
|
|
|
|
|
|
then an exception will be thrown detailing the error. |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
Returns the object, to facilitate method chaining. |
|
217
|
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
B |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
=over 4 |
|
221
|
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=item C<< env_from => $from >> |
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
The envelope from address (C data). |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
=item C<< env_to => \@env_tos >> |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
The envelope to addresses as an array reference (C data). |
|
229
|
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
B<< WARNING: >> if you pass an empty list here then DCC will assume |
|
231
|
|
|
|
|
|
|
zero recipients and not increment the counter for this email (equivalent |
|
232
|
|
|
|
|
|
|
to doing a C<< query_only >> lookup). |
|
233
|
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=item C<< helo => $helo >> |
|
235
|
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
The HELO line. |
|
237
|
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
=item C<< homedir => $dir >> |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
Specifies the location of the C unix domain socket. |
|
241
|
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=item C<< clnt_addr => $addr >> |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
Specifies the IP address of the connecting server. If this is an invalid |
|
245
|
|
|
|
|
|
|
address then an exception will be thrown. |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
=item C<< clnt_name => $name >> |
|
248
|
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
Specifies the host name of the connecting server. If the C is |
|
250
|
|
|
|
|
|
|
specified, but C is not, then a hostname lookup will be |
|
251
|
|
|
|
|
|
|
performed to try and determine the IP address. If this lookup fails an |
|
252
|
|
|
|
|
|
|
exception will be thrown. |
|
253
|
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
=item C<< known_spam => 1 >> |
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
Specifies that we already know this email is spam (i.e. it came in to |
|
257
|
|
|
|
|
|
|
a spamtrap address) and so we let the DCC server know about it. |
|
258
|
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
=item C<< output_body => 1 >> |
|
260
|
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
Makes L<< get_output()|/$dcc->get_output(%options) >> return the full body of the email with |
|
262
|
|
|
|
|
|
|
a header added to it. |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
=item C<< output_header => 1 >> |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
Makes L<< get_output()|/$dcc->get_output(%options) >> return just a header line. |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
=item C<< query_only => 1 >> |
|
269
|
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
Issues a query only, rather than first incrementing the database and then |
|
271
|
|
|
|
|
|
|
querying. |
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=back |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
=head2 C<< $dcc->dcc_file($filename) >> |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
Opens the file and calls L<< dcc_fh()|/$dcc->dcc_fh($fh) >> on the resulting filehandle. |
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
Returns C<($result, @mappings)>. See L below. |
|
280
|
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=head2 C<< $dcc->dcc_fh($fh) >> |
|
282
|
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
Sends the contents of the filehandle to the dcc server. |
|
284
|
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
Returns C<($result, @mappings)>. See L below. |
|
286
|
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
=head2 C<< $dcc->send($type, @data) >> |
|
288
|
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
Sends raw text data to the dcc server. The type is usually one of C<"header"> or |
|
290
|
|
|
|
|
|
|
C<"body">, and is used in error messages if there is a problem sending the |
|
291
|
|
|
|
|
|
|
data. |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
Use this method B any calls to C or C. Using it after |
|
294
|
|
|
|
|
|
|
may result in an error or unexpected results. |
|
295
|
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=head2 C<< $dcc->get_results() >> |
|
297
|
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
Following sending the email via C you have to manually extract the |
|
299
|
|
|
|
|
|
|
results (these are the same results as returned by C and C |
|
300
|
|
|
|
|
|
|
above). |
|
301
|
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
=head2 C<< $dcc->get_output(%options) >> |
|
303
|
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
This method returns the header or body from the dcc server that resulted from |
|
305
|
|
|
|
|
|
|
running dcc on the data. The output depends on the values of the C |
|
306
|
|
|
|
|
|
|
or C options passed in the C call. |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
Returns the data as a string unless the C or C options |
|
309
|
|
|
|
|
|
|
are set. |
|
310
|
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
B |
|
312
|
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
=over 4 |
|
314
|
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
=item C<< output_fh => $fh >> |
|
316
|
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
A filehandle to send the output to. If you wish the output to go to STDOUT, you can |
|
318
|
|
|
|
|
|
|
pass it with C<< $dcc->get_output(output_fh => \*STDOUT) >>. |
|
319
|
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
This option overrides any setting for C. |
|
321
|
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=item C<< output_file => $file >> |
|
323
|
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
A filename to send the output to, as with C above. |
|
325
|
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
=back |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
=head2 C<< $dcc->disconnect() >> |
|
329
|
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
Disconnect from the dccifd server and cleanup. |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
=head1 Results |
|
333
|
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
The results returned from C, C and C above are a |
|
335
|
|
|
|
|
|
|
list of values: C<($action, @mappings)>. |
|
336
|
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
The C<$action> value is one of: |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
=over 4 |
|
340
|
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
=item "Accept" |
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
=item "Reject" |
|
344
|
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
=item "Reject Some" |
|
346
|
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
=item "Temporary Failure" |
|
348
|
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
=back |
|
350
|
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
The C<@mappings> value is a list of envelope to addresses followed by the action |
|
352
|
|
|
|
|
|
|
that should be taken for that address. It is often easier to map this to a hash: |
|
353
|
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
my ($action, %mappings) = $dcc->get_results(); |
|
355
|
|
|
|
|
|
|
print "Action: $action\n"; |
|
356
|
|
|
|
|
|
|
print "Matt Sergeant action: " . $mappings{'matt@sergeant.org'} . "\n"; |
|
357
|
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
This should only have differing values in it should the primary action be |
|
359
|
|
|
|
|
|
|
"Reject Some", otherwise the values will all be the same as C<$action>. |
|
360
|
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
Ordering of the mappings will be the same as the order of C addresses |
|
362
|
|
|
|
|
|
|
passed to C above. Note that this ordering will be lost if you |
|
363
|
|
|
|
|
|
|
map it to a hash. |
|
364
|
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
=head1 Exceptions |
|
366
|
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
This module throws exceptions for all errors. In order to catch these errors |
|
368
|
|
|
|
|
|
|
without having your program exit you can use the C construct: |
|
369
|
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
my $dcc = Net::DCCIf->new(); |
|
371
|
|
|
|
|
|
|
eval { |
|
372
|
|
|
|
|
|
|
$dcc->connect(); |
|
373
|
|
|
|
|
|
|
my ($results, %mapping) = $dcc->dcc_file("test.eml"); |
|
374
|
|
|
|
|
|
|
print "Results: $results\n"; |
|
375
|
|
|
|
|
|
|
print "Recipients: $_ => $mapping{$_}\n" for keys %mapping; |
|
376
|
|
|
|
|
|
|
}; |
|
377
|
|
|
|
|
|
|
if ($@) { |
|
378
|
|
|
|
|
|
|
warn("An error occurred in dcc: $@"); |
|
379
|
|
|
|
|
|
|
} |
|
380
|
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
=head1 BUGS |
|
382
|
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
No real test suite yet, as its hard to do when testing daemons and so I |
|
384
|
|
|
|
|
|
|
got lazy :-( |
|
385
|
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
=head1 AUTHOR |
|
387
|
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
Matt Sergeant working for MessageLabs |
|
389
|
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
=head1 LICENSE |
|
391
|
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
This is free software. You may redistribute it under the same terms |
|
393
|
|
|
|
|
|
|
as Perl itself. |
|
394
|
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
Copyright 2003. All Rights Reserved. |
|
396
|
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
=cut |