Permalink
Browse files

#14 Fix coding style

  • Loading branch information...
1 parent e8349aa commit cdf4e14146935b7738cf17673a60e96b88e06090 @jfritschi jfritschi committed Dec 11, 2011
View
10 CAS.php
@@ -4,19 +4,21 @@
* 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.php
* @category Authentication
* @package PhpCAS
View
135 source/CAS/AuthenticationException.php
@@ -4,70 +4,103 @@
* 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
+extends RuntimeException
+implements CAS_Exception
{
- /**
- * This method is used to print the HTML output when the user was not authenticated.
- *
- * @param $client phpcas client
- * @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
- */
- 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();
- }
-
+ /**
+ * 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 boolean $no_response the response from the CAS server (other
+ * parameters are ignored if TRUE)
+ * @param boolean $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 integer $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();
+ }
+
}
?>
View
15 source/CAS/Autoload.php
@@ -2,9 +2,10 @@
/**
* Autoloader Class
- *
+ *
* PHP Version 5
- *
+ *
+ * @file CAS/Autoload.php
* @category Authentication
* @package SimpleCAS
* @author Brett Bieber <brett.bieber@gmail.com>
@@ -15,9 +16,9 @@
/**
* Autoload a class
- *
+ *
* @param string $class Classname to load
- *
+ *
* @return boolean
*/
function CAS_autoload($class)
@@ -71,12 +72,12 @@ function CAS_autoload($class)
}
unset($_____t);
} elseif (!function_exists('__autoload')) {
-
+
/**
* Autoload a class
- *
+ *
* @param string $class Class name
- *
+ *
* @return boolean
*/
function __autoload($class)
View
299 source/CAS/Client.php
@@ -4,13 +4,13 @@
* 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.
@@ -61,9 +61,9 @@ class CAS_Client
*/
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);
+ $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;
}
@@ -86,7 +86,8 @@ private function HTMLFilterOutput($str)
*/
public function printHTMLHeader($title)
{
- $this->HTMLFilterOutput(str_replace('__TITLE__',
+ $this->HTMLFilterOutput(str_replace(
+ '__TITLE__',
$title,
(empty($this->_output_header)
? '<html><head><title>__TITLE__</title></head><body><h1>__TITLE__</h1>'
@@ -137,8 +138,8 @@ public function setHTMLFooter($footer)
{
$this->_output_footer = $footer;
}
-
-
+
+
/** @} */
@@ -170,7 +171,7 @@ public function setLang($lang)
$this->_lang = $lang;
}
/**
- * Create the language
+ * Create the language
* @return Class implementing the CAS_Languages_LanguageInterface
*/
public function getLangObj(){
@@ -373,12 +374,12 @@ public function getServerSamlValidateURL()
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 a URL.
@@ -401,7 +402,7 @@ public function getServerProxyValidateURL()
phpCAS::traceEnd($url);
return $url;
}
-
+
/**
* This method is used to retrieve the proxy URL of the CAS server.
@@ -458,18 +459,18 @@ 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.
@@ -492,13 +493,13 @@ public function setRequestImplementation ($className) {
$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
@@ -511,31 +512,31 @@ public function setRequestImplementation ($className) {
public function setNoClearTicketsFromUrl () {
$this->_clearTicketsFromUrl = false;
}
-
+
/**
- * @var callback $_postAuthenticateCallbackFunction;
+ * @var callback $_postAuthenticateCallbackFunction;
*/
private $_postAuthenticateCallbackFunction = null;
-
+
/**
- * @var array $_postAuthenticateCallbackArgs;
+ * @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
+ * 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 callback $function
* @param optional array $additionalArgs
* @return void
@@ -544,26 +545,26 @@ public function setPostAuthenticateCallback ($function, array $additionalArgs =
$this->_postAuthenticateCallbackFunction = $function;
$this->_postAuthenticateCallbackArgs = $additionalArgs;
}
-
+
/**
- * @var callback $_signoutCallbackFunction;
+ * @var callback $_signoutCallbackFunction;
*/
private $_signoutCallbackFunction = null;
-
+
/**
- * @var array $_signoutCallbackArgs;
+ * @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
+ * to support single-signout in applications that manage their own sessions
* (rather than letting phpCAS start and destroy the session).
- *
+ *
* @param callback $function
* @param optional array $additionalArgs
* @return void
@@ -572,16 +573,16 @@ public function setSingleSignoutCallback ($function, array $additionalArgs = arr
$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 boolean $result True if authentication was successful, false otherwise.
* @return null
*/
@@ -596,76 +597,76 @@ public function markAuthenticationCall ($auth) {
);
}
private $_authentication_caller;
-
+
/**
* Answer true if authentication has been checked.
- *
+ *
* @return boolean
*/
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 boolean
*/
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'];
}
-
+
/** @} */
// ########################################################################
@@ -675,7 +676,7 @@ public function getAuthenticationCallerMethod () {
* @addtogroup internalConfig
* @{
*/
-
+
/**
* CAS_Client constructor.
*
@@ -704,7 +705,7 @@ public function __construct(
{
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");
+ " session handling to phpcas");
}
// skip Session Handling for logout requests and if don't want it'
if ($start_session && !$this->isLogoutRequest())
@@ -787,7 +788,7 @@ public function __construct(
//ill-formed ticket, halt
phpCAS::error('ill-formed ticket found in the URL (ticket=`'.htmlentities($ticket).'\')');
}
-
+
}
phpCAS::traceEnd();
}
@@ -804,8 +805,8 @@ public function __construct(
* @addtogroup internalConfig
* @{
*/
-
-
+
+
/**
* A variable to whether phpcas will use its own session handling. Default = true
* @hideinitializer
@@ -823,7 +824,7 @@ public function getStartSession()
}
/** @} */
-
+
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
// XX XX
// XX AUTHENTICATION XX
@@ -989,7 +990,7 @@ public function checkAuthentication()
// 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))
{
@@ -1173,13 +1174,13 @@ private function wasPreviouslyAuthenticated()
}
$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']).'"');
+ 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
@@ -1205,13 +1206,13 @@ private function wasPreviouslyAuthenticated()
$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']).'"');
+ phpCAS::trace('proxies = "'.implode('", "', $_SESSION['phpCAS']['proxies']).'"');
}
-
+
$auth = TRUE;
} else {
phpCAS::trace('no user found');
@@ -1240,7 +1241,7 @@ public function redirectToCas($gateway=false,$renew=false){
$this->printHTMLHeader($lang->getAuthenticationWanted());
printf('<p>'.$lang->getShouldHaveBeenRedirected().'</p>',$cas_url);
$this->printHTMLFooter();
- phpCAS::traceExit();
+ phpCAS::traceExit();
throw new CAS_GracefullTerminationException();
}
@@ -1508,18 +1509,18 @@ public function validateCAS10(&$validate_url,&$text_response,&$tree_response)
$this->setUser(trim($arr[1]));
$result = TRUE;
break;
-
+
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
// ########################################################################
@@ -1675,7 +1676,7 @@ private function setSessionAttributes($text_response)
phpCAS::traceEnd($result);
return $result;
}
-
+
/** @} */
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
@@ -1863,13 +1864,13 @@ private function callback()
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
+ // 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();
}
-
+
/** @} */
@@ -2147,18 +2148,18 @@ public function retrievePT($target_service,&$err_code,&$err_msg)
phpCAS::traceEnd(FALSE);
return FALSE;
}
-
+
/** @} */
// ########################################################################
// READ CAS SERVER ANSWERS
// ########################################################################
-
+
/**
* @addtogroup internalMisc
* @{
*/
-
+
/**
* This method is used to acces a remote URL.
*
@@ -2181,7 +2182,7 @@ private function readURL($url, &$headers, &$body, &$err_msg)
}
$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.');
}
@@ -2241,28 +2242,28 @@ public function _curl_read_headers($ch, $header)
$this->_curl_headers[] = $header;
return strlen($header);
}
-
+
/** @} **/
-
+
// ########################################################################
// 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.
*/
@@ -2271,7 +2272,7 @@ public function getProxiedService ($type) {
case PHPCAS_PROXIED_SERVICE_HTTP_GET:
case PHPCAS_PROXIED_SERVICE_HTTP_POST:
$requestClass = $this->_requestImplementation;
- $request = new $requestClass();
+ $request = new $requestClass();
if (count($this->_curl_options)) {
$request->setCurlOptions($this->_curl_options);
}
@@ -2288,15 +2289,15 @@ public function getProxiedService ($type) {
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
* @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
+ * 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.
@@ -2305,7 +2306,7 @@ 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);
@@ -2370,7 +2371,7 @@ public function serviceMail($url,$serviceUrl,$flags,&$err_code,&$err_msg,&$pt)
$service->setServiceUrl($serviceUrl);
$service->setMailbox($url);
$service->setOptions($flags);
-
+
$stream = $service->open();
$err_code = PHPCAS_SERVICE_OK;
$pt = $service->getImapProxyTicket();
@@ -2404,7 +2405,7 @@ public function serviceMail($url,$serviceUrl,$flags,&$err_code,&$err_msg,&$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
@@ -2414,24 +2415,24 @@ public function serviceMail($url,$serviceUrl,$flags,&$err_code,&$err_msg,&$pt)
* @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
* @since 6/25/09
*/
public function getProxies () {
return $this->_proxies;
}
-
+
/**
* Set the Proxy array, probably from persistant storage.
- *
+ *
* @param array $proxies
* @return void
* @access private
@@ -2449,25 +2450,25 @@ private function setProxies ($proxies) {
$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
@@ -2609,8 +2610,8 @@ public function validateCAS20(&$validate_url,&$text_response,&$tree_response)
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.
@@ -2624,9 +2625,9 @@ 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>
@@ -2640,7 +2641,7 @@ private function readExtraAttributesCas20($success_elements)
// <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");
@@ -2651,23 +2652,23 @@ private function readExtraAttributesCas20($success_elements)
$this->addAttributeToArray($extra_attributes, $attr_child->localName, $attr_child->nodeValue);
}
}
- }
+ }
// "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>
- //
+ //
else {
phpCas :: trace("Testing for rubycas style attributes");
$childnodes = $success_elements->item(0)->childNodes;
@@ -2685,27 +2686,27 @@ private function readExtraAttributesCas20($success_elements)
}
}
}
-
+
// "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);
@@ -2720,15 +2721,15 @@ private function readExtraAttributesCas20($success_elements)
}
}
}
-
+
$this->setAttributes($extra_attributes);
phpCAS::traceEnd();
return TRUE;
}
-
+
/**
* Add an attribute value to an array of attributes.
- *
+ *
* @param ref array $array
* @param string $name
* @param string $value
@@ -2742,7 +2743,7 @@ private function addAttributeToArray (array &$attributeArray, $name, $value) {
$existingValue = $attributeArray[$name];
$attributeArray[$name] = array($existingValue);
}
-
+
$attributeArray[$name][] = trim($value);
} else {
$attributeArray[$name] = trim($value);
@@ -2773,7 +2774,7 @@ private function addAttributeToArray (array &$attributeArray, $name, $value) {
*/
private $_url = '';
-
+
/**
* This method sets the URL of the current request
*
@@ -2783,7 +2784,7 @@ public function setURL($url)
{
$this->_url = $url;
}
-
+
/**
* This method returns the URL of the current request (without any ticket
* CGI parameter).
@@ -2803,7 +2804,7 @@ public function getURL()
$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]);
@@ -2813,14 +2814,14 @@ public function getURL()
$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.
@@ -2877,21 +2878,21 @@ 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 $url base url to add the query params to
* @param $query params in query form with & separated
- * @return url with query params
+ * @return url with query params
*/
private function buildQueryUrl($url, $query) {
$url .= (strstr($url,'?') === FALSE) ? '?' : '&';
$url .= $query;
return $url;
}
-
+
/**
* Renaming the session
*/
@@ -2920,7 +2921,7 @@ private function renameSession($ticket)
phpCAS::traceEnd();
}
-
+
// ########################################################################
// AUTHENTICATION ERROR HANDLING
// ########################################################################
@@ -2967,43 +2968,43 @@ private function authError($failure,$cas_url,$no_response,$bad_response='',$cas_
}
$this->printHTMLFooter();
phpCAS::traceExit();
- throw new CAS_GracefullTerminationException();
+ 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.
- *
+ *
*/
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;
+ return self::IP;
} else {
phpCAS::traceEnd(self::HOSTNAME);
return self::HOSTNAME;
}
}
-
+
/**
* Store the rebroadcast node for pgtIou/pgtId and logout requests.
*
@@ -3022,35 +3023,35 @@ public function addRebroadcastNode($rebroadcastNodeUrl)
private $_rebroadcast_headers = array();
/**
- * This method is used to add header parameters when rebroadcasting
+ * This method is used to add header parameters when rebroadcasting
* pgtIou/pgtId or logoutRequest.
- *
+ *
* @param String $header Header to send when rebroadcasting.
*/
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.
*/
- private function rebroadcast($type) {
+ 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'];
@@ -3064,20 +3065,20 @@ private function rebroadcast($type) {
}
$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
@@ -3088,7 +3089,7 @@ private function rebroadcast($type) {
}
$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:''));
@@ -3100,7 +3101,7 @@ private function rebroadcast($type) {
}
phpCAS::traceEnd();
}
-
+
/** @} */
}
View
634 source/CAS/CookieJar.php
@@ -4,325 +4,353 @@
* 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 ref array $storageArray
- * @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 An 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'];
- // If max-age is zero, then the cookie should be removed imediately
- // so set an expiry before now.
- else
- $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 private
- */
- protected function storeCookie ($cookie) {
- // Discard any old versions of this cookie.
- $this->discardCookie($cookie);
- $this->_cookies[] = $cookie;
-
- }
-
- /**
- * Discard an existing cookie
- *
- * @param stdClass $cookie
- *
- * @return void
- *
- * @access private
- */
- 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 private
- */
- 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 boolean
- *
- * @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
- }
- // non-exact host-name matches.
- else {
- // 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;
- }
- }
- // If the cookie host doesn't begin with '.', the host must case-insensitive
- // match exactly
- else {
- 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;
+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'];
+ // If max-age is zero, then the cookie should be removed imediately
+ // so set an expiry before now.
+ else
+ $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 boolean
+ *
+ * @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;
}
}
View
35 source/CAS/Exception.php
@@ -4,18 +4,27 @@
* 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
*/
/**
@@ -27,14 +36,24 @@
*
* For example, an InvalidArgumentException in phpCAS should be defined as
*
- * class CAS_InvalidArgumentException
- * extends InvalidArgumentException
+ * class CAS_InvalidArgumentException
+ * extends InvalidArgumentException
* implements CAS_Exception
* { }
*
- * This definition allows the CAS_InvalidArgumentException to be caught as either
+ * 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 {
+interface CAS_Exception
+{
-}
+}
+?>
View
98 source/CAS/GracefullTerminationException.php
@@ -4,53 +4,83 @@
* 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
+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.
- */
- public function __construct ($message = 'Terminate Gracefully', $code = 0) {
- // Exit cleanly to avoid filling up the logs with uncaught exceptions.
- if (self::$exitWhenThrown) {
- exit;
- }
- // Throw exceptions to allow unit testing to continue;
- else {
- 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.
- */
- public static function throwInsteadOfExiting() {
- self::$exitWhenThrown = false;
- }
-
+ /**
+ * 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.