Filename | /usr/share/perl5/Authen/CAS/Client.pm |
Statements | Executed 24 statements in 3.85ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 1.56ms | 3.12ms | BEGIN@8 | Authen::CAS::Client::
1 | 1 | 1 | 1.23ms | 1.27ms | BEGIN@11 | Authen::CAS::Client::
1 | 1 | 1 | 210µs | 210µs | BEGIN@10 | Authen::CAS::Client::
1 | 1 | 1 | 26µs | 529µs | BEGIN@12 | Authen::CAS::Client::
1 | 1 | 1 | 25µs | 50µs | BEGIN@6 | Authen::CAS::Client::
1 | 1 | 1 | 24µs | 24µs | BEGIN@9 | Authen::CAS::Client::
1 | 1 | 1 | 18µs | 22µs | BEGIN@5 | Authen::CAS::Client::
0 | 0 | 0 | 0s | 0s | _error | Authen::CAS::Client::
0 | 0 | 0 | 0s | 0s | _parse_auth_response | Authen::CAS::Client::
0 | 0 | 0 | 0s | 0s | _parse_proxy_response | Authen::CAS::Client::
0 | 0 | 0 | 0s | 0s | _server_request | Authen::CAS::Client::
0 | 0 | 0 | 0s | 0s | _url | Authen::CAS::Client::
0 | 0 | 0 | 0s | 0s | _v20_validate | Authen::CAS::Client::
0 | 0 | 0 | 0s | 0s | login_url | Authen::CAS::Client::
0 | 0 | 0 | 0s | 0s | logout_url | Authen::CAS::Client::
0 | 0 | 0 | 0s | 0s | new | Authen::CAS::Client::
0 | 0 | 0 | 0s | 0s | proxy | Authen::CAS::Client::
0 | 0 | 0 | 0s | 0s | proxy_validate | Authen::CAS::Client::
0 | 0 | 0 | 0s | 0s | service_validate | Authen::CAS::Client::
0 | 0 | 0 | 0s | 0s | validate | Authen::CAS::Client::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Authen::CAS::Client; | ||||
2 | |||||
3 | 1 | 39µs | require 5.006_001; | ||
4 | |||||
5 | 3 | 28µs | 2 | 26µs | # spent 22µs (18+4) within Authen::CAS::Client::BEGIN@5 which was called:
# once (18µs+4µs) by C4::Auth_with_cas::BEGIN@26 at line 5 # spent 22µs making 1 call to Authen::CAS::Client::BEGIN@5
# spent 4µs making 1 call to strict::import |
6 | 3 | 57µs | 2 | 74µs | # spent 50µs (25+25) within Authen::CAS::Client::BEGIN@6 which was called:
# once (25µs+25µs) by C4::Auth_with_cas::BEGIN@26 at line 6 # spent 50µs making 1 call to Authen::CAS::Client::BEGIN@6
# spent 25µs making 1 call to warnings::import |
7 | |||||
8 | 3 | 195µs | 1 | 3.12ms | # spent 3.12ms (1.56+1.55) within Authen::CAS::Client::BEGIN@8 which was called:
# once (1.56ms+1.55ms) by C4::Auth_with_cas::BEGIN@26 at line 8 # spent 3.12ms making 1 call to Authen::CAS::Client::BEGIN@8 |
9 | 3 | 259µs | 1 | 24µs | # spent 24µs within Authen::CAS::Client::BEGIN@9 which was called:
# once (24µs+0s) by C4::Auth_with_cas::BEGIN@26 at line 9 # spent 24µs making 1 call to Authen::CAS::Client::BEGIN@9 |
10 | 3 | 66µs | 1 | 210µs | # spent 210µs within Authen::CAS::Client::BEGIN@10 which was called:
# once (210µs+0s) by C4::Auth_with_cas::BEGIN@26 at line 10 # spent 210µs making 1 call to Authen::CAS::Client::BEGIN@10 |
11 | 3 | 228µs | 1 | 1.27ms | # spent 1.27ms (1.23+41µs) within Authen::CAS::Client::BEGIN@11 which was called:
# once (1.23ms+41µs) by C4::Auth_with_cas::BEGIN@26 at line 11 # spent 1.27ms making 1 call to Authen::CAS::Client::BEGIN@11 |
12 | 3 | 2.97ms | 2 | 1.03ms | # spent 529µs (26+502) within Authen::CAS::Client::BEGIN@12 which was called:
# once (26µs+502µs) by C4::Auth_with_cas::BEGIN@26 at line 12 # spent 529µs making 1 call to Authen::CAS::Client::BEGIN@12
# spent 502µs making 1 call to XML::LibXML::import |
13 | |||||
14 | 1 | 2µs | our $VERSION = '0.05'; | ||
15 | |||||
16 | |||||
17 | #====================================================================== | ||||
18 | # constructor | ||||
19 | # | ||||
20 | |||||
21 | sub new { | ||||
22 | my ( $class, $cas, %args ) = @_; | ||||
23 | |||||
24 | my $self = { | ||||
25 | _cas => URI->new( $cas ), | ||||
26 | _ua => LWP::UserAgent->new( agent => "Authen-CAS-Client/$VERSION" ), | ||||
27 | _fatal => $args{fatal} ? 1 : 0, | ||||
28 | }; | ||||
29 | |||||
30 | bless $self, $class; | ||||
31 | } | ||||
32 | |||||
33 | |||||
34 | #====================================================================== | ||||
35 | # private methods | ||||
36 | # | ||||
37 | |||||
38 | sub _error { | ||||
39 | my ( $self, $error, $doc ) = @_; | ||||
40 | |||||
41 | die $error | ||||
42 | if $self->{_fatal}; | ||||
43 | |||||
44 | Authen::CAS::Client::Response::Error->new( error => $error, doc => $doc ); | ||||
45 | } | ||||
46 | |||||
47 | sub _parse_auth_response { | ||||
48 | my ( $self, $xml ) = @_; | ||||
49 | |||||
50 | my $doc = eval { XML::LibXML->new->parse_string( $xml ) }; | ||||
51 | return $self->_error( 'Failed to parse XML', $xml ) | ||||
52 | if $@; | ||||
53 | |||||
54 | my ( $node, $response ); | ||||
55 | |||||
56 | eval { | ||||
57 | if( $node = $doc->find( '/cas:serviceResponse/cas:authenticationSuccess' )->get_node( 1 ) ) { | ||||
58 | $response = eval { | ||||
59 | my $user = $node->find( './cas:user' )->get_node( 1 )->textContent; | ||||
60 | |||||
61 | my $iou = $node->find( './cas:proxyGrantingTicket' )->get_node( 1 ); | ||||
62 | $iou = $iou->textContent | ||||
63 | if( defined $iou ); | ||||
64 | |||||
65 | my $proxies = $node->findnodes( './cas:proxies/cas:proxy' ); | ||||
66 | $proxies = [ map $_->textContent, @$proxies ] | ||||
67 | if defined @$proxies; | ||||
68 | |||||
69 | Authen::CAS::Client::Response::AuthSuccess->new( | ||||
70 | user => $user, | ||||
71 | iou => $iou, | ||||
72 | proxies => $proxies, | ||||
73 | doc => $doc, | ||||
74 | ); | ||||
75 | }; | ||||
76 | |||||
77 | $response = $self->_error( 'Failed to parse authentication success response', $doc ) | ||||
78 | if $@; | ||||
79 | } | ||||
80 | elsif( $node = $doc->find( '/cas:serviceResponse/cas:authenticationFailure' )->get_node( 1 ) ) { | ||||
81 | $response = eval { | ||||
82 | die | ||||
83 | unless $node->hasAttribute( 'code' ); | ||||
84 | my $code = $node->getAttribute( 'code' ); | ||||
85 | |||||
86 | my $message = $node->textContent; | ||||
87 | s/^\s+//, s/\s+\z// | ||||
88 | for $message; | ||||
89 | |||||
90 | Authen::CAS::Client::Response::AuthFailure->new( | ||||
91 | code => $code, | ||||
92 | message => $message, | ||||
93 | doc => $doc, | ||||
94 | ); | ||||
95 | }; | ||||
96 | |||||
97 | $response = $self->_error( 'Failed to parse authentication failure response', $doc ) | ||||
98 | if $@; | ||||
99 | } | ||||
100 | else { | ||||
101 | die; | ||||
102 | } | ||||
103 | }; | ||||
104 | |||||
105 | $response = $self->_error( 'Invalid CAS response', $doc ) | ||||
106 | if $@; | ||||
107 | |||||
108 | return $response; | ||||
109 | } | ||||
110 | |||||
111 | sub _parse_proxy_response { | ||||
112 | my ( $self, $xml ) = @_; | ||||
113 | |||||
114 | my $doc = eval { XML::LibXML->new->parse_string( $xml ) }; | ||||
115 | return $self->_error( 'Failed to parse XML', $xml ) | ||||
116 | if $@; | ||||
117 | |||||
118 | my ( $node, $response ); | ||||
119 | |||||
120 | eval { | ||||
121 | if( $node = $doc->find( '/cas:serviceResponse/cas:proxySuccess' )->get_node( 1 ) ) { | ||||
122 | $response = eval { | ||||
123 | my $proxy_ticket = $node->find( './cas:proxyTicket' )->get_node( 1 )->textContent; | ||||
124 | |||||
125 | Authen::CAS::Client::Response::ProxySuccess->new( | ||||
126 | proxy_ticket => $proxy_ticket, | ||||
127 | doc => $doc, | ||||
128 | ); | ||||
129 | }; | ||||
130 | $response = $self->_error( 'Failed to parse proxy success response', $doc ) | ||||
131 | if $@; | ||||
132 | } | ||||
133 | elsif( $node = $doc->find( '/cas:serviceResponse/cas:proxyFailure' )->get_node( 1 ) ) { | ||||
134 | $response = eval { | ||||
135 | die | ||||
136 | unless $node->hasAttribute( 'code' ); | ||||
137 | my $code = $node->getAttribute( 'code' ); | ||||
138 | |||||
139 | my $message = $node->textContent; | ||||
140 | s/^\s+//, s/\s+\z// | ||||
141 | for $message; | ||||
142 | |||||
143 | Authen::CAS::Client::Response::ProxyFailure->new( | ||||
144 | code => $code, | ||||
145 | message => $message, | ||||
146 | doc => $doc, | ||||
147 | ); | ||||
148 | }; | ||||
149 | $response = $self->_error( 'Failed to parse proxy failure response', $doc ) | ||||
150 | if $@; | ||||
151 | } | ||||
152 | else { | ||||
153 | die; | ||||
154 | } | ||||
155 | }; | ||||
156 | |||||
157 | $response = $self->_error( 'Invalid CAS response', $doc ) | ||||
158 | if $@; | ||||
159 | |||||
160 | return $response; | ||||
161 | } | ||||
162 | |||||
163 | sub _server_request { | ||||
164 | my ( $self, $path, $params ) = @_; | ||||
165 | |||||
166 | my $url = $self->_url( $path, $params )->canonical; | ||||
167 | my $response = $self->{_ua}->get( $url ); | ||||
168 | |||||
169 | unless( $response->is_success ) { | ||||
170 | return $self->_error( | ||||
171 | 'HTTP request failed: ' . $response->code . ': ' . $response->message, | ||||
172 | $response->content | ||||
173 | ); | ||||
174 | } | ||||
175 | |||||
176 | return $response->content; | ||||
177 | } | ||||
178 | |||||
179 | sub _url { | ||||
180 | my ( $self, $path, $params ) = @_; | ||||
181 | |||||
182 | my $url = $self->{_cas}->clone; | ||||
183 | |||||
184 | $url->path( $url->path . $path ); | ||||
185 | $url->query_param_append( $_ => $params->{$_} ) | ||||
186 | for keys %$params; | ||||
187 | |||||
188 | return $url; | ||||
189 | } | ||||
190 | |||||
191 | sub _v20_validate { | ||||
192 | my ( $self, $path, $service, $ticket, %args ) = @_; | ||||
193 | |||||
194 | my %params = ( service => $service, ticket => $ticket ); | ||||
195 | |||||
196 | $params{renew} = 'true' | ||||
197 | if $args{renew}; | ||||
198 | $params{pgtUrl} = URI->new( $args{pgtUrl} )->canonical | ||||
199 | if defined $args{pgtUrl}; | ||||
200 | |||||
201 | my $content = $self->_server_request( $path, \%params ); | ||||
202 | return $content | ||||
203 | if ref $content; | ||||
204 | |||||
205 | return $self->_parse_auth_response( $content ); | ||||
206 | } | ||||
207 | |||||
208 | |||||
209 | #====================================================================== | ||||
210 | # public methods | ||||
211 | # | ||||
212 | |||||
213 | sub login_url { | ||||
214 | my ( $self, $service, %args ) = @_; | ||||
215 | |||||
216 | my %params = ( service => $service ); | ||||
217 | |||||
218 | for ( qw/ renew gateway / ) { | ||||
219 | $params{$_} = 'true', last | ||||
220 | if $args{$_}; | ||||
221 | } | ||||
222 | |||||
223 | return $self->_url( '/login', \%params )->canonical; | ||||
224 | } | ||||
225 | |||||
226 | sub logout_url { | ||||
227 | my ( $self, %args ) = @_; | ||||
228 | |||||
229 | my %params; | ||||
230 | |||||
231 | $params{url} = $args{url} | ||||
232 | if defined $args{url}; | ||||
233 | |||||
234 | return $self->_url( '/logout', \%params )->canonical; | ||||
235 | } | ||||
236 | |||||
237 | sub validate { | ||||
238 | my ( $self, $service, $ticket, %args ) = @_; | ||||
239 | |||||
240 | my %params = ( service => $service, ticket => $ticket ); | ||||
241 | |||||
242 | $params{renew} = 'true' | ||||
243 | if $args{renew}; | ||||
244 | |||||
245 | my $content = $self->_server_request( '/validate', \%params ); | ||||
246 | return $content | ||||
247 | if ref $content; | ||||
248 | |||||
249 | my $response; | ||||
250 | |||||
251 | if( $content =~ /^no\n\n\z/ ) { | ||||
252 | $response = Authen::CAS::Client::Response::AuthFailure->new( code => 'V10_AUTH_FAILURE', doc => $content ); | ||||
253 | } | ||||
254 | elsif( $content =~ /^yes\n([^\n]+)\n\z/ ) { | ||||
255 | $response = Authen::CAS::Client::Response::AuthSuccess->new( user => $1, doc => $content ); | ||||
256 | } | ||||
257 | else { | ||||
258 | $response = $self->_error( 'Invalid CAS response', $content ); | ||||
259 | } | ||||
260 | |||||
261 | return $response; | ||||
262 | } | ||||
263 | |||||
264 | sub service_validate { | ||||
265 | my ( $self, $service, $ticket, %args ) = @_; | ||||
266 | return $self->_v20_validate( '/serviceValidate', $service, $ticket, %args ); | ||||
267 | } | ||||
268 | |||||
269 | sub proxy_validate { | ||||
270 | my ( $self, $service, $ticket, %args ) = @_; | ||||
271 | return $self->_v20_validate( '/proxyValidate', $service, $ticket, %args ); | ||||
272 | } | ||||
273 | |||||
274 | sub proxy { | ||||
275 | my ( $self, $pgt, $target ) = @_; | ||||
276 | |||||
277 | my %params = ( pgt => $pgt, targetService => URI->new( $target ) ); | ||||
278 | |||||
279 | my $content = $self->_server_request( '/proxy', \%params ); | ||||
280 | return $content | ||||
281 | if ref $content; | ||||
282 | |||||
283 | return $self->_parse_proxy_response( $content ); | ||||
284 | } | ||||
285 | |||||
286 | |||||
287 | 1 | 6µs | 1 | ||
288 | __END__ |