diff --git a/bakery.inc b/bakery.inc index 8701197..366f4be 100644 --- a/bakery.inc +++ b/bakery.inc @@ -21,20 +21,40 @@ class Bakery { // Optional debug messaging. Drupal dependant. protected $debug; + /** + * Bakery cookie namanger. + * + * @var ICookieManager + */ + private $cookie_manager; + // Holds an instance of the Bakery object. protected static $instance = NULL; - public function __construct($is_master, $domain, $key, $options = array()) { + public function __construct($is_master, $domain, $key, $cookie_manager, $options = array()) { + // Provide default options. + $options += array( + 'sso_cookie' => 'BAKERYSSO', + 'login_cookie' => 'BAKERYLOG', + 'registration_cookie' => 'BAKERYREG', + 'lifetime' => 3600, + 'expiration' => 3600 * 24 * 7, + 'slaves' => array(), + 'debug' => FALSE, + ); + $this->isMaster = $is_master; $this->domain = $domain; $this->key = $key; - $this->SsoCookieName = isset($options['sso_cookie']) ? $options['sso_cookie'] : 'BAKERYSSO'; - $this->loginCookieName = isset($options['login_cookie']) ? $options['login_cookie'] : 'BAKERYLOG'; - $this->registrationCookieName = isset($options['registration_cookie']) ? $options['registration_cookie'] : 'BAKERYREG'; - $this->lifetime = isset($options['lifetime']) ? $options['lifetime'] : 3600; - $this->expiration = isset($options['expiration']) ? $options['expiration'] : 3600 * 24 * 7; - $this->slaves = isset($options['slaves']) ? $options['slaves'] : array(); - $this->debug = isset($options['debug']) ? $options['debug'] : FALSE; + $this->SsoCookieName = $options['sso_cookie']; + $this->loginCookieName = $optiosn['login_cookie']; + $this->registrationCookieName = $options['registration_cookie']; + $this->lifetime = $options['lifetime']; + $this->expiration = $options['expiration']; + $this->slaves = $options['slaves']; + $this->debug = $options['debug']; + + $this->setCookieManager($cookie_manager); } /** @@ -43,18 +63,39 @@ class Bakery { * @param bool $master Whether this site is a Bakery master or not. * @param string $domain Bakery domain. * @param string $key Per-cluster Bakery secret key. + * @param ICookieManager $cookie_manager Cookie manager. * @param array Array of Bakery optional settings. * * @return Bakery object. */ - public static function instance($is_master, $domain, $key, $options = array()) { + public static function instance($is_master, $domain, $key, ICookieManager $cookie_manager, $options = array()) { if (!self::$instance) { - self::$instance = new self($is_master, $domain, $key, $options); + self::$instance = new self($is_master, $domain, $key, $cookie_manager, $options); } return self::$instance; } /** + * Retrieve cookie mananger. + * + * @return ICookieManager + * Cookie manager. + */ + public function getCookieManager() { + return $this->cookie_manager; + } + + /** + * Set new cookie manager. + * + * @param ICookieManager $manager + * Cookie manager. + */ + public function setCookieManager(ICookieManager $cookie_manager) { + $this->cookie_manager = $cookie_manager; + } + + /** * Create SSO cookie for account. * * @param User account object. @@ -131,13 +172,13 @@ class Bakery { $key = $this->key; $type = $this->SsoCookieName; - if (!isset($_COOKIE[$type]) || !$key || !$this->domain) { + if (!$this->cookie_manager->get($type) || !$key || !$this->domain) { // No cookie is set or site is misconfigured. Return NULL so existing // cookie is not deleted. return NULL; } try { - $data = $this->validateData($_COOKIE[$type], $type); + $data = $this->validateData($this->cookie_manager->get($type), $type); $this->debug('in validate', $data); return $data; } @@ -166,8 +207,8 @@ class Bakery { * @param string $data Cookie data. */ protected function setCookie($name, $data) { - $cookie_secure = ini_get('session.cookie_secure'); - setcookie($name, $data, $_SERVER['REQUEST_TIME'] + $this->expiration, '/', $this->domain, (empty($cookie_secure) ? FALSE : TRUE)); + drupal_alter('bakery_cookie', $data, $name);; + $this->cookie_manager->set($name, $data, $_SERVER['REQUEST_TIME'] + $this->expiration, '/'); } /** @@ -176,9 +217,7 @@ class Bakery { * @param string $name Cookie name. */ protected function deleteCookie($name) { - $cookie_secure = ini_get('session.cookie_secure'); - setcookie($name, '', $_SERVER['REQUEST_TIME'] - 3600, '/', '', (empty($cookie_secure) ? FALSE : TRUE)); - setcookie($name, '', $_SERVER['REQUEST_TIME'] - 3600, '/', $this->domain, (empty($cookie_secure) ? FALSE : TRUE)); + $this->cookie_manager->delete($name); } /** diff --git a/bakery.info b/bakery.info index 77ee767..4ebab33 100644 --- a/bakery.info +++ b/bakery.info @@ -3,4 +3,5 @@ description = Provides single-sign-on support across second-level domains. core = 7.x files[] = bakery.module files[] = bakery.inc +files[] = includes/cookie_manager.inc php = 5.1.2 diff --git a/bakery.module b/bakery.module index 353c9fd..3a74f03 100644 --- a/bakery.module +++ b/bakery.module @@ -85,7 +85,8 @@ function bakery_get_bakery() { 'expiration' => variable_get('bakery_expiration', 3600 * 24 * 7), 'debug' => variable_get('bakery_debug', FALSE), ); - return Bakery::instance($is_master, $domain, $key, $options); + $cookie_manager = new BakeryHttpCookieManager($domain, ini_get('session.cookie_secure')); + return Bakery::instance($is_master, $domain, $key, $cookie_manager, $options); } /** @@ -555,6 +556,7 @@ function bakery_login() { else { // Passed all checks, create identification cookie and log in. $init = _bakery_init_field($account->uid); + $bakery = bakery_get_bakery(); _bakery_bake_chocolatechip_cookie($account->name, $account->mail, $init); global $user; $user = $account; diff --git a/includes/cookie_manager.inc b/includes/cookie_manager.inc new file mode 100644 index 0000000..ffc9420 --- /dev/null +++ b/includes/cookie_manager.inc @@ -0,0 +1,134 @@ +domain = $domain; + $this->secure = (bool) $secure; + $this->httponly = $httponly; + } + + /** + * Read cookie. + * + * @inherit + */ + public function get($name) { + $this->debug('get', $name); + return isset($_COOKIE[$name]) ? $_COOKIE[$name] : NULL; + } + + /** + * Set a cookie. + */ + public function set($name, $value, $expire = 0, $path = NULL) { + $this->debug('write', array($name, $value, $expire, $path)); + setcookie($name, $value, $expire, $path, $this->domain, $this->secure, $this->httponly); + } + + /** + * Delete the cookie. + */ + public function delete($name) { + $this->debug('delete', $name); + setcookie($name, '', $_SERVER['REQUEST_TIME'] - 3600, '/', '', $this->secure); + setcookie($name, '', $_SERVER['REQUEST_TIME'] - 3600, '/', $this->domain, $this->secure); + } + + protected function debug($name, $value = NULL) { + if ($this->debug) { + watchdog('bakery_cookie_manager', "@name =>
@value
", array( + '@name' => $name, '@value' => print_r($value, TRUE)), WATCHDOG_NOTICE); + } + } +}