PageRenderTime 60ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/site/www/_js/libs/tiny_mce/plugins/imagemanager/classes/ManagerEngine.php

https://bitbucket.org/thiscode/thiscode-shop
PHP | 1224 lines | 663 code | 246 blank | 315 comment | 208 complexity | 5c2b7ec25d1fc5d0d387ec8daba6c432 MD5 | raw file
  1. <?php
  2. /**
  3. * $Id: ManagerEngine.php 751 2009-10-20 12:05:36Z spocke $
  4. *
  5. * @package MCManager
  6. * @author Moxiecode
  7. * @copyright Copyright Š 2007, Moxiecode Systems AB, All rights reserved.
  8. */
  9. // Get base path
  10. define('MCMANAGER_ABSPATH', dirname(__FILE__) . "/");
  11. // Import core classes
  12. require_once(MCMANAGER_ABSPATH . "Utils/Logger.class.php");
  13. require_once(MCMANAGER_ABSPATH . "ManagerPlugin.php");
  14. require_once(MCMANAGER_ABSPATH . "Utils/ResultSet.php");
  15. require_once(MCMANAGER_ABSPATH . "Utils/LanguagePack.php");
  16. require_once(MCMANAGER_ABSPATH . "FileSystems/BaseFile.php");
  17. require_once(MCMANAGER_ABSPATH . "FileSystems/FileStream.php");
  18. require_once(MCMANAGER_ABSPATH . "FileSystems/FileFilter.php");
  19. require_once(MCMANAGER_ABSPATH . "FileSystems/FileTreeHandler.php");
  20. /**
  21. * This class handles the core logic of the MCManager it's responsible for event handeling, configuration management,
  22. * language packs and plugins.
  23. *
  24. * @package MCManager
  25. */
  26. class Moxiecode_ManagerEngine {
  27. /**#@+
  28. * @access private
  29. */
  30. var $_config;
  31. var $_plugins;
  32. var $_prefixes;
  33. var $_fileSystems;
  34. var $_rootPaths;
  35. var $_language;
  36. var $_type;
  37. var $_logger;
  38. var $_langPackPath;
  39. /**#@+
  40. * @access public
  41. */
  42. /**
  43. * Main constructor.
  44. *
  45. * @param String $type Language pack type prefix. Used inorder to load the correct language pack like im or fm.
  46. */
  47. function Moxiecode_ManagerEngine($type) {
  48. $this->_plugins = array();
  49. $this->_prefixes = array();
  50. $this->_rootPaths = array();
  51. $this->_config = array();
  52. $this->_type = $type;
  53. }
  54. /**
  55. * Sets the name/value array of config options. This method will also force some relative config option paths to absolute.
  56. *
  57. * @param Array $config Name/value array of config options.
  58. * @param bool $setup_values True/false if the paths etc of the config should be set to default values or not.
  59. */
  60. function setConfig($config, $setup_values = true) {
  61. $this->_rootPaths = array();
  62. if ($setup_values) {
  63. // Auto add rootpaths and force them absolute in config
  64. $newRoots = array();
  65. $roots = explode(';', $config['filesystem.rootpath']);
  66. foreach ($roots as $root) {
  67. $rootParts = explode('=', $root);
  68. // Unnamed root
  69. if (count($rootParts) == 1) {
  70. $rootParts[0] = $this->removeTrailingSlash($this->toAbsPath($rootParts[0]));
  71. $this->addRootPath($rootParts[0]);
  72. }
  73. // Named root
  74. if (count($rootParts) == 2) {
  75. $rootParts[1] = $this->removeTrailingSlash($this->toAbsPath($rootParts[1]));
  76. $this->addRootPath($rootParts[1]);
  77. }
  78. $newRoots[] = implode('=', $rootParts);
  79. }
  80. $config['filesystem.rootpath'] = implode(';', $newRoots);
  81. // Force absolute path
  82. if ($config['filesystem.path'] == "")
  83. $config['filesystem.path'] = $this->_rootPaths[0];
  84. else
  85. $config['filesystem.path'] = $this->removeTrailingSlash($this->toAbsPath($config['filesystem.path']));
  86. // Check if path is within any of the roots
  87. $found = false;
  88. foreach ($this->_rootPaths as $root) {
  89. if ($this->isChildPath($root, $config['filesystem.path'])) {
  90. $found = true;
  91. break;
  92. }
  93. }
  94. // Path was not within any of the rootpaths use the first one
  95. if (!$found)
  96. $config['filesystem.path'] = $this->_rootPaths[0];
  97. // Setup absolute wwwroot
  98. if (isset($config['preview.wwwroot']) && $config['preview.wwwroot'])
  99. $config['preview.wwwroot'] = $this->toUnixPath($this->toAbsPath($config['preview.wwwroot']));
  100. else
  101. $config['preview.wwwroot'] = $this->getSiteRoot();
  102. // Setup preview.urlprefix
  103. if ($config["preview.urlprefix"]) {
  104. if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on")
  105. $config["preview.urlprefix"] = str_replace("{proto}", "https", $config["preview.urlprefix"]);
  106. else
  107. $config["preview.urlprefix"] = str_replace("{proto}", "http", $config["preview.urlprefix"]);
  108. $config["preview.urlprefix"] = str_replace("{host}", $_SERVER['HTTP_HOST'], $config["preview.urlprefix"]);
  109. $config["preview.urlprefix"] = str_replace("{port}", $_SERVER['SERVER_PORT'], $config["preview.urlprefix"]);
  110. }
  111. }
  112. $this->_config =& $config;
  113. }
  114. function getType() {
  115. return $this->_type;
  116. }
  117. function setLangPackPath($path) {
  118. $this->_langPackPath = $path;
  119. }
  120. function getLangPackPath() {
  121. return $this->_langPackPath;
  122. }
  123. /**
  124. * Returns a LanguagePack instance of the current language pack.
  125. *
  126. * @return LanguagePack Instance of the current language pack.
  127. */
  128. function &getLangPack() {
  129. if (!$this->_language) {
  130. $config = $this->getConfig();
  131. $this->_language = new Moxiecode_LanguagePack();
  132. $this->_language->load($this->toAbsPath("language/" . $this->_langPackPath . "/" . $config['general.language'] . ".xml"));
  133. }
  134. return $this->_language;
  135. }
  136. /**
  137. * Returns a lang item by group and key.
  138. *
  139. * @param string $group Language group to look in.
  140. * @param string $item Item to get inside group.
  141. * @param Array $replace Name/Value array of variables to replace in language pack.
  142. * @return string Language pack string loaded from XML file.
  143. */
  144. function getLangItem($group, $item, $replace = array()) {
  145. $pack =& $this->getLangPack();
  146. $string = $pack->get($group, $item);
  147. foreach ($replace as $key => $val)
  148. $string = str_replace("{". $key ."}", $val, $string);
  149. return $string;
  150. }
  151. /**
  152. * Returns an array of plugin paths to be loaded/required/includes.
  153. *
  154. * @return Array Array of file paths to load.
  155. */
  156. function getPluginPaths() {
  157. $config = $this->getConfig();
  158. $plugins = array();
  159. if (isset($config["general.plugins"]) && $config["general.plugins"])
  160. $plugins = preg_split("/,/i", $config["general.plugins"]);
  161. $out = array();
  162. foreach($plugins as $plugin) {
  163. if (!isset($this->_plugins[strtolower($plugin)])) {
  164. // Check for single file plugins
  165. if (file_exists(MCMANAGER_ABSPATH . "../plugins/" . $plugin . ".php"))
  166. $out[] = "plugins/" . $plugin . ".php";
  167. else
  168. $out[] = "plugins/" . $plugin . "/". $plugin . ".php";
  169. }
  170. }
  171. // Check the string first
  172. if ($config["authenticator"] == "")
  173. $config["authenticator"] = "BaseAuthenticator";
  174. $authenticators = array();
  175. // Check string for delimiter, preg_split returns php warning if delimiter is not found!
  176. if (strpos($config["authenticator"], "+") || strpos($config["authenticator"], "|"))
  177. $authenticators = preg_split("/\+|\|/i", $config["authenticator"], -1, PREG_SPLIT_NO_EMPTY);
  178. if (count($authenticators) != 0) {
  179. foreach ($authenticators as $auth) {
  180. // Check for single file plugins
  181. if (!isset($this->_plugins[strtolower($auth)])) {
  182. if (file_exists(MCMANAGER_ABSPATH . "../plugins/" . $auth . ".php"))
  183. $out[] = "plugins/" . $auth . ".php";
  184. else
  185. $out[] = "plugins/" . $auth . "/". $auth . ".php";
  186. }
  187. }
  188. } else {
  189. if (!isset($this->_plugins[strtolower($config["authenticator"])])) {
  190. if (file_exists(MCMANAGER_ABSPATH . "Authenticators/" . $config["authenticator"] . ".php"))
  191. $out[] = "classes/Authenticators/" . $config["authenticator"] . ".php";
  192. else if (file_exists(MCMANAGER_ABSPATH . "../plugins/" . $config["authenticator"] . ".php"))
  193. $out[] = "plugins/" . $config["authenticator"] . ".php";
  194. else
  195. $out[] = "plugins/" . $config["authenticator"] . "/" . $config["authenticator"] . ".php";
  196. }
  197. }
  198. // Check so that they all exists
  199. foreach ($out as $path) {
  200. if (!file_exists(MCMANAGER_ABSPATH . "../" . $path))
  201. trigger_error("Plugin could not be found: " . $path, FATAL);
  202. }
  203. return $out;
  204. }
  205. /**
  206. * Adds a path to the list of root paths.
  207. *
  208. * @param String $path Path to add must be a absolute path.
  209. */
  210. function addRootPath($path) {
  211. $this->_rootPaths[] = $path;
  212. }
  213. /**
  214. * Returns an array of root paths.
  215. *
  216. * @return Array Root paths.
  217. */
  218. function getRootPaths() {
  219. return $this->_rootPaths;
  220. }
  221. /**
  222. * Returns a plugin by id/name.
  223. *
  224. * @param String $name Plugin id/name.
  225. * @return MCManagerPlugin instance object.
  226. */
  227. function getPlugin($name) {
  228. return isset($this->_plugins[$name]) ? $this->_plugins[$name] : null;
  229. }
  230. /**
  231. * Returns a true/false check for plugin.
  232. *
  233. * @param String $name Plugin id/name.
  234. * @return Bool true/false
  235. */
  236. function hasPlugin($name) {
  237. return isset($this->_plugins[$name]);
  238. }
  239. /**
  240. * Returns a name/value array of plugins.
  241. *
  242. * @return Array name/value array of MCManagerPlugin instances.
  243. */
  244. function getPlugins() {
  245. return $this->_plugins;
  246. }
  247. /**
  248. * Registers a plugin by id/name.
  249. *
  250. * @param $name Id/name to register plugin by.
  251. * @param $plugin Plugin instance to register/add to list.
  252. *
  253. * @return SmallMCEPlugin The added plugin instance.
  254. */
  255. function &registerPlugin($name, &$plugin, $prefix = false) {
  256. $name = strtolower($name);
  257. $this->_plugins[$name] =& $plugin;
  258. if ($prefix != false)
  259. $this->_prefixes[$name] = $prefix;
  260. return $plugin;
  261. }
  262. /**
  263. * Returns the MCManager config as name/value array.
  264. *
  265. * @return Array MCManager config as name/value array.
  266. */
  267. function &getConfig() {
  268. return $this->_config;
  269. }
  270. /**
  271. * Returns the a config item by name.
  272. *
  273. * @param string $key Config item key to retrive.
  274. * @param string $def Default value to return.
  275. * @return mixed config item by name.
  276. */
  277. function getConfigItem($key, $def = false) {
  278. return isset($this->_config[$key]) ? $this->_config[$key] : $def;
  279. }
  280. /**
  281. * Returns a merged JS config. It will only export configured items controlled by the allow_export suffix.
  282. *
  283. * @return Array Name/Value array of JS config options.
  284. */
  285. function &getJSConfig($config = false, $prefixes = '*') {
  286. $encrypted = array("filesystem.path", "filesystem.rootpath", "filesystem.directory_templates");
  287. $jsConfig = array();
  288. $prefixes = explode(",", $prefixes);
  289. if (!$config)
  290. $config = $this->getConfig();
  291. foreach ($config as $name => $value) {
  292. $pos = strpos($name, ".allow_export");
  293. if ($pos > 0) {
  294. $names = explode(",", $value);
  295. $prefix = substr($name, 0, $pos);
  296. if (in_array("*", $prefixes) || in_array($prefix, $prefixes)) {
  297. foreach ($names as $key) {
  298. $key = $prefix . "." . $key ;
  299. // Encrypt some paths
  300. if (in_array($key, $encrypted))
  301. $jsConfig[$key] = "" . $this->encryptPath($config[$key]);
  302. else
  303. $jsConfig[$key] = "" . is_bool($config[$key]) ? ($config[$key] ? "true" : "false") : $config[$key];
  304. }
  305. }
  306. }
  307. }
  308. return $jsConfig;
  309. }
  310. /**
  311. * Encrypts the specified path so that it doesn't contain full paths on the client side of the application.
  312. *
  313. * @param string $path Path to encrypt.
  314. * @return string Encrypted short path.
  315. */
  316. function encryptPath($path) {
  317. $config = $this->getConfig();
  318. if (checkBool($config['general.encrypt_paths'])) {
  319. $count = 0;
  320. foreach ($this->_rootPaths as $rootPath) {
  321. // Needs encryption?
  322. if ($rootPath != "/")
  323. $path = str_replace($rootPath, "{" . $count++ . "}", $path);
  324. }
  325. }
  326. return utf8_encode($path);
  327. }
  328. /**
  329. * Decrypts the specified path from a non absolute path to a absolute path.
  330. *
  331. * @param string $path Path to decrypt.
  332. * @return string Decrypted absolute path.
  333. */
  334. function decryptPath($path) {
  335. if (!$path)
  336. return "";
  337. $count = 0;
  338. $path = $this->toUnixPath($path);
  339. // Is relative path
  340. if (!(strpos($path, '/') === 0 || strpos($path, ':') !== false || strpos($path, '{') !== false))
  341. $path = realpath(dirname(__FILE__) . '/../' . $path);
  342. foreach ($this->_rootPaths as $rootPath)
  343. $path = str_replace("{" . $count++ . "}", $rootPath, $path);
  344. $path = str_replace("{default}", $this->_config["filesystem.path"], $path);
  345. return $path;
  346. }
  347. /**
  348. * isAuthenticated checks against the configuration and sends events to auth plugins.
  349. * This method will also call the onBeforeInit, onInit and onAfterInit methods if the user was authenticated.
  350. *
  351. * @return bool Returns true if authenticated, false if not.
  352. */
  353. function isAuthenticated() {
  354. $config = $this->getConfig();
  355. $authenticators = strtolower($config["authenticator"]);
  356. // Check the string first
  357. if ($authenticators != "" && $authenticators != "BaseAuthenticator") {
  358. if (strpos($authenticators, "|") && strpos($authenticators, "+"))
  359. trigger_error("You can not use both + and | at the same time for adding authenticators.", FATAL);
  360. $pass = false;
  361. // Check for AND authenticators
  362. if (strpos($authenticators, "+")) {
  363. $authArray = preg_split("/\+/i", $authenticators, -1, PREG_SPLIT_NO_EMPTY);
  364. if (!$authArray)
  365. trigger_error("No Authenticator could be used.", FATAL);
  366. // Verify that all authenticators exists
  367. foreach($authArray as $auth) {
  368. if (!$this->hasPlugin($auth))
  369. trigger_error("Authenticator \"". htmlentities($auth) ."\" was not found.", FATAL);
  370. }
  371. // Default to true
  372. $pass = true;
  373. // Send AND event
  374. foreach ($authArray as $auth) {
  375. $plugin = $this->getPlugin($auth);
  376. if ($pass && !$plugin->onAuthenticate($this))
  377. $pass = false;
  378. }
  379. // Check for OR authentocator string
  380. } else if (strpos($authenticators, "|")) {
  381. $authArray = preg_split("/\|/i", $authenticators, -1, PREG_SPLIT_NO_EMPTY);
  382. if (!$authArray)
  383. trigger_error("No Authenticator could be used.", FATAL);
  384. // Verify that all authenticators exists
  385. foreach ($authArray as $auth) {
  386. if (!$this->hasPlugin($auth))
  387. trigger_error("Authenticator \"". htmlentities($auth) ."\" was not found.", FATAL);
  388. }
  389. // Default to false
  390. $pass = false;
  391. // Send OR event
  392. foreach ($authArray as $auth) {
  393. $plugin = $this->getPlugin($auth);
  394. if ($plugin->onAuthenticate($this))
  395. $pass = true;
  396. }
  397. } else {
  398. $plugin = $this->getPlugin($authenticators);
  399. if ($plugin->onAuthenticate($this))
  400. $pass = true;
  401. }
  402. } else
  403. $pass = true;
  404. // Is authenticated, call onInit
  405. if ($pass)
  406. $this->dispatchEvent("onInit");
  407. // Set config again to update rootpaths etc
  408. $this->setConfig($this->_config);
  409. return $pass;
  410. }
  411. /**
  412. * Dispatches a event to all registered plugins. This method will loop through all plugins and call the specific event if this
  413. * event method returns false the chain will be terminated.
  414. *
  415. * @param String $event Event name to be dispatched for example onAjaxCommand.
  416. * @param Array $args Optional array with arguments.
  417. * @return Bool Returns true of a plugin returned true, false if not.
  418. */
  419. function dispatchEvent($event, $args = false) {
  420. // Setup event arguments
  421. $keys = array_keys($this->_plugins);
  422. for ($i=0; $i<count($keys); $i++) {
  423. $plugin =& $this->_plugins[$keys[$i]];
  424. // Valid prefix
  425. if (isset($this->_prefixes[$keys[$i]])) {
  426. if ($this->_type != $this->_prefixes[$keys[$i]])
  427. continue;
  428. }
  429. switch ($event) {
  430. case "onAuthenticate":
  431. if (!$plugin->onAuthenticate($this))
  432. return false;
  433. break;
  434. case "onInit":
  435. if (!$plugin->onInit($this))
  436. return false;
  437. break;
  438. case "onPreInit":
  439. if (!$plugin->onPreInit($this, $args[0]))
  440. return false;
  441. break;
  442. case "onLogin":
  443. if (!$plugin->onLogin($this))
  444. return false;
  445. break;
  446. case "onLogout":
  447. if (!$plugin->onLogout($this))
  448. return false;
  449. break;
  450. case "onBeforeFileAction":
  451. if (!isset($args[2]))
  452. $args[2] = null;
  453. if (!$plugin->onBeforeFileAction($this, $args[0], $args[1], $args[2]))
  454. return false;
  455. break;
  456. case "onFileAction":
  457. if (!isset($args[2]))
  458. $args[2] = null;
  459. if (!$plugin->onFileAction($this, $args[0], $args[1], $args[2]))
  460. return false;
  461. break;
  462. case "onBeforeRPC":
  463. if (!$plugin->onBeforeRPC($this, $args[0], $args[1]))
  464. return false;
  465. break;
  466. case "onBeforeStream":
  467. if (!$plugin->onBeforeStream($this, $args[0], $args[1]))
  468. return false;
  469. break;
  470. case "onStream":
  471. if (!$plugin->onStream($this, $args[0], $args[1]))
  472. return false;
  473. break;
  474. case "onAfterStream":
  475. if (!$plugin->onAfterStream($this, $args[0], $args[1]))
  476. return false;
  477. break;
  478. case "onBeforeUpload":
  479. if (!$plugin->onBeforeUpload($this, $args[0], $args[1]))
  480. return false;
  481. break;
  482. case "onAfterUpload":
  483. if (!$plugin->onAfterUpload($this, $args[0], $args[1]))
  484. return false;
  485. break;
  486. case "onCustomInfo":
  487. if (!$plugin->onCustomInfo($this, $args[0], $args[1], $args[2]))
  488. return false;
  489. break;
  490. case "onListFiles":
  491. if (!$plugin->onListFiles($this, $args[0], $args[1]))
  492. return false;
  493. break;
  494. case "onInsertFile":
  495. if (!$plugin->onInsertFile($this, $args[0]))
  496. return false;
  497. break;
  498. case "onRequestResources":
  499. if (!$plugin->onRequestResources($this, $args[0], $args[1], $args[2], $args[3], $args[4]))
  500. return false;
  501. break;
  502. }
  503. }
  504. return true;
  505. }
  506. /**
  507. * Executes a event in all registered plugins if a plugin returns a object or array the execution chain will be
  508. * terminated.
  509. *
  510. * @param String $event Event name to be dispatched for example onAjaxCommand.
  511. * @param Array $args Optional array with arguments.
  512. * @return Bool Returns true of a plugin returned true, false if not.
  513. */
  514. function executeEvent($event, $args=false) {
  515. // Setup event arguments
  516. $keys = array_keys($this->_plugins);
  517. for ($i=0; $i<count($keys); $i++) {
  518. $plugin =& $this->_plugins[$keys[$i]];
  519. // Valid prefix
  520. if (isset($this->_prefixes[$keys[$i]])) {
  521. if ($this->_type != $this->_prefixes[$keys[$i]])
  522. continue;
  523. }
  524. switch ($event) {
  525. case "onRPC":
  526. $result =& $plugin->onRPC($this, $args[0], $args[1]);
  527. if (!is_null($result))
  528. return $result;
  529. break;
  530. case "onUpload":
  531. $result =& $plugin->onUpload($this, $args[0], $args[1]);
  532. if (!is_null($result))
  533. return $result;
  534. break;
  535. }
  536. }
  537. return null;
  538. }
  539. function getInvalidFileMsg() {
  540. return $this->_invalidFileMsg;
  541. }
  542. /**
  543. * Returns the wwwroot if it fails it will trigger a fatal error.
  544. *
  545. * @return String wwwroot or null string if it was impossible to get.
  546. */
  547. function getSiteRoot() {
  548. // Check config
  549. if (isset($this->_config['preview.wwwroot']) && $this->_config['preview.wwwroot'])
  550. return $this->toUnixPath(realpath($this->_config['preview.wwwroot']));
  551. // Try script file
  552. if (isset($_SERVER["SCRIPT_NAME"]) && isset($_SERVER["SCRIPT_FILENAME"])) {
  553. $path = str_replace($this->toUnixPath($_SERVER["SCRIPT_NAME"]), "", $this->toUnixPath($_SERVER["SCRIPT_FILENAME"]));
  554. if (is_dir($path))
  555. return $this->toUnixPath(realpath($path));
  556. }
  557. // If all else fails, try this.
  558. if (isset($_SERVER["SCRIPT_NAME"]) && isset($_SERVER["PATH_TRANSLATED"])) {
  559. $path = str_replace($this->toUnixPath($_SERVER["SCRIPT_NAME"]), "", str_replace("//", "/", $this->toUnixPath($_SERVER["PATH_TRANSLATED"])));
  560. if (is_dir($path))
  561. return $this->toUnixPath(realpath($path));
  562. }
  563. // Check document root
  564. if (isset($_SERVER['DOCUMENT_ROOT']))
  565. return $this->toUnixPath(realpath($_SERVER['DOCUMENT_ROOT']));
  566. trigger_error("Could not resolve WWWROOT path, please set an absolute path in preview.wwwroot config option. Check the Wiki documentation for details.", FATAL);
  567. return null;
  568. }
  569. /**
  570. * Returns a absolute file system path of a absolute URI path for example /mydir/myfile.htm
  571. * will be resolved to /www/mywwwroot/mydir/myfile.htm.
  572. *
  573. * @param String $uri Absolute URI path for example /mydir/myfile.htm
  574. * @param String $root Option site root to use.
  575. * @return String Absolute file system path or empty string on failure.
  576. */
  577. function resolveURI($uri, $root = false) {
  578. // Use default root if not specified
  579. if (!$root)
  580. $root = $this->getSiteRoot();
  581. return realpath($root . $uri);
  582. }
  583. /**
  584. * Returns a site absolute path from a absolute file system path for example /www/mywwwroot/mydir/myfile.htm
  585. * will be converted to /mydir/myfile.htm.
  586. *
  587. * @param String $abs_path Absolute path for example /mydir/myfile.htm
  588. * @return String Site absolute path (URI) or empty string on failure.
  589. */
  590. function convertPathToURI($abs_path, $root = false) {
  591. $log =& $this->getLogger();
  592. // No root defined use specified root
  593. if (!$root)
  594. $root = $this->getSiteRoot();
  595. if (!$root) {
  596. trigger_error("Could not resolve WWWROOT path, please set an absolute path in preview.wwwroot config option.", FATAL);
  597. die();
  598. }
  599. if ($root == "/") {
  600. if ($log && $log->isDebugEnabled())
  601. $log->info("ConvertPathToURI: SiteRoot=" . $root . ", Path: " . $abs_path . " -> URI: " . $abs_path);
  602. return $abs_path;
  603. }
  604. $uri = substr($abs_path, strlen($root));
  605. if ($log && $log->isDebugEnabled())
  606. $log->info("ConvertPathToURI: SiteRoot=" . $root . ", Path: " . $abs_path . " -> URI: " . $uri);
  607. return $uri;
  608. }
  609. /**
  610. * Converts a URI such as /somedir/somefile.gif to /system/path/somedir/somefile.gif
  611. *
  612. * @param String $uri URI to convert to path.
  613. * @param String $root Optional site root to use.
  614. * @return String Path out of URI.
  615. */
  616. function convertURIToPath($uri, $root = false) {
  617. $log =& $this->getLogger();
  618. if (!$root)
  619. $root = $this->getSiteRoot();
  620. if ($log && $log->isDebugEnabled())
  621. $log->info("ConvertURIToPath: SiteRoot=" . $root . ", URI: " . $uri . " -> Path: " . $this->removeTrailingSlash($root) . $uri);
  622. return $this->removeTrailingSlash($root) . $uri;
  623. }
  624. /**
  625. * Converts an path into a visualy presentatble path. So that special folder names
  626. * gets translated and root paths gets replaced with their names.
  627. *
  628. * @param String $path Path to convert into a visual path.
  629. * @return String Visual path based on input path.
  630. */
  631. function toVisualPath($path, $root = false) {
  632. $fs = "file";
  633. // Parse out FS
  634. if (preg_match('/([a-z]+):\/\/(.+)/', $path, $matches)) {
  635. $fs = $matches[1];
  636. $path = $matches[2];
  637. }
  638. $path = $this->decryptPath($path);
  639. // Speficied root
  640. if ($root) {
  641. $pos = strpos($path, $root);
  642. if ($pos === 0)
  643. $path = substr($path, strlen($root));
  644. if ($path == "")
  645. $path = "/";
  646. // Re-attach fs
  647. if ($fs != "file")
  648. $path = $fs . "://" . $path;
  649. return $this->encryptPath($path);
  650. }
  651. // Use config roots
  652. $rootNames = $this->_getRootNames();
  653. foreach ($rootNames as $rootPath => $name) {
  654. $pos = strpos($path, $rootPath);
  655. if ($pos === 0) {
  656. $path = substr($path, strlen($rootPath));
  657. if ($name == "/")
  658. $name = "";
  659. $path = "/" . $name . $path;
  660. }
  661. }
  662. if (!$path)
  663. $path = "/";
  664. // Re-attach fs
  665. if ($fs != "file")
  666. $path = $fs . "://" . $path;
  667. return $this->encryptPath($path);
  668. }
  669. /**
  670. * Verifies that a path is within the parent path.
  671. *
  672. * @param String $parent_path Parent path that must contain the path.
  673. * @param String $path Path that must contained the parent path.
  674. * @return Bool true if it's valid, false if it's not.
  675. */
  676. function isChildPath($parent_path, $path) {
  677. return strpos(strtolower($path), strtolower($parent_path)) === 0;
  678. }
  679. /**
  680. * Checks if a specific tool is enabled or not.
  681. *
  682. * @param string $tool Tool to check for.
  683. * @param Array $config Name/Value config array to check tool against.
  684. * @return bool true/false if the tool is enabled or not.
  685. */
  686. function isToolEnabled($tool, $config = false) {
  687. if (!$config)
  688. $config = $this->getConfig();
  689. $ar = explode(',', $config['general.disabled_tools']);
  690. if (in_array($tool, $ar))
  691. return false;
  692. $ar = explode(',', $config['general.tools']);
  693. if (in_array($tool, $ar))
  694. return true;
  695. return false;
  696. }
  697. /**
  698. * Verifies that the specified path is within valid root paths.
  699. *
  700. * @param String $path Path to verify.
  701. * @return Bool true if the path is valid, false if it's invalid.
  702. */
  703. function verifyPath($path) {
  704. $fs = "file";
  705. $valid = false;
  706. // Parse out FS
  707. if (preg_match('/([a-z]+):\/\/(.+)/', $path, $matches)) {
  708. $fs = $matches[1];
  709. $path = $matches[2];
  710. }
  711. // Filesystem wasn't found
  712. if (!isset($this->_fileSystems[$fs])) {
  713. trigger_error($this->getLangItem("error", "no_filesystem", array("path" => $path)), FATAL);
  714. die();
  715. }
  716. $path = $this->decryptPath($path);
  717. // /../ is never valid
  718. if (indexOf($this->addTrailingSlash($path), "/../") != -1)
  719. return false;
  720. if ($fs != 'file')
  721. return true;
  722. foreach ($this->_rootPaths as $rootPath) {
  723. if ($this->isChildPath($rootPath, $path))
  724. $valid = true;
  725. }
  726. return $valid;
  727. }
  728. /**
  729. * Returns the file system for a path for file if it couldn't be extracted.
  730. *
  731. * @param string $path Path to get FS from.
  732. * @return string Filesystem for path.
  733. */
  734. function getFSFromPath($path) {
  735. $fs = "file";
  736. // Parse out FS
  737. if (preg_match('/([a-z]+):\/\/(.+)/', $path, $matches))
  738. $fs = $matches[1];
  739. return $fs;
  740. }
  741. /**
  742. * Verifies that the specified file is valid agains the filters specified in config.
  743. *
  744. * @param String $path Path to verify.
  745. * @param String $action Action to get config options by.
  746. * @param Array $config Name/Value array of config options.
  747. * @return int Reason why it was denied.
  748. */
  749. function verifyFile($file, $action = false, $config = false) {
  750. $config = $config ? $config : $file->getConfig();
  751. // Verify filesystem config
  752. $fileFilter = new Moxiecode_BasicFileFilter();
  753. $fileFilter->setIncludeDirectoryPattern($config['filesystem.include_directory_pattern']);
  754. $fileFilter->setExcludeDirectoryPattern($config['filesystem.exclude_directory_pattern']);
  755. $fileFilter->setIncludeFilePattern($config['filesystem.include_file_pattern']);
  756. $fileFilter->setExcludeFilePattern($config['filesystem.exclude_file_pattern']);
  757. $fileFilter->setIncludeExtensions($config['filesystem.extensions']);
  758. $this->_invalidFileMsg = "{#error.invalid_filename}";
  759. $status = $fileFilter->accept($file);
  760. if ($status != BASIC_FILEFILTER_ACCEPTED) {
  761. if ($status == BASIC_FILEFILTER_INVALID_NAME) {
  762. if ($file->isFile() && isset($config['filesystem.invalid_file_name_msg']))
  763. $this->_invalidFileMsg = $config['filesystem.invalid_file_name_msg'];
  764. else if (!$file->isFile() && isset($config['filesystem.invalid_directory_name_msg']))
  765. $this->_invalidFileMsg = $config['filesystem.invalid_directory_name_msg'];
  766. if (!$this->_invalidFileMsg)
  767. $this->_invalidFileMsg = "{#error.invalid_filename}";
  768. }
  769. return $status;
  770. }
  771. // Verify action specific config
  772. $fileFilter = new Moxiecode_BasicFileFilter();
  773. if ($action) {
  774. if (isset($config[$action . '.include_directory_pattern']))
  775. $fileFilter->setIncludeDirectoryPattern($config[$action . '.include_directory_pattern']);
  776. if (isset($config[$action . '.exclude_directory_pattern']))
  777. $fileFilter->setExcludeDirectoryPattern($config[$action . '.exclude_directory_pattern']);
  778. if (isset($config[$action . '.include_file_pattern']))
  779. $fileFilter->setIncludeFilePattern($config[$action . '.include_file_pattern']);
  780. if (isset($config[$action . '.exclude_file_pattern']))
  781. $fileFilter->setExcludeFilePattern($config[$action . '.exclude_file_pattern']);
  782. if (isset($config[$action . '.extensions']))
  783. $fileFilter->setIncludeExtensions($config[$action . '.extensions']);
  784. } else
  785. return BASIC_FILEFILTER_ACCEPTED;
  786. $status = $fileFilter->accept($file);
  787. if ($status != BASIC_FILEFILTER_ACCEPTED) {
  788. if ($status == BASIC_FILEFILTER_INVALID_NAME) {
  789. $this->_invalidFileMsg = "{#error.invalid_filename}";
  790. if ($file->isFile()) {
  791. if (isset($config[$action . '.invalid_file_name_msg']))
  792. $this->_invalidFileMsg = $config[$action . '.invalid_file_name_msg'];
  793. } else {
  794. if (isset($config[$action . '.invalid_directory_name_msg']))
  795. $this->_invalidFileMsg = $config[$action . '.invalid_directory_name_msg'];
  796. }
  797. }
  798. return $status;
  799. }
  800. return BASIC_FILEFILTER_ACCEPTED;
  801. }
  802. /**
  803. * Returns a file object represtentation of a file path this
  804. * will also do security checks agains the list of valid paths
  805. * so that file IO can't be done outside the valid paths.
  806. *
  807. * @param String $path Path to return as File object.
  808. * @param String $file_name Optional file name.
  809. * @param String $type Optional file type.
  810. * @return File File object representation of a file.
  811. */
  812. function &getFile($path, $file_name = "", $type = MC_IS_FILE) {
  813. $path = utf8_decode($path);
  814. $file_name = utf8_decode($file_name);
  815. $fs = 'file';
  816. $matches = array();
  817. $oldpath = $path;
  818. // Parse out FS
  819. if (preg_match('/([a-z]+):\/\/(.+)/', $path, $matches)) {
  820. $fs = $matches[1];
  821. $path = $matches[2];
  822. }
  823. // Filesystem wasn't found
  824. if (!isset($this->_fileSystems[$fs])) {
  825. trigger_error($this->getLangItem("error", "no_filesystem", array("path" => $path)), FATAL);
  826. die();
  827. }
  828. $path = $this->decryptPath($path);
  829. $path = $this->removeTrailingSlash($this->toUnixPath($path));
  830. // Verfiy path if no file was returned
  831. if ($fs == 'file' && !$this->verifyPath($path)) {
  832. $log =& $this->getLogger();
  833. if ($log && $log->isDebugEnabled())
  834. $log->debug("Could not access path: " . $path);
  835. trigger_error("{#error.no_access}", FATAL);
  836. die();
  837. }
  838. // Validate file name
  839. if ($fs == 'file' && $file_name) {
  840. if (preg_match('/[\\\\\\/:]+/', $file_name, $matches)) {
  841. $log =& $this->getLogger();
  842. if ($log && $log->isDebugEnabled())
  843. $log->debug("Could not access path: " . $path);
  844. trigger_error("{#error.no_access}", FATAL);
  845. die();
  846. }
  847. }
  848. // Get file instance
  849. $file = new $this->_fileSystems[$fs]($this, $path, $file_name, $type);
  850. // Verfiy path if no file was returned
  851. if ($fs == 'file' && !$this->verifyPath($file->getAbsolutePath())) {
  852. $log =& $this->getLogger();
  853. if ($log && $log->isDebugEnabled())
  854. $log->debug("Could not access path: " . $path);
  855. trigger_error("{#error.no_access}", FATAL);
  856. die();
  857. }
  858. return $file;
  859. }
  860. /**
  861. * Converts a relative path to absolute path.
  862. *
  863. * @param string $path Path to convert to absolute.
  864. * @param string $basepath Optional base path default to ../.
  865. */
  866. function toAbsPath($path, $basepath = false) {
  867. $path = $this->toUnixPath($path);
  868. if (!$basepath)
  869. $basepath = dirname(__FILE__) . "/../";
  870. // Is absolute unix or windows
  871. if (substr($path, 0, 1) == '/' || strpos($path, ":") !== false) {
  872. // Resolve symlinks
  873. $tmp = realpath($path);
  874. if ($tmp)
  875. $path = $tmp;
  876. return $this->toUnixPath($path);
  877. }
  878. $path = $this->toUnixPath($this->addTrailingSlash($this->toUnixPath(realpath($basepath))) . $path);
  879. // Local FS and exists remove any ../../
  880. if (strpos($path, "://") === false && file_exists($path))
  881. $path = $this->toUnixPath(realpath($path));
  882. return $path;
  883. }
  884. /**
  885. * Converts a Unix path to OS specific path.
  886. *
  887. * @param String $path Unix path to convert.
  888. */
  889. function toOSPath($path) {
  890. return str_replace("/", DIRECTORY_SEPARATOR, $path);
  891. }
  892. /**
  893. * Converts a OS specific path to Unix path.
  894. *
  895. * @param String $path OS path to convert to Unix style.
  896. */
  897. function toUnixPath($path) {
  898. return str_replace(DIRECTORY_SEPARATOR, "/", $path);
  899. }
  900. /**
  901. * Adds a trailing slash to a path.
  902. *
  903. * @param String path Path to add trailing slash on.
  904. * @return String New path with trailing slash.
  905. */
  906. function addTrailingSlash($path) {
  907. if (strlen($path) > 0 && $path[strlen($path)-1] != '/')
  908. $path .= '/';
  909. return $path;
  910. }
  911. /**
  912. * Removes the trailing slash from a path.
  913. *
  914. * @param String path Path to remove trailing slash from.
  915. * @return String New path without trailing slash.
  916. */
  917. function removeTrailingSlash($path) {
  918. // Is root
  919. if ($path == "/")
  920. return $path;
  921. if ($path == "")
  922. return $path;
  923. if ($path[strlen($path)-1] == '/')
  924. $path = substr($path, 0, strlen($path)-1);
  925. return $path;
  926. }
  927. /**
  928. * Adds a new file system bu name.
  929. *
  930. * @param String $protocol File protocol like zip/ftp etc.
  931. * @param String $file_system Name of class to create instances by.
  932. */
  933. function registerFileSystem($protocol, $file_system) {
  934. $this->_fileSystems[$protocol] = $file_system;
  935. }
  936. /**
  937. * Returns a logger instance.
  938. *
  939. * @return Logger New logger instance.
  940. */
  941. function &getLogger() {
  942. if (!$this->_logger) {
  943. $log = new Moxiecode_Logger();
  944. $null = null; // PHP why!!! Other languages can return null
  945. if (!checkBool($this->getConfigItem("log.enabled")))
  946. return $null;
  947. // Set logger options
  948. $log->setLevel($this->getConfigItem("log.level", "fatal"));
  949. $log->setPath($this->toAbsPath($this->getConfigItem("log.path", "logs")));
  950. $log->setFileName($this->getConfigItem("log.filename", "{level}.log"));
  951. $log->setFormat($this->getConfigItem("log.format", "[{time}] [{level}] {message}"));
  952. $log->setMaxSize($this->getConfigItem("log.max_size", "100k"));
  953. $log->setMaxFiles($this->getConfigItem("log.max_files", "10"));
  954. $this->_logger = $log;
  955. }
  956. return $this->_logger;
  957. }
  958. // * * * * * * * Private methods
  959. function _getRootNames() {
  960. $config = $this->getConfig();
  961. $output = array();
  962. $roots = explode(';', $config['filesystem.rootpath']);
  963. foreach ($roots as $root) {
  964. $rootParts = explode('=', $root);
  965. if (count($rootParts) > 1)
  966. $output[$rootParts[1]] = $rootParts[0];
  967. else {
  968. $output[$rootParts[0]] = basename($root);
  969. // If it's root
  970. if ($output[$rootParts[0]] == "")
  971. $output[$rootParts[0]] = "/";
  972. }
  973. }
  974. return $output;
  975. }
  976. /**#@-*/
  977. }
  978. ?>