line  
 stmt  
 bran  
 cond  
 sub  
 pod  
 time  
 code  
 
1 
 
 
 
 
 
 
 
 
 
 
 
 
 
 package Net::Pavatar;  
 
2 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
3 
 
1
 
 
 
 
 
  
1
   
 
 
 
21289
 
 use warnings;  
 
  
 
1
 
 
 
 
 
 
 
 
 
2
 
    
 
  
 
1
 
 
 
 
 
 
 
 
 
32
 
    
 
4 
 
1
 
 
 
 
 
  
1
   
 
 
 
5
 
 use strict;  
 
  
 
1
 
 
 
 
 
 
 
 
 
1
 
    
 
  
 
1
 
 
 
 
 
 
 
 
 
30
 
    
 
5 
 
1
 
 
 
 
 
  
1
   
 
 
 
5457
 
 use LWPx::ParanoidAgent;  
 
  
 
1
 
 
 
 
 
 
 
 
 
382575
 
    
 
  
 
1
 
 
 
 
 
 
 
 
 
990
 
    
 
6 
 
1
 
 
 
 
 
  
1
   
 
 
 
16
 
 use Carp;  
 
  
 
1
 
 
 
 
 
 
 
 
 
1
 
    
 
  
 
1
 
 
 
 
 
 
 
 
 
474
 
    
 
7 
 
1
 
 
 
 
 
  
1
   
 
 
 
11
 
 use URI;  
 
  
 
1
 
 
 
 
 
 
 
 
 
2
 
    
 
  
 
1
 
 
 
 
 
 
 
 
 
37
 
    
 
8 
 
1
 
 
 
 
 
  
1
   
 
 
 
1005
 
 use GD;  
 
  
 
0
 
 
 
 
 
 
 
 
 
 
 
    
 
  
 
0
 
 
 
 
 
 
 
 
 
 
 
    
 
9 
 
 
 
 
 
 
 
 
 
 
 
 
 
 use Regexp::Common qw /URI/;  
 
10 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
11 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 NAME  
 
12 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
13 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Net::Pavatar - Pavatar client  
 
14 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
15 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 VERSION  
 
16 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
17 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Version 1.01  
 
18 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
19 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
20 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
21 
 
 
 
 
 
 
 
 
 
 
 
 
 
 our $VERSION = '1.01';  
 
22 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
23 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 SYNOPSIS  
 
24 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
25 
 
 
 
 
 
 
 
 
 
 
 
 
 
     use Net::Pavatar;  
 
26 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
27 
 
 
 
 
 
 
 
 
 
 
 
 
 
     my ($hash, $file_type) = Net::Pavatar->fetch( 'http://someblog.com/', { size => [32, 48] } );  
 
28 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
29 
 
 
 
 
 
 
 
 
 
 
 
 
 
     if ($file_type) {  
 
30 
 
 
 
 
 
 
 
 
 
 
 
 
 
         open FILE, ">avatar.$file_type";  
 
31 
 
 
 
 
 
 
 
 
 
 
 
 
 
         print FILE $hash->{'48'};  
 
32 
 
 
 
 
 
 
 
 
 
 
 
 
 
         close FILE;  
 
33 
 
 
 
 
 
 
 
 
 
 
 
 
 
     }  
 
34 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
35 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
36 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
37 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub _browser_get {  
 
38 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $url = shift;  
 
39 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $browser = shift;  
 
40 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
41 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my ($i, $resp) = (0, undef);  
 
42 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	do {  
 
43 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		if ($i++) { sleep(1); }  
 
44 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		$resp = $browser->get($url);  
 
45 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	} until ($i >= 3 or $resp->code <= 499);  
 
46 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	return wantarray ? ($resp, $resp->is_success) : $resp;  
 
47 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
48 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
49 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
50 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 DESCRIPTION  
 
51 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
52 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Fetches a pavatar image from a given URL and gives it to you in the sizes you specify. Uses LWPx::ParanoidAgent to protect your servers from attacks.  
 
53 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
54 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This module fully conforms to Pavatar spec 0.3.0 (L), which is the latest one on Apr 25th, 2007.   
 
55 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
56 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 METHODS  
 
57 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
58 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
59 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
60 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub _discover {  
 
61 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $class = shift;  
 
62 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $url = shift;  
 
63 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $params = shift || {};  
 
64 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
65 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $ua = $params->{'ua'} || LWPx::ParanoidAgent->new( timeout => 15, parse_head => 0 );  
 
66 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my ($resp, $ok) = &_browser_get($url, $ua);  
 
67 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	if (! $ok) { return }  
 
68 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $base = $resp->base();  
 
69 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
70 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	# STEP 3.a of spec  
 
71 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my ($answer) = $resp->header('X-Pavatar');  
 
72 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	if (defined $answer) {  
 
73 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		if ($answer eq 'none' or $answer !~ /$RE{'URI'}{'HTTP'}/) { return }  
 
74 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		return $answer;  
 
75 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	}  
 
76 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
77 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	# STEP 3.b of spec  
 
78 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $page = $resp->content;  
 
79 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	if ($resp->content_type =~ /\b(x?html|xml)\b/) {  
 
80 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		($answer) = $page =~ / 
 
81 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		if (defined $answer) {  
 
82 
 
 
 
 
 
 
 
 
 
 
 
 
 
 			if ($answer eq 'none' or $answer !~ /$RE{'URI'}{'HTTP'}/) { return }  
 
83 
 
 
 
 
 
 
 
 
 
 
 
 
 
 			return $answer;  
 
84 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		}  
 
85 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	}  
 
86 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
87 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	# STEP 3.c of spec  
 
88 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $uri = URI->new($url);  
 
89 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	#my $uri = $resp->request->uri;  
 
90 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	if ($uri->scheme ne 'http') { return; }  
 
91 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	$uri = 'http://'.$uri->host_port.($uri->path || '/');  
 
92 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $pavuri = URI->new_abs('pavatar.png', $uri);  
 
93 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
94 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $max_size = $ua->max_size;  
 
95 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	$ua->max_size(51200);  
 
96 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
97 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	($resp, $ok) = &_browser_get( $pavuri->as_string, $ua );  
 
98 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	if ($ok) { $ua->max_size($max_size); return wantarray ? ($pavuri, $resp) : $pavuri; }  
 
99 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
100 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $did_pavuri = $pavuri->as_string;  
 
101 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	$pavuri->path('/pavatar.png');  
 
102 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
103 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	if ($pavuri->as_string ne $did_pavuri) {  
 
104 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		($resp, $ok) = &_browser_get( $pavuri, $ua );  
 
105 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		if ($ok) { $ua->max_size($max_size); return wantarray ? ($pavuri, $resp) : $pavuri; }  
 
106 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	}  
 
107 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
108 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	$ua->max_size($max_size);  
 
109 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
110 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	return;  
 
111 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
112 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
113 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
114 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
115 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head2 my ($hashref, $type) = Net::Pavatar->fetch( $url, \%opts )  
 
116 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
117 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Returns a hashref and a string, as a 2-list. The hash contains the image sizes as keys, and the image data for each size as values. The string contains the image type and can either be 'jpeg', 'png' or 'gif'. If a pavatar does not exist, or is not valid for any reason, returns null.  
 
118 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
119 
 
 
 
 
 
 
 
 
 
 
 
 
 
 The \%opts hashref is optional, and accepts the following keys:  
 
120 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
121 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C : the sizes that you want the pavatar image returned in - defaults to 80   
 
122 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
123 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C : the total time that UserAgent is allowed to retrieve each page or image - defaults to 15   
 
124 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
125 
 
 
 
 
 
 
 
 
 
 
 
 
 
 e.g. C<< Net::Pavatar->fetch( $url, { size => [32, 48], timeout => 25 } ) >>  
 
126 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
127 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
128 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
129 
 
 
 
 
 
 
 
 
 
 
 
 
 
 sub fetch {  
 
130 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $class = shift;  
 
131 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $url = shift;  
 
132 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $params = shift || {};  
 
133 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
134 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $ua = $params->{'ua'} || LWPx::ParanoidAgent->new( timeout => 15, parse_head => 0 );  
 
135 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	($url, my $resp) = $class->_discover($url, { ua => $ua });  
 
136 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	if (! $url) { return; }  
 
137 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
138 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $max_size = $ua->max_size;  
 
139 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	$ua->max_size(51200);  
 
140 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $ok;  
 
141 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	if (! $resp) {  
 
142 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		($resp, $ok) = &_browser_get($url, $ua);  
 
143 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	} else {  
 
144 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		$ok = 1;  
 
145 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	}  
 
146 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	$ua->max_size($max_size);  
 
147 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	if (! $ok) { return; }  
 
148 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
149 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $type = $resp->content_type;  
 
150 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	($type) = $type =~ /^image\/(.+)$/g;  
 
151 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
152 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $img;  
 
153 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	if ($type eq 'jpeg') {  
 
154 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		$img = GD::Image->newFromJpegData($resp->content, 1);  
 
155 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	} elsif ($type eq 'gif') {  
 
156 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		$img = GD::Image->newFromGifData($resp->content, 1);  
 
157 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	} elsif ($type eq 'png') {  
 
158 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		$img = GD::Image->newFromPngData($resp->content, 1);  
 
159 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	} else {  
 
160 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		return;  
 
161 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	}  
 
162 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	if (! $img) { return; }  
 
163 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
164 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my ($width, $height) = $img->getBounds();  
 
165 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	if ($width != 80 or $height != 80) { return; }  
 
166 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my @sizes;  
 
167 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $size = $params->{'size'};  
 
168 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	if (! defined $size) {  
 
169 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		@sizes = (80);  
 
170 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	} elsif (ref $size eq 'ARRAY') {  
 
171 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		@sizes = grep { /^\d+$/ } @$size;  
 
172 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	} elsif (! ref $size) {  
 
173 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		@sizes = int($size);  
 
174 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	} else {  
 
175 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		confess "Error: sizes parameter needs to be a number or an arrayref";  
 
176 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	}  
 
177 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
178 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	my $return = { };  
 
179 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	foreach my $size (@sizes) {  
 
180 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		if ($size == 80) {  
 
181 
 
 
 
 
 
 
 
 
 
 
 
 
 
 			$return->{'80'} = $resp->content();  
 
182 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		} elsif ($size > 0 and $size < 80) {  
 
183 
 
 
 
 
 
 
 
 
 
 
 
 
 
 			my $newimage = GD::Image->new($size, $size, 1);  
 
184 
 
 
 
 
 
 
 
 
 
 
 
 
 
 			$newimage->copyResampled($img, 0, 0, 0, 0, $size, $size, 80, 80);  
 
185 
 
 
 
 
 
 
 
 
 
 
 
 
 
 			my $data = $newimage->$type();  
 
186 
 
 
 
 
 
 
 
 
 
 
 
 
 
 			$return->{$size} = $data;  
 
187 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		} else {  
 
188 
 
 
 
 
 
 
 
 
 
 
 
 
 
 			confess "Error: problem with size = '$size' (needs to be an integer between 1 and 80 inclusive)";  
 
189 
 
 
 
 
 
 
 
 
 
 
 
 
 
 		}  
 
190 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	}  
 
191 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	if (! keys %$return) { return; }  
 
192 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
193 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	return ($return, $type);  
 
194 
 
 
 
 
 
 
 
 
 
 
 
 
 
 }  
 
195 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
196 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 AUTHOR  
 
197 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
198 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Alexander Karelas, C<<  >>   
 
199 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
200 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 BUGS  
 
201 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
202 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Please report any bugs or feature requests to  
 
203 
 
 
 
 
 
 
 
 
 
 
 
 
 
 C, or through the web interface at   
 
204 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L.   
 
205 
 
 
 
 
 
 
 
 
 
 
 
 
 
 I will be notified, and then you'll automatically be notified of progress on  
 
206 
 
 
 
 
 
 
 
 
 
 
 
 
 
 your bug as I make changes.  
 
207 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
208 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 SUPPORT  
 
209 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
210 
 
 
 
 
 
 
 
 
 
 
 
 
 
 You can find documentation for this module with the perldoc command.  
 
211 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
212 
 
 
 
 
 
 
 
 
 
 
 
 
 
     perldoc Net::Pavatar  
 
213 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
214 
 
 
 
 
 
 
 
 
 
 
 
 
 
 You can also look for information at:  
 
215 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
216 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =over 4  
 
217 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
218 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item * AnnoCPAN: Annotated CPAN documentation  
 
219 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
220 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L   
 
221 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
222 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item * CPAN Ratings  
 
223 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
224 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L   
 
225 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
226 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item * RT: CPAN's request tracker  
 
227 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
228 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L   
 
229 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
230 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item * Search CPAN  
 
231 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
232 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L   
 
233 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
234 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =item * Module's RSS feed  
 
235 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
236 
 
 
 
 
 
 
 
 
 
 
 
 
 
 L   
 
237 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
238 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =back  
 
239 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
240 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 ACKNOWLEDGEMENTS  
 
241 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
242 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =head1 COPYRIGHT & LICENSE  
 
243 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
244 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Copyright 2007 Alexander Karelas, all rights reserved.  
 
245 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
246 
 
 
 
 
 
 
 
 
 
 
 
 
 
 This program is free software; you can redistribute it and/or modify it  
 
247 
 
 
 
 
 
 
 
 
 
 
 
 
 
 under the same terms as Perl itself.  
 
248 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
249 
 
 
 
 
 
 
 
 
 
 
 
 
 
 =cut  
 
250 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
 
251 
 
 
 
 
 
 
 
 
 
 
 
 
 
 1; # End of Net::Pavatar