Guest User

Untitled

a guest
Mar 20th, 2019
149
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.31 KB | None | 0 0
  1. <?php
  2.  
  3. /**
  4. * Basic setup class and facade into app-specific configurations and the DIC.
  5. */
  6. class XF
  7. {
  8. /**
  9. * Current printable and encoded versions. These are used for visual output
  10. * and installation/upgrading.
  11. *
  12. * @var string
  13. * @var integer
  14. */
  15. public static $version = '2.0.12';
  16. public static $versionId = 2001270; // abbccde = a.b.c d (alpha: 1, beta: 3, RC: 5, stable: 7, PL: 9) e
  17.  
  18. protected static $requestCleaned = false;
  19.  
  20. protected static $memoryLimit = null;
  21.  
  22. /**
  23. * @var \Composer\Autoload\ClassLoader
  24. */
  25. public static $autoLoader = null;
  26.  
  27. public static $debugMode = false;
  28. public static $time = 0;
  29.  
  30. protected static $rootDirectory = '.';
  31. protected static $sourceDirectory = '.';
  32.  
  33. protected static $app = null;
  34.  
  35. /**
  36. * @var \XF\Entity\User
  37. */
  38. protected static $visitor = null;
  39.  
  40. /**
  41. * @var \XF\Language
  42. */
  43. protected static $language = null;
  44.  
  45. /**
  46. * Starts the XF framework and standardized the environment.
  47. */
  48. public static function start($rootDirectory)
  49. {
  50. self::$time = time();
  51. self::$rootDirectory = $rootDirectory;
  52. self::$sourceDirectory = __DIR__;
  53.  
  54. self::standardizeEnvironment();
  55. self::startAutoloader();
  56. self::startSystem();
  57. }
  58.  
  59. /**
  60. * Sets up the PHP environment in the XF-expected way
  61. */
  62. public static function standardizeEnvironment()
  63. {
  64. ignore_user_abort(true);
  65.  
  66. self::setMemoryLimit(128 * 1024 * 1024);
  67.  
  68. error_reporting(E_ALL | E_STRICT & ~8192);
  69. set_error_handler(['XF', 'handlePhpError']);
  70. set_exception_handler(['XF', 'handleException']);
  71. register_shutdown_function(['XF', 'handleFatalError']);
  72.  
  73. date_default_timezone_set('UTC');
  74. setlocale(LC_ALL, 'C');
  75.  
  76. // if you really need to load a phar file, you can call stream_wrapper_restore('phar');
  77. @stream_wrapper_unregister('phar');
  78.  
  79. @ini_set('output_buffering', false);
  80.  
  81. // see http://bugs.php.net/bug.php?id=36514
  82. // and http://xenforo.com/community/threads/53637/
  83. if (!@ini_get('output_handler'))
  84. {
  85. $level = ob_get_level();
  86. while ($level)
  87. {
  88. @ob_end_clean();
  89. $newLevel = ob_get_level();
  90. if ($newLevel >= $level)
  91. {
  92. break;
  93. }
  94. $level = $newLevel;
  95. }
  96. }
  97. }
  98.  
  99. /**
  100. * Handler for set_error_handler to convert notices, warnings, and other errors
  101. * into exceptions.
  102. *
  103. * @param integer $errorType Type of error (one of the E_* constants)
  104. * @param string $errorString
  105. * @param string $file
  106. * @param integer $line
  107. *
  108. * @throws \ErrorException
  109. */
  110. public static function handlePhpError($errorType, $errorString, $file, $line)
  111. {
  112. if ($errorType & error_reporting())
  113. {
  114. $errorString = '[' . \XF\Util\Php::convertErrorCodeToString($errorType) . '] '. $errorString;
  115.  
  116. $trigger = true;
  117. if (!self::$debugMode)
  118. {
  119. if ($errorType & E_STRICT
  120. || $errorType & E_DEPRECATED
  121. || $errorType & E_USER_DEPRECATED
  122. )
  123. {
  124. $trigger = false;
  125. }
  126. else if ($errorType & E_NOTICE || $errorType & E_USER_NOTICE)
  127. {
  128. $trigger = false;
  129. $e = new \ErrorException($errorString, 0, $errorType, $file, $line);
  130. self::app()->logException($e);
  131. }
  132. }
  133.  
  134. if ($trigger)
  135. {
  136. throw new \ErrorException($errorString, 0, $errorType, $file, $line);
  137. }
  138. }
  139. }
  140.  
  141. /**
  142. * Default exception handler.
  143. *
  144. * @param Exception $e
  145. */
  146. public static function handleException($e)
  147. {
  148. $app = self::app();
  149. $app->logException($e, true); // exiting so rollback
  150. $app->displayFatalExceptionMessage($e);
  151. }
  152.  
  153. /**
  154. * @param \Exception|\Throwable $e
  155. * @param bool $rollback
  156. * @param string $messagePrefix
  157. * @param bool $forceLog
  158. */
  159. public static function logException($e, $rollback = false, $messagePrefix = '', $forceLog = false)
  160. {
  161. self::app()->error()->logException($e, $rollback, $messagePrefix, $forceLog);
  162. }
  163.  
  164. public static function logError($message, $forceLog = false)
  165. {
  166. self::app()->error()->logError($message, $forceLog);
  167. }
  168.  
  169. /**
  170. * Try to log fatal errors so that debugging is easier.
  171. */
  172. public static function handleFatalError()
  173. {
  174. $error = @error_get_last();
  175. if (!$error)
  176. {
  177. return;
  178. }
  179.  
  180. if (empty($error['type']) || !($error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR)))
  181. {
  182. return;
  183. }
  184.  
  185. try
  186. {
  187. self::app()->logException(
  188. new ErrorException("Fatal Error: " . $error['message'], $error['type'], 1, $error['file'], $error['line']),
  189. true
  190. );
  191. }
  192. catch (Exception $e) {}
  193. }
  194.  
  195. /**
  196. * Sets up XF's autoloader
  197. */
  198. public static function startAutoloader()
  199. {
  200. if (self::$autoLoader)
  201. {
  202. return;
  203. }
  204.  
  205. /** @var \Composer\Autoload\ClassLoader $autoLoader */
  206. $autoLoader = require(__DIR__ . '/vendor/autoload.php');
  207. $autoLoader->register();
  208.  
  209. self::$autoLoader = $autoLoader;
  210. }
  211.  
  212. public static function startSystem()
  213. {
  214. register_shutdown_function(['XF', 'triggerRunOnce']);
  215.  
  216. require(__DIR__ . '/vendor/dokuwiki/utf8/utf8.php');
  217. }
  218.  
  219. protected static $runOnce = [];
  220.  
  221. public static function runOnce($key, \Closure $fn)
  222. {
  223. if (isset(self::$runOnce[$key]))
  224. {
  225. // if this key already exists, allow a new function with the
  226. // same key to replace it and move to the end of the queue.
  227. unset(self::$runOnce[$key]);
  228. }
  229. self::$runOnce[$key] = $fn;
  230. }
  231.  
  232. public static function runLater(\Closure $fn)
  233. {
  234. self::$runOnce[] = $fn;
  235. }
  236.  
  237. public static function triggerRunOnce($rethrow = false)
  238. {
  239. $i = 0;
  240.  
  241. do
  242. {
  243. foreach (self::$runOnce AS $key => $fn)
  244. {
  245. unset(self::$runOnce[$key]);
  246.  
  247. try
  248. {
  249. $fn();
  250. }
  251. catch (\Exception $e)
  252. {
  253. self::logException($e, true);
  254. // can't know if we have an open transaction from before so have to roll it back
  255.  
  256. if ($rethrow)
  257. {
  258. throw $e;
  259. }
  260. }
  261. }
  262.  
  263. $i++;
  264. }
  265. while (self::$runOnce && $i < 5);
  266. }
  267.  
  268. public static function getRootDirectory()
  269. {
  270. return self::$rootDirectory;
  271. }
  272.  
  273. public static function getSourceDirectory()
  274. {
  275. return self::$sourceDirectory;
  276. }
  277.  
  278. public static function getAddOnDirectory()
  279. {
  280. return \XF::getSourceDirectory() . DIRECTORY_SEPARATOR . 'addons';
  281. }
  282.  
  283. /**
  284. * @param \XF\App $app
  285. */
  286. public static function setApp(\XF\App $app)
  287. {
  288. if (self::$app)
  289. {
  290. throw new \LogicException(
  291. 'A second app cannot be setup. '
  292. . 'Tried to set ' . get_class($app) . ' after setting ' . get_class(self::$app)
  293. );
  294. }
  295.  
  296. self::$app = $app;
  297. }
  298.  
  299. /**
  300. * @return \XF\App
  301. */
  302. public static function app()
  303. {
  304. if (!self::$app)
  305. {
  306. return self::setupApp('\XF\App');
  307. }
  308.  
  309. return self::$app;
  310. }
  311.  
  312. public static function setupApp($appClass, array $setupOptions = [])
  313. {
  314. /** @var \XF\App $app */
  315. $app = new $appClass(new \XF\Container());
  316. self::setApp($app);
  317. $app->setup($setupOptions);
  318.  
  319. return $app;
  320. }
  321.  
  322. /**
  323. * Runs the specified application
  324. *
  325. * @param string $appClass
  326. */
  327. public static function runApp($appClass)
  328. {
  329. $app = self::setupApp($appClass);
  330.  
  331. ob_start();
  332.  
  333. $response = $app->run();
  334.  
  335. $extraOutput = ob_get_clean();
  336. if (strlen($extraOutput))
  337. {
  338. $body = $response->body();
  339. if (is_string($body))
  340. {
  341. if ($response->contentType() == 'text/html')
  342. {
  343. if (strpos($body, '<!--XF:EXTRA_OUTPUT-->') !== false)
  344. {
  345. $body = str_replace('<!--XF:EXTRA_OUTPUT-->', $extraOutput . '<!--XF:EXTRA_OUTPUT-->', $body);
  346. }
  347. else
  348. {
  349. $body = preg_replace('#<body[^>]*>#i', "\\0$extraOutput", $body);
  350. }
  351. $response->body($body);
  352. }
  353. else
  354. {
  355. $response->body($extraOutput . $body);
  356. }
  357. }
  358. }
  359.  
  360. $response->send($app->request());
  361. }
  362.  
  363. /**
  364. * @return \XF\Entity\User
  365. */
  366. public static function visitor()
  367. {
  368. if (!self::$visitor)
  369. {
  370. /** @var \XF\Repository\User $userRepo */
  371. $userRepo = self::repository('XF:User');
  372. self::$visitor = $userRepo->getVisitor(0);
  373. }
  374.  
  375. return self::$visitor;
  376. }
  377.  
  378. public static function setVisitor(\XF\Entity\User $user = null)
  379. {
  380. self::$visitor = $user;
  381. }
  382.  
  383. /**
  384. * Temporarily take an action with the given user considered to be the visitor
  385. *
  386. * @param \XF\Entity\User $user
  387. * @param callable $action
  388. *
  389. * @return mixed Result from the action
  390. */
  391. public static function asVisitor(\XF\Entity\User $user, \Closure $action)
  392. {
  393. $old = self::$visitor;
  394. self::setVisitor($user);
  395. try
  396. {
  397. $return = $action();
  398. self::setVisitor($old);
  399. }
  400. catch (\Exception $e)
  401. {
  402. self::setVisitor($old);
  403. throw $e;
  404. }
  405.  
  406. return $return;
  407. }
  408.  
  409. /**
  410. * @return \XF\Language
  411. */
  412. public static function language()
  413. {
  414. if (!self::$language)
  415. {
  416. self::$language = self::app()->language(0);
  417. }
  418.  
  419. return self::$language;
  420. }
  421.  
  422. public static function setLanguage(\XF\Language $language)
  423. {
  424. self::$language = $language;
  425. }
  426.  
  427. public static function phrasedException($name, array $params = [])
  428. {
  429. return new \XF\PrintableException(
  430. self::phrase($name, $params)->render(),
  431. $name
  432. );
  433. }
  434.  
  435. public static function phrase($name, array $params = [], $allowHtml = true)
  436. {
  437. return self::language()->phrase($name, $params, true, $allowHtml);
  438. }
  439.  
  440. public static function phraseDeferred($name, array $params = [])
  441. {
  442. return self::language()->phrase($name, $params, false);
  443. }
  444.  
  445. public static function string(array $parts = [])
  446. {
  447. return new \XF\StringBuilder($parts);
  448. }
  449.  
  450. public static function config($key = null)
  451. {
  452. return self::app()->config($key);
  453. }
  454.  
  455. /**
  456. * @return \XF\Session\Session
  457. */
  458. public static function session()
  459. {
  460. return self::app()->session();
  461. }
  462.  
  463. /**
  464. * @return \ArrayObject
  465. */
  466. public static function options()
  467. {
  468. return self::app()->options();
  469. }
  470.  
  471. /**
  472. * @return \XF\Mail\Mailer
  473. */
  474. public static function mailer()
  475. {
  476. return self::app()->mailer();
  477. }
  478.  
  479. /**
  480. * @return \XF\Db\AbstractAdapter
  481. */
  482. public static function db()
  483. {
  484. return self::app()->db();
  485. }
  486.  
  487. /**
  488. * @return \XF\PermissionCache
  489. */
  490. public static function permissionCache()
  491. {
  492. return self::app()->permissionCache();
  493. }
  494.  
  495. /**
  496. * @return \XF\Mvc\Entity\Manager
  497. */
  498. public static function em()
  499. {
  500. return self::app()->em();
  501. }
  502.  
  503. /**
  504. * @param string $identifier
  505. *
  506. * @return \XF\Mvc\Entity\Finder
  507. */
  508. public static function finder($identifier)
  509. {
  510. return self::app()->finder($identifier);
  511. }
  512.  
  513. /**
  514. * @param string $identifier
  515. *
  516. * @return \XF\Mvc\Entity\Repository
  517. */
  518. public static function repository($identifier)
  519. {
  520. return self::app()->repository($identifier);
  521. }
  522.  
  523. /**
  524. * @param string $class
  525. *
  526. * @return \XF\Service\AbstractService
  527. */
  528. public static function service($class)
  529. {
  530. $args = func_get_args();
  531. return call_user_func_array([self::app(), 'service'], $args);
  532. }
  533.  
  534. /**
  535. * @return \XF\DataRegistry
  536. */
  537. public static function registry()
  538. {
  539. return self::app()->registry();
  540. }
  541.  
  542. /**
  543. * @return \League\Flysystem\MountManager
  544. */
  545. public static function fs()
  546. {
  547. return self::app()->fs();
  548. }
  549.  
  550. public static function extension()
  551. {
  552. return self::app()->extension();
  553. }
  554.  
  555. /**
  556. * Fires a code event for an extension point
  557. *
  558. * @param string $event
  559. * @param array $args
  560. * @param null|string $hint
  561. *
  562. * @return bool
  563. */
  564. public static function fire($event, array $args, $hint = null)
  565. {
  566. return self::extension()->fire($event, $args, $hint);
  567. }
  568.  
  569. /**
  570. * Gets the callable class name for a dynamically extended class.
  571. *
  572. * @param string $class
  573. * @param null|string $fakeBaseClass
  574. * @return string
  575. *
  576. * @throws Exception
  577. */
  578. public static function extendClass($class, $fakeBaseClass = null)
  579. {
  580. return self::app()->extendClass($class, $fakeBaseClass);
  581. }
  582.  
  583. /**
  584. * Sets the memory limit. Will not shrink the limit.
  585. *
  586. * @param integer $limit Limit must be given in integer (byte) format.
  587. *
  588. * @return bool True if the limit was updated (or already met)
  589. */
  590. public static function setMemoryLimit($limit)
  591. {
  592. $existingLimit = self::getMemoryLimit();
  593. if ($existingLimit < 0)
  594. {
  595. return true;
  596. }
  597.  
  598. $limit = intval($limit);
  599. if ($limit > $existingLimit && $existingLimit)
  600. {
  601. if (@ini_set('memory_limit', $limit) === false)
  602. {
  603. return false;
  604. }
  605.  
  606. self::$memoryLimit = $limit;
  607. }
  608.  
  609. return true;
  610. }
  611.  
  612. public static function increaseMemoryLimit($amount)
  613. {
  614. $amount = intval($amount);
  615. if ($amount <= 0)
  616. {
  617. return false;
  618. }
  619.  
  620. $currentLimit = self::getMemoryLimit();
  621. if ($currentLimit < 0)
  622. {
  623. return true;
  624. }
  625.  
  626. return self::setMemoryLimit($currentLimit + $amount);
  627. }
  628.  
  629. /**
  630. * Gets the current memory limit.
  631. *
  632. * @return int
  633. */
  634. public static function getMemoryLimit()
  635. {
  636. if (self::$memoryLimit === null)
  637. {
  638. $curLimit = @ini_get('memory_limit');
  639. if ($curLimit === false)
  640. {
  641. // reading failed, so we have to treat it as unlimited - unlikely to be able to change anyway
  642. $curLimitInt = -1;
  643. }
  644. else
  645. {
  646. $curLimitInt = intval($curLimit);
  647.  
  648. switch (substr($curLimit, -1))
  649. {
  650. case 'g':
  651. case 'G':
  652. $curLimitInt *= 1024;
  653. // fall through
  654.  
  655. case 'm':
  656. case 'M':
  657. $curLimitInt *= 1024;
  658. // fall through
  659.  
  660. case 'k':
  661. case 'K':
  662. $curLimitInt *= 1024;
  663. }
  664. }
  665.  
  666. self::$memoryLimit = $curLimitInt;
  667. }
  668.  
  669. return self::$memoryLimit;
  670. }
  671.  
  672. /**
  673. * Attempts to determine the current available amount of memory.
  674. * If there is no memory limit
  675. *
  676. * @return int
  677. */
  678. public static function getAvailableMemory()
  679. {
  680. $limit = self::getMemoryLimit();
  681. if ($limit < 0)
  682. {
  683. return PHP_INT_MAX;
  684. }
  685.  
  686. $used = memory_get_usage();
  687. $available = $limit - $used;
  688.  
  689. return ($available < 0 ? 0 : $available);
  690. }
  691.  
  692. /**
  693. * Generates a psuedo-random string of the specified length.
  694. *
  695. * @param integer $length
  696. * @param boolean $raw If true, raw binary is returned, otherwise modified base64
  697. *
  698. * @return string
  699. */
  700. public static function generateRandomString($length, $raw = false)
  701. {
  702. if ($raw)
  703. {
  704. return \XF\Util\Random::getRandomBytes($length);
  705. }
  706. else
  707. {
  708. return \XF\Util\Random::getRandomString($length);
  709. }
  710. }
  711.  
  712. public static function stringToClass($string, $formatter, $defaultInfix = null)
  713. {
  714. $parts = explode(':', $string, 3);
  715. if (count($parts) == 1)
  716. {
  717. // already a class
  718. return $string;
  719. }
  720.  
  721. $prefix = $parts[0];
  722. if (isset($parts[2]))
  723. {
  724. $infix = $parts[1];
  725. $suffix = $parts[2];
  726. }
  727. else
  728. {
  729. $infix = $defaultInfix;
  730. $suffix = $parts[1];
  731. }
  732.  
  733. return $defaultInfix === null
  734. ? sprintf($formatter, $prefix, $suffix)
  735. : sprintf($formatter, $prefix, $infix, $suffix);
  736. }
  737.  
  738. public static function getCopyrightHtml()
  739. {
  740. return '';
  741. }
  742.  
  743. public static function isPreEscaped($value, $type = 'html')
  744. {
  745. if ($value instanceof \XF\PreEscaped && $value->escapeType == $type)
  746. {
  747. return true;
  748. }
  749. else if ($value instanceof \XF\PreEscapedInterface && $value->getPreEscapeType() == $type)
  750. {
  751. return true;
  752. }
  753. else
  754. {
  755. return false;
  756. }
  757. }
  758.  
  759. public static function escapeString($value, $type = 'html')
  760. {
  761. if ($type === false)
  762. {
  763. $type = 'raw';
  764. }
  765. else if ($type === true)
  766. {
  767. $type = 'html';
  768. }
  769.  
  770. if (self::isPreEscaped($value, $type))
  771. {
  772. return strval($value);
  773. }
  774. else if ($type == 'html' && ($value instanceof \XF\Phrase || $value instanceof \XF\Template\Template))
  775. {
  776. return strval($value);
  777. }
  778.  
  779. $value = strval($value);
  780.  
  781. switch ($type)
  782. {
  783. case 'html':
  784. return htmlspecialchars($value, ENT_QUOTES, 'utf-8');
  785.  
  786. case 'raw':
  787. return $value;
  788.  
  789. case 'js':
  790. $value = strtr($value, [
  791. '\\' => '\\\\',
  792. '"' => '\\"',
  793. "'" => "\\'",
  794. "\r" => '\r',
  795. "\n" => '\n',
  796. '</' => '<\\/',
  797. ]);
  798. $value = preg_replace('/-(?=-)/', '-\\', $value);
  799. return $value;
  800.  
  801. case 'json':
  802. $value = strtr($value, [
  803. '\\' => '\\\\',
  804. '"' => '\\"',
  805. "\r" => '\r',
  806. "\n" => '\n',
  807. '/' => '\\/',
  808. '<!' => '\u003C!'
  809. ]);
  810. return $value;
  811.  
  812. case 'htmljs':
  813. return \XF::escapeString(\XF::escapeString($value, 'html'), 'js');
  814.  
  815. case 'datauri':
  816. $value = strtr($value, [
  817. "\r" => '%0D',
  818. "\n" => '%0A',
  819. '%' => '%25',
  820. '#' => '%23',
  821. '(' => '%28',
  822. ')' => '%29',
  823. '<' => '%3C',
  824. '>' => '%3E',
  825. '?' => '%3F',
  826. '[' => '%5B',
  827. ']' => '%5D',
  828. '\\' => '%5C',
  829. '^' => '%5E',
  830. '`' => '%60',
  831. '{' => '%7B',
  832. '}' => '%7D',
  833. '|' => '%7C'
  834. ]);
  835. return $value;
  836.  
  837. default:
  838. return htmlspecialchars($value, ENT_QUOTES, 'utf-8');
  839. }
  840. }
  841.  
  842. public static function cleanString($string, $trim = true)
  843. {
  844. return self::app()->inputFilterer()->cleanString($string, $trim);
  845. }
  846.  
  847. public static function cleanArrayStrings(array $input, $trim = true)
  848. {
  849. return self::app()->inputFilterer()->cleanArrayStrings($input, $trim);
  850. }
  851.  
  852. public static function dump($var)
  853. {
  854. self::app()->debugger()->dump($var);
  855. }
  856.  
  857. public static function dumpSimple($var, $echo = true)
  858. {
  859. return self::app()->debugger()->dumpSimple($var, $echo);
  860. }
  861.  
  862. public static function dumpConsole($var, $type = 'log')
  863. {
  864. return self::app()->debugger()->dumpConsole($var, $type);
  865. }
  866. }
Add Comment
Please, Sign In to add comment