_storage = $storage; $this->_storageType = $storageType; $this->_sessionContainer = $sessionContainer; $this->_sessionContainerPartition = $sessionContainerPartition; } /** * Registers the current session handler as PHP's session handler * * @return boolean */ public function register() { return session_set_save_handler(array($this, 'open'), array($this, 'close'), array($this, 'read'), array($this, 'write'), array($this, 'destroy'), array($this, 'gc') ); } /** * Open the session store * * @return bool */ public function open() { // Make sure storage container exists if ($this->_storageType == self::STORAGE_TYPE_TABLE) { $this->_storage->createTableIfNotExists($this->_sessionContainer); } else if ($this->_storageType == self::STORAGE_TYPE_BLOB) { $this->_storage->createContainerIfNotExists($this->_sessionContainer); } // Ok! return true; } /** * Close the session store * * @return bool */ public function close() { return true; } /** * Read a specific session * * @param int $id Session Id * @return string */ public function read($id) { // Read data if ($this->_storageType == self::STORAGE_TYPE_TABLE) { // In table storage try { $sessionRecord = $this->_storage->retrieveEntityById( $this->_sessionContainer, $this->_sessionContainerPartition, $id ); return unserialize(base64_decode($sessionRecord->serializedData)); } catch (Zend_Service_WindowsAzure_Exception $ex) { return ''; } } else if ($this->_storageType == self::STORAGE_TYPE_BLOB) { // In blob storage try { $data = $this->_storage->getBlobData( $this->_sessionContainer, $this->_sessionContainerPartition . '/' . $id ); return unserialize(base64_decode($data)); } catch (Zend_Service_WindowsAzure_Exception $ex) { return false; } } } /** * Write a specific session * * @param int $id Session Id * @param string $serializedData Serialized PHP object * @throws Exception */ public function write($id, $serializedData) { // Encode data $serializedData = base64_encode(serialize($serializedData)); if (strlen($serializedData) >= self::MAX_TS_PROPERTY_SIZE && $this->_storageType == self::STORAGE_TYPE_TABLE) { 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.'); } // Store data if ($this->_storageType == self::STORAGE_TYPE_TABLE) { // In table storage $sessionRecord = new Zend_Service_WindowsAzure_Storage_DynamicTableEntity($this->_sessionContainerPartition, $id); $sessionRecord->sessionExpires = time(); $sessionRecord->serializedData = $serializedData; $sessionRecord->setAzurePropertyType('sessionExpires', 'Edm.Int32'); try { $this->_storage->updateEntity($this->_sessionContainer, $sessionRecord); } catch (Zend_Service_WindowsAzure_Exception $unknownRecord) { $this->_storage->insertEntity($this->_sessionContainer, $sessionRecord); } } else if ($this->_storageType == self::STORAGE_TYPE_BLOB) { // In blob storage $this->_storage->putBlobData( $this->_sessionContainer, $this->_sessionContainerPartition . '/' . $id, $serializedData, array('sessionexpires' => time()) ); } } /** * Destroy a specific session * * @param int $id Session Id * @return boolean */ public function destroy($id) { // Destroy data if ($this->_storageType == self::STORAGE_TYPE_TABLE) { // In table storage try { $sessionRecord = $this->_storage->retrieveEntityById( $this->_sessionContainer, $this->_sessionContainerPartition, $id ); $this->_storage->deleteEntity($this->_sessionContainer, $sessionRecord); return true; } catch (Zend_Service_WindowsAzure_Exception $ex) { return false; } } else if ($this->_storageType == self::STORAGE_TYPE_BLOB) { // In blob storage try { $this->_storage->deleteBlob( $this->_sessionContainer, $this->_sessionContainerPartition . '/' . $id ); return true; } catch (Zend_Service_WindowsAzure_Exception $ex) { return false; } } } /** * Garbage collector * * @param int $lifeTime Session maximal lifetime * @see session.gc_divisor 100 * @see session.gc_maxlifetime 1440 * @see session.gc_probability 1 * @usage Execution rate 1/100 (session.gc_probability/session.gc_divisor) * @return boolean */ public function gc($lifeTime) { if ($this->_storageType == self::STORAGE_TYPE_TABLE) { // In table storage try { $result = $this->_storage->retrieveEntities($this->_sessionContainer, 'PartitionKey eq \'' . $this->_sessionContainerPartition . '\' and sessionExpires lt ' . (time() - $lifeTime)); foreach ($result as $sessionRecord) { $this->_storage->deleteEntity($this->_sessionContainer, $sessionRecord); } return true; } catch (Zend_Service_WindowsAzure_exception $ex) { return false; } } else if ($this->_storageType == self::STORAGE_TYPE_BLOB) { // In blob storage try { $result = $this->_storage->listBlobs($this->_sessionContainer, $this->_sessionContainerPartition, '', null, null, 'metadata'); foreach ($result as $sessionRecord) { if ($sessionRecord->Metadata['sessionexpires'] < (time() - $lifeTime)) { $this->_storage->deleteBlob($this->_sessionContainer, $sessionRecord->Name); } } return true; } catch (Zend_Service_WindowsAzure_exception $ex) { return false; } } } }