[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

/auth/cas/CAS/ -> client.php (source)

   1  <?php
   2  
   3  /**
   4   * @file CAS/client.php
   5   * Main class of the phpCAS library
   6   */
   7  
   8  // include internationalization stuff
   9  include_once(dirname(__FILE__).'/languages/languages.php');
  10  
  11  // include PGT storage classes
  12  include_once(dirname(__FILE__).'/PGTStorage/pgt-main.php');
  13  
  14  /**
  15   * @class CASClient
  16   * The CASClient class is a client interface that provides CAS authentication
  17   * to PHP applications.
  18   *
  19   * @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>
  20   */
  21  
  22  class CASClient
  23  {
  24  
  25    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  26    // XX                                                                    XX
  27    // XX                          CONFIGURATION                             XX
  28    // XX                                                                    XX
  29    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  30  
  31    // ########################################################################
  32    //  HTML OUTPUT
  33    // ########################################################################
  34    /**
  35     * @addtogroup internalOutput
  36     * @{
  37     */  
  38    
  39    /**
  40     * This method filters a string by replacing special tokens by appropriate values
  41     * and prints it. The corresponding tokens are taken into account:
  42     * - __CAS_VERSION__
  43     * - __PHPCAS_VERSION__
  44     * - __SERVER_BASE_URL__
  45     *
  46     * Used by CASClient::PrintHTMLHeader() and CASClient::printHTMLFooter().
  47     *
  48     * @param $str the string to filter and output
  49     *
  50     * @private
  51     */
  52    function HTMLFilterOutput($str)
  53      {
  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);
  57        echo $str;
  58      }
  59  
  60    /**
  61     * A string used to print the header of HTML pages. Written by CASClient::setHTMLHeader(),
  62     * read by CASClient::printHTMLHeader().
  63     *
  64     * @hideinitializer
  65     * @private
  66     * @see CASClient::setHTMLHeader, CASClient::printHTMLHeader()
  67     */
  68    var $_output_header = '';
  69    
  70    /**
  71     * This method prints the header of the HTML output (after filtering). If
  72     * CASClient::setHTMLHeader() was not used, a default header is output.
  73     *
  74     * @param $title the title of the page
  75     *
  76     * @see HTMLFilterOutput()
  77     * @private
  78     */
  79    function printHTMLHeader($title)
  80      {
  81        $this->HTMLFilterOutput(str_replace('__TITLE__',
  82                        $title,
  83                        (empty($this->_output_header)
  84                         ? '<html><head><title>__TITLE__</title></head><body><h1>__TITLE__</h1>'
  85                         : $this->_output_header)
  86                        )
  87                    );
  88      }
  89  
  90    /**
  91     * A string used to print the footer of HTML pages. Written by CASClient::setHTMLFooter(),
  92     * read by printHTMLFooter().
  93     *
  94     * @hideinitializer
  95     * @private
  96     * @see CASClient::setHTMLFooter, CASClient::printHTMLFooter()
  97     */
  98    var $_output_footer = '';
  99    
 100    /**
 101     * This method prints the footer of the HTML output (after filtering). If
 102     * CASClient::setHTMLFooter() was not used, a default footer is output.
 103     *
 104     * @see HTMLFilterOutput()
 105     * @private
 106     */
 107    function printHTMLFooter()
 108      {
 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);
 112      }
 113  
 114    /**
 115     * This method set the HTML header used for all outputs.
 116     *
 117     * @param $header the HTML header.
 118     *
 119     * @public
 120     */
 121    function setHTMLHeader($header)
 122      {
 123        $this->_output_header = $header;
 124      }
 125  
 126    /**
 127     * This method set the HTML footer used for all outputs.
 128     *
 129     * @param $footer the HTML footer.
 130     *
 131     * @public
 132     */
 133    function setHTMLFooter($footer)
 134      {
 135        $this->_output_footer = $footer;
 136      }
 137  
 138    /** @} */
 139    // ########################################################################
 140    //  INTERNATIONALIZATION
 141    // ########################################################################
 142    /**
 143     * @addtogroup internalLang
 144     * @{
 145     */  
 146    /**
 147     * A string corresponding to the language used by phpCAS. Written by 
 148     * CASClient::setLang(), read by CASClient::getLang().
 149  
 150     * @note debugging information is always in english (debug purposes only).
 151     *
 152     * @hideinitializer
 153     * @private
 154     * @sa CASClient::_strings, CASClient::getString()
 155     */
 156    var $_lang = '';
 157    
 158    /**
 159     * This method returns the language used by phpCAS.
 160     *
 161     * @return a string representing the language
 162     *
 163     * @private
 164     */
 165    function getLang()
 166      {
 167        if ( empty($this->_lang) )
 168      $this->setLang(PHPCAS_LANG_DEFAULT);
 169        return $this->_lang;
 170      }
 171  
 172    /**
 173     * array containing the strings used by phpCAS. Written by CASClient::setLang(), read by 
 174     * CASClient::getString() and used by CASClient::setLang().
 175     *
 176     * @note This array is filled by instructions in CAS/languages/<$this->_lang>.php
 177     *
 178     * @private
 179     * @see CASClient::_lang, CASClient::getString(), CASClient::setLang(), CASClient::getLang()
 180     */
 181    var $_strings;
 182  
 183    /**
 184     * This method returns a string depending on the language.
 185     *
 186     * @param $str the index of the string in $_string.
 187     *
 188     * @return the string corresponding to $index in $string.
 189     *
 190     * @private
 191     */
 192    function getString($str)
 193      {
 194        // call CASclient::getLang() to be sure the language is initialized
 195        $this->getLang();
 196        
 197        if ( !isset($this->_strings[$str]) ) {
 198      trigger_error('string `'.$str.'\' not defined for language `'.$this->getLang().'\'',E_USER_ERROR);
 199        }
 200        return $this->_strings[$str];
 201      }
 202  
 203    /**
 204     * This method is used to set the language used by phpCAS. 
 205     * @note Can be called only once.
 206     *
 207     * @param $lang a string representing the language.
 208     *
 209     * @public
 210     * @sa CAS_LANG_FRENCH, CAS_LANG_ENGLISH
 211     */
 212    function setLang($lang)
 213      {
 214        // include the corresponding language file
 215        include_once(dirname(__FILE__).'/languages/'.$lang.'.php');
 216  
 217        if ( !is_array($this->_strings) ) {
 218      trigger_error('language `'.$lang.'\' is not implemented',E_USER_ERROR);
 219        }
 220        $this->_lang = $lang;
 221      }
 222  
 223    /** @} */
 224    // ########################################################################
 225    //  CAS SERVER CONFIG
 226    // ########################################################################
 227    /**
 228     * @addtogroup internalConfig
 229     * @{
 230     */  
 231    
 232    /**
 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
 244     *
 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().
 248     *
 249     * The other fields are written and read by CASClient::getServerBaseURL(), 
 250     * CASClient::getServerLoginURL(), CASClient::getServerServiceValidateURL(), 
 251     * CASClient::getServerProxyValidateURL() and CASClient::getServerLogoutURL().
 252     *
 253     * @hideinitializer
 254     * @private
 255     */
 256    var $_server = array(
 257                 'version' => -1,
 258                 'hostname' => 'none',
 259                 'port' => -1,
 260                 'uri' => 'none'
 261                 );
 262    
 263    /**
 264     * This method is used to retrieve the version of the CAS server.
 265     * @return the version of the CAS server.
 266     * @private
 267     */
 268    function getServerVersion()
 269      { 
 270        return $this->_server['version']; 
 271      }
 272  
 273    /**
 274     * This method is used to retrieve the hostname of the CAS server.
 275     * @return the hostname of the CAS server.
 276     * @private
 277     */
 278    function getServerHostname()
 279      { return $this->_server['hostname']; }
 280  
 281    /**
 282     * This method is used to retrieve the port of the CAS server.
 283     * @return the port of the CAS server.
 284     * @private
 285     */
 286    function getServerPort()
 287      { return $this->_server['port']; }
 288  
 289    /**
 290     * This method is used to retrieve the URI of the CAS server.
 291     * @return a URI.
 292     * @private
 293     */
 294    function getServerURI()
 295      { return $this->_server['uri']; }
 296  
 297    /**
 298     * This method is used to retrieve the base URL of the CAS server.
 299     * @return a URL.
 300     * @private
 301     */
 302    function getServerBaseURL()
 303      { 
 304        // the URL is build only when needed
 305        if ( empty($this->_server['base_url']) ) {
 306      $this->_server['base_url'] = 'https://'
 307        .$this->getServerHostname()
 308        .':'
 309        .$this->getServerPort()
 310        .$this->getServerURI();
 311        }
 312        return $this->_server['base_url']; 
 313      }
 314  
 315    /**
 316     * This method is used to retrieve the login URL of the CAS server.
 317     * @param $gateway true to check authentication, false to force it
 318     * @return a URL.
 319     * @private
 320     */
 321    function getServerLoginURL($gateway=false)
 322      { 
 323        phpCAS::traceBegin();
 324        // the URL is build only when needed
 325        if ( empty($this->_server['login_url']) ) {
 326          $this->_server['login_url'] = $this->getServerBaseURL();
 327          $this->_server['login_url'] .= 'login?service=';
 328  //        $this->_server['login_url'] .= preg_replace('/&/','%26',$this->getURL());
 329          $this->_server['login_url'] .= urlencode($this->getURL());
 330          if ($gateway) {
 331            $this->_server['login_url'] .= '&gateway=true';
 332          }
 333        }
 334        phpCAS::traceEnd($this->_server['login_url']);
 335        return $this->_server['login_url']; 
 336      }
 337  
 338    /**
 339     * This method sets the login URL of the CAS server.
 340     * @param $url the login URL
 341     * @private
 342     * @since 0.4.21 by Wyman Chan
 343     */
 344    function setServerLoginURL($url)
 345      {
 346        return $this->_server['login_url'] = $url;
 347      }
 348  
 349    /**
 350     * This method is used to retrieve the service validating URL of the CAS server.
 351     * @return a URL.
 352     * @private
 353     */
 354    function getServerServiceValidateURL()
 355      { 
 356        // the URL is build only when needed
 357        if ( empty($this->_server['service_validate_url']) ) {
 358      switch ($this->getServerVersion()) {
 359      case CAS_VERSION_1_0:
 360        $this->_server['service_validate_url'] = $this->getServerBaseURL().'validate';
 361        break;
 362      case CAS_VERSION_2_0:
 363        $this->_server['service_validate_url'] = $this->getServerBaseURL().'serviceValidate';
 364        break;
 365      }
 366        }
 367  //      return $this->_server['service_validate_url'].'?service='.preg_replace('/&/','%26',$this->getURL()); 
 368        return $this->_server['service_validate_url'].'?service='.urlencode($this->getURL()); 
 369      }
 370  
 371    /**
 372     * This method is used to retrieve the proxy validating URL of the CAS server.
 373     * @return a URL.
 374     * @private
 375     */
 376    function getServerProxyValidateURL()
 377      { 
 378        // the URL is build only when needed
 379        if ( empty($this->_server['proxy_validate_url']) ) {
 380      switch ($this->getServerVersion()) {
 381      case CAS_VERSION_1_0:
 382        $this->_server['proxy_validate_url'] = '';
 383        break;
 384      case CAS_VERSION_2_0:
 385        $this->_server['proxy_validate_url'] = $this->getServerBaseURL().'proxyValidate';
 386        break;
 387      }
 388        }
 389  //      return $this->_server['proxy_validate_url'].'?service='.preg_replace('/&/','%26',$this->getURL()); 
 390        return $this->_server['proxy_validate_url'].'?service='.urlencode($this->getURL()); 
 391      }
 392  
 393    /**
 394     * This method is used to retrieve the proxy URL of the CAS server.
 395     * @return a URL.
 396     * @private
 397     */
 398    function getServerProxyURL()
 399      { 
 400        // the URL is build only when needed
 401        if ( empty($this->_server['proxy_url']) ) {
 402      switch ($this->getServerVersion()) {
 403      case CAS_VERSION_1_0:
 404        $this->_server['proxy_url'] = '';
 405        break;
 406      case CAS_VERSION_2_0:
 407        $this->_server['proxy_url'] = $this->getServerBaseURL().'proxy';
 408        break;
 409      }
 410        }
 411        return $this->_server['proxy_url']; 
 412      }
 413  
 414    /**
 415     * This method is used to retrieve the logout URL of the CAS server.
 416     * @return a URL.
 417     * @private
 418     */
 419    function getServerLogoutURL()
 420      { 
 421        // the URL is build only when needed
 422        if ( empty($this->_server['logout_url']) ) {
 423      $this->_server['logout_url'] = $this->getServerBaseURL().'logout';
 424        }
 425        return $this->_server['logout_url']; 
 426      }
 427  
 428    /**
 429     * This method sets the logout URL of the CAS server.
 430     * @param $url the logout URL
 431     * @private
 432     * @since 0.4.21 by Wyman Chan
 433     */
 434    function setServerLogoutURL($url)
 435      {
 436        return $this->_server['logout_url'] = $url;
 437      }
 438  
 439    /**
 440     * This method checks to see if the request is secured via HTTPS
 441     * @return true if https, false otherwise
 442     * @private
 443     */
 444    function isHttps() {
 445      //if ( isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) ) {
 446      //0.4.24 by Hinnack
 447      if ( isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
 448        return true;
 449      } else {
 450        return false;
 451      }
 452    }
 453  
 454    // ########################################################################
 455    //  CONSTRUCTOR
 456    // ########################################################################
 457     /**
 458      * CASClient constructor.
 459      *
 460      * @param $server_version the version of the CAS server
 461      * @param $proxy TRUE if the CAS client is a CAS proxy, FALSE otherwise
 462      * @param $server_hostname the hostname of the CAS server
 463      * @param $server_port the port the CAS server is running on
 464      * @param $server_uri the URI the CAS server is responding on
 465      * @param $start_session Have phpCAS start PHP sessions (default true)
 466      *
 467      * @return a newly created CASClient object
 468      *
 469      * @public
 470      */
 471    function CASClient(
 472        $server_version,
 473      $proxy,
 474      $server_hostname,
 475      $server_port,
 476      $server_uri,
 477      $start_session = true) {
 478  
 479      phpCAS::traceBegin();
 480  
 481      //activate session mechanism if desired
 482      if ($start_session) {
 483        session_start();
 484      }
 485  
 486      $this->_proxy = $proxy;
 487  
 488      //check version
 489      switch ($server_version) {
 490        case CAS_VERSION_1_0:
 491          if ( $this->isProxy() )
 492            phpCAS::error('CAS proxies are not supported in CAS '
 493                .$server_version);
 494          break;
 495        case CAS_VERSION_2_0:
 496          break;
 497        default:
 498          phpCAS::error('this version of CAS (`'
 499              .$server_version
 500              .'\') is not supported by phpCAS '
 501              .phpCAS::getVersion());
 502      }
 503      $this->_server['version'] = $server_version;
 504  
 505      //check hostname
 506      if ( empty($server_hostname) 
 507          || !preg_match('/[\.\d\-abcdefghijklmnopqrstuvwxyz]*/',$server_hostname) ) {
 508        phpCAS::error('bad CAS server hostname (`'.$server_hostname.'\')');
 509      }
 510      $this->_server['hostname'] = $server_hostname;
 511  
 512      //check port
 513      if ( $server_port == 0 
 514          || !is_int($server_port) ) {
 515        phpCAS::error('bad CAS server port (`'.$server_hostname.'\')');
 516      }
 517      $this->_server['port'] = $server_port;
 518  
 519      //check URI
 520      if ( !preg_match('/[\.\d\-_abcdefghijklmnopqrstuvwxyz\/]*/',$server_uri) ) {
 521        phpCAS::error('bad CAS server URI (`'.$server_uri.'\')');
 522      }
 523      //add leading and trailing `/' and remove doubles      
 524      $server_uri = preg_replace('/\/\//','/','/'.$server_uri.'/');
 525      $this->_server['uri'] = $server_uri;
 526  
 527      //set to callback mode if PgtIou and PgtId CGI GET parameters are provided 
 528      if ( $this->isProxy() ) {
 529        $this->setCallbackMode(!empty($_GET['pgtIou'])&&!empty($_GET['pgtId']));
 530      }
 531  
 532      if ( $this->isCallbackMode() ) {
 533        //callback mode: check that phpCAS is secured
 534        if ( !$this->isHttps() ) {
 535          phpCAS::error('CAS proxies must be secured to use phpCAS; PGT\'s will not be received from the CAS server');
 536        }
 537      } else {
 538        //normal mode: get ticket and remove it from CGI parameters for developpers
 539        $ticket = (isset($_GET['ticket']) ? $_GET['ticket'] : null);
 540        switch ($this->getServerVersion()) {
 541          case CAS_VERSION_1_0: // check for a Service Ticket
 542            if( preg_match('/^ST-/',$ticket) ) {
 543              phpCAS::trace('ST \''.$ticket.'\' found');
 544              //ST present
 545              $this->setST($ticket);
 546              //ticket has been taken into account, unset it to hide it to applications
 547              unset($_GET['ticket']);
 548            } else if ( !empty($ticket) ) {
 549              //ill-formed ticket, halt
 550              phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')');
 551            }
 552            break;
 553          case CAS_VERSION_2_0: // check for a Service or Proxy Ticket
 554            if( preg_match('/^[SP]T-/',$ticket) ) {
 555              phpCAS::trace('ST or PT \''.$ticket.'\' found');
 556              $this->setPT($ticket);
 557              unset($_GET['ticket']);
 558            } else if ( !empty($ticket) ) {
 559              //ill-formed ticket, halt
 560              phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')');
 561            } 
 562            break;
 563          }
 564      }
 565      phpCAS::traceEnd();
 566    }
 567  
 568    /** @} */
 569  
 570    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 571    // XX                                                                    XX
 572    // XX                           AUTHENTICATION                           XX
 573    // XX                                                                    XX
 574    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 575  
 576    /**
 577     * @addtogroup internalAuthentication
 578     * @{
 579     */  
 580    
 581    /**
 582     * The Authenticated user. Written by CASClient::setUser(), read by CASClient::getUser().
 583     * @attention client applications should use phpCAS::getUser().
 584     *
 585     * @hideinitializer
 586     * @private
 587     */
 588    var $_user = '';
 589    
 590    /**
 591     * This method sets the CAS user's login name.
 592     *
 593     * @param $user the login name of the authenticated user.
 594     *
 595     * @private
 596     */
 597    function setUser($user)
 598      {
 599        $this->_user = $user;
 600      }
 601  
 602    /**
 603     * This method returns the CAS user's login name.
 604     * @warning should be called only after CASClient::forceAuthentication() or 
 605     * CASClient::isAuthenticated(), otherwise halt with an error.
 606     *
 607     * @return the login name of the authenticated user
 608     */
 609    function getUser()
 610      {
 611        if ( empty($this->_user) ) {
 612      phpCAS::error('this method should be used only after '.__CLASS__.'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()');
 613        }
 614        return $this->_user;
 615      }
 616  
 617    /**
 618     * This method is called to be sure that the user is authenticated. When not 
 619     * authenticated, halt by redirecting to the CAS server; otherwise return TRUE.
 620     * @return TRUE when the user is authenticated; otherwise halt.
 621     * @public
 622     */
 623    function forceAuthentication()
 624      {
 625        phpCAS::traceBegin();
 626  
 627        if ( $this->isAuthenticated() ) {
 628          // the user is authenticated, nothing to be done.
 629          phpCAS::trace('no need to authenticate');
 630          $res = TRUE;
 631  
 632        } else {
 633          // the user is not authenticated, redirect to the CAS server
 634          unset($_SESSION['phpCAS']['auth_checked']);
 635          $this->redirectToCas(FALSE/* no gateway */);    
 636          // never reached
 637          $res = FALSE;
 638        }
 639        phpCAS::traceEnd($res);
 640        return $res;
 641      }
 642  
 643    /**
 644     * An integer that gives the number of times authentication will be cached before rechecked.
 645     *
 646     * @hideinitializer
 647     * @private
 648     */
 649    var $_cache_times_for_auth_recheck = 0;
 650    
 651    /**
 652     * Set the number of times authentication will be cached before rechecked.
 653     *
 654     * @param $n an integer.
 655     *
 656     * @public
 657     */
 658    function setCacheTimesForAuthRequest($n)
 659      {
 660        $this->_cache_times_for_auth_recheck = n;
 661      }
 662  
 663    /**
 664     * This method is called to check whether the user is authenticated or not.
 665     * @return TRUE when the user is authenticated, FALSE otherwise.
 666     * @public
 667     */
 668    function checkAuthentication()
 669      {
 670        phpCAS::traceBegin();
 671  
 672        if ( $this->isAuthenticated() ) {
 673          phpCAS::trace('user is authenticated');
 674          $res = TRUE;
 675        } else if (isset($_SESSION['phpCAS']['auth_checked'])) {
 676          // the previous request has redirected the client to the CAS server with gateway=true
 677          unset($_SESSION['phpCAS']['auth_checked']);
 678          $res = FALSE;
 679        } else {
 680  //        $_SESSION['phpCAS']['auth_checked'] = true;
 681  //        $this->redirectToCas(TRUE/* gateway */);    
 682  //        // never reached
 683  //        $res = FALSE;
 684          // avoid a check against CAS on every request
 685          if (! isset($_SESSION['phpCAS']['unauth_count']) )
 686             $_SESSION['phpCAS']['unauth_count'] = -2; // uninitialized
 687          
 688          if (($_SESSION['phpCAS']['unauth_count'] != -2 && $this->_cache_times_for_auth_recheck == -1) 
 689            || ($_SESSION['phpCAS']['unauth_count'] >= 0 && $_SESSION['phpCAS']['unauth_count'] < $this->_cache_times_for_auth_recheck))
 690          {
 691             $res = FALSE;
 692             
 693             if ($this->_cache_times_for_auth_recheck != -1)
 694             {
 695                   $_SESSION['phpCAS']['unauth_count']++;
 696                   phpCAS::trace('user is not authenticated (cached for '.$_SESSION['phpCAS']['unauth_count'].' times of '.$this->_cache_times_for_auth_recheck.')');
 697             }
 698             else
 699             {
 700                   phpCAS::trace('user is not authenticated (cached for until login pressed)');
 701             }
 702          }
 703          else
 704          {
 705               $_SESSION['phpCAS']['unauth_count'] = 0;
 706              $_SESSION['phpCAS']['auth_checked'] = true;
 707              phpCAS::trace('user is not authenticated (cache reset)');
 708              $this->redirectToCas(TRUE/* gateway */);    
 709              // never reached
 710              $res = FALSE;
 711          }
 712        }
 713        phpCAS::traceEnd($res);
 714        return $res;
 715      }
 716    
 717    /**
 718     * This method is called to check if the user is authenticated (previously or by
 719     * tickets given in the URL).
 720     *
 721     * @return TRUE when the user is authenticated.
 722     *
 723     * @public
 724     */
 725    function isAuthenticated()
 726    {
 727        phpCAS::traceBegin();
 728        $res = FALSE;
 729        $validate_url = '';
 730  
 731        if ( $this->wasPreviouslyAuthenticated() ) {
 732             // the user has already (previously during the session) been 
 733           // authenticated, nothing to be done.
 734          phpCAS::trace('user was already authenticated, no need to look for tickets');
 735          $res = TRUE;
 736        } 
 737        elseif ( $this->hasST() ) {
 738          // if a Service Ticket was given, validate it
 739          phpCAS::trace('ST `'.$this->getST().'\' is present');
 740          $this->validateST($validate_url,$text_response,$tree_response); // if it fails, it halts
 741          phpCAS::trace('ST `'.$this->getST().'\' was validated');
 742          if ( $this->isProxy() ) {
 743             $this->validatePGT($validate_url,$text_response,$tree_response); // idem
 744             phpCAS::trace('PGT `'.$this->getPGT().'\' was validated');
 745             $_SESSION['phpCAS']['pgt'] = $this->getPGT();
 746          }
 747          $_SESSION['phpCAS']['user'] = $this->getUser();
 748          $res = TRUE;
 749      }
 750      elseif ( $this->hasPT() ) {
 751          // if a Proxy Ticket was given, validate it
 752          phpCAS::trace('PT `'.$this->getPT().'\' is present');
 753          $this->validatePT($validate_url,$text_response,$tree_response); // note: if it fails, it halts
 754          phpCAS::trace('PT `'.$this->getPT().'\' was validated');
 755  
 756          if ( $this->isProxy() ) {
 757  
 758             $this->validatePGT($validate_url,$text_response,$tree_response); // idem
 759             phpCAS::trace('PGT `'.$this->getPGT().'\' was validated');
 760             $_SESSION['phpCAS']['pgt'] = $this->getPGT();
 761          }
 762          $_SESSION['phpCAS']['user'] = $this->getUser();
 763          $res = TRUE;
 764      } 
 765      else {
 766          // no ticket given, not authenticated
 767          phpCAS::trace('no ticket found');
 768      }
 769  
 770      phpCAS::traceEnd($res);
 771      return $res;
 772    }
 773    
 774    /**
 775     * This method tells if the current session is authenticated.
 776     * @return true if authenticated based soley on $_SESSION variable
 777     * @since 0.4.22 by Brendan Arnold
 778     */
 779    function isSessionAuthenticated ()
 780      {
 781        return !empty($_SESSION['phpCAS']['user']);
 782      }
 783  
 784    /**
 785     * This method tells if the user has already been (previously) authenticated
 786     * by looking into the session variables.
 787     *
 788     * @note This function switches to callback mode when needed.
 789     *
 790     * @return TRUE when the user has already been authenticated; FALSE otherwise.
 791     *
 792     * @private
 793     */
 794    function wasPreviouslyAuthenticated()
 795      {
 796        phpCAS::traceBegin();
 797  
 798        if ( $this->isCallbackMode() ) {
 799  
 800      $this->callback();
 801        }
 802  
 803        $auth = FALSE;
 804  
 805        if ( $this->isProxy() ) {
 806      // CAS proxy: username and PGT must be present
 807      if ( $this->isSessionAuthenticated() && !empty($_SESSION['phpCAS']['pgt']) ) {
 808        // authentication already done
 809        $this->setUser($_SESSION['phpCAS']['user']);
 810        $this->setPGT($_SESSION['phpCAS']['pgt']);
 811        phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\', PGT = `'.$_SESSION['phpCAS']['pgt'].'\''); 
 812        $auth = TRUE;
 813      } elseif ( $this->isSessionAuthenticated() && empty($_SESSION['phpCAS']['pgt']) ) {
 814        // these two variables should be empty or not empty at the same time
 815        phpCAS::trace('username found (`'.$_SESSION['phpCAS']['user'].'\') but PGT is empty');
 816        // unset all tickets to enforce authentication
 817        unset($_SESSION['phpCAS']);
 818        $this->setST('');
 819        $this->setPT('');
 820      } elseif ( !$this->isSessionAuthenticated() && !empty($_SESSION['phpCAS']['pgt']) ) {
 821        // these two variables should be empty or not empty at the same time
 822        phpCAS::trace('PGT found (`'.$_SESSION['phpCAS']['pgt'].'\') but username is empty'); 
 823        // unset all tickets to enforce authentication
 824        unset($_SESSION['phpCAS']);
 825        $this->setST('');
 826        $this->setPT('');
 827      } else {
 828        phpCAS::trace('neither user not PGT found'); 
 829      }
 830        } else {
 831      // `simple' CAS client (not a proxy): username must be present
 832      if ( $this->isSessionAuthenticated() ) {
 833        // authentication already done
 834        $this->setUser($_SESSION['phpCAS']['user']);
 835        phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\''); 
 836        $auth = TRUE;
 837      } else {
 838        phpCAS::trace('no user found');
 839      }
 840        }
 841        
 842        phpCAS::traceEnd($auth);
 843        return $auth;
 844      }
 845    
 846    /**
 847     * This method is used to redirect the client to the CAS server.
 848     * It is used by CASClient::forceAuthentication() and CASClient::checkAuthentication().
 849     * @param $gateway true to check authentication, false to force it
 850     * @public
 851     */
 852    function redirectToCas($gateway=false)
 853      {
 854        phpCAS::traceBegin();
 855        $cas_url = $this->getServerLoginURL($gateway);
 856        header('Location: '.$cas_url);
 857        $this->printHTMLHeader($this->getString(CAS_STR_AUTHENTICATION_WANTED));
 858        printf('<p>'.$this->getString(CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'</p>',$cas_url);
 859        $this->printHTMLFooter();
 860        phpCAS::traceExit();
 861        exit();
 862      }
 863    
 864    /**
 865     * This method is used to logout from CAS.
 866     * @param $url a URL that will be transmitted to the CAS server (to come back to when logged out)
 867     * @public
 868     */
 869    function logout($url = "")
 870      {
 871        phpCAS::traceBegin();
 872        $cas_url = $this->getServerLogoutURL();
 873        // v0.4.14 sebastien.gougeon at univ-rennes1.fr
 874        // header('Location: '.$cas_url);
 875        if ( $url != "" ) {
 876          $url = '?service=' . $url;
 877        }
 878        header('Location: '.$cas_url . $url);
 879        session_unset();
 880        session_destroy();
 881        $this->printHTMLHeader($this->getString(CAS_STR_LOGOUT));
 882        printf('<p>'.$this->getString(CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'</p>',$cas_url);
 883        $this->printHTMLFooter();
 884        phpCAS::traceExit();
 885        exit();
 886      }
 887    
 888    /** @} */
 889  
 890    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 891    // XX                                                                    XX
 892    // XX                  BASIC CLIENT FEATURES (CAS 1.0)                   XX
 893    // XX                                                                    XX
 894    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 895  
 896    // ########################################################################
 897    //  ST
 898    // ########################################################################
 899    /**
 900     * @addtogroup internalBasic
 901     * @{
 902     */  
 903    
 904    /**
 905     * the Service Ticket provided in the URL of the request if present
 906     * (empty otherwise). Written by CASClient::CASClient(), read by 
 907     * CASClient::getST() and CASClient::hasPGT().
 908     *
 909     * @hideinitializer
 910     * @private
 911     */
 912    var $_st = '';
 913    
 914    /**
 915     * This method returns the Service Ticket provided in the URL of the request.
 916     * @return The service ticket.
 917     * @private
 918     */
 919    function getST()
 920      { return $this->_st; }
 921  
 922    /**
 923     * This method stores the Service Ticket.
 924     * @param $st The Service Ticket.
 925     * @private
 926     */
 927    function setST($st)
 928      { $this->_st = $st; }
 929  
 930    /**
 931     * This method tells if a Service Ticket was stored.
 932     * @return TRUE if a Service Ticket has been stored.
 933     * @private
 934     */
 935    function hasST()
 936      { return !empty($this->_st); }
 937  
 938    /** @} */
 939  
 940    // ########################################################################
 941    //  ST VALIDATION
 942    // ########################################################################
 943    /**
 944     * @addtogroup internalBasic
 945     * @{
 946     */  
 947  
 948    /**
 949     * This method is used to validate a ST; halt on failure, and sets $validate_url,
 950     * $text_reponse and $tree_response on success. These parameters are used later
 951     * by CASClient::validatePGT() for CAS proxies.
 952     * 
 953     * @param $validate_url the URL of the request to the CAS server.
 954     * @param $text_response the response of the CAS server, as is (XML text).
 955     * @param $tree_response the response of the CAS server, as a DOM XML tree.
 956     *
 957     * @return bool TRUE when successfull, halt otherwise by calling CASClient::authError().
 958     *
 959     * @private
 960     */
 961    function validateST($validate_url,&$text_response,&$tree_response)
 962      {
 963        phpCAS::traceBegin();
 964        // build the URL to validate the ticket
 965        $validate_url = $this->getServerServiceValidateURL().'&ticket='.$this->getST();
 966        if ( $this->isProxy() ) {
 967             // pass the callback url for CAS proxies
 968           $validate_url .= '&pgtUrl='.$this->getCallbackURL();
 969        }
 970  
 971        // open and read the URL
 972        if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) {
 973      phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
 974      $this->authError('ST not validated',
 975               $validate_url,
 976               TRUE/*$no_response*/);
 977        }
 978  
 979        // analyze the result depending on the version
 980        switch ($this->getServerVersion()) {
 981        case CAS_VERSION_1_0:
 982      if (preg_match('/^no\n/',$text_response)) {
 983        phpCAS::trace('ST has not been validated');
 984        $this->authError('ST not validated',
 985                 $validate_url,
 986                 FALSE/*$no_response*/,
 987                 FALSE/*$bad_response*/,
 988                 $text_response);
 989      }
 990      if (!preg_match('/^yes\n/',$text_response)) {
 991        phpCAS::trace('ill-formed response');
 992        $this->authError('ST not validated',
 993                 $validate_url,
 994                 FALSE/*$no_response*/,
 995                 TRUE/*$bad_response*/,
 996                 $text_response);
 997      }
 998      // ST has been validated, extract the user name
 999      $arr = preg_split('/\n/',$text_response);
1000      $this->setUser(trim($arr[1]));
1001      break;
1002        case CAS_VERSION_2_0:
1003      // read the response of the CAS server into a DOM object
1004      if ( !($dom = domxml_open_mem($text_response))) {
1005        phpCAS::trace('domxml_open_mem() failed');
1006        $this->authError('ST not validated',
1007                 $validate_url,
1008                 FALSE/*$no_response*/,
1009                 TRUE/*$bad_response*/,
1010                 $text_response);
1011      }
1012      // read the root node of the XML tree
1013      if ( !($tree_response = $dom->document_element()) ) {
1014        phpCAS::trace('document_element() failed');
1015        $this->authError('ST not validated',
1016                 $validate_url,
1017                 FALSE/*$no_response*/,
1018                 TRUE/*$bad_response*/,
1019                 $text_response);
1020      }
1021      // insure that tag name is 'serviceResponse'
1022      if ( $tree_response->node_name() != 'serviceResponse' ) {
1023        phpCAS::trace('bad XML root node (should be `serviceResponse\' instead of `'.$tree_response->node_name().'\'');
1024        $this->authError('ST not validated',
1025                 $validate_url,
1026                 FALSE/*$no_response*/,
1027                 TRUE/*$bad_response*/,
1028                 $text_response);
1029      }
1030      if ( sizeof($success_elements = $tree_response->get_elements_by_tagname("authenticationSuccess")) != 0) {
1031        // authentication succeded, extract the user name
1032        if ( sizeof($user_elements = $success_elements[0]->get_elements_by_tagname("user")) == 0) {
1033          phpCAS::trace('<authenticationSuccess> found, but no <user>');
1034          $this->authError('ST not validated',
1035               $validate_url,
1036               FALSE/*$no_response*/,
1037               TRUE/*$bad_response*/,
1038               $text_response);
1039        }
1040        $user = trim($user_elements[0]->get_content());
1041        phpCAS::trace('user = `'.$user);
1042        $this->setUser($user);
1043        
1044      } else if ( sizeof($failure_elements = $tree_response->get_elements_by_tagname("authenticationFailure")) != 0) {
1045        phpCAS::trace('<authenticationFailure> found');
1046        // authentication failed, extract the error code and message
1047        $this->authError('ST not validated',
1048                 $validate_url,
1049                 FALSE/*$no_response*/,
1050                 FALSE/*$bad_response*/,
1051                 $text_response,
1052                 $failure_elements[0]->get_attribute('code')/*$err_code*/,
1053                 trim($failure_elements[0]->get_content())/*$err_msg*/);
1054      } else {
1055        phpCAS::trace('neither <authenticationSuccess> nor <authenticationFailure> found');
1056        $this->authError('ST not validated',
1057                 $validate_url,
1058                 FALSE/*$no_response*/,
1059                 TRUE/*$bad_response*/,
1060                 $text_response);
1061      }
1062      break;
1063        }
1064        
1065        // at this step, ST has been validated and $this->_user has been set,
1066        phpCAS::traceEnd(TRUE);
1067        return TRUE;
1068      }
1069  
1070    /** @} */
1071  
1072    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1073    // XX                                                                    XX
1074    // XX                     PROXY FEATURES (CAS 2.0)                       XX
1075    // XX                                                                    XX
1076    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1077  
1078    // ########################################################################
1079    //  PROXYING
1080    // ########################################################################
1081    /**
1082     * @addtogroup internalProxy
1083     * @{
1084     */
1085  
1086    /**
1087     * A boolean telling if the client is a CAS proxy or not. Written by CASClient::CASClient(), 
1088     * read by CASClient::isProxy().
1089     *
1090     * @private
1091     */
1092    var $_proxy;
1093    
1094    /**
1095     * Tells if a CAS client is a CAS proxy or not
1096     *
1097     * @return TRUE when the CAS client is a CAs proxy, FALSE otherwise
1098     *
1099     * @private
1100     */
1101    function isProxy()
1102      {
1103        return $this->_proxy;
1104      }
1105  
1106    /** @} */
1107    // ########################################################################
1108    //  PGT
1109    // ########################################################################
1110    /**
1111     * @addtogroup internalProxy
1112     * @{
1113     */  
1114    
1115    /**
1116     * the Proxy Grnting Ticket given by the CAS server (empty otherwise). 
1117     * Written by CASClient::setPGT(), read by CASClient::getPGT() and CASClient::hasPGT().
1118     *
1119     * @hideinitializer
1120     * @private
1121     */
1122    var $_pgt = '';
1123    
1124    /**
1125     * This method returns the Proxy Granting Ticket given by the CAS server.
1126     * @return The Proxy Granting Ticket.
1127     * @private
1128     */
1129    function getPGT()
1130      { return $this->_pgt; }
1131  
1132    /**
1133     * This method stores the Proxy Granting Ticket.
1134     * @param $pgt The Proxy Granting Ticket.
1135     * @private
1136     */
1137    function setPGT($pgt)
1138      { $this->_pgt = $pgt; }
1139  
1140    /**
1141     * This method tells if a Proxy Granting Ticket was stored.
1142     * @return TRUE if a Proxy Granting Ticket has been stored.
1143     * @private
1144     */
1145    function hasPGT()
1146      { return !empty($this->_pgt); }
1147  
1148    /** @} */
1149  
1150    // ########################################################################
1151    //  CALLBACK MODE
1152    // ########################################################################
1153    /**
1154     * @addtogroup internalCallback
1155     * @{
1156     */  
1157    /**
1158     * each PHP script using phpCAS in proxy mode is its own callback to get the
1159     * PGT back from the CAS server. callback_mode is detected by the constructor
1160     * thanks to the GET parameters.
1161     */
1162  
1163    /**
1164     * a boolean to know if the CAS client is running in callback mode. Written by
1165     * CASClient::setCallBackMode(), read by CASClient::isCallbackMode().
1166     *
1167     * @hideinitializer
1168     * @private
1169     */
1170    var $_callback_mode = FALSE;
1171    
1172    /**
1173     * This method sets/unsets callback mode.
1174     *
1175     * @param $callback_mode TRUE to set callback mode, FALSE otherwise.
1176     *
1177     * @private
1178     */
1179    function setCallbackMode($callback_mode)
1180      {
1181        $this->_callback_mode = $callback_mode;
1182      }
1183  
1184    /**
1185     * This method returns TRUE when the CAs client is running i callback mode, 
1186     * FALSE otherwise.
1187     *
1188     * @return A boolean.
1189     *
1190     * @private
1191     */
1192    function isCallbackMode()
1193      {
1194        return $this->_callback_mode;
1195      }
1196  
1197    /**
1198     * the URL that should be used for the PGT callback (in fact the URL of the 
1199     * current request without any CGI parameter). Written and read by 
1200     * CASClient::getCallbackURL().
1201     *
1202     * @hideinitializer
1203     * @private
1204     */
1205    var $_callback_url = '';
1206  
1207    /**
1208     * This method returns the URL that should be used for the PGT callback (in
1209     * fact the URL of the current request without any CGI parameter, except if
1210     * phpCAS::setFixedCallbackURL() was used).
1211     *
1212     * @return The callback URL
1213     *
1214     * @private
1215     */
1216    function getCallbackURL()
1217      {
1218        // the URL is built when needed only
1219        if ( empty($this->_callback_url) ) {
1220          $final_uri = '';
1221          // remove the ticket if present in the URL
1222          $final_uri = 'https://';
1223          /* replaced by Julien Marchal - v0.4.6
1224           * $this->uri .= $_SERVER['SERVER_NAME'];
1225           */
1226          if(empty($_SERVER['HTTP_X_FORWARDED_SERVER'])){
1227            /* replaced by teedog - v0.4.12
1228             * $final_uri .= $_SERVER['SERVER_NAME'];
1229             */
1230            if (empty($_SERVER['SERVER_NAME'])) {
1231              $final_uri .= $_SERVER['HTTP_HOST'];
1232            } else {
1233              $final_uri .= $_SERVER['SERVER_NAME'];
1234            }
1235          } else {
1236            $final_uri .= $_SERVER['HTTP_X_FORWARDED_SERVER'];
1237          }
1238          if ( ($this->isHttps() && $_SERVER['SERVER_PORT']!=443)
1239             || (!$this->isHttps() && $_SERVER['SERVER_PORT']!=80) ) {
1240            $final_uri .= ':';
1241            $final_uri .= $_SERVER['SERVER_PORT'];
1242          }
1243          $request_uri = $_SERVER['REQUEST_URI'];
1244          $request_uri = preg_replace('/\?.*$/','',$request_uri);
1245          $final_uri .= $request_uri;
1246          $this->setCallbackURL($final_uri);
1247        }
1248        return $this->_callback_url;
1249      }
1250  
1251    /**
1252     * This method sets the callback url.
1253     *
1254     * @param $callback_url url to set callback 
1255     *
1256     * @private
1257     */
1258    function setCallbackURL($url)
1259      {
1260        return $this->_callback_url = $url;
1261      }
1262  
1263    /**
1264     * This method is called by CASClient::CASClient() when running in callback
1265     * mode. It stores the PGT and its PGT Iou, prints its output and halts.
1266     *
1267     * @private
1268     */
1269    function callback()
1270      {
1271        phpCAS::traceBegin();
1272        $this->printHTMLHeader('phpCAS callback');
1273        $pgt_iou = $_GET['pgtIou'];
1274        $pgt = $_GET['pgtId'];
1275        phpCAS::trace('Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\')');
1276        echo '<p>Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\').</p>';
1277        $this->storePGT($pgt,$pgt_iou);
1278        $this->printHTMLFooter();
1279        phpCAS::traceExit();
1280      }
1281  
1282    /** @} */
1283  
1284    // ########################################################################
1285    //  PGT STORAGE
1286    // ########################################################################
1287    /**
1288     * @addtogroup internalPGTStorage
1289     * @{
1290     */  
1291      
1292    /**
1293     * an instance of a class inheriting of PGTStorage, used to deal with PGT
1294     * storage. Created by CASClient::setPGTStorageFile() or CASClient::setPGTStorageDB(), used 
1295     * by CASClient::setPGTStorageFile(), CASClient::setPGTStorageDB() and CASClient::initPGTStorage().
1296     *
1297     * @hideinitializer
1298     * @private
1299     */
1300    var $_pgt_storage = null;
1301  
1302    /**
1303     * This method is used to initialize the storage of PGT's.
1304     * Halts on error.
1305     *
1306     * @private
1307     */
1308    function initPGTStorage()
1309      {
1310        // if no SetPGTStorageXxx() has been used, default to file
1311        if ( !is_object($this->_pgt_storage) ) {
1312      $this->setPGTStorageFile();
1313        }
1314  
1315        // initializes the storage
1316        $this->_pgt_storage->init();
1317      }
1318    
1319    /**
1320     * This method stores a PGT. Halts on error.
1321     *
1322     * @param $pgt the PGT to store
1323     * @param $pgt_iou its corresponding Iou
1324     *
1325     * @private
1326     */
1327    function storePGT($pgt,$pgt_iou)
1328      {
1329        // ensure that storage is initialized
1330        $this->initPGTStorage();
1331  
1332        // writes the PGT
1333        $this->_pgt_storage->write($pgt,$pgt_iou);
1334      }
1335    
1336    /**
1337     * This method reads a PGT from its Iou and deletes the corresponding storage entry.
1338     *
1339     * @param $pgt_iou the PGT Iou
1340     *
1341     * @return The PGT corresponding to the Iou, FALSE when not found.
1342     *
1343     * @private
1344     */
1345    function loadPGT($pgt_iou)
1346      {
1347        // ensure that storage is initialized
1348        $this->initPGTStorage();
1349  
1350        // read the PGT
1351        return $this->_pgt_storage->read($pgt_iou);
1352      }
1353    
1354    /**
1355     * This method is used to tell phpCAS to store the response of the
1356     * CAS server to PGT requests onto the filesystem. 
1357     *
1358     * @param $format the format used to store the PGT's (`plain' and `xml' allowed)
1359     * @param $path the path where the PGT's should be stored
1360     *
1361     * @public
1362     */
1363    function setPGTStorageFile($format='',
1364                   $path='')
1365      {
1366        // check that the storage has not already been set
1367        if ( is_object($this->_pgt_storage) ) {
1368      phpCAS::error('PGT storage already defined');
1369        }
1370  
1371        // create the storage object
1372        $this->_pgt_storage = &new PGTStorageFile($this,$format,$path);
1373      }
1374    
1375    /**
1376     * This method is used to tell phpCAS to store the response of the
1377     * CAS server to PGT requests into a database. 
1378     * @note The connection to the database is done only when needed. 
1379     * As a consequence, bad parameters are detected only when 
1380     * initializing PGT storage.
1381     *
1382     * @param $user the user to access the data with
1383     * @param $password the user's password
1384     * @param $database_type the type of the database hosting the data
1385     * @param $hostname the server hosting the database
1386     * @param $port the port the server is listening on
1387     * @param $database the name of the database
1388     * @param $table the name of the table storing the data
1389     *
1390     * @public
1391     */
1392    function setPGTStorageDB($user,
1393                 $password,
1394                 $database_type,
1395                 $hostname,
1396                 $port,
1397                 $database,
1398                 $table)
1399      {
1400        // check that the storage has not already been set
1401        if ( is_object($this->_pgt_storage) ) {
1402      phpCAS::error('PGT storage already defined');
1403        }
1404  
1405        // warn the user that he should use file storage...
1406        trigger_error('PGT storage into database is an experimental feature, use at your own risk',E_USER_WARNING);
1407  
1408        // create the storage object
1409        $this->_pgt_storage = & new PGTStorageDB($this,$user,$password,$database_type,$hostname,$port,$database,$table);
1410      }
1411    
1412    // ########################################################################
1413    //  PGT VALIDATION
1414    // ########################################################################
1415    /**
1416     * This method is used to validate a PGT; halt on failure.
1417     * 
1418     * @param $validate_url the URL of the request to the CAS server.
1419     * @param $text_response the response of the CAS server, as is (XML text); result
1420     * of CASClient::validateST() or CASClient::validatePT().
1421     * @param $tree_response the response of the CAS server, as a DOM XML tree; result
1422     * of CASClient::validateST() or CASClient::validatePT().
1423     *
1424     * @return bool TRUE when successfull, halt otherwise by calling CASClient::authError().
1425     *
1426     * @private
1427     */
1428    function validatePGT(&$validate_url,$text_response,$tree_response)
1429      {
1430        phpCAS::traceBegin();
1431        if ( sizeof($arr = $tree_response->get_elements_by_tagname("proxyGrantingTicket")) == 0) {
1432      phpCAS::trace('<proxyGrantingTicket> not found');
1433      // authentication succeded, but no PGT Iou was transmitted
1434      $this->authError('Ticket validated but no PGT Iou transmitted',
1435               $validate_url,
1436               FALSE/*$no_response*/,
1437               FALSE/*$bad_response*/,
1438               $text_response);
1439        } else {
1440      // PGT Iou transmitted, extract it
1441      $pgt_iou = trim($arr[0]->get_content());
1442      $pgt = $this->loadPGT($pgt_iou);
1443      if ( $pgt == FALSE ) {
1444  
1445        phpCAS::trace('could not load PGT');
1446  
1447        $this->authError('PGT Iou was transmitted but PGT could not be retrieved',
1448                 $validate_url,
1449                 FALSE/*$no_response*/,
1450                 FALSE/*$bad_response*/,
1451                 $text_response);
1452  
1453  
1454      }
1455      $this->setPGT($pgt);
1456        }
1457        phpCAS::traceEnd(TRUE);
1458        return TRUE;
1459      }
1460  
1461    // ########################################################################
1462    //  PGT VALIDATION
1463    // ########################################################################
1464  
1465    /**
1466     * This method is used to retrieve PT's from the CAS server thanks to a PGT.
1467     * 
1468     * @param $target_service the service to ask for with the PT.
1469     * @param $err_code an error code (PHPCAS_SERVICE_OK on success).
1470     * @param $err_msg an error message (empty on success).
1471     *
1472     * @return a Proxy Ticket, or FALSE on error.
1473     *
1474     * @private
1475     */
1476    function retrievePT($target_service,&$err_code,&$err_msg)
1477      {
1478        phpCAS::traceBegin();
1479  
1480        // by default, $err_msg is set empty and $pt to TRUE. On error, $pt is
1481        // set to false and $err_msg to an error message. At the end, if $pt is FALSE 
1482        // and $error_msg is still empty, it is set to 'invalid response' (the most
1483        // commonly encountered error).
1484        $err_msg = '';
1485  
1486        // build the URL to retrieve the PT
1487  //      $cas_url = $this->getServerProxyURL().'?targetService='.preg_replace('/&/','%26',$target_service).'&pgt='.$this->getPGT();
1488        $cas_url = $this->getServerProxyURL().'?targetService='.urlencode($target_service).'&pgt='.$this->getPGT();
1489  
1490        // open and read the URL
1491        if ( !$this->readURL($cas_url,''/*cookies*/,$headers,$cas_response,$err_msg) ) {
1492      phpCAS::trace('could not open URL \''.$cas_url.'\' to validate ('.$err_msg.')');
1493      $err_code = PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE;
1494      $err_msg = 'could not retrieve PT (no response from the CAS server)';
1495      phpCAS::traceEnd(FALSE);
1496      return FALSE;
1497        }
1498  
1499        $bad_response = FALSE;
1500  
1501        if ( !$bad_response ) {
1502      // read the response of the CAS server into a DOM object
1503      if ( !($dom = @domxml_open_mem($cas_response))) {
1504        phpCAS::trace('domxml_open_mem() failed');
1505        // read failed
1506        $bad_response = TRUE;
1507      } 
1508        }
1509  
1510        if ( !$bad_response ) {
1511      // read the root node of the XML tree
1512      if ( !($root = $dom->document_element()) ) {
1513        phpCAS::trace('document_element() failed');
1514        // read failed
1515        $bad_response = TRUE;
1516      } 
1517        }
1518  
1519        if ( !$bad_response ) {
1520      // insure that tag name is 'serviceResponse'
1521      if ( $root->node_name() != 'serviceResponse' ) {
1522        phpCAS::trace('node_name() failed');
1523        // bad root node
1524        $bad_response = TRUE;
1525      } 
1526        }
1527  
1528        if ( !$bad_response ) {
1529      // look for a proxySuccess tag
1530      if ( sizeof($arr = $root->get_elements_by_tagname("proxySuccess")) != 0) {
1531        // authentication succeded, look for a proxyTicket tag
1532        if ( sizeof($arr = $root->get_elements_by_tagname("proxyTicket")) != 0) {
1533          $err_code = PHPCAS_SERVICE_OK;
1534          $err_msg = '';
1535          phpCAS::trace('original PT: '.trim($arr[0]->get_content()));
1536          $pt = trim($arr[0]->get_content());
1537          phpCAS::traceEnd($pt);
1538          return $pt;
1539        } else {
1540          phpCAS::trace('<proxySuccess> was found, but not <proxyTicket>');
1541        }
1542      } 
1543      // look for a proxyFailure tag
1544      else if ( sizeof($arr = $root->get_elements_by_tagname("proxyFailure")) != 0) {
1545        // authentication failed, extract the error
1546        $err_code = PHPCAS_SERVICE_PT_FAILURE;
1547        $err_msg = 'PT retrieving failed (code=`'
1548          .$arr[0]->get_attribute('code')
1549          .'\', message=`'
1550          .trim($arr[0]->get_content())
1551          .'\')';
1552        phpCAS::traceEnd(FALSE);
1553        return FALSE;
1554      } else {
1555        phpCAS::trace('neither <proxySuccess> nor <proxyFailure> found');
1556      }
1557        }
1558  
1559        // at this step, we are sure that the response of the CAS server was ill-formed
1560        $err_code = PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE;
1561        $err_msg = 'Invalid response from the CAS server (response=`'.$cas_response.'\')';
1562  
1563        phpCAS::traceEnd(FALSE);
1564        return FALSE;
1565      }
1566  
1567    // ########################################################################
1568    // ACCESS TO EXTERNAL SERVICES
1569    // ########################################################################
1570  
1571    /**
1572     * This method is used to acces a remote URL.
1573     *
1574     * @param $url the URL to access.
1575     * @param $cookies an array containing cookies strings such as 'name=val'
1576     * @param $headers an array containing the HTTP header lines of the response
1577     * (an empty array on failure).
1578     * @param $body the body of the response, as a string (empty on failure).
1579     * @param $err_msg an error message, filled on failure.
1580     *
1581     * @return TRUE on success, FALSE otherwise (in this later case, $err_msg
1582     * contains an error message).
1583     *
1584     * @private
1585     */
1586    function readURL($url,$cookies,&$headers,&$body,&$err_msg)
1587      {
1588        phpCAS::traceBegin();
1589        $headers = '';
1590        $body = '';
1591        $err_msg = '';
1592  
1593        $res = TRUE;
1594  
1595        // initialize the CURL session
1596        $ch = curl_init($url);
1597      
1598        // verify the the server's certificate corresponds to its name
1599        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
1600        // but do not verify the certificate itself
1601        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
1602  
1603        // return the CURL output into a variable
1604        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
1605        // include the HTTP header with the body
1606        curl_setopt($ch, CURLOPT_HEADER, 1);
1607        // add cookies headers
1608        if ( is_array($cookies) ) {
1609      curl_setopt($ch,CURLOPT_COOKIE,implode(';',$cookies));
1610        }
1611        // perform the query
1612        $buf = curl_exec ($ch);
1613        if ( $buf === FALSE ) {
1614      phpCAS::trace('cur_exec() failed');
1615      $err_msg = 'CURL error #'.curl_errno($ch).': '.curl_error($ch);
1616      // close the CURL session
1617      curl_close ($ch);
1618      $res = FALSE;
1619        } else {
1620      // close the CURL session
1621      curl_close ($ch);
1622      
1623      // find the end of the headers
1624      // note: strpos($str,"\n\r\n\r") does not work (?)
1625      $pos = FALSE;
1626      for ($i=0; $i<strlen($buf); $i++) {
1627        if ( $buf[$i] == chr(13) ) 
1628          if ( $buf[$i+1] == chr(10) ) 
1629            if ( $buf[$i+2] == chr(13) ) 
1630          if ( $buf[$i+3] == chr(10) ) {
1631            // header found
1632            $pos = $i;
1633            break;
1634          }
1635      }
1636      
1637      if ( $pos === FALSE ) {
1638        // end of header not found
1639        $err_msg = 'no header found';
1640        phpCAS::trace($err_msg);
1641        $res = FALSE;
1642      } else { 
1643        // extract headers into an array
1644        $headers = preg_split ("/[\n\r]+/",substr($buf,0,$pos));      
1645        // extract body into a string
1646        $body = substr($buf,$pos+4);
1647      }
1648        }
1649  
1650        phpCAS::traceEnd($res);
1651        return $res;
1652      }
1653  
1654    /**
1655     * This method is used to access an HTTP[S] service.
1656     * 
1657     * @param $url the service to access.
1658     * @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on
1659     * success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE,
1660     * PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_NOT AVAILABLE.
1661     * @param $output the output of the service (also used to give an error
1662     * message on failure).
1663     *
1664     * @return TRUE on success, FALSE otherwise (in this later case, $err_code
1665     * gives the reason why it failed and $output contains an error message).
1666     *
1667     * @public
1668     */
1669    function serviceWeb($url,&$err_code,&$output)
1670      {
1671        phpCAS::traceBegin();
1672        // at first retrieve a PT
1673        $pt = $this->retrievePT($url,$err_code,$output);
1674  
1675        $res = TRUE;
1676        
1677        // test if PT was retrieved correctly
1678        if ( !$pt ) {
1679      // note: $err_code and $err_msg are filled by CASClient::retrievePT()
1680      phpCAS::trace('PT was not retrieved correctly');
1681      $res = FALSE;
1682        } else {
1683      // add cookies if necessary
1684      if ( is_array($_SESSION['phpCAS']['services'][$url]['cookies']) ) {
1685        foreach ( $_SESSION['phpCAS']['services'][$url]['cookies'] as $name => $val ) { 
1686          $cookies[] = $name.'='.$val;
1687        }
1688      }
1689      
1690      // build the URL including the PT
1691      if ( strstr($url,'?') === FALSE ) {
1692        $service_url = $url.'?ticket='.$pt;
1693      } else {
1694        $service_url = $url.'&ticket='.$pt;
1695      }
1696      
1697      phpCAS::trace('reading URL`'.$service_url.'\'');
1698      if ( !$this->readURL($service_url,$cookies,$headers,$output,$err_msg) ) {
1699        phpCAS::trace('could not read URL`'.$service_url.'\'');
1700        $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
1701        // give an error message
1702        $output = sprintf($this->getString(CAS_STR_SERVICE_UNAVAILABLE),
1703                  $service_url,
1704                  $err_msg);
1705        $res = FALSE;
1706      } else {
1707        // URL has been fetched, extract the cookies
1708        phpCAS::trace('URL`'.$service_url.'\' has been read, storing cookies:');
1709        foreach ( $headers as $header ) {
1710          // test if the header is a cookie
1711          if ( preg_match('/^Set-Cookie:/',$header) ) {
1712            // the header is a cookie, remove the beginning
1713            $header_val = preg_replace('/^Set-Cookie: */','',$header);
1714            // extract interesting information
1715            $name_val = strtok($header_val,'; ');
1716            // extract the name and the value of the cookie
1717            $cookie_name = strtok($name_val,'=');
1718            $cookie_val = strtok('=');
1719            // store the cookie 
1720            $_SESSION['phpCAS']['services'][$url]['cookies'][$cookie_name] = $cookie_val;
1721            phpCAS::trace($cookie_name.' -> '.$cookie_val);
1722          }
1723        }
1724      }
1725        }
1726  
1727        phpCAS::traceEnd($res);
1728        return $res;
1729    }
1730  
1731    /**
1732     * This method is used to access an IMAP/POP3/NNTP service.
1733     * 
1734     * @param $url a string giving the URL of the service, including the mailing box
1735     * for IMAP URLs, as accepted by imap_open().
1736     * @param $flags options given to imap_open().
1737     * @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on
1738     * success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE,
1739     * PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_NOT AVAILABLE.
1740     * @param $err_msg an error message on failure
1741     * @param $pt the Proxy Ticket (PT) retrieved from the CAS server to access the URL
1742     * on success, FALSE on error).
1743     *
1744     * @return an IMAP stream on success, FALSE otherwise (in this later case, $err_code
1745     * gives the reason why it failed and $err_msg contains an error message).
1746     *
1747     * @public
1748     */
1749    function serviceMail($url,$flags,&$err_code,&$err_msg,&$pt)
1750      {
1751        phpCAS::traceBegin();
1752        // at first retrieve a PT
1753        $pt = $this->retrievePT($target_service,$err_code,$output);
1754  
1755        $stream = FALSE;
1756        
1757        // test if PT was retrieved correctly
1758        if ( !$pt ) {
1759      // note: $err_code and $err_msg are filled by CASClient::retrievePT()
1760      phpCAS::trace('PT was not retrieved correctly');
1761        } else {
1762      phpCAS::trace('opening IMAP URL `'.$url.'\'...');
1763      $stream = @imap_open($url,$this->getUser(),$pt,$flags);
1764      if ( !$stream ) {
1765        phpCAS::trace('could not open URL');
1766        $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
1767        // give an error message
1768        $err_msg = sprintf($this->getString(CAS_STR_SERVICE_UNAVAILABLE),
1769                   $service_url,
1770                   var_export(imap_errors(),TRUE));
1771        $pt = FALSE;
1772        $stream = FALSE;
1773      } else {
1774        phpCAS::trace('ok');
1775      }
1776        }
1777  
1778        phpCAS::traceEnd($stream);
1779        return $stream;
1780    }
1781  
1782    /** @} */
1783  
1784    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1785    // XX                                                                    XX
1786    // XX                  PROXIED CLIENT FEATURES (CAS 2.0)                 XX
1787    // XX                                                                    XX
1788    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1789  
1790    // ########################################################################
1791    //  PT
1792    // ########################################################################
1793    /**
1794     * @addtogroup internalProxied
1795     * @{
1796     */  
1797    
1798    /**
1799     * the Proxy Ticket provided in the URL of the request if present
1800     * (empty otherwise). Written by CASClient::CASClient(), read by 
1801     * CASClient::getPT() and CASClient::hasPGT().
1802     *
1803     * @hideinitializer
1804     * @private
1805     */
1806    var $_pt = '';
1807    
1808    /**
1809     * This method returns the Proxy Ticket provided in the URL of the request.
1810     * @return The proxy ticket.
1811     * @private
1812     */
1813    function getPT()
1814      {
1815        return 'ST'.substr($this->_pt, 2);
1816      }
1817  
1818    /**
1819     * This method stores the Proxy Ticket.
1820     * @param $pt The Proxy Ticket.
1821     * @private
1822     */
1823    function setPT($pt)
1824      { $this->_pt = $pt; }
1825  
1826    /**
1827     * This method tells if a Proxy Ticket was stored.
1828     * @return TRUE if a Proxy Ticket has been stored.
1829     * @private
1830     */
1831    function hasPT()
1832      { return !empty($this->_pt); }
1833  
1834    /** @} */
1835    // ########################################################################
1836    //  PT VALIDATION
1837    // ########################################################################
1838    /**
1839     * @addtogroup internalProxied
1840     * @{
1841     */  
1842  
1843    /**
1844     * This method is used to validate a PT; halt on failure
1845     * 
1846     * @return bool TRUE when successfull, halt otherwise by calling CASClient::authError().
1847     *
1848     * @private
1849     */
1850    function validatePT(&$validate_url,&$text_response,&$tree_response)
1851      {
1852        phpCAS::traceBegin();
1853        // build the URL to validate the ticket
1854        $validate_url = $this->getServerProxyValidateURL().'&ticket='.$this->getPT();
1855  
1856        if ( $this->isProxy() ) {
1857        // pass the callback url for CAS proxies
1858      $validate_url .= '&pgtUrl='.$this->getCallbackURL();
1859        }
1860  
1861        // open and read the URL
1862        if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) {
1863      phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
1864      $this->authError('PT not validated',
1865               $validate_url,
1866               TRUE/*$no_response*/);
1867        }
1868  
1869        // read the response of the CAS server into a DOM object
1870        if ( !($dom = domxml_open_mem($text_response))) {
1871      // read failed
1872      $this->authError('PT not validated',
1873               $validate_url,
1874               FALSE/*$no_response*/,
1875               TRUE/*$bad_response*/,
1876               $text_response);
1877        }
1878        // read the root node of the XML tree
1879        if ( !($tree_response = $dom->document_element()) ) {
1880      // read failed
1881      $this->authError('PT not validated',
1882               $validate_url,
1883               FALSE/*$no_response*/,
1884               TRUE/*$bad_response*/,
1885               $text_response);
1886        }
1887        // insure that tag name is 'serviceResponse'
1888        if ( $tree_response->node_name() != 'serviceResponse' ) {
1889      // bad root node
1890      $this->authError('PT not validated',
1891               $validate_url,
1892               FALSE/*$no_response*/,
1893               TRUE/*$bad_response*/,
1894               $text_response);
1895        }
1896        if ( sizeof($arr = $tree_response->get_elements_by_tagname("authenticationSuccess")) != 0) {
1897      // authentication succeded, extract the user name
1898      if ( sizeof($arr = $tree_response->get_elements_by_tagname("user")) == 0) {
1899        // no user specified => error
1900        $this->authError('PT not validated',
1901                 $validate_url,
1902                 FALSE/*$no_response*/,
1903                 TRUE/*$bad_response*/,
1904                 $text_response);
1905      }
1906      $this->setUser(trim($arr[0]->get_content()));
1907      
1908        } else if ( sizeof($arr = $tree_response->get_elements_by_tagname("authenticationFailure")) != 0) {
1909      // authentication succeded, extract the error code and message
1910      $this->authError('PT not validated',
1911               $validate_url,
1912               FALSE/*$no_response*/,
1913               FALSE/*$bad_response*/,
1914               $text_response,
1915               $arr[0]->get_attribute('code')/*$err_code*/,
1916               trim($arr[0]->get_content())/*$err_msg*/);
1917        } else {
1918      $this->authError('PT not validated',
1919               $validate_url,    
1920               FALSE/*$no_response*/,
1921               TRUE/*$bad_response*/,
1922               $text_response);
1923        }
1924        
1925        // at this step, PT has been validated and $this->_user has been set,
1926  
1927        phpCAS::traceEnd(TRUE);
1928        return TRUE;
1929      }
1930  
1931    /** @} */
1932  
1933    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1934    // XX                                                                    XX
1935    // XX                               MISC                                 XX
1936    // XX                                                                    XX
1937    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1938  
1939    /**
1940     * @addtogroup internalMisc
1941     * @{
1942     */  
1943    
1944    // ########################################################################
1945    //  URL
1946    // ########################################################################
1947    /**
1948     * the URL of the current request (without any ticket CGI parameter). Written 
1949     * and read by CASClient::getURL().
1950     *
1951     * @hideinitializer
1952     * @private
1953     */
1954    var $_url = '';
1955  
1956    /**
1957     * This method returns the URL of the current request (without any ticket
1958     * CGI parameter).
1959     *
1960     * @return The URL
1961     *
1962     * @private
1963     */
1964    function getURL()
1965      {
1966        phpCAS::traceBegin();
1967        // the URL is built when needed only
1968        if ( empty($this->_url) ) {
1969          $final_uri = '';
1970          // remove the ticket if present in the URL
1971          $final_uri = ($this->isHttps()) ? 'https' : 'http';
1972          $final_uri .= '://';
1973          /* replaced by Julien Marchal - v0.4.6
1974           * $this->_url .= $_SERVER['SERVER_NAME'];
1975           */
1976          if(empty($_SERVER['HTTP_X_FORWARDED_SERVER'])){
1977            /* replaced by teedog - v0.4.12
1978             * $this->_url .= $_SERVER['SERVER_NAME'];
1979             */
1980            if (empty($_SERVER['SERVER_NAME'])) {
1981              $server_name = $_SERVER['HTTP_HOST'];
1982            } else {
1983              $server_name = $_SERVER['SERVER_NAME'];
1984            }
1985          } else {
1986            $server_name = $_SERVER['HTTP_X_FORWARDED_SERVER'];
1987          }
1988        $final_uri .= $server_name;
1989        if (!strpos($server_name, ':')) {
1990            if ( ($this->isHttps() && $_SERVER['SERVER_PORT']!=443)
1991             || (!$this->isHttps() && $_SERVER['SERVER_PORT']!=80) ) {
1992            $final_uri .= ':';
1993            $final_uri .= $_SERVER['SERVER_PORT'];
1994          }
1995        }
1996  
1997        $final_uri .= strtok($_SERVER['REQUEST_URI'],"?");
1998        $cgi_params = '?'.strtok("?");
1999        // remove the ticket if present in the CGI parameters
2000        $cgi_params = preg_replace('/&ticket=[^&]*/','',$cgi_params);
2001        $cgi_params = preg_replace('/\?ticket=[^&;]*/','?',$cgi_params);
2002        $cgi_params = preg_replace('/\?%26/','?',$cgi_params);
2003        $cgi_params = preg_replace('/\?&/','?',$cgi_params);
2004        $cgi_params = preg_replace('/\?$/','',$cgi_params);
2005        $final_uri .= $cgi_params;
2006        $this->setURL($final_uri);
2007      }
2008      phpCAS::traceEnd($this->_url);
2009      return $this->_url;
2010    }
2011  
2012    /**
2013     * This method sets the URL of the current request 
2014     *
2015     * @param $url url to set for service
2016     *
2017     * @private
2018     */
2019    function setURL($url)
2020      {
2021        $this->_url = $url;
2022      }
2023    
2024    // ########################################################################
2025    //  AUTHENTICATION ERROR HANDLING
2026    // ########################################################################
2027    /**
2028     * This method is used to print the HTML output when the user was not authenticated.
2029     *
2030     * @param $failure the failure that occured
2031     * @param $cas_url the URL the CAS server was asked for
2032     * @param $no_response the response from the CAS server (other 
2033     * parameters are ignored if TRUE)
2034     * @param $bad_response bad response from the CAS server ($err_code
2035     * and $err_msg ignored if TRUE)
2036     * @param $cas_response the response of the CAS server
2037     * @param $err_code the error code given by the CAS server
2038     * @param $err_msg the error message given by the CAS server
2039     *
2040     * @private
2041     */
2042    function authError($failure,$cas_url,$no_response,$bad_response='',$cas_response='',$err_code='',$err_msg='')
2043      {
2044        phpCAS::traceBegin();
2045  
2046        $this->printHTMLHeader($this->getString(CAS_STR_AUTHENTICATION_FAILED));
2047        printf($this->getString(CAS_STR_YOU_WERE_NOT_AUTHENTICATED),$this->getURL(),$_SERVER['SERVER_ADMIN']);
2048        phpCAS::trace('CAS URL: '.$cas_url);
2049        phpCAS::trace('Authentication failure: '.$failure);
2050        if ( $no_response ) {
2051      phpCAS::trace('Reason: no response from the CAS server');
2052        } else {
2053      if ( $bad_response ) {
2054          phpCAS::trace('Reason: bad response from the CAS server');
2055      } else {
2056        switch ($this->getServerVersion()) {
2057        case CAS_VERSION_1_0:
2058          phpCAS::trace('Reason: CAS error');
2059          break;
2060        case CAS_VERSION_2_0:
2061          if ( empty($err_code) )
2062            phpCAS::trace('Reason: no CAS error');
2063          else
2064            phpCAS::trace('Reason: ['.$err_code.'] CAS error: '.$err_msg);
2065          break;
2066        }
2067      }
2068      phpCAS::trace('CAS response: '.$cas_response);
2069        }
2070        $this->printHTMLFooter();
2071        phpCAS::traceExit();
2072        exit();
2073      }
2074  
2075    /** @} */
2076  }
2077  
2078  ?>


Generated: Wed Jan 14 11:33:29 2009 Cross-referenced by PHPXref 0.7