line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Moxy; |
2
|
14
|
|
|
14
|
|
269431
|
use 5.00800; |
|
14
|
|
|
|
|
55
|
|
|
14
|
|
|
|
|
550
|
|
3
|
14
|
|
|
14
|
|
71
|
use strict; |
|
14
|
|
|
|
|
23
|
|
|
14
|
|
|
|
|
498
|
|
4
|
14
|
|
|
14
|
|
78
|
use warnings; |
|
14
|
|
|
|
|
38
|
|
|
14
|
|
|
|
|
459
|
|
5
|
14
|
|
|
14
|
|
73
|
use base qw/Class::Accessor::Fast/; |
|
14
|
|
|
|
|
23
|
|
|
14
|
|
|
|
|
16824
|
|
6
|
14
|
|
|
14
|
|
72174
|
use Class::Component 0.16; |
|
14
|
|
|
|
|
267723
|
|
|
14
|
|
|
|
|
117
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION = '0.70'; |
9
|
|
|
|
|
|
|
|
10
|
14
|
|
|
14
|
|
1371
|
use Carp; |
|
14
|
|
|
|
|
25
|
|
|
14
|
|
|
|
|
1107
|
|
11
|
14
|
|
|
14
|
|
15604
|
use Encode; |
|
14
|
|
|
|
|
196351
|
|
|
14
|
|
|
|
|
1377
|
|
12
|
14
|
|
|
14
|
|
13719
|
use File::Spec::Functions; |
|
14
|
|
|
|
|
13066
|
|
|
14
|
|
|
|
|
1273
|
|
13
|
14
|
|
|
14
|
|
89
|
use File::Basename; |
|
14
|
|
|
|
|
28
|
|
|
14
|
|
|
|
|
1332
|
|
14
|
14
|
|
|
14
|
|
13028
|
use FindBin; |
|
14
|
|
|
|
|
16172
|
|
|
14
|
|
|
|
|
623
|
|
15
|
14
|
|
|
14
|
|
14712
|
use HTML::Entities; |
|
14
|
|
|
|
|
107609
|
|
|
14
|
|
|
|
|
1609
|
|
16
|
14
|
|
|
14
|
|
128
|
use HTML::Parser; |
|
14
|
|
|
|
|
22
|
|
|
14
|
|
|
|
|
178
|
|
17
|
14
|
|
|
14
|
|
15704
|
use HTML::TreeBuilder::XPath; |
|
14
|
|
|
|
|
1110087
|
|
|
14
|
|
|
|
|
183
|
|
18
|
14
|
|
|
14
|
|
619
|
use HTML::TreeBuilder; |
|
14
|
|
|
|
|
34
|
|
|
14
|
|
|
|
|
108
|
|
19
|
14
|
|
|
14
|
|
15231
|
use HTTP::Cookies; |
|
14
|
|
|
|
|
216330
|
|
|
14
|
|
|
|
|
228
|
|
20
|
14
|
|
|
14
|
|
12217
|
use HTTP::Session; |
|
14
|
|
|
|
|
64827
|
|
|
14
|
|
|
|
|
133
|
|
21
|
14
|
|
|
14
|
|
18636
|
use LWP::UserAgent; |
|
14
|
|
|
|
|
625900
|
|
|
14
|
|
|
|
|
215
|
|
22
|
14
|
|
|
14
|
|
14802
|
use MIME::Base64; |
|
14
|
|
|
|
|
21198
|
|
|
14
|
|
|
|
|
1093
|
|
23
|
14
|
|
|
14
|
|
8134
|
use Moxy::Util; |
|
14
|
|
|
|
|
51
|
|
|
14
|
|
|
|
|
232
|
|
24
|
14
|
|
|
14
|
|
18429
|
use Params::Validate ':all'; |
|
14
|
|
|
|
|
127974
|
|
|
14
|
|
|
|
|
3415
|
|
25
|
14
|
|
|
14
|
|
12535
|
use Path::Class; |
|
14
|
|
|
|
|
784953
|
|
|
14
|
|
|
|
|
1121
|
|
26
|
14
|
|
|
14
|
|
217
|
use Scalar::Util qw/blessed/; |
|
14
|
|
|
|
|
35
|
|
|
14
|
|
|
|
|
758
|
|
27
|
14
|
|
|
14
|
|
127
|
use UNIVERSAL::require; |
|
14
|
|
|
|
|
33
|
|
|
14
|
|
|
|
|
133
|
|
28
|
14
|
|
|
14
|
|
300
|
use URI::Escape; |
|
14
|
|
|
|
|
32
|
|
|
14
|
|
|
|
|
865
|
|
29
|
14
|
|
|
14
|
|
14051
|
use URI::Heuristic qw(uf_uristr); |
|
14
|
|
|
|
|
40222
|
|
|
14
|
|
|
|
|
1024
|
|
30
|
14
|
|
|
14
|
|
136
|
use URI; |
|
14
|
|
|
|
|
30
|
|
|
14
|
|
|
|
|
204
|
|
31
|
14
|
|
|
14
|
|
12579
|
use YAML; |
|
14
|
|
|
|
|
112469
|
|
|
14
|
|
|
|
|
885
|
|
32
|
14
|
|
|
14
|
|
14285
|
use Time::HiRes (); |
|
14
|
|
|
|
|
27769
|
|
|
14
|
|
|
|
|
422
|
|
33
|
14
|
|
|
14
|
|
12626
|
use Plack::Response; |
|
14
|
|
|
|
|
37401
|
|
|
14
|
|
|
|
|
197
|
|
34
|
14
|
|
|
14
|
|
8080
|
use Moxy::Request; |
|
14
|
|
|
|
|
59
|
|
|
14
|
|
|
|
|
163
|
|
35
|
14
|
|
|
14
|
|
14008
|
use HTTP::Message::PSGI; |
|
14
|
|
|
|
|
82481
|
|
|
14
|
|
|
|
|
877
|
|
36
|
14
|
|
|
14
|
|
197
|
use File::Temp; |
|
14
|
|
|
|
|
31
|
|
|
14
|
|
|
|
|
1303
|
|
37
|
14
|
|
|
14
|
|
76
|
use File::Spec; |
|
14
|
|
|
|
|
28
|
|
|
14
|
|
|
|
|
106
|
|
38
|
14
|
|
|
|
|
212
|
use HTTP::MobileAttribute plugins => [ |
39
|
|
|
|
|
|
|
qw/CarrierLetter IS/, |
40
|
|
|
|
|
|
|
{ |
41
|
|
|
|
|
|
|
module => 'Display', |
42
|
|
|
|
|
|
|
config => { |
43
|
|
|
|
|
|
|
DoCoMoMap => YAML::LoadFile( |
44
|
|
|
|
|
|
|
catfile( 'assets', 'common', 'docomo-display-map.yaml' ) |
45
|
|
|
|
|
|
|
) |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
}, |
48
|
14
|
|
|
14
|
|
13614
|
]; |
|
14
|
|
|
|
|
681317
|
|
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
__PACKAGE__->load_components(qw/Plaggerize Autocall::InjectMethod Context/); |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
__PACKAGE__->load_plugins(qw/ |
53
|
|
|
|
|
|
|
DisplayWidth ControlPanel LocationBar Pictogram |
54
|
|
|
|
|
|
|
Status::401 Status::500 Status::404 |
55
|
|
|
|
|
|
|
UserID XMLisHTML UserAgentSwitcher RefererCutter CookieCutter FlashUseImgTag |
56
|
|
|
|
|
|
|
DisableTableTag GPS HTTPHeader QRCode ShowHTTPHeaders |
57
|
|
|
|
|
|
|
/); |
58
|
|
|
|
|
|
|
__PACKAGE__->mk_accessors(qw/response_time/); |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
sub new { |
61
|
11
|
|
|
11
|
1
|
263855
|
my ($class, $config) = @_; |
62
|
|
|
|
|
|
|
|
63
|
11
|
50
|
|
|
|
79
|
if ( $config->{global}->{plugins} ) { |
64
|
0
|
|
|
|
|
0
|
$class->load_plugins(@{ $config->{global}->{plugins} }); |
|
0
|
|
|
|
|
0
|
|
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
|
67
|
11
|
|
100
|
|
|
469
|
$config->{global}->{log}->{level} ||= 'info'; |
68
|
|
|
|
|
|
|
|
69
|
11
|
|
66
|
|
|
270
|
$config->{global}->{assets_path} ||= do { |
70
|
9
|
|
|
|
|
34
|
my $libpath = $INC{'Moxy.pm'}; |
71
|
9
|
|
|
|
|
264
|
$libpath =~ s!(?:blib/)?lib/+Moxy\.pm$!!; |
72
|
9
|
|
50
|
|
|
44
|
$libpath ||= './'; |
73
|
9
|
|
|
|
|
1006
|
$libpath = File::Spec->rel2abs($libpath); |
74
|
9
|
|
|
|
|
464
|
File::Spec->catdir($libpath, 'assets'); |
75
|
|
|
|
|
|
|
}; |
76
|
|
|
|
|
|
|
|
77
|
11
|
|
|
|
|
644
|
my $self = $class->NEXT( 'new' => { config => $config } ); |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
$self->conf->{global}->{session}->{store} ||= +{ |
80
|
|
|
|
|
|
|
module => 'File', |
81
|
|
|
|
|
|
|
config => { |
82
|
0
|
|
0
|
|
|
0
|
dir => do { |
83
|
0
|
|
|
|
|
0
|
my $dir = File::Temp::tempdir('moxyXXXXXX', CLEANUP => 1, DIR => File::Spec->tmpdir); |
84
|
0
|
|
|
|
|
0
|
$self->{__session} = $dir; |
85
|
0
|
|
|
|
|
0
|
"$dir", # we need stringify for file::temp |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
}, |
88
|
|
|
|
|
|
|
}; |
89
|
|
|
|
|
|
|
|
90
|
0
|
|
0
|
|
|
0
|
$self->conf->{global}->{log}->{fh} ||= \*STDERR; |
91
|
|
|
|
|
|
|
|
92
|
0
|
|
|
|
|
0
|
return $self; |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
0
|
|
|
0
|
0
|
0
|
sub assets_path { shift->conf->{global}->{assets_path} } |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
sub res { |
98
|
0
|
|
|
0
|
0
|
0
|
Plack::Response->new(@_); |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
sub HTTP::Response::to_plack_response { |
101
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
102
|
0
|
|
|
|
|
0
|
return res( |
103
|
|
|
|
|
|
|
$self->code, |
104
|
|
|
|
|
|
|
$self->headers, |
105
|
|
|
|
|
|
|
$self->content, |
106
|
|
|
|
|
|
|
); |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# ------------------------------------------------------------------------- |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
sub run_hook_and_get_response { |
112
|
0
|
|
|
0
|
0
|
0
|
my ($self, $hook, @args) = @_; |
113
|
|
|
|
|
|
|
|
114
|
0
|
|
|
|
|
0
|
$self->log(debug => "Run hook and get response: $hook"); |
115
|
0
|
|
|
|
|
0
|
for my $action (@{$self->class_component_hooks->{$hook}}) { |
|
0
|
|
|
|
|
0
|
|
116
|
0
|
|
|
|
|
0
|
my $code = $action->{plugin}->can($action->{method}); |
117
|
0
|
|
|
|
|
0
|
my $response = $code->($action->{plugin}, $self, @args); |
118
|
0
|
0
|
0
|
|
|
0
|
return $response if blessed $response && $response->isa('HTTP::Response'); |
119
|
|
|
|
|
|
|
} |
120
|
0
|
|
|
|
|
0
|
return; # not finished yet |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
sub rewrite_css { |
124
|
2
|
|
|
2
|
0
|
10138
|
my ($base, $css, $url) = @_; |
125
|
2
|
|
|
|
|
15
|
my $base_url = URI->new($url); |
126
|
|
|
|
|
|
|
|
127
|
2
|
|
|
|
|
8514
|
$css =~ s{url\(([^\)]+)\)}{ |
128
|
2
|
|
|
|
|
6
|
my $x = $1; |
129
|
2
|
50
|
|
|
|
173
|
sprintf "url(%s%s%s)", |
130
|
|
|
|
|
|
|
$base, |
131
|
|
|
|
|
|
|
($base =~ m{/$} ? '' : '/'), |
132
|
|
|
|
|
|
|
uri_escape( URI->new($x)->abs($base_url) ) |
133
|
|
|
|
|
|
|
}ge; |
134
|
|
|
|
|
|
|
|
135
|
2
|
|
|
|
|
3469
|
$css; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
sub rewrite_html { |
139
|
12
|
|
|
12
|
0
|
27824
|
my ($base, $html, $url) = @_; |
140
|
|
|
|
|
|
|
|
141
|
12
|
|
|
|
|
53
|
my $base_url = URI->new($url); |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
# parse. |
144
|
12
|
|
|
|
|
9812
|
my $tree = HTML::TreeBuilder::XPath->new; |
145
|
12
|
|
|
|
|
2425
|
$tree->implicit_tags(0); |
146
|
12
|
|
|
|
|
117
|
$tree->no_space_compacting(1); |
147
|
12
|
|
|
|
|
100
|
$tree->ignore_ignorable_whitespace(0); |
148
|
12
|
|
|
|
|
87
|
$tree->store_comments(1); |
149
|
12
|
|
|
|
|
96
|
$tree->ignore_unknown(0); |
150
|
12
|
|
|
|
|
229
|
$tree->parse($html); |
151
|
12
|
|
|
|
|
2181
|
$tree->eof; |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
# define replacer. |
154
|
|
|
|
|
|
|
my $replace = sub { |
155
|
72
|
|
|
72
|
|
98
|
my ( $tag, $attr_name ) = @_; |
156
|
|
|
|
|
|
|
|
157
|
72
|
|
|
|
|
226
|
for my $node ( $tree->findnodes("//$tag") ) { |
158
|
11
|
100
|
|
|
|
5897
|
if ( my $attr = $node->attr($attr_name) ) { |
159
|
10
|
100
|
|
|
|
476
|
next if $attr =~ /^mailto:/; |
160
|
9
|
100
|
|
|
|
25
|
if ($attr =~ /^tel:([0-9-]+)$/) { |
161
|
1
|
|
|
|
|
4
|
my $tel = $1; |
162
|
1
|
|
|
|
|
174
|
$node->attr( |
163
|
|
|
|
|
|
|
'onclick' => qq{prompt('tel', '$1');return false;} |
164
|
|
|
|
|
|
|
); |
165
|
|
|
|
|
|
|
} else { |
166
|
|
|
|
|
|
|
# maybe /https?/ |
167
|
8
|
|
|
|
|
29
|
my $target_url = URI->new($attr); |
168
|
8
|
50
|
|
|
|
505
|
$target_url = $target_url->abs($base_url) if $base_url; |
169
|
8
|
50
|
|
|
|
938
|
$node->attr( |
170
|
|
|
|
|
|
|
$attr_name => sprintf( qq{%s%s%s}, |
171
|
|
|
|
|
|
|
$base, |
172
|
|
|
|
|
|
|
($base =~ m{/$} ? '' : '/'), |
173
|
|
|
|
|
|
|
uri_escape( $target_url ) ) |
174
|
|
|
|
|
|
|
); |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
} |
178
|
12
|
|
|
|
|
1319
|
}; |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
# replace. |
181
|
12
|
|
|
|
|
26
|
$replace->( 'img' => 'src' ); |
182
|
12
|
|
|
|
|
5385
|
$replace->( 'script' => 'src' ); |
183
|
12
|
|
|
|
|
4014
|
$replace->( 'form' => 'action' ); |
184
|
12
|
|
|
|
|
3455
|
$replace->( 'a' => 'href' ); |
185
|
12
|
|
|
|
|
2090
|
$replace->( 'link' => 'href' ); |
186
|
12
|
|
|
|
|
7565
|
$replace->( 'object' => 'data' ); |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
# dump. |
189
|
12
|
|
|
|
|
4088
|
my $result = ''; |
190
|
12
|
|
|
|
|
43
|
for my $elm ($tree->guts) { |
191
|
24
|
100
|
|
|
|
3498
|
$result .= ref $elm ? $elm->as_HTML(q{<>"&'}, '', {}) : $elm; |
192
|
|
|
|
|
|
|
} |
193
|
12
|
|
|
|
|
52
|
$tree->delete; # cleanup :-) HTML::TreeBuilder needs this. |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
# return result. |
196
|
12
|
50
|
|
|
|
459
|
$result = ''.$result.'' unless $result =~ /<\s*html/; |
197
|
12
|
|
|
|
|
221
|
return $result; |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
sub to_app { |
201
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
202
|
|
|
|
|
|
|
sub { |
203
|
0
|
|
|
0
|
|
|
my $env = shift; |
204
|
0
|
|
|
|
|
|
my $req = Moxy::Request->new($env); |
205
|
0
|
|
|
|
|
|
my $res = $self->handle_request($req); |
206
|
0
|
|
|
|
|
|
$res->content_length( length($res->content) ); # adjust content-length. |
207
|
0
|
|
|
|
|
|
$res->finalize(); |
208
|
0
|
|
|
|
|
|
}; |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
sub handle_request { |
212
|
0
|
|
|
0
|
0
|
|
my ($self, $req) = @_; |
213
|
|
|
|
|
|
|
|
214
|
0
|
|
|
|
|
|
$self->log(debug => "---------------------------"); |
215
|
|
|
|
|
|
|
|
216
|
0
|
|
|
|
|
|
my $conf = $self->conf->{global}->{session}; |
217
|
0
|
|
0
|
|
|
|
my $state_type = $conf->{state}->{module} || 'BasicAuth'; |
218
|
|
|
|
|
|
|
my $state = sub { |
219
|
0
|
0
|
|
0
|
|
|
if ($state_type eq 'Cookie') { |
220
|
0
|
|
|
|
|
|
require HTTP::Session::State::Cookie; |
221
|
0
|
|
|
|
|
|
HTTP::Session::State::Cookie->new( |
222
|
|
|
|
|
|
|
$conf->{state}->{config} |
223
|
|
|
|
|
|
|
); |
224
|
|
|
|
|
|
|
} else { |
225
|
0
|
|
|
|
|
|
require Moxy::Session::State::BasicAuth; |
226
|
0
|
|
0
|
|
|
|
Moxy::Session::State::BasicAuth->new( |
227
|
|
|
|
|
|
|
$conf->{state}->{config} || {} |
228
|
|
|
|
|
|
|
); |
229
|
|
|
|
|
|
|
} |
230
|
0
|
|
|
|
|
|
}->(); |
231
|
|
|
|
|
|
|
my $store = sub { |
232
|
0
|
0
|
|
0
|
|
|
my $postfix = $conf->{store}->{module} or die "missing session store module name"; |
233
|
0
|
|
|
|
|
|
my $klass = "HTTP::Session::Store::${postfix}"; |
234
|
0
|
0
|
|
|
|
|
$klass->require or die $@; |
235
|
0
|
|
|
|
|
|
$klass->new( $conf->{store}->{config} ); |
236
|
0
|
|
|
|
|
|
}->(); |
237
|
|
|
|
|
|
|
|
238
|
0
|
|
|
|
|
|
my $auth = join(',', $req->headers->authorization_basic); |
239
|
0
|
0
|
0
|
|
|
|
if ($state->isa('Moxy::Session::State::BasicAuth') && !$auth) { |
240
|
0
|
|
|
|
|
|
$self->log(debug => 'basicauth'); |
241
|
0
|
|
|
|
|
|
return res( |
242
|
|
|
|
|
|
|
401, |
243
|
|
|
|
|
|
|
[ |
244
|
|
|
|
|
|
|
WWW_Authenticate => qq{Basic realm="Moxy needs basic auth.Only for identification.Password is dummy."}, |
245
|
|
|
|
|
|
|
], |
246
|
|
|
|
|
|
|
'authentication required', |
247
|
|
|
|
|
|
|
); |
248
|
|
|
|
|
|
|
} else { |
249
|
0
|
|
|
|
|
|
$self->log(debug => "session: state: $state, store: $store"); |
250
|
0
|
|
|
|
|
|
my $session = HTTP::Session->new( |
251
|
|
|
|
|
|
|
state => $state, |
252
|
|
|
|
|
|
|
store => $store, |
253
|
|
|
|
|
|
|
request => $req, |
254
|
|
|
|
|
|
|
); |
255
|
0
|
|
|
|
|
|
$self->log(debug => "session: $session"); |
256
|
0
|
|
|
|
|
|
my $res = $self->_make_response( |
257
|
|
|
|
|
|
|
req => $req, |
258
|
|
|
|
|
|
|
session => $session, |
259
|
|
|
|
|
|
|
); |
260
|
0
|
|
|
|
|
|
$session->response_filter($res); |
261
|
0
|
|
|
|
|
|
$session->finalize; |
262
|
|
|
|
|
|
|
|
263
|
0
|
|
|
|
|
|
return $res; |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
sub _make_response { |
268
|
0
|
|
|
0
|
|
|
my $self = shift; |
269
|
0
|
|
|
|
|
|
my %args = validate( |
270
|
|
|
|
|
|
|
@_ => +{ |
271
|
|
|
|
|
|
|
req => { isa => 'Moxy::Request', }, |
272
|
|
|
|
|
|
|
session => { type => OBJECT }, |
273
|
|
|
|
|
|
|
} |
274
|
|
|
|
|
|
|
); |
275
|
0
|
|
|
|
|
|
my $req = $args{req}; |
276
|
|
|
|
|
|
|
|
277
|
0
|
|
|
|
|
|
my $base = $req->uri->clone; |
278
|
0
|
|
|
|
|
|
$base->path(''); |
279
|
0
|
|
|
|
|
|
$base->query_form({}); |
280
|
|
|
|
|
|
|
|
281
|
0
|
|
|
|
|
|
(my $url = $req->uri->path_query) =~ s!^/!!; |
282
|
0
|
|
|
|
|
|
$url = uf_uristr(uri_unescape($url)); |
283
|
|
|
|
|
|
|
|
284
|
0
|
0
|
|
|
|
|
if ($url) { |
285
|
|
|
|
|
|
|
# do proxy |
286
|
0
|
|
|
|
|
|
my $res = $self->_do_request( |
287
|
|
|
|
|
|
|
url => $url, |
288
|
|
|
|
|
|
|
request => $req->as_http_request, |
289
|
|
|
|
|
|
|
session => $args{session}, |
290
|
|
|
|
|
|
|
); |
291
|
0
|
|
|
|
|
|
$self->log(debug => '-- response status: ' . $res->code); |
292
|
|
|
|
|
|
|
|
293
|
0
|
0
|
|
|
|
|
if ($res->code == 302) { |
294
|
|
|
|
|
|
|
# rewrite redirect |
295
|
0
|
|
|
|
|
|
my $location = URI->new($res->header('Location')); |
296
|
0
|
|
|
|
|
|
$self->log(debug => "redirect to $location"); |
297
|
0
|
|
|
|
|
|
my $uri = URI->new($url); |
298
|
0
|
0
|
|
|
|
|
if (not defined $location->scheme) { |
299
|
|
|
|
|
|
|
# path only redirect is invalid! |
300
|
|
|
|
|
|
|
# e.g. Location: /foo/ |
301
|
0
|
|
|
|
|
|
$self->log(error => "----------------------------"); |
302
|
0
|
|
|
|
|
|
$self->log(error => "INVALID REDIRECT!! $location"); |
303
|
0
|
|
|
|
|
|
$self->log(error => "----------------------------"); |
304
|
0
|
|
|
|
|
|
$location = URI->new( $location->as_string, $uri->scheme ); |
305
|
0
|
|
|
|
|
|
$location->scheme($uri->scheme); |
306
|
0
|
|
|
|
|
|
$location->host($uri->host); |
307
|
0
|
|
|
|
|
|
$location->port($uri->port); |
308
|
0
|
|
|
|
|
|
$self->log(error => "FIXED TO: $location"); |
309
|
0
|
|
|
|
|
|
$self->log(error => "----------------------------"); |
310
|
|
|
|
|
|
|
} else { |
311
|
0
|
0
|
0
|
|
|
|
if ($uri->port != 80 && $location->port != $uri->port) { |
312
|
0
|
|
|
|
|
|
$location->port($uri->port); |
313
|
|
|
|
|
|
|
} |
314
|
|
|
|
|
|
|
} |
315
|
0
|
|
|
|
|
|
my $redirect = $base . '/' . uri_escape($location); |
316
|
0
|
|
|
|
|
|
$self->log(debug => "redirect to $redirect"); |
317
|
0
|
|
|
|
|
|
return res( |
318
|
|
|
|
|
|
|
302, [ |
319
|
|
|
|
|
|
|
Location => $redirect, |
320
|
|
|
|
|
|
|
], |
321
|
|
|
|
|
|
|
); |
322
|
|
|
|
|
|
|
} else { |
323
|
0
|
|
|
|
|
|
my $content_type = $res->header('Content-Type'); |
324
|
0
|
|
|
|
|
|
$self->log(debug => "Content-Type: $content_type"); |
325
|
0
|
0
|
|
|
|
|
if ($content_type =~ /html/i) { |
|
|
0
|
|
|
|
|
|
326
|
0
|
|
|
|
|
|
$res->content( encode($res->charset, rewrite_html($base, decode($res->charset, $res->content), $url), Encode::FB_HTMLCREF) ); |
327
|
|
|
|
|
|
|
} elsif ($content_type =~ m{text/css}) { |
328
|
0
|
|
|
|
|
|
$res->content( encode($res->charset, rewrite_css($base, decode($res->charset, $res->content), $url), Encode::FB_HTMLCREF) ); |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
|
331
|
0
|
|
|
|
|
|
return $res->to_plack_response(); |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
} else { |
334
|
|
|
|
|
|
|
# please input url. |
335
|
0
|
|
|
|
|
|
my $response = HTTP::Response->new( |
336
|
|
|
|
|
|
|
200 => 'ok', HTTP::Headers->new( |
337
|
|
|
|
|
|
|
'content-type' => 'text/html;charset=utf-8', |
338
|
|
|
|
|
|
|
), q{ |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
moxy start page |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
moxy start page |
347
|
|
|
|
|
|
|
please input url to location bar |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
}, |
351
|
|
|
|
|
|
|
); |
352
|
0
|
|
|
|
|
|
$response->request($req->as_http_request); |
353
|
0
|
|
|
|
|
|
$self->_post_process( |
354
|
|
|
|
|
|
|
response => $response, |
355
|
|
|
|
|
|
|
mobile_attribute => HTTP::MobileAttribute->new('KDDI-KC26 UP.Browser/6.2.0.7.3.129 (GUI) MMP/2.0'), |
356
|
|
|
|
|
|
|
session => $args{session}, |
357
|
|
|
|
|
|
|
); |
358
|
0
|
|
|
|
|
|
$response->content( encode($response->charset, rewrite_html($base, decode($response->charset, $response->content), ''), Encode::FB_HTMLCREF) ); |
359
|
0
|
|
|
|
|
|
return $response->to_plack_response(); |
360
|
|
|
|
|
|
|
} |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
sub _do_request { |
364
|
0
|
|
|
0
|
|
|
my $self = shift; |
365
|
0
|
|
|
|
|
|
my %args = validate( |
366
|
|
|
|
|
|
|
@_ => +{ |
367
|
|
|
|
|
|
|
url => qr{^https?://}, |
368
|
|
|
|
|
|
|
request => { isa => 'HTTP::Request' }, |
369
|
|
|
|
|
|
|
session => { type => OBJECT }, |
370
|
|
|
|
|
|
|
} |
371
|
|
|
|
|
|
|
); |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
# make request |
374
|
0
|
|
|
|
|
|
my $req = $args{request}->clone; |
375
|
0
|
|
|
|
|
|
$req->uri($args{url}); |
376
|
0
|
|
|
|
|
|
$req->header('Host' => do { |
377
|
0
|
|
|
|
|
|
my $u = URI->new($args{url}); |
378
|
0
|
|
|
|
|
|
my $header = $u->host; |
379
|
0
|
0
|
|
|
|
|
$header .= ':' . $u->port if $u->port != 80; |
380
|
0
|
|
|
|
|
|
$header; |
381
|
|
|
|
|
|
|
} |
382
|
|
|
|
|
|
|
); |
383
|
|
|
|
|
|
|
|
384
|
0
|
|
|
|
|
|
$self->run_hook( |
385
|
|
|
|
|
|
|
'request_filter_process_agent', |
386
|
|
|
|
|
|
|
{ request => $req, # HTTP::Request object |
387
|
|
|
|
|
|
|
session => $args{session}, |
388
|
|
|
|
|
|
|
} |
389
|
|
|
|
|
|
|
); |
390
|
|
|
|
|
|
|
|
391
|
0
|
|
|
|
|
|
my $mobile_attribute = HTTP::MobileAttribute->new($req->headers); |
392
|
0
|
|
|
|
|
|
my $carrier = $mobile_attribute->carrier; |
393
|
0
|
|
0
|
|
|
|
my $cookie_jar = $args{session}->get('cookies') || HTTP::Cookies->new(); # load cookies |
394
|
0
|
0
|
|
|
|
|
if ($mobile_attribute->is_docomo) { |
395
|
0
|
|
|
|
|
|
undef $cookie_jar; # docomo phone doesn't support cookies |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
|
398
|
0
|
|
|
|
|
|
for my $hook ('url_handle', "url_handle_$carrier") { |
399
|
0
|
|
|
|
|
|
my $response = $self->run_hook_and_get_response( |
400
|
|
|
|
|
|
|
$hook, |
401
|
|
|
|
|
|
|
+{ |
402
|
|
|
|
|
|
|
request => $req, # HTTP::Request object |
403
|
|
|
|
|
|
|
mobile_attribute => $mobile_attribute, |
404
|
|
|
|
|
|
|
session => $args{session}, |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
); |
407
|
0
|
0
|
|
|
|
|
if ($response) { |
408
|
0
|
|
|
|
|
|
return $response; # finished |
409
|
|
|
|
|
|
|
} |
410
|
|
|
|
|
|
|
} |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
# do request |
413
|
0
|
|
0
|
|
|
|
my $ua = LWP::UserAgent->new( |
414
|
|
|
|
|
|
|
timeout => $self->conf->{global}->{timeout} || 10, |
415
|
|
|
|
|
|
|
max_redirects => 0, |
416
|
|
|
|
|
|
|
protocols_allowed => [qw/http https/], |
417
|
|
|
|
|
|
|
parse_head => 0, |
418
|
|
|
|
|
|
|
cookie_jar => $cookie_jar, |
419
|
|
|
|
|
|
|
); |
420
|
|
|
|
|
|
|
$ua->add_handler( request_prepare => sub { |
421
|
0
|
|
|
0
|
|
|
my ($req, $ua, $h) = @_; |
422
|
|
|
|
|
|
|
|
423
|
0
|
|
|
|
|
|
for my $hook ('request_filter', "request_filter_$carrier") { |
424
|
0
|
|
|
|
|
|
my $response = $self->run_hook_and_get_response( |
425
|
|
|
|
|
|
|
$hook, |
426
|
|
|
|
|
|
|
+{ |
427
|
|
|
|
|
|
|
request => $req, # HTTP::Request object |
428
|
|
|
|
|
|
|
mobile_attribute => $mobile_attribute, |
429
|
|
|
|
|
|
|
session => $args{session}, |
430
|
|
|
|
|
|
|
} |
431
|
|
|
|
|
|
|
); |
432
|
0
|
0
|
|
|
|
|
if ($response) { |
433
|
0
|
|
|
|
|
|
return $response; # finished |
434
|
|
|
|
|
|
|
} |
435
|
|
|
|
|
|
|
} |
436
|
0
|
|
|
|
|
|
$req->remove_header('Accept-Encoding'); # I HATE gziped CONTENT |
437
|
0
|
|
|
|
|
|
$req->remove_header('Cookie'); # remove Cookie from the client |
438
|
|
|
|
|
|
|
|
439
|
0
|
|
|
|
|
|
$req; |
440
|
0
|
|
|
|
|
|
}); |
441
|
|
|
|
|
|
|
$ua->add_handler( response_done => sub { |
442
|
0
|
|
|
0
|
|
|
my ($response, $ua, $h) = @_; |
443
|
0
|
|
|
|
|
|
my $location = $response->header('Location'); |
444
|
0
|
0
|
|
|
|
|
if ($location) { |
445
|
0
|
|
0
|
|
|
|
my $content = $response->content || ''; |
446
|
0
|
|
|
|
|
|
$self->log(info => "redirect to '$location', $content"); |
447
|
|
|
|
|
|
|
} |
448
|
0
|
|
|
|
|
|
$response; |
449
|
0
|
|
|
|
|
|
}); |
450
|
|
|
|
|
|
|
|
451
|
0
|
|
|
|
|
|
$self->log(debug => "request to @{[ $req->uri ]}"); |
|
0
|
|
|
|
|
|
|
452
|
0
|
|
|
|
|
|
my $t1 = Time::HiRes::gettimeofday(); |
453
|
0
|
|
|
|
|
|
my $response = $ua->request($req); |
454
|
0
|
|
|
|
|
|
my $t2 = Time::HiRes::gettimeofday(); |
455
|
0
|
|
|
|
|
|
$self->response_time( $t2-$t1 ); |
456
|
0
|
|
|
|
|
|
$self->log(debug => "and, request was @{[ $response->request->uri ]}"); |
|
0
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
|
458
|
0
|
|
|
|
|
|
$args{session}->set('cookies' => $cookie_jar); # save cookies |
459
|
|
|
|
|
|
|
|
460
|
0
|
|
|
|
|
|
$self->_post_process( |
461
|
|
|
|
|
|
|
response => $response, |
462
|
|
|
|
|
|
|
mobile_attribute => $mobile_attribute, |
463
|
|
|
|
|
|
|
session => $args{session}, |
464
|
|
|
|
|
|
|
); |
465
|
0
|
|
|
|
|
|
$self->response_time( -1 ); # clear response time |
466
|
|
|
|
|
|
|
|
467
|
0
|
|
|
|
|
|
$response; |
468
|
|
|
|
|
|
|
} |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
sub _post_process { |
471
|
0
|
|
|
0
|
|
|
my $self = shift; |
472
|
0
|
|
|
|
|
|
my %args = validate( |
473
|
|
|
|
|
|
|
@_ => { |
474
|
|
|
|
|
|
|
response => 1, |
475
|
|
|
|
|
|
|
mobile_attribute => 1, |
476
|
|
|
|
|
|
|
session => 1, |
477
|
|
|
|
|
|
|
}, |
478
|
|
|
|
|
|
|
); |
479
|
|
|
|
|
|
|
|
480
|
0
|
|
|
|
|
|
my $carrier = $args{mobile_attribute}->carrier; |
481
|
0
|
|
|
|
|
|
for my $hook ( |
482
|
|
|
|
|
|
|
'status_handler', 'security_filter', |
483
|
|
|
|
|
|
|
'response_filter', "response_filter_$carrier", |
484
|
|
|
|
|
|
|
'render_location_bar' |
485
|
|
|
|
|
|
|
) |
486
|
|
|
|
|
|
|
{ |
487
|
0
|
|
|
|
|
|
$self->run_hook( $hook, \%args ); |
488
|
|
|
|
|
|
|
} |
489
|
|
|
|
|
|
|
} |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
1; |
492
|
|
|
|
|
|
|
__END__ |