Merge branch 'MDL-42507-master' of git://github.com/andrewnicols/moodle
authorDan Poltawski <dan@moodle.com>
Tue, 29 Oct 2013 06:48:27 +0000 (14:48 +0800)
committerDan Poltawski <dan@moodle.com>
Tue, 29 Oct 2013 06:48:27 +0000 (14:48 +0800)
340 files changed:
admin/auth_config.php
admin/roles/assign.php
admin/roles/check.php
admin/roles/define.php
admin/roles/override.php
admin/roles/permissions.php
admin/roles/usersroles.php
admin/settings.php
admin/settings/frontpage.php
admin/tests/behat/behat_admin.php
admin/tests/behat/display_short_names.feature
admin/tool/behat/renderer.php
admin/tool/customlang/edit.php
admin/tool/customlang/index.php
admin/tool/generator/classes/testplan_backend.php
admin/tool/generator/cli/maketestplan.php
admin/tool/installaddon/classes/installer.php
admin/tool/installaddon/deploy.php
admin/tool/installaddon/tests/installer_test.php
auth/cas/CAS/CAS.php
auth/cas/CAS/CAS/AuthenticationException.php [new file with mode: 0644]
auth/cas/CAS/CAS/Autoload.php [new file with mode: 0644]
auth/cas/CAS/CAS/Client.php [new file with mode: 0644]
auth/cas/CAS/CAS/CookieJar.php [new file with mode: 0644]
auth/cas/CAS/CAS/Exception.php [new file with mode: 0644]
auth/cas/CAS/CAS/GracefullTerminationException.php [new file with mode: 0644]
auth/cas/CAS/CAS/InvalidArgumentException.php [new file with mode: 0644]
auth/cas/CAS/CAS/Languages/Catalan.php [new file with mode: 0644]
auth/cas/CAS/CAS/Languages/English.php [new file with mode: 0644]
auth/cas/CAS/CAS/Languages/French.php [new file with mode: 0644]
auth/cas/CAS/CAS/Languages/German.php [new file with mode: 0644]
auth/cas/CAS/CAS/Languages/Greek.php [new file with mode: 0644]
auth/cas/CAS/CAS/Languages/Japanese.php [new file with mode: 0644]
auth/cas/CAS/CAS/Languages/LanguageInterface.php [new file with mode: 0644]
auth/cas/CAS/CAS/Languages/Spanish.php [new file with mode: 0644]
auth/cas/CAS/CAS/OutOfSequenceException.php [new file with mode: 0644]
auth/cas/CAS/CAS/PGTStorage/AbstractStorage.php [new file with mode: 0644]
auth/cas/CAS/CAS/PGTStorage/Db.php [new file with mode: 0644]
auth/cas/CAS/CAS/PGTStorage/File.php [new file with mode: 0644]
auth/cas/CAS/CAS/PGTStorage/pgt-file.php [deleted file]
auth/cas/CAS/CAS/PGTStorage/pgt-main.php [deleted file]
auth/cas/CAS/CAS/ProxiedService.php [new file with mode: 0644]
auth/cas/CAS/CAS/ProxiedService/Abstract.php [new file with mode: 0644]
auth/cas/CAS/CAS/ProxiedService/Exception.php [new file with mode: 0644]
auth/cas/CAS/CAS/ProxiedService/Http.php [new file with mode: 0644]
auth/cas/CAS/CAS/ProxiedService/Http/Abstract.php [new file with mode: 0644]
auth/cas/CAS/CAS/ProxiedService/Http/Get.php [new file with mode: 0644]
auth/cas/CAS/CAS/ProxiedService/Http/Post.php [new file with mode: 0644]
auth/cas/CAS/CAS/ProxiedService/Imap.php [new file with mode: 0644]
auth/cas/CAS/CAS/ProxiedService/Testable.php [new file with mode: 0644]
auth/cas/CAS/CAS/ProxyChain.php [new file with mode: 0644]
auth/cas/CAS/CAS/ProxyChain/AllowedList.php [new file with mode: 0644]
auth/cas/CAS/CAS/ProxyChain/Any.php [new file with mode: 0644]
auth/cas/CAS/CAS/ProxyChain/Interface.php [new file with mode: 0644]
auth/cas/CAS/CAS/ProxyChain/Trusted.php [new file with mode: 0644]
auth/cas/CAS/CAS/ProxyTicketException.php [new file with mode: 0644]
auth/cas/CAS/CAS/Request/AbstractRequest.php [new file with mode: 0644]
auth/cas/CAS/CAS/Request/CurlMultiRequest.php [new file with mode: 0644]
auth/cas/CAS/CAS/Request/CurlRequest.php [new file with mode: 0644]
auth/cas/CAS/CAS/Request/Exception.php [new file with mode: 0644]
auth/cas/CAS/CAS/Request/MultiRequestInterface.php [new file with mode: 0644]
auth/cas/CAS/CAS/Request/RequestInterface.php [new file with mode: 0644]
auth/cas/CAS/CAS/client.php [deleted file]
auth/cas/CAS/CAS/domxml-php4-to-php5.php [deleted file]
auth/cas/CAS/CAS/languages/catalan.php [deleted file]
auth/cas/CAS/CAS/languages/english.php [deleted file]
auth/cas/CAS/CAS/languages/french.php [deleted file]
auth/cas/CAS/CAS/languages/german.php [deleted file]
auth/cas/CAS/CAS/languages/greek.php [deleted file]
auth/cas/CAS/CAS/languages/japanese.php [deleted file]
auth/cas/CAS/CAS/languages/languages.php [deleted file]
auth/cas/CAS/CAS/languages/spanish.php [deleted file]
auth/cas/CAS/moodle_readme.txt [new file with mode: 0644]
auth/cas/auth.php
auth/cas/config.html
auth/cas/db/upgrade.php
auth/cas/languages.php
auth/cas/thirdpartylibs.xml
auth/cas/version.php
auth/db/config.html
auth/fc/config.html
auth/ldap/config.html
auth/yui/passwordunmask/passwordunmask.js [new file with mode: 0644]
backup/moodle2/backup_xml_transformer.class.php
backup/moodle2/restore_section_task.class.php
backup/moodle2/restore_stepslib.php
backup/util/dbops/restore_dbops.class.php
backup/util/helper/backup_cron_helper.class.php
badges/action.php
badges/award.php
badges/criteria.php
badges/criteria_action.php
badges/criteria_settings.php
badges/edit.php
badges/index.php
badges/overview.php
badges/recipients.php
blocks/course_overview/block_course_overview.php
blocks/course_overview/lang/en/block_course_overview.php
blocks/course_overview/locallib.php
blocks/course_overview/renderer.php
blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-debug.js
blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-min.js
blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js
blocks/navigation/yui/src/navigation/js/navigation.js
blocks/quiz_results/block_quiz_results.php
blocks/tests/behat/return_block_original_state.feature [new file with mode: 0644]
cohort/assign.php
cohort/edit.php
cohort/index.php
completion/tests/behat/restrict_activity_by_date.feature [new file with mode: 0644]
completion/tests/behat/restrict_activity_by_grade.feature [new file with mode: 0644]
completion/tests/behat/restrict_section_availability.feature
config-dist.php
course/ajax/management.php
course/classes/management/helper.php
course/classes/management_renderer.php
course/delete.php
course/editcategory.php
course/format/renderer.php
course/management.php
course/modedit.php
course/reset.php
course/tests/behat/behat_course.php
course/tests/behat/course_category_management_listing.feature
course/tests/behat/course_controls.feature
course/tests/behat/create_delete_course.feature
course/tests/courselib_test.php
course/user.php
course/yui/build/moodle-course-management/moodle-course-management-debug.js
course/yui/build/moodle-course-management/moodle-course-management-min.js
course/yui/build/moodle-course-management/moodle-course-management.js
course/yui/src/management/js/category.js
course/yui/src/management/js/console.js
enrol/imsenterprise/README.txt [deleted file]
enrol/imsenterprise/TODO.txt [deleted file]
enrol/imsenterprise/db/install.php
enrol/imsenterprise/db/upgrade.php
enrol/imsenterprise/entv1p1_conformance_summary.html [deleted file]
enrol/imsenterprise/importnow.php
enrol/imsenterprise/lib.php
enrol/imsenterprise/locallib.php
enrol/imsenterprise/settings.php
enrol/imsenterprise/tests/imsenterprise_test.php
enrol/imsenterprise/version.php
enrol/meta/lib.php
enrol/self/lib.php
enrol/self/tests/behat/self_enrolment.feature
files/index.php
files/renderer.php
filter/glossary/yui/build/moodle-filter_glossary-autolinker/moodle-filter_glossary-autolinker-debug.js
filter/glossary/yui/build/moodle-filter_glossary-autolinker/moodle-filter_glossary-autolinker-min.js
filter/glossary/yui/build/moodle-filter_glossary-autolinker/moodle-filter_glossary-autolinker.js
filter/glossary/yui/src/autolinker/js/autolinker.js
filter/glossary/yui/src/autolinker/meta/autolinker.json
filter/manage.php
group/import.php
group/tests/behat/auto_creation.feature
lang/en/backup.php
lang/en/cache.php
lang/en/moodle.php
lib/accesslib.php
lib/adminlib.php
lib/ajax/getsiteadminbranch.php [new file with mode: 0644]
lib/classes/event/course_deleted.php
lib/classes/event/user_deleted.php
lib/classes/plugininfo/filter.php
lib/classes/session/handler.php
lib/classes/session/manager.php
lib/classes/session/memcached.php
lib/classes/useragent.php
lib/db/caches.php
lib/deprecatedlib.php
lib/dml/moodle_database.php
lib/dml/mssql_native_moodle_database.php
lib/dml/mysqli_native_moodle_database.php
lib/dml/oci_native_moodle_database.php
lib/dml/pgsql_native_moodle_database.php
lib/dml/sqlite3_pdo_moodle_database.php
lib/dml/sqlsrv_native_moodle_database.php
lib/editor/tinymce/plugins/pdw/readme_moodle.txt
lib/editor/tinymce/plugins/pdw/tinymce/editor_plugin.js
lib/excellib.class.php
lib/filelib.php
lib/filterlib.php
lib/formslib.php
lib/moodlelib.php
lib/navigationlib.php
lib/outputrenderers.php
lib/pear/OLE.php [deleted file]
lib/pear/README.txt
lib/pear/README_MOODLE.txt
lib/portfoliolib.php
lib/setup.php
lib/tests/accesslib_test.php
lib/tests/behat/behat_data_generators.php
lib/tests/datalib_test.php
lib/tests/filterlib_test.php
lib/tests/moodlelib_test.php
lib/tests/useragent_test.php
lib/thirdpartylibs.xml
lib/yui/build/moodle-core-blocks/moodle-core-blocks-debug.js
lib/yui/build/moodle-core-blocks/moodle-core-blocks-min.js
lib/yui/build/moodle-core-blocks/moodle-core-blocks.js
lib/yui/build/moodle-core-formautosubmit/moodle-core-formautosubmit-debug.js
lib/yui/build/moodle-core-formautosubmit/moodle-core-formautosubmit-min.js
lib/yui/build/moodle-core-formautosubmit/moodle-core-formautosubmit.js
lib/yui/dragdrop/dragdrop.js
lib/yui/src/blocks/js/blocks.js
lib/yui/src/formautosubmit/js/formautosubmit.js
login/change_password.php
message/edit.php
message/lib.php
mod/assign/feedback/editpdf/ajax_progress.php [new file with mode: 0644]
mod/assign/feedback/editpdf/classes/document_services.php
mod/assign/feedback/editpdf/classes/renderer.php
mod/assign/feedback/editpdf/classes/widget.php
mod/assign/feedback/editpdf/lang/en/assignfeedback_editpdf.php
mod/assign/feedback/editpdf/locallib.php
mod/assign/feedback/editpdf/styles.css
mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-debug.js
mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor-min.js
mod/assign/feedback/editpdf/yui/build/moodle-assignfeedback_editpdf-editor/moodle-assignfeedback_editpdf-editor.js
mod/assign/feedback/editpdf/yui/src/editor/js/editor.js
mod/assign/feedback/editpdf/yui/src/editor/js/globals.js
mod/book/tool/importhtml/locallib.php
mod/choice/tests/behat/limit_responses.feature [new file with mode: 0644]
mod/data/templates.php
mod/feedback/item/multichoice/lib.php
mod/feedback/item/multichoicerated/lib.php
mod/feedback/item/numeric/lib.php
mod/feedback/item/textarea/lib.php
mod/feedback/item/textfield/lib.php
mod/forum/lib.php
mod/forum/tests/behat/edit_post_student.feature
mod/lti/grade.php
mod/lti/lang/en/lti.php
mod/lti/locallib.php
mod/lti/service.php
mod/lti/servicelib.php
mod/lti/tests/locallib_test.php
mod/quiz/locallib.php
mod/quiz/report/grading/report.php
pix/a/add_file.png
pix/a/add_file.svg [new file with mode: 0644]
pix/a/create_folder.png
pix/a/create_folder.svg [new file with mode: 0644]
pix/a/download_all.png
pix/a/download_all.svg [new file with mode: 0644]
pix/a/help.png
pix/a/help.svg [new file with mode: 0644]
pix/a/logout.png
pix/a/logout.svg [new file with mode: 0644]
pix/a/refresh.png
pix/a/refresh.svg [new file with mode: 0644]
pix/a/search.png
pix/a/search.svg [new file with mode: 0644]
pix/a/setting.png
pix/a/setting.svg [new file with mode: 0644]
pix/a/view_icon_active.png [new file with mode: 0644]
pix/a/view_icon_active.svg [new file with mode: 0644]
pix/a/view_list_active.png [new file with mode: 0644]
pix/a/view_list_active.svg [new file with mode: 0644]
pix/a/view_tree_active.png [new file with mode: 0644]
pix/a/view_tree_active.svg [new file with mode: 0644]
question/tests/behat/delete_questions.feature [new file with mode: 0644]
report/log/user.php
report/loglive/index.php
report/outline/user.php
report/stats/index.php
report/stats/user.php
repository/skydrive/lang/en/repository_skydrive.php
repository/upload/tests/behat/behat_repository_upload.php
tag/lib.php
theme/base/pix/fp/add_file.png [new file with mode: 0644]
theme/base/pix/fp/add_file.svg [new file with mode: 0644]
theme/base/pix/fp/create_folder.png [new file with mode: 0644]
theme/base/pix/fp/create_folder.svg [new file with mode: 0644]
theme/base/pix/fp/download_all.png [new file with mode: 0644]
theme/base/pix/fp/download_all.svg [new file with mode: 0644]
theme/base/pix/fp/help.png [new file with mode: 0644]
theme/base/pix/fp/help.svg [new file with mode: 0644]
theme/base/pix/fp/logout.png [new file with mode: 0644]
theme/base/pix/fp/logout.svg [new file with mode: 0644]
theme/base/pix/fp/refresh.png [new file with mode: 0644]
theme/base/pix/fp/refresh.svg [new file with mode: 0644]
theme/base/pix/fp/search.png [new file with mode: 0644]
theme/base/pix/fp/search.svg [new file with mode: 0644]
theme/base/pix/fp/setting.png [new file with mode: 0644]
theme/base/pix/fp/setting.svg [new file with mode: 0644]
theme/base/pix/fp/view_icon_active.png
theme/base/pix/fp/view_icon_active.svg [new file with mode: 0644]
theme/base/pix/fp/view_icon_inactive.png [deleted file]
theme/base/pix/fp/view_icon_selected.png [deleted file]
theme/base/pix/fp/view_list_active.png
theme/base/pix/fp/view_list_active.svg [new file with mode: 0644]
theme/base/pix/fp/view_list_inactive.png [deleted file]
theme/base/pix/fp/view_list_selected.png [deleted file]
theme/base/pix/fp/view_tree_active.png
theme/base/pix/fp/view_tree_active.svg [new file with mode: 0644]
theme/base/pix/fp/view_tree_inactive.png [deleted file]
theme/base/pix/fp/view_tree_selected.png [deleted file]
theme/base/style/core.css
theme/base/style/course.css
theme/base/style/filemanager.css
theme/bootstrapbase/less/moodle/course.less
theme/bootstrapbase/less/moodle/filemanager.less
theme/bootstrapbase/pix/fp/add_file.png [new file with mode: 0644]
theme/bootstrapbase/pix/fp/add_file.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/create_folder.png [new file with mode: 0644]
theme/bootstrapbase/pix/fp/create_folder.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/download_all.png [new file with mode: 0644]
theme/bootstrapbase/pix/fp/download_all.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/help.png [new file with mode: 0644]
theme/bootstrapbase/pix/fp/help.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/logout.png [new file with mode: 0644]
theme/bootstrapbase/pix/fp/logout.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/refresh.png [new file with mode: 0644]
theme/bootstrapbase/pix/fp/refresh.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/search.png [new file with mode: 0644]
theme/bootstrapbase/pix/fp/search.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/setting.png [new file with mode: 0644]
theme/bootstrapbase/pix/fp/setting.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/view_icon_active.png
theme/bootstrapbase/pix/fp/view_icon_active.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/view_icon_inactive.png [deleted file]
theme/bootstrapbase/pix/fp/view_icon_selected.png [deleted file]
theme/bootstrapbase/pix/fp/view_list_active.png
theme/bootstrapbase/pix/fp/view_list_active.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/view_list_inactive.png [deleted file]
theme/bootstrapbase/pix/fp/view_list_selected.png [deleted file]
theme/bootstrapbase/pix/fp/view_tree_active.png
theme/bootstrapbase/pix/fp/view_tree_active.svg [new file with mode: 0644]
theme/bootstrapbase/pix/fp/view_tree_inactive.png [deleted file]
theme/bootstrapbase/pix/fp/view_tree_selected.png [deleted file]
theme/bootstrapbase/style/moodle.css
theme/yui_combo.php
user/edit.php
user/editadvanced.php
version.php

index 50bcfc9..ed5fb41 100644 (file)
@@ -78,6 +78,9 @@ echo '<p style="text-align: center"><input type="submit" value="' . get_string("
 echo "</div>\n";
 echo "</form>\n";
 
+$PAGE->requires->string_for_js('unmaskpassword', 'core_form');
+$PAGE->requires->yui_module('moodle-auth-passwordunmask', 'M.auth.passwordunmask');
+
 echo $OUTPUT->footer();
 exit;
 
index 980e2ae..421eca2 100644 (file)
@@ -149,12 +149,11 @@ switch ($context->contextlevel) {
         $showroles = 1;
         break;
     case CONTEXT_COURSECAT:
-        $PAGE->set_heading("$SITE->fullname: ".get_string("categories"));
+        $PAGE->set_heading($SITE->fullname);
         break;
     case CONTEXT_COURSE:
         if ($isfrontpage) {
-            require_once($CFG->libdir.'/adminlib.php');
-            admin_externalpage_setup('frontpageroles', '', array('contextid' => $contextid, 'roleid' => $roleid));
+            $PAGE->set_heading(get_string('frontpage', 'admin'));
         } else {
             $PAGE->set_heading($course->fullname);
         }
index 0590165..938fc90 100644 (file)
@@ -50,6 +50,14 @@ if (!has_any_capability(array('moodle/role:assign', 'moodle/role:safeoverride',
     print_error('nopermissions', 'error', '', get_string('checkpermissions', 'core_role'));
 }
 $PAGE->set_url($url);
+
+if ($context->contextlevel == CONTEXT_USER and $USER->id != $context->instanceid) {
+    $PAGE->navigation->extend_for_user($user);
+    $PAGE->set_context(context_course::instance($course->id));
+} else {
+    $PAGE->set_context($context);
+}
+
 $PAGE->set_context($context);
 
 $courseid = $course->id;
@@ -79,12 +87,11 @@ switch ($context->contextlevel) {
         $showroles = 1;
         break;
     case CONTEXT_COURSECAT:
-        $PAGE->set_heading("$SITE->fullname: ".get_string("categories"));
+        $PAGE->set_heading($SITE->fullname);
         break;
     case CONTEXT_COURSE:
         if ($isfrontpage) {
-            require_once($CFG->libdir.'/adminlib.php');
-            admin_externalpage_setup('frontpageroles', '', array('contextid' => $contextid), $CFG->wwwroot . '/' . $CFG->admin . '/roles/check.php');
+            $PAGE->set_heading(get_string('frontpage', 'admin'));
         } else {
             $PAGE->set_heading($course->fullname);
         }
index 265b100..d30ad3e 100644 (file)
@@ -201,8 +201,7 @@ if (optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey() && $de
     $event = \core\event\role_capabilities_updated::create(
         array(
             'context' => $systemcontext,
-            'objectid' => $roleid,
-            'other' => array('name' => $definitiontable->get_role_name())
+            'objectid' => $roleid
         )
     );
     $event->set_legacy_logdata(array(SITEID, 'role', $action, 'admin/roles/define.php?action=view&roleid=' . $tableroleid,
index bc506f1..ab80e69 100644 (file)
@@ -53,9 +53,19 @@ if (!has_capability('moodle/role:override', $context)) {
     $safeoverridesonly = true;
 }
 $PAGE->set_url($url);
-$PAGE->set_context($context);
 $PAGE->set_pagelayout('admin');
 
+if ($context->contextlevel == CONTEXT_USER and $USER->id != $context->instanceid) {
+    $PAGE->navigation->extend_for_user($user);
+    $PAGE->set_context(context_course::instance($course->id));
+    navigation_node::override_active_url(new moodle_url('/admin/roles/permissions.php',
+        array('contextid'=>$context->id, 'userid'=>$context->instanceid, 'courseid'=>$course->id)));
+
+} else {
+    $PAGE->set_context($context);
+    navigation_node::override_active_url(new moodle_url('/admin/roles/permissions.php', array('contextid'=>$context->id)));
+}
+
 $courseid = $course->id;
 
 $returnurl = new moodle_url('/admin/roles/permissions.php', array('contextid' => $context->id));
@@ -91,12 +101,11 @@ switch ($context->contextlevel) {
         $showroles = 1;
         break;
     case CONTEXT_COURSECAT:
-        $PAGE->set_heading("$SITE->fullname: ".get_string("categories"));
+        $PAGE->set_heading($SITE->fullname);
         break;
     case CONTEXT_COURSE:
         if ($isfrontpage) {
-            require_once($CFG->libdir.'/adminlib.php');
-            admin_externalpage_setup('frontpageroles', '', array(), $PAGE->url);
+            $PAGE->set_heading(get_string('frontpage', 'admin'));
         } else {
             $PAGE->set_heading($course->fullname);
         }
@@ -130,8 +139,7 @@ if (optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey()) {
         array(
             'context' => $context,
             'objectid' => $roleid,
-            'courseid' => $courseid,
-            'other' => array('name' => $rolename)
+            'courseid' => $courseid
         )
     );
 
index 8af137a..3670a86 100644 (file)
@@ -57,7 +57,14 @@ if ($course) {
 require_login($course, false, $cm);
 require_capability('moodle/role:review', $context);
 $PAGE->set_url($url);
-$PAGE->set_context($context);
+
+if ($context->contextlevel == CONTEXT_USER and $USER->id != $context->instanceid) {
+    $PAGE->navigation->extend_for_user($user);
+    $PAGE->set_context(context_course::instance($course->id));
+} else {
+    $PAGE->set_context($context);
+}
+
 $courseid = $course->id;
 
 
@@ -88,12 +95,11 @@ switch ($context->contextlevel) {
         $showroles = 1;
         break;
     case CONTEXT_COURSECAT:
-        $PAGE->set_heading("$SITE->fullname: ".get_string("categories"));
+        $PAGE->set_heading($SITE->fullname);
         break;
     case CONTEXT_COURSE:
         if ($isfrontpage) {
-            require_once($CFG->libdir.'/adminlib.php');
-            admin_externalpage_setup('frontpageroles', '', array(), $PAGE->url);
+            $PAGE->set_heading(get_string('frontpage', 'admin'));
         } else {
             $PAGE->set_heading($course->fullname);
         }
index c62c979..99ded8f 100644 (file)
@@ -41,11 +41,17 @@ $systemcontext = context_system::instance();
 $baseurl = new moodle_url('/admin/roles/usersroles.php', array('userid'=>$userid, 'courseid'=>$courseid));
 
 $PAGE->set_url($baseurl);
-$PAGE->set_context($coursecontext);
 $PAGE->set_pagelayout('admin');
 
 // Check login and permissions.
-require_login($course);
+if ($course->id == SITEID) {
+    require_login();
+    $PAGE->set_context($usercontext);
+} else {
+    require_login($course);
+    $PAGE->set_context($coursecontext);
+}
+
 $canview = has_any_capability(array('moodle/role:assign', 'moodle/role:safeoverride',
         'moodle/role:override', 'moodle/role:manage'), $usercontext);
 if (!$canview) {
@@ -120,10 +126,10 @@ $title = get_string('xroleassignments', 'core_role', $fullname);
 
 // Course header.
 $PAGE->set_title($title);
-if ($courseid != SITEID) {
+if ($courseid == SITEID) {
     $PAGE->set_heading($fullname);
 } else {
-    $PAGE->set_heading($course->fullname);
+    $PAGE->set_heading($course->fullname.': '.$fullname);
 }
 echo $OUTPUT->header();
 echo $OUTPUT->heading($title, 3);
index c8444c5..3236444 100644 (file)
@@ -14,6 +14,7 @@ $PAGE->set_url('/admin/settings.php', array('section' => $section));
 $PAGE->set_pagetype('admin-setting-' . $section);
 $PAGE->set_pagelayout('admin');
 $PAGE->navigation->clear_cache();
+navigation_node::require_admin_tree();
 
 $adminroot = admin_get_root(); // need all settings
 $settingspage = $adminroot->locate($section, true);
index e52f6ff..d435022 100644 (file)
@@ -69,29 +69,6 @@ if (!during_initial_install()) { //do not use during installation
         }
         $temp->add(new admin_setting_configselect('defaultfrontpageroleid', new lang_string('frontpagedefaultrole', 'admin'), '', $defaultfrontpageroleid, $options));
 
-
         $ADMIN->add('frontpage', $temp);
-
-        $ADMIN->add('frontpage', new admin_externalpage('frontpageroles', new lang_string('frontpageroles', 'admin'), "$CFG->wwwroot/$CFG->admin/roles/assign.php?contextid=" . $frontpagecontext->id, 'moodle/role:assign', false, $frontpagecontext));
-
-        $ADMIN->add('frontpage', new admin_externalpage('frontpagefilters', new lang_string('frontpagefilters', 'admin'), "$CFG->wwwroot/filter/manage.php?contextid=" . $frontpagecontext->id, 'moodle/filter:manage', false, $frontpagecontext));
-
-        $ADMIN->add('frontpage', new admin_externalpage('frontpagebackup', new lang_string('frontpagebackup', 'admin'), $CFG->wwwroot.'/backup/backup.php?id='.SITEID, 'moodle/backup:backupcourse', false, $frontpagecontext));
-
-        $ADMIN->add('frontpage', new admin_externalpage('frontpagerestore', new lang_string('frontpagerestore', 'admin'), $CFG->wwwroot.'/backup/restorefile.php?contextid='.$frontpagecontext->id, 'moodle/restore:restorecourse', false, $frontpagecontext));
-
-        $questioncapabilities = array(
-                'moodle/question:add',
-                'moodle/question:editmine',
-                'moodle/question:editall',
-                'moodle/question:viewmine',
-                'moodle/question:viewall',
-                'moodle/question:movemine',
-                'moodle/question:moveall');
-        $ADMIN->add('frontpage', new admin_externalpage('frontpagequestions', new lang_string('frontpagequestions', 'admin'), $CFG->wwwroot.'/question/edit.php?courseid='.SITEID, $questioncapabilities, false, $frontpagecontext));
-
-        if (!empty($SITE->legacyfiles) and $SITE->legacyfiles === 2) {
-            $ADMIN->add('frontpage', new admin_externalpage('sitefiles', new lang_string('sitelegacyfiles'), $CFG->wwwroot . '/files/index.php?id=' . SITEID, 'moodle/course:managefiles', false, $frontpagecontext));
-        }
     }
 }
index 6b4f88f..91afdcf 100644 (file)
@@ -28,7 +28,8 @@
 require_once(__DIR__ . '/../../../lib/behat/behat_base.php');
 require_once(__DIR__ . '/../../../lib/behat/behat_field_manager.php');
 
-use Behat\Gherkin\Node\TableNode as TableNode,
+use Behat\Behat\Context\Step\Given as Given,
+    Behat\Gherkin\Node\TableNode as TableNode,
     Behat\Mink\Exception\ElementNotFoundException as ElementNotFoundException;
 
 /**
@@ -110,4 +111,23 @@ class behat_admin extends behat_base {
             $this->getSession()->wait($timeout, $javascript);
         }
     }
+
+    /**
+     * Goes to notification page ensuring site admin navigation is loaded.
+     *
+     * @Given /^I go to notifications page$/
+     * @return Given[]
+     */
+    public function i_go_to_notifications_page() {
+        if ($this->running_javascript()) {
+            return array(
+                new Given('I expand "' . get_string('administrationsite') . '" node'),
+                new Given('I follow "' . get_string('notifications') . '"')
+            );
+        } else {
+            return array(
+                new Given('I follow "' . get_string('administrationsite') . '"')
+            );
+        }
+    }
 }
index f17f092..86231b2 100644 (file)
@@ -15,7 +15,8 @@ Feature: Display extended course names
     And I should not see "C_shortname Course fullname"
 
   Scenario: Courses list with extended course names
-    Given I click on "Courses" "link" in the "//div[@id='settingsnav']/descendant::li[contains(concat(' ', normalize-space(@class), ' '), ' type_setting ')][not(contains(., 'Site administration'))][contains(., 'Appearance')]" "xpath_element"
+    Given I go to notifications page
+    And I click on "Courses" "link" in the "//div[@id='settingsnav']/descendant::li[contains(concat(' ', normalize-space(@class), ' '), ' type_setting ')][contains(., 'Appearance')]" "xpath_element"
     And I check "Display extended course names"
     When I press "Save changes"
     And I am on homepage
index 0f5ac5e..324241b 100644 (file)
@@ -105,6 +105,15 @@ class tool_behat_renderer extends plugin_renderer_base {
                 $stepsdefinitions
             );
 
+            // Replace simple OR options.
+            $regex = '#\(\?P<[^>]+>([^\)|]+\|[^\)]+)\)#';
+            $stepsdefinitions = preg_replace_callback($regex,
+                function($matches){
+                    return html_writer::select(explode('|', $matches[1]), uniqid());
+                },
+                $stepsdefinitions
+            );
+
         }
 
         // Steps definitions.
index 6aaec2f..71c54fe 100644 (file)
@@ -24,6 +24,7 @@
 require(dirname(dirname(dirname(dirname(__FILE__)))) . '/config.php');
 require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/customlang/locallib.php');
 require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/customlang/filter_form.php');
+require_once($CFG->libdir.'/adminlib.php');
 
 require_login(SITEID, false);
 require_capability('tool/customlang:edit', context_system::instance());
@@ -32,11 +33,10 @@ $lng                    = required_param('lng', PARAM_LANG);
 $currentpage            = optional_param('p', 0, PARAM_INT);
 $translatorsubmitted    = optional_param('translatorsubmitted', 0, PARAM_BOOL);
 
-$PAGE->set_pagelayout('report'); // Allows for wide page contents.
-$PAGE->set_url('/admin/tool/customlang/edit.php', array('lng' => $lng));
-navigation_node::override_active_url(new moodle_url('/admin/tool/customlang/index.php'));
-$PAGE->set_title(get_string('pluginname', 'tool_customlang'));
-$PAGE->set_heading(get_string('pluginname', 'tool_customlang'));
+admin_externalpage_setup('toolcustomlang', '', null,
+    new moodle_url('/admin/tool/customlang/edit.php', array('lng' => $lng)),
+    array('pagelayout' => 'report')); // Hack: allows for wide page contents.
+
 $PAGE->requires->js_init_call('M.tool_customlang.init_editor', array(), true);
 
 if (empty($lng)) {
index aff45ef..431a911 100644 (file)
@@ -29,7 +29,7 @@ require(dirname(dirname(dirname(dirname(__FILE__)))) . '/config.php');
 require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/customlang/locallib.php');
 require_once($CFG->libdir.'/adminlib.php');
 
-require_login(SITEID, false);
+require_login(null, false);
 require_capability('tool/customlang:view', context_system::instance());
 
 $action  = optional_param('action', '', PARAM_ALPHA);
index 7499500..2e43b4c 100644 (file)
@@ -317,7 +317,7 @@ class tool_generator_testplan_backend extends tool_generator_backend {
 
         // Checks that the selected course has enough users.
         $coursesizes = tool_generator_course_backend::get_users_per_size();
-        if (count($users) < $coursesizes[$size]) {
+        if (count($users) < self::$users[$size]) {
             $errors['size'] = get_string('notenoughusers', 'tool_generator');
         }
 
index 456393d..78ab7e4 100644 (file)
@@ -94,7 +94,7 @@ if (empty($CFG->tool_generator_users_password) || is_bool($CFG->tool_generator_u
 }
 
 // Switch to admin user account.
-session_set_user(get_admin());
+\core\session\manager::set_user(get_admin());
 
 // Create files.
 $courseid = $DB->get_field('course', 'id', array('shortname' => $shortname));
index 1a1866c..e759c43 100644 (file)
@@ -392,8 +392,10 @@ class tool_installaddon_installer {
      *
      * @param string $source full path to the existing directory
      * @param string $target full path to the new location of the directory
+     * @param int $dirpermissions
+     * @param int $filepermissions
      */
-    public function move_directory($source, $target) {
+    public function move_directory($source, $target, $dirpermissions, $filepermissions) {
 
         if (file_exists($target)) {
             throw new tool_installaddon_installer_exception('err_folder_already_exists', array('path' => $target));
@@ -405,7 +407,16 @@ class tool_installaddon_installer {
             throw new tool_installaddon_installer_exception('err_no_such_folder', array('path' => $source));
         }
 
-        make_writable_directory($target);
+        if (!file_exists($target)) {
+            // Do not use make_writable_directory() here - it is intended for dataroot only.
+            mkdir($target, true);
+            @chmod($target, $dirpermissions);
+        }
+
+        if (!is_writable($target)) {
+            closedir($handle);
+            throw new tool_installaddon_installer_exception('err_folder_not_writable', array('path' => $target));
+        }
 
         while ($filename = readdir($handle)) {
             $sourcepath = $source.'/'.$filename;
@@ -416,10 +427,11 @@ class tool_installaddon_installer {
             }
 
             if (is_dir($sourcepath)) {
-                $this->move_directory($sourcepath, $targetpath);
+                $this->move_directory($sourcepath, $targetpath, $dirpermissions, $filepermissions);
 
             } else {
                 rename($sourcepath, $targetpath);
+                @chmod($targetpath, $filepermissions);
             }
         }
 
index 7dea2cc..b80af83 100644 (file)
@@ -69,6 +69,10 @@ if (file_exists($plugintypepath.'/'.$pluginname)) {
         get_string('invaliddata', 'core_error'));
 }
 
-$installer->move_directory($zipcontentpath.'/'.$pluginname, $plugintypepath.'/'.$pluginname);
+// Copy permissions form the plugin type directory.
+$dirpermissions = fileperms($plugintypepath);
+$filepermissions = ($dirpermissions & 0666); // Strip execute flags.
+
+$installer->move_directory($zipcontentpath.'/'.$pluginname, $plugintypepath.'/'.$pluginname, $dirpermissions, $filepermissions);
 fulldelete($CFG->tempdir.'/tool_installaddon/'.$jobid);
 redirect(new moodle_url('/admin'));
index 28e37bd..948294c 100644 (file)
@@ -33,7 +33,7 @@ defined('MOODLE_INTERNAL') || die();
  * @copyright 2013 David Mudrak <david@moodle.com>
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-class tool_installaddon_installer_test extends advanced_testcase {
+class tool_installaddon_installer_testcase extends advanced_testcase {
 
     public function test_get_addons_repository_url() {
         $installer = testable_tool_installaddon_installer::instance();
@@ -137,7 +137,7 @@ class tool_installaddon_installer_test extends advanced_testcase {
         file_put_contents($contentsdir.'/readme.txt', 'Hello world!');
 
         $installer = tool_installaddon_installer::instance();
-        $installer->move_directory($jobroot.'/contents', $jobroot.'/moved');
+        $installer->move_directory($jobroot.'/contents', $jobroot.'/moved', 0777, 0666);
 
         $this->assertFalse(is_dir($jobroot.'/contents'));
         $this->assertTrue(is_file($jobroot.'/moved/sub/folder/readme.txt'));
index f9c60fa..6efafce 100644 (file)
-<?php\r
-\r
-/*\r
- * Copyright © 2003-2010, The ESUP-Portail consortium & the JA-SIG Collaborative.\r
- * All rights reserved.\r
- * \r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions are met:\r
- * \r
- *     * Redistributions of source code must retain the above copyright notice,\r
- *       this list of conditions and the following disclaimer.\r
- *     * Redistributions in binary form must reproduce the above copyright notice,\r
- *       this list of conditions and the following disclaimer in the documentation\r
- *       and/or other materials provided with the distribution.\r
- *     * Neither the name of the ESUP-Portail consortium & the JA-SIG\r
- *       Collaborative nor the names of its contributors may be used to endorse or\r
- *       promote products derived from this software without specific prior\r
- *       written permission.\r
-\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\r
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\r
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-\r
-//\r
-// hack by Vangelis Haniotakis to handle the absence of $_SERVER['REQUEST_URI'] in IIS\r
-//\r
-$_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'];\r
-if (isset($_SERVER['QUERY_STRING'])) {\r
-    $_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];\r
-}\r
-\r
-//\r
-// another one by Vangelis Haniotakis also to make phpCAS work with PHP5\r
-//\r
-if (version_compare(PHP_VERSION, '5', '>=') && !(function_exists('domxml_new_doc'))) {\r
-       require_once (dirname(__FILE__) . '/CAS/domxml-php4-to-php5.php');\r
-}\r
-\r
-/**\r
- * @file CAS/CAS.php\r
- * Interface class of the phpCAS library\r
- *\r
- * @ingroup public\r
- */\r
-\r
-// ########################################################################\r
-//  CONSTANTS\r
-// ########################################################################\r
-\r
-// ------------------------------------------------------------------------\r
-//  CAS VERSIONS\r
-// ------------------------------------------------------------------------\r
-\r
-/**\r
- * phpCAS version. accessible for the user by phpCAS::getVersion().\r
- */\r
-define('PHPCAS_VERSION', '1.1.3');\r
-\r
-// ------------------------------------------------------------------------\r
-//  CAS VERSIONS\r
-// ------------------------------------------------------------------------\r
-/**\r
- * @addtogroup public\r
- * @{\r
- */\r
-\r
-/**\r
- * CAS version 1.0\r
- */\r
-define("CAS_VERSION_1_0", '1.0');\r
-/*!\r
- * CAS version 2.0\r
- */\r
-define("CAS_VERSION_2_0", '2.0');\r
-\r
-// ------------------------------------------------------------------------\r
-//  SAML defines\r
-// ------------------------------------------------------------------------\r
-\r
-/**\r
- * SAML protocol\r
- */\r
-define("SAML_VERSION_1_1", 'S1');\r
-\r
-/**\r
- * XML header for SAML POST\r
- */\r
-define("SAML_XML_HEADER", '<?xml version="1.0" encoding="UTF-8"?>');\r
-\r
-/**\r
- * SOAP envelope for SAML POST\r
- */\r
-define("SAML_SOAP_ENV", '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/>');\r
-\r
-/**\r
- * SOAP body for SAML POST\r
- */\r
-define("SAML_SOAP_BODY", '<SOAP-ENV:Body>');\r
-\r
-/**\r
- * SAMLP request\r
- */\r
-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">');\r
-define("SAMLP_REQUEST_CLOSE", '</samlp:Request>');\r
-\r
-/**\r
- * SAMLP artifact tag (for the ticket)\r
- */\r
-define("SAML_ASSERTION_ARTIFACT", '<samlp:AssertionArtifact>');\r
-\r
-/**\r
- * SAMLP close\r
- */\r
-define("SAML_ASSERTION_ARTIFACT_CLOSE", '</samlp:AssertionArtifact>');\r
-\r
-/**\r
- * SOAP body close\r
- */\r
-define("SAML_SOAP_BODY_CLOSE", '</SOAP-ENV:Body>');\r
-\r
-/**\r
- * SOAP envelope close\r
- */\r
-define("SAML_SOAP_ENV_CLOSE", '</SOAP-ENV:Envelope>');\r
-\r
-/**\r
- * SAML Attributes\r
- */\r
-define("SAML_ATTRIBUTES", 'SAMLATTRIBS');\r
-\r
-/** @} */\r
-/**\r
- * @addtogroup publicPGTStorage\r
- * @{\r
- */\r
-// ------------------------------------------------------------------------\r
-//  FILE PGT STORAGE\r
-// ------------------------------------------------------------------------\r
-/**\r
- * Default path used when storing PGT's to file\r
- */\r
-define("CAS_PGT_STORAGE_FILE_DEFAULT_PATH", '/tmp');\r
-/**\r
- * phpCAS::setPGTStorageFile()'s 2nd parameter to write plain text files\r
- */\r
-define("CAS_PGT_STORAGE_FILE_FORMAT_PLAIN", 'plain');\r
-/**\r
- * phpCAS::setPGTStorageFile()'s 2nd parameter to write xml files\r
- */\r
-define("CAS_PGT_STORAGE_FILE_FORMAT_XML", 'xml');\r
-/**\r
- * Default format used when storing PGT's to file\r
- */\r
-define("CAS_PGT_STORAGE_FILE_DEFAULT_FORMAT", CAS_PGT_STORAGE_FILE_FORMAT_PLAIN);\r
-/** @} */\r
-// ------------------------------------------------------------------------\r
-// SERVICE ACCESS ERRORS\r
-// ------------------------------------------------------------------------\r
-/**\r
- * @addtogroup publicServices\r
- * @{\r
- */\r
-\r
-/**\r
- * phpCAS::service() error code on success\r
- */\r
-define("PHPCAS_SERVICE_OK", 0);\r
-/**\r
- * phpCAS::service() error code when the PT could not retrieve because\r
- * the CAS server did not respond.\r
- */\r
-define("PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE", 1);\r
-/**\r
- * phpCAS::service() error code when the PT could not retrieve because\r
- * the response of the CAS server was ill-formed.\r
- */\r
-define("PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE", 2);\r
-/**\r
- * phpCAS::service() error code when the PT could not retrieve because\r
- * the CAS server did not want to.\r
- */\r
-define("PHPCAS_SERVICE_PT_FAILURE", 3);\r
-/**\r
- * phpCAS::service() error code when the service was not available.\r
- */\r
-define("PHPCAS_SERVICE_NOT AVAILABLE", 4);\r
-\r
-/** @} */\r
-// ------------------------------------------------------------------------\r
-//  LANGUAGES\r
-// ------------------------------------------------------------------------\r
-/**\r
- * @addtogroup publicLang\r
- * @{\r
- */\r
-\r
-define("PHPCAS_LANG_ENGLISH", 'english');\r
-define("PHPCAS_LANG_FRENCH", 'french');\r
-define("PHPCAS_LANG_GREEK", 'greek');\r
-define("PHPCAS_LANG_GERMAN", 'german');\r
-define("PHPCAS_LANG_JAPANESE", 'japanese');\r
-define("PHPCAS_LANG_SPANISH", 'spanish');\r
-define("PHPCAS_LANG_CATALAN", 'catalan');\r
-\r
-/** @} */\r
-\r
-/**\r
- * @addtogroup internalLang\r
- * @{\r
- */\r
-\r
-/**\r
- * phpCAS default language (when phpCAS::setLang() is not used)\r
- */\r
-define("PHPCAS_LANG_DEFAULT", PHPCAS_LANG_ENGLISH);\r
-\r
-/** @} */\r
-// ------------------------------------------------------------------------\r
-//  DEBUG\r
-// ------------------------------------------------------------------------\r
-/**\r
- * @addtogroup publicDebug\r
- * @{\r
- */\r
-\r
-/**\r
- * The default directory for the debug file under Unix.\r
- */\r
-define('DEFAULT_DEBUG_DIR', '/tmp/');\r
-\r
-/** @} */\r
-// ------------------------------------------------------------------------\r
-//  MISC\r
-// ------------------------------------------------------------------------\r
-/**\r
- * @addtogroup internalMisc\r
- * @{\r
- */\r
-\r
-/**\r
- * This global variable is used by the interface class phpCAS.\r
- *\r
- * @hideinitializer\r
- */\r
-$GLOBALS['PHPCAS_CLIENT'] = null;\r
-\r
-/**\r
- * This global variable is used to store where the initializer is called from \r
- * (to print a comprehensive error in case of multiple calls).\r
- *\r
- * @hideinitializer\r
- */\r
-$GLOBALS['PHPCAS_INIT_CALL'] = array (\r
-       'done' => FALSE,\r
-       'file' => '?',\r
-       'line' => -1,\r
-       'method' => '?'\r
-);\r
-\r
-/**\r
- * This global variable is used to store where the method checking\r
- * the authentication is called from (to print comprehensive errors)\r
- *\r
- * @hideinitializer\r
- */\r
-$GLOBALS['PHPCAS_AUTH_CHECK_CALL'] = array (\r
-       'done' => FALSE,\r
-       'file' => '?',\r
-       'line' => -1,\r
-       'method' => '?',\r
-       'result' => FALSE\r
-);\r
-\r
-/**\r
- * This global variable is used to store phpCAS debug mode.\r
- *\r
- * @hideinitializer\r
- */\r
-$GLOBALS['PHPCAS_DEBUG'] = array (\r
-       'filename' => FALSE,\r
-       'indent' => 0,\r
-       'unique_id' => ''\r
-);\r
-\r
-/** @} */\r
-\r
-// ########################################################################\r
-//  CLIENT CLASS\r
-// ########################################################################\r
-\r
-// include client class\r
-include_once (dirname(__FILE__) . '/CAS/client.php');\r
-\r
-// ########################################################################\r
-//  INTERFACE CLASS\r
-// ########################################################################\r
-\r
-/**\r
- * @class phpCAS\r
- * The phpCAS class is a simple container for the phpCAS library. It provides CAS\r
- * authentication for web applications written in PHP.\r
- *\r
- * @ingroup public\r
- * @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>\r
- *\r
- * \internal All its methods access the same object ($PHPCAS_CLIENT, declared \r
- * at the end of CAS/client.php).\r
- */\r
-\r
-class phpCAS {\r
-\r
-       // ########################################################################\r
-       //  INITIALIZATION\r
-       // ########################################################################\r
-\r
-       /**\r
-        * @addtogroup publicInit\r
-        * @{\r
-        */\r
-\r
-       /**\r
-        * phpCAS client initializer.\r
-        * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be\r
-        * called, only once, and before all other methods (except phpCAS::getVersion()\r
-        * and phpCAS::setDebug()).\r
-        *\r
-        * @param $server_version the version of the CAS server\r
-        * @param $server_hostname the hostname of the CAS server\r
-        * @param $server_port the port the CAS server is running on\r
-        * @param $server_uri the URI the CAS server is responding on\r
-        * @param $start_session Have phpCAS start PHP sessions (default true)\r
-        *\r
-        * @return a newly created CASClient object\r
-        */\r
-       public static function client($server_version, $server_hostname, $server_port, $server_uri, $start_session = true) {\r
-               global $PHPCAS_CLIENT, $PHPCAS_INIT_CALL;\r
-\r
-               phpCAS :: traceBegin();\r
-               if (is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error($PHPCAS_INIT_CALL['method'] . '() has already been called (at ' . $PHPCAS_INIT_CALL['file'] . ':' . $PHPCAS_INIT_CALL['line'] . ')');\r
-               }\r
-               if (gettype($server_version) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $server_version (should be `string\')');\r
-               }\r
-               if (gettype($server_hostname) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $server_hostname (should be `string\')');\r
-               }\r
-               if (gettype($server_port) != 'integer') {\r
-                       phpCAS :: error('type mismatched for parameter $server_port (should be `integer\')');\r
-               }\r
-               if (gettype($server_uri) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $server_uri (should be `string\')');\r
-               }\r
-\r
-               // store where the initializer is called from\r
-               $dbg = phpCAS :: backtrace();\r
-               $PHPCAS_INIT_CALL = array (\r
-                       'done' => TRUE,\r
-                       'file' => $dbg[0]['file'],\r
-                       'line' => $dbg[0]['line'],\r
-                       'method' => __CLASS__ . '::' . __FUNCTION__\r
-               );\r
-\r
-               // initialize the global object $PHPCAS_CLIENT\r
-               $PHPCAS_CLIENT = new CASClient($server_version, FALSE /*proxy*/\r
-               , $server_hostname, $server_port, $server_uri, $start_session);\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-       /**\r
-        * phpCAS proxy initializer.\r
-        * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be\r
-        * called, only once, and before all other methods (except phpCAS::getVersion()\r
-        * and phpCAS::setDebug()).\r
-        *\r
-        * @param $server_version the version of the CAS server\r
-        * @param $server_hostname the hostname of the CAS server\r
-        * @param $server_port the port the CAS server is running on\r
-        * @param $server_uri the URI the CAS server is responding on\r
-        * @param $start_session Have phpCAS start PHP sessions (default true)\r
-        *\r
-        * @return a newly created CASClient object\r
-        */\r
-       public static function proxy($server_version, $server_hostname, $server_port, $server_uri, $start_session = true) {\r
-               global $PHPCAS_CLIENT, $PHPCAS_INIT_CALL;\r
-\r
-               phpCAS :: traceBegin();\r
-               if (is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error($PHPCAS_INIT_CALL['method'] . '() has already been called (at ' . $PHPCAS_INIT_CALL['file'] . ':' . $PHPCAS_INIT_CALL['line'] . ')');\r
-               }\r
-               if (gettype($server_version) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $server_version (should be `string\')');\r
-               }\r
-               if (gettype($server_hostname) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $server_hostname (should be `string\')');\r
-               }\r
-               if (gettype($server_port) != 'integer') {\r
-                       phpCAS :: error('type mismatched for parameter $server_port (should be `integer\')');\r
-               }\r
-               if (gettype($server_uri) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $server_uri (should be `string\')');\r
-               }\r
-\r
-               // store where the initialzer is called from\r
-               $dbg = phpCAS :: backtrace();\r
-               $PHPCAS_INIT_CALL = array (\r
-                       'done' => TRUE,\r
-                       'file' => $dbg[0]['file'],\r
-                       'line' => $dbg[0]['line'],\r
-                       'method' => __CLASS__ . '::' . __FUNCTION__\r
-               );\r
-\r
-               // initialize the global object $PHPCAS_CLIENT\r
-               $PHPCAS_CLIENT = new CASClient($server_version, TRUE /*proxy*/\r
-               , $server_hostname, $server_port, $server_uri, $start_session);\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-       /** @} */\r
-       // ########################################################################\r
-       //  DEBUGGING\r
-       // ########################################################################\r
-\r
-       /**\r
-        * @addtogroup publicDebug\r
-        * @{\r
-        */\r
-\r
-       /**\r
-        * Set/unset debug mode\r
-        *\r
-        * @param $filename the name of the file used for logging, or FALSE to stop debugging.\r
-        */\r
-       public static function setDebug($filename = '') {\r
-               global $PHPCAS_DEBUG;\r
-\r
-               if ($filename != FALSE && gettype($filename) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $dbg (should be FALSE or the name of the log file)');\r
-               }\r
-\r
-               if (empty ($filename)) {\r
-                       if (preg_match('/^Win.*/', getenv('OS'))) {\r
-                               if (isset ($_ENV['TMP'])) {\r
-                                       $debugDir = $_ENV['TMP'] . '/';\r
-                               } else\r
-                                       if (isset ($_ENV['TEMP'])) {\r
-                                               $debugDir = $_ENV['TEMP'] . '/';\r
-                                       } else {\r
-                                               $debugDir = '';\r
-                                       }\r
-                       } else {\r
-                               $debugDir = DEFAULT_DEBUG_DIR;\r
-                       }\r
-                       $filename = $debugDir . 'phpCAS.log';\r
-               }\r
-\r
-               if (empty ($PHPCAS_DEBUG['unique_id'])) {\r
-                       $PHPCAS_DEBUG['unique_id'] = substr(strtoupper(md5(uniqid(''))), 0, 4);\r
-               }\r
-\r
-               $PHPCAS_DEBUG['filename'] = $filename;\r
-\r
-               phpCAS :: trace('START phpCAS-' . PHPCAS_VERSION . ' ******************');\r
-       }\r
-\r
-       /** @} */\r
-       /**\r
-        * @addtogroup internalDebug\r
-        * @{\r
-        */\r
-\r
-       /**\r
-        * This method is a wrapper for debug_backtrace() that is not available \r
-        * in all PHP versions (>= 4.3.0 only)\r
-        */\r
-       public static function backtrace() {\r
-               if (function_exists('debug_backtrace')) {\r
-                       return debug_backtrace();\r
-               } else {\r
-                       // poor man's hack ... but it does work ...\r
-                       return array ();\r
-               }\r
-       }\r
-\r
-       /**\r
-        * Logs a string in debug mode.\r
-        *\r
-        * @param $str the string to write\r
-        *\r
-        * @private\r
-        */\r
-       public static function log($str) {\r
-               $indent_str = ".";\r
-               global $PHPCAS_DEBUG;\r
-\r
-               if ($PHPCAS_DEBUG['filename']) {\r
-                       for ($i = 0; $i < $PHPCAS_DEBUG['indent']; $i++) {\r
-                               $indent_str .= '|    ';\r
-                       }\r
-                       error_log($PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str . $str . "\n", 3, $PHPCAS_DEBUG['filename']);\r
-               }\r
-\r
-       }\r
-\r
-       /**\r
-        * This method is used by interface methods to print an error and where the function\r
-        * was originally called from.\r
-        *\r
-        * @param $msg the message to print\r
-        *\r
-        * @private\r
-        */\r
-       public static function error($msg) {\r
-               $dbg = phpCAS :: backtrace();\r
-               $function = '?';\r
-               $file = '?';\r
-               $line = '?';\r
-               if (is_array($dbg)) {\r
-                       for ($i = 1; $i < sizeof($dbg); $i++) {\r
-                               if (is_array($dbg[$i])) {\r
-                                       if ($dbg[$i]['class'] == __CLASS__) {\r
-                                               $function = $dbg[$i]['function'];\r
-                                               $file = $dbg[$i]['file'];\r
-                                               $line = $dbg[$i]['line'];\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-               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";\r
-               phpCAS :: trace($msg);\r
-               phpCAS :: traceExit();\r
-               exit ();\r
-       }\r
-\r
-       /**\r
-        * This method is used to log something in debug mode.\r
-        */\r
-       public static function trace($str) {\r
-               $dbg = phpCAS :: backtrace();\r
-               phpCAS :: log($str . ' [' . basename($dbg[1]['file']) . ':' . $dbg[1]['line'] . ']');\r
-       }\r
-\r
-       /**\r
-        * This method is used to indicate the start of the execution of a function in debug mode.\r
-        */\r
-       public static function traceBegin() {\r
-               global $PHPCAS_DEBUG;\r
-\r
-               $dbg = phpCAS :: backtrace();\r
-               $str = '=> ';\r
-               if (!empty ($dbg[2]['class'])) {\r
-                       $str .= $dbg[2]['class'] . '::';\r
-               }\r
-               $str .= $dbg[2]['function'] . '(';\r
-               if (is_array($dbg[2]['args'])) {\r
-                       foreach ($dbg[2]['args'] as $index => $arg) {\r
-                               if ($index != 0) {\r
-                                       $str .= ', ';\r
-                               }\r
-                               $str .= str_replace("\n", "", var_export($arg, TRUE));\r
-                       }\r
-               }\r
-               $str .= ') [' . basename($dbg[2]['file']) . ':' . $dbg[2]['line'] . ']';\r
-               phpCAS :: log($str);\r
-               $PHPCAS_DEBUG['indent']++;\r
-       }\r
-\r
-       /**\r
-        * This method is used to indicate the end of the execution of a function in debug mode.\r
-        *\r
-        * @param $res the result of the function\r
-        */\r
-       public static function traceEnd($res = '') {\r
-               global $PHPCAS_DEBUG;\r
-\r
-               $PHPCAS_DEBUG['indent']--;\r
-               $dbg = phpCAS :: backtrace();\r
-               $str = '';\r
-               $str .= '<= ' . str_replace("\n", "", var_export($res, TRUE));\r
-               phpCAS :: log($str);\r
-       }\r
-\r
-       /**\r
-        * This method is used to indicate the end of the execution of the program\r
-        */\r
-       public static function traceExit() {\r
-               global $PHPCAS_DEBUG;\r
-\r
-               phpCAS :: log('exit()');\r
-               while ($PHPCAS_DEBUG['indent'] > 0) {\r
-                       phpCAS :: log('-');\r
-                       $PHPCAS_DEBUG['indent']--;\r
-               }\r
-       }\r
-\r
-       /** @} */\r
-       // ########################################################################\r
-       //  INTERNATIONALIZATION\r
-       // ########################################################################\r
-       /**\r
-        * @addtogroup publicLang\r
-        * @{\r
-        */\r
-\r
-       /**\r
-        * This method is used to set the language used by phpCAS. \r
-        * @note Can be called only once.\r
-        *\r
-        * @param $lang a string representing the language.\r
-        *\r
-        * @sa PHPCAS_LANG_FRENCH, PHPCAS_LANG_ENGLISH\r
-        */\r
-       public static function setLang($lang) {\r
-               global $PHPCAS_CLIENT;\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (gettype($lang) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $lang (should be `string\')');\r
-               }\r
-               $PHPCAS_CLIENT->setLang($lang);\r
-       }\r
-\r
-       /** @} */\r
-       // ########################################################################\r
-       //  VERSION\r
-       // ########################################################################\r
-       /**\r
-        * @addtogroup public\r
-        * @{\r
-        */\r
-\r
-       /**\r
-        * This method returns the phpCAS version.\r
-        *\r
-        * @return the phpCAS version.\r
-        */\r
-       public static function getVersion() {\r
-               return PHPCAS_VERSION;\r
-       }\r
-\r
-       /** @} */\r
-       // ########################################################################\r
-       //  HTML OUTPUT\r
-       // ########################################################################\r
-       /**\r
-        * @addtogroup publicOutput\r
-        * @{\r
-        */\r
-\r
-       /**\r
-        * This method sets the HTML header used for all outputs.\r
-        *\r
-        * @param $header the HTML header.\r
-        */\r
-       public static function setHTMLHeader($header) {\r
-               global $PHPCAS_CLIENT;\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (gettype($header) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $header (should be `string\')');\r
-               }\r
-               $PHPCAS_CLIENT->setHTMLHeader($header);\r
-       }\r
-\r
-       /**\r
-        * This method sets the HTML footer used for all outputs.\r
-        *\r
-        * @param $footer the HTML footer.\r
-        */\r
-       public static function setHTMLFooter($footer) {\r
-               global $PHPCAS_CLIENT;\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (gettype($footer) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $footer (should be `string\')');\r
-               }\r
-               $PHPCAS_CLIENT->setHTMLFooter($footer);\r
-       }\r
-\r
-       /** @} */\r
-       // ########################################################################\r
-       //  PGT STORAGE\r
-       // ########################################################################\r
-       /**\r
-        * @addtogroup publicPGTStorage\r
-        * @{\r
-        */\r
-\r
-       /**\r
-        * This method is used to tell phpCAS to store the response of the\r
-        * CAS server to PGT requests onto the filesystem. \r
-        *\r
-        * @param $format the format used to store the PGT's (`plain' and `xml' allowed)\r
-        * @param $path the path where the PGT's should be stored\r
-        */\r
-       public static function setPGTStorageFile($format = '', $path = '') {\r
-               global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
-\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (!$PHPCAS_CLIENT->isProxy()) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
-               }\r
-               if ($PHPCAS_AUTH_CHECK_CALL['done']) {\r
-                       phpCAS :: error('this method should only be called before ' . $PHPCAS_AUTH_CHECK_CALL['method'] . '() (called at ' . $PHPCAS_AUTH_CHECK_CALL['file'] . ':' . $PHPCAS_AUTH_CHECK_CALL['line'] . ')');\r
-               }\r
-               if (gettype($format) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $format (should be `string\')');\r
-               }\r
-               if (gettype($path) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $format (should be `string\')');\r
-               }\r
-               $PHPCAS_CLIENT->setPGTStorageFile($format, $path);\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-\r
-       /** @} */\r
-       // ########################################################################\r
-       // ACCESS TO EXTERNAL SERVICES\r
-       // ########################################################################\r
-       /**\r
-        * @addtogroup publicServices\r
-        * @{\r
-        */\r
-\r
-       /**\r
-        * This method is used to access an HTTP[S] service.\r
-        * \r
-        * @param $url the service to access.\r
-        * @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on\r
-        * success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE,\r
-        * PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_NOT AVAILABLE.\r
-        * @param $output the output of the service (also used to give an error\r
-        * message on failure).\r
-        *\r
-        * @return TRUE on success, FALSE otherwise (in this later case, $err_code\r
-        * gives the reason why it failed and $output contains an error message).\r
-        */\r
-       public static function serviceWeb($url, & $err_code, & $output) {\r
-               global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
-\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (!$PHPCAS_CLIENT->isProxy()) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (!$PHPCAS_AUTH_CHECK_CALL['done']) {\r
-                       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()');\r
-               }\r
-               if (!$PHPCAS_AUTH_CHECK_CALL['result']) {\r
-                       phpCAS :: error('authentication was checked (by ' . $PHPCAS_AUTH_CHECK_CALL['method'] . '() at ' . $PHPCAS_AUTH_CHECK_CALL['file'] . ':' . $PHPCAS_AUTH_CHECK_CALL['line'] . ') but the method returned FALSE');\r
-               }\r
-               if (gettype($url) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $url (should be `string\')');\r
-               }\r
-\r
-               $res = $PHPCAS_CLIENT->serviceWeb($url, $err_code, $output);\r
-\r
-               phpCAS :: traceEnd($res);\r
-               return $res;\r
-       }\r
-\r
-       /**\r
-        * This method is used to access an IMAP/POP3/NNTP service.\r
-        * \r
-        * @param $url a string giving the URL of the service, including the mailing box\r
-        * for IMAP URLs, as accepted by imap_open().\r
-        * @param $service a string giving for CAS retrieve Proxy ticket\r
-        * @param $flags options given to imap_open().\r
-        * @param $err_code an error code Possible values are PHPCAS_SERVICE_OK (on\r
-        * success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE,\r
-        * PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_NOT AVAILABLE.\r
-        * @param $err_msg an error message on failure\r
-        * @param $pt the Proxy Ticket (PT) retrieved from the CAS server to access the URL\r
-        * on success, FALSE on error).\r
-        *\r
-        * @return an IMAP stream on success, FALSE otherwise (in this later case, $err_code\r
-        * gives the reason why it failed and $err_msg contains an error message).\r
-        */\r
-       public static function serviceMail($url, $service, $flags, & $err_code, & $err_msg, & $pt) {\r
-               global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
-\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (!$PHPCAS_CLIENT->isProxy()) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (!$PHPCAS_AUTH_CHECK_CALL['done']) {\r
-                       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()');\r
-               }\r
-               if (!$PHPCAS_AUTH_CHECK_CALL['result']) {\r
-                       phpCAS :: error('authentication was checked (by ' . $PHPCAS_AUTH_CHECK_CALL['method'] . '() at ' . $PHPCAS_AUTH_CHECK_CALL['file'] . ':' . $PHPCAS_AUTH_CHECK_CALL['line'] . ') but the method returned FALSE');\r
-               }\r
-               if (gettype($url) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $url (should be `string\')');\r
-               }\r
-\r
-               if (gettype($flags) != 'integer') {\r
-                       phpCAS :: error('type mismatched for parameter $flags (should be `integer\')');\r
-               }\r
-\r
-               $res = $PHPCAS_CLIENT->serviceMail($url, $service, $flags, $err_code, $err_msg, $pt);\r
-\r
-               phpCAS :: traceEnd($res);\r
-               return $res;\r
-       }\r
-\r
-       /** @} */\r
-       // ########################################################################\r
-       //  AUTHENTICATION\r
-       // ########################################################################\r
-       /**\r
-        * @addtogroup publicAuth\r
-        * @{\r
-        */\r
-\r
-       /**\r
-        * Set the times authentication will be cached before really accessing the CAS server in gateway mode: \r
-        * - -1: check only once, and then never again (until you pree login)\r
-        * - 0: always check\r
-        * - n: check every "n" time\r
-        *\r
-        * @param $n an integer.\r
-        */\r
-       public static function setCacheTimesForAuthRecheck($n) {\r
-               global $PHPCAS_CLIENT;\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (gettype($n) != 'integer') {\r
-                       phpCAS :: error('type mismatched for parameter $header (should be `string\')');\r
-               }\r
-               $PHPCAS_CLIENT->setCacheTimesForAuthRecheck($n);\r
-       }\r
-\r
-       /**\r
-        * This method is called to check if the user is authenticated (use the gateway feature).\r
-        * @return TRUE when the user is authenticated; otherwise FALSE.\r
-        */\r
-       public static function checkAuthentication() {\r
-               global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
-\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
-               }\r
-\r
-               $auth = $PHPCAS_CLIENT->checkAuthentication();\r
-\r
-               // store where the authentication has been checked and the result\r
-               $dbg = phpCAS :: backtrace();\r
-               $PHPCAS_AUTH_CHECK_CALL = array (\r
-                       'done' => TRUE,\r
-                       'file' => $dbg[0]['file'],\r
-                       'line' => $dbg[0]['line'],\r
-                       'method' => __CLASS__ . '::' . __FUNCTION__,\r
-                       'result' => $auth\r
-               );\r
-               phpCAS :: traceEnd($auth);\r
-               return $auth;\r
-       }\r
-\r
-       /**\r
-        * This method is called to force authentication if the user was not already \r
-        * authenticated. If the user is not authenticated, halt by redirecting to \r
-        * the CAS server.\r
-        */\r
-       public static function forceAuthentication() {\r
-               global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
-\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
-               }\r
-\r
-               $auth = $PHPCAS_CLIENT->forceAuthentication();\r
-\r
-               // store where the authentication has been checked and the result\r
-               $dbg = phpCAS :: backtrace();\r
-               $PHPCAS_AUTH_CHECK_CALL = array (\r
-                       'done' => TRUE,\r
-                       'file' => $dbg[0]['file'],\r
-                       'line' => $dbg[0]['line'],\r
-                       'method' => __CLASS__ . '::' . __FUNCTION__,\r
-                       'result' => $auth\r
-               );\r
-\r
-               if (!$auth) {\r
-                       phpCAS :: trace('user is not authenticated, redirecting to the CAS server');\r
-                       $PHPCAS_CLIENT->forceAuthentication();\r
-               } else {\r
-                       phpCAS :: trace('no need to authenticate (user `' . phpCAS :: getUser() . '\' is already authenticated)');\r
-               }\r
-\r
-               phpCAS :: traceEnd();\r
-               return $auth;\r
-       }\r
-\r
-       /**\r
-        * This method is called to renew the authentication.\r
-        **/\r
-       public static function renewAuthentication() {\r
-               global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
-\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should not be called before' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
-               }\r
-\r
-               // store where the authentication has been checked and the result\r
-               $dbg = phpCAS :: backtrace();\r
-               $PHPCAS_AUTH_CHECK_CALL = array (\r
-                       'done' => TRUE,\r
-                       'file' => $dbg[0]['file'],\r
-                       'line' => $dbg[0]['line'],\r
-                       'method' => __CLASS__ . '::' . __FUNCTION__,\r
-                       'result' => $auth\r
-               );\r
-\r
-               $PHPCAS_CLIENT->renewAuthentication();\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-       /**\r
-        * This method has been left from version 0.4.1 for compatibility reasons.\r
-        */\r
-       public static function authenticate() {\r
-               phpCAS :: error('this method is deprecated. You should use ' . __CLASS__ . '::forceAuthentication() instead');\r
-       }\r
-\r
-       /**\r
-        * This method is called to check if the user is authenticated (previously or by\r
-        * tickets given in the URL).\r
-        *\r
-        * @return TRUE when the user is authenticated.\r
-        */\r
-       public static function isAuthenticated() {\r
-               global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
-\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
-               }\r
-\r
-               // call the isAuthenticated method of the global $PHPCAS_CLIENT object\r
-               $auth = $PHPCAS_CLIENT->isAuthenticated();\r
-\r
-               // store where the authentication has been checked and the result\r
-               $dbg = phpCAS :: backtrace();\r
-               $PHPCAS_AUTH_CHECK_CALL = array (\r
-                       'done' => TRUE,\r
-                       'file' => $dbg[0]['file'],\r
-                       'line' => $dbg[0]['line'],\r
-                       'method' => __CLASS__ . '::' . __FUNCTION__,\r
-                       'result' => $auth\r
-               );\r
-               phpCAS :: traceEnd($auth);\r
-               return $auth;\r
-       }\r
-\r
-       /**\r
-        * Checks whether authenticated based on $_SESSION. Useful to avoid\r
-        * server calls.\r
-        * @return true if authenticated, false otherwise.\r
-        * @since 0.4.22 by Brendan Arnold\r
-        */\r
-       public static function isSessionAuthenticated() {\r
-               global $PHPCAS_CLIENT;\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
-               }\r
-               return ($PHPCAS_CLIENT->isSessionAuthenticated());\r
-       }\r
-\r
-       /**\r
-        * This method returns the CAS user's login name.\r
-        * @warning should not be called only after phpCAS::forceAuthentication()\r
-        * or phpCAS::checkAuthentication().\r
-        *\r
-        * @return the login name of the authenticated user\r
-        */\r
-       public static function getUser() {\r
-               global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (!$PHPCAS_AUTH_CHECK_CALL['done']) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::forceAuthentication() or ' . __CLASS__ . '::isAuthenticated()');\r
-               }\r
-               if (!$PHPCAS_AUTH_CHECK_CALL['result']) {\r
-                       phpCAS :: error('authentication was checked (by ' . $PHPCAS_AUTH_CHECK_CALL['method'] . '() at ' . $PHPCAS_AUTH_CHECK_CALL['file'] . ':' . $PHPCAS_AUTH_CHECK_CALL['line'] . ') but the method returned FALSE');\r
-               }\r
-               return $PHPCAS_CLIENT->getUser();\r
-       }\r
-\r
-       /**\r
-        * This method returns the CAS user's login name.\r
-        * @warning should not be called only after phpCAS::forceAuthentication()\r
-        * or phpCAS::checkAuthentication().\r
-        *\r
-        * @return the login name of the authenticated user\r
-        */\r
-       public static function getAttributes() {\r
-               global $PHPCAS_CLIENT, $PHPCAS_AUTH_CHECK_CALL;\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (!$PHPCAS_AUTH_CHECK_CALL['done']) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::forceAuthentication() or ' . __CLASS__ . '::isAuthenticated()');\r
-               }\r
-               if (!$PHPCAS_AUTH_CHECK_CALL['result']) {\r
-                       phpCAS :: error('authentication was checked (by ' . $PHPCAS_AUTH_CHECK_CALL['method'] . '() at ' . $PHPCAS_AUTH_CHECK_CALL['file'] . ':' . $PHPCAS_AUTH_CHECK_CALL['line'] . ') but the method returned FALSE');\r
-               }\r
-               return $PHPCAS_CLIENT->getAttributes();\r
-       }\r
-       /**\r
-        * Handle logout requests.\r
-        */\r
-       public static function handleLogoutRequests($check_client = true, $allowed_clients = false) {\r
-               global $PHPCAS_CLIENT;\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
-               }\r
-               return ($PHPCAS_CLIENT->handleLogoutRequests($check_client, $allowed_clients));\r
-       }\r
-\r
-       /**\r
-        * This method returns the URL to be used to login.\r
-        * or phpCAS::isAuthenticated().\r
-        *\r
-        * @return the login name of the authenticated user\r
-        */\r
-       public static function getServerLoginURL() {\r
-               global $PHPCAS_CLIENT;\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
-               }\r
-               return $PHPCAS_CLIENT->getServerLoginURL();\r
-       }\r
-\r
-       /**\r
-        * Set the login URL of the CAS server.\r
-        * @param $url the login URL\r
-        * @since 0.4.21 by Wyman Chan\r
-        */\r
-       public static function setServerLoginURL($url = '') {\r
-               global $PHPCAS_CLIENT;\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after\r
-                                                       ' . __CLASS__ . '::client()');\r
-               }\r
-               if (gettype($url) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $url (should be\r
-                                               `string\')');\r
-               }\r
-               $PHPCAS_CLIENT->setServerLoginURL($url);\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-       /**\r
-        * Set the serviceValidate URL of the CAS server.\r
-        * Used only in CAS 1.0 validations\r
-        * @param $url the serviceValidate URL\r
-        * @since 1.1.0 by Joachim Fritschi\r
-        */\r
-       public static function setServerServiceValidateURL($url = '') {\r
-               global $PHPCAS_CLIENT;\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after\r
-                                                       ' . __CLASS__ . '::client()');\r
-               }\r
-               if (gettype($url) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $url (should be\r
-                                               `string\')');\r
-               }\r
-               $PHPCAS_CLIENT->setServerServiceValidateURL($url);\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-       /**\r
-        * Set the proxyValidate URL of the CAS server.\r
-        * Used for all CAS 2.0 validations\r
-        * @param $url the proxyValidate URL\r
-        * @since 1.1.0 by Joachim Fritschi\r
-        */\r
-       public static function setServerProxyValidateURL($url = '') {\r
-               global $PHPCAS_CLIENT;\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after\r
-                                                       ' . __CLASS__ . '::client()');\r
-               }\r
-               if (gettype($url) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $url (should be\r
-                                               `string\')');\r
-               }\r
-               $PHPCAS_CLIENT->setServerProxyValidateURL($url);\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-       /**\r
-        * Set the samlValidate URL of the CAS server.\r
-        * @param $url the samlValidate URL\r
-        * @since 1.1.0 by Joachim Fritschi\r
-        */\r
-       public static function setServerSamlValidateURL($url = '') {\r
-               global $PHPCAS_CLIENT;\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after\r
-                                                       ' . __CLASS__ . '::client()');\r
-               }\r
-               if (gettype($url) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $url (should be\r
-                                               `string\')');\r
-               }\r
-               $PHPCAS_CLIENT->setServerSamlValidateURL($url);\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-       /**\r
-        * This method returns the URL to be used to login.\r
-        * or phpCAS::isAuthenticated().\r
-        *\r
-        * @return the login name of the authenticated user\r
-        */\r
-       public static function getServerLogoutURL() {\r
-               global $PHPCAS_CLIENT;\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');\r
-               }\r
-               return $PHPCAS_CLIENT->getServerLogoutURL();\r
-       }\r
-\r
-       /**\r
-        * Set the logout URL of the CAS server.\r
-        * @param $url the logout URL\r
-        * @since 0.4.21 by Wyman Chan\r
-        */\r
-       public static function setServerLogoutURL($url = '') {\r
-               global $PHPCAS_CLIENT;\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after\r
-                                                       ' . __CLASS__ . '::client()');\r
-               }\r
-               if (gettype($url) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $url (should be\r
-                                               `string\')');\r
-               }\r
-               $PHPCAS_CLIENT->setServerLogoutURL($url);\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-       /**\r
-        * This method is used to logout from CAS.\r
-        * @params $params an array that contains the optional url and service parameters that will be passed to the CAS server\r
-        * @public\r
-        */\r
-       public static function logout($params = "") {\r
-               global $PHPCAS_CLIENT;\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');\r
-               }\r
-               $parsedParams = array ();\r
-               if ($params != "") {\r
-                       if (is_string($params)) {\r
-                               phpCAS :: error('method `phpCAS::logout($url)\' is now deprecated, use `phpCAS::logoutWithUrl($url)\' instead');\r
-                       }\r
-                       if (!is_array($params)) {\r
-                               phpCAS :: error('type mismatched for parameter $params (should be `array\')');\r
-                       }\r
-                       foreach ($params as $key => $value) {\r
-                               if ($key != "service" && $key != "url") {\r
-                                       phpCAS :: error('only `url\' and `service\' parameters are allowed for method `phpCAS::logout($params)\'');\r
-                               }\r
-                               $parsedParams[$key] = $value;\r
-                       }\r
-               }\r
-               $PHPCAS_CLIENT->logout($parsedParams);\r
-               // never reached\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-       /**\r
-        * This method is used to logout from CAS. Halts by redirecting to the CAS server.\r
-        * @param $service a URL that will be transmitted to the CAS server\r
-        */\r
-       public static function logoutWithRedirectService($service) {\r
-               global $PHPCAS_CLIENT;\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (!is_string($service)) {\r
-                       phpCAS :: error('type mismatched for parameter $service (should be `string\')');\r
-               }\r
-               $PHPCAS_CLIENT->logout(array (\r
-                       "service" => $service\r
-               ));\r
-               // never reached\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-       /**\r
-        * This method is used to logout from CAS. Halts by redirecting to the CAS server.\r
-        * @param $url a URL that will be transmitted to the CAS server\r
-        */\r
-       public static function logoutWithUrl($url) {\r
-               global $PHPCAS_CLIENT;\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (!is_string($url)) {\r
-                       phpCAS :: error('type mismatched for parameter $url (should be `string\')');\r
-               }\r
-               $PHPCAS_CLIENT->logout(array (\r
-                       "url" => $url\r
-               ));\r
-               // never reached\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-       /**\r
-        * This method is used to logout from CAS. Halts by redirecting to the CAS server.\r
-        * @param $service a URL that will be transmitted to the CAS server\r
-        * @param $url a URL that will be transmitted to the CAS server\r
-        */\r
-       public static function logoutWithRedirectServiceAndUrl($service, $url) {\r
-               global $PHPCAS_CLIENT;\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (!is_string($service)) {\r
-                       phpCAS :: error('type mismatched for parameter $service (should be `string\')');\r
-               }\r
-               if (!is_string($url)) {\r
-                       phpCAS :: error('type mismatched for parameter $url (should be `string\')');\r
-               }\r
-               $PHPCAS_CLIENT->logout(array (\r
-                       "service" => $service,\r
-                       "url" => $url\r
-               ));\r
-               // never reached\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-       /**\r
-        * Set the fixed URL that will be used by the CAS server to transmit the PGT.\r
-        * When this method is not called, a phpCAS script uses its own URL for the callback.\r
-        *\r
-        * @param $url the URL\r
-        */\r
-       public static function setFixedCallbackURL($url = '') {\r
-               global $PHPCAS_CLIENT;\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (!$PHPCAS_CLIENT->isProxy()) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (gettype($url) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $url (should be `string\')');\r
-               }\r
-               $PHPCAS_CLIENT->setCallbackURL($url);\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-       /**\r
-        * Set the fixed URL that will be set as the CAS service parameter. When this\r
-        * method is not called, a phpCAS script uses its own URL.\r
-        *\r
-        * @param $url the URL\r
-        */\r
-       public static function setFixedServiceURL($url) {\r
-               global $PHPCAS_CLIENT;\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (gettype($url) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $url (should be `string\')');\r
-               }\r
-               $PHPCAS_CLIENT->setURL($url);\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-       /**\r
-        * Get the URL that is set as the CAS service parameter.\r
-        */\r
-       public static function getServiceURL() {\r
-               global $PHPCAS_CLIENT;\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
-               }\r
-               return ($PHPCAS_CLIENT->getURL());\r
-       }\r
-\r
-       /**\r
-        * Retrieve a Proxy Ticket from the CAS server.\r
-        */\r
-       public static function retrievePT($target_service, & $err_code, & $err_msg) {\r
-               global $PHPCAS_CLIENT;\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (gettype($target_service) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $target_service(should be `string\')');\r
-               }\r
-               return ($PHPCAS_CLIENT->retrievePT($target_service, $err_code, $err_msg));\r
-       }\r
-\r
-       /**\r
-        * Set the certificate of the CAS server.\r
-        *\r
-        * @param $cert the PEM certificate\r
-        */\r
-       public static function setCasServerCert($cert) {\r
-               global $PHPCAS_CLIENT;\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (gettype($cert) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $cert (should be `string\')');\r
-               }\r
-               $PHPCAS_CLIENT->setCasServerCert($cert);\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-       /**\r
-        * Set the certificate of the CAS server CA.\r
-        *\r
-        * @param $cert the CA certificate\r
-        */\r
-       public static function setCasServerCACert($cert) {\r
-               global $PHPCAS_CLIENT;\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');\r
-               }\r
-               if (gettype($cert) != 'string') {\r
-                       phpCAS :: error('type mismatched for parameter $cert (should be `string\')');\r
-               }\r
-               $PHPCAS_CLIENT->setCasServerCACert($cert);\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-       /**\r
-        * Set no SSL validation for the CAS server.\r
-        */\r
-       public static function setNoCasServerValidation() {\r
-               global $PHPCAS_CLIENT;\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');\r
-               }\r
-               $PHPCAS_CLIENT->setNoCasServerValidation();\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-       /** @} */\r
-\r
-       /**\r
-        * Change CURL options.\r
-        * CURL is used to connect through HTTPS to CAS server\r
-        * @param $key the option key\r
-        * @param $value the value to set\r
-        */\r
-       public static function setExtraCurlOption($key, $value) {\r
-               global $PHPCAS_CLIENT;\r
-               phpCAS :: traceBegin();\r
-               if (!is_object($PHPCAS_CLIENT)) {\r
-                       phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');\r
-               }\r
-               $PHPCAS_CLIENT->setExtraCurlOption($key, $value);\r
-               phpCAS :: traceEnd();\r
-       }\r
-\r
-}\r
-\r
-// ########################################################################\r
-// DOCUMENTATION\r
-// ########################################################################\r
-\r
-// ########################################################################\r
-//  MAIN PAGE\r
-\r
-/**\r
- * @mainpage\r
- *\r
- * The following pages only show the source documentation.\r
- *\r
- */\r
-\r
-// ########################################################################\r
-//  MODULES DEFINITION\r
-\r
-/** @defgroup public User interface */\r
-\r
-/** @defgroup publicInit Initialization\r
- *  @ingroup public */\r
-\r
-/** @defgroup publicAuth Authentication\r
- *  @ingroup public */\r
-\r
-/** @defgroup publicServices Access to external services\r
- *  @ingroup public */\r
-\r
-/** @defgroup publicConfig Configuration\r
- *  @ingroup public */\r
-\r
-/** @defgroup publicLang Internationalization\r
- *  @ingroup publicConfig */\r
-\r
-/** @defgroup publicOutput HTML output\r
- *  @ingroup publicConfig */\r
-\r
-/** @defgroup publicPGTStorage PGT storage\r
- *  @ingroup publicConfig */\r
-\r
-/** @defgroup publicDebug Debugging\r
- *  @ingroup public */\r
-\r
-/** @defgroup internal Implementation */\r
-\r
-/** @defgroup internalAuthentication Authentication\r
- *  @ingroup internal */\r
-\r
-/** @defgroup internalBasic CAS Basic client features (CAS 1.0, Service Tickets)\r
- *  @ingroup internal */\r
-\r
-/** @defgroup internalProxy CAS Proxy features (CAS 2.0, Proxy Granting Tickets)\r
- *  @ingroup internal */\r
-\r
-/** @defgroup internalPGTStorage PGT storage\r
- *  @ingroup internalProxy */\r
-\r
-/** @defgroup internalPGTStorageFile PGT storage on the filesystem\r
- *  @ingroup internalPGTStorage */\r
-\r
-/** @defgroup internalCallback Callback from the CAS server\r
- *  @ingroup internalProxy */\r
-\r
-/** @defgroup internalProxied CAS proxied client features (CAS 2.0, Proxy Tickets)\r
- *  @ingroup internal */\r
-\r
-/** @defgroup internalConfig Configuration\r
- *  @ingroup internal */\r
-\r
-/** @defgroup internalOutput HTML output\r
- *  @ingroup internalConfig */\r
-\r
-/** @defgroup internalLang Internationalization\r
- *  @ingroup internalConfig\r
- *\r
- * To add a new language:\r
- * - 1. define a new constant PHPCAS_LANG_XXXXXX in CAS/CAS.php\r
- * - 2. copy any file from CAS/languages to CAS/languages/XXXXXX.php\r
- * - 3. Make the translations\r
- */\r
-\r
-/** @defgroup internalDebug Debugging\r
- *  @ingroup internal */\r
-\r
-/** @defgroup internalMisc Miscellaneous\r
- *  @ingroup internal */\r
-\r
-// ########################################################################\r
-//  EXAMPLES\r
-\r
-/**\r
- * @example example_simple.php\r
- */\r
-/**\r
- * @example example_proxy.php\r
- */\r
-/**\r
- * @example example_proxy2.php\r
- */\r
-/**\r
- * @example example_lang.php\r
- */\r
-/**\r
- * @example example_html.php\r
- */\r
-/**\r
- * @example example_file.php\r
- */\r
-/**\r
- * @example example_db.php\r
- */\r
-/**\r
- * @example example_service.php\r
- */\r
-/**\r
- * @example example_session_proxy.php\r
- */\r
-/**\r
- * @example example_session_service.php\r
- */\r
-/**\r
- * @example example_gateway.php\r
- */\r
-/**\r
- * @example example_custom_urls.php\r
- */\r
-?>\r
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ *
+ * Interface class of the phpCAS library
+ * PHP Version 5
+ *
+ * @file     CAS/CAS.php
+ * @category Authentication
+ * @package  PhpCAS
+ * @author   Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @author   Olivier Berger <olivier.berger@it-sudparis.eu>
+ * @author   Brett Bieber <brett.bieber@gmail.com>
+ * @author   Joachim Fritschi <jfritschi@freenet.de>
+ * @author   Adam Franco <afranco@middlebury.edu>
+ * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License 2.0
+ * @link     https://wiki.jasig.org/display/CASC/phpCAS
+ * @ingroup public
+ */
+
+
+//
+// hack by Vangelis Haniotakis to handle the absence of $_SERVER['REQUEST_URI']
+// in IIS
+//
+if (php_sapi_name() != 'cli') {
+    if (!isset($_SERVER['REQUEST_URI'])) {
+        $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING'];
+    }
+}
+
+// Add a E_USER_DEPRECATED for php versions <= 5.2
+if (!defined('E_USER_DEPRECATED')) {
+    define('E_USER_DEPRECATED', E_USER_NOTICE);
+}
+
+
+// ########################################################################
+//  CONSTANTS
+// ########################################################################
+
+// ------------------------------------------------------------------------
+//  CAS VERSIONS
+// ------------------------------------------------------------------------
+
+/**
+ * phpCAS version. accessible for the user by phpCAS::getVersion().
+ */
+define('PHPCAS_VERSION', '1.3.2');
+
+/**
+ * @addtogroup public
+ * @{
+ */
+
+/**
+ * CAS version 1.0
+ */
+define("CAS_VERSION_1_0", '1.0');
+/*!
+ * CAS version 2.0
+*/
+define("CAS_VERSION_2_0", '2.0');
+
+// ------------------------------------------------------------------------
+//  SAML defines
+// ------------------------------------------------------------------------
+
+/**
+ * SAML protocol
+ */
+define("SAML_VERSION_1_1", 'S1');
+
+/**
+ * XML header for SAML POST
+ */
+define("SAML_XML_HEADER", '<?xml version="1.0" encoding="UTF-8"?>');
+
+/**
+ * SOAP envelope for SAML POST
+ */
+define("SAML_SOAP_ENV", '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/>');
+
+/**
+ * SOAP body for SAML POST
+ */
+define("SAML_SOAP_BODY", '<SOAP-ENV:Body>');
+
+/**
+ * SAMLP request
+ */
+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">');
+define("SAMLP_REQUEST_CLOSE", '</samlp:Request>');
+
+/**
+ * SAMLP artifact tag (for the ticket)
+ */
+define("SAML_ASSERTION_ARTIFACT", '<samlp:AssertionArtifact>');
+
+/**
+ * SAMLP close
+ */
+define("SAML_ASSERTION_ARTIFACT_CLOSE", '</samlp:AssertionArtifact>');
+
+/**
+ * SOAP body close
+ */
+define("SAML_SOAP_BODY_CLOSE", '</SOAP-ENV:Body>');
+
+/**
+ * SOAP envelope close
+ */
+define("SAML_SOAP_ENV_CLOSE", '</SOAP-ENV:Envelope>');
+
+/**
+ * SAML Attributes
+ */
+define("SAML_ATTRIBUTES", 'SAMLATTRIBS');
+
+/** @} */
+/**
+ * @addtogroup publicPGTStorage
+ * @{
+ */
+// ------------------------------------------------------------------------
+//  FILE PGT STORAGE
+// ------------------------------------------------------------------------
+/**
+ * Default path used when storing PGT's to file
+ */
+define("CAS_PGT_STORAGE_FILE_DEFAULT_PATH", session_save_path());
+/** @} */
+// ------------------------------------------------------------------------
+// SERVICE ACCESS ERRORS
+// ------------------------------------------------------------------------
+/**
+ * @addtogroup publicServices
+ * @{
+ */
+
+/**
+ * phpCAS::service() error code on success
+ */
+define("PHPCAS_SERVICE_OK", 0);
+/**
+ * phpCAS::service() error code when the PT could not retrieve because
+ * the CAS server did not respond.
+ */
+define("PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE", 1);
+/**
+ * phpCAS::service() error code when the PT could not retrieve because
+ * the response of the CAS server was ill-formed.
+ */
+define("PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE", 2);
+/**
+ * phpCAS::service() error code when the PT could not retrieve because
+ * the CAS server did not want to.
+ */
+define("PHPCAS_SERVICE_PT_FAILURE", 3);
+/**
+ * phpCAS::service() error code when the service was not available.
+ */
+define("PHPCAS_SERVICE_NOT_AVAILABLE", 4);
+
+// ------------------------------------------------------------------------
+// SERVICE TYPES
+// ------------------------------------------------------------------------
+/**
+ * phpCAS::getProxiedService() type for HTTP GET
+ */
+define("PHPCAS_PROXIED_SERVICE_HTTP_GET", 'CAS_ProxiedService_Http_Get');
+/**
+ * phpCAS::getProxiedService() type for HTTP POST
+ */
+define("PHPCAS_PROXIED_SERVICE_HTTP_POST", 'CAS_ProxiedService_Http_Post');
+/**
+ * phpCAS::getProxiedService() type for IMAP
+ */
+define("PHPCAS_PROXIED_SERVICE_IMAP", 'CAS_ProxiedService_Imap');
+
+
+/** @} */
+// ------------------------------------------------------------------------
+//  LANGUAGES
+// ------------------------------------------------------------------------
+/**
+ * @addtogroup publicLang
+ * @{
+ */
+
+define("PHPCAS_LANG_ENGLISH", 'CAS_Languages_English');
+define("PHPCAS_LANG_FRENCH", 'CAS_Languages_French');
+define("PHPCAS_LANG_GREEK", 'CAS_Languages_Greek');
+define("PHPCAS_LANG_GERMAN", 'CAS_Languages_German');
+define("PHPCAS_LANG_JAPANESE", 'CAS_Languages_Japanese');
+define("PHPCAS_LANG_SPANISH", 'CAS_Languages_Spanish');
+define("PHPCAS_LANG_CATALAN", 'CAS_Languages_Catalan');
+
+/** @} */
+
+/**
+ * @addtogroup internalLang
+ * @{
+ */
+
+/**
+ * phpCAS default language (when phpCAS::setLang() is not used)
+ */
+define("PHPCAS_LANG_DEFAULT", PHPCAS_LANG_ENGLISH);
+
+/** @} */
+// ------------------------------------------------------------------------
+//  DEBUG
+// ------------------------------------------------------------------------
+/**
+ * @addtogroup publicDebug
+ * @{
+ */
+
+/**
+ * The default directory for the debug file under Unix.
+ */
+define('DEFAULT_DEBUG_DIR', '/tmp/');
+
+/** @} */
+
+// include the class autoloader
+require_once dirname(__FILE__) . '/CAS/Autoload.php';
+
+/**
+ * The phpCAS class is a simple container for the phpCAS library. It provides CAS
+ * authentication for web applications written in PHP.
+ *
+ * @ingroup public
+ * @class phpCAS
+ * @category Authentication
+ * @package  PhpCAS
+ * @author   Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @author   Olivier Berger <olivier.berger@it-sudparis.eu>
+ * @author   Brett Bieber <brett.bieber@gmail.com>
+ * @author   Joachim Fritschi <jfritschi@freenet.de>
+ * @author   Adam Franco <afranco@middlebury.edu>
+ * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License 2.0
+ * @link     https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+class phpCAS
+{
+
+    /**
+     * This variable is used by the interface class phpCAS.
+     *
+     * @hideinitializer
+     */
+    private static $_PHPCAS_CLIENT;
+
+    /**
+     * This variable is used to store where the initializer is called from
+     * (to print a comprehensive error in case of multiple calls).
+     *
+     * @hideinitializer
+     */
+    private static $_PHPCAS_INIT_CALL;
+
+    /**
+     * This variable is used to store phpCAS debug mode.
+     *
+     * @hideinitializer
+     */
+    private static $_PHPCAS_DEBUG;
+
+
+    // ########################################################################
+    //  INITIALIZATION
+    // ########################################################################
+
+    /**
+     * @addtogroup publicInit
+     * @{
+     */
+
+    /**
+     * phpCAS client initializer.
+     *
+     * @param string $server_version  the version of the CAS server
+     * @param string $server_hostname the hostname of the CAS server
+     * @param string $server_port     the port the CAS server is running on
+     * @param string $server_uri      the URI the CAS server is responding on
+     * @param bool   $changeSessionID Allow phpCAS to change the session_id (Single
+     * Sign Out/handleLogoutRequests is based on that change)
+     *
+     * @return a newly created CAS_Client object
+     * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be
+     * called, only once, and before all other methods (except phpCAS::getVersion()
+     * and phpCAS::setDebug()).
+     */
+    public static function client($server_version, $server_hostname,
+        $server_port, $server_uri, $changeSessionID = true
+    ) {
+        phpCAS :: traceBegin();
+        if (is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error(self::$_PHPCAS_INIT_CALL['method'] . '() has already been called (at ' . self::$_PHPCAS_INIT_CALL['file'] . ':' . self::$_PHPCAS_INIT_CALL['line'] . ')');
+        }
+        if (gettype($server_version) != 'string') {
+            phpCAS :: error('type mismatched for parameter $server_version (should be `string\')');
+        }
+        if (gettype($server_hostname) != 'string') {
+            phpCAS :: error('type mismatched for parameter $server_hostname (should be `string\')');
+        }
+        if (gettype($server_port) != 'integer') {
+            phpCAS :: error('type mismatched for parameter $server_port (should be `integer\')');
+        }
+        if (gettype($server_uri) != 'string') {
+            phpCAS :: error('type mismatched for parameter $server_uri (should be `string\')');
+        }
+
+        // store where the initializer is called from
+        $dbg = debug_backtrace();
+        self::$_PHPCAS_INIT_CALL = array (
+            'done' => true,
+            'file' => $dbg[0]['file'],
+            'line' => $dbg[0]['line'],
+            'method' => __CLASS__ . '::' . __FUNCTION__
+        );
+
+        // initialize the object $_PHPCAS_CLIENT
+        self::$_PHPCAS_CLIENT = new CAS_Client(
+            $server_version, false, $server_hostname, $server_port, $server_uri,
+            $changeSessionID
+        );
+        phpCAS :: traceEnd();
+    }
+
+    /**
+     * phpCAS proxy initializer.
+     *
+     * @param string $server_version  the version of the CAS server
+     * @param string $server_hostname the hostname of the CAS server
+     * @param string $server_port     the port the CAS server is running on
+     * @param string $server_uri      the URI the CAS server is responding on
+     * @param bool   $changeSessionID Allow phpCAS to change the session_id (Single
+     * Sign Out/handleLogoutRequests is based on that change)
+     *
+     * @return a newly created CAS_Client object
+     * @note Only one of the phpCAS::client() and phpCAS::proxy functions should be
+     * called, only once, and before all other methods (except phpCAS::getVersion()
+     * and phpCAS::setDebug()).
+     */
+    public static function proxy($server_version, $server_hostname,
+        $server_port, $server_uri, $changeSessionID = true
+    ) {
+        phpCAS :: traceBegin();
+        if (is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error(self::$_PHPCAS_INIT_CALL['method'] . '() has already been called (at ' . self::$_PHPCAS_INIT_CALL['file'] . ':' . self::$_PHPCAS_INIT_CALL['line'] . ')');
+        }
+        if (gettype($server_version) != 'string') {
+            phpCAS :: error('type mismatched for parameter $server_version (should be `string\')');
+        }
+        if (gettype($server_hostname) != 'string') {
+            phpCAS :: error('type mismatched for parameter $server_hostname (should be `string\')');
+        }
+        if (gettype($server_port) != 'integer') {
+            phpCAS :: error('type mismatched for parameter $server_port (should be `integer\')');
+        }
+        if (gettype($server_uri) != 'string') {
+            phpCAS :: error('type mismatched for parameter $server_uri (should be `string\')');
+        }
+
+        // store where the initialzer is called from
+        $dbg = debug_backtrace();
+        self::$_PHPCAS_INIT_CALL = array (
+            'done' => true,
+            'file' => $dbg[0]['file'],
+            'line' => $dbg[0]['line'],
+            'method' => __CLASS__ . '::' . __FUNCTION__
+        );
+
+        // initialize the object $_PHPCAS_CLIENT
+        self::$_PHPCAS_CLIENT = new CAS_Client(
+            $server_version, true, $server_hostname, $server_port, $server_uri,
+            $changeSessionID
+        );
+        phpCAS :: traceEnd();
+    }
+
+    /** @} */
+    // ########################################################################
+    //  DEBUGGING
+    // ########################################################################
+
+    /**
+     * @addtogroup publicDebug
+     * @{
+     */
+
+    /**
+     * Set/unset debug mode
+     *
+     * @param string $filename the name of the file used for logging, or false
+     * to stop debugging.
+     *
+     * @return void
+     */
+    public static function setDebug($filename = '')
+    {
+        if ($filename != false && gettype($filename) != 'string') {
+            phpCAS :: error('type mismatched for parameter $dbg (should be false or the name of the log file)');
+        }
+        if ($filename === false) {
+            self::$_PHPCAS_DEBUG['filename'] = false;
+
+        } else {
+            if (empty ($filename)) {
+                if (preg_match('/^Win.*/', getenv('OS'))) {
+                    if (isset ($_ENV['TMP'])) {
+                        $debugDir = $_ENV['TMP'] . '/';
+                    } else {
+                        $debugDir = '';
+                    }
+                } else {
+                    $debugDir = DEFAULT_DEBUG_DIR;
+                }
+                $filename = $debugDir . 'phpCAS.log';
+            }
+
+            if (empty (self::$_PHPCAS_DEBUG['unique_id'])) {
+                self::$_PHPCAS_DEBUG['unique_id'] = substr(strtoupper(md5(uniqid(''))), 0, 4);
+            }
+
+            self::$_PHPCAS_DEBUG['filename'] = $filename;
+            self::$_PHPCAS_DEBUG['indent'] = 0;
+
+            phpCAS :: trace('START phpCAS-' . PHPCAS_VERSION . ' ******************');
+        }
+    }
+
+
+    /**
+     * Logs a string in debug mode.
+     *
+     * @param string $str the string to write
+     *
+     * @return void
+     * @private
+     */
+    public static function log($str)
+    {
+        $indent_str = ".";
+
+
+        if (!empty(self::$_PHPCAS_DEBUG['filename'])) {
+            // Check if file exists and modifiy file permissions to be only
+            // readable by the webserver
+            if (!file_exists(self::$_PHPCAS_DEBUG['filename'])) {
+                touch(self::$_PHPCAS_DEBUG['filename']);
+                // Chmod will fail on windows
+                @chmod(self::$_PHPCAS_DEBUG['filename'], 0600);
+            }
+            for ($i = 0; $i < self::$_PHPCAS_DEBUG['indent']; $i++) {
+
+                $indent_str .= '|    ';
+            }
+            // allow for multiline output with proper identing. Usefull for
+            // dumping cas answers etc.
+            $str2 = str_replace("\n", "\n" . self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str, $str);
+            error_log(self::$_PHPCAS_DEBUG['unique_id'] . ' ' . $indent_str . $str2 . "\n", 3, self::$_PHPCAS_DEBUG['filename']);
+        }
+
+    }
+
+    /**
+     * This method is used by interface methods to print an error and where the
+     * function was originally called from.
+     *
+     * @param string $msg the message to print
+     *
+     * @return void
+     * @private
+     */
+    public static function error($msg)
+    {
+        $dbg = debug_backtrace();
+        $function = '?';
+        $file = '?';
+        $line = '?';
+        if (is_array($dbg)) {
+            for ($i = 1; $i < sizeof($dbg); $i++) {
+                if (is_array($dbg[$i]) && isset($dbg[$i]['class']) ) {
+                    if ($dbg[$i]['class'] == __CLASS__) {
+                        $function = $dbg[$i]['function'];
+                        $file = $dbg[$i]['file'];
+                        $line = $dbg[$i]['line'];
+                    }
+                }
+            }
+        }
+        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";
+        phpCAS :: trace($msg);
+        phpCAS :: traceEnd();
+
+        throw new CAS_GracefullTerminationException(__CLASS__ . "::" . $function . '(): ' . $msg);
+    }
+
+    /**
+     * This method is used to log something in debug mode.
+     *
+     * @param string $str string to log
+     *
+     * @return void
+     */
+    public static function trace($str)
+    {
+        $dbg = debug_backtrace();
+        phpCAS :: log($str . ' [' . basename($dbg[0]['file']) . ':' . $dbg[0]['line'] . ']');
+    }
+
+    /**
+     * This method is used to indicate the start of the execution of a function in debug mode.
+     *
+     * @return void
+     */
+    public static function traceBegin()
+    {
+        $dbg = debug_backtrace();
+        $str = '=> ';
+        if (!empty ($dbg[1]['class'])) {
+            $str .= $dbg[1]['class'] . '::';
+        }
+        $str .= $dbg[1]['function'] . '(';
+        if (is_array($dbg[1]['args'])) {
+            foreach ($dbg[1]['args'] as $index => $arg) {
+                if ($index != 0) {
+                    $str .= ', ';
+                }
+                if (is_object($arg)) {
+                    $str .= get_class($arg);
+                } else {
+                    $str .= str_replace(array("\r\n", "\n", "\r"), "", var_export($arg, true));
+                }
+            }
+        }
+        if (isset($dbg[1]['file'])) {
+            $file = basename($dbg[1]['file']);
+        } else {
+            $file = 'unknown_file';
+        }
+        if (isset($dbg[1]['line'])) {
+            $line = $dbg[1]['line'];
+        } else {
+            $line = 'unknown_line';
+        }
+        $str .= ') [' . $file . ':' . $line . ']';
+        phpCAS :: log($str);
+        if (!isset(self::$_PHPCAS_DEBUG['indent'])) {
+            self::$_PHPCAS_DEBUG['indent'] = 0;
+        } else {
+            self::$_PHPCAS_DEBUG['indent']++;
+        }
+    }
+
+    /**
+     * This method is used to indicate the end of the execution of a function in
+     * debug mode.
+     *
+     * @param string $res the result of the function
+     *
+     * @return void
+     */
+    public static function traceEnd($res = '')
+    {
+        if (empty(self::$_PHPCAS_DEBUG['indent'])) {
+            self::$_PHPCAS_DEBUG['indent'] = 0;
+        } else {
+            self::$_PHPCAS_DEBUG['indent']--;
+        }
+        $dbg = debug_backtrace();
+        $str = '';
+        if (is_object($res)) {
+            $str .= '<= ' . get_class($res);
+        } else {
+            $str .= '<= ' . str_replace(array("\r\n", "\n", "\r"), "", var_export($res, true));
+        }
+
+        phpCAS :: log($str);
+    }
+
+    /**
+     * This method is used to indicate the end of the execution of the program
+     *
+     * @return void
+     */
+    public static function traceExit()
+    {
+        phpCAS :: log('exit()');
+        while (self::$_PHPCAS_DEBUG['indent'] > 0) {
+            phpCAS :: log('-');
+            self::$_PHPCAS_DEBUG['indent']--;
+        }
+    }
+
+    /** @} */
+    // ########################################################################
+    //  INTERNATIONALIZATION
+    // ########################################################################
+    /**
+    * @addtogroup publicLang
+    * @{
+    */
+
+    /**
+     * This method is used to set the language used by phpCAS.
+     *
+     * @param string $lang string representing the language.
+     *
+     * @return void
+     *
+     * @sa PHPCAS_LANG_FRENCH, PHPCAS_LANG_ENGLISH
+     * @note Can be called only once.
+     */
+    public static function setLang($lang)
+    {
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+        if (gettype($lang) != 'string') {
+            phpCAS :: error('type mismatched for parameter $lang (should be `string\')');
+        }
+        self::$_PHPCAS_CLIENT->setLang($lang);
+    }
+
+    /** @} */
+    // ########################################################################
+    //  VERSION
+    // ########################################################################
+    /**
+    * @addtogroup public
+    * @{
+    */
+
+    /**
+     * This method returns the phpCAS version.
+     *
+     * @return the phpCAS version.
+     */
+    public static function getVersion()
+    {
+        return PHPCAS_VERSION;
+    }
+
+    /** @} */
+    // ########################################################################
+    //  HTML OUTPUT
+    // ########################################################################
+    /**
+    * @addtogroup publicOutput
+    * @{
+    */
+
+    /**
+     * This method sets the HTML header used for all outputs.
+     *
+     * @param string $header the HTML header.
+     *
+     * @return void
+     */
+    public static function setHTMLHeader($header)
+    {
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+        if (gettype($header) != 'string') {
+            phpCAS :: error('type mismatched for parameter $header (should be `string\')');
+        }
+        self::$_PHPCAS_CLIENT->setHTMLHeader($header);
+    }
+
+    /**
+     * This method sets the HTML footer used for all outputs.
+     *
+     * @param string $footer the HTML footer.
+     *
+     * @return void
+     */
+    public static function setHTMLFooter($footer)
+    {
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+        if (gettype($footer) != 'string') {
+            phpCAS :: error('type mismatched for parameter $footer (should be `string\')');
+        }
+        self::$_PHPCAS_CLIENT->setHTMLFooter($footer);
+    }
+
+    /** @} */
+    // ########################################################################
+    //  PGT STORAGE
+    // ########################################################################
+    /**
+    * @addtogroup publicPGTStorage
+    * @{
+    */
+
+    /**
+     * This method can be used to set a custom PGT storage object.
+     *
+     * @param CAS_PGTStorage $storage a PGT storage object that inherits from the
+     * CAS_PGTStorage class
+     *
+     * @return void
+     */
+    public static function setPGTStorage($storage)
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        if (!self::$_PHPCAS_CLIENT->isProxy()) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        if (self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
+            phpCAS :: error('this method should only be called before ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() (called at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ')');
+        }
+        if ( !($storage instanceof CAS_PGTStorage) ) {
+            phpCAS :: error('type mismatched for parameter $storage (should be a CAS_PGTStorage `object\')');
+        }
+        self::$_PHPCAS_CLIENT->setPGTStorage($storage);
+        phpCAS :: traceEnd();
+    }
+
+    /**
+     * This method is used to tell phpCAS to store the response of the
+     * CAS server to PGT requests in a database.
+     *
+     * @param string $dsn_or_pdo     a dsn string to use for creating a PDO
+     * object or a PDO object
+     * @param string $username       the username to use when connecting to the
+     * database
+     * @param string $password       the password to use when connecting to the
+     * database
+     * @param string $table          the table to use for storing and retrieving
+     * PGT's
+     * @param string $driver_options any driver options to use when connecting
+     * to the database
+     *
+     * @return void
+     */
+    public static function setPGTStorageDb($dsn_or_pdo, $username='',
+        $password='', $table='', $driver_options=null
+    ) {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        if (!self::$_PHPCAS_CLIENT->isProxy()) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        if (self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
+            phpCAS :: error('this method should only be called before ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() (called at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ')');
+        }
+        if (gettype($username) != 'string') {
+            phpCAS :: error('type mismatched for parameter $username (should be `string\')');
+        }
+        if (gettype($password) != 'string') {
+            phpCAS :: error('type mismatched for parameter $password (should be `string\')');
+        }
+        if (gettype($table) != 'string') {
+            phpCAS :: error('type mismatched for parameter $table (should be `string\')');
+        }
+        self::$_PHPCAS_CLIENT->setPGTStorageDb($dsn_or_pdo, $username, $password, $table, $driver_options);
+        phpCAS :: traceEnd();
+    }
+
+    /**
+     * This method is used to tell phpCAS to store the response of the
+     * CAS server to PGT requests onto the filesystem.
+     *
+     * @param string $path the path where the PGT's should be stored
+     *
+     * @return void
+     */
+    public static function setPGTStorageFile($path = '')
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        if (!self::$_PHPCAS_CLIENT->isProxy()) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        if (self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
+            phpCAS :: error('this method should only be called before ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() (called at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ')');
+        }
+        if (gettype($path) != 'string') {
+            phpCAS :: error('type mismatched for parameter $path (should be `string\')');
+        }
+        self::$_PHPCAS_CLIENT->setPGTStorageFile($path);
+        phpCAS :: traceEnd();
+    }
+    /** @} */
+    // ########################################################################
+    // ACCESS TO EXTERNAL SERVICES
+    // ########################################################################
+    /**
+    * @addtogroup publicServices
+    * @{
+    */
+
+    /**
+     * Answer a proxy-authenticated service handler.
+     *
+     * @param string $type The service type. One of
+     * PHPCAS_PROXIED_SERVICE_HTTP_GET; PHPCAS_PROXIED_SERVICE_HTTP_POST;
+     * PHPCAS_PROXIED_SERVICE_IMAP
+     *
+     * @return CAS_ProxiedService
+     * @throws InvalidArgumentException If the service type is unknown.
+     */
+    public static function getProxiedService ($type)
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        if (!self::$_PHPCAS_CLIENT->isProxy()) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        if (!self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
+            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()');
+        }
+        if (!self::$_PHPCAS_CLIENT->wasAuthenticationCallSuccessful()) {
+            phpCAS :: error('authentication was checked (by ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ') but the method returned false');
+        }
+        if (gettype($type) != 'string') {
+            phpCAS :: error('type mismatched for parameter $type (should be `string\')');
+        }
+
+        $res = self::$_PHPCAS_CLIENT->getProxiedService($type);
+
+        phpCAS :: traceEnd();
+        return $res;
+    }
+
+    /**
+     * Initialize a proxied-service handler with the proxy-ticket it should use.
+     *
+     * @param CAS_ProxiedService $proxiedService Proxied Service Handler
+     *
+     * @return void
+     * @throws CAS_ProxyTicketException If there is a proxy-ticket failure.
+     *         The code of the Exception will be one of:
+     *                 PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE
+     *                 PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE
+     *                 PHPCAS_SERVICE_PT_FAILURE
+     */
+    public static function initializeProxiedService (CAS_ProxiedService $proxiedService)
+    {
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        if (!self::$_PHPCAS_CLIENT->isProxy()) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        if (!self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
+            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()');
+        }
+        if (!self::$_PHPCAS_CLIENT->wasAuthenticationCallSuccessful()) {
+            phpCAS :: error('authentication was checked (by ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ') but the method returned false');
+        }
+
+        self::$_PHPCAS_CLIENT->initializeProxiedService($proxiedService);
+    }
+
+    /**
+     * This method is used to access an HTTP[S] service.
+     *
+     * @param string $url       the service to access.
+     * @param string &$err_code an error code Possible values are
+     * PHPCAS_SERVICE_OK (on success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE,
+     * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, PHPCAS_SERVICE_PT_FAILURE,
+     * PHPCAS_SERVICE_NOT_AVAILABLE.
+     * @param string &$output   the output of the service (also used to give an
+     * error message on failure).
+     *
+     * @return bool true on success, false otherwise (in this later case,
+     * $err_code gives the reason why it failed and $output contains an error
+     * message).
+     */
+    public static function serviceWeb($url, & $err_code, & $output)
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        if (!self::$_PHPCAS_CLIENT->isProxy()) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        if (!self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
+            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()');
+        }
+        if (!self::$_PHPCAS_CLIENT->wasAuthenticationCallSuccessful()) {
+            phpCAS :: error('authentication was checked (by ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ') but the method returned false');
+        }
+        if (gettype($url) != 'string') {
+            phpCAS :: error('type mismatched for parameter $url (should be `string\')');
+        }
+
+        $res = self::$_PHPCAS_CLIENT->serviceWeb($url, $err_code, $output);
+
+        phpCAS :: traceEnd($res);
+        return $res;
+    }
+
+    /**
+     * This method is used to access an IMAP/POP3/NNTP service.
+     *
+     * @param string $url       a string giving the URL of the service,
+     * including the mailing box for IMAP URLs, as accepted by imap_open().
+     * @param string $service   a string giving for CAS retrieve Proxy ticket
+     * @param string $flags     options given to imap_open().
+     * @param string &$err_code an error code Possible values are
+     * PHPCAS_SERVICE_OK (on success), PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE,
+     * PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE, PHPCAS_SERVICE_PT_FAILURE,
+     * PHPCAS_SERVICE_NOT_AVAILABLE.
+     * @param string &$err_msg  an error message on failure
+     * @param string &$pt       the Proxy Ticket (PT) retrieved from the CAS
+     * server to access the URL on success, false on error).
+     *
+     * @return object IMAP stream on success, false otherwise (in this later
+     * case, $err_code gives the reason why it failed and $err_msg contains an
+     * error message).
+     */
+    public static function serviceMail($url, $service, $flags, & $err_code, & $err_msg, & $pt)
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        if (!self::$_PHPCAS_CLIENT->isProxy()) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        if (!self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
+            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()');
+        }
+        if (!self::$_PHPCAS_CLIENT->wasAuthenticationCallSuccessful()) {
+            phpCAS :: error('authentication was checked (by ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ') but the method returned false');
+        }
+        if (gettype($url) != 'string') {
+            phpCAS :: error('type mismatched for parameter $url (should be `string\')');
+        }
+
+        if (gettype($flags) != 'integer') {
+            phpCAS :: error('type mismatched for parameter $flags (should be `integer\')');
+        }
+
+        $res = self::$_PHPCAS_CLIENT->serviceMail($url, $service, $flags, $err_code, $err_msg, $pt);
+
+        phpCAS :: traceEnd($res);
+        return $res;
+    }
+
+    /** @} */
+    // ########################################################################
+    //  AUTHENTICATION
+    // ########################################################################
+    /**
+    * @addtogroup publicAuth
+    * @{
+    */
+
+    /**
+     * Set the times authentication will be cached before really accessing the
+     * CAS server in gateway mode:
+     * - -1: check only once, and then never again (until you pree login)
+     * - 0: always check
+     * - n: check every "n" time
+     *
+     * @param int $n an integer.
+     *
+     * @return void
+     */
+    public static function setCacheTimesForAuthRecheck($n)
+    {
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+        if (gettype($n) != 'integer') {
+            phpCAS :: error('type mismatched for parameter $n (should be `integer\')');
+        }
+        self::$_PHPCAS_CLIENT->setCacheTimesForAuthRecheck($n);
+    }
+
+    /**
+     * Set a callback function to be run when a user authenticates.
+     *
+     * The callback function will be passed a $logoutTicket as its first
+     * parameter, followed by any $additionalArgs you pass. The $logoutTicket
+     * parameter is an opaque string that can be used to map the session-id to
+     * logout request in order to support single-signout in applications that
+     * manage their own sessions (rather than letting phpCAS start the session).
+     *
+     * phpCAS::forceAuthentication() will always exit and forward client unless
+     * they are already authenticated. To perform an action at the moment the user
+     * logs in (such as registering an account, performing logging, etc), register
+     * a callback function here.
+     *
+     * @param string $function       Callback function
+     * @param array  $additionalArgs optional array of arguments
+     *
+     * @return void
+     */
+    public static function setPostAuthenticateCallback ($function, array $additionalArgs = array())
+    {
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+
+        self::$_PHPCAS_CLIENT->setPostAuthenticateCallback($function, $additionalArgs);
+    }
+
+    /**
+     * Set a callback function to be run when a single-signout request is
+     * received. The callback function will be passed a $logoutTicket as its
+     * first parameter, followed by any $additionalArgs you pass. The
+     * $logoutTicket parameter is an opaque string that can be used to map a
+     * session-id to the logout request in order to support single-signout in
+     * applications that manage their own sessions (rather than letting phpCAS
+     * start and destroy the session).
+     *
+     * @param string $function       Callback function
+     * @param array  $additionalArgs optional array of arguments
+     *
+     * @return void
+     */
+    public static function setSingleSignoutCallback ($function, array $additionalArgs = array())
+    {
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+
+        self::$_PHPCAS_CLIENT->setSingleSignoutCallback($function, $additionalArgs);
+    }
+
+    /**
+     * This method is called to check if the user is already authenticated
+     * locally or has a global cas session. A already existing cas session is
+     * determined by a cas gateway call.(cas login call without any interactive
+     * prompt)
+     *
+     * @return true when the user is authenticated, false when a previous
+     * gateway login failed or the function will not return if the user is
+     * redirected to the cas server for a gateway login attempt
+     */
+    public static function checkAuthentication()
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+
+        $auth = self::$_PHPCAS_CLIENT->checkAuthentication();
+
+        // store where the authentication has been checked and the result
+        self::$_PHPCAS_CLIENT->markAuthenticationCall($auth);
+
+        phpCAS :: traceEnd($auth);
+        return $auth;
+    }
+
+    /**
+     * This method is called to force authentication if the user was not already
+     * authenticated. If the user is not authenticated, halt by redirecting to
+     * the CAS server.
+     *
+     * @return bool Authentication
+     */
+    public static function forceAuthentication()
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+
+        $auth = self::$_PHPCAS_CLIENT->forceAuthentication();
+
+        // store where the authentication has been checked and the result
+        self::$_PHPCAS_CLIENT->markAuthenticationCall($auth);
+
+        /*             if (!$auth) {
+         phpCAS :: trace('user is not authenticated, redirecting to the CAS server');
+        self::$_PHPCAS_CLIENT->forceAuthentication();
+        } else {
+        phpCAS :: trace('no need to authenticate (user `' . phpCAS :: getUser() . '\' is already authenticated)');
+        }*/
+
+        phpCAS :: traceEnd();
+        return $auth;
+    }
+
+    /**
+     * This method is called to renew the authentication.
+     *
+     * @return void
+     **/
+    public static function renewAuthentication()
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+        $auth = self::$_PHPCAS_CLIENT->renewAuthentication();
+
+        // store where the authentication has been checked and the result
+        self::$_PHPCAS_CLIENT->markAuthenticationCall($auth);
+
+        //self::$_PHPCAS_CLIENT->renewAuthentication();
+        phpCAS :: traceEnd();
+    }
+
+    /**
+     * This method is called to check if the user is authenticated (previously or by
+     * tickets given in the URL).
+     *
+     * @return true when the user is authenticated.
+     */
+    public static function isAuthenticated()
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+
+        // call the isAuthenticated method of the $_PHPCAS_CLIENT object
+        $auth = self::$_PHPCAS_CLIENT->isAuthenticated();
+
+        // store where the authentication has been checked and the result
+        self::$_PHPCAS_CLIENT->markAuthenticationCall($auth);
+
+        phpCAS :: traceEnd($auth);
+        return $auth;
+    }
+
+    /**
+     * Checks whether authenticated based on $_SESSION. Useful to avoid
+     * server calls.
+     *
+     * @return bool true if authenticated, false otherwise.
+     * @since 0.4.22 by Brendan Arnold
+     */
+    public static function isSessionAuthenticated()
+    {
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+        return (self::$_PHPCAS_CLIENT->isSessionAuthenticated());
+    }
+
+    /**
+     * This method returns the CAS user's login name.
+     *
+     * @return string the login name of the authenticated user
+     * @warning should not be called only after phpCAS::forceAuthentication()
+     * or phpCAS::checkAuthentication().
+     * */
+    public static function getUser()
+    {
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+        if (!self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::forceAuthentication() or ' . __CLASS__ . '::isAuthenticated()');
+        }
+        if (!self::$_PHPCAS_CLIENT->wasAuthenticationCallSuccessful()) {
+            phpCAS :: error('authentication was checked (by ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ') but the method returned false');
+        }
+        return self::$_PHPCAS_CLIENT->getUser();
+    }
+
+    /**
+     * Answer attributes about the authenticated user.
+     *
+     * @warning should not be called only after phpCAS::forceAuthentication()
+     * or phpCAS::checkAuthentication().
+     *
+     * @return array
+     */
+    public static function getAttributes()
+    {
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+        if (!self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::forceAuthentication() or ' . __CLASS__ . '::isAuthenticated()');
+        }
+        if (!self::$_PHPCAS_CLIENT->wasAuthenticationCallSuccessful()) {
+            phpCAS :: error('authentication was checked (by ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ') but the method returned false');
+        }
+        return self::$_PHPCAS_CLIENT->getAttributes();
+    }
+
+    /**
+     * Answer true if there are attributes for the authenticated user.
+     *
+     * @warning should not be called only after phpCAS::forceAuthentication()
+     * or phpCAS::checkAuthentication().
+     *
+     * @return bool
+     */
+    public static function hasAttributes()
+    {
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+        if (!self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::forceAuthentication() or ' . __CLASS__ . '::isAuthenticated()');
+        }
+        if (!self::$_PHPCAS_CLIENT->wasAuthenticationCallSuccessful()) {
+            phpCAS :: error('authentication was checked (by ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ') but the method returned false');
+        }
+        return self::$_PHPCAS_CLIENT->hasAttributes();
+    }
+
+    /**
+     * Answer true if an attribute exists for the authenticated user.
+     *
+     * @param string $key attribute name
+     *
+     * @return bool
+     * @warning should not be called only after phpCAS::forceAuthentication()
+     * or phpCAS::checkAuthentication().
+     */
+    public static function hasAttribute($key)
+    {
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+        if (!self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::forceAuthentication() or ' . __CLASS__ . '::isAuthenticated()');
+        }
+        if (!self::$_PHPCAS_CLIENT->wasAuthenticationCallSuccessful()) {
+            phpCAS :: error('authentication was checked (by ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ') but the method returned false');
+        }
+        return self::$_PHPCAS_CLIENT->hasAttribute($key);
+    }
+
+    /**
+     * Answer an attribute for the authenticated user.
+     *
+     * @param string $key attribute name
+     *
+     * @return mixed string for a single value or an array if multiple values exist.
+     * @warning should not be called only after phpCAS::forceAuthentication()
+     * or phpCAS::checkAuthentication().
+     */
+    public static function getAttribute($key)
+    {
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+        if (!self::$_PHPCAS_CLIENT->wasAuthenticationCalled()) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::forceAuthentication() or ' . __CLASS__ . '::isAuthenticated()');
+        }
+        if (!self::$_PHPCAS_CLIENT->wasAuthenticationCallSuccessful()) {
+            phpCAS :: error('authentication was checked (by ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerMethod() . '() at ' . self::$_PHPCAS_CLIENT->getAuthenticationCallerFile() . ':' . self::$_PHPCAS_CLIENT->getAuthenticationCallerLine() . ') but the method returned false');
+        }
+        return self::$_PHPCAS_CLIENT->getAttribute($key);
+    }
+
+    /**
+     * Handle logout requests.
+     *
+     * @param bool  $check_client    additional safety check
+     * @param array $allowed_clients array of allowed clients
+     *
+     * @return void
+     */
+    public static function handleLogoutRequests($check_client = true, $allowed_clients = false)
+    {
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+        return (self::$_PHPCAS_CLIENT->handleLogoutRequests($check_client, $allowed_clients));
+    }
+
+    /**
+     * This method returns the URL to be used to login.
+     * or phpCAS::isAuthenticated().
+     *
+     * @return the login name of the authenticated user
+     */
+    public static function getServerLoginURL()
+    {
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+        return self::$_PHPCAS_CLIENT->getServerLoginURL();
+    }
+
+    /**
+     * Set the login URL of the CAS server.
+     *
+     * @param string $url the login URL
+     *
+     * @return void
+     * @since 0.4.21 by Wyman Chan
+     */
+    public static function setServerLoginURL($url = '')
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after' . __CLASS__ . '::client()');
+        }
+        if (gettype($url) != 'string') {
+            phpCAS :: error('type mismatched for parameter $url (should be `string`)');
+        }
+        self::$_PHPCAS_CLIENT->setServerLoginURL($url);
+        phpCAS :: traceEnd();
+    }
+
+    /**
+     * Set the serviceValidate URL of the CAS server.
+     * Used only in CAS 1.0 validations
+     *
+     * @param string $url the serviceValidate URL
+     *
+     * @return void
+     */
+    public static function setServerServiceValidateURL($url = '')
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after' . __CLASS__ . '::client()');
+        }
+        if (gettype($url) != 'string') {
+            phpCAS :: error('type mismatched for parameter $url (should be `string`)');
+        }
+        self::$_PHPCAS_CLIENT->setServerServiceValidateURL($url);
+        phpCAS :: traceEnd();
+    }
+
+    /**
+     * Set the proxyValidate URL of the CAS server.
+     * Used for all CAS 2.0 validations
+     *
+     * @param string $url the proxyValidate URL
+     *
+     * @return void
+     */
+    public static function setServerProxyValidateURL($url = '')
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after' . __CLASS__ . '::client()');
+        }
+        if (gettype($url) != 'string') {
+            phpCAS :: error('type mismatched for parameter $url (should be `string`)');
+        }
+        self::$_PHPCAS_CLIENT->setServerProxyValidateURL($url);
+        phpCAS :: traceEnd();
+    }
+
+    /**
+     * Set the samlValidate URL of the CAS server.
+     *
+     * @param string $url the samlValidate URL
+     *
+     * @return void
+     */
+    public static function setServerSamlValidateURL($url = '')
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after' . __CLASS__ . '::client()');
+        }
+        if (gettype($url) != 'string') {
+            phpCAS :: error('type mismatched for parameter $url (should be`string\')');
+        }
+        self::$_PHPCAS_CLIENT->setServerSamlValidateURL($url);
+        phpCAS :: traceEnd();
+    }
+
+    /**
+     * This method returns the URL to be used to login.
+     * or phpCAS::isAuthenticated().
+     *
+     * @return the login name of the authenticated user
+     */
+    public static function getServerLogoutURL()
+    {
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should not be called before ' . __CLASS__ . '::client() or ' . __CLASS__ . '::proxy()');
+        }
+        return self::$_PHPCAS_CLIENT->getServerLogoutURL();
+    }
+
+    /**
+     * Set the logout URL of the CAS server.
+     *
+     * @param string $url the logout URL
+     *
+     * @return void
+     * @since 0.4.21 by Wyman Chan
+     */
+    public static function setServerLogoutURL($url = '')
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error(
+                'this method should only be called after' . __CLASS__ . '::client()'
+            );
+        }
+        if (gettype($url) != 'string') {
+            phpCAS :: error(
+                'type mismatched for parameter $url (should be `string`)'
+            );
+        }
+        self::$_PHPCAS_CLIENT->setServerLogoutURL($url);
+        phpCAS :: traceEnd();
+    }
+
+    /**
+     * This method is used to logout from CAS.
+     *
+     * @param string $params an array that contains the optional url and
+     * service parameters that will be passed to the CAS server
+     *
+     * @return void
+     */
+    public static function logout($params = "")
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
+        }
+        $parsedParams = array ();
+        if ($params != "") {
+            if (is_string($params)) {
+                phpCAS :: error('method `phpCAS::logout($url)\' is now deprecated, use `phpCAS::logoutWithUrl($url)\' instead');
+            }
+            if (!is_array($params)) {
+                phpCAS :: error('type mismatched for parameter $params (should be `array\')');
+            }
+            foreach ($params as $key => $value) {
+                if ($key != "service" && $key != "url") {
+                    phpCAS :: error('only `url\' and `service\' parameters are allowed for method `phpCAS::logout($params)\'');
+                }
+                $parsedParams[$key] = $value;
+            }
+        }
+        self::$_PHPCAS_CLIENT->logout($parsedParams);
+        // never reached
+        phpCAS :: traceEnd();
+    }
+
+    /**
+     * This method is used to logout from CAS. Halts by redirecting to the CAS
+     * server.
+     *
+     * @param service $service a URL that will be transmitted to the CAS server
+     *
+     * @return void
+     */
+    public static function logoutWithRedirectService($service)
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
+        }
+        if (!is_string($service)) {
+            phpCAS :: error('type mismatched for parameter $service (should be `string\')');
+        }
+        self::$_PHPCAS_CLIENT->logout(array ( "service" => $service ));
+        // never reached
+        phpCAS :: traceEnd();
+    }
+
+    /**
+     * This method is used to logout from CAS. Halts by redirecting to the CAS
+     * server.
+     *
+     * @param string $url a URL that will be transmitted to the CAS server
+     *
+     * @return void
+     * @deprecated The url parameter has been removed from the CAS server as of
+     * version 3.3.5.1
+     */
+    public static function logoutWithUrl($url)
+    {
+        trigger_error('Function deprecated for cas servers >= 3.3.5.1', E_USER_DEPRECATED);
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
+        }
+        if (!is_string($url)) {
+            phpCAS :: error('type mismatched for parameter $url (should be `string\')');
+        }
+        self::$_PHPCAS_CLIENT->logout(array ( "url" => $url ));
+        // never reached
+        phpCAS :: traceEnd();
+    }
+
+    /**
+     * This method is used to logout from CAS. Halts by redirecting to the CAS
+     * server.
+     *
+     * @param string $service a URL that will be transmitted to the CAS server
+     * @param string $url     a URL that will be transmitted to the CAS server
+     *
+     * @return void
+     *
+     * @deprecated The url parameter has been removed from the CAS server as of
+     * version 3.3.5.1
+     */
+    public static function logoutWithRedirectServiceAndUrl($service, $url)
+    {
+        trigger_error('Function deprecated for cas servers >= 3.3.5.1', E_USER_DEPRECATED);
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
+        }
+        if (!is_string($service)) {
+            phpCAS :: error('type mismatched for parameter $service (should be `string\')');
+        }
+        if (!is_string($url)) {
+            phpCAS :: error('type mismatched for parameter $url (should be `string\')');
+        }
+        self::$_PHPCAS_CLIENT->logout(
+            array (
+                "service" => $service,
+                "url" => $url
+            )
+        );
+        // never reached
+        phpCAS :: traceEnd();
+    }
+
+    /**
+     * Set the fixed URL that will be used by the CAS server to transmit the
+     * PGT. When this method is not called, a phpCAS script uses its own URL
+     * for the callback.
+     *
+     * @param string $url the URL
+     *
+     * @return void
+     */
+    public static function setFixedCallbackURL($url = '')
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        if (!self::$_PHPCAS_CLIENT->isProxy()) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        if (gettype($url) != 'string') {
+            phpCAS :: error('type mismatched for parameter $url (should be `string\')');
+        }
+        self::$_PHPCAS_CLIENT->setCallbackURL($url);
+        phpCAS :: traceEnd();
+    }
+
+    /**
+     * Set the fixed URL that will be set as the CAS service parameter. When this
+     * method is not called, a phpCAS script uses its own URL.
+     *
+     * @param string $url the URL
+     *
+     * @return void
+     */
+    public static function setFixedServiceURL($url)
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        if (gettype($url) != 'string') {
+            phpCAS :: error('type mismatched for parameter $url (should be `string\')');
+        }
+        self::$_PHPCAS_CLIENT->setURL($url);
+        phpCAS :: traceEnd();
+    }
+
+    /**
+     * Get the URL that is set as the CAS service parameter.
+     *
+     * @return string Service Url
+     */
+    public static function getServiceURL()
+    {
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        return (self::$_PHPCAS_CLIENT->getURL());
+    }
+
+    /**
+     * Retrieve a Proxy Ticket from the CAS server.
+     *
+     * @param string $target_service Url string of service to proxy
+     * @param string &$err_code      error code
+     * @param string &$err_msg       error message
+     *
+     * @return string Proxy Ticket
+     */
+    public static function retrievePT($target_service, & $err_code, & $err_msg)
+    {
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::proxy()');
+        }
+        if (gettype($target_service) != 'string') {
+            phpCAS :: error('type mismatched for parameter $target_service(should be `string\')');
+        }
+        return (self::$_PHPCAS_CLIENT->retrievePT($target_service, $err_code, $err_msg));
+    }
+
+    /**
+     * Set the certificate of the CAS server CA and if the CN should be properly
+     * verified.
+     *
+     * @param string $cert        CA certificate file name
+     * @param bool   $validate_cn Validate CN in certificate (default true)
+     *
+     * @return void
+     */
+    public static function setCasServerCACert($cert, $validate_cn = true)
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
+        }
+        if (gettype($cert) != 'string') {
+            phpCAS :: error('type mismatched for parameter $cert (should be `string\')');
+        }
+        if (gettype($validate_cn) != 'boolean') {\r
+            phpCAS :: error('type mismatched for parameter $validate_cn (should be `boolean\')');\r
+        }
+        self::$_PHPCAS_CLIENT->setCasServerCACert($cert, $validate_cn);
+        phpCAS :: traceEnd();
+    }
+
+    /**
+     * Set no SSL validation for the CAS server.
+     *
+     * @return void
+     */
+    public static function setNoCasServerValidation()
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
+        }
+        phpCAS :: trace('You have configured no validation of the legitimacy of the cas server. This is not recommended for production use.');
+        self::$_PHPCAS_CLIENT->setNoCasServerValidation();
+        phpCAS :: traceEnd();
+    }
+
+
+    /**
+     * Disable the removal of a CAS-Ticket from the URL when authenticating
+     * DISABLING POSES A SECURITY RISK:
+     * We normally remove the ticket by an additional redirect as a security
+     * precaution to prevent a ticket in the HTTP_REFERRER or be carried over in
+     * the URL parameter
+     *
+     * @return void
+     */
+    public static function setNoClearTicketsFromUrl()
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
+        }
+        self::$_PHPCAS_CLIENT->setNoClearTicketsFromUrl();
+        phpCAS :: traceEnd();
+    }
+
+    /** @} */
+
+    /**
+     * Change CURL options.
+     * CURL is used to connect through HTTPS to CAS server
+     *
+     * @param string $key   the option key
+     * @param string $value the value to set
+     *
+     * @return void
+     */
+    public static function setExtraCurlOption($key, $value)
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
+        }
+        self::$_PHPCAS_CLIENT->setExtraCurlOption($key, $value);
+        phpCAS :: traceEnd();
+    }
+
+    /**
+     * If you want your service to be proxied you have to enable it (default
+     * disabled) and define an accepable list of proxies that are allowed to
+     * proxy your service.
+     *
+     * Add each allowed proxy definition object. For the normal CAS_ProxyChain
+     * class, the constructor takes an array of proxies to match. The list is in
+     * reverse just as seen from the service. Proxies have to be defined in reverse
+     * from the service to the user. If a user hits service A and gets proxied via
+     * B to service C the list of acceptable on C would be array(B,A). The definition
+     * of an individual proxy can be either a string or a regexp (preg_match is used)
+     * that will be matched against the proxy list supplied by the cas server
+     * when validating the proxy tickets. The strings are compared starting from
+     * the beginning and must fully match with the proxies in the list.
+     * Example:
+     *                 phpCAS::allowProxyChain(new CAS_ProxyChain(array(
+     *                         'https://app.example.com/'
+     *                 )));
+     *                 phpCAS::allowProxyChain(new CAS_ProxyChain(array(
+     *                         '/^https:\/\/app[0-9]\.example\.com\/rest\//',
+     *                         'http://client.example.com/'
+     *                 )));
+     *
+     * For quick testing or in certain production screnarios you might want to
+     * allow allow any other valid service to proxy your service. To do so, add
+     * the "Any" chain:
+     *         phpcas::allowProxyChain(new CAS_ProxyChain_Any);
+     * THIS SETTING IS HOWEVER NOT RECOMMENDED FOR PRODUCTION AND HAS SECURITY
+     * IMPLICATIONS: YOU ARE ALLOWING ANY SERVICE TO ACT ON BEHALF OF A USER
+     * ON THIS SERVICE.
+     *
+     * @param CAS_ProxyChain_Interface $proxy_chain A proxy-chain that will be
+     * matched against the proxies requesting access
+     *
+     * @return void
+     */
+    public static function allowProxyChain(CAS_ProxyChain_Interface $proxy_chain)
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
+        }
+        if (self::$_PHPCAS_CLIENT->getServerVersion() !== CAS_VERSION_2_0) {
+            phpCAS :: error('this method can only be used with the cas 2.0 protool');
+        }
+        self::$_PHPCAS_CLIENT->getAllowedProxyChains()->allowProxyChain($proxy_chain);
+        phpCAS :: traceEnd();
+    }
+
+    /**
+     * Answer an array of proxies that are sitting in front of this application.
+     * This method will only return a non-empty array if we have received and
+     * validated a Proxy Ticket.
+     *
+     * @return array
+     * @access public
+     * @since 6/25/09
+     */
+    public static function getProxies ()
+    {
+        if ( !is_object(self::$_PHPCAS_CLIENT) ) {
+            phpCAS::error('this method should only be called after '.__CLASS__.'::client()');
+        }
+
+        return(self::$_PHPCAS_CLIENT->getProxies());
+    }
+
+    // ########################################################################
+    // PGTIOU/PGTID and logoutRequest rebroadcasting
+    // ########################################################################
+
+    /**
+     * Add a pgtIou/pgtId and logoutRequest rebroadcast node.
+     *
+     * @param string $rebroadcastNodeUrl The rebroadcast node URL. Can be
+     * hostname or IP.
+     *
+     * @return void
+     */
+    public static function addRebroadcastNode($rebroadcastNodeUrl)
+    {
+        phpCAS::traceBegin();
+        phpCAS::log('rebroadcastNodeUrl:'.$rebroadcastNodeUrl);
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
+        }
+        if ( !(bool)preg_match("/^(http|https):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i", $rebroadcastNodeUrl)) {
+            phpCAS::error('type mismatched for parameter $rebroadcastNodeUrl (should be `url\')');
+        }
+        self::$_PHPCAS_CLIENT->addRebroadcastNode($rebroadcastNodeUrl);
+        phpCAS::traceEnd();
+    }
+
+    /**
+     * This method is used to add header parameters when rebroadcasting
+     * pgtIou/pgtId or logoutRequest.
+     *
+     * @param String $header Header to send when rebroadcasting.
+     *
+     * @return void
+     */
+    public static function addRebroadcastHeader($header)
+    {
+        phpCAS :: traceBegin();
+        if (!is_object(self::$_PHPCAS_CLIENT)) {
+            phpCAS :: error('this method should only be called after ' . __CLASS__ . '::client() or' . __CLASS__ . '::proxy()');
+        }
+        self::$_PHPCAS_CLIENT->addRebroadcastHeader($header);
+        phpCAS :: traceEnd();
+    }
+}
+
+// ########################################################################
+// DOCUMENTATION
+// ########################################################################
+
+// ########################################################################
+//  MAIN PAGE
+
+/**
+ * @mainpage
+ *
+ * The following pages only show the source documentation.
+ *
+ */
+
+// ########################################################################
+//  MODULES DEFINITION
+
+/** @defgroup public User interface */
+
+/** @defgroup publicInit Initialization
+ *  @ingroup public */
+
+/** @defgroup publicAuth Authentication
+ *  @ingroup public */
+
+/** @defgroup publicServices Access to external services
+ *  @ingroup public */
+
+/** @defgroup publicConfig Configuration
+ *  @ingroup public */
+
+/** @defgroup publicLang Internationalization
+ *  @ingroup publicConfig */
+
+/** @defgroup publicOutput HTML output
+ *  @ingroup publicConfig */
+
+/** @defgroup publicPGTStorage PGT storage
+ *  @ingroup publicConfig */
+
+/** @defgroup publicDebug Debugging
+ *  @ingroup public */
+
+/** @defgroup internal Implementation */
+
+/** @defgroup internalAuthentication Authentication
+ *  @ingroup internal */
+
+/** @defgroup internalBasic CAS Basic client features (CAS 1.0, Service Tickets)
+ *  @ingroup internal */
+
+/** @defgroup internalProxy CAS Proxy features (CAS 2.0, Proxy Granting Tickets)
+ *  @ingroup internal */
+
+/** @defgroup internalSAML CAS SAML features (SAML 1.1)
+ *  @ingroup internal */
+
+/** @defgroup internalPGTStorage PGT storage
+ *  @ingroup internalProxy */
+
+/** @defgroup internalPGTStorageDb PGT storage in a database
+ *  @ingroup internalPGTStorage */
+
+/** @defgroup internalPGTStorageFile PGT storage on the filesystem
+ *  @ingroup internalPGTStorage */
+
+/** @defgroup internalCallback Callback from the CAS server
+ *  @ingroup internalProxy */
+
+/** @defgroup internalProxyServices Proxy other services
+ *  @ingroup internalProxy */
+
+/** @defgroup internalService CAS client features (CAS 2.0, Proxied service)
+ *  @ingroup internal */
+
+/** @defgroup internalConfig Configuration
+ *  @ingroup internal */
+
+/** @defgroup internalBehave Internal behaviour of phpCAS
+ *  @ingroup internalConfig */
+
+/** @defgroup internalOutput HTML output
+ *  @ingroup internalConfig */
+
+/** @defgroup internalLang Internationalization
+ *  @ingroup internalConfig
+ *
+ * To add a new language:
+ * - 1. define a new constant PHPCAS_LANG_XXXXXX in CAS/CAS.php
+ * - 2. copy any file from CAS/languages to CAS/languages/XXXXXX.php
+ * - 3. Make the translations
+ */
+
+/** @defgroup internalDebug Debugging
+ *  @ingroup internal */
+
+/** @defgroup internalMisc Miscellaneous
+ *  @ingroup internal */
+
+// ########################################################################
+//  EXAMPLES
+
+/**
+ * @example example_simple.php
+ */
+/**
+ * @example example_service.php
+ */
+/**
+ * @example example_service_that_proxies.php
+ */
+/**
+ * @example example_service_POST.php
+ */
+/**
+ * @example example_proxy_serviceWeb.php
+ */
+/**
+ * @example example_proxy_serviceWeb_chaining.php
+ */
+/**
+ * @example example_proxy_POST.php
+ */
+/**
+ * @example example_proxy_GET.php
+ */
+/**
+ * @example example_lang.php
+ */
+/**
+ * @example example_html.php
+ */
+/**
+ * @example example_pgt_storage_file.php
+ */
+/**
+ * @example example_pgt_storage_db.php
+ */
+/**
+ * @example example_gateway.php
+ */
+/**
+ * @example example_logout.php
+ */
+/**
+ * @example example_rebroadcast.php
+ */
+/**
+ * @example example_custom_urls.php
+ */
+/**
+ * @example example_advanced_saml11.php
+ */
+?>
diff --git a/auth/cas/CAS/CAS/AuthenticationException.php b/auth/cas/CAS/CAS/AuthenticationException.php
new file mode 100644 (file)
index 0000000..801156e
--- /dev/null
@@ -0,0 +1,107 @@
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file     CAS/AuthenticationException.php
+ * @category Authentication
+ * @package  PhpCAS
+ * @author   Joachim Fritschi <jfritschi@freenet.de>
+ * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License 2.0
+ * @link     https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * This interface defines methods that allow proxy-authenticated service handlers
+ * to interact with phpCAS.
+ *
+ * Proxy service handlers must implement this interface as well as call
+ * phpCAS::initializeProxiedService($this) at some point in their implementation.
+ *
+ * While not required, proxy-authenticated service handlers are encouraged to
+ * implement the CAS_ProxiedService_Testable interface to facilitate unit testing.
+ *
+ * @class    CAS_AuthenticationException
+ * @category Authentication
+ * @package  PhpCAS
+ * @author   Joachim Fritschi <jfritschi@freenet.de>
+ * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License 2.0
+ * @link     https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+class CAS_AuthenticationException
+extends RuntimeException
+implements CAS_Exception
+{
+
+    /**
+     * This method is used to print the HTML output when the user was not
+     * authenticated.
+     *
+     * @param CAS_Client $client       phpcas client
+     * @param string     $failure      the failure that occured
+     * @param string     $cas_url      the URL the CAS server was asked for
+     * @param bool       $no_response  the response from the CAS server (other
+     * parameters are ignored if TRUE)
+     * @param bool       $bad_response bad response from the CAS server ($err_code
+     * and $err_msg ignored if TRUE)
+     * @param string     $cas_response the response of the CAS server
+     * @param int        $err_code     the error code given by the CAS server
+     * @param string     $err_msg      the error message given by the CAS server
+     */
+    public function __construct($client,$failure,$cas_url,$no_response,
+        $bad_response='',$cas_response='',$err_code='',$err_msg=''
+    ) {
+        phpCAS::traceBegin();
+        $lang = $client->getLangObj();
+        $client->printHTMLHeader($lang->getAuthenticationFailed());
+        printf(
+            $lang->getYouWereNotAuthenticated(),
+            htmlentities($client->getURL()),
+            $_SERVER['SERVER_ADMIN']
+        );
+        phpCAS::trace('CAS URL: '.$cas_url);
+        phpCAS::trace('Authentication failure: '.$failure);
+        if ( $no_response ) {
+            phpCAS::trace('Reason: no response from the CAS server');
+        } else {
+            if ( $bad_response ) {
+                phpCAS::trace('Reason: bad response from the CAS server');
+            } else {
+                switch ($client->getServerVersion()) {
+                case CAS_VERSION_1_0:
+                    phpCAS::trace('Reason: CAS error');
+                    break;
+                case CAS_VERSION_2_0:
+                    if ( empty($err_code) ) {
+                        phpCAS::trace('Reason: no CAS error');
+                    } else {
+                        phpCAS::trace('Reason: ['.$err_code.'] CAS error: '.$err_msg);
+                    }
+                    break;
+                }
+            }
+            phpCAS::trace('CAS response: '.$cas_response);
+        }
+        $client->printHTMLFooter();
+        phpCAS::traceExit();
+    }
+
+}
+?>
diff --git a/auth/cas/CAS/CAS/Autoload.php b/auth/cas/CAS/CAS/Autoload.php
new file mode 100644 (file)
index 0000000..c7d436e
--- /dev/null
@@ -0,0 +1,97 @@
+<?php
+
+/**
+ * Autoloader Class
+ *
+ *  PHP Version 5
+ *
+ * @file      CAS/Autoload.php
+ * @category  Authentication
+ * @package   SimpleCAS
+ * @author    Brett Bieber <brett.bieber@gmail.com>
+ * @copyright 2008 Regents of the University of Nebraska
+ * @license   http://www1.unl.edu/wdn/wiki/Software_License BSD License
+ * @link      http://code.google.com/p/simplecas/
+ **/
+
+/**
+ * Autoload a class
+ *
+ * @param string $class Classname to load
+ *
+ * @return bool
+ */
+function CAS_autoload($class)
+{
+    // Static to hold the Include Path to CAS
+    static $include_path;
+    // Setup the include path if it's not already set from a previous call
+    if (!$include_path) {
+        $include_path = dirname(dirname(__FILE__));
+    }
+    if (substr($class, 0, 4) !== 'CAS_') {
+        return false;
+    }
+    // Declare local variable to store the expected full path to the file
+    $file_path = $include_path . '/' . str_replace('_', '/', $class) . '.php';
+
+    $fp = @fopen($file_path, 'r', true);
+    if ($fp) {
+        fclose($fp);
+        include $file_path;
+        if (!class_exists($class, false) && !interface_exists($class, false)) {
+            die(
+                new Exception(
+                    'Class ' . $class . ' was not present in ' .
+                    $file_path .
+                    ' [CAS_autoload]'
+                )
+            );
+        }
+        return true;
+    }
+    $e = new Exception(
+        'Class ' . $class . ' could not be loaded from ' .
+        $file_path . ', file does not exist (Path="'
+        . $include_path .'") [CAS_autoload]'
+    );
+    $trace = $e->getTrace();
+    if (isset($trace[2]) && isset($trace[2]['function'])
+        && in_array($trace[2]['function'], array('class_exists', 'interface_exists'))
+    ) {
+        return false;
+    }
+    if (isset($trace[1]) && isset($trace[1]['function'])
+        && in_array($trace[1]['function'], array('class_exists', 'interface_exists'))
+    ) {
+        return false;
+    }
+    die ((string) $e);
+}
+
+// set up __autoload
+if (function_exists('spl_autoload_register')) {
+    if (!(spl_autoload_functions()) || !in_array('CAS_autoload', spl_autoload_functions())) {
+        spl_autoload_register('CAS_autoload');
+        if (function_exists('__autoload') && !in_array('__autoload', spl_autoload_functions())) {
+            // __autoload() was being used, but now would be ignored, add
+            // it to the autoload stack
+            spl_autoload_register('__autoload');
+        }
+    }
+} elseif (!function_exists('__autoload')) {
+
+    /**
+     * Autoload a class
+     *
+     * @param string $class Class name
+     *
+     * @return bool
+     */
+    function __autoload($class)
+    {
+        return CAS_autoload($class);
+    }
+}
+
+?>
\ No newline at end of file
diff --git a/auth/cas/CAS/CAS/Client.php b/auth/cas/CAS/CAS/Client.php
new file mode 100644 (file)
index 0000000..f5d0d4e
--- /dev/null
@@ -0,0 +1,3401 @@
+<?php
+
+/**
+ * Licensed to Jasig under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * Jasig licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * PHP Version 5
+ *
+ * @file     CAS/Client.php
+ * @category Authentication
+ * @package  PhpCAS
+ * @author   Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @author   Olivier Berger <olivier.berger@it-sudparis.eu>
+ * @author   Brett Bieber <brett.bieber@gmail.com>
+ * @author   Joachim Fritschi <jfritschi@freenet.de>
+ * @author   Adam Franco <afranco@middlebury.edu>
+ * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License 2.0
+ * @link     https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * The CAS_Client class is a client interface that provides CAS authentication
+ * to PHP applications.
+ *
+ * @class    CAS_Client
+ * @category Authentication
+ * @package  PhpCAS
+ * @author   Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @author   Olivier Berger <olivier.berger@it-sudparis.eu>
+ * @author   Brett Bieber <brett.bieber@gmail.com>
+ * @author   Joachim Fritschi <jfritschi@freenet.de>
+ * @author   Adam Franco <afranco@middlebury.edu>
+ * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License 2.0
+ * @link     https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ */
+
+class CAS_Client
+{
+
+    // ########################################################################
+    //  HTML OUTPUT
+    // ########################################################################
+    /**
+    * @addtogroup internalOutput
+    * @{
+    */
+
+    /**
+     * This method filters a string by replacing special tokens by appropriate values
+     * and prints it. The corresponding tokens are taken into account:
+     * - __CAS_VERSION__
+     * - __PHPCAS_VERSION__
+     * - __SERVER_BASE_URL__
+     *
+     * Used by CAS_Client::PrintHTMLHeader() and CAS_Client::printHTMLFooter().
+     *
+     * @param string $str the string to filter and output
+     *
+     * @return void
+     */
+    private function _htmlFilterOutput($str)
+    {
+        $str = str_replace('__CAS_VERSION__', $this->getServerVersion(), $str);
+        $str = str_replace('__PHPCAS_VERSION__', phpCAS::getVersion(), $str);
+        $str = str_replace('__SERVER_BASE_URL__', $this->_getServerBaseURL(), $str);
+        echo $str;
+    }
+
+    /**
+     * A string used to print the header of HTML pages. Written by
+     * CAS_Client::setHTMLHeader(), read by CAS_Client::printHTMLHeader().
+     *
+     * @hideinitializer
+     * @see CAS_Client::setHTMLHeader, CAS_Client::printHTMLHeader()
+     */
+    private $_output_header = '';
+
+    /**
+     * This method prints the header of the HTML output (after filtering). If
+     * CAS_Client::setHTMLHeader() was not used, a default header is output.
+     *
+     * @param string $title the title of the page
+     *
+     * @return void
+     * @see _htmlFilterOutput()
+     */
+    public function printHTMLHeader($title)
+    {
+        $this->_htmlFilterOutput(
+            str_replace(
+                '__TITLE__', $title,
+                (empty($this->_output_header)
+                ? '<html><head><title>__TITLE__</title></head><body><h1>__TITLE__</h1>'
+                : $this->_output_header)
+            )
+        );
+    }
+
+    /**
+     * A string used to print the footer of HTML pages. Written by
+     * CAS_Client::setHTMLFooter(), read by printHTMLFooter().
+     *
+     * @hideinitializer
+     * @see CAS_Client::setHTMLFooter, CAS_Client::printHTMLFooter()
+     */
+    private $_output_footer = '';
+
+    /**
+     * This method prints the footer of the HTML output (after filtering). If
+     * CAS_Client::setHTMLFooter() was not used, a default footer is output.
+     *
+     * @return void
+     * @see _htmlFilterOutput()
+     */
+    public function printHTMLFooter()
+    {
+        $lang = $this->getLangObj();
+        $this->_htmlFilterOutput(
+            empty($this->_output_footer)?
+            ('<hr><address>phpCAS __PHPCAS_VERSION__ '
+            .$lang->getUsingServer()
+            .' <a href="__SERVER_BASE_URL__">__SERVER_BASE_URL__</a> (CAS __CAS_VERSION__)</a></address></body></html>')
+            :$this->_output_footer
+        );
+    }
+
+    /**
+     * This method set the HTML header used for all outputs.
+     *
+     * @param string $header the HTML header.
+     *
+     * @return void
+     */
+    public function setHTMLHeader($header)
+    {
+        $this->_output_header = $header;
+    }
+
+    /**
+     * This method set the HTML footer used for all outputs.
+     *
+     * @param string $footer the HTML footer.
+     *
+     * @return void
+     */
+    public function setHTMLFooter($footer)
+    {
+        $this->_output_footer = $footer;
+    }
+
+
+    /** @} */
+
+
+    // ########################################################################
+    //  INTERNATIONALIZATION
+    // ########################################################################
+    /**
+    * @addtogroup internalLang
+    * @{
+    */
+    /**
+     * A string corresponding to the language used by phpCAS. Written by
+     * CAS_Client::setLang(), read by CAS_Client::getLang().
+
+     * @note debugging information is always in english (debug purposes only).
+     */
+    private $_lang = PHPCAS_LANG_DEFAULT;
+
+    /**
+     * This method is used to set the language used by phpCAS.
+     *
+     * @param string $lang representing the language.
+     *
+     * @return void
+     */
+    public function setLang($lang)
+    {
+        phpCAS::traceBegin();
+        $obj = new $lang();
+        if (!($obj instanceof CAS_Languages_LanguageInterface)) {
+            throw new CAS_InvalidArgumentException('$className must implement the CAS_Languages_LanguageInterface');
+        }
+        $this->_lang = $lang;
+        phpCAS::traceEnd();
+    }
+    /**
+     * Create the language
+     *
+     * @return CAS_Languages_LanguageInterface object implementing the class
+     */
+    public function getLangObj()
+    {
+        $classname = $this->_lang;
+        return new $classname();
+    }
+
+    /** @} */
+    // ########################################################################
+    //  CAS SERVER CONFIG
+    // ########################################################################
+    /**
+    * @addtogroup internalConfig
+    * @{
+    */
+
+    /**
+     * a record to store information about the CAS server.
+     * - $_server['version']: the version of the CAS server
+     * - $_server['hostname']: the hostname of the CAS server
+     * - $_server['port']: the port the CAS server is running on
+     * - $_server['uri']: the base URI the CAS server is responding on
+     * - $_server['base_url']: the base URL of the CAS server
+     * - $_server['login_url']: the login URL of the CAS server
+     * - $_server['service_validate_url']: the service validating URL of the
+     *   CAS server
+     * - $_server['proxy_url']: the proxy URL of the CAS server
+     * - $_server['proxy_validate_url']: the proxy validating URL of the CAS server
+     * - $_server['logout_url']: the logout URL of the CAS server
+     *
+     * $_server['version'], $_server['hostname'], $_server['port'] and
+     * $_server['uri'] are written by CAS_Client::CAS_Client(), read by
+     * CAS_Client::getServerVersion(), CAS_Client::_getServerHostname(),
+     * CAS_Client::_getServerPort() and CAS_Client::_getServerURI().
+     *
+     * The other fields are written and read by CAS_Client::_getServerBaseURL(),
+     * CAS_Client::getServerLoginURL(), CAS_Client::getServerServiceValidateURL(),
+     * CAS_Client::getServerProxyValidateURL() and CAS_Client::getServerLogoutURL().
+     *
+     * @hideinitializer
+     */
+    private $_server = array(
+        'version' => -1,
+        'hostname' => 'none',
+        'port' => -1,
+        'uri' => 'none');
+
+    /**
+     * This method is used to retrieve the version of the CAS server.
+     *
+     * @return string the version of the CAS server.
+     */
+    public function getServerVersion()
+    {
+        return $this->_server['version'];
+    }
+
+    /**
+     * This method is used to retrieve the hostname of the CAS server.
+     *
+     * @return string the hostname of the CAS server.
+     */
+    private function _getServerHostname()
+    {
+        return $this->_server['hostname'];
+    }
+
+    /**
+     * This method is used to retrieve the port of the CAS server.
+     *
+     * @return string the port of the CAS server.
+     */
+    private function _getServerPort()
+    {
+        return $this->_server['port'];
+    }
+
+    /**
+     * This method is used to retrieve the URI of the CAS server.
+     *
+     * @return string a URI.
+     */
+    private function _getServerURI()
+    {
+        return $this->_server['uri'];
+    }
+
+    /**
+     * This method is used to retrieve the base URL of the CAS server.
+     *
+     * @return string a URL.
+     */
+    private function _getServerBaseURL()
+    {
+        // the URL is build only when needed
+        if ( empty($this->_server['base_url']) ) {
+            $this->_server['base_url'] = 'https://' . $this->_getServerHostname();
+            if ($this->_getServerPort()!=443) {
+                $this->_server['base_url'] .= ':'
+                .$this->_getServerPort();
+            }
+            $this->_server['base_url'] .= $this->_getServerURI();
+        }
+        return $this->_server['base_url'];
+    }
+
+    /**
+     * This method is used to retrieve the login URL of the CAS server.
+     *
+     * @param bool $gateway true to check authentication, false to force it
+     * @param bool $renew   true to force the authentication with the CAS server
+     *
+     * @return a URL.
+     * @note It is recommended that CAS implementations ignore the "gateway"
+     * parameter if "renew" is set
+     */
+    public function getServerLoginURL($gateway=false,$renew=false)
+    {
+        phpCAS::traceBegin();
+        // the URL is build only when needed
+        if ( empty($this->_server['login_url']) ) {
+            $this->_server['login_url'] = $this->_getServerBaseURL();
+            $this->_server['login_url'] .= 'login?service=';
+            $this->_server['login_url'] .= urlencode($this->getURL());
+        }
+        $url = $this->_server['login_url'];
+        if ($renew) {
+            // It is recommended that when the "renew" parameter is set, its
+            // value be "true"
+            $url = $this->_buildQueryUrl($url, 'renew=true');
+        } elseif ($gateway) {
+            // It is recommended that when the "gateway" parameter is set, its
+            // value be "true"
+            $url = $this->_buildQueryUrl($url, 'gateway=true');
+        }
+        phpCAS::traceEnd($url);
+        return $url;
+    }
+
+    /**
+     * This method sets the login URL of the CAS server.
+     *
+     * @param string $url the login URL
+     *
+     * @return string login url
+     */
+    public function setServerLoginURL($url)
+    {
+        return $this->_server['login_url'] = $url;
+    }
+
+
+    /**
+     * This method sets the serviceValidate URL of the CAS server.
+     *
+     * @param string $url the serviceValidate URL
+     *
+     * @return string serviceValidate URL
+     */
+    public function setServerServiceValidateURL($url)
+    {
+        return $this->_server['service_validate_url'] = $url;
+    }
+
+
+    /**
+     * This method sets the proxyValidate URL of the CAS server.
+     *
+     * @param string $url the proxyValidate URL
+     *
+     * @return string proxyValidate URL
+     */
+    public function setServerProxyValidateURL($url)
+    {
+        return $this->_server['proxy_validate_url'] = $url;
+    }
+
+
+    /**
+     * This method sets the samlValidate URL of the CAS server.
+     *
+     * @param string $url the samlValidate URL
+     *
+     * @return string samlValidate URL
+     */
+    public function setServerSamlValidateURL($url)
+    {
+        return $this->_server['saml_validate_url'] = $url;
+    }
+
+
+    /**
+     * This method is used to retrieve the service validating URL of the CAS server.
+     *
+     * @return string serviceValidate URL.
+     */
+    public function getServerServiceValidateURL()
+    {
+        phpCAS::traceBegin();
+        // the URL is build only when needed
+        if ( empty($this->_server['service_validate_url']) ) {
+            switch ($this->getServerVersion()) {
+            case CAS_VERSION_1_0:
+                $this->_server['service_validate_url'] = $this->_getServerBaseURL()
+                .'validate';
+                break;
+            case CAS_VERSION_2_0:
+                $this->_server['service_validate_url'] = $this->_getServerBaseURL()
+                .'serviceValidate';
+                break;
+            }
+        }
+        $url = $this->_buildQueryUrl($this->_server['service_validate_url'], 'service='.urlencode($this->getURL()));
+        phpCAS::traceEnd($url);
+        return $url;
+    }
+    /**
+     * This method is used to retrieve the SAML validating URL of the CAS server.
+     *
+     * @return string samlValidate URL.
+     */
+    public function getServerSamlValidateURL()
+    {
+        phpCAS::traceBegin();
+        // the URL is build only when needed
+        if ( empty($this->_server['saml_validate_url']) ) {
+            switch ($this->getServerVersion()) {
+            case SAML_VERSION_1_1:
+                $this->_server['saml_validate_url'] = $this->_getServerBaseURL().'samlValidate';
+                break;
+            }
+        }
+
+        $url = $this->_buildQueryUrl($this->_server['saml_validate_url'], 'TARGET='.urlencode($this->getURL()));
+        phpCAS::traceEnd($url);
+        return $url;
+    }
+
+    /**
+     * This method is used to retrieve the proxy validating URL of the CAS server.
+     *
+     * @return string proxyValidate URL.
+     */
+    public function getServerProxyValidateURL()
+    {
+        phpCAS::traceBegin();
+        // the URL is build only when needed
+        if ( empty($this->_server['proxy_validate_url']) ) {
+            switch ($this->getServerVersion()) {
+            case CAS_VERSION_1_0:
+                $this->_server['proxy_validate_url'] = '';
+                break;
+            case CAS_VERSION_2_0:
+                $this->_server['proxy_validate_url'] = $this->_getServerBaseURL().'proxyValidate';
+                break;
+            }
+        }
+        $url = $this->_buildQueryUrl($this->_server['proxy_validate_url'], 'service='.urlencode($this->getURL()));
+        phpCAS::traceEnd($url);
+        return $url;
+    }
+
+
+    /**
+     * This method is used to retrieve the proxy URL of the CAS server.
+     *
+     * @return  string proxy URL.
+     */
+    public function getServerProxyURL()
+    {
+        // the URL is build only when needed
+        if ( empty($this->_server['proxy_url']) ) {
+            switch ($this->getServerVersion()) {
+            case CAS_VERSION_1_0:
+                $this->_server['proxy_url'] = '';
+                break;
+            case CAS_VERSION_2_0:
+                $this->_server['proxy_url'] = $this->_getServerBaseURL().'proxy';
+                break;
+            }
+        }
+        return $this->_server['proxy_url'];
+    }
+
+    /**
+     * This method is used to retrieve the logout URL of the CAS server.
+     *
+     * @return string logout URL.
+     */
+    public function getServerLogoutURL()
+    {
+        // the URL is build only when needed
+        if ( empty($this->_server['logout_url']) ) {
+            $this->_server['logout_url'] = $this->_getServerBaseURL().'logout';
+        }
+        return $this->_server['logout_url'];
+    }
+
+    /**
+     * This method sets the logout URL of the CAS server.
+     *
+     * @param string $url the logout URL
+     *
+     * @return string logout url
+     */
+    public function setServerLogoutURL($url)
+    {
+        return $this->_server['logout_url'] = $url;
+    }
+
+    /**
+     * An array to store extra curl options.
+     */
+    private $_curl_options = array();
+
+    /**
+     * This method is used to set additional user curl options.
+     *
+     * @param string $key   name of the curl option
+     * @param string $value value of the curl option
+     *
+     * @return void
+     */
+    public function setExtraCurlOption($key, $value)
+    {
+        $this->_curl_options[$key] = $value;
+    }
+
+    /** @} */
+
+    // ########################################################################
+    //  Change the internal behaviour of phpcas
+    // ########################################################################
+
+    /**
+     * @addtogroup internalBehave
+     * @{
+     */
+
+    /**
+     * The class to instantiate for making web requests in readUrl().
+     * The class specified must implement the CAS_Request_RequestInterface.
+     * By default CAS_Request_CurlRequest is used, but this may be overridden to
+     * supply alternate request mechanisms for testing.
+     */
+    private $_requestImplementation = 'CAS_Request_CurlRequest';
+
+    /**
+     * Override the default implementation used to make web requests in readUrl().
+     * This class must implement the CAS_Request_RequestInterface.
+     *
+     * @param string $className name of the RequestImplementation class
+     *
+     * @return void
+     */
+    public function setRequestImplementation ($className)
+    {
+        $obj = new $className;
+        if (!($obj instanceof CAS_Request_RequestInterface)) {
+            throw new CAS_InvalidArgumentException('$className must implement the CAS_Request_RequestInterface');
+        }
+        $this->_requestImplementation = $className;
+    }
+
+    /**
+     * @var boolean $_clearTicketsFromUrl; If true, phpCAS will clear session
+     * tickets from the URL after a successful authentication.
+     */
+    private $_clearTicketsFromUrl = true;
+
+    /**
+     * Configure the client to not send redirect headers and call exit() on
+     * authentication success. The normal redirect is used to remove the service
+     * ticket from the client's URL, but for running unit tests we need to
+     * continue without exiting.
+     *
+     * Needed for testing authentication
+     *
+     * @return void
+     */
+    public function setNoClearTicketsFromUrl ()
+    {
+        $this->_clearTicketsFromUrl = false;
+    }
+
+    /**
+     * @var callback $_postAuthenticateCallbackFunction;
+     */
+    private $_postAuthenticateCallbackFunction = null;
+
+    /**
+     * @var array $_postAuthenticateCallbackArgs;
+     */
+    private $_postAuthenticateCallbackArgs = array();
+
+    /**
+     * Set a callback function to be run when a user authenticates.
+     *
+     * The callback function will be passed a $logoutTicket as its first parameter,
+     * followed by any $additionalArgs you pass. The $logoutTicket parameter is an
+     * opaque string that can be used to map a session-id to the logout request
+     * in order to support single-signout in applications that manage their own
+     * sessions (rather than letting phpCAS start the session).
+     *
+     * phpCAS::forceAuthentication() will always exit and forward client unless
+     * they are already authenticated. To perform an action at the moment the user
+     * logs in (such as registering an account, performing logging, etc), register
+     * a callback function here.
+     *
+     * @param string $function       callback function to call
+     * @param array  $additionalArgs optional array of arguments
+     *
+     * @return void
+     */
+    public function setPostAuthenticateCallback ($function, array $additionalArgs = array())
+    {
+        $this->_postAuthenticateCallbackFunction = $function;
+        $this->_postAuthenticateCallbackArgs = $additionalArgs;
+    }
+
+    /**
+     * @var callback $_signoutCallbackFunction;
+     */
+    private $_signoutCallbackFunction = null;
+
+    /**
+     * @var array $_signoutCallbackArgs;
+     */
+    private $_signoutCallbackArgs = array();
+
+    /**
+     * Set a callback function to be run when a single-signout request is received.
+     *
+     * The callback function will be passed a $logoutTicket as its first parameter,
+     * followed by any $additionalArgs you pass. The $logoutTicket parameter is an
+     * opaque string that can be used to map a session-id to the logout request in
+     * order to support single-signout in applications that manage their own sessions
+     * (rather than letting phpCAS start and destroy the session).
+     *
+     * @param string $function       callback function to call
+     * @param array  $additionalArgs optional array of arguments
+     *
+     * @return void
+     */
+    public function setSingleSignoutCallback ($function, array $additionalArgs = array())
+    {
+        $this->_signoutCallbackFunction = $function;
+        $this->_signoutCallbackArgs = $additionalArgs;
+    }
+
+    // ########################################################################
+    //  Methods for supplying code-flow feedback to integrators.
+    // ########################################################################
+
+    /**
+     * Mark the caller of authentication. This will help client integraters determine
+     * problems with their code flow if they call a function such as getUser() before
+     * authentication has occurred.
+     *
+     * @param bool $auth True if authentication was successful, false otherwise.
+     *
+     * @return null
+     */
+    public function markAuthenticationCall ($auth)
+    {
+        // store where the authentication has been checked and the result
+        $dbg = debug_backtrace();
+        $this->_authentication_caller = array (
+            'file' => $dbg[1]['file'],
+            'line' => $dbg[1]['line'],
+            'method' => $dbg[1]['class'] . '::' . $dbg[1]['function'],
+            'result' => (boolean)$auth
+        );
+    }
+    private $_authentication_caller;
+
+    /**
+     * Answer true if authentication has been checked.
+     *
+     * @return bool
+     */
+    public function wasAuthenticationCalled ()
+    {
+        return !empty($this->_authentication_caller);
+    }
+
+    /**
+     * Answer the result of the authentication call.
+     *
+     * Throws a CAS_OutOfSequenceException if wasAuthenticationCalled() is false
+     * and markAuthenticationCall() didn't happen.
+     *
+     * @return bool
+     */
+    public function wasAuthenticationCallSuccessful ()
+    {
+        if (empty($this->_authentication_caller)) {
+            throw new CAS_OutOfSequenceException('markAuthenticationCall() hasn\'t happened.');
+        }
+        return $this->_authentication_caller['result'];
+    }
+
+    /**
+     * Answer information about the authentication caller.
+     *
+     * Throws a CAS_OutOfSequenceException if wasAuthenticationCalled() is false
+     * and markAuthenticationCall() didn't happen.
+     *
+     * @return array Keys are 'file', 'line', and 'method'
+     */
+    public function getAuthenticationCallerFile ()
+    {
+        if (empty($this->_authentication_caller)) {
+            throw new CAS_OutOfSequenceException('markAuthenticationCall() hasn\'t happened.');
+        }
+        return $this->_authentication_caller['file'];
+    }
+
+    /**
+     * Answer information about the authentication caller.
+     *
+     * Throws a CAS_OutOfSequenceException if wasAuthenticationCalled() is false
+     * and markAuthenticationCall() didn't happen.
+     *
+     * @return array Keys are 'file', 'line', and 'method'
+     */
+    public function getAuthenticationCallerLine ()
+    {
+        if (empty($this->_authentication_caller)) {
+            throw new CAS_OutOfSequenceException('markAuthenticationCall() hasn\'t happened.');
+        }
+        return $this->_authentication_caller['line'];
+    }
+
+    /**
+     * Answer information about the authentication caller.
+     *
+     * Throws a CAS_OutOfSequenceException if wasAuthenticationCalled() is false
+     * and markAuthenticationCall() didn't happen.
+     *
+     * @return array Keys are 'file', 'line', and 'method'
+     */
+    public function getAuthenticationCallerMethod ()
+    {
+        if (empty($this->_authentication_caller)) {
+            throw new CAS_OutOfSequenceException('markAuthenticationCall() hasn\'t happened.');
+        }
+        return $this->_authentication_caller['method'];
+    }
+
+    /** @} */
+
+    // ########################################################################
+    //  CONSTRUCTOR
+    // ########################################################################
+    /**
+    * @addtogroup internalConfig
+    * @{
+    */
+
+    /**
+     * CAS_Client constructor.
+     *
+     * @param string $server_version  the version of the CAS server
+     * @param bool   $proxy           true if the CAS client is a CAS proxy
+     * @param string $server_hostname the hostname of the CAS server
+     * @param int    $server_port     the port the CAS server is running on
+     * @param string $server_uri      the URI the CAS server is responding on
+     * @param bool   $changeSessionID Allow phpCAS to change the session_id (Single Sign Out/handleLogoutRequests is based on that change)
+     *
+     * @return a newly created CAS_Client object
+     */
+    public function __construct(
+        $server_version,
+        $proxy,
+        $server_hostname,
+        $server_port,
+        $server_uri,
+        $changeSessionID = true
+    ) {
+
+        phpCAS::traceBegin();
+
+        $this->_setChangeSessionID($changeSessionID); // true : allow to change the session_id(), false session_id won't be change and logout won't be handle because of that
+
+        // skip Session Handling for logout requests and if don't want it'
+        if (session_id()=="" && !$this->_isLogoutRequest()) {
+            phpCAS :: trace("Starting a new session");
+            session_start();
+        }
+
+        // are we in proxy mode ?
+        $this->_proxy = $proxy;
+
+        // Make cookie handling available.
+        if ($this->isProxy()) {
+            if (!isset($_SESSION['phpCAS'])) {
+                $_SESSION['phpCAS'] = array();
+            }
+            if (!isset($_SESSION['phpCAS']['service_cookies'])) {
+                $_SESSION['phpCAS']['service_cookies'] = array();
+            }
+            $this->_serviceCookieJar = new CAS_CookieJar($_SESSION['phpCAS']['service_cookies']);
+        }
+
+        //check version
+        switch ($server_version) {
+        case CAS_VERSION_1_0:
+            if ( $this->isProxy() ) {
+                phpCAS::error(
+                    'CAS proxies are not supported in CAS '.$server_version
+                );
+            }
+            break;
+        case CAS_VERSION_2_0:
+            break;
+        case SAML_VERSION_1_1:
+            break;
+        default:
+            phpCAS::error(
+                'this version of CAS (`'.$server_version
+                .'\') is not supported by phpCAS '.phpCAS::getVersion()
+            );
+        }
+        $this->_server['version'] = $server_version;
+
+        // check hostname
+        if ( empty($server_hostname)
+            || !preg_match('/[\.\d\-abcdefghijklmnopqrstuvwxyz]*/', $server_hostname)
+        ) {
+            phpCAS::error('bad CAS server hostname (`'.$server_hostname.'\')');
+        }
+        $this->_server['hostname'] = $server_hostname;
+
+        // check port
+        if ( $server_port == 0
+            || !is_int($server_port)
+        ) {
+            phpCAS::error('bad CAS server port (`'.$server_hostname.'\')');
+        }
+        $this->_server['port'] = $server_port;
+
+        // check URI
+        if ( !preg_match('/[\.\d\-_abcdefghijklmnopqrstuvwxyz\/]*/', $server_uri) ) {
+            phpCAS::error('bad CAS server URI (`'.$server_uri.'\')');
+        }
+        // add leading and trailing `/' and remove doubles
+        $server_uri = preg_replace('/\/\//', '/', '/'.$server_uri.'/');
+        $this->_server['uri'] = $server_uri;
+
+        // set to callback mode if PgtIou and PgtId CGI GET parameters are provided
+        if ( $this->isProxy() ) {
+            $this->_setCallbackMode(!empty($_GET['pgtIou'])&&!empty($_GET['pgtId']));
+        }
+
+        if ( $this->_isCallbackMode() ) {
+            //callback mode: check that phpCAS is secured
+            if ( !$this->_isHttps() ) {
+                phpCAS::error('CAS proxies must be secured to use phpCAS; PGT\'s will not be received from the CAS server');
+            }
+        } else {
+            //normal mode: get ticket and remove it from CGI parameters for
+            // developers
+            $ticket = (isset($_GET['ticket']) ? $_GET['ticket'] : null);
+            if (preg_match('/^[SP]T-/', $ticket) ) {
+                phpCAS::trace('Ticket \''.$ticket.'\' found');
+                $this->setTicket($ticket);
+                unset($_GET['ticket']);
+            } else if ( !empty($ticket) ) {
+                //ill-formed ticket, halt
+                phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')');
+            }
+
+        }
+        phpCAS::traceEnd();
+    }
+
+    /** @} */
+
+    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+    // XX                                                                    XX
+    // XX                           Session Handling                         XX
+    // XX                                                                    XX
+    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+
+    /**
+     * @addtogroup internalConfig
+     * @{
+     */
+
+
+    /**
+     * A variable to whether phpcas will use its own session handling. Default = true
+     * @hideinitializer
+     */
+    private $_change_session_id = true;
+
+    /**
+     * Set a parameter whether to allow phpCas to change session_id
+     *
+     * @param bool $allowed allow phpCas to change session_id
+     *
+     * @return void
+     */
+    private function _setChangeSessionID($allowed)
+    {
+        $this->_change_session_id = $allowed;
+    }
+
+    /**
+     * Get whether phpCas is allowed to change session_id
+     *
+     * @return bool
+     */
+    public function getChangeSessionID()
+    {
+        return $this->_change_session_id;
+    }
+
+    /** @} */
+
+    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+    // XX                                                                    XX
+    // XX                           AUTHENTICATION                           XX
+    // XX                                                                    XX
+    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+
+    /**
+     * @addtogroup internalAuthentication
+     * @{
+     */
+
+    /**
+     * The Authenticated user. Written by CAS_Client::_setUser(), read by
+     * CAS_Client::getUser().
+     *
+     * @hideinitializer
+     */
+    private $_user = '';
+
+    /**
+     * This method sets the CAS user's login name.
+     *
+     * @param string $user the login name of the authenticated user.
+     *
+     * @return void
+     */
+    private function _setUser($user)
+    {
+        $this->_user = $user;
+    }
+
+    /**
+     * This method returns the CAS user's login name.
+     *
+     * @return string the login name of the authenticated user
+     *
+     * @warning should be called only after CAS_Client::forceAuthentication() or
+     * CAS_Client::isAuthenticated(), otherwise halt with an error.
+     */
+    public function getUser()
+    {
+        if ( empty($this->_user) ) {
+            phpCAS::error(
+                'this method should be used only after '.__CLASS__
+                .'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()'
+            );
+        }
+        return $this->_user;
+    }
+
+    /**
+     * The Authenticated users attributes. Written by
+     * CAS_Client::setAttributes(), read by CAS_Client::getAttributes().
+     * @attention client applications should use phpCAS::getAttributes().
+     *
+     * @hideinitializer
+     */
+    private $_attributes = array();
+
+    /**
+     * Set an array of attributes
+     *
+     * @param array $attributes a key value array of attributes
+     *
+     * @return void
+     */
+    public function setAttributes($attributes)
+    {
+        $this->_attributes = $attributes;
+    }
+
+    /**
+     * Get an key values arry of attributes
+     *
+     * @return arry of attributes
+     */
+    public function getAttributes()
+    {
+        if ( empty($this->_user) ) {
+            // if no user is set, there shouldn't be any attributes also...
+            phpCAS::error(
+                'this method should be used only after '.__CLASS__
+                .'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()'
+            );
+        }
+        return $this->_attributes;
+    }
+
+    /**
+     * Check whether attributes are available
+     *
+     * @return bool attributes available
+     */
+    public function hasAttributes()
+    {
+        return !empty($this->_attributes);
+    }
+    /**
+     * Check whether a specific attribute with a name is available
+     *
+     * @param string $key name of attribute
+     *
+     * @return bool is attribute available
+     */
+    public function hasAttribute($key)
+    {
+        return (is_array($this->_attributes)
+            && array_key_exists($key, $this->_attributes));
+    }
+
+    /**
+     * Get a specific attribute by name
+     *
+     * @param string $key name of attribute
+     *
+     * @return string attribute values
+     */
+    public function getAttribute($key)
+    {
+        if ($this->hasAttribute($key)) {
+            return $this->_attributes[$key];
+        }
+    }
+
+    /**
+     * This method is called to renew the authentication of the user
+     * If the user is authenticated, renew the connection
+     * If not, redirect to CAS
+     *
+     * @return  void
+     */
+    public function renewAuthentication()
+    {
+        phpCAS::traceBegin();
+        // Either way, the user is authenticated by CAS
+        if (isset( $_SESSION['phpCAS']['auth_checked'])) {
+            unset($_SESSION['phpCAS']['auth_checked']);
+        }
+        if ( $this->isAuthenticated() ) {
+            phpCAS::trace('user already authenticated; renew');
+            $this->redirectToCas(false, true);
+        } else {
+            $this->redirectToCas();
+        }
+        phpCAS::traceEnd();
+    }
+
+    /**
+     * This method is called to be sure that the user is authenticated. When not
+     * authenticated, halt by redirecting to the CAS server; otherwise return true.
+     *
+     * @return true when the user is authenticated; otherwise halt.
+     */
+    public function forceAuthentication()
+    {
+        phpCAS::traceBegin();
+
+        if ( $this->isAuthenticated() ) {
+            // the user is authenticated, nothing to be done.
+            phpCAS::trace('no need to authenticate');
+            $res = true;
+        } else {
+            // the user is not authenticated, redirect to the CAS server
+            if (isset($_SESSION['phpCAS']['auth_checked'])) {
+                unset($_SESSION['phpCAS']['auth_checked']);
+            }
+            $this->redirectToCas(false/* no gateway */);
+            // never reached
+            $res = false;
+        }
+        phpCAS::traceEnd($res);
+        return $res;
+    }
+
+    /**
+     * An integer that gives the number of times authentication will be cached
+     * before rechecked.
+     *
+     * @hideinitializer
+     */
+    private $_cache_times_for_auth_recheck = 0;
+
+    /**
+     * Set the number of times authentication will be cached before rechecked.
+     *
+     * @param int $n number of times to wait for a recheck
+     *
+     * @return void
+     */
+    public function setCacheTimesForAuthRecheck($n)
+    {
+        $this->_cache_times_for_auth_recheck = $n;
+    }
+
+    /**
+     * This method is called to check whether the user is authenticated or not.
+     *
+     * @return true when the user is authenticated, false when a previous
+     * gateway login failed or  the function will not return if the user is
+     * redirected to the cas server for a gateway login attempt
+     */
+    public function checkAuthentication()
+    {
+        phpCAS::traceBegin();
+        $res = false;
+        if ( $this->isAuthenticated() ) {
+            phpCAS::trace('user is authenticated');
+            /* The 'auth_checked' variable is removed just in case it's set. */
+            unset($_SESSION['phpCAS']['auth_checked']);
+            $res = true;
+        } else if (isset($_SESSION['phpCAS']['auth_checked'])) {
+            // the previous request has redirected the client to the CAS server
+            // with gateway=true
+            unset($_SESSION['phpCAS']['auth_checked']);
+            $res = false;
+        } else {
+            // avoid a check against CAS on every request
+            if (!isset($_SESSION['phpCAS']['unauth_count'])) {
+                $_SESSION['phpCAS']['unauth_count'] = -2; // uninitialized
+            }
+
+            if (($_SESSION['phpCAS']['unauth_count'] != -2
+                && $this->_cache_times_for_auth_recheck == -1)
+                || ($_SESSION['phpCAS']['unauth_count'] >= 0
+                && $_SESSION['phpCAS']['unauth_count'] < $this->_cache_times_for_auth_recheck)
+            ) {
+                $res = false;
+
+                if ($this->_cache_times_for_auth_recheck != -1) {
+                    $_SESSION['phpCAS']['unauth_count']++;
+                    phpCAS::trace(
+                        'user is not authenticated (cached for '
+                        .$_SESSION['phpCAS']['unauth_count'].' times of '
+                        .$this->_cache_times_for_auth_recheck.')'
+                    );
+                } else {
+                    phpCAS::trace('user is not authenticated (cached for until login pressed)');
+                }
+            } else {
+                $_SESSION['phpCAS']['unauth_count'] = 0;
+                $_SESSION['phpCAS']['auth_checked'] = true;
+                phpCAS::trace('user is not authenticated (cache reset)');
+                $this->redirectToCas(true/* gateway */);
+                // never reached
+                $res = false;
+            }
+        }
+        phpCAS::traceEnd($res);
+        return $res;
+    }
+
+    /**
+     * This method is called to check if the user is authenticated (previously or by
+     * tickets given in the URL).
+     *
+     * @return true when the user is authenticated. Also may redirect to the
+     * same URL without the ticket.
+     */
+    public function isAuthenticated()
+    {
+        phpCAS::traceBegin();
+        $res = false;
+        $validate_url = '';
+        if ( $this->_wasPreviouslyAuthenticated() ) {
+            if ($this->hasTicket()) {
+                // User has a additional ticket but was already authenticated
+                phpCAS::trace('ticket was present and will be discarded, use renewAuthenticate()');
+                if ($this->_clearTicketsFromUrl) {
+                    phpCAS::trace("Prepare redirect to : ".$this->getURL());
+                    header('Location: '.$this->getURL());
+                    flush();
+                    phpCAS::traceExit();
+                    throw new CAS_GracefullTerminationException();
+                } else {
+                    phpCAS::trace('Already authenticated, but skipping ticket clearing since setNoClearTicketsFromUrl() was used.');
+                    $res = true;
+                }
+            } else {
+                // the user has already (previously during the session) been
+                // authenticated, nothing to be done.
+                phpCAS::trace('user was already authenticated, no need to look for tickets');
+                $res = true;
+            }
+        } else {
+            if ($this->hasTicket()) {
+                switch ($this->getServerVersion()) {
+                case CAS_VERSION_1_0:
+                    // if a Service Ticket was given, validate it
+                    phpCAS::trace('CAS 1.0 ticket `'.$this->getTicket().'\' is present');
+                    $this->validateCAS10($validate_url, $text_response, $tree_response); // if it fails, it halts
+                    phpCAS::trace('CAS 1.0 ticket `'.$this->getTicket().'\' was validated');
+                    $_SESSION['phpCAS']['user'] = $this->getUser();
+                    $res = true;
+                    $logoutTicket = $this->getTicket();
+                    break;
+                case CAS_VERSION_2_0:
+                    // if a Proxy Ticket was given, validate it
+                    phpCAS::trace('CAS 2.0 ticket `'.$this->getTicket().'\' is present');
+                    $this->validateCAS20($validate_url, $text_response, $tree_response); // note: if it fails, it halts
+                    phpCAS::trace('CAS 2.0 ticket `'.$this->getTicket().'\' was validated');
+                    if ( $this->isProxy() ) {
+                        $this->_validatePGT($validate_url, $text_response, $tree_response); // idem
+                        phpCAS::trace('PGT `'.$this->_getPGT().'\' was validated');
+                        $_SESSION['phpCAS']['pgt'] = $this->_getPGT();
+                    }
+                    $_SESSION['phpCAS']['user'] = $this->getUser();
+                    if ($this->hasAttributes()) {
+                        $_SESSION['phpCAS']['attributes'] = $this->getAttributes();
+                    }
+                    $proxies = $this->getProxies();
+                    if (!empty($proxies)) {
+                        $_SESSION['phpCAS']['proxies'] = $this->getProxies();
+                    }
+                    $res = true;
+                    $logoutTicket = $this->getTicket();
+                    break;
+                case SAML_VERSION_1_1:
+                    // if we have a SAML ticket, validate it.
+                    phpCAS::trace('SAML 1.1 ticket `'.$this->getTicket().'\' is present');
+                    $this->validateSA($validate_url, $text_response, $tree_response); // if it fails, it halts
+                    phpCAS::trace('SAML 1.1 ticket `'.$this->getTicket().'\' was validated');
+                    $_SESSION['phpCAS']['user'] = $this->getUser();
+                    $_SESSION['phpCAS']['attributes'] = $this->getAttributes();
+                    $res = true;
+                    $logoutTicket = $this->getTicket();
+                    break;
+                default:
+                    phpCAS::trace('Protocoll error');
+                    break;
+                }
+            } else {
+                // no ticket given, not authenticated
+                phpCAS::trace('no ticket found');
+            }
+            if ($res) {
+                // Mark the auth-check as complete to allow post-authentication
+                // callbacks to make use of phpCAS::getUser() and similar methods
+                $this->markAuthenticationCall($res);
+
+                // call the post-authenticate callback if registered.
+                if ($this->_postAuthenticateCallbackFunction) {
+                    $args = $this->_postAuthenticateCallbackArgs;
+                    array_unshift($args, $logoutTicket);
+                    call_user_func_array($this->_postAuthenticateCallbackFunction, $args);
+                }
+
+                // if called with a ticket parameter, we need to redirect to the
+                // app without the ticket so that CAS-ification is transparent
+                // to the browser (for later POSTS) most of the checks and
+                // errors should have been made now, so we're safe for redirect
+                // without masking error messages. remove the ticket as a
+                // security precaution to prevent a ticket in the HTTP_REFERRER
+                if ($this->_clearTicketsFromUrl) {
+                    phpCAS::trace("Prepare redirect to : ".$this->getURL());
+                    header('Location: '.$this->getURL());
+                    flush();
+                    phpCAS::traceExit();
+                    throw new CAS_GracefullTerminationException();
+                }
+            }
+        }
+
+        phpCAS::traceEnd($res);
+        return $res;
+    }
+
+    /**
+     * This method tells if the current session is authenticated.
+     *
+     * @return true if authenticated based soley on $_SESSION variable
+     */
+    public function isSessionAuthenticated ()
+    {
+        return !empty($_SESSION['phpCAS']['user']);
+    }
+
+    /**
+     * This method tells if the user has already been (previously) authenticated
+     * by looking into the session variables.
+     *
+     * @note This function switches to callback mode when needed.
+     *
+     * @return true when the user has already been authenticated; false otherwise.
+     */
+    private function _wasPreviouslyAuthenticated()
+    {
+        phpCAS::traceBegin();
+
+        if ( $this->_isCallbackMode() ) {
+            // Rebroadcast the pgtIou and pgtId to all nodes
+            if ($this->_rebroadcast&&!isset($_POST['rebroadcast'])) {
+                $this->_rebroadcast(self::PGTIOU);
+            }
+            $this->_callback();
+        }
+
+        $auth = false;
+
+        if ( $this->isProxy() ) {
+            // CAS proxy: username and PGT must be present
+            if ( $this->isSessionAuthenticated() && !empty($_SESSION['phpCAS']['pgt']) ) {
+                // authentication already done
+                $this->_setUser($_SESSION['phpCAS']['user']);
+                if (isset($_SESSION['phpCAS']['attributes'])) {
+                    $this->setAttributes($_SESSION['phpCAS']['attributes']);
+                }
+                $this->_setPGT($_SESSION['phpCAS']['pgt']);
+                phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\', PGT = `'.$_SESSION['phpCAS']['pgt'].'\'');
+
+                // Include the list of proxies
+                if (isset($_SESSION['phpCAS']['proxies'])) {
+                    $this->_setProxies($_SESSION['phpCAS']['proxies']);
+                    phpCAS::trace('proxies = "'.implode('", "', $_SESSION['phpCAS']['proxies']).'"');
+                }
+
+                $auth = true;
+            } elseif ( $this->isSessionAuthenticated() && empty($_SESSION['phpCAS']['pgt']) ) {
+                // these two variables should be empty or not empty at the same time
+                phpCAS::trace('username found (`'.$_SESSION['phpCAS']['user'].'\') but PGT is empty');
+                // unset all tickets to enforce authentication
+                unset($_SESSION['phpCAS']);
+                $this->setTicket('');
+            } elseif ( !$this->isSessionAuthenticated() && !empty($_SESSION['phpCAS']['pgt']) ) {
+                // these two variables should be empty or not empty at the same time
+                phpCAS::trace('PGT found (`'.$_SESSION['phpCAS']['pgt'].'\') but username is empty');
+                // unset all tickets to enforce authentication
+                unset($_SESSION['phpCAS']);
+                $this->setTicket('');
+            } else {
+                phpCAS::trace('neither user nor PGT found');
+            }
+        } else {
+            // `simple' CAS client (not a proxy): username must be present
+            if ( $this->isSessionAuthenticated() ) {
+                // authentication already done
+                $this->_setUser($_SESSION['phpCAS']['user']);
+                if (isset($_SESSION['phpCAS']['attributes'])) {
+                    $this->setAttributes($_SESSION['phpCAS']['attributes']);
+                }
+                phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\'');
+
+                // Include the list of proxies
+                if (isset($_SESSION['phpCAS']['proxies'])) {
+                    $this->_setProxies($_SESSION['phpCAS']['proxies']);
+                    phpCAS::trace('proxies = "'.implode('", "', $_SESSION['phpCAS']['proxies']).'"');
+                }
+
+                $auth = true;
+            } else {
+                phpCAS::trace('no user found');
+            }
+        }
+
+        phpCAS::traceEnd($auth);
+        return $auth;
+    }
+
+    /**
+     * This method is used to redirect the client to the CAS server.
+     * It is used by CAS_Client::forceAuthentication() and
+     * CAS_Client::checkAuthentication().
+     *
+     * @param bool $gateway true to check authentication, false to force it
+     * @param bool $renew   true to force the authentication with the CAS server
+     *
+     * @return void
+     */
+    public function redirectToCas($gateway=false,$renew=false)
+    {
+        phpCAS::traceBegin();
+        $cas_url = $this->getServerLoginURL($gateway, $renew);
+        if (php_sapi_name() === 'cli') {
+            @header('Location: '.$cas_url);
+        } else {
+            header('Location: '.$cas_url);
+        }
+        phpCAS::trace("Redirect to : ".$cas_url);
+        $lang = $this->getLangObj();
+        $this->printHTMLHeader($lang->getAuthenticationWanted());
+        printf('<p>'. $lang->getShouldHaveBeenRedirected(). '</p>', $cas_url);
+        $this->printHTMLFooter();
+        phpCAS::traceExit();
+        throw new CAS_GracefullTerminationException();
+    }
+
+
+    /**
+     * This method is used to logout from CAS.
+     *
+     * @param array $params an array that contains the optional url and service
+     * parameters that will be passed to the CAS server
+     *
+     * @return void
+     */
+    public function logout($params)
+    {
+        phpCAS::traceBegin();
+        $cas_url = $this->getServerLogoutURL();
+        $paramSeparator = '?';
+        if (isset($params['url'])) {
+            $cas_url = $cas_url . $paramSeparator . "url=" . urlencode($params['url']);
+            $paramSeparator = '&';
+        }
+        if (isset($params['service'])) {
+            $cas_url = $cas_url . $paramSeparator . "service=" . urlencode($params['service']);
+        }
+        header('Location: '.$cas_url);
+        phpCAS::trace("Prepare redirect to : ".$cas_url);
+
+        session_unset();
+        session_destroy();
+        $lang = $this->getLangObj();
+        $this->printHTMLHeader($lang->getLogout());
+        printf('<p>'.$lang->getShouldHaveBeenRedirected(). '</p>', $cas_url);
+        $this->printHTMLFooter();
+        phpCAS::traceExit();
+        throw new CAS_GracefullTerminationException();
+    }
+
+    /**
+     * Check of the current request is a logout request
+     *
+     * @return bool is logout request.
+     */
+    private function _isLogoutRequest()
+    {
+        return !empty($_POST['logoutRequest']);
+    }
+
+    /**
+     * This method handles logout requests.
+     *
+     * @param bool $check_client    true to check the client bofore handling
+     * the request, false not to perform any access control. True by default.
+     * @param bool $allowed_clients an array of host names allowed to send
+     * logout requests.
+     *
+     * @return void
+     */
+    public function handleLogoutRequests($check_client=true, $allowed_clients=false)
+    {
+        phpCAS::traceBegin();
+        if (!$this->_isLogoutRequest()) {
+            phpCAS::trace("Not a logout request");
+            phpCAS::traceEnd();
+            return;
+        }
+        if (!$this->getChangeSessionID() && is_null($this->_signoutCallbackFunction)) {
+            phpCAS::trace("phpCAS can't handle logout requests if it is not allowed to change session_id.");
+        }
+        phpCAS::trace("Logout requested");
+        $decoded_logout_rq = urldecode($_POST['logoutRequest']);
+        phpCAS::trace("SAML REQUEST: ".$decoded_logout_rq);
+        $allowed = false;
+        if ($check_client) {
+            if (!$allowed_clients) {
+                $allowed_clients = array( $this->_getServerHostname() );
+            }
+            $client_ip = $_SERVER['REMOTE_ADDR'];
+            $client = gethostbyaddr($client_ip);
+            phpCAS::trace("Client: ".$client."/".$client_ip);
+            foreach ($allowed_clients as $allowed_client) {
+                if (($client == $allowed_client) or ($client_ip == $allowed_client)) {
+                    phpCAS::trace("Allowed client '".$allowed_client."' matches, logout request is allowed");
+                    $allowed = true;
+                    break;
+                } else {
+                    phpCAS::trace("Allowed client '".$allowed_client."' does not match");
+                }
+            }
+        } else {
+            phpCAS::trace("No access control set");
+            $allowed = true;
+        }
+        // If Logout command is permitted proceed with the logout
+        if ($allowed) {
+            phpCAS::trace("Logout command allowed");
+            // Rebroadcast the logout request
+            if ($this->_rebroadcast && !isset($_POST['rebroadcast'])) {
+                $this->_rebroadcast(self::LOGOUT);
+            }
+            // Extract the ticket from the SAML Request
+            preg_match("|<samlp:SessionIndex>(.*)</samlp:SessionIndex>|", $decoded_logout_rq, $tick, PREG_OFFSET_CAPTURE, 3);
+            $wrappedSamlSessionIndex = preg_replace('|<samlp:SessionIndex>|', '', $tick[0][0]);
+            $ticket2logout = preg_replace('|</samlp:SessionIndex>|', '', $wrappedSamlSessionIndex);
+            phpCAS::trace("Ticket to logout: ".$ticket2logout);
+
+            // call the post-authenticate callback if registered.
+            if ($this->_signoutCallbackFunction) {
+                $args = $this->_signoutCallbackArgs;
+                array_unshift($args, $ticket2logout);
+                call_user_func_array($this->_signoutCallbackFunction, $args);
+            }
+
+            // If phpCAS is managing the session_id, destroy session thanks to session_id.
+            if ($this->getChangeSessionID()) {
+                $session_id = preg_replace('/[^a-zA-Z0-9\-]/', '', $ticket2logout);
+                phpCAS::trace("Session id: ".$session_id);
+
+                // destroy a possible application session created before phpcas
+                if (session_id() !== "") {
+                    session_unset();
+                    session_destroy();
+                }
+                // fix session ID
+                session_id($session_id);
+                $_COOKIE[session_name()]=$session_id;
+                $_GET[session_name()]=$session_id;
+
+                // Overwrite session
+                session_start();
+                session_unset();
+                session_destroy();
+                phpCAS::trace("Session ". $session_id . " destroyed");
+            }
+        } else {
+            phpCAS::error("Unauthorized logout request from client '".$client."'");
+            phpCAS::trace("Unauthorized logout request from client '".$client."'");
+        }
+        flush();
+        phpCAS::traceExit();
+        throw new CAS_GracefullTerminationException();
+
+    }
+
+    /** @} */
+
+    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+    // XX                                                                    XX
+    // XX                  BASIC CLIENT FEATURES (CAS 1.0)                   XX
+    // XX                                                                    XX
+    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+
+    // ########################################################################
+    //  ST
+    // ########################################################################
+    /**
+    * @addtogroup internalBasic
+    * @{
+    */
+
+    /**
+     * The Ticket provided in the URL of the request if present
+     * (empty otherwise). Written by CAS_Client::CAS_Client(), read by
+     * CAS_Client::getTicket() and CAS_Client::_hasPGT().
+     *
+     * @hideinitializer
+     */
+    private $_ticket = '';
+
+    /**
+     * This method returns the Service Ticket provided in the URL of the request.
+     *
+     * @return string service ticket.
+     */
+    public  function getTicket()
+    {
+        return $this->_ticket;
+    }
+
+    /**
+     * This method stores the Service Ticket.
+     *
+     * @param string $st The Service Ticket.
+     *
+     * @return void
+     */
+    public function setTicket($st)
+    {
+        $this->_ticket = $st;
+    }
+
+    /**
+     * This method tells if a Service Ticket was stored.
+     *
+     * @return bool if a Service Ticket has been stored.
+     */
+    public function hasTicket()
+    {
+        return !empty($this->_ticket);
+    }
+
+    /** @} */
+
+    // ########################################################################
+    //  ST VALIDATION
+    // ########################################################################
+    /**
+    * @addtogroup internalBasic
+    * @{
+    */
+
+    /**
+     * the certificate of the CAS server CA.
+     *
+     * @hideinitializer
+     */
+    private $_cas_server_ca_cert = null;
+
+
+    /**\r
+     * validate CN of the CAS server certificate\r
+     *\r
+     * @hideinitializer\r
+     */\r
+    private $_cas_server_cn_validate = true;
+
+    /**
+     * Set to true not to validate the CAS server.
+     *
+     * @hideinitializer
+     */
+    private $_no_cas_server_validation = false;
+
+
+    /**
+     * Set the CA certificate of the CAS server.
+     *
+     * @param string $cert        the PEM certificate file name of the CA that emited
+     * the cert of the server
+     * @param bool   $validate_cn valiate CN of the CAS server certificate
+     *
+     * @return void
+     */
+    public function setCasServerCACert($cert, $validate_cn)
+    {
+        $this->_cas_server_ca_cert = $cert;
+        $this->_cas_server_cn_validate = $validate_cn;
+    }
+
+    /**
+     * Set no SSL validation for the CAS server.
+     *
+     * @return void
+     */
+    public function setNoCasSer