PageRenderTime 70ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/pradolite.php

https://bitbucket.org/freshflow/prado-fork-v3.10
PHP | 9635 lines | 9623 code | 1 blank | 11 comment | 266 complexity | 9963c86421231f6fd32c82a06ecb61a8 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * File Name: pradolite.php
  4. * Last Update: 2011/11/01 00:20:48
  5. * Generated By: buildscripts/phpbuilder/build.php
  6. *
  7. * This file is used in lieu of prado.php to boost PRADO application performance.
  8. * It is generated by expanding prado.php with included files.
  9. * Comments and trace statements are stripped off.
  10. *
  11. * Do not modify this file manually.
  12. */
  13. if(!defined('PRADO_DIR'))
  14. define('PRADO_DIR',dirname(__FILE__));
  15. if(!defined('PRADO_CHMOD'))
  16. define('PRADO_CHMOD',0777);
  17. class PradoBase
  18. {
  19. const CLASS_FILE_EXT='.php';
  20. private static $_aliases=array('System'=>PRADO_DIR);
  21. private static $_usings=array();
  22. private static $_application=null;
  23. private static $_logger=null;
  24. protected static $classExists = array();
  25. public static function getVersion()
  26. {
  27. return '3.1.10';
  28. }
  29. public static function initErrorHandlers()
  30. {
  31. set_error_handler(array('PradoBase','phpErrorHandler'),error_reporting());
  32. set_exception_handler(array('PradoBase','exceptionHandler'));
  33. }
  34. public static function autoload($className)
  35. {
  36. include_once($className.self::CLASS_FILE_EXT);
  37. if(!class_exists($className,false) && !interface_exists($className,false))
  38. self::fatalError("Class file for '$className' cannot be found.");
  39. }
  40. public static function poweredByPrado($logoType=0)
  41. {
  42. $logoName=$logoType==1?'powered2':'powered';
  43. if(self::$_application!==null)
  44. {
  45. $am=self::$_application->getAssetManager();
  46. $url=$am->publishFilePath(self::getPathOfNamespace('System.'.$logoName,'.gif'));
  47. }
  48. else
  49. $url='http://www.pradosoft.com/images/'.$logoName.'.gif';
  50. return '<a title="Powered by PRADO" href="http://www.pradosoft.com/" target="_blank"><img src="'.$url.'" style="border-width:0px;" alt="Powered by PRADO" /></a>';
  51. }
  52. public static function phpErrorHandler($errno,$errstr,$errfile,$errline)
  53. {
  54. if(error_reporting()!=0)
  55. throw new TPhpErrorException($errno,$errstr,$errfile,$errline);
  56. }
  57. public static function exceptionHandler($exception)
  58. {
  59. if(self::$_application!==null && ($errorHandler=self::$_application->getErrorHandler())!==null)
  60. {
  61. $errorHandler->handleError(null,$exception);
  62. }
  63. else
  64. {
  65. echo $exception;
  66. }
  67. exit(1);
  68. }
  69. public static function setApplication($application)
  70. {
  71. if(self::$_application!==null)
  72. throw new TInvalidOperationException('prado_application_singleton_required');
  73. self::$_application=$application;
  74. }
  75. public static function getApplication()
  76. {
  77. return self::$_application;
  78. }
  79. public static function getFrameworkPath()
  80. {
  81. return PRADO_DIR;
  82. }
  83. public static function serialize($data)
  84. {
  85. $arr[0]=$data;
  86. return serialize($arr);
  87. }
  88. public static function unserialize($str)
  89. {
  90. $arr=unserialize($str);
  91. return isset($arr[0])?$arr[0]:null;
  92. }
  93. public static function createComponent($type)
  94. {
  95. if(!isset(self::$classExists[$type]))
  96. self::$classExists[$type] = class_exists($type, false);
  97. if( !isset(self::$_usings[$type]) && !self::$classExists[$type]) {
  98. self::using($type);
  99. self::$classExists[$type] = class_exists($type, false);
  100. }
  101. if( ($pos = strrpos($type, '.')) !== false)
  102. $type = substr($type,$pos+1);
  103. if(($n=func_num_args())>1)
  104. {
  105. $args = func_get_args();
  106. switch($n) {
  107. case 2:
  108. return new $type($args[1]);
  109. break;
  110. case 3:
  111. return new $type($args[1], $args[2]);
  112. break;
  113. case 4:
  114. return new $type($args[1], $args[2], $args[3]);
  115. break;
  116. case 5:
  117. return new $type($args[1], $args[2], $args[3], $args[4]);
  118. break;
  119. default:
  120. $s='$args[1]';
  121. for($i=2;$i<$n;++$i)
  122. $s.=",\$args[$i]";
  123. eval("\$component=new $type($s);");
  124. return $component;
  125. break;
  126. }
  127. }
  128. else
  129. return new $type;
  130. }
  131. public static function using($namespace,$checkClassExistence=true)
  132. {
  133. if(isset(self::$_usings[$namespace]) || class_exists($namespace,false))
  134. return;
  135. if(($pos=strrpos($namespace,'.'))===false) {
  136. try
  137. {
  138. include_once($namespace.self::CLASS_FILE_EXT);
  139. }
  140. catch(Exception $e)
  141. {
  142. if($checkClassExistence && !class_exists($namespace,false))
  143. throw new TInvalidOperationException('prado_component_unknown',$namespace,$e->getMessage());
  144. else
  145. throw $e;
  146. }
  147. }
  148. else if(($path=self::getPathOfNamespace($namespace,self::CLASS_FILE_EXT))!==null)
  149. {
  150. $className=substr($namespace,$pos+1);
  151. if($className==='*') {
  152. self::$_usings[$namespace]=$path;
  153. set_include_path(get_include_path().PATH_SEPARATOR.$path);
  154. }
  155. else {
  156. self::$_usings[$namespace]=$path;
  157. if(!$checkClassExistence || !class_exists($className,false))
  158. {
  159. try
  160. {
  161. include_once($path);
  162. }
  163. catch(Exception $e)
  164. {
  165. if($checkClassExistence && !class_exists($className,false))
  166. throw new TInvalidOperationException('prado_component_unknown',$className,$e->getMessage());
  167. else
  168. throw $e;
  169. }
  170. }
  171. }
  172. }
  173. else
  174. throw new TInvalidDataValueException('prado_using_invalid',$namespace);
  175. }
  176. public static function getPathOfNamespace($namespace, $ext='')
  177. {
  178. if(self::CLASS_FILE_EXT === $ext || empty($ext))
  179. {
  180. if(isset(self::$_usings[$namespace]))
  181. return self::$_usings[$namespace];
  182. if(isset(self::$_aliases[$namespace]))
  183. return self::$_aliases[$namespace];
  184. }
  185. $segs = explode('.',$namespace);
  186. $alias = array_shift($segs);
  187. if(null !== ($file = array_pop($segs)) && null !== ($root = self::getPathOfAlias($alias)))
  188. return rtrim($root.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR ,$segs),'/\\').(($file === '*') ? '' : DIRECTORY_SEPARATOR.$file.$ext);
  189. return null;
  190. }
  191. public static function getPathOfAlias($alias)
  192. {
  193. return isset(self::$_aliases[$alias])?self::$_aliases[$alias]:null;
  194. }
  195. protected static function getPathAliases()
  196. {
  197. return self::$_aliases;
  198. }
  199. public static function setPathOfAlias($alias,$path)
  200. {
  201. if(isset(self::$_aliases[$alias]))
  202. throw new TInvalidOperationException('prado_alias_redefined',$alias);
  203. else if(($rp=realpath($path))!==false && is_dir($rp))
  204. {
  205. if(strpos($alias,'.')===false)
  206. self::$_aliases[$alias]=$rp;
  207. else
  208. throw new TInvalidDataValueException('prado_aliasname_invalid',$alias);
  209. }
  210. else
  211. throw new TInvalidDataValueException('prado_alias_invalid',$alias,$path);
  212. }
  213. public static function fatalError($msg)
  214. {
  215. echo '<h1>Fatal Error</h1>';
  216. echo '<p>'.$msg.'</p>';
  217. if(!function_exists('debug_backtrace'))
  218. return;
  219. echo '<h2>Debug Backtrace</h2>';
  220. echo '<pre>';
  221. $index=-1;
  222. foreach(debug_backtrace() as $t)
  223. {
  224. $index++;
  225. if($index==0) continue;
  226. echo '#'.$index.' ';
  227. if(isset($t['file']))
  228. echo basename($t['file']) . ':' . $t['line'];
  229. else
  230. echo '<PHP inner-code>';
  231. echo ' -- ';
  232. if(isset($t['class']))
  233. echo $t['class'] . $t['type'];
  234. echo $t['function'] . '(';
  235. if(isset($t['args']) && sizeof($t['args']) > 0)
  236. {
  237. $count=0;
  238. foreach($t['args'] as $item)
  239. {
  240. if(is_string($item))
  241. {
  242. $str=htmlentities(str_replace("\r\n", "", $item), ENT_QUOTES);
  243. if (strlen($item) > 70)
  244. echo "'". substr($str, 0, 70) . "...'";
  245. else
  246. echo "'" . $str . "'";
  247. }
  248. else if (is_int($item) || is_float($item))
  249. echo $item;
  250. else if (is_object($item))
  251. echo get_class($item);
  252. else if (is_array($item))
  253. echo 'array(' . count($item) . ')';
  254. else if (is_bool($item))
  255. echo $item ? 'true' : 'false';
  256. else if ($item === null)
  257. echo 'NULL';
  258. else if (is_resource($item))
  259. echo get_resource_type($item);
  260. $count++;
  261. if (count($t['args']) > $count)
  262. echo ', ';
  263. }
  264. }
  265. echo ")\n";
  266. }
  267. echo '</pre>';
  268. exit(1);
  269. }
  270. public static function getUserLanguages()
  271. {
  272. static $languages=null;
  273. if($languages===null)
  274. {
  275. if(!isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
  276. $languages[0]='en';
  277. else
  278. {
  279. $languages=array();
  280. foreach(explode(',',$_SERVER['HTTP_ACCEPT_LANGUAGE']) as $language)
  281. {
  282. $array=explode(';q=',trim($language));
  283. $languages[trim($array[0])]=isset($array[1])?(float)$array[1]:1.0;
  284. }
  285. arsort($languages);
  286. $languages=array_keys($languages);
  287. if(empty($languages))
  288. $languages[0]='en';
  289. }
  290. }
  291. return $languages;
  292. }
  293. public static function getPreferredLanguage()
  294. {
  295. static $language=null;
  296. if($language===null)
  297. {
  298. $langs=Prado::getUserLanguages();
  299. $lang=explode('-',$langs[0]);
  300. if(empty($lang[0]) || !ctype_alpha($lang[0]))
  301. $language='en';
  302. else
  303. $language=$lang[0];
  304. }
  305. return $language;
  306. }
  307. public static function trace($msg,$category='Uncategorized')
  308. {
  309. if(self::$_application && self::$_application->getMode()===TApplicationMode::Performance)
  310. return;
  311. if(!self::$_application || self::$_application->getMode()===TApplicationMode::Debug)
  312. {
  313. $trace=debug_backtrace();
  314. if(isset($trace[0]['file']) && isset($trace[0]['line']))
  315. $msg.=" (line {$trace[0]['line']}, {$trace[0]['file']})";
  316. $level=TLogger::DEBUG;
  317. }
  318. else
  319. $level=TLogger::INFO;
  320. self::log($msg,$level,$category);
  321. }
  322. public static function log($msg,$level=TLogger::INFO,$category='Uncategorized')
  323. {
  324. if(self::$_logger===null)
  325. self::$_logger=new TLogger;
  326. self::$_logger->log($msg,$level,$category);
  327. }
  328. public static function getLogger()
  329. {
  330. if(self::$_logger===null)
  331. self::$_logger=new TLogger;
  332. return self::$_logger;
  333. }
  334. public static function varDump($var,$depth=10,$highlight=false)
  335. {
  336. Prado::using('System.Util.TVarDumper');
  337. return TVarDumper::dump($var,$depth,$highlight);
  338. }
  339. public static function localize($text, $parameters=array(), $catalogue=null, $charset=null)
  340. {
  341. Prado::using('System.I18N.Translation');
  342. $app = Prado::getApplication()->getGlobalization(false);
  343. $params = array();
  344. foreach($parameters as $key => $value)
  345. $params['{'.$key.'}'] = $value;
  346. if($app===null || ($config = $app->getTranslationConfiguration())===null)
  347. return strtr($text, $params);
  348. if ($catalogue===null)
  349. $catalogue=isset($config['catalogue'])?$config['catalogue']:'messages';
  350. Translation::init($catalogue);
  351. $appCharset = $app===null ? '' : $app->getCharset();
  352. $defaultCharset = ($app===null) ? 'UTF-8' : $app->getDefaultCharset();
  353. if(empty($charset)) $charset = $appCharset;
  354. if(empty($charset)) $charset = $defaultCharset;
  355. return Translation::formatter($catalogue)->format($text,$params,$catalogue,$charset);
  356. }
  357. }
  358. class TReflectionClass extends ReflectionClass
  359. {
  360. }
  361. PradoBase::using('System.TComponent');
  362. PradoBase::using('System.Exceptions.TException');
  363. PradoBase::using('System.Util.TLogger');
  364. if(!class_exists('Prado',false))
  365. {
  366. class Prado extends PradoBase
  367. {
  368. }
  369. }
  370. spl_autoload_register(array('Prado','autoload'));
  371. Prado::initErrorHandlers();
  372. interface IModule
  373. {
  374. public function init($config);
  375. public function getID();
  376. public function setID($id);
  377. }
  378. interface IService
  379. {
  380. public function init($config);
  381. public function getID();
  382. public function setID($id);
  383. public function getEnabled();
  384. public function setEnabled($value);
  385. public function run();
  386. }
  387. interface ITextWriter
  388. {
  389. public function write($str);
  390. public function flush();
  391. }
  392. interface IUser
  393. {
  394. public function getName();
  395. public function setName($value);
  396. public function getIsGuest();
  397. public function setIsGuest($value);
  398. public function getRoles();
  399. public function setRoles($value);
  400. public function isInRole($role);
  401. public function saveToString();
  402. public function loadFromString($string);
  403. }
  404. interface IStatePersister
  405. {
  406. public function load();
  407. public function save($state);
  408. }
  409. interface ICache
  410. {
  411. public function get($id);
  412. public function set($id,$value,$expire=0,$dependency=null);
  413. public function add($id,$value,$expire=0,$dependency=null);
  414. public function delete($id);
  415. public function flush();
  416. }
  417. interface ICacheDependency
  418. {
  419. public function getHasChanged();
  420. }
  421. interface IRenderable
  422. {
  423. public function render($writer);
  424. }
  425. interface IBindable
  426. {
  427. public function dataBind();
  428. }
  429. interface IStyleable
  430. {
  431. public function getHasStyle();
  432. public function getStyle();
  433. public function clearStyle();
  434. }
  435. interface IActiveControl
  436. {
  437. public function getActiveControl();
  438. }
  439. interface ICallbackEventHandler
  440. {
  441. public function raiseCallbackEvent($eventArgument);
  442. }
  443. interface IDataRenderer
  444. {
  445. public function getData();
  446. public function setData($value);
  447. }
  448. class TApplicationComponent extends TComponent
  449. {
  450. public function getApplication()
  451. {
  452. return Prado::getApplication();
  453. }
  454. public function getService()
  455. {
  456. return Prado::getApplication()->getService();
  457. }
  458. public function getRequest()
  459. {
  460. return Prado::getApplication()->getRequest();
  461. }
  462. public function getResponse()
  463. {
  464. return Prado::getApplication()->getResponse();
  465. }
  466. public function getSession()
  467. {
  468. return Prado::getApplication()->getSession();
  469. }
  470. public function getUser()
  471. {
  472. return Prado::getApplication()->getUser();
  473. }
  474. public function publishAsset($assetPath,$className=null)
  475. {
  476. if($className===null)
  477. $className=get_class($this);
  478. $class=new ReflectionClass($className);
  479. $fullPath=dirname($class->getFileName()).DIRECTORY_SEPARATOR.$assetPath;
  480. return $this->publishFilePath($fullPath);
  481. }
  482. public function publishFilePath($fullPath)
  483. {
  484. return Prado::getApplication()->getAssetManager()->publishFilePath($fullPath);
  485. }
  486. }
  487. abstract class TModule extends TApplicationComponent implements IModule
  488. {
  489. private $_id;
  490. public function init($config)
  491. {
  492. }
  493. public function getID()
  494. {
  495. return $this->_id;
  496. }
  497. public function setID($value)
  498. {
  499. $this->_id=$value;
  500. }
  501. }
  502. abstract class TService extends TApplicationComponent implements IService
  503. {
  504. private $_id;
  505. private $_enabled=true;
  506. public function init($config)
  507. {
  508. }
  509. public function getID()
  510. {
  511. return $this->_id;
  512. }
  513. public function setID($value)
  514. {
  515. $this->_id=$value;
  516. }
  517. public function getEnabled()
  518. {
  519. return $this->_enabled;
  520. }
  521. public function setEnabled($value)
  522. {
  523. $this->_enabled=TPropertyValue::ensureBoolean($value);
  524. }
  525. public function run()
  526. {
  527. }
  528. }
  529. class TErrorHandler extends TModule
  530. {
  531. const ERROR_FILE_NAME='error';
  532. const EXCEPTION_FILE_NAME='exception';
  533. const SOURCE_LINES=12;
  534. private $_templatePath=null;
  535. public function init($config)
  536. {
  537. $this->getApplication()->setErrorHandler($this);
  538. }
  539. public function getErrorTemplatePath()
  540. {
  541. if($this->_templatePath===null)
  542. $this->_templatePath=Prado::getFrameworkPath().'/Exceptions/templates';
  543. return $this->_templatePath;
  544. }
  545. public function setErrorTemplatePath($value)
  546. {
  547. if(($templatePath=Prado::getPathOfNamespace($value))!==null && is_dir($templatePath))
  548. $this->_templatePath=$templatePath;
  549. else
  550. throw new TConfigurationException('errorhandler_errortemplatepath_invalid',$value);
  551. }
  552. public function handleError($sender,$param)
  553. {
  554. static $handling=false;
  555. restore_error_handler();
  556. restore_exception_handler();
  557. if($handling)
  558. $this->handleRecursiveError($param);
  559. else
  560. {
  561. $handling=true;
  562. if(($response=$this->getResponse())!==null)
  563. $response->clear();
  564. if(!headers_sent())
  565. header('Content-Type: text/html; charset=UTF-8');
  566. if($param instanceof THttpException)
  567. $this->handleExternalError($param->getStatusCode(),$param);
  568. else if($this->getApplication()->getMode()===TApplicationMode::Debug)
  569. $this->displayException($param);
  570. else
  571. $this->handleExternalError(500,$param);
  572. }
  573. }
  574. protected static function hideSecurityRelated($value, $exception=null)
  575. {
  576. $aRpl = array();
  577. if($exception !== null && $exception instanceof Exception)
  578. {
  579. $aTrace = $exception->getTrace();
  580. foreach($aTrace as $item)
  581. {
  582. $file = $item['file'];
  583. $aRpl[dirname($file) . DIRECTORY_SEPARATOR] = '<hidden>' . DIRECTORY_SEPARATOR;
  584. }
  585. }
  586. $aRpl[$_SERVER['DOCUMENT_ROOT']] = '${DocumentRoot}';
  587. $aRpl[str_replace('/', DIRECTORY_SEPARATOR, $_SERVER['DOCUMENT_ROOT'])] = '${DocumentRoot}';
  588. $aRpl[PRADO_DIR . DIRECTORY_SEPARATOR] = '${PradoFramework}' . DIRECTORY_SEPARATOR;
  589. if(isset($aRpl[DIRECTORY_SEPARATOR])) unset($aRpl[DIRECTORY_SEPARATOR]);
  590. $aRpl = array_reverse($aRpl, true);
  591. return str_replace(array_keys($aRpl), $aRpl, $value);
  592. }
  593. protected function handleExternalError($statusCode,$exception)
  594. {
  595. if(!($exception instanceof THttpException))
  596. error_log($exception->__toString());
  597. $content=$this->getErrorTemplate($statusCode,$exception);
  598. $serverAdmin=isset($_SERVER['SERVER_ADMIN'])?$_SERVER['SERVER_ADMIN']:'';
  599. $isDebug = $this->getApplication()->getMode()===TApplicationMode::Debug;
  600. $errorMessage = $exception->getMessage();
  601. if($isDebug)
  602. $version=$_SERVER['SERVER_SOFTWARE'].' <a href="http://www.pradosoft.com/">PRADO</a>/'.Prado::getVersion();
  603. else
  604. {
  605. $version='';
  606. $errorMessage = self::hideSecurityRelated($errorMessage, $exception);
  607. }
  608. $tokens=array(
  609. '%%StatusCode%%' => "$statusCode",
  610. '%%ErrorMessage%%' => htmlspecialchars($errorMessage),
  611. '%%ServerAdmin%%' => $serverAdmin,
  612. '%%Version%%' => $version,
  613. '%%Time%%' => @strftime('%Y-%m-%d %H:%M',time())
  614. );
  615. if($isDebug)
  616. header("HTTP/1.0 $statusCode ".$exception->getMessage(), true, TPropertyValue::ensureInteger($statusCode));
  617. else
  618. header("HTTP/1.0 $statusCode", true, TPropertyValue::ensureInteger($statusCode));
  619. echo strtr($content,$tokens);
  620. }
  621. protected function handleRecursiveError($exception)
  622. {
  623. if($this->getApplication()->getMode()===TApplicationMode::Debug)
  624. {
  625. echo "<html><head><title>Recursive Error</title></head>\n";
  626. echo "<body><h1>Recursive Error</h1>\n";
  627. echo "<pre>".$exception->__toString()."</pre>\n";
  628. echo "</body></html>";
  629. }
  630. else
  631. {
  632. error_log("Error happened while processing an existing error:\n".$exception->__toString());
  633. header('HTTP/1.0 500 Internal Error');
  634. }
  635. }
  636. protected function displayException($exception)
  637. {
  638. if(php_sapi_name()==='cli')
  639. {
  640. echo $exception->getMessage()."\n";
  641. echo $exception->getTraceAsString();
  642. return;
  643. }
  644. if($exception instanceof TTemplateException)
  645. {
  646. $fileName=$exception->getTemplateFile();
  647. $lines=empty($fileName)?explode("\n",$exception->getTemplateSource()):@file($fileName);
  648. $source=$this->getSourceCode($lines,$exception->getLineNumber());
  649. if($fileName==='')
  650. $fileName='---embedded template---';
  651. $errorLine=$exception->getLineNumber();
  652. }
  653. else
  654. {
  655. if(($trace=$this->getExactTrace($exception))!==null)
  656. {
  657. $fileName=$trace['file'];
  658. $errorLine=$trace['line'];
  659. }
  660. else
  661. {
  662. $fileName=$exception->getFile();
  663. $errorLine=$exception->getLine();
  664. }
  665. $source=$this->getSourceCode(@file($fileName),$errorLine);
  666. }
  667. if($this->getApplication()->getMode()===TApplicationMode::Debug)
  668. $version=$_SERVER['SERVER_SOFTWARE'].' <a href="http://www.pradosoft.com/">PRADO</a>/'.Prado::getVersion();
  669. else
  670. $version='';
  671. $tokens=array(
  672. '%%ErrorType%%' => get_class($exception),
  673. '%%ErrorMessage%%' => $this->addLink(htmlspecialchars($exception->getMessage())),
  674. '%%SourceFile%%' => htmlspecialchars($fileName).' ('.$errorLine.')',
  675. '%%SourceCode%%' => $source,
  676. '%%StackTrace%%' => htmlspecialchars($exception->getTraceAsString()),
  677. '%%Version%%' => $version,
  678. '%%Time%%' => @strftime('%Y-%m-%d %H:%M',time())
  679. );
  680. $content=$this->getExceptionTemplate($exception);
  681. echo strtr($content,$tokens);
  682. }
  683. protected function getExceptionTemplate($exception)
  684. {
  685. $lang=Prado::getPreferredLanguage();
  686. $exceptionFile=Prado::getFrameworkPath().'/Exceptions/templates/'.self::EXCEPTION_FILE_NAME.'-'.$lang.'.html';
  687. if(!is_file($exceptionFile))
  688. $exceptionFile=Prado::getFrameworkPath().'/Exceptions/templates/'.self::EXCEPTION_FILE_NAME.'.html';
  689. if(($content=@file_get_contents($exceptionFile))===false)
  690. die("Unable to open exception template file '$exceptionFile'.");
  691. return $content;
  692. }
  693. protected function getErrorTemplate($statusCode,$exception)
  694. {
  695. $base=$this->getErrorTemplatePath().DIRECTORY_SEPARATOR.self::ERROR_FILE_NAME;
  696. $lang=Prado::getPreferredLanguage();
  697. if(is_file("$base$statusCode-$lang.html"))
  698. $errorFile="$base$statusCode-$lang.html";
  699. else if(is_file("$base$statusCode.html"))
  700. $errorFile="$base$statusCode.html";
  701. else if(is_file("$base-$lang.html"))
  702. $errorFile="$base-$lang.html";
  703. else
  704. $errorFile="$base.html";
  705. if(($content=@file_get_contents($errorFile))===false)
  706. die("Unable to open error template file '$errorFile'.");
  707. return $content;
  708. }
  709. private function getExactTrace($exception)
  710. {
  711. $trace=$exception->getTrace();
  712. $result=null;
  713. if($exception instanceof TPhpErrorException)
  714. $result=isset($trace[0]['file'])?$trace[0]:$trace[1];
  715. else if($exception instanceof TInvalidOperationException)
  716. {
  717. if(($result=$this->getPropertyAccessTrace($trace,'__get'))===null)
  718. $result=$this->getPropertyAccessTrace($trace,'__set');
  719. }
  720. if($result!==null && strpos($result['file'],': eval()\'d code')!==false)
  721. return null;
  722. return $result;
  723. }
  724. private function getPropertyAccessTrace($trace,$pattern)
  725. {
  726. $result=null;
  727. foreach($trace as $t)
  728. {
  729. if(isset($t['function']) && $t['function']===$pattern)
  730. $result=$t;
  731. else
  732. break;
  733. }
  734. return $result;
  735. }
  736. private function getSourceCode($lines,$errorLine)
  737. {
  738. $beginLine=$errorLine-self::SOURCE_LINES>=0?$errorLine-self::SOURCE_LINES:0;
  739. $endLine=$errorLine+self::SOURCE_LINES<=count($lines)?$errorLine+self::SOURCE_LINES:count($lines);
  740. $source='';
  741. for($i=$beginLine;$i<$endLine;++$i)
  742. {
  743. if($i===$errorLine-1)
  744. {
  745. $line=htmlspecialchars(sprintf("%04d: %s",$i+1,str_replace("\t",' ',$lines[$i])));
  746. $source.="<div class=\"error\">".$line."</div>";
  747. }
  748. else
  749. $source.=htmlspecialchars(sprintf("%04d: %s",$i+1,str_replace("\t",' ',$lines[$i])));
  750. }
  751. return $source;
  752. }
  753. private function addLink($message)
  754. {
  755. $baseUrl='http://www.pradosoft.com/docs/classdoc';
  756. return preg_replace('/\b(T[A-Z]\w+)\b/',"<a href=\"$baseUrl/\${1}\" target=\"_blank\">\${1}</a>",$message);
  757. }
  758. }
  759. class TList extends TComponent implements IteratorAggregate,ArrayAccess,Countable
  760. {
  761. private $_d=array();
  762. private $_c=0;
  763. private $_r=false;
  764. public function __construct($data=null,$readOnly=false)
  765. {
  766. if($data!==null)
  767. $this->copyFrom($data);
  768. $this->setReadOnly($readOnly);
  769. }
  770. public function getReadOnly()
  771. {
  772. return $this->_r;
  773. }
  774. protected function setReadOnly($value)
  775. {
  776. $this->_r=TPropertyValue::ensureBoolean($value);
  777. }
  778. public function getIterator()
  779. {
  780. return new ArrayIterator( $this->_d );
  781. }
  782. public function count()
  783. {
  784. return $this->getCount();
  785. }
  786. public function getCount()
  787. {
  788. return $this->_c;
  789. }
  790. public function itemAt($index)
  791. {
  792. if($index>=0 && $index<$this->_c)
  793. return $this->_d[$index];
  794. else
  795. throw new TInvalidDataValueException('list_index_invalid',$index);
  796. }
  797. public function add($item)
  798. {
  799. $this->insertAt($this->_c,$item);
  800. return $this->_c-1;
  801. }
  802. public function insertAt($index,$item)
  803. {
  804. if(!$this->_r)
  805. {
  806. if($index===$this->_c)
  807. $this->_d[$this->_c++]=$item;
  808. else if($index>=0 && $index<$this->_c)
  809. {
  810. array_splice($this->_d,$index,0,array($item));
  811. $this->_c++;
  812. }
  813. else
  814. throw new TInvalidDataValueException('list_index_invalid',$index);
  815. }
  816. else
  817. throw new TInvalidOperationException('list_readonly',get_class($this));
  818. }
  819. public function remove($item)
  820. {
  821. if(($index=$this->indexOf($item))>=0)
  822. {
  823. $this->removeAt($index);
  824. return $index;
  825. }
  826. else
  827. throw new TInvalidDataValueException('list_item_inexistent');
  828. }
  829. public function removeAt($index)
  830. {
  831. if(!$this->_r)
  832. {
  833. if($index>=0 && $index<$this->_c)
  834. {
  835. $this->_c--;
  836. if($index===$this->_c)
  837. return array_pop($this->_d);
  838. else
  839. {
  840. $item=$this->_d[$index];
  841. array_splice($this->_d,$index,1);
  842. return $item;
  843. }
  844. }
  845. else
  846. throw new TInvalidDataValueException('list_index_invalid',$index);
  847. }
  848. else
  849. throw new TInvalidOperationException('list_readonly',get_class($this));
  850. }
  851. public function clear()
  852. {
  853. for($i=$this->_c-1;$i>=0;--$i)
  854. $this->removeAt($i);
  855. }
  856. public function contains($item)
  857. {
  858. return $this->indexOf($item)>=0;
  859. }
  860. public function indexOf($item)
  861. {
  862. if(($index=array_search($item,$this->_d,true))===false)
  863. return -1;
  864. else
  865. return $index;
  866. }
  867. public function toArray()
  868. {
  869. return $this->_d;
  870. }
  871. public function copyFrom($data)
  872. {
  873. if(is_array($data) || ($data instanceof Traversable))
  874. {
  875. if($this->_c>0)
  876. $this->clear();
  877. foreach($data as $item)
  878. $this->add($item);
  879. }
  880. else if($data!==null)
  881. throw new TInvalidDataTypeException('list_data_not_iterable');
  882. }
  883. public function mergeWith($data)
  884. {
  885. if(is_array($data) || ($data instanceof Traversable))
  886. {
  887. foreach($data as $item)
  888. $this->add($item);
  889. }
  890. else if($data!==null)
  891. throw new TInvalidDataTypeException('list_data_not_iterable');
  892. }
  893. public function offsetExists($offset)
  894. {
  895. return ($offset>=0 && $offset<$this->_c);
  896. }
  897. public function offsetGet($offset)
  898. {
  899. return $this->itemAt($offset);
  900. }
  901. public function offsetSet($offset,$item)
  902. {
  903. if($offset===null || $offset===$this->_c)
  904. $this->insertAt($this->_c,$item);
  905. else
  906. {
  907. $this->removeAt($offset);
  908. $this->insertAt($offset,$item);
  909. }
  910. }
  911. public function offsetUnset($offset)
  912. {
  913. $this->removeAt($offset);
  914. }
  915. }
  916. class TListIterator implements Iterator
  917. {
  918. private $_d;
  919. private $_i;
  920. private $_c;
  921. public function __construct(&$data)
  922. {
  923. $this->_d=&$data;
  924. $this->_i=0;
  925. $this->_c=count($this->_d);
  926. }
  927. public function rewind()
  928. {
  929. $this->_i=0;
  930. }
  931. public function key()
  932. {
  933. return $this->_i;
  934. }
  935. public function current()
  936. {
  937. return $this->_d[$this->_i];
  938. }
  939. public function next()
  940. {
  941. $this->_i++;
  942. }
  943. public function valid()
  944. {
  945. return $this->_i<$this->_c;
  946. }
  947. }
  948. abstract class TCache extends TModule implements ICache, ArrayAccess
  949. {
  950. private $_prefix=null;
  951. private $_primary=true;
  952. public function init($config)
  953. {
  954. if($this->_prefix===null)
  955. $this->_prefix=$this->getApplication()->getUniqueID();
  956. if($this->_primary)
  957. {
  958. if($this->getApplication()->getCache()===null)
  959. $this->getApplication()->setCache($this);
  960. else
  961. throw new TConfigurationException('cache_primary_duplicated',get_class($this));
  962. }
  963. }
  964. public function getPrimaryCache()
  965. {
  966. return $this->_primary;
  967. }
  968. public function setPrimaryCache($value)
  969. {
  970. $this->_primary=TPropertyValue::ensureBoolean($value);
  971. }
  972. public function getKeyPrefix()
  973. {
  974. return $this->_prefix;
  975. }
  976. public function setKeyPrefix($value)
  977. {
  978. $this->_prefix=$value;
  979. }
  980. protected function generateUniqueKey($key)
  981. {
  982. return md5($this->_prefix.$key);
  983. }
  984. public function get($id)
  985. {
  986. if(($value=$this->getValue($this->generateUniqueKey($id)))!==false)
  987. {
  988. $data=unserialize($value);
  989. if(!is_array($data))
  990. return false;
  991. if(!($data[1] instanceof ICacheDependency) || !$data[1]->getHasChanged())
  992. return $data[0];
  993. }
  994. return false;
  995. }
  996. public function set($id,$value,$expire=0,$dependency=null)
  997. {
  998. if(empty($value) && $expire === 0)
  999. $this->delete($id);
  1000. else
  1001. {
  1002. $data=array($value,$dependency);
  1003. return $this->setValue($this->generateUniqueKey($id),serialize($data),$expire);
  1004. }
  1005. }
  1006. public function add($id,$value,$expire=0,$dependency=null)
  1007. {
  1008. if(empty($value) && $expire === 0)
  1009. return false;
  1010. $data=array($value,$dependency);
  1011. return $this->addValue($this->generateUniqueKey($id),serialize($data),$expire);
  1012. }
  1013. public function delete($id)
  1014. {
  1015. return $this->deleteValue($this->generateUniqueKey($id));
  1016. }
  1017. public function flush()
  1018. {
  1019. throw new TNotSupportedException('cache_flush_unsupported');
  1020. }
  1021. abstract protected function getValue($key);
  1022. abstract protected function setValue($key,$value,$expire);
  1023. abstract protected function addValue($key,$value,$expire);
  1024. abstract protected function deleteValue($key);
  1025. public function offsetExists($id)
  1026. {
  1027. return $this->get($id) !== false;
  1028. }
  1029. public function offsetGet($id)
  1030. {
  1031. return $this->get($id);
  1032. }
  1033. public function offsetSet($id, $value)
  1034. {
  1035. $this->set($id, $value);
  1036. }
  1037. public function offsetUnset($id)
  1038. {
  1039. $this->delete($id);
  1040. }
  1041. }
  1042. abstract class TCacheDependency extends TComponent implements ICacheDependency
  1043. {
  1044. }
  1045. class TFileCacheDependency extends TCacheDependency
  1046. {
  1047. private $_fileName;
  1048. private $_timestamp;
  1049. public function __construct($fileName)
  1050. {
  1051. $this->setFileName($fileName);
  1052. }
  1053. public function getFileName()
  1054. {
  1055. return $this->_fileName;
  1056. }
  1057. public function setFileName($value)
  1058. {
  1059. $this->_fileName=$value;
  1060. $this->_timestamp=@filemtime($value);
  1061. }
  1062. public function getTimestamp()
  1063. {
  1064. return $this->_timestamp;
  1065. }
  1066. public function getHasChanged()
  1067. {
  1068. return @filemtime($this->_fileName)!==$this->_timestamp;
  1069. }
  1070. }
  1071. class TDirectoryCacheDependency extends TCacheDependency
  1072. {
  1073. private $_recursiveCheck=true;
  1074. private $_recursiveLevel=-1;
  1075. private $_timestamps;
  1076. private $_directory;
  1077. public function __construct($directory)
  1078. {
  1079. $this->setDirectory($directory);
  1080. }
  1081. public function getDirectory()
  1082. {
  1083. return $this->_directory;
  1084. }
  1085. public function setDirectory($directory)
  1086. {
  1087. if(($path=realpath($directory))===false || !is_dir($path))
  1088. throw new TInvalidDataValueException('directorycachedependency_directory_invalid',$directory);
  1089. $this->_directory=$path;
  1090. $this->_timestamps=$this->generateTimestamps($path);
  1091. }
  1092. public function getRecursiveCheck()
  1093. {
  1094. return $this->_recursiveCheck;
  1095. }
  1096. public function setRecursiveCheck($value)
  1097. {
  1098. $this->_recursiveCheck=TPropertyValue::ensureBoolean($value);
  1099. }
  1100. public function getRecursiveLevel()
  1101. {
  1102. return $this->_recursiveLevel;
  1103. }
  1104. public function setRecursiveLevel($value)
  1105. {
  1106. $this->_recursiveLevel=TPropertyValue::ensureInteger($value);
  1107. }
  1108. public function getHasChanged()
  1109. {
  1110. return $this->generateTimestamps($this->_directory)!=$this->_timestamps;
  1111. }
  1112. protected function validateFile($fileName)
  1113. {
  1114. return true;
  1115. }
  1116. protected function validateDirectory($directory)
  1117. {
  1118. return true;
  1119. }
  1120. protected function generateTimestamps($directory,$level=0)
  1121. {
  1122. if(($dir=opendir($directory))===false)
  1123. throw new TIOException('directorycachedependency_directory_invalid',$directory);
  1124. $timestamps=array();
  1125. while(($file=readdir($dir))!==false)
  1126. {
  1127. $path=$directory.DIRECTORY_SEPARATOR.$file;
  1128. if($file==='.' || $file==='..')
  1129. continue;
  1130. else if(is_dir($path))
  1131. {
  1132. if(($this->_recursiveLevel<0 || $level<$this->_recursiveLevel) && $this->validateDirectory($path))
  1133. $timestamps=array_merge($this->generateTimestamps($path,$level+1));
  1134. }
  1135. else if($this->validateFile($path))
  1136. $timestamps[$path]=filemtime($path);
  1137. }
  1138. closedir($dir);
  1139. return $timestamps;
  1140. }
  1141. }
  1142. class TGlobalStateCacheDependency extends TCacheDependency
  1143. {
  1144. private $_stateName;
  1145. private $_stateValue;
  1146. public function __construct($name)
  1147. {
  1148. $this->setStateName($name);
  1149. }
  1150. public function getStateName()
  1151. {
  1152. return $this->_stateName;
  1153. }
  1154. public function setStateName($value)
  1155. {
  1156. $this->_stateName=$value;
  1157. $this->_stateValue=Prado::getApplication()->getGlobalState($value);
  1158. }
  1159. public function getHasChanged()
  1160. {
  1161. return $this->_stateValue!==Prado::getApplication()->getGlobalState($this->_stateName);
  1162. }
  1163. }
  1164. class TChainedCacheDependency extends TCacheDependency
  1165. {
  1166. private $_dependencies=null;
  1167. public function getDependencies()
  1168. {
  1169. if($this->_dependencies===null)
  1170. $this->_dependencies=new TCacheDependencyList;
  1171. return $this->_dependencies;
  1172. }
  1173. public function getHasChanged()
  1174. {
  1175. if($this->_dependencies!==null)
  1176. {
  1177. foreach($this->_dependencies as $dependency)
  1178. if($dependency->getHasChanged())
  1179. return true;
  1180. }
  1181. return false;
  1182. }
  1183. }
  1184. class TApplicationStateCacheDependency extends TCacheDependency
  1185. {
  1186. public function getHasChanged()
  1187. {
  1188. return Prado::getApplication()->getMode()!==TApplicationMode::Performance;
  1189. }
  1190. }
  1191. class TCacheDependencyList extends TList
  1192. {
  1193. public function insertAt($index,$item)
  1194. {
  1195. if($item instanceof ICacheDependency)
  1196. parent::insertAt($index,$item);
  1197. else
  1198. throw new TInvalidDataTypeException('cachedependencylist_cachedependency_required');
  1199. }
  1200. }
  1201. class TTextWriter extends TComponent implements ITextWriter
  1202. {
  1203. private $_str='';
  1204. public function flush()
  1205. {
  1206. $str=$this->_str;
  1207. $this->_str='';
  1208. return $str;
  1209. }
  1210. public function write($str)
  1211. {
  1212. $this->_str.=$str;
  1213. }
  1214. public function writeLine($str='')
  1215. {
  1216. $this->write($str."\n");
  1217. }
  1218. }
  1219. class TMap extends TComponent implements IteratorAggregate,ArrayAccess,Countable
  1220. {
  1221. private $_d=array();
  1222. private $_r=false;
  1223. public function __construct($data=null,$readOnly=false)
  1224. {
  1225. if($data!==null)
  1226. $this->copyFrom($data);
  1227. $this->setReadOnly($readOnly);
  1228. }
  1229. public function getReadOnly()
  1230. {
  1231. return $this->_r;
  1232. }
  1233. protected function setReadOnly($value)
  1234. {
  1235. $this->_r=TPropertyValue::ensureBoolean($value);
  1236. }
  1237. public function getIterator()
  1238. {
  1239. return new ArrayIterator( $this->_d );
  1240. }
  1241. public function count()
  1242. {
  1243. return $this->getCount();
  1244. }
  1245. public function getCount()
  1246. {
  1247. return count($this->_d);
  1248. }
  1249. public function getKeys()
  1250. {
  1251. return array_keys($this->_d);
  1252. }
  1253. public function itemAt($key)
  1254. {
  1255. return isset($this->_d[$key]) ? $this->_d[$key] : null;
  1256. }
  1257. public function add($key,$value)
  1258. {
  1259. if(!$this->_r)
  1260. $this->_d[$key]=$value;
  1261. else
  1262. throw new TInvalidOperationException('map_readonly',get_class($this));
  1263. }
  1264. public function remove($key)
  1265. {
  1266. if(!$this->_r)
  1267. {
  1268. if(isset($this->_d[$key]) || array_key_exists($key,$this->_d))
  1269. {
  1270. $value=$this->_d[$key];
  1271. unset($this->_d[$key]);
  1272. return $value;
  1273. }
  1274. else
  1275. return null;
  1276. }
  1277. else
  1278. throw new TInvalidOperationException('map_readonly',get_class($this));
  1279. }
  1280. public function clear()
  1281. {
  1282. foreach(array_keys($this->_d) as $key)
  1283. $this->remove($key);
  1284. }
  1285. public function contains($key)
  1286. {
  1287. return isset($this->_d[$key]) || array_key_exists($key,$this->_d);
  1288. }
  1289. public function toArray()
  1290. {
  1291. return $this->_d;
  1292. }
  1293. public function copyFrom($data)
  1294. {
  1295. if(is_array($data) || $data instanceof Traversable)
  1296. {
  1297. if($this->getCount()>0)
  1298. $this->clear();
  1299. foreach($data as $key=>$value)
  1300. $this->add($key,$value);
  1301. }
  1302. else if($data!==null)
  1303. throw new TInvalidDataTypeException('map_data_not_iterable');
  1304. }
  1305. public function mergeWith($data)
  1306. {
  1307. if(is_array($data) || $data instanceof Traversable)
  1308. {
  1309. foreach($data as $key=>$value)
  1310. $this->add($key,$value);
  1311. }
  1312. else if($data!==null)
  1313. throw new TInvalidDataTypeException('map_data_not_iterable');
  1314. }
  1315. public function offsetExists($offset)
  1316. {
  1317. return $this->contains($offset);
  1318. }
  1319. public function offsetGet($offset)
  1320. {
  1321. return $this->itemAt($offset);
  1322. }
  1323. public function offsetSet($offset,$item)
  1324. {
  1325. $this->add($offset,$item);
  1326. }
  1327. public function offsetUnset($offset)
  1328. {
  1329. $this->remove($offset);
  1330. }
  1331. }
  1332. class TMapIterator implements Iterator
  1333. {
  1334. private $_d;
  1335. private $_keys;
  1336. private $_key;
  1337. public function __construct(&$data)
  1338. {
  1339. $this->_d=&$data;
  1340. $this->_keys=array_keys($data);
  1341. }
  1342. public function rewind()
  1343. {
  1344. $this->_key=reset($this->_keys);
  1345. }
  1346. public function key()
  1347. {
  1348. return $this->_key;
  1349. }
  1350. public function current()
  1351. {
  1352. return $this->_d[$this->_key];
  1353. }
  1354. public function next()
  1355. {
  1356. $this->_key=next($this->_keys);
  1357. }
  1358. public function valid()
  1359. {
  1360. return $this->_key!==false;
  1361. }
  1362. }
  1363. class TStack extends TComponent implements IteratorAggregate,Countable
  1364. {
  1365. private $_d=array();
  1366. private $_c=0;
  1367. public function __construct($data=null)
  1368. {
  1369. if($data!==null)
  1370. $this->copyFrom($data);
  1371. }
  1372. public function toArray()
  1373. {
  1374. return $this->_d;
  1375. }
  1376. public function copyFrom($data)
  1377. {
  1378. if(is_array($data) || ($data instanceof Traversable))
  1379. {
  1380. $this->clear();
  1381. foreach($data as $item)
  1382. {
  1383. $this->_d[]=$item;
  1384. ++$this->_c;
  1385. }
  1386. }
  1387. else if($data!==null)
  1388. throw new TInvalidDataTypeException('stack_data_not_iterable');
  1389. }
  1390. public function clear()
  1391. {
  1392. $this->_c=0;
  1393. $this->_d=array();
  1394. }
  1395. public function contains($item)
  1396. {
  1397. return array_search($item,$this->_d,true)!==false;
  1398. }
  1399. public function peek()
  1400. {
  1401. if($this->_c===0)
  1402. throw new TInvalidOperationException('stack_empty');
  1403. else
  1404. return $this->_d[$this->_c-1];
  1405. }
  1406. public function pop()
  1407. {
  1408. if($this->_c===0)
  1409. throw new TInvalidOperationException('stack_empty');
  1410. else
  1411. {
  1412. --$this->_c;
  1413. return array_pop($this->_d);
  1414. }
  1415. }
  1416. public function push($item)
  1417. {
  1418. ++$this->_c;
  1419. $this->_d[] = $item;
  1420. }
  1421. public function getIterator()
  1422. {
  1423. return new ArrayIterator( $this->_d );
  1424. }
  1425. public function getCount()
  1426. {
  1427. return $this->_c;
  1428. }
  1429. public function count()
  1430. {
  1431. return $this->getCount();
  1432. }
  1433. }
  1434. class TStackIterator implements Iterator
  1435. {
  1436. private $_d;
  1437. private $_i;
  1438. private $_c;
  1439. public function __construct(&$data)
  1440. {
  1441. $this->_d=&$data;
  1442. $this->_i=0;
  1443. $this->_c=count($this->_d);
  1444. }
  1445. public function rewind()
  1446. {
  1447. $this->_i=0;
  1448. }
  1449. public function key()
  1450. {
  1451. return $this->_i;
  1452. }
  1453. public function current()
  1454. {
  1455. return $this->_d[$this->_i];
  1456. }
  1457. public function next()
  1458. {
  1459. $this->_i++;
  1460. }
  1461. public function valid()
  1462. {
  1463. return $this->_i<$this->_c;
  1464. }
  1465. }
  1466. class TXmlElement extends TComponent
  1467. {
  1468. private $_parent=null;
  1469. private $_tagName='unknown';
  1470. private $_value='';
  1471. private $_elements=null;
  1472. private $_attributes=null;
  1473. public function __construct($tagName)
  1474. {
  1475. $this->setTagName($tagName);
  1476. }
  1477. public function getParent()
  1478. {
  1479. return $this->_parent;
  1480. }
  1481. public function setParent($parent)
  1482. {
  1483. $this->_parent=$parent;
  1484. }
  1485. public function getTagName()
  1486. {
  1487. return $this->_tagName;
  1488. }
  1489. public function setTagName($tagName)
  1490. {
  1491. $this->_tagName=$tagName;
  1492. }
  1493. public function getValue()
  1494. {
  1495. return $this->_value;
  1496. }
  1497. public function setValue($value)
  1498. {
  1499. $this->_value=TPropertyValue::ensureString($value);
  1500. }
  1501. public function getHasElement()
  1502. {
  1503. return $this->_elements!==null && $this->_elements->getCount()>0;
  1504. }
  1505. public function getHasAttribute()
  1506. {
  1507. return $this->_attributes!==null && $this->_attributes->getCount()>0;
  1508. }
  1509. public function getAttribute($name)
  1510. {
  1511. if($this->_attributes!==null)
  1512. return $this->_attributes->itemAt($name);
  1513. else
  1514. return null;
  1515. }
  1516. public function setAttribute($name,$value)
  1517. {
  1518. $this->getAttributes()->add($name,TPropertyValue::ensureString($value));
  1519. }
  1520. public function getElements()
  1521. {
  1522. if(!$this->_elements)
  1523. $this->_elements=new TXmlElementList($this);
  1524. return $this->_elements;
  1525. }
  1526. public function getAttributes()
  1527. {
  1528. if(!$this->_attributes)
  1529. $this->_attributes=new TMap;
  1530. return $this->_attributes;
  1531. }
  1532. public function getElementByTagName($tagName)
  1533. {
  1534. if($this->_elements)
  1535. {
  1536. foreach($this->_elements as $element)
  1537. if($element->_tagName===$tagName)
  1538. return $element;
  1539. }
  1540. return null;
  1541. }
  1542. public function getElementsByTagName($tagName)
  1543. {
  1544. $list=new TList;
  1545. if($this->_elements)
  1546. {
  1547. foreach($this->_elements as $element)
  1548. if($element->_tagName===$tagName)
  1549. $list->add($element);
  1550. }
  1551. return $list;
  1552. }
  1553. public function toString($indent=0)
  1554. {
  1555. $attr='';
  1556. if($this->_attributes!==null)
  1557. {
  1558. foreach($this->_attributes as $name=>$value)
  1559. {
  1560. $value=$this->xmlEncode($value);
  1561. $attr.=" $name=\"$value\"";
  1562. }
  1563. }
  1564. $prefix=str_repeat(' ',$indent*4);
  1565. if($this->getHasElement())
  1566. {
  1567. $str=$prefix."<{$this->_tagName}$attr>\n";
  1568. foreach($this->getElements() as $element)
  1569. $str.=$element->toString($indent+1)."\n";
  1570. $str.=$prefix."</{$this->_tagName}>";
  1571. return $str;
  1572. }
  1573. else if(($value=$this->getValue())!=='')
  1574. {
  1575. $value=$this->xmlEncode($value);
  1576. return $prefix."<{$this->_tagName}$attr>$value</{$this->_tagName}>";
  1577. }
  1578. else
  1579. return $prefix."<{$this->_tagName}$attr />";
  1580. }
  1581. public function __toString()
  1582. {
  1583. return $this->toString();
  1584. }
  1585. private function xmlEncode($str)
  1586. {
  1587. return strtr($str,array(
  1588. '>'=>'&gt;',
  1589. '<'=>'&lt;',
  1590. '&'=>'&amp;',
  1591. '"'=>'&quot;',
  1592. "\r"=>'&#xD;',
  1593. "\t"=>'&#x9;',
  1594. "\n"=>'&#xA;'));
  1595. }
  1596. }
  1597. class TXmlDocument extends TXmlElement
  1598. {
  1599. private $_version;
  1600. private $_encoding;
  1601. public function __construct($version='1.0',$encoding='')
  1602. {
  1603. parent::__construct('');
  1604. $this->setVersion($version);
  1605. $this->setEncoding($encoding);
  1606. }
  1607. public function getVersion()
  1608. {
  1609. return $this->_version;
  1610. }
  1611. public function setVersion($version)
  1612. {
  1613. $this->_version=$version;
  1614. }
  1615. public function getEncoding()
  1616. {
  1617. return $this->_encoding;
  1618. }
  1619. public function setEncoding($encoding)
  1620. {
  1621. $this->_encoding=$encoding;
  1622. }
  1623. public function loadFromFile($file)
  1624. {
  1625. if(($str=@file_get_contents($file))!==false)
  1626. return $this->loadFromString($str);
  1627. else
  1628. throw new TIOException('xmldocument_file_read_failed',$file);
  1629. }
  1630. public function loadFromString($string)
  1631. {
  1632. $doc=new DOMDocument();
  1633. if($doc->loadXML($string)===false)
  1634. return false;
  1635. $this->setEncoding($doc->encoding);
  1636. $this->setVersion($doc->version);
  1637. $element=$doc->documentElement;
  1638. $this->setTagName($element->tagName);
  1639. $this->setValue($element->nodeValue);
  1640. $elements=$this->getElements();
  1641. $attributes=$this->getAttributes();
  1642. $elements->clear();
  1643. $attributes->clear();
  1644. static $bSimpleXml;
  1645. if($bSimpleXml === null)
  1646. $bSimpleXml = (boolean)function_exists('simplexml_load_string');
  1647. if($bSimpleXml)
  1648. {
  1649. $simpleDoc = simplexml_load_string($string);
  1650. $docNamespaces = $simpleDoc->getDocNamespaces(false);
  1651. $simpleDoc = null;
  1652. foreach($docNamespaces as $prefix => $uri)
  1653. {
  1654. if($prefix === '')
  1655. $attributes->add('xmlns', $uri);
  1656. else
  1657. $attributes->add('xmlns:'.$prefix, $uri);
  1658. }
  1659. }
  1660. foreach($element->attributes as $name=>$attr)
  1661. $attributes->add(($attr->prefix === '' ? '' : $attr->prefix . ':') .$name,$attr->value);
  1662. foreach($element->childNodes as $child)
  1663. {
  1664. if($child instanceof DOMElement)
  1665. $elements->add($this->buildElement($child));
  1666. }
  1667. return true;
  1668. }
  1669. public function saveToFile($file)
  1670. {
  1671. if(($fw=fopen($file,'w'))!==false)
  1672. {
  1673. fwrite($fw,$this->saveToString());
  1674. fclose($fw);
  1675. }
  1676. else
  1677. throw new TIOException('xmldocument_file_write_failed',$file);
  1678. }
  1679. public function saveToString()
  1680. {
  1681. $version=empty($this->_version)?' version="1.0"':' version="'.$this->_version.'"';
  1682. $encoding=empty($this->_encoding)?'':' encoding="'.$this->_encoding.'"';
  1683. return "<?xml{$version}{$encoding}?>\n".$this->toString(0);
  1684. }
  1685. public function __toString()
  1686. {
  1687. return $this->saveToString();
  1688. }
  1689. private function buildElement($node)
  1690. {
  1691. $element=new TXmlElement($node->tagName);
  1692. $element->setValue($node->nodeValue);
  1693. foreach($node->attributes as $name=>$attr)
  1694. $element->getAttributes()->add(($attr->prefix === '' ? '' : $attr->prefix . ':') . $name,$attr->value);
  1695. foreach($node->childNodes as $child)
  1696. {
  1697. if($child instanceof DOMElement)
  1698. $element->getElements()->add($this->buildElement($child));
  1699. }
  1700. return $element;
  1701. }
  1702. }
  1703. class TXmlElementList extends TList
  1704. {
  1705. private $_o;
  1706. public function __construct(TXmlElement $owner)
  1707. {
  1708. $this->_o=$owner;
  1709. }
  1710. protected function getOwner()
  1711. {
  1712. return $this->_o;
  1713. }
  1714. public function insertAt($index,$item)
  1715. {
  1716. if($item instanceof TXmlElement)
  1717. {
  1718. parent::insertAt($index,$item);
  1719. if($item->getParent()!==null)
  1720. $item->getParent()->getElements()->remove($item);
  1721. $item->setParent($this->_o);
  1722. }
  1723. else
  1724. throw new TInvalidDataTypeException('xmlelementlist_xmlelement_required');
  1725. }
  1726. public function removeAt($index)
  1727. {
  1728. $item=parent::removeAt($index);
  1729. if($item instanceof TXmlElement)
  1730. $item->setParent(null);
  1731. return $item;
  1732. }
  1733. }
  1734. class TAuthorizationRule extends TComponent
  1735. {
  1736. private $_action;
  1737. private $_users;
  1738. private $_roles;
  1739. private $_verb;
  1740. private $_ipRules;
  1741. private $_everyone;
  1742. private $_guest;
  1743. private $_authenticated;
  1744. public function __construct($action,$users,$roles,$verb='',$ipRules='')
  1745. {
  1746. $action=strtolower(trim($action));
  1747. if($action==='allow' || $action==='deny')
  1748. $this->_action=$action;
  1749. else
  1750. throw new TInvalidDataValueException('authorizationrule_action_invalid',$action);
  1751. $this->_users=array();
  1752. $this->_roles=array();
  1753. $this->_ipRules=array();
  1754. $this->_everyone=false;
  1755. $this->_guest=false;
  1756. $this->_authenticated=false;
  1757. if(trim($users)==='')
  1758. $users='*';
  1759. foreach(explode(',',$users) as $user)
  1760. {
  1761. if(($user=trim(strtolower($user)))!=='')
  1762. {
  1763. if($user==='*')
  1764. {
  1765. $this->_everyone=true;
  1766. break;
  1767. }
  1768. else if($user==='?')
  1769. $this->_guest=true;
  1770. else if($user==='@')
  1771. $this->_authenticated=true;
  1772. else
  1773. $this->_users[]=$user;
  1774. }
  1775. }
  1776. if(trim($roles)==='')
  1777. $roles='*';
  1778. foreach(explode(',',$roles) as $role)
  1779. {
  1780. if(($role=trim(strtolower($role)))!=='')
  1781. $this->_roles[]=$role;
  1782. }
  1783. if(($verb=trim(strtolower($verb)))==='')
  1784. $verb='*';
  1785. if($verb==='*' || $verb==='get' || $verb==='post')
  1786. $this->_verb=$verb;
  1787. else
  1788. throw new TInvalidDataValueException('authorizationrule_verb_invalid',$verb);
  1789. if(trim($ipRules)==='')
  1790. $ipRules='*';
  1791. foreach(explode(',',$ipRules) as $ipRule)
  1792. {
  1793. if(($ipRule=trim($ipRule))!=='')
  1794. $this->_ipRules[]=$ipRule;
  1795. }
  1796. }
  1797. public function getAction()
  1798. {
  1799. return $this->_action;
  1800. }
  1801. public function getUsers()
  1802. {
  1803. return $this->_users;
  1804. }
  1805. public function getRoles()
  1806. {
  1807. return $this->_roles;
  1808. }
  1809. public function getVerb()
  1810. {
  1811. return $this->_verb;
  1812. }
  1813. public function getIPRules()
  1814. {
  1815. return $this->_ipRules;
  1816. }
  1817. public function getGuestApplied()
  1818. {
  1819. return $this->_guest || $this->_everyone;
  1820. }
  1821. public function getEveryoneApplied()
  1822. {
  1823. return $this->_everyone;
  1824. }
  1825. public function getAuthenticatedApplied()
  1826. {
  1827. return $this->_authenticated || $this->_everyone;
  1828. }
  1829. public function isUserAllowed(IUser $user,$verb,$ip)
  1830. {
  1831. if($this->isVerbMatched($verb) && $this->isIpMatched($ip) && $this->isUserMatched($user) && $this->isRoleMatched($user))
  1832. return ($this->_action==='allow')?1:-1;
  1833. else
  1834. return 0;
  1835. }
  1836. private function isIpMatched($ip)
  1837. {
  1838. if(empty($this->_ipRules))
  1839. return 1;
  1840. foreach($this->_ipRules as $rule)
  1841. {
  1842. if($rule==='*' || $rule===$ip || (($pos=strpos($rule,'*'))!==false && strncmp($ip,$rule,$pos)===0))
  1843. return 1;
  1844. }
  1845. return 0;
  1846. }
  1847. private function isUserMatched($user)
  1848. {
  1849. return ($this->_everyone || ($this->_guest && $user->getIsGuest()) || ($this->_authenticated && !$user->getIsGuest()) || in_array(strtolower($user->getName()),$this->_users));
  1850. }
  1851. private function isRoleMatched($user)
  1852. {
  1853. foreach($this->_roles as $role)
  1854. {
  1855. if($role==='*' || $user->isInRole($role))
  1856. return true;
  1857. }
  1858. return false;
  1859. }
  1860. private function isVerbMatched($verb)
  1861. {
  1862. return ($this->_verb==='*' || strcasecmp($verb,$this->_verb)===0);
  1863. }
  1864. }
  1865. class TAuthorizationRuleCollection extends TList
  1866. {
  1867. public function isUserAllowed($user,$verb,$ip)
  1868. {
  1869. if($user instanceof IUser)
  1870. {
  1871. $verb=strtolower(trim($verb));
  1872. foreach($this as $rule)
  1873. {
  1874. if(($decision=$rule->isUserAllowed($user,$verb,$ip))!==0)
  1875. return ($decision>0);
  1876. }
  1877. return true;
  1878. }
  1879. else
  1880. return false;
  1881. }
  1882. public function insertAt($index,$item)
  1883. {
  1884. if($item instanceof TAuthorizationRule)
  1885. parent::insertAt($index,$item);
  1886. else
  1887. throw new TInvalidDataTypeException('authorizationrulecollection_authorizationrule_required');
  1888. }
  1889. }
  1890. class TSecurityManager extends TModule
  1891. {
  1892. const STATE_VALIDATION_KEY = 'prado:securitymanager:validationkey';
  1893. const STATE_ENCRYPTION_KEY = 'prado:securitymanager:encryptionkey';
  1894. private $_validationKey = null;
  1895. private $_encryptionKey = null;
  1896. private $_validation = TSecurityManagerValidationMode::SHA1;
  1897. private $_encryption = '3DES';
  1898. public function init($config)
  1899. {
  1900. $this->getApplication()->setSecurityManager($this);
  1901. }
  1902. protected function generateRandomKey()
  1903. {
  1904. return rand().rand().rand().rand();
  1905. }
  1906. public function getValidationKey()
  1907. {
  1908. if(null === $this->_validationKey) {
  1909. if(null === ($this->_validationKey = $this->getApplication()->getGlobalState(self::STATE_VALIDATION_KEY))) {
  1910. $this->_validationKey = $this->generateRandomKey();
  1911. $this->getApplication()->setGlobalState(self::STATE_VALIDATION_KEY, $this->_validationKey, null);
  1912. }
  1913. }
  1914. return $this->_validationKey;
  1915. }
  1916. public function setValidationKey($value)
  1917. {
  1918. if('' === $value)
  1919. throw new TInvalidDataValueException('securitymanager_validationkey_invalid');
  1920. $this->_validationKey = $value;
  1921. }
  1922. public function getEncryptionKey()
  1923. {
  1924. if(null === $this->_encryptionKey) {
  1925. if(null === ($this->_encryptionKey = $this->getApplication()->getGlobalState(self::STATE_ENCRYPTION_KEY))) {
  1926. $this->_encryptionKey = $this->generateRandomKey();
  1927. $this->getApplication()->setGlobalState(self::STATE_ENCRYPTION_KEY, $this->_encryptionKey, null);
  1928. }
  1929. }
  1930. return $this->_encryptionKey;
  1931. }
  1932. public function setEncryptionKey($value)
  1933. {
  1934. if('' === $value)
  1935. throw new TInvalidDataValueException('securitymanager_encryptionkey_invalid');
  1936. $this->_encryptionKey = $value;
  1937. }
  1938. public function getValidation()
  1939. {
  1940. return $this->_validation;
  1941. }
  1942. public function setValidation($value)
  1943. {
  1944. $this->_validation = TPropertyValue::ensureEnum($value, 'TSecurityManagerValidationMode');
  1945. }
  1946. public function getEncryption()
  1947. {
  1948. return $this->_encryption;
  1949. }
  1950. public function setEncryption($value)
  1951. {
  1952. throw new TNotSupportedException('Currently only 3DES encryption is supported');
  1953. }
  1954. public function encrypt($data)
  1955. {
  1956. if(!function_exists('mcrypt_encrypt'))
  1957. throw new TNotSupportedException('securitymanager_mcryptextension_required');
  1958. $module = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_CBC, '');
  1959. $key = substr(md5($this->getEncryptionKey()), 0, mcrypt_enc_get_key_size($module));
  1960. srand();
  1961. $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($module), MCRYPT_RAND);
  1962. mcrypt_generic_init($module, $key, $iv);
  1963. $encrypted = $iv.mcrypt_generic($module, $data);
  1964. mcrypt_generic_deinit($module);
  1965. mcrypt_module_close($module);
  1966. return $encrypted;
  1967. }
  1968. public function decrypt($data)
  1969. {
  1970. if(!function_exists('mcrypt_decrypt'))
  1971. throw new TNotSupportedException('securitymanager_mcryptextension_required');
  1972. $module = mcrypt_module_open(MCRYPT_3DES, '', MCRYPT_MODE_CBC, '');
  1973. $key = substr(md5($this->getEncryptionKey()), 0, mcrypt_enc_get_key_size($module));
  1974. $ivSize = mcrypt_enc_get_iv_size($module);
  1975. $iv = substr($data, 0, $ivSize);
  1976. mcrypt_generic_init($module, $key, $iv);
  1977. $decrypted = mdecrypt_generic($module, substr($data, $ivSize));
  1978. mcrypt_generic_deinit($module);
  1979. mcrypt_module_close($module);
  1980. return $decrypted;
  1981. }
  1982. public function hashData($data)
  1983. {
  1984. $hmac = $this->computeH

Large files files are truncated, but you can click here to view the full file