5
* Main class of the phpCAS library
8
// include internationalization stuff
9
include_once(dirname(__FILE__).'/languages/languages.php');
11
// include PGT storage classes
12
include_once(dirname(__FILE__).'/PGTStorage/pgt-main.php');
16
* The CASClient class is a client interface that provides CAS authentication
17
* to PHP applications.
19
* @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>
25
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
27
// XX CONFIGURATION XX
29
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
31
// ########################################################################
33
// ########################################################################
35
* @addtogroup internalOutput
40
* This method filters a string by replacing special tokens by appropriate values
41
* and prints it. The corresponding tokens are taken into account:
43
* - __PHPCAS_VERSION__
44
* - __SERVER_BASE_URL__
46
* Used by CASClient::PrintHTMLHeader() and CASClient::printHTMLFooter().
48
* @param $str the string to filter and output
52
function HTMLFilterOutput($str)
54
$str = str_replace('__CAS_VERSION__',$this->getServerVersion(),$str);
55
$str = str_replace('__PHPCAS_VERSION__',phpCAS::getVersion(),$str);
56
$str = str_replace('__SERVER_BASE_URL__',$this->getServerBaseURL(),$str);
61
* A string used to print the header of HTML pages. Written by CASClient::setHTMLHeader(),
62
* read by CASClient::printHTMLHeader().
66
* @see CASClient::setHTMLHeader, CASClient::printHTMLHeader()
68
var $_output_header = '';
71
* This method prints the header of the HTML output (after filtering). If
72
* CASClient::setHTMLHeader() was not used, a default header is output.
74
* @param $title the title of the page
76
* @see HTMLFilterOutput()
79
function printHTMLHeader($title)
81
$this->HTMLFilterOutput(str_replace('__TITLE__',
83
(empty($this->_output_header)
84
? '<html><head><title>__TITLE__</title></head><body><h1>__TITLE__</h1>'
85
: $this->output_header)
91
* A string used to print the footer of HTML pages. Written by CASClient::setHTMLFooter(),
92
* read by printHTMLFooter().
96
* @see CASClient::setHTMLFooter, CASClient::printHTMLFooter()
98
var $_output_footer = '';
101
* This method prints the footer of the HTML output (after filtering). If
102
* CASClient::setHTMLFooter() was not used, a default footer is output.
104
* @see HTMLFilterOutput()
107
function printHTMLFooter()
109
$this->HTMLFilterOutput(empty($this->_output_footer)
110
?('<hr><address>phpCAS __PHPCAS_VERSION__ '.$this->getString(CAS_STR_USING_SERVER).' <a href="__SERVER_BASE_URL__">__SERVER_BASE_URL__</a> (CAS __CAS_VERSION__)</a></address></body></html>')
111
:$this->_output_footer);
115
* This method set the HTML header used for all outputs.
117
* @param $header the HTML header.
121
function setHTMLHeader($header)
123
$this->_output_header = $header;
127
* This method set the HTML footer used for all outputs.
129
* @param $footer the HTML footer.
133
function setHTMLFooter($footer)
135
$this->_output_footer = $footer;
139
// ########################################################################
140
// INTERNATIONALIZATION
141
// ########################################################################
143
* @addtogroup internalLang
147
* A string corresponding to the language used by phpCAS. Written by
148
* CASClient::setLang(), read by CASClient::getLang().
150
* @note debugging information is always in english (debug purposes only).
154
* @sa CASClient::_strings, CASClient::getString()
159
* This method returns the language used by phpCAS.
161
* @return a string representing the language
167
if ( empty($this->_lang) )
168
$this->setLang(PHPCAS_LANG_DEFAULT);
173
* array containing the strings used by phpCAS. Written by CASClient::setLang(), read by
174
* CASClient::getString() and used by CASClient::setLang().
176
* @note This array is filled by instructions in CAS/languages/<$this->_lang>.php
179
* @see CASClient::_lang, CASClient::getString(), CASClient::setLang(), CASClient::getLang()
184
* This method returns a string depending on the language.
186
* @param $str the index of the string in $_string.
188
* @return the string corresponding to $index in $string.
192
function getString($str)
194
// call CASclient::getLang() to be sure the language is initialized
197
if ( !isset($this->_strings[$str]) ) {
198
trigger_error('string `'.$str.'\' not defined for language `'.$this->getLang().'\'',E_USER_ERROR);
200
return $this->_strings[$str];
204
* This method is used to set the language used by phpCAS.
205
* @note Can be called only once.
207
* @param $lang a string representing the language.
210
* @sa CAS_LANG_FRENCH, CAS_LANG_ENGLISH
212
function setLang($lang)
214
// include the corresponding language file
215
include_once(dirname(__FILE__).'/languages/'.$lang.'.php');
217
if ( !is_array($this->_strings) ) {
218
trigger_error('language `'.$lang.'\' is not implemented',E_USER_ERROR);
220
$this->_lang = $lang;
224
// ########################################################################
226
// ########################################################################
228
* @addtogroup internalConfig
233
* a record to store information about the CAS server.
234
* - $_server["version"]: the version of the CAS server
235
* - $_server["hostname"]: the hostname of the CAS server
236
* - $_server["port"]: the port the CAS server is running on
237
* - $_server["uri"]: the base URI the CAS server is responding on
238
* - $_server["base_url"]: the base URL of the CAS server
239
* - $_server["login_url"]: the login URL of the CAS server
240
* - $_server["service_validate_url"]: the service validating URL of the CAS server
241
* - $_server["proxy_url"]: the proxy URL of the CAS server
242
* - $_server["proxy_validate_url"]: the proxy validating URL of the CAS server
243
* - $_server["logout_url"]: the logout URL of the CAS server
245
* $_server["version"], $_server["hostname"], $_server["port"] and $_server["uri"]
246
* are written by CASClient::CASClient(), read by CASClient::getServerVersion(),
247
* CASClient::getServerHostname(), CASClient::getServerPort() and CASClient::getServerURI().
249
* The other fields are written and read by CASClient::getServerBaseURL(),
250
* CASClient::getServerLoginURL(), CASClient::getServerServiceValidateURL(),
251
* CASClient::getServerProxyValidateURL() and CASClient::getServerLogoutURL().
256
var $_server = array(
258
'hostname' => 'none',
264
* This method is used to retrieve the version of the CAS server.
265
* @return the version of the CAS server.
268
function getServerVersion()
270
return $this->_server['version'];
274
* This method is used to retrieve the hostname of the CAS server.
275
* @return the hostname of the CAS server.
278
function getServerHostname()
279
{ return $this->_server['hostname']; }
282
* This method is used to retrieve the port of the CAS server.
283
* @return the port of the CAS server.
286
function getServerPort()
287
{ return $this->_server['port']; }
290
* This method is used to retrieve the URI of the CAS server.
294
function getServerURI()
295
{ return $this->_server['uri']; }
298
* This method is used to retrieve the base URL of the CAS server.
302
function getServerBaseURL()
304
// the URL is build only when needed
305
if ( empty($this->_server['base_url']) ) {
306
$this->_server['base_url'] = 'https://'
307
.$this->getServerHostname()
309
.$this->getServerPort()
310
.$this->getServerURI();
312
return $this->_server['base_url'];
316
* This method is used to retrieve the login URL of the CAS server.
320
function getServerLoginURL()
322
// the URL is build only when needed
323
if ( empty($this->_server['login_url']) ) {
324
$this->_server['login_url'] = $this->getServerBaseURL().'login?service='.preg_replace('/&/','%26',$this->getURL());
326
return $this->_server['login_url'];
330
* This method is used to retrieve the service validating URL of the CAS server.
334
function getServerServiceValidateURL()
336
// the URL is build only when needed
337
if ( empty($this->_server['service_validate_url']) ) {
338
switch ($this->getServerVersion()) {
339
case CAS_VERSION_1_0:
340
$this->_server['service_validate_url'] = $this->getServerBaseURL().'validate';
342
case CAS_VERSION_2_0:
343
$this->_server['service_validate_url'] = $this->getServerBaseURL().'serviceValidate';
347
return $this->_server['service_validate_url'].'?service='.preg_replace('/&/','%26',$this->getURL());
351
* This method is used to retrieve the proxy validating URL of the CAS server.
355
function getServerProxyValidateURL()
357
// the URL is build only when needed
358
if ( empty($this->_server['proxy_validate_url']) ) {
359
switch ($this->getServerVersion()) {
360
case CAS_VERSION_1_0:
361
$this->_server['proxy_validate_url'] = '';
363
case CAS_VERSION_2_0:
364
$this->_server['proxy_validate_url'] = $this->getServerBaseURL().'proxyValidate';
368
return $this->_server['proxy_validate_url'].'?service='.preg_replace('/&/','%26',$this->getURL());
372
* This method is used to retrieve the proxy URL of the CAS server.
376
function getServerProxyURL()
378
// the URL is build only when needed
379
if ( empty($this->_server['proxy_url']) ) {
380
switch ($this->getServerVersion()) {
381
case CAS_VERSION_1_0:
382
$this->_server['proxy_url'] = '';
384
case CAS_VERSION_2_0:
385
$this->_server['proxy_url'] = $this->getServerBaseURL().'proxy';
389
return $this->_server['proxy_url'];
393
* This method is used to retrieve the logout URL of the CAS server.
397
function getServerLogoutURL()
399
// the URL is build only when needed
400
if ( empty($this->_server['logout_url']) ) {
401
$this->_server['logout_url'] = $this->getServerBaseURL().'logout';
403
return $this->_server['logout_url'];
406
// ########################################################################
408
// ########################################################################
410
* CASClient constructor.
412
* @param $server_version the version of the CAS server
413
* @param $proxy TRUE if the CAS client is a CAS proxy, FALSE otherwise
414
* @param $server_hostname the hostname of the CAS server
415
* @param $server_port the port the CAS server is running on
416
* @param $server_uri the URI the CAS server is responding on
418
* @return a newly created CASClient object
422
function CASClient($server_version,
428
phpCAS::traceBegin();
430
// activate session mechanism
433
$this->_proxy = $proxy;
436
switch ($server_version) {
437
case CAS_VERSION_1_0:
438
if ( $this->isProxy() )
439
phpCAS::error('CAS proxies are not supported in CAS '
442
case CAS_VERSION_2_0:
445
phpCAS::error('this version of CAS (`'
447
.'\') is not supported by phpCAS '
448
.phpCAS::getVersion());
450
$this->_server['version'] = $server_version;
453
if ( empty($server_hostname)
454
|| !preg_match('/[\.\d\-abcdefghijklmnopqrstuvwxyz]*/',$server_hostname) ) {
455
phpCAS::error('bad CAS server hostname (`'.$server_hostname.'\')');
457
$this->_server['hostname'] = $server_hostname;
460
if ( $server_port == 0
461
|| !is_int($server_port) ) {
462
phpCAS::error('bad CAS server port (`'.$server_hostname.'\')');
464
$this->_server['port'] = $server_port;
467
if ( !preg_match('/[\.\d\-_abcdefghijklmnopqrstuvwxyz\/]*/',$server_uri) ) {
468
phpCAS::error('bad CAS server URI (`'.$server_uri.'\')');
470
// add leading and trailing `/' and remove doubles
471
$server_uri = preg_replace('/\/\//','/','/'.$server_uri.'/');
472
$this->_server['uri'] = $server_uri;
474
// set to callback mode if PgtIou and PgtId CGI GET parameters are provided
475
if ( $this->isProxy() ) {
476
$this->setCallbackMode(!empty($_GET['pgtIou'])&&!empty($_GET['pgtId']));
479
if ( $this->isCallbackMode() ) {
480
// callback mode: check that phpCAS is secured
481
if ( $_SERVER['HTTPS'] != 'on' ) {
482
phpCAS::error('CAS proxies must be secured to use phpCAS; PGT\'s will not be received from the CAS server');
485
// normal mode: get ticket and remove it from CGI parameters for developpers
486
$ticket = $_GET['ticket'];
487
// at first check for a Service Ticket
488
if( preg_match('/^ST-/',$ticket)) {
489
phpCAS::trace('ST \''.$ticket.'\' found');
491
$this->setST($ticket);
493
// in a second time check for a Proxy Ticket (CAS >= 2.0)
494
else if( ($this->getServerVersion()!=CAS_VERSION_1_0) && preg_match('/^PT-/',$ticket) ) {
495
phpCAS::trace('PT \''.$ticket.'\' found');
496
$this->setPT($ticket);
498
// ill-formed ticket, halt
499
else if ( !empty($ticket) ) {
500
phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')');
502
// ticket has been taken into account, unset it to hide it to applications
503
unset($_GET['ticket']);
510
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
512
// XX AUTHENTICATION XX
514
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
517
* @addtogroup internalAuthentication
522
* The Authenticated user. Written by CASClient::setUser(), read by CASClient::getUser().
523
* @attention client applications should use phpCAS::getUser().
531
* This method sets the CAS user's login name.
533
* @param $user the login name of the authenticated user.
537
function setUser($user)
539
$this->_user = $user;
543
* This method returns the CAS user's login name.
544
* @warning should be called only after CASClient::authenticateIfNeeded() or
545
* CASClient::isAuthenticated(), otherwise halt with an error.
547
* @return the login name of the authenticated user
551
if ( empty($this->_user) ) {
552
phpCAS::error('this method should be used only after '.__CLASS__.'::authenticateIfNeeded() or '.__CLASS__.'::isAuthenticated()');
558
* This method is called to check if the user is authenticated. When not
559
* authenticated, halt by redirecting to the CAS server; otherwise return TRUE.
561
* @return TRUE when the user is authenticated; otherwise halt.
565
function authenticateIfNeeded()
567
phpCAS::traceBegin();
570
if ( $this->isAuthenticated() ) {
571
// the user is authenticated, nothing to be done.
572
phpCAS::trace('no need to authenticate');
575
// the user is not authenticated, redirect to the CAS server
576
$this->forceAuthentication();
580
phpCAS::traceEnd($res);
585
* This method is called to check if the user is authenticated (previously or by
586
* tickets given in the URL
588
* @return TRUE when the user is authenticated; otherwise halt.
592
function isAuthenticated()
594
phpCAS::traceBegin();
598
if ( $this->wasPreviouslyAuthenticated() ) {
599
// the user has already (previously during the session) been
600
// authenticated, nothing to be done.
601
phpCAS::trace('user was already authenticated, no need to look for tickets');
603
} elseif ( $this->hasST() ) {
604
// if a Service Ticket was given, validate it
605
phpCAS::trace('ST `'.$this->getST().'\' is present');
606
$this->validateST($validate_url,$text_response,$tree_response); // if it fails, it halts
607
phpCAS::trace('ST `'.$this->getST().'\' was validated');
608
if ( $this->isProxy() ) {
609
$this->validatePGT($validate_url,$text_response,$tree_response); // idem
610
phpCAS::trace('PGT `'.$this->getPGT().'\' was validated');
611
$_SESSION['phpCAS']['pgt'] = $this->getPGT();
613
$_SESSION['phpCAS']['user'] = $this->getUser();
615
} elseif ( $this->hasPT() ) {
616
// if a Proxy Ticket was given, validate it
617
phpCAS::trace('PT `'.$this->getPT().'\' is present');
618
$this->validatePT($validate_url,$text_response,$tree_response); // note: if it fails, it halts
619
phpCAS::trace('PT `'.$this->getPT().'\' was validated');
620
if ( $this->isProxy() ) {
621
$this->validatePGT($validate_url,$text_response,$tree_response); // idem
622
phpCAS::trace('PGT `'.$this->getPGT().'\' was validated');
623
$_SESSION['phpCAS']['pgt'] = $this->getPGT();
625
$_SESSION['phpCAS']['user'] = $this->getUser();
628
// no ticket given, not authenticated
629
phpCAS::trace('no ticket found');
632
phpCAS::traceEnd($res);
637
* This method tells if the user has already been (previously) authenticated
638
* by looking into the session variables.
640
* @note This function switches to callback mode when needed.
642
* @return TRUE when the user has already been authenticated; FALSE otherwise.
646
function wasPreviouslyAuthenticated()
648
phpCAS::traceBegin();
650
if ( $this->isCallbackMode() ) {
656
if ( $this->isProxy() ) {
657
// CAS proxy: username and PGT must be present
658
if ( !empty($_SESSION['phpCAS']['user']) && !empty($_SESSION['phpCAS']['pgt']) ) {
659
// authentication already done
660
$this->setUser($_SESSION['phpCAS']['user']);
661
$this->setPGT($_SESSION['phpCAS']['pgt']);
662
phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\', PGT = `'.$_SESSION['phpCAS']['pgt'].'\'');
664
} elseif ( !empty($_SESSION['phpCAS']['user']) && empty($_SESSION['phpCAS']['pgt']) ) {
665
// these two variables should be empty or not empty at the same time
666
phpCAS::trace('username found (`'.$_SESSION['phpCAS']['user'].'\') but PGT is empty');
667
// unset all tickets to enforce authentication
668
unset($_SESSION['phpCAS']);
671
} elseif ( empty($_SESSION['phpCAS']['user']) && !empty($_SESSION['phpCAS']['pgt']) ) {
672
// these two variables should be empty or not empty at the same time
673
phpCAS::trace('PGT found (`'.$_SESSION['phpCAS']['pgt'].'\') but username is empty');
674
// unset all tickets to enforce authentication
675
unset($_SESSION['phpCAS']);
679
phpCAS::trace('neither user not PGT found');
682
// `simple' CAS client (not a proxy): username must be present
683
if ( !empty($_SESSION['phpCAS']['user']) ) {
684
// authentication already done
685
$this->setUser($_SESSION['phpCAS']['user']);
686
phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\'');
689
phpCAS::trace('no user found');
693
phpCAS::traceEnd($auth);
698
* This method is used to force authentication by redirecting to the CAS server.
699
* It is used by CASClient::authenticateIfNeeded() when the user is not authenticated,
700
* and can also be called by phpCAS::forceAuthentication().
704
function forceAuthentication()
706
phpCAS::traceBegin();
707
$cas_url = $this->getServerLoginURL();
708
header('Location: '.$cas_url);
709
$this->printHTMLHeader($this->getString(CAS_STR_AUTHENTICATION_WANTED));
710
printf('<p>'.$this->getString(CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'</p>',$cas_url);
711
$this->printHTMLFooter();
717
* This method is used to logout from CAS.
718
* @param $url a URL that will be transmitted to the CAS server (to come back to when logged out)
721
function logout($url = "")
723
phpCAS::traceBegin();
724
$cas_url = $this->getServerLogoutURL();
725
// v0.4.14 sebastien.gougeon at univ-rennes1.fr
726
// header('Location: '.$cas_url);
728
$url = '?service=' . $url;
730
header('Location: '.$cas_url . $url);
733
$this->printHTMLHeader($this->getString(CAS_STR_LOGOUT));
734
printf('<p>'.$this->getString(CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'</p>',$cas_url);
735
$this->printHTMLFooter();
742
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
744
// XX BASIC CLIENT FEATURES (CAS 1.0) XX
746
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
748
// ########################################################################
750
// ########################################################################
752
* @addtogroup internalBasic
757
* the Service Ticket provided in the URL of the request if present
758
* (empty otherwise). Written by CASClient::CASClient(), read by
759
* CASClient::getST() and CASClient::hasPGT().
767
* This method returns the Service Ticket provided in the URL of the request.
768
* @return The service ticket.
772
{ return $this->_st; }
775
* This method stores the Service Ticket.
776
* @param $st The Service Ticket.
780
{ $this->_st = $st; }
783
* This method tells if a Service Ticket was stored.
784
* @return TRUE if a Service Ticket has been stored.
788
{ return !empty($this->_st); }
792
// ########################################################################
794
// ########################################################################
796
* @addtogroup internalBasic
801
* This method is used to validate a ST; halt on failure, and sets $validate_url,
802
* $text_reponse and $tree_response on success. These parameters are used later
803
* by CASClient::validatePGT() for CAS proxies.
805
* @param $validate_url the URL of the request to the CAS server.
806
* @param $text_response the response of the CAS server, as is (XML text).
807
* @param $tree_response the response of the CAS server, as a DOM XML tree.
809
* @return bool TRUE when successfull, halt otherwise by calling CASClient::authError().
813
function validateST($validate_url,&$text_response,&$tree_response)
815
phpCAS::traceBegin();
816
// build the URL to validate the ticket
817
$validate_url = $this->getServerServiceValidateURL().'&ticket='.$this->getST();
818
if ( $this->isProxy() ) {
819
// pass the callback url for CAS proxies
820
$validate_url .= '&pgtUrl='.$this->getCallbackURL();
823
// open and read the URL
824
if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) {
825
phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
826
$this->authError('ST not validated',
828
TRUE/*$no_response*/);
831
// analyze the result depending on the version
832
switch ($this->getServerVersion()) {
833
case CAS_VERSION_1_0:
834
if (preg_match('/^no\n/',$text_response)) {
835
phpCAS::trace('ST has not been validated');
836
$this->authError('ST not validated',
838
FALSE/*$no_response*/,
839
FALSE/*$bad_response*/,
842
if (!preg_match('/^yes\n/',$text_response)) {
843
phpCAS::trace('ill-formed response');
844
$this->authError('ST not validated',
846
FALSE/*$no_response*/,
847
TRUE/*$bad_response*/,
850
// ST has been validated, extract the user name
851
$arr = preg_split('/\n/',$text_response);
852
$this->setUser(trim($arr[1]));
854
case CAS_VERSION_2_0:
855
// read the response of the CAS server into a DOM object
856
if ( !($dom = domxml_open_mem($text_response))) {
857
phpCAS::trace('domxml_open_mem() failed');
858
$this->authError('ST not validated',
860
FALSE/*$no_response*/,
861
TRUE/*$bad_response*/,
864
// read the root node of the XML tree
865
if ( !($tree_response = $dom->document_element()) ) {
866
phpCAS::trace('document_element() failed');
867
$this->authError('ST not validated',
869
FALSE/*$no_response*/,
870
TRUE/*$bad_response*/,
873
// insure that tag name is 'serviceResponse'
874
if ( $tree_response->node_name() != 'serviceResponse' ) {
875
phpCAS::trace('bad XML root node (should be `serviceResponse\' instead of `'.$tree_response->node_name().'\'');
876
$this->authError('ST not validated',
878
FALSE/*$no_response*/,
879
TRUE/*$bad_response*/,
882
if ( sizeof($success_elements = $tree_response->get_elements_by_tagname("authenticationSuccess")) != 0) {
883
// authentication succeded, extract the user name
884
if ( sizeof($user_elements = $success_elements[0]->get_elements_by_tagname("user")) == 0) {
885
phpCAS::trace('<authenticationSuccess> found, but no <user>');
886
$this->authError('ST not validated',
888
FALSE/*$no_response*/,
889
TRUE/*$bad_response*/,
892
$user = trim($user_elements[0]->get_content());
893
phpCAS::trace('user = `'.$user);
894
$this->setUser($user);
896
} else if ( sizeof($failure_elements = $tree_response->get_elements_by_tagname("authenticationFailure")) != 0) {
897
phpCAS::trace('<authenticationFailure> found');
898
// authentication failed, extract the error code and message
899
$this->authError('ST not validated',
901
FALSE/*$no_response*/,
902
FALSE/*$bad_response*/,
904
$failure_elements[0]->get_attribute('code')/*$err_code*/,
905
trim($failure_elements[0]->get_content())/*$err_msg*/);
907
phpCAS::trace('neither <authenticationSuccess> nor <authenticationFailure> found');
908
$this->authError('ST not validated',
910
FALSE/*$no_response*/,
911
TRUE/*$bad_response*/,
917
// at this step, ST has been validated and $this->_user has been set,
918
phpCAS::traceEnd(TRUE);
924
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
926
// XX PROXY FEATURES (CAS 2.0) XX
928
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
930
// ########################################################################
932
// ########################################################################
934
* @addtogroup internalProxy
939
* A boolean telling if the client is a CAS proxy or not. Written by CASClient::CASClient(),
940
* read by CASClient::isProxy().
947
* Tells if a CAS client is a CAS proxy or not
949
* @return TRUE when the CAS client is a CAs proxy, FALSE otherwise
955
return $this->_proxy;
959
// ########################################################################
961
// ########################################################################
963
* @addtogroup internalProxy
968
* the Proxy Grnting Ticket given by the CAS server (empty otherwise).
969
* Written by CASClient::setPGT(), read by CASClient::getPGT() and CASClient::hasPGT().
977
* This method returns the Proxy Granting Ticket given by the CAS server.
978
* @return The Proxy Granting Ticket.
982
{ return $this->_pgt; }
985
* This method stores the Proxy Granting Ticket.
986
* @param $pgt The Proxy Granting Ticket.
989
function setPGT($pgt)
990
{ $this->_pgt = $pgt; }
993
* This method tells if a Proxy Granting Ticket was stored.
994
* @return TRUE if a Proxy Granting Ticket has been stored.
998
{ return !empty($this->_pgt); }
1002
// ########################################################################
1004
// ########################################################################
1006
* @addtogroup internalCallback
1010
* each PHP script using phpCAS in proxy mode is its own callback to get the
1011
* PGT back from the CAS server. callback_mode is detected by the constructor
1012
* thanks to the GET parameters.
1016
* a boolean to know if the CAS client is running in callback mode. Written by
1017
* CASClient::setCallBackMode(), read by CASClient::isCallbackMode().
1022
var $_callback_mode = FALSE;
1025
* This method sets/unsets callback mode.
1027
* @param $callback_mode TRUE to set callback mode, FALSE otherwise.
1031
function setCallbackMode($callback_mode)
1033
$this->_callback_mode = $callback_mode;
1037
* This method returns TRUE when the CAs client is running i callback mode,
1040
* @return A boolean.
1044
function isCallbackMode()
1046
return $this->_callback_mode;
1050
* the URL that should be used for the PGT callback (in fact the URL of the
1051
* current request without any CGI parameter). Written and read by
1052
* CASClient::getCallbackURL().
1057
var $_callback_url = '';
1060
* This method returns the URL that should be used for the PGT callback (in
1061
* fact the URL of the current request without any CGI parameter).
1063
* @return The callback URL
1067
function getCallbackURL()
1069
// the URL is built when needed only
1070
if ( empty($this->_callback_url) ) {
1071
// remove the ticket if present in the URL
1072
$this->_callback_url = 'https://';
1073
/* replaced by Julien Marchal - v0.4.6
1074
* $this->_callback_url .= $_SERVER['SERVER_NAME'];
1076
if(empty($_SERVER['HTTP_X_FORWARDED_SERVER'])){
1077
/* replaced by teedog - v0.4.12
1078
* $this->_callback_url .= $_SERVER['SERVER_NAME'];
1080
if (empty($_SERVER['SERVER_NAME'])) {
1081
$this->_callback_url .= $_SERVER['HTTP_HOST'];
1083
$this->_callback_url .= $_SERVER['SERVER_NAME'];
1086
$this->_callback_url .= $_SERVER['HTTP_X_FORWARDED_SERVER'];
1088
if ( ($_SERVER['HTTPS']=='on' && $_SERVER['SERVER_PORT']!=443)
1089
|| ($_SERVER['HTTPS']!='on' && $_SERVER['SERVER_PORT']!=80) ) {
1090
$this->_callback_url .= ':';
1091
$this->_callback_url .= $_SERVER['SERVER_PORT'];
1093
$request_uri = $_SERVER['REQUEST_URI'];
1094
$request_uri = preg_replace('/\?.*$/','',$request_uri);
1095
$this->_callback_url .= $request_uri;
1097
return $this->_callback_url;
1101
* This method is called by CASClient::CASClient() when running in callback
1102
* mode. It stores the PGT and its PGT Iou, prints its output and halts.
1108
phpCAS::traceBegin();
1109
$this->printHTMLHeader('phpCAS callback');
1110
$pgt_iou = $_GET['pgtIou'];
1111
$pgt = $_GET['pgtId'];
1112
phpCAS::trace('Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\')');
1113
echo '<p>Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\').</p>';
1114
$this->storePGT($pgt,$pgt_iou);
1115
$this->printHTMLFooter();
1116
phpCAS::traceExit();
1121
// ########################################################################
1123
// ########################################################################
1125
* @addtogroup internalPGTStorage
1130
* an instance of a class inheriting of PGTStorage, used to deal with PGT
1131
* storage. Created by CASClient::setPGTStorageFile() or CASClient::setPGTStorageDB(), used
1132
* by CASClient::setPGTStorageFile(), CASClient::setPGTStorageDB() and CASClient::initPGTStorage().
1137
var $_pgt_storage = null;
1140
* This method is used to initialize the storage of PGT's.
1145
function initPGTStorage()
1147
// if no SetPGTStorageXxx() has been used, default to file
1148
if ( !is_object($this->_pgt_storage) ) {
1149
$this->setPGTStorageFile();
1152
// initializes the storage
1153
$this->_pgt_storage->init();
1157
* This method stores a PGT. Halts on error.
1159
* @param $pgt the PGT to store
1160
* @param $pgt_iou its corresponding Iou
1164
function storePGT($pgt,$pgt_iou)
1166
// ensure that storage is initialized
1167
$this->initPGTStorage();
1169
$this->_pgt_storage->write($pgt,$pgt_iou);
1173
* This method reads a PGT from its Iou and deletes the corresponding storage entry.
1175
* @param $pgt_iou the PGT Iou
1177
* @return The PGT corresponding to the Iou, FALSE when not found.
1181
function loadPGT($pgt_iou)
1183
// ensure that storage is initialized
1184
$this->initPGTStorage();
1186
return $this->_pgt_storage->read($pgt_iou);
1190
* This method is used to tell phpCAS to store the response of the
1191
* CAS server to PGT requests onto the filesystem.
1193
* @param $format the format used to store the PGT's (`plain' and `xml' allowed)
1194
* @param $path the path where the PGT's should be stored
1198
function setPGTStorageFile($format='',
1201
// check that the storage has not already been set
1202
if ( is_object($this->_pgt_storage) ) {
1203
phpCAS::error('PGT storage already defined');
1206
// create the storage object
1207
$this->_pgt_storage = &new PGTStorageFile($this,$format,$path);
1211
* This method is used to tell phpCAS to store the response of the
1212
* CAS server to PGT requests into a database.
1213
* @note The connection to the database is done only when needed.
1214
* As a consequence, bad parameters are detected only when
1215
* initializing PGT storage.
1217
* @param $user the user to access the data with
1218
* @param $password the user's password
1219
* @param $database_type the type of the database hosting the data
1220
* @param $hostname the server hosting the database
1221
* @param $port the port the server is listening on
1222
* @param $database the name of the database
1223
* @param $table the name of the table storing the data
1227
function setPGTStorageDB($user,
1235
// check that the storage has not already been set
1236
if ( is_object($this->_pgt_storage) ) {
1237
phpCAS::error('PGT storage already defined');
1240
// warn the user that he should use file storage...
1241
trigger_error('PGT storage into database is an experimental feature, use at your own risk',E_USER_WARNING);
1243
// create the storage object
1244
$this->_pgt_storage = & new PGTStorageDB($this,$user,$password,$database_type,$hostname,$port,$database,$table);
1247
// ########################################################################
1249
// ########################################################################
1251
* This method is used to validate a PGT; halt on failure.
1253
* @param $validate_url the URL of the request to the CAS server.
1254
* @param $text_response the response of the CAS server, as is (XML text); result
1255
* of CASClient::validateST() or CASClient::validatePT().
1256
* @param $tree_response the response of the CAS server, as a DOM XML tree; result
1257
* of CASClient::validateST() or CASClient::validatePT().
1259
* @return bool TRUE when successfull, halt otherwise by calling CASClient::authError().
1263
function validatePGT(&$validate_url,$text_response,$tree_response)
1265
phpCAS::traceBegin();
1266
if ( sizeof($arr = $tree_response->get_elements_by_tagname("proxyGrantingTicket")) == 0) {
1267
phpCAS::trace('<proxyGrantingTicket> not found');
1268
// authentication succeded, but no PGT Iou was transmitted
1269
$this->authError('Ticket validated but no PGT Iou transmitted',
1271
FALSE/*$no_response*/,
1272
FALSE/*$bad_response*/,
1275
// PGT Iou transmitted, extract it
1276
$pgt_iou = trim($arr[0]->get_content());
1277
$pgt = $this->loadPGT($pgt_iou);
1278
if ( $pgt == FALSE ) {
1279
phpCAS::trace('could not load PGT');
1280
$this->authError('PGT Iou was transmitted but PGT could not be retrieved',
1282
FALSE/*$no_response*/,
1283
FALSE/*$bad_response*/,
1286
$this->setPGT($pgt);
1288
phpCAS::traceEnd(TRUE);
1292
// ########################################################################
1294
// ########################################################################
1297
* This method is used to retrieve PT's from the CAS server thanks to a PGT.
1299
* @param $target_service the service to ask for with the PT.
1300
* @param $err_code an error code (PHPCAS_SERVICE_OK on success).
1301
* @param $err_msg an error message (empty on success).
1303
* @return a Proxy Ticket, or FALSE on error.
1307
function retrievePT($target_service,&$err_code,&$err_msg)
1309
phpCAS::traceBegin();
1311
// by default, $err_msg is set empty and $pt to TRUE. On error, $pt is
1312
// set to false and $err_msg to an error message. At the end, if $pt is FALSE
1313
// and $error_msg is still empty, it is set to 'invalid response' (the most
1314
// commonly encountered error).
1317
// build the URL to retrieve the PT
1318
$cas_url = $this->getServerProxyURL().'?targetService='.preg_replace('/&/','%26',$target_service).'&pgt='.$this->getPGT();
1320
// open and read the URL
1321
if ( !$this->readURL($cas_url,''/*cookies*/,$headers,$cas_response,$err_msg) ) {
1322
phpCAS::trace('could not open URL \''.$cas_url.'\' to validate ('.$err_msg.')');
1323
$err_code = PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE;
1324
$err_msg = 'could not retrieve PT (no response from the CAS server)';
1325
phpCAS::traceEnd(FALSE);
1329
$bas_response = FALSE;
1331
if ( !$bad_response ) {
1332
// read the response of the CAS server into a DOM object
1333
if ( !($dom = @domxml_open_mem($cas_response))) {
1334
phpCAS::trace('domxml_open_mem() failed');
1336
$bad_response = TRUE;
1340
if ( !$bad_response ) {
1341
// read the root node of the XML tree
1342
if ( !($root = $dom->document_element()) ) {
1343
phpCAS::trace('document_element() failed');
1345
$bad_response = TRUE;
1349
if ( !$bad_response ) {
1350
// insure that tag name is 'serviceResponse'
1351
if ( $root->node_name() != 'serviceResponse' ) {
1352
phpCAS::trace('node_name() failed');
1354
$bad_response = TRUE;
1358
if ( !$bad_response ) {
1359
// look for a proxySuccess tag
1360
if ( sizeof($arr = $root->get_elements_by_tagname("proxySuccess")) != 0) {
1361
// authentication succeded, look for a proxyTicket tag
1362
if ( sizeof($arr = $root->get_elements_by_tagname("proxyTicket")) != 0) {
1363
$err_code = PHPCAS_SERVICE_OK;
1365
$pt = trim($arr[0]->get_content());
1366
phpCAS::traceEnd($pt);
1369
phpCAS::trace('<proxySuccess> was found, but not <proxyTicket>');
1372
// look for a proxyFailure tag
1373
else if ( sizeof($arr = $root->get_elements_by_tagname("proxyFailure")) != 0) {
1374
// authentication failed, extract the error
1375
$err_code = PHPCAS_SERVICE_PT_FAILURE;
1376
$err_msg = 'PT retrieving failed (code=`'
1377
.$arr[0]->get_attribute('code')
1379
.trim($arr[0]->get_content())
1381
phpCAS::traceEnd(FALSE);
1384
phpCAS::trace('neither <proxySuccess> nor <proxyFailure> found');
1388
// at this step, we are sure that the response of the CAS server was ill-formed
1389
$err_code = PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE;
1390
$err_msg = 'Invalid response from the CAS server (response=`'.$cas_response.'\')';
1392
phpCAS::traceEnd(FALSE);
1396
// ########################################################################
1397
// ACCESS TO EXTERNAL SERVICES
1398
// ########################################################################
1401
* This method is used to acces a remote URL.
1403
* @param $url the URL to access.
1404
* @param $cookies an array containing cookies strings such as 'name=val'
1405
* @param $headers an array containing the HTTP header lines of the response
1406
* (an empty array on failure).
1407
* @param $body the body of the response, as a string (empty on failure).
1408
* @param $err_msg an error message, filled on failure.
1410
* @return TRUE on success, FALSE otherwise (in this later case, $err_msg
1411
* contains an error message).
1415
function readURL($url,$cookies,&$headers,&$body,&$err_msg)
1417
phpCAS::traceBegin();
1424
// initialize the CURL session
1425
$ch = curl_init($url);
1427
// verify the the server's certificate corresponds to its name
1428
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
1429
// but do not verify the certificate itself
1430
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
1432
// return the CURL output into a variable
1433
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
1434
// include the HTTP header with the body
1435
curl_setopt($ch, CURLOPT_HEADER, 1);
1436
// add cookies headers
1437
if ( is_array($cookies) ) {
1438
curl_setopt($ch,CURLOPT_COOKIE,implode(';',$cookies));
1440
// perform the query
1441
$buf = curl_exec ($ch);
1442
if ( $buf === FALSE ) {
1443
phpCAS::trace('cur_exec() failed');
1444
$err_msg = 'CURL error #'.curl_errno($ch).': '.curl_error($ch);
1445
// close the CURL session
1449
// close the CURL session
1452
// find the end of the headers
1453
// note: strpos($str,"\n\r\n\r") does not work (?)
1455
for ($i=0; $i<strlen($buf); $i++) {
1456
if ( $buf[$i] == chr(13) )
1457
if ( $buf[$i+1] == chr(10) )
1458
if ( $buf[$i+2] == chr(13) )
1459
if ( $buf[$i+3] == chr(10) ) {
1466
if ( $pos === FALSE ) {
1467
// end of header not found
1468
$err_msg = 'no header found';
1469
phpCAS::trace($err_msg);
1472
// extract headers into an array
1473
$headers = preg_split ("/[\n\r]+/",substr($buf,0,$pos));
1474
// extract body into a string
1475
$body = substr($buf,$pos+4);
1479
phpCAS::traceEnd($res);
1484
* This method is used to access an HTTP[S] service.
1486
* @param $url the service to access.
1487
* @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on
1488
* success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE,
1489
* PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_NOT AVAILABLE.
1490
* @param $output the output of the service (also used to give an error
1491
* message on failure).
1493
* @return TRUE on success, FALSE otherwise (in this later case, $err_code
1494
* gives the reason why it failed and $output contains an error message).
1498
function serviceWeb($url,&$err_code,&$output)
1500
phpCAS::traceBegin();
1501
// at first retrieve a PT
1502
$pt = $this->retrievePT($url,$err_code,$output);
1506
// test if PT was retrieved correctly
1508
// note: $err_code and $err_msg are filled by CASClient::retrievePT()
1509
phpCAS::trace('PT was not retrieved correctly');
1512
// add cookies if necessary
1513
if ( is_array($_SESSION['phpCAS']['services'][$url]['cookies']) ) {
1514
foreach ( $_SESSION['phpCAS']['services'][$url]['cookies'] as $name => $val ) {
1515
$cookies[] = $name.'='.$val;
1519
// build the URL including the PT
1520
if ( strstr($url,'?') === FALSE ) {
1521
$service_url = $url.'?ticket='.$pt;
1523
$service_url = $url.'&ticket='.$pt;
1526
phpCAS::trace('reading URL`'.$service_url.'\'');
1527
if ( !$this->readURL($service_url,$cookies,$headers,$output,$err_msg) ) {
1528
phpCAS::trace('could not read URL`'.$service_url.'\'');
1529
$err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
1530
// give an error message
1531
$output = sprintf($this->getString(CAS_STR_SERVICE_UNAVAILABLE),
1536
// URL has been fetched, extract the cookies
1537
phpCAS::trace('URL`'.$service_url.'\' has been read, storing cookies:');
1538
foreach ( $headers as $header ) {
1539
// test if the header is a cookie
1540
if ( preg_match('/^Set-Cookie:/',$header) ) {
1541
// the header is a cookie, remove the beginning
1542
$header_val = preg_replace('/^Set-Cookie: */','',$header);
1543
// extract interesting information
1544
$name_val = strtok($header_val,'; ');
1545
// extract the name and the value of the cookie
1546
$cookie_name = strtok($name_val,'=');
1547
$cookie_val = strtok('=');
1549
$_SESSION['phpCAS']['services'][$url]['cookies'][$cookie_name] = $cookie_val;
1550
phpCAS::trace($cookie_name.' -> '.$cookie_val);
1556
phpCAS::traceEnd($res);
1561
* This method is used to access an IMAP/POP3/NNTP service.
1563
* @param $url a string giving the URL of the service, including the mailing box
1564
* for IMAP URLs, as accepted by imap_open().
1565
* @param $flags options given to imap_open().
1566
* @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on
1567
* success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE,
1568
* PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_NOT AVAILABLE.
1569
* @param $err_msg an error message on failure
1570
* @param $pt the Proxy Ticket (PT) retrieved from the CAS server to access the URL
1571
* on success, FALSE on error).
1573
* @return an IMAP stream on success, FALSE otherwise (in this later case, $err_code
1574
* gives the reason why it failed and $err_msg contains an error message).
1578
function serviceMail($url,$flags,&$err_code,&$err_msg,&$pt)
1580
phpCAS::traceBegin();
1581
// at first retrieve a PT
1582
$pt = $this->retrievePT($target_service,$err_code,$output);
1586
// test if PT was retrieved correctly
1588
// note: $err_code and $err_msg are filled by CASClient::retrievePT()
1589
phpCAS::trace('PT was not retrieved correctly');
1591
phpCAS::trace('opening IMAP URL `'.$url.'\'...');
1592
$stream = @imap_open($url,$this->getUser(),$pt,$flags);
1594
phpCAS::trace('could not open URL');
1595
$err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
1596
// give an error message
1597
$err_msg = sprintf($this->getString(CAS_STR_SERVICE_UNAVAILABLE),
1599
var_export(imap_errors(),TRUE));
1603
phpCAS::trace('ok');
1607
phpCAS::traceEnd($stream);
1613
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1615
// XX PROXIED CLIENT FEATURES (CAS 2.0) XX
1617
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1619
// ########################################################################
1621
// ########################################################################
1623
* @addtogroup internalProxied
1628
* the Proxy Ticket provided in the URL of the request if present
1629
* (empty otherwise). Written by CASClient::CASClient(), read by
1630
* CASClient::getPT() and CASClient::hasPGT().
1638
* This method returns the Proxy Ticket provided in the URL of the request.
1639
* @return The proxy ticket.
1643
{ return $this->_pt; }
1646
* This method stores the Proxy Ticket.
1647
* @param $pt The Proxy Ticket.
1651
{ $this->_pt = $pt; }
1654
* This method tells if a Proxy Ticket was stored.
1655
* @return TRUE if a Proxy Ticket has been stored.
1659
{ return !empty($this->_pt); }
1662
// ########################################################################
1664
// ########################################################################
1666
* @addtogroup internalProxied
1671
* This method is used to validate a PT; halt on failure
1673
* @return bool TRUE when successfull, halt otherwise by calling CASClient::authError().
1677
function validatePT(&$validate_url,&$text_response,&$tree_response)
1679
phpCAS::traceBegin();
1680
// build the URL to validate the ticket
1681
$validate_url = $this->getServerProxyValidateURL().'&ticket='.$this->getPT();
1683
if ( $this->isProxy() ) {
1684
// pass the callback url for CAS proxies
1685
$validate_url .= '&pgtUrl='.$this->getCallbackURL();
1688
// open and read the URL
1689
if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) {
1690
phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
1691
$this->authError('PT not validated',
1693
TRUE/*$no_response*/);
1696
// read the response of the CAS server into a DOM object
1697
if ( !($dom = domxml_open_mem($text_response))) {
1699
$this->authError('PT not validated',
1701
FALSE/*$no_response*/,
1702
TRUE/*$bad_response*/,
1705
// read the root node of the XML tree
1706
if ( !($tree_response = $dom->document_element()) ) {
1708
$this->authError('PT not validated',
1710
FALSE/*$no_response*/,
1711
TRUE/*$bad_response*/,
1714
// insure that tag name is 'serviceResponse'
1715
if ( $tree_response->node_name() != 'serviceResponse' ) {
1717
$this->authError('PT not validated',
1719
FALSE/*$no_response*/,
1720
TRUE/*$bad_response*/,
1723
if ( sizeof($arr = $tree_response->get_elements_by_tagname("authenticationSuccess")) != 0) {
1724
// authentication succeded, extract the user name
1725
if ( sizeof($arr = $tree_response->get_elements_by_tagname("user")) == 0) {
1726
// no user specified => error
1727
$this->authError('PT not validated',
1729
FALSE/*$no_response*/,
1730
TRUE/*$bad_response*/,
1733
$this->setUser(trim($arr[0]->get_content()));
1735
} else if ( sizeof($arr = $tree_response->get_elements_by_tagname("authenticationFailure")) != 0) {
1736
// authentication succeded, extract the error code and message
1737
$this->authError('PT not validated',
1739
FALSE/*$no_response*/,
1740
FALSE/*$bad_response*/,
1742
$arr[0]->get_attribute('code')/*$err_code*/,
1743
trim($arr[0]->get_content())/*$err_msg*/);
1745
$this->authError('PT not validated',
1747
FALSE/*$no_response*/,
1748
TRUE/*$bad_response*/,
1752
// at this step, PT has been validated and $this->_user has been set,
1754
phpCAS::traceEnd(TRUE);
1760
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1764
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1767
* @addtogroup internalMisc
1771
// ########################################################################
1773
// ########################################################################
1775
* the URL of the current request (without any ticket CGI parameter). Written
1776
* and read by CASClient::getURL().
1784
* This method returns the URL of the current request (without any ticket
1793
phpCAS::traceBegin();
1794
// the URL is built when needed only
1795
if ( empty($this->_url) ) {
1796
// remove the ticket if present in the URL
1797
$this->_url = ($_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
1798
$this->_url .= '://';
1799
/* replaced by Julien Marchal - v0.4.6
1800
* $this->_url .= $_SERVER['SERVER_NAME'];
1802
if(empty($_SERVER['HTTP_X_FORWARDED_SERVER'])){
1803
/* replaced by teedog - v0.4.12
1804
* $this->_url .= $_SERVER['SERVER_NAME'];
1806
if (empty($_SERVER['SERVER_NAME'])) {
1807
$this->_url .= $_SERVER['HTTP_HOST'];
1809
$this->_url .= $_SERVER['SERVER_NAME'];
1812
$this->_url .= $_SERVER['HTTP_X_FORWARDED_SERVER'];
1814
if ( ($_SERVER['HTTPS']=='on' && $_SERVER['SERVER_PORT']!=443)
1815
|| ($_SERVER['HTTPS']!='on' && $_SERVER['SERVER_PORT']!=80) ) {
1817
$this->_url .= $_SERVER['SERVER_PORT'];
1820
$this->_url .= strtok($_SERVER['REQUEST_URI'],"?");
1821
$cgi_params = '?'.strtok("?");
1822
// remove the ticket if present in the CGI parameters
1823
$cgi_params = preg_replace('/&ticket=[^&]*/','',$cgi_params);
1824
$cgi_params = preg_replace('/\?ticket=[^&]*/','?',$cgi_params);
1825
$cgi_params = preg_replace('/\?$/','',$cgi_params);
1826
$this->_url .= $cgi_params;
1828
phpCAS::traceEnd($this->_url);
1833
// ########################################################################
1834
// AUTHENTICATION ERROR HANDLING
1835
// ########################################################################
1837
* This method is used to print the HTML output when the user was not authenticated.
1839
* @param $failure the failure that occured
1840
* @param $cas_url the URL the CAS server was asked for
1841
* @param $no_response the response from the CAS server (other
1842
* parameters are ignored if TRUE)
1843
* @param $bad_response bad response from the CAS server ($err_code
1844
* and $err_msg ignored if TRUE)
1845
* @param $cas_response the response of the CAS server
1846
* @param $err_code the error code given by the CAS server
1847
* @param $err_msg the error message given by the CAS server
1851
function authError($failure,$cas_url,$no_response,$bad_response='',$cas_response='',$err_code='',$err_msg='')
1853
phpCAS::traceBegin();
1855
$this->printHTMLHeader($this->getString(CAS_STR_AUTHENTICATION_FAILED));
1856
printf($this->getString(CAS_STR_YOU_WERE_NOT_AUTHENTICATED),$this->getURL(),$_SERVER['SERVER_ADMIN']);
1857
phpCAS::trace('CAS URL: '.$cas_url);
1858
phpCAS::trace('Authentication failure: '.$failure);
1859
if ( $no_response ) {
1860
phpCAS::trace('Reason: no response from the CAS server');
1862
if ( $bad_response ) {
1863
phpCAS::trace('Reason: bad response from the CAS server');
1865
switch ($this->getServerVersion()) {
1866
case CAS_VERSION_1_0:
1867
phpCAS::trace('Reason: CAS error');
1869
case CAS_VERSION_2_0:
1870
if ( empty($err_code) )
1871
phpCAS::trace('Reason: no CAS error');
1873
phpCAS::trace('Reason: ['.$err_code.'] CAS error: '.$err_msg);
1877
phpCAS::trace('CAS response: '.$cas_response);
1879
$this->printHTMLFooter();
1880
phpCAS::traceExit();
b'\\ No newline at end of file'