From 57b6793551d29bad2b3b89f9a3f77a11682ccb48 Mon Sep 17 00:00:00 2001 From: xue <> Date: Wed, 18 Jan 2006 02:43:31 +0000 Subject: Updated phpbuilder and the file list. Added pradolite.php. --- framework/I18N/TTranslate.php | 64 +- framework/Web/UI/WebControls/TExpression.php | 2 +- framework/Web/UI/WebControls/TPlaceHolder.php | 2 +- framework/Web/UI/WebControls/TStatements.php | 2 +- framework/Web/UI/WebControls/TTextHighlighter.php | 1 - framework/core.php | 22 + framework/pradolite.php | 14631 ++++++++++++++++++++ 7 files changed, 14687 insertions(+), 37 deletions(-) create mode 100644 framework/pradolite.php (limited to 'framework') diff --git a/framework/I18N/TTranslate.php b/framework/I18N/TTranslate.php index ac708191..d38e3281 100644 --- a/framework/I18N/TTranslate.php +++ b/framework/I18N/TTranslate.php @@ -2,11 +2,11 @@ /** * TTranslate, I18N translation component. - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the BSD License. * - * Copyright(c) 2004 by Xiang Wei Zhuo. + * Copyright(c) 2004 by Xiang Wei Zhuo. * * To contact the author write to {@link mailto:qiang.xue@gmail.com Qiang Xue} * The latest version of PRADO can be obtained from: @@ -17,11 +17,9 @@ * @package System.I18N */ - Prado::using('System.IO.TTextWriter'); - /** * TTranslate class. - * + * * This component performs message/string translation. The translation * source is set in the TGlobalization handler. The following example * demonstrated a simple message translation. @@ -32,9 +30,9 @@ * Depending on the culture set on the page, the phrase "Goodbye" will * be translated. * - * The values of any attribute in TTranslate are consider as values for - * substitution. Strings enclosed with "{" and "}" are consider as the - * parameters. The following example will substitution the string + * The values of any attribute in TTranslate are consider as values for + * substitution. Strings enclosed with "{" and "}" are consider as the + * parameters. The following example will substitution the string * "{time}" with the value of the attribute "time="#time()". Note that * the value of the attribute time is evaluated. * @@ -44,17 +42,17 @@ * * * More complex string substitution can be applied using the - * TParam component. + * TParam component. * * Namespace: System.I18N * * Properties - * - Text, string, - *
Gets or sets the string to translate. + * - Text, string, + *
Gets or sets the string to translate. * - Catalogue, string, *
Gets or sets the catalogue for message translation. The * default catalogue can be set by the @Page directive. - * - Key, string, + * - Key, string, *
Gets or sets the key used to message look up. * - Trim, boolean, *
Gets or sets an option to trim the contents. @@ -65,7 +63,7 @@ * @package System.I18N */ class TTranslate extends TI18NControl -{ +{ /** * @return string the text to be localized/translated. */ @@ -91,52 +89,52 @@ class TTranslate extends TI18NControl { $this->setViewState('Key',$value,''); } - + /** * Get the key for message lookup. * @return string key - */ + */ function getKey() { return $this->getViewState('Key',''); } - + /** * Get the message catalogue. - * @return string catalogue. + * @return string catalogue. */ function getCatalogue() { return $this->getViewState('Catalogue',''); } - + /** * Set the message catalogue. - * @param string catalogue. - */ + * @param string catalogue. + */ function setCatalogue($value) { $this->setViewState('Catalogue',$value,''); } - + /** * Set the option to trim the contents. * @param boolean trim or not. - */ + */ function setTrim($value) { $this->setViewState('Trim',TPropertyValue::ensureBoolean($value),true); } - + /** * Trim the content or not. - * @return boolean trim or not. - */ + * @return boolean trim or not. + */ function getTrim() { return $this->getViewState('Trim',true); } - + /** * renders the translated string. */ @@ -157,8 +155,8 @@ class TTranslate extends TI18NControl $text = $this->getText(); if(strlen($text)==0) - $text = $textWriter->flush(); - if($this->getTrim()) + $text = $textWriter->flush(); + if($this->getTrim()) $text = trim($text); $writer->write($this->translateText($text, $subs)); @@ -177,20 +175,20 @@ class TTranslate extends TI18NControl //no translation handler provided if(is_null($config = $app->getTranslationConfiguration())) return strtr($text, $subs); - + Translation::init(); - + $catalogue = $this->getCatalogue(); if(empty($catalogue) && isset($config['catalogue'])) $catalogue = $config['catalogue']; - + $key = $this->getKey(); if(!empty($key)) $text = $key; - + //translate it return Translation::formatter()->format($text, $subs, $catalogue, $this->getCharset()); - } + } } ?> \ No newline at end of file diff --git a/framework/Web/UI/WebControls/TExpression.php b/framework/Web/UI/WebControls/TExpression.php index eb1151b0..a1c00c9a 100644 --- a/framework/Web/UI/WebControls/TExpression.php +++ b/framework/Web/UI/WebControls/TExpression.php @@ -60,4 +60,4 @@ class TExpression extends TControl } } -?> +?> \ No newline at end of file diff --git a/framework/Web/UI/WebControls/TPlaceHolder.php b/framework/Web/UI/WebControls/TPlaceHolder.php index 91979a26..bc6858ff 100644 --- a/framework/Web/UI/WebControls/TPlaceHolder.php +++ b/framework/Web/UI/WebControls/TPlaceHolder.php @@ -26,4 +26,4 @@ class TPlaceHolder extends TControl { } -?> +?> \ No newline at end of file diff --git a/framework/Web/UI/WebControls/TStatements.php b/framework/Web/UI/WebControls/TStatements.php index 0474acf1..28e25500 100644 --- a/framework/Web/UI/WebControls/TStatements.php +++ b/framework/Web/UI/WebControls/TStatements.php @@ -61,4 +61,4 @@ class TStatements extends TControl } } -?> +?> \ No newline at end of file diff --git a/framework/Web/UI/WebControls/TTextHighlighter.php b/framework/Web/UI/WebControls/TTextHighlighter.php index 56ae406e..be104896 100644 --- a/framework/Web/UI/WebControls/TTextHighlighter.php +++ b/framework/Web/UI/WebControls/TTextHighlighter.php @@ -14,7 +14,6 @@ * Using GeSHi and TTextWriter classes */ Prado::using('System.3rdParty.geshi.geshi'); -Prado::using('System.IO.TTextWriter'); /** * TTextHighlighter class. diff --git a/framework/core.php b/framework/core.php index de307cad..57c683b2 100644 --- a/framework/core.php +++ b/framework/core.php @@ -771,6 +771,28 @@ class PradoBase } } +class TTextWriter extends TComponent implements ITextWriter +{ + private $_str=''; + + public function flush() + { + $str=$this->_str; + $this->_str=''; + return $str; + } + + public function write($str) + { + $this->_str.=$str; + } + + public function writeLine($str='') + { + $this->write($str."\n"); + } +} + class TDate extends TComponent { } diff --git a/framework/pradolite.php b/framework/pradolite.php new file mode 100644 index 00000000..6b8a5e2f --- /dev/null +++ b/framework/pradolite.php @@ -0,0 +1,14631 @@ +$getter(); + } + else if(method_exists($this,'on'.$name)) + { + $name=strtolower($name); + if(!isset($this->_e[$name])) + $this->_e[$name]=new TList; + return $this->_e[$name]; + } + else + { + throw new TInvalidOperationException('component_property_undefined',get_class($this),$name); + } + } +public function __set($name,$value) + { + $setter='set'.$name; + if(method_exists($this,$setter)) + { + $this->$setter($value); + } + else if(method_exists($this,'on'.$name)) + { + $this->attachEventHandler($name,$value); + } + else if(method_exists($this,'get'.$name)) + { + throw new TInvalidOperationException('component_property_readonly',get_class($this),$name); + } + else + { + throw new TInvalidOperationException('component_property_undefined',get_class($this),$name); + } + } +final public function hasProperty($name) + { + return method_exists($this,'get'.$name) || method_exists($this,'set'.$name); + } +final public function canGetProperty($name) + { + return method_exists($this,'get'.$name); + } +final public function canSetProperty($name) + { + return method_exists($this,'set'.$name); + } +public function getSubProperty($path) + { + $object=$this; + foreach(explode('.',$path) as $property) + $object=$object->$property; + return $object; + } +public function setSubProperty($path,$value) + { + $object=$this; + if(($pos=strrpos($path,'.'))===false) + $property=$path; + else + { + $object=$this->getSubProperty(substr($path,0,$pos)); + $property=substr($path,$pos+1); + } + $object->$property=$value; + } +public function hasEvent($name) + { + return method_exists($this,'on'.$name); + } +public function hasEventHandler($name) + { + $name=strtolower($name); + return isset($this->_e[$name]) && $this->_e[$name]->getCount()>0; + } +public function getEventHandlers($name) + { + if(method_exists($this,'on'.$name)) + { + $name=strtolower($name); + if(!isset($this->_e[$name])) + $this->_e[$name]=new TList; + return $this->_e[$name]; + } + else + throw new TInvalidOperationException('component_event_undefined',get_class($this),$name); + } +public function attachEventHandler($name,$handler) + { + $this->getEventHandlers($name)->add($handler); + } +public function detachEventHandler($name,$handler) + { + if($this->hasEventHandler($name)) + { + try + { + $this->getEventHandlers($name)->remove($handler); + return true; + } + catch(Exception $e) + { + } + } + return false; + } +public function raiseEvent($name,$sender,$param) + { + $name=strtolower($name); + if(isset($this->_e[$name])) + { + foreach($this->_e[$name] as $handler) + { + if(is_string($handler)) + { + call_user_func($handler,$sender,$param); + } + else if(is_callable($handler,true)) + { + list($object,$method)=$handler; + if(is_string($object)) call_user_func($handler,$sender,$param); + else + { + if(($pos=strrpos($method,'.'))!==false) + { + $object=$this->getSubProperty(substr($method,0,$pos)); + $method=substr($method,$pos+1); + } + $object->$method($sender,$param); + } + } + else + throw new TInvalidDataValueException('component_eventhandler_invalid',get_class($this),$name); + } + } + else if(!$this->hasEvent($name)) + throw new TInvalidOperationException('component_event_undefined',get_class($this),$name); + } +public function evaluateExpression($expression) + { + try + { + if(eval("\$result=$expression;")===false) + throw new Exception(''); + return $result; + } + catch(Exception $e) + { + throw new TInvalidOperationException('component_expression_invalid',get_class($this),$expression,$e->getMessage()); + } + } +public function evaluateStatements($statements) + { + try + { + ob_start(); + if(eval($statements)===false) + throw new Exception(''); + $content=ob_get_contents(); + ob_end_clean(); + return $content; + } + catch(Exception $e) + { + throw new TInvalidOperationException('component_statements_invalid',get_class($this),$statements,$e->getMessage()); + } + } +public function getApplication() + { + return Prado::getApplication(); + } +public function getService() + { + return Prado::getApplication()->getService(); + } +public function getRequest() + { + return Prado::getApplication()->getRequest(); + } +public function getResponse() + { + return Prado::getApplication()->getResponse(); + } +public function getSession() + { + return Prado::getApplication()->getSession(); + } +public function getUser() + { + return Prado::getApplication()->getUser(); + } +} +class TPropertyValue +{ +public static function ensureBoolean($value) + { + if (is_string($value)) + return strcasecmp($value,'true')==0 || $value!=0; + else + return (boolean)$value; + } +public static function ensureString($value) + { + if (is_bool($value)) + return $value?'true':'false'; + else + return (string)$value; + } +public static function ensureInteger($value) + { + return (integer)$value; + } +public static function ensureFloat($value) + { + return (float)$value; + } +public static function ensureArray($value) + { + if(is_string($value)) + { + $trimmed = trim($value); + $len = strlen($value); + if ($len >= 2 && $trimmed[0] == '(' && $trimmed[$len-1] == ')') + { + eval('$array=array'.$trimmed.';'); + return $array; + } + else + return $len>0?array($value):array(); + } + else + return (array)$value; + } +public static function ensureObject($value) + { + return (object)$value; + } +public static function ensureEnum($value,$enums) + { + if(!is_array($enums)) + { + $enums=func_get_args(); + array_shift($enums); + } + if(in_array($value,$enums,true)) + return $value; + else + throw new TInvalidDataValueException('propertyvalue_enumvalue_invalid',$value,implode(' | ',$enums)); + } +} +class TEventParameter extends TComponent +{ +} +?>_errorCode=$errorMessage; + $args=func_get_args(); + $args[0]=$this->translateErrorMessage($errorMessage); + $str=call_user_func_array('sprintf',$args); + parent::__construct($str); + } +protected function translateErrorMessage($key) + { + $lang=Prado::getPreferredLanguage(); + $msgFile=Prado::getFrameworkPath().'/Exceptions/messages-'.$lang.'.txt'; + if(!is_file($msgFile)) + $msgFile=Prado::getFrameworkPath().'/Exceptions/messages.txt'; + if(($entries=@file($msgFile))===false) + return $key; + else + { + foreach($entries as $entry) + { + @list($code,$message)=explode('=',$entry,2); + if(trim($code)===$key) + return trim($message); + } + return $key; + } + } +public function getErrorCode() + { + return $this->_errorCode; + } +public function getErrorMessage() + { + return $this->getMessage(); + } +} +class TSystemException extends TException +{ +} +class TApplicationException extends TException +{ +} +class TInvalidOperationException extends TSystemException +{ +} +class TInvalidDataTypeException extends TSystemException +{ +} +class TInvalidDataValueException extends TSystemException +{ +} +class TInvalidDataFormatException extends TSystemException +{ +} +class TConfigurationException extends TSystemException +{ +} +class TIOException extends TSystemException +{ +} +class TDBException extends TSystemException +{ +} +class TSecurityException extends TSystemException +{ +} +class TNotSupportedException extends TSystemException +{ +} +class TTemplateParsingException extends TSystemException +{ +} +class TTemplateRuntimeException extends TSystemException +{ +} +class TPhpErrorException extends TException +{ + public function __construct($errno,$errstr,$errfile,$errline) + { + static $errorTypes=array( + E_ERROR => "Error", + E_WARNING => "Warning", + E_PARSE => "Parsing Error", + E_NOTICE => "Notice", + E_CORE_ERROR => "Core Error", + E_CORE_WARNING => "Core Warning", + E_COMPILE_ERROR => "Compile Error", + E_COMPILE_WARNING => "Compile Warning", + E_USER_ERROR => "User Error", + E_USER_WARNING => "User Warning", + E_USER_NOTICE => "User Notice", + E_STRICT => "Runtime Notice" + ); + $errorType=isset($errorTypes[$errno])?$errorTypes[$errno]:'Unknown Error'; + parent::__construct("[$errorType] $errstr (@line $errline in file $errfile)."); + } +} +class THttpException extends TException +{ + private $_statusCode; +public function __construct($statusCode,$errorMessage) + { + $args=func_get_args(); + array_shift($args); + call_user_func_array(array('TException', '__construct'), $args); + $this->_statusCode=TPropertyValue::ensureInteger($statusCode); + } +public function getStatusCode() + { + return $this->_statusCode; + } +} +?>copyFrom($data); + } +public function getIterator() + { + return new TListIterator($this->_d); + } +public function getCount() + { + return $this->_c; + } +public function itemAt($index) + { + if(isset($this->_d[$index])) + return $this->_d[$index]; + else + throw new TInvalidDataValueException('list_index_invalid',$index); + } +public function add($item) + { + if($this->canAddItem($item)) + { + $this->_d[$this->_c++]=$item; + $this->addedItem($item); + } + else + throw new TInvalidOperationException('list_addition_disallowed'); + } +public function insert($index,$item) + { + if($this->canAddItem($item)) + { + if($index===$this->_c) + $this->add($item); + else if($index>=0 && $index<$this->_c) + { + array_splice($this->_d,$index,0,array($item)); + $this->_c++; + $this->addedItem($item); + } + else + throw new TInvalidDataValueException('list_index_invalid',$index); + } + else + throw new TInvalidOperationException('list_addition_disallowed'); +} +public function remove($item) + { + if(($index=$this->indexOf($item))>=0) + { + if($this->canRemoveItem($item)) + $this->removeAt($index); + else + throw new TInvalidOperationException('list_item_unremovable'); + } + else + throw new TInvalidDataValueException('list_item_inexistent'); + } +public function removeAt($index) + { + if(isset($this->_d[$index])) + { + $item=$this->_d[$index]; + if($this->canRemoveItem($item)) + { + if($index===$this->_c-1) + unset($this->_d[$index]); + else + array_splice($this->_d,$index,1); + $this->_c--; + $this->removedItem($item); + return $item; + } + else + throw new TInvalidOperationException('list_item_unremovable'); + } + else + throw new TInvalidDataValueException('list_index_invalid',$index); + } +public function clear() + { + for($i=$this->_c-1;$i>=0;--$i) + $this->removeAt($i); + } +public function contains($item) + { + return $this->indexOf($item)>=0; + } +public function indexOf($item) + { + if(($index=array_search($item,$this->_d,true))===false) + return -1; + else + return $index; + } +public function toArray() + { + return $this->_d; + } +public function copyFrom($data) + { + if(is_array($data) || ($data instanceof Traversable)) + { + if($this->_c>0) + $this->clear(); + foreach($data as $item) + $this->add($item); + } + else if($data!==null) + throw new TInvalidDataTypeException('list_data_not_iterable'); + } +public function mergeWith($data) + { + if(is_array($data) || ($data instanceof Traversable)) + { + foreach($data as $item) + $this->add($item); + } + else if($data!==null) + throw new TInvalidDataTypeException('list_data_not_iterable'); + } +public function offsetExists($offset) + { + return isset($this->_d[$offset]); + } +public function offsetGet($offset) + { + if(isset($this->_d[$offset])) + return $this->_d[$offset]; + else + throw new TInvalidDataValueException('list_index_invalid',$offset); + } +public function offsetSet($offset,$item) + { + if($offset===null || $offset===$this->_c) + $this->add($item); + else + { + $this->removeAt($offset); + $this->insert($offset,$item); + } + } +public function offsetUnset($offset) + { + $this->removeAt($offset); + } +protected function addedItem($item) + { + } +protected function removedItem($item) + { + } +protected function canAddItem($item) + { + return true; + } +protected function canRemoveItem($item) + { + return true; + } +} +class TListIterator implements Iterator +{ +private $_d; +private $_i; +public function __construct(&$data) + { + $this->_d=&$data; + $this->_i=0; + } +public function rewind() + { + $this->_i=0; + } +public function key() + { + return $this->_i; + } +public function current() + { + return $this->_d[$this->_i]; + } +public function next() + { + $this->_i++; + } +public function valid() + { + return isset($this->_d[$this->_i]); + } +} +?>copyFrom($data); + } +public function getIterator() + { + return new TMapIterator($this->_d); + } +public function getCount() + { + return count($this->_d); + } +public function getKeys() + { + return array_keys($this->_d); + } +public function itemAt($key) + { + return isset($this->_d[$key]) ? $this->_d[$key] : null; + } +public function add($key,$value) + { + if($this->canAddItem($key,$value)) + { + if(isset($this->_d[$key])) + $this->remove($key); + $this->_d[$key]=$value; + $this->addedItem($key,$value); + } + else + throw new TInvalidOperationException('map_addition_disallowed'); + } +public function remove($key) + { + if(isset($this->_d[$key])) + { + $value=$this->_d[$key]; + if($this->canRemoveItem($key,$value)) + { + unset($this->_d[$key]); + $this->removedItem($key,$value); + return $value; + } + else + throw new TInvalidOperationException('map_item_unremovable'); + } + else + return null; + } +public function clear() + { + foreach(array_keys($this->_d) as $key) + $this->remove($key); + } +public function contains($key) + { + return isset($this->_d[$key]); + } +public function toArray() + { + return $this->_d; + } +public function copyFrom($data) + { + if(is_array($data) || $data instanceof Traversable) + { + if($this->getCount()>0) + $this->clear(); + foreach($data as $key=>$value) + $this->add($key,$value); + } + else if($data!==null) + throw new TInvalidDataTypeException('map_data_not_iterable'); + } +public function mergeWith($data) + { + if(is_array($data) || $data instanceof Traversable) + { + foreach($data as $key=>$value) + $this->add($key,$value); + } + else if($data!==null) + throw new TInvalidDataTypeException('map_data_not_iterable'); + } +public function offsetExists($offset) + { + return $this->contains($offset); + } +public function offsetGet($offset) + { + return isset($this->_d[$offset]) ? $this->_d[$offset] : null; + } +public function offsetSet($offset,$item) + { + $this->add($offset,$item); + } +public function offsetUnset($offset) + { + $this->remove($offset); + } +protected function addedItem($key,$item) + { + } +protected function removedItem($key,$item) + { + } +protected function canAddItem($key,$item) + { + return true; + } +protected function canRemoveItem($key,$item) + { + return true; + } +} +class TMapIterator implements Iterator +{ +private $_d; +private $_keys; +private $_key; +public function __construct(&$data) + { + $this->_d=&$data; + $this->_keys=array_keys($data); + } +public function rewind() + { + $this->_key=reset($this->_keys); + } +public function key() + { + return $this->_key; + } +public function current() + { + return $this->_d[$this->_key]; + } +public function next() + { + do + { + $this->_key=next($this->_keys); + } + while(!isset($this->_d[$this->_key]) && $this->_key!==false); + } +public function valid() + { + return $this->_key!==false; + } +} +?>setTagName($tagName); + } +public function getParent() + { + return $this->_parent; + } +public function setParent($parent) + { + $this->_parent=$parent; + } +public function getTagName() + { + return $this->_tagName; + } +public function setTagName($tagName) + { + $this->_tagName=$tagName; + } +public function getValue() + { + return $this->_value; + } +public function setValue($value) + { + $this->_value=$value; + } +public function getHasElement() + { + return $this->_elements!==null && $this->_elements->getCount()>0; + } +public function getHasAttribute() + { + return $this->_attributes!==null && $this->_attributes->getCount()>0; + } +public function getAttribute($name) + { + if($this->_attributes!==null) + return $this->_attributes->itemAt($name); + else + return null; + } +public function getElements() + { + if(!$this->_elements) + $this->_elements=new TXmlElementList($this); + return $this->_elements; + } +public function getAttributes() + { + if(!$this->_attributes) + $this->_attributes=new TMap; + return $this->_attributes; + } +public function getElementByTagName($tagName) + { + if($this->_elements) + { + foreach($this->_elements as $element) + if($element->_tagName===$tagName) + return $element; + } + return null; + } +public function getElementsByTagName($tagName) + { + $list=new TList; + if($this->_elements) + { + foreach($this->_elements as $element) + if($element->_tagName===$tagName) + $list->add($element); + } + return $list; + } +public function toString($indent=0) + { + $attr=''; + if($this->_attributes!==null) + { + foreach($this->_attributes as $name=>$value) + $attr.=" $name=\"$value\""; + } + $prefix=str_repeat(' ',$indent*4); + if($this->getHasElement()) + { + $str=$prefix."<{$this->_tagName}$attr>\n"; + foreach($this->getElements() as $element) + $str.=$element->toString($indent+1)."\n"; + $str.=$prefix."_tagName}>"; + return $str; + } + else if($this->getValue()!=='') + { + return $prefix."<{$this->_tagName}$attr>{$this->_value}_tagName}>"; + } + else + return $prefix."<{$this->_tagName}$attr />"; + } +} +class TXmlDocument extends TXmlElement +{ +private $_version; +private $_encoding; +public function __construct($version='1.0',$encoding='') + { + parent::__construct(''); + $this->setversion($version); + $this->setEncoding($encoding); + } +public function getVersion() + { + return $this->_version; + } +public function setVersion($version) + { + $this->_version=$version; + } +public function getEncoding() + { + return $this->_encoding; + } +public function setEncoding($encoding) + { + $this->_encoding=$encoding; + } +public function loadFromFile($file) + { + if(($str=@file_get_contents($file))!==false) + return $this->loadFromString($str); + else + throw new TIOException('xmldocument_file_read_failed',$file); + } +public function loadFromString($string) + { + $doc=new DOMDocument(); + if($doc->loadXML($string)===false) + return false; +$this->setEncoding($doc->encoding); + $this->setVersion($doc->version); +$element=$doc->documentElement; + $this->setTagName($element->tagName); + $this->setValue($element->nodeValue); + $elements=$this->getElements(); + $attributes=$this->getAttributes(); + $elements->clear(); + $attributes->clear(); + foreach($element->attributes as $name=>$attr) + $attributes->add($name,$attr->value); + foreach($element->childNodes as $child) + { + if($child instanceof DOMElement) + $elements->add($this->buildElement($child)); + } +return true; + } +public function saveToFile($file) + { + if(($fw=fopen($file,'w'))!==false) + { + fwrite($fw,$this->saveToString()); + fclose($fw); + } + else + throw new TIOException('xmldocument_file_write_failed',$file); + } +public function saveToString() + { + $version=empty($this->_version)?' version="1.0"':' version="'.$this->_version.'"'; + $encoding=empty($this->_encoding)?'':' encoding="'.$this->_encoding.'"'; + return "\n".$this->toString(0); + } +private function buildElement($node) + { + $element=new TXmlElement($node->tagName); + $element->setValue($node->nodeValue); + foreach($node->attributes as $name=>$attr) + $element->getAttributes()->add($name,$attr->value); + foreach($node->childNodes as $child) + { + if($child instanceof DOMElement) + $element->getElements()->add($this->buildElement($child)); + } + return $element; + } +} +class TXmlElementList extends TList +{ +private $_o; +public function __construct(TXmlElement $owner) + { + parent::__construct(); + $this->_o=$owner; + } +protected function getOwner() + { + return $this->_o; + } +protected function addedItem($item) + { + if($item->getParent()!==null) + $item->getParent()->getElements()->remove($item); + $item->setParent($this->_o); + } +protected function removedItem($item) + { + $item->setParent(null); + } +protected function canAddItem($item) + { + return ($item instanceof TXmlElement); + } +} +?>'%25',"\t"=>'\t',"\n"=>'\n',"\r"=>'\r','"'=>'\"','\''=>'\\\'','\\'=>'\\\\')); + else + return strtr($js,array("\t"=>'\t',"\n"=>'\n',"\r"=>'\r','"'=>'\"','\''=>'\\\'','\\'=>'\\\\')); + } +public static function trimJavaScriptString($js) + { + if($js!=='' && $js!==null) + { + $js=trim($js); + if(($pos=strpos($js,'javascript:'))===0) + $js=substr($js,11); + $js=rtrim($js,';').';'; + } + return $js; + } +} +?>_logs[]=array($message,$level,$category,microtime(true)); + } +public function getLogs($levels=null,$categories=null) + { + $this->_levels=$levels; + $this->_categories=$categories; + if(empty($levels) && empty($categories)) + return $this->_logs; + else if(empty($levels)) + return array_values(array_filter(array_filter($this->_logs,array($this,'filterByCategories')))); + else if(empty($categories)) + return array_values(array_filter(array_filter($this->_logs,array($this,'filterByLevels')))); + else + { + $ret=array_values(array_filter(array_filter($this->_logs,array($this,'filterByLevels')))); + return array_values(array_filter(array_filter($ret,array($this,'filterByCategories')))); + } + } +private function filterByCategories($value) + { + foreach($this->_categories as $category) + { + if(strpos($value[2],$category)===0) + return $value; + } + return false; + } +private function filterByLevels($value) + { + if($value[1] & $this->_levels) + return $value; + else + return false; + } +} +?>_id; + } +public function setID($value) + { + $this->_id=$value; + } +} +abstract class TService extends TComponent implements IService +{ +private $_id; +public function init($config) + { + } +public function getID() + { + return $this->_id; + } +public function setID($value) + { + $this->_id=$value; + } +public function run() + { + } +} +class PradoBase +{ +const CLASS_FILE_EXT='.php'; +private static $_aliases=array('System'=>PRADO_DIR); +private static $_usings=array(); +private static $_application=null; +private static $_logger=null; +public static function getVersion() + { + return '3.0a'; + } +public static function phpErrorHandler($errno,$errstr,$errfile,$errline) + { + if(error_reporting()!=0) + throw new TPhpErrorException($errno,$errstr,$errfile,$errline); + } +public static function exceptionHandler($exception) + { + if(self::$_application!==null && ($errorHandler=self::$_application->getErrorHandler())!==null) + { + $errorHandler->handleError(null,$exception); + } + else + { + echo $exception; + } + exit(1); + } +public static function setApplication($application) + { + if(self::$_application!==null) + throw new TInvalidOperationException('prado_application_singleton_required'); + self::$_application=$application; + } +public static function getApplication() + { + return self::$_application; + } +public static function getFrameworkPath() + { + return PRADO_DIR; + } +public static function serialize($data) + { + $arr[0]=$data; + return serialize($arr); + } +public static function unserialize($str) + { + $arr=unserialize($str); + return isset($arr[0])?$arr[0]:null; + } +public static function createComponent($type) + { + if(!class_exists($type,false)) + { + if(($pos=strrpos($type,'.'))===false) + { + include_once($type.self::CLASS_FILE_EXT); + if(!class_exists($type,false)) + throw new TInvalidOperationException('prado_component_unknown',$type); + } + else + { + $className=substr($type,$pos+1); + if(!class_exists($className,false) && ($path=self::getPathOfNamespace($type))!==null) + { + include_once($path.self::CLASS_FILE_EXT); + if(!class_exists($className,false)) + throw new TInvalidOperationException('prado_component_unknown',$type); + } + $type=$className; + } + } + if(($n=func_num_args())>1) + { + $args=func_get_args(); + $s='$args[1]'; + for($i=2;$i<$n;++$i) + $s.=",\$args[$i]"; + eval("\$component=new $type($s);"); + return $component; + } + else + return new $type; + } +public static function using($namespace) + { + if(!isset(self::$_usings[$namespace])) + { + if(($path=self::getPathOfNamespace($namespace,self::CLASS_FILE_EXT))===null) + throw new TInvalidDataValueException('prado_using_invalid',$namespace); + else + { + if($namespace[strlen($namespace)-1]==='*') { + if(is_dir($path)) + { + self::$_usings[$namespace]=$path; + set_include_path(get_include_path().PATH_SEPARATOR.$path); + } + else + throw new TInvalidDataValueException('prado_using_invalid',$namespace); + } + else { + if(is_file($path)) + { + self::$_usings[$namespace]=$path; + if(!class_exists(substr(strrchr($namespace,'.'),1),false)) + require_once($path); + } + else + throw new TInvalidDataValueException('prado_using_invalid',$namespace); + } + } + } + } +public static function getPathOfNamespace($namespace,$ext='') + { + if(isset(self::$_usings[$namespace])) + return self::$_usings[$namespace]; + else if(isset(self::$_aliases[$namespace])) + return self::$_aliases[$namespace]; + else + { + $segs=explode('.',$namespace); + $alias=array_shift($segs); + if(($file=array_pop($segs))!==null && ($root=self::getPathOfAlias($alias))!==null) + return rtrim($root.'/'.implode('/',$segs),'/').(($file==='*')?'':'/'.$file.$ext); + else + return null; + } + } +public static function getPathOfAlias($alias) + { + if(isset(self::$_aliases[$alias])) + return self::$_aliases[$alias]; + else + return null; + } +public static function setPathOfAlias($alias,$path) + { + if(isset(self::$_aliases[$alias])) + throw new TInvalidOperationException('prado_alias_redefined',$alias); + else if(($rp=realpath($path))!==false && is_dir($rp)) + self::$_aliases[$alias]=$rp; + else + throw new TInvalidDataValueException('prado_alias_invalid',$alias,$path); + } +public static function fatalError($msg) + { + echo '

Fatal Error

'; + echo '

'.$msg.'

'; + if(!function_exists('debug_backtrace')) + return; + echo '

Debug Backtrace

'; + echo '
'; 
+		$index=-1; 
+		foreach(debug_backtrace() as $t) 
+		{ 
+			$index++; 
+			if($index==0)  				continue; 
+			echo '#'.$index.' '; 
+			if(isset($t['file'])) 
+				echo basename($t['file']) . ':' . $t['line']; 
+			else 
+			   echo ''; 
+			echo ' -- '; 
+			if(isset($t['class'])) 
+				echo $t['class'] . $t['type']; 
+			echo $t['function']; 
+			if(isset($t['args']) && sizeof($t['args']) > 0) 
+				echo '(...)'; 
+			else 
+				echo '()'; 
+			echo "\n"; 
+		} 
+		echo '
'; + exit(1); + } +public static function getUserLanguages() + { + static $languages=null; + if($languages===null) + { + $languages=array(); + foreach(explode(',',$_SERVER['HTTP_ACCEPT_LANGUAGE']) as $language) + { + $array=split(';q=',trim($language)); + $languages[trim($array[0])]=isset($array[1])?(float)$array[1]:1.0; + } + arsort($languages); + $languages=array_keys($languages); + if(empty($languages)) + $languages[0]='en'; + } + return $languages; + } +public static function getPreferredLanguage() + { + static $language=null; + if($language===null) + { + $langs=Prado::getUserLanguages(); + $lang=explode('-',$langs[0]); + if(empty($lang[0]) || !ctype_alpha($lang[0])) + $language='en'; + else + $language=$lang[0]; + } + return $language; + } +public static function trace($msg,$category='Uncategorized') + { + if(self::$_application && self::$_application->getMode()==='Performance') + return; + if(!self::$_application || self::$_application->getMode()==='Debug') + { + $trace=debug_backtrace(); + if(isset($trace[0]['file']) && isset($trace[0]['line'])) + $msg.=" (line {$trace[0]['line']}, {$trace[0]['file']})"; + $level=TLogger::DEBUG; + } + else + $level=TLogger::INFO; + self::log($msg,$level,$category); + } +public static function log($msg,$level=TLogger::INFO,$category='Uncategorized') + { + if(self::$_logger===null) + self::$_logger=new TLogger; + self::$_logger->log($msg,$level,$category); + } +public static function getLogger() + { + if(self::$_logger===null) + self::$_logger=new TLogger; + return self::$_logger; + } +} +class TTextWriter extends TComponent implements ITextWriter +{ + private $_str=''; +public function flush() + { + $str=$this->_str; + $this->_str=''; + return $str; + } +public function write($str) + { + $this->_str.=$str; + } +public function writeLine($str='') + { + $this->write($str."\n"); + } +} +class TDate extends TComponent +{ +} +?>_basePath=realpath($basePath))===false || !is_dir($this->_basePath)) + throw new TConfigurationException('application_basepath_invalid',$basePath); + $configFile=$this->_basePath.'/'.self::CONFIG_FILE; + $this->_configFile=is_file($configFile) ? $configFile : null; + $this->_runtimePath=$this->_basePath.'/'.self::RUNTIME_PATH; + if(!is_dir($this->_runtimePath) || !is_writable($this->_runtimePath)) + throw new TConfigurationException('application_runtimepath_invalid',$this->_runtimePath); +$this->_cacheFile=$cacheConfig ? $this->_runtimePath.'/'.self::CONFIGCACHE_FILE : null; +$this->_uniqueID=md5($this->_basePath); + } +public function run() + { + try + { + $this->initApplication(); + $n=count(self::$_steps); + $this->_step=0; + $this->_requestCompleted=false; + while($this->_step<$n) + { + if($this->_mode===self::STATE_OFF) + throw new THttpException(503,'application_service_unavailable'); + $method='on'.self::$_steps[$this->_step]; + + $this->$method($this); + if($this->_requestCompleted && $this->_step<$n-1) + $this->_step=$n-1; + else + $this->_step++; + } + } + catch(Exception $e) + { + $this->onError($e); + } + } +public function completeRequest() + { + $this->_requestCompleted=true; + } +public function getGlobalState($key,$defaultValue=null) + { + return isset($this->_globals[$key])?$this->_globals[$key]:$defaultValue; + } +public function setGlobalState($key,$value,$defaultValue=null) + { + $this->_stateChanged=true; + if($value===$defaultValue) + unset($this->_globals[$key]); + else + $this->_globals[$key]=$value; + } +public function clearGlobalState($key) + { + $this->_stateChanged=true; + unset($this->_globals[$key]); + } +protected function loadGlobals() + { + $this->_globals=$this->getApplicationStatePersister()->load(); + } +protected function saveGlobals() + { + if(!$this->_stateChanged) + return; + $this->getApplicationStatePersister()->save($this->_globals); + } +public function getID() + { + return $this->_id; + } +public function setID($value) + { + $this->_id=$value; + } +public function getUniqueID() + { + return $this->_uniqueID; + } +public function getMode() + { + return $this->_mode; + } +public function setMode($value) + { + $this->_mode=TPropertyValue::ensureEnum($value,array(self::STATE_OFF,self::STATE_DEBUG,self::STATE_NORMAL,self::STATE_PERFORMANCE)); + } +public function getBasePath() + { + return $this->_basePath; + } +public function getConfigurationFile() + { + return $this->_configFile; + } +public function getRuntimePath() + { + return $this->_runtimePath; + } +public function getService() + { + return $this->_service; + } +public function setModule($id,IModule $module) + { + if(isset($this->_modules[$id])) + throw new TConfigurationException('application_moduleid_duplicated',$id); + else + $this->_modules[$id]=$module; + } +public function getModule($id) + { + return isset($this->_modules[$id])?$this->_modules[$id]:null; + } +public function getModules() + { + return $this->_modules; + } +public function getParameters() + { + return $this->_parameters; + } +public function getPageService() + { + if(!$this->_pageService) + { + $this->_pageService=new TPageService; + $this->_pageService->init(null); + } + return $this->_pageService; + } +public function setPageService(TPageService $service) + { + $this->_pageService=$service; + } +public function getRequest() + { + if(!$this->_request) + { + $this->_request=new THttpRequest; + $this->_request->init(null); + } + return $this->_request; + } +public function setRequest(THttpRequest $request) + { + $this->_request=$request; + } +public function getResponse() + { + if(!$this->_response) + { + $this->_response=new THttpResponse; + $this->_response->init(null); + } + return $this->_response; + } +public function setResponse(THttpResponse $response) + { + $this->_response=$response; + } +public function getSession() + { + if(!$this->_session) + { + $this->_session=new THttpSession; + $this->_session->init(null); + } + return $this->_session; + } +public function setSession(THttpSession $session) + { + $this->_session=$session; + } +public function getErrorHandler() + { + if(!$this->_errorHandler) + { + $this->_errorHandler=new TErrorHandler; + $this->_errorHandler->init(null); + } + return $this->_errorHandler; + } +public function setErrorHandler(TErrorHandler $handler) + { + $this->_errorHandler=$handler; + } +public function getApplicationStatePersister() + { + if(!$this->_statePersister) + { + $this->_statePersister=new TApplicationStatePersister; + $this->_statePersister->init(null); + } + return $this->_statePersister; + } +public function setApplicationStatePersister(IStatePersister $persister) + { + $this->_statePersister=$persister; + } +public function getCache() + { + return $this->_cache; + } +public function setCache(ICache $cache) + { + $this->_cache=$cache; + } +public function getUser() + { + return $this->_user; + } +public function setUser(IUser $user) + { + $this->_user=$user; + } +public function getGlobalization() + { + return $this->_globalization; + } +public function setGlobalization(TGlobalization $handler) + { + $this->_globalization = $handler; + } +public function getAuthorizationRules() + { + if($this->_authRules===null) + $this->_authRules=new TAuthorizationRuleCollection; + return $this->_authRules; + } +protected function initApplication() + { + +Prado::setPathOfAlias('Application',$this->_basePath); +if($this->_configFile===null) + { + $this->getRequest()->setAvailableServices(array(self::PAGE_SERVICE_ID)); + $this->_service=$this->getPageService(); + return; + } +if($this->_cacheFile===null || @filemtime($this->_cacheFile)_configFile)) + { + $config=new TApplicationConfiguration; + $config->loadFromFile($this->_configFile); + if($this->_cacheFile!==null) + { + if(($fp=fopen($this->_cacheFile,'wb'))!==false) + { + fputs($fp,Prado::serialize($config)); + fclose($fp); + } + else + syslog(LOG_WARNING, 'Prado application config cache file "'.$this->_cacheFile.'" cannot be created.'); + } + } + else + { + $config=Prado::unserialize(file_get_contents($this->_cacheFile)); + } +foreach($config->getAliases() as $alias=>$path) + Prado::setPathOfAlias($alias,$path); + foreach($config->getUsings() as $using) + Prado::using($using); +foreach($config->getProperties() as $name=>$value) + $this->setSubProperty($name,$value); +$this->_parameters=new TMap; + foreach($config->getParameters() as $id=>$parameter) + { + if(is_string($parameter)) + $this->_parameters->add($id,$parameter); + else + { + $component=Prado::createComponent($parameter[0]); + foreach($parameter[1] as $name=>$value) + $component->setSubProperty($name,$value); + $this->_parameters->add($id,$component); + } + } +$this->_modules=array(); + foreach($config->getModules() as $id=>$moduleConfig) + { + +$module=Prado::createComponent($moduleConfig[0]); + $this->setModule($id,$module); + foreach($moduleConfig[1] as $name=>$value) + $module->setSubProperty($name,$value); + $module->init($moduleConfig[2]); + } +$services=$config->getServices(); + $serviceIDs=array_keys($services); + array_unshift($serviceIDs,self::PAGE_SERVICE_ID); + $request=$this->getRequest(); + $request->setAvailableServices($serviceIDs); +if(($serviceID=$request->getServiceID())===null) + $serviceID=self::PAGE_SERVICE_ID; + if(isset($services[$serviceID])) + { + $serviceConfig=$services[$serviceID]; + $service=Prado::createComponent($serviceConfig[0]); + if(!($service instanceof IService)) + throw new THttpException(500,'application_service_unknown',$serviceID); + $this->_service=$service; + foreach($serviceConfig[1] as $name=>$value) + $service->setSubProperty($name,$value); + $service->init($serviceConfig[2]); + } + else + $this->_service=$this->getPageService(); + } +public function onError($param) + { + if($this->hasEventHandler('Error')) + $this->raiseEvent('Error',$this,$param); + else + $this->getErrorHandler()->handleError($this,$param); + } +public function onBeginRequest($param) + { + $this->raiseEvent('BeginRequest',$this,$param); + } +public function onAuthentication($param) + { + $this->raiseEvent('Authentication',$this,$param); + } +public function onPostAuthentication($param) + { + $this->raiseEvent('PostAuthentication',$this,$param); + } +public function onAuthorization($param) + { + $this->raiseEvent('Authorization',$this,$param); + } +public function onPostAuthorization($param) + { + $this->raiseEvent('PostAuthorization',$this,$param); + } +public function onLoadState($param) + { + $this->loadGlobals(); + $this->raiseEvent('LoadState',$this,$param); + } +public function onPostLoadState($param) + { + $this->raiseEvent('PostLoadState',$this,$param); + } +public function onPreRunService($param) + { + $this->raiseEvent('PreRunService',$this,$param); + } +public function onRunService($param) + { + $this->raiseEvent('RunService',$this,$param); + if($this->_service) + $this->_service->run(); + } +public function onPostRunService($param) + { + $this->raiseEvent('PostRunService',$this,$param); + } +public function onSaveState($param) + { + $this->raiseEvent('SaveState',$this,$param); + $this->saveGlobals(); + } +public function onPostSaveState($param) + { + $this->raiseEvent('PostSaveState',$this,$param); + } +public function onEndRequest($param) + { + $this->raiseEvent('EndRequest',$this,$param); + } +} +class TApplicationConfiguration extends TComponent +{ +private $_properties=array(); +private $_usings=array(); +private $_aliases=array(); +private $_modules=array(); +private $_services=array(); +private $_parameters=array(); +public function loadFromFile($fname) + { + $configPath=dirname($fname); + $dom=new TXmlDocument; + $dom->loadFromFile($fname); +foreach($dom->getAttributes() as $name=>$value) + $this->_properties[$name]=$value; +if(($pathsNode=$dom->getElementByTagName('paths'))!==null) + { + foreach($pathsNode->getElementsByTagName('alias') as $aliasNode) + { + if(($id=$aliasNode->getAttribute('id'))!==null && ($path=$aliasNode->getAttribute('path'))!==null) + { + $path=str_replace('\\','/',$path); + if(preg_match('/^\\/|.:\\/|.:\\\\/',$path)) $p=realpath($path); + else + $p=realpath($configPath.'/'.$path); + if($p===false || !is_dir($p)) + throw new TConfigurationException('appconfig_aliaspath_invalid',$id,$path); + if(isset($this->_aliases[$id])) + throw new TConfigurationException('appconfig_alias_redefined',$id); + $this->_aliases[$id]=$p; + } + else + throw new TConfigurationException('appconfig_alias_invalid'); + } + foreach($pathsNode->getElementsByTagName('using') as $usingNode) + { + if(($namespace=$usingNode->getAttribute('namespace'))!==null) + $this->_usings[]=$namespace; + else + throw new TConfigurationException('appconfig_using_invalid'); + } + } +if(($modulesNode=$dom->getElementByTagName('modules'))!==null) + { + foreach($modulesNode->getElementsByTagName('module') as $node) + { + $properties=$node->getAttributes(); + if(($id=$properties->itemAt('id'))===null) + throw new TConfigurationException('appconfig_moduleid_required'); + if(($type=$properties->remove('class'))===null && isset($this->_modules[$id]) && $this->_modules[$id][2]===null) + $type=$this->_modules[$id][0]; + if($type===null) + throw new TConfigurationException('appconfig_moduletype_required',$id); + $node->setParent(null); + $this->_modules[$id]=array($type,$properties->toArray(),$node); + } + } +if(($servicesNode=$dom->getElementByTagName('services'))!==null) + { + foreach($servicesNode->getElementsByTagName('service') as $node) + { + $properties=$node->getAttributes(); + if(($id=$properties->itemAt('id'))===null) + throw new TConfigurationException('appconfig_serviceid_required'); + if(($type=$properties->remove('class'))===null && isset($this->_services[$id]) && $this->_services[$id][2]===null) + $type=$this->_services[$id][0]; + if($type===null) + throw new TConfigurationException('appconfig_servicetype_required',$id); + $node->setParent(null); + $this->_services[$id]=array($type,$properties->toArray(),$node); + } + } +if(($parametersNode=$dom->getElementByTagName('parameters'))!==null) + { + foreach($parametersNode->getElementsByTagName('parameter') as $node) + { + $properties=$node->getAttributes(); + if(($id=$properties->remove('id'))===null) + throw new TConfigurationException('appconfig_parameterid_required'); + if(($type=$properties->remove('class'))===null) + $this->_parameters[$id]=$node->getValue(); + else + $this->_parameters[$id]=array($type,$properties->toArray()); + } + } + } +public function getProperties() + { + return $this->_properties; + } +public function getAliases() + { + return $this->_aliases; + } +public function getUsings() + { + return $this->_usings; + } +public function getModules() + { + return $this->_modules; + } +public function getServices() + { + return $this->_services; + } +public function getParameters() + { + return $this->_parameters; + } +} +class TApplicationStatePersister extends TModule implements IStatePersister +{ +const CACHE_NAME='prado:appstate'; +public function init($config) + { + $this->getApplication()->setApplicationStatePersister($this); + } +protected function getStateFilePath() + { + return $this->getApplication()->getRuntimePath().'/global.cache'; + } +public function load() + { + if(($cache=$this->getApplication()->getCache())!==null && ($value=$cache->get(self::CACHE_NAME))!==false) + return unserialize($value); + else + { + if(($content=@file_get_contents($this->getStateFilePath()))!==false) + return unserialize($content); + else + return null; + } + } +public function save($state) + { + $content=serialize($state); + $saveFile=true; + if(($cache=$this->getApplication()->getCache())!==null) + { + if($cache->get(self::CACHE_NAME)===$content) + $saveFile=false; + else + $cache->set(self::CACHE_NAME,$content); + } + if($saveFile) + { + $fileName=$this->getStateFilePath(); + if(version_compare(phpversion(),'5.1.0','>=')) + file_put_contents($fileName,$content,LOCK_EX); + else + file_put_contents($fileName,$content); + } + } +} +?>getApplication()->setErrorHandler($this); + } +public function getErrorTemplatePath() + { + return $this->_templatePath; + } +public function setErrorTemplatePath($value) + { + if(($templatePath=Prado::getPathOfNamespace($this->_templatePath))!==null && is_dir($templatePath)) + $this->_templatePath=$templatePath; + else + throw new TConfigurationException('errorhandler_errortemplatepath_invalid',$value); + } +public function handleError($sender,$param) + { + static $handling=false; + restore_error_handler(); + restore_exception_handler(); + if($handling) + $this->handleRecursiveError($param); + else + { + $handling=true; + if(($response=$this->getResponse())!==null) + $response->clear(); + if(!headers_sent()) + header('Content-Type: text/html; charset=UTF-8'); + if($param instanceof THttpException) + $this->handleExternalError($param->getStatusCode(),$param); + else if($this->getApplication()->getMode()===TApplication::STATE_DEBUG) + $this->displayException($param); + else + $this->handleExternalError(500,$param); + } + exit(1); + } +protected function handleExternalError($statusCode,$exception) + { + if(!($exception instanceof THttpException)) + error_log($exception->__toString()); + if($this->_templatePath===null) + $this->_templatePath=Prado::getFrameworkPath().'/Exceptions/templates'; + $base=$this->_templatePath.'/'.self::ERROR_FILE_NAME; + $lang=Prado::getPreferredLanguage(); + if(is_file("$base$statusCode-$lang.html")) + $errorFile="$base$statusCode-$lang.html"; + else if(is_file("$base$statusCode.html")) + $errorFile="$base$statusCode.html"; + else if(is_file("$base-$lang.html")) + $errorFile="$base-$lang.html"; + else + $errorFile="$base.html"; + if(($content=@file_get_contents($errorFile))===false) + die("Unable to open error template file '$errorFile'."); +$serverAdmin=isset($_SERVER['SERVER_ADMIN'])?$_SERVER['SERVER_ADMIN']:''; + $tokens=array( + '%%StatusCode%%' => "$statusCode", + '%%ErrorMessage%%' => htmlspecialchars($exception->getMessage()), + '%%ServerAdmin%%' => $serverAdmin, + '%%Version%%' => $_SERVER['SERVER_SOFTWARE'].' PRADO/'.Prado::getVersion(), + '%%Time%%' => @strftime('%Y-%m-%d %H:%M',time()) + ); + echo strtr($content,$tokens); + } +protected function handleRecursiveError($exception) + { + if($this->getApplication()->getMode()===TApplication::STATE_DEBUG) + { + echo "Recursive Error\n"; + echo "

Recursive Error

\n"; + echo "
".$exception->__toString()."
\n"; + echo ""; + } + else + { + error_log("Error happened while processing an existing error:\n".$param->__toString()); + header('HTTP/1.0 500 Internal Error'); + } + } +protected function displayException($exception) + { + $lines=file($exception->getFile()); + $errorLine=$exception->getLine(); + $beginLine=$errorLine-self::SOURCE_LINES>=0?$errorLine-self::SOURCE_LINES:0; + $endLine=$errorLine+self::SOURCE_LINES<=count($lines)?$errorLine+self::SOURCE_LINES:count($lines); +$source=''; + for($i=$beginLine-1;$i<$endLine;++$i) + { + if($i===$errorLine-1) + { + $line=htmlspecialchars(sprintf("%04d: %s",$i+1,str_replace("\t",' ',$lines[$i]))); + $source.="
".$line."
"; + } + else + $source.=htmlspecialchars(sprintf("%04d: %s",$i+1,str_replace("\t",' ',$lines[$i]))); + } +$tokens=array( + '%%ErrorType%%' => get_class($exception), + '%%ErrorMessage%%' => htmlspecialchars($exception->getMessage()), + '%%SourceFile%%' => htmlspecialchars($exception->getFile()).' ('.$exception->getLine().')', + '%%SourceCode%%' => $source, + '%%StackTrace%%' => htmlspecialchars($exception->getTraceAsString()), + '%%Version%%' => $_SERVER['SERVER_SOFTWARE'].' PRADO/'.Prado::getVersion(), + '%%Time%%' => @strftime('%Y-%m-%d %H:%M',time()) + ); + $lang=Prado::getPreferredLanguage(); + $exceptionFile=Prado::getFrameworkPath().'/Exceptions/templates/'.self::EXCEPTION_FILE_NAME.'-'.$lang.'.html'; + if(!is_file($exceptionFile)) + $exceptionFile=Prado::getFrameworkPath().'/Exceptions/templates/'.self::EXCEPTION_FILE_NAME.'.html'; + if(($content=@file_get_contents($exceptionFile))===false) + die("Unable to open exception template file '$exceptionFile'."); + echo strtr($content,$tokens); + } +} +?>_requestUri=$_SERVER['REQUEST_URI']; + else $this->_requestUri=$_SERVER['SCRIPT_NAME'].(empty($_SERVER['QUERY_STRING'])?'':'?'.$_SERVER['QUERY_STRING']); +if(isset($_SERVER['PATH_INFO'])) + $this->_pathInfo=$_SERVER['PATH_INFO']; + else if(strpos($_SERVER['PHP_SELF'],$_SERVER['SCRIPT_NAME'])===0) + $this->_pathInfo=substr($_SERVER['PHP_SELF'],strlen($_SERVER['SCRIPT_NAME'])); + else + $this->_pathInfo=''; +if(get_magic_quotes_gpc()) + { + if(isset($_GET)) + $_GET=$this->stripSlashes($_GET); + if(isset($_POST)) + $_POST=$this->stripSlashes($_POST); + if(isset($_REQUEST)) + $_REQUEST=$this->stripSlashes($_REQUEST); + if(isset($_COOKIE)) + $_COOKIE=$this->stripSlashes($_COOKIE); + } +$this->_items=new TMap(array_merge($_POST,$_GET)); +$this->_initialized=true; + $this->getApplication()->setRequest($this); + } +public function stripSlashes(&$data) + { + return is_array($data)?array_map(array($this,'stripSlashes'),$data):stripslashes($data); + } +public function getUrl() + { + if($this->_url===null) + { + $secure=$this->getIsSecureConnection(); + $url=$secure?'https://':'http://'; + if(empty($_SERVER['HTTP_HOST'])) + { + $url.=$_SERVER['SERVER_NAME']; + $port=$_SERVER['SERVER_PORT']; + if(($port!=80 && !$secure) || ($port!=443 && $secure)) + $url.=':'.$port; + } + else + $url.=$_SERVER['HTTP_HOST']; + $url.=$this->getRequestUri(); + $this->_url=new TUri($url); + } + return $this->_url; + } +public function getRequestType() + { + return $_SERVER['REQUEST_METHOD']; + } +public function getIsSecureConnection() + { + return !empty($_SERVER['HTTPS']); + } +public function getPathInfo() + { + return $this->_pathInfo; + } +public function getQueryString() + { + return isset($_SERVER['QUERY_STRING'])?$_SERVER['QUERY_STRING']:''; + } +public function getRequestUri() + { + return $this->_requestUri; + } +public function getApplicationPath() + { + return $_SERVER['SCRIPT_NAME']; + } +public function getPhysicalApplicationPath() + { + return realpath($_SERVER['SCRIPT_FILENAME']); + } +public function getServerName() + { + return $_SERVER['SERVER_NAME']; + } +public function getServerPort() + { + return $_SERVER['SERVER_PORT']; + } +public function getUrlReferrer() + { + return isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:null; + } +public function getBrowser() + { + return get_browser(); + } +public function getUserAgent() + { + return $_SERVER['HTTP_USER_AGENT']; + } +public function getUserHostAddress() + { + return $_SERVER['REMOTE_ADDR']; + } +public function getUserHost() + { + return isset($_SERVER['REMOTE_HOST'])?$_SERVER['REMOTE_HOST']:null; + } +public function getAcceptTypes() + { + return $_SERVER['HTTP_ACCEPT']; + } +public function getUserLanguages() + { + return Prado::getUserLanguages(); + } +public function getItems() + { + return $this->_items; + } +public function getParameters() + { + return $this->_items; + } +public function getCookies() + { + if($this->_cookies===null) + { + $this->_cookies=new THttpCookieCollection; + foreach($_COOKIE as $key=>$value) + $this->_cookies->add(new THttpCookie($key,$value)); + } + return $this->_cookies; + } +public function getUploadedFiles() + { + return $_FILES; + } +public function getServerVariables() + { + return $_SERVER; + } +public function getEnvironmentVariables() + { + return $_ENV; + } +public function constructUrl($serviceID,$serviceParam,$getItems=null,$encodeAmpersand=false) + { + $url=$this->getApplicationPath(); + $url.='?'.$serviceID.'='; + if(!empty($serviceParam)) + $url.=$serviceParam; + $amp=$encodeAmpersand?'&':'&'; + if(is_array($getItems) || $getItems instanceof Traversable) + { + foreach($getItems as $name=>$value) + $url.=$amp.urlencode($name).'='.urlencode($value); + } + if(defined('SID') && SID != '') + $url.=$amp.SID; + return $url; + } +protected function resolveRequest() + { + + $this->_requestResolved=true; + foreach($this->_services as $id) + { + if(isset($_GET[$id])) + { + $this->setServiceID($id); + $this->setServiceParameter($_GET[$id]); + break; + } + } + } +public function getAvailableServices() + { + return $this->_services; + } +public function setAvailableServices($services) + { + $this->_services=$services; + } +public function getServiceID() + { + if(!$this->_requestResolved) + $this->resolveRequest(); + return $this->_serviceID; + } +protected function setServiceID($value) + { + $this->_serviceID=$value; + } +public function getServiceParameter() + { + if(!$this->_requestResolved) + $this->resolveRequest(); + return $this->_serviceParam; + } +protected function setServiceParameter($value) + { + $this->_serviceParam=$value; + } +} +class THttpCookieCollection extends TList +{ +private $_o; +public function __construct($owner=null) + { + parent::__construct(); + $this->_o=$owner; + } +protected function addedItem($item) + { + if($this->_o instanceof THttpResponse) + $this->_o->addCookie($item); + } +protected function removedItem($item) + { + if($this->_o instanceof THttpResponse) + $this->_o->removeCookie($item); + } +protected function canAddItem($item) + { + return ($item instanceof THttpCookie); + } +} +class THttpCookie extends TComponent +{ +private $_domain=''; +private $_name; +private $_value=0; +private $_expire=0; +private $_path='/'; +private $_secure=false; +public function __construct($name,$value) + { + parent::__construct(); + $this->_name=$name; + $this->_value=$value; + } +public function getDomain() + { + return $this->_domain; + } +public function setDomain($value) + { + $this->_domain=$value; + } +public function getExpire() + { + return $this->_expire; + } +public function setExpire($value) + { + $this->_expire=TPropertyValue::ensureInteger($value); + } +public function getName() + { + return $this->_name; + } +public function setName($value) + { + $this->_name=$value; + } +public function getValue() + { + return $this->_value; + } +public function setValue($value) + { + $this->_value=$value; + } +public function getPath() + { + return $this->_path; + } +public function setPath($value) + { + $this->_path=$value; + } +public function getSecure() + { + return $this->_secure; + } +public function setSecure($value) + { + $this->_secure=TPropertyValue::ensureBoolean($value); + } +} +class TUri extends TComponent +{ +private static $_defaultPort=array( + 'ftp'=>21, + 'gopher'=>70, + 'http'=>80, + 'https'=>443, + 'news'=>119, + 'nntp'=>119, + 'wais'=>210, + 'telnet'=>23 + ); +private $_scheme; +private $_host; +private $_port; +private $_user; +private $_pass; +private $_path; +private $_query; +private $_fragment; +private $_uri; +public function __construct($uri) + { + parent::__construct(); + if(($ret=@parse_url($uri))!==false) + { + $this->_scheme=$ret['scheme']; + $this->_host=$ret['host']; + $this->_port=$ret['port']; + $this->_user=$ret['user']; + $this->_pass=$ret['pass']; + $this->_path=$ret['path']; + $this->_query=$ret['query']; + $this->_fragment=$ret['fragment']; + $this->_uri=$uri; + } + else + { + throw new TInvalidDataValueException('uri_format_invalid',$uri); + } + } +public function getUri() + { + return $this->_uri; + } +public function getScheme() + { + return $this->_scheme; + } +public function getHost() + { + return $this->_host; + } +public function getPort() + { + return $this->_port; + } +public function getUser() + { + return $this->_user; + } +public function getPassword() + { + return $this->_pass; + } +public function getPath() + { + return $this->_path; + } +public function getQuery() + { + return $this->_query; + } +public function getFragment() + { + return $this->_fragment; + } +} +?>_bufferOutput) + @ob_end_flush(); + parent::__destruct(); + } +public function init($config) + { + if($this->_bufferOutput) + ob_start(); + $this->_initialized=true; + $this->getApplication()->setResponse($this); + } +public function getCacheExpire() + { + return session_cache_expire(); + } +public function setCacheExpire($value) + { + session_cache_expire(TPropertyValue::ensureInteger($value)); + } +public function getCacheControl() + { + return session_cache_limiter(); + } +public function setCacheControl($value) + { + session_cache_limiter(TPropertyValue::ensureEnum($value,array('none','nocache','private','private_no_expire','public'))); + } +public function setContentType($type) + { + $this->_contentType = $type; + } +public function getContentType() + { + return $this->_contentType; + } +public function getCharset() + { + return $this->_charset; + } +public function setCharset($charset) + { + $this->_charset = $charset; + } +public function getBufferOutput() + { + return $this->_bufferOutput; + } +public function setBufferOutput($value) + { + if($this->_initialized) + throw new TInvalidOperationException('httpresponse_bufferoutput_unchangeable'); + else + $this->_bufferOutput=TPropertyValue::ensureBoolean($value); + } +public function getStatusCode() + { + return $this->_status; + } +public function setStatusCode($status) + { + $this->_status=TPropertyValue::ensureInteger($status); + } +public function getCookies() + { + if($this->_cookies===null) + $this->_cookies=new THttpCookieCollection($this); + return $this->_cookies; + } +public function write($str) + { + echo $str; + } +public function writeFile($fileName) + { + static $defaultMimeTypes=array( + 'css'=>'text/css', + 'gif'=>'image/gif', + 'jpg'=>'image/jpeg', + 'jpeg'=>'image/jpeg', + 'htm'=>'text/html', + 'html'=>'text/html', + 'js'=>'javascript/js' + ); +if(!is_file($fileName)) + throw new TInvalidDataValueException('httpresponse_file_inexistent',$fileName); + header('Pragma: public'); + header('Expires: 0'); + header('Cache-Component: must-revalidate, post-check=0, pre-check=0'); + $mimeType='text/plain'; + if(function_exists('mime_content_type')) + $mimeType=mime_content_type($fileName); + else + { + $ext=array_pop(explode('.',$fileName)); + if(isset($defaultMimeTypes[$ext])) + $mimeType=$defaultMimeTypes[$ext]; + } + $fn=basename($fileName); + header("Content-type: $mimeType"); + header('Content-Length: '.filesize($fileName)); + header("Content-Disposition: attachment; filename=\"$fn\""); + header('Content-Transfer-Encoding: binary'); + readfile($fileName); + } +public function redirect($url) + { + header('Location:'.$url); + exit(); + } +public function flush() + { + $header = $this->getContentTypeHeader(); + $this->appendHeader($header); + if($this->_bufferOutput) + ob_flush(); + + } +protected function getContentTypeHeader() + { + $app = $this->getApplication()->getGlobalization(); + $charset = $this->getCharset(); + if(empty($charset)) + $charset = !is_null($app) ? $app->getCharset() : 'UTF-8'; + $type = $this->getContentType(); + return "Content-Type: $type; charset=$charset"; + } +public function clear() + { + if($this->_bufferOutput) + ob_clean(); + + } +public function appendHeader($value) + { + header($value); + } +public function sendContentTypeHeader($type=null) + { +} +public function appendLog($message,$messageType=0,$destination='',$extraHeaders='') + { + error_log($message,$messageType,$destination,$extraHeaders); + } +public function addCookie($cookie) + { + setcookie($cookie->getName(),$cookie->getValue(),$cookie->getExpire(),$cookie->getPath(),$cookie->getDomain(),$cookie->getSecure()); + } +public function removeCookie($cookie) + { + setcookie($cookie->getName(),null,0,$cookie->getPath(),$cookie->getDomain(),$cookie->getSecure()); + } +public function getHtmlWriterType() + { + return $this->_htmlWriterType; + } +public function setHtmlWriterType($value) + { + $this->_htmlWriterType=$value; + } +public function createHtmlWriter($type=null) + { + if($type===null) + $type=$this->_htmlWriterType; + return Prado::createComponent($type,$this); + } +} +?>_autoStart) + session_start(); + $this->_initialized=true; + $this->getApplication()->setSession($this); + } +public function open() + { + if(!$this->_started) + { + if($this->_cookie!==null) + session_set_cookie_params($this->_cookie->getExpire(),$this->_cookie->getPath(),$this->_cookie->getDomain(),$this->_cookie->getSecure()); + session_start(); + $this->_started=true; + } + } +public function close() + { + if($this->_started) + { + session_write_close(); + $this->_started=false; + } + } +public function destroy() + { + if($this->_started) + { + session_destroy(); + $this->_started=false; + } + } +public function getItems() + { + if($this->_items===null) + $this->_items=new THttpSessionCollection($_SESSION); + return $this->_items; + } +public function getIsStarted() + { + return $this->_started; + } +public function getSessionID() + { + return session_id(); + } +public function setSessionID($value) + { + if($this->_started) + throw new TInvalidOperationException('httpsession_sessionid_unchangeable'); + else + session_id($value); + } +public function getSessionName() + { + return session_name(); + } +public function setSessionName($value) + { + if($this->_started) + throw new TInvalidOperationException('httpsession_sessionname_unchangeable'); + else if(ctype_alnum($value)) + session_name($value); + else + throw new TInvalidDataValueException('httpsession_sessionname_invalid',$name); + } +public function getSavePath() + { + return session_save_path(); + } +public function setSavePath($value) + { + if($this->_started) + throw new TInvalidOperationException('httpsession_savepath_unchangeable'); + else if(is_dir($value)) + session_save_path($value); + else + throw new TInvalidDataValueException('httpsession_savepath_invalid',$value); + } +public function getStorage() + { + switch(session_module_name()) + { + case 'files': return 'File'; + case 'mm': return 'SharedMemory'; + case 'user': return 'Custom'; + default: return 'Unknown'; + } + } +public function setStorage($value) + { + if($this->_started) + throw new TInvalidOperationException('httpsession_storage_unchangeable'); + else + { + $value=TPropertyValue::ensureEnum($value,array('File','SharedMemory','Custom')); + if($value==='Custom') + session_set_save_handler(array($this,'_open'),array($this,'_close'),array($this,'_read'),array($this,'_write'),array($this,'_destroy'),array($this,'_gc')); + switch($value) + { + case 'Custom': + session_module_name('user'); + break; + case 'SharedMemory': + session_module_name('mm'); + break; + default: + session_module_name('files'); + break; + } + } + } +public function getCookie() + { + if($this->_cookie===null) + $this->_cookie=new THttpCookie($this->getSessionName(),$this->getSessionID()); + return $this->_cookie; + } +public function getCookieMode() + { + if(ini_get('session.use_cookies')==='0') + return 'None'; + else if(ini_get('session.use_only_cookies')==='0') + return 'Allow'; + else + return 'Only'; + } +public function setCookieMode($value) + { + if($this->_started) + throw new TInvalidOperationException('httpsession_cookiemode_unchangeable'); + else + { + $value=TPropertyValue::ensureEnum($value,array('None','Allow','Only')); + if($value==='None') + ini_set('session.use_cookies','0'); + else if($value==='Allow') + { + ini_set('session.use_cookies','1'); + ini_set('session.use_only_cookies','0'); + } + else + { + ini_set('session.use_cookies','1'); + ini_set('session.use_only_cookies','1'); + } + } + } +public function getAutoStart() + { + return $this->_autoStart; + } +public function setAutoStart($value) + { + if($this->_initialized) + throw new TInvalidOperationException('httpsession_autostart_unchangeable'); + else + $this->_autoStart=TPropertyValue::ensureBoolean($value); + } +public function getGCProbability() + { + return TPropertyValue::ensureInteger(ini_get('session.gc_probability')); + } +public function setGCProbability($value) + { + if($this->_started) + throw new TInvalidOperationException('httpsession_gcprobability_unchangeable'); + else + { + $value=TPropertyValue::ensureInteger($value); + if($value>=0 && $value<=100) + { + ini_set('session.gc_probability',$value); + ini_set('session.gc_divisor','100'); + } + else + throw new TInvalidDataValueException('httpsession_gcprobability_invalid',$value); + } + } +public function getUseTransparentSessionID() + { + return ini_get('session.use_trans_sid')==='1'; + } +public function setUseTransparentSessionID($value) + { + if($this->_started) + throw new TInvalidOperationException('httpsession_transid_unchangeable'); + else + ini_set('session.use_only_cookies',TPropertyValue::ensureBoolean($value)?'1':'0'); + } +public function getTimeout() + { + return TPropertyValue::ensureInteger(ini_get('session.gc_maxlifetime')); + } +public function setTimeout($value) + { + if($this->_started) + throw new TInvalidOperationException('httpsession_maxlifetime_unchangeable'); + else + ini_set('session.gc_maxlifetime',$value); + } +public function _open($savePath,$sessionName) + { + return true; + } +public function _close() + { + return true; + } +public function _read($id) + { + return ''; + } +public function _write($id,$data) + { + return true; + } +public function _destroy($id) + { + return true; + } +public function _gc($maxLifetime) + { + return true; + } +} +class THttpSessionCollection extends TMap +{ +private $_initialized=false; +public function __construct($data=null) + { + parent::__construct($data); + $this->_initialized=true; + } +protected function addedItem($key,$value) + { + if($this->_initialized) + $_SESSION[$key]=$value; + } +protected function removedItem($key,$value) + { + unset($_SESSION[$key]); + } +} +?>_action=$action; + else + throw new TInvalidDataValueException('authorizationrule_action_invalid',$action); + $this->_users=array(); + $this->_roles=array(); + $this->_everyone=false; + $this->_guest=false; + foreach(explode(',',$users) as $user) + { + if(($user=trim(strtolower($user)))!=='') + { + if($user==='*') + $this->_everyone=true; + else if($user==='?') + $this->_guest=true; + else + $this->_users[]=$user; + } + } + foreach(explode(',',$roles) as $role) + { + if(($role=trim(strtolower($role)))!=='') + $this->_roles[]=$role; + } + $verb=trim(strtolower($verb)); + if($verb==='' || $verb==='get' || $verb==='post') + $this->_verb=$verb; + else + throw new TInvalidDataValueException('authorizationrule_verb_invalid',$verb); + } +public function getAction() + { + return $this->_action; + } +public function getUsers() + { + return $this->_users; + } +public function getRoles() + { + return $this->_roles; + } +public function getVerb() + { + return $this->_verb; + } +public function getGuestApplied() + { + return $this->_guest; + } +public function getEveryoneApplied() + { + return $this->_everyone; + } +public function isUserAllowed(IUser $user,$verb) + { + $decision=($this->_action==='allow')?1:-1; + if($this->_verb==='' || strcasecmp($verb,$this->_verb)===0) + { + if($this->_everyone || ($this->_guest && $user->getIsGuest())) + return $decision; + if(in_array(strtolower($user->getName()),$this->_users)) + return $decision; + foreach($this->_roles as $role) + if($user->isInRole($role)) + return $decision; + } + return 0; + } +} +class TAuthorizationRuleCollection extends TList +{ +public function isUserAllowed($user,$verb) + { + if($user instanceof IUser) + { + $verb=strtolower(trim($verb)); + foreach($this as $rule) + { + if(($decision=$rule->isUserAllowed($user,$verb))!==0) + return ($decision>0); + } + return true; + } + else + return false; + } +protected function canAddItem($item) + { + return ($item instanceof TAuthorizationRule); + } +} +?>getApplication(); +$application->setPageService($this); +if($this->_basePath===null) + { + $basePath=$application->getBasePath().'/'.self::DEFAULT_BASEPATH; + if(($this->_basePath=realpath($basePath))===false || !is_dir($this->_basePath)) + throw new TConfigurationException('pageservice_basepath_invalid',$basePath); + } +$this->_pagePath=$application->getRequest()->getServiceParameter(); + if(empty($this->_pagePath)) + $this->_pagePath=$this->_defaultPage; + if(empty($this->_pagePath)) + throw new THttpException(404,'pageservice_page_required'); +if(($cache=$application->getCache())===null) + { + $pageConfig=new TPageConfiguration; + if($config!==null) + $pageConfig->loadXmlElement($config,$application->getBasePath(),null); + $pageConfig->loadConfigurationFiles($this->_pagePath,$this->_basePath); + } + else + { + $configCached=true; + $currentTimestamp=array(); + $arr=$cache->get(self::CONFIG_CACHE_PREFIX.$this->_pagePath); + if(is_array($arr)) + { + list($pageConfig,$timestamps)=$arr; + if($application->getMode()!==TApplication::STATE_PERFORMANCE) + { + foreach($timestamps as $fileName=>$timestamp) + { + if($fileName===0) { + $appConfigFile=$application->getConfigurationFile(); + $currentTimestamp[0]=$appConfigFile===null?0:@filemtime($appConfigFile); + if($currentTimestamp[0]>$timestamp || ($timestamp>0 && !$currentTimestamp[0])) + $configCached=false; + } + else + { + $currentTimestamp[$fileName]=@filemtime($fileName); + if($currentTimestamp[$fileName]>$timestamp || ($timestamp>0 && !$currentTimestamp[$fileName])) + $configCached=false; + } + } + } + } + else + { + $configCached=false; + $paths=explode('.',$this->_pagePath); + array_pop($paths); + $configPath=$this->_basePath; + foreach($paths as $path) + { + $configFile=$configPath.'/'.self::CONFIG_FILE; + $currentTimestamp[$configFile]=@filemtime($configFile); + $configPath.='/'.$path; + } + $appConfigFile=$application->getConfigurationFile(); + $currentTimestamp[0]=$appConfigFile===null?0:@filemtime($appConfigFile); + } + if(!$configCached) + { + $pageConfig=new TPageConfiguration; + if($config!==null) + $pageConfig->loadXmlElement($config,$application->getBasePath(),null); + $pageConfig->loadConfigurationFiles($this->_pagePath,$this->_basePath); + $cache->set(self::CONFIG_CACHE_PREFIX.$this->_pagePath,array($pageConfig,$currentTimestamp)); + } + } +foreach($pageConfig->getAliases() as $alias=>$path) + Prado::setPathOfAlias($alias,$path); + foreach($pageConfig->getUsings() as $using) + Prado::using($using); +$this->_properties=$pageConfig->getProperties(); +$parameters=$application->getParameters(); + foreach($pageConfig->getParameters() as $id=>$parameter) + { + if(is_string($parameter)) + $parameters->add($id,$parameter); + else + { + $component=Prado::createComponent($parameter[0]); + foreach($parameter[1] as $name=>$value) + $component->setSubProperty($name,$value); + $parameters->add($id,$component); + } + } +foreach($pageConfig->getModules() as $id=>$moduleConfig) + { + + $module=Prado::createComponent($moduleConfig[0]); + $application->setModule($id,$module); + foreach($moduleConfig[1] as $name=>$value) + $module->setSubProperty($name,$value); + $module->init($moduleConfig[2]); + } +$application->getAuthorizationRules()->mergeWith($pageConfig->getRules()); +$this->_initialized=true; + } +public function getID() + { + return $this->_id; + } +public function setID($value) + { + $this->_id=$value; + } +public function getTemplateManager() + { + if(!$this->_templateManager) + { + $this->_templateManager=new TTemplateManager; + $this->_templateManager->init(null); + } + return $this->_templateManager; + } +public function setTemplateManager(TTemplateManager $value) + { + $this->_templateManager=$value; + } +public function getAssetManager() + { + if(!$this->_assetManager) + { + $this->_assetManager=new TAssetManager; + $this->_assetManager->init(null); + } + return $this->_assetManager; + } +public function setAssetManager(TAssetManager $value) + { + $this->_assetManager=$value; + } +public function getThemeManager() + { + if(!$this->_themeManager) + { + $this->_themeManager=new TThemeManager; + $this->_themeManager->init(null); + } + return $this->_themeManager; + } +public function setThemeManager(TThemeManager $value) + { + $this->_themeManager=$value; + } +public function getPageStatePersister() + { + if(!$this->_pageStatePersister) + { + $this->_pageStatePersister=new TPageStatePersister; + $this->_pageStatePersister->init(null); + } + return $this->_pageStatePersister; + } +public function setPageStatePersister(IStatePersister $value) + { + $this->_pageStatePersister=$value; + } +public function getRequestedPagePath() + { + return $this->_pagePath; + } +public function getRequestedPage() + { + return $this->_page; + } +public function getDefaultPage() + { + return $this->_defaultPage; + } +public function setDefaultPage($value) + { + if($this->_initialized) + throw new TInvalidOperationException('pageservice_defaultpage_unchangeable'); + else + $this->_defaultPage=$value; + } +public function getBasePath() + { + return $this->_basePath; + } +public function setBasePath($value) + { + if($this->_initialized) + throw new TInvalidOperationException('pageservice_basepath_unchangeable'); + else if(($this->_basePath=realpath(Prado::getPathOfNamespace($value)))===false || !is_dir($this->_basePath)) + throw new TConfigurationException('pageservice_basepath_invalid',$value); + } +public function run() + { + + $page=null; + $path=$this->_basePath.'/'.strtr($this->_pagePath,'.','/'); + if(is_file($path.self::PAGE_FILE_EXT)) + { + if(is_file($path.Prado::CLASS_FILE_EXT)) + { + $className=basename($path); + if(!class_exists($className,false)) + include_once($path.Prado::CLASS_FILE_EXT); + if(!class_exists($className,false)) + throw new TConfigurationException('pageservice_pageclass_unknown',$className); + } + else + $className='TPage'; + $this->_properties['Template']=$this->getTemplateManager()->getTemplateByFileName($path.self::PAGE_FILE_EXT); + $this->_page=new $className($this->_properties); + } + else + throw new THttpException(404,'pageservice_page_unknown',$this->_pagePath); +$writer=$this->getResponse()->createHtmlWriter(); + $this->_page->run($writer); + $writer->flush(); + } +public function constructUrl($pagePath,$getParams=null,$encodeAmpersand=false) + { + return $this->getRequest()->constructUrl($this->_id,$pagePath,$getParams,$encodeAmpersand); + } +public function getAsset($path) + { + return $this->getAssetManager()->publishFilePath($path); + } +} +class TPageConfiguration extends TComponent +{ +private $_properties=array(); +private $_usings=array(); +private $_aliases=array(); +private $_modules=array(); +private $_parameters=array(); +private $_rules=array(); +public function getProperties() + { + return $this->_properties; + } +public function getAliases() + { + return $this->_aliases; + } +public function getUsings() + { + return $this->_usings; + } +public function getModules() + { + return $this->_modules; + } +public function getParameters() + { + return $this->_parameters; + } +public function getRules() + { + return $this->_rules; + } +public function loadConfigurationFiles($pagePath,$basePath) + { + $paths=explode('.',$pagePath); + $page=array_pop($paths); + $path=$basePath; + foreach($paths as $p) + { + $this->loadFromFile($path.'/'.TPageService::CONFIG_FILE,null); + $path.='/'.$p; + } + $this->loadFromFile($path.'/'.TPageService::CONFIG_FILE,$page); + $this->_rules=new TAuthorizationRuleCollection($this->_rules); + } +private function loadFromFile($fname,$page) + { + + if(empty($fname) || !is_file($fname)) + return; + $dom=new TXmlDocument; + if($dom->loadFromFile($fname)) + $this->loadXmlElement($dom,dirname($fname),$page); + else + throw new TConfigurationException('pageserviceconf_file_invalid',$fname); + } +public function loadXmlElement($dom,$configPath,$page) + { + if(($pathsNode=$dom->getElementByTagName('paths'))!==null) + { + foreach($pathsNode->getElementsByTagName('alias') as $aliasNode) + { + if(($id=$aliasNode->getAttribute('id'))!==null && ($p=$aliasNode->getAttribute('path'))!==null) + { + $p=str_replace('\\','/',$p); + $path=realpath(preg_match('/^\\/|.:\\//',$p)?$p:$configPath.'/'.$p); + if($path===false || !is_dir($path)) + throw new TConfigurationException('pageserviceconf_aliaspath_invalid',$id,$p,$configPath); + if(isset($this->_aliases[$id])) + throw new TConfigurationException('pageserviceconf_alias_redefined',$id,$configPath); + $this->_aliases[$id]=$path; + } + else + throw new TConfigurationException('pageserviceconf_alias_invalid',$configPath); + } + foreach($pathsNode->getElementsByTagName('using') as $usingNode) + { + if(($namespace=$usingNode->getAttribute('namespace'))!==null) + $this->_usings[]=$namespace; + else + throw new TConfigurationException('pageserviceconf_using_invalid',$configPath); + } + } +if(($modulesNode=$dom->getElementByTagName('modules'))!==null) + { + foreach($modulesNode->getElementsByTagName('module') as $node) + { + $properties=$node->getAttributes(); + $type=$properties->remove('class'); + if(($id=$properties->itemAt('id'))===null) + throw new TConfigurationException('pageserviceconf_module_invalid',$configPath); + if(isset($this->_modules[$id])) + { + if($type===null || $type===$this->_modules[$id][0]) + { + $this->_modules[$id][1]=array_merge($this->_modules[$id][1],$properties->toArray()); + $elements=$this->_modules[$id][2]->getElements(); + foreach($node->getElements() as $element) + $elements->add($element); + } + else + { + $node->setParent(null); + $this->_modules[$id]=array($type,$properties->toArray(),$node); + } + } + else if($type===null) + throw new TConfigurationException('pageserviceconf_moduletype_required',$id,$configPath); + else + { + $node->setParent(null); + $this->_modules[$id]=array($type,$properties->toArray(),$node); + } + } + } +if(($parametersNode=$dom->getElementByTagName('parameters'))!==null) + { + foreach($parametersNode->getElementsByTagName('parameter') as $node) + { + $properties=$node->getAttributes(); + if(($id=$properties->remove('id'))===null) + throw new TConfigurationException('pageserviceconf_parameter_invalid',$configPath); + if(($type=$properties->remove('class'))===null) + $this->_parameters[$id]=$node->getValue(); + else + $this->_parameters[$id]=array($type,$properties->toArray()); + } + } +if(($authorizationNode=$dom->getElementByTagName('authorization'))!==null) + { + $rules=array(); + foreach($authorizationNode->getElements() as $node) + { + $pages=$node->getAttribute('pages'); + $ruleApplies=false; + if(empty($pages)) + $ruleApplies=true; + else if($page!==null) + { + $ps=explode(',',$pages); + foreach($ps as $p) + { + if($page===trim($p)) + { + $ruleApplies=true; + break; + } + } + } + if($ruleApplies) + $rules[]=new TAuthorizationRule($node->getTagName(),$node->getAttribute('users'),$node->getAttribute('roles'),$node->getAttribute('verb')); + } + $this->_rules=array_merge($rules,$this->_rules); + } +if(($pagesNode=$dom->getElementByTagName('pages'))!==null) + { + $this->_properties=array_merge($this->_properties,$pagesNode->getAttributes()->toArray()); + if($page!==null) { + foreach($pagesNode->getElementsByTagName('page') as $node) + { + $properties=$node->getAttributes(); + if(($id=$properties->itemAt('id'))===null) + throw new TConfigurationException('pageserviceconf_page_invalid',$configPath); + if($id===$page) + $this->_properties=array_merge($this->_properties,$properties->toArray()); + } + } + } + } +} +?>2, + 'a'=>0, + 'acronym'=>0, + 'address'=>2, + 'area'=>1, + 'b'=>0, + 'base'=>1, + 'basefont'=>1, + 'bdo'=>0, + 'bgsound'=>1, + 'big'=>0, + 'blockquote'=>2, + 'body'=>2, + 'br'=>2, + 'button'=>0, + 'caption'=>2, + 'center'=>2, + 'cite'=>0, + 'code'=>0, + 'col'=>1, + 'colgroup'=>2, + 'del'=>0, + 'dd'=>0, + 'dfn'=>0, + 'dir'=>2, + 'div'=>2, + 'dl'=>2, + 'dt'=>0, + 'em'=>0, + 'embed'=>1, + 'fieldset'=>2, + 'font'=>0, + 'form'=>2, + 'frame'=>1, + 'frameset'=>2, + 'h1'=>2, + 'h2'=>2, + 'h3'=>2, + 'h4'=>2, + 'h5'=>2, + 'h6'=>2, + 'head'=>2, + 'hr'=>1, + 'html'=>2, + 'i'=>0, + 'iframe'=>2, + 'img'=>1, + 'input'=>1, + 'ins'=>0, + 'isindex'=>1, + 'kbd'=>0, + 'label'=>0, + 'legend'=>2, + 'li'=>0, + 'link'=>1, + 'map'=>2, + 'marquee'=>2, + 'menu'=>2, + 'meta'=>1, + 'nobr'=>0, + 'noframes'=>2, + 'noscript'=>2, + 'object'=>2, + 'ol'=>2, + 'option'=>2, + 'p'=>0, + 'param'=>2, + 'pre'=>2, + 'ruby'=>2, + 'rt'=>2, + 'q'=>0, + 's'=>0, + 'samp'=>0, + 'script'=>2, + 'select'=>2, + 'small'=>2, + 'span'=>0, + 'strike'=>0, + 'strong'=>0, + 'style'=>2, + 'sub'=>0, + 'sup'=>0, + 'table'=>2, + 'tbody'=>2, + 'td'=>0, + 'textarea'=>0, + 'tfoot'=>2, + 'th'=>0, + 'thead'=>2, + 'title'=>2, + 'tr'=>2, + 'tt'=>0, + 'u'=>0, + 'ul'=>2, + 'var'=>0, + 'wbr'=>1, + 'xml'=>2 + ); + private static $_attrEncode=array( + 'abbr'=>true, + 'accesskey'=>true, + 'alt'=>true, + 'axis'=>true, + 'background'=>true, + 'class'=>true, + 'content'=>true, + 'headers'=>true, + 'href'=>true, + 'longdesc'=>true, + 'onclick'=>true, + 'onchange'=>true, + 'src'=>true, + 'title'=>true, + 'value'=>true + ); + private static $_styleEncode=array( + 'background-image'=>true, + 'list-style-image'=>true + ); + private $_attributes=array(); + private $_openTags=array(); + private $_writer=null; + private $_styles=array(); +public function __construct($writer) + { + $this->_writer=$writer; + } +public function isValidFormAttribute($name) + { + return true; + } +public function addAttributes($attrs) + { + foreach($attrs as $name=>$value) + $this->_attributes[$name]=isset(self::$_attrEncode[$name])?THttpUtility::htmlEncode($value):$value; + } +public function addAttribute($name,$value) + { + $this->_attributes[$name]=isset(self::$_attrEncode[$name])?THttpUtility::htmlEncode($value):$value; + } +public function addStyleAttribute($name,$value) + { + $this->_styles[$name]=isset(self::$_styleEncode[$name])?THttpUtility::htmlEncode($value):$value; + } +public function flush() + { + $this->_writer->flush(); + } +public function write($str) + { + $this->_writer->write($str); + } +public function writeLine($str='') + { + $this->_writer->write($str.self::CHAR_NEWLINE); + } +public function writeBreak() + { + $this->_writer->write('
'); + } +public function writeAttribute($name,$value,$encode=false) + { + $this->_writer->write(' '.$name.='"'.($encode?THttpUtility::htmlEncode($value):$value).'"'); + } +public function renderBeginTag($tagName) + { + $tagType=isset(self::$_tagTypes[$tagName])?self::$_tagTypes[$tagName]:self::TAG_OTHER; + $str='<'.$tagName; + foreach($this->_attributes as $name=>$value) + $str.=' '.$name.'="'.$value.'"'; + if(!empty($this->_styles)) + { + $str.=' style="'; + foreach($this->_styles as $name=>$value) + $str.=$name.':'.$value.';'; + $str.='"'; + } + if($tagType===self::TAG_NONCLOSING) + { + $str.=' />'; + array_push($this->_openTags,''); + } + else + { + $str.='>'; + array_push($this->_openTags,$tagName); + } + $this->_writer->write($str); + $this->_attributes=array(); + $this->_styles=array(); + } +public function renderEndTag() + { + if(!empty($this->_openTags) && ($tagName=array_pop($this->_openTags))!=='') + $this->_writer->write(''); + } +} +?>getService()->setTemplateManager($this); + } +public function getTemplateByClassName($className) + { + $class=new ReflectionClass($className); + $tplFile=dirname($class->getFileName()).'/'.$className.self::TEMPLATE_FILE_EXT; + return $this->getTemplateByFileName($tplFile); + } +public function getTemplateByFileName($fileName) + { + if(!is_null($fileName=$this->getLocalizedTemplate($fileName))) + { + + if(($cache=$this->getApplication()->getCache())===null) + return new TTemplate(file_get_contents($fileName),dirname($fileName),$fileName); + else + { + $array=$cache->get(self::TEMPLATE_CACHE_PREFIX.$fileName); + if(is_array($array)) + { + list($template,$timestamp)=$array; + if(filemtime($fileName)<$timestamp) + return $template; + } + $template=new TTemplate(file_get_contents($fileName),dirname($fileName),$fileName); + $cache->set(self::TEMPLATE_CACHE_PREFIX.$fileName,array($template,time())); + return $template; + } + } + else + return null; + } +protected function getLocalizedTemplate($filename) + { + $app = $this->getApplication()->getGlobalization(); + if(is_null($app)) return $filename; + foreach($app->getLocalizedResource($filename) as $file) + { + if(($file=realpath($file))!==false && is_file($file)) + return $file; + } +} +} +class TTemplate extends TComponent implements ITemplate +{ +const REGEX_RULES='/||<\/?com:([\w\.]+)((?:\s*[\w\.]+=\'.*?\'|\s*[\w\.]+=".*?"|\s*[\w\.]+=<%.*?%>)*)\s*\/?>|<\/?prop:([\w\.]+)\s*>|<%@\s*((?:\s*[\w\.]+=\'.*?\'|\s*[\w\.]+=".*?")*)\s*%>|<%[%#~\\$=\\[](.*?)%>/msS'; +const CONFIG_DATABIND=0; + const CONFIG_EXPRESSION=1; + const CONFIG_ASSET=2; + const CONFIG_PARAMETER=3; + const CONFIG_LOCALIZATION=4; +private $_tpl=array(); +private $_directive=array(); +private $_contextPath; +private $_tplFile=null; +private $_assetManager; +public function __construct($template,$contextPath,$tplFile=null) + { + $this->_contextPath=$contextPath; + $this->_tplFile=$tplFile; + $this->parse($template); + } +public function getContextPath() + { + return $this->_contextPath; + } +public function getDirective() + { + return $this->_directive; + } +public function &getItems() + { + return $this->_tpl; + } +public function instantiateIn($tplControl) + { + if(($page=$tplControl->getPage())===null) + $page=$this->getService()->getRequestedPage(); + $this->_assetManager=$this->getService()->getAssetManager(); + $controls=array(); + foreach($this->_tpl as $key=>$object) + { + if(isset($object[2])) { + $component=Prado::createComponent($object[1]); + if($component instanceof TControl) + { + $controls[$key]=$component; + $component->setTemplateControl($tplControl); + if(isset($object[2]['id'])) + $tplControl->registerObject($object[2]['id'],$component); + if(isset($object[2]['skinid'])) + { + $component->setSkinID($object[2]['skinid']); + unset($object[2]['skinid']); + } + $component->applyStyleSheetSkin($page); + foreach($object[2] as $name=>$value) + $this->configureControl($component,$name,$value); + $parent=isset($controls[$object[0]])?$controls[$object[0]]:$tplControl; + $component->createdOnTemplate($parent); + } + else if($component instanceof TComponent) + { + if(isset($object[2]['id'])) + { + $tplControl->registerObject($object[2]['id'],$component); + if(!$component->hasProperty('id')) + unset($object[2]['id']); + } + foreach($object[2] as $name=>$value) + $this->configureComponent($component,$name,$value); + $parent=isset($controls[$object[0]])?$controls[$object[0]]:$tplControl; + $parent->addParsedObject($component); + } + else + throw new TTemplateRuntimeException('template_component_required',$object[1]); + } + else { + if(isset($controls[$object[0]])) + $controls[$object[0]]->addParsedObject($object[1]); + else + $tplControl->addParsedObject($object[1]); + } + } + } +protected function configureControl($control,$name,$value) + { + if(is_string($value) && $control->hasEvent($name)) $this->configureEvent($control,$name,$value); + else if(strpos($name,'.')===false) { + if($control->hasProperty($name)) + $this->configureProperty($control,$name,$value); + else if($control->getAllowCustomAttributes()) + $this->configureAttribute($control,$name,$value); + else + throw new TTemplateRuntimeException('template_property_undefined',get_class($control),$name); + } + else { + $this->configureSubProperty($control,$name,$value); + } + } +protected function configureComponent($component,$name,$value) + { + if(strpos($name,'.')===false) { + if($component->hasProperty($name)) + $this->configureProperty($component,$name,$value); + else + throw new TTemplateRuntimeException('template_property_undefined',get_class($component),$name); + } + else { + $this->configureSubProperty($component,$name,$value); + } + } +protected function configureEvent($component,$name,$value) + { + $value=THttpUtility::htmlDecode($value); + if(strpos($value,'.')===false) + $component->attachEventHandler($name,array($component,'TemplateControl.'.$value)); + else + $component->attachEventHandler($name,array($component,$value)); + } +protected function configureProperty($component,$name,$value) + { + if($component->canSetProperty($name)) + { + $setter='set'.$name; + if(is_array($value)) + { + $v=THttpUtility::htmlDecode($value[1]); + switch($value[0]) + { + case self::CONFIG_DATABIND: + $component->bindProperty($name,$v); + break; + case self::CONFIG_EXPRESSION: + $component->$setter($component->evaluateExpression($v)); + break; + case self::CONFIG_ASSET: $url=$this->_assetManager->publishFilePath($this->_contextPath.'/'.$v); + $component->$setter($url); + break; + case self::CONFIG_PARAMETER: $component->$setter($this->getApplication()->getParameters()->itemAt($v)); + break; + case self::CONFIG_LOCALIZATION: + $component->$setter(localize($v)); + break; + default: break; + } + } + else + $component->$setter(THttpUtility::htmlDecode($value)); + } + else + throw new TTemplateRuntimeException('template_property_readonly',get_class($component),$name); + } +protected function configureSubProperty($component,$name,$value) + { + if(is_array($value)) + { + $v=THttpUtility::htmlDecode($value[1]); + switch($value[0]) + { + case self::CONFIG_DATABIND: $component->bindProperty($name,$v); + break; + case self::CONFIG_EXPRESSION: $component->setSubProperty($name,$component->evaluateExpression($v)); + break; + case self::CONFIG_ASSET: $url=$this->_assetManager->publishFilePath($this->_contextPath.'/'.$v); + $component->setSubProperty($name,$url); + break; + case self::CONFIG_PARAMETER: $component->setSubProperty($name,$this->getApplication()->getParameters()->itemAt($v)); + break; + case self::CONFIG_LOCALIZATION: + $component->setSubProperty($name,localize($v)); + break; + default: break; + } + } + else + $component->setSubProperty($name,THttpUtility::htmlDecode($value)); + } +protected function configureAttribute($control,$name,$value) + { + if(is_array($value)) + { + switch($value[0]) + { + case self::CONFIG_DATABIND: throw new TTemplateRuntimeException('template_attribute_unbindable',get_class($control),$name); + case self::CONFIG_EXPRESSION: + $value=$control->evaluateExpression($value[1]); + break; + case self::CONFIG_ASSET: + $value=$this->_assetManager->publishFilePath($this->_contextPath.'/'.ltrim($value[1],'/')); + break; + case self::CONFIG_PARAMETER: + $value=$this->getApplication()->getParameters()->itemAt($value[1]); + break; + case self::CONFIG_LOCALIZATION: + $value=localize($value[1]); + break; + default: + break; + } + } + $control->getAttributes()->add($name,$value); + } +protected function parse($input) + { + $tpl=&$this->_tpl; + $n=preg_match_all(self::REGEX_RULES,$input,$matches,PREG_SET_ORDER|PREG_OFFSET_CAPTURE); + $expectPropEnd=false; + $textStart=0; + $stack=array(); + $container=-1; + $c=0; + for($i=0;$i<$n;++$i) + { + $match=&$matches[$i]; + $str=$match[0][0]; + $matchStart=$match[0][1]; + $matchEnd=$matchStart+strlen($str)-1; + if(strpos($str,'$textStart) + $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart)); + $textStart=$matchEnd+1; + $type=$match[1][0]; + $attributes=$this->parseAttributes($match[2][0]); + $tpl[$c++]=array($container,$type,$attributes); + if($str[strlen($str)-2]!=='/') { + array_push($stack,$type); + $container=$c-1; + } + } + else if(strpos($str,'$textStart) + $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart)); + $textStart=$matchEnd+1; + $type=$match[1][0]; +if(empty($stack)) + { + $line=count(explode("\n",substr($input,0,$matchEnd+1))); + if($this->_tplFile===null) + throw new TTemplateParsingException('template_closingtag_unexpected',"Line $line",""); + else + throw new TTemplateParsingException('template_closingtag_unexpected',"{$this->_tplFile} (Line $line)",""); + } +$name=array_pop($stack); + if($name!==$type) + { + if($name[0]==='@') + $tag=''; + else + $tag=''; + $line=count(explode("\n",substr($input,0,$matchEnd+1))); + if($this->_tplFile===null) + throw new TTemplateParsingException('template_closingtag_expected',"Line $line",$tag); + else + throw new TTemplateParsingException('template_closingtag_expected',"{$this->_tplFile} (Line $line)",$tag); + } + $container=$tpl[$container][0]; + } + else if(strpos($str,'<%@')===0) { + if($expectPropEnd) + continue; + if($matchStart>$textStart) + $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart)); + $textStart=$matchEnd+1; + if(isset($tpl[0])) + { + $line=count(explode("\n",substr($input,0,$matchEnd+1))); + if($this->_tplFile===null) + throw new TTemplateParsingException('template_directive_nonunique',"Line $line"); + else + throw new TTemplateParsingException('template_directive_nonunique',"{$this->_tplFile} (Line $line)"); + } + $this->_directive=$this->parseAttributes($match[4][0]); + } + else if(strpos($str,'<%')===0) { + if($expectPropEnd) + continue; + if($matchStart>$textStart) + $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart)); + $textStart=$matchEnd+1; + if($str[2]==='=') $tpl[$c++]=array($container,'TExpression',array('Expression'=>$match[5][0])); + else if($str[2]==='%') $tpl[$c++]=array($container,'TStatements',array('Statements'=>$match[5][0])); + else + $tpl[$c++]=array($container,'TLiteral',array('Text'=>$this->parseAttribute($str))); + } + else if(strpos($str,'$textStart) + $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart)); + $textStart=$matchEnd+1; + $expectPropEnd=true; + } + } + else if(strpos($str,'_tplFile===null) + throw new TTemplateParsingException('template_closingtag_unexpected',"Line $line",""); + else + throw new TTemplateParsingException('template_closingtag_unexpected',"{$this->_tplFile} (Line $line)",""); + } + $name=array_pop($stack); + if($name!=='@'.$prop) + { + if($name[0]==='@') + $tag=''; + else + $tag=''; + $line=count(explode("\n",substr($input,0,$matchEnd+1))); + if($this->_tplFile===null) + throw new TTemplateParsingException('template_closingtag_expected',"Line $line",$tag); + else + throw new TTemplateParsingException('template_closingtag_expected',"{$this->_tplFile} (Line $line)",$tag); + } + if(($last=count($stack))<1 || $stack[$last-1][0]!=='@') + { + if($matchStart>$textStart && $container>=0) + { + $value=substr($input,$textStart,$matchStart-$textStart); + $tpl[$container][2][$prop]=$this->parseAttribute($value); + $textStart=$matchEnd+1; + } + $expectPropEnd=false; + } + } + else if(strpos($str,'