PageRenderTime 58ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/www/assets/tiny_mce/plugins/imagemanager/classes/ManagerEngine.php

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