-<?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
-if (!isset($_SERVER['REQUEST_URI'])) {\r
- $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] . '?' . $_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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
+ */
+?>
--- /dev/null
+<?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();
+ }
+
+}
+?>
--- /dev/null
+<?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
--- /dev/null
+<?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 setNoCasServerValidation()
+ {
+ $this->_no_cas_server_validation = true;
+ }
+
+ /**
+ * This method is used to validate a CAS 1,0 ticket; halt on failure, and
+ * sets $validate_url, $text_reponse and $tree_response on success.
+ *
+ * @param string &$validate_url reference to the the URL of the request to
+ * the CAS server.
+ * @param string &$text_response reference to the response of the CAS
+ * server, as is (XML text).
+ * @param string &$tree_response reference to the response of the CAS
+ * server, as a DOM XML tree.
+ *
+ * @return bool true when successfull and issue a CAS_AuthenticationException
+ * and false on an error
+ */
+ public function validateCAS10(&$validate_url,&$text_response,&$tree_response)
+ {
+ phpCAS::traceBegin();
+ $result = false;
+ // build the URL to validate the ticket
+ $validate_url = $this->getServerServiceValidateURL().'&ticket='.$this->getTicket();
+
+ // open and read the URL
+ if ( !$this->_readURL($validate_url, $headers, $text_response, $err_msg) ) {
+ phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
+ throw new CAS_AuthenticationException(
+ $this, 'CAS 1.0 ticket not validated', $validate_url,
+ true/*$no_response*/
+ );
+ $result = false;
+ }
+
+ if (preg_match('/^no\n/', $text_response)) {
+ phpCAS::trace('Ticket has not been validated');
+ throw new CAS_AuthenticationException(
+ $this, 'ST not validated', $validate_url, false/*$no_response*/,
+ false/*$bad_response*/, $text_response
+ );
+ $result = false;
+ } else if (!preg_match('/^yes\n/', $text_response)) {
+ phpCAS::trace('ill-formed response');
+ throw new CAS_AuthenticationException(
+ $this, 'Ticket not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/, $text_response
+ );
+ $result = false;
+ }
+ // ticket has been validated, extract the user name
+ $arr = preg_split('/\n/', $text_response);
+ $this->_setUser(trim($arr[1]));
+ $result = true;
+
+ if ($result) {
+ $this->_renameSession($this->getTicket());
+ }
+ // at this step, ticket has been validated and $this->_user has been set,
+ phpCAS::traceEnd(true);
+ return true;
+ }
+
+ /** @} */
+
+
+ // ########################################################################
+ // SAML VALIDATION
+ // ########################################################################
+ /**
+ * @addtogroup internalSAML
+ * @{
+ */
+
+ /**
+ * This method is used to validate a SAML TICKET; halt on failure, and sets
+ * $validate_url, $text_reponse and $tree_response on success. These
+ * parameters are used later by CAS_Client::_validatePGT() for CAS proxies.
+ *
+ * @param string &$validate_url reference to the the URL of the request to
+ * the CAS server.
+ * @param string &$text_response reference to the response of the CAS
+ * server, as is (XML text).
+ * @param string &$tree_response reference to the response of the CAS
+ * server, as a DOM XML tree.
+ *
+ * @return bool true when successfull and issue a CAS_AuthenticationException
+ * and false on an error
+ */
+ public function validateSA(&$validate_url,&$text_response,&$tree_response)
+ {
+ phpCAS::traceBegin();
+ $result = false;
+ // build the URL to validate the ticket
+ $validate_url = $this->getServerSamlValidateURL();
+
+ // open and read the URL
+ if ( !$this->_readURL($validate_url, $headers, $text_response, $err_msg) ) {
+ phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
+ throw new CAS_AuthenticationException($this, 'SA not validated', $validate_url, true/*$no_response*/);
+ }
+
+ phpCAS::trace('server version: '.$this->getServerVersion());
+
+ // analyze the result depending on the version
+ switch ($this->getServerVersion()) {
+ case SAML_VERSION_1_1:
+ // create new DOMDocument Object
+ $dom = new DOMDocument();
+ // Fix possible whitspace problems
+ $dom->preserveWhiteSpace = false;
+ // read the response of the CAS server into a DOM object
+ if (!($dom->loadXML($text_response))) {
+ phpCAS::trace('dom->loadXML() failed');
+ throw new CAS_AuthenticationException(
+ $this, 'SA not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/,
+ $text_response
+ );
+ $result = false;
+ }
+ // read the root node of the XML tree
+ if (!($tree_response = $dom->documentElement)) {
+ phpCAS::trace('documentElement() failed');
+ throw new CAS_AuthenticationException(
+ $this, 'SA not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/,
+ $text_response
+ );
+ $result = false;
+ } else if ( $tree_response->localName != 'Envelope' ) {
+ // insure that tag name is 'Envelope'
+ phpCAS::trace('bad XML root node (should be `Envelope\' instead of `'.$tree_response->localName.'\'');
+ throw new CAS_AuthenticationException(
+ $this, 'SA not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/,
+ $text_response
+ );
+ $result = false;
+ } else if ($tree_response->getElementsByTagName("NameIdentifier")->length != 0) {
+ // check for the NameIdentifier tag in the SAML response
+ $success_elements = $tree_response->getElementsByTagName("NameIdentifier");
+ phpCAS::trace('NameIdentifier found');
+ $user = trim($success_elements->item(0)->nodeValue);
+ phpCAS::trace('user = `'.$user.'`');
+ $this->_setUser($user);
+ $this->_setSessionAttributes($text_response);
+ $result = true;
+ } else {
+ phpCAS::trace('no <NameIdentifier> tag found in SAML payload');
+ throw new CAS_AuthenticationException(
+ $this, 'SA not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/,
+ $text_response
+ );
+ $result = false;
+ }
+ }
+ if ($result) {
+ $this->_renameSession($this->getTicket());
+ }
+ // at this step, ST has been validated and $this->_user has been set,
+ phpCAS::traceEnd($result);
+ return $result;
+ }
+
+ /**
+ * This method will parse the DOM and pull out the attributes from the SAML
+ * payload and put them into an array, then put the array into the session.
+ *
+ * @param string $text_response the SAML payload.
+ *
+ * @return bool true when successfull and false if no attributes a found
+ */
+ private function _setSessionAttributes($text_response)
+ {
+ phpCAS::traceBegin();
+
+ $result = false;
+
+ $attr_array = array();
+
+ // create new DOMDocument Object
+ $dom = new DOMDocument();
+ // Fix possible whitspace problems
+ $dom->preserveWhiteSpace = false;
+ if (($dom->loadXML($text_response))) {
+ $xPath = new DOMXpath($dom);
+ $xPath->registerNamespace('samlp', 'urn:oasis:names:tc:SAML:1.0:protocol');
+ $xPath->registerNamespace('saml', 'urn:oasis:names:tc:SAML:1.0:assertion');
+ $nodelist = $xPath->query("//saml:Attribute");
+
+ if ($nodelist) {
+ foreach ($nodelist as $node) {
+ $xres = $xPath->query("saml:AttributeValue", $node);
+ $name = $node->getAttribute("AttributeName");
+ $value_array = array();
+ foreach ($xres as $node2) {
+ $value_array[] = $node2->nodeValue;
+ }
+ $attr_array[$name] = $value_array;
+ }
+ // UGent addition...
+ foreach ($attr_array as $attr_key => $attr_value) {
+ if (count($attr_value) > 1) {
+ $this->_attributes[$attr_key] = $attr_value;
+ phpCAS::trace("* " . $attr_key . "=" . $attr_value);
+ } else {
+ $this->_attributes[$attr_key] = $attr_value[0];
+ phpCAS::trace("* " . $attr_key . "=" . $attr_value[0]);
+ }
+ }
+ $result = true;
+ } else {
+ phpCAS::trace("SAML Attributes are empty");
+ $result = false;
+ }
+ }
+ phpCAS::traceEnd($result);
+ return $result;
+ }
+
+ /** @} */
+
+ // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ // XX XX
+ // XX PROXY FEATURES (CAS 2.0) XX
+ // XX XX
+ // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+
+ // ########################################################################
+ // PROXYING
+ // ########################################################################
+ /**
+ * @addtogroup internalProxy
+ * @{
+ */
+
+ /**
+ * A boolean telling if the client is a CAS proxy or not. Written by
+ * CAS_Client::CAS_Client(), read by CAS_Client::isProxy().
+ */
+ private $_proxy;
+
+ /**
+ * Handler for managing service cookies.
+ */
+ private $_serviceCookieJar;
+
+ /**
+ * Tells if a CAS client is a CAS proxy or not
+ *
+ * @return true when the CAS client is a CAs proxy, false otherwise
+ */
+ public function isProxy()
+ {
+ return $this->_proxy;
+ }
+
+ /** @} */
+ // ########################################################################
+ // PGT
+ // ########################################################################
+ /**
+ * @addtogroup internalProxy
+ * @{
+ */
+
+ /**
+ * the Proxy Grnting Ticket given by the CAS server (empty otherwise).
+ * Written by CAS_Client::_setPGT(), read by CAS_Client::_getPGT() and
+ * CAS_Client::_hasPGT().
+ *
+ * @hideinitializer
+ */
+ private $_pgt = '';
+
+ /**
+ * This method returns the Proxy Granting Ticket given by the CAS server.
+ *
+ * @return string the Proxy Granting Ticket.
+ */
+ private function _getPGT()
+ {
+ return $this->_pgt;
+ }
+
+ /**
+ * This method stores the Proxy Granting Ticket.
+ *
+ * @param string $pgt The Proxy Granting Ticket.
+ *
+ * @return void
+ */
+ private function _setPGT($pgt)
+ {
+ $this->_pgt = $pgt;
+ }
+
+ /**
+ * This method tells if a Proxy Granting Ticket was stored.
+ *
+ * @return true if a Proxy Granting Ticket has been stored.
+ */
+ private function _hasPGT()
+ {
+ return !empty($this->_pgt);
+ }
+
+ /** @} */
+
+ // ########################################################################
+ // CALLBACK MODE
+ // ########################################################################
+ /**
+ * @addtogroup internalCallback
+ * @{
+ */
+ /**
+ * each PHP script using phpCAS in proxy mode is its own callback to get the
+ * PGT back from the CAS server. callback_mode is detected by the constructor
+ * thanks to the GET parameters.
+ */
+
+ /**
+ * a boolean to know if the CAS client is running in callback mode. Written by
+ * CAS_Client::setCallBackMode(), read by CAS_Client::_isCallbackMode().
+ *
+ * @hideinitializer
+ */
+ private $_callback_mode = false;
+
+ /**
+ * This method sets/unsets callback mode.
+ *
+ * @param bool $callback_mode true to set callback mode, false otherwise.
+ *
+ * @return void
+ */
+ private function _setCallbackMode($callback_mode)
+ {
+ $this->_callback_mode = $callback_mode;
+ }
+
+ /**
+ * This method returns true when the CAs client is running i callback mode,
+ * false otherwise.
+ *
+ * @return A boolean.
+ */
+ private function _isCallbackMode()
+ {
+ return $this->_callback_mode;
+ }
+
+ /**
+ * the URL that should be used for the PGT callback (in fact the URL of the
+ * current request without any CGI parameter). Written and read by
+ * CAS_Client::_getCallbackURL().
+ *
+ * @hideinitializer
+ */
+ private $_callback_url = '';
+
+ /**
+ * This method returns the URL that should be used for the PGT callback (in
+ * fact the URL of the current request without any CGI parameter, except if
+ * phpCAS::setFixedCallbackURL() was used).
+ *
+ * @return The callback URL
+ */
+ private function _getCallbackURL()
+ {
+ // the URL is built when needed only
+ if ( empty($this->_callback_url) ) {
+ $final_uri = '';
+ // remove the ticket if present in the URL
+ $final_uri = 'https://';
+ $final_uri .= $this->_getServerUrl();
+ $request_uri = $_SERVER['REQUEST_URI'];
+ $request_uri = preg_replace('/\?.*$/', '', $request_uri);
+ $final_uri .= $request_uri;
+ $this->setCallbackURL($final_uri);
+ }
+ return $this->_callback_url;
+ }
+
+ /**
+ * This method sets the callback url.
+ *
+ * @param string $url url to set callback
+ *
+ * @return void
+ */
+ public function setCallbackURL($url)
+ {
+ return $this->_callback_url = $url;
+ }
+
+ /**
+ * This method is called by CAS_Client::CAS_Client() when running in callback
+ * mode. It stores the PGT and its PGT Iou, prints its output and halts.
+ *
+ * @return void
+ */
+ private function _callback()
+ {
+ phpCAS::traceBegin();
+ if (preg_match('/PGTIOU-[\.\-\w]/', $_GET['pgtIou'])) {
+ if (preg_match('/[PT]GT-[\.\-\w]/', $_GET['pgtId'])) {
+ $this->printHTMLHeader('phpCAS callback');
+ $pgt_iou = $_GET['pgtIou'];
+ $pgt = $_GET['pgtId'];
+ phpCAS::trace('Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\')');
+ echo '<p>Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\').</p>';
+ $this->_storePGT($pgt, $pgt_iou);
+ $this->printHTMLFooter();
+ phpCAS::traceExit("Successfull Callback");
+ } else {
+ phpCAS::error('PGT format invalid' . $_GET['pgtId']);
+ phpCAS::traceExit('PGT format invalid' . $_GET['pgtId']);
+ }
+ } else {
+ phpCAS::error('PGTiou format invalid' . $_GET['pgtIou']);
+ phpCAS::traceExit('PGTiou format invalid' . $_GET['pgtIou']);
+ }
+
+ // Flush the buffer to prevent from sending anything other then a 200
+ // Success Status back to the CAS Server. The Exception would normally
+ // report as a 500 error.
+ flush();
+ throw new CAS_GracefullTerminationException();
+ }
+
+
+ /** @} */
+
+ // ########################################################################
+ // PGT STORAGE
+ // ########################################################################
+ /**
+ * @addtogroup internalPGTStorage
+ * @{
+ */
+
+ /**
+ * an instance of a class inheriting of PGTStorage, used to deal with PGT
+ * storage. Created by CAS_Client::setPGTStorageFile(), used
+ * by CAS_Client::setPGTStorageFile() and CAS_Client::_initPGTStorage().
+ *
+ * @hideinitializer
+ */
+ private $_pgt_storage = null;
+
+ /**
+ * This method is used to initialize the storage of PGT's.
+ * Halts on error.
+ *
+ * @return void
+ */
+ private function _initPGTStorage()
+ {
+ // if no SetPGTStorageXxx() has been used, default to file
+ if ( !is_object($this->_pgt_storage) ) {
+ $this->setPGTStorageFile();
+ }
+
+ // initializes the storage
+ $this->_pgt_storage->init();
+ }
+
+ /**
+ * This method stores a PGT. Halts on error.
+ *
+ * @param string $pgt the PGT to store
+ * @param string $pgt_iou its corresponding Iou
+ *
+ * @return void
+ */
+ private function _storePGT($pgt,$pgt_iou)
+ {
+ // ensure that storage is initialized
+ $this->_initPGTStorage();
+ // writes the PGT
+ $this->_pgt_storage->write($pgt, $pgt_iou);
+ }
+
+ /**
+ * This method reads a PGT from its Iou and deletes the corresponding
+ * storage entry.
+ *
+ * @param string $pgt_iou the PGT Iou
+ *
+ * @return mul The PGT corresponding to the Iou, false when not found.
+ */
+ private function _loadPGT($pgt_iou)
+ {
+ // ensure that storage is initialized
+ $this->_initPGTStorage();
+ // read the PGT
+ return $this->_pgt_storage->read($pgt_iou);
+ }
+
+ /**
+ * This method can be used to set a custom PGT storage object.
+ *
+ * @param CAS_PGTStorage_AbstractStorage $storage a PGT storage object that
+ * inherits from the CAS_PGTStorage_AbstractStorage class
+ *
+ * @return void
+ */
+ public function setPGTStorage($storage)
+ {
+ // check that the storage has not already been set
+ if ( is_object($this->_pgt_storage) ) {
+ phpCAS::error('PGT storage already defined');
+ }
+
+ // check to make sure a valid storage object was specified
+ if ( !($storage instanceof CAS_PGTStorage_AbstractStorage) ) {
+ phpCAS::error('Invalid PGT storage object');
+ }
+
+ // store the PGTStorage object
+ $this->_pgt_storage = $storage;
+ }
+
+ /**
+ * 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
+ * PGTs
+ * @param string $driver_options any driver options to use when connecting
+ * to the database
+ *
+ * @return void
+ */
+ public function setPGTStorageDb($dsn_or_pdo, $username='', $password='', $table='', $driver_options=null)
+ {
+ // create the storage object
+ $this->setPGTStorage(new CAS_PGTStorage_Db($this, $dsn_or_pdo, $username, $password, $table, $driver_options));
+ }
+
+ /**
+ * 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 function setPGTStorageFile($path='')
+ {
+ // create the storage object
+ $this->setPGTStorage(new CAS_PGTStorage_File($this, $path));
+ }
+
+
+ // ########################################################################
+ // PGT VALIDATION
+ // ########################################################################
+ /**
+ * This method is used to validate a PGT; halt on failure.
+ *
+ * @param string &$validate_url the URL of the request to the CAS server.
+ * @param string $text_response the response of the CAS server, as is
+ * (XML text); result of CAS_Client::validateCAS10() or CAS_Client::validateCAS20().
+ * @param string $tree_response the response of the CAS server, as a DOM XML
+ * tree; result of CAS_Client::validateCAS10() or CAS_Client::validateCAS20().
+ *
+ * @return bool true when successfull and issue a CAS_AuthenticationException
+ * and false on an error
+ */
+ private function _validatePGT(&$validate_url,$text_response,$tree_response)
+ {
+ phpCAS::traceBegin();
+ if ( $tree_response->getElementsByTagName("proxyGrantingTicket")->length == 0) {
+ phpCAS::trace('<proxyGrantingTicket> not found');
+ // authentication succeded, but no PGT Iou was transmitted
+ throw new CAS_AuthenticationException(
+ $this, 'Ticket validated but no PGT Iou transmitted',
+ $validate_url, false/*$no_response*/, false/*$bad_response*/,
+ $text_response
+ );
+ } else {
+ // PGT Iou transmitted, extract it
+ $pgt_iou = trim($tree_response->getElementsByTagName("proxyGrantingTicket")->item(0)->nodeValue);
+ if (preg_match('/PGTIOU-[\.\-\w]/', $pgt_iou)) {
+ $pgt = $this->_loadPGT($pgt_iou);
+ if ( $pgt == false ) {
+ phpCAS::trace('could not load PGT');
+ throw new CAS_AuthenticationException(
+ $this, 'PGT Iou was transmitted but PGT could not be retrieved',
+ $validate_url, false/*$no_response*/,
+ false/*$bad_response*/, $text_response
+ );
+ }
+ $this->_setPGT($pgt);
+ } else {
+ phpCAS::trace('PGTiou format error');
+ throw new CAS_AuthenticationException(
+ $this, 'PGT Iou was transmitted but has wrong format',
+ $validate_url, false/*$no_response*/, false/*$bad_response*/,
+ $text_response
+ );
+ }
+ }
+ phpCAS::traceEnd(true);
+ return true;
+ }
+
+ // ########################################################################
+ // PGT VALIDATION
+ // ########################################################################
+
+ /**
+ * This method is used to retrieve PT's from the CAS server thanks to a PGT.
+ *
+ * @param string $target_service the service to ask for with the PT.
+ * @param string &$err_code an error code (PHPCAS_SERVICE_OK on success).
+ * @param string &$err_msg an error message (empty on success).
+ *
+ * @return a Proxy Ticket, or false on error.
+ */
+ public function retrievePT($target_service,&$err_code,&$err_msg)
+ {
+ phpCAS::traceBegin();
+
+ // by default, $err_msg is set empty and $pt to true. On error, $pt is
+ // set to false and $err_msg to an error message. At the end, if $pt is false
+ // and $error_msg is still empty, it is set to 'invalid response' (the most
+ // commonly encountered error).
+ $err_msg = '';
+
+ // build the URL to retrieve the PT
+ $cas_url = $this->getServerProxyURL().'?targetService='.urlencode($target_service).'&pgt='.$this->_getPGT();
+
+ // open and read the URL
+ if ( !$this->_readURL($cas_url, $headers, $cas_response, $err_msg) ) {
+ phpCAS::trace('could not open URL \''.$cas_url.'\' to validate ('.$err_msg.')');
+ $err_code = PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE;
+ $err_msg = 'could not retrieve PT (no response from the CAS server)';
+ phpCAS::traceEnd(false);
+ return false;
+ }
+
+ $bad_response = false;
+
+ if ( !$bad_response ) {
+ // create new DOMDocument object
+ $dom = new DOMDocument();
+ // Fix possible whitspace problems
+ $dom->preserveWhiteSpace = false;
+ // read the response of the CAS server into a DOM object
+ if ( !($dom->loadXML($cas_response))) {
+ phpCAS::trace('dom->loadXML() failed');
+ // read failed
+ $bad_response = true;
+ }
+ }
+
+ if ( !$bad_response ) {
+ // read the root node of the XML tree
+ if ( !($root = $dom->documentElement) ) {
+ phpCAS::trace('documentElement failed');
+ // read failed
+ $bad_response = true;
+ }
+ }
+
+ if ( !$bad_response ) {
+ // insure that tag name is 'serviceResponse'
+ if ( $root->localName != 'serviceResponse' ) {
+ phpCAS::trace('localName failed');
+ // bad root node
+ $bad_response = true;
+ }
+ }
+
+ if ( !$bad_response ) {
+ // look for a proxySuccess tag
+ if ( $root->getElementsByTagName("proxySuccess")->length != 0) {
+ $proxy_success_list = $root->getElementsByTagName("proxySuccess");
+
+ // authentication succeded, look for a proxyTicket tag
+ if ( $proxy_success_list->item(0)->getElementsByTagName("proxyTicket")->length != 0) {
+ $err_code = PHPCAS_SERVICE_OK;
+ $err_msg = '';
+ $pt = trim($proxy_success_list->item(0)->getElementsByTagName("proxyTicket")->item(0)->nodeValue);
+ phpCAS::trace('original PT: '.trim($pt));
+ phpCAS::traceEnd($pt);
+ return $pt;
+ } else {
+ phpCAS::trace('<proxySuccess> was found, but not <proxyTicket>');
+ }
+ } else if ($root->getElementsByTagName("proxyFailure")->length != 0) {
+ // look for a proxyFailure tag
+ $proxy_failure_list = $root->getElementsByTagName("proxyFailure");
+
+ // authentication failed, extract the error
+ $err_code = PHPCAS_SERVICE_PT_FAILURE;
+ $err_msg = 'PT retrieving failed (code=`'
+ .$proxy_failure_list->item(0)->getAttribute('code')
+ .'\', message=`'
+ .trim($proxy_failure_list->item(0)->nodeValue)
+ .'\')';
+ phpCAS::traceEnd(false);
+ return false;
+ } else {
+ phpCAS::trace('neither <proxySuccess> nor <proxyFailure> found');
+ }
+ }
+
+ // at this step, we are sure that the response of the CAS server was
+ // illformed
+ $err_code = PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE;
+ $err_msg = 'Invalid response from the CAS server (response=`'.$cas_response.'\')';
+
+ phpCAS::traceEnd(false);
+ return false;
+ }
+
+ /** @} */
+
+ // ########################################################################
+ // READ CAS SERVER ANSWERS
+ // ########################################################################
+
+ /**
+ * @addtogroup internalMisc
+ * @{
+ */
+
+ /**
+ * This method is used to acces a remote URL.
+ *
+ * @param string $url the URL to access.
+ * @param string &$headers an array containing the HTTP header lines of the
+ * response (an empty array on failure).
+ * @param string &$body the body of the response, as a string (empty on
+ * failure).
+ * @param string &$err_msg an error message, filled on failure.
+ *
+ * @return true on success, false otherwise (in this later case, $err_msg
+ * contains an error message).
+ */
+ private function _readURL($url, &$headers, &$body, &$err_msg)
+ {
+ phpCAS::traceBegin();
+ $className = $this->_requestImplementation;
+ $request = new $className();
+
+ if (count($this->_curl_options)) {
+ $request->setCurlOptions($this->_curl_options);
+ }
+
+ $request->setUrl($url);
+
+ if (empty($this->_cas_server_ca_cert) && !$this->_no_cas_server_validation) {
+ phpCAS::error('one of the methods phpCAS::setCasServerCACert() or phpCAS::setNoCasServerValidation() must be called.');
+ }
+ if ($this->_cas_server_ca_cert != '') {
+ $request->setSslCaCert($this->_cas_server_ca_cert, $this->_cas_server_cn_validate);
+ }
+
+ // add extra stuff if SAML
+ if ($this->getServerVersion() == SAML_VERSION_1_1) {
+ $request->addHeader("soapaction: http://www.oasis-open.org/committees/security");
+ $request->addHeader("cache-control: no-cache");
+ $request->addHeader("pragma: no-cache");
+ $request->addHeader("accept: text/xml");
+ $request->addHeader("connection: keep-alive");
+ $request->addHeader("content-type: text/xml");
+ $request->makePost();
+ $request->setPostBody($this->_buildSAMLPayload());
+ }
+
+ if ($request->send()) {
+ $headers = $request->getResponseHeaders();
+ $body = $request->getResponseBody();
+ $err_msg = '';
+ phpCAS::traceEnd(true);
+ return true;
+ } else {
+ $headers = '';
+ $body = '';
+ $err_msg = $request->getErrorMessage();
+ phpCAS::traceEnd(false);
+ return false;
+ }
+ }
+
+ /**
+ * This method is used to build the SAML POST body sent to /samlValidate URL.
+ *
+ * @return the SOAP-encased SAMLP artifact (the ticket).
+ */
+ private function _buildSAMLPayload()
+ {
+ phpCAS::traceBegin();
+
+ //get the ticket
+ $sa = $this->getTicket();
+
+ $body=SAML_SOAP_ENV.SAML_SOAP_BODY.SAMLP_REQUEST.SAML_ASSERTION_ARTIFACT.$sa.SAML_ASSERTION_ARTIFACT_CLOSE.SAMLP_REQUEST_CLOSE.SAML_SOAP_BODY_CLOSE.SAML_SOAP_ENV_CLOSE;
+
+ phpCAS::traceEnd($body);
+ return ($body);
+ }
+
+ /** @} **/
+
+ // ########################################################################
+ // ACCESS TO EXTERNAL SERVICES
+ // ########################################################################
+
+ /**
+ * @addtogroup internalProxyServices
+ * @{
+ */
+
+
+ /**
+ * 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 function getProxiedService ($type)
+ {
+ switch ($type) {
+ case PHPCAS_PROXIED_SERVICE_HTTP_GET:
+ case PHPCAS_PROXIED_SERVICE_HTTP_POST:
+ $requestClass = $this->_requestImplementation;
+ $request = new $requestClass();
+ if (count($this->_curl_options)) {
+ $request->setCurlOptions($this->_curl_options);
+ }
+ $proxiedService = new $type($request, $this->_serviceCookieJar);
+ if ($proxiedService instanceof CAS_ProxiedService_Testable) {
+ $proxiedService->setCasClient($this);
+ }
+ return $proxiedService;
+ case PHPCAS_PROXIED_SERVICE_IMAP;
+ $proxiedService = new CAS_ProxiedService_Imap($this->getUser());
+ if ($proxiedService instanceof CAS_ProxiedService_Testable) {
+ $proxiedService->setCasClient($this);
+ }
+ return $proxiedService;
+ default:
+ throw new CAS_InvalidArgumentException("Unknown proxied-service type, $type.");
+ }
+ }
+
+ /**
+ * Initialize a proxied-service handler with the proxy-ticket it should use.
+ *
+ * @param CAS_ProxiedService $proxiedService 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
+ * @throws CAS_ProxiedService_Exception If there is a failure getting the
+ * url from the proxied service.
+ */
+ public function initializeProxiedService (CAS_ProxiedService $proxiedService)
+ {
+ $url = $proxiedService->getServiceUrl();
+ if (!is_string($url)) {
+ throw new CAS_ProxiedService_Exception("Proxied Service ".get_class($proxiedService)."->getServiceUrl() should have returned a string, returned a ".gettype($url)." instead.");
+ }
+ $pt = $this->retrievePT($url, $err_code, $err_msg);
+ if (!$pt) {
+ throw new CAS_ProxyTicketException($err_msg, $err_code);
+ }
+ $proxiedService->setProxyTicket($pt);
+ }
+
+ /**
+ * This method is used to access an HTTP[S] service.
+ *
+ * @param string $url the service to access.
+ * @param int &$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 true on success, false otherwise (in this later case, $err_code
+ * gives the reason why it failed and $output contains an error message).
+ */
+ public function serviceWeb($url,&$err_code,&$output)
+ {
+ try {
+ $service = $this->getProxiedService(PHPCAS_PROXIED_SERVICE_HTTP_GET);
+ $service->setUrl($url);
+ $service->send();
+ $output = $service->getResponseBody();
+ $err_code = PHPCAS_SERVICE_OK;
+ return true;
+ } catch (CAS_ProxyTicketException $e) {
+ $err_code = $e->getCode();
+ $output = $e->getMessage();
+ return false;
+ } catch (CAS_ProxiedService_Exception $e) {
+ $lang = $this->getLangObj();
+ $output = sprintf($lang->getServiceUnavailable(), $url, $e->getMessage());
+ $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
+ return false;
+ }
+ }
+
+ /**
+ * 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 $serviceUrl a string giving for CAS retrieve Proxy ticket
+ * @param string $flags options given to imap_open().
+ * @param int &$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 an 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 function serviceMail($url,$serviceUrl,$flags,&$err_code,&$err_msg,&$pt)
+ {
+ try {
+ $service = $this->getProxiedService(PHPCAS_PROXIED_SERVICE_IMAP);
+ $service->setServiceUrl($serviceUrl);
+ $service->setMailbox($url);
+ $service->setOptions($flags);
+
+ $stream = $service->open();
+ $err_code = PHPCAS_SERVICE_OK;
+ $pt = $service->getImapProxyTicket();
+ return $stream;
+ } catch (CAS_ProxyTicketException $e) {
+ $err_msg = $e->getMessage();
+ $err_code = $e->getCode();
+ $pt = false;
+ return false;
+ } catch (CAS_ProxiedService_Exception $e) {
+ $lang = $this->getLangObj();
+ $err_msg = sprintf(
+ $lang->getServiceUnavailable(),
+ $url,
+ $e->getMessage()
+ );
+ $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
+ $pt = false;
+ return false;
+ }
+ }
+
+ /** @} **/
+
+ // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ // XX XX
+ // XX PROXIED CLIENT FEATURES (CAS 2.0) XX
+ // XX XX
+ // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+
+ // ########################################################################
+ // PT
+ // ########################################################################
+ /**
+ * @addtogroup internalService
+ * @{
+ */
+
+ /**
+ * This array will store a list of proxies in front of this application. This
+ * property will only be populated if this script is being proxied rather than
+ * accessed directly.
+ *
+ * It is set in CAS_Client::validateCAS20() and can be read by
+ * CAS_Client::getProxies()
+ *
+ * @access private
+ */
+ private $_proxies = array();
+
+ /**
+ * 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
+ */
+ public function getProxies()
+ {
+ return $this->_proxies;
+ }
+
+ /**
+ * Set the Proxy array, probably from persistant storage.
+ *
+ * @param array $proxies An array of proxies
+ *
+ * @return void
+ * @access private
+ */
+ private function _setProxies($proxies)
+ {
+ $this->_proxies = $proxies;
+ if (!empty($proxies)) {
+ // For proxy-authenticated requests people are not viewing the URL
+ // directly since the client is another application making a
+ // web-service call.
+ // Because of this, stripping the ticket from the URL is unnecessary
+ // and causes another web-service request to be performed. Additionally,
+ // if session handling on either the client or the server malfunctions
+ // then the subsequent request will not complete successfully.
+ $this->setNoClearTicketsFromUrl();
+ }
+ }
+
+ /**
+ * A container of patterns to be allowed as proxies in front of the cas client.
+ *
+ * @var CAS_ProxyChain_AllowedList
+ */
+ private $_allowed_proxy_chains;
+
+ /**
+ * Answer the CAS_ProxyChain_AllowedList object for this client.
+ *
+ * @return CAS_ProxyChain_AllowedList
+ */
+ public function getAllowedProxyChains ()
+ {
+ if (empty($this->_allowed_proxy_chains)) {
+ $this->_allowed_proxy_chains = new CAS_ProxyChain_AllowedList();
+ }
+ return $this->_allowed_proxy_chains;
+ }
+
+ /** @} */
+ // ########################################################################
+ // PT VALIDATION
+ // ########################################################################
+ /**
+ * @addtogroup internalProxied
+ * @{
+ */
+
+ /**
+ * This method is used to validate a cas 2.0 ST or PT; halt on failure
+ * Used for all CAS 2.0 validations
+ *
+ * @param string &$validate_url the url of the reponse
+ * @param string &$text_response the text of the repsones
+ * @param string &$tree_response the domxml tree of the respones
+ *
+ * @return bool true when successfull and issue a CAS_AuthenticationException
+ * and false on an error
+ */
+ public function validateCAS20(&$validate_url,&$text_response,&$tree_response)
+ {
+ phpCAS::traceBegin();
+ phpCAS::trace($text_response);
+ $result = false;
+ // build the URL to validate the ticket
+ if ($this->getAllowedProxyChains()->isProxyingAllowed()) {
+ $validate_url = $this->getServerProxyValidateURL().'&ticket='.$this->getTicket();
+ } else {
+ $validate_url = $this->getServerServiceValidateURL().'&ticket='.$this->getTicket();
+ }
+
+ if ( $this->isProxy() ) {
+ // pass the callback url for CAS proxies
+ $validate_url .= '&pgtUrl='.urlencode($this->_getCallbackURL());
+ }
+
+ // open and read the URL
+ if ( !$this->_readURL($validate_url, $headers, $text_response, $err_msg) ) {
+ phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
+ throw new CAS_AuthenticationException(
+ $this, 'Ticket not validated', $validate_url,
+ true/*$no_response*/
+ );
+ $result = false;
+ }
+
+ // create new DOMDocument object
+ $dom = new DOMDocument();
+ // Fix possible whitspace problems
+ $dom->preserveWhiteSpace = false;
+ // CAS servers should only return data in utf-8
+ $dom->encoding = "utf-8";
+ // read the response of the CAS server into a DOMDocument object
+ if ( !($dom->loadXML($text_response))) {
+ // read failed
+ throw new CAS_AuthenticationException(
+ $this, 'Ticket not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/, $text_response
+ );
+ $result = false;
+ } else if ( !($tree_response = $dom->documentElement) ) {
+ // read the root node of the XML tree
+ // read failed
+ throw new CAS_AuthenticationException(
+ $this, 'Ticket not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/, $text_response
+ );
+ $result = false;
+ } else if ($tree_response->localName != 'serviceResponse') {
+ // insure that tag name is 'serviceResponse'
+ // bad root node
+ throw new CAS_AuthenticationException(
+ $this, 'Ticket not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/, $text_response
+ );
+ $result = false;
+ } else if ($tree_response->getElementsByTagName("authenticationSuccess")->length != 0) {
+ // authentication succeded, extract the user name
+ $success_elements = $tree_response->getElementsByTagName("authenticationSuccess");
+ if ( $success_elements->item(0)->getElementsByTagName("user")->length == 0) {
+ // no user specified => error
+ throw new CAS_AuthenticationException(
+ $this, 'Ticket not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/, $text_response
+ );
+ $result = false;
+ } else {
+ $this->_setUser(trim($success_elements->item(0)->getElementsByTagName("user")->item(0)->nodeValue));
+ $this->_readExtraAttributesCas20($success_elements);
+ // Store the proxies we are sitting behind for authorization checking
+ $proxyList = array();
+ if ( sizeof($arr = $success_elements->item(0)->getElementsByTagName("proxy")) > 0) {
+ foreach ($arr as $proxyElem) {
+ phpCAS::trace("Found Proxy: ".$proxyElem->nodeValue);
+ $proxyList[] = trim($proxyElem->nodeValue);
+ }
+ $this->_setProxies($proxyList);
+ phpCAS::trace("Storing Proxy List");
+ }
+ // Check if the proxies in front of us are allowed
+ if (!$this->getAllowedProxyChains()->isProxyListAllowed($proxyList)) {
+ throw new CAS_AuthenticationException(
+ $this, 'Proxy not allowed', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/,
+ $text_response
+ );
+ $result = false;
+ } else {
+ $result = true;
+ }
+ }
+ } else if ( $tree_response->getElementsByTagName("authenticationFailure")->length != 0) {
+ // authentication succeded, extract the error code and message
+ $auth_fail_list = $tree_response->getElementsByTagName("authenticationFailure");
+ throw new CAS_AuthenticationException(
+ $this, 'Ticket not validated', $validate_url,
+ false/*$no_response*/, false/*$bad_response*/,
+ $text_response,
+ $auth_fail_list->item(0)->getAttribute('code')/*$err_code*/,
+ trim($auth_fail_list->item(0)->nodeValue)/*$err_msg*/
+ );
+ $result = false;
+ } else {
+ throw new CAS_AuthenticationException(
+ $this, 'Ticket not validated', $validate_url,
+ false/*$no_response*/, true/*$bad_response*/,
+ $text_response
+ );
+ $result = false;
+ }
+ if ($result) {
+ $this->_renameSession($this->getTicket());
+ }
+ // at this step, Ticket has been validated and $this->_user has been set,
+
+ phpCAS::traceEnd($result);
+ return $result;
+ }
+
+
+ /**
+ * This method will parse the DOM and pull out the attributes from the XML
+ * payload and put them into an array, then put the array into the session.
+ *
+ * @param string $success_elements payload of the response
+ *
+ * @return bool true when successfull, halt otherwise by calling
+ * CAS_Client::_authError().
+ */
+ private function _readExtraAttributesCas20($success_elements)
+ {
+ phpCAS::traceBegin();
+
+ $extra_attributes = array();
+
+ // "Jasig Style" Attributes:
+ //
+ // <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
+ // <cas:authenticationSuccess>
+ // <cas:user>jsmith</cas:user>
+ // <cas:attributes>
+ // <cas:attraStyle>RubyCAS</cas:attraStyle>
+ // <cas:surname>Smith</cas:surname>
+ // <cas:givenName>John</cas:givenName>
+ // <cas:memberOf>CN=Staff,OU=Groups,DC=example,DC=edu</cas:memberOf>
+ // <cas:memberOf>CN=Spanish Department,OU=Departments,OU=Groups,DC=example,DC=edu</cas:memberOf>
+ // </cas:attributes>
+ // <cas:proxyGrantingTicket>PGTIOU-84678-8a9d2sfa23casd</cas:proxyGrantingTicket>
+ // </cas:authenticationSuccess>
+ // </cas:serviceResponse>
+ //
+ if ( $success_elements->item(0)->getElementsByTagName("attributes")->length != 0) {
+ $attr_nodes = $success_elements->item(0)->getElementsByTagName("attributes");
+ phpCas :: trace("Found nested jasig style attributes");
+ if ($attr_nodes->item(0)->hasChildNodes()) {
+ // Nested Attributes
+ foreach ($attr_nodes->item(0)->childNodes as $attr_child) {
+ phpCas :: trace("Attribute [".$attr_child->localName."] = ".$attr_child->nodeValue);
+ $this->_addAttributeToArray($extra_attributes, $attr_child->localName, $attr_child->nodeValue);
+ }
+ }
+ } else {
+ // "RubyCAS Style" attributes
+ //
+ // <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
+ // <cas:authenticationSuccess>
+ // <cas:user>jsmith</cas:user>
+ //
+ // <cas:attraStyle>RubyCAS</cas:attraStyle>
+ // <cas:surname>Smith</cas:surname>
+ // <cas:givenName>John</cas:givenName>
+ // <cas:memberOf>CN=Staff,OU=Groups,DC=example,DC=edu</cas:memberOf>
+ // <cas:memberOf>CN=Spanish Department,OU=Departments,OU=Groups,DC=example,DC=edu</cas:memberOf>
+ //
+ // <cas:proxyGrantingTicket>PGTIOU-84678-8a9d2sfa23casd</cas:proxyGrantingTicket>
+ // </cas:authenticationSuccess>
+ // </cas:serviceResponse>
+ //
+ phpCas :: trace("Testing for rubycas style attributes");
+ $childnodes = $success_elements->item(0)->childNodes;
+ foreach ($childnodes as $attr_node) {
+ switch ($attr_node->localName) {
+ case 'user':
+ case 'proxies':
+ case 'proxyGrantingTicket':
+ continue;
+ default:
+ if (strlen(trim($attr_node->nodeValue))) {
+ phpCas :: trace("Attribute [".$attr_node->localName."] = ".$attr_node->nodeValue);
+ $this->_addAttributeToArray($extra_attributes, $attr_node->localName, $attr_node->nodeValue);
+ }
+ }
+ }
+ }
+
+ // "Name-Value" attributes.
+ //
+ // Attribute format from these mailing list thread:
+ // http://jasig.275507.n4.nabble.com/CAS-attributes-and-how-they-appear-in-the-CAS-response-td264272.html
+ // Note: This is a less widely used format, but in use by at least two institutions.
+ //
+ // <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
+ // <cas:authenticationSuccess>
+ // <cas:user>jsmith</cas:user>
+ //
+ // <cas:attribute name='attraStyle' value='Name-Value' />
+ // <cas:attribute name='surname' value='Smith' />
+ // <cas:attribute name='givenName' value='John' />
+ // <cas:attribute name='memberOf' value='CN=Staff,OU=Groups,DC=example,DC=edu' />
+ // <cas:attribute name='memberOf' value='CN=Spanish Department,OU=Departments,OU=Groups,DC=example,DC=edu' />
+ //
+ // <cas:proxyGrantingTicket>PGTIOU-84678-8a9d2sfa23casd</cas:proxyGrantingTicket>
+ // </cas:authenticationSuccess>
+ // </cas:serviceResponse>
+ //
+ if (!count($extra_attributes) && $success_elements->item(0)->getElementsByTagName("attribute")->length != 0) {
+ $attr_nodes = $success_elements->item(0)->getElementsByTagName("attribute");
+ $firstAttr = $attr_nodes->item(0);
+ if (!$firstAttr->hasChildNodes() && $firstAttr->hasAttribute('name') && $firstAttr->hasAttribute('value')) {
+ phpCas :: trace("Found Name-Value style attributes");
+ // Nested Attributes
+ foreach ($attr_nodes as $attr_node) {
+ if ($attr_node->hasAttribute('name') && $attr_node->hasAttribute('value')) {
+ phpCas :: trace("Attribute [".$attr_node->getAttribute('name')."] = ".$attr_node->getAttribute('value'));
+ $this->_addAttributeToArray($extra_attributes, $attr_node->getAttribute('name'), $attr_node->getAttribute('value'));
+ }
+ }
+ }
+ }
+
+ $this->setAttributes($extra_attributes);
+ phpCAS::traceEnd();
+ return true;
+ }
+
+ /**
+ * Add an attribute value to an array of attributes.
+ *
+ * @param array &$attributeArray reference to array
+ * @param string $name name of attribute
+ * @param string $value value of attribute
+ *
+ * @return void
+ */
+ private function _addAttributeToArray(array &$attributeArray, $name, $value)
+ {
+ // If multiple attributes exist, add as an array value
+ if (isset($attributeArray[$name])) {
+ // Initialize the array with the existing value
+ if (!is_array($attributeArray[$name])) {
+ $existingValue = $attributeArray[$name];
+ $attributeArray[$name] = array($existingValue);
+ }
+
+ $attributeArray[$name][] = trim($value);
+ } else {
+ $attributeArray[$name] = trim($value);
+ }
+ }
+
+ /** @} */
+
+ // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ // XX XX
+ // XX MISC XX
+ // XX XX
+ // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+
+ /**
+ * @addtogroup internalMisc
+ * @{
+ */
+
+ // ########################################################################
+ // URL
+ // ########################################################################
+ /**
+ * the URL of the current request (without any ticket CGI parameter). Written
+ * and read by CAS_Client::getURL().
+ *
+ * @hideinitializer
+ */
+ private $_url = '';
+
+
+ /**
+ * This method sets the URL of the current request
+ *
+ * @param string $url url to set for service
+ *
+ * @return void
+ */
+ public function setURL($url)
+ {
+ $this->_url = $url;
+ }
+
+ /**
+ * This method returns the URL of the current request (without any ticket
+ * CGI parameter).
+ *
+ * @return The URL
+ */
+ public function getURL()
+ {
+ phpCAS::traceBegin();
+ // the URL is built when needed only
+ if ( empty($this->_url) ) {
+ $final_uri = '';
+ // remove the ticket if present in the URL
+ $final_uri = ($this->_isHttps()) ? 'https' : 'http';
+ $final_uri .= '://';
+
+ $final_uri .= $this->_getServerUrl();
+ $request_uri = explode('?', $_SERVER['REQUEST_URI'], 2);
+ $final_uri .= $request_uri[0];
+
+ if (isset($request_uri[1]) && $request_uri[1]) {
+ $query_string= $this->_removeParameterFromQueryString('ticket', $request_uri[1]);
+
+ // If the query string still has anything left, append it to the final URI
+ if ($query_string !== '') {
+ $final_uri .= "?$query_string";
+ }
+ }
+
+ phpCAS::trace("Final URI: $final_uri");
+ $this->setURL($final_uri);
+ }
+ phpCAS::traceEnd($this->_url);
+ return $this->_url;
+ }
+
+
+ /**
+ * Try to figure out the server URL with possible Proxys / Ports etc.
+ *
+ * @return string Server URL with domain:port
+ */
+ private function _getServerUrl()
+ {
+ $server_url = '';
+ if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
+ // explode the host list separated by comma and use the first host
+ $hosts = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']);
+ $server_url = $hosts[0];
+ } else if (!empty($_SERVER['HTTP_X_FORWARDED_SERVER'])) {
+ $server_url = $_SERVER['HTTP_X_FORWARDED_SERVER'];
+ } else {
+ if (empty($_SERVER['SERVER_NAME'])) {
+ $server_url = $_SERVER['HTTP_HOST'];
+ } else {
+ $server_url = $_SERVER['SERVER_NAME'];
+ }
+ }
+ if (!strpos($server_url, ':')) {
+ if (empty($_SERVER['HTTP_X_FORWARDED_PORT'])) {
+ $server_port = $_SERVER['SERVER_PORT'];
+ } else {
+ $server_port = $_SERVER['HTTP_X_FORWARDED_PORT'];
+ }
+
+ if ( ($this->_isHttps() && $server_port!=443)
+ || (!$this->_isHttps() && $server_port!=80)
+ ) {
+ $server_url .= ':';
+ $server_url .= $server_port;
+ }
+ }
+ return $server_url;
+ }
+
+ /**
+ * This method checks to see if the request is secured via HTTPS
+ *
+ * @return bool true if https, false otherwise
+ */
+ private function _isHttps()
+ {
+ if ( isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Removes a parameter from a query string
+ *
+ * @param string $parameterName name of parameter
+ * @param string $queryString query string
+ *
+ * @return string new query string
+ *
+ * @link http://stackoverflow.com/questions/1842681/regular-expression-to-remove-one-parameter-from-query-string
+ */
+ private function _removeParameterFromQueryString($parameterName, $queryString)
+ {
+ $parameterName = preg_quote($parameterName);
+ return preg_replace("/&$parameterName(=[^&]*)?|^$parameterName(=[^&]*)?&?/", '', $queryString);
+ }
+
+ /**
+ * This method is used to append query parameters to an url. Since the url
+ * might already contain parameter it has to be detected and to build a proper
+ * URL
+ *
+ * @param string $url base url to add the query params to
+ * @param string $query params in query form with & separated
+ *
+ * @return url with query params
+ */
+ private function _buildQueryUrl($url, $query)
+ {
+ $url .= (strstr($url, '?') === false) ? '?' : '&';
+ $url .= $query;
+ return $url;
+ }
+
+ /**
+ * Renaming the session
+ *
+ * @param string $ticket name of the ticket
+ *
+ * @return void
+ */
+ private function _renameSession($ticket)
+ {
+ phpCAS::traceBegin();
+ if ($this->getChangeSessionID()) {
+ if (!empty($this->_user)) {
+ $old_session = $_SESSION;
+ session_destroy();
+ // set up a new session, of name based on the ticket
+ $session_id = preg_replace('/[^a-zA-Z0-9\-]/', '', $ticket);
+ phpCAS :: trace("Session ID: ".$session_id);
+ session_id($session_id);
+ session_start();
+ phpCAS :: trace("Restoring old session vars");
+ $_SESSION = $old_session;
+ } else {
+ phpCAS :: error('Session should only be renamed after successfull authentication');
+ }
+ } else {
+ phpCAS :: trace("Skipping session rename since phpCAS is not handling the session.");
+ }
+ phpCAS::traceEnd();
+ }
+
+
+ // ########################################################################
+ // AUTHENTICATION ERROR HANDLING
+ // ########################################################################
+ /**
+ * This method is used to print the HTML output when the user was not
+ * authenticated.
+ *
+ * @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
+ *
+ * @return void
+ */
+ private function _authError(
+ $failure,
+ $cas_url,
+ $no_response,
+ $bad_response='',
+ $cas_response='',
+ $err_code='',
+ $err_msg=''
+ ) {
+ phpCAS::traceBegin();
+ $lang = $this->getLangObj();
+ $this->printHTMLHeader($lang->getAuthenticationFailed());
+ printf($lang->getYouWereNotAuthenticated(), htmlentities($this->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 ($this->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);
+ }
+ $this->printHTMLFooter();
+ phpCAS::traceExit();
+ throw new CAS_GracefullTerminationException();
+ }
+
+ // ########################################################################
+ // PGTIOU/PGTID and logoutRequest rebroadcasting
+ // ########################################################################
+
+ /**
+ * Boolean of whether to rebroadcast pgtIou/pgtId and logoutRequest, and
+ * array of the nodes.
+ */
+ private $_rebroadcast = false;
+ private $_rebroadcast_nodes = array();
+
+ /**
+ * Constants used for determining rebroadcast node type.
+ */
+ const HOSTNAME = 0;
+ const IP = 1;
+
+ /**
+ * Determine the node type from the URL.
+ *
+ * @param String $nodeURL The node URL.
+ *
+ * @return string hostname
+ *
+ */
+ private function _getNodeType($nodeURL)
+ {
+ phpCAS::traceBegin();
+ if (preg_match("/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/", $nodeURL)) {
+ phpCAS::traceEnd(self::IP);
+ return self::IP;
+ } else {
+ phpCAS::traceEnd(self::HOSTNAME);
+ return self::HOSTNAME;
+ }
+ }
+
+ /**
+ * Store the rebroadcast node for pgtIou/pgtId and logout requests.
+ *
+ * @param string $rebroadcastNodeUrl The rebroadcast node URL.
+ *
+ * @return void
+ */
+ public function addRebroadcastNode($rebroadcastNodeUrl)
+ {
+ // Store the rebroadcast node and set flag
+ $this->_rebroadcast = true;
+ $this->_rebroadcast_nodes[] = $rebroadcastNodeUrl;
+ }
+
+ /**
+ * An array to store extra rebroadcast curl options.
+ */
+ private $_rebroadcast_headers = array();
+
+ /**
+ * 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 function addRebroadcastHeader($header)
+ {
+ $this->_rebroadcast_headers[] = $header;
+ }
+
+ /**
+ * Constants used for determining rebroadcast type (logout or pgtIou/pgtId).
+ */
+ const LOGOUT = 0;
+ const PGTIOU = 1;
+
+ /**
+ * This method rebroadcasts logout/pgtIou requests. Can be LOGOUT,PGTIOU
+ *
+ * @param int $type type of rebroadcasting.
+ *
+ * @return void
+ */
+ private function _rebroadcast($type)
+ {
+ phpCAS::traceBegin();
+
+ $rebroadcast_curl_options = array(
+ CURLOPT_FAILONERROR => 1,
+ CURLOPT_FOLLOWLOCATION => 1,
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_CONNECTTIMEOUT => 1,
+ CURLOPT_TIMEOUT => 4);
+
+ // Try to determine the IP address of the server
+ if (!empty($_SERVER['SERVER_ADDR'])) {
+ $ip = $_SERVER['SERVER_ADDR'];
+ } else if (!empty($_SERVER['LOCAL_ADDR'])) {
+ // IIS 7
+ $ip = $_SERVER['LOCAL_ADDR'];
+ }
+ // Try to determine the DNS name of the server
+ if (!empty($ip)) {
+ $dns = gethostbyaddr($ip);
+ }
+ $multiClassName = 'CAS_Request_CurlMultiRequest';
+ $multiRequest = new $multiClassName();
+
+ for ($i = 0; $i < sizeof($this->_rebroadcast_nodes); $i++) {
+ if ((($this->_getNodeType($this->_rebroadcast_nodes[$i]) == self::HOSTNAME) && !empty($dns) && (stripos($this->_rebroadcast_nodes[$i], $dns) === false)) || (($this->_getNodeType($this->_rebroadcast_nodes[$i]) == self::IP) && !empty($ip) && (stripos($this->_rebroadcast_nodes[$i], $ip) === false))) {
+ phpCAS::trace('Rebroadcast target URL: '.$this->_rebroadcast_nodes[$i].$_SERVER['REQUEST_URI']);
+ $className = $this->_requestImplementation;
+ $request = new $className();
+
+ $url = $this->_rebroadcast_nodes[$i].$_SERVER['REQUEST_URI'];
+ $request->setUrl($url);
+
+ if (count($this->_rebroadcast_headers)) {
+ $request->addHeaders($this->_rebroadcast_headers);
+ }
+
+ $request->makePost();
+ if ($type == self::LOGOUT) {
+ // Logout request
+ $request->setPostBody('rebroadcast=false&logoutRequest='.$_POST['logoutRequest']);
+ } else if ($type == self::PGTIOU) {
+ // pgtIou/pgtId rebroadcast
+ $request->setPostBody('rebroadcast=false');
+ }
+
+ $request->setCurlOptions($rebroadcast_curl_options);
+
+ $multiRequest->addRequest($request);
+ } else {
+ phpCAS::trace('Rebroadcast not sent to self: '.$this->_rebroadcast_nodes[$i].' == '.(!empty($ip)?$ip:'').'/'.(!empty($dns)?$dns:''));
+ }
+ }
+ // We need at least 1 request
+ if ($multiRequest->getNumRequests() > 0) {
+ $multiRequest->send();
+ }
+ phpCAS::traceEnd();
+ }
+
+ /** @} */
+}
+
+?>
--- /dev/null
+<?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/CookieJar.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * This class provides access to service cookies and handles parsing of response
+ * headers to pull out cookie values.
+ *
+ * @class CAS_CookieJar
+ * @category Authentication
+ * @package PhpCAS
+ * @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_CookieJar
+{
+
+ private $_cookies;
+
+ /**
+ * Create a new cookie jar by passing it a reference to an array in which it
+ * should store cookies.
+ *
+ * @param array &$storageArray Array to store cookies
+ *
+ * @return void
+ */
+ public function __construct (array &$storageArray)
+ {
+ $this->_cookies =& $storageArray;
+ }
+
+ /**
+ * Store cookies for a web service request.
+ * Cookie storage is based on RFC 2965: http://www.ietf.org/rfc/rfc2965.txt
+ *
+ * @param string $request_url The URL that generated the response headers.
+ * @param array $response_headers An array of the HTTP response header strings.
+ *
+ * @return void
+ *
+ * @access private
+ */
+ public function storeCookies ($request_url, $response_headers)
+ {
+ $urlParts = parse_url($request_url);
+ $defaultDomain = $urlParts['host'];
+
+ $cookies = $this->parseCookieHeaders($response_headers, $defaultDomain);
+
+ // var_dump($cookies);
+ foreach ($cookies as $cookie) {
+ // Enforce the same-origin policy by verifying that the cookie
+ // would match the url that is setting it
+ if (!$this->cookieMatchesTarget($cookie, $urlParts)) {
+ continue;
+ }
+
+ // store the cookie
+ $this->storeCookie($cookie);
+
+ phpCAS::trace($cookie['name'].' -> '.$cookie['value']);
+ }
+ }
+
+ /**
+ * Retrieve cookies applicable for a web service request.
+ * Cookie applicability is based on RFC 2965: http://www.ietf.org/rfc/rfc2965.txt
+ *
+ * @param string $request_url The url that the cookies will be for.
+ *
+ * @return array An array containing cookies. E.g. array('name' => 'val');
+ *
+ * @access private
+ */
+ public function getCookies ($request_url)
+ {
+ if (!count($this->_cookies)) {
+ return array();
+ }
+
+ // If our request URL can't be parsed, no cookies apply.
+ $target = parse_url($request_url);
+ if ($target === false) {
+ return array();
+ }
+
+ $this->expireCookies();
+
+ $matching_cookies = array();
+ foreach ($this->_cookies as $key => $cookie) {
+ if ($this->cookieMatchesTarget($cookie, $target)) {
+ $matching_cookies[$cookie['name']] = $cookie['value'];
+ }
+ }
+ return $matching_cookies;
+ }
+
+
+ /**
+ * Parse Cookies without PECL
+ * From the comments in http://php.net/manual/en/function.http-parse-cookie.php
+ *
+ * @param array $header array of header lines.
+ * @param string $defaultDomain The domain to use if none is specified in
+ * the cookie.
+ *
+ * @return array of cookies
+ */
+ protected function parseCookieHeaders( $header, $defaultDomain )
+ {
+ phpCAS::traceBegin();
+ $cookies = array();
+ foreach ( $header as $line ) {
+ if ( preg_match('/^Set-Cookie2?: /i', $line)) {
+ $cookies[] = $this->parseCookieHeader($line, $defaultDomain);
+ }
+ }
+
+ phpCAS::traceEnd($cookies);
+ return $cookies;
+ }
+
+ /**
+ * Parse a single cookie header line.
+ *
+ * Based on RFC2965 http://www.ietf.org/rfc/rfc2965.txt
+ *
+ * @param string $line The header line.
+ * @param string $defaultDomain The domain to use if none is specified in
+ * the cookie.
+ *
+ * @return array
+ */
+ protected function parseCookieHeader ($line, $defaultDomain)
+ {
+ if (!$defaultDomain) {
+ throw new CAS_InvalidArgumentException('$defaultDomain was not provided.');
+ }
+
+ // Set our default values
+ $cookie = array(
+ 'domain' => $defaultDomain,
+ 'path' => '/',
+ 'secure' => false,
+ );
+
+ $line = preg_replace('/^Set-Cookie2?: /i', '', trim($line));
+
+ // trim any trailing semicolons.
+ $line = trim($line, ';');
+
+ phpCAS::trace("Cookie Line: $line");
+
+ // This implementation makes the assumption that semicolons will not
+ // be present in quoted attribute values. While attribute values that
+ // contain semicolons are allowed by RFC2965, they are hopefully rare
+ // enough to ignore for our purposes. Most browsers make the same
+ // assumption.
+ $attributeStrings = explode(';', $line);
+
+ foreach ( $attributeStrings as $attributeString ) {
+ // split on the first equals sign and use the rest as value
+ $attributeParts = explode('=', $attributeString, 2);
+
+ $attributeName = trim($attributeParts[0]);
+ $attributeNameLC = strtolower($attributeName);
+
+ if (isset($attributeParts[1])) {
+ $attributeValue = trim($attributeParts[1]);
+ // Values may be quoted strings.
+ if (strpos($attributeValue, '"') === 0) {
+ $attributeValue = trim($attributeValue, '"');
+ // unescape any escaped quotes:
+ $attributeValue = str_replace('\"', '"', $attributeValue);
+ }
+ } else {
+ $attributeValue = null;
+ }
+
+ switch ($attributeNameLC) {
+ case 'expires':
+ $cookie['expires'] = strtotime($attributeValue);
+ break;
+ case 'max-age':
+ $cookie['max-age'] = (int)$attributeValue;
+ // Set an expiry time based on the max-age
+ if ($cookie['max-age']) {
+ $cookie['expires'] = time() + $cookie['max-age'];
+ } else {
+ // If max-age is zero, then the cookie should be removed
+ // imediately so set an expiry before now.
+ $cookie['expires'] = time() - 1;
+ }
+ break;
+ case 'secure':
+ $cookie['secure'] = true;
+ break;
+ case 'domain':
+ case 'path':
+ case 'port':
+ case 'version':
+ case 'comment':
+ case 'commenturl':
+ case 'discard':
+ case 'httponly':
+ $cookie[$attributeNameLC] = $attributeValue;
+ break;
+ default:
+ $cookie['name'] = $attributeName;
+ $cookie['value'] = $attributeValue;
+ }
+ }
+
+ return $cookie;
+ }
+
+ /**
+ * Add, update, or remove a cookie.
+ *
+ * @param array $cookie A cookie array as created by parseCookieHeaders()
+ *
+ * @return void
+ *
+ * @access protected
+ */
+ protected function storeCookie ($cookie)
+ {
+ // Discard any old versions of this cookie.
+ $this->discardCookie($cookie);
+ $this->_cookies[] = $cookie;
+
+ }
+
+ /**
+ * Discard an existing cookie
+ *
+ * @param array $cookie An cookie
+ *
+ * @return void
+ *
+ * @access protected
+ */
+ protected function discardCookie ($cookie)
+ {
+ if (!isset($cookie['domain'])
+ || !isset($cookie['path'])
+ || !isset($cookie['path'])
+ ) {
+ throw new CAS_InvalidArgumentException('Invalid Cookie array passed.');
+ }
+
+ foreach ($this->_cookies as $key => $old_cookie) {
+ if ( $cookie['domain'] == $old_cookie['domain']
+ && $cookie['path'] == $old_cookie['path']
+ && $cookie['name'] == $old_cookie['name']
+ ) {
+ unset($this->_cookies[$key]);
+ }
+ }
+ }
+
+ /**
+ * Go through our stored cookies and remove any that are expired.
+ *
+ * @return void
+ *
+ * @access protected
+ */
+ protected function expireCookies ()
+ {
+ foreach ($this->_cookies as $key => $cookie) {
+ if (isset($cookie['expires']) && $cookie['expires'] < time()) {
+ unset($this->_cookies[$key]);
+ }
+ }
+ }
+
+ /**
+ * Answer true if cookie is applicable to a target.
+ *
+ * @param array $cookie An array of cookie attributes.
+ * @param array $target An array of URL attributes as generated by parse_url().
+ *
+ * @return bool
+ *
+ * @access private
+ */
+ protected function cookieMatchesTarget ($cookie, $target)
+ {
+ if (!is_array($target)) {
+ throw new CAS_InvalidArgumentException('$target must be an array of URL attributes as generated by parse_url().');
+ }
+ if (!isset($target['host'])) {
+ throw new CAS_InvalidArgumentException('$target must be an array of URL attributes as generated by parse_url().');
+ }
+
+ // Verify that the scheme matches
+ if ($cookie['secure'] && $target['scheme'] != 'https') {
+ return false;
+ }
+
+ // Verify that the host matches
+ // Match domain and mulit-host cookies
+ if (strpos($cookie['domain'], '.') === 0) {
+ // .host.domain.edu cookies are valid for host.domain.edu
+ if (substr($cookie['domain'], 1) == $target['host']) {
+ // continue with other checks
+ } else {
+ // non-exact host-name matches.
+ // check that the target host a.b.c.edu is within .b.c.edu
+ $pos = strripos($target['host'], $cookie['domain']);
+ if (!$pos) {
+ return false;
+ }
+ // verify that the cookie domain is the last part of the host.
+ if ($pos + strlen($cookie['domain']) != strlen($target['host'])) {
+ return false;
+ }
+ // verify that the host name does not contain interior dots as per
+ // RFC 2965 section 3.3.2 Rejecting Cookies
+ // http://www.ietf.org/rfc/rfc2965.txt
+ $hostname = substr($target['host'], 0, $pos);
+ if (strpos($hostname, '.') !== false) {
+ return false;
+ }
+ }
+ } else {
+ // If the cookie host doesn't begin with '.', the host must case-insensitive
+ // match exactly
+ if (strcasecmp($target['host'], $cookie['domain']) !== 0) {
+ return false;
+ }
+ }
+
+ // Verify that the port matches
+ if (isset($cookie['ports']) && !in_array($target['port'], $cookie['ports'])) {
+ return false;
+ }
+
+ // Verify that the path matches
+ if (strpos($target['path'], $cookie['path']) !== 0) {
+ return false;
+ }
+
+ return true;
+ }
+
+}
+
+?>
--- /dev/null
+<?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/Exception.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * A root exception interface for all exceptions in phpCAS.
+ *
+ * All exceptions thrown in phpCAS should implement this interface to allow them
+ * to be caught as a category by clients. Each phpCAS exception should extend
+ * an appropriate SPL exception class that best fits its type.
+ *
+ * For example, an InvalidArgumentException in phpCAS should be defined as
+ *
+ * class CAS_InvalidArgumentException
+ * extends InvalidArgumentException
+ * implements CAS_Exception
+ * { }
+ *
+ * This definition allows the CAS_InvalidArgumentException to be caught as either
+ * an InvalidArgumentException or as a CAS_Exception.
+ *
+ * @class CAS_Exception
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ *
+ */
+interface CAS_Exception
+{
+
+}
+?>
\ No newline at end of file
--- /dev/null
+<?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/GracefullTerminationException.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * An exception for terminatinating execution or to throw for unit testing
+ *
+ * @class CAS_GracefullTerminationException.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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_GracefullTerminationException
+extends RuntimeException
+implements CAS_Exception
+{
+
+ /**
+ * Test if exceptions should be thrown or if we should just exit.
+ * In production usage we want to just exit cleanly when prompting the user
+ * for a redirect without filling the error logs with uncaught exceptions.
+ * In unit testing scenarios we cannot exit or we won't be able to continue
+ * with our tests.
+ *
+ * @param string $message Message Text
+ * @param string $code Error code
+ *
+ * @return void
+ */
+ public function __construct ($message = 'Terminate Gracefully', $code = 0)
+ {
+ // Exit cleanly to avoid filling up the logs with uncaught exceptions.
+ if (self::$_exitWhenThrown) {
+ exit;
+ } else {
+ // Throw exceptions to allow unit testing to continue;
+ parent::__construct($message, $code);
+ }
+ }
+
+ private static $_exitWhenThrown = true;
+ /**
+ * Force phpcas to thow Exceptions instead of calling exit()
+ * Needed for unit testing. Generally shouldn't be used in production due to
+ * an increase in Apache error logging if CAS_GracefulTerminiationExceptions
+ * are not caught and handled.
+ *
+ * @return void
+ */
+ public static function throwInsteadOfExiting()
+ {
+ self::$_exitWhenThrown = false;
+ }
+
+}
+?>
\ No newline at end of file
--- /dev/null
+<?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/InvalidArgumentException.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * Exception that denotes invalid arguments were passed.
+ *
+ * @class CAS_InvalidArgumentException
+ * @category Authentication
+ * @package PhpCAS
+ * @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_InvalidArgumentException
+extends InvalidArgumentException
+implements CAS_Exception
+{
+
+}
+?>
\ No newline at end of file
--- /dev/null
+<?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/Language/Catalan.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Iván-Benjamín García Torà <ivaniclixx@gmail.com>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * Catalan language class
+ *
+ * @class CAS_Languages_Catalan
+ * @category Authentication
+ * @package PhpCAS
+ * @author Iván-Benjamín García Torà <ivaniclixx@gmail.com>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ * @sa @link internalLang Internationalization @endlink
+ * @ingroup internalLang
+ */
+class CAS_Languages_Catalan implements CAS_Languages_LanguageInterface
+{
+ /**
+ * Get the using server string
+ *
+ * @return string using server
+ */
+ public function getUsingServer()
+ {
+ return 'usant servidor';
+ }
+
+ /**
+ * Get authentication wanted string
+ *
+ * @return string authentication wanted
+ */
+ public function getAuthenticationWanted()
+ {
+ return 'Autentificació CAS necessària!';
+ }
+
+ /**
+ * Get logout string
+ *
+ * @return string logout
+ */
+ public function getLogout()
+ {
+ return 'Sortida de CAS necessària!';
+ }
+
+ /**
+ * Get the should have been redirected string
+ *
+ * @return string should habe been redirected
+ */
+ public function getShouldHaveBeenRedirected()
+ {
+ return 'Ja hauria d\ haver estat redireccionat al servidor CAS. Feu click <a href="%s">aquí</a> per a continuar.';
+ }
+
+ /**
+ * Get authentication failed string
+ *
+ * @return string authentication failed
+ */
+ public function getAuthenticationFailed()
+ {
+ return 'Autentificació CAS fallida!';
+ }
+
+ /**
+ * Get the your were not authenticated string
+ *
+ * @return string not authenticated
+ */
+ public function getYouWereNotAuthenticated()
+ {
+ return '<p>No estàs autentificat.</p><p>Pots tornar a intentar-ho fent click <a href="%s">aquí</a>.</p><p>Si el problema persisteix hauría de contactar amb l\'<a href="mailto:%s">administrador d\'aquest llocc</a>.</p>';
+ }
+
+ /**
+ * Get the service unavailable string
+ *
+ * @return string service unavailable
+ */
+ public function getServiceUnavailable()
+ {
+ return 'El servei `<b>%s</b>\' no està disponible (<b>%s</b>).';
+ }
+}
--- /dev/null
+<?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/Language/English.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * English language class
+ *
+ * @class CAS_Languages_English
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ * @sa @link internalLang Internationalization @endlink
+ * @ingroup internalLang
+ */
+class CAS_Languages_English implements CAS_Languages_LanguageInterface
+{
+ /**
+ * Get the using server string
+ *
+ * @return string using server
+ */
+ public function getUsingServer()
+ {
+ return 'using server';
+ }
+
+ /**
+ * Get authentication wanted string
+ *
+ * @return string authentication wanted
+ */
+ public function getAuthenticationWanted()
+ {
+ return 'CAS Authentication wanted!';
+ }
+
+ /**
+ * Get logout string
+ *
+ * @return string logout
+ */
+ public function getLogout()
+ {
+ return 'CAS logout wanted!';
+ }
+
+ /**
+ * Get the should have been redirected string
+ *
+ * @return string should habe been redirected
+ */
+ public function getShouldHaveBeenRedirected()
+ {
+ return 'You should already have been redirected to the CAS server. Click <a href="%s">here</a> to continue.';
+ }
+
+ /**
+ * Get authentication failed string
+ *
+ * @return string authentication failed
+ */
+ public function getAuthenticationFailed()
+ {
+ return 'CAS Authentication failed!';
+ }
+
+ /**
+ * Get the your were not authenticated string
+ *
+ * @return string not authenticated
+ */
+ public function getYouWereNotAuthenticated()
+ {
+ return '<p>You were not authenticated.</p><p>You may submit your request again by clicking <a href="%s">here</a>.</p><p>If the problem persists, you may contact <a href="mailto:%s">the administrator of this site</a>.</p>';
+ }
+
+ /**
+ * Get the service unavailable string
+ *
+ * @return string service unavailable
+ */
+ public function getServiceUnavailable()
+ {
+ return 'The service `<b>%s</b>\' is not available (<b>%s</b>).';
+ }
+}
\ No newline at end of file
--- /dev/null
+<?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/Language/French.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * French language class
+ *
+ * @class CAS_Languages_French
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ * @sa @link internalLang Internationalization @endlink
+ * @ingroup internalLang
+ */
+class CAS_Languages_French implements CAS_Languages_LanguageInterface
+{
+ /**
+ * Get the using server string
+ *
+ * @return string using server
+ */
+ public function getUsingServer()
+ {
+ return 'utilisant le serveur';
+ }
+
+ /**
+ * Get authentication wanted string
+ *
+ * @return string authentication wanted
+ */
+ public function getAuthenticationWanted()
+ {
+ return 'Authentication CAS nécessaire !';
+ }
+
+ /**
+ * Get logout string
+ *
+ * @return string logout
+ */
+ public function getLogout()
+ {
+ return 'Déconnexion demandée !';
+ }
+
+ /**
+ * Get the should have been redirected string
+ *
+ * @return string should habe been redirected
+ */
+ public function getShouldHaveBeenRedirected()
+ {
+ return 'Vous auriez du etre redirigé(e) vers le serveur CAS. Cliquez <a href="%s">ici</a> pour continuer.';
+ }
+
+ /**
+ * Get authentication failed string
+ *
+ * @return string authentication failed
+ */
+ public function getAuthenticationFailed()
+ {
+ return 'Authentification CAS infructueuse !';
+ }
+
+ /**
+ * Get the your were not authenticated string
+ *
+ * @return string not authenticated
+ */
+ public function getYouWereNotAuthenticated()
+ {
+ return '<p>Vous n\'avez pas été authentifié(e).</p><p>Vous pouvez soumettre votre requete à nouveau en cliquant <a href="%s">ici</a>.</p><p>Si le problème persiste, vous pouvez contacter <a href="mailto:%s">l\'administrateur de ce site</a>.</p>';
+ }
+
+ /**
+ * Get the service unavailable string
+ *
+ * @return string service unavailable
+ */
+ public function getServiceUnavailable()
+ {
+ return 'Le service `<b>%s</b>\' est indisponible (<b>%s</b>)';
+ }
+}
+
+?>
\ No newline at end of file
--- /dev/null
+<?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/Language/German.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Henrik Genssen <hg@mediafactory.de>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * German language class
+ *
+ * @class CAS_Languages_German
+ * @category Authentication
+ * @package PhpCAS
+ * @author Henrik Genssen <hg@mediafactory.de>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ * @sa @link internalLang Internationalization @endlink
+ * @ingroup internalLang
+ */
+class CAS_Languages_German implements CAS_Languages_LanguageInterface
+{
+ /**
+ * Get the using server string
+ *
+ * @return string using server
+ */
+ public function getUsingServer()
+ {
+ return 'via Server';
+ }
+
+ /**
+ * Get authentication wanted string
+ *
+ * @return string authentication wanted
+ */
+ public function getAuthenticationWanted()
+ {
+ return 'CAS Authentifizierung erforderlich!';
+ }
+
+ /**
+ * Get logout string
+ *
+ * @return string logout
+ */
+ public function getLogout()
+ {
+ return 'CAS Abmeldung!';
+ }
+
+ /**
+ * Get the should have been redirected string
+ *
+ * @return string should habe been redirected
+ */
+ public function getShouldHaveBeenRedirected()
+ {
+ return 'eigentlich häten Sie zum CAS Server weitergeleitet werden sollen. Drücken Sie <a href="%s">hier</a> um fortzufahren.';
+ }
+
+ /**
+ * Get authentication failed string
+ *
+ * @return string authentication failed
+ */
+ public function getAuthenticationFailed()
+ {
+ return 'CAS Anmeldung fehlgeschlagen!';
+ }
+
+ /**
+ * Get the your were not authenticated string
+ *
+ * @return string not authenticated
+ */
+ public function getYouWereNotAuthenticated()
+ {
+ return '<p>Sie wurden nicht angemeldet.</p><p>Um es erneut zu versuchen klicken Sie <a href="%s">hier</a>.</p><p>Wenn das Problem bestehen bleibt, kontkatieren Sie den <a href="mailto:%s">Administrator</a> dieser Seite.</p>';
+ }
+
+ /**
+ * Get the service unavailable string
+ *
+ * @return string service unavailable
+ */
+ public function getServiceUnavailable()
+ {
+ return 'Der Dienst `<b>%s</b>\' ist nicht verfügbar (<b>%s</b>).';
+ }
+}
+
+?>
\ No newline at end of file
--- /dev/null
+<?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/Language/Greek.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Vangelis Haniotakis <haniotak@ucnet.uoc.gr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * Greek language class
+ *
+ * @class CAS_Languages_Greek
+ * @category Authentication
+ * @package PhpCAS
+ * @author Vangelis Haniotakis <haniotak@ucnet.uoc.gr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ * @sa @link internalLang Internationalization @endlink
+ * @ingroup internalLang
+ */
+class CAS_Languages_Greek implements CAS_Languages_LanguageInterface
+{
+ /**
+ * Get the using server string
+ *
+ * @return string using server
+ */
+ public function getUsingServer()
+ {
+ return '÷ñçóéìïðïéåßôáé ï åîõðçñåôçôÞò';
+ }
+
+ /**
+ * Get authentication wanted string
+ *
+ * @return string authentication wanted
+ */
+ public function getAuthenticationWanted()
+ {
+ return 'Áðáéôåßôáé ç ôáõôïðïßçóç CAS!';
+ }
+
+ /**
+ * Get logout string
+ *
+ * @return string logout
+ */
+ public function getLogout()
+ {
+ return 'Áðáéôåßôáé ç áðïóýíäåóç áðü CAS!';
+ }
+
+ /**
+ * Get the should have been redirected string
+ *
+ * @return string should habe been redirected
+ */
+ public function getShouldHaveBeenRedirected()
+ {
+ return 'Èá Ýðñåðå íá åß÷áôå áíáêáôåõèõíèåß óôïí åîõðçñåôçôÞ CAS. ÊÜíôå êëßê <a href="%s">åäþ</a> ãéá íá óõíå÷ßóåôå.';
+ }
+
+ /**
+ * Get authentication failed string
+ *
+ * @return string authentication failed
+ */
+ public function getAuthenticationFailed()
+ {
+ return 'Ç ôáõôïðïßçóç CAS áðÝôõ÷å!';
+ }
+
+ /**
+ * Get the your were not authenticated string
+ *
+ * @return string not authenticated
+ */
+ public function getYouWereNotAuthenticated()
+ {
+ return '<p>Äåí ôáõôïðïéçèÞêáôå.</p><p>Ìðïñåßôå íá îáíáðñïóðáèÞóåôå, êÜíïíôáò êëßê <a href="%s">åäþ</a>.</p><p>Åáí ôï ðñüâëçìá åðéìåßíåé, åëÜôå óå åðáöÞ ìå ôïí <a href="mailto:%s">äéá÷åéñéóôÞ</a>.</p>';
+ }
+
+ /**
+ * Get the service unavailable string
+ *
+ * @return string service unavailable
+ */
+ public function getServiceUnavailable()
+ {
+ return 'Ç õðçñåóßá `<b>%s</b>\' äåí åßíáé äéáèÝóéìç (<b>%s</b>).';
+ }
+}
+?>
\ No newline at end of file
--- /dev/null
+<?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/Language/Japanese.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author fnorif <fnorif@yahoo.co.jp>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * Japanese language class. Now Encoding is EUC-JP and LF
+ *
+ * @class CAS_Languages_Japanese
+ * @category Authentication
+ * @package PhpCAS
+ * @author fnorif <fnorif@yahoo.co.jp>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ **/
+class CAS_Languages_Japanese implements CAS_Languages_LanguageInterface
+{
+ /**
+ * Get the using server string
+ *
+ * @return string using server
+ */
+ public function getUsingServer()
+ {
+ return 'using server';
+ }
+
+ /**
+ * Get authentication wanted string
+ *
+ * @return string authentication wanted
+ */
+ public function getAuthenticationWanted()
+ {
+ return 'CAS�ˤ��ǧ�ڤ�Ԥ��ޤ�';
+ }
+
+ /**
+ * Get logout string
+ *
+ * @return string logout
+ */
+ public function getLogout()
+ {
+ return 'CAS����?�����Ȥ��ޤ�!';
+ }
+
+ /**
+ * Get the should have been redirected string
+ *
+ * @return string should habe been redirected
+ */
+ public function getShouldHaveBeenRedirected()
+ {
+ return 'CAS�����Ф˹Ԥ�ɬ�פ�����ޤ�����ưŪ��ž������ʤ����� <a href="%s">������</a> ��å�����³�Ԥ��ޤ��';
+ }
+
+ /**
+ * Get authentication failed string
+ *
+ * @return string authentication failed
+ */
+ public function getAuthenticationFailed()
+ {
+ return 'CAS�ˤ��ǧ�ڤ˼��Ԥ��ޤ���';
+ }
+
+ /**
+ * Get the your were not authenticated string
+ *
+ * @return string not authenticated
+ */
+ public function getYouWereNotAuthenticated()
+ {
+ return '<p>ǧ�ڤǤ��ޤ���Ǥ���.</p><p>�⤦���٥ꥯ�����Ȥ������������<a href="%s">������</a>��å�.</p><p>���꤬��褷�ʤ����� <a href="mailto:%s">���Υ����Ȥδ����</a>���䤤��碌�Ƥ�������.</p>';
+ }
+
+ /**
+ * Get the service unavailable string
+ *
+ * @return string service unavailable
+ */
+ public function getServiceUnavailable()
+ {
+ return '�����ӥ� `<b>%s</b>\' �����ѤǤ��ޤ��� (<b>%s</b>).';
+ }
+}
+?>
\ No newline at end of file
--- /dev/null
+<?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/Language/LanguageInterface.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
+ */
+
+/**
+ * Language Interface class for all internationalization files
+ *
+ * @class CAS_Languages_LanguageInterface
+ * @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
+ *
+ * @sa @link internalLang Internationalization @endlink
+ * @ingroup internalLang
+ */
+
+interface CAS_Languages_LanguageInterface
+{
+ /**
+ * Get the using server string
+ *
+ * @return string using server
+ */
+ public function getUsingServer();
+
+ /**
+ * Get authentication wanted string
+ *
+ * @return string authentication wanted
+ */
+ public function getAuthenticationWanted();
+
+ /**
+ * Get logout string
+ *
+ * @return string logout
+ */
+ public function getLogout();
+
+ /**
+ * Get the should have been redirected string
+ *
+ * @return string should habe been redirected
+ */
+ public function getShouldHaveBeenRedirected();
+
+ /**
+ * Get authentication failed string
+ *
+ * @return string authentication failed
+ */
+ public function getAuthenticationFailed();
+
+ /**
+ * Get the your were not authenticated string
+ *
+ * @return string not authenticated
+ */
+ public function getYouWereNotAuthenticated();
+
+ /**
+ * Get the service unavailable string
+ *
+ * @return string service unavailable
+ */
+ public function getServiceUnavailable();
+
+}
+?>
\ No newline at end of file
--- /dev/null
+<?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/Language/Spanish.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Iván-Benjamín García Torà <ivaniclixx@gmail.com>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * Spanish language class
+ *
+ * @class CAS_Languages_Spanish
+ * @category Authentication
+ * @package PhpCAS
+ * @author Iván-Benjamín García Torà <ivaniclixx@gmail.com>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+
+ * @sa @link internalLang Internationalization @endlink
+ * @ingroup internalLang
+ */
+class CAS_Languages_Spanish implements CAS_Languages_LanguageInterface
+{
+
+ /**
+ * Get the using server string
+ *
+ * @return string using server
+ */
+ public function getUsingServer()
+ {
+ return 'usando servidor';
+ }
+
+ /**
+ * Get authentication wanted string
+ *
+ * @return string authentication wanted
+ */
+ public function getAuthenticationWanted()
+ {
+ return '¡Autentificación CAS necesaria!';
+ }
+
+ /**
+ * Get logout string
+ *
+ * @return string logout
+ */
+ public function getLogout()
+ {
+ return '¡Salida CAS necesaria!';
+ }
+
+ /**
+ * Get the should have been redirected string
+ *
+ * @return string should habe been redirected
+ */
+ public function getShouldHaveBeenRedirected()
+ {
+ return 'Ya debería haber sido redireccionado al servidor CAS. Haga click <a href="%s">aquí</a> para continuar.';
+ }
+
+ /**
+ * Get authentication failed string
+ *
+ * @return string authentication failed
+ */
+ public function getAuthenticationFailed()
+ {
+ return '¡Autentificación CAS fallida!';
+ }
+
+ /**
+ * Get the your were not authenticated string
+ *
+ * @return string not authenticated
+ */
+ public function getYouWereNotAuthenticated()
+ {
+ return '<p>No estás autentificado.</p><p>Puedes volver a intentarlo haciendo click <a href="%s">aquí</a>.</p><p>Si el problema persiste debería contactar con el <a href="mailto:%s">administrador de este sitio</a>.</p>';
+ }
+
+ /**
+ * Get the service unavailable string
+ *
+ * @return string service unavailable
+ */
+ public function getServiceUnavailable()
+ {
+ return 'El servicio `<b>%s</b>\' no está disponible (<b>%s</b>).';
+ }
+}
+?>
--- /dev/null
+<?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/OutOfSequenceException.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * This class defines Exceptions that should be thrown when the sequence of
+ * operations is invalid. Examples are:
+ * - Requesting the response before executing a request.
+ * - Changing the URL of a request after executing the request.
+ *
+ * @class CAS_OutOfSequenceException
+ * @category Authentication
+ * @package PhpCAS
+ * @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_OutOfSequenceException
+extends BadMethodCallException
+implements CAS_Exception
+{
+
+}
--- /dev/null
+<?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/PGTStorage/AbstractStorage.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * Basic class for PGT storage
+ * The CAS_PGTStorage_AbstractStorage class is a generic class for PGT storage.
+ * This class should not be instanciated itself but inherited by specific PGT
+ * storage classes.
+ *
+ * @class CAS_PGTStorage_AbstractStorage
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ * @ingroup internalPGTStorage
+ */
+
+abstract class CAS_PGTStorage_AbstractStorage
+{
+ /**
+ * @addtogroup internalPGTStorage
+ * @{
+ */
+
+ // ########################################################################
+ // CONSTRUCTOR
+ // ########################################################################
+
+ /**
+ * The constructor of the class, should be called only by inherited classes.
+ *
+ * @param CAS_Client $cas_parent the CAS _client instance that creates the
+ * current object.
+ *
+ * @return void
+ *
+ * @protected
+ */
+ function __construct($cas_parent)
+ {
+ phpCAS::traceBegin();
+ if ( !$cas_parent->isProxy() ) {
+ phpCAS::error('defining PGT storage makes no sense when not using a CAS proxy');
+ }
+ phpCAS::traceEnd();
+ }
+
+ // ########################################################################
+ // DEBUGGING
+ // ########################################################################
+
+ /**
+ * This virtual method returns an informational string giving the type of storage
+ * used by the object (used for debugging purposes).
+ *
+ * @return void
+ *
+ * @public
+ */
+ function getStorageType()
+ {
+ phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called');
+ }
+
+ /**
+ * This virtual method returns an informational string giving informations on the
+ * parameters of the storage.(used for debugging purposes).
+ *
+ * @return void
+ *
+ * @public
+ */
+ function getStorageInfo()
+ {
+ phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called');
+ }
+
+ // ########################################################################
+ // ERROR HANDLING
+ // ########################################################################
+
+ /**
+ * string used to store an error message. Written by
+ * PGTStorage::setErrorMessage(), read by PGTStorage::getErrorMessage().
+ *
+ * @hideinitializer
+ * @deprecated not used.
+ */
+ var $_error_message=false;
+
+ /**
+ * This method sets en error message, which can be read later by
+ * PGTStorage::getErrorMessage().
+ *
+ * @param string $error_message an error message
+ *
+ * @return void
+ *
+ * @deprecated not used.
+ */
+ function setErrorMessage($error_message)
+ {
+ $this->_error_message = $error_message;
+ }
+
+ /**
+ * This method returns an error message set by PGTStorage::setErrorMessage().
+ *
+ * @return an error message when set by PGTStorage::setErrorMessage(), FALSE
+ * otherwise.
+ *
+ * @deprecated not used.
+ */
+ function getErrorMessage()
+ {
+ return $this->_error_message;
+ }
+
+ // ########################################################################
+ // INITIALIZATION
+ // ########################################################################
+
+ /**
+ * a boolean telling if the storage has already been initialized. Written by
+ * PGTStorage::init(), read by PGTStorage::isInitialized().
+ *
+ * @hideinitializer
+ */
+ var $_initialized = false;
+
+ /**
+ * This method tells if the storage has already been intialized.
+ *
+ * @return a boolean
+ *
+ * @protected
+ */
+ function isInitialized()
+ {
+ return $this->_initialized;
+ }
+
+ /**
+ * This virtual method initializes the object.
+ *
+ * @return void
+ */
+ function init()
+ {
+ $this->_initialized = true;
+ }
+
+ // ########################################################################
+ // PGT I/O
+ // ########################################################################
+
+ /**
+ * This virtual method stores a PGT and its corresponding PGT Iuo.
+ *
+ * @param string $pgt the PGT
+ * @param string $pgt_iou the PGT iou
+ *
+ * @return void
+ *
+ * @note Should never be called.
+ *
+ */
+ function write($pgt,$pgt_iou)
+ {
+ phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called');
+ }
+
+ /**
+ * This virtual method reads a PGT corresponding to a PGT Iou and deletes
+ * the corresponding storage entry.
+ *
+ * @param string $pgt_iou the PGT iou
+ *
+ * @return void
+ *
+ * @note Should never be called.
+ */
+ function read($pgt_iou)
+ {
+ phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called');
+ }
+
+ /** @} */
+
+}
+
+?>
--- /dev/null
+<?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/PGTStorage/Db.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Daniel Frett <daniel.frett@gmail.com>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+define('CAS_PGT_STORAGE_DB_DEFAULT_TABLE', 'cas_pgts');
+
+/**
+ * Basic class for PGT database storage
+ * The CAS_PGTStorage_Db class is a class for PGT database storage.
+ *
+ * @class CAS_PGTStorage_Db
+ * @category Authentication
+ * @package PhpCAS
+ * @author Daniel Frett <daniel.frett@gmail.com>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ * @ingroup internalPGTStorageDb
+ */
+
+class CAS_PGTStorage_Db extends CAS_PGTStorage_AbstractStorage
+{
+ /**
+ * @addtogroup internalCAS_PGTStorageDb
+ * @{
+ */
+
+ /**
+ * the PDO object to use for database interactions
+ */
+ private $_pdo;
+
+ /**
+ * This method returns the PDO object to use for database interactions.
+ *
+ * @return the PDO object
+ */
+ private function _getPdo()
+ {
+ return $this->_pdo;
+ }
+
+ /**
+ * database connection options to use when creating a new PDO object
+ */
+ private $_dsn;
+ private $_username;
+ private $_password;
+ private $_table_options;
+
+ /**
+ * the table to use for storing/retrieving pgt's
+ */
+ private $_table;
+
+ /**
+ * This method returns the table to use when storing/retrieving PGT's
+ *
+ * @return the name of the pgt storage table.
+ */
+ private function _getTable()
+ {
+ return $this->_table;
+ }
+
+ // ########################################################################
+ // DEBUGGING
+ // ########################################################################
+
+ /**
+ * This method returns an informational string giving the type of storage
+ * used by the object (used for debugging purposes).
+ *
+ * @return an informational string.
+ */
+ public function getStorageType()
+ {
+ return "db";
+ }
+
+ /**
+ * This method returns an informational string giving informations on the
+ * parameters of the storage.(used for debugging purposes).
+ *
+ * @return an informational string.
+ * @public
+ */
+ public function getStorageInfo()
+ {
+ return 'table=`'.$this->_getTable().'\'';
+ }
+
+ // ########################################################################
+ // CONSTRUCTOR
+ // ########################################################################
+
+ /**
+ * The class constructor.
+ *
+ * @param CAS_Client $cas_parent the CAS_Client instance that creates
+ * the object.
+ * @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
+ */
+ public function __construct($cas_parent, $dsn_or_pdo, $username='', $password='', $table='', $driver_options=null)
+ {
+ phpCAS::traceBegin();
+ // call the ancestor's constructor
+ parent::__construct($cas_parent);
+
+ // set default values
+ if ( empty($table) ) {
+ $table = CAS_PGT_STORAGE_DB_DEFAULT_TABLE;
+ }
+ if ( !is_array($driver_options) ) {
+ $driver_options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
+ }
+
+ // store the specified parameters
+ if ($dsn_or_pdo instanceof PDO) {
+ $this->_pdo = $dsn_or_pdo;
+ } else {
+ $this->_dsn = $dsn_or_pdo;
+ $this->_username = $username;
+ $this->_password = $password;
+ $this->_driver_options = $driver_options;
+ }
+
+ // store the table name
+ $this->_table = $table;
+
+ phpCAS::traceEnd();
+ }
+
+ // ########################################################################
+ // INITIALIZATION
+ // ########################################################################
+
+ /**
+ * This method is used to initialize the storage. Halts on error.
+ *
+ * @return void
+ */
+ public function init()
+ {
+ phpCAS::traceBegin();
+ // if the storage has already been initialized, return immediatly
+ if ($this->isInitialized()) {
+ return;
+ }
+
+ // initialize the base object
+ parent::init();
+
+ // create the PDO object if it doesn't exist already
+ if (!($this->_pdo instanceof PDO)) {
+ try {
+ $this->_pdo = new PDO($this->_dsn, $this->_username, $this->_password, $this->_driver_options);
+ }
+ catch(PDOException $e) {
+ phpCAS::error('Database connection error: ' . $e->getMessage());
+ }
+ }
+
+ phpCAS::traceEnd();
+ }
+
+ // ########################################################################
+ // PDO database interaction
+ // ########################################################################
+
+ /**
+ * attribute that stores the previous error mode for the PDO handle while
+ * processing a transaction
+ */
+ private $_errMode;
+
+ /**
+ * This method will enable the Exception error mode on the PDO object
+ *
+ * @return void
+ */
+ private function _setErrorMode()
+ {
+ // get PDO object and enable exception error mode
+ $pdo = $this->_getPdo();
+ $this->_errMode = $pdo->getAttribute(PDO::ATTR_ERRMODE);
+ $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+ }
+
+ /**
+ * this method will reset the error mode on the PDO object
+ *
+ * @return void
+ */
+ private function _resetErrorMode()
+ {
+ // get PDO object and reset the error mode to what it was originally
+ $pdo = $this->_getPdo();
+ $pdo->setAttribute(PDO::ATTR_ERRMODE, $this->_errMode);
+ }
+
+ // ########################################################################
+ // database queries
+ // ########################################################################
+ // these queries are potentially unsafe because the person using this library
+ // can set the table to use, but there is no reliable way to escape SQL
+ // fieldnames in PDO yet
+
+ /**
+ * This method returns the query used to create a pgt storage table
+ *
+ * @return the create table SQL, no bind params in query
+ */
+ protected function createTableSql()
+ {
+ return 'CREATE TABLE ' . $this->_getTable() . ' (pgt_iou VARCHAR(255) NOT NULL PRIMARY KEY, pgt VARCHAR(255) NOT NULL)';
+ }
+
+ /**
+ * This method returns the query used to store a pgt
+ *
+ * @return the store PGT SQL, :pgt and :pgt_iou are the bind params contained in the query
+ */
+ protected function storePgtSql()
+ {
+ return 'INSERT INTO ' . $this->_getTable() . ' (pgt_iou, pgt) VALUES (:pgt_iou, :pgt)';
+ }
+
+ /**
+ * This method returns the query used to retrieve a pgt. the first column of the first row should contain the pgt
+ *
+ * @return the retrieve PGT SQL, :pgt_iou is the only bind param contained in the query
+ */
+ protected function retrievePgtSql()
+ {
+ return 'SELECT pgt FROM ' . $this->_getTable() . ' WHERE pgt_iou = :pgt_iou';
+ }
+
+ /**
+ * This method returns the query used to delete a pgt.
+ *
+ * @return the delete PGT SQL, :pgt_iou is the only bind param contained in the query
+ */
+ protected function deletePgtSql()
+ {
+ return 'DELETE FROM ' . $this->_getTable() . ' WHERE pgt_iou = :pgt_iou';
+ }
+
+ // ########################################################################
+ // PGT I/O
+ // ########################################################################
+
+ /**
+ * This method creates the database table used to store pgt's and pgtiou's
+ *
+ * @return void
+ */
+ public function createTable()
+ {
+ phpCAS::traceBegin();
+
+ // initialize this PGTStorage object if it hasn't been initialized yet
+ if ( !$this->isInitialized() ) {
+ $this->init();
+ }
+
+ // initialize the PDO object for this method
+ $pdo = $this->_getPdo();
+ $this->_setErrorMode();
+
+ try {
+ $pdo->beginTransaction();
+
+ $query = $pdo->query($this->createTableSQL());
+ $query->closeCursor();
+
+ $pdo->commit();
+ }
+ catch(PDOException $e) {
+ // attempt rolling back the transaction before throwing a phpCAS error
+ try {
+ $pdo->rollBack();
+ }
+ catch(PDOException $e) {
+ }
+ phpCAS::error('error creating PGT storage table: ' . $e->getMessage());
+ }
+
+ // reset the PDO object
+ $this->_resetErrorMode();
+
+ phpCAS::traceEnd();
+ }
+
+ /**
+ * This method stores a PGT and its corresponding PGT Iou in the database.
+ * Echoes a warning on error.
+ *
+ * @param string $pgt the PGT
+ * @param string $pgt_iou the PGT iou
+ *
+ * @return void
+ */
+ public function write($pgt, $pgt_iou)
+ {
+ phpCAS::traceBegin();
+
+ // initialize the PDO object for this method
+ $pdo = $this->_getPdo();
+ $this->_setErrorMode();
+
+ try {
+ $pdo->beginTransaction();
+
+ $query = $pdo->prepare($this->storePgtSql());
+ $query->bindValue(':pgt', $pgt, PDO::PARAM_STR);
+ $query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR);
+ $query->execute();
+ $query->closeCursor();
+
+ $pdo->commit();
+ }
+ catch(PDOException $e) {
+ // attempt rolling back the transaction before throwing a phpCAS error
+ try {
+ $pdo->rollBack();
+ }
+ catch(PDOException $e) {
+ }
+ phpCAS::error('error writing PGT to database: ' . $e->getMessage());
+ }
+
+ // reset the PDO object
+ $this->_resetErrorMode();
+
+ phpCAS::traceEnd();
+ }
+
+ /**
+ * This method reads a PGT corresponding to a PGT Iou and deletes the
+ * corresponding db entry.
+ *
+ * @param string $pgt_iou the PGT iou
+ *
+ * @return the corresponding PGT, or FALSE on error
+ */
+ public function read($pgt_iou)
+ {
+ phpCAS::traceBegin();
+ $pgt = false;
+
+ // initialize the PDO object for this method
+ $pdo = $this->_getPdo();
+ $this->_setErrorMode();
+
+ try {
+ $pdo->beginTransaction();
+
+ // fetch the pgt for the specified pgt_iou
+ $query = $pdo->prepare($this->retrievePgtSql());
+ $query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR);
+ $query->execute();
+ $pgt = $query->fetchColumn(0);
+ $query->closeCursor();
+
+ // delete the specified pgt_iou from the database
+ $query = $pdo->prepare($this->deletePgtSql());
+ $query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR);
+ $query->execute();
+ $query->closeCursor();
+
+ $pdo->commit();
+ }
+ catch(PDOException $e) {
+ // attempt rolling back the transaction before throwing a phpCAS error
+ try {
+ $pdo->rollBack();
+ }
+ catch(PDOException $e) {
+ }
+ phpCAS::trace('error reading PGT from database: ' . $e->getMessage());
+ }
+
+ // reset the PDO object
+ $this->_resetErrorMode();
+
+ phpCAS::traceEnd();
+ return $pgt;
+ }
+
+ /** @} */
+
+}
+
+?>
--- /dev/null
+<?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/PGTStorage/AbstractStorage.php
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ */
+
+/**
+ * The CAS_PGTStorage_File class is a class for PGT file storage. An instance of
+ * this class is returned by CAS_Client::SetPGTStorageFile().
+ *
+ * @class CAS_PGTStorage_File
+ * @category Authentication
+ * @package PhpCAS
+ * @author Pascal Aubry <pascal.aubry@univ-rennes1.fr>
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
+ * @link https://wiki.jasig.org/display/CASC/phpCAS
+ *
+ *
+ * @ingroup internalPGTStorageFile
+ */
+
+class CAS_PGTStorage_File extends CAS_PGTStorage_AbstractStorage
+{
+ /**
+ * @addtogroup internalPGTStorageFile
+ * @{
+ */
+
+ /**
+ * a string telling where PGT's should be stored on the filesystem. Written by
+ * PGTStorageFile::PGTStorageFile(), read by getPath().
+ *
+ * @private
+ */
+ var $_path;
+
+ /**
+ * This method returns the name of the directory where PGT's should be stored
+ * on the filesystem.
+ *
+ * @return the name of a directory (with leading and trailing '/')
+ *
+ * @private
+ */
+ function getPath()
+ {
+ return $this->_path;
+ }
+
+ // ########################################################################
+ // DEBUGGING
+ // ########################################################################
+
+ /**
+ * This method returns an informational string giving the type of storage
+ * used by the object (used for debugging purposes).
+ *
+ * @return an informational string.
+ * @public
+ */
+ function getStorageType()
+ {
+ return "file";
+ }
+
+ /**
+ * This method returns an informational string giving informations on the
+ * parameters of the storage.(used for debugging purposes).
+ *
+ * @return an informational string.
+ * @public
+ */
+ function getStorageInfo()
+ {
+ return 'path=`'.$this->getPath().'\'';
+ }
+
+ // ########################################################################
+ // CONSTRUCTOR
+ // ########################################################################
+
+ /**
+ * The class constructor, called by CAS_Client::SetPGTStorageFile().
+ *
+ * @param CAS_Client $cas_parent the CAS_Client instance that creates the object.
+ * @param string $path the path where the PGT's should be stored
+ *
+ * @return void
+ *
+ * @public
+ */
+ function __construct($cas_parent,$path)
+ {
+ phpCAS::traceBegin();
+ // call the ancestor's constructor
+ parent::__construct($cas_parent);
+
+ if (empty($path)) {
+ $path = CAS_PGT_STORAGE_FILE_DEFAULT_PATH;
+ }
+ // check that the path is an absolute path
+ if (getenv("OS")=="Windows_NT") {
+
+ if (!preg_match('`^[a-zA-Z]:`', $path)) {
+ phpCAS::error('an absolute path is needed for PGT storage to file');
+ }
+
+ } else {
+
+ if ( $path[0] != '/' ) {
+ phpCAS::error('an absolute path is needed for PGT storage to file');
+ }
+
+ // store the path (with a leading and trailing '/')
+ $path = preg_replace('|[/]*$|', '/', $path);
+ $path = preg_replace('|^[/]*|', '/', $path);
+ }
+
+ $this->_path = $path;
+ phpCAS::traceEnd();
+ }
+
+ // ########################################################################
+ // INITIALIZATION
+ // ########################################################################
+
+ /**
+ * This method is used to initialize the storage. Halts on error.
+ *
+ * @return void
+ * @public
+ */
+ function init()
+ {
+ phpCAS::traceBegin();
+ // if the storage has already been initialized, return immediatly
+ if ($this->isInitialized()) {
+ return;
+ }
+ // call the ancestor's method (mark as initialized)
+ parent::init();
+ phpCAS::traceEnd();
+ }
+
+ // ########################################################################
+ // PGT I/O
+ // ########################################################################
+
+ /**
+ * This method returns the filename corresponding to a PGT Iou.
+ *
+ * @param string $pgt_iou the PGT iou.
+ *
+ * @return a filename
+ * @private
+ */
+ function getPGTIouFilename($pgt_iou)
+ {
+ phpCAS::traceBegin();
+ $filename = $this->getPath().$pgt_iou.'.plain';
+ phpCAS::traceEnd($filename);
+ return $filename;
+ }
+
+ /**
+ * This method stores a PGT and its corresponding PGT Iou into a file. Echoes a
+ * warning on error.
+ *
+ * @param string $pgt the PGT
+ * @param string $pgt_iou the PGT iou
+ *
+ * @return void
+ *
+ * @public
+ */
+ function write($pgt,$pgt_iou)
+ {
+ phpCAS::traceBegin();
+ $fname = $this->getPGTIouFilename($pgt_iou);
+ if (!file_exists($fname)) {
+ touch($fname);
+ // Chmod will fail on windows
+ @chmod($fname, 0600);
+ if ($f=fopen($fname, "w")) {
+ if (fputs($f, $pgt) === false) {
+ phpCAS::error('could not write PGT to `'.$fname.'\'');
+ }
+ phpCAS::trace('Successful write of PGT to `'.$fname.'\'');
+ fclose($f);
+ } else {
+ phpCAS::error('could not open `'.$fname.'\'');
+ }
+ } else {
+ phpCAS::error('File exists: `'.$fname.'\'');
+ }
+ phpCAS::traceEnd();
+ }
+
+ /**
+ * This method reads a PGT corresponding to a PGT Iou and deletes the
+ * corresponding file.
+ *
+ * @param string $pgt_iou the PGT iou
+ *
+ * @return the corresponding PGT, or FALSE on error
+ *
+ * @public
+ */
+ function read($pgt_iou)
+ {
+ phpCAS::traceBegin();
+ $pgt = false;
+ $fname = $this->getPGTIouFilename($pgt_iou);
+ if (file_exists($fname)) {
+ if (!($f=fopen($fname, "r"))) {
+ phpCAS::error('could not open `'.$fname.'\'');
+ } else {
+ if (($pgt=fgets($f)) === false) {
+ phpCAS::error('could not read PGT from `'.$fname.'\'');
+ }
+ phpCAS::trace('Successful read of PGT to `'.$fname.'\'');
+ fclose($f);
+ }
+ // delete the PGT file
+ @unlink($fname);
+ } else {
+ phpCAS::error('No such file `'.$fname.'\'');
+ }
+ phpCAS::traceEnd($pgt);
+ return $pgt;
+ }
+
+ /** @} */
+
+}
+?>
\ No newline at end of file
+++ /dev/null
-<?php\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
- * @file CAS/PGTStorage/pgt-file.php\r
- * Basic class for PGT file storage\r
- */\r
-\r
-/**\r
- * @class PGTStorageFile\r
- * The PGTStorageFile class is a class for PGT file storage. An instance of \r
- * this class is returned by CASClient::SetPGTStorageFile().\r
- *\r
- * @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>\r
- *\r
- * @ingroup internalPGTStorageFile\r
- */\r
-\r
-class PGTStorageFile extends PGTStorage\r
-{\r
- /** \r
- * @addtogroup internalPGTStorageFile \r
- * @{ \r
- */\r
-\r
- /**\r
- * a string telling where PGT's should be stored on the filesystem. Written by\r
- * PGTStorageFile::PGTStorageFile(), read by getPath().\r
- *\r
- * @private\r
- */\r
- var $_path;\r
-\r
- /**\r
- * This method returns the name of the directory where PGT's should be stored \r
- * on the filesystem.\r
- *\r
- * @return the name of a directory (with leading and trailing '/')\r
- *\r
- * @private\r
- */\r
- function getPath()\r
- {\r
- return $this->_path;\r
- }\r
-\r
- /**\r
- * a string telling the format to use to store PGT's (plain or xml). Written by\r
- * PGTStorageFile::PGTStorageFile(), read by getFormat().\r
- *\r
- * @private\r
- */\r
- var $_format;\r
-\r
- /**\r
- * This method returns the format to use when storing PGT's on the filesystem.\r
- *\r
- * @return a string corresponding to the format used (plain or xml).\r
- *\r
- * @private\r
- */\r
- function getFormat()\r
- {\r
- return $this->_format;\r
- }\r
-\r
- // ########################################################################\r
- // DEBUGGING\r
- // ########################################################################\r
- \r
- /**\r
- * This method returns an informational string giving the type of storage\r
- * used by the object (used for debugging purposes).\r
- *\r
- * @return an informational string.\r
- * @public\r
- */\r
- function getStorageType()\r
- {\r
- return "file";\r
- }\r
-\r
- /**\r
- * This method returns an informational string giving informations on the\r
- * parameters of the storage.(used for debugging purposes).\r
- *\r
- * @return an informational string.\r
- * @public\r
- */\r
- function getStorageInfo()\r
- {\r
- return 'path=`'.$this->getPath().'\', format=`'.$this->getFormat().'\'';\r
- }\r
-\r
- // ########################################################################\r
- // CONSTRUCTOR\r
- // ########################################################################\r
- \r
- /**\r
- * The class constructor, called by CASClient::SetPGTStorageFile().\r
- *\r
- * @param $cas_parent the CASClient instance that creates the object.\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\r
- */\r
- function PGTStorageFile($cas_parent,$format,$path)\r
- {\r
- phpCAS::traceBegin();\r
- // call the ancestor's constructor\r
- $this->PGTStorage($cas_parent);\r
-\r
- if (empty($format) ) $format = CAS_PGT_STORAGE_FILE_DEFAULT_FORMAT;\r
- if (empty($path) ) $path = CAS_PGT_STORAGE_FILE_DEFAULT_PATH;\r
-\r
- // check that the path is an absolute path\r
- if (getenv("OS")=="Windows_NT"){\r
- \r
- if (!preg_match('`^[a-zA-Z]:`', $path)) {\r
- phpCAS::error('an absolute path is needed for PGT storage to file');\r
- }\r
- \r
- }\r
- else\r
- {\r
- \r
- if ( $path[0] != '/' ) {\r
- phpCAS::error('an absolute path is needed for PGT storage to file');\r
- }\r
-\r
- // store the path (with a leading and trailing '/') \r
- $path = preg_replace('|[/]*$|','/',$path);\r
- $path = preg_replace('|^[/]*|','/',$path);\r
- }\r
- \r
- $this->_path = $path;\r
- // check the format and store it\r
- switch ($format) {\r
- case CAS_PGT_STORAGE_FILE_FORMAT_PLAIN:\r
- case CAS_PGT_STORAGE_FILE_FORMAT_XML:\r
- $this->_format = $format;\r
- break;\r
- default:\r
- phpCAS::error('unknown PGT file storage format (`'.CAS_PGT_STORAGE_FILE_FORMAT_PLAIN.'\' and `'.CAS_PGT_STORAGE_FILE_FORMAT_XML.'\' allowed)');\r
- }\r
- phpCAS::traceEnd(); \r
- }\r
-\r
- // ########################################################################\r
- // INITIALIZATION\r
- // ########################################################################\r
- \r
- /**\r
- * This method is used to initialize the storage. Halts on error.\r
- *\r
- * @public\r
- */\r
- function init()\r
- {\r
- phpCAS::traceBegin();\r
- // if the storage has already been initialized, return immediatly\r
- if ( $this->isInitialized() )\r
- return;\r
- // call the ancestor's method (mark as initialized)\r
- parent::init();\r
- phpCAS::traceEnd(); \r
- }\r
-\r
- // ########################################################################\r
- // PGT I/O\r
- // ########################################################################\r
-\r
- /**\r
- * This method returns the filename corresponding to a PGT Iou.\r
- *\r
- * @param $pgt_iou the PGT iou.\r
- *\r
- * @return a filename\r
- * @private\r
- */\r
- function getPGTIouFilename($pgt_iou)\r
- {\r
- phpCAS::traceBegin();\r
- $filename = $this->getPath().$pgt_iou.'.'.$this->getFormat();\r
- phpCAS::traceEnd($filename);\r
- return $filename;\r
- }\r
- \r
- /**\r
- * This method stores a PGT and its corresponding PGT Iou into a file. Echoes a\r
- * warning on error.\r
- *\r
- * @param $pgt the PGT\r
- * @param $pgt_iou the PGT iou\r
- *\r
- * @public\r
- */\r
- function write($pgt,$pgt_iou)\r
- {\r
- phpCAS::traceBegin();\r
- $fname = $this->getPGTIouFilename($pgt_iou);\r
- if(!file_exists($fname)){\r
- if ( $f=fopen($fname,"w") ) {\r
- if ( fputs($f,$pgt) === FALSE ) {\r
- phpCAS::error('could not write PGT to `'.$fname.'\'');\r
- }\r
- fclose($f);\r
- } else {\r
- phpCAS::error('could not open `'.$fname.'\'');\r
- }\r
- }else{\r
- phpCAS::error('File exists: `'.$fname.'\'');\r
- }\r
- phpCAS::traceEnd(); \r
- }\r
-\r
- /**\r
- * This method reads a PGT corresponding to a PGT Iou and deletes the \r
- * corresponding file.\r
- *\r
- * @param $pgt_iou the PGT iou\r
- *\r
- * @return the corresponding PGT, or FALSE on error\r
- *\r
- * @public\r
- */\r
- function read($pgt_iou)\r
- {\r
- phpCAS::traceBegin();\r
- $pgt = FALSE;\r
- $fname = $this->getPGTIouFilename($pgt_iou);\r
- if (file_exists($fname)){\r
- if ( !($f=fopen($fname,"r")) ) {\r
- phpCAS::trace('could not open `'.$fname.'\'');\r
- } else {\r
- if ( ($pgt=fgets($f)) === FALSE ) {\r
- phpCAS::trace('could not read PGT from `'.$fname.'\'');\r
- } \r
- fclose($f);\r
- }\r
- \r
- // delete the PGT file\r
- @unlink($fname);\r
- }else{\r
- phpCAS::trace('No such file `'.$fname.'\'');\r
- }\r
- phpCAS::traceEnd($pgt);\r
- return $pgt;\r
- }\r
- \r
- /** @} */\r
- \r
-}\r
-\r
- \r
-?>
\ No newline at end of file
+++ /dev/null
-<?php\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
- * @file CAS/PGTStorage/pgt-main.php\r
- * Basic class for PGT storage\r
- */\r
-\r
-/**\r
- * @class PGTStorage\r
- * The PGTStorage class is a generic class for PGT storage. This class should\r
- * not be instanciated itself but inherited by specific PGT storage classes.\r
- *\r
- * @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>\r
- *\r
- * @ingroup internalPGTStorage\r
- */\r
-\r
-class PGTStorage\r
-{\r
- /** \r
- * @addtogroup internalPGTStorage\r
- * @{ \r
- */\r
-\r
- // ########################################################################\r
- // CONSTRUCTOR\r
- // ########################################################################\r
- \r
- /**\r
- * The constructor of the class, should be called only by inherited classes.\r
- *\r
- * @param $cas_parent the CASclient instance that creates the current object.\r
- *\r
- * @protected\r
- */\r
- function PGTStorage($cas_parent)\r
- {\r
- phpCAS::traceBegin();\r
- if ( !$cas_parent->isProxy() ) {\r
- phpCAS::error('defining PGT storage makes no sense when not using a CAS proxy'); \r
- }\r
- phpCAS::traceEnd();\r
- }\r
-\r
- // ########################################################################\r
- // DEBUGGING\r
- // ########################################################################\r
- \r
- /**\r
- * This virtual method returns an informational string giving the type of storage\r
- * used by the object (used for debugging purposes).\r
- *\r
- * @public\r
- */\r
- function getStorageType()\r
- {\r
- phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); \r
- }\r
-\r
- /**\r
- * This virtual method returns an informational string giving informations on the\r
- * parameters of the storage.(used for debugging purposes).\r
- *\r
- * @public\r
- */\r
- function getStorageInfo()\r
- {\r
- phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); \r
- }\r
-\r
- // ########################################################################\r
- // ERROR HANDLING\r
- // ########################################################################\r
- \r
- /**\r
- * string used to store an error message. Written by PGTStorage::setErrorMessage(),\r
- * read by PGTStorage::getErrorMessage().\r
- *\r
- * @hideinitializer\r
- * @private\r
- * @deprecated not used.\r
- */\r
- var $_error_message=FALSE;\r
-\r
- /**\r
- * This method sets en error message, which can be read later by \r
- * PGTStorage::getErrorMessage().\r
- *\r
- * @param $error_message an error message\r
- *\r
- * @protected\r
- * @deprecated not used.\r
- */\r
- function setErrorMessage($error_message)\r
- {\r
- $this->_error_message = $error_message;\r
- }\r
-\r
- /**\r
- * This method returns an error message set by PGTStorage::setErrorMessage().\r
- *\r
- * @return an error message when set by PGTStorage::setErrorMessage(), FALSE\r
- * otherwise.\r
- *\r
- * @public\r
- * @deprecated not used.\r
- */\r
- function getErrorMessage()\r
- {\r
- return $this->_error_message;\r
- }\r
-\r
- // ########################################################################\r
- // INITIALIZATION\r
- // ########################################################################\r
-\r
- /**\r
- * a boolean telling if the storage has already been initialized. Written by \r
- * PGTStorage::init(), read by PGTStorage::isInitialized().\r
- *\r
- * @hideinitializer\r
- * @private\r
- */\r
- var $_initialized = FALSE;\r
-\r
- /**\r
- * This method tells if the storage has already been intialized.\r
- *\r
- * @return a boolean\r
- *\r
- * @protected\r
- */\r
- function isInitialized()\r
- {\r
- return $this->_initialized;\r
- }\r
-\r
- /**\r
- * This virtual method initializes the object.\r
- *\r
- * @protected\r
- */\r
- function init()\r
- {\r
- $this->_initialized = TRUE;\r
- }\r
-\r
- // ########################################################################\r
- // PGT I/O\r
- // ########################################################################\r
-\r
- /**\r
- * This virtual method stores a PGT and its corresponding PGT Iuo.\r
- * @note Should never be called.\r
- *\r
- * @param $pgt the PGT\r
- * @param $pgt_iou the PGT iou\r
- *\r
- * @protected\r
- */\r
- function write($pgt,$pgt_iou)\r
- {\r
- phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); \r
- }\r
-\r
- /**\r
- * This virtual method reads a PGT corresponding to a PGT Iou and deletes\r
- * the corresponding storage entry.\r
- * @note Should never be called.\r
- *\r
- * @param $pgt_iou the PGT iou\r
- *\r
- * @protected\r
- */\r
- function read($pgt_iou)\r
- {\r
- phpCAS::error(__CLASS__.'::'.__FUNCTION__.'() should never be called'); \r
- }\r
-\r
- /** @} */\r
- \r
-} \r
-\r
-// include specific PGT storage classes\r
-include_once(dirname(__FILE__).'/pgt-file.php'); \r
- \r
-?>
\ No newline at end of file
--- /dev/null
+<?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/ProxiedService.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * 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_ProxiedService
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+interface CAS_ProxiedService
+{
+
+ /**
+ * Answer a service identifier (URL) for whom we should fetch a proxy ticket.
+ *
+ * @return string
+ * @throws Exception If no service url is available.
+ */
+ public function getServiceUrl ();
+
+ /**
+ * Register a proxy ticket with the ProxiedService that it can use when
+ * making requests.
+ *
+ * @param string $proxyTicket Proxy ticket string
+ *
+ * @return void
+ * @throws InvalidArgumentException If the $proxyTicket is invalid.
+ * @throws CAS_OutOfSequenceException If called after a proxy ticket has
+ * already been initialized/set.
+ */
+ public function setProxyTicket ($proxyTicket);
+
+}
+?>
--- /dev/null
+<?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/ProxiedService/Abstract.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * This class implements common methods for ProxiedService implementations included
+ * with phpCAS.
+ *
+ * @class CAS_ProxiedService_Abstract
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+abstract class CAS_ProxiedService_Abstract
+implements CAS_ProxiedService, CAS_ProxiedService_Testable
+{
+
+ /**
+ * The proxy ticket that can be used when making service requests.
+ * @var string $_proxyTicket;
+ */
+ private $_proxyTicket;
+
+ /**
+ * Register a proxy ticket with the Proxy that it can use when making requests.
+ *
+ * @param string $proxyTicket proxy ticket
+ *
+ * @return void
+ * @throws InvalidArgumentException If the $proxyTicket is invalid.
+ * @throws CAS_OutOfSequenceException If called after a proxy ticket has already been initialized/set.
+ */
+ public function setProxyTicket ($proxyTicket)
+ {
+ if (empty($proxyTicket)) {
+ throw new CAS_InvalidArgumentException("Trying to initialize with an empty proxy ticket.");
+ }
+ if (!empty($this->_proxyTicket)) {
+ throw new CAS_OutOfSequenceException('Already initialized, cannot change the proxy ticket.');
+ }
+ $this->_proxyTicket = $proxyTicket;
+ }
+
+ /**
+ * Answer the proxy ticket to be used when making requests.
+ *
+ * @return string
+ * @throws CAS_OutOfSequenceException If called before a proxy ticket has
+ * already been initialized/set.
+ */
+ protected function getProxyTicket ()
+ {
+ if (empty($this->_proxyTicket)) {
+ throw new CAS_OutOfSequenceException('No proxy ticket yet. Call $this->initializeProxyTicket() to aquire the proxy ticket.');
+ }
+
+ return $this->_proxyTicket;
+ }
+
+ /**
+ * @var CAS_Client $_casClient;
+ */
+ private $_casClient;
+
+ /**
+ * Use a particular CAS_Client->initializeProxiedService() rather than the
+ * static phpCAS::initializeProxiedService().
+ *
+ * This method should not be called in standard operation, but is needed for unit
+ * testing.
+ *
+ * @param CAS_Client $casClient cas client
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after a proxy ticket has
+ * already been initialized/set.
+ */
+ public function setCasClient (CAS_Client $casClient)
+ {
+ if (!empty($this->_proxyTicket)) {
+ throw new CAS_OutOfSequenceException('Already initialized, cannot change the CAS_Client.');
+ }
+
+ $this->_casClient = $casClient;
+ }
+
+ /**
+ * Fetch our proxy ticket.
+ *
+ * Descendent classes should call this method once their service URL is available
+ * to initialize their proxy ticket.
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after a proxy ticket has
+ * already been initialized.
+ */
+ protected function initializeProxyTicket()
+ {
+ if (!empty($this->_proxyTicket)) {
+ throw new CAS_OutOfSequenceException('Already initialized, cannot initialize again.');
+ }
+ // Allow usage of a particular CAS_Client for unit testing.
+ if (empty($this->_casClient)) {
+ phpCAS::initializeProxiedService($this);
+ } else {
+ $this->_casClient->initializeProxiedService($this);
+ }
+ }
+
+}
+?>
--- /dev/null
+<?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/ProxiedService/Exception.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * An Exception for problems communicating with a proxied service.
+ *
+ * @class CAS_ProxiedService_Exception
+ * @category Authentication
+ * @package PhpCAS
+ * @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_ProxiedService_Exception
+extends Exception
+implements CAS_Exception
+{
+
+}
+?>
--- /dev/null
+<?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/ProxiedService/Http.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * This interface defines methods that clients should use for configuring, sending,
+ * and receiving proxied HTTP requests.
+ *
+ * @class CAS_ProxiedService_Http
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+interface CAS_ProxiedService_Http
+{
+
+ /*********************************************************
+ * Configure the Request
+ *********************************************************/
+
+ /**
+ * Set the URL of the Request
+ *
+ * @param string $url Url to set
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setUrl ($url);
+
+ /*********************************************************
+ * 2. Send the Request
+ *********************************************************/
+
+ /**
+ * Perform the request.
+ *
+ * @return bool TRUE on success, FALSE on failure.
+ * @throws CAS_OutOfSequenceException If called multiple times.
+ */
+ public function send ();
+
+ /*********************************************************
+ * 3. Access the response
+ *********************************************************/
+
+ /**
+ * Answer the headers of the response.
+ *
+ * @return array An array of header strings.
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseHeaders ();
+
+ /**
+ * Answer the body of response.
+ *
+ * @return string
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseBody ();
+
+}
+?>
--- /dev/null
+<?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/ProxiedService/Http/Abstract.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * This class implements common methods for ProxiedService implementations included
+ * with phpCAS.
+ *
+ * @class CAS_ProxiedService_Http_Abstract
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+abstract class CAS_ProxiedService_Http_Abstract
+extends CAS_ProxiedService_Abstract
+implements CAS_ProxiedService_Http
+{
+ /**
+ * The HTTP request mechanism talking to the target service.
+ *
+ * @var CAS_Request_RequestInterface $requestHandler
+ */
+ protected $requestHandler;
+
+ /**
+ * The storage mechanism for cookies set by the target service.
+ *
+ * @var CAS_CookieJar $_cookieJar
+ */
+ private $_cookieJar;
+
+ /**
+ * Constructor.
+ *
+ * @param CAS_Request_RequestInterface $requestHandler request handler object
+ * @param CAS_CookieJar $cookieJar cookieJar object
+ *
+ * @return void
+ */
+ public function __construct (CAS_Request_RequestInterface $requestHandler, CAS_CookieJar $cookieJar)
+ {
+ $this->requestHandler = $requestHandler;
+ $this->_cookieJar = $cookieJar;
+ }
+
+ /**
+ * The target service url.
+ * @var string $_url;
+ */
+ private $_url;
+
+ /**
+ * Answer a service identifier (URL) for whom we should fetch a proxy ticket.
+ *
+ * @return string
+ * @throws Exception If no service url is available.
+ */
+ public function getServiceUrl ()
+ {
+ if (empty($this->_url)) {
+ throw new CAS_ProxiedService_Exception('No URL set via '.get_class($this).'->setUrl($url).');
+ }
+
+ return $this->_url;
+ }
+
+ /*********************************************************
+ * Configure the Request
+ *********************************************************/
+
+ /**
+ * Set the URL of the Request
+ *
+ * @param string $url url to set
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setUrl ($url)
+ {
+ if ($this->hasBeenSent()) {
+ throw new CAS_OutOfSequenceException('Cannot set the URL, request already sent.');
+ }
+ if (!is_string($url)) {
+ throw new CAS_InvalidArgumentException('$url must be a string.');
+ }
+
+ $this->_url = $url;
+ }
+
+ /*********************************************************
+ * 2. Send the Request
+ *********************************************************/
+
+ /**
+ * Perform the request.
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called multiple times.
+ * @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
+ * @throws CAS_ProxiedService_Exception If there is a failure sending the
+ * request to the target service.
+ */
+ public function send ()
+ {
+ if ($this->hasBeenSent()) {
+ throw new CAS_OutOfSequenceException('Cannot send, request already sent.');
+ }
+
+ phpCAS::traceBegin();
+
+ // Get our proxy ticket and append it to our URL.
+ $this->initializeProxyTicket();
+ $url = $this->getServiceUrl();
+ if (strstr($url, '?') === false) {
+ $url = $url.'?ticket='.$this->getProxyTicket();
+ } else {
+ $url = $url.'&ticket='.$this->getProxyTicket();
+ }
+
+ try {
+ $this->makeRequest($url);
+ } catch (Exception $e) {
+ phpCAS::traceEnd();
+ throw $e;
+ }
+ }
+
+ /**
+ * Indicator of the number of requests (including redirects performed.
+ *
+ * @var int $_numRequests;
+ */
+ private $_numRequests = 0;
+
+ /**
+ * The response headers.
+ *
+ * @var array $_responseHeaders;
+ */
+ private $_responseHeaders = array();
+
+ /**
+ * The response status code.
+ *
+ * @var string $_responseStatusCode;
+ */
+ private $_responseStatusCode = '';
+
+ /**
+ * The response headers.
+ *
+ * @var string $_responseBody;
+ */
+ private $_responseBody = '';
+
+ /**
+ * Build and perform a request, following redirects
+ *
+ * @param string $url url for the request
+ *
+ * @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
+ * @throws CAS_ProxiedService_Exception If there is a failure sending the
+ * request to the target service.
+ */
+ protected function makeRequest ($url)
+ {
+ // Verify that we are not in a redirect loop
+ $this->_numRequests++;
+ if ($this->_numRequests > 4) {
+ $message = 'Exceeded the maximum number of redirects (3) in proxied service request.';
+ phpCAS::trace($message);
+ throw new CAS_ProxiedService_Exception($message);
+ }
+
+ // Create a new request.
+ $request = clone $this->requestHandler;
+ $request->setUrl($url);
+
+ // Add any cookies to the request.
+ $request->addCookies($this->_cookieJar->getCookies($url));
+
+ // Add any other parts of the request needed by concrete classes
+ $this->populateRequest($request);
+
+ // Perform the request.
+ phpCAS::trace('Performing proxied service request to \''.$url.'\'');
+ if (!$request->send()) {
+ $message = 'Could not perform proxied service request to URL`'.$url.'\'. '.$request->getErrorMessage();
+ phpCAS::trace($message);
+ throw new CAS_ProxiedService_Exception($message);
+ }
+
+ // Store any cookies from the response;
+ $this->_cookieJar->storeCookies($url, $request->getResponseHeaders());
+
+ // Follow any redirects
+ if ($redirectUrl = $this->getRedirectUrl($request->getResponseHeaders())) {
+ phpCAS :: trace('Found redirect:'.$redirectUrl);
+ $this->makeRequest($redirectUrl);
+ } else {
+
+ $this->_responseHeaders = $request->getResponseHeaders();
+ $this->_responseBody = $request->getResponseBody();
+ $this->_responseStatusCode = $request->getResponseStatusCode();
+ }
+ }
+
+ /**
+ * Add any other parts of the request needed by concrete classes
+ *
+ * @param CAS_Request_RequestInterface $request request interface object
+ *
+ * @return void
+ */
+ abstract protected function populateRequest (CAS_Request_RequestInterface $request);
+
+ /**
+ * Answer a redirect URL if a redirect header is found, otherwise null.
+ *
+ * @param array $responseHeaders response header to extract a redirect from
+ *
+ * @return string or null
+ */
+ protected function getRedirectUrl (array $responseHeaders)
+ {
+ // Check for the redirect after authentication
+ foreach ($responseHeaders as $header) {
+ if (preg_match('/^(Location:|URI:)\s*([^\s]+.*)$/', $header, $matches)) {
+ return trim(array_pop($matches));
+ }
+ }
+ return null;
+ }
+
+ /*********************************************************
+ * 3. Access the response
+ *********************************************************/
+
+ /**
+ * Answer true if our request has been sent yet.
+ *
+ * @return bool
+ */
+ protected function hasBeenSent ()
+ {
+ return ($this->_numRequests > 0);
+ }
+
+ /**
+ * Answer the headers of the response.
+ *
+ * @return array An array of header strings.
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseHeaders ()
+ {
+ if (!$this->hasBeenSent()) {
+ throw new CAS_OutOfSequenceException('Cannot access response, request not sent yet.');
+ }
+
+ return $this->_responseHeaders;
+ }
+
+ /**
+ * Answer HTTP status code of the response
+ *
+ * @return int
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseStatusCode ()
+ {
+ if (!$this->hasBeenSent()) {
+ throw new CAS_OutOfSequenceException('Cannot access response, request not sent yet.');
+ }
+
+ return $this->_responseStatusCode;
+ }
+
+ /**
+ * Answer the body of response.
+ *
+ * @return string
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseBody ()
+ {
+ if (!$this->hasBeenSent()) {
+ throw new CAS_OutOfSequenceException('Cannot access response, request not sent yet.');
+ }
+
+ return $this->_responseBody;
+ }
+
+ /**
+ * Answer the cookies from the response. This may include cookies set during
+ * redirect responses.
+ *
+ * @return array An array containing cookies. E.g. array('name' => 'val');
+ */
+ public function getCookies ()
+ {
+ return $this->_cookieJar->getCookies($this->getServiceUrl());
+ }
+
+}
+?>
--- /dev/null
+<?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/ProxiedService/Http/Get.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * This class is used to make proxied service requests via the HTTP GET method.
+ *
+ * Usage Example:
+ *
+ * try {
+ * $service = phpCAS::getProxiedService(PHPCAS_PROXIED_SERVICE_HTTP_GET);
+ * $service->setUrl('http://www.example.com/path/');
+ * $service->send();
+ * if ($service->getResponseStatusCode() == 200)
+ * return $service->getResponseBody();
+ * else
+ * // The service responded with an error code 404, 500, etc.
+ * throw new Exception('The service responded with an error.');
+ *
+ * } catch (CAS_ProxyTicketException $e) {
+ * if ($e->getCode() == PHPCAS_SERVICE_PT_FAILURE)
+ * return "Your login has timed out. You need to log in again.";
+ * else
+ * // Other proxy ticket errors are from bad request format (shouldn't happen)
+ * // or CAS server failure (unlikely) so lets just stop if we hit those.
+ * throw $e;
+ * } catch (CAS_ProxiedService_Exception $e) {
+ * // Something prevented the service request from being sent or received.
+ * // We didn't even get a valid error response (404, 500, etc), so this
+ * // might be caused by a network error or a DNS resolution failure.
+ * // We could handle it in some way, but for now we will just stop.
+ * throw $e;
+ * }
+ *
+ * @class CAS_ProxiedService_Http_Get
+ * @category Authentication
+ * @package PhpCAS
+ * @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_ProxiedService_Http_Get
+extends CAS_ProxiedService_Http_Abstract
+{
+
+ /**
+ * Add any other parts of the request needed by concrete classes
+ *
+ * @param CAS_Request_RequestInterface $request request interface
+ *
+ * @return void
+ */
+ protected function populateRequest (CAS_Request_RequestInterface $request)
+ {
+ // do nothing, since the URL has already been sent and that is our
+ // only data.
+ }
+}
+?>
--- /dev/null
+<?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/ProxiedService/Http/Post.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * This class is used to make proxied service requests via the HTTP POST method.
+ *
+ * Usage Example:
+ *
+ * try {
+ * $service = phpCAS::getProxiedService(PHPCAS_PROXIED_SERVICE_HTTP_POST);
+ * $service->setUrl('http://www.example.com/path/');
+ * $service->setContentType('text/xml');
+ * $service->setBody(''<?xml version="1.0"?'.'><methodCall><methodName>example.search</methodName></methodCall>');
+ * $service->send();
+ * if ($service->getResponseStatusCode() == 200)
+ * return $service->getResponseBody();
+ * else
+ * // The service responded with an error code 404, 500, etc.
+ * throw new Exception('The service responded with an error.');
+ *
+ * } catch (CAS_ProxyTicketException $e) {
+ * if ($e->getCode() == PHPCAS_SERVICE_PT_FAILURE)
+ * return "Your login has timed out. You need to log in again.";
+ * else
+ * // Other proxy ticket errors are from bad request format (shouldn't happen)
+ * // or CAS server failure (unlikely) so lets just stop if we hit those.
+ * throw $e;
+ * } catch (CAS_ProxiedService_Exception $e) {
+ * // Something prevented the service request from being sent or received.
+ * // We didn't even get a valid error response (404, 500, etc), so this
+ * // might be caused by a network error or a DNS resolution failure.
+ * // We could handle it in some way, but for now we will just stop.
+ * throw $e;
+ * }
+ *
+ * @class CAS_ProxiedService_Http_Post
+ * @category Authentication
+ * @package PhpCAS
+ * @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_ProxiedService_Http_Post
+extends CAS_ProxiedService_Http_Abstract
+{
+
+ /**
+ * The content-type of this request
+ *
+ * @var string $_contentType
+ */
+ private $_contentType;
+
+ /**
+ * The body of the this request
+ *
+ * @var string $_body
+ */
+ private $_body;
+
+ /**
+ * Set the content type of this POST request.
+ *
+ * @param string $contentType content type
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setContentType ($contentType)
+ {
+ if ($this->hasBeenSent()) {
+ throw new CAS_OutOfSequenceException('Cannot set the content type, request already sent.');
+ }
+
+ $this->_contentType = $contentType;
+ }
+
+ /**
+ * Set the body of this POST request.
+ *
+ * @param string $body body to set
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setBody ($body)
+ {
+ if ($this->hasBeenSent()) {
+ throw new CAS_OutOfSequenceException('Cannot set the body, request already sent.');
+ }
+
+ $this->_body = $body;
+ }
+
+ /**
+ * Add any other parts of the request needed by concrete classes
+ *
+ * @param CAS_Request_RequestInterface $request request interface class
+ *
+ * @return void
+ */
+ protected function populateRequest (CAS_Request_RequestInterface $request)
+ {
+ if (empty($this->_contentType) && !empty($this->_body)) {
+ throw new CAS_ProxiedService_Exception("If you pass a POST body, you must specify a content type via ".get_class($this).'->setContentType($contentType).');
+ }
+
+ $request->makePost();
+ if (!empty($this->_body)) {
+ $request->addHeader('Content-Type: '.$this->_contentType);
+ $request->addHeader('Content-Length: '.strlen($this->_body));
+ $request->setPostBody($this->_body);
+ }
+ }
+
+
+}
+?>
--- /dev/null
+<?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/ProxiedService/Imap.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * Provides access to a proxy-authenticated IMAP stream
+ *
+ * @class CAS_ProxiedService_Imap
+ * @category Authentication
+ * @package PhpCAS
+ * @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_ProxiedService_Imap
+extends CAS_ProxiedService_Abstract
+{
+
+ /**
+ * The username to send via imap_open.
+ *
+ * @var string $_username;
+ */
+ private $_username;
+
+ /**
+ * Constructor.
+ *
+ * @param string $username Username
+ *
+ * @return void
+ */
+ public function __construct ($username)
+ {
+ if (!is_string($username) || !strlen($username)) {
+ throw new CAS_InvalidArgumentException('Invalid username.');
+ }
+
+ $this->_username = $username;
+ }
+
+ /**
+ * The target service url.
+ * @var string $_url;
+ */
+ private $_url;
+
+ /**
+ * Answer a service identifier (URL) for whom we should fetch a proxy ticket.
+ *
+ * @return string
+ * @throws Exception If no service url is available.
+ */
+ public function getServiceUrl ()
+ {
+ if (empty($this->_url)) {
+ throw new CAS_ProxiedService_Exception('No URL set via '.get_class($this).'->getServiceUrl($url).');
+ }
+
+ return $this->_url;
+ }
+
+ /*********************************************************
+ * Configure the Stream
+ *********************************************************/
+
+ /**
+ * Set the URL of the service to pass to CAS for proxy-ticket retrieval.
+ *
+ * @param string $url Url to set
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the stream has been opened.
+ */
+ public function setServiceUrl ($url)
+ {
+ if ($this->hasBeenOpened()) {
+ throw new CAS_OutOfSequenceException('Cannot set the URL, stream already opened.');
+ }
+ if (!is_string($url) || !strlen($url)) {
+ throw new CAS_InvalidArgumentException('Invalid url.');
+ }
+
+ $this->_url = $url;
+ }
+
+ /**
+ * The mailbox to open. See the $mailbox parameter of imap_open().
+ *
+ * @var string $_mailbox
+ */
+ private $_mailbox;
+
+ /**
+ * Set the mailbox to open. See the $mailbox parameter of imap_open().
+ *
+ * @param string $mailbox Mailbox to set
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the stream has been opened.
+ */
+ public function setMailbox ($mailbox)
+ {
+ if ($this->hasBeenOpened()) {
+ throw new CAS_OutOfSequenceException('Cannot set the mailbox, stream already opened.');
+ }
+ if (!is_string($mailbox) || !strlen($mailbox)) {
+ throw new CAS_InvalidArgumentException('Invalid mailbox.');
+ }
+
+ $this->_mailbox = $mailbox;
+ }
+
+ /**
+ * A bit mask of options to pass to imap_open() as the $options parameter.
+ *
+ * @var int $_options
+ */
+ private $_options = null;
+
+ /**
+ * Set the options for opening the stream. See the $options parameter of
+ * imap_open().
+ *
+ * @param int $options Options for the stream
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the stream has been opened.
+ */
+ public function setOptions ($options)
+ {
+ if ($this->hasBeenOpened()) {
+ throw new CAS_OutOfSequenceException('Cannot set options, stream already opened.');
+ }
+ if (!is_int($options)) {
+ throw new CAS_InvalidArgumentException('Invalid options.');
+ }
+
+ $this->_options = $options;
+ }
+
+ /*********************************************************
+ * 2. Open the stream
+ *********************************************************/
+
+ /**
+ * Open the IMAP stream (similar to imap_open()).
+ *
+ * @return resource Returns an IMAP stream on success
+ * @throws CAS_OutOfSequenceException If called multiple times.
+ * @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
+ * @throws CAS_ProxiedService_Exception If there is a failure sending the request to the target service. */
+ public function open ()
+ {
+ if ($this->hasBeenOpened()) {
+ throw new CAS_OutOfSequenceException('Stream already opened.');
+ }
+ if (empty($this->_mailbox)) {
+ throw new CAS_ProxiedService_Exception('You must specify a mailbox via '.get_class($this).'->setMailbox($mailbox)');
+ }
+
+ phpCAS::traceBegin();
+
+ // Get our proxy ticket and append it to our URL.
+ $this->initializeProxyTicket();
+ phpCAS::trace('opening IMAP mailbox `'.$this->_mailbox.'\'...');
+ $this->_stream = @imap_open($this->_mailbox, $this->_username, $this->getProxyTicket(), $this->_options);
+ if ($this->_stream) {
+ phpCAS::trace('ok');
+ } else {
+ phpCAS::trace('could not open mailbox');
+ // @todo add localization integration.
+ $message = 'IMAP Error: '.$url.' '. var_export(imap_errors(), true);
+ phpCAS::trace($message);
+ throw new CAS_ProxiedService_Exception($message);
+ }
+
+ phpCAS::traceEnd();
+ return $this->_stream;
+ }
+
+ /**
+ * Answer true if our request has been sent yet.
+ *
+ * @return bool
+ */
+ protected function hasBeenOpened ()
+ {
+ return !empty($this->_stream);
+ }
+
+ /*********************************************************
+ * 3. Access the result
+ *********************************************************/
+ /**
+ * The IMAP stream
+ *
+ * @var resource $_stream
+ */
+ private $_stream;
+
+ /**
+ * Answer the IMAP stream
+ *
+ * @return resource
+ */
+ public function getStream ()
+ {
+ if (!$this->hasBeenOpened()) {
+ throw new CAS_OutOfSequenceException('Cannot access stream, not opened yet.');
+ }
+ return $this->_stream;
+ }
+
+ /**
+ * CAS_Client::serviceMail() needs to return the proxy ticket for some reason,
+ * so this method provides access to it.
+ *
+ * @return string
+ * @throws CAS_OutOfSequenceException If called before the stream has been
+ * opened.
+ */
+ public function getImapProxyTicket ()
+ {
+ if (!$this->hasBeenOpened()) {
+ throw new CAS_OutOfSequenceException('Cannot access errors, stream not opened yet.');
+ }
+ return $this->getProxyTicket();
+ }
+}
+?>
--- /dev/null
+<?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/ProxiedService/Testabel.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * This interface defines methods that allow proxy-authenticated service handlers
+ * to be tested in unit tests.
+ *
+ * Classes implementing this interface SHOULD store the CAS_Client passed and initialize
+ * themselves with that client rather than via the static phpCAS method. For example:
+ *
+ * / **
+ * * Fetch our proxy ticket.
+ * * /
+ * protected function initializeProxyTicket() {
+ * // Allow usage of a particular CAS_Client for unit testing.
+ * if (is_null($this->casClient))
+ * phpCAS::initializeProxiedService($this);
+ * else
+ * $this->casClient->initializeProxiedService($this);
+ * }
+ *
+ * @class CAS_ProxiedService_Testabel
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+interface CAS_ProxiedService_Testable
+{
+
+ /**
+ * Use a particular CAS_Client->initializeProxiedService() rather than the
+ * static phpCAS::initializeProxiedService().
+ *
+ * This method should not be called in standard operation, but is needed for unit
+ * testing.
+ *
+ * @param CAS_Client $casClient Cas client object
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after a proxy ticket has already been initialized/set.
+ */
+ public function setCasClient (CAS_Client $casClient);
+
+}
+?>
--- /dev/null
+<?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/ProxyChain.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * A normal proxy-chain definition that lists each level of the chain as either
+ * a string or regular expression.
+ *
+ * @class CAS_ProxyChain
+ * @category Authentication
+ * @package PhpCAS
+ * @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_ProxyChain
+implements CAS_ProxyChain_Interface
+{
+
+ protected $chain = array();
+
+ /**
+ * A chain is an array of strings or regexp strings that will be matched
+ * against. Regexp will be matched with preg_match and strings will be
+ * matched from the beginning. A string must fully match the beginning of
+ * an proxy url. So you can define a full domain as acceptable or go further
+ * down.
+ * Proxies have to be defined in reverse from the service to the user. If a
+ * user hits service A get proxied via B to service C the list of acceptable
+ * proxies on C would be array(B,A);
+ *
+ * @param array $chain A chain of proxies
+ */
+ public function __construct(array $chain)
+ {
+ $this->chain = array_values($chain); // Ensure that we have an indexed array
+ }
+
+ /**
+ * Match a list of proxies.
+ *
+ * @param array $list The list of proxies in front of this service.
+ *
+ * @return bool
+ */
+ public function matches(array $list)
+ {
+ $list = array_values($list); // Ensure that we have an indexed array
+ if ($this->isSizeValid($list)) {
+ $mismatch = false;
+ foreach ($this->chain as $i => $search) {
+ $proxy_url = $list[$i];
+ if (preg_match('/^\/.*\/[ixASUXu]*$/s', $search)) {
+ if (preg_match($search, $proxy_url)) {
+ phpCAS::trace("Found regexp " . $search . " matching " . $proxy_url);
+ } else {
+ phpCAS::trace("No regexp match " . $search . " != " . $proxy_url);
+ $mismatch = true;
+ break;
+ }
+ } else {
+ if (strncasecmp($search, $proxy_url, strlen($search)) == 0) {
+ phpCAS::trace("Found string " . $search . " matching " . $proxy_url);
+ } else {
+ phpCAS::trace("No match " . $search . " != " . $proxy_url);
+ $mismatch = true;
+ break;
+ }
+ }
+ }
+ if (!$mismatch) {
+ phpCAS::trace("Proxy chain matches");
+ return true;
+ }
+ } else {
+ phpCAS::trace("Proxy chain skipped: size mismatch");
+ }
+ return false;
+ }
+
+ /**
+ * Validate the size of the the list as compared to our chain.
+ *
+ * @param array $list List of proxies
+ *
+ * @return bool
+ */
+ protected function isSizeValid (array $list)
+ {
+ return (sizeof($this->chain) == sizeof($list));
+ }
+}
--- /dev/null
+<?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/ProxyChain/AllowedList.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+
+/**
+ * ProxyChain is a container for storing chains of valid proxies that can
+ * be used to validate proxied requests to a service
+ *
+ * @class CAS_ProxyChain_AllowedList
+ * @category Authentication
+ * @package PhpCAS
+ * @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_ProxyChain_AllowedList
+{
+
+ private $_chains = array();
+
+ /**
+ * Check whether proxies are allowed by configuration
+ *
+ * @return bool
+ */
+ public function isProxyingAllowed()
+ {
+ return (count($this->_chains) > 0);
+ }
+
+ /**
+ * Add a chain of proxies to the list of possible chains
+ *
+ * @param CAS_ProxyChain_Interface $chain A chain of proxies
+ *
+ * @return void
+ */
+ public function allowProxyChain(CAS_ProxyChain_Interface $chain)
+ {
+ $this->_chains[] = $chain;
+ }
+
+ /**
+ * Check if the proxies found in the response match the allowed proxies
+ *
+ * @param array $proxies list of proxies to check
+ *
+ * @return bool whether the proxies match the allowed proxies
+ */
+ public function isProxyListAllowed(array $proxies)
+ {
+ phpCAS::traceBegin();
+ if (empty($proxies)) {
+ phpCAS::trace("No proxies were found in the response");
+ phpCAS::traceEnd(true);
+ return true;
+ } elseif (!$this->isProxyingAllowed()) {
+ phpCAS::trace("Proxies are not allowed");
+ phpCAS::traceEnd(false);
+ return false;
+ } else {
+ $res = $this->contains($proxies);
+ phpCAS::traceEnd($res);
+ return $res;
+ }
+ }
+
+ /**
+ * Validate the proxies from the proxy ticket validation against the
+ * chains that were definded.
+ *
+ * @param array $list List of proxies from the proxy ticket validation.
+ *
+ * @return if any chain fully matches the supplied list
+ */
+ public function contains(array $list)
+ {
+ phpCAS::traceBegin();
+ $count = 0;
+ foreach ($this->_chains as $chain) {
+ phpCAS::trace("Checking chain ". $count++);
+ if ($chain->matches($list)) {
+ phpCAS::traceEnd(true);
+ return true;
+ }
+ }
+ phpCAS::trace("No proxy chain matches.");
+ phpCAS::traceEnd(false);
+ return false;
+ }
+}
+?>
--- /dev/null
+<?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/ProxyChain/Any.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * A proxy-chain definition that will match any list of proxies.
+ *
+ * Use this class for quick testing or in certain production screnarios you
+ * might want to allow allow any other valid service to proxy your service.
+ *
+ * THIS CLASS 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.
+ *
+ * @class CAS_ProxyChain_Any
+ * @category Authentication
+ * @package PhpCAS
+ * @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_ProxyChain_Any
+implements CAS_ProxyChain_Interface
+{
+
+ /**
+ * Match a list of proxies.
+ *
+ * @param array $list The list of proxies in front of this service.
+ *
+ * @return bool
+ */
+ public function matches(array $list)
+ {
+ phpCAS::trace("Using CAS_ProxyChain_Any. No proxy validation is performed.");
+ return true;
+ }
+
+}
--- /dev/null
+<?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/ProxyChain/Interface.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * An interface for classes that define a list of allowed proxies in front of
+ * the current application.
+ *
+ * @class CAS_ProxyChain_Interface
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+interface CAS_ProxyChain_Interface
+{
+
+ /**
+ * Match a list of proxies.
+ *
+ * @param array $list The list of proxies in front of this service.
+ *
+ * @return bool
+ */
+ public function matches(array $list);
+
+}
\ No newline at end of file
--- /dev/null
+<?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/ProxyChain/Trusted.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * A proxy-chain definition that defines a chain up to a trusted proxy and
+ * delegates the resposibility of validating the rest of the chain to that
+ * trusted proxy.
+ *
+ * @class CAS_ProxyChain_Trusted
+ * @category Authentication
+ * @package PhpCAS
+ * @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_ProxyChain_Trusted
+extends CAS_ProxyChain
+implements CAS_ProxyChain_Interface
+{
+
+ /**
+ * Validate the size of the the list as compared to our chain.
+ *
+ * @param array $list list of proxies
+ *
+ * @return bool
+ */
+ protected function isSizeValid (array $list)
+ {
+ return (sizeof($this->chain) <= sizeof($list));
+ }
+
+}
--- /dev/null
+<?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
+ *
+ * @class CAS/ProxyTicketException.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ *
+ */
+
+/**
+ * An Exception for errors related to fetching or validating proxy tickets.
+ *
+ * @class CAS_ProxyTicketException
+ * @category Authentication
+ * @package PhpCAS
+ * @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_ProxyTicketException
+extends BadMethodCallException
+implements CAS_Exception
+{
+
+ /**
+ * Constructor
+ *
+ * @param string $message Message text
+ * @param int $code Error code
+ *
+ * @return void
+ */
+ public function __construct ($message, $code = PHPCAS_SERVICE_PT_FAILURE)
+ {
+ // Warn if the code is not in our allowed list
+ $ptCodes = array(
+ PHPCAS_SERVICE_PT_FAILURE,
+ PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE,
+ PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE,
+ );
+ if (!in_array($code, $ptCodes)) {
+ trigger_error('Invalid code '.$code.' passed. Must be one of PHPCAS_SERVICE_PT_FAILURE, PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE, or PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE.');
+ }
+
+ parent::__construct($message, $code);
+ }
+}
--- /dev/null
+<?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/Request/AbstractRequest.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * Provides support for performing web-requests via curl
+ *
+ * @class CAS_Request_AbstractRequest
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+abstract class CAS_Request_AbstractRequest
+implements CAS_Request_RequestInterface
+{
+
+ protected $url = null;
+ protected $cookies = array();
+ protected $headers = array();
+ protected $isPost = false;
+ protected $postBody = null;
+ protected $caCertPath = null;
+ protected $validateCN = true;
+ private $_sent = false;
+ private $_responseHeaders = array();
+ private $_responseBody = null;
+ private $_errorMessage = '';
+
+ /*********************************************************
+ * Configure the Request
+ *********************************************************/
+
+ /**
+ * Set the URL of the Request
+ *
+ * @param string $url Url to set
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setUrl ($url)
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException('Request has already been sent cannot '.__METHOD__);
+ }
+
+ $this->url = $url;
+ }
+
+ /**
+ * Add a cookie to the request.
+ *
+ * @param string $name Name of entry
+ * @param string $value value of entry
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function addCookie ($name, $value)
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException('Request has already been sent cannot '.__METHOD__);
+ }
+
+ $this->cookies[$name] = $value;
+ }
+
+ /**
+ * Add an array of cookies to the request.
+ * The cookie array is of the form
+ * array('cookie_name' => 'cookie_value', 'cookie_name2' => cookie_value2')
+ *
+ * @param array $cookies cookies to add
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function addCookies (array $cookies)
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException('Request has already been sent cannot '.__METHOD__);
+ }
+
+ $this->cookies = array_merge($this->cookies, $cookies);
+ }
+
+ /**
+ * Add a header string to the request.
+ *
+ * @param string $header Header to add
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function addHeader ($header)
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException('Request has already been sent cannot '.__METHOD__);
+ }
+
+ $this->headers[] = $header;
+ }
+
+ /**
+ * Add an array of header strings to the request.
+ *
+ * @param array $headers headers to add
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function addHeaders (array $headers)
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException('Request has already been sent cannot '.__METHOD__);
+ }
+
+ $this->headers = array_merge($this->headers, $headers);
+ }
+
+ /**
+ * Make the request a POST request rather than the default GET request.
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function makePost ()
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException('Request has already been sent cannot '.__METHOD__);
+ }
+
+ $this->isPost = true;
+ }
+
+ /**
+ * Add a POST body to the request
+ *
+ * @param string $body body to add
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setPostBody ($body)
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException('Request has already been sent cannot '.__METHOD__);
+ }
+ if (!$this->isPost) {
+ throw new CAS_OutOfSequenceException('Cannot add a POST body to a GET request, use makePost() first.');
+ }
+
+ $this->postBody = $body;
+ }
+
+ /**
+ * Specify the path to an SSL CA certificate to validate the server with.
+ *
+ * @param string $caCertPath path to cert
+ * @param bool $validate_cn valdiate CN of certificate
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setSslCaCert ($caCertPath,$validate_cn=true)
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException('Request has already been sent cannot '.__METHOD__);
+ }
+ $this->caCertPath = $caCertPath;
+ $this->validateCN = $validate_cn;
+ }
+
+ /*********************************************************
+ * 2. Send the Request
+ *********************************************************/
+
+ /**
+ * Perform the request.
+ *
+ * @return bool TRUE on success, FALSE on failure.
+ * @throws CAS_OutOfSequenceException If called multiple times.
+ */
+ public function send ()
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException('Request has already been sent cannot send again.');
+ }
+ if (is_null($this->url) || !$this->url) {
+ throw new CAS_OutOfSequenceException('A url must be specified via setUrl() before the request can be sent.');
+ }
+ $this->_sent = true;
+ return $this->sendRequest();
+ }
+
+ /**
+ * Send the request and store the results.
+ *
+ * @return bool TRUE on success, FALSE on failure.
+ */
+ abstract protected function sendRequest ();
+
+ /**
+ * Store the response headers.
+ *
+ * @param array $headers headers to store
+ *
+ * @return void
+ */
+ protected function storeResponseHeaders (array $headers)
+ {
+ $this->_responseHeaders = array_merge($this->_responseHeaders, $headers);
+ }
+
+ /**
+ * Store a single response header to our array.
+ *
+ * @param string $header header to store
+ *
+ * @return void
+ */
+ protected function storeResponseHeader ($header)
+ {
+ $this->_responseHeaders[] = $header;
+ }
+
+ /**
+ * Store the response body.
+ *
+ * @param string $body body to store
+ *
+ * @return void
+ */
+ protected function storeResponseBody ($body)
+ {
+ $this->_responseBody = $body;
+ }
+
+ /**
+ * Add a string to our error message.
+ *
+ * @param string $message message to add
+ *
+ * @return void
+ */
+ protected function storeErrorMessage ($message)
+ {
+ $this->_errorMessage .= $message;
+ }
+
+ /*********************************************************
+ * 3. Access the response
+ *********************************************************/
+
+ /**
+ * Answer the headers of the response.
+ *
+ * @return array An array of header strings.
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseHeaders ()
+ {
+ if (!$this->_sent) {
+ throw new CAS_OutOfSequenceException('Request has not been sent yet. Cannot '.__METHOD__);
+ }
+ return $this->_responseHeaders;
+ }
+
+ /**
+ * Answer HTTP status code of the response
+ *
+ * @return int
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseStatusCode ()
+ {
+ if (!$this->_sent) {
+ throw new CAS_OutOfSequenceException('Request has not been sent yet. Cannot '.__METHOD__);
+ }
+
+ if (!preg_match('/HTTP\/[0-9.]+\s+([0-9]+)\s*(.*)/', $this->_responseHeaders[0], $matches)) {
+ throw new CAS_Request_Exception("Bad response, no status code was found in the first line.");
+ }
+
+ return intval($matches[1]);
+ }
+
+ /**
+ * Answer the body of response.
+ *
+ * @return string
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseBody ()
+ {
+ if (!$this->_sent) {
+ throw new CAS_OutOfSequenceException('Request has not been sent yet. Cannot '.__METHOD__);
+ }
+
+ return $this->_responseBody;
+ }
+
+ /**
+ * Answer a message describing any errors if the request failed.
+ *
+ * @return string
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getErrorMessage ()
+ {
+ if (!$this->_sent) {
+ throw new CAS_OutOfSequenceException('Request has not been sent yet. Cannot '.__METHOD__);
+ }
+ return $this->_errorMessage;
+ }
+}
--- /dev/null
+<?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/Request/AbstractRequest.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * This interface defines a class library for performing multiple web requests
+ * in batches. Implementations of this interface may perform requests serially
+ * or in parallel.
+ *
+ * @class CAS_Request_CurlMultiRequest
+ * @category Authentication
+ * @package PhpCAS
+ * @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_Request_CurlMultiRequest
+implements CAS_Request_MultiRequestInterface
+{
+ private $_requests = array();
+ private $_sent = false;
+
+ /*********************************************************
+ * Add Requests
+ *********************************************************/
+
+ /**
+ * Add a new Request to this batch.
+ * Note, implementations will likely restrict requests to their own concrete
+ * class hierarchy.
+ *
+ * @param CAS_Request_RequestInterface $request reqest to add
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ * @throws CAS_InvalidArgumentException If passed a Request of the wrong
+ * implmentation.
+ */
+ public function addRequest (CAS_Request_RequestInterface $request)
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException('Request has already been sent cannot '.__METHOD__);
+ }
+ if (!$request instanceof CAS_Request_CurlRequest) {
+ throw new CAS_InvalidArgumentException('As a CAS_Request_CurlMultiRequest, I can only work with CAS_Request_CurlRequest objects.');
+ }
+
+ $this->_requests[] = $request;
+ }
+
+ /**
+ * Retrieve the number of requests added to this batch.
+ *
+ * @return number of request elements
+ */
+ public function getNumRequests()
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException('Request has already been sent cannot '.__METHOD__);
+ }
+ return count($this->_requests);
+ }
+
+ /*********************************************************
+ * 2. Send the Request
+ *********************************************************/
+
+ /**
+ * Perform the request. After sending, all requests will have their
+ * responses poulated.
+ *
+ * @return bool TRUE on success, FALSE on failure.
+ * @throws CAS_OutOfSequenceException If called multiple times.
+ */
+ public function send ()
+ {
+ if ($this->_sent) {
+ throw new CAS_OutOfSequenceException('Request has already been sent cannot send again.');
+ }
+ if (!count($this->_requests)) {
+ throw new CAS_OutOfSequenceException('At least one request must be added via addRequest() before the multi-request can be sent.');
+ }
+
+ $this->_sent = true;
+
+ // Initialize our handles and configure all requests.
+ $handles = array();
+ $multiHandle = curl_multi_init();
+ foreach ($this->_requests as $i => $request) {
+ $handle = $request->_initAndConfigure();
+ curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
+ $handles[$i] = $handle;
+ curl_multi_add_handle($multiHandle, $handle);
+ }
+
+ // Execute the requests in parallel.
+ do {
+ curl_multi_exec($multiHandle, $running);
+ } while ($running > 0);
+
+ // Populate all of the responses or errors back into the request objects.
+ foreach ($this->_requests as $i => $request) {
+ $buf = curl_multi_getcontent($handles[$i]);
+ $request->_storeResponseBody($buf);
+ curl_multi_remove_handle($multiHandle, $handles[$i]);
+ curl_close($handles[$i]);
+ }
+
+ curl_multi_close($multiHandle);
+ }
+}
--- /dev/null
+<?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/Request/CurlRequest.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * Provides support for performing web-requests via curl
+ *
+ * @class CAS_Request_CurlRequest
+ * @category Authentication
+ * @package PhpCAS
+ * @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_Request_CurlRequest
+extends CAS_Request_AbstractRequest
+implements CAS_Request_RequestInterface
+{
+
+ /**
+ * Set additional curl options
+ *
+ * @param array $options option to set
+ *
+ * @return void
+ */
+ public function setCurlOptions (array $options)
+ {
+ $this->_curlOptions = $options;
+ }
+ private $_curlOptions = array();
+
+ /**
+ * Send the request and store the results.
+ *
+ * @return bool true on success, false on failure.
+ */
+ protected function sendRequest ()
+ {
+ phpCAS::traceBegin();
+
+ /*********************************************************
+ * initialize the CURL session
+ *********************************************************/
+ $ch = $this->_initAndConfigure();
+
+ /*********************************************************
+ * Perform the query
+ *********************************************************/
+ $buf = curl_exec($ch);
+ if ( $buf === false ) {
+ phpCAS::trace('curl_exec() failed');
+ $this->storeErrorMessage('CURL error #'.curl_errno($ch).': '.curl_error($ch));
+ $res = false;
+ } else {
+ $this->storeResponseBody($buf);
+ phpCAS::trace("Response Body: \n".$buf."\n");
+ $res = true;
+
+ }
+ // close the CURL session
+ curl_close($ch);
+
+ phpCAS::traceEnd($res);
+ return $res;
+ }
+
+ /**
+ * Internal method to initialize our cURL handle and configure the request.
+ * This method should NOT be used outside of the CurlRequest or the
+ * CurlMultiRequest.
+ *
+ * @return resource The cURL handle on success, false on failure
+ */
+ private function _initAndConfigure()
+ {
+ /*********************************************************
+ * initialize the CURL session
+ *********************************************************/
+ $ch = curl_init($this->url);
+
+ if (version_compare(PHP_VERSION, '5.1.3', '>=')) {
+ //only avaible in php5
+ curl_setopt_array($ch, $this->_curlOptions);
+ } else {
+ foreach ($this->_curlOptions as $key => $value) {
+ curl_setopt($ch, $key, $value);
+ }
+ }
+
+ /*********************************************************
+ * Set SSL configuration
+ *********************************************************/
+ if ($this->caCertPath) {
+ if ($this->validateCN) {
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
+ } else {
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
+ }
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
+ curl_setopt($ch, CURLOPT_CAINFO, $this->caCertPath);
+ phpCAS::trace('CURL: Set CURLOPT_CAINFO ' . $this->caCertPath);
+ } else {
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
+ }
+
+ /*********************************************************
+ * Configure curl to capture our output.
+ *********************************************************/
+ // return the CURL output into a variable
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+
+ // get the HTTP header with a callback
+ curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, '_curlReadHeaders'));
+
+ /*********************************************************
+ * Add cookie headers to our request.
+ *********************************************************/
+ if (count($this->cookies)) {
+ $cookieStrings = array();
+ foreach ($this->cookies as $name => $val) {
+ $cookieStrings[] = $name.'='.$val;
+ }
+ curl_setopt($ch, CURLOPT_COOKIE, implode(';', $cookieStrings));
+ }
+
+ /*********************************************************
+ * Add any additional headers
+ *********************************************************/
+ if (count($this->headers)) {
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers);
+ }
+
+ /*********************************************************
+ * Flag and Body for POST requests
+ *********************************************************/
+ if ($this->isPost) {
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $this->postBody);
+ }
+
+ return $ch;
+ }
+
+ /**
+ * Store the response body.
+ * This method should NOT be used outside of the CurlRequest or the
+ * CurlMultiRequest.
+ *
+ * @param string $body body to stor
+ *
+ * @return void
+ */
+ private function _storeResponseBody ($body)
+ {
+ $this->storeResponseBody($body);
+ }
+
+ /**
+ * Internal method for capturing the headers from a curl request.
+ *
+ * @param handle $ch handle of curl
+ * @param string $header header
+ *
+ * @return void
+ */
+ private function _curlReadHeaders ($ch, $header)
+ {
+ $this->storeResponseHeader($header);
+ return strlen($header);
+ }
+}
--- /dev/null
+<?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/Request/Exception.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * An Exception for problems performing requests
+ *
+ * @class CAS_Request_Exception
+ * @category Authentication
+ * @package PhpCAS
+ * @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_Request_Exception
+extends Exception
+implements CAS_Exception
+{
+
+}
--- /dev/null
+<?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/Request/MultiRequestInterface.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * This interface defines a class library for performing multiple web requests
+ * in batches. Implementations of this interface may perform requests serially
+ * or in parallel.
+ *
+ * @class CAS_Request_MultiRequestInterface
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+interface CAS_Request_MultiRequestInterface
+{
+
+ /*********************************************************
+ * Add Requests
+ *********************************************************/
+
+ /**
+ * Add a new Request to this batch.
+ * Note, implementations will likely restrict requests to their own concrete
+ * class hierarchy.
+ *
+ * @param CAS_Request_RequestInterface $request request interface
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been
+ * sent.
+ * @throws CAS_InvalidArgumentException If passed a Request of the wrong
+ * implmentation.
+ */
+ public function addRequest (CAS_Request_RequestInterface $request);
+
+ /**
+ * Retrieve the number of requests added to this batch.
+ *
+ * @return number of request elements
+ */
+ public function getNumRequests ();
+
+ /*********************************************************
+ * 2. Send the Request
+ *********************************************************/
+
+ /**
+ * Perform the request. After sending, all requests will have their
+ * responses poulated.
+ *
+ * @return bool TRUE on success, FALSE on failure.
+ * @throws CAS_OutOfSequenceException If called multiple times.
+ */
+ public function send ();
+}
--- /dev/null
+<?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/Request/RequestInterface.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+/**
+ * This interface defines a class library for performing web requests.
+ *
+ * @class CAS_Request_RequestInterface
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+interface CAS_Request_RequestInterface
+{
+
+ /*********************************************************
+ * Configure the Request
+ *********************************************************/
+
+ /**
+ * Set the URL of the Request
+ *
+ * @param string $url url to set
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setUrl ($url);
+
+ /**
+ * Add a cookie to the request.
+ *
+ * @param string $name name of cookie
+ * @param string $value value of cookie
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function addCookie ($name, $value);
+
+ /**
+ * Add an array of cookies to the request.
+ * The cookie array is of the form
+ * array('cookie_name' => 'cookie_value', 'cookie_name2' => cookie_value2')
+ *
+ * @param array $cookies cookies to add
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function addCookies (array $cookies);
+
+ /**
+ * Add a header string to the request.
+ *
+ * @param string $header header to add
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function addHeader ($header);
+
+ /**
+ * Add an array of header strings to the request.
+ *
+ * @param array $headers headers to add
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function addHeaders (array $headers);
+
+ /**
+ * Make the request a POST request rather than the default GET request.
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function makePost ();
+
+ /**
+ * Add a POST body to the request
+ *
+ * @param string $body body to add
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setPostBody ($body);
+
+
+ /**
+ * Specify the path to an SSL CA certificate to validate the server with.
+ *
+ * @param string $caCertPath path to cert file
+ * @param boolean $validate_cn validate CN of SSL certificate
+ *
+ * @return void
+ * @throws CAS_OutOfSequenceException If called after the Request has been sent.
+ */
+ public function setSslCaCert ($caCertPath, $validate_cn = true);
+
+
+
+ /*********************************************************
+ * 2. Send the Request
+ *********************************************************/
+
+ /**
+ * Perform the request.
+ *
+ * @return bool TRUE on success, FALSE on failure.
+ * @throws CAS_OutOfSequenceException If called multiple times.
+ */
+ public function send ();
+
+ /*********************************************************
+ * 3. Access the response
+ *********************************************************/
+
+ /**
+ * Answer the headers of the response.
+ *
+ * @return array An array of header strings.
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseHeaders ();
+
+ /**
+ * Answer HTTP status code of the response
+ *
+ * @return int
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseStatusCode ();
+
+ /**
+ * Answer the body of response.
+ *
+ * @return string
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getResponseBody ();
+
+ /**
+ * Answer a message describing any errors if the request failed.
+ *
+ * @return string
+ * @throws CAS_OutOfSequenceException If called before the Request has been sent.
+ */
+ public function getErrorMessage ();
+}
+++ /dev/null
-<?php
-
-/*
- * Copyright © 2003-2010, The ESUP-Portail consortium & the JA-SIG Collaborative.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of the ESUP-Portail consortium & the JA-SIG
- * Collaborative nor the names of its contributors may be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
-
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file CAS/client.php
- * Main class of the phpCAS library
- */
-
-// include internationalization stuff
-include_once(dirname(__FILE__).'/languages/languages.php');
-
-// include PGT storage classes
-include_once(dirname(__FILE__).'/PGTStorage/pgt-main.php');
-
-/**
- * @class CASClient
- * The CASClient class is a client interface that provides CAS authentication
- * to PHP applications.
- *
- * @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>
- */
-
-class CASClient
-{
-
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- // XX XX
- // XX CONFIGURATION XX
- // XX XX
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
- // ########################################################################
- // 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 CASClient::PrintHTMLHeader() and CASClient::printHTMLFooter().
- *
- * @param $str the string to filter and output
- *
- * @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 CASClient::setHTMLHeader(),
- * read by CASClient::printHTMLHeader().
- *
- * @hideinitializer
- * @private
- * @see CASClient::setHTMLHeader, CASClient::printHTMLHeader()
- */
- var $_output_header = '';
-
- /**
- * This method prints the header of the HTML output (after filtering). If
- * CASClient::setHTMLHeader() was not used, a default header is output.
- *
- * @param $title the title of the page
- *
- * @see HTMLFilterOutput()
- * @private
- */
- 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 CASClient::setHTMLFooter(),
- * read by printHTMLFooter().
- *
- * @hideinitializer
- * @private
- * @see CASClient::setHTMLFooter, CASClient::printHTMLFooter()
- */
- var $_output_footer = '';
-
- /**
- * This method prints the footer of the HTML output (after filtering). If
- * CASClient::setHTMLFooter() was not used, a default footer is output.
- *
- * @see HTMLFilterOutput()
- * @private
- */
- function printHTMLFooter()
- {
- $this->HTMLFilterOutput(empty($this->_output_footer)
- ?('<hr><address>phpCAS __PHPCAS_VERSION__ '.$this->getString(CAS_STR_USING_SERVER).' <a href="__SERVER_BASE_URL__">__SERVER_BASE_URL__</a> (CAS __CAS_VERSION__)</a></address></body></html>')
- :$this->_output_footer);
- }
-
- /**
- * This method set the HTML header used for all outputs.
- *
- * @param $header the HTML header.
- *
- * @public
- */
- function setHTMLHeader($header)
- {
- $this->_output_header = $header;
- }
-
- /**
- * This method set the HTML footer used for all outputs.
- *
- * @param $footer the HTML footer.
- *
- * @public
- */
- function setHTMLFooter($footer)
- {
- $this->_output_footer = $footer;
- }
-
- /** @} */
- // ########################################################################
- // INTERNATIONALIZATION
- // ########################################################################
- /**
- * @addtogroup internalLang
- * @{
- */
- /**
- * A string corresponding to the language used by phpCAS. Written by
- * CASClient::setLang(), read by CASClient::getLang().
-
- * @note debugging information is always in english (debug purposes only).
- *
- * @hideinitializer
- * @private
- * @sa CASClient::_strings, CASClient::getString()
- */
- var $_lang = '';
-
- /**
- * This method returns the language used by phpCAS.
- *
- * @return a string representing the language
- *
- * @private
- */
- function getLang()
- {
- if ( empty($this->_lang) )
- $this->setLang(PHPCAS_LANG_DEFAULT);
- return $this->_lang;
- }
-
- /**
- * array containing the strings used by phpCAS. Written by CASClient::setLang(), read by
- * CASClient::getString() and used by CASClient::setLang().
- *
- * @note This array is filled by instructions in CAS/languages/<$this->_lang>.php
- *
- * @private
- * @see CASClient::_lang, CASClient::getString(), CASClient::setLang(), CASClient::getLang()
- */
- var $_strings;
-
- /**
- * This method returns a string depending on the language.
- *
- * @param $str the index of the string in $_string.
- *
- * @return the string corresponding to $index in $string.
- *
- * @private
- */
- function getString($str)
- {
- // call CASclient::getLang() to be sure the language is initialized
- $this->getLang();
-
- if ( !isset($this->_strings[$str]) ) {
- trigger_error('string `'.$str.'\' not defined for language `'.$this->getLang().'\'',E_USER_ERROR);
- }
- return $this->_strings[$str];
- }
-
- /**
- * This method is used to set the language used by phpCAS.
- * @note Can be called only once.
- *
- * @param $lang a string representing the language.
- *
- * @public
- * @sa CAS_LANG_FRENCH, CAS_LANG_ENGLISH
- */
- function setLang($lang)
- {
- // include the corresponding language file
- include_once(dirname(__FILE__).'/languages/'.$lang.'.php');
-
- if ( !is_array($this->_strings) ) {
- trigger_error('language `'.$lang.'\' is not implemented',E_USER_ERROR);
- }
- $this->_lang = $lang;
- }
-
- /** @} */
- // ########################################################################
- // 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 CASClient::CASClient(), read by CASClient::getServerVersion(),
- * CASClient::getServerHostname(), CASClient::getServerPort() and CASClient::getServerURI().
- *
- * The other fields are written and read by CASClient::getServerBaseURL(),
- * CASClient::getServerLoginURL(), CASClient::getServerServiceValidateURL(),
- * CASClient::getServerProxyValidateURL() and CASClient::getServerLogoutURL().
- *
- * @hideinitializer
- * @private
- */
- var $_server = array(
- 'version' => -1,
- 'hostname' => 'none',
- 'port' => -1,
- 'uri' => 'none'
- );
-
- /**
- * This method is used to retrieve the version of the CAS server.
- * @return the version of the CAS server.
- * @private
- */
- function getServerVersion()
- {
- return $this->_server['version'];
- }
-
- /**
- * This method is used to retrieve the hostname of the CAS server.
- * @return 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 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 a URI.
- * @private
- */
- function getServerURI()
- { return $this->_server['uri']; }
-
- /**
- * This method is used to retrieve the base URL of the CAS server.
- * @return 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 $gateway true to check authentication, false to force it
- * @param $renew true to force the authentication with the CAS server
- * NOTE : It is recommended that CAS implementations ignore the
- "gateway" parameter if "renew" is set
- * @return a URL.
- * @private
- */
- 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'] .= preg_replace('/&/','%26',$this->getURL());
- $this->_server['login_url'] .= urlencode($this->getURL());
- if($renew) {
- // It is recommended that when the "renew" parameter is set, its value be "true"
- $this->_server['login_url'] .= '&renew=true';
- } elseif ($gateway) {
- // It is recommended that when the "gateway" parameter is set, its value be "true"
- $this->_server['login_url'] .= '&gateway=true';
- }
- }
- phpCAS::traceEnd($this->_server['login_url']);
- return $this->_server['login_url'];
- }
-
- /**
- * This method sets the login URL of the CAS server.
- * @param $url the login URL
- * @private
- * @since 0.4.21 by Wyman Chan
- */
- function setServerLoginURL($url)
- {
- return $this->_server['login_url'] = $url;
- }
-
-
- /**
- * This method sets the serviceValidate URL of the CAS server.
- * @param $url the serviceValidate URL
- * @private
- * @since 1.1.0 by Joachim Fritschi
- */
- function setServerServiceValidateURL($url)
- {
- return $this->_server['service_validate_url'] = $url;
- }
-
-
- /**
- * This method sets the proxyValidate URL of the CAS server.
- * @param $url the proxyValidate URL
- * @private
- * @since 1.1.0 by Joachim Fritschi
- */
- function setServerProxyValidateURL($url)
- {
- return $this->_server['proxy_validate_url'] = $url;
- }
-
-
- /**
- * This method sets the samlValidate URL of the CAS server.
- * @param $url the samlValidate URL
- * @private
- * @since 1.1.0 by Joachim Fritschi
- */
- 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 a URL.
- * @private
- */
- function getServerServiceValidateURL()
- {
- // 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;
- }
- }
- // return $this->_server['service_validate_url'].'?service='.preg_replace('/&/','%26',$this->getURL());
- return $this->_server['service_validate_url'].'?service='.urlencode($this->getURL());
- }
- /**
- * This method is used to retrieve the SAML validating URL of the CAS server.
- * @return a URL.
- * @private
- */
- 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;
- }
- }
- phpCAS::traceEnd($this->_server['saml_validate_url'].'?TARGET='.urlencode($this->getURL()));
- return $this->_server['saml_validate_url'].'?TARGET='.urlencode($this->getURL());
- }
- /**
- * This method is used to retrieve the proxy validating URL of the CAS server.
- * @return a URL.
- * @private
- */
- function getServerProxyValidateURL()
- {
- // 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;
- }
- }
- // return $this->_server['proxy_validate_url'].'?service='.preg_replace('/&/','%26',$this->getURL());
- return $this->_server['proxy_validate_url'].'?service='.urlencode($this->getURL());
- }
-
- /**
- * This method is used to retrieve the proxy URL of the CAS server.
- * @return a URL.
- * @private
- */
- 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 a URL.
- * @private
- */
- 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 $url the logout URL
- * @private
- * @since 0.4.21 by Wyman Chan
- */
- function setServerLogoutURL($url)
- {
- return $this->_server['logout_url'] = $url;
- }
-
- /**
- * An array to store extra curl options.
- */
- var $_curl_options = array();
-
- /**
- * This method is used to set additional user curl options.
- */
- function setExtraCurlOption($key, $value)
- {
- $this->_curl_options[$key] = $value;
- }
-
- /**
- * This method checks to see if the request is secured via HTTPS
- * @return true if https, false otherwise
- * @private
- */
- function isHttps() {
- //if ( isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) ) {
- //0.4.24 by Hinnack
- if ( isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
- return true;
- } else {
- return false;
- }
- }
-
- // ########################################################################
- // CONSTRUCTOR
- // ########################################################################
- /**
- * CASClient constructor.
- *
- * @param $server_version the version of the CAS server
- * @param $proxy TRUE if the CAS client is a CAS proxy, FALSE otherwise
- * @param $server_hostname the hostname of the CAS server
- * @param $server_port the port the CAS server is running on
- * @param $server_uri the URI the CAS server is responding on
- * @param $start_session Have phpCAS start PHP sessions (default true)
- *
- * @return a newly created CASClient object
- *
- * @public
- */
- function CASClient(
- $server_version,
- $proxy,
- $server_hostname,
- $server_port,
- $server_uri,
- $start_session = true) {
-
- phpCAS::traceBegin();
-
- // the redirect header() call and DOM parsing code from domxml-php4-php5.php won't work in PHP4 compatibility mode
- if (version_compare(PHP_VERSION,'5','>=') && ini_get('zend.ze1_compatibility_mode')) {
- phpCAS::error('phpCAS cannot support zend.ze1_compatibility_mode. Sorry.');
- }
- $this->_start_session = $start_session;
-
- if ($this->_start_session && session_id() !== "")
- {
- phpCAS :: error("Another session was started before phpcas. Either disable the session" .
- " handling for phpcas in the client() call or modify your application to leave" .
- " session handling to phpcas");
- }
- // skip Session Handling for logout requests and if don't want it'
- if ($start_session && !$this->isLogoutRequest())
- {
- phpCAS :: trace("Starting a new session");
- session_start();
- }
-
-
- // are we in proxy mode ?
- $this->_proxy = $proxy;
-
- //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 developpers
- $ticket = (isset($_GET['ticket']) ? $_GET['ticket'] : null);
- switch ($this->getServerVersion()) {
- case CAS_VERSION_1_0: // check for a Service Ticket
- if( preg_match('/^ST-/',$ticket) ) {
- phpCAS::trace('ST \''.$ticket.'\' found');
- //ST present
- $this->setST($ticket);
- //ticket has been taken into account, unset it to hide it to applications
- unset($_GET['ticket']);
- } else if ( !empty($ticket) ) {
- //ill-formed ticket, halt
- phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')');
- }
- break;
- case CAS_VERSION_2_0: // check for a Service or Proxy Ticket
- if( preg_match('/^[SP]T-/',$ticket) ) {
- phpCAS::trace('ST or PT \''.$ticket.'\' found');
- $this->setPT($ticket);
- unset($_GET['ticket']);
- } else if ( !empty($ticket) ) {
- //ill-formed ticket, halt
- phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')');
- }
- break;
- case SAML_VERSION_1_1: // SAML just does Service Tickets
- if( preg_match('/^[SP]T-/',$ticket) ) {
- phpCAS::trace('SA \''.$ticket.'\' found');
- $this->setSA($ticket);
- unset($_GET['ticket']);
- } else if ( !empty($ticket) ) {
- //ill-formed ticket, halt
- phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')');
- }
- break;
- }
- }
- phpCAS::traceEnd();
- }
-
- /** @} */
-
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- // XX XX
- // XX Session Handling XX
- // XX XX
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
- /**
- * A variable to whether phpcas will use its own session handling. Default = true
- * @hideinitializer
- * @private
- */
- var $_start_session = true;
-
- function setStartSession($session)
- {
- $this->_start_session = session;
- }
-
- function getStartSession($session)
- {
- $this->_start_session = session;
- }
-
- /**
- * Renaming the session
- */
- function renameSession($ticket)
- {
- phpCAS::traceBegin();
- if($this->_start_session){
- if (!empty ($this->_user))
- {
- $old_session = $_SESSION;
- session_destroy();
- // set up a new session, of name based on the ticket
- $session_id = preg_replace('/[^\w]/', '', $ticket);
- phpCAS :: trace("Session ID: ".$session_id);
- session_id($session_id);
- session_start();
- phpCAS :: trace("Restoring old session vars");
- $_SESSION = $old_session;
- } else
- {
- phpCAS :: error('Session should only be renamed after successfull authentication');
- }
- }else{
- phpCAS :: trace("Skipping session rename since phpCAS is not handling the session.");
- }
- phpCAS::traceEnd();
- }
-
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- // XX XX
- // XX AUTHENTICATION XX
- // XX XX
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
- /**
- * @addtogroup internalAuthentication
- * @{
- */
-
- /**
- * The Authenticated user. Written by CASClient::setUser(), read by CASClient::getUser().
- * @attention client applications should use phpCAS::getUser().
- *
- * @hideinitializer
- * @private
- */
- var $_user = '';
-
- /**
- * This method sets the CAS user's login name.
- *
- * @param $user the login name of the authenticated user.
- *
- * @private
- */
- function setUser($user)
- {
- $this->_user = $user;
- }
-
- /**
- * This method returns the CAS user's login name.
- * @warning should be called only after CASClient::forceAuthentication() or
- * CASClient::isAuthenticated(), otherwise halt with an error.
- *
- * @return the login name of the authenticated user
- */
- function getUser()
- {
- if ( empty($this->_user) ) {
- phpCAS::error('this method should be used only after '.__CLASS__.'::forceAuthentication() or '.__CLASS__.'::isAuthenticated()');
- }
- return $this->_user;
- }
-
-
-
- /***********************************************************************************************************************
- * Atrributes section
- *
- * @author Matthias Crauwels <matthias.crauwels@ugent.be>, Ghent University, Belgium
- *
- ***********************************************************************************************************************/
- /**
- * The Authenticated users attributes. Written by CASClient::setAttributes(), read by CASClient::getAttributes().
- * @attention client applications should use phpCAS::getAttributes().
- *
- * @hideinitializer
- * @private
- */
- var $_attributes = array();
-
- function setAttributes($attributes)
- { $this->_attributes = $attributes; }
-
- 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;
- }
-
- function hasAttributes()
- { return !empty($this->_attributes); }
-
- function hasAttribute($key)
- { return (is_array($this->_attributes) && array_key_exists($key, $this->_attributes)); }
-
- 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
- * @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
- */
- var $_cache_times_for_auth_recheck = 0;
-
- /**
- * Set the number of times authentication will be cached before rechecked.
- *
- * @param $n an integer.
- *
- * @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 otherwise.
- * @public
- */
- function checkAuthentication()
- {
- phpCAS::traceBegin();
-
- if ( $this->isAuthenticated() ) {
- phpCAS::trace('user is authenticated');
- $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 {
- // $_SESSION['phpCAS']['auth_checked'] = true;
- // $this->redirectToCas(TRUE/* gateway */);
- // // never reached
- // $res = FALSE;
- // 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->hasST() || $this->hasPT() || $this->hasSA()){
- // User has a additional ticket but was already authenticated
- phpCAS::trace('ticket was present and will be discarded, use renewAuthenticate()');
- header('Location: '.$this->getURL());
- phpCAS::log( "Prepare redirect to remove ticket: ".$this->getURL() );
- phpCAS::traceExit();
- exit();
- }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->hasST() ) {
- // if a Service Ticket was given, validate it
- phpCAS::trace('ST `'.$this->getST().'\' is present');
- $this->validateST($validate_url,$text_response,$tree_response); // if it fails, it halts
- phpCAS::trace('ST `'.$this->getST().'\' 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();
- $res = TRUE;
- }
- elseif ( $this->hasPT() ) {
- // if a Proxy Ticket was given, validate it
- phpCAS::trace('PT `'.$this->getPT().'\' is present');
- $this->validatePT($validate_url,$text_response,$tree_response); // note: if it fails, it halts
- phpCAS::trace('PT `'.$this->getPT().'\' 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();
- $res = TRUE;
- }
- elseif ( $this->hasSA() ) {
- // if we have a SAML ticket, validate it.
- phpCAS::trace('SA `'.$this->getSA().'\' is present');
- $this->validateSA($validate_url,$text_response,$tree_response); // if it fails, it halts
- phpCAS::trace('SA `'.$this->getSA().'\' was validated');
- $_SESSION['phpCAS']['user'] = $this->getUser();
- $_SESSION['phpCAS']['attributes'] = $this->getAttributes();
- $res = TRUE;
- }
- else {
- // no ticket given, not authenticated
- phpCAS::trace('no ticket found');
- }
- if ($res) {
- // 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
- header('Location: '.$this->getURL());
- phpCAS::log( "Prepare redirect to : ".$this->getURL() );
- phpCAS::traceExit();
- exit();
- }
- }
-
- phpCAS::traceEnd($res);
- return $res;
- }
-
- /**
- * This method tells if the current session is authenticated.
- * @return true if authenticated based soley on $_SESSION variable
- * @since 0.4.22 by Brendan Arnold
- */
- 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() ) {
- $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']);
- $this->setPGT($_SESSION['phpCAS']['pgt']);
- phpCAS::trace('user = `'.$_SESSION['phpCAS']['user'].'\', PGT = `'.$_SESSION['phpCAS']['pgt'].'\'');
- $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->setST('');
- $this->setPT('');
- } 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->setST('');
- $this->setPT('');
- } else {
- phpCAS::trace('neither user not 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'].'\'');
- $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 CASClient::forceAuthentication() and CASClient::checkAuthentication().
- * @param $gateway true to check authentication, false to force it
- * @param $renew true to force the authentication with the CAS server
- * @public
- */
- function redirectToCas($gateway=false,$renew=false){
- phpCAS::traceBegin();
- $cas_url = $this->getServerLoginURL($gateway,$renew);
- header('Location: '.$cas_url);
- phpCAS::log( "Redirect to : ".$cas_url );
-
- $this->printHTMLHeader($this->getString(CAS_STR_AUTHENTICATION_WANTED));
-
- printf('<p>'.$this->getString(CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'</p>',$cas_url);
- $this->printHTMLFooter();
-
- phpCAS::traceExit();
- exit();
- }
-
-
- /**
- * This method is used to logout from CAS.
- * @params $params an array that contains the optional url and service parameters that will be passed to the CAS server
- * @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::log( "Prepare redirect to : ".$cas_url );
-
- session_unset();
- session_destroy();
-
- $this->printHTMLHeader($this->getString(CAS_STR_LOGOUT));
- printf('<p>'.$this->getString(CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED).'</p>',$cas_url);
- $this->printHTMLFooter();
-
- phpCAS::traceExit();
- exit();
- }
-
- /**
- * @return true if the current request is a logout request.
- * @private
- */
- function isLogoutRequest() {
- return !empty($_POST['logoutRequest']);
- }
-
- /**
- * @return true if a logout request is allowed.
- * @private
- */
- function isLogoutRequestAllowed() {
- }
-
- /**
- * This method handles logout requests.
- * @param $check_client true to check the client bofore handling the request,
- * false not to perform any access control. True by default.
- * @param $allowed_clients an array of host names allowed to send logout requests.
- * By default, only the CAs server (declared in the constructor) will be allowed.
- * @public
- */
- function handleLogoutRequests($check_client=true, $allowed_clients=false) {
- phpCAS::traceBegin();
- if (!$this->isLogoutRequest()) {
- phpCAS::log("Not a logout request");
- phpCAS::traceEnd();
- return;
- }
- if(!$this->_start_session){
- phpCAS::log("phpCAS can't handle logout requests if it does not manage the session.");
- }
- phpCAS::log("Logout requested");
- phpCAS::log("SAML REQUEST: ".$_POST['logoutRequest']);
- if ($check_client) {
- if (!$allowed_clients) {
- $allowed_clients = array( $this->getServerHostname() );
- }
- $client_ip = $_SERVER['REMOTE_ADDR'];
- $client = gethostbyaddr($client_ip);
- phpCAS::log("Client: ".$client."/".$client_ip);
- $allowed = false;
- foreach ($allowed_clients as $allowed_client) {
- if (($client == $allowed_client) or ($client_ip == $allowed_client)) {
- phpCAS::log("Allowed client '".$allowed_client."' matches, logout request is allowed");
- $allowed = true;
- break;
- } else {
- phpCAS::log("Allowed client '".$allowed_client."' does not match");
- }
- }
- if (!$allowed) {
- phpCAS::error("Unauthorized logout request from client '".$client."'");
- printf("Unauthorized!");
- phpCAS::traceExit();
- exit();
- }
- } else {
- phpCAS::log("No access control set");
- }
- // Extract the ticket from the SAML Request
- preg_match("|<samlp:SessionIndex>(.*)</samlp:SessionIndex>|", $_POST['logoutRequest'], $tick, PREG_OFFSET_CAPTURE, 3);
- $wrappedSamlSessionIndex = preg_replace('|<samlp:SessionIndex>|','',$tick[0][0]);
- $ticket2logout = preg_replace('|</samlp:SessionIndex>|','',$wrappedSamlSessionIndex);
- phpCAS::log("Ticket to logout: ".$ticket2logout);
- $session_id = preg_replace('/[^\w]/','',$ticket2logout);
- phpCAS::log("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();
- printf("Disconnected!");
- phpCAS::traceExit();
- exit();
- }
-
- /** @} */
-
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- // XX XX
- // XX BASIC CLIENT FEATURES (CAS 1.0) XX
- // XX XX
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
- // ########################################################################
- // ST
- // ########################################################################
- /**
- * @addtogroup internalBasic
- * @{
- */
-
- /**
- * the Service Ticket provided in the URL of the request if present
- * (empty otherwise). Written by CASClient::CASClient(), read by
- * CASClient::getST() and CASClient::hasPGT().
- *
- * @hideinitializer
- * @private
- */
- var $_st = '';
-
- /**
- * This method returns the Service Ticket provided in the URL of the request.
- * @return The service ticket.
- * @private
- */
- function getST()
- { return $this->_st; }
-
- /**
- * This method stores the Service Ticket.
- * @param $st The Service Ticket.
- * @private
- */
- function setST($st)
- { $this->_st = $st; }
-
- /**
- * This method tells if a Service Ticket was stored.
- * @return TRUE if a Service Ticket has been stored.
- * @private
- */
- function hasST()
- { return !empty($this->_st); }
-
- /** @} */
-
- // ########################################################################
- // ST VALIDATION
- // ########################################################################
- /**
- * @addtogroup internalBasic
- * @{
- */
-
- /**
- * the certificate of the CAS server.
- *
- * @hideinitializer
- * @private
- */
- var $_cas_server_cert = '';
-
- /**
- * the certificate of the CAS server CA.
- *
- * @hideinitializer
- * @private
- */
- var $_cas_server_ca_cert = '';
-
- /**
- * Set to true not to validate the CAS server.
- *
- * @hideinitializer
- * @private
- */
- var $_no_cas_server_validation = false;
-
- /**
- * Set the certificate of the CAS server.
- *
- * @param $cert the PEM certificate
- */
- function setCasServerCert($cert)
- {
- $this->_cas_server_cert = $cert;
- }
-
- /**
- * Set the CA certificate of the CAS server.
- *
- * @param $cert the PEM certificate of the CA that emited the cert of the server
- */
- function setCasServerCACert($cert)
- {
- $this->_cas_server_ca_cert = $cert;
- }
-
- /**
- * Set no SSL validation for the CAS server.
- */
- function setNoCasServerValidation()
- {
- $this->_no_cas_server_validation = true;
- }
-
- /**
- * This method is used to validate a ST; halt on failure, and sets $validate_url,
- * $text_reponse and $tree_response on success. These parameters are used later
- * by CASClient::validatePGT() for CAS proxies.
- * Used for all CAS 1.0 validations
- * @param $validate_url the URL of the request to the CAS server.
- * @param $text_response the response of the CAS server, as is (XML text).
- * @param $tree_response the response of the CAS server, as a DOM XML tree.
- *
- * @return bool TRUE when successfull, halt otherwise by calling CASClient::authError().
- *
- * @private
- */
- function validateST($validate_url,&$text_response,&$tree_response)
- {
- phpCAS::traceBegin();
- // build the URL to validate the ticket
- $validate_url = $this->getServerServiceValidateURL().'&ticket='.$this->getST();
- if ( $this->isProxy() ) {
- // pass the callback url for CAS proxies
- $validate_url .= '&pgtUrl='.urlencode($this->getCallbackURL());
- }
-
- // open and read the URL
- if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) {
- phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
- $this->authError('ST not validated',
- $validate_url,
- TRUE/*$no_response*/);
- }
-
- // analyze the result depending on the version
- switch ($this->getServerVersion()) {
- case CAS_VERSION_1_0:
- if (preg_match('/^no\n/',$text_response)) {
- phpCAS::trace('ST has not been validated');
- $this->authError('ST not validated',
- $validate_url,
- FALSE/*$no_response*/,
- FALSE/*$bad_response*/,
- $text_response);
- }
- if (!preg_match('/^yes\n/',$text_response)) {
- phpCAS::trace('ill-formed response');
- $this->authError('ST not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- // ST has been validated, extract the user name
- $arr = preg_split('/\n/',$text_response);
- $this->setUser(trim($arr[1]));
- break;
- case CAS_VERSION_2_0:
- // read the response of the CAS server into a DOM object
- if ( !($dom = domxml_open_mem($text_response))) {
- phpCAS::trace('domxml_open_mem() failed');
- $this->authError('ST not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- // read the root node of the XML tree
- if ( !($tree_response = $dom->document_element()) ) {
- phpCAS::trace('document_element() failed');
- $this->authError('ST not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- // insure that tag name is 'serviceResponse'
- if ( $tree_response->node_name() != 'serviceResponse' ) {
- phpCAS::trace('bad XML root node (should be `serviceResponse\' instead of `'.$tree_response->node_name().'\'');
- $this->authError('ST not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- if ( sizeof($success_elements = $tree_response->get_elements_by_tagname("authenticationSuccess")) != 0) {
- // authentication succeded, extract the user name
- if ( sizeof($user_elements = $success_elements[0]->get_elements_by_tagname("user")) == 0) {
- phpCAS::trace('<authenticationSuccess> found, but no <user>');
- $this->authError('ST not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- $user = trim($user_elements[0]->get_content());
- phpCAS::trace('user = `'.$user);
- $this->setUser($user);
-
- } else if ( sizeof($failure_elements = $tree_response->get_elements_by_tagname("authenticationFailure")) != 0) {
- phpCAS::trace('<authenticationFailure> found');
- // authentication failed, extract the error code and message
- $this->authError('ST not validated',
- $validate_url,
- FALSE/*$no_response*/,
- FALSE/*$bad_response*/,
- $text_response,
- $failure_elements[0]->get_attribute('code')/*$err_code*/,
- trim($failure_elements[0]->get_content())/*$err_msg*/);
- } else {
- phpCAS::trace('neither <authenticationSuccess> nor <authenticationFailure> found');
- $this->authError('ST not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- break;
- }
- $this->renameSession($this->getST());
- // at this step, ST has been validated and $this->_user has been set,
- phpCAS::traceEnd(TRUE);
- return TRUE;
- }
-
- // ########################################################################
- // SAML VALIDATION
- // ########################################################################
- /**
- * @addtogroup internalBasic
- * @{
- */
-
- /**
- * This method is used to validate a SAML TICKET; halt on failure, and sets $validate_url,
- * $text_reponse and $tree_response on success. These parameters are used later
- * by CASClient::validatePGT() for CAS proxies.
- *
- * @param $validate_url the URL of the request to the CAS server.
- * @param $text_response the response of the CAS server, as is (XML text).
- * @param $tree_response the response of the CAS server, as a DOM XML tree.
- *
- * @return bool TRUE when successfull, halt otherwise by calling CASClient::authError().
- *
- * @private
- */
- function validateSA($validate_url,&$text_response,&$tree_response)
- {
- phpCAS::traceBegin();
-
- // build the URL to validate the ticket
- $validate_url = $this->getServerSamlValidateURL();
-
- // open and read the URL
- if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) {
- phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
- $this->authError('SA not validated', $validate_url, TRUE/*$no_response*/);
- }
-
- phpCAS::trace('server version: '.$this->getServerVersion());
-
- // analyze the result depending on the version
- switch ($this->getServerVersion()) {
- case SAML_VERSION_1_1:
-
- // read the response of the CAS server into a DOM object
- if ( !($dom = domxml_open_mem($text_response))) {
- phpCAS::trace('domxml_open_mem() failed');
- $this->authError('SA not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- // read the root node of the XML tree
- if ( !($tree_response = $dom->document_element()) ) {
- phpCAS::trace('document_element() failed');
- $this->authError('SA not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- // insure that tag name is 'Envelope'
- if ( $tree_response->node_name() != 'Envelope' ) {
- phpCAS::trace('bad XML root node (should be `Envelope\' instead of `'.$tree_response->node_name().'\'');
- $this->authError('SA not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- // check for the NameIdentifier tag in the SAML response
- if ( sizeof($success_elements = $tree_response->get_elements_by_tagname("NameIdentifier")) != 0) {
- phpCAS::trace('NameIdentifier found');
- $user = trim($success_elements[0]->get_content());
- phpCAS::trace('user = `'.$user.'`');
- $this->setUser($user);
- $this->setSessionAttributes($text_response);
- } else {
- phpCAS::trace('no <NameIdentifier> tag found in SAML payload');
- $this->authError('SA not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- break;
- }
- $this->renameSession($this->getSA());
- // at this step, ST has been validated and $this->_user has been set,
- phpCAS::traceEnd(TRUE);
- return TRUE;
- }
-
- /**
- * This method will parse the DOM and pull out the attributes from the SAML
- * payload and put them into an array, then put the array into the session.
- *
- * @param $text_response the SAML payload.
- * @return bool TRUE when successfull and FALSE if no attributes a found
- *
- * @private
- */
- function setSessionAttributes($text_response)
- {
- phpCAS::traceBegin();
-
- $result = FALSE;
-
- if (isset($_SESSION[SAML_ATTRIBUTES])) {
- phpCAS::trace("session attrs already set."); //testbml - do we care?
- }
-
- $attr_array = array();
-
- if (($dom = domxml_open_mem($text_response))) {
- $xPath = $dom->xpath_new_context();
- $xPath->xpath_register_ns('samlp', 'urn:oasis:names:tc:SAML:1.0:protocol');
- $xPath->xpath_register_ns('saml', 'urn:oasis:names:tc:SAML:1.0:assertion');
- $nodelist = $xPath->xpath_eval("//saml:Attribute");
- if($nodelist){
- $attrs = $nodelist->nodeset;
- foreach($attrs as $attr){
- $xres = $xPath->xpath_eval("saml:AttributeValue", $attr);
- $name = $attr->get_attribute("AttributeName");
- $value_array = array();
- foreach($xres->nodeset as $node){
- $value_array[] = $node->get_content();
- }
- $attr_array[$name] = $value_array;
- }
- $_SESSION[SAML_ATTRIBUTES] = $attr_array;
- // UGent addition...
- foreach($attr_array as $attr_key => $attr_value) {
- if(count($attr_value) > 1) {
- $this->_attributes[$attr_key] = $attr_value;
- phpCAS::trace("* " . $attr_key . "=" . $attr_value);
- }
- else {
- $this->_attributes[$attr_key] = $attr_value[0];
- phpCAS::trace("* " . $attr_key . "=" . $attr_value[0]);
- }
- }
- $result = TRUE;
- }else{
- phpCAS::trace("SAML Attributes are empty");
- $result = FALSE;
- }
- }
- phpCAS::traceEnd($result);
- return $result;
- }
-
- /** @} */
-
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- // XX XX
- // XX PROXY FEATURES (CAS 2.0) XX
- // XX XX
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
- // ########################################################################
- // PROXYING
- // ########################################################################
- /**
- * @addtogroup internalProxy
- * @{
- */
-
- /**
- * A boolean telling if the client is a CAS proxy or not. Written by CASClient::CASClient(),
- * read by CASClient::isProxy().
- *
- * @private
- */
- var $_proxy;
-
- /**
- * Tells if a CAS client is a CAS proxy or not
- *
- * @return TRUE when the CAS client is a CAs proxy, FALSE otherwise
- *
- * @private
- */
- function isProxy()
- {
- return $this->_proxy;
- }
-
- /** @} */
- // ########################################################################
- // PGT
- // ########################################################################
- /**
- * @addtogroup internalProxy
- * @{
- */
-
- /**
- * the Proxy Grnting Ticket given by the CAS server (empty otherwise).
- * Written by CASClient::setPGT(), read by CASClient::getPGT() and CASClient::hasPGT().
- *
- * @hideinitializer
- * @private
- */
- var $_pgt = '';
-
- /**
- * This method returns the Proxy Granting Ticket given by the CAS server.
- * @return The Proxy Granting Ticket.
- * @private
- */
- function getPGT()
- { return $this->_pgt; }
-
- /**
- * This method stores the Proxy Granting Ticket.
- * @param $pgt The Proxy Granting Ticket.
- * @private
- */
- function setPGT($pgt)
- { $this->_pgt = $pgt; }
-
- /**
- * This method tells if a Proxy Granting Ticket was stored.
- * @return TRUE if a Proxy Granting Ticket has been stored.
- * @private
- */
- function hasPGT()
- { return !empty($this->_pgt); }
-
- /** @} */
-
- // ########################################################################
- // CALLBACK MODE
- // ########################################################################
- /**
- * @addtogroup internalCallback
- * @{
- */
- /**
- * each PHP script using phpCAS in proxy mode is its own callback to get the
- * PGT back from the CAS server. callback_mode is detected by the constructor
- * thanks to the GET parameters.
- */
-
- /**
- * a boolean to know if the CAS client is running in callback mode. Written by
- * CASClient::setCallBackMode(), read by CASClient::isCallbackMode().
- *
- * @hideinitializer
- * @private
- */
- var $_callback_mode = FALSE;
-
- /**
- * This method sets/unsets callback mode.
- *
- * @param $callback_mode TRUE to set callback mode, FALSE otherwise.
- *
- * @private
- */
- function setCallbackMode($callback_mode)
- {
- $this->_callback_mode = $callback_mode;
- }
-
- /**
- * This method returns TRUE when the CAs client is running i callback mode,
- * FALSE otherwise.
- *
- * @return A boolean.
- *
- * @private
- */
- function isCallbackMode()
- {
- return $this->_callback_mode;
- }
-
- /**
- * the URL that should be used for the PGT callback (in fact the URL of the
- * current request without any CGI parameter). Written and read by
- * CASClient::getCallbackURL().
- *
- * @hideinitializer
- * @private
- */
- var $_callback_url = '';
-
- /**
- * This method returns the URL that should be used for the PGT callback (in
- * fact the URL of the current request without any CGI parameter, except if
- * phpCAS::setFixedCallbackURL() was used).
- *
- * @return The callback URL
- *
- * @private
- */
- function getCallbackURL()
- {
- // the URL is built when needed only
- if ( empty($this->_callback_url) ) {
- $final_uri = '';
- // remove the ticket if present in the URL
- $final_uri = 'https://';
- /* replaced by Julien Marchal - v0.4.6
- * $this->uri .= $_SERVER['SERVER_NAME'];
- */
- if(empty($_SERVER['HTTP_X_FORWARDED_SERVER'])){
- /* replaced by teedog - v0.4.12
- * $final_uri .= $_SERVER['SERVER_NAME'];
- */
- if (empty($_SERVER['SERVER_NAME'])) {
- $final_uri .= $_SERVER['HTTP_HOST'];
- } else {
- $final_uri .= $_SERVER['SERVER_NAME'];
- }
- } else {
- $final_uri .= $_SERVER['HTTP_X_FORWARDED_SERVER'];
- }
- if ( ($this->isHttps() && $_SERVER['SERVER_PORT']!=443)
- || (!$this->isHttps() && $_SERVER['SERVER_PORT']!=80) ) {
- $final_uri .= ':';
- $final_uri .= $_SERVER['SERVER_PORT'];
- }
- $request_uri = $_SERVER['REQUEST_URI'];
- $request_uri = preg_replace('/\?.*$/','',$request_uri);
- $final_uri .= $request_uri;
- $this->setCallbackURL($final_uri);
- }
- return $this->_callback_url;
- }
-
- /**
- * This method sets the callback url.
- *
- * @param $callback_url url to set callback
- *
- * @private
- */
- function setCallbackURL($url)
- {
- return $this->_callback_url = $url;
- }
-
- /**
- * This method is called by CASClient::CASClient() when running in callback
- * mode. It stores the PGT and its PGT Iou, prints its output and halts.
- *
- * @private
- */
- function callback()
- {
- phpCAS::traceBegin();
- if (preg_match('/PGTIOU-[\.\-\w]/', $_GET['pgtIou'])){
- if(preg_match('/[PT]GT-[\.\-\w]/', $_GET['pgtId'])){
- $this->printHTMLHeader('phpCAS callback');
- $pgt_iou = $_GET['pgtIou'];
- $pgt = $_GET['pgtId'];
- phpCAS::trace('Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\')');
- echo '<p>Storing PGT `'.$pgt.'\' (id=`'.$pgt_iou.'\').</p>';
- $this->storePGT($pgt,$pgt_iou);
- $this->printHTMLFooter();
- }else{
- phpCAS::error('PGT format invalid' . $_GET['pgtId']);
- }
- }else{
- phpCAS::error('PGTiou format invalid' . $_GET['pgtIou']);
- }
- phpCAS::traceExit();
- exit();
- }
-
- /** @} */
-
- // ########################################################################
- // PGT STORAGE
- // ########################################################################
- /**
- * @addtogroup internalPGTStorage
- * @{
- */
-
- /**
- * an instance of a class inheriting of PGTStorage, used to deal with PGT
- * storage. Created by CASClient::setPGTStorageFile() or CASClient::setPGTStorageDB(), used
- * by CASClient::setPGTStorageFile(), CASClient::setPGTStorageDB() and CASClient::initPGTStorage().
- *
- * @hideinitializer
- * @private
- */
- var $_pgt_storage = null;
-
- /**
- * This method is used to initialize the storage of PGT's.
- * Halts on error.
- *
- * @private
- */
- function initPGTStorage()
- {
- // if no SetPGTStorageXxx() has been used, default to file
- if ( !is_object($this->_pgt_storage) ) {
- $this->setPGTStorageFile();
- }
-
- // initializes the storage
- $this->_pgt_storage->init();
- }
-
- /**
- * This method stores a PGT. Halts on error.
- *
- * @param $pgt the PGT to store
- * @param $pgt_iou its corresponding Iou
- *
- * @private
- */
- function storePGT($pgt,$pgt_iou)
- {
- // ensure that storage is initialized
- $this->initPGTStorage();
- // writes the PGT
- $this->_pgt_storage->write($pgt,$pgt_iou);
- }
-
- /**
- * This method reads a PGT from its Iou and deletes the corresponding storage entry.
- *
- * @param $pgt_iou the PGT Iou
- *
- * @return The PGT corresponding to the Iou, FALSE when not found.
- *
- * @private
- */
- function loadPGT($pgt_iou)
- {
- // ensure that storage is initialized
- $this->initPGTStorage();
- // read the PGT
- return $this->_pgt_storage->read($pgt_iou);
- }
-
- /**
- * This method is used to tell phpCAS to store the response of the
- * CAS server to PGT requests onto the filesystem.
- *
- * @param $format the format used to store the PGT's (`plain' and `xml' allowed)
- * @param $path the path where the PGT's should be stored
- *
- * @public
- */
- function setPGTStorageFile($format='',
- $path='')
- {
- // check that the storage has not already been set
- if ( is_object($this->_pgt_storage) ) {
- phpCAS::error('PGT storage already defined');
- }
-
- // create the storage object
- $this->_pgt_storage = new PGTStorageFile($this,$format,$path);
- }
-
- // ########################################################################
- // PGT VALIDATION
- // ########################################################################
- /**
- * This method is used to validate a PGT; halt on failure.
- *
- * @param $validate_url the URL of the request to the CAS server.
- * @param $text_response the response of the CAS server, as is (XML text); result
- * of CASClient::validateST() or CASClient::validatePT().
- * @param $tree_response the response of the CAS server, as a DOM XML tree; result
- * of CASClient::validateST() or CASClient::validatePT().
- *
- * @return bool TRUE when successfull, halt otherwise by calling CASClient::authError().
- *
- * @private
- */
- function validatePGT(&$validate_url,$text_response,$tree_response)
- {
- // here cannot use phpCAS::traceBegin(); alongside domxml-php4-to-php5.php
- phpCAS::log('start validatePGT()');
- if ( sizeof($arr = $tree_response->get_elements_by_tagname("proxyGrantingTicket")) == 0) {
- phpCAS::trace('<proxyGrantingTicket> not found');
- // authentication succeded, but no PGT Iou was transmitted
- $this->authError('Ticket validated but no PGT Iou transmitted',
- $validate_url,
- FALSE/*$no_response*/,
- FALSE/*$bad_response*/,
- $text_response);
- } else {
- // PGT Iou transmitted, extract it
- $pgt_iou = trim($arr[0]->get_content());
- if(preg_match('/PGTIOU-[\.\-\w]/',$pgt_iou)){
- $pgt = $this->loadPGT($pgt_iou);
- if ( $pgt == FALSE ) {
- phpCAS::trace('could not load PGT');
- $this->authError('PGT Iou was transmitted but PGT could not be retrieved',
- $validate_url,
- FALSE/*$no_response*/,
- FALSE/*$bad_response*/,
- $text_response);
- }
- $this->setPGT($pgt);
- }else{
- phpCAS::trace('PGTiou format error');
- $this->authError('PGT Iou was transmitted but has wrong fromat',
- $validate_url,
- FALSE/*$no_response*/,
- FALSE/*$bad_response*/,
- $text_response);
- }
-
- }
- // here, cannot use phpCAS::traceEnd(TRUE); alongside domxml-php4-to-php5.php
- phpCAS::log('end validatePGT()');
- return TRUE;
- }
-
- // ########################################################################
- // PGT VALIDATION
- // ########################################################################
-
- /**
- * This method is used to retrieve PT's from the CAS server thanks to a PGT.
- *
- * @param $target_service the service to ask for with the PT.
- * @param $err_code an error code (PHPCAS_SERVICE_OK on success).
- * @param $err_msg an error message (empty on success).
- *
- * @return a Proxy Ticket, or FALSE on error.
- *
- * @private
- */
- function retrievePT($target_service,&$err_code,&$err_msg)
- {
- phpCAS::traceBegin();
-
- // by default, $err_msg is set empty and $pt to TRUE. On error, $pt is
- // set to false and $err_msg to an error message. At the end, if $pt is FALSE
- // and $error_msg is still empty, it is set to 'invalid response' (the most
- // commonly encountered error).
- $err_msg = '';
-
- // build the URL to retrieve the PT
- // $cas_url = $this->getServerProxyURL().'?targetService='.preg_replace('/&/','%26',$target_service).'&pgt='.$this->getPGT();
- $cas_url = $this->getServerProxyURL().'?targetService='.urlencode($target_service).'&pgt='.$this->getPGT();
-
- // open and read the URL
- if ( !$this->readURL($cas_url,''/*cookies*/,$headers,$cas_response,$err_msg) ) {
- phpCAS::trace('could not open URL \''.$cas_url.'\' to validate ('.$err_msg.')');
- $err_code = PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE;
- $err_msg = 'could not retrieve PT (no response from the CAS server)';
- phpCAS::traceEnd(FALSE);
- return FALSE;
- }
-
- $bad_response = FALSE;
-
- if ( !$bad_response ) {
- // read the response of the CAS server into a DOM object
- if ( !($dom = @domxml_open_mem($cas_response))) {
- phpCAS::trace('domxml_open_mem() failed');
- // read failed
- $bad_response = TRUE;
- }
- }
-
- if ( !$bad_response ) {
- // read the root node of the XML tree
- if ( !($root = $dom->document_element()) ) {
- phpCAS::trace('document_element() failed');
- // read failed
- $bad_response = TRUE;
- }
- }
-
- if ( !$bad_response ) {
- // insure that tag name is 'serviceResponse'
- if ( $root->node_name() != 'serviceResponse' ) {
- phpCAS::trace('node_name() failed');
- // bad root node
- $bad_response = TRUE;
- }
- }
-
- if ( !$bad_response ) {
- // look for a proxySuccess tag
- if ( sizeof($arr = $root->get_elements_by_tagname("proxySuccess")) != 0) {
- // authentication succeded, look for a proxyTicket tag
- if ( sizeof($arr = $root->get_elements_by_tagname("proxyTicket")) != 0) {
- $err_code = PHPCAS_SERVICE_OK;
- $err_msg = '';
- phpCAS::trace('original PT: '.trim($arr[0]->get_content()));
- $pt = trim($arr[0]->get_content());
- phpCAS::traceEnd($pt);
- return $pt;
- } else {
- phpCAS::trace('<proxySuccess> was found, but not <proxyTicket>');
- }
- }
- // look for a proxyFailure tag
- else if ( sizeof($arr = $root->get_elements_by_tagname("proxyFailure")) != 0) {
- // authentication failed, extract the error
- $err_code = PHPCAS_SERVICE_PT_FAILURE;
- $err_msg = 'PT retrieving failed (code=`'
- .$arr[0]->get_attribute('code')
- .'\', message=`'
- .trim($arr[0]->get_content())
- .'\')';
- phpCAS::traceEnd(FALSE);
- return FALSE;
- } else {
- phpCAS::trace('neither <proxySuccess> nor <proxyFailure> found');
- }
- }
-
- // at this step, we are sure that the response of the CAS server was ill-formed
- $err_code = PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE;
- $err_msg = 'Invalid response from the CAS server (response=`'.$cas_response.'\')';
-
- phpCAS::traceEnd(FALSE);
- return FALSE;
- }
-
- // ########################################################################
- // ACCESS TO EXTERNAL SERVICES
- // ########################################################################
-
- /**
- * This method is used to acces a remote URL.
- *
- * @param $url the URL to access.
- * @param $cookies an array containing cookies strings such as 'name=val'
- * @param $headers an array containing the HTTP header lines of the response
- * (an empty array on failure).
- * @param $body the body of the response, as a string (empty on failure).
- * @param $err_msg an error message, filled on failure.
- *
- * @return TRUE on success, FALSE otherwise (in this later case, $err_msg
- * contains an error message).
- *
- * @private
- */
- function readURL($url,$cookies,&$headers,&$body,&$err_msg)
- {
- phpCAS::traceBegin();
- $headers = '';
- $body = '';
- $err_msg = '';
-
- $res = TRUE;
-
- // initialize the CURL session
- $ch = curl_init($url);
-
- if (version_compare(PHP_VERSION,'5.1.3','>=')) {
- //only avaible in php5
- curl_setopt_array($ch, $this->_curl_options);
- } else {
- foreach ($this->_curl_options as $key => $value) {
- curl_setopt($ch, $key, $value);
- }
- }
-
- if ($this->_cas_server_cert == '' && $this->_cas_server_ca_cert == '' && !$this->_no_cas_server_validation) {
- phpCAS::error('one of the methods phpCAS::setCasServerCert(), phpCAS::setCasServerCACert() or phpCAS::setNoCasServerValidation() must be called.');
- }
- if ($this->_cas_server_cert != '' && $this->_cas_server_ca_cert != '') {
- // This branch added by IDMS. Seems phpCAS implementor got a bit confused about the curl options CURLOPT_SSLCERT and CURLOPT_CAINFO
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
- curl_setopt($ch, CURLOPT_SSLCERT, $this->_cas_server_cert);
- curl_setopt($ch, CURLOPT_CAINFO, $this->_cas_server_ca_cert);
- curl_setopt($ch, CURLOPT_VERBOSE, '1');
- phpCAS::trace('CURL: Set all required opts for mutual authentication ------');
- } else if ($this->_cas_server_cert != '' ) {
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
- curl_setopt($ch, CURLOPT_SSLCERT, $this->_cas_server_cert);
- } else if ($this->_cas_server_ca_cert != '') {
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
- curl_setopt($ch, CURLOPT_CAINFO, $this->_cas_server_ca_cert);
- } else {
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
- }
-
- // return the CURL output into a variable
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- // get the HTTP header with a callback
- $this->_curl_headers = array(); // empty the headers array
- curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, '_curl_read_headers'));
- // add cookies headers
- if ( is_array($cookies) ) {
- curl_setopt($ch,CURLOPT_COOKIE,implode(';',$cookies));
- }
- // add extra stuff if SAML
- if ($this->hasSA()) {
- $more_headers = array ("soapaction: http://www.oasis-open.org/committees/security",
- "cache-control: no-cache",
- "pragma: no-cache",
- "accept: text/xml",
- "connection: keep-alive",
- "content-type: text/xml");
-
- curl_setopt($ch, CURLOPT_HTTPHEADER, $more_headers);
- curl_setopt($ch, CURLOPT_POST, 1);
- $data = $this->buildSAMLPayload();
- //phpCAS::trace('SAML Payload: '.print_r($data, TRUE));
- curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
- }
- // perform the query
- $buf = curl_exec ($ch);
- //phpCAS::trace('CURL: Call completed. Response body is: \''.$buf.'\'');
- if ( $buf === FALSE ) {
- phpCAS::trace('curl_exec() failed');
- $err_msg = 'CURL error #'.curl_errno($ch).': '.curl_error($ch);
- //phpCAS::trace('curl error: '.$err_msg);
- // close the CURL session
- curl_close ($ch);
- $res = FALSE;
- } else {
- // close the CURL session
- curl_close ($ch);
-
- $headers = $this->_curl_headers;
- $body = $buf;
- }
-
- phpCAS::traceEnd($res);
- return $res;
- }
-
- /**
- * This method is used to build the SAML POST body sent to /samlValidate URL.
- *
- * @return the SOAP-encased SAMLP artifact (the ticket).
- *
- * @private
- */
- function buildSAMLPayload()
- {
- phpCAS::traceBegin();
-
- //get the ticket
- $sa = $this->getSA();
- //phpCAS::trace("SA: ".$sa);
-
- $body=SAML_SOAP_ENV.SAML_SOAP_BODY.SAMLP_REQUEST.SAML_ASSERTION_ARTIFACT.$sa.SAML_ASSERTION_ARTIFACT_CLOSE.SAMLP_REQUEST_CLOSE.SAML_SOAP_BODY_CLOSE.SAML_SOAP_ENV_CLOSE;
-
- phpCAS::traceEnd($body);
- return ($body);
- }
-
- /**
- * This method is the callback used by readURL method to request HTTP headers.
- */
- var $_curl_headers = array();
- function _curl_read_headers($ch, $header)
- {
- $this->_curl_headers[] = $header;
- return strlen($header);
- }
-
- /**
- * This method is used to access an HTTP[S] service.
- *
- * @param $url the service to access.
- * @param $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 $output the output of the service (also used to give an error
- * message on failure).
- *
- * @return TRUE on success, FALSE otherwise (in this later case, $err_code
- * gives the reason why it failed and $output contains an error message).
- *
- * @public
- */
- function serviceWeb($url,&$err_code,&$output)
- {
- phpCAS::traceBegin();
- // at first retrieve a PT
- $pt = $this->retrievePT($url,$err_code,$output);
-
- $res = TRUE;
-
- // test if PT was retrieved correctly
- if ( !$pt ) {
- // note: $err_code and $err_msg are filled by CASClient::retrievePT()
- phpCAS::trace('PT was not retrieved correctly');
- $res = FALSE;
- } else {
- // add cookies if necessary
- $cookies = $this->getCookies($url);
-
- // build the URL including the PT
- if ( strstr($url,'?') === FALSE ) {
- $service_url = $url.'?ticket='.$pt;
- } else {
- $service_url = $url.'&ticket='.$pt;
- }
-
- phpCAS::trace('reading URL`'.$service_url.'\'');
- if ( !$this->readURL($service_url,$cookies,$headers,$output,$err_msg) ) {
- phpCAS::trace('could not read URL`'.$service_url.'\'');
- $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
- // give an error message
- $output = sprintf($this->getString(CAS_STR_SERVICE_UNAVAILABLE),
- $service_url,
- $err_msg);
- $res = FALSE;
- } else {
- // URL has been fetched, extract the cookies
- phpCAS::trace('URL`'.$service_url.'\' has been read, storing cookies:');
- $this->setCookies($headers,$url);
- // Check for a possible redirect (phpCAS authenticiation redirect after ticket removal)
- foreach($headers as $header){
- if (preg_match('/(Location:|URI:)(.*?)\n/', $header, $matches))
- {
- $redirect_url = trim(array_pop($matches));
- phpCAS :: trace('Found redirect:'.$redirect_url);
- $cookies = $this->getCookies($redirect_url);
- phpCAS::trace('reading URL`'.$redirect_url.'\'');
- if ( !$this->readURL($redirect_url,$cookies,$headers,$output,$err_msg) ) {
- phpCAS::trace('could not read URL`'.$redirect_url.'\'');
- $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
- // give an error message
- $output = sprintf($this->getString(CAS_STR_SERVICE_UNAVAILABLE),
- $service_url,
- $err_msg);
- $res = FALSE;
- } else {
- // URL has been fetched, extract the cookies
- phpCAS::trace('URL`'.$redirect_url.'\' has been read, storing cookies:');
- $this->setCookies($headers,$redirect_url);
- }
- break;
- }
- }
- }
- }
-
- phpCAS::traceEnd($res);
- return $res;
- }
-
- /**
- * This method stores cookies from a HTTP Header in the session
- * @param $header HTTP Header
- * @param $url the url the Header is from
- */
-
- function setCookies($headers,$url){
- phpCAS::traceBegin();
- foreach ( $headers as $header ) {
- // test if the header is a cookie
- if ( preg_match('/^Set-Cookie:/',$header) ) {
- // the header is a cookie, remove the beginning
- $header_val = preg_replace('/^Set-Cookie: */','',$header);
- // extract interesting information
- $name_val = strtok($header_val,'; ');
- // extract the name and the value of the cookie
- $cookie_name = strtok($name_val,'=');
- $cookie_val = strtok('=');
- // store the cookie
- $_SESSION['phpCAS']['services'][$url]['cookies'][$cookie_name] = $cookie_val;
- phpCAS::trace($cookie_name.' -> '.$cookie_val);
- }
- }
- phpCAS::traceEnd();
- }
-
- /**
- * This method get the cookies from the session
- */
-
- function getCookies($url){
- $cookies = array();
- if ( isset($_SESSION['phpCAS']['services'][$url]['cookies']) &&
- is_array($_SESSION['phpCAS']['services'][$url]['cookies']) ) {
- foreach ( $_SESSION['phpCAS']['services'][$url]['cookies'] as $name => $val ) {
- $cookies[] = $name.'='.$val;
- }
- }
- return $cookies;
- }
-
- /**
- * This method is used to access an IMAP/POP3/NNTP service.
- *
- * @param $url a string giving the URL of the service, including the mailing box
- * for IMAP URLs, as accepted by imap_open().
- * @param $service a string giving for CAS retrieve Proxy ticket
- * @param $flags options given to imap_open().
- * @param $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 $err_msg an error message on failure
- * @param $pt the Proxy Ticket (PT) retrieved from the CAS server to access the URL
- * on success, FALSE on error).
- *
- * @return an 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
- */
- function serviceMail($url,$service,$flags,&$err_code,&$err_msg,&$pt)
- {
- phpCAS::traceBegin();
- // at first retrieve a PT
- $pt = $this->retrievePT($service,$err_code,$output);
-
- $stream = FALSE;
-
- // test if PT was retrieved correctly
- if ( !$pt ) {
- // note: $err_code and $err_msg are filled by CASClient::retrievePT()
- phpCAS::trace('PT was not retrieved correctly');
- } else {
- phpCAS::trace('opening IMAP URL `'.$url.'\'...');
- $stream = @imap_open($url,$this->getUser(),$pt,$flags);
- if ( !$stream ) {
- phpCAS::trace('could not open URL');
- $err_code = PHPCAS_SERVICE_NOT_AVAILABLE;
- // give an error message
- $err_msg = sprintf($this->getString(CAS_STR_SERVICE_UNAVAILABLE),
- $service_url,
- var_export(imap_errors(),TRUE));
- $pt = FALSE;
- $stream = FALSE;
- } else {
- phpCAS::trace('ok');
- }
- }
-
- phpCAS::traceEnd($stream);
- return $stream;
- }
-
- /** @} */
-
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- // XX XX
- // XX PROXIED CLIENT FEATURES (CAS 2.0) XX
- // XX XX
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
- // ########################################################################
- // PT
- // ########################################################################
- /**
- * @addtogroup internalProxied
- * @{
- */
-
- /**
- * the Proxy Ticket provided in the URL of the request if present
- * (empty otherwise). Written by CASClient::CASClient(), read by
- * CASClient::getPT() and CASClient::hasPGT().
- *
- * @hideinitializer
- * @private
- */
- var $_pt = '';
-
- /**
- * This method returns the Proxy Ticket provided in the URL of the request.
- * @return The proxy ticket.
- * @private
- */
- function getPT()
- {
- // return 'ST'.substr($this->_pt, 2);
- return $this->_pt;
- }
-
- /**
- * This method stores the Proxy Ticket.
- * @param $pt The Proxy Ticket.
- * @private
- */
- function setPT($pt)
- { $this->_pt = $pt; }
-
- /**
- * This method tells if a Proxy Ticket was stored.
- * @return TRUE if a Proxy Ticket has been stored.
- * @private
- */
- function hasPT()
- { return !empty($this->_pt); }
- /**
- * This method returns the SAML Ticket provided in the URL of the request.
- * @return The SAML ticket.
- * @private
- */
- function getSA()
- { return 'ST'.substr($this->_sa, 2); }
-
- /**
- * This method stores the SAML Ticket.
- * @param $sa The SAML Ticket.
- * @private
- */
- function setSA($sa)
- { $this->_sa = $sa; }
-
- /**
- * This method tells if a SAML Ticket was stored.
- * @return TRUE if a SAML Ticket has been stored.
- * @private
- */
- function hasSA()
- { return !empty($this->_sa); }
-
- /** @} */
- // ########################################################################
- // PT VALIDATION
- // ########################################################################
- /**
- * @addtogroup internalProxied
- * @{
- */
-
- /**
- * This method is used to validate a ST or PT; halt on failure
- * Used for all CAS 2.0 validations
- * @return bool TRUE when successfull, halt otherwise by calling CASClient::authError().
- *
- * @private
- */
- function validatePT(&$validate_url,&$text_response,&$tree_response)
- {
- phpCAS::traceBegin();
- // build the URL to validate the ticket
- $validate_url = $this->getServerProxyValidateURL().'&ticket='.$this->getPT();
-
- if ( $this->isProxy() ) {
- // pass the callback url for CAS proxies
- $validate_url .= '&pgtUrl='.urlencode($this->getCallbackURL());
- }
-
- // open and read the URL
- if ( !$this->readURL($validate_url,''/*cookies*/,$headers,$text_response,$err_msg) ) {
- phpCAS::trace('could not open URL \''.$validate_url.'\' to validate ('.$err_msg.')');
- $this->authError('PT not validated',
- $validate_url,
- TRUE/*$no_response*/);
- }
-
- // read the response of the CAS server into a DOM object
- if ( !($dom = domxml_open_mem($text_response))) {
- // read failed
- $this->authError('PT not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- // read the root node of the XML tree
- if ( !($tree_response = $dom->document_element()) ) {
- // read failed
- $this->authError('PT not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- // insure that tag name is 'serviceResponse'
- if ( $tree_response->node_name() != 'serviceResponse' ) {
- // bad root node
- $this->authError('PT not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- if ( sizeof($arr = $tree_response->get_elements_by_tagname("authenticationSuccess")) != 0) {
- // authentication succeded, extract the user name
- if ( sizeof($arr = $tree_response->get_elements_by_tagname("user")) == 0) {
- // no user specified => error
- $this->authError('PT not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
- $this->setUser(trim($arr[0]->get_content()));
-
- } else if ( sizeof($arr = $tree_response->get_elements_by_tagname("authenticationFailure")) != 0) {
- // authentication succeded, extract the error code and message
- $this->authError('PT not validated',
- $validate_url,
- FALSE/*$no_response*/,
- FALSE/*$bad_response*/,
- $text_response,
- $arr[0]->get_attribute('code')/*$err_code*/,
- trim($arr[0]->get_content())/*$err_msg*/);
- } else {
- $this->authError('PT not validated',
- $validate_url,
- FALSE/*$no_response*/,
- TRUE/*$bad_response*/,
- $text_response);
- }
-
- $this->renameSession($this->getPT());
- // at this step, PT has been validated and $this->_user has been set,
-
- phpCAS::traceEnd(TRUE);
- return TRUE;
- }
-
- /** @} */
-
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- // XX XX
- // XX MISC XX
- // XX XX
- // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-
- /**
- * @addtogroup internalMisc
- * @{
- */
-
- // ########################################################################
- // URL
- // ########################################################################
- /**
- * the URL of the current request (without any ticket CGI parameter). Written
- * and read by CASClient::getURL().
- *
- * @hideinitializer
- * @private
- */
- var $_url = '';
-
- /**
- * This method returns the URL of the current request (without any ticket
- * CGI parameter).
- *
- * @return The URL
- *
- * @private
- */
- function getURL()
- {
- phpCAS::traceBegin();
- // the URL is built when needed only
- if ( empty($this->_url) ) {
- $final_uri = '';
- // remove the ticket if present in the URL
- $final_uri = ($this->isHttps()) ? 'https' : 'http';
- $final_uri .= '://';
- /* replaced by Julien Marchal - v0.4.6
- * $this->_url .= $_SERVER['SERVER_NAME'];
- */
- if(empty($_SERVER['HTTP_X_FORWARDED_SERVER'])){
- /* replaced by teedog - v0.4.12
- * $this->_url .= $_SERVER['SERVER_NAME'];
- */
- if (empty($_SERVER['SERVER_NAME'])) {
- $server_name = $_SERVER['HTTP_HOST'];
- } else {
- $server_name = $_SERVER['SERVER_NAME'];
- }
- } else {
- $server_name = $_SERVER['HTTP_X_FORWARDED_SERVER'];
- }
- $final_uri .= $server_name;
- if (!strpos($server_name, ':')) {
- if ( ($this->isHttps() && $_SERVER['SERVER_PORT']!=443)
- || (!$this->isHttps() && $_SERVER['SERVER_PORT']!=80) ) {
- $final_uri .= ':';
- $final_uri .= $_SERVER['SERVER_PORT'];
- }
- }
-
- $request_uri = explode('?', $_SERVER['REQUEST_URI'], 2);
- $final_uri .= $request_uri[0];
-
- if (isset($request_uri[1]) && $request_uri[1])
- {
- $query_string = $this->removeParameterFromQueryString('ticket', $request_uri[1]);
-
- // If the query string still has anything left, append it to the final URI
- if ($query_string !== '')
- $final_uri .= "?$query_string";
-
- }
-
- phpCAS::trace("Final URI: $final_uri");
- $this->setURL($final_uri);
- }
- phpCAS::traceEnd($this->_url);
- return $this->_url;
- }
-
-
-
- /**
- * Removes a parameter from a query string
- *
- * @param string $parameterName
- * @param string $queryString
- * @return string
- *
- * @link http://stackoverflow.com/questions/1842681/regular-expression-to-remove-one-parameter-from-query-string
- */
- function removeParameterFromQueryString($parameterName, $queryString)
- {
- $parameterName = preg_quote($parameterName);
- return preg_replace("/&$parameterName(=[^&]*)?|^$parameterName(=[^&]*)?&?/", '', $queryString);
- }
-
-
- /**
- * This method sets the URL of the current request
- *
- * @param $url url to set for service
- *
- * @private
- */
- function setURL($url)
- {
- $this->_url = $url;
- }
-
- // ########################################################################
- // AUTHENTICATION ERROR HANDLING
- // ########################################################################
- /**
- * This method is used to print the HTML output when the user was not authenticated.
- *
- * @param $failure the failure that occured
- * @param $cas_url the URL the CAS server was asked for
- * @param $no_response the response from the CAS server (other
- * parameters are ignored if TRUE)
- * @param $bad_response bad response from the CAS server ($err_code
- * and $err_msg ignored if TRUE)
- * @param $cas_response the response of the CAS server
- * @param $err_code the error code given by the CAS server
- * @param $err_msg the error message given by the CAS server
- *
- * @private
- */
- function authError($failure,$cas_url,$no_response,$bad_response='',$cas_response='',$err_code='',$err_msg='')
- {
- phpCAS::traceBegin();
-
- $this->printHTMLHeader($this->getString(CAS_STR_AUTHENTICATION_FAILED));
- printf($this->getString(CAS_STR_YOU_WERE_NOT_AUTHENTICATED),htmlentities($this->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 ($this->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);
- }
- $this->printHTMLFooter();
- phpCAS::traceExit();
- exit();
- }
-
- /** @} */
-}
-
-?>
+++ /dev/null
-<?php
-/*
- Requires PHP5, uses built-in DOM extension.
- To be used in PHP4 scripts using DOMXML extension: allows PHP4/DOMXML scripts to run on PHP5/DOM.
- (Optional: requires PHP5/XSL extension for domxml_xslt functions, PHP>=5.1 for XPath evaluation functions, and PHP>=5.1/libxml for DOMXML error reports)
-
- Typical use:
- {
- if (PHP_VERSION>='5')
- require_once('domxml-php4-to-php5.php');
- }
-
- Version 1.21.1a, 2009-03-13, http://alexandre.alapetite.fr/doc-alex/domxml-php4-php5/
-
- ------------------------------------------------------------------
- Written by Alexandre Alapetite, http://alexandre.alapetite.fr/cv/
-
- Copyright 2004-2009, GNU Lesser General Public License,
- http://www.gnu.org/licenses/lgpl.html
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/lgpl.html>
-
- == Rights and obligations ==
- - Attribution: You must give the original author credit.
- - Share Alike: If you alter or transform this library,
- you may distribute the resulting library only under the same license GNU/LGPL.
- - In case of jurisdiction dispute, the French law is authoritative.
- - Any of these conditions can be waived if you get permission from Alexandre Alapetite.
- - Not required, but please send to Alexandre Alapetite the modifications you make,
- in order to improve this file for the benefit of everybody.
-
- If you want to distribute this code, please do it as a link to:
- http://alexandre.alapetite.fr/doc-alex/domxml-php4-php5/
-*/
-
-define('DOMXML_LOAD_PARSING',0);
-define('DOMXML_LOAD_VALIDATING',1);
-define('DOMXML_LOAD_RECOVERING',2);
-define('DOMXML_LOAD_SUBSTITUTE_ENTITIES',4);
-//define('DOMXML_LOAD_COMPLETE_ATTRS',8);
-define('DOMXML_LOAD_DONT_KEEP_BLANKS',16);
-
-function domxml_new_doc($version) {return new php4DOMDocument();}
-function domxml_new_xmldoc($version) {return new php4DOMDocument();}
-function domxml_open_file($filename,$mode=DOMXML_LOAD_PARSING,&$error=null)
-{
- $dom=new php4DOMDocument($mode);
- $errorMode=(func_num_args()>2)&&defined('LIBXML_VERSION');
- if ($errorMode) libxml_use_internal_errors(true);
- if (!$dom->myDOMNode->load($filename)) $dom=null;
- if ($errorMode)
- {
- $error=array_map('_error_report',libxml_get_errors());
- libxml_clear_errors();
- }
- return $dom;
-}
-function domxml_open_mem($str,$mode=DOMXML_LOAD_PARSING,&$error=null)
-{
- $dom=new php4DOMDocument($mode);
- $errorMode=(func_num_args()>2)&&defined('LIBXML_VERSION');
- if ($errorMode) libxml_use_internal_errors(true);
- if (!$dom->myDOMNode->loadXML($str)) $dom=null;
- if ($errorMode)
- {
- $error=array_map('_error_report',libxml_get_errors());
- libxml_clear_errors();
- }
- return $dom;
-}
-function html_doc($html_doc,$from_file=false)
-{
- $dom=new php4DOMDocument();
- if ($from_file) $result=$dom->myDOMNode->loadHTMLFile($html_doc);
- else $result=$dom->myDOMNode->loadHTML($html_doc);
- return $result ? $dom : null;
-}
-function html_doc_file($filename) {return html_doc($filename,true);}
-function xmldoc($str) {return domxml_open_mem($str);}
-function xmldocfile($filename) {return domxml_open_file($filename);}
-function xpath_eval($xpath_context,$eval_str,$contextnode=null) {return $xpath_context->xpath_eval($eval_str,$contextnode);}
-function xpath_new_context($dom_document) {return new php4DOMXPath($dom_document);}
-function xpath_register_ns($xpath_context,$prefix,$namespaceURI) {return $xpath_context->myDOMXPath->registerNamespace($prefix,$namespaceURI);}
-function _entityDecode($text) {return html_entity_decode(strtr($text,array('''=>'\'')),ENT_QUOTES,'UTF-8');}
-function _error_report($error) {return array('errormessage'=>$error->message,'nodename'=>'','line'=>$error->line,'col'=>$error->column)+($error->file==''?array():array('directory'=>dirname($error->file),'file'=>basename($error->file)));}
-
-class php4DOMAttr extends php4DOMNode
-{
- function __get($name)
- {
- if ($name==='name') return $this->myDOMNode->name;
- else return parent::__get($name);
- }
- function name() {return $this->myDOMNode->name;}
- function set_content($text) {}
- //function set_value($content) {return $this->myDOMNode->value=htmlspecialchars($content,ENT_QUOTES);}
- function specified() {return $this->myDOMNode->specified;}
- function value() {return $this->myDOMNode->value;}
-}
-
-class php4DOMDocument extends php4DOMNode
-{
- function php4DOMDocument($mode=DOMXML_LOAD_PARSING)
- {
- $this->myDOMNode=new DOMDocument();
- $this->myOwnerDocument=$this;
- if ($mode & DOMXML_LOAD_VALIDATING) $this->myDOMNode->validateOnParse=true;
- if ($mode & DOMXML_LOAD_RECOVERING) $this->myDOMNode->recover=true;
- if ($mode & DOMXML_LOAD_SUBSTITUTE_ENTITIES) $this->myDOMNode->substituteEntities=true;
- if ($mode & DOMXML_LOAD_DONT_KEEP_BLANKS) $this->myDOMNode->preserveWhiteSpace=false;
- }
- function add_root($name)
- {
- if ($this->myDOMNode->hasChildNodes()) $this->myDOMNode->removeChild($this->myDOMNode->firstChild);
- return new php4DOMElement($this->myDOMNode->appendChild($this->myDOMNode->createElement($name)),$this->myOwnerDocument);
- }
- function create_attribute($name,$value)
- {
- $myAttr=$this->myDOMNode->createAttribute($name);
- $myAttr->value=htmlspecialchars($value,ENT_QUOTES);
- return new php4DOMAttr($myAttr,$this);
- }
- function create_cdata_section($content) {return new php4DOMNode($this->myDOMNode->createCDATASection($content),$this);}
- function create_comment($data) {return new php4DOMNode($this->myDOMNode->createComment($data),$this);}
- function create_element($name) {return new php4DOMElement($this->myDOMNode->createElement($name),$this);}
- function create_element_ns($uri,$name,$prefix=null)
- {
- if ($prefix==null) $prefix=$this->myDOMNode->lookupPrefix($uri);
- if (($prefix==null)&&(($this->myDOMNode->documentElement==null)||(!$this->myDOMNode->documentElement->isDefaultNamespace($uri)))) $prefix='a'.sprintf('%u',crc32($uri));
- return new php4DOMElement($this->myDOMNode->createElementNS($uri,$prefix==null ? $name : $prefix.':'.$name),$this);
- }
- function create_entity_reference($content) {return new php4DOMNode($this->myDOMNode->createEntityReference($content),$this);} //By Walter Ebert 2007-01-22
- function create_processing_instruction($target,$data=''){return new php4DomProcessingInstruction($this->myDOMNode->createProcessingInstruction($target,$data),$this);}
- function create_text_node($content) {return new php4DOMText($this->myDOMNode->createTextNode($content),$this);}
- function document_element() {return parent::_newDOMElement($this->myDOMNode->documentElement,$this);}
- function dump_file($filename,$compressionmode=false,$format=false)
- {
- $format0=$this->myDOMNode->formatOutput;
- $this->myDOMNode->formatOutput=$format;
- $res=$this->myDOMNode->save($filename);
- $this->myDOMNode->formatOutput=$format0;
- return $res;
- }
- function dump_mem($format=false,$encoding=false)
- {
- $format0=$this->myDOMNode->formatOutput;
- $this->myDOMNode->formatOutput=$format;
- $encoding0=$this->myDOMNode->encoding;
- if ($encoding) $this->myDOMNode->encoding=$encoding;
- $dump=$this->myDOMNode->saveXML();
- $this->myDOMNode->formatOutput=$format0;
- if ($encoding) $this->myDOMNode->encoding= $encoding0=='' ? 'UTF-8' : $encoding0; //UTF-8 is XML default encoding
- return $dump;
- }
- function free()
- {
- if ($this->myDOMNode->hasChildNodes()) $this->myDOMNode->removeChild($this->myDOMNode->firstChild);
- $this->myDOMNode=null;
- $this->myOwnerDocument=null;
- }
- function get_element_by_id($id) {return parent::_newDOMElement($this->myDOMNode->getElementById($id),$this);}
- function get_elements_by_tagname($name)
- {
- $myDOMNodeList=$this->myDOMNode->getElementsByTagName($name);
- $nodeSet=array();
- $i=0;
- if (isset($myDOMNodeList))
- while ($node=$myDOMNodeList->item($i++)) $nodeSet[]=new php4DOMElement($node,$this);
- return $nodeSet;
- }
- function html_dump_mem() {return $this->myDOMNode->saveHTML();}
- function root() {return parent::_newDOMElement($this->myDOMNode->documentElement,$this);}
- function xinclude() {return $this->myDOMNode->xinclude();}
- function xpath_new_context() {return new php4DOMXPath($this);}
-}
-
-class php4DOMElement extends php4DOMNode
-{
- function add_namespace($uri,$prefix)
- {
- if ($this->myDOMNode->hasAttributeNS('http://www.w3.org/2000/xmlns/',$prefix)) return false;
- else
- {
- $this->myDOMNode->setAttributeNS('http://www.w3.org/2000/xmlns/','xmlns:'.$prefix,$uri); //By Daniel Walker 2006-09-08
- return true;
- }
- }
- function get_attribute($name) {return $this->myDOMNode->getAttribute($name);}
- function get_attribute_node($name) {return parent::_newDOMElement($this->myDOMNode->getAttributeNode($name),$this->myOwnerDocument);}
- function get_elements_by_tagname($name)
- {
- $myDOMNodeList=$this->myDOMNode->getElementsByTagName($name);
- $nodeSet=array();
- $i=0;
- if (isset($myDOMNodeList))
- while ($node=$myDOMNodeList->item($i++)) $nodeSet[]=new php4DOMElement($node,$this->myOwnerDocument);
- return $nodeSet;
- }
- function has_attribute($name) {return $this->myDOMNode->hasAttribute($name);}
- function remove_attribute($name) {return $this->myDOMNode->removeAttribute($name);}
- function set_attribute($name,$value)
- {
- //return $this->myDOMNode->setAttribute($name,$value); //Does not return a DomAttr
- $myAttr=$this->myDOMNode->ownerDocument->createAttribute($name);
- $myAttr->value=htmlspecialchars($value,ENT_QUOTES); //Entity problem reported by AL-DesignWorks 2007-09-07
- $this->myDOMNode->setAttributeNode($myAttr);
- return new php4DOMAttr($myAttr,$this->myOwnerDocument);
- }
- /*function set_attribute_node($attr)
- {
- $this->myDOMNode->setAttributeNode($this->_importNode($attr));
- return $attr;
- }*/
- function set_name($name)
- {
- if ($this->myDOMNode->prefix=='') $newNode=$this->myDOMNode->ownerDocument->createElement($name);
- else $newNode=$this->myDOMNode->ownerDocument->createElementNS($this->myDOMNode->namespaceURI,$this->myDOMNode->prefix.':'.$name);
- $myDOMNodeList=$this->myDOMNode->attributes;
- $i=0;
- if (isset($myDOMNodeList))
- while ($node=$myDOMNodeList->item($i++))
- if ($node->namespaceURI=='') $newNode->setAttribute($node->name,$node->value);
- else $newNode->setAttributeNS($node->namespaceURI,$node->nodeName,$node->value);
- $myDOMNodeList=$this->myDOMNode->childNodes;
- if (isset($myDOMNodeList))
- while ($node=$myDOMNodeList->item(0)) $newNode->appendChild($node);
- $this->myDOMNode->parentNode->replaceChild($newNode,$this->myDOMNode);
- $this->myDOMNode=$newNode;
- return true;
- }
- function tagname() {return $this->tagname;}
-}
-
-class php4DOMNode
-{
- public $myDOMNode;
- public $myOwnerDocument;
- function php4DOMNode($aDomNode,$aOwnerDocument)
- {
- $this->myDOMNode=$aDomNode;
- $this->myOwnerDocument=$aOwnerDocument;
- }
- function __get($name)
- {
- switch ($name)
- {
- case 'type': return $this->myDOMNode->nodeType;
- case 'tagname': return ($this->myDOMNode->nodeType===XML_ELEMENT_NODE) ? $this->myDOMNode->localName : $this->myDOMNode->tagName; //Avoid namespace prefix for DOMElement
- case 'content': return $this->myDOMNode->textContent;
- case 'value': return $this->myDOMNode->value;
- default:
- $myErrors=debug_backtrace();
- trigger_error('Undefined property: '.get_class($this).'::$'.$name.' ['.$myErrors[0]['file'].':'.$myErrors[0]['line'].']',E_USER_NOTICE);
- return false;
- }
- }
- function add_child($newnode) {return $this->append_child($newnode);}
- function add_namespace($uri,$prefix) {return false;}
- function append_child($newnode) {return self::_newDOMElement($this->myDOMNode->appendChild($this->_importNode($newnode)),$this->myOwnerDocument);}
- function append_sibling($newnode) {return self::_newDOMElement($this->myDOMNode->parentNode->appendChild($this->_importNode($newnode)),$this->myOwnerDocument);}
- function attributes()
- {
- $myDOMNodeList=$this->myDOMNode->attributes;
- if (!(isset($myDOMNodeList)&&$this->myDOMNode->hasAttributes())) return null;
- $nodeSet=array();
- $i=0;
- while ($node=$myDOMNodeList->item($i++)) $nodeSet[]=new php4DOMAttr($node,$this->myOwnerDocument);
- return $nodeSet;
- }
- function child_nodes()
- {
- $myDOMNodeList=$this->myDOMNode->childNodes;
- $nodeSet=array();
- $i=0;
- if (isset($myDOMNodeList))
- while ($node=$myDOMNodeList->item($i++)) $nodeSet[]=self::_newDOMElement($node,$this->myOwnerDocument);
- return $nodeSet;
- }
- function children() {return $this->child_nodes();}
- function clone_node($deep=false) {return self::_newDOMElement($this->myDOMNode->cloneNode($deep),$this->myOwnerDocument);}
- //dump_node($node) should only be called on php4DOMDocument
- function dump_node($node=null) {return $node==null ? $this->myOwnerDocument->myDOMNode->saveXML($this->myDOMNode) : $this->myOwnerDocument->myDOMNode->saveXML($node->myDOMNode);}
- function first_child() {return self::_newDOMElement($this->myDOMNode->firstChild,$this->myOwnerDocument);}
- function get_content() {return $this->myDOMNode->textContent;}
- function has_attributes() {return $this->myDOMNode->hasAttributes();}
- function has_child_nodes() {return $this->myDOMNode->hasChildNodes();}
- function insert_before($newnode,$refnode) {return self::_newDOMElement($this->myDOMNode->insertBefore($this->_importNode($newnode),$refnode==null?null:$refnode->myDOMNode),$this->myOwnerDocument);}
- function is_blank_node() {return ($this->myDOMNode->nodeType===XML_TEXT_NODE)&&preg_match('%^\s*$%',$this->myDOMNode->nodeValue);}
- function last_child() {return self::_newDOMElement($this->myDOMNode->lastChild,$this->myOwnerDocument);}
- function new_child($name,$content)
- {
- $mySubNode=$this->myDOMNode->ownerDocument->createElement($name);
- $mySubNode->appendChild($this->myDOMNode->ownerDocument->createTextNode(_entityDecode($content)));
- $this->myDOMNode->appendChild($mySubNode);
- return new php4DOMElement($mySubNode,$this->myOwnerDocument);
- }
- function next_sibling() {return self::_newDOMElement($this->myDOMNode->nextSibling,$this->myOwnerDocument);}
- function node_name() {return ($this->myDOMNode->nodeType===XML_ELEMENT_NODE) ? $this->myDOMNode->localName : $this->myDOMNode->nodeName;} //Avoid namespace prefix for DOMElement
- function node_type() {return $this->myDOMNode->nodeType;}
- function node_value() {return $this->myDOMNode->nodeValue;}
- function owner_document() {return $this->myOwnerDocument;}
- function parent_node() {return self::_newDOMElement($this->myDOMNode->parentNode,$this->myOwnerDocument);}
- function prefix() {return $this->myDOMNode->prefix;}
- function previous_sibling() {return self::_newDOMElement($this->myDOMNode->previousSibling,$this->myOwnerDocument);}
- function remove_child($oldchild) {return self::_newDOMElement($this->myDOMNode->removeChild($oldchild->myDOMNode),$this->myOwnerDocument);}
- function replace_child($newnode,$oldnode) {return self::_newDOMElement($this->myDOMNode->replaceChild($this->_importNode($newnode),$oldnode->myDOMNode),$this->myOwnerDocument);}
- function replace_node($newnode) {return self::_newDOMElement($this->myDOMNode->parentNode->replaceChild($this->_importNode($newnode),$this->myDOMNode),$this->myOwnerDocument);}
- function set_content($text) {return $this->myDOMNode->appendChild($this->myDOMNode->ownerDocument->createTextNode(_entityDecode($text)));} //Entity problem reported by AL-DesignWorks 2007-09-07
- //function set_name($name) {return $this->myOwnerDocument->renameNode($this->myDOMNode,$this->myDOMNode->namespaceURI,$name);}
- function set_namespace($uri,$prefix=null)
- {//Contributions by Daniel Walker 2006-09-08
- $nsprefix=$this->myDOMNode->lookupPrefix($uri);
- if ($nsprefix==null)
- {
- $nsprefix= $prefix==null ? $nsprefix='a'.sprintf('%u',crc32($uri)) : $prefix;
- if ($this->myDOMNode->nodeType===XML_ATTRIBUTE_NODE)
- {
- if (($prefix!=null)&&$this->myDOMNode->ownerElement->hasAttributeNS('http://www.w3.org/2000/xmlns/',$nsprefix)&&
- ($this->myDOMNode->ownerElement->getAttributeNS('http://www.w3.org/2000/xmlns/',$nsprefix)!=$uri))
- {//Remove namespace
- $parent=$this->myDOMNode->ownerElement;
- $parent->removeAttributeNode($this->myDOMNode);
- $parent->setAttribute($this->myDOMNode->localName,$this->myDOMNode->nodeValue);
- $this->myDOMNode=$parent->getAttributeNode($this->myDOMNode->localName);
- return;
- }
- $this->myDOMNode->ownerElement->setAttributeNS('http://www.w3.org/2000/xmlns/','xmlns:'.$nsprefix,$uri);
- }
- }
- if ($this->myDOMNode->nodeType===XML_ATTRIBUTE_NODE)
- {
- $parent=$this->myDOMNode->ownerElement;
- $parent->removeAttributeNode($this->myDOMNode);
- $parent->setAttributeNS($uri,$nsprefix.':'.$this->myDOMNode->localName,$this->myDOMNode->nodeValue);
- $this->myDOMNode=$parent->getAttributeNodeNS($uri,$this->myDOMNode->localName);
- }
- elseif ($this->myDOMNode->nodeType===XML_ELEMENT_NODE)
- {
- $NewNode=$this->myDOMNode->ownerDocument->createElementNS($uri,$nsprefix.':'.$this->myDOMNode->localName);
- foreach ($this->myDOMNode->attributes as $n) $NewNode->appendChild($n->cloneNode(true));
- foreach ($this->myDOMNode->childNodes as $n) $NewNode->appendChild($n->cloneNode(true));
- $xpath=new DOMXPath($this->myDOMNode->ownerDocument);
- $myDOMNodeList=$xpath->query('namespace::*[name()!="xml"]',$this->myDOMNode); //Add old namespaces
- foreach ($myDOMNodeList as $n) $NewNode->setAttributeNS('http://www.w3.org/2000/xmlns/',$n->nodeName,$n->nodeValue);
- $this->myDOMNode->parentNode->replaceChild($NewNode,$this->myDOMNode);
- $this->myDOMNode=$NewNode;
- }
- }
- function unlink_node()
- {
- if ($this->myDOMNode->parentNode!=null)
- {
- if ($this->myDOMNode->nodeType===XML_ATTRIBUTE_NODE) $this->myDOMNode->parentNode->removeAttributeNode($this->myDOMNode);
- else $this->myDOMNode->parentNode->removeChild($this->myDOMNode);
- }
- }
- protected function _importNode($newnode) {return $this->myOwnerDocument===$newnode->myOwnerDocument ? $newnode->myDOMNode : $this->myOwnerDocument->myDOMNode->importNode($newnode->myDOMNode,true);} //To import DOMNode from another DOMDocument
- static function _newDOMElement($aDOMNode,$aOwnerDocument)
- {//Check the PHP5 DOMNode before creating a new associated PHP4 DOMNode wrapper
- if ($aDOMNode==null) return null;
- switch ($aDOMNode->nodeType)
- {
- case XML_ELEMENT_NODE: return new php4DOMElement($aDOMNode,$aOwnerDocument);
- case XML_TEXT_NODE: return new php4DOMText($aDOMNode,$aOwnerDocument);
- case XML_ATTRIBUTE_NODE: return new php4DOMAttr($aDOMNode,$aOwnerDocument);
- case XML_PI_NODE: return new php4DomProcessingInstruction($aDOMNode,$aOwnerDocument);
- default: return new php4DOMNode($aDOMNode,$aOwnerDocument);
- }
- }
-}
-
-class php4DomProcessingInstruction extends php4DOMNode
-{
- function data() {return $this->myDOMNode->data;}
- function target() {return $this->myDOMNode->target;}
-}
-
-class php4DOMText extends php4DOMNode
-{
- function __get($name)
- {
- if ($name==='tagname') return '#text';
- else return parent::__get($name);
- }
- function tagname() {return '#text';}
- function set_content($text) {$this->myDOMNode->nodeValue=$text; return true;}
-}
-
-if (!defined('XPATH_NODESET'))
-{
- define('XPATH_UNDEFINED',0);
- define('XPATH_NODESET',1);
- define('XPATH_BOOLEAN',2);
- define('XPATH_NUMBER',3);
- define('XPATH_STRING',4);
- /*define('XPATH_POINT',5);
- define('XPATH_RANGE',6);
- define('XPATH_LOCATIONSET',7);
- define('XPATH_USERS',8);
- define('XPATH_XSLT_TREE',9);*/
-}
-
-class php4DOMNodelist
-{
- private $myDOMNodelist;
- public $nodeset;
- public $type=XPATH_UNDEFINED;
- public $value;
- function php4DOMNodelist($aDOMNodelist,$aOwnerDocument)
- {
- if (!isset($aDOMNodelist)) return;
- elseif (is_object($aDOMNodelist)||is_array($aDOMNodelist))
- {
- if ($aDOMNodelist->length>0)
- {
- $this->myDOMNodelist=$aDOMNodelist;
- $this->nodeset=array();
- $this->type=XPATH_NODESET;
- $i=0;
- while ($node=$this->myDOMNodelist->item($i++)) $this->nodeset[]=php4DOMNode::_newDOMElement($node,$aOwnerDocument);
- }
- }
- elseif (is_int($aDOMNodelist)||is_float($aDOMNodelist))
- {
- $this->type=XPATH_NUMBER;
- $this->value=$aDOMNodelist;
- }
- elseif (is_bool($aDOMNodelist))
- {
- $this->type=XPATH_BOOLEAN;
- $this->value=$aDOMNodelist;
- }
- elseif (is_string($aDOMNodelist))
- {
- $this->type=XPATH_STRING;
- $this->value=$aDOMNodelist;
- }
- }
-}
-
-class php4DOMXPath
-{
- public $myDOMXPath;
- private $myOwnerDocument;
- function php4DOMXPath($dom_document)
- {
- //TODO: If $dom_document is a DomElement, make that default $contextnode and modify XPath. Ex: '/test'
- $this->myOwnerDocument=$dom_document->myOwnerDocument;
- $this->myDOMXPath=new DOMXPath($this->myOwnerDocument->myDOMNode);
- }
- function xpath_eval($eval_str,$contextnode=null)
- {
- if (method_exists($this->myDOMXPath,'evaluate')) $xp=isset($contextnode->myDOMNode) ? $this->myDOMXPath->evaluate($eval_str,$contextnode->myDOMNode) : $this->myDOMXPath->evaluate($eval_str);
- else $xp=isset($contextnode->myDOMNode) ? $this->myDOMXPath->query($eval_str,$contextnode->myDOMNode) : $this->myDOMXPath->query($eval_str);
- $xp=new php4DOMNodelist($xp,$this->myOwnerDocument);
- return ($xp->type===XPATH_UNDEFINED) ? false : $xp;
- }
- function xpath_register_ns($prefix,$namespaceURI) {return $this->myDOMXPath->registerNamespace($prefix,$namespaceURI);}
-}
-
-if (extension_loaded('xsl'))
-{//See also: http://alexandre.alapetite.fr/doc-alex/xslt-php4-php5/
- function domxml_xslt_stylesheet($xslstring) {return new php4DomXsltStylesheet(DOMDocument::loadXML($xslstring));}
- function domxml_xslt_stylesheet_doc($dom_document) {return new php4DomXsltStylesheet($dom_document);}
- function domxml_xslt_stylesheet_file($xslfile) {return new php4DomXsltStylesheet(DOMDocument::load($xslfile));}
- class php4DomXsltStylesheet
- {
- private $myxsltProcessor;
- function php4DomXsltStylesheet($dom_document)
- {
- $this->myxsltProcessor=new xsltProcessor();
- $this->myxsltProcessor->importStyleSheet($dom_document);
- }
- function process($dom_document,$xslt_parameters=array(),$param_is_xpath=false)
- {
- foreach ($xslt_parameters as $param=>$value) $this->myxsltProcessor->setParameter('',$param,$value);
- $myphp4DOMDocument=new php4DOMDocument();
- $myphp4DOMDocument->myDOMNode=$this->myxsltProcessor->transformToDoc($dom_document->myDOMNode);
- return $myphp4DOMDocument;
- }
- function result_dump_file($dom_document,$filename)
- {
- $html=$dom_document->myDOMNode->saveHTML();
- file_put_contents($filename,$html);
- return $html;
- }
- function result_dump_mem($dom_document) {return $dom_document->myDOMNode->saveHTML();}
- }
-}
-?>
+++ /dev/null
-<?php\r
-\r
-/**\r
- * @file languages/spanish.php\r
- * @author Iván-Benjamín García Torà <ivaniclixx AT gmail DOT com>\r
- * @sa @link internalLang Internationalization @endlink\r
- * @ingroup internalLang\r
- */\r
-\r
-$this->_strings = array(\r
- CAS_STR_USING_SERVER \r
- => 'usant servidor',\r
- CAS_STR_AUTHENTICATION_WANTED \r
- => 'Autentificació CAS necessària!',\r
- CAS_STR_LOGOUT \r
- => 'Sortida de CAS necessària!',\r
- CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED \r
- => 'Ja hauria d\ haver estat redireccionat al servidor CAS. Feu click <a href="%s">aquí</a> per a continuar.',\r
- CAS_STR_AUTHENTICATION_FAILED \r
- => 'Autentificació CAS fallida!',\r
- CAS_STR_YOU_WERE_NOT_AUTHENTICATED \r
- => '<p>No estàs autentificat.</p><p>Pots tornar a intentar-ho fent click <a href="%s">aquí</a>.</p><p>Si el problema persisteix hauría de contactar amb l\'<a href="mailto:%s">administrador d\'aquest llocc</a>.</p>',\r
- CAS_STR_SERVICE_UNAVAILABLE\r
- => 'El servei `<b>%s</b>\' no està disponible (<b>%s</b>).'\r
-);\r
-\r
-?>\r
+++ /dev/null
-<?php\r
-\r
-/**\r
- * @file languages/english.php\r
- * @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>\r
- * @sa @link internalLang Internationalization @endlink\r
- * @ingroup internalLang\r
- */\r
-\r
-$this->_strings = array(\r
- CAS_STR_USING_SERVER \r
- => 'using server',\r
- CAS_STR_AUTHENTICATION_WANTED \r
- => 'CAS Authentication wanted!',\r
- CAS_STR_LOGOUT \r
- => 'CAS logout wanted!',\r
- CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED \r
- => 'You should already have been redirected to the CAS server. Click <a href="%s">here</a> to continue.',\r
- CAS_STR_AUTHENTICATION_FAILED \r
- => 'CAS Authentication failed!',\r
- CAS_STR_YOU_WERE_NOT_AUTHENTICATED \r
- => '<p>You were not authenticated.</p><p>You may submit your request again by clicking <a href="%s">here</a>.</p><p>If the problem persists, you may contact <a href="mailto:%s">the administrator of this site</a>.</p>',\r
- CAS_STR_SERVICE_UNAVAILABLE\r
- => 'The service `<b>%s</b>\' is not available (<b>%s</b>).'\r
-);\r
-\r
-?>
\ No newline at end of file
+++ /dev/null
-<?php\r
-\r
-/**\r
- * @file languages/english.php\r
- * @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>\r
- * @sa @link internalLang Internationalization @endlink\r
- * @ingroup internalLang\r
- */\r
-\r
-$this->_strings = array(\r
- CAS_STR_USING_SERVER \r
- => 'utilisant le serveur',\r
- CAS_STR_AUTHENTICATION_WANTED \r
- => 'Authentication CAS n�cessaire !',\r
- CAS_STR_LOGOUT \r
- => 'D�connexion demand�e !',\r
- CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED \r
- => 'Vous auriez du etre redirig�(e) vers le serveur CAS. Cliquez <a href="%s">ici</a> pour continuer.',\r
- CAS_STR_AUTHENTICATION_FAILED \r
- => 'Authentification CAS infructueuse !',\r
- CAS_STR_YOU_WERE_NOT_AUTHENTICATED \r
- => '<p>Vous n\'avez pas �t� authentifi�(e).</p><p>Vous pouvez soumettre votre requete � nouveau en cliquant <a href="%s">ici</a>.</p><p>Si le probl�me persiste, vous pouvez contacter <a href="mailto:%s">l\'administrateur de ce site</a>.</p>',\r
- CAS_STR_SERVICE_UNAVAILABLE\r
- => 'Le service `<b>%s</b>\' est indisponible (<b>%s</b>)'\r
-\r
-);\r
-\r
-?>
\ No newline at end of file
+++ /dev/null
-<?php\r
-\r
-/**\r
- * @file languages/german.php\r
- * @author Henrik Genssen <hg at mediafactory.de>\r
- * @sa @link internalLang Internationalization @endlink\r
- * @ingroup internalLang\r
- */\r
-\r
-$this->_strings = array(\r
- CAS_STR_USING_SERVER \r
- => 'via Server',\r
- CAS_STR_AUTHENTICATION_WANTED \r
- => 'CAS Authentifizierung erforderlich!',\r
- CAS_STR_LOGOUT \r
- => 'CAS Abmeldung!',\r
- CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED \r
- => 'eigentlich häten Sie zum CAS Server weitergeleitet werden sollen. Drücken Sie <a href="%s">hier</a> um fortzufahren.',\r
- CAS_STR_AUTHENTICATION_FAILED \r
- => 'CAS Anmeldung fehlgeschlagen!',\r
- CAS_STR_YOU_WERE_NOT_AUTHENTICATED \r
- => '<p>Sie wurden nicht angemeldet.</p><p>Um es erneut zu versuchen klicken Sie <a href="%s">hier</a>.</p><p>Wenn das Problem bestehen bleibt, kontkatieren Sie den <a href="mailto:%s">Administrator</a> dieser Seite.</p>',\r
- CAS_STR_SERVICE_UNAVAILABLE\r
- => 'Der Dienst `<b>%s</b>\' ist nicht verfügbar (<b>%s</b>).'\r
-);\r
-\r
-?>
\ No newline at end of file
+++ /dev/null
-<?php\r
-\r
-/**\r
- * @file languages/greek.php\r
- * @author Vangelis Haniotakis <haniotak at ucnet.uoc.gr>\r
- * @sa @link internalLang Internationalization @endlink\r
- * @ingroup internalLang\r
- */\r
-\r
-$this->_strings = array(\r
- CAS_STR_USING_SERVER \r
- => '��������������� � ������������',\r
- CAS_STR_AUTHENTICATION_WANTED \r
- => '���������� � ����������� CAS!',\r
- CAS_STR_LOGOUT \r
- => '���������� � ���������� ��� CAS!',\r
- CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED \r
- => '�� ������ �� ������ �������������� ���� ����������� CAS. ����� ���� <a href="%s">���</a> ��� �� ����������.',\r
- CAS_STR_AUTHENTICATION_FAILED \r
- => '� ����������� CAS �������!',\r
- CAS_STR_YOU_WERE_NOT_AUTHENTICATED \r
- => '<p>��� ���������������.</p><p>�������� �� ����������������, �������� ���� <a href="%s">���</a>.</p><p>��� �� �������� ���������, ����� �� ����� �� ��� <a href="mailto:%s">�����������</a>.</p>',\r
- CAS_STR_SERVICE_UNAVAILABLE\r
- => '� �������� `<b>%s</b>\' ��� ����� ��������� (<b>%s</b>).'\r
-);\r
-\r
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-
-/**
- * @file languages/japanese.php
- * @author fnorif (fnorif@yahoo.co.jp)
- *
- * Now Encoding is EUC-JP and LF
- **/
-
-$this->_strings = array(
- CAS_STR_USING_SERVER
- => 'using server',
- CAS_STR_AUTHENTICATION_WANTED
- => 'CAS�ˤ��ǧ�ڤ�Ԥ��ޤ�',
- CAS_STR_LOGOUT
- => 'CAS����?�����Ȥ��ޤ�!',
- CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED
- => 'CAS�����Ф˹Ԥ�ɬ�פ�����ޤ�����ưŪ��ž������ʤ����� <a href="%s">������</a> ��å�����³�Ԥ��ޤ���',
- CAS_STR_AUTHENTICATION_FAILED
- => 'CAS�ˤ��ǧ�ڤ˼��Ԥ��ޤ���',
- CAS_STR_YOU_WERE_NOT_AUTHENTICATED
- => '<p>ǧ�ڤǤ��ޤ���Ǥ���.</p><p>�⤦���٥ꥯ�����Ȥ������������<a href="%s">������</a>��å�.</p><p>���꤬��褷�ʤ����� <a href="mailto:%s">���Υ����Ȥδ����</a>���䤤��碌�Ƥ�������.</p>',
- CAS_STR_SERVICE_UNAVAILABLE
- => '�����ӥ� `<b>%s</b>\' �����ѤǤ��ޤ��� (<b>%s</b>).'
-);
-
-?>
\ No newline at end of file
+++ /dev/null
-<?php\r
-\r
-/**\r
- * @file languages/languages.php\r
- * Internationalization constants\r
- * @author Pascal Aubry <pascal.aubry at univ-rennes1.fr>\r
- * @sa @link internalLang Internationalization @endlink\r
- * @ingroup internalLang\r
- */\r
-\r
-//@{\r
-/**\r
- * a phpCAS string index\r
- */\r
-define("CAS_STR_USING_SERVER", 1);\r
-define("CAS_STR_AUTHENTICATION_WANTED", 2);\r
-define("CAS_STR_LOGOUT", 3);\r
-define("CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED", 4);\r
-define("CAS_STR_AUTHENTICATION_FAILED", 5);\r
-define("CAS_STR_YOU_WERE_NOT_AUTHENTICATED", 6);\r
-define("CAS_STR_SERVICE_UNAVAILABLE", 7);\r
-//@}\r
-\r
-?>
\ No newline at end of file
+++ /dev/null
-<?php\r
-\r
-/**\r
- * @file languages/spanish.php\r
- * @author Iván-Benjamín García Torà <ivaniclixx AT gmail DOT com>\r
- * @sa @link internalLang Internationalization @endlink\r
- * @ingroup internalLang\r
- */\r
-\r
-$this->_strings = array(\r
- CAS_STR_USING_SERVER \r
- => 'usando servidor',\r
- CAS_STR_AUTHENTICATION_WANTED \r
- => '¡Autentificación CAS necesaria!',\r
- CAS_STR_LOGOUT \r
- => '¡Salida CAS necesaria!',\r
- CAS_STR_SHOULD_HAVE_BEEN_REDIRECTED \r
- => 'Ya debería haber sido redireccionado al servidor CAS. Haga click <a href="%s">aquí</a> para continuar.',\r
- CAS_STR_AUTHENTICATION_FAILED \r
- => '¡Autentificación CAS fallida!',\r
- CAS_STR_YOU_WERE_NOT_AUTHENTICATED \r
- => '<p>No estás autentificado.</p><p>Puedes volver a intentarlo haciendo click <a href="%s">aquí</a>.</p><p>Si el problema persiste debería contactar con el <a href="mailto:%s">administrador de este sitio</a>.</p>',\r
- CAS_STR_SERVICE_UNAVAILABLE\r
- => 'El servicio `<b>%s</b>\' no está disponible (<b>%s</b>).'\r
-);\r
-\r
-?>\r
--- /dev/null
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed 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.
--- /dev/null
+Copyright 2007-2011, JA-SIG, Inc.
+This project includes software developed by Jasig.
+http://www.jasig.org/
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this software 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.
+
+===========================================================================
+
+Copyright © 2003-2007, The ESUP-Portail consortium
+
+Requirements for sources originally licensed under the New BSD License:
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+- Neither the name of JA-SIG, Inc. nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+===========================================================================
+
+Copyright (c) 2009, Regents of the University of Nebraska
+All rights reserved.
+
+Requirements for CAS_Autloader originally licensed under the New BSD License:
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of the University of Nebraska nor the names of its contributors
+may be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
--- /dev/null
+phpCAS
+=======
+
+phpCAS is an authentication library that allows PHP applications to easily authenticate
+users via a Central Authentication Service (CAS) server.
+
+Please see the phpCAS website for more information:
+
+https://wiki.jasig.org/display/CASC/phpCAS
+
+LICENSE
+-------
+
+Copyright 2007-2011, JA-SIG, Inc.
+This project includes software developed by Jasig.
+http://www.jasig.org/
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this software 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.
--- /dev/null
+########################################
+### Build process for phpCAS package ###
+########################################
+
+1. Prepare your own build config:
+
+go to the utils/ dir and copy build-example.properties to a
+build.properties file and adjust the path for all needed binaries. You need
+at least php and doxygen for package creation. Git is needed as a developer with
+commit priviledges and upload right for the distribution package.
+
+2. Install necessary php packages:
+
+Install the pear package PEAR_PackageFileManager2 via the command
+
+"pear install PEAR_PackageFileManager2"
+
+
+3. Run the "ant" tasks to build the phpCAS package and other developer tasks:
+
+ant dist # create a local package
+ant clean # clear local packages and temporary files
+ant prepare # The default action, tags, packages, and commits to the local git repository
+ant push # Push the new commits and tags to the origin repository (github)
+ant upload # Upload to jasig
+ant makeCurrentSymlink # Set the symbolic link on the jasig site for the most current packages
+ant revert # To revert any "ant prepare" actions before they are pushed to the github repo
+
+The ant prepare target is equivalent to ant tag && ant dist && ant markdev.
+
+To revert the commits and tag additions added in the ant tag and ant markdev
+targets, use the new ant revert target. This should not be done after pushing.
+Running ant prepare is safe and can be followed by ant revert to get rid of the
+added commits and tag in your local repository.
\ No newline at end of file
--- /dev/null
+Changes in version 1.3.2
+Security Fixes:
+ * CVE-2012-5583 Missing CN validation of CAS server certificate [#58] (Joachim Fritschi)
+
+Bug Fixes:
+ * Fix broken character encoding in Greek and French [#40] (Joachim Fritschi)
+ * Minor error corrections in a few example files [] (Joachim Fritschi)
+ * Remove erroneous break statement [#44] (jbittel)
+ * Use X-Forwarded-Port [#45] (Andrew Kirkpatrick)
+ * Stop autoloader using set_include_path [#51/#52] (drysdaleb)
+ * Fix undefined property in the rebroadcast code [#47] (Joachim Fritschi)
+
+Improvement:
+ * Enable getCookies on a proxied sevices [#56] (Adam Franco)
+
+Changes in version 1.3.1
+Bug Fixes:
+ * Readd PEAR support to the package [#30] (Joachim Fritschi)
+ * fix a __autoload conflicts in the autoloader [#36] (Joachim Fritschi)
+ * fix PEAR code style errors [25] (Joachim Fritschi)
+ * properly unset variables during checkAuthenticate[#35] (Joachim Fritschi)
+
+Changes in version 1.3.0
+Improvements:
+ * enable single sign-out when session has already started [#29] (Benvii)
+
+Changes in version 1.3.0RC1
+
+Bug Fixes:
+ * the saml logout url should be parsed urlencoded [#24] (dlineate)
+ * fix a proxy mode bug introduced in a previous comitt [#16] (Adam Franco)
+ * Fix include_path order so that the phpCAS path takes precedence [#13] (Adam Franco)
+ * fix invalid characters in the php session naming [#17] (Joachim Fritschi)
+ * fix an initialisation problem introduced in the PGT storage [18] (Daniel Frett)
+ * make sure the PGTStorage object is initialized if a user is utilizing the createTable method [#4] (Daniel Frett)
+ * Fix error message in phpCAS::setCacheTimesForAuthRecheck() [PHPCAS-132/#1] (Bradley Froehle)
+ * Always return attributes in utf8 [PHPCAS-102]
+ * Fix warning during debugging if debug is set to false [PHPCAS-123] (Sean Watkins)
+
+New Features:
+ * Add a script to create the PGT db table in proxy mode [#11] (Joachim Fritschi)
+ * Switch to the Apache License [#5] (Adam Franco, Joachim Fritschi)
+ * Move to github and add all necessary file to package [#12] (Adam Franco)
+ * New build process for github [#12] (Adam Franco)
+ * Update unit tests to work with the lastest phpunit version [PHPCAS-128] (Adam Franco)
+ * Refacatoring of the protocol decision making to allow validation of proxied usage [PHPCAS-69] (Joachim Fritschi, Adam Franco)
+ * Rebroadcast of logout and pgtiou to support clustered phpcas [PHPCAS-100] (Matthew Selwood, Adam Franco)
+
+Improvements:
+ * Improved cookie handling [] (Adam Franco
+ * Indent, format and user name guidelines of PEAR [#14] (Joachim Fritschi)
+ * Add a class autoloading feature [PHPCAS-125/#8] (Joachim Fritschi)
+ * Remove global variables [PHPCAS-126] (Adam Franco)
+ * Implementation of an exception framework to allow gracefull termination [PHPCAS-109] (Joachim Fritschi)
+
+Security Fixes:
+ * CVE-2012-1104 validate proxied usage of a service [PHPCAS-69] (Joachim Fritschi, Adam Franco)
+ * CVE-2012-1105 change the default PGT save path to the session storage path and set proper permissions [#22] (Joachim Fritschi)
+
+Changes in version 1.2.2
+
+Bug Fixes:
+ * Improve compatibility with php < 5.3 for E_USER_DEPRECATED [PHPCAS-116] (Hugh Eaves)
+
+Changes in version 1.2.2RC1
+
+Bug Fixes:
+ * CASClient::getURL() cannot be private [PHPCAS-103] (Joachim Fritschi)
+ * CASClient::getServerServiceValidateURL() doesn't respect existing query strings [PHPCAS-104] (Bradley Froehle, Joachim Fritschi)
+ * CASClient::retrievePT() must be a public function [PHPCAS-107] (Joachim Fritschi)
+ * Expose setNoClearTicketsFromUrl() to the client [PHPCAS-108] (Joachim Fritschi)
+ * Remove the PGT filestorage in xml format that is not implemented [PHPCAS-112] (Joachim Fritschi)
+ * Fix compatibility of the PGT db storage interface with postgres [PHPCAS-113] (Joachim Fritschi)
+
+Improvement
+ * Support for proxied POST requests. [PHPCAS-90] (Adam Franco)
+ * Add missing example for the new pgt-db storage [PHPCAS-101] (Joachim Fritschi)
+ * CASClient::getServerLoginURL(): Don't cache gateway/renew parameters [PHPCAS-105] (Bradley Froehle)
+ * fix parsing of cookies with special symbols in their values [PHPCAS-106] (Joachim Fritschi)
+ * Removal of the debug_backtrace hack for php4 [PHPCAS-110] (Joachim Fritschi)
+ * Clean up the naming structure of the classes [PHPCAS-111] (Joachim Fritschi)
+ * Better debug log output format [PHPCAS-114] (Joachim Fritschi)
+ * Many more examples and one central config. Improved code documentation [PHPCAS-86] (Joachim Fritschi, Adam Franco)
+
+Changes in version 1.2.1
+ * None
+
+Changes in version 1.2.1RC1
+Improvements
+ * add support for storing PGTs in a database [PHPCAS-94] (Daniel Frett)
+
+Bug Fixes
+ * phpCAS::setDebug(FALSE) should stop logging [PHPCAS-95] (Joachim Fritschi)
+ * fix checkAuthenticate return value documentation [PHPCAS-92] (Joachim Fritschi)
+ * fix PGTStorage contructor name [PHPCAS-93] (Daniel Frett)
+ * fix the PHPCAS_SERVICE_NOT_AVAILABLE constant [PHPCAS-91] (Daniel Frett)
+ * fix redirection with multiple proxies in HTTP_X_FORWARDED_HOST [PHPCAS-98] (Joachim Fritschi)
+ * fix some undefinde variable warnings in debug mode [PHPCAS-96] (Joachim Fritschi)
+
+Changes in version 1.2.0
+ * None
+
+Changes in version 1.2.0RC2
+Improvements
+ * add callback hooks during authentication and single sign-out [PHPCAS-76] (Adam Franco)
+
+Changes in version 1.2.0RC1
+Improvements
+ * add hasAttribute($key) and getAttribute($key) [PHPCAS-43] (Adam Franco)
+ * add unit tests for cas 2.0 attribute support [PHPCAS-88] (Adam Franco)
+ * expose the proxy chain through the phpcas interface [PHPCAS-89] (Adam Franco)
+ * add deprecation messages to the logout functions with an url parameter [PHPCAS-85] (Joachim Fritschi)
+
+Bug Fixes
+ * fix public/private modifier for some functions [PHPCAS-87] (Joachim Fritschi)
+
+Changes in version 1.2.0-beta1
+
+Bug Fixes
+ * fix redirection behind a proxy. [PHPCAS-78] (Alex Barker)
+ * remove the bogus setCasServerCert() function and clean up the curl ssl settings [PHPCAS-84] (Joachim Fritschi)
+
+Improvements
+ * mark the logout functions with an url parameter a deprecated [PHPCAS-85] (Joachim Fritschi)
+ * add public/private modifier for all vars and functions [PHPCAS-77] (Joachim Fritschi)
+ * add a testing framwork that implement on and offline testing capabilities [PHPCAS-66] (Adam Franco)
+ * add RFC compliant cookie storage for the proxy() mode. [PHPCAS-54] (Adam Franco)
+ * removal of the domxml compatibility lib [PHPCAS-72] (Matthew Brooks, Joachim Fritschi)
+ * add support for attributes for the cas_2.0 protocol [PHPCAS-43] (Joachim Fritschi, Adam Franco)
+ * removal of unused code and comments [PHPCAS-63] (Joachim Fritschi)
+ * fix static function warnings for php 5.x [PHPCAS-46] (Joachim Fritschi)
+
+Changes in version 1.1.3
+ Bug Fixes
+ * removal of the non functional pgt-db backend [PHPCAS-65] (Joachim Fritschi)
+
+Changes in version 1.1.3RC1
+ Security Issue
+ * CVE-2010-3690 phpCAS: XSS during a proxy callback [PHPCAS-80] (Joachim Fritschi)
+ * CVE-2010-3691 phpCAS: prevent symlink attacks during a proxy callback [PHPCAS-80] (Joachim Fritschi)
+ * CVE-2010-3692 phpCAS: directory traversal during a proxy callback [PHPCAS-80] (Joachim Fritschi)
+
+ Bug Fixes
+ * fix missing $this in domxml-php4-to-php5 [PHPCAS-73] (Iñaki Arenaza)
+ * fix broken redirection with safari [PHPCAS-79] (Alex Barker)
+ * fix missing exit() call during ticket validation [PHPCAS-76] (Igor Blanco,Joachim Fritschi)
+ * fix a notice because REQUEST_URL is not defined on IIS [PHPCAS-81] (Iñaki Arenaza)
+ * fix a typo in pgt-db.php [PHPCAS-75] (Julien Cochennec)
+
+ Improvements
+ * upgrade domxml-php4-to-php5 to the newest version [PHPCAS-74] (Joachim Fritschi)
+
+Changes in version 1.1.2
+ * None
+
+Changes in version 1.1.2RC2
+ Bug Fixes
+ * Prevent domxml-php4-to-php5 to be inclueded twice [PHPCAS-48] (Brad Krane)
+
+Changes in version 1.1.2RC1
+Security Issue
+ * Fix a session hijacking hole CVE-2010-2795 [PHPCAS-61] (Joachim Fritschi)
+ * callbackurl in proxy mode should be urlencoded CVE-2010-2796 [PHPCAS-67] (Joachim Fritschi)
+
+ Improvement
+ * Debuglog contains phpCAS version information [PHPCAS-62] (Joachim Fritschi)
+
+ Bug Fixes
+ * Fix warnings for SAML responses without attributes [PHPCAS-59] (Joachim Fritschi)
+ * Fix duplicate SAML debug output [PHPCAS-64] (Joachim Fritschi)
+ * Providing a new ST/PT/SA during an authenticated session will be ignored
+ and a warning will be issued to the debug log. [PHPCAS-61] (Joachim Fritschi)
+ * fix 2 undefinded variable notices in serviceWeb() [PHPCAS-68] (Joachim Fritschi)
+
+Changes in version 1.1.1
+Improvement
+ * On Single Sign Out destroy any existing application session before deleting the phpcas session [PHPCAS-58] (Joachim Fritschi)
+
+Changes in version 1.1.1RC2
+Bug fixes
+ * Fix bug in handling urls containing parameters without values [PHPCAS-57] (Joe Lencioni)
+ * New XSS patch for PHPCAS-52 that was undone in r48507 [PHPCAS-57] (Joachim Fritschi)
+
+Changes in version 1.1.1RC1
+Bug fixes
+ * Fix bug in restoring an existing session [PHPCAS-55] (Joachim Fritschi)
+
+Changes in version 1.1.0
+Improvement
+ * Replace deprecated split() with explode(). [PHPCAS-42] (Joe Lencioni)
+
+Changes in version 1.1.0RC8
+Bug fixes
+ * Add additional comments regarding the use of serviceValidate and proxyValdiate [PHPCAS-44] (Joachim Fritschi)
+ * Revert all changes made to the ticket parsing in r47347 r48210 [PHPCAS-44] (Joachim Fritschi)
+ * Fix warning when destroying uninitialized session [PHPCAS-53] (Yann Richard,Joachim Fritschi)
+
+Changes in version 1.1.0RC7
+Security fixes
+ * Fix XSS Vulnerability. Sanatize parameters before using the url submitted by a client [PHPCAS-52] (Joachim Fritschi)
+
+Changes in version 1.1.0RC6
+Bug fixes
+ * restore any possible old session before renaming the session [PHPCAS-50] (Joachim Fritschi)
+
+Changes in version 1.1.0RC5
+Bug fixes
+ * fixed don't destroy existing sessions unless needed, more debug output [PHPCAS-50] (Joachim Fritschi)
+
+Changes in version 1.1.0RC4
+Bug fixes
+
+ * fixed use PHP4 functions to parse saml11 attributes [PHPCAS-51] (Joachim Fritschi)
+
+Changes in version 1.1.0RC3
+Bug fixes
+
+ * added a check for missing params [PHPCAS-42] (Joachim Fritschi)
+
+Changes in version 1.1.0RC2
+New features
+
+ * added custom validation Urls [PHPCAS-45] (Joachim Fritschi).
+
+Bug fixes
+
+ * fixed PGT DB storage parameter list [PHPCAS-47] (Paul Merchant, Jr.)
+ * fixed parsing of STs [PHPCAS-44] (Joachim Fritschi)
+ * fixed session initialisation [PHPCAS-50] (Joachim Fritschi)
+ * fixed urls with than one query parameter [PHPCAS-42] (Caio Chassot)
+
+Changes in version 1.1.0RC1
+New features
+
+ * added SAML support [PHPCAS-40] (Brian Long and Matthias Crauwels).
+
+Bug fixes
+
+ * fixed invalid validation URLs [PHPCAS-39] (Alex Danieli).
+ * removed old PHP4 references [PHPCAS-41] (Yann Richard).
+ * fixed curl options [PHPCAS-38] (Andy Cowling).
+
+Improvement
+
+ * added accept IP addresses for allowed clients [PHPCAS-37] (Arunas Stockus)
+
+Changes in version 1.0.2RC1
+Bug fixes
+
+ * fix redirections masking error messages [PHPCAS-36] (Olivier Berger)
+ * fixed validatePGT() failing on phpCAS::traceBegin() with newer domxml-php4-to-php5.php [PHPCAS-35] (Olivier Berger)
+ * Fixed missing exit() at end of callback() method [PHPCAS-34] (Olivier Berger)
+ * Update included domxml-php4-php5.php to most recent version now under LGPL [PHPCAS-30] (Olivier Berger)
+ * fixed empty $target_service in CAS_Client:serviceMail [PHPCAS-22] (Julien Marchal).
+
+Changes in version 1.0.1
+Bug fixes
+
+ * fixed PEAR base install directory [PHPCAS-28] (Brett Bieber).
+ * fixed illegal characters in session id [PHPCAS-29] (Michael Ströder, Brett Bieber).
+ * fixed refresh with ticket causes authentication failure [related to PHPCAS-27] (Brett Bieber).
+ * fixed conflict with custom session handlers [PHPCAS-26] (Martin Gonzalez).
+
+Changes in version 1.0.0
+New features
+
+ * phpCAS is now PEAR-installable (Brett Bieber).
+ * added method handleLogoutRequests() to handle logout requests incoming from the CAS server (Julien Marchal and Pascal Aubry, requested by Craig Andrews).
+ * added methods setHttpProxy(), setNetworkInterface() and setExtraCurlOptions() (Stéphane Gully).
+
+Enhancements
+
+ * removed undesirable notice (Glennie Vignarajah).
+ * removed PEAR DB dependency when storing PGTs to the filesytem (Stéphane Gully).
+
+Changes in version 0.6.0
+New features
+
+ * added methods setCasServerCert() and setCasServerCaCert() to authenticate the CAS server, and method setNoCasServerValidation() to skip the SSL checks (Pascal Aubry, requested by Andrew Petro).
+ * Added spanish and catalan translations (Ivan Garcia).
+
+Bug fix
+
+ * fixed PGT storage path on Windows (Olivier Thebault).
+
+Changes in version 0.5.1
+New features
+
+ * restored method isAuthenticated() (Julien Marchal).
+
+Changes in version 0.5.0
+New features
+
+ * added japanese translation (Noriyuki Fukuoka).
+ * added german translation (Henrik Genssen).
+ * phpCAS now works for CAS v3 proxy tickets (Matt Zukowski).
+ * phpCAS now also works with lighttpd (Marvin Addison)
+
+Bug fixes
+
+ * fixed method setHTMLFooter() (Noriyuki Fukuoka).
+ * fixed method setHTMLHeader() (Xavier Castanho).
+ * fixed method isHttps() (Henrik Genssen).
+ * fixed method PGTStorageDB() (Ray Lambe).
+ * encode all the parameters, not only '&' characters (Matthew Debus).
+ * fixed ST proxy tickets (Julien Marchal).
+
+Changes in version 0.4.23
+Enhancement
+
+ * removed notice messages (David Lowry).
+
+Changes in version 0.4.22
+Bug fix
+
+ * added default value for parameter gateway in methods setServerLoginUrl() and redirectToCas() (Velpi).
+
+New Feature
+
+ * added method isSessionAuthenticated() (Brendan Arnold).
+
+Other change
+
+ * removed the call to error_reporting() to allow the configuration of error reporting at server level (Pascal Aubry, requested by Sylvain Derosiaux).
+
+Changes in version 0.4.21
+Bug fix
+
+ * some URLs were ill-formed in some rare circumstances (Jérôme Andrieux).
+
+New Feature
+
+ * added methods setServerLoginURL() and setServerLogoutURL() (Wyman Chan).
+
+Changes in version 0.4.20
+New feature
+
+ * phpCAS::checkAuthentication() implements the gateway feature of CAS (Pascal Aubry, requested by Romuald Lorthioir).
+
+Other change
+
+ * phpCAS::authenticateIfNeeded() was renamed phpCAS::forceAuthentication() (Pascal Aubry).
+
+Changes in version 0.4.19
+New features
+
+ * the service URL for the CAs server can be fixed with method phpCAS::setFixedServiceURL (Julien Marchal).
+ * the callback URL used to receive PGTs can be fixed with method phpCAS::setFixedCallbackURL() (Julien Marchal).
+
+ * added a CAS_Client wrapper to class phpCAS for method retrievePGT() (Julien Marchal).
+
+Changes in version 0.4.18
+Bug fixes
+
+ * debugging information was missing (Alexandre Boisseau).
+ * used an undefined variable in pgt-file.php (Alexandre Boisseau).
+
+Changes in version 0.4.17
+Enhancement
+
+ * made phpCAS PHP5 compliant (Vangelis Haniotakis).
+
+Changes in version 0.4.16
+Enhancement
+
+ * added the possibility not to start the session management (Vangelis Haniotakis).
+
+Changes in version 0.4.15
+Enhancement
+
+ * added a hack to make phpCAS work with IIS (Vangelis Haniotakis).
+
+Changes in version 0.4.14
+Enhancement
+
+ * a URL can be given to the CAS server on logout (Sébastien Gougeon and Yann Richard).
+
+Changes in version 0.4.13
+Bug fix
+
+ * Removed infinite loop in debug mode (Robert Legros).
+
+Changes in version 0.4.12
+Enhancement
+
+ * phpCAS now works even if the web server does not set SERVER_NAME, by relying on HTTP_HOST (Terence Chiu).
+
+Changes in version 0.4.11
+Bug fix
+
+ * A typo prevented ticket validation to work correctly (Robert Legros).
+
+Changes in version 0.4.10
+Enhancement
+
+ * phpCAS was previously working with PHP >= 4.3.0. A debug_backtrace() wrapper was added and get_elements_by_tagname() calls were modified to make phpCAS work with phpCAS >= 4.2.2 (Robert Legros).
+
+Changes in version 0.4.9
+New features
+
+ * Added greek translation (Haniotakis Vangelis).
+
+Changes in version 0.4.8
+Enhancements
+
+ * PEAR's DB.php inclusion is done only if a DB class was not already included. This eases the integration into some stand-alone tools that already include DB.php, like Tikiwiki (Pascal Aubry, requested by Terence Chiu).
+
+Changes in version 0.4.7
+Enhancements
+
+ * PHP session is now destroyed when using the phpCAS::logout() method (Pascal Aubry, requested by Ruben Recaba).
+ * Call getenv() whenever possible instead of directly dealing with environment variables (with $_ENV['xxx']), as $_ENV is not available par default on some Windows systems (Pascal Aubry).
+ * Set error reporting level to E_ALL ~ E_NOTICE (Pascal Aubry).
+ * Added the release number in the name of the main directory of the zip distribution file (Pascal Aubry, requested by Vincent Mathieu).
+ * Explicitly set certificate control to get round with different curl default configurations (Wyman Chan).
+
+Changes in version 0.4.6
+Security bug fix
+
+ * Credentials given to HTTP realms were given in the service URLs to the CAS server (Julien Marchal).
+
+Enhancements
+
+ * phpCAS now works behind an Apache reverse proxy (Julien Marchal).
+
+Changes in version 0.4.5
+Enhancements
+
+ * Developer releasing is now made by ant (Pascal Aubry).
+
+Bug fixes
+
+ * CAS/PGTStorage files have been renamed to fit to Windows case insensitivity (Pascal Aubry);
+ * %TMP% and %TEMP% environment variables are now taken into account to set the location of the log file (Pascal Aubry).
+
+Changes in version 0.4.4
+Enhancement
+
+ * ticket retrieval and validation is now made with curl (Pascal Aubry).
+
+Changes in version 0.4.3
+Bug fix
+
+ * phpCAS was not exiting right after redirecting in callback mode (Julien Marchal)
+
+Changes in version 0.4.2
+New features
+
+ * Authentication checking is not necessarily redirecting to the CAS server (introduced phpCAS::isAuthenticated()) (Pascal Aubry)
+ * phpCAS can now be used to access IMAP/POP3/NNTP services (cf phpCAS::serviceMail()) (Pascal Aubry)
+
+Enhancements
+
+ * debugging informations has been improved and is now send to a separate file (/tmp/phpCAS.log by default, can be changed by phpCAS::setDebug()) (Pascal Aubry)
+
+Changes
+
+ * phpCAS::authenticate() is replaced by phpCAS::authenticateIfNeeded() (semantics unchanged) (Pascal Aubry)
+ * phpCAS::service() is replaced by phpCAS::serviceWeb() (semantics unchanged) (Pascal Aubry)
+ * phpCAS::setDebug() accepts FALSE (to stop debugging) or the name of a file (to log informations) (Pascal Aubry)
+
+Changes in version 0.4.1
+New features
+
+ * Sessionning between CAS proxies and services (Pascal Aubry)
+
+Changes in version 0.4
+New features
+
+ * CAS proxies can be chained (Pascal Aubry)
+ * improved error printing and debugging (introduced phpCAS::error()) (Pascal Aubry)
+
+Enhancements
+
+ * proxy parameter removed from phpCAS::client() and introduced phpCAS::proxy() (Pascal Aubry)
+ * moved history from CAS/doc.php to history.php (create_version script updated accordingly) (Pascal Aubry)
+ * improved type-checking and controls for phpCAS methods (Pascal Aubry)
+
+Changes in version 0.3.2
+New features
+
+ * CAS proxies now work with HTTP (HTTPS only used for callbacks) (Pascal Aubry)
+
+Changes in version 0.3.1
+Bug fixes
+
+ * syntax error in CAS/Client.php (Julien Marchal)
+
+Changes in version 0.3
+New features
+
+ * CAS proxies are now supported (but no PGT retrieving for proxied client) (Pascal Aubry)
+ * introduced phpCAS container (Pascal Aubry)
+
+Bug fixes
+
+ * CAS_LANG_DEFAULT is now taken into account (Pascal Aubry)
+
+TODO
+
+ * support for PGT storage to databases (Pascal Aubry)
+ * PGT retrieving for proxied clients (Pascal Aubry)
+
+Version 0.2
+Features (Pascal Aubry)
+
+ * `Basic' (1.0) CAS mechanism supported (CAS proxies not implemented)
+ * Support for CAS versions 1.0 and 2.0 URL's
+ * Debug mode
+ * Customization of all output pages
+ * Internationalization (english and french, looking for translators...)
--- /dev/null
+################################
+### Upgrading 1.3.1 -> 1.3.2 ###
+################################
+
+Due to the missing validation of the CN of the SSL certifcate it may be that
+phpcas fails validation of CAS server certicates that do not match the IP/DNS
+name you use in the phpcas client() or proxy() setup.
+If this happens a quick workaround to change the setup to the old but unsecure
+behaviour. This can be seen in the no_ssl_cn_validation example.
+This is not a recommended setting and is no a secure setup!
+
+################################
+### Upgrading 1.2.x -> 1.3.0 ###
+################################
+
+
+------------------------------------------------------------------
+1. Changing of the default debug.log permissions:
+------------------------------------------------------------------
+
+The default debug log is now created with 0600 permissions to be only readable
+by the webserver
+
+-------------------------------------------------------
+2. Changing of the behaviour of proxied applications:
+-------------------------------------------------------
+
+If your application is being proxied (Another casified application is using
+proxy tickets to access your service you need to change your configuration. The
+new default configuration is now to deny any proxied use of your service unless
+it is exlicitly allowed:
+
+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.
+
+Examples:
+ phpCAS::allowProxyChain(new CAS_ProxyChain(array(
+ 'https://app.example.com/'
+ )));
+or
+ 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.
+
+
+----------------------------------------------------------------
+3. Changing of the default PGT file storage location in proxy mode:
+----------------------------------------------------------------
+
+The default storage of the sensitive PGT session files is the
+session_save_path() now. This is a php environment dependent dir which is also
+used for storing your php session data. The default permissions are also changed
+to 0600 to be only readable by the webserver.
+
+
+
+
+------------------------------------------------------------------
+4. The setPGTStorageFile() function has changed it parameters.
+------------------------------------------------------------------
+
+The setPGTStorageFile() function no longer needs an storage "format" argument.
+Since the format functionality was never implemented it has now been dropped
+and only the path argument is necessary.
+
+------------------------------------------------------------------
+5. The startSession boolean in the constructor has been changed to
+changeSessionID
+------------------------------------------------------------------
+
+The last parameter of the constructor for has been changed from "start session"
+to "change session ID". This has no negative effects on existion integrations
+but will allow integration with other frameworks to take advantage of single
+sign-out if they switch to "true". phpCAS will then rename the session id
+(keeping all vars) and be able to single sign-out users.
+
+
+
+
--- /dev/null
+<?php
+
+/**
+ * The purpose of this central config file is configuring all examples
+ * in one place with minimal work for your working environment
+ * Just configure all the items in this config according to your environment
+ * and rename the file to config.php
+ *
+ * PHP Version 5
+ *
+ * @file config.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+$phpcas_path = '../../source/';
+
+///////////////////////////////////////
+// Basic Config of the phpCAS client //
+///////////////////////////////////////
+
+// Full Hostname of your CAS Server
+$cas_host = 'cas.example.com';
+
+// Context of the CAS Server
+$cas_context = '/cas';
+
+// Port of your CAS server. Normally for a https server it's 443
+$cas_port = 443;
+
+// Path to the ca chain that issued the cas server certificate
+$cas_server_ca_cert_path = '/path/to/cachain.pem';
+
+//////////////////////////////////////////
+// Advanced Config for special purposes //
+//////////////////////////////////////////
+
+// The "real" hosts of clustered cas server that send SAML logout messages
+// Assumes the cas server is load balanced across multiple hosts
+$cas_real_hosts = array('cas-real-1.example.com', 'cas-real-2.example.com');
+
+// Database config for PGT Storage
+$db = 'pgsql:host=localhost;dbname=phpcas';
+//$db = 'mysql:host=localhost;dbname=phpcas';
+$db_user = 'phpcasuser';
+$db_password = 'mysupersecretpass';
+$db_table = 'phpcastabel';
+$driver_options = '';
+
+///////////////////////////////////////////
+// End Configuration -- Don't edit below //
+///////////////////////////////////////////
+
+// Generating the URLS for the local cas example services for proxy testing
+if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
+ $curbase = 'https://' . $_SERVER['SERVER_NAME'];
+} else {
+ $curbase = 'http://' . $_SERVER['SERVER_NAME'];
+}
+if ($_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443) {
+ $curbase .= ':' . $_SERVER['SERVER_PORT'];
+}
+
+$curdir = dirname($_SERVER['REQUEST_URI']) . "/";
+
+// CAS client nodes for rebroadcasting pgtIou/pgtId and logoutRequest
+$rebroadcast_node_1 = 'http://cas-client-1.example.com';
+$rebroadcast_node_2 = 'http://cas-client-2.example.com';
+
+// access to a single service
+$serviceUrl = $curbase . $curdir . 'example_service.php';
+// access to a second service
+$serviceUrl2 = $curbase . $curdir . 'example_service_that_proxies.php';
+
+$pgtBase = preg_quote(preg_replace('/^http:/', 'https:', $curbase . $curdir), '/');
+$pgtUrlRegexp = '/^' . $pgtBase . '.*$/';
+
+$cas_url = 'https://' . $cas_host;
+if ($cas_port != '443') {
+ $cas_url = $cas_url . ':' . $cas_port;
+}
+$cas_url = $cas_url . $cas_context;
+
+// Set the session-name to be unique to the current script so that the client script
+// doesn't share its session with a proxied script.
+// This is just useful when running the example code, but not normally.
+session_name(
+ 'session_for:'
+ . preg_replace('/[^a-z0-9-]/i', '_', basename($_SERVER['SCRIPT_NAME']))
+);
+// Set an UTF-8 encoding header for internation characters (User attributes)
+header('Content-Type: text/html; charset=utf-8');
+?>
--- /dev/null
+<?php
+
+/**
+ * Script that generates a default table for PGT/PGTiou storage. This script
+ * assumes a database with proper permissions exists and we are habe
+ * permissions to create a table.
+ * All database settings have to be set in the config.php file. Or the
+ * CAS_PGTStorage_Db() options:
+ * $db, $db_user, $db_password, $db_table, $driver_options
+ * have to filled out directly. Option examples can be found in the
+ * config.example.php
+ *
+ * PHP Version 5
+ *
+ * @file create_pgt_storage_table.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
+ */
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+
+// Dummy client because we need a 'client' object
+$client = new CAS_Client(CAS_VERSION_2_0, true, $cas_host, $cas_port, $cas_context, false);
+
+// Set the torage object
+$cas_obj = new CAS_PGTStorage_Db($client, $db, $db_user, $db_password, $db_table, $driver_options);
+$cas_obj->init();
+$cas_obj->createTable();
+?>
+<html>
+ <head>
+ <title>phpCAS PGT db storage table creation</title>
+ <link rel="stylesheet" type='text/css' href='example.css'/>
+ </head>
+<body>
+<div class="success">
+<?php
+echo 'Table <b>' . $db_table . '</b> successfully created in database <b>' . $db . '</b>';
+?>
+</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+.error {
+ border: 1px solid #aa0000;
+ color: #aa0000;
+ padding: 5px;
+}
+.success {
+ border: 1px solid #00aa00;
+ color: #00aa00;
+ padding: 5px;
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Advanced example for SAML with attributes and single logout
+ *
+ * PHP Version 5
+ *
+ * @file example_advanced_saml.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+// Uncomment to enable debugging
+phpCAS::setDebug();
+
+// Initialize phpCAS
+phpCAS::client(SAML_VERSION_1_1, $cas_host, $cas_port, $cas_context);
+
+// For production use set the CA certificate that is the issuer of the cert
+// on the CAS server and uncomment the line below
+phpCAS::setCasServerCACert($cas_server_ca_cert_path);
+
+// For quick testing you can disable SSL validation of the CAS server.
+// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
+// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
+// phpCAS::setNoCasServerValidation();
+
+// Handle SAML logout requests that emanate from the CAS host exclusively.
+// Failure to restrict SAML logout requests to authorized hosts could
+// allow denial of service attacks where at the least the server is
+// tied up parsing bogus XML messages.
+phpCAS::handleLogoutRequests(true, $cas_real_hosts);
+
+// Force CAS authentication on any page that includes this file
+phpCAS::forceAuthentication();
+
+// Some small code triggered by the logout button\r
+if (isset($_REQUEST['logout'])) {\r
+ phpCAS::logout();\r
+}
+?>
+<html>
+ <head>
+ <title>Advanced SAML 1.1 example</title>
+ </head>
+ <body>
+<h2>Advanced SAML 1.1 example</h2>
+<?php require 'script_info.php' ?>
+
+Authentication succeeded for user
+<strong><?php echo phpCAS::getUser(); ?></strong>.
+
+<h3>User Attributes</h3>
+<ul>
+<?php
+foreach (phpCAS::getAttributes() as $key => $value) {
+ if (is_array($value)) {
+ echo '<li>', $key, ':<ol>';
+ foreach ($value as $item) {
+ echo '<li><strong>', $item, '</strong></li>';
+ }
+ echo '</ol></li>';
+ } else {
+ echo '<li>', $key, ': <strong>', $value, '</strong></li>' . PHP_EOL;
+ }
+}
+ ?>
+</ul>
+<p><a href="?logout=">Logout</a></p>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Example for overriding validation urls
+ *
+ * PHP Version 5
+ *
+ * @file example_custom_urls.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+// Uncomment to enable debugging
+phpCAS::setDebug();
+
+// Initialize phpCAS
+phpCAS::client(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context);
+
+// For production use set the CA certificate that is the issuer of the cert
+// on the CAS server and uncomment the line below
+// phpCAS::setCasServerCACert($cas_server_ca_cert_path);
+
+// For quick testing you can disable SSL validation of the CAS server.
+// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
+// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
+phpCAS::setNoCasServerValidation();
+
+// Override the validation url for any (ST and PT) CAS 2.0 validation
+phpCAS::setServerProxyValidateURL('https://cas.example.org:1443/proxyValidate');
+// Override the validation url for any CAS 1.0 validation
+//phpCAS::setServerServiceValidateURL('https://cas.example.org:1443/serviceValidate');
+//Override the validation url for any SAML11 validation
+//phpCAS::setServerSamlValidateURL('https://cas.example.org:1443/samlValidate');
+
+// force CAS authentication
+phpCAS::forceAuthentication();
+
+// at this step, the user has been authenticated by the CAS server
+// and the user's login name can be read with phpCAS::getUser().
+
+// logout if desired
+if (isset($_REQUEST['logout'])) {
+ phpCAS::logout();
+}
+
+// for this test, simply print that the authentication was successfull
+?>
+<html>
+ <head>
+ <title>phpCAS simple client</title>
+ </head>
+ <body>
+ <h1>Successfull Authentication!</h1>
+ <?php require 'script_info.php' ?>
+ <p>the user's login is <b><?php echo phpCAS::getUser(); ?></b>.</p>
+ <p>phpCAS version is <b><?php echo phpCAS::getVersion(); ?></b>.</p>
+ <p><a href="?logout=">Logout</a></p>
+ </body>
+</html>
--- /dev/null
+<?php
+
+/**
+ * Example that uses the CAS gateway feature
+ *
+ * PHP Version 5
+ *
+ * @file example_gateway.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+// Uncomment to enable debugging
+phpCAS::setDebug();
+
+// Initialize phpCAS
+phpCAS::client(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context);
+
+// For production use set the CA certificate that is the issuer of the cert
+// on the CAS server and uncomment the line below
+// phpCAS::setCasServerCACert($cas_server_ca_cert_path);
+
+// For quick testing you can disable SSL validation of the CAS server.
+// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
+// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
+phpCAS::setNoCasServerValidation();
+
+if (isset($_REQUEST['logout'])) {
+ phpCAS::logout();
+}
+if (isset($_REQUEST['login'])) {
+ phpCAS::forceAuthentication();
+}
+
+// check CAS authentication
+$auth = phpCAS::checkAuthentication();
+
+?>
+<html>
+ <head>
+ <title>phpCAS simple client</title>
+ </head>
+ <body>
+<?php
+if ($auth) {
+ // for this test, simply print that the authentication was successfull
+ ?>
+ <h1>Successfull Authentication!</h1>
+ <?php include 'script_info.php' ?>
+ <p>the user's login is <b><?php echo phpCAS::getUser(); ?></b>.</p>
+ <p><a href="?logout=">Logout</a></p><?php
+} else {
+ ?>
+ <h1>Guest mode</h1>
+ <p><a href="?login=">Login</a></p><?php
+}
+ ?>
+ <p>phpCAS version is <b><?php echo phpCAS::getVersion(); ?></b>.</p>
+ </body>
+</html>
--- /dev/null
+<?php
+
+/**
+ * Example that changes html of phpcas messages
+ *
+ * PHP Version 5
+ *
+ * @file example_html.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+// Uncomment to enable debugging
+phpCAS::setDebug();
+
+// Initialize phpCAS
+phpCAS::client(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context);
+
+// For production use set the CA certificate that is the issuer of the cert
+// on the CAS server and uncomment the line below
+// phpCAS::setCasServerCACert($cas_server_ca_cert_path);
+
+// For quick testing you can disable SSL validation of the CAS server.
+// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
+// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
+phpCAS::setNoCasServerValidation();
+
+// customize HTML output
+phpCAS::setHTMLHeader(
+ '<html>
+ <head>
+ <title>__TITLE__</title>
+ </head>
+ <body>
+ <h1>__TITLE__</h1>'
+);
+phpCAS::setHTMLFooter(
+ '<hr>
+ <address>
+ phpCAS __PHPCAS_VERSION__,
+ CAS __CAS_VERSION__ (__SERVER_BASE_URL__)
+ </address>
+ </body>
+</html>'
+);
+
+// force CAS authentication
+phpCAS::forceAuthentication();
+
+// at this step, the user has been authenticated by the CAS server
+// and the user's login name can be read with phpCAS::getUser().
+
+// for this test, simply print that the authentication was successfull
+?>
+<html>
+ <head>
+ <title>phpCAS simple client with HTML output customization</title>
+ </head>
+ <body>
+ <h1>Successfull Authentication!</h1>
+ <?php require 'script_info.php' ?>
+ <p>the user's login is <b><?php echo phpCAS::getUser(); ?></b>.</p>
+ <p>phpCAS version is <b><?php echo phpCAS::getVersion(); ?></b>.</p>
+ </body>
+</html>
--- /dev/null
+<?php
+
+/**
+ * Example that changes language of phpcas pages
+ *
+ * PHP Version 5
+ *
+ * @file example_lang.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+// Uncomment to enable debugging
+phpCAS::setDebug();
+
+// Initialize phpCAS
+phpCAS::client(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context);
+
+// For production use set the CA certificate that is the issuer of the cert
+// on the CAS server and uncomment the line below
+// phpCAS::setCasServerCACert($cas_server_ca_cert_path);
+
+// For quick testing you can disable SSL validation of the CAS server.
+// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
+// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
+phpCAS::setNoCasServerValidation();
+
+// set the language to french
+phpCAS::setLang(PHPCAS_LANG_FRENCH);
+
+// force CAS authentication
+phpCAS::forceAuthentication();
+
+// at this step, the user has been authenticated by the CAS server
+// and the user's login name can be read with phpCAS::getUser().
+
+// moreover, a PGT was retrieved from the CAS server that will
+// permit to gain accesses to new services.
+
+// for this test, simply print that the authentication was successfull
+?>
+<html>
+ <head>
+ <title>Exemple d'internationalisation de phpCAS</title>
+ </head>
+ <body>
+ <h1>Authentification réussie !</h1>
+ <?php require 'script_info.php' ?>
+ <p>L'utilisateur connecté est <b><?php echo phpCAS::getUser(); ?></b>.</p>
+ <p>La version de phpCAS est <b><?php echo phpCAS::getVersion(); ?></b>.</p>
+ </body>
+</html>
--- /dev/null
+<?php
+
+/**
+ * Example for handling logout requests
+ *
+ * PHP Version 5
+ *
+ * @file example_logout.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+// Uncomment to enable debugging
+phpCAS::setDebug();
+
+// Initialize phpCAS
+phpCAS::client(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context);
+
+// For production use set the CA certificate that is the issuer of the cert
+// on the CAS server and uncomment the line below
+// phpCAS::setCasServerCACert($cas_server_ca_cert_path);
+
+// For quick testing you can disable SSL validation of the CAS server.
+// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
+// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
+phpCAS::setNoCasServerValidation();
+
+// handle incoming logout requests
+phpCAS::handleLogoutRequests();
+
+// Or as an advanced featue handle SAML logout requests that emanate from the
+// CAS host exclusively.
+// Failure to restrict SAML logout requests to authorized hosts could
+// allow denial of service attacks where at the least the server is
+// tied up parsing bogus XML messages.
+// phpCAS::handleLogoutRequests(true, $cas_real_hosts);
+
+// force CAS authentication
+phpCAS::forceAuthentication();
+
+// for this test, simply print that the authentication was successfull
+?>
+<html>
+ <head>
+ <title>phpCAS simple client</title>
+ </head>
+ <body>
+ <h1>Successfull Authentication!</h1>
+ <?php require 'script_info.php' ?>
+ <p>the user's login is <b><?php echo phpCAS::getUser(); ?></b>.</p>
+ <p>phpCAS version is <b><?php echo phpCAS::getVersion(); ?></b>.</p>
+ </body>
+</html>
--- /dev/null
+<?php
+
+/**
+ * Example for diabling SSL CN valdiation
+ *
+ * PHP Version 5
+ *
+ * @file example_simple.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+// Uncomment to enable debugging
+phpCAS::setDebug();
+
+// Initialize phpCAS
+phpCAS::client(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context);
+
+// For production use set the CA certificate that is the issuer of the cert
+// on the CAS server and uncomment the line below
+// phpCAS::setCasServerCACert($cas_server_ca_cert_path);
+
+// For quick testing you can disable SSL validation of the CAS server.
+// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
+// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
+// phpCAS::setNoCasServerValidation();
+// You can also disable the validation of the certficate CN. This means the
+// certificate must be valid but the CN of the certificate must not match the
+// IP or hostname you are using to access the server
+phpCAS::setCasServerCACert($cas_server_ca_cert_path, false);
+
+
+// force CAS authentication
+phpCAS::forceAuthentication();
+
+// at this step, the user has been authenticated by the CAS server
+// and the user's login name can be read with phpCAS::getUser().
+
+// logout if desired
+if (isset($_REQUEST['logout'])) {
+ phpCAS::logout();
+}
+
+// for this test, simply print that the authentication was successfull
+?>
+<html>
+ <head>
+ <title>phpCAS simple client</title>
+ </head>
+ <body>
+ <h1>Successfull Authentication!</h1>
+ <?php require 'script_info.php' ?>
+ <p>the user's login is <b><?php echo phpCAS::getUser(); ?></b>.</p>
+ <p>phpCAS version is <b><?php echo phpCAS::getVersion(); ?></b>.</p>
+ <p><a href="?logout=">Logout</a></p>
+ </body>
+</html>
--- /dev/null
+<?php
+
+/**
+ * Example that changes the storage of the pgt tickets
+ *
+ * PHP Version 5
+ *
+ * @file example_pgt_storage_db.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+// Uncomment to enable debugging
+phpCAS::setDebug();
+
+// Initialize phpCAS
+phpCAS::proxy(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context);
+
+// For production use set the CA certificate that is the issuer of the cert
+// on the CAS server and uncomment the line below
+// phpCAS::setCasServerCACert($cas_server_ca_cert_path);
+
+// For quick testing you can disable SSL validation of the CAS server.
+// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
+// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
+phpCAS::setNoCasServerValidation();
+
+// set PGT storage to file in plain format in the same directory as session files
+phpCAS::setPGTStorageDB($db, $db_user, $db_password, $db_table);
+
+// force CAS authentication
+phpCAS::forceAuthentication();
+
+// at this step, the user has been authenticated by the CAS server
+// and the user's login name can be read with phpCAS::getUser().
+
+// moreover, a PGT was retrieved from the CAS server that will
+// permit to gain accesses to new services.
+
+?>
+<html>
+ <head>
+ <title>phpCAS proxy example with PGT storage to a database</title>
+ <link rel="stylesheet" type='text/css' href='example.css'/>
+ </head>
+ <body>
+ <h1>phpCAS proxy example with PGT storage to file</h1>
+ <?php require 'script_info.php' ?>
+ <p>the user's login is <b><?php echo phpCAS::getUser(); ?></b>.</p>
+ <h2>Response from service <?php echo $serviceUrl; ?></h2>
+<?php
+flush();
+// call a service and change the color depending on the result
+if (phpCAS::serviceWeb($serviceUrl, $err_code, $output)) {
+ echo '<div class="success">';
+} else {
+ echo '<div class="error">';
+}
+echo $output;
+echo '</div>';
+ ?>
+ </body>
+</html>
--- /dev/null
+<?php
+
+/**
+* Example that changes the storage of the pgt tickets to file
+*
+* PHP Version 5
+*
+* @file example_pgt_storage_db.php
+* @category Authentication
+* @package PhpCAS
+* @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
+*/
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+// Uncomment to enable debugging
+phpCAS::setDebug();
+
+// Initialize phpCAS
+phpCAS::proxy(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context);
+
+// For production use set the CA certificate that is the issuer of the cert
+// on the CAS server and uncomment the line below
+// phpCAS::setCasServerCACert($cas_server_ca_cert_path);
+
+// For quick testing you can disable SSL validation of the CAS server.
+// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
+// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
+phpCAS::setNoCasServerValidation();
+
+// set PGT storage to file in plain format in the same directory as session files
+phpCAS::setPGTStorageFile(session_save_path());
+
+// force CAS authentication
+phpCAS::forceAuthentication();
+
+// at this step, the user has been authenticated by the CAS server
+// and the user's login name can be read with phpCAS::getUser().
+
+// moreover, a PGT was retrieved from the CAS server that will
+// permit to gain accesses to new services.
+
+?>
+<html>
+ <head>
+ <title>phpCAS proxy example with PGT storage to file</title>
+ <link rel="stylesheet" type='text/css' href='example.css'/>
+ </head>
+ <body>
+ <h1>phpCAS proxy example with PGT storage to file</h1>
+ <?php require 'script_info.php' ?>
+ <p>the user's login is <b><?php echo phpCAS::getUser(); ?></b>.</p>
+ <h2>Response from service <?php echo $serviceUrl; ?></h2>
+<?php
+ flush();
+ // call a service and change the color depending on the result
+if ( phpCAS::serviceWeb($serviceUrl, $err_code, $output) ) {
+ echo '<div class="success">';
+} else {
+ echo '<div class="error">';
+}
+ echo $output;
+ echo '</div>';
+?>
+ </body>
+</html>
--- /dev/null
+<?php
+
+/**
+ * Example for a proxy that makes a GET request.
+ *
+ * PHP Version 5
+ *
+ * @file example_proxy_GET.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+// Uncomment to enable debugging
+phpCAS::setDebug();
+
+// Initialize phpCAS
+phpCAS::proxy(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context);
+
+// For production use set the CA certificate that is the issuer of the cert
+// on the CAS server and uncomment the line below
+// phpCAS::setCasServerCACert($cas_server_ca_cert_path);
+
+// For quick testing you can disable SSL validation of the CAS server.
+// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
+// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
+phpCAS::setNoCasServerValidation();
+
+// force CAS authentication
+phpCAS::forceAuthentication();
+
+// at this step, the user has been authenticated by the CAS server
+// and the user's login name can be read with phpCAS::getUser().
+
+// moreover, a PGT was retrieved from the CAS server that will
+// permit to gain accesses to new services.
+
+?>
+<html>
+ <head>
+ <title>phpCAS proxy example #2</title>
+ <link rel="stylesheet" type='text/css' href='example.css'/>
+ </head>
+ <body>
+ <h1>phpCAS proxied proxy example</h1>
+ <?php require 'script_info.php' ?>
+ <p>the user's login is <b><?php echo phpCAS::getUser(); ?></b>.</p>
+ <h2>Response from service <?php echo $serviceUrl; ?></h2>
+<?php
+flush();
+
+// call a service and change the color depending on the result
+try {
+ $service = phpCAS::getProxiedService(PHPCAS_PROXIED_SERVICE_HTTP_GET);
+ $service->setUrl($serviceUrl);
+ $service->send();
+ if ($service->getResponseStatusCode() == 200) {
+ echo '<div class="success">';
+ echo $service->getResponseBody();
+ echo '</div>';
+ } else {
+ // The service responded with an error code 404, 500, etc.
+ echo '<div class="error">';
+ echo 'The service responded with a '
+ . $service->getResponseStatusCode() . ' error.';
+ echo '</div>';
+ }
+} catch (CAS_ProxyTicketException $e) {
+ if ($e->getCode() == PHPCAS_SERVICE_PT_FAILURE) {
+ echo '<div class="error">';
+ echo "Your login has timed out. You need to log in again.";
+ echo '</div>';
+ } else {
+ // Other proxy ticket errors are from bad request format (shouldn't happen)
+ // or CAS server failure (unlikely) so lets just stop if we hit those.
+ throw $e;
+ }
+} catch (CAS_ProxiedService_Exception $e) {
+ // Something prevented the service request from being sent or received.
+ // We didn't even get a valid error response (404, 500, etc), so this
+ // might be caused by a network error or a DNS resolution failure.
+ // We could handle it in some way, but for now we will just stop.
+ throw $e;
+}
+
+ ?>
+ </body>
+</html>
--- /dev/null
+<?php
+
+/**
+ * Example for a proxy that makes a POST request.
+ *
+ * PHP Version 5
+ *
+ * @file example_proxy_POST.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+// Uncomment to enable debugging
+phpCAS::setDebug();
+
+// Initialize phpCAS
+phpCAS::proxy(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context);
+
+// For production use set the CA certificate that is the issuer of the cert
+// on the CAS server and uncomment the line below
+// phpCAS::setCasServerCACert($cas_server_ca_cert_path);
+
+// For quick testing you can disable SSL validation of the CAS server.
+// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
+// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
+phpCAS::setNoCasServerValidation();
+
+// force CAS authentication
+phpCAS::forceAuthentication();
+
+// at this step, the user has been authenticated by the CAS server
+// and the user's login name can be read with phpCAS::getUser().
+
+// moreover, a PGT was retrieved from the CAS server that will
+// permit to gain accesses to new services.
+
+$serviceUrl = $curbase . $curdir . 'example_service_POST.php';
+
+?>
+<html>
+ <head>
+ <title>phpCAS proxy POST example</title>
+ <link rel="stylesheet" type='text/css' href='example.css'/>
+ </head>
+ <body>
+ <h1>phpCAS proxy POST example</h1>
+ <?php require 'script_info.php' ?>
+ <p>the user's login is <b><?php echo phpCAS::getUser(); ?></b>.</p>
+ <h2>Response from service <?php echo $serviceUrl; ?></h2>
+<?php
+flush();
+
+// call a service and change the color depending on the result
+try {
+ $service = phpCAS::getProxiedService(PHPCAS_PROXIED_SERVICE_HTTP_POST);
+ $service->setUrl($serviceUrl);
+ $service->setContentType('application/x-www-form-urlencoded');
+ $service->setBody('favorite_color=blue');
+ $service->send();
+ if ($service->getResponseStatusCode() == 200) {
+ echo '<div class="success">';
+ echo $service->getResponseBody();
+ echo '</div>';
+ } else {
+ // The service responded with an error code 404, 500, etc.
+ echo '<div class="error">';
+ echo 'The service responded with a '
+ . $service->getResponseStatusCode() . ' error.';
+ echo $service->getResponseBody();
+ echo '</div>';
+ }
+} catch (CAS_ProxyTicketException $e) {
+ if ($e->getCode() == PHPCAS_SERVICE_PT_FAILURE) {
+ echo '<div class="error">';
+ echo "Your login has timed out. You need to log in again.";
+ echo '</div>';
+ } else {
+ // Other proxy ticket errors are from bad request format (shouldn't happen)
+ // or CAS server failure (unlikely) so lets just stop if we hit those.
+ throw $e;
+ }
+} catch (CAS_ProxiedService_Exception $e) {
+ // Something prevented the service request from being sent or received.
+ // We didn't even get a valid error response (404, 500, etc), so this
+ // might be caused by a network error or a DNS resolution failure.
+ // We could handle it in some way, but for now we will just stop.
+ throw $e;
+}
+
+ ?>
+ </body>
+</html>
--- /dev/null
+<?php
+
+/**
+ * Example for a proxy that rebroadcasts all PGTs to different servers in the
+ * cluster
+ *
+ * PHP Version 5
+ *
+ * @file example_proxy_rebroadcast.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+// Enable debugging
+phpCAS::setDebug();
+
+// Initialize phpCAS
+phpCAS::proxy(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context);
+
+// For production use set the CA certificate that is the issuer of the cert
+// on the CAS server and uncomment the line below
+// phpCAS::setCasServerCACert($cas_server_ca_cert_path);
+
+// For quick testing you can disable SSL validation of the CAS server.
+// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
+// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
+phpCAS::setNoCasServerValidation();
+
+// Set the nodes for rebroadcasting pgtIou/pgtId and logoutRequest
+phpCAS::addRebroadcastNode($rebroadcast_node_1);
+phpCAS::addRebroadcastNode($rebroadcast_node_2);
+
+// handle incoming logout requests
+phpCAS::handleLogoutRequests();
+
+// force CAS authentication
+phpCAS::forceAuthentication();
+
+// at this step, the user has been authenticated by the CAS server
+// and the user's login name can be read with phpCAS::getUser().
+
+?>
+<html>
+ <head>
+ <title>phpCAS proxy rebroadcast example</title>
+ <link rel="stylesheet" type='text/css' href='example.css'/>
+ </head>
+ <body>
+ <h1>phpCAS proxy rebroadcast example</h1>
+ <p>the user's login is <b><?php echo phpCAS::getUser(); ?></b>.</p>
+ </body>
+</html>
--- /dev/null
+<?php
+
+/**
+ * Example for a proxy with session usage
+ *
+ * PHP Version 5
+ *
+ * @file example_proxy_GET.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+// Uncomment to enable debugging
+phpCAS::setDebug();
+
+// Initialize phpCAS
+phpCAS::proxy(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context);
+
+// For production use set the CA certificate that is the issuer of the cert
+// on the CAS server and uncomment the line below
+// phpCAS::setCasServerCACert($cas_server_ca_cert_path);
+
+// For quick testing you can disable SSL validation of the CAS server.
+// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
+// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
+phpCAS::setNoCasServerValidation();
+
+// force CAS authentication
+phpCAS::forceAuthentication();
+
+// at this step, the user has been authenticated by the CAS server
+// and the user's login name can be read with phpCAS::getUser().
+
+// moreover, a PGT was retrieved from the CAS server that will
+// permit to gain accesses to new services.
+
+?>
+<html>
+ <head>
+ <title>phpCAS proxied proxy example (with sessioning)</title>
+ <link rel="stylesheet" type='text/css' href='example.css'/>
+ </head>
+ <body>
+ <h1>phpCAS proxied proxy example (with sessioning)</h1>
+ <?php require 'script_info.php' ?>
+ <p>the user's login is <b><?php echo phpCAS::getUser(); ?></b>.</p>
+ <h2>Response from service <?php echo $serviceUrl; ?></h2>
+<?php
+flush();
+// call a service and change the color depending on the result
+if (phpCAS::serviceWeb($serviceUrl, $err_code, $output)) {
+ echo '<div class="success">';
+} else {
+ echo '<div class="error">';
+}
+echo $output;
+echo '</div>';
+ ?>
+ </body>
+</html>
--- /dev/null
+<?php
+
+/**
+ * Example for a proxy with session usage
+ *
+ * PHP Version 5
+ *
+ * @file example_proxy_serviceWeb_chaining.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+// Uncomment to enable debugging
+phpCAS::setDebug();
+
+// Initialize phpCAS
+phpCAS::proxy(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context);
+
+// For production use set the CA certificate that is the issuer of the cert
+// on the CAS server and uncomment the line below
+// phpCAS::setCasServerCACert($cas_server_ca_cert_path);
+
+// For quick testing you can disable SSL validation of the CAS server.
+// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
+// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
+phpCAS::setNoCasServerValidation();
+
+// force CAS authentication
+phpCAS::forceAuthentication();
+
+// at this step, the user has been authenticated by the CAS server
+// and the user's login name can be read with phpCAS::getUser().
+
+// moreover, a PGT was retrieved from the CAS server that will
+// permit to gain accesses to new services.
+
+?>
+<html>
+ <head>
+ <title>phpCAS proxy example #2</title>
+ <link rel="stylesheet" type='text/css' href='example.css'/>
+ </head>
+ <body>
+ <h1>phpCAS proxied proxy example</h1>
+ <?php require 'script_info.php' ?>
+ <p>the user's login is <b><?php echo phpCAS::getUser(); ?></b>.</p>
+ <h2>Response from service <?php echo $serviceUrl2; ?></h2>
+<?php
+flush();
+// call a service and change the color depending on the result
+if (phpCAS::serviceWeb($serviceUrl2, $err_code, $output)) {
+ echo '<div class="success">';
+} else {
+ echo '<div class="error">';
+}
+echo $output;
+echo '</div>';
+ ?>
+ </body>
+</html>
--- /dev/null
+<?php
+
+/**
+ * Example for proxied service with session support
+ *
+ * PHP Version 5
+ *
+ * @file example_service.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+// Uncomment to enable debugging
+phpCAS::setDebug();
+
+// Initialize phpCAS
+phpCAS::client(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context);
+
+// For production use set the CA certificate that is the issuer of the cert
+// on the CAS server and uncomment the line below
+// phpCAS::setCasServerCACert($cas_server_ca_cert_path);
+
+// For quick testing you can disable SSL validation of the CAS server.
+// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
+// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
+phpCAS::setNoCasServerValidation();
+
+// 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/'
+// )));
+phpCAS::allowProxyChain(new CAS_ProxyChain(array($pgtUrlRegexp)));
+phpCAS::allowProxyChain(
+ new CAS_ProxyChain(
+ array('/^' . $pgtBase . 'example_service_that_proxies.php$/',
+ '/^' . $pgtBase . 'example_proxy_serviceWeb_chaining.php$/'
+ )
+ )
+);
+
+// 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.
+//phpcas::allowProxyChain(new CAS_ProxyChain_Any);
+
+// force CAS authentication
+phpCAS::forceAuthentication();
+
+print '<h1>I am a service that can be proxied.</h1>';
+
+// at this step, the user has been authenticated by the CAS server
+// and the user's login name can be read with phpCAS::getUser().
+require 'script_info.php';
+
+// for this test, simply print that the authentication was successfull
+echo '<p>The user\'s login is <b>' . phpCAS::getUser() . '</b>.</p>';
+
+// increment the number of requests of the session and print it
+if (!isset($_SESSION['n'])) {
+ $_SESSION['n'] = 0;
+}
+echo '<p>request #' . (++$_SESSION['n']) . '</p>';
+
+?>
--- /dev/null
+<?php
+
+/**
+ * Example for proxied service with session support and POST support
+ *
+ * PHP Version 5
+ *
+ * @file example_service_POST.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+// Uncomment to enable debugging
+phpCAS::setDebug();
+
+// Initialize phpCAS
+phpCAS::client(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context);
+
+// For production use set the CA certificate that is the issuer of the cert
+// on the CAS server and uncomment the line below
+// phpCAS::setCasServerCACert($cas_server_ca_cert_path);
+
+// For quick testing you can disable SSL validation of the CAS server.
+// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
+// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
+phpCAS::setNoCasServerValidation();
+
+// 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/'
+// )));
+phpCAS::allowProxyChain(new CAS_ProxyChain(array($pgtUrlRegexp)));
+
+// 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.
+//phpcas::allowProxyChain(new CAS_ProxyChain_Any);
+
+// force CAS authentication
+phpCAS::forceAuthentication();
+
+if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+ header('HTTP/1.1 400 Bad Request');
+ print
+ "<h1>I only respond to POST requests. This is a "
+ . $_SERVER['REQUEST_METHOD'] . " request.</h1>";
+ exit;
+}
+if (empty($_POST['favorite_color'])) {
+ header('HTTP/1.1 400 Bad Request');
+ print '<h1>You must post a <strong>favorite_color</strong>.</h1>';
+ exit;
+}
+
+print '<h1>I am a service that responds to POST requests.</h1>';
+
+// at this step, the user has been authenticated by the CAS server
+// and the user's login name can be read with phpCAS::getUser().
+require 'script_info.php';
+
+// for this test, simply print that the authentication was successfull
+echo '<p>The user\'s login is <b>' . phpCAS::getUser() . '</b>.</p>';
+
+print
+ '<h1>Your favorite color is ' . htmlentities($_POST['favorite_color'])
+ . '</h1>';
+
+// increment the number of requests of the session and print it
+if (!isset($_SESSION['n'])) {
+ $_SESSION['n'] = 0;
+}
+echo '<p>request #' . (++$_SESSION['n']) . '</p>';
+
--- /dev/null
+<?php
+
+/**
+ * Example for a proxied proxy
+ *
+ * PHP Version 5
+ *
+ * @file example_service_that_proxies.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+// Uncomment to enable debugging
+phpCAS::setDebug();
+
+// Initialize phpCAS
+phpCAS::proxy(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context);
+
+// For production use set the CA certificate that is the issuer of the cert
+// on the CAS server and uncomment the line below
+// phpCAS::setCasServerCACert($cas_server_ca_cert_path);
+
+// For quick testing you can disable SSL validation of the CAS server.
+// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
+// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
+phpCAS::setNoCasServerValidation();
+
+// 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/'
+// )));
+phpCAS::allowProxyChain(new CAS_ProxyChain(array($pgtUrlRegexp)));
+
+// 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.
+//phpcas::allowProxyChain(new CAS_ProxyChain_Any);
+
+// force CAS authentication
+phpCAS::forceAuthentication();
+
+// at this step, the user has been authenticated by the CAS server
+// and the user's login name can be read with phpCAS::getUser().
+
+// moreover, a PGT was retrieved from the CAS server that will
+// permit to gain accesses to new services.
+
+
+
+?>
+<html>
+ <head>
+ <title>phpCAS proxied proxy service example</title>
+ <link rel="stylesheet" type='text/css' href='example.css'/>
+ </head>
+ <body>
+ <h1>I am a service that can be proxied. In turn, I proxy another service.</h1>
+ <?php require 'script_info.php' ?>
+ <p>the user's login is <b><?php echo phpCAS::getUser(); ?></b>.</p>
+ <h2>Response from service <?php echo $serviceUrl; ?></h2>
+<?php
+ flush();
+ // call a service and change the color depending on the result
+if ( phpCAS::serviceWeb($serviceUrl, $err_code, $output) ) {
+ echo '<div class="success">';
+} else {
+ echo '<div class="error">';
+}
+ echo $output;
+ echo '</div>';
+?>
+ </body>
+</html>
+
--- /dev/null
+<?php
+
+/**
+ * Example for a simple cas 2.0 client
+ *
+ * PHP Version 5
+ *
+ * @file example_simple.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */
+
+// Load the settings from the central config file
+require_once 'config.php';
+// Load the CAS lib
+require_once $phpcas_path . '/CAS.php';
+
+// Uncomment to enable debugging
+phpCAS::setDebug();
+
+// Initialize phpCAS
+phpCAS::client(CAS_VERSION_2_0, $cas_host, $cas_port, $cas_context);
+
+// For production use set the CA certificate that is the issuer of the cert
+// on the CAS server and uncomment the line below
+// phpCAS::setCasServerCACert($cas_server_ca_cert_path);
+
+// For quick testing you can disable SSL validation of the CAS server.
+// THIS SETTING IS NOT RECOMMENDED FOR PRODUCTION.
+// VALIDATING THE CAS SERVER IS CRUCIAL TO THE SECURITY OF THE CAS PROTOCOL!
+phpCAS::setNoCasServerValidation();
+
+// force CAS authentication
+phpCAS::forceAuthentication();
+
+// at this step, the user has been authenticated by the CAS server
+// and the user's login name can be read with phpCAS::getUser().
+
+// logout if desired
+if (isset($_REQUEST['logout'])) {
+ phpCAS::logout();
+}
+
+// for this test, simply print that the authentication was successfull
+?>
+<html>
+ <head>
+ <title>phpCAS simple client</title>
+ </head>
+ <body>
+ <h1>Successfull Authentication!</h1>
+ <?php require 'script_info.php' ?>
+ <p>the user's login is <b><?php echo phpCAS::getUser(); ?></b>.</p>
+ <p>phpCAS version is <b><?php echo phpCAS::getVersion(); ?></b>.</p>
+ <p><a href="?logout=">Logout</a></p>
+ </body>
+</html>
--- /dev/null
+<?php
+/**
+ * Small script to add some info about the example script that is running.
+ * Adds some info that makes it easier to distinguish different proxy sessions
+ *
+ * PHP Version 5
+ *
+ * @file script_info.php
+ * @category Authentication
+ * @package PhpCAS
+ * @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
+ */ ?>
+ <dl style='border: 1px dotted; padding: 5px;'>
+ <dt>Current script</dt><dd><?php print basename($_SERVER['SCRIPT_NAME']); ?></dd>
+ <dt>session_name():</dt><dd> <?php print session_name(); ?></dd>
+ <dt>session_id():</dt><dd> <?php print session_id(); ?></dd>
+ </dl>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\r
+ <head>\r
+ <title>phpCAS</title>\r
+ </head>\r
+ <body>\r
+ <p><img src="images/phpcas.png" width="191" height="68"/></p>\r
+ <p>phpCAS documentation is hosted at <a href="https://wiki.jasig.org/display/CASC/phpCAS">https://wiki.jasig.org/display/CASC/phpCAS</a>.</p>\r
+ <ul>\r
+ <li><a href="examples">examples</a></li>\r
+ <li><a href="http://downloads.jasig.org/cas-clients/php/1.3.2/docs/api/">source documentation</a></li>\r
+ </ul>\r
+ <p><img src="images/esup-portail.png" width="182" height="68"/> <img src="images/jasig.png" width="169" height="87"/></p>\r
+ <p> </p>\r
+ </body>\r
+</html>\r
+ \r
* Compatible with Piwik 2.1
* Removed the "additional root logins" option (Piwik handles multiple superusers natively now)
* Added custom CAS login image
+ * Upgrade to phpCAS-1.3.2
0.6.3
* Bugfix: Added $this->setBasicVariablesView($view) to Controller.php to fix missing variables issue