line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Mail::Run::Crypt; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# Force me to write this properly |
4
|
6
|
|
|
6
|
|
417303
|
use strict; |
|
6
|
|
|
|
|
55
|
|
|
6
|
|
|
|
|
182
|
|
5
|
6
|
|
|
6
|
|
34
|
use warnings; |
|
6
|
|
|
|
|
12
|
|
|
6
|
|
|
|
|
142
|
|
6
|
6
|
|
|
6
|
|
29
|
use utf8; |
|
6
|
|
|
|
|
9
|
|
|
6
|
|
|
|
|
35
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
# Require this version of Perl |
9
|
6
|
|
|
6
|
|
252
|
use 5.008_001; |
|
6
|
|
|
|
|
20
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
# Import required modules |
12
|
6
|
|
|
6
|
|
72
|
use Carp; |
|
6
|
|
|
|
|
23
|
|
|
6
|
|
|
|
|
421
|
|
13
|
6
|
|
|
6
|
|
2116
|
use English '-no_match_vars'; |
|
6
|
|
|
|
|
14405
|
|
|
6
|
|
|
|
|
36
|
|
14
|
6
|
|
|
6
|
|
5320
|
use IPC::Run3; |
|
6
|
|
|
|
|
190833
|
|
|
6
|
|
|
|
|
387
|
|
15
|
6
|
|
|
6
|
|
3393
|
use Mail::GnuPG; |
|
6
|
|
|
|
|
3018823
|
|
|
6
|
|
|
|
|
286
|
|
16
|
6
|
|
|
6
|
|
63
|
use MIME::Entity; |
|
6
|
|
|
|
|
12
|
|
|
6
|
|
|
|
|
3218
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# Specify package verson |
19
|
|
|
|
|
|
|
our $VERSION = '0.12'; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
# Default exit value |
22
|
|
|
|
|
|
|
our $DEFAULT_EXIT = 127; ## no critic (ProhibitMagicNumbers) |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# Oldschool constructor |
25
|
|
|
|
|
|
|
sub new { |
26
|
7
|
|
|
7
|
1
|
1386
|
my ( $class, %opts ) = @_; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# Blindly slurp in all the options given |
29
|
7
|
|
|
|
|
30
|
my $self = {%opts}; |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# We must have a recipient |
32
|
|
|
|
|
|
|
defined $self->{mailto} |
33
|
7
|
100
|
|
|
|
196
|
or croak 'MAILTO required'; |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# Default the instance name to the package name if it wasn't given; |
36
|
|
|
|
|
|
|
# runcrypt(1) will pass it in |
37
|
6
|
100
|
|
|
|
28
|
defined $self->{name} or $self->{name} = $class; |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# We default to encrypting but not signing |
40
|
6
|
100
|
|
|
|
25
|
defined $self->{encrypt} or $self->{encrypt} = 1; |
41
|
6
|
100
|
|
|
|
23
|
defined $self->{sign} or $self->{sign} = 0; |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
# If signing, we need a key ID and a passphrase |
44
|
6
|
100
|
|
|
|
23
|
if ( $self->{sign} ) { |
45
|
|
|
|
|
|
|
defined $self->{keyid} |
46
|
3
|
100
|
|
|
|
217
|
or croak 'Key ID required for signing'; |
47
|
|
|
|
|
|
|
defined $self->{passphrase} |
48
|
2
|
100
|
|
|
|
128
|
or croak 'Passphrase required for signing'; |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# Return objectified self |
52
|
4
|
|
|
|
|
31
|
return bless $self, $class; |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
# Run a given command |
56
|
|
|
|
|
|
|
sub run { |
57
|
0
|
|
|
0
|
1
|
0
|
my ( $self, @command ) = @_; |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
# Run the command and wait for it to finish; keep its exit value for later |
60
|
0
|
|
|
|
|
0
|
my ( @out, @err ); |
61
|
0
|
0
|
|
|
|
0
|
eval { run3 \@command, undef, \@out, \@err } |
|
0
|
|
|
|
|
0
|
|
62
|
|
|
|
|
|
|
or warn "Command failed: $EVAL_ERROR\n"; |
63
|
0
|
|
|
|
|
0
|
$self->{exit} = $CHILD_ERROR >> 8; |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# If there was output, mail it |
66
|
0
|
0
|
|
|
|
0
|
if (@out) { |
67
|
0
|
|
|
|
|
0
|
my $command = join q{ }, @command; |
68
|
0
|
|
|
|
|
0
|
my $subject = "$self->{name} output: $command"; |
69
|
0
|
|
|
|
|
0
|
$self->_mail( $subject, \@out ); |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# If there were errors, mail them |
73
|
0
|
0
|
|
|
|
0
|
if (@err) { |
74
|
0
|
|
|
|
|
0
|
my $command = join q{ }, @command; |
75
|
0
|
|
|
|
|
0
|
my $subject = "$self->{name} errors: $command"; |
76
|
0
|
|
|
|
|
0
|
$self->_mail( $subject, \@err ); |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
# Return status reflecting the command exit value |
80
|
0
|
|
|
|
|
0
|
return $self->{exit} == 0; |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
# Return the value of the most recently run command, or 1 otherwise |
84
|
|
|
|
|
|
|
sub bail { |
85
|
2
|
|
|
2
|
1
|
2539
|
my $self = shift; |
86
|
|
|
|
|
|
|
my $exit = |
87
|
|
|
|
|
|
|
defined $self->{exit} |
88
|
|
|
|
|
|
|
? $self->{exit} |
89
|
2
|
50
|
|
|
|
18
|
: $DEFAULT_EXIT; |
90
|
2
|
|
|
|
|
9
|
return $exit; |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
# Send the message to the address in $ENV{MAILTO} |
94
|
|
|
|
|
|
|
sub _mail { |
95
|
0
|
|
|
0
|
|
|
my ( $self, $subject, $content ) = @_; |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
# Build MIME object with plaintext message |
98
|
|
|
|
|
|
|
my $mime = MIME::Entity->build( |
99
|
|
|
|
|
|
|
To => $self->{mailto}, |
100
|
0
|
|
|
|
|
|
Subject => $subject, |
101
|
|
|
|
|
|
|
Data => $content, |
102
|
|
|
|
|
|
|
); |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
# Encrypt the MIME object |
105
|
|
|
|
|
|
|
my $mgpg = Mail::GnuPG->new( |
106
|
|
|
|
|
|
|
key => $self->{keyid}, |
107
|
|
|
|
|
|
|
passphrase => $self->{passphrase}, |
108
|
0
|
|
|
|
|
|
); |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
# Sign and/or encrypt as appropriate |
111
|
0
|
0
|
0
|
|
|
|
if ( $self->{sign} and $self->{encrypt} ) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
112
|
0
|
|
|
|
|
|
$mgpg->mime_signencrypt( $mime, $self->{mailto} ); |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
elsif ( $self->{sign} ) { |
115
|
0
|
|
|
|
|
|
$mgpg->mime_sign( $mime, $self->{mailto} ); |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
elsif ( $self->{encrypt} ) { |
118
|
0
|
|
|
|
|
|
$mgpg->mime_encrypt( $mime, $self->{mailto} ); |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
# Send it |
122
|
0
|
|
|
|
|
|
return $mime->send(); |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
1; |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
__END__ |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=pod |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
=for stopwords |
132
|
|
|
|
|
|
|
mailserver decrypt runcrypt GPG OpenPGP tradename licensable MERCHANTABILITY |
133
|
|
|
|
|
|
|
mailto keyid |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=head1 NAME |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
Mail::Run::Crypt - Encrypt and mail output from command runs |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
=head1 VERSION |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
Version 0.12 |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=head1 DESCRIPTION |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
This module runs a system command with L<IPC::Run3|IPC::Run3>, and collects any |
146
|
|
|
|
|
|
|
standard output and standard error it emits. If there is any standard output or |
147
|
|
|
|
|
|
|
standard error content, it is encrypted and optionally signed with GnuPG, and |
148
|
|
|
|
|
|
|
then each stream's content is mailed separately to a specified recipient |
149
|
|
|
|
|
|
|
address. |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
The idea is to allow you to view the output of automated commands while having |
152
|
|
|
|
|
|
|
the content encrypted as it passes through to your mailserver, and optionally |
153
|
|
|
|
|
|
|
to have some assurance that the content was actually generated by the server |
154
|
|
|
|
|
|
|
concerned. B<cron(8)> scripts are the ideal use case, but this would also work |
155
|
|
|
|
|
|
|
with B<at(1)>, or anything else that might non-interactively run jobs for which |
156
|
|
|
|
|
|
|
output is significant. |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
You will probably want to call this with the L<B<runcrypt(1)>|runcrypt> program |
159
|
|
|
|
|
|
|
provided by this distribution, which includes a means to set the properties for |
160
|
|
|
|
|
|
|
the module via environment variables or command line options. |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=head1 SYNOPSIS |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
use Mail::Run::Crypt; |
165
|
|
|
|
|
|
|
... |
166
|
|
|
|
|
|
|
my $mrc = Mail::Run::Crypt->new( |
167
|
|
|
|
|
|
|
mailto => 'you@example.net', |
168
|
|
|
|
|
|
|
); |
169
|
|
|
|
|
|
|
$mrc->run($command, @args); |
170
|
|
|
|
|
|
|
... |
171
|
|
|
|
|
|
|
my $mrc = Mail::Run::Crypt->new( |
172
|
|
|
|
|
|
|
sign => 1, |
173
|
|
|
|
|
|
|
keyid => '0x1234DEAD5678BEEF', |
174
|
|
|
|
|
|
|
passphrase => 'able was i ere i saw elba', |
175
|
|
|
|
|
|
|
mailto => 'you@example.net', |
176
|
|
|
|
|
|
|
); |
177
|
|
|
|
|
|
|
$mrc->run($command, @args); |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=head1 SUBROUTINES/METHODS |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=head2 C<new(%opts)> |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
Constructor method; accepts the following named parameters: |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
=over 4 |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
=item C<mailto> |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
The recipient email address for the content. This is always required. |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=item C<encrypt> |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
Whether to encrypt the command output. This defaults to 1. |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=item C<sign> |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
Whether to sign the command output. This defaults to 0. A C<keyid> and |
198
|
|
|
|
|
|
|
C<passphrase> will be required for signing. |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
It is I<strongly> recommended that a dedicated key and passphrase be used for |
201
|
|
|
|
|
|
|
signatures if this is needed. You should carefully consider the consequences of |
202
|
|
|
|
|
|
|
a compromised key. |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=item C<keyid> |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
The GnuPG key ID that should be used to sign messages. This is required for |
207
|
|
|
|
|
|
|
signing, and has no effect without C<sign>. It can be any means of identifying |
208
|
|
|
|
|
|
|
the key acceptable to GnuPG; the key's 8-byte ("long") hexadecimal ID prefixed |
209
|
|
|
|
|
|
|
with C<0x> is probably the best way. |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
=item C<passphrase> |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
The passphrase used to decrypt the key. This is required for signing, and has |
214
|
|
|
|
|
|
|
no effect without C<sign>. |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=item C<name> |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
(Optional) The name of the object. When called from the |
219
|
|
|
|
|
|
|
L<B<runcrypt(1)>|runcrypt> program, this will be the string "runcrypt". |
220
|
|
|
|
|
|
|
Otherwise, it will default to this package's name. |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=back |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
=head2 C<run(@command)> |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
Run the specified arguments as a command with L<IPC::Run3|IPC::Run3>, and email |
227
|
|
|
|
|
|
|
any output or error content to the email recipient, encrypting and/or signing |
228
|
|
|
|
|
|
|
as configured. Returns 1 if the command succeeded, 0 otherwise. Use |
229
|
|
|
|
|
|
|
L<C<bail()>|/bail()> to get the actual exit code if needed. |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
=head2 C<bail()> |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
Return the exit status of the most recently run command, or 127 if no command |
234
|
|
|
|
|
|
|
has been successfully run. |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
=head1 DIAGNOSTICS |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
=over 4 |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
=item C<mailto required> |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
The required C<mailto> property was not passed in the constructor. |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=item C<keyid required for signing> |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
Signing was specified, but no C<keyid> attribute was passed in the constructor. |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
=item C<passphrase required for signing> |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
Signing was specified, but no C<passphrase> attribute was passed in the constructor. |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
=item C<command failed: %s> |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
The command could not be run at all, raising the given error string. This is |
255
|
|
|
|
|
|
|
typically due to problems finding the executable. |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
=back |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
=head1 CONFIGURATION AND ENVIRONMENT |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
You will need to have a functioning GnuPG public key setup for this to work, |
262
|
|
|
|
|
|
|
including stored keys or a key retrieval system for your recipients. You will |
263
|
|
|
|
|
|
|
also need a secret key if you want to sign the messages. |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
You should I<definitely not> use your personal key for this; generate one |
266
|
|
|
|
|
|
|
specifically for mail signing and encryption instead. |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
I wrote a tutorial on GnuPG key setup, including agent configuration, as part |
269
|
|
|
|
|
|
|
of this series: |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
L<https://sanctum.geek.nz/arabesque/series/gnu-linux-crypto/> |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=head1 DEPENDENCIES |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
=over 4 |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
=item * |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
Perl v5.8.1 or newer |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=item * |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
L<Carp|Carp> |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
=item * |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
L<English|English> |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
=item * |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
L<IPC::Run3|IPC::Run3> |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
=item * |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
L<Mail::GnuPG|Mail::GnuPG> |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
=item * |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
L<MIME::Entity|MIME::Entity> |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
=back |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
=head1 INCOMPATIBILITIES |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
This module uses L<Mail::GnuPG|Mail::GnuPG> and other GnuPG-specific code, so |
306
|
|
|
|
|
|
|
it won't work with other OpenPGP implementations. |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=head1 BUGS AND LIMITATIONS |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
Definitely. This code is not production-ready. The test suite coverage is still |
311
|
|
|
|
|
|
|
not great, but should improve in newer versions. |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
=head1 AUTHOR |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
Tom Ryder C<< <tom@sanctum.geek.nz> >> |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
Copyright (C) 2017 Tom Ryder |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it under |
322
|
|
|
|
|
|
|
the terms of the Artistic License (2.0). You may obtain a copy of the full |
323
|
|
|
|
|
|
|
license at: |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
L<http://www.perlfoundation.org/artistic_license_2_0> |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
Any use, modification, and distribution of the Standard or Modified Versions is |
328
|
|
|
|
|
|
|
governed by this Artistic License. By using, modifying or distributing the |
329
|
|
|
|
|
|
|
Package, you accept this license. Do not use, modify, or distribute the |
330
|
|
|
|
|
|
|
Package, if you do not accept this license. |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
If your Modified Version has been derived from a Modified Version made by |
333
|
|
|
|
|
|
|
someone other than you, you are nevertheless required to ensure that your |
334
|
|
|
|
|
|
|
Modified Version complies with the requirements of this license. |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
This license does not grant you the right to use any trademark, service mark, |
337
|
|
|
|
|
|
|
tradename, or logo of the Copyright Holder. |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
This license includes the non-exclusive, worldwide, free-of-charge patent |
340
|
|
|
|
|
|
|
license to make, have made, use, offer to sell, sell, import and otherwise |
341
|
|
|
|
|
|
|
transfer the Package with respect to any patent claims licensable by the |
342
|
|
|
|
|
|
|
Copyright Holder that are necessarily infringed by the Package. If you |
343
|
|
|
|
|
|
|
institute patent litigation (including a cross-claim or counterclaim) against |
344
|
|
|
|
|
|
|
any party alleging that the Package constitutes direct or contributory patent |
345
|
|
|
|
|
|
|
infringement, then this Artistic License to you shall terminate on the date |
346
|
|
|
|
|
|
|
that such litigation is filed. |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND |
349
|
|
|
|
|
|
|
CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED |
350
|
|
|
|
|
|
|
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR |
351
|
|
|
|
|
|
|
NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. |
352
|
|
|
|
|
|
|
UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR |
353
|
|
|
|
|
|
|
ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY |
354
|
|
|
|
|
|
|
OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
355
|
|
|
|
|
|
|
DAMAGE. |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
=cut |