Upgrade phpCAS
[piwik-CASLogin.git] / CAS / CAS.php
1 <?php
2
3 /**
4  * Licensed to Jasig under one or more contributor license
5  * agreements. See the NOTICE file distributed with this work for
6  * additional information regarding copyright ownership.
7  *
8  * Jasig licenses this file to you under the Apache License,
9  * Version 2.0 (the "License"); you may not use this file except in
10  * compliance with the License. You may obtain a copy of the License at:
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *
21  *
22  * Interface class of the phpCAS library
23  * PHP Version 5
24  *
25  * @file     CAS/CAS.php
26  * @category Authentication
27  * @package  PhpCAS
28  * @author   Pascal Aubry <pascal.aubry@univ-rennes1.fr>
29  * @author   Olivier Berger <olivier.berger@it-sudparis.eu>
30  * @author   Brett Bieber <brett.bieber@gmail.com>
31  * @author   Joachim Fritschi <jfritschi@freenet.de>
32  * @author   Adam Franco <afranco@middlebury.edu>
33  * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License 2.0
34  * @link     https://wiki.jasig.org/display/CASC/phpCAS
35  * @ingroup public
36  */
37
38
39 //
40 // hack by Vangelis Haniotakis to handle the absence of $_SERVER['REQUEST_URI']
41 // in IIS
42 //
43 if (php_sapi_name() != 'cli') {
44     if (!isset($_SERVER['REQUEST_URI'])) {
45         $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING'];
46     }
47 }
48
49 // Add a E_USER_DEPRECATED for php versions <= 5.2
50 if (!defined('E_USER_DEPRECATED')) {
51     define('E_USER_DEPRECATED', E_USER_NOTICE);
52 }
53
54
55 // ########################################################################
56 //  CONSTANTS
57 // ########################################################################
58
59 // ------------------------------------------------------------------------
60 //  CAS VERSIONS
61 // ------------------------------------------------------------------------
62
63 /**
64  * phpCAS version. accessible for the user by phpCAS::getVersion().
65  */
66 define('PHPCAS_VERSION', '1.3.2');
67
68 /**
69  * @addtogroup public
70  * @{
71  */
72
73 /**
74  * CAS version 1.0
75  */
76 define("CAS_VERSION_1_0", '1.0');
77 /*!
78  * CAS version 2.0
79 */
80 define("CAS_VERSION_2_0", '2.0');
81
82 // ------------------------------------------------------------------------
83 //  SAML defines
84 // ------------------------------------------------------------------------
85
86 /**
87  * SAML protocol
88  */
89 define("SAML_VERSION_1_1", 'S1');
90
91 /**
92  * XML header for SAML POST
93  */
94 define("SAML_XML_HEADER", '<?xml version="1.0" encoding="UTF-8"?>');
95
96 /**
97  * SOAP envelope for SAML POST
98  */
99 define("SAML_SOAP_ENV", '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/>');
100
101 /**
102  * SOAP body for SAML POST
103  */
104 define("SAML_SOAP_BODY", '<SOAP-ENV:Body>');
105
106 /**
107  * SAMLP request
108  */
109 define("SAMLP_REQUEST", '<samlp:Request xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol"  MajorVersion="1" MinorVersion="1" RequestID="_192.168.16.51.1024506224022" IssueInstant="2002-06-19T17:03:44.022Z">');
110 define("SAMLP_REQUEST_CLOSE", '</samlp:Request>');
111
112 /**
113  * SAMLP artifact tag (for the ticket)
114  */
115 define("SAML_ASSERTION_ARTIFACT", '<samlp:AssertionArtifact>');
116
117 /**
118  * SAMLP close
119  */
120 define("SAML_ASSERTION_ARTIFACT_CLOSE", '</samlp:AssertionArtifact>');
121
122 /**
123  * SOAP body close
124  */
125 define("SAML_SOAP_BODY_CLOSE", '</SOAP-ENV:Body>');
126
127 /**
128  * SOAP envelope close
129  */
130 define("SAML_SOAP_ENV_CLOSE", '</SOAP-ENV:Envelope>');
131
132 /**
133  * SAML Attributes
134  */
135 define("SAML_ATTRIBUTES", 'SAMLATTRIBS');
136
137 /** @} */
138 /**
139  * @addtogroup publicPGTStorage
140  * @{
141  */
142 // ------------------------------------------------------------------------
143 //  FILE PGT STORAGE
144 // ------------------------------------------------------------------------
145 /**
146  * Default path used when storing PGT's to file
147  */
148 define("CAS_PGT_STORAGE_FILE_DEFAULT_PATH", session_save_path());
149 /** @} */
150 // ------------------------------------------------------------------------
151 // SERVICE ACCESS ERRORS
152 // ------------------------------------------------------------------------
153 /**
154  * @addtogroup publicServices
155  * @{
156  */
157
158 /**
159  * phpCAS::service() error code on success
160  */
161 define("PHPCAS_SERVICE_OK", 0);
162 /**
163  * phpCAS::service() error code when the PT could not retrieve because
164  * the CAS server did not respond.
165  */
166 define("PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE", 1);
167 /**
168  * phpCAS::service() error code when the PT could not retrieve because
169  * the response of the CAS server was ill-formed.
170  */
171 define("PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE", 2);
172 /**
173  * phpCAS::service() error code when the PT could not retrieve because
174  * the CAS server did not want to.
175  */
176 define("PHPCAS_SERVICE_PT_FAILURE", 3);
177 /**
178  * phpCAS::service() error code when the service was not available.
179  */
180 define("PHPCAS_SERVICE_NOT_AVAILABLE", 4);
181
182 // ------------------------------------------------------------------------
183 // SERVICE TYPES
184 // ------------------------------------------------------------------------
185 /**
186  * phpCAS::getProxiedService() type for HTTP GET
187  */
188 define("PHPCAS_PROXIED_SERVICE_HTTP_GET", 'CAS_ProxiedService_Http_Get');
189 /**
190  * phpCAS::getProxiedService() type for HTTP POST
191  */
192 define("PHPCAS_PROXIED_SERVICE_HTTP_POST", 'CAS_ProxiedService_Http_Post');
193 /**
194  * phpCAS::getProxiedService() type for IMAP
195  */
196 define("PHPCAS_PROXIED_SERVICE_IMAP", 'CAS_ProxiedService_Imap');
197
198
199 /** @} */
200 // ------------------------------------------------------------------------
201 //  LANGUAGES
202 // ------------------------------------------------------------------------
203 /**
204  * @addtogroup publicLang
205  * @{
206  */
207
208 define("PHPCAS_LANG_ENGLISH", 'CAS_Languages_English');
209 define("PHPCAS_LANG_FRENCH", 'CAS_Languages_French');
210 define("PHPCAS_LANG_GREEK", 'CAS_Languages_Greek');
211 define("PHPCAS_LANG_GERMAN", 'CAS_Languages_German');
212 define("PHPCAS_LANG_JAPANESE", 'CAS_Languages_Japanese');
213 define("PHPCAS_LANG_SPANISH", 'CAS_Languages_Spanish');
214 define("PHPCAS_LANG_CATALAN", 'CAS_Languages_Catalan');
215
216 /** @} */
217
218 /**
219  * @addtogroup internalLang
220  * @{
221  */
222
223 /**
224  * phpCAS default language (when phpCAS::setLang() is not used)
225  */
226 define("PHPCAS_LANG_DEFAULT", PHPCAS_LANG_ENGLISH);
227
228 /** @} */
229 // ------------------------------------------------------------------------
230 //  DEBUG
231 // ------------------------------------------------------------------------
232 /**
233  * @addtogroup publicDebug
234  * @{
235  */
236
237 /**
238  * The default directory for the debug file under Unix.
239  */
240 define('DEFAULT_DEBUG_DIR', '/tmp/');
241
242 /** @} */
243
244 // include the class autoloader
245 require_once dirname(__FILE__) . '/CAS/Autoload.php';
246
247 /**
248  * The phpCAS class is a simple container for the phpCAS library. It provides CAS
249  * authentication for web applications written in PHP.
250  *
251  * @ingroup public
252  * @class phpCAS
253  * @category Authentication
254  * @package  PhpCAS
255  * @author   Pascal Aubry <pascal.aubry@univ-rennes1.fr>
256  * @author   Olivier Berger <olivier.berger@it-sudparis.eu>
257  * @author   Brett Bieber <brett.bieber@gmail.com>
258  * @author   Joachim Fritschi <jfritschi@freenet.de>
259  * @author   Adam Franco <afranco@middlebury.edu>
260  * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License 2.0
261  * @link     https://wiki.jasig.org/display/CASC/phpCAS
262  */
263
264 class phpCAS
265 {
266
267     /**
268      * This variable is used by the interface class phpCAS.
269      *
270      * @hideinitializer
271      */
272     private static $_PHPCAS_CLIENT;
273
274     /**
275      * This variable is used to store where the initializer is called from
276      * (to print a comprehensive error in case of multiple calls).
277      *
278      * @hideinitializer
279      */
280     private static $_PHPCAS_INIT_CALL;
281
282     /**
283      * This variable is used to store phpCAS debug mode.
284      *
285      * @hideinitializer
286      */
287     private static $_PHPCAS_DEBUG;
288
289
290     // ########################################################################
291     //  INITIALIZATION
292     // ########################################################################
293
294     /**
295      * @addtogroup publicInit
296      * @{
297      */
298
299     /**
300      * phpCAS client initializer.
301      *
302      * @param string $server_version  the version of the CAS server
303      * @param string $server_hostname the hostname of the CAS server
304      * @param string $server_port     the port the CAS server is running on
305      * @param string $server_uri      the URI the CAS server is responding on
306      * @param bool   $changeSessionID Allow phpCAS to change the session_id (Single
307      * Sign Out/handleLogoutRequests is based on that change)
308      *
309      * @return a newly created CAS_Client object
310      * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be
311      * called, only once, and before all other methods (except phpCAS::getVersion()
312      * and phpCAS::setDebug()).
313      */
314     public static function client($server_version, $server_hostname,
315         $server_port, $server_uri, $changeSessionID = true
316     ) {
317         phpCAS :: traceBegin();
318         if (is_object(self::$_PHPCAS_CLIENT)) {
319             phpCAS :: error(self::$_PHPCAS_INIT_CALL['method'] . '() has already been called (at ' . self::$_PHPCAS_INIT_CALL['file'] . ':' . self::$_PHPCAS_INIT_CALL['line'] . ')');
320         }
321         if (gettype($server_version) != 'string') {
322             phpCAS :: error('type mismatched for parameter $server_version (should be `string\')');
323         }
324         if (gettype($server_hostname) != 'string') {
325             phpCAS :: error('type mismatched for parameter $server_hostname (should be `string\')');
326         }
327         if (gettype($server_port) != 'integer') {
328             phpCAS :: error('type mismatched for parameter $server_port (should be `integer\')');
329         }
330         if (gettype($server_uri) != 'string') {
331             phpCAS :: error('type mismatched for parameter $server_uri (should be `string\')');
332         }
333
334         // store where the initializer is called from
335         $dbg = debug_backtrace();
336         self::$_PHPCAS_INIT_CALL = array (
337             'done' => true,
338             'file' => $dbg[0]['file'],
339             'line' => $dbg[0]['line'],
340             'method' => __CLASS__ . '::' . __FUNCTION__
341         );
342
343         // initialize the object $_PHPCAS_CLIENT
344         self::$_PHPCAS_CLIENT = new CAS_Client(
345             $server_version, false, $server_hostname, $server_port, $server_uri,
346             $changeSessionID
347         );
348         phpCAS :: traceEnd();
349     }
350
351     /**
352      * phpCAS proxy initializer.
353      *
354      * @param string $server_version  the version of the CAS server
355      * @param string $server_hostname the hostname of the CAS server
356      * @param string $server_port     the port the CAS server is running on
357      * @param string $server_uri      the URI the CAS server is responding on
358      * @param bool   $changeSessionID Allow phpCAS to change the session_id (Single
359      * Sign Out/handleLogoutRequests is based on that change)
360      *
361      * @return a newly created CAS_Client object
362      * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be
363      * called, only once, and before all other methods (except phpCAS::getVersion()
364      * and phpCAS::setDebug()).
365      */
366     public static function proxy($server_version, $server_hostname,
367         $server_port, $server_uri, $changeSessionID = true
368     ) {
369         phpCAS :: traceBegin();
370         if (is_object(self::$_PHPCAS_CLIENT)) {
371             phpCAS :: error(self::$_PHPCAS_INIT_CALL['method'] . '() has already been called (at ' . self::$_PHPCAS_INIT_CALL['file'] . ':' . self::$_PHPCAS_INIT_CALL['line'] . ')');
372         }
373         if (gettype($server_version) != 'string') {
374             phpCAS :: error('type mismatched for parameter $server_version (should be `string\')');
375         }
376         if (gettype($server_hostname) != 'string') {
377             phpCAS :: error('type mismatched for parameter $server_hostname (should be `string\')');
378         }
379         if (gettype($server_port) != 'integer') {
380             phpCAS :: error('type mismatched for parameter $server_port (should be `integer\')');
381         }
382         if (gettype($server_uri) != 'string') {
383             phpCAS :: error('type mismatched for parameter $server_uri (should be `string\')');
384         }
385
386         // store where the initialzer is called from
387         $dbg = debug_backtrace();
388         self::$_PHPCAS_INIT_CALL = array (
389             'done' => true,
390             'file' => $dbg[0]['file'],
391             'line' => $dbg[0]['line'],
392             'method' => __CLASS__ . '::' . __FUNCTION__
393         );
394
395         // initialize the object $_PHPCAS_CLIENT
396         self::$_PHPCAS_CLIENT = new CAS_Client(
397             $server_version, true, $server_hostname, $server_port, $server_uri,
398             $changeSessionID
399         );
400         phpCAS :: traceEnd();
401     }
402
403     /** @} */
404     // ########################################################################
405     //  DEBUGGING
406     // ########################################################################
407
408     /**
409      * @addtogroup publicDebug
410      * @{
411      */
412
413     /**
414      * Set/unset debug mode
415      *
416      * @param string $filename the name of the file used for logging, or false
417      * to stop debugging.
418      *
419      * @return void
420      */
421     public static function setDebug($filename = '')
422     {
423         if ($filename != false && gettype($filename) != 'string') {
424             phpCAS :: error('type mismatched for parameter $dbg (should be false or the name of the log file)');
425         }
426         if ($filename === false) {
427             self::$_PHPCAS_DEBUG['filename'] = false;
428
429         } else {
430             if (empty ($filename)) {
431                 if (preg_match('/^Win.*/', getenv('OS'))) {
432                     if (isset ($_ENV['TMP'])) {
433                         $debugDir = $_ENV['TMP'] . '/';
434                     } else {
435                         $debugDir = '';
436                     }
437                 } else {
438                     $debugDir = DEFAULT_DEBUG_DIR;
439                 }
440                 $filename = $debugDir . 'phpCAS.log';
441             }
442
443             if (empty (self::$_PHPCAS_DEBUG['unique_id'])) {
444                 self::$_PHPCAS_DEBUG['unique_id'] = substr(strtoupper(md5(uniqid(''))), 0, 4);
445             }
446
447             self::$_PHPCAS_DEBUG['filename'] = $filename;
448             self::$_PHPCAS_DEBUG['indent'] = 0;
449
450             phpCAS :: trace('START phpCAS-' . PHPCAS_VERSION . ' ******************');
451         }
452     }
453
454
455     /**
456      * Logs a string in debug mode.
457      *
458      * @param string $str the string to write
459      *
460      * @return void
461      * @private
462      */
463     public static function log($str)
464     {
465         $indent_str = ".";
466
467
468         if (!empty(self::$_PHPCAS_DEBUG['filename'])) {
469             // Check if file exists and modifiy file permissions to be only
470             // readable by the webserver
471             if (!file_exists(self::$_PHPCAS_DEBUG['filename'])) {
472                 touch(self::$_PHPCAS_DEBUG['filename']);
473                 // Chmod will fail on windows
474                 @chmod(self::$_PHPCAS_DEBUG['filename'], 0600);
475             }
476             for ($i = 0; $i < self::$_PHPCAS_DEBUG['indent']; $i++) {
477
478                 $indent_str .= '|    ';
479             }
480             // allow for multiline output with proper identing. Usefull for
481             // dumping cas answers etc.
482             $str2 = str_replace("\n", "\n" . self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str, $str);
483             error_log(self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str . $str2 . "\n", 3, self::$_PHPCAS_DEBUG['filename']);
484         }
485
486     }
487
488     /**
489      * This method is used by interface methods to print an error and where the
490      * function was originally called from.
491      *
492      * @param string $msg the message to print
493      *
494      * @return void
495      * @private
496      */
497     public static function error($msg)
498     {
499         $dbg = debug_backtrace();
500         $function = '?';
501         $file = '?';
502         $line = '?';
503         if (is_array($dbg)) {
504             for ($i = 1; $i < sizeof($dbg); $i++) {
505                 if (is_array($dbg[$i]) && isset($dbg[$i]['class']) ) {
506                     if ($dbg[$i]['class'] == __CLASS__) {
507                         $function = $dbg[$i]['function'];
508                         $file = $dbg[$i]['file'];
509                         $line = $dbg[$i]['line'];
510                     }
511                 }
512             }
513         }
514         echo "<br />\n<b>phpCAS error</b>: <font color=\"FF0000\"><b>" . __CLASS__ . "::" . $function . '(): ' . htmlentities($msg) . "</b></font> in <b>" . $file . "</b> on line <b>" . $line . "</b><br />\n";
515         phpCAS :: trace($msg);
516         phpCAS :: traceEnd();
517
518         throw new CAS_GracefullTerminationException(__CLASS__ . "::" . $function . '(): ' . $msg);
519     }
520
521     /**
522      * This method is used to log something in debug mode.
523      *
524      * @param string $str string to log
525      *
526      * @return void
527      */
528     public static function trace($str)
529     {
530         $dbg = debug_backtrace();
531         phpCAS :: log($str . ' [' . basename($dbg[0]['file']) . ':' . $dbg[0]['line'] . ']');
532     }
533
534     /**
535      * This method is used to indicate the start of the execution of a function in debug mode.
536      *
537      * @return void
538      */
539     public static function traceBegin()
540     {
541         $dbg = debug_backtrace();
542         $str = '=> ';
543         if (!empty ($dbg[1]['class'])) {
544             $str .= $dbg[1]['class'] . '::';
545         }
546         $str .= $dbg[1]['function'] . '(';
547         if (is_array($dbg[1]['args'])) {
548             foreach ($dbg[1]['args'] as $index => $arg) {
549                 if ($index != 0) {
550                     $str .= ', ';
551                 }
552                 if (is_object($arg)) {
553                     $str .= get_class($arg);
554                 } else {
555                     $str .= str_replace(array("\r\n", "\n", "\r"), "", var_export($arg, true));
556                 }
557             }
558         }
559         if (isset($dbg[1]['file'])) {
560             $file = basename($dbg[1]['file']);
561         } else {
562             $file = 'unknown_file';
563         }
564         if (isset($dbg[1]['line'])) {
565             $line = $dbg[1]['line'];
566         } else {
567             $line = 'unknown_line';
568         }
569         $str .= ') [' . $file . ':' . $line . ']';
570         phpCAS :: log($str);
571         if (!isset(self::$_PHPCAS_DEBUG['indent'])) {
572             self::$_PHPCAS_DEBUG['indent'] = 0;
573         } else {
574             self::$_PHPCAS_DEBUG['indent']++;
575         }
576     }
577
578     /**
579      * This method is used to indicate the end of the execution of a function in
580      * debug mode.
581      *
582      * @param string $res the result of the function
583      *
584      * @return void
585      */
586     public static function traceEnd($res = '')
587     {
588         if (empty(self::$_PHPCAS_DEBUG['indent'])) {
589             self::$_PHPCAS_DEBUG['indent'] = 0;
590         } else {
591             self::$_PHPCAS_DEBUG['indent']--;
592         }
593         $dbg = debug_backtrace();
594         $str = '';
595         if (is_object($res)) {
596             $str .= '<= ' . get_class($res);
597         } else {
598             $str .= '<= ' . str_replace(array("\r\n", "\n", "\r"), "", var_export($res, true));
599         }
600
601         phpCAS :: log($str);
602     }
603
604     /**
605      * This method is used to indicate the end of the execution of the program
606      *
607      * @return void
608      */
609     public static function traceExit()
610     {
611         phpCAS :: log('exit()');
612         while (self::$_PHPCAS_DEBUG['indent'] > 0) {
613             phpCAS :: log('-');
614             self::$_PHPCAS_DEBUG['indent']--;
615         }
616     }
617
618     /** @} */
619     // ########################################################################
620     //  INTERNATIONALIZATION
621     // ########################################################################
622     /**
623     * @addtogroup publicLang
624     * @{
625     */
626
627     /**
628      * This method is used to set the language used by phpCAS.
629      *
630      * @param string $lang string representing the language.
631      *
632      * @return void
633      *
634      * @sa PHPCAS_LANG_FRENCH, PHPCAS_LANG_ENGLISH
635      * @note Can be called only once.
636      */
637     public static function setLang($lang)
638     {
639         if (!is_object(self::$_PHPCAS_CLIENT)) {
640             phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
641         }
642         if (gettype($lang) != 'string') {
643             phpCAS :: error('type mismatched for parameter $lang (should be `string\')');
644         }
645         self::$_PHPCAS_CLIENT->setLang($lang);
646     }
647
648     /** @} */
649     // ########################################################################
650     //  VERSION
651     // ########################################################################
652     /**
653     * @addtogroup public
654     * @{
655     */
656
657     /**
658      * This method returns the phpCAS version.
659      *
660      * @return the phpCAS version.
661      */
662     public static function getVersion()
663     {
664         return PHPCAS_VERSION;
665     }
666
667     /** @} */
668     // ########################################################################
669     //  HTML OUTPUT
670     // ########################################################################
671     /**
672     * @addtogroup publicOutput
673     * @{
674     */
675
676     /**
677      * This method sets the HTML header used for all outputs.
678      *
679      * @param string $header the HTML header.
680      *
681      * @return void
682      */
683     public static function setHTMLHeader($header)
684     {
685         if (!is_object(self::$_PHPCAS_CLIENT)) {
686             phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
687         }
688         if (gettype($header) != 'string') {
689             phpCAS :: error('type mismatched for parameter $header (should be `string\')');
690         }
691         self::$_PHPCAS_CLIENT->setHTMLHeader($header);
692     }
693
694     /**
695      * This method sets the HTML footer used for all outputs.
696      *
697      * @param string $footer the HTML footer.
698      *
699      * @return void
700      */
701     public static function setHTMLFooter($footer)
702     {
703         if (!is_object(self::$_PHPCAS_CLIENT)) {
704             phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
705         }
706         if (gettype($footer) != 'string') {
707             phpCAS :: error('type mismatched for parameter $footer (should be `string\')');
708         }
709         self::$_PHPCAS_CLIENT->setHTMLFooter($footer);
710     }
711
712     /** @} */
713     // ########################################################################
714     //  PGT STORAGE
715     // ########################################################################
716     /**
717     * @addtogroup publicPGTStorage
718     * @{
719     */
720
721     /**
722      * This method can be used to set a custom PGT storage object.
723      *
724      * @param CAS_PGTStorage $storage a PGT storage object that inherits from the
725      * CAS_PGTStorage class
726      *
727      * @return void
728      */
729     public static function setPGTStorage($storage)
730     {
731         phpCAS :: traceBegin();
732         if (!is_object(self::$_PHPCAS_CLIENT)) {
733             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
734         }
735         if (!self::$_PHPCAS_CLIENT->isProxy()) {
736             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
737         }
738         if (self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
739             phpCAS :: error('this method should only be called before ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() (called at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ')');
740         }
741         if ( !($storage instanceof CAS_PGTStorage) ) {
742             phpCAS :: error('type mismatched for parameter $storage (should be a CAS_PGTStorage `object\')');
743         }
744         self::$_PHPCAS_CLIENT->setPGTStorage($storage);
745         phpCAS :: traceEnd();
746     }
747
748     /**
749      * This method is used to tell phpCAS to store the response of the
750      * CAS server to PGT requests in a database.
751      *
752      * @param string $dsn_or_pdo     a dsn string to use for creating a PDO
753      * object or a PDO object
754      * @param string $username       the username to use when connecting to the
755      * database
756      * @param string $password       the password to use when connecting to the
757      * database
758      * @param string $table          the table to use for storing and retrieving
759      * PGT's
760      * @param string $driver_options any driver options to use when connecting
761      * to the database
762      *
763      * @return void
764      */
765     public static function setPGTStorageDb($dsn_or_pdo, $username='',
766         $password='', $table='', $driver_options=null
767     ) {
768         phpCAS :: traceBegin();
769         if (!is_object(self::$_PHPCAS_CLIENT)) {
770             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
771         }
772         if (!self::$_PHPCAS_CLIENT->isProxy()) {
773             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
774         }
775         if (self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
776             phpCAS :: error('this method should only be called before ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() (called at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ')');
777         }
778         if (gettype($username) != 'string') {
779             phpCAS :: error('type mismatched for parameter $username (should be `string\')');
780         }
781         if (gettype($password) != 'string') {
782             phpCAS :: error('type mismatched for parameter $password (should be `string\')');
783         }
784         if (gettype($table) != 'string') {
785             phpCAS :: error('type mismatched for parameter $table (should be `string\')');
786         }
787         self::$_PHPCAS_CLIENT->setPGTStorageDb($dsn_or_pdo, $username, $password, $table, $driver_options);
788         phpCAS :: traceEnd();
789     }
790
791     /**
792      * This method is used to tell phpCAS to store the response of the
793      * CAS server to PGT requests onto the filesystem.
794      *
795      * @param string $path the path where the PGT's should be stored
796      *
797      * @return void
798      */
799     public static function setPGTStorageFile($path = '')
800     {
801         phpCAS :: traceBegin();
802         if (!is_object(self::$_PHPCAS_CLIENT)) {
803             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
804         }
805         if (!self::$_PHPCAS_CLIENT->isProxy()) {
806             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
807         }
808         if (self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
809             phpCAS :: error('this method should only be called before ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() (called at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ')');
810         }
811         if (gettype($path) != 'string') {
812             phpCAS :: error('type mismatched for parameter $path (should be `string\')');
813         }
814         self::$_PHPCAS_CLIENT->setPGTStorageFile($path);
815         phpCAS :: traceEnd();
816     }
817     /** @} */
818     // ########################################################################
819     // ACCESS TO EXTERNAL SERVICES
820     // ########################################################################
821     /**
822     * @addtogroup publicServices
823     * @{
824     */
825
826     /**
827      * Answer a proxy-authenticated service handler.
828      *
829      * @param string $type The service type. One of
830      * PHPCAS_PROXIED_SERVICE_HTTP_GET; PHPCAS_PROXIED_SERVICE_HTTP_POST;
831      * PHPCAS_PROXIED_SERVICE_IMAP
832      *
833      * @return CAS_ProxiedService
834      * @throws InvalidArgumentException If the service type is unknown.
835      */
836     public static function getProxiedService ($type)
837     {
838         phpCAS :: traceBegin();
839         if (!is_object(self::$_PHPCAS_CLIENT)) {
840             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
841         }
842         if (!self::$_PHPCAS_CLIENT->isProxy()) {
843             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
844         }
845         if (!self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
846             phpCAS :: error('this method should only be called after the programmer is sure the user has been authenticated (by calling ' . __CLASS__ . '::checkAuthentication() or ' . __CLASS__ . '::forceAuthentication()');
847         }
848         if (!self::$_PHPCAS_CLIENT->wasAuthenticationCallSuccessful()) {
849             phpCAS :: error('authentication was checked (by ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ') but the method returned false');
850         }
851         if (gettype($type) != 'string') {
852             phpCAS :: error('type mismatched for parameter $type (should be `string\')');
853         }
854
855         $res = self::$_PHPCAS_CLIENT->getProxiedService($type);
856
857         phpCAS :: traceEnd();
858         return $res;
859     }
860
861     /**
862      * Initialize a proxied-service handler with the proxy-ticket it should use.
863      *
864      * @param CAS_ProxiedService $proxiedService Proxied Service Handler
865      *
866      * @return void
867      * @throws CAS_ProxyTicketException If there is a proxy-ticket failure.
868      *          The code of the Exception will be one of:
869      *                  PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE
870      *                  PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE
871      *                  PHPCAS_SERVICE_PT_FAILURE
872      */
873     public static function initializeProxiedService (CAS_ProxiedService $proxiedService)
874     {
875         if (!is_object(self::$_PHPCAS_CLIENT)) {
876             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
877         }
878         if (!self::$_PHPCAS_CLIENT->isProxy()) {
879             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
880         }
881         if (!self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
882             phpCAS :: error('this method should only be called after the programmer is sure the user has been authenticated (by calling ' . __CLASS__ . '::checkAuthentication() or ' . __CLASS__ . '::forceAuthentication()');
883         }
884         if (!self::$_PHPCAS_CLIENT->wasAuthenticationCallSuccessful()) {
885             phpCAS :: error('authentication was checked (by ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ') but the method returned false');
886         }
887
888         self::$_PHPCAS_CLIENT->initializeProxiedService($proxiedService);
889     }
890
891     /**
892      * This method is used to access an HTTP[S] service.
893      *
894      * @param string $url       the service to access.
895      * @param string &$err_code an error code Possible values are
896      * PHPCAS_SERVICE_OK (on success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE,
897      * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, PHPCAS_SERVICE_PT_FAILURE,
898      * PHPCAS_SERVICE_NOT_AVAILABLE.
899      * @param string &$output   the output of the service (also used to give an
900      * error message on failure).
901      *
902      * @return bool true on success, false otherwise (in this later case,
903      * $err_code gives the reason why it failed and $output contains an error
904      * message).
905      */
906     public static function serviceWeb($url, & $err_code, & $output)
907     {
908         phpCAS :: traceBegin();
909         if (!is_object(self::$_PHPCAS_CLIENT)) {
910             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
911         }
912         if (!self::$_PHPCAS_CLIENT->isProxy()) {
913             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
914         }
915         if (!self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
916             phpCAS :: error('this method should only be called after the programmer is sure the user has been authenticated (by calling ' . __CLASS__ . '::checkAuthentication() or ' . __CLASS__ . '::forceAuthentication()');
917         }
918         if (!self::$_PHPCAS_CLIENT->wasAuthenticationCallSuccessful()) {
919             phpCAS :: error('authentication was checked (by ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ') but the method returned false');
920         }
921         if (gettype($url) != 'string') {
922             phpCAS :: error('type mismatched for parameter $url (should be `string\')');
923         }
924
925         $res = self::$_PHPCAS_CLIENT->serviceWeb($url, $err_code, $output);
926
927         phpCAS :: traceEnd($res);
928         return $res;
929     }
930
931     /**
932      * This method is used to access an IMAP/POP3/NNTP service.
933      *
934      * @param string $url       a string giving the URL of the service,
935      * including the mailing box for IMAP URLs, as accepted by imap_open().
936      * @param string $service   a string giving for CAS retrieve Proxy ticket
937      * @param string $flags     options given to imap_open().
938      * @param string &$err_code an error code Possible values are
939      * PHPCAS_SERVICE_OK (on success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE,
940      * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, PHPCAS_SERVICE_PT_FAILURE,
941      * PHPCAS_SERVICE_NOT_AVAILABLE.
942      * @param string &$err_msg  an error message on failure
943      * @param string &$pt       the Proxy Ticket (PT) retrieved from the CAS
944      * server to access the URL on success, false on error).
945      *
946      * @return object IMAP stream on success, false otherwise (in this later
947      * case, $err_code gives the reason why it failed and $err_msg contains an
948      * error message).
949      */
950     public static function serviceMail($url, $service, $flags, & $err_code, & $err_msg, & $pt)
951     {
952         phpCAS :: traceBegin();
953         if (!is_object(self::$_PHPCAS_CLIENT)) {
954             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
955         }
956         if (!self::$_PHPCAS_CLIENT->isProxy()) {
957             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
958         }
959         if (!self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
960             phpCAS :: error('this method should only be called after the programmer is sure the user has been authenticated (by calling ' . __CLASS__ . '::checkAuthentication() or ' . __CLASS__ . '::forceAuthentication()');
961         }
962         if (!self::$_PHPCAS_CLIENT->wasAuthenticationCallSuccessful()) {
963             phpCAS :: error('authentication was checked (by ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ') but the method returned false');
964         }
965         if (gettype($url) != 'string') {
966             phpCAS :: error('type mismatched for parameter $url (should be `string\')');
967         }
968
969         if (gettype($flags) != 'integer') {
970             phpCAS :: error('type mismatched for parameter $flags (should be `integer\')');
971         }
972
973         $res = self::$_PHPCAS_CLIENT->serviceMail($url, $service, $flags, $err_code, $err_msg, $pt);
974
975         phpCAS :: traceEnd($res);
976         return $res;
977     }
978
979     /** @} */
980     // ########################################################################
981     //  AUTHENTICATION
982     // ########################################################################
983     /**
984     * @addtogroup publicAuth
985     * @{
986     */
987
988     /**
989      * Set the times authentication will be cached before really accessing the
990      * CAS server in gateway mode:
991      * - -1: check only once, and then never again (until you pree login)
992      * - 0: always check
993      * - n: check every "n" time
994      *
995      * @param int $n an integer.
996      *
997      * @return void
998      */
999     public static function setCacheTimesForAuthRecheck($n)
1000     {
1001         if (!is_object(self::$_PHPCAS_CLIENT)) {
1002             phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
1003         }
1004         if (gettype($n) != 'integer') {
1005             phpCAS :: error('type mismatched for parameter $n (should be `integer\')');
1006         }
1007         self::$_PHPCAS_CLIENT->setCacheTimesForAuthRecheck($n);
1008     }
1009
1010     /**
1011      * Set a callback function to be run when a user authenticates.
1012      *
1013      * The callback function will be passed a $logoutTicket as its first
1014      * parameter, followed by any $additionalArgs you pass. The $logoutTicket
1015      * parameter is an opaque string that can be used to map the session-id to
1016      * logout request in order to support single-signout in applications that
1017      * manage their own sessions (rather than letting phpCAS start the session).
1018      *
1019      * phpCAS::forceAuthentication() will always exit and forward client unless
1020      * they are already authenticated. To perform an action at the moment the user
1021      * logs in (such as registering an account, performing logging, etc), register
1022      * a callback function here.
1023      *
1024      * @param string $function       Callback function
1025      * @param array  $additionalArgs optional array of arguments
1026      *
1027      * @return void
1028      */
1029     public static function setPostAuthenticateCallback ($function, array $additionalArgs = array())
1030     {
1031         if (!is_object(self::$_PHPCAS_CLIENT)) {
1032             phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
1033         }
1034
1035         self::$_PHPCAS_CLIENT->setPostAuthenticateCallback($function, $additionalArgs);
1036     }
1037
1038     /**
1039      * Set a callback function to be run when a single-signout request is
1040      * received. The callback function will be passed a $logoutTicket as its
1041      * first parameter, followed by any $additionalArgs you pass. The
1042      * $logoutTicket parameter is an opaque string that can be used to map a
1043      * session-id to the logout request in order to support single-signout in
1044      * applications that manage their own sessions (rather than letting phpCAS
1045      * start and destroy the session).
1046      *
1047      * @param string $function       Callback function
1048      * @param array  $additionalArgs optional array of arguments
1049      *
1050      * @return void
1051      */
1052     public static function setSingleSignoutCallback ($function, array $additionalArgs = array())
1053     {
1054         if (!is_object(self::$_PHPCAS_CLIENT)) {
1055             phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
1056         }
1057
1058         self::$_PHPCAS_CLIENT->setSingleSignoutCallback($function, $additionalArgs);
1059     }
1060
1061     /**
1062      * This method is called to check if the user is already authenticated
1063      * locally or has a global cas session. A already existing cas session is
1064      * determined by a cas gateway call.(cas login call without any interactive
1065      * prompt)
1066      *
1067      * @return true when the user is authenticated, false when a previous
1068      * gateway login failed or the function will not return if the user is
1069      * redirected to the cas server for a gateway login attempt
1070      */
1071     public static function checkAuthentication()
1072     {
1073         phpCAS :: traceBegin();
1074         if (!is_object(self::$_PHPCAS_CLIENT)) {
1075             phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
1076         }
1077
1078         $auth = self::$_PHPCAS_CLIENT->checkAuthentication();
1079
1080         // store where the authentication has been checked and the result
1081         self::$_PHPCAS_CLIENT->markAuthenticationCall($auth);
1082
1083         phpCAS :: traceEnd($auth);
1084         return $auth;
1085     }
1086
1087     /**
1088      * This method is called to force authentication if the user was not already
1089      * authenticated. If the user is not authenticated, halt by redirecting to
1090      * the CAS server.
1091      *
1092      * @return bool Authentication
1093      */
1094     public static function forceAuthentication()
1095     {
1096         phpCAS :: traceBegin();
1097         if (!is_object(self::$_PHPCAS_CLIENT)) {
1098             phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
1099         }
1100
1101         $auth = self::$_PHPCAS_CLIENT->forceAuthentication();
1102
1103         // store where the authentication has been checked and the result
1104         self::$_PHPCAS_CLIENT->markAuthenticationCall($auth);
1105
1106         /*              if (!$auth) {
1107          phpCAS :: trace('user is not authenticated, redirecting to the CAS server');
1108         self::$_PHPCAS_CLIENT->forceAuthentication();
1109         } else {
1110         phpCAS :: trace('no need to authenticate (user `' . phpCAS :: getUser() . '\' is already authenticated)');
1111         }*/
1112
1113         phpCAS :: traceEnd();
1114         return $auth;
1115     }
1116
1117     /**
1118      * This method is called to renew the authentication.
1119      *
1120      * @return void
1121      **/
1122     public static function renewAuthentication()
1123     {
1124         phpCAS :: traceBegin();
1125         if (!is_object(self::$_PHPCAS_CLIENT)) {
1126             phpCAS :: error('this method should not be called before' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
1127         }
1128         $auth = self::$_PHPCAS_CLIENT->renewAuthentication();
1129
1130         // store where the authentication has been checked and the result
1131         self::$_PHPCAS_CLIENT->markAuthenticationCall($auth);
1132
1133         //self::$_PHPCAS_CLIENT->renewAuthentication();
1134         phpCAS :: traceEnd();
1135     }
1136
1137     /**
1138      * This method is called to check if the user is authenticated (previously or by
1139      * tickets given in the URL).
1140      *
1141      * @return true when the user is authenticated.
1142      */
1143     public static function isAuthenticated()
1144     {
1145         phpCAS :: traceBegin();
1146         if (!is_object(self::$_PHPCAS_CLIENT)) {
1147             phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
1148         }
1149
1150         // call the isAuthenticated method of the $_PHPCAS_CLIENT object
1151         $auth = self::$_PHPCAS_CLIENT->isAuthenticated();
1152
1153         // store where the authentication has been checked and the result
1154         self::$_PHPCAS_CLIENT->markAuthenticationCall($auth);
1155
1156         phpCAS :: traceEnd($auth);
1157         return $auth;
1158     }
1159
1160     /**
1161      * Checks whether authenticated based on $_SESSION. Useful to avoid
1162      * server calls.
1163      *
1164      * @return bool true if authenticated, false otherwise.
1165      * @since 0.4.22 by Brendan Arnold
1166      */
1167     public static function isSessionAuthenticated()
1168     {
1169         if (!is_object(self::$_PHPCAS_CLIENT)) {
1170             phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
1171         }
1172         return (self::$_PHPCAS_CLIENT->isSessionAuthenticated());
1173     }
1174
1175     /**
1176      * This method returns the CAS user's login name.
1177      *
1178      * @return string the login name of the authenticated user
1179      * @warning should not be called only after phpCAS::forceAuthentication()
1180      * or phpCAS::checkAuthentication().
1181      * */
1182     public static function getUser()
1183     {
1184         if (!is_object(self::$_PHPCAS_CLIENT)) {
1185             phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
1186         }
1187         if (!self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
1188             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::forceAuthentication() or ' . __CLASS__ . '::isAuthenticated()');
1189         }
1190         if (!self::$_PHPCAS_CLIENT->wasAuthenticationCallSuccessful()) {
1191             phpCAS :: error('authentication was checked (by ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ') but the method returned false');
1192         }
1193         return self::$_PHPCAS_CLIENT->getUser();
1194     }
1195
1196     /**
1197      * Answer attributes about the authenticated user.
1198      *
1199      * @warning should not be called only after phpCAS::forceAuthentication()
1200      * or phpCAS::checkAuthentication().
1201      *
1202      * @return array
1203      */
1204     public static function getAttributes()
1205     {
1206         if (!is_object(self::$_PHPCAS_CLIENT)) {
1207             phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
1208         }
1209         if (!self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
1210             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::forceAuthentication() or ' . __CLASS__ . '::isAuthenticated()');
1211         }
1212         if (!self::$_PHPCAS_CLIENT->wasAuthenticationCallSuccessful()) {
1213             phpCAS :: error('authentication was checked (by ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ') but the method returned false');
1214         }
1215         return self::$_PHPCAS_CLIENT->getAttributes();
1216     }
1217
1218     /**
1219      * Answer true if there are attributes for the authenticated user.
1220      *
1221      * @warning should not be called only after phpCAS::forceAuthentication()
1222      * or phpCAS::checkAuthentication().
1223      *
1224      * @return bool
1225      */
1226     public static function hasAttributes()
1227     {
1228         if (!is_object(self::$_PHPCAS_CLIENT)) {
1229             phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
1230         }
1231         if (!self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
1232             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::forceAuthentication() or ' . __CLASS__ . '::isAuthenticated()');
1233         }
1234         if (!self::$_PHPCAS_CLIENT->wasAuthenticationCallSuccessful()) {
1235             phpCAS :: error('authentication was checked (by ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ') but the method returned false');
1236         }
1237         return self::$_PHPCAS_CLIENT->hasAttributes();
1238     }
1239
1240     /**
1241      * Answer true if an attribute exists for the authenticated user.
1242      *
1243      * @param string $key attribute name
1244      *
1245      * @return bool
1246      * @warning should not be called only after phpCAS::forceAuthentication()
1247      * or phpCAS::checkAuthentication().
1248      */
1249     public static function hasAttribute($key)
1250     {
1251         if (!is_object(self::$_PHPCAS_CLIENT)) {
1252             phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
1253         }
1254         if (!self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
1255             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::forceAuthentication() or ' . __CLASS__ . '::isAuthenticated()');
1256         }
1257         if (!self::$_PHPCAS_CLIENT->wasAuthenticationCallSuccessful()) {
1258             phpCAS :: error('authentication was checked (by ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ') but the method returned false');
1259         }
1260         return self::$_PHPCAS_CLIENT->hasAttribute($key);
1261     }
1262
1263     /**
1264      * Answer an attribute for the authenticated user.
1265      *
1266      * @param string $key attribute name
1267      *
1268      * @return mixed string for a single value or an array if multiple values exist.
1269      * @warning should not be called only after phpCAS::forceAuthentication()
1270      * or phpCAS::checkAuthentication().
1271      */
1272     public static function getAttribute($key)
1273     {
1274         if (!is_object(self::$_PHPCAS_CLIENT)) {
1275             phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
1276         }
1277         if (!self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
1278             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::forceAuthentication() or ' . __CLASS__ . '::isAuthenticated()');
1279         }
1280         if (!self::$_PHPCAS_CLIENT->wasAuthenticationCallSuccessful()) {
1281             phpCAS :: error('authentication was checked (by ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ') but the method returned false');
1282         }
1283         return self::$_PHPCAS_CLIENT->getAttribute($key);
1284     }
1285
1286     /**
1287      * Handle logout requests.
1288      *
1289      * @param bool  $check_client    additional safety check
1290      * @param array $allowed_clients array of allowed clients
1291      *
1292      * @return void
1293      */
1294     public static function handleLogoutRequests($check_client = true, $allowed_clients = false)
1295     {
1296         if (!is_object(self::$_PHPCAS_CLIENT)) {
1297             phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
1298         }
1299         return (self::$_PHPCAS_CLIENT->handleLogoutRequests($check_client, $allowed_clients));
1300     }
1301
1302     /**
1303      * This method returns the URL to be used to login.
1304      * or phpCAS::isAuthenticated().
1305      *
1306      * @return the login name of the authenticated user
1307      */
1308     public static function getServerLoginURL()
1309     {
1310         if (!is_object(self::$_PHPCAS_CLIENT)) {
1311             phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
1312         }
1313         return self::$_PHPCAS_CLIENT->getServerLoginURL();
1314     }
1315
1316     /**
1317      * Set the login URL of the CAS server.
1318      *
1319      * @param string $url the login URL
1320      *
1321      * @return void
1322      * @since 0.4.21 by Wyman Chan
1323      */
1324     public static function setServerLoginURL($url = '')
1325     {
1326         phpCAS :: traceBegin();
1327         if (!is_object(self::$_PHPCAS_CLIENT)) {
1328             phpCAS :: error('this method should only be called after' . __CLASS__ . '::client()');
1329         }
1330         if (gettype($url) != 'string') {
1331             phpCAS :: error('type mismatched for parameter $url (should be `string`)');
1332         }
1333         self::$_PHPCAS_CLIENT->setServerLoginURL($url);
1334         phpCAS :: traceEnd();
1335     }
1336
1337     /**
1338      * Set the serviceValidate URL of the CAS server.
1339      * Used only in CAS 1.0 validations
1340      *
1341      * @param string $url the serviceValidate URL
1342      *
1343      * @return void
1344      */
1345     public static function setServerServiceValidateURL($url = '')
1346     {
1347         phpCAS :: traceBegin();
1348         if (!is_object(self::$_PHPCAS_CLIENT)) {
1349             phpCAS :: error('this method should only be called after' . __CLASS__ . '::client()');
1350         }
1351         if (gettype($url) != 'string') {
1352             phpCAS :: error('type mismatched for parameter $url (should be `string`)');
1353         }
1354         self::$_PHPCAS_CLIENT->setServerServiceValidateURL($url);
1355         phpCAS :: traceEnd();
1356     }
1357
1358     /**
1359      * Set the proxyValidate URL of the CAS server.
1360      * Used for all CAS 2.0 validations
1361      *
1362      * @param string $url the proxyValidate URL
1363      *
1364      * @return void
1365      */
1366     public static function setServerProxyValidateURL($url = '')
1367     {
1368         phpCAS :: traceBegin();
1369         if (!is_object(self::$_PHPCAS_CLIENT)) {
1370             phpCAS :: error('this method should only be called after' . __CLASS__ . '::client()');
1371         }
1372         if (gettype($url) != 'string') {
1373             phpCAS :: error('type mismatched for parameter $url (should be `string`)');
1374         }
1375         self::$_PHPCAS_CLIENT->setServerProxyValidateURL($url);
1376         phpCAS :: traceEnd();
1377     }
1378
1379     /**
1380      * Set the samlValidate URL of the CAS server.
1381      *
1382      * @param string $url the samlValidate URL
1383      *
1384      * @return void
1385      */
1386     public static function setServerSamlValidateURL($url = '')
1387     {
1388         phpCAS :: traceBegin();
1389         if (!is_object(self::$_PHPCAS_CLIENT)) {
1390             phpCAS :: error('this method should only be called after' . __CLASS__ . '::client()');
1391         }
1392         if (gettype($url) != 'string') {
1393             phpCAS :: error('type mismatched for parameter $url (should be`string\')');
1394         }
1395         self::$_PHPCAS_CLIENT->setServerSamlValidateURL($url);
1396         phpCAS :: traceEnd();
1397     }
1398
1399     /**
1400      * This method returns the URL to be used to login.
1401      * or phpCAS::isAuthenticated().
1402      *
1403      * @return the login name of the authenticated user
1404      */
1405     public static function getServerLogoutURL()
1406     {
1407         if (!is_object(self::$_PHPCAS_CLIENT)) {
1408             phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
1409         }
1410         return self::$_PHPCAS_CLIENT->getServerLogoutURL();
1411     }
1412
1413     /**
1414      * Set the logout URL of the CAS server.
1415      *
1416      * @param string $url the logout URL
1417      *
1418      * @return void
1419      * @since 0.4.21 by Wyman Chan
1420      */
1421     public static function setServerLogoutURL($url = '')
1422     {
1423         phpCAS :: traceBegin();
1424         if (!is_object(self::$_PHPCAS_CLIENT)) {
1425             phpCAS :: error(
1426                 'this method should only be called after' . __CLASS__ . '::client()'
1427             );
1428         }
1429         if (gettype($url) != 'string') {
1430             phpCAS :: error(
1431                 'type mismatched for parameter $url (should be `string`)'
1432             );
1433         }
1434         self::$_PHPCAS_CLIENT->setServerLogoutURL($url);
1435         phpCAS :: traceEnd();
1436     }
1437
1438     /**
1439      * This method is used to logout from CAS.
1440      *
1441      * @param string $params an array that contains the optional url and
1442      * service parameters that will be passed to the CAS server
1443      *
1444      * @return void
1445      */
1446     public static function logout($params = "")
1447     {
1448         phpCAS :: traceBegin();
1449         if (!is_object(self::$_PHPCAS_CLIENT)) {
1450             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
1451         }
1452         $parsedParams = array ();
1453         if ($params != "") {
1454             if (is_string($params)) {
1455                 phpCAS :: error('method `phpCAS::logout($url)\' is now deprecated, use `phpCAS::logoutWithUrl($url)\' instead');
1456             }
1457             if (!is_array($params)) {
1458                 phpCAS :: error('type mismatched for parameter $params (should be `array\')');
1459             }
1460             foreach ($params as $key => $value) {
1461                 if ($key != "service" && $key != "url") {
1462                     phpCAS :: error('only `url\' and `service\' parameters are allowed for method `phpCAS::logout($params)\'');
1463                 }
1464                 $parsedParams[$key] = $value;
1465             }
1466         }
1467         self::$_PHPCAS_CLIENT->logout($parsedParams);
1468         // never reached
1469         phpCAS :: traceEnd();
1470     }
1471
1472     /**
1473      * This method is used to logout from CAS. Halts by redirecting to the CAS
1474      * server.
1475      *
1476      * @param service $service a URL that will be transmitted to the CAS server
1477      *
1478      * @return void
1479      */
1480     public static function logoutWithRedirectService($service)
1481     {
1482         phpCAS :: traceBegin();
1483         if (!is_object(self::$_PHPCAS_CLIENT)) {
1484             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
1485         }
1486         if (!is_string($service)) {
1487             phpCAS :: error('type mismatched for parameter $service (should be `string\')');
1488         }
1489         self::$_PHPCAS_CLIENT->logout(array ( "service" => $service ));
1490         // never reached
1491         phpCAS :: traceEnd();
1492     }
1493
1494     /**
1495      * This method is used to logout from CAS. Halts by redirecting to the CAS
1496      * server.
1497      *
1498      * @param string $url a URL that will be transmitted to the CAS server
1499      *
1500      * @return void
1501      * @deprecated The url parameter has been removed from the CAS server as of
1502      * version 3.3.5.1
1503      */
1504     public static function logoutWithUrl($url)
1505     {
1506         trigger_error('Function deprecated for cas servers >= 3.3.5.1', E_USER_DEPRECATED);
1507         phpCAS :: traceBegin();
1508         if (!is_object(self::$_PHPCAS_CLIENT)) {
1509             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
1510         }
1511         if (!is_string($url)) {
1512             phpCAS :: error('type mismatched for parameter $url (should be `string\')');
1513         }
1514         self::$_PHPCAS_CLIENT->logout(array ( "url" => $url ));
1515         // never reached
1516         phpCAS :: traceEnd();
1517     }
1518
1519     /**
1520      * This method is used to logout from CAS. Halts by redirecting to the CAS
1521      * server.
1522      *
1523      * @param string $service a URL that will be transmitted to the CAS server
1524      * @param string $url     a URL that will be transmitted to the CAS server
1525      *
1526      * @return void
1527      *
1528      * @deprecated The url parameter has been removed from the CAS server as of
1529      * version 3.3.5.1
1530      */
1531     public static function logoutWithRedirectServiceAndUrl($service, $url)
1532     {
1533         trigger_error('Function deprecated for cas servers >= 3.3.5.1', E_USER_DEPRECATED);
1534         phpCAS :: traceBegin();
1535         if (!is_object(self::$_PHPCAS_CLIENT)) {
1536             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
1537         }
1538         if (!is_string($service)) {
1539             phpCAS :: error('type mismatched for parameter $service (should be `string\')');
1540         }
1541         if (!is_string($url)) {
1542             phpCAS :: error('type mismatched for parameter $url (should be `string\')');
1543         }
1544         self::$_PHPCAS_CLIENT->logout(
1545             array (
1546                 "service" => $service,
1547                 "url" => $url
1548             )
1549         );
1550         // never reached
1551         phpCAS :: traceEnd();
1552     }
1553
1554     /**
1555      * Set the fixed URL that will be used by the CAS server to transmit the
1556      * PGT. When this method is not called, a phpCAS script uses its own URL
1557      * for the callback.
1558      *
1559      * @param string $url the URL
1560      *
1561      * @return void
1562      */
1563     public static function setFixedCallbackURL($url = '')
1564     {
1565         phpCAS :: traceBegin();
1566         if (!is_object(self::$_PHPCAS_CLIENT)) {
1567             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
1568         }
1569         if (!self::$_PHPCAS_CLIENT->isProxy()) {
1570             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
1571         }
1572         if (gettype($url) != 'string') {
1573             phpCAS :: error('type mismatched for parameter $url (should be `string\')');
1574         }
1575         self::$_PHPCAS_CLIENT->setCallbackURL($url);
1576         phpCAS :: traceEnd();
1577     }
1578
1579     /**
1580      * Set the fixed URL that will be set as the CAS service parameter. When this
1581      * method is not called, a phpCAS script uses its own URL.
1582      *
1583      * @param string $url the URL
1584      *
1585      * @return void
1586      */
1587     public static function setFixedServiceURL($url)
1588     {
1589         phpCAS :: traceBegin();
1590         if (!is_object(self::$_PHPCAS_CLIENT)) {
1591             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
1592         }
1593         if (gettype($url) != 'string') {
1594             phpCAS :: error('type mismatched for parameter $url (should be `string\')');
1595         }
1596         self::$_PHPCAS_CLIENT->setURL($url);
1597         phpCAS :: traceEnd();
1598     }
1599
1600     /**
1601      * Get the URL that is set as the CAS service parameter.
1602      *
1603      * @return string Service Url
1604      */
1605     public static function getServiceURL()
1606     {
1607         if (!is_object(self::$_PHPCAS_CLIENT)) {
1608             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
1609         }
1610         return (self::$_PHPCAS_CLIENT->getURL());
1611     }
1612
1613     /**
1614      * Retrieve a Proxy Ticket from the CAS server.
1615      *
1616      * @param string $target_service Url string of service to proxy
1617      * @param string &$err_code      error code
1618      * @param string &$err_msg       error message
1619      *
1620      * @return string Proxy Ticket
1621      */
1622     public static function retrievePT($target_service, & $err_code, & $err_msg)
1623     {
1624         if (!is_object(self::$_PHPCAS_CLIENT)) {
1625             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
1626         }
1627         if (gettype($target_service) != 'string') {
1628             phpCAS :: error('type mismatched for parameter $target_service(should be `string\')');
1629         }
1630         return (self::$_PHPCAS_CLIENT->retrievePT($target_service, $err_code, $err_msg));
1631     }
1632
1633     /**
1634      * Set the certificate of the CAS server CA and if the CN should be properly
1635      * verified.
1636      *
1637      * @param string $cert        CA certificate file name
1638      * @param bool   $validate_cn Validate CN in certificate (default true)
1639      *
1640      * @return void
1641      */
1642     public static function setCasServerCACert($cert, $validate_cn = true)
1643     {
1644         phpCAS :: traceBegin();
1645         if (!is_object(self::$_PHPCAS_CLIENT)) {
1646             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
1647         }
1648         if (gettype($cert) != 'string') {
1649             phpCAS :: error('type mismatched for parameter $cert (should be `string\')');
1650         }
1651         if (gettype($validate_cn) != 'boolean') {\r
1652             phpCAS :: error('type mismatched for parameter $validate_cn (should be `boolean\')');\r
1653         }
1654         self::$_PHPCAS_CLIENT->setCasServerCACert($cert, $validate_cn);
1655         phpCAS :: traceEnd();
1656     }
1657
1658     /**
1659      * Set no SSL validation for the CAS server.
1660      *
1661      * @return void
1662      */
1663     public static function setNoCasServerValidation()
1664     {
1665         phpCAS :: traceBegin();
1666         if (!is_object(self::$_PHPCAS_CLIENT)) {
1667             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
1668         }
1669         phpCAS :: trace('You have configured no validation of the legitimacy of the cas server. This is not recommended for production use.');
1670         self::$_PHPCAS_CLIENT->setNoCasServerValidation();
1671         phpCAS :: traceEnd();
1672     }
1673
1674
1675     /**
1676      * Disable the removal of a CAS-Ticket from the URL when authenticating
1677      * DISABLING POSES A SECURITY RISK:
1678      * We normally remove the ticket by an additional redirect as a security
1679      * precaution to prevent a ticket in the HTTP_REFERRER or be carried over in
1680      * the URL parameter
1681      *
1682      * @return void
1683      */
1684     public static function setNoClearTicketsFromUrl()
1685     {
1686         phpCAS :: traceBegin();
1687         if (!is_object(self::$_PHPCAS_CLIENT)) {
1688             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
1689         }
1690         self::$_PHPCAS_CLIENT->setNoClearTicketsFromUrl();
1691         phpCAS :: traceEnd();
1692     }
1693
1694     /** @} */
1695
1696     /**
1697      * Change CURL options.
1698      * CURL is used to connect through HTTPS to CAS server
1699      *
1700      * @param string $key   the option key
1701      * @param string $value the value to set
1702      *
1703      * @return void
1704      */
1705     public static function setExtraCurlOption($key, $value)
1706     {
1707         phpCAS :: traceBegin();
1708         if (!is_object(self::$_PHPCAS_CLIENT)) {
1709             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
1710         }
1711         self::$_PHPCAS_CLIENT->setExtraCurlOption($key, $value);
1712         phpCAS :: traceEnd();
1713     }
1714
1715     /**
1716      * If you want your service to be proxied you have to enable it (default
1717      * disabled) and define an accepable list of proxies that are allowed to
1718      * proxy your service.
1719      *
1720      * Add each allowed proxy definition object. For the normal CAS_ProxyChain
1721      * class, the constructor takes an array of proxies to match. The list is in
1722      * reverse just as seen from the service. Proxies have to be defined in reverse
1723      * from the service to the user. If a user hits service A and gets proxied via
1724      * B to service C the list of acceptable on C would be array(B,A). The definition
1725      * of an individual proxy can be either a string or a regexp (preg_match is used)
1726      * that will be matched against the proxy list supplied by the cas server
1727      * when validating the proxy tickets. The strings are compared starting from
1728      * the beginning and must fully match with the proxies in the list.
1729      * Example:
1730      *          phpCAS::allowProxyChain(new CAS_ProxyChain(array(
1731      *                          'https://app.example.com/'
1732      *                  )));
1733      *          phpCAS::allowProxyChain(new CAS_ProxyChain(array(
1734      *                          '/^https:\/\/app[0-9]\.example\.com\/rest\//',
1735      *                          'http://client.example.com/'
1736      *                  )));
1737      *
1738      * For quick testing or in certain production screnarios you might want to
1739      * allow allow any other valid service to proxy your service. To do so, add
1740      * the "Any" chain:
1741      *          phpcas::allowProxyChain(new CAS_ProxyChain_Any);
1742      * THIS SETTING IS HOWEVER NOT RECOMMENDED FOR PRODUCTION AND HAS SECURITY
1743      * IMPLICATIONS: YOU ARE ALLOWING ANY SERVICE TO ACT ON BEHALF OF A USER
1744      * ON THIS SERVICE.
1745      *
1746      * @param CAS_ProxyChain_Interface $proxy_chain A proxy-chain that will be
1747      * matched against the proxies requesting access
1748      *
1749      * @return void
1750      */
1751     public static function allowProxyChain(CAS_ProxyChain_Interface $proxy_chain)
1752     {
1753         phpCAS :: traceBegin();
1754         if (!is_object(self::$_PHPCAS_CLIENT)) {
1755             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
1756         }
1757         if (self::$_PHPCAS_CLIENT->getServerVersion() !== CAS_VERSION_2_0) {
1758             phpCAS :: error('this method can only be used with the cas 2.0 protool');
1759         }
1760         self::$_PHPCAS_CLIENT->getAllowedProxyChains()->allowProxyChain($proxy_chain);
1761         phpCAS :: traceEnd();
1762     }
1763
1764     /**
1765      * Answer an array of proxies that are sitting in front of this application.
1766      * This method will only return a non-empty array if we have received and
1767      * validated a Proxy Ticket.
1768      *
1769      * @return array
1770      * @access public
1771      * @since 6/25/09
1772      */
1773     public static function getProxies ()
1774     {
1775         if ( !is_object(self::$_PHPCAS_CLIENT) ) {
1776             phpCAS::error('this method should only be called after '.__CLASS__.'::client()');
1777         }
1778
1779         return(self::$_PHPCAS_CLIENT->getProxies());
1780     }
1781
1782     // ########################################################################
1783     // PGTIOU/PGTID and logoutRequest rebroadcasting
1784     // ########################################################################
1785
1786     /**
1787      * Add a pgtIou/pgtId and logoutRequest rebroadcast node.
1788      *
1789      * @param string $rebroadcastNodeUrl The rebroadcast node URL. Can be
1790      * hostname or IP.
1791      *
1792      * @return void
1793      */
1794     public static function addRebroadcastNode($rebroadcastNodeUrl)
1795     {
1796         phpCAS::traceBegin();
1797         phpCAS::log('rebroadcastNodeUrl:'.$rebroadcastNodeUrl);
1798         if (!is_object(self::$_PHPCAS_CLIENT)) {
1799             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
1800         }
1801         if ( !(bool)preg_match("/^(http|https):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i", $rebroadcastNodeUrl)) {
1802             phpCAS::error('type mismatched for parameter $rebroadcastNodeUrl (should be `url\')');
1803         }
1804         self::$_PHPCAS_CLIENT->addRebroadcastNode($rebroadcastNodeUrl);
1805         phpCAS::traceEnd();
1806     }
1807
1808     /**
1809      * This method is used to add header parameters when rebroadcasting
1810      * pgtIou/pgtId or logoutRequest.
1811      *
1812      * @param String $header Header to send when rebroadcasting.
1813      *
1814      * @return void
1815      */
1816     public static function addRebroadcastHeader($header)
1817     {
1818         phpCAS :: traceBegin();
1819         if (!is_object(self::$_PHPCAS_CLIENT)) {
1820             phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
1821         }
1822         self::$_PHPCAS_CLIENT->addRebroadcastHeader($header);
1823         phpCAS :: traceEnd();
1824     }
1825 }
1826
1827 // ########################################################################
1828 // DOCUMENTATION
1829 // ########################################################################
1830
1831 // ########################################################################
1832 //  MAIN PAGE
1833
1834 /**
1835  * @mainpage
1836  *
1837  * The following pages only show the source documentation.
1838  *
1839  */
1840
1841 // ########################################################################
1842 //  MODULES DEFINITION
1843
1844 /** @defgroup public User interface */
1845
1846 /** @defgroup publicInit Initialization
1847  *  @ingroup public */
1848
1849 /** @defgroup publicAuth Authentication
1850  *  @ingroup public */
1851
1852 /** @defgroup publicServices Access to external services
1853  *  @ingroup public */
1854
1855 /** @defgroup publicConfig Configuration
1856  *  @ingroup public */
1857
1858 /** @defgroup publicLang Internationalization
1859  *  @ingroup publicConfig */
1860
1861 /** @defgroup publicOutput HTML output
1862  *  @ingroup publicConfig */
1863
1864 /** @defgroup publicPGTStorage PGT storage
1865  *  @ingroup publicConfig */
1866
1867 /** @defgroup publicDebug Debugging
1868  *  @ingroup public */
1869
1870 /** @defgroup internal Implementation */
1871
1872 /** @defgroup internalAuthentication Authentication
1873  *  @ingroup internal */
1874
1875 /** @defgroup internalBasic CAS Basic client features (CAS 1.0, Service Tickets)
1876  *  @ingroup internal */
1877
1878 /** @defgroup internalProxy CAS Proxy features (CAS 2.0, Proxy Granting Tickets)
1879  *  @ingroup internal */
1880
1881 /** @defgroup internalSAML CAS SAML features (SAML 1.1)
1882  *  @ingroup internal */
1883
1884 /** @defgroup internalPGTStorage PGT storage
1885  *  @ingroup internalProxy */
1886
1887 /** @defgroup internalPGTStorageDb PGT storage in a database
1888  *  @ingroup internalPGTStorage */
1889
1890 /** @defgroup internalPGTStorageFile PGT storage on the filesystem
1891  *  @ingroup internalPGTStorage */
1892
1893 /** @defgroup internalCallback Callback from the CAS server
1894  *  @ingroup internalProxy */
1895
1896 /** @defgroup internalProxyServices Proxy other services
1897  *  @ingroup internalProxy */
1898
1899 /** @defgroup internalService CAS client features (CAS 2.0, Proxied service)
1900  *  @ingroup internal */
1901
1902 /** @defgroup internalConfig Configuration
1903  *  @ingroup internal */
1904
1905 /** @defgroup internalBehave Internal behaviour of phpCAS
1906  *  @ingroup internalConfig */
1907
1908 /** @defgroup internalOutput HTML output
1909  *  @ingroup internalConfig */
1910
1911 /** @defgroup internalLang Internationalization
1912  *  @ingroup internalConfig
1913  *
1914  * To add a new language:
1915  * - 1. define a new constant PHPCAS_LANG_XXXXXX in CAS/CAS.php
1916  * - 2. copy any file from CAS/languages to CAS/languages/XXXXXX.php
1917  * - 3. Make the translations
1918  */
1919
1920 /** @defgroup internalDebug Debugging
1921  *  @ingroup internal */
1922
1923 /** @defgroup internalMisc Miscellaneous
1924  *  @ingroup internal */
1925
1926 // ########################################################################
1927 //  EXAMPLES
1928
1929 /**
1930  * @example example_simple.php
1931  */
1932 /**
1933  * @example example_service.php
1934  */
1935 /**
1936  * @example example_service_that_proxies.php
1937  */
1938 /**
1939  * @example example_service_POST.php
1940  */
1941 /**
1942  * @example example_proxy_serviceWeb.php
1943  */
1944 /**
1945  * @example example_proxy_serviceWeb_chaining.php
1946  */
1947 /**
1948  * @example example_proxy_POST.php
1949  */
1950 /**
1951  * @example example_proxy_GET.php
1952  */
1953 /**
1954  * @example example_lang.php
1955  */
1956 /**
1957  * @example example_html.php
1958  */
1959 /**
1960  * @example example_pgt_storage_file.php
1961  */
1962 /**
1963  * @example example_pgt_storage_db.php
1964  */
1965 /**
1966  * @example example_gateway.php
1967  */
1968 /**
1969  * @example example_logout.php
1970  */
1971 /**
1972  * @example example_rebroadcast.php
1973  */
1974 /**
1975  * @example example_custom_urls.php
1976  */
1977 /**
1978  * @example example_advanced_saml11.php
1979  */
1980 ?>