From 37f4d81a1ce6bdea84b00a38b0c8fc32f82f9e5d Mon Sep 17 00:00:00 2001 From: xue <> Date: Tue, 11 Apr 2006 00:58:46 +0000 Subject: Refactored page state persister. --- framework/Web/UI/TPage.php | 104 ++++++++++++++++++++++++++++++- framework/Web/UI/TPageStatePersister.php | 44 +++---------- 2 files changed, 112 insertions(+), 36 deletions(-) (limited to 'framework/Web/UI') diff --git a/framework/Web/UI/TPage.php b/framework/Web/UI/TPage.php index 6a4083b0..e34101d9 100644 --- a/framework/Web/UI/TPage.php +++ b/framework/Web/UI/TPage.php @@ -145,6 +145,10 @@ class TPage extends TTemplateControl * @var TStack stack used to store currently active caching controls */ private $_cachingStack=null; + /** + * @var string state string to be stored on the client side + */ + private $_clientState=''; /** * Constructor. @@ -740,6 +744,7 @@ class TPage extends TTemplateControl $this->_formRendered=true; $this->_inFormRender=true; $cs=$this->getClientScript(); + $cs->registerHiddenField(self::FIELD_PAGESTATE,$this->getClientState()); $cs->renderHiddenFields($writer); $cs->renderScriptFiles($writer); $cs->renderBeginScripts($writer); @@ -841,6 +846,34 @@ class TPage extends TTemplateControl $this->_title=$value; } + /** + * Returns the state to be stored on the client side. + * This method should only be used by framework and control developers. + * @return string the state to be stored on the client side + */ + public function getClientState() + { + return $this->_clientState; + } + + /** + * Sets the state to be stored on the client side. + * This method should only be used by framework and control developers. + * @param string the state to be stored on the client side + */ + public function setClientState($state) + { + $this->_clientState=$state; + } + + /** + * @return string the state postback from client side + */ + public function getRequestClientState() + { + return $this->getRequest()->itemAt(self::FIELD_PAGESTATE); + } + /** * @return string class name of the page state persister. Defaults to TPageStatePersister. */ @@ -937,7 +970,7 @@ class TPage extends TTemplateControl * @author Qiang Xue * @version $Revision: $ $Date: $ * @package System.Web.UI - * @since 3.0 + * @since 3.1 */ interface IPageStatePersister { @@ -961,4 +994,73 @@ interface IPageStatePersister public function load(); } + +/** + * TPageStateFormatter class. + * + * TPageStateFormatter is a utility class to transform the page state + * into and from a string that can be properly saved in persistent storage. + * + * Depending on the {@link TPage::getEnableStateValidation() EnableStateValidation} + * and {@link TPage::getEnableStateEncryption() EnableStateEncryption}, + * TPageStateFormatter may do HMAC validation and encryption to prevent + * the state data from being tampered or viewed. + * The private keys and hashing/encryption methods are determined by + * {@link TApplication::getSecurityManager() SecurityManager}. + * + * @author Qiang Xue + * @version $Revision: $ $Date: $ + * @package System.Web.UI + * @since 3.1 + */ +class TPageStateFormatter +{ + /** + * @param TPage + * @param mixed state data + * @return string serialized data + */ + public static function serialize($page,$data) + { + $sm=$page->getApplication()->getSecurityManager(); + if($page->getEnableStateValidation()) + $str=$sm->hashData(Prado::serialize($data)); + else + $str=Prado::serialize($data); + if($page->getEnableStateEncryption()) + $str=$sm->encrypt($str); + if(extension_loaded('zlib')) + $str=gzcompress($str); + return base64_encode($str); + } + + /** + * @param TPage + * @param string serialized data + * @return mixed unserialized state data, null if data is corrupted + */ + public static function unserialize($page,$data) + { + $str=base64_decode($data); + if($str==='') + return null; + if(extension_loaded('zlib')) + $str=gzuncompress($str); + if($str!==false) + { + $sm=$page->getApplication()->getSecurityManager(); + if($page->getEnableStateEncryption()) + $str=$sm->decrypt($str); + if($page->getEnableStateValidation()) + { + if(($str=$sm->validateData($str))!==false) + return Prado::unserialize($str); + } + else + return $str; + } + return null; + } +} + ?> \ No newline at end of file diff --git a/framework/Web/UI/TPageStatePersister.php b/framework/Web/UI/TPageStatePersister.php index 3551b5f6..ff5b088b 100644 --- a/framework/Web/UI/TPageStatePersister.php +++ b/framework/Web/UI/TPageStatePersister.php @@ -16,19 +16,17 @@ * TPageStatePersister implements a page state persistent method based on * form hidden fields. * - * Depending on the {@link TPage::getEnableStateValidation() EnableStateValidation} - * and {@link TPage::getEnableStateEncryption() EnableStateEncryption}, - * TPageStatePersister may do HMAC validation and encryption to prevent - * the state data from being tampered or viewed. - * The private keys and hashing/encryption methods are determined by - * {@link TApplication::getSecurityManager() SecurityManager}. + * Since page state can be very big for complex pages, consider using + * alternative persisters, such as {@link TSessionPageStatePersister}, + * which store page state on the server side and thus reduce the network + * traffic for transmitting bulky page state. * * @author Qiang Xue * @version $Revision: $ $Date: $ * @package System.Web.UI * @since 3.0 */ -class TPageStatePersister extends TApplicationComponent implements IPageStatePersister +class TPageStatePersister extends TComponent implements IPageStatePersister { private $_page; @@ -54,15 +52,7 @@ class TPageStatePersister extends TApplicationComponent implements IPageStatePer */ public function save($state) { - if($this->_page->getEnableStateValidation()) - $data=$this->getApplication()->getSecurityManager()->hashData(Prado::serialize($state)); - else - $data=Prado::serialize($state); - if($this->_page->getEnableStateEncryption()) - $data=$this->getApplication()->getSecurityManager()->encrypt($data); - if(extension_loaded('zlib')) - $data=gzcompress($data); - $this->_page->getClientScript()->registerHiddenField(TPage::FIELD_PAGESTATE,base64_encode($data)); + $this->_page->setClientState(TPageStateFormatter::serialize($this->_page,$state)); } /** @@ -72,26 +62,10 @@ class TPageStatePersister extends TApplicationComponent implements IPageStatePer */ public function load() { - $str=base64_decode($this->getRequest()->itemAt(TPage::FIELD_PAGESTATE)); - if($str==='') - return null; - if(extension_loaded('zlib')) - $data=gzuncompress($str); + if(($data=TPageStateFormatter::unserialize($this->_page,$this->_page->getRequestClientState()))!==null) + return $data; else - $data=$str; - if($data!==false) - { - if($this->_page->getEnableStateEncryption()) - $data=$this->getApplication()->getSecurityManager()->decrypt($data); - if($this->_page->getEnableStateValidation()) - { - if(($data=$this->getApplication()->getSecurityManager()->validateData($data))!==false) - return Prado::unserialize($data); - } - else - return $data; - } - throw new THttpException(400,'pagestatepersister_pagestate_corrupted'); + throw new THttpException(400,'pagestatepersister_pagestate_corrupted'); } } -- cgit v1.2.3