line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package HTTP::Exception; |
2
|
|
|
|
|
|
|
$HTTP::Exception::VERSION = '0.04007'; |
3
|
27
|
|
|
27
|
|
1011781
|
use strict; |
|
27
|
|
|
|
|
183
|
|
|
27
|
|
|
|
|
569
|
|
4
|
27
|
|
|
27
|
|
100
|
use warnings; |
|
27
|
|
|
|
|
34
|
|
|
27
|
|
|
|
|
492
|
|
5
|
27
|
|
|
27
|
|
9347
|
use HTTP::Status; |
|
27
|
|
|
|
|
88338
|
|
|
27
|
|
|
|
|
4412
|
|
6
|
27
|
|
|
27
|
|
170
|
use Scalar::Util qw(blessed); |
|
27
|
|
|
|
|
35
|
|
|
27
|
|
|
|
|
4988
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
################################################################################ |
9
|
|
|
|
|
|
|
sub import { |
10
|
28
|
|
|
28
|
|
21893
|
my ($class) = shift; |
11
|
28
|
|
|
|
|
8284
|
require HTTP::Exception::Loader; |
12
|
28
|
|
|
|
|
164
|
HTTP::Exception::Loader->import(@_); |
13
|
|
|
|
|
|
|
} |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
# act as a kind of factory here |
16
|
|
|
|
|
|
|
sub new { |
17
|
34
|
|
|
34
|
1
|
18968
|
my $class = shift; |
18
|
34
|
|
|
|
|
48
|
my $error_code = shift; |
19
|
|
|
|
|
|
|
|
20
|
34
|
100
|
|
|
|
82
|
die ('HTTP::Exception->throw needs a HTTP-Statuscode to throw') unless ($error_code); |
21
|
32
|
100
|
|
|
|
130
|
die ("Unknown HTTP-Statuscode: $error_code") unless (HTTP::Status::status_message ($error_code)); |
22
|
|
|
|
|
|
|
|
23
|
30
|
|
|
|
|
328
|
"HTTP::Exception::$error_code"->new(@_); |
24
|
|
|
|
|
|
|
} |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
# makes HTTP::Exception->caught possible instead of HTTP::Exception::Base->caught |
27
|
|
|
|
|
|
|
sub caught { |
28
|
143
|
|
|
143
|
0
|
3607
|
my $self = shift; |
29
|
143
|
|
|
|
|
228
|
my $e = $@; |
30
|
143
|
100
|
100
|
|
|
1161
|
return $e if (blessed $e && $e->isa('HTTP::Exception::Base')); |
31
|
3
|
|
|
|
|
16
|
$self->SUPER::caught(@_); |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
1; |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=head1 NAME |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
HTTP::Exception - throw HTTP-Errors as (Exception::Class-) Exceptions |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
=head1 VERSION |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
version 0.04007 |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
=begin readme |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=head1 INSTALLATION |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
To install this module, run the following commands: |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
perl Build.PL |
52
|
|
|
|
|
|
|
./Build |
53
|
|
|
|
|
|
|
./Build test |
54
|
|
|
|
|
|
|
./Build install |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=end readme |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=head1 SYNOPSIS |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
HTTP::Exception lets you throw HTTP-Errors as Exceptions. |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
use HTTP::Exception; |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
# throw a 404 Exception |
65
|
|
|
|
|
|
|
HTTP::Exception->throw(404); |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
# later in your framework |
68
|
|
|
|
|
|
|
eval { ... }; |
69
|
|
|
|
|
|
|
if (my $e = HTTP::Exception->caught) { |
70
|
|
|
|
|
|
|
# do some errorhandling stuff |
71
|
|
|
|
|
|
|
print $e->code; # 404 |
72
|
|
|
|
|
|
|
print $e->status_message; # Not Found |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
You can also throw HTTP::Exception-subclasses like this. |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# same 404 Exception |
78
|
|
|
|
|
|
|
eval { HTTP::Exception::404->throw(); }; |
79
|
|
|
|
|
|
|
eval { HTTP::Exception::NOT_FOUND->throw(); }; |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
And catch them accordingly. |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
# same 404 Exception |
84
|
|
|
|
|
|
|
eval { HTTP::Exception::404->throw(); }; |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
if (my $e = HTTP::Exception::405->caught) { do stuff } # won't catch |
87
|
|
|
|
|
|
|
if (my $e = HTTP::Exception::404->caught) { do stuff } # will catch |
88
|
|
|
|
|
|
|
if (my $e = HTTP::Exception::NOT_FOUND->caught) { do stuff } # will catch |
89
|
|
|
|
|
|
|
if (my $e = HTTP::Exception::4XX->caught) { do stuff } # will catch all 4XX Exceptions |
90
|
|
|
|
|
|
|
if (my $e = HTTP::Exception->caught) { do stuff } # will catch every HTTP::Exception |
91
|
|
|
|
|
|
|
if (my $e = Exception::Class->caught) { do stuff } # catch'em all |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
You can create Exceptions and not throw them, because maybe you want to set some |
94
|
|
|
|
|
|
|
fields manually. See L and |
95
|
|
|
|
|
|
|
L for more info. |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
# is not thrown, ie doesn't die, only created |
98
|
|
|
|
|
|
|
my $e = HTTP::Exception->new(404); |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
# usual stuff works |
101
|
|
|
|
|
|
|
$e->code; # 404 |
102
|
|
|
|
|
|
|
$e->status_message # Not Found |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
# set status_message to something else |
105
|
|
|
|
|
|
|
$e->status_message('Nothing Here') |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# fails, because code is only an accessor, see section ACCESSORS below |
108
|
|
|
|
|
|
|
# $e->code(403); |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
# and finally throw our prepared exception |
111
|
|
|
|
|
|
|
$e->throw; |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=head1 DESCRIPTION |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
Every HTTP::Exception is a L - Class. So the same mechanisms |
116
|
|
|
|
|
|
|
apply as with L-classes. In fact have a look at |
117
|
|
|
|
|
|
|
L' docs for more general information on exceptions and |
118
|
|
|
|
|
|
|
L for information on what methods a caught exception |
119
|
|
|
|
|
|
|
also has. |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
HTTP::Exception is only a factory for HTTP::Exception::XXX (where X is a number) |
122
|
|
|
|
|
|
|
subclasses. That means that HTTP::Exception->new(404) returns a |
123
|
|
|
|
|
|
|
HTTP::Exception::404 object, which in turn is a HTTP::Exception::Base - Object. |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
Don't bother checking a caught HTTP::Exception::...-class with "isa" as it might |
126
|
|
|
|
|
|
|
not contain what you would expect. Use the code- or status_message-attributes |
127
|
|
|
|
|
|
|
and the is_ -methods instead. |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
The subclasses are created at compile-time, ie the first time you make |
130
|
|
|
|
|
|
|
"use HTTP::Exception". See paragraph below for the naming scheme of those |
131
|
|
|
|
|
|
|
subclasses. |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
Subclassing the subclasses works as expected. |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=head1 NAMING SCHEME |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=head2 HTTP::Exception::XXX |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
X is a Number and XXX is a valid HTTP-Statuscode. All HTTP-Statuscodes are |
140
|
|
|
|
|
|
|
supported. See chapter L |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=head2 HTTP::Exception::STATUS_MESSAGE |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
STATUS_MESSAGE is the same name as a L Constant B |
145
|
|
|
|
|
|
|
the HTTP_ at the beginning. So see L for more details. |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=head1 IMPORTING SPECIFIC ERROR RANGES |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
It is possible to load only specific ranges of errors. For example |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
use HTTP::Exception qw(5XX); |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
HTTP::Exception::500->throw; # works |
154
|
|
|
|
|
|
|
HTTP::Exception::400->throw; # won't work anymore |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
will only create HTTP::Exception::500 till HTTP::Exception::510. In theory this |
157
|
|
|
|
|
|
|
should save some memory, but I don't have any numbers, that back up this claim. |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
You can load multiple ranges |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
use HTTP::Exception qw(3XX 4XX 5XX); |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
And there are aliases for ranges |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
use HTTP::Exception qw(CLIENT_ERROR) |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
The following aliases exist and load the specified ranges: |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
REDIRECTION => 3XX |
170
|
|
|
|
|
|
|
CLIENT_ERROR => 4XX |
171
|
|
|
|
|
|
|
SERVER_ERROR => 5XX |
172
|
|
|
|
|
|
|
ERROR => 4XX 5XX |
173
|
|
|
|
|
|
|
ALL => 1XX 2XX 3XX 4XX 5XX |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
And of course, you can load multiple aliased ranges |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
use HTTP::Exception qw(REDIRECTION ERROR) |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
ALL is the same as not specifying any specific range. |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
# the same |
182
|
|
|
|
|
|
|
use HTTP::Exception qw(ALL); |
183
|
|
|
|
|
|
|
use HTTP::Exception; |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
=head1 ACCESSORS (READONLY) |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
=head2 code |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
A valid HTTP-Statuscode. See L for information on what codes exist. |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=head2 is_info |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
Return TRUE if C<$self->code> is an I status code (1xx). This |
194
|
|
|
|
|
|
|
class of status code indicates a provisional response which can't have |
195
|
|
|
|
|
|
|
any content. |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
=head2 is_success |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
Return TRUE if C<$self->code> is a I status code (2xx). |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=head2 is_redirect |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
Return TRUE if C<$self->code> is a I status code (3xx). This class |
204
|
|
|
|
|
|
|
if status code indicates that further action needs to be taken by the |
205
|
|
|
|
|
|
|
user agent in order to fulfill the request. |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=head2 is_error |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
Return TRUE if C<$self->code> is an I status code (4xx or 5xx). The |
210
|
|
|
|
|
|
|
function return TRUE for both client error or a server error status codes. |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
=head2 is_client_error |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
Return TRUE if C<$self->code> is an I status code (4xx). This |
215
|
|
|
|
|
|
|
class of status code is intended for cases in which the client seems to |
216
|
|
|
|
|
|
|
have erred. |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
=head2 is_server_error |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
Return TRUE if C<$self->code> is an I status code (5xx). This |
221
|
|
|
|
|
|
|
class of status codes is intended for cases in which the server is aware |
222
|
|
|
|
|
|
|
that it has erred or is incapable of performing the request. |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
I, so check back there and |
225
|
|
|
|
|
|
|
alert me of changes.> |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
=head1 FIELDS |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
Fields are the same as ACCESSORS except they can be set. Either you set them |
230
|
|
|
|
|
|
|
during Exception creation (->new) or Exception throwing (->throw). |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
HTTP::Exception->new(200, status_message => "Everything's fine"); |
233
|
|
|
|
|
|
|
HTTP::Exception::200->new(status_message => "Everything's fine"); |
234
|
|
|
|
|
|
|
HTTP::Exception::OK->new(status_message => "Everything's fine"); |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
HTTP::Exception->throw(200, status_message => "Everything's fine"); |
237
|
|
|
|
|
|
|
HTTP::Exception::200->throw(status_message => "Everything's fine"); |
238
|
|
|
|
|
|
|
HTTP::Exception::OK->throw(status_message => "Everything's fine"); |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
Catch them in your Webframework like this |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
eval { ... } |
243
|
|
|
|
|
|
|
if (my $e = HTTP::Exception->caught) { |
244
|
|
|
|
|
|
|
print $e->code; # 200 |
245
|
|
|
|
|
|
|
print $e->status_message # "Everything's fine" instead of the usual ok |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
=head2 status_message |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
B The HTTP-Statusmessage as provided by L |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
A Message, that represents the Execptions' Status for Humans. |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
=head1 PLACK |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
HTTP::Exception can be used with L. But |
257
|
|
|
|
|
|
|
HTTP::Exception does not depend on L, you can use it anywhere else. It |
258
|
|
|
|
|
|
|
just plays nicely with L. |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
=head1 COMPLETENESS |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
For the sake of completeness, HTTP::Exception provides exceptions for |
263
|
|
|
|
|
|
|
non-error-http-statuscodes. This means you can do |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
HTTP::Exception->throw(200); |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
which throws an Exception of type OK. Maybe useless, but complete. |
268
|
|
|
|
|
|
|
A more realworld-example would be a redirection |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
# all are exactly the same |
271
|
|
|
|
|
|
|
HTTP::Exception->throw(301, location => 'google.com'); |
272
|
|
|
|
|
|
|
HTTP::Exception::301->throw(location => 'google.com'); |
273
|
|
|
|
|
|
|
HTTP::Exception::MOVED_PERMANENTLY->throw(location => 'google.com'); |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
=head1 CAVEATS |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
The HTTP::Exception-Subclass-Creation relies on L. |
278
|
|
|
|
|
|
|
It's possible that the Subclasses change, when HTTP::Status' |
279
|
|
|
|
|
|
|
constants are changed. |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
New Subclasses are created automatically, when constants are added to |
282
|
|
|
|
|
|
|
HTTP::Status. That means in turn, that Subclasses disappear, when constants |
283
|
|
|
|
|
|
|
are removed from L. |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
Some constants were added to L' in February 2012. As a result |
286
|
|
|
|
|
|
|
HTTP::Exception broke. But that was the result of uncareful coding on my side. |
287
|
|
|
|
|
|
|
I think, that breaking changes are now quite unlikely. |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
=head1 AUTHOR |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
Thomas Mueller, C<< >> |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
=head1 SEE ALSO |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
=head2 L, L |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
Consult Exception::Class' documentation for the Exception-Mechanism and |
298
|
|
|
|
|
|
|
Exception::Class::Base' docs for a list of methods our caught Exception is also |
299
|
|
|
|
|
|
|
capable of. |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
=head2 L |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
Constants, Statuscodes and Statusmessages |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
=head2 L, built on top of the more modern L framework (the successor to L) |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
=head2 L, especially L |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
Have a look at Plack, because it rules in general. In the first place, this |
310
|
|
|
|
|
|
|
Module was written as the companion for L, |
311
|
|
|
|
|
|
|
but since it doesn't depend on Plack, you can use it anywhere else, too. |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
=head1 BUGS |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
Please report any bugs or feature requests to |
316
|
|
|
|
|
|
|
C, or through the web interface at |
317
|
|
|
|
|
|
|
L. |
318
|
|
|
|
|
|
|
I will be notified, and then you'll automatically be notified of progress on |
319
|
|
|
|
|
|
|
your bug as I make changes. |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
=head1 SUPPORT |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
perldoc HTTP::Exception |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
You can also look for information at: |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
=over 4 |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
L |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
L |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
=item * CPAN Ratings |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
L |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
=item * Search CPAN |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
L |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
=back |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
Copyright 2010 Thomas Mueller. |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
354
|
|
|
|
|
|
|
under the terms of either: the GNU General Public License as published |
355
|
|
|
|
|
|
|
by the Free Software Foundation; or the Artistic License. |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
See http://dev.perl.org/licenses/ for more information. |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
=cut |