CAS/client.php

Go to the documentation of this file.
00001 <?php
00002 
00008 // include internationalization stuff
00009 include_once(dirname(__FILE__).'/languages/languages.php');
00010 
00011 // include PGT storage classes
00012 include_once(dirname(__FILE__).'/PGTStorage/pgt-main.php');
00013 
00022 class CASClient
00023 {
00024 
00025   // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
00026   // XX                                                                    XX
00027   // XX                          CONFIGURATION                             XX
00028   // XX                                                                    XX
00029   // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
00030 
00031   // ########################################################################
00032   //  HTML OUTPUT
00033   // ########################################################################
00052   function HTMLFilterOutput($str)
00053     {
00054       $str = str_replace('__CAS_VERSION__',$this->getServerVersion(),$str);
00055       $str = str_replace('__PHPCAS_VERSION__',phpCAS::getVersion(),$str);
00056       $str = str_replace('__SERVER_BASE_URL__',$this->getServerBaseURL(),$str);
00057       echo $str;
00058     }
00059 
00068   var $_output_header = '';
00069   
00079   function printHTMLHeader($title)
00080     {
00081       $this->HTMLFilterOutput(str_replace('__TITLE__',
00082                                           $title,
00083                                           (empty($this->_output_header)
00084                                            ? '<html><head><title>__TITLE__</title></head><body><h1>__TITLE__</h1>'
00085                                            : $this->_output_header)
00086                                           )
00087                               );
00088     }
00089 
00098   var $_output_footer = '';
00099   
00107   function printHTMLFooter()
00108     {
00109       $this->HTMLFilterOutput(empty($this->_output_footer)
00110                               ?('<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>')
00111                               :$this->_output_footer);
00112     }
00113 
00121   function setHTMLHeader($header)
00122     {
00123       $this->_output_header = $header;
00124     }
00125 
00133   function setHTMLFooter($footer)
00134     {
00135       $this->_output_footer = $footer;
00136     }
00137 
00139   // ########################################################################
00140   //  INTERNATIONALIZATION
00141   // ########################################################################
00156   var $_lang = '';
00157   
00165   function getLang()
00166     {
00167       if ( empty($this->_lang) )
00168         $this->setLang(PHPCAS_LANG_DEFAULT);
00169       return $this->_lang;
00170     }
00171 
00181   var $_strings;
00182 
00192   function getString($str)
00193     {
00194       // call CASclient::getLang() to be sure the language is initialized
00195       $this->getLang();
00196       
00197       if ( !isset($this->_strings[$str]) ) {
00198         trigger_error('string `'.$str.'\' not defined for language `'.$this->getLang().'\'',E_USER_ERROR);
00199       }
00200       return $this->_strings[$str];
00201     }
00202 
00212   function setLang($lang)
00213     {
00214       // include the corresponding language file
00215       include_once(dirname(__FILE__).'/languages/'.$lang.'.php');
00216 
00217       if ( !is_array($this->_strings) ) {
00218         trigger_error('language `'.$lang.'\' is not implemented',E_USER_ERROR);
00219       }
00220       $this->_lang = $lang;
00221     }
00222 
00224   // ########################################################################
00225   //  CAS SERVER CONFIG
00226   // ########################################################################
00256   var $_server = array(
00257                        'version' => -1,
00258                        'hostname' => 'none',
00259                        'port' => -1,
00260                        'uri' => 'none'
00261                        );
00262   
00268   function getServerVersion()
00269     { 
00270       return $this->_server['version']; 
00271     }
00272 
00278   function getServerHostname()
00279     { return $this->_server['hostname']; }
00280 
00286   function getServerPort()
00287     { return $this->_server['port']; }
00288 
00294   function getServerURI()
00295     { return $this->_server['uri']; }
00296 
00302   function getServerBaseURL()
00303     { 
00304       // the URL is build only when needed
00305       if ( empty($this->_server['base_url']) ) {
00306         $this->_server['base_url'] = 'https://'
00307           .$this->getServerHostname()
00308           .':'
00309           .$this->getServerPort()
00310           .$this->getServerURI();
00311       }
00312       return $this->_server['base_url']; 
00313     }
00314 
00321   function getServerLoginURL($gateway=false)
00322     { 
00323       phpCAS::traceBegin();
00324       // the URL is build only when needed
00325       if ( empty($this->_server['login_url']) ) {
00326         $this->_server['login_url'] = $this->getServerBaseURL();
00327         $this->_server['login_url'] .= 'login?service=';
00328 //        $this->_server['login_url'] .= preg_replace('/&/','%26',$this->getURL());
00329         $this->_server['login_url'] .= urlencode($this->getURL());
00330         if ($gateway) {
00331           $this->_server['login_url'] .= '&gateway=true';
00332         }
00333       }
00334       phpCAS::traceEnd($this->_server['login_url']);
00335       return $this->_server['login_url']; 
00336     }
00337 
00344   function setServerLoginURL($url)
00345     {
00346       return $this->_server['login_url'] = $url;
00347     }
00348 
00354   function getServerServiceValidateURL()
00355     { 
00356       // the URL is build only when needed
00357       if ( empty($this->_server['service_validate_url']) ) {
00358         switch ($this->getServerVersion()) {
00359         case CAS_VERSION_1_0:
00360           $this->_server['service_validate_url'] = $this->getServerBaseURL().'validate';
00361           break;
00362         case CAS_VERSION_2_0:
00363           $this->_server['service_validate_url'] = $this->getServerBaseURL().'serviceValidate';
00364           break;
00365         }
00366       }
00367 //      return $this->_server['service_validate_url'].'?service='.preg_replace('/&/','%26',$this->getURL()); 
00368       return $this->_server['service_validate_url'].'?service='.urlencode($this->getURL()); 
00369     }
00370 
00376   function getServerProxyValidateURL()
00377     { 
00378       // the URL is build only when needed
00379       if ( empty($this->_server['proxy_validate_url']) ) {
00380         switch ($this->getServerVersion()) {
00381         case CAS_VERSION_1_0:
00382           $this->_server['proxy_validate_url'] = '';
00383           break;
00384         case CAS_VERSION_2_0:
00385           $this->_server['proxy_validate_url'] = $this->getServerBaseURL().'proxyValidate';
00386           break;
00387         }
00388       }
00389 //      return $this->_server['proxy_validate_url'].'?service='.preg_replace('/&/','%26',$this->getURL()); 
00390       return $this->_server['proxy_validate_url'].'?service='.urlencode($this->getURL()); 
00391     }
00392 
00398   function getServerProxyURL()
00399     { 
00400       // the URL is build only when needed
00401       if ( empty($this->_server['proxy_url']) ) {
00402         switch ($this->getServerVersion()) {
00403         case CAS_VERSION_1_0:
00404           $this->_server['proxy_url'] = '';
00405           break;
00406         case CAS_VERSION_2_0:
00407           $this->_server['proxy_url'] = $this->getServerBaseURL().'proxy';
00408           break;
00409         }
00410       }
00411       return $this->_server['proxy_url']; 
00412     }
00413 
00419   function getServerLogoutURL()
00420     { 
00421       // the URL is build only when needed
00422       if ( empty($this->_server['logout_url']) ) {
00423         $this->_server['logout_url'] = $this->getServerBaseURL().'logout';
00424       }
00425       return $this->_server['logout_url']; 
00426     }
00427 
00434   function setServerLogoutURL($url)
00435     {
00436       return $this->_server['logout_url'] = $url;
00437     }
00438 
00444   function isHttps() {
00445     //if ( isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) ) {
00446     //0.4.24 by Hinnack
00447     if ( isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
00448       return true;
00449     } else {
00450       return false;
00451     }
00452   }
00453 
00454   // ########################################################################
00455   //  CONSTRUCTOR
00456   // ########################################################################
00471   function CASClient(
00472         $server_version,
00473         $proxy,
00474         $server_hostname,
00475         $server_port,
00476         $server_uri,
00477         $start_session = true) {
00478 
00479     phpCAS::traceBegin();
00480 
00481     //activate session mechanism if desired
00482     if ($start_session) {
00483       session_start();
00484     }
00485 
00486     $this->_proxy = $proxy;
00487 
00488     //check version
00489     switch ($server_version) {
00490       case CAS_VERSION_1_0:
00491         if ( $this->isProxy() )
00492           phpCAS::error('CAS proxies are not supported in CAS '
00493               .$server_version);
00494         break;
00495       case CAS_VERSION_2_0:
00496         break;
00497       default:
00498         phpCAS::error('this version of CAS (`'
00499             .$server_version
00500             .'\') is not supported by phpCAS '
00501             .phpCAS::getVersion());
00502     }
00503     $this->_server['version'] = $server_version;
00504 
00505     //check hostname
00506     if ( empty($server_hostname) 
00507         || !preg_match('/[\.\d\-abcdefghijklmnopqrstuvwxyz]*/',$server_hostname) ) {
00508       phpCAS::error('bad CAS server hostname (`'.$server_hostname.'\')');
00509     }
00510     $this->_server['hostname'] = $server_hostname;
00511 
00512     //check port
00513     if ( $server_port == 0 
00514         || !is_int($server_port) ) {
00515       phpCAS::error('bad CAS server port (`'.$server_hostname.'\')');
00516     }
00517     $this->_server['port'] = $server_port;
00518 
00519     //check URI
00520     if ( !preg_match('/[\.\d\-_abcdefghijklmnopqrstuvwxyz\/]*/',$server_uri) ) {
00521       phpCAS::error('bad CAS server URI (`'.$server_uri.'\')');
00522     }
00523     //add leading and trailing `/' and remove doubles      
00524     $server_uri = preg_replace('/\/\//','/','/'.$server_uri.'/');
00525     $this->_server['uri'] = $server_uri;
00526 
00527     //set to callback mode if PgtIou and PgtId CGI GET parameters are provided 
00528     if ( $this->isProxy() ) {
00529       $this->setCallbackMode(!empty($_GET['pgtIou'])&&!empty($_GET['pgtId']));
00530     }
00531 
00532     if ( $this->isCallbackMode() ) {
00533       //callback mode: check that phpCAS is secured
00534       if ( !$this->isHttps() ) {
00535         phpCAS::error('CAS proxies must be secured to use phpCAS; PGT\'s will not be received from the CAS server');
00536       }
00537     } else {
00538       //normal mode: get ticket and remove it from CGI parameters for developpers
00539       $ticket = (isset($_GET['ticket']) ? $_GET['ticket'] : null);
00540       switch ($this->getServerVersion()) {
00541         case CAS_VERSION_1_0: // check for a Service Ticket
00542           if( preg_match('/^ST-/',$ticket) ) {
00543             phpCAS::trace('ST \''.$ticket.'\' found');
00544             //ST present
00545             $this->setST($ticket);
00546             //ticket has been taken into account, unset it to hide it to applications
00547             unset($_GET['ticket']);
00548           } else if ( !empty($ticket) ) {
00549             //ill-formed ticket, halt
00550             phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')');
00551           }
00552           break;
00553         case CAS_VERSION_2_0: // check for a Service or Proxy Ticket
00554           if( preg_match('/^[SP]T-/',$ticket) ) {
00555             phpCAS::trace('ST or PT \''.$ticket.'\' found');
00556             $this->setPT($ticket);
00557             unset($_GET['ticket']);
00558           } else if ( !empty($ticket) ) {
00559             //ill-formed ticket, halt
00560             phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')');
00561           } 
00562           break;
00563         }
00564         }
00565     phpCAS::traceEnd();
00566   }
00567 
00570   // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
00571   // XX                                                                    XX
00572   // XX                           AUTHENTICATION                           XX
00573   // XX                                                                    XX
00574   // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
00575 
00588   var $_user = '';
00589   
00597   function setUser($user)
00598     {
00599       $this->_user = $user;
00600     }
00601 
00609   function getUser()
00610     {
00611       if ( empty($this->_user) ) {
00612         phpCAS::error('this method should be used only after '.__CLASS__.'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()');
00613       }
00614       return $this->_user;
00615     }
00616 
00623   function forceAuthentication()
00624     {
00625       phpCAS::traceBegin();
00626 
00627       if ( $this->isAuthenticated() ) {
00628         // the user is authenticated, nothing to be done.
00629             phpCAS::trace('no need to authenticate');
00630             $res = TRUE;
00631       } else {
00632             // the user is not authenticated, redirect to the CAS server
00633         unset($_SESSION['phpCAS']['auth_checked']);
00634             $this->redirectToCas(FALSE/* no gateway */);        
00635             // never reached
00636             $res = FALSE;
00637       }
00638       phpCAS::traceEnd($res);
00639       return $res;
00640     }
00641 
00648   var $_cache_times_for_auth_recheck = 0;
00649   
00657   function setCacheTimesForAuthRequest($n)
00658     {
00659       $this->_cache_times_for_auth_recheck = n;
00660     }
00661 
00667   function checkAuthentication()
00668     {
00669       phpCAS::traceBegin();
00670 
00671       if ( $this->isAuthenticated() ) {
00672             phpCAS::trace('user is authenticated');
00673             $res = TRUE;
00674       } else if (isset($_SESSION['phpCAS']['auth_checked'])) {
00675         // the previous request has redirected the client to the CAS server with gateway=true
00676         unset($_SESSION['phpCAS']['auth_checked']);
00677         $res = FALSE;
00678       } else {
00679 //        $_SESSION['phpCAS']['auth_checked'] = true;
00680 //          $this->redirectToCas(TRUE/* gateway */);    
00681 //          // never reached
00682 //          $res = FALSE;
00683         // avoid a check against CAS on every request
00684         if (! isset($_SESSION['phpCAS']['unauth_count']) )
00685            $_SESSION['phpCAS']['unauth_count'] = -2; // uninitialized
00686         
00687         if (($_SESSION['phpCAS']['unauth_count'] != -2 && $this->_cache_times_for_auth_recheck == -1) 
00688           || ($_SESSION['phpCAS']['unauth_count'] >= 0 && $_SESSION['phpCAS']['unauth_count'] < $this->_cache_times_for_auth_recheck))
00689         {
00690            $res = FALSE;
00691            
00692            if ($this->_cache_times_for_auth_recheck != -1)
00693            {
00694                           $_SESSION['phpCAS']['unauth_count']++;
00695                   phpCAS::trace('user is not authenticated (cached for '.$_SESSION['phpCAS']['unauth_count'].' times of '.$this->_cache_times_for_auth_recheck.')');
00696            }
00697            else
00698            {
00699                   phpCAS::trace('user is not authenticated (cached for until login pressed)');
00700            }
00701         }
00702         else
00703         {
00704                 $_SESSION['phpCAS']['unauth_count'] = 0;
00705             $_SESSION['phpCAS']['auth_checked'] = true;
00706             phpCAS::trace('user is not authenticated (cache reset)');
00707             $this->redirectToCas(TRUE/* gateway */);    
00708             // never reached
00709             $res = FALSE;
00710         }
00711       }
00712       phpCAS::traceEnd($res);
00713       return $res;
00714     }
00715   
00724   function isAuthenticated()
00725   {
00726       phpCAS::traceBegin();
00727       $res = FALSE;
00728       $validate_url = '';
00729 
00730       if ( $this->wasPreviouslyAuthenticated() ) {
00731                  // the user has already (previously during the session) been 
00732                  // authenticated, nothing to be done.
00733         phpCAS::trace('user was already authenticated, no need to look for tickets');
00734         $res = TRUE;
00735       } 
00736           elseif ( $this->hasST() ) {
00737         // if a Service Ticket was given, validate it
00738         phpCAS::trace('ST `'.$this->getST().'\' is present');
00739         $this->validateST($validate_url,$text_response,$tree_response); // if it fails, it halts
00740         phpCAS::trace('ST `'.$this->getST().'\' was validated');
00741         if ( $this->isProxy() ) {
00742                    $this->validatePGT($validate_url,$text_response,$tree_response); // idem
00743                    phpCAS::trace('PGT `'.$this->getPGT().'\' was validated');
00744                    $_SESSION['phpCAS']['pgt'] = $this->getPGT();
00745                 }
00746                 $_SESSION['phpCAS']['user'] = $this->getUser();
00747                 $res = TRUE;
00748         }
00749         elseif ( $this->hasPT() ) {
00750                 // if a Proxy Ticket was given, validate it
00751                 phpCAS::trace('PT `'.$this->getPT().'\' is present');
00752                 $this->validatePT($validate_url,$text_response,$tree_response); // note: if it fails, it halts
00753                 phpCAS::trace('PT `'.$this->getPT().'\' was validated');
00754                 if ( $this->isProxy() ) {
00755                    $this->validatePGT($validate_url,$text_response,$tree_response); // idem
00756                    phpCAS::trace('PGT `'.$this->getPGT().'\' was validated');
00757                    $_SESSION['phpCAS']['pgt'] = $this->getPGT();
00758                 }
00759         $_SESSION['phpCAS']['user'] = $this->getUser();
00760                 $res = TRUE;
00761         } 
00762         else {
00763         // no ticket given, not authenticated
00764         phpCAS::trace('no ticket found');
00765         }
00766 
00767         phpCAS::traceEnd($res);
00768         return $res;
00769   }
00770   
00776   function isSessionAuthenticated ()
00777     {
00778       return !empty($_SESSION['phpCAS']['user']);
00779     }
00780 
00791   function wasPreviouslyAuthenticated()
00792     {
00793       phpCAS::traceBegin();
00794 
00795       if ( $this->isCallbackMode() ) {
00796         $this->callback();
00797       }
00798 
00799       $auth = FALSE;
00800 
00801       if ( $this->isProxy() ) {
00802         // CAS proxy: username and PGT must be present
00803         if ( $this->isSessionAuthenticated() && !empty($_SESSION['phpCAS']['pgt']) ) {
00804           // authentication already done
00805           $this->setUser($_SESSION['phpCAS']['user']);
00806           $this->setPGT($_SESSION['phpCAS']['pgt']);
00807           phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\', PGT = `'.$_SESSION['phpCAS']['pgt'].'\''); 
00808           $auth = TRUE;
00809         } elseif ( $this->isSessionAuthenticated() && empty($_SESSION['phpCAS']['pgt']) ) {
00810           // these two variables should be empty or not empty at the same time
00811           phpCAS::trace('username found (`'.$_SESSION['phpCAS']['user'].'\') but PGT is empty');
00812           // unset all tickets to enforce authentication
00813           unset($_SESSION['phpCAS']);
00814           $this->setST('');
00815           $this->setPT('');
00816         } elseif ( !$this->isSessionAuthenticated() && !empty($_SESSION['phpCAS']['pgt']) ) {
00817           // these two variables should be empty or not empty at the same time
00818           phpCAS::trace('PGT found (`'.$_SESSION['phpCAS']['pgt'].'\') but username is empty'); 
00819           // unset all tickets to enforce authentication
00820           unset($_SESSION['phpCAS']);
00821           $this->setST('');
00822           $this->setPT('');
00823         } else {
00824           phpCAS::trace('neither user not PGT found'); 
00825         }
00826       } else {
00827         // `simple' CAS client (not a proxy): username must be present
00828         if ( $this->isSessionAuthenticated() ) {
00829           // authentication already done
00830           $this->setUser($_SESSION['phpCAS']['user']);
00831           phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\''); 
00832           $auth = TRUE;
00833         } else {
00834           phpCAS::trace('no user found');
00835         }
00836       }
00837       
00838       phpCAS::traceEnd($auth);
00839       return $auth;
00840     }
00841   
00848   function redirectToCas($gateway=false)
00849     {
00850       phpCAS::traceBegin();
00851       $cas_url = $this->getServerLoginURL($gateway);
00852       header('Location: '.$cas_url);
00853       $this->printHTMLHeader($this->getString(CAS_STR_AUTHENTICATION_WANTED));
00854       printf('<p>'.$this->getString(CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'</p>',$cas_url);
00855       $this->printHTMLFooter();
00856       phpCAS::traceExit();
00857       exit();
00858     }
00859   
00865   function logout($url = "")
00866     {
00867       phpCAS::traceBegin();
00868       $cas_url = $this->getServerLogoutURL();
00869       // v0.4.14 sebastien.gougeon at univ-rennes1.fr
00870       // header('Location: '.$cas_url);
00871       if ( $url != "" ) {
00872         $url = '?service=' . $url;
00873       }
00874       header('Location: '.$cas_url . $url);
00875       session_unset();
00876       session_destroy();
00877       $this->printHTMLHeader($this->getString(CAS_STR_LOGOUT));
00878       printf('<p>'.$this->getString(CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'</p>',$cas_url);
00879       $this->printHTMLFooter();
00880       phpCAS::traceExit();
00881       exit();
00882     }
00883   
00886   // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
00887   // XX                                                                    XX
00888   // XX                  BASIC CLIENT FEATURES (CAS 1.0)                   XX
00889   // XX                                                                    XX
00890   // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
00891 
00892   // ########################################################################
00893   //  ST
00894   // ########################################################################
00908   var $_st = '';
00909   
00915   function getST()
00916     { return $this->_st; }
00917 
00923   function setST($st)
00924     { $this->_st = $st; }
00925 
00931   function hasST()
00932     { return !empty($this->_st); }
00933 
00936   // ########################################################################
00937   //  ST VALIDATION
00938   // ########################################################################
00957   function validateST($validate_url,&$text_response,&$tree_response)
00958     {
00959       phpCAS::traceBegin();
00960       // build the URL to validate the ticket
00961       $validate_url = $this->getServerServiceValidateURL().'&ticket='.$this->getST();
00962       if ( $this->isProxy() ) {
00963                  // pass the callback url for CAS proxies
00964                  $validate_url .= '&pgtUrl='.$this->getCallbackURL();
00965       }
00966 
00967       // open and read the URL
00968       if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) {
00969         phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
00970         $this->authError('ST not validated',
00971                          $validate_url,
00972                          TRUE/*$no_response*/);
00973       }
00974 
00975       // analyze the result depending on the version
00976       switch ($this->getServerVersion()) {
00977       case CAS_VERSION_1_0:
00978         if (preg_match('/^no\n/',$text_response)) {
00979           phpCAS::trace('ST has not been validated');
00980           $this->authError('ST not validated',
00981                        $validate_url,
00982                        FALSE/*$no_response*/,
00983                        FALSE/*$bad_response*/,
00984                        $text_response);
00985         }
00986         if (!preg_match('/^yes\n/',$text_response)) {
00987           phpCAS::trace('ill-formed response');
00988           $this->authError('ST not validated',
00989                        $validate_url,
00990                        FALSE/*$no_response*/,
00991                        TRUE/*$bad_response*/,
00992                        $text_response);
00993         }
00994         // ST has been validated, extract the user name
00995         $arr = preg_split('/\n/',$text_response);
00996         $this->setUser(trim($arr[1]));
00997         break;
00998       case CAS_VERSION_2_0:
00999         // read the response of the CAS server into a DOM object
01000         if ( !($dom = domxml_open_mem($text_response))) {
01001           phpCAS::trace('domxml_open_mem() failed');
01002           $this->authError('ST not validated',
01003                        $validate_url,
01004                        FALSE/*$no_response*/,
01005                        TRUE/*$bad_response*/,
01006                        $text_response);
01007         }
01008         // read the root node of the XML tree
01009         if ( !($tree_response = $dom->document_element()) ) {
01010           phpCAS::trace('document_element() failed');
01011           $this->authError('ST not validated',
01012                        $validate_url,
01013                        FALSE/*$no_response*/,
01014                        TRUE/*$bad_response*/,
01015                        $text_response);
01016         }
01017         // insure that tag name is 'serviceResponse'
01018         if ( $tree_response->node_name() != 'serviceResponse' ) {
01019           phpCAS::trace('bad XML root node (should be `serviceResponse\' instead of `'.$tree_response->node_name().'\'');
01020           $this->authError('ST not validated',
01021                        $validate_url,
01022                        FALSE/*$no_response*/,
01023                        TRUE/*$bad_response*/,
01024                        $text_response);
01025         }
01026         if ( sizeof($success_elements = $tree_response->get_elements_by_tagname("authenticationSuccess")) != 0) {
01027           // authentication succeded, extract the user name
01028           if ( sizeof($user_elements = $success_elements[0]->get_elements_by_tagname("user")) == 0) {
01029             phpCAS::trace('<authenticationSuccess> found, but no <user>');
01030             $this->authError('ST not validated',
01031                          $validate_url,
01032                          FALSE/*$no_response*/,
01033                          TRUE/*$bad_response*/,
01034                          $text_response);
01035           }
01036           $user = trim($user_elements[0]->get_content());
01037           phpCAS::trace('user = `'.$user);
01038           $this->setUser($user);
01039           
01040         } else if ( sizeof($failure_elements = $tree_response->get_elements_by_tagname("authenticationFailure")) != 0) {
01041           phpCAS::trace('<authenticationFailure> found');
01042           // authentication failed, extract the error code and message
01043           $this->authError('ST not validated',
01044                        $validate_url,
01045                        FALSE/*$no_response*/,
01046                        FALSE/*$bad_response*/,
01047                        $text_response,
01048                        $failure_elements[0]->get_attribute('code')/*$err_code*/,
01049                        trim($failure_elements[0]->get_content())/*$err_msg*/);
01050         } else {
01051           phpCAS::trace('neither <authenticationSuccess> nor <authenticationFailure> found');
01052           $this->authError('ST not validated',
01053                        $validate_url,
01054                        FALSE/*$no_response*/,
01055                        TRUE/*$bad_response*/,
01056                        $text_response);
01057         }
01058         break;
01059       }
01060       
01061       // at this step, ST has been validated and $this->_user has been set,
01062       phpCAS::traceEnd(TRUE);
01063       return TRUE;
01064     }
01065 
01068   // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
01069   // XX                                                                    XX
01070   // XX                     PROXY FEATURES (CAS 2.0)                       XX
01071   // XX                                                                    XX
01072   // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
01073 
01074   // ########################################################################
01075   //  PROXYING
01076   // ########################################################################
01088   var $_proxy;
01089   
01097   function isProxy()
01098     {
01099       return $this->_proxy;
01100     }
01101 
01103   // ########################################################################
01104   //  PGT
01105   // ########################################################################
01118   var $_pgt = '';
01119   
01125   function getPGT()
01126     { return $this->_pgt; }
01127 
01133   function setPGT($pgt)
01134     { $this->_pgt = $pgt; }
01135 
01141   function hasPGT()
01142     { return !empty($this->_pgt); }
01143 
01146   // ########################################################################
01147   //  CALLBACK MODE
01148   // ########################################################################
01166   var $_callback_mode = FALSE;
01167   
01175   function setCallbackMode($callback_mode)
01176     {
01177       $this->_callback_mode = $callback_mode;
01178     }
01179 
01188   function isCallbackMode()
01189     {
01190       return $this->_callback_mode;
01191     }
01192 
01201   var $_callback_url = '';
01202 
01212   function getCallbackURL()
01213     {
01214       // the URL is built when needed only
01215       if ( empty($this->_callback_url) ) {
01216         $final_uri = '';
01217             // remove the ticket if present in the URL
01218             $final_uri = 'https://';
01219             /* replaced by Julien Marchal - v0.4.6
01220              * $this->uri .= $_SERVER['SERVER_NAME'];
01221              */
01222         if(empty($_SERVER['HTTP_X_FORWARDED_SERVER'])){
01223           /* replaced by teedog - v0.4.12
01224            * $final_uri .= $_SERVER['SERVER_NAME'];
01225            */
01226           if (empty($_SERVER['SERVER_NAME'])) {
01227             $final_uri .= $_SERVER['HTTP_HOST'];
01228           } else {
01229             $final_uri .= $_SERVER['SERVER_NAME'];
01230           }
01231         } else {
01232           $final_uri .= $_SERVER['HTTP_X_FORWARDED_SERVER'];
01233         }
01234             if ( ($this->isHttps() && $_SERVER['SERVER_PORT']!=443)
01235                || (!$this->isHttps() && $_SERVER['SERVER_PORT']!=80) ) {
01236               $final_uri .= ':';
01237               $final_uri .= $_SERVER['SERVER_PORT'];
01238             }
01239             $request_uri = $_SERVER['REQUEST_URI'];
01240             $request_uri = preg_replace('/\?.*$/','',$request_uri);
01241             $final_uri .= $request_uri;
01242             $this->setCallbackURL($final_uri);
01243       }
01244       return $this->_callback_url;
01245     }
01246 
01254   function setCallbackURL($url)
01255     {
01256       return $this->_callback_url = $url;
01257     }
01258 
01265   function callback()
01266     {
01267       phpCAS::traceBegin();
01268       $this->printHTMLHeader('phpCAS callback');
01269       $pgt_iou = $_GET['pgtIou'];
01270       $pgt = $_GET['pgtId'];
01271       phpCAS::trace('Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\')');
01272       echo '<p>Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\').</p>';
01273       $this->storePGT($pgt,$pgt_iou);
01274       $this->printHTMLFooter();
01275       phpCAS::traceExit();
01276     }
01277 
01280   // ########################################################################
01281   //  PGT STORAGE
01282   // ########################################################################
01296   var $_pgt_storage = null;
01297 
01304   function initPGTStorage()
01305     {
01306       // if no SetPGTStorageXxx() has been used, default to file
01307       if ( !is_object($this->_pgt_storage) ) {
01308         $this->setPGTStorageFile();
01309       }
01310 
01311       // initializes the storage
01312       $this->_pgt_storage->init();
01313     }
01314   
01323   function storePGT($pgt,$pgt_iou)
01324     {
01325       // ensure that storage is initialized
01326       $this->initPGTStorage();
01327       // writes the PGT
01328       $this->_pgt_storage->write($pgt,$pgt_iou);
01329     }
01330   
01340   function loadPGT($pgt_iou)
01341     {
01342       // ensure that storage is initialized
01343       $this->initPGTStorage();
01344       // read the PGT
01345       return $this->_pgt_storage->read($pgt_iou);
01346     }
01347   
01357   function setPGTStorageFile($format='',
01358                              $path='')
01359     {
01360       // check that the storage has not already been set
01361       if ( is_object($this->_pgt_storage) ) {
01362         phpCAS::error('PGT storage already defined');
01363       }
01364 
01365       // create the storage object
01366       $this->_pgt_storage = &new PGTStorageFile($this,$format,$path);
01367     }
01368   
01386   function setPGTStorageDB($user,
01387                            $password,
01388                            $database_type,
01389                            $hostname,
01390                            $port,
01391                            $database,
01392                            $table)
01393     {
01394       // check that the storage has not already been set
01395       if ( is_object($this->_pgt_storage) ) {
01396         phpCAS::error('PGT storage already defined');
01397       }
01398 
01399       // warn the user that he should use file storage...
01400       trigger_error('PGT storage into database is an experimental feature, use at your own risk',E_USER_WARNING);
01401 
01402       // create the storage object
01403       $this->_pgt_storage = & new PGTStorageDB($this,$user,$password,$database_type,$hostname,$port,$database,$table);
01404     }
01405   
01406   // ########################################################################
01407   //  PGT VALIDATION
01408   // ########################################################################
01422   function validatePGT(&$validate_url,$text_response,$tree_response)
01423     {
01424       phpCAS::traceBegin();
01425       if ( sizeof($arr = $tree_response->get_elements_by_tagname("proxyGrantingTicket")) == 0) {
01426         phpCAS::trace('<proxyGrantingTicket> not found');
01427         // authentication succeded, but no PGT Iou was transmitted
01428         $this->authError('Ticket validated but no PGT Iou transmitted',
01429                      $validate_url,
01430                      FALSE/*$no_response*/,
01431                      FALSE/*$bad_response*/,
01432                      $text_response);
01433       } else {
01434         // PGT Iou transmitted, extract it
01435         $pgt_iou = trim($arr[0]->get_content());
01436         $pgt = $this->loadPGT($pgt_iou);
01437         if ( $pgt == FALSE ) {
01438           phpCAS::trace('could not load PGT');
01439           $this->authError('PGT Iou was transmitted but PGT could not be retrieved',
01440                        $validate_url,
01441                        FALSE/*$no_response*/,
01442                        FALSE/*$bad_response*/,
01443                        $text_response);
01444         }
01445         $this->setPGT($pgt);
01446       }
01447       phpCAS::traceEnd(TRUE);
01448       return TRUE;
01449     }
01450 
01451   // ########################################################################
01452   //  PGT VALIDATION
01453   // ########################################################################
01454 
01466   function retrievePT($target_service,&$err_code,&$err_msg)
01467     {
01468       phpCAS::traceBegin();
01469 
01470       // by default, $err_msg is set empty and $pt to TRUE. On error, $pt is
01471       // set to false and $err_msg to an error message. At the end, if $pt is FALSE 
01472       // and $error_msg is still empty, it is set to 'invalid response' (the most
01473       // commonly encountered error).
01474       $err_msg = '';
01475 
01476       // build the URL to retrieve the PT
01477 //      $cas_url = $this->getServerProxyURL().'?targetService='.preg_replace('/&/','%26',$target_service).'&pgt='.$this->getPGT();
01478       $cas_url = $this->getServerProxyURL().'?targetService='.urlencode($target_service).'&pgt='.$this->getPGT();
01479 
01480       // open and read the URL
01481       if ( !$this->readURL($cas_url,''/*cookies*/,$headers,$cas_response,$err_msg) ) {
01482         phpCAS::trace('could not open URL \''.$cas_url.'\' to validate ('.$err_msg.')');
01483         $err_code = PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE;
01484         $err_msg = 'could not retrieve PT (no response from the CAS server)';
01485         phpCAS::traceEnd(FALSE);
01486         return FALSE;
01487       }
01488 
01489       $bad_response = FALSE;
01490 
01491       if ( !$bad_response ) {
01492         // read the response of the CAS server into a DOM object
01493         if ( !($dom = @domxml_open_mem($cas_response))) {
01494           phpCAS::trace('domxml_open_mem() failed');
01495           // read failed
01496           $bad_response = TRUE;
01497         } 
01498       }
01499 
01500       if ( !$bad_response ) {
01501         // read the root node of the XML tree
01502         if ( !($root = $dom->document_element()) ) {
01503           phpCAS::trace('document_element() failed');
01504           // read failed
01505           $bad_response = TRUE;
01506         } 
01507       }
01508 
01509       if ( !$bad_response ) {
01510         // insure that tag name is 'serviceResponse'
01511         if ( $root->node_name() != 'serviceResponse' ) {
01512           phpCAS::trace('node_name() failed');
01513           // bad root node
01514           $bad_response = TRUE;
01515         } 
01516       }
01517 
01518       if ( !$bad_response ) {
01519         // look for a proxySuccess tag
01520         if ( sizeof($arr = $root->get_elements_by_tagname("proxySuccess")) != 0) {
01521           // authentication succeded, look for a proxyTicket tag
01522           if ( sizeof($arr = $root->get_elements_by_tagname("proxyTicket")) != 0) {
01523             $err_code = PHPCAS_SERVICE_OK;
01524             $err_msg = '';
01525         phpCAS::trace('original PT: '.trim($arr[0]->get_content()));
01526         $pt = trim($arr[0]->get_content());
01527             phpCAS::traceEnd($pt);
01528             return $pt;
01529           } else {
01530             phpCAS::trace('<proxySuccess> was found, but not <proxyTicket>');
01531           }
01532         } 
01533         // look for a proxyFailure tag
01534         else if ( sizeof($arr = $root->get_elements_by_tagname("proxyFailure")) != 0) {
01535           // authentication failed, extract the error
01536           $err_code = PHPCAS_SERVICE_PT_FAILURE;
01537           $err_msg = 'PT retrieving failed (code=`'
01538             .$arr[0]->get_attribute('code')
01539             .'\', message=`'
01540             .trim($arr[0]->get_content())
01541             .'\')';
01542           phpCAS::traceEnd(FALSE);
01543           return FALSE;
01544         } else {
01545           phpCAS::trace('neither <proxySuccess> nor <proxyFailure> found');
01546         }
01547       }
01548 
01549       // at this step, we are sure that the response of the CAS server was ill-formed
01550       $err_code = PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE;
01551       $err_msg = 'Invalid response from the CAS server (response=`'.$cas_response.'\')';
01552 
01553       phpCAS::traceEnd(FALSE);
01554       return FALSE;
01555     }
01556 
01557   // ########################################################################
01558   // ACCESS TO EXTERNAL SERVICES
01559   // ########################################################################
01560 
01576   function readURL($url,$cookies,&$headers,&$body,&$err_msg)
01577     {
01578       phpCAS::traceBegin();
01579       $headers = '';
01580       $body = '';
01581       $err_msg = '';
01582 
01583       $res = TRUE;
01584 
01585       // initialize the CURL session
01586       $ch = curl_init($url);
01587         
01588           // verify the the server's certificate corresponds to its name
01589           curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
01590           // but do not verify the certificate itself
01591           curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
01592 
01593       // return the CURL output into a variable
01594       curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
01595       // include the HTTP header with the body
01596       curl_setopt($ch, CURLOPT_HEADER, 1);
01597       // add cookies headers
01598       if ( is_array($cookies) ) {
01599         curl_setopt($ch,CURLOPT_COOKIE,implode(';',$cookies));
01600       }
01601       // perform the query
01602       $buf = curl_exec ($ch);
01603       if ( $buf === FALSE ) {
01604         phpCAS::trace('cur_exec() failed');
01605         $err_msg = 'CURL error #'.curl_errno($ch).': '.curl_error($ch);
01606         // close the CURL session
01607         curl_close ($ch);
01608         $res = FALSE;
01609       } else {
01610         // close the CURL session
01611         curl_close ($ch);
01612         
01613         // find the end of the headers
01614         // note: strpos($str,"\n\r\n\r") does not work (?)
01615         $pos = FALSE;
01616         for ($i=0; $i<strlen($buf); $i++) {
01617           if ( $buf[$i] == chr(13) ) 
01618             if ( $buf[$i+1] == chr(10) ) 
01619               if ( $buf[$i+2] == chr(13) ) 
01620                 if ( $buf[$i+3] == chr(10) ) {
01621                   // header found
01622                   $pos = $i;
01623                   break;
01624                 }
01625         }
01626         
01627         if ( $pos === FALSE ) {
01628           // end of header not found
01629           $err_msg = 'no header found';
01630           phpCAS::trace($err_msg);
01631           $res = FALSE;
01632         } else { 
01633           // extract headers into an array
01634           $headers = preg_split ("/[\n\r]+/",substr($buf,0,$pos));        
01635           // extract body into a string
01636           $body = substr($buf,$pos+4);
01637         }
01638       }
01639 
01640       phpCAS::traceEnd($res);
01641       return $res;
01642     }
01643 
01659   function serviceWeb($url,&$err_code,&$output)
01660     {
01661       phpCAS::traceBegin();
01662       // at first retrieve a PT
01663       $pt = $this->retrievePT($url,$err_code,$output);
01664 
01665       $res = TRUE;
01666       
01667       // test if PT was retrieved correctly
01668       if ( !$pt ) {
01669         // note: $err_code and $err_msg are filled by CASClient::retrievePT()
01670         phpCAS::trace('PT was not retrieved correctly');
01671         $res = FALSE;
01672       } else {
01673         // add cookies if necessary
01674         if ( is_array($_SESSION['phpCAS']['services'][$url]['cookies']) ) {
01675           foreach ( $_SESSION['phpCAS']['services'][$url]['cookies'] as $name => $val ) { 
01676             $cookies[] = $name.'='.$val;
01677           }
01678         }
01679         
01680         // build the URL including the PT
01681         if ( strstr($url,'?') === FALSE ) {
01682           $service_url = $url.'?ticket='.$pt;
01683         } else {
01684           $service_url = $url.'&ticket='.$pt;
01685         }
01686         
01687         phpCAS::trace('reading URL`'.$service_url.'\'');
01688         if ( !$this->readURL($service_url,$cookies,$headers,$output,$err_msg) ) {
01689           phpCAS::trace('could not read URL`'.$service_url.'\'');
01690           $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
01691           // give an error message
01692           $output = sprintf($this->getString(CAS_STR_SERVICE_UNAVAILABLE),
01693                             $service_url,
01694                             $err_msg);
01695           $res = FALSE;
01696         } else {
01697           // URL has been fetched, extract the cookies
01698           phpCAS::trace('URL`'.$service_url.'\' has been read, storing cookies:');
01699           foreach ( $headers as $header ) {
01700             // test if the header is a cookie
01701             if ( preg_match('/^Set-Cookie:/',$header) ) {
01702               // the header is a cookie, remove the beginning
01703               $header_val = preg_replace('/^Set-Cookie: */','',$header);
01704               // extract interesting information
01705               $name_val = strtok($header_val,'; ');
01706               // extract the name and the value of the cookie
01707               $cookie_name = strtok($name_val,'=');
01708               $cookie_val = strtok('=');
01709               // store the cookie 
01710               $_SESSION['phpCAS']['services'][$url]['cookies'][$cookie_name] = $cookie_val;
01711               phpCAS::trace($cookie_name.' -> '.$cookie_val);
01712             }
01713           }
01714         }
01715       }
01716 
01717       phpCAS::traceEnd($res);
01718       return $res;
01719   }
01720 
01739   function serviceMail($url,$flags,&$err_code,&$err_msg,&$pt)
01740     {
01741       phpCAS::traceBegin();
01742       // at first retrieve a PT
01743       $pt = $this->retrievePT($target_service,$err_code,$output);
01744 
01745       $stream = FALSE;
01746       
01747       // test if PT was retrieved correctly
01748       if ( !$pt ) {
01749         // note: $err_code and $err_msg are filled by CASClient::retrievePT()
01750         phpCAS::trace('PT was not retrieved correctly');
01751       } else {
01752         phpCAS::trace('opening IMAP URL `'.$url.'\'...');
01753         $stream = @imap_open($url,$this->getUser(),$pt,$flags);
01754         if ( !$stream ) {
01755           phpCAS::trace('could not open URL');
01756           $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
01757           // give an error message
01758           $err_msg = sprintf($this->getString(CAS_STR_SERVICE_UNAVAILABLE),
01759                              $service_url,
01760                              var_export(imap_errors(),TRUE));
01761           $pt = FALSE;
01762           $stream = FALSE;
01763         } else {
01764           phpCAS::trace('ok');
01765         }
01766       }
01767 
01768       phpCAS::traceEnd($stream);
01769       return $stream;
01770   }
01771 
01774   // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
01775   // XX                                                                    XX
01776   // XX                  PROXIED CLIENT FEATURES (CAS 2.0)                 XX
01777   // XX                                                                    XX
01778   // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
01779 
01780   // ########################################################################
01781   //  PT
01782   // ########################################################################
01796   var $_pt = '';
01797   
01803   function getPT()
01804     {
01805       return 'ST'.substr($this->_pt, 2);
01806     }
01807 
01813   function setPT($pt)
01814     { $this->_pt = $pt; }
01815 
01821   function hasPT()
01822     { return !empty($this->_pt); }
01823 
01825   // ########################################################################
01826   //  PT VALIDATION
01827   // ########################################################################
01840   function validatePT(&$validate_url,&$text_response,&$tree_response)
01841     {
01842       phpCAS::traceBegin();
01843       // build the URL to validate the ticket
01844       $validate_url = $this->getServerProxyValidateURL().'&ticket='.$this->getPT();
01845 
01846       if ( $this->isProxy() ) {
01847       // pass the callback url for CAS proxies
01848         $validate_url .= '&pgtUrl='.$this->getCallbackURL();
01849       }
01850 
01851       // open and read the URL
01852       if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) {
01853         phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
01854         $this->authError('PT not validated',
01855                          $validate_url,
01856                          TRUE/*$no_response*/);
01857       }
01858 
01859       // read the response of the CAS server into a DOM object
01860       if ( !($dom = domxml_open_mem($text_response))) {
01861         // read failed
01862         $this->authError('PT not validated',
01863                      $validate_url,
01864                      FALSE/*$no_response*/,
01865                      TRUE/*$bad_response*/,
01866                      $text_response);
01867       }
01868       // read the root node of the XML tree
01869       if ( !($tree_response = $dom->document_element()) ) {
01870         // read failed
01871         $this->authError('PT not validated',
01872                      $validate_url,
01873                      FALSE/*$no_response*/,
01874                      TRUE/*$bad_response*/,
01875                      $text_response);
01876       }
01877       // insure that tag name is 'serviceResponse'
01878       if ( $tree_response->node_name() != 'serviceResponse' ) {
01879         // bad root node
01880         $this->authError('PT not validated',
01881                      $validate_url,
01882                      FALSE/*$no_response*/,
01883                      TRUE/*$bad_response*/,
01884                      $text_response);
01885       }
01886       if ( sizeof($arr = $tree_response->get_elements_by_tagname("authenticationSuccess")) != 0) {
01887         // authentication succeded, extract the user name
01888         if ( sizeof($arr = $tree_response->get_elements_by_tagname("user")) == 0) {
01889           // no user specified => error
01890           $this->authError('PT not validated',
01891                        $validate_url,
01892                        FALSE/*$no_response*/,
01893                        TRUE/*$bad_response*/,
01894                        $text_response);
01895         }
01896         $this->setUser(trim($arr[0]->get_content()));
01897         
01898       } else if ( sizeof($arr = $tree_response->get_elements_by_tagname("authenticationFailure")) != 0) {
01899         // authentication succeded, extract the error code and message
01900         $this->authError('PT not validated',
01901                      $validate_url,
01902                      FALSE/*$no_response*/,
01903                      FALSE/*$bad_response*/,
01904                      $text_response,
01905                      $arr[0]->get_attribute('code')/*$err_code*/,
01906                      trim($arr[0]->get_content())/*$err_msg*/);
01907       } else {
01908         $this->authError('PT not validated',
01909                      $validate_url,     
01910                      FALSE/*$no_response*/,
01911                      TRUE/*$bad_response*/,
01912                      $text_response);
01913       }
01914       
01915       // at this step, PT has been validated and $this->_user has been set,
01916 
01917       phpCAS::traceEnd(TRUE);
01918       return TRUE;
01919     }
01920 
01923   // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
01924   // XX                                                                    XX
01925   // XX                               MISC                                 XX
01926   // XX                                                                    XX
01927   // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
01928 
01934   // ########################################################################
01935   //  URL
01936   // ########################################################################
01944   var $_url = '';
01945 
01954   function getURL()
01955     {
01956       phpCAS::traceBegin();
01957       // the URL is built when needed only
01958       if ( empty($this->_url) ) {
01959             $final_uri = '';
01960             // remove the ticket if present in the URL
01961             $final_uri = ($this->isHttps()) ? 'https' : 'http';
01962             $final_uri .= '://';
01963             /* replaced by Julien Marchal - v0.4.6
01964              * $this->_url .= $_SERVER['SERVER_NAME'];
01965              */
01966         if(empty($_SERVER['HTTP_X_FORWARDED_SERVER'])){
01967           /* replaced by teedog - v0.4.12
01968            * $this->_url .= $_SERVER['SERVER_NAME'];
01969            */
01970           if (empty($_SERVER['SERVER_NAME'])) {
01971             $server_name = $_SERVER['HTTP_HOST'];
01972           } else {
01973             $server_name = $_SERVER['SERVER_NAME'];
01974           }
01975         } else {
01976           $server_name = $_SERVER['HTTP_X_FORWARDED_SERVER'];
01977         }
01978       $final_uri .= $server_name;
01979       if (!strpos($server_name, ':')) {
01980             if ( ($this->isHttps() && $_SERVER['SERVER_PORT']!=443)
01981                || (!$this->isHttps() && $_SERVER['SERVER_PORT']!=80) ) {
01982               $final_uri .= ':';
01983               $final_uri .= $_SERVER['SERVER_PORT'];
01984             }
01985       }
01986 
01987           $final_uri .= strtok($_SERVER['REQUEST_URI'],"?");
01988           $cgi_params = '?'.strtok("?");
01989           // remove the ticket if present in the CGI parameters
01990           $cgi_params = preg_replace('/&ticket=[^&]*/','',$cgi_params);
01991           $cgi_params = preg_replace('/\?ticket=[^&;]*/','?',$cgi_params);
01992           $cgi_params = preg_replace('/\?%26/','?',$cgi_params);
01993           $cgi_params = preg_replace('/\?&/','?',$cgi_params);
01994           $cgi_params = preg_replace('/\?$/','',$cgi_params);
01995           $final_uri .= $cgi_params;
01996           $this->setURL($final_uri);
01997     }
01998     phpCAS::traceEnd($this->_url);
01999     return $this->_url;
02000   }
02001 
02009   function setURL($url)
02010     {
02011       $this->_url = $url;
02012     }
02013   
02014   // ########################################################################
02015   //  AUTHENTICATION ERROR HANDLING
02016   // ########################################################################
02032   function authError($failure,$cas_url,$no_response,$bad_response='',$cas_response='',$err_code='',$err_msg='')
02033     {
02034       phpCAS::traceBegin();
02035 
02036       $this->printHTMLHeader($this->getString(CAS_STR_AUTHENTICATION_FAILED));
02037       printf($this->getString(CAS_STR_YOU_WERE_NOT_AUTHENTICATED),$this->getURL(),$_SERVER['SERVER_ADMIN']);
02038       phpCAS::trace('CAS URL: '.$cas_url);
02039       phpCAS::trace('Authentication failure: '.$failure);
02040       if ( $no_response ) {
02041         phpCAS::trace('Reason: no response from the CAS server');
02042       } else {
02043         if ( $bad_response ) {
02044             phpCAS::trace('Reason: bad response from the CAS server');
02045         } else {
02046           switch ($this->getServerVersion()) {
02047           case CAS_VERSION_1_0:
02048             phpCAS::trace('Reason: CAS error');
02049             break;
02050           case CAS_VERSION_2_0:
02051             if ( empty($err_code) )
02052               phpCAS::trace('Reason: no CAS error');
02053             else
02054               phpCAS::trace('Reason: ['.$err_code.'] CAS error: '.$err_msg);
02055             break;
02056           }
02057         }
02058         phpCAS::trace('CAS response: '.$cas_response);
02059       }
02060       $this->printHTMLFooter();
02061       phpCAS::traceExit();
02062       exit();
02063     }
02064 
02066 }
02067 
02068 ?>

Generated on Wed Mar 14 14:55:56 2007 for phpCAS by  doxygen 1.5.0