line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package LWP::UserAgent::RandomProxyConnect; |
2
|
1
|
|
|
1
|
|
52376
|
use base( "LWP::UserAgent" ); |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
1444
|
|
3
|
1
|
|
|
1
|
|
66307
|
use Data::Dumper; |
|
1
|
|
|
|
|
15244
|
|
|
1
|
|
|
|
|
82
|
|
4
|
1
|
|
|
1
|
|
33
|
use 5.006; |
|
1
|
|
|
|
|
8
|
|
|
1
|
|
|
|
|
33
|
|
5
|
1
|
|
|
1
|
|
5
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
34
|
|
6
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
41
|
|
7
|
|
|
|
|
|
|
our $AUTOLOAD; |
8
|
1
|
|
|
1
|
|
5
|
use Carp; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
926
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
=head1 NAME |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
LWP::UserAgent::RandomProxyConnect - A LWP::UserAgent extension for becoming an omnipresent client. |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head1 VERSION |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
Version 1.10 |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=cut |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
our $VERSION = '1.10'; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=head1 SYNOPSIS |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
This Object does exactly the same than the L class with a |
26
|
|
|
|
|
|
|
new useful feature: it can make each HTTP request throw a different proxy each |
27
|
|
|
|
|
|
|
time. Also, a few methods improve the proxy list management, and makes the iterative |
28
|
|
|
|
|
|
|
connections faster. |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
=head1 CONSTRUCTOR |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=head2 new() |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
When this class is invoked as: |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
my $obj = LWP::UserAgent::RandomProxyConnect->new |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
several test will be made. First, the class must find a valid file with a proxy |
39
|
|
|
|
|
|
|
list, if not, this object will stop. This file must be placed in the environmental |
40
|
|
|
|
|
|
|
variable $ENV{PROXY_LIST}. |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
However, the class can be invoked as: |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
my $obj = LWP::UserAgent::RandomProxyConnect->new(-proxy_list => $proxy_file_path) |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
the created object will search the file at the specified path. |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
Whatever the method you use to invoke the class, the object will |
49
|
|
|
|
|
|
|
stop if the specified file doest not exists, is not readable or there is no proxy |
50
|
|
|
|
|
|
|
found into it. |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
Furthermore, you can add as argument all the properties described at L |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=cut |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
sub new{ |
57
|
|
|
|
|
|
|
|
58
|
0
|
|
|
0
|
1
|
|
my ($class, %arg) = @_; |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
# Extended attributes declaration |
63
|
0
|
|
|
|
|
|
my %def; |
64
|
0
|
0
|
|
|
|
|
$def{proxy_list} = $ENV{PROXY_LIST} unless delete $arg{proxy_list}; |
65
|
0
|
0
|
|
|
|
|
$def{protocol} = "http" unless delete $arg{protocol}; |
66
|
0
|
0
|
|
|
|
|
$def{allowed_protocols} = ["http","https"] unless delete $arg{allowed_protocols}; |
67
|
0
|
|
|
|
|
|
$def{current_proxy} = "????:??"; |
68
|
0
|
|
|
|
|
|
$def{last_proxy} = "????:??"; |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
# Create the SUPER object with the remaining arguments |
71
|
0
|
|
|
|
|
|
my $ua = LWP::UserAgent->new(%arg); |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
# And add the extended attributes |
74
|
0
|
|
|
|
|
|
$ua->{proxy_list} = $def{proxy_list}; |
75
|
0
|
|
|
|
|
|
$ua->{protocol} = $def{protocol}; |
76
|
0
|
|
|
|
|
|
$ua->{allowed_protocols} = $def{allowed_protocols}; |
77
|
0
|
|
|
|
|
|
$ua->{current_proxy} = $def{current_proxy}; |
78
|
0
|
|
|
|
|
|
$ua->{last_proxy} = $def{last_proxy}; |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# Let's load a new "current_proxy". By this way, if there are any errors |
81
|
|
|
|
|
|
|
# the object will stop. |
82
|
0
|
|
|
|
|
|
my $self = bless $ua, $class; |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
# Let's load a random proxy! |
85
|
0
|
|
|
|
|
|
$self->renove_proxy; |
86
|
|
|
|
|
|
|
|
87
|
0
|
|
|
|
|
|
return $self; |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=head1 THE EXTENDED REQUEST METHOD |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
=head2 request |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
This method is exactly the same than LWP::UserAgent->request L |
97
|
|
|
|
|
|
|
with the implemented proxy-change in each request. It obiously make the connection |
98
|
|
|
|
|
|
|
slowler. NOTICE: Only http and https protocols are allowed. |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
=cut |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
sub request |
103
|
|
|
|
|
|
|
{ |
104
|
|
|
|
|
|
|
|
105
|
0
|
|
|
0
|
1
|
|
my($self, $request, $arg, $size, $previous) = @_; |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
# I want to use the same method name to invoke the request, so I am |
108
|
|
|
|
|
|
|
# overriding it in this block. However, I need the original (SUPER) |
109
|
|
|
|
|
|
|
# method to do the request. So I'm going to replicate the object into |
110
|
|
|
|
|
|
|
# a new LWP::UserAgent superclass. |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
# Get the proxy |
114
|
0
|
|
|
|
|
|
my $new_proxy = $self->get_current_proxy; |
115
|
0
|
|
|
|
|
|
my $allowed_protocols = $self->get_allowed_protocols; |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
# Set the proxy in the user agent |
118
|
0
|
|
|
|
|
|
$self->SUPER::proxy($allowed_protocols,$new_proxy); |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
# Set a new proxy for the next connection |
121
|
0
|
|
|
|
|
|
$self->renove_proxy; |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
# Set the "last proxy used" value |
124
|
0
|
|
|
|
|
|
$self->set_last_proxy($new_proxy); |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
# Make the request |
127
|
0
|
|
|
|
|
|
my $response = $self->SUPER::request($request,$arg,$size,$previous); |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
# Return exactly the same than LWP::UserAgeng->request($request) method |
130
|
0
|
|
|
|
|
|
return ($response); |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
# I can't do that, and I don't know why!! |
135
|
|
|
|
|
|
|
# Override the proxy methods |
136
|
|
|
|
|
|
|
#sub proxy{ |
137
|
|
|
|
|
|
|
# my ($self) = @_; |
138
|
|
|
|
|
|
|
# carp(<
|
139
|
|
|
|
|
|
|
#\nWARNING:\nBad class usage: The method LWP::UserAgent::RandomProxyConnect->proxy is incompatible with the philosophy of this class and it has been disabled, the proxy is randomized by this class and it can't be set as static. You can use the LWP::UserAgent class to do it yourself. |
140
|
|
|
|
|
|
|
#The execution continue ignoring this warning. |
141
|
|
|
|
|
|
|
#EOF |
142
|
|
|
|
|
|
|
#} |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=head2 env_proxy |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
This function overrides the original function in order to avoid the static proxy configuration |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=cut |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
sub env_proxy{ |
151
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
152
|
0
|
|
|
|
|
|
carp(<
|
153
|
|
|
|
|
|
|
\nWARNING:\nBad class usage: The method LWP::UserAgent::RandomProxyConnect->env_proxy is incompatible with the philosophy of this class and it has been disabled, the proxy is randomized by this class and it can't be set as static. You can use the LWP::UserAgent class to do it yourself. |
154
|
|
|
|
|
|
|
The execution continue ignoring this warning. |
155
|
|
|
|
|
|
|
EOF |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
As inherited class from LWP::UserAgent, it contains the described attributes at |
162
|
|
|
|
|
|
|
L, but there is some new attributes in this class: |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
=head2 proxy_list (Default value: $ENV{"PROXY_LIST"}) |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
The C attribute contains the string with the proxy list file path. |
167
|
|
|
|
|
|
|
The accessor method: |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
my $proxy_list = $obj->get_proxy_list; |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
returns such string. |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
Also it can be set by the mutator method: |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
$obj->set_proxy_list($new_proxy_list_value); |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=head2 protocols_allowed (Default value: ['http','https']) |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
Protocols allowed to stablish the communication. |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=head2 protocol (Default value: 'http') |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
The protocol used to communicate. e.g.: if the specified protocol is "ftp", |
184
|
|
|
|
|
|
|
the absolute proxy URI will be: |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
ftp://proxy.url.or.ip:port/ |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=cut |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
=head1 METHODS FOR HANDLING THE PROXY LIST |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=head2 renove_proxy |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
This function returns a new random proxy from the list. This return value |
195
|
|
|
|
|
|
|
is a string with the format: :. This is just a query |
196
|
|
|
|
|
|
|
for a single request. |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=cut |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
sub renove_proxy { |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
# This method must handle errors correctly; it is a critical test for |
203
|
|
|
|
|
|
|
# proxy list integrity. |
204
|
|
|
|
|
|
|
|
205
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
206
|
|
|
|
|
|
|
|
207
|
0
|
|
|
|
|
|
open FH, $self->get_proxy_list; |
208
|
0
|
|
|
|
|
|
my @provisional_proxy_list = ; |
209
|
0
|
|
|
|
|
|
close FH; |
210
|
|
|
|
|
|
|
|
211
|
0
|
|
|
|
|
|
my $random_proxy = $provisional_proxy_list[rand @provisional_proxy_list]; |
212
|
0
|
|
|
|
|
|
chomp($random_proxy); |
213
|
0
|
|
|
|
|
|
my $protocol = $self->get_protocol; |
214
|
|
|
|
|
|
|
|
215
|
0
|
|
|
|
|
|
$self->set_current_proxy($protocol."://".$random_proxy); |
216
|
|
|
|
|
|
|
|
217
|
0
|
|
|
|
|
|
return 1; |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
#if(1){ |
220
|
|
|
|
|
|
|
# my $obj_name = ref($self); |
221
|
|
|
|
|
|
|
# croak("The object ".$obj_name." could not load any proxy at ".$self->get_proxy_list."\n"); |
222
|
|
|
|
|
|
|
#} |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
# |
233
|
|
|
|
|
|
|
# The AUTOLOAD method to get/set the class attributes |
234
|
|
|
|
|
|
|
# sub get_attribute {...} |
235
|
|
|
|
|
|
|
# sub set_attribute {...} |
236
|
|
|
|
|
|
|
sub AUTOLOAD{ |
237
|
|
|
|
|
|
|
|
238
|
0
|
|
|
0
|
|
|
my ($self,$newvalue) = @_; |
239
|
|
|
|
|
|
|
|
240
|
0
|
|
|
|
|
|
my ($operation,$attribute) = ($AUTOLOAD =~ /(get|set)_(\w+)$/); |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
# Is this a legal method name? |
243
|
0
|
0
|
0
|
|
|
|
unless($operation && $attribute){ croak "Method name $AUTOLOAD is not the recogniced form (get|set)_attribute\n"; } |
|
0
|
|
|
|
|
|
|
244
|
0
|
0
|
|
|
|
|
unless(exists $self->{$attribute}){ croak "No such attribute '$attribute' exists in the class ", ref($self); } |
|
0
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
# Turn off strict references to enagle magic AUTOLOAD speedup |
247
|
1
|
|
|
1
|
|
7
|
no strict 'refs'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
470
|
|
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
# AUTOLOAD Accessors |
250
|
0
|
0
|
|
|
|
|
if($operation eq 'get'){ |
|
|
0
|
|
|
|
|
|
251
|
|
|
|
|
|
|
# Define subroutine |
252
|
0
|
|
|
0
|
|
|
*{$AUTOLOAD} = sub { shift->{$attribute} }; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
# AUTOLOAD Mutators |
255
|
|
|
|
|
|
|
}elsif($operation eq 'set'){ |
256
|
|
|
|
|
|
|
# Define subroutine ... |
257
|
0
|
|
|
0
|
|
|
*{$AUTOLOAD} = sub { shift->{$attribute} = shift; }; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
# ... and set the new attribute value. |
259
|
0
|
|
|
|
|
|
$self->{$attribute} = $newvalue; |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
# Turn strict references back on |
263
|
1
|
|
|
1
|
|
6
|
use strict 'refs'; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
84
|
|
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
# Return the attribute value |
266
|
0
|
|
|
|
|
|
return $self->{$attribute}; |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
sub DESTROY{ |
271
|
0
|
|
|
0
|
|
|
my $self = @_; |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
__END__ |