* @copyright Copyright © 2008 Peter Adams * @license http://www.gnu.org/copyleft/gpl.html GPL v2.0 * @category owa * @package owa * @version $Revision$ * @since owa 1.0.0 */ class owa_state { var $stores = array(); var $stores_meta = array(); var $is_dirty; var $dirty_stores; var $default_store_type = 'cookie'; var $stores_with_cdh = array('c','v','s'); var $store_formats = array ('v' => 'assoc', 's' => 'assoc'); var $initial_state = array(); function __construct() { } function __destruct() { $this->persistState(); } function persistState() { return false; } function get($store, $name = '') { owa_coreAPI::debug("Getting state - store: ".$store.' key: '.$name); if ( ! isset($this->stores[$store] ) ) { $this->loadState($store); } if (array_key_exists($store, $this->stores)) { if (!empty($name)) { // check to ensure this is an array, could be a string. if (is_array($this->stores[$store]) && array_key_exists($name, $this->stores[$store])) { return $this->stores[$store][$name]; } else { return false; } } else { return $this->stores[$store]; } } else { return false; } } function setState($store, $name = '', $value, $store_type = '', $is_perminent = false) { owa_coreAPI::debug(sprintf('populating state for store: %s, name: %s, value: %s, store type: %s, is_perm: %s', $store, $name, print_r($value, true), $store_type, $is_perminent)); // first call to set for a store sets the meta if (!array_key_exists($store, $this->stores)) { if (empty($store_type)) { $store_type = $this->default_store_type; } $this->stores_meta[$store]['type'] = $store_type; if ($is_perminent === true) { $this->stores_meta[$store]['is_perminent'] = true; } } // set values if (empty($name)) { $this->stores[$store] = $value; //owa_coreAPI::debug(print_r($this->stores, true)); } else { //just in case the store was set first as a string instead of as an array. if ( array_key_exists($store, $this->stores)) { if ( ! is_array( $this->stores[$store] ) ) { $new_store = array(); // check to see if we need ot ad a cdh if ( $this->isCdhRequired($store) ) { $new_store['cdh'] = $this->getCookieDomainHash(); } $new_store[$name] = $value; $this->stores[$store] = $new_store; } else { $this->stores[$store][$name] = $value; } // if the store does not exist then maybe add a cdh and the value } else { if ( $this->isCdhRequired($store) ) { $this->stores[$store]['cdh'] = $this->getCookieDomainHash(); } $this->stores[$store][$name] = $value; } } $this->dirty_stores[] = $store; //owa_coreAPI::debug(print_r($this->stores, true)); } function isCdhRequired($store_name) { return in_array( $store_name, $this->stores_with_cdh ); } function set($store, $name = '', $value, $store_type = '', $is_perminent = false) { if ( ! isset($this->stores[$store] ) ) { $this->loadState($store); } $this->setState($store, $name, $value, $store_type, $is_perminent); // persist immeadiately if the store type is cookie if ($this->stores_meta[$store]['type'] === 'cookie') { $time = 0; // needed? i dont think so. if (isset($this->stores_meta[$store]['is_perminent']) && $this->stores_meta[$store]['is_perminent'] === true) { $time = $this->getPermExpiration(); } elseif (isset($this->stores_meta[$store]['is_perminent']) && $this->stores_meta[$store]['is_perminent'] > 0) { $time = $this->stores_meta[$store]['is_perminent'] * 3600 * 24; } if ($is_perminent === true) { $time = $this->getPermExpiration(); } // transform state array into a string using proper format if ( is_array( $this->stores[$store] ) ) { // check for old style assoc format if (isset($this->store_formats[$store]) && $this->store_formats[$store] === 'assoc') { $cookie_value = owa_lib::implode_assoc('=>', '|||', $this->stores[$store] ); } else { $cookie_value = json_encode( $this->stores[$store] ); } } owa_coreAPI::createCookie($store, $this->stores[$store], $time, "/", owa_coreAPI::getSetting('base', 'cookie_domain')); } } function setInitialState($store, $value, $store_type) { if ($value) { $this->initial_state[$store] = $value; } } function loadState($store, $name = '', $value = '', $store_type = 'cookie') { if ( ! $value && isset( $this->initial_state[$store] ) ) { $value = $this->initial_state[$store]; } else { return; } // check format of value if (strpos($value, "|||")) { $value = owa_lib::assocFromString($value); } else if (strpos($value, '{')) { $value = json_decode($value); } else { $value = $value; } if ( in_array( $store, $this->stores_with_cdh ) ) { if ( is_array( $value ) && isset( $value['cdh'] ) ) { $runtime_cdh = $this->getCookieDomainHash(); $cdh_from_state = $value['cdh']; // return as the cdh's do not match if ( $cdh_from_state != $runtime_cdh ) { // cookie domains do not match so we need to delete the cookie in the offending domain // which is always likely to be a sub.domain.com and thus HTTP_HOST. // if ccokie is not deleted then new cookies set on .domain.com will never be seen by PHP // as only the sub domain cookies are available. owa_coreAPI::debug("Not loading state store: $store. Domain hashes do not match - runtime: $runtime_cdh, cookie: $cdh_from_state"); owa_coreAPI::debug("deleting cookie: owa_$store"); owa_coreAPI::deleteCookie($store,'/', $_SERVER['HTTP_HOST']); unset($this->initial_state[$store]); return; } } else { owa_coreAPI::debug("Not loading state store: $store. No domain hash found."); return; } } return $this->setState($store, $name, $value, $store_type); } function clear($store) { if ( ! isset($this->stores[$store] ) ) { $this->loadState($store); } if (array_key_exists($store, $this->stores)) { unset($this->stores[$store]); if ($this->stores_meta[$store]['type'] === 'cookie') { return owa_coreAPI::deleteCookie($store); } } } function getPermExpiration() { $time = time()+3600*24*365*15; return $time; } function addStores($array) { $this->stores = array_merge($this->stores, $array); return; } function getCookieDomainHash($domain = '') { if ( ! $domain ) { $domain = owa_coreAPI::getSetting( 'base', 'cookie_domain' ); } return owa_lib::crc32AsHex($domain); } } ?>