File indexing completed on 2024-12-22 05:37:05
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Service_WindowsAzure 0017 * @subpackage Session 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 /** 0024 * @category Zend 0025 * @package Zend_Service_WindowsAzure 0026 * @subpackage Session 0027 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0028 * @license http://framework.zend.com/license/new-bsd New BSD License 0029 */ 0030 class Zend_Service_WindowsAzure_SessionHandler 0031 { 0032 /** 0033 * Maximal property size in table storage. 0034 * 0035 * @var int 0036 * @see http://msdn.microsoft.com/en-us/library/dd179338.aspx 0037 */ 0038 const MAX_TS_PROPERTY_SIZE = 65536; 0039 0040 /** Storage backend type */ 0041 const STORAGE_TYPE_TABLE = 'table'; 0042 const STORAGE_TYPE_BLOB = 'blob'; 0043 0044 /** 0045 * Storage back-end 0046 * 0047 * @var Zend_Service_WindowsAzure_Storage_Table|Zend_Service_WindowsAzure_Storage_Blob 0048 */ 0049 protected $_storage; 0050 0051 /** 0052 * Storage backend type 0053 * 0054 * @var string 0055 */ 0056 protected $_storageType; 0057 0058 /** 0059 * Session container name 0060 * 0061 * @var string 0062 */ 0063 protected $_sessionContainer; 0064 0065 /** 0066 * Session container partition 0067 * 0068 * @var string 0069 */ 0070 protected $_sessionContainerPartition; 0071 0072 /** 0073 * Creates a new Zend_Service_WindowsAzure_SessionHandler instance 0074 * 0075 * @param Zend_Service_WindowsAzure_Storage_Table|Zend_Service_WindowsAzure_Storage_Blob $storage Storage back-end, can be table storage and blob storage 0076 * @param string $sessionContainer Session container name 0077 * @param string $sessionContainerPartition Session container partition 0078 */ 0079 public function __construct(Zend_Service_WindowsAzure_Storage $storage, $sessionContainer = 'phpsessions', $sessionContainerPartition = 'sessions') 0080 { 0081 // Validate $storage 0082 if (!($storage instanceof Zend_Service_WindowsAzure_Storage_Table || $storage instanceof Zend_Service_WindowsAzure_Storage_Blob)) { 0083 // require_once 'Zend/Service/WindowsAzure/Exception.php'; 0084 throw new Zend_Service_WindowsAzure_Exception('Invalid storage back-end given. Storage back-end should be of type Zend_Service_WindowsAzure_Storage_Table or Zend_Service_WindowsAzure_Storage_Blob.'); 0085 } 0086 0087 // Validate other parameters 0088 if ($sessionContainer == '' || $sessionContainerPartition == '') { 0089 // require_once 'Zend/Service/WindowsAzure/Exception.php'; 0090 throw new Zend_Service_WindowsAzure_Exception('Session container and session partition should be specified.'); 0091 } 0092 0093 // Determine storage type 0094 $storageType = self::STORAGE_TYPE_TABLE; 0095 if ($storage instanceof Zend_Service_WindowsAzure_Storage_Blob) { 0096 $storageType = self::STORAGE_TYPE_BLOB; 0097 } 0098 0099 // Set properties 0100 $this->_storage = $storage; 0101 $this->_storageType = $storageType; 0102 $this->_sessionContainer = $sessionContainer; 0103 $this->_sessionContainerPartition = $sessionContainerPartition; 0104 } 0105 0106 /** 0107 * Registers the current session handler as PHP's session handler 0108 * 0109 * @return boolean 0110 */ 0111 public function register() 0112 { 0113 return session_set_save_handler(array($this, 'open'), 0114 array($this, 'close'), 0115 array($this, 'read'), 0116 array($this, 'write'), 0117 array($this, 'destroy'), 0118 array($this, 'gc') 0119 ); 0120 } 0121 0122 /** 0123 * Open the session store 0124 * 0125 * @return bool 0126 */ 0127 public function open() 0128 { 0129 // Make sure storage container exists 0130 if ($this->_storageType == self::STORAGE_TYPE_TABLE) { 0131 $this->_storage->createTableIfNotExists($this->_sessionContainer); 0132 } else if ($this->_storageType == self::STORAGE_TYPE_BLOB) { 0133 $this->_storage->createContainerIfNotExists($this->_sessionContainer); 0134 } 0135 0136 // Ok! 0137 return true; 0138 } 0139 0140 /** 0141 * Close the session store 0142 * 0143 * @return bool 0144 */ 0145 public function close() 0146 { 0147 return true; 0148 } 0149 0150 /** 0151 * Read a specific session 0152 * 0153 * @param int $id Session Id 0154 * @return string 0155 */ 0156 public function read($id) 0157 { 0158 // Read data 0159 if ($this->_storageType == self::STORAGE_TYPE_TABLE) { 0160 // In table storage 0161 try 0162 { 0163 $sessionRecord = $this->_storage->retrieveEntityById( 0164 $this->_sessionContainer, 0165 $this->_sessionContainerPartition, 0166 $id 0167 ); 0168 return unserialize(base64_decode($sessionRecord->serializedData)); 0169 } 0170 catch (Zend_Service_WindowsAzure_Exception $ex) 0171 { 0172 return ''; 0173 } 0174 } else if ($this->_storageType == self::STORAGE_TYPE_BLOB) { 0175 // In blob storage 0176 try 0177 { 0178 $data = $this->_storage->getBlobData( 0179 $this->_sessionContainer, 0180 $this->_sessionContainerPartition . '/' . $id 0181 ); 0182 return unserialize(base64_decode($data)); 0183 } 0184 catch (Zend_Service_WindowsAzure_Exception $ex) 0185 { 0186 return false; 0187 } 0188 } 0189 } 0190 0191 /** 0192 * Write a specific session 0193 * 0194 * @param int $id Session Id 0195 * @param string $serializedData Serialized PHP object 0196 * @throws Exception 0197 */ 0198 public function write($id, $serializedData) 0199 { 0200 // Encode data 0201 $serializedData = base64_encode(serialize($serializedData)); 0202 if (strlen($serializedData) >= self::MAX_TS_PROPERTY_SIZE && $this->_storageType == self::STORAGE_TYPE_TABLE) { 0203 throw new Zend_Service_WindowsAzure_Exception('Session data exceeds the maximum allowed size of ' . self::MAX_TS_PROPERTY_SIZE . ' bytes that can be stored using table storage. Consider switching to a blob storage back-end or try reducing session data size.'); 0204 } 0205 0206 // Store data 0207 if ($this->_storageType == self::STORAGE_TYPE_TABLE) { 0208 // In table storage 0209 $sessionRecord = new Zend_Service_WindowsAzure_Storage_DynamicTableEntity($this->_sessionContainerPartition, $id); 0210 $sessionRecord->sessionExpires = time(); 0211 $sessionRecord->serializedData = $serializedData; 0212 0213 $sessionRecord->setAzurePropertyType('sessionExpires', 'Edm.Int32'); 0214 0215 try 0216 { 0217 $this->_storage->updateEntity($this->_sessionContainer, $sessionRecord); 0218 } 0219 catch (Zend_Service_WindowsAzure_Exception $unknownRecord) 0220 { 0221 $this->_storage->insertEntity($this->_sessionContainer, $sessionRecord); 0222 } 0223 } else if ($this->_storageType == self::STORAGE_TYPE_BLOB) { 0224 // In blob storage 0225 $this->_storage->putBlobData( 0226 $this->_sessionContainer, 0227 $this->_sessionContainerPartition . '/' . $id, 0228 $serializedData, 0229 array('sessionexpires' => time()) 0230 ); 0231 } 0232 } 0233 0234 /** 0235 * Destroy a specific session 0236 * 0237 * @param int $id Session Id 0238 * @return boolean 0239 */ 0240 public function destroy($id) 0241 { 0242 // Destroy data 0243 if ($this->_storageType == self::STORAGE_TYPE_TABLE) { 0244 // In table storage 0245 try 0246 { 0247 $sessionRecord = $this->_storage->retrieveEntityById( 0248 $this->_sessionContainer, 0249 $this->_sessionContainerPartition, 0250 $id 0251 ); 0252 $this->_storage->deleteEntity($this->_sessionContainer, $sessionRecord); 0253 0254 return true; 0255 } 0256 catch (Zend_Service_WindowsAzure_Exception $ex) 0257 { 0258 return false; 0259 } 0260 } else if ($this->_storageType == self::STORAGE_TYPE_BLOB) { 0261 // In blob storage 0262 try 0263 { 0264 $this->_storage->deleteBlob( 0265 $this->_sessionContainer, 0266 $this->_sessionContainerPartition . '/' . $id 0267 ); 0268 0269 return true; 0270 } 0271 catch (Zend_Service_WindowsAzure_Exception $ex) 0272 { 0273 return false; 0274 } 0275 } 0276 } 0277 0278 /** 0279 * Garbage collector 0280 * 0281 * @param int $lifeTime Session maximal lifetime 0282 * @see session.gc_divisor 100 0283 * @see session.gc_maxlifetime 1440 0284 * @see session.gc_probability 1 0285 * @usage Execution rate 1/100 (session.gc_probability/session.gc_divisor) 0286 * @return boolean 0287 */ 0288 public function gc($lifeTime) 0289 { 0290 if ($this->_storageType == self::STORAGE_TYPE_TABLE) { 0291 // In table storage 0292 try 0293 { 0294 $result = $this->_storage->retrieveEntities($this->_sessionContainer, 'PartitionKey eq \'' . $this->_sessionContainerPartition . '\' and sessionExpires lt ' . (time() - $lifeTime)); 0295 foreach ($result as $sessionRecord) 0296 { 0297 $this->_storage->deleteEntity($this->_sessionContainer, $sessionRecord); 0298 } 0299 return true; 0300 } 0301 catch (Zend_Service_WindowsAzure_exception $ex) 0302 { 0303 return false; 0304 } 0305 } else if ($this->_storageType == self::STORAGE_TYPE_BLOB) { 0306 // In blob storage 0307 try 0308 { 0309 $result = $this->_storage->listBlobs($this->_sessionContainer, $this->_sessionContainerPartition, '', null, null, 'metadata'); 0310 foreach ($result as $sessionRecord) 0311 { 0312 if ($sessionRecord->Metadata['sessionexpires'] < (time() - $lifeTime)) { 0313 $this->_storage->deleteBlob($this->_sessionContainer, $sessionRecord->Name); 0314 } 0315 } 0316 return true; 0317 } 0318 catch (Zend_Service_WindowsAzure_exception $ex) 0319 { 0320 return false; 0321 } 0322 } 0323 } 0324 }