PageRenderTime 67ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/e107_handlers/e107_class.php

https://github.com/CasperGemini/e107
PHP | 3742 lines | 1991 code | 446 blank | 1305 comment | 316 complexity | a517ec26db31667465c4b0d116aef157 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. /*
  3. * e107 website system
  4. *
  5. * Copyright (C) 2008-2012 e107 Inc (e107.org)
  6. * Released under the terms and conditions of the
  7. * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
  8. *
  9. * e107 Main
  10. *
  11. * $URL$
  12. * $Id$
  13. */
  14. if (!defined('e107_INIT')) { exit; }
  15. /**
  16. *
  17. * @package e107
  18. * @category e107_handlers
  19. * @version $Id$
  20. * @author e107inc
  21. *
  22. * e107_class - core class with many system-related methods
  23. */
  24. class e107
  25. {
  26. /**
  27. * IPV6 string for localhost - as stored in DB
  28. */
  29. const LOCALHOST_IP = '0000:0000:0000:0000:0000:ffff:7f00:0001';
  30. public $server_path;
  31. public $e107_dirs = array();
  32. /**
  33. * @var array SQL connection data
  34. */
  35. protected $e107_config_mysql_info = array();
  36. public $http_path;
  37. public $https_path;
  38. public $base_path;
  39. public $file_path;
  40. public $site_path;
  41. public $relative_base_path;
  42. public $_ip_cache;
  43. public $_host_name_cache;
  44. public $site_theme; // class2 -> check valid theme
  45. public $http_theme_dir; // class2 -> check valid theme
  46. /**
  47. * Contains reference to global $_E107 array
  48. * Assignment is done inside prepare_request() method
  49. *
  50. * @var array
  51. */
  52. protected $_E107 = array();
  53. /**
  54. * @var string Current request type (http or https)
  55. */
  56. protected $HTTP_SCHEME;
  57. /**
  58. * Used for runtime caching of user extended struct
  59. *
  60. * @var array
  61. * @see get_user_data()
  62. */
  63. public $extended_struct;
  64. /**
  65. * User login name
  66. *
  67. * @var string
  68. * @see init_session()
  69. */
  70. public $currentUser = '';
  71. /**
  72. * Run once load core shortcodes
  73. * while initialize SC parser
  74. *
  75. * @var boolean
  76. */
  77. protected static $_sc_core_loaded = false;
  78. /**
  79. * Singleton instance
  80. * Allow class extends - override {@link getInstance()}
  81. *
  82. * @var e107
  83. */
  84. protected static $_instance = null;
  85. /**
  86. * e107 registry
  87. *
  88. * @var array
  89. */
  90. private static $_registry = array();
  91. /**
  92. * e107 core config object storage
  93. *
  94. * @var array
  95. */
  96. protected static $_core_config_arr = array();
  97. /**
  98. * e107 plugin config object storage
  99. *
  100. * @var array
  101. */
  102. protected static $_plug_config_arr = array();
  103. /**
  104. * Core handlers array
  105. * For new/missing handler add
  106. * 'class name' => 'path' pair
  107. *
  108. * Used to auto-load core/plugin handlers
  109. * NOTE: aplhabetically sorted! (by class name)
  110. *
  111. * @see addHandler()
  112. * @see setHandlerOverload()
  113. * @see getSingleton()
  114. * @see getObject()
  115. * @var array
  116. */
  117. protected static $_known_handlers = array(
  118. 'UserHandler' => '{e_HANDLER}user_handler.php',
  119. 'comment' => '{e_HANDLER}comment_class.php',
  120. 'convert' => '{e_HANDLER}date_handler.php',
  121. 'db' => '{e_HANDLER}mysql_class.php',
  122. 'e107Email' => '{e_HANDLER}mail.php',
  123. 'e107_event' => '{e_HANDLER}event_class.php',
  124. 'e107_db_debug' => '{e_HANDLER}db_debug_class.php',
  125. 'e107_traffic' => '{e_HANDLER}traffic_class.php',
  126. 'e107_user_extended' => '{e_HANDLER}user_extended_class.php',
  127. 'e107plugin' => '{e_HANDLER}plugin_class.php',
  128. 'e_chart' => '{e_HANDLER}chart_class.php',
  129. 'e_core_session' => '{e_HANDLER}session_handler.php',
  130. 'e_admin_controller' => '{e_HANDLER}admin_ui.php',
  131. 'e_admin_controller_ui' => '{e_HANDLER}admin_ui.php',
  132. 'e_admin_dispatcher' => '{e_HANDLER}admin_ui.php',
  133. 'e_admin_form_ui' => '{e_HANDLER}admin_ui.php',
  134. 'e_admin_log' => '{e_HANDLER}admin_log_class.php',
  135. 'e_admin_model' => '{e_HANDLER}model_class.php',
  136. 'e_admin_request' => '{e_HANDLER}admin_ui.php',
  137. 'e_admin_response' => '{e_HANDLER}admin_ui.php',
  138. 'e_admin_ui' => '{e_HANDLER}admin_ui.php',
  139. 'e_array' => '{e_HANDLER}core_functions.php', // Old ArrayStorage.
  140. 'e_bbcode' => '{e_HANDLER}bbcode_handler.php',
  141. 'e_bb_base' => '{e_HANDLER}bbcode_handler.php',
  142. 'e_file' => '{e_HANDLER}file_class.php',
  143. 'e_form' => '{e_HANDLER}form_handler.php',
  144. 'e_jshelper' => '{e_HANDLER}js_helper.php',
  145. 'e_media' => '{e_HANDLER}media_class.php',
  146. 'e_menu' => '{e_HANDLER}menu_class.php',
  147. 'e_model' => '{e_HANDLER}model_class.php',
  148. 'e_navigation' => '{e_HANDLER}sitelinks_class.php',
  149. 'e_news_item' => '{e_HANDLER}news_class.php',
  150. 'e_news_tree' => '{e_HANDLER}news_class.php',
  151. 'e_object' => '{e_HANDLER}model_class.php',
  152. 'e_online' => '{e_HANDLER}online_class.php',
  153. 'e_parse' => '{e_HANDLER}e_parse_class.php',
  154. 'e_parser' => '{e_HANDLER}e_parse_class.php',
  155. 'e_parse_shortcode' => '{e_HANDLER}shortcode_handler.php',
  156. 'e_ranks' => '{e_HANDLER}e_ranks_class.php',
  157. 'e_shortcode' => '{e_HANDLER}shortcode_handler.php',
  158. 'e_system_user' => '{e_HANDLER}user_model.php',
  159. 'e_upgrade' => '{e_HANDLER}e_upgrade_class.php',
  160. 'e_user_model' => '{e_HANDLER}user_model.php',
  161. 'e_user' => '{e_HANDLER}user_model.php',
  162. 'e_user_extended_structure_tree' => '{e_HANDLER}user_model.php',
  163. 'e_userperms' => '{e_HANDLER}user_handler.php',
  164. 'e_validator' => '{e_HANDLER}validator_class.php',
  165. 'e_vars' => '{e_HANDLER}model_class.php',
  166. 'ecache' => '{e_HANDLER}cache_handler.php',
  167. 'eController' => '{e_HANDLER}application.php',
  168. 'eDispatcher' => '{e_HANDLER}application.php',
  169. 'eException' => '{e_HANDLER}application.php',
  170. 'eFront' => '{e_HANDLER}application.php',
  171. 'eHelper' => '{e_HANDLER}application.php',
  172. 'eIPHandler' => '{e_HANDLER}iphandler_class.php',
  173. 'email_validation_class' => '{e_HANDLER}mail_validation_class.php',
  174. 'eMessage' => '{e_HANDLER}message_handler.php',
  175. 'eRequest' => '{e_HANDLER}application.php',
  176. 'eResponse' => '{e_HANDLER}application.php',
  177. 'eRouter' => '{e_HANDLER}application.php',
  178. 'eUrl' => '{e_HANDLER}e107Url.php',
  179. 'eUrlConfig' => '{e_HANDLER}application.php',
  180. 'eUrlRule' => '{e_HANDLER}application.php',
  181. 'Hybrid_Auth' => '{e_HANDLER}hybridauth/Hybrid/Auth.php',
  182. 'language' => '{e_HANDLER}language_class.php',
  183. 'news' => '{e_HANDLER}news_class.php',
  184. 'notify' => '{e_HANDLER}notify_class.php',
  185. 'override' => '{e_HANDLER}override_class.php',
  186. 'rater' => '{e_HANDLER}rate_class.php',
  187. 'redirection' => '{e_HANDLER}redirection_class.php',
  188. 'secure_image' => '{e_HANDLER}secure_img_handler.php',
  189. 'sitelinks' => '{e_HANDLER}sitelinks_class.php',
  190. 'themeHandler' => '{e_HANDLER}theme_handler.php',
  191. 'user_class' => '{e_HANDLER}userclass_class.php',
  192. 'userlogin' => '{e_HANDLER}login.php',
  193. 'validatorClass' => '{e_HANDLER}validator_class.php',
  194. 'xmlClass' => '{e_HANDLER}xml_class.php',
  195. );
  196. /**
  197. * Overload core handlers array
  198. * Format: 'core_class' => array('overload_class', 'overload_path');
  199. *
  200. * NOTE: to overload core singleton objects, you have to add record to
  201. * $_overload_handlers before the first singleton call.
  202. *
  203. * Example:
  204. * <code> array('e_form' => array('plugin_myplugin_form_handler' => '{e_PLUGIN}myplugin/includes/form/handler.php'));</code>
  205. *
  206. * Used to auto-load core handlers
  207. *
  208. * @var array
  209. */
  210. protected static $_overload_handlers = array();
  211. /**
  212. * Constructor
  213. *
  214. * Use {@link getInstance()}, direct instantiating
  215. * is not possible for singleton objects
  216. *
  217. * @return void
  218. */
  219. protected function __construct()
  220. {
  221. // FIXME registered shutdown functions not executed after the $page output in footer - investigate
  222. // Currently manually called in front-end/admin footer
  223. //register_shutdown_function(array($this, 'destruct'));
  224. }
  225. /**
  226. * Cloning is not allowed
  227. *
  228. */
  229. private function __clone()
  230. {
  231. }
  232. /**
  233. * Get singleton instance (php4 no more supported)
  234. *
  235. * @return e107
  236. */
  237. public static function getInstance()
  238. {
  239. if(null == self::$_instance)
  240. {
  241. self::$_instance = new self();
  242. }
  243. return self::$_instance;
  244. }
  245. /**
  246. * Initialize environment path constants
  247. * Public proxy to the protected method {@link _init()}
  248. *
  249. * @return e107
  250. */
  251. public function initCore($e107_paths, $e107_root_path, $e107_config_mysql_info, $e107_config_override = array())
  252. {
  253. return $this->_init($e107_paths, $e107_root_path, $e107_config_mysql_info, $e107_config_override);
  254. }
  255. /**
  256. * Initialize environment path constants while installing e107
  257. *
  258. * @return e107
  259. */
  260. public function initInstall($e107_paths, $e107_root_path, $e107_config_override = array())
  261. {
  262. $e107_config = 'e107_config.php';
  263. if (!file_exists($e107_config)) // prevent blank-page with missing file during install.
  264. {
  265. if(file_put_contents($e107_config, '')===false)
  266. {
  267. return false;
  268. }
  269. }
  270. // Do some security checks/cleanup, prepare the environment
  271. $this->prepare_request();
  272. //generated from mysql data at stage 5 of install.
  273. $this->site_path = isset($e107_config_override['site_path']) ? $e107_config_override['site_path'] : "[hash]"; // placeholder
  274. // folder info
  275. //$this->e107_dirs = $e107_paths;
  276. $this->setDirs($e107_paths, $e107_config_override);
  277. // build all paths
  278. $this->set_paths();
  279. $this->file_path = $this->fix_windows_paths($e107_root_path)."/";
  280. // set base path, SSL is auto-detected
  281. $this->set_base_path();
  282. // cleanup QUERY_STRING and friends, set related constants
  283. $this->set_request();
  284. // set some core URLs (e_LOGIN/SIGNUP)
  285. $this->set_urls();
  286. return $this;
  287. }
  288. /**
  289. * Resolve paths, will run only once
  290. *
  291. * @return e107
  292. */
  293. protected function _init($e107_paths, $e107_root_path, $e107_config_mysql_info, $e107_config_override = array())
  294. {
  295. if(empty($this->e107_dirs))
  296. {
  297. // Do some security checks/cleanup, prepare the environment
  298. $this->prepare_request();
  299. // mysql connection info
  300. $this->e107_config_mysql_info = $e107_config_mysql_info;
  301. // unique folder for e_MEDIA - support for multiple websites from single-install. Must be set before setDirs()
  302. $this->site_path = $this->makeSiteHash($e107_config_mysql_info['mySQLdefaultdb'], $e107_config_mysql_info['mySQLprefix']);
  303. // Set default folder (and override paths) if missing from e107_config.php
  304. $this->setDirs($e107_paths, $e107_config_override);
  305. // various constants - MAGIC_QUOTES_GPC, MPREFIX, ...
  306. $this->set_constants();
  307. // build all paths
  308. $this->set_paths();
  309. $this->file_path = $this->fix_windows_paths($e107_root_path)."/";
  310. // set base path, SSL is auto-detected
  311. $this->set_base_path();
  312. // cleanup QUERY_STRING and friends, set related constants
  313. $this->set_request();
  314. // set some core URLs (e_LOGIN/SIGNUP)
  315. $this->set_urls();
  316. }
  317. return $this;
  318. }
  319. // Create a unique hash for each database configuration (multi-site support)
  320. function makeSiteHash($db,$prefix) // also used by install.
  321. {
  322. return substr(md5($db.".".$prefix),0,10);
  323. }
  324. /**
  325. * Set system folders and override paths
  326. * $e107_paths is the 'compact' version of e107_config folder vars ($ADMIN_DIRECTORY, $IMAGES_DIRECTORY, etc)
  327. * $e107_config_override is the new override method - it can do it for all server and http paths via
  328. * the newly introduced $E107_CONFIG array.
  329. *
  330. * Overriding just replace _DIRECTORY with _SERVER or _HTTP:
  331. * - override server path example:
  332. * <code>$E107_CONFIG['SYSTEM_SERVER'] = '/home/user/system/';</code>
  333. *
  334. * - override http path example:
  335. * <code>$E107_CONFIG['MEDIA_VIDEOS_HTTP'] = 'http://static.mydomain.com/videos/';</code>
  336. *
  337. * @param array $e107_dirs Override folder instructions (*_DIRECTORY vars - e107_config.php)
  338. * @param array $e107_config_override Override path insructions ($E107_CONFIG array - e107_config.php)
  339. * @return e107
  340. */
  341. public function setDirs($e107_dirs, $e107_config_override = array())
  342. {
  343. $override = array_merge((array) $e107_dirs, (array) $e107_config_override);
  344. // override all
  345. $this->e107_dirs = array_merge($this->defaultDirs($override), $override);
  346. // TODO add e_MEDIA_BASE, e_SYSTEM_BASE (free of site path constants);
  347. if(strpos($this->e107_dirs['MEDIA_DIRECTORY'],$this->site_path) === false)
  348. {
  349. $this->e107_dirs['MEDIA_DIRECTORY'] .= $this->site_path."/"; // multisite support.
  350. }
  351. if(strpos($this->e107_dirs['SYSTEM_DIRECTORY'],$this->site_path) === false)
  352. {
  353. $this->e107_dirs['SYSTEM_DIRECTORY'] .= $this->site_path."/"; // multisite support.
  354. }
  355. // FIXME Quick fix - override base cache folder for legacy configs (e.g. e107_files/cache), discuss
  356. if(strpos($this->e107_dirs['CACHE_DIRECTORY'], $this->site_path) === false)
  357. {
  358. $this->e107_dirs['CACHE_DIRECTORY'] = $this->e107_dirs['SYSTEM_DIRECTORY']."cache/"; // multisite support.
  359. }
  360. return $this;
  361. }
  362. /**
  363. * Get default e107 folders, root folders can be overridden by passed override array
  364. *
  365. * @param array $override_root
  366. * @param boolean $return_root
  367. * @return array
  368. */
  369. public function defaultDirs($override_root = array(), $return_root = false)
  370. {
  371. $ret = array_merge(array(
  372. 'ADMIN_DIRECTORY' => 'e107_admin/',
  373. 'IMAGES_DIRECTORY' => 'e107_images/',
  374. 'THEMES_DIRECTORY' => 'e107_themes/',
  375. 'PLUGINS_DIRECTORY' => 'e107_plugins/',
  376. 'FILES_DIRECTORY' => 'e107_files/', // DEPRECATED!!!
  377. 'HANDLERS_DIRECTORY' => 'e107_handlers/',
  378. 'LANGUAGES_DIRECTORY' => 'e107_languages/',
  379. 'DOCS_DIRECTORY' => 'e107_docs/',
  380. 'MEDIA_DIRECTORY' => 'e107_media/',
  381. 'SYSTEM_DIRECTORY' => 'e107_system/',
  382. 'CORE_DIRECTORY' => 'e107_core/',
  383. 'WEB_DIRECTORY' => 'e107_web/',
  384. ), (array) $override_root);
  385. $ret['MEDIA_DIRECTORY'] .= $this->site_path."/"; // multisite support.
  386. $ret['SYSTEM_DIRECTORY'] .= $this->site_path."/"; // multisite support.
  387. if($return_root) return $ret;
  388. $ret['HELP_DIRECTORY'] = $ret['DOCS_DIRECTORY'].'help/';
  389. $ret['MEDIA_IMAGES_DIRECTORY'] = $ret['MEDIA_DIRECTORY'].'images/';
  390. $ret['MEDIA_ICONS_DIRECTORY'] = $ret['MEDIA_DIRECTORY'].'icons/';
  391. $ret['MEDIA_VIDEOS_DIRECTORY'] = $ret['MEDIA_DIRECTORY'].'videos/';
  392. $ret['MEDIA_FILES_DIRECTORY'] = $ret['MEDIA_DIRECTORY'].'files/';
  393. $ret['MEDIA_UPLOAD_DIRECTORY'] = $ret['SYSTEM_DIRECTORY'].'temp/'; // security measure. Media is public, system is private.
  394. $ret['AVATARS_DIRECTORY'] = $ret['MEDIA_DIRECTORY'].'avatars/';
  395. $ret['WEB_JS_DIRECTORY'] = $ret['WEB_DIRECTORY'].'js/';
  396. // $ret['WEB_JS_DIRECTORY'] = $ret['FILES_DIRECTORY'].'jslib/';
  397. $ret['WEB_CSS_DIRECTORY'] = $ret['WEB_DIRECTORY'].'css/';
  398. $ret['WEB_IMAGES_DIRECTORY'] = $ret['WEB_DIRECTORY'].'images/';
  399. // $ret['WEB_PACKS_DIRECTORY'] = $ret['WEB_DIRECTORY'].'packages/';
  400. $ret['DOWNLOADS_DIRECTORY'] = $ret['MEDIA_FILES_DIRECTORY'];
  401. $ret['UPLOADS_DIRECTORY'] = $ret['MEDIA_UPLOAD_DIRECTORY'];
  402. $ret['CACHE_DIRECTORY'] = $ret['SYSTEM_DIRECTORY'].'cache/';
  403. $ret['CACHE_CONTENT_DIRECTORY'] = $ret['CACHE_DIRECTORY'].'content/';
  404. $ret['CACHE_IMAGE_DIRECTORY'] = $ret['CACHE_DIRECTORY'].'images/';
  405. $ret['CACHE_DB_DIRECTORY'] = $ret['CACHE_DIRECTORY'].'db/';
  406. $ret['CACHE_URL_DIRECTORY'] = $ret['CACHE_DIRECTORY'].'url/';
  407. $ret['AVATARS_UPLOAD_DIRECTORY'] = $ret['AVATARS_DIRECTORY'].'upload/';
  408. $ret['AVATARS_DEFAULT_DIRECTORY'] = $ret['AVATARS_DIRECTORY'].'default/';
  409. $ret['LOGS_DIRECTORY'] = $ret['SYSTEM_DIRECTORY'].'logs/';
  410. $ret['BACKUP_DIRECTORY'] = $ret['SYSTEM_DIRECTORY'].'backup/';
  411. $ret['TEMP_DIRECTORY'] = $ret['SYSTEM_DIRECTORY'].'temp/';
  412. $ret['IMPORT_DIRECTORY'] = $ret['SYSTEM_DIRECTORY'].'import/';
  413. //TODO create directories which don't exist.
  414. return $ret;
  415. }
  416. /**
  417. * Set mysql data
  418. *
  419. * @return e107
  420. */
  421. public function initInstallSql($e107_config_mysql_info)
  422. {
  423. // mysql connection info
  424. $this->e107_config_mysql_info = $e107_config_mysql_info;
  425. // various constants - MAGIC_QUOTES_GPC, MPREFIX, ...
  426. $this->set_constants();
  427. return $this;
  428. }
  429. /**
  430. * Get data from the registry
  431. * Returns $default if data not found
  432. * Replacement of cachevar()
  433. *
  434. * @param string $id
  435. * @return mixed
  436. */
  437. public static function getRegistry($id, $default = null)
  438. {
  439. if(isset(self::$_registry[$id]))
  440. {
  441. return self::$_registry[$id];
  442. }
  443. return $default;
  444. }
  445. /**
  446. * Add data to the registry - replacement of getcachedvars().
  447. * $id is path-like unique id bind to the passed data.
  448. * If $data argument is null, $id will be removed from the registry.
  449. * When removing objects from the registry, __destruct() method will be auto-executed
  450. * if available
  451. *
  452. * Naming standards (namespaces):
  453. * 'area/area_id/storage_type'<br>
  454. * where <br>
  455. * - area = 'core'|'plugin'|'external' (everything else)
  456. * - area_id = core handler id|plugin name (depends on area)
  457. * - (optional) storage_type = current data storage stack
  458. *
  459. * Examples:
  460. * - 'core/e107/' - reserved for this class
  461. * - 'core/e107/singleton/' - singleton objects repo {@link getSingleton()}
  462. *
  463. * @param string $id
  464. * @param mixed|null $data
  465. * @return void
  466. */
  467. public static function setRegistry($id, $data = null, $allow_override = true)
  468. {
  469. if(null === $data)
  470. {
  471. if(is_object(self::$_registry[$id]) && method_exists(self::$_registry[$id], '__destruct'))
  472. {
  473. self::$_registry[$id]->__destruct();
  474. }
  475. unset(self::$_registry[$id]);
  476. return;
  477. }
  478. if(!$allow_override && null !== self::getRegistry($id))
  479. {
  480. return;
  481. }
  482. self::$_registry[$id] = $data;
  483. }
  484. /**
  485. * Get folder name (e107_config)
  486. * Replaces all $(*)_DIRECTORY globals
  487. * Example: <code>$e107->getFolder('images')</code>;
  488. *
  489. * @param string $for
  490. * @return string
  491. */
  492. function getFolder($for)
  493. {
  494. $key = strtoupper($for).'_DIRECTORY';
  495. $self = self::getInstance();
  496. return (isset($self->e107_dirs[$key]) ? $self->e107_dirs[$key] : '');
  497. }
  498. /**
  499. * Get value from $_E107 config array
  500. * Note: will always return false if called before prepare_request() method!
  501. *
  502. * @param string $key
  503. * @return boolean
  504. */
  505. public static function getE107($key = null)
  506. {
  507. $self = self::getInstance();
  508. if(null === $key) return $self->_E107;
  509. return (isset($self->_E107[$key]) && $self->_E107[$key] ? true : false);
  510. }
  511. /**
  512. * Convenient proxy to $_E107 getter - check if
  513. * the system is currently running in cli mode
  514. * Note: will always return false if called before prepare_request() method!
  515. *
  516. * @return boolean
  517. */
  518. public static function isCli()
  519. {
  520. return self::getE107('cli');
  521. }
  522. /**
  523. * Get mysql config var (e107_config.php)
  524. * Replaces all $mySQL(*) globals
  525. * Example: <code>$e107->getMySQLConfig('prefix');</code>
  526. *
  527. * @param string $for prefix|server|user|password|defaultdb - leave blank for full array.
  528. * @return string or array
  529. */
  530. function getMySQLConfig($for='')
  531. {
  532. $key = 'mySQL'.$for;
  533. $self = self::getInstance();
  534. if($for == '')
  535. {
  536. return $self->e107_config_mysql_info;
  537. }
  538. return (isset($self->e107_config_mysql_info[$key]) ? $self->e107_config_mysql_info[$key] : '');
  539. }
  540. /**
  541. * Return a unique path based on database used. ie. multi-site support from single install.
  542. *
  543. * @return string
  544. * @author
  545. */
  546. function getSitePath()
  547. {
  548. $self = self::getInstance();
  549. return $self->site_path;
  550. }
  551. /**
  552. * Get known handler path
  553. *
  554. * @param string $class_name
  555. * @param boolean $parse_path [optional] parse path shortcodes
  556. * @return string|null
  557. */
  558. public static function getHandlerPath($class_name, $parse_path = true)
  559. {
  560. $ret = isset(self::$_known_handlers[$class_name]) ? self::$_known_handlers[$class_name] : null;
  561. if($parse_path && $ret)
  562. {
  563. $ret = self::getParser()->replaceConstants($ret);
  564. }
  565. return $ret;
  566. }
  567. /**
  568. * Add handler to $_known_handlers array on runtime
  569. * If class name is array, method will add it (recursion) and ignore $path argument
  570. *
  571. * @param array|string $class_name
  572. * @param string $path [optional]
  573. * @return void
  574. */
  575. public static function addHandler($class_name, $path = '')
  576. {
  577. if(is_array($class_name))
  578. {
  579. foreach ($class_name as $cname => $path)
  580. {
  581. self::addHandler($cname, $path);
  582. }
  583. return;
  584. }
  585. if(!self::isHandler($class_name))
  586. {
  587. self::$_known_handlers[$class_name] = $path;
  588. }
  589. }
  590. /**
  591. * Check handler presence
  592. *
  593. * @param string $class_name
  594. * @return boolean
  595. */
  596. public static function isHandler($class_name)
  597. {
  598. return isset(self::$_known_handlers[$class_name]);
  599. }
  600. /**
  601. * Get overlod class and path (if any)
  602. *
  603. * @param object $class_name
  604. * @param object $default_handler [optional] return data from $_known_handlers if no overload data available
  605. * @param object $parse_path [optional] parse path shortcodes
  606. * @return array
  607. */
  608. public static function getHandlerOverload($class_name, $default_handler = true, $parse_path = true)
  609. {
  610. $ret = (isset(self::$_overload_handlers[$class_name]) ? self::$_overload_handlers[$class_name] : ($default_handler ? array($class_name, self::getHandlerPath($class_name, false)) : array()));
  611. if ($parse_path && isset($ret[1]))
  612. {
  613. $ret[1] = self::getParser()->replaceConstants($ret[1]);
  614. }
  615. return $ret;
  616. }
  617. /**
  618. * Overload present handler.
  619. * If class name is array, method will add it (recursion) and
  620. * ignore $overload_class_name and $overload_path arguments
  621. *
  622. * @param string $class_name
  623. * @param string $overload_name [optional]
  624. * @param string $overload_path [optional]
  625. * @return void
  626. */
  627. public static function setHandlerOverload($class_name, $overload_class_name = '', $overload_path = '')
  628. {
  629. if(is_array($class_name))
  630. {
  631. foreach ($class_name as $cname => $overload_array)
  632. {
  633. self::setHandlerOverload($cname, $overload_array[0], $overload_array[1]);
  634. }
  635. return;
  636. }
  637. if(self::isHandler($class_name) && !self::isHandlerOverloadable($class_name))
  638. {
  639. self::$_overload_handlers[$class_name] = array($overload_class_name, $overload_path);
  640. }
  641. }
  642. /**
  643. * Check if handler is already overloaded
  644. *
  645. * @param string $class_name
  646. * @return boolean
  647. */
  648. public static function isHandlerOverloadable($class_name)
  649. {
  650. return isset(self::$_overload_handlers[$class_name]);
  651. }
  652. /**
  653. * Retrieve singleton object
  654. *
  655. * @param string $class_name
  656. * @param string|boolean $path optional script path
  657. * @param string $regpath additional registry path
  658. * @return Object
  659. */
  660. public static function getSingleton($class_name, $path = true, $regpath = '')
  661. {
  662. $id = 'core/e107/singleton/'.$class_name.$regpath;
  663. //singleton object found - overload not possible
  664. if(self::getRegistry($id))
  665. {
  666. return self::getRegistry($id);
  667. }
  668. //auto detection + overload check
  669. if(is_bool($path))
  670. {
  671. //overload allowed
  672. if(true === $path && self::isHandlerOverloadable($class_name))
  673. {
  674. $tmp = self::getHandlerOverload($class_name);
  675. $class_name = $tmp[0];
  676. $path = $tmp[1];
  677. }
  678. //overload not allowed
  679. else
  680. {
  681. $path = self::getHandlerPath($class_name);
  682. }
  683. }
  684. if($path && is_string($path) && !class_exists($class_name, false))
  685. {
  686. e107_require_once($path); //no existence/security checks here!
  687. //e107_require_once() is available without class2.php. - see core_functions.php
  688. }
  689. if(class_exists($class_name, false))
  690. {
  691. e107::setRegistry($id, new $class_name());
  692. }
  693. return self::getRegistry($id);
  694. }
  695. /**
  696. * Retrieve object
  697. * Prepare for __autoload
  698. *
  699. * @param string $class_name
  700. * @param mxed $arguments
  701. * @param string|boolean $path optional script path
  702. * @return object|null
  703. */
  704. public static function getObject($class_name, $arguments = null, $path = true)
  705. {
  706. if(true === $path)
  707. {
  708. if(isset(self::$_known_handlers[$class_name]))
  709. {
  710. $path = self::getParser()->replaceConstants(self::$_known_handlers[$class_name]);
  711. }
  712. }
  713. //auto detection + overload check
  714. if(is_bool($path))
  715. {
  716. //overload allowed
  717. if(true === $path && self::isHandlerOverloadable($class_name))
  718. {
  719. $tmp = self::getHandlerOverload($class_name);
  720. $class_name = $tmp[0];
  721. $path = $tmp[1];
  722. }
  723. //overload not allowed
  724. else
  725. {
  726. $path = self::getHandlerPath($class_name);
  727. }
  728. }
  729. if($path && is_string($path) && !class_exists($class_name, false))
  730. {
  731. e107_require_once($path); //no existence/security checks here!
  732. }
  733. if(class_exists($class_name, false))
  734. {
  735. if(null !== $arguments) return new $class_name($arguments);
  736. return new $class_name();
  737. }
  738. trigger_error("Class {$class_name} not found!", E_USER_ERROR);
  739. return null;
  740. }
  741. /**
  742. * Retrieve core config handlers.
  743. * List of allowed $name values (aliases) could be found
  744. * in {@link e_core_pref} class
  745. *
  746. * @param string $name core|core_backup|emote|menu|search|notify
  747. * @return e_core_pref
  748. */
  749. public static function getConfig($name = 'core', $load = true, $refresh=false)
  750. {
  751. if(isset(self::$_plug_config_arr[$name])) //FIXME Load pluginPref Object instead - Not quite working with calendar_menu.
  752. {
  753. return self::getPlugConfig($name);
  754. }
  755. if(!isset(self::$_core_config_arr[$name]) || ($refresh == true)) // required by update_routines to clear out earlier values.
  756. {
  757. e107_require_once(e_HANDLER.'pref_class.php');
  758. self::$_core_config_arr[$name] = new e_core_pref($name, $load);
  759. if($name == 'core') // prevent loop between pref and cache handlers.
  760. {
  761. e107::getCache()->UserCacheActive = self::getPref('cachestatus');
  762. e107::getCache()->SystemCacheActive = self::getPref('syscachestatus');
  763. }
  764. }
  765. return self::$_core_config_arr[$name];
  766. }
  767. /**
  768. * Retrieve core config handler preference value or the core preference array
  769. * Shorthand of self::getConfig()->get()
  770. *
  771. * @see e_core_pref::get()
  772. * @param string $pref_name
  773. * @param mixed $default default value if preference is not found
  774. * @return mixed
  775. */
  776. public static function getPref($pref_name = '', $default = null)
  777. {
  778. return empty($pref_name) ? self::getConfig()->getPref() : self::getConfig()->get($pref_name, $default);
  779. }
  780. /**
  781. * Advanced version of self::getPref(). $pref_name is parsed,
  782. * so that $pref_name = 'x/y/z' will search for value pref_data[x][y][z]
  783. * Shorthand of self::getConfig()->getPref()
  784. *
  785. * @see e_core_pref::getPref()
  786. * @param string $pref_name
  787. * @param mixed $default default value if preference is not found
  788. * @return mixed
  789. */
  790. public static function findPref($pref_name, $default = null, $index = null)
  791. {
  792. return self::getConfig()->getPref($pref_name, $default, $index);
  793. }
  794. /**
  795. * Retrieve plugin config handlers.
  796. * Multiple plugin preference DB rows are supported
  797. * Class overload is supported.
  798. * Examples:
  799. * - <code>e107::getPluginConfig('myplug');</code>
  800. * will search for e107_plugins/myplug/e_pref/myplug_pref.php which
  801. * should contain class 'e_plugin_myplug_pref' class (child of e_plugin_pref)
  802. * - <code>e107::getPluginConfig('myplug', 'row2');</code>
  803. * will search for e107_plugins/myplug/e_pref/myplug_row2_pref.php which
  804. * should contain class 'e_plugin_myplug_row2_pref' class (child of e_plugin_pref)
  805. *
  806. * @param string $plug_name
  807. * @param string $multi_row
  808. * @param boolean $load load from DB on startup
  809. * @return e_plugin_pref
  810. */
  811. public static function getPlugConfig($plug_name, $multi_row = '', $load = true)
  812. {
  813. if(!isset(self::$_plug_config_arr[$plug_name.$multi_row]))
  814. {
  815. e107_require_once(e_HANDLER.'pref_class.php');
  816. $override_id = $plug_name.($multi_row ? "_{$multi_row}" : '');
  817. //check (once) for custom plugin pref handler
  818. if(is_readable(e_PLUGIN.$plug_name.'/e_pref/'.$override_id.'_pref.php'))
  819. {
  820. require_once(e_PLUGIN.$plug_name.'/e_pref/'.$override_id.'_pref.php');
  821. $class_name = 'e_plugin_'.$override_id.'_pref';
  822. //PHPVER: string parameter for is_subclass_of require PHP 5.0.3+
  823. if(class_exists($class_name, false) && is_subclass_of('e_plugin_pref', $class_name)) //or e_pref ?
  824. {
  825. self::$_plug_config_arr[$plug_name.$multi_row] = new $class_name($load);
  826. return self::$_plug_config_arr[$plug_name.$multi_row];
  827. }
  828. }
  829. self::$_plug_config_arr[$plug_name.$multi_row] = new e_plugin_pref($plug_name, $multi_row, $load);
  830. }
  831. return self::$_plug_config_arr[$plug_name.$multi_row];
  832. }
  833. /**
  834. * Retrieve plugin preference value.
  835. * Shorthand of self::getPluginConfig()->get()
  836. * NOTE: Multiple plugin preference DB rows are NOT supported
  837. * This will only look for your default plugin config (empty $milti_row)
  838. *
  839. * @see e_plugin_pref::get()
  840. * @param string $plug_name
  841. * @param string $pref_name
  842. * @param mixed $default default value if preference is not found
  843. * @return mixed
  844. */
  845. public static function getPlugPref($plug_name, $pref_name = '', $default = null)
  846. {
  847. return empty($pref_name) ? self::getPlugConfig($plug_name)->getPref() : self::getPlugConfig($plug_name)->get($pref_name, $default);
  848. }
  849. /**
  850. * Advanced version of self::getPlugPref(). $pref_name is parsed,
  851. * so that $pref_name = 'x/y/z' will search for value pref_data[x][y][z]
  852. * Shorthand of self::getPluginConfig()->getPref()
  853. *
  854. * @see e_core_pref::getPref()
  855. * @param string $pref_name
  856. * @param mixed $default default value if preference is not found
  857. * @return mixed
  858. */
  859. public static function findPlugPref($plug_name, $pref_name, $default = null, $index = null)
  860. {
  861. return self::getPlugConfig($plug_name)->getPref($pref_name, $default, $index);
  862. }
  863. /**
  864. * Get current theme preference. $pref_name is parsed,
  865. * so that $pref_name = 'x/y/z' will search for value pref_data[x][y][z]
  866. * Shorthand of self::getConfig()->getPref('current_theme/sitetheme_pref/pref_name')
  867. *
  868. * @see e_core_pref::getPref()
  869. * @param string $pref_name
  870. * @param mixed $default default value if preference is not found
  871. * @return mixed
  872. */
  873. public static function getThemePref($pref_name = '', $default = null, $index = null)
  874. {
  875. if($pref_name) $pref_name = '/'.$pref_name;
  876. return e107::getConfig()->getPref('sitetheme_pref'.$pref_name, $default, $index);
  877. }
  878. /**
  879. * Set current theme preference. $pref_name is parsed,
  880. * so that $pref_name = 'x/y/z' will set value pref_data[x][y][z]
  881. *
  882. * @param string|array $pref_name
  883. * @param mixed $pref_value
  884. * @return e_pref
  885. */
  886. public static function setThemePref($pref_name, $pref_value = null)
  887. {
  888. if(is_array($pref_name)) return e107::getConfig()->set('sitetheme_pref', $pref_name);
  889. return e107::getConfig()->updatePref('sitetheme_pref/'.$pref_name, $pref_value, false);
  890. }
  891. /**
  892. * Retrieve text parser singleton object
  893. *
  894. * @return e_parse
  895. */
  896. public static function getParser()
  897. {
  898. return self::getSingleton('e_parse', e_HANDLER.'e_parse_class.php'); //WARNING - don't change this - infinite loop!!!
  899. }
  900. /**
  901. * Retrieve sc parser singleton object
  902. *
  903. * @return e_parse_shortcode
  904. */
  905. public static function getScParser()
  906. {
  907. return self::getSingleton('e_parse_shortcode', true);
  908. }
  909. /**
  910. * Retrieve secure_image singleton object
  911. *
  912. * @return secure_image
  913. */
  914. public static function getSecureImg()
  915. {
  916. return self::getSingleton('secure_image', true); // more flexible.
  917. // return self::getObject('secure_image');
  918. }
  919. /**
  920. * Retrieve registered sc object (batch) by class name
  921. * Note - '_shortcodes' part of the class/override is added by the method
  922. * Override is possible only if class is not already instantiated by shortcode parser
  923. *
  924. * <code><?php
  925. *
  926. * // Core news shortcodes (news_shortcodes.php using class news_shortcodes )
  927. * e107::getScObject('news');
  928. *
  929. * // Core page shortcodes (page_shortcodes.php.php with class cpage_shortcode)
  930. * e107::getScObject('page', null,'cpage');
  931. *
  932. * // object of plugin_myplugin_my_shortcodes class -> myplugin/shortcodes/batch/my_shortcodes.php
  933. * e107::getScObject('my', 'myplugin');
  934. *
  935. * // news override - plugin_myplugin_news_shortcodes extends news_shortcodes -> myplugin/shortcodes/batch/news_shortcodes.php
  936. * e107::getScObject('news', 'myplugin', true);
  937. *
  938. * // news override - plugin_myplugin_mynews_shortcodes extends news_shortcodes -> myplugin/shortcodes/batch/mynews_shortcodes.php
  939. * e107::getScObject('news', 'myplugin', 'mynews');
  940. * </code>
  941. *
  942. * @param string $className
  943. * @param string $pluginName
  944. * @param string|true $overrideClass
  945. * @return e_shortcode
  946. */
  947. public static function getScBatch($className, $pluginName = null, $overrideClass = null)
  948. {
  949. if(is_string($overrideClass)) $overrideClass .= '_shortcodes';
  950. return self::getScParser()->getScObject($className.'_shortcodes', $pluginName, $overrideClass);
  951. }
  952. /**
  953. * Retrieve DB singleton object based on the
  954. * $instance_id
  955. *
  956. * @param string $instance_id
  957. * @return e_db_mysql
  958. */
  959. public static function getDb($instance_id = '')
  960. {
  961. return self::getSingleton('db', true, $instance_id);
  962. }
  963. /**
  964. * Retrieve cache singleton object
  965. *
  966. * @return ecache
  967. */
  968. public static function getCache()
  969. {
  970. return self::getSingleton('ecache', true);
  971. }
  972. /**
  973. * Retrieve bbcode singleton object
  974. *
  975. * @return e_bbcode
  976. */
  977. public static function getBB()
  978. {
  979. return self::getSingleton('e_bbcode', true);
  980. }
  981. /**
  982. * Retrieve user-session singleton object
  983. *
  984. * @return UserHandler
  985. */
  986. public static function getUserSession()
  987. {
  988. return self::getSingleton('UserHandler', true);
  989. }
  990. /**
  991. * Retrieve core session singleton object(s)
  992. *
  993. * @return e_core_session
  994. */
  995. public static function getSession($namespace = null)
  996. {
  997. $id = 'core/e107/session/'.(null === $namespace ? 'e107' : $namespace);
  998. if(self::getRegistry($id))
  999. {
  1000. return self::getRegistry($id);
  1001. }
  1002. $session = self::getObject('e_core_session', array('namespace' => $namespace), true);
  1003. self::setRegistry($id, $session);
  1004. return $session;
  1005. }
  1006. /**
  1007. * Retrieve redirection singleton object
  1008. *
  1009. * @return redirection
  1010. */
  1011. public static function getRedirect()
  1012. {
  1013. return self::getSingleton('redirection', true);
  1014. }
  1015. /**
  1016. * Retrieve rater singleton object
  1017. *
  1018. * @return rate
  1019. */
  1020. public static function getRate()
  1021. {
  1022. return self::getSingleton('rater', true);
  1023. }
  1024. /**
  1025. * Retrieve sitelinks singleton object
  1026. *
  1027. * @return sitelinks
  1028. */
  1029. public static function getSitelinks()
  1030. {
  1031. return self::getSingleton('sitelinks', true);
  1032. }
  1033. /**
  1034. * Retrieve render singleton object
  1035. *
  1036. * @return e107table
  1037. */
  1038. public static function getRender()
  1039. {
  1040. return self::getSingleton('e107table');
  1041. }
  1042. /**
  1043. * Retrieve e107Email singleton object
  1044. *
  1045. * @return e107Email
  1046. */
  1047. public static function getEmail()
  1048. {
  1049. return self::getSingleton('e107Email', true);
  1050. }
  1051. /**
  1052. * Retrieve event singleton object
  1053. *
  1054. * @return e107_event
  1055. */
  1056. public static function getEvent()
  1057. {
  1058. return self::getSingleton('e107_event', true);
  1059. }
  1060. /**
  1061. * Retrieve array storage singleton object
  1062. *
  1063. * @return e_array
  1064. */
  1065. public static function getArrayStorage()
  1066. {
  1067. return self::getSingleton('e_array', true);
  1068. }
  1069. /**
  1070. * Retrieve menu handler singleton object
  1071. *
  1072. * @return e_menu
  1073. */
  1074. public static function getMenu()
  1075. {
  1076. return self::getSingleton('e_menu', true);
  1077. }
  1078. /**
  1079. * Retrieve URL singleton object
  1080. *
  1081. * @return eURL
  1082. */
  1083. public static function getUrl()
  1084. {
  1085. return self::getSingleton('eUrl', true);
  1086. }
  1087. /**
  1088. * Retrieve file handler singleton or new fresh object
  1089. *
  1090. * @param boolean $singleton default true
  1091. * @return e_file
  1092. */
  1093. public static function getFile($singleton = false)
  1094. {
  1095. if($singleton)
  1096. {
  1097. return self::getSingleton('e_file', true);
  1098. }
  1099. return self::getObject('e_file', null, true);
  1100. }
  1101. /**
  1102. * Retrieve form handler singleton or new fresh object
  1103. *
  1104. * @param boolean $singleton default false
  1105. * @param boolean $tabindex passed to e_form when initialized as an object (not singleton)
  1106. * @return e_form
  1107. */
  1108. public static function getForm($singleton = false, $tabindex = false)
  1109. {
  1110. if($singleton)
  1111. {
  1112. return self::getSingleton('e_form', true);
  1113. }
  1114. return self::getObject('e_form', $tabindex, true);
  1115. }
  1116. /**
  1117. * Retrieve admin log singleton object
  1118. *
  1119. * @return e_admin_log
  1120. */
  1121. public static function getAdminLog()
  1122. {
  1123. return self::getSingleton('e_admin_log', true);
  1124. }
  1125. /**
  1126. * Retrieve date handler singleton object
  1127. *
  1128. * @return convert
  1129. */
  1130. public static function getDateConvert()
  1131. {
  1132. return self::getSingleton('convert', true);
  1133. }
  1134. /**
  1135. * Retrieve date handler singleton object - preferred method.
  1136. *
  1137. * @return convert
  1138. */
  1139. public static function getDate()
  1140. {
  1141. return self::getSingleton('convert', true);
  1142. }
  1143. /**
  1144. * Retrieve date handler singleton object - preferred method.
  1145. *
  1146. * @return convert
  1147. */
  1148. public static function getDebug() //XXX Discuss - possible with current setup?
  1149. {
  1150. return self::getSingleton('e107_db_debug', true);
  1151. }
  1152. /**
  1153. * Retrieve notify handler singleton object
  1154. *
  1155. * @return notify
  1156. */
  1157. public static function getNotify()
  1158. {
  1159. return self::getSingleton('notify', true);
  1160. }
  1161. /**
  1162. * Retrieve override handler singleton object
  1163. *
  1164. * @return notify
  1165. */
  1166. public static function getOverride()
  1167. {
  1168. return self::getSingleton('override', true);
  1169. }
  1170. /**
  1171. * Retrieve Language handler singleton object
  1172. *
  1173. * @return language
  1174. */
  1175. public static function getLanguage()
  1176. {
  1177. return self::getSingleton('language', true);
  1178. }
  1179. /**
  1180. * Retrieve IP/ban handler singleton object
  1181. *
  1182. * @return eIPHandler
  1183. */
  1184. public static function getIPHandler()
  1185. {
  1186. return self::getSingleton('eIPHandler', true);
  1187. }
  1188. /**
  1189. * Retrieve Xml handler singleton or new instance object
  1190. * @param mixed $singleton false - new instance, true - singleton from default registry location, 'string' - registry path
  1191. * @return xmlClass
  1192. */
  1193. public static function getXml($singleton = true)
  1194. {
  1195. if($singleton)
  1196. {
  1197. return self::getSingleton('xmlClass', true, (true === $singleton ? '' : $singleton));
  1198. }
  1199. return self::getObject('xmlClass', null, true);
  1200. }
  1201. /**
  1202. * Retrieve HybridAuth object
  1203. *
  1204. * @return Hybrid_Auth
  1205. */
  1206. public static function getHybridAuth($config = null)
  1207. {
  1208. if(null === $config)
  1209. {
  1210. $config = array(
  1211. 'base_url' => e107::getUrl()->create('system/xup/endpoint', array(), array('full' => true)),
  1212. 'providers' => e107::getPref('social_login', array()),
  1213. 'debug_mode' => false,
  1214. 'debug_file' => ''
  1215. );
  1216. }
  1217. return new Hybrid_Auth($config);
  1218. }
  1219. /**
  1220. * Retrieve userclass singleton object
  1221. *
  1222. * @return user_class
  1223. */
  1224. public static function getUserClass()
  1225. {
  1226. return self::getSingleton('user_class', true);
  1227. }
  1228. /**
  1229. * Retrieve user model object.
  1230. *
  1231. * @param integer $user_id target user
  1232. * @param boolean $checkIfCurrent if tru user_id will be compared to current user, if there is a match
  1233. * current user object will be returned
  1234. * @return e_system_user
  1235. */
  1236. public static function getSystemUser($user_id, $checkIfCurrent = true)
  1237. {
  1238. if($checkIfCurrent && $user_id && $user_id === self::getUser()->getId())
  1239. {
  1240. return self::getUser();
  1241. }
  1242. if(!$user_id) return self::getObject('e_system_user');
  1243. $user = self::getRegistry('core/e107/user/'.$user_id);
  1244. if(null === $user)
  1245. {
  1246. $user = self::getObject('e_system_user');
  1247. if($user_id) $user->load($user_id); // self registered on load
  1248. }
  1249. return $user;
  1250. }
  1251. /**
  1252. * Simple replacement for deprecated get_user_data(). e107::user();
  1253. * @param $uid integer user_id or leave empty for currently logged in user.
  1254. * @return array of user data
  1255. */
  1256. public static function user($uid=null)
  1257. {
  1258. if(!$uid){ return false; }
  1259. $user = self::getSystemUser($uid, true);
  1260. $var = array();
  1261. if($user)
  1262. {
  1263. $var = $user->getUserData();
  1264. }
  1265. return $var;
  1266. }
  1267. /**
  1268. * Return a string containg exported array data. - preferred.
  1269. *
  1270. * @param array $ArrayData array to be stored
  1271. * @param bool $AddSlashes default false, add slashes for db storage, else false
  1272. * @return string
  1273. */
  1274. public static function serialize($ArrayData, $AddSlashes = false)
  1275. {
  1276. return self::getArrayStorage()->serialize($ArrayData, $AddSlashes);
  1277. }
  1278. /**
  1279. * Returns an array from stored array data.
  1280. *
  1281. * @param string $ArrayData
  1282. * @return array stored data
  1283. */
  1284. public static function unserialize($ArrayData)
  1285. {
  1286. return self::getArrayStorage()->unserialize($ArrayData);
  1287. }
  1288. /**
  1289. * Retrieve current user model object.
  1290. *
  1291. * @return e_user
  1292. */
  1293. public static function getUser()
  1294. {
  1295. $user = self::getRegistry('core/e107/current_user');
  1296. if(null === $user)
  1297. {
  1298. $user = self::getObject('e_user');
  1299. self::setRegistry('core/e107/current_user', $user);
  1300. }
  1301. return $user;
  1302. }
  1303. /**
  1304. * Retrieve user model object.
  1305. *
  1306. * @param integer $user_id target user
  1307. * @return e_current_user
  1308. */
  1309. public static function getUserStructure()
  1310. {
  1311. return self::getSingleton('e_user_extended_structure_tree', true);
  1312. }
  1313. /**
  1314. * Retrieve User Extended handler singleton object
  1315. * @return e107_user_extended
  1316. */
  1317. public static function getUserExt()
  1318. {
  1319. return self::getSingleton('e107_user_extended', true);
  1320. }
  1321. /**
  1322. * Retrieve User Perms (admin perms) handler singleton object
  1323. * @return e_userperms
  1324. */
  1325. public static function getUserPerms()
  1326. {
  1327. return self::getSingleton('e_userperms', true);
  1328. }
  1329. /**
  1330. * Retrieve online users handler singleton object
  1331. * @return e_ranks
  1332. */
  1333. public static function getRank()
  1334. {
  1335. return self::getSingleton('e_ranks', true);
  1336. }
  1337. /**
  1338. * Retrieve plugin handler singleton object
  1339. * @return e107plugin
  1340. */
  1341. public static function getPlugin()
  1342. {
  1343. return self::getSingleton('e107plugin', true);
  1344. }
  1345. /**
  1346. * Retrieve online users handler singleton object
  1347. * @return e_online
  1348. */
  1349. public static function getOnline()
  1350. {
  1351. return self::getSingleton('e_online', true);
  1352. }
  1353. /**
  1354. * Retrieve chart handler singleton object
  1355. * @return e_chart
  1356. */
  1357. public static function getChart()
  1358. {
  1359. return self::getSingleton('e_chart', true);
  1360. }
  1361. /**
  1362. * Retrieve comments handler singleton object
  1363. * @return comment
  1364. */
  1365. public static function getComment()
  1366. {
  1367. return self::getSingleton('comment', true);
  1368. }
  1369. /**
  1370. * Retrieve Media handler singleton object
  1371. * @return e_media
  1372. */
  1373. public static function getMedia()
  1374. {
  1375. return self::getSingleton('e_media', true);
  1376. }
  1377. /**
  1378. * Retrieve Navigation Menu handler singleton object
  1379. * @return e_navigation
  1380. */
  1381. public static function getNav()
  1382. {
  1383. return self::getSingleton('e_navigation', true);
  1384. }
  1385. /**
  1386. * Retrieve message handler singleton
  1387. * @return eMessage
  1388. */
  1389. public static function getMessage()
  1390. {
  1391. // static $included = false;
  1392. // if(!$included)
  1393. // {
  1394. // e107_require_once(e_HANDLER.'message_handler.php');
  1395. // $included = true;
  1396. // }
  1397. // return eMessage::getInstance();
  1398. return self::getSingleton('eMessage', true);
  1399. }
  1400. /**
  1401. * Retrieve JS Manager singleton object
  1402. *
  1403. * @return e_jsmanager
  1404. */
  1405. public static function getJs()
  1406. {
  1407. static $included = false;
  1408. if(!$included)
  1409. {
  1410. e107_require_once(e_HANDLER.'js_manager.php');
  1411. $included = true;
  1412. }
  1413. return e_jsmanager::getInstance();
  1414. }
  1415. /**
  1416. * JS Common Public Function. Prefered is shortcode script path
  1417. * @param string $type core|theme|footer|inline|footer-inline|url or any existing plugin_name
  1418. * @param string $data depends on the type - path/url or inline js source
  1419. * @param integer $zone [optional] leave it null for default zone
  1420. * @param string $dep dependence : null | prototype | jquery
  1421. */
  1422. public static function js($type, $data, $dep = null, $zone = null, $pre = '', $post = '')
  1423. {
  1424. $jshandler = e107::getJs();
  1425. $jshandler->setDependency($dep);
  1426. switch ($type)
  1427. {
  1428. case 'core':
  1429. // data is e.g. 'core/tabs.js'
  1430. if(null !== $zone) $jshandler->requireCoreLib($data, $zone);
  1431. else $jshandler->requireCoreLib($data);
  1432. break;
  1433. case 'bootstrap': //TODO Eventually add own method and render for bootstrap.
  1434. if(null !== $zone) $jshandler->requireCoreLib('bootstrap/js/'.$data, $zone);
  1435. else $jshandler->requireCoreLib('bootstrap/js/'.$data);
  1436. break;
  1437. case 'theme':
  1438. // data is e.g. 'jslib/mytheme.js'
  1439. if(null !== $zone) $jshandler->headerTheme($data, $zone, $pre, $post);
  1440. else $jshandler->headerTheme($data, 5, $pre, $post);
  1441. break;
  1442. case 'inline':
  1443. // data is JS source (without script tags)
  1444. if(null !== $zone) $jshandler->headerInline($data, $zone);
  1445. else $jshandler->headerInline($data);
  1446. break;
  1447. case 'footer-inline':
  1448. // data is JS source (without script tags)
  1449. if(null !== $zone) $jshandler->footerInline($data, $zone);
  1450. else $jshandler->footerInline($data);
  1451. break;
  1452. case 'url':
  1453. // data is e.g. 'http://cdn.somesite.com/some.js'
  1454. if(null !== $zone) $jshandler->headerFile($data, $zone, $pre, $post);
  1455. else $jshandler->headerFile($data, 5, $pre, $post);
  1456. break;
  1457. case 'footer':
  1458. // data is e.g. '{e_PLUGIN}myplugin/jslib/myplug.js'
  1459. if(null !== $zone) $jshandler->footerFile($data, $zone);
  1460. else $jshandler->footerFile($data);
  1461. break;
  1462. // $type is plugin name
  1463. default:
  1464. // data is e.g. 'jslib/myplug.js'
  1465. if(!self::isInstalled($type)) return;
  1466. if(null !== $zone) $jshandler->requirePluginLib($type, $data, $zone);
  1467. else $jshandler->requirePluginLib($type, $data);
  1468. break;
  1469. }
  1470. $jshandler->resetDependency();
  1471. }
  1472. /**
  1473. * CSS Common Public Function. Prefered is shortcode script path
  1474. * @param string $type core|theme|footer|inline|footer-inline|url or any existing plugin_name
  1475. * @param string $data depends on the type - path/url or inline js source
  1476. * @param string $media any valid media attribute string - http://www.w3schools.com/TAGS/att_link_media.asp
  1477. * @param string $preComment possible comment e.g. <!--[if lt IE 7]>
  1478. * @param string $postComment possible comment e.g. <![endif]-->
  1479. */
  1480. public static function css($type, $data, $dep = null, $media = 'all', $preComment = '', $postComment = '', $dependence = null)
  1481. {
  1482. if((strstr($data,'bootstrap.css') || strstr($data,'bootstrap.min.css')) && !defined("BOOTSTRAP")) // detect bootstrap is enabled. - used in nextprev.sc and forum currently.
  1483. {
  1484. define("BOOTSTRAP", true);
  1485. }
  1486. $jshandler = e107::getJs();
  1487. $jshandler->setDependency($dep);
  1488. switch ($type)
  1489. {
  1490. case 'core':
  1491. // data is path relative to e_FILE/jslib/
  1492. $jshandler->coreCSS($data, $media, $preComment, $postComment);
  1493. break;
  1494. case 'bootstrap':
  1495. // data is path relative to e_FILE/jslib/
  1496. $jshandler->coreCSS('bootstrap/css/'.$data, $media, $preComment, $postComment);
  1497. break;
  1498. case 'theme':
  1499. // data is path relative to current theme
  1500. $jshandler->themeCSS($data, $media, $preComment, $postComment);
  1501. break;
  1502. case 'inline':
  1503. // data is CSS source (without style tags)
  1504. $jshandler->inlineCSS($data, $media);
  1505. break;
  1506. case 'url':
  1507. // data is e.g. 'http://cdn.somesite.com/some.css'
  1508. $jshandler->otherCSS($data, $media, $preComment, $postComment);
  1509. break;
  1510. // $type is plugin name
  1511. default:
  1512. // data is e.g. 'css/myplug.css'
  1513. if(self::isInstalled($type)) $jshandler->pluginCSS($type, $data, $media, $preComment, $postComment);
  1514. break;
  1515. }
  1516. $jshandler->resetDependency();
  1517. }
  1518. /**
  1519. * Retrieve JS Helper object
  1520. *
  1521. * @param boolean|string $singleton if true return singleton, if string return singleton object, use string as namespace, default false
  1522. * @return e_jshelper
  1523. */
  1524. public static function getJshelper($singleton = false)
  1525. {
  1526. if($singleton)
  1527. {
  1528. return self::getSingleton('e_jshelper', true, (true === $singleton ? '' : $singleton));
  1529. }
  1530. return self::getObject('e_jshelper', null, true);
  1531. }
  1532. /**
  1533. * @see eResponse::addMeta()
  1534. * @return eResponse
  1535. */
  1536. public static function meta($name = null, $content = null, $extended = array())
  1537. {
  1538. if($name == 'description')
  1539. {
  1540. e107::getUrl()->response()->addMetaDescription($content); //Cam: TBD
  1541. }
  1542. if($name == 'keywords')
  1543. {
  1544. e107::getUrl()->response()->addMetaKeywords($content); //Cam: TBD
  1545. }
  1546. return e107::getUrl()->response()->addMeta($name, $content, $extended);
  1547. }
  1548. /**
  1549. * Retrieve admin dispatcher instance.
  1550. * It's instance is self registered (for now, this could change in the future) on initialization (__construct())
  1551. *
  1552. * @see e_admin_dispatcher
  1553. * @return e_admin_dispatcher
  1554. */
  1555. public static function getAdminUI()
  1556. {
  1557. return self::getRegistry('admin/ui/dispatcher');
  1558. }
  1559. /**
  1560. * Retrieves class Object for specific plugin's addon such as e_url.php, e_cron.php, e_sitelink.php
  1561. * FIXME override from e.g. core/override/addons/
  1562. *
  1563. * @param string $pluginName e.g. faq, page
  1564. * @param string $addonName eg. e_cron, e_url, e_module
  1565. * @param mixed $className [optional] true - use default name, false - no object is returned (include only), any string will be used as class name
  1566. * @return none
  1567. */
  1568. public static function getAddon($pluginName, $addonName, $className = true)
  1569. {
  1570. $filename = $addonName; // e.g. 'e_cron';
  1571. // fixme, temporary adding 's' to className, should be core fixed, better naming
  1572. if(true === $className) $className = $pluginName.'_'.substr($addonName, 2); // remove 'e_'
  1573. $elist = self::getPref($filename.'_list');
  1574. if(!isset($elist[$pluginName])) return null;
  1575. // TODO override check comes here
  1576. $path = e_PLUGIN.$pluginName.'/'.$filename.'.php';
  1577. // e.g. include e_module, e_meta etc
  1578. if(false === $className) return include_once($path);
  1579. if(!class_exists($className, false))
  1580. {
  1581. include_once($path);
  1582. }
  1583. if(!class_exists($className, false))
  1584. {
  1585. return null;
  1586. }
  1587. return new $className;
  1588. }
  1589. /**
  1590. * Retrieves config() from all plugins for addons such as e_url.php, e_cron.php, e_sitelink.php
  1591. * @param string $addonName eg. e_cron, e_url
  1592. * @param string $className [optional] (if different from addonName)
  1593. * @return none
  1594. */
  1595. public function getAddonConfig($addonName, $className = '')
  1596. {
  1597. $new_addon = array();
  1598. $sql = e107::getDb(); // Might be used by older plugins.
  1599. $filename = $addonName; // e.g. 'e_cron';
  1600. if(!$className)
  1601. {
  1602. $className = substr($filename, 2); // remove 'e_'
  1603. }
  1604. $elist = self::getPref($filename.'_list');
  1605. if($elist)
  1606. {
  1607. foreach(array_keys($elist) as $key)
  1608. {
  1609. if(is_readable(e_PLUGIN.$key.'/'.$filename.'.php'))
  1610. {
  1611. include_once(e_PLUGIN.$key.'/'.$filename.'.php');
  1612. $class_name = $key.'_'.$className;
  1613. $array = self::callMethod($class_name, 'config');
  1614. if($array)
  1615. {
  1616. $new_addon[$key] = $array;
  1617. }
  1618. }
  1619. }
  1620. }
  1621. return $new_addon;
  1622. }
  1623. /**
  1624. * Safe way to call user methods.
  1625. * @param string $class_name
  1626. * @param string $method_name
  1627. * @return boolean FALSE
  1628. */
  1629. public static function callMethod($class_name, $method_name, $param='')
  1630. {
  1631. $mes = e107::getMessage();
  1632. if(class_exists($class_name))
  1633. {
  1634. $obj = new $class_name;
  1635. if(method_exists($obj, $method_name))
  1636. {
  1637. if(E107_DBG_INCLUDES)
  1638. {
  1639. $mes->debug('Executing <strong>'.$class_name.' :: '.$method_name.'()</strong>');
  1640. }
  1641. return call_user_func(array($obj, $method_name),$param);
  1642. }
  1643. else
  1644. {
  1645. $mes->debug('Function <strong>'.$class_name.' :: '.$method_name.'()</strong> NOT found.');
  1646. }
  1647. }
  1648. return FALSE;
  1649. }
  1650. /**
  1651. * Get theme name or path.
  1652. *
  1653. * @param mixed $for true (default) - auto-detect (current), admin - admin theme, front - site theme
  1654. * @param string $path default empty string (return name only), 'abs' - absolute url path, 'rel' - relative server path
  1655. * @return string
  1656. */
  1657. public static function getThemeInfo($for = true, $path = '')
  1658. {
  1659. global $user_pref; // FIXME - user model, kill user_pref global
  1660. if(true === $for)
  1661. {
  1662. $for = e_ADMIN_AREA ? 'admin' : 'front';
  1663. }
  1664. switch($for )
  1665. {
  1666. case 'admin':
  1667. $for = e107::getPref('admintheme');
  1668. break;
  1669. case 'front':
  1670. $for = isset($user_pref['sitetheme']) ? $user_pref['sitetheme'] : e107::getPref('sitetheme');
  1671. break;
  1672. }
  1673. if(!$path) return $for;
  1674. switch($path)
  1675. {
  1676. case 'abs':
  1677. $path = e_THEME_ABS.$for.'/';
  1678. break;
  1679. case 'rel':
  1680. default:
  1681. $path = e_THEME.$for.'/';
  1682. break;
  1683. }
  1684. return $path;
  1685. }
  1686. /**
  1687. * Retrieve core template path
  1688. * Example: <code>echo e107::coreTemplatePath('admin_icons');</code>
  1689. *
  1690. * @see getThemeInfo()
  1691. * @param string $id part of the path/file name without _template.php part
  1692. * @param boolean $override default true
  1693. * @return string relative path
  1694. */
  1695. public static function coreTemplatePath($id, $override = true)
  1696. {
  1697. $id = str_replace('..', '', $id); //simple security, '/' is allowed
  1698. $curTheme = self::getThemeInfo($override, 'rel');
  1699. $override_path = $override ? $curTheme.'templates/'.$id.'_template.php' : null;
  1700. $legacy_override_path = $override ? $curTheme.$id.'_template.php' : null;
  1701. $legacy_core_path = e_THEME.'templates/'.$id.'_template.php';
  1702. $core_path = e_CORE.'templates/'.$id.'_template.php';
  1703. if($override_path && is_readable($override_path)) // v2 override template.
  1704. {
  1705. return $override_path;
  1706. }
  1707. elseif($legacy_override_path && is_readable($legacy_override_path)) //v1 override template.
  1708. {
  1709. return $legacy_override_path;
  1710. }
  1711. elseif(is_readable($legacy_core_path)) //v1 core template.
  1712. {
  1713. return $legacy_core_path;
  1714. }
  1715. return $core_path;
  1716. }
  1717. /**
  1718. * Retrieve plugin template path
  1719. * Override path could be forced to front- or back-end via
  1720. * the $override parameter e.g. <code> e107::templatePath(plug_name, 'my', 'front')</code>
  1721. * Example:
  1722. * <code>
  1723. * echo e107::templatePath(plug_name, 'my');
  1724. * // result is something like:
  1725. * // e107_themes/current_theme/templates/plug_name/my_template.php
  1726. * // or if not found
  1727. * // e107_plugins/plug_name/templates/my_template.php
  1728. * </code>
  1729. *
  1730. * @see getThemeInfo()
  1731. * @param string $plug_name plugin name
  1732. * @param string $id part of the path/file name without _template.php part
  1733. * @param boolean|string $override default true
  1734. * @return string relative path
  1735. */
  1736. public static function templatePath($plug_name, $id, $override = true)
  1737. {
  1738. $id = str_replace('..', '', $id); //simple security, '/' is allowed
  1739. $plug_name = preg_replace('#[^a-z0-9_]#i', '', $plug_name); // only latin allowed, so \w not a solution since PHP5.3
  1740. $override_path = $override ? self::getThemeInfo($override, 'rel').'templates/'.$plug_name.'/'.$id.'_template.php' : null;
  1741. $default_path = e_PLUGIN.$plug_name.'/templates/'.$id.'_template.php';
  1742. return ($override_path && is_readable($override_path) ? $override_path : $default_path);
  1743. }
  1744. /**
  1745. * Get core template. Use this method for templates, which are following the
  1746. * new template standards:
  1747. * - template variables naming conventions
  1748. * - one array variable per template only
  1749. * - theme override is made now by current_theme/templates/ folder
  1750. *
  1751. * <br><br>Results are cached (depending on $id and $override so it's safe to use
  1752. * this method e.g. in loop for retrieving a template string. If template (or template key) is not
  1753. * found, <b>NULL</b> is returned.<br><br>
  1754. *
  1755. * Example usage: <code>e107::getCoreTemplate('user', 'short_start');</code>
  1756. * Will search for:
  1757. * - e107_themes/current_frontend_theme/templates/user_template.php (if $override is true)
  1758. * - e107_themes/templates/user_template.php (if override not found or $override is false)
  1759. * - $USER_TEMPLATE array which contains all user templates
  1760. * - $USER_TEMPLATE['short_start'] (if key is null, $USER_TEMPLATE will be returned)
  1761. *
  1762. * @param string $id - file prefix, e.g. user for user_template.php
  1763. * @param string|null $key
  1764. * @param boolean $override see {@link getThemeInfo()}
  1765. * @param boolean $merge merge theme with core templates, default is false
  1766. * @param boolean $info retrieve template info only
  1767. * @return string|array
  1768. */
  1769. public static function getCoreTemplate($id, $key = null, $override = true, $merge = false, $info = false)
  1770. {
  1771. $reg_path = 'core/e107/templates/'.$id.($override ? '/ext' : '');
  1772. $path = self::coreTemplatePath($id, $override);
  1773. $id = str_replace('/', '_', $id);
  1774. $ret = self::_getTemplate($id, $key, $reg_path, $path, $info);
  1775. ### Attempt to fix merge issues; in case we override - template array not found in theme,
  1776. ### so we need to continue and merge with core templates
  1777. if($merge && $override && empty($ret))
  1778. {
  1779. $ret = array();
  1780. }
  1781. if((!$merge && !$override) || is_string($ret))
  1782. {
  1783. return $ret;
  1784. }
  1785. // merge
  1786. $reg_path = 'core/e107/templates/'.$id;
  1787. $path = self::coreTemplatePath($id, false);
  1788. $id = str_replace('/', '_', $id);
  1789. $ret_core = self::_getTemplate($id, $key, $reg_path, $path, $info);
  1790. return (is_array($ret_core) ? array_merge($ret_core, $ret) : $ret);
  1791. }
  1792. /**
  1793. * Get plugin template. Use this method for plugin templates, which are following the
  1794. * new template standards:
  1795. * - template variables naming conventions ie. ${NAME IN CAPS}_TEMPLATE['{ID}'] = "<div>...</div>";
  1796. * - one array variable per template only
  1797. * - theme override is made now by current_theme/templates/plugin_name/ folder
  1798. *
  1799. * <br><br>Results are cached (depending on $id and $override so it's safe to use
  1800. * this method e.g. in loop for retrieving a template string. If template (or template key) is not
  1801. * found, <b>NULL</b> is returned.<br><br>
  1802. *
  1803. * Example usage: <code>e107::getTemplate('user', 'short_start');</code>
  1804. * Will search for:
  1805. * - e107_themes/current_frontend_theme/templates/user_template.php (if $override is true)
  1806. * - e107_themes/templates/user_template.php (if override not found or $override is false)
  1807. * - $USER_TEMPLATE array which contains all user templates
  1808. * - $USER_TEMPLATE['short_start'] (if key is null, $USER_TEMPLATE will be returned)
  1809. *
  1810. * @param string $plug_name if null getCoreTemplate method will be called
  1811. * @param string $id - file prefix, e.g. calendar for calendar_template.php
  1812. * @param string|null $key
  1813. * @param boolean $override see {@link getThemeInfo()}
  1814. * @param boolean $merge merge theme with plugin templates, default is false
  1815. * @param boolean $info retrieve template info only
  1816. * @return string|array
  1817. */
  1818. public static function getTemplate($plug_name, $id = null, $key = null, $override = true, $merge = false, $info = false)
  1819. {
  1820. if(null === $plug_name)
  1821. {
  1822. return self::getCoreTemplate($id, $key, $override, $merge, $info);
  1823. }
  1824. if(null == $id || true === $id) // loads {$plug_name}/templates/{$plug_name}_template.php and an array ${PLUG_NAME}_TEMPLATE
  1825. {
  1826. $id = $plug_name;
  1827. }
  1828. $reg_path = 'plugin/'.$plug_name.'/templates/'.$id.($override ? '/ext' : '');
  1829. $path = self::templatePath($plug_name, $id, $override);
  1830. if(ADMIN && E107_DBG_INCLUDES)
  1831. {
  1832. e107::getMessage()->addDebug( "template path=".$path );
  1833. }
  1834. $id = str_replace('/', '_', $id);
  1835. $ret = self::_getTemplate($id, $key, $reg_path, $path, $info);
  1836. if(!$merge || !$override || !is_array($ret))
  1837. {
  1838. return $ret;
  1839. }
  1840. // merge
  1841. $reg_path = 'plugin/'.$plug_name.'/templates/'.$id;
  1842. $path = self::templatePath($plug_name, $id, false);
  1843. $id = str_replace('/', '_', $id);
  1844. $ret_plug = self::_getTemplate($id, $key, $reg_path, $path, $info);
  1845. return (is_array($ret_plug) ? array_merge($ret_plug, $ret) : $ret);
  1846. }
  1847. /**
  1848. * Register sc_style registry
  1849. * @param string $templateId e.g. 'contact/form' or 'contact' for all contact template wrappers
  1850. * @param string $scName [optional] shortcode name - if provided, wrapper (string) for the corresponding code will be returned
  1851. * @return array|string
  1852. */
  1853. public static function templateWrapper($templateId, $scName = null)
  1854. {
  1855. if(!$templateId) return array();
  1856. list($templateId, $templateKey) = explode('/', $templateId, 2);
  1857. $wrapperRegPath = 'templates/wrapper/'.$templateId;
  1858. $wrapper = self::getRegistry($wrapperRegPath);
  1859. if(empty($wrapper) || !is_array($wrapper)) $wrapper = array();
  1860. if($templateKey) $wrapper = (isset($wrapper[$templateKey]) ? $wrapper[$templateKey] : array());
  1861. if(null !== $scName)
  1862. {
  1863. $scName = strtoupper($scName);
  1864. return isset($wrapper[$scName]) ? $wrapper[$scName] : '';
  1865. }
  1866. return $wrapper;
  1867. }
  1868. /**
  1869. * Retrieve/set sc_style array (global shortcode wrapper)
  1870. * @param array $set template defined $sc_style, will be merged with current registry content
  1871. * @return array
  1872. */
  1873. public static function scStyle($set = null)
  1874. {
  1875. $_sc_style = self::getRegistry('shortcodes/sc_style');
  1876. if(!is_array($_sc_style)) $_sc_style = array();
  1877. if(is_array($set) && !empty($set))
  1878. {
  1879. self::setRegistry('shortcodes/sc_style', array_merge($_sc_style, $set));
  1880. }
  1881. return $_sc_style;
  1882. }
  1883. /**
  1884. * Get Template Info array.
  1885. * Note: Available only after getTemplate()/getCoreTemplate() call
  1886. *
  1887. * @param string $plug_name if null - search for core template
  1888. * @param string $id
  1889. * @param string $key
  1890. * @param boolean $override
  1891. * @param boolean $merge
  1892. * @return array
  1893. */
  1894. public function getTemplateInfo($plug_name = null, $id, $key = null, $override = true, $merge = false)
  1895. {
  1896. if($plug_name)
  1897. {
  1898. $ret = self::getTemplate($plug_name, $id, null, $override, $merge, true);
  1899. }
  1900. else
  1901. {
  1902. $ret = self::getCoreTemplate($id, null, $override, $merge, true);
  1903. }
  1904. if($key && isset($ret[$key]) && is_array($ret[$key]))
  1905. {
  1906. return $ret[$key];
  1907. }
  1908. return $ret;
  1909. }
  1910. /**
  1911. * Return a list of available template IDs for a plugin(eg. $MYTEMPLATE['my_id'] -> array('id' => 'My Id'))
  1912. *
  1913. * FIXME - the format of $allinfo=true array is not usable at all, convert it so that it's compatible with e_form::selectbox() method
  1914. *
  1915. * @param string $plugin_name
  1916. * @param string $template_id [optional] if different from $plugin_name;
  1917. * @param mixed $where true - current theme, 'admin' - admin theme, 'front' (default) - front theme
  1918. * @param boolean $merge merge theme with core/plugin layouts, default is false
  1919. * @param boolean $allinfo reutrn nimerical array of templates and all available template information
  1920. * @return array
  1921. */
  1922. public static function getLayouts($plugin_name, $template_id = '', $where = 'front', $filter_mask = '', $merge = false, $allinfo = true)
  1923. {
  1924. if(!$plugin_name) // Core template
  1925. {
  1926. $tmp = self::getCoreTemplate($template_id, null, $where, $merge);
  1927. $tmp_info = self::getTemplateInfo(null, $template_id, null, $where, $merge);
  1928. }
  1929. else // Plugin template
  1930. {
  1931. $id = (!$template_id) ? $plugin_name : $template_id;
  1932. $tmp = self::getTemplate($plugin_name, $id, null, $where, $merge);
  1933. $tmp_info = self::getTemplateInfo($plugin_name, $id, null, $where, $merge);
  1934. }
  1935. $templates = array();
  1936. if(!$filter_mask)
  1937. {
  1938. $filter_mask = array();
  1939. }
  1940. elseif(!is_array($filter_mask))
  1941. {
  1942. $filter_mask = array($filter_mask);
  1943. }
  1944. foreach($tmp as $key => $val)
  1945. {
  1946. $match = true;
  1947. if($filter_mask)
  1948. {
  1949. $match = false;
  1950. foreach ($filter_mask as $mask)
  1951. {
  1952. if(preg_match($mask, $key)) //e.g. retrieve only keys starting with 'layout_'
  1953. {
  1954. $match = true;
  1955. break;
  1956. }
  1957. }
  1958. if(!$match) continue;
  1959. }
  1960. if(isset($tmp_info[$key]))
  1961. {
  1962. $templates[$key] = defset($tmp_info[$key]['title'], $tmp_info[$key]['title']);
  1963. continue;
  1964. }
  1965. $templates[$key] = implode(' ', array_map('ucfirst', explode('_', $key))); //TODO add LANS?
  1966. }
  1967. return ($allinfo ? array($templates, $tmp_info) : $templates);
  1968. }
  1969. /**
  1970. * More abstsract template loader, used
  1971. * internal in {@link getTemplate()} and {@link getCoreTemplate()} methods
  1972. * If $info is set to true, only template informational array will be returned
  1973. *
  1974. * @param string $id
  1975. * @param string|null $key
  1976. * @param string $reg_path
  1977. * @param string $path
  1978. * @param boolean $info
  1979. * @return string|array
  1980. */
  1981. public static function _getTemplate($id, $key, $reg_path, $path, $info = false)
  1982. {
  1983. $regPath = $reg_path;
  1984. $var = strtoupper($id).'_TEMPLATE';
  1985. $regPathInfo = $reg_path.'/info';
  1986. $var_info = strtoupper($id).'_INFO';
  1987. $wrapper = strtoupper($id).'_WRAPPER'; // see contact_template.php
  1988. $wrapperRegPath = 'templates/wrapper/'.$id;
  1989. //FIXME XXX URGENT - Add support for _WRAPPER and $sc_style BC. - save in registry and retrieve in getScBatch()?
  1990. // Use: list($pre,$post) = explode("{---}",$text,2);
  1991. if(null === self::getRegistry($regPath))
  1992. {
  1993. (deftrue('E107_DEBUG_LEVEL') ? include_once($path) : @include_once($path));
  1994. self::setRegistry($regPath, (isset($$var) ? $$var : array()));
  1995. // sc_style not a global anymore and uppercase
  1996. if(isset($SC_WRAPPER))
  1997. {
  1998. self::scStyle($SC_WRAPPER);
  1999. }
  2000. // ID_WRAPPER support
  2001. if(isset($$wrapper) && !empty($$wrapper) && is_array($$wrapper))
  2002. {
  2003. self::setRegistry($wrapperRegPath, $$wrapper);
  2004. }
  2005. }
  2006. if(null === self::getRegistry($regPathInfo))
  2007. {
  2008. self::setRegistry($regPathInfo, (isset($$var_info) && is_array($$var_info) ? $$var_info : array()));
  2009. }
  2010. $ret = (!$info ? self::getRegistry($regPath) : self::getRegistry($regPathInfo));
  2011. if(!$key)
  2012. {
  2013. return $ret;
  2014. }
  2015. return ($ret && is_array($ret) && isset($ret[$key]) ? $ret[$key] : '');
  2016. }
  2017. /**
  2018. * Load language file, replacement of include_lan()
  2019. *
  2020. * @param string $path
  2021. * @param boolean $force
  2022. * @return string
  2023. */
  2024. public static function includeLan($path, $force = false)
  2025. {
  2026. if (!is_readable($path))
  2027. {
  2028. if (self::getPref('noLanguageSubs') || (e_LANGUAGE == 'English'))
  2029. {
  2030. return FALSE;
  2031. }
  2032. self::getMessage()->addDebug("Couldn't load language file: ".$path);
  2033. $path = str_replace(e_LANGUAGE, 'English', $path);
  2034. if(!is_readable($path))
  2035. {
  2036. return;
  2037. }
  2038. }
  2039. $adminLanguage = self::getPref('adminlanguage');
  2040. if(e_ADMIN_AREA && vartrue($adminLanguage))
  2041. {
  2042. $path = str_replace(e_LANGUAGE, $adminLanguage, $path);
  2043. }
  2044. $ret = ($force) ? include($path) : include_once($path);
  2045. return (isset($ret)) ? $ret : "";
  2046. }
  2047. /**
  2048. * Simplify importing of core Language files.
  2049. * All inputs are sanitized.
  2050. * Core Exceptions as e_LANGUAGE.'.php' and e_LANGUAGE.'_custom.php' are manually loaded. (see class2.php)
  2051. *
  2052. * Examples:
  2053. * <code><?php
  2054. * // import defeinitions from /e107_languages/[CurrentLanguage]/lan_comment.php</code>
  2055. * e107::coreLan('comment');
  2056. *
  2057. * // import defeinitions from /e107_languages/[CurrentLanguage]/admin/lan_banlist.php
  2058. * e107::coreLan('banlist', true);
  2059. * </code>
  2060. *
  2061. * @param string $fname filename without the extension part (e.g. 'comment')
  2062. * @param boolean $admin true if it's an administration language file
  2063. * @return void
  2064. */
  2065. public static function coreLan($fname, $admin = false)
  2066. {
  2067. $cstring = 'corelan/'.e_LANGUAGE.'_'.$fname.($admin ? '_admin' : '_front');
  2068. if(e107::getRegistry($cstring)) return;
  2069. $fname = ($admin ? 'admin/' : '').'lan_'.preg_replace('/[^\w]/', '', trim($fname, '/')).'.php';
  2070. $path = e_LANGUAGEDIR.e_LANGUAGE.'/'.$fname;
  2071. e107::setRegistry($cstring, true);
  2072. self::includeLan($path, false);
  2073. }
  2074. /**
  2075. * Simplify importing of plugin Language files (following e107 plugin structure standards).
  2076. * All inputs are sanitized.
  2077. *
  2078. * Examples:
  2079. * <code><?php
  2080. * // import defeinitions from /e107_plugins/forum/languages/[CurrentLanguage]/lan_forum.php
  2081. * e107::plugLan('forum', 'lan_forum');
  2082. *
  2083. * // import defeinitions from /e107_plugins/featurebox/languages/[CurrentLanguage]_admin_featurebox.php
  2084. * // OR /e107_plugins/featurebox/languages/[CurrentLanguage]/[CurrentLanguage]_admin_featurebox.php (auto-detected)
  2085. * e107::plugLan('featurebox', 'admin_featurebox', true);
  2086. *
  2087. * // import defeinitions from /e107_plugins/myplug/languages/[CurrentLanguage]_front.php
  2088. * e107::plugLan('myplug');
  2089. *
  2090. * // import defeinitions from /e107_plugins/myplug/languages/[CurrentLanguage]_admin.php
  2091. * e107::plugLan('myplug', true);
  2092. *
  2093. * // import defeinitions from /e107_plugins/myplug/languages/[CurrentLanguage]/admin/common.php
  2094. * e107::plugLan('myplug', 'admin/common');
  2095. * </code>
  2096. *
  2097. * @param string $plugin plugin name
  2098. * @param string $fname filename without the extension part (e.g. 'common')
  2099. * @param boolean $flat false (default, preferred) Language folder structure; true - prepend Language to file name
  2100. * @return void
  2101. */
  2102. public static function plugLan($plugin, $fname = '', $flat = false)
  2103. {
  2104. $cstring = 'pluglan/'.e_LANGUAGE.'_'.$plugin.'_'.$fname.($flat ? '_1' : '_0');
  2105. if(e107::getRegistry($cstring)) return;
  2106. $plugin = preg_replace('/[^\w]/', '', $plugin);
  2107. if($fname && is_string($fname))
  2108. {
  2109. $fname = e_LANGUAGE.($flat ? '_' : '/').preg_replace('#[^\w/]#', '', trim($fname, '/'));
  2110. }
  2111. elseif($fname === true) // admin file.
  2112. {
  2113. //$fname = "admin/".e_LANGUAGE;
  2114. $fname = e_LANGUAGE."_admin";
  2115. }
  2116. else
  2117. {
  2118. // $fname = e_LANGUAGE;
  2119. $fname = e_LANGUAGE."_front";
  2120. }
  2121. if($flat === true && is_dir(e_PLUGIN.$plugin."/languages/".e_LANGUAGE)) // support for alt_auth/languages/English/English_log.php etc.
  2122. {
  2123. $path = e_PLUGIN.$plugin.'/languages/'.e_LANGUAGE.'/'.$fname.'.php';
  2124. }
  2125. else
  2126. {
  2127. $path = e_PLUGIN.$plugin.'/languages/'.$fname.'.php';
  2128. }
  2129. if(E107_DBG_INCLUDES)
  2130. {
  2131. e107::getMessage()->addDebug("Attempting to Load: ".$path);
  2132. }
  2133. e107::setRegistry($cstring, true);
  2134. self::includeLan($path, false);
  2135. }
  2136. /**
  2137. * Simplify importing of theme Language files (following e107 plugin structure standards).
  2138. * All inputs are sanitized.
  2139. *
  2140. * Examples:
  2141. * <code><?php
  2142. * // import defeinitions from /e107_themes/[CurrentTheme]/languages/[CurrentLanguage]/lan.php
  2143. * e107::themeLan('lan');
  2144. *
  2145. * // import defeinitions from /e107_themes/[currentTheme]/languages/[CurrentLanguage].php
  2146. * e107::themeLan();
  2147. *
  2148. * // import defeinitions from /e107_themes/[currentTheme]/languages/[CurrentLanguage]_lan.php
  2149. * e107::themeLan('lan', null, true);
  2150. *
  2151. * // import defeinitions from /e107_themes/[currentTheme]/languages/[CurrentLanguage]/admin/lan.php
  2152. * e107::themeLan('admin/lan');
  2153. *
  2154. * // import defeinitions from /e107_themes/some_theme/languages/[CurrentLanguage].php
  2155. * e107::themeLan('', 'some_theme');
  2156. * </code>
  2157. *
  2158. * @param string $fname filename without the extension part (e.g. 'common' for common.php)
  2159. * @param string $theme theme name, if null current theme will be used
  2160. * @param boolean $flat false (default, preferred) Language folder structure; true - prepend Language to file name
  2161. * @return void
  2162. */
  2163. public static function themeLan($fname = '', $theme = null, $flat = false)
  2164. {
  2165. if(null === $theme) $theme = THEME.'/languages/';
  2166. else $theme = e_THEME.preg_replace('#[^\w/]#', '', $theme).'/languages/';
  2167. $cstring = 'themelan/'.$theme.$fname.($flat ? '_1' : '_0');
  2168. if(e107::getRegistry($cstring)) return;
  2169. if($fname) $fname = e_LANGUAGE.($flat ? '_' : '/').preg_replace('#[^\w/]#', '', trim($fname, '/'));
  2170. else $fname = e_LANGUAGE;
  2171. $path = $theme.$fname.'.php';
  2172. if(E107_DBG_INCLUDES)
  2173. {
  2174. e107::getMessage()->addDebug("Attempting to Load: ".$path);
  2175. }
  2176. e107::setRegistry($cstring, true);
  2177. self::includeLan($path, false);
  2178. }
  2179. /**
  2180. * PREFERRED Generic Language File Loading Function for use by theme and plugin developers.
  2181. * Language-file equivalent to e107::js, e107::meta and e107::css
  2182. * FIXME disallow themes and plugins named 'core' and 'theme'
  2183. * @param string $type : 'theme' or plugin name
  2184. * @param $string $fname (optional): relative path to the theme or plugin language folder. (same as in the other functions)
  2185. * when missing, [e_LANGUAGE]_front.php will be used, when true [e_LANGUAGE]_admin.php will be used
  2186. * @param $options : Set to True for admin.
  2187. * @example e107::lan('theme'); // Loads THEME."languages/English.php (if English is the current language)
  2188. * @example e107::lan('gallery'); // Loads e_PLUGIN."gallery/languages/English_front.php (if English is the current language)
  2189. * @example e107::lan('gallery', 'admin'); // Loads e_PLUGIN."gallery/languages/English/admin.php (if English is the current language)
  2190. * @example e107::lan('gallery', 'admin', true); // Loads e_PLUGIN."gallery/languages/English_admin.php (if English is the current language)
  2191. * @example e107::lan('gallery', 'admin/example'); // Loads e_PLUGIN."gallery/languages/English/admin/example.php (if English is the current language)
  2192. * @example e107::lan('gallery', true); // Loads e_PLUGIN."gallery/languages/English_admin.php (if English is the current language)
  2193. * @example e107::lan('gallery', "something", true); // Loads e_PLUGIN."gallery/languages/English_something.php (if English is the current language)
  2194. */
  2195. public static function lan($type, $fname = null, $options = null)
  2196. {
  2197. $options = $options ? true : false;
  2198. switch ($type)
  2199. {
  2200. case 'core' :
  2201. self::coreLan($fname, $options);
  2202. break;
  2203. case 'theme' :
  2204. self::themeLan($fname, null, $options);
  2205. break;
  2206. default :
  2207. self::plugLan($type, $fname, $options);
  2208. break;
  2209. }
  2210. }
  2211. /**
  2212. * Generic PREF retrieval Method for use by theme and plugin developers.
  2213. */
  2214. public static function pref($type = 'core', $pname = null, $default = null)
  2215. {
  2216. switch ($type)
  2217. {
  2218. case 'core' :
  2219. return self::getPref($pname, $default);
  2220. break;
  2221. case 'theme' :
  2222. return self::getThemePref($pname, $default);
  2223. break;
  2224. default:
  2225. return self::getPlugPref($type, $pname, $default);
  2226. break;
  2227. }
  2228. }
  2229. /**
  2230. * Experimental static (easy) sef-url creation method (works with e_url.php @see /index.php)
  2231. */
  2232. public static function url($plugin='',$key)
  2233. {
  2234. $tmp = e107::getAddonConfig('e_url');
  2235. if(varset($tmp[$plugin][$key]['sef']))
  2236. {
  2237. return e_HTTP.$tmp[$plugin][$key]['sef'];
  2238. }
  2239. elseif(varset($tmp[$plugin][$key]['redirect']))
  2240. {
  2241. return self::getParser()->replaceConstants($tmp[$plugin][$key]['redirect'],'full');
  2242. }
  2243. return;
  2244. }
  2245. /**
  2246. * Routine looks in standard paths for language files associated with a plugin or
  2247. * theme - primarily for core routines, which won't know for sure where the author has put them.
  2248. * $unitName is the name (directory path) of the plugin or theme
  2249. * $type determines what is to be loaded:
  2250. * - 'runtime' - the standard runtime language file for a plugin
  2251. * - 'admin' - the standard admin language file for a plugin
  2252. * - 'theme' - the standard language file for a plugin (these are usually pretty small, so one is enough)
  2253. * Otherwise, $type is treated as part of a filename within the plugin's language directory,
  2254. * prefixed with the current language.
  2255. * Returns FALSE on failure (not found).
  2256. * Returns the include_once error return if there is one
  2257. * Otherwise returns an empty string.
  2258. * Note - if the code knows precisely where the language file is located, use {@link getLan()}
  2259. * $pref['noLanguageSubs'] can be set TRUE to prevent searching for the English files if
  2260. * the files for the current site language don't exist.
  2261. *
  2262. * @param string $unitName
  2263. * @param string $type predefined types are runtime|admin|theme
  2264. * @return boolean|string
  2265. */
  2266. public static function loadLanFiles($unitName, $type='runtime')
  2267. {
  2268. //global $pref;
  2269. switch ($type)
  2270. {
  2271. case 'runtime' :
  2272. $searchPath[1] = e_PLUGIN.$unitName.'/languages/'.e_LANGUAGE.'_'.$unitName.'.php';
  2273. $searchPath[2] = e_PLUGIN.$unitName.'/languages/'.e_LANGUAGE.'/'.$unitName.'.php';
  2274. $searchPath[3] = e_PLUGIN.$unitName.'/languages/'.e_LANGUAGE.'.php'; // menu language file.
  2275. break;
  2276. case 'admin' :
  2277. $adminLan = vartrue(self::getPref('adminlanguage'), e_LANGUAGE);
  2278. $searchPath[1] = e_PLUGIN.$unitName.'/languages/'.$adminLan.'_admin_'.$unitName.'.php';
  2279. $searchPath[2] = e_PLUGIN.$unitName.'/languages/'.$adminLan.'/'.'admin_'.$unitName.'.php';
  2280. $searchPath[3] = e_PLUGIN.$unitName.'/languages/'.$adminLan.'/admin/'.$adminLan.'.php';
  2281. $searchPath[4] = e_PLUGIN.$unitName.'/languages/'.$adminLan.'/'.$adminLan.'_admin.php'; // Preferred.
  2282. $searchPath[5] = e_PLUGIN.$unitName.'/languages/'.$adminLan.'_admin.php'; // consistent with English_global.php, English_log.php etc.
  2283. break;
  2284. case 'theme' :
  2285. $searchPath[1] = e_THEME.$unitName.'/languages/'.e_LANGUAGE.'_'.$unitName.'.php';
  2286. $searchPath[2] = e_THEME.$unitName.'/languages/'.e_LANGUAGE.'/'.$unitName.'.php';
  2287. break;
  2288. default :
  2289. $searchPath[1] = e_PLUGIN.$unitName.'/languages/'.e_LANGUAGE.'_'.$type.'.php';
  2290. $searchPath[2] = e_PLUGIN.$unitName.'/languages/'.e_LANGUAGE.'/'.$type.'.php';
  2291. }
  2292. foreach ($searchPath as $s) // Look for files in current language first - should usually be found
  2293. {
  2294. if (is_readable($s))
  2295. {
  2296. $ret = include_once($s);
  2297. return (isset($ret)) ? $ret : "";
  2298. }
  2299. }
  2300. if (e107::getPref('noLanguageSubs') || (e_LANGUAGE == 'English'))
  2301. {
  2302. return FALSE; // No point looking for the English files twice
  2303. }
  2304. foreach ($searchPath as $s) // Now look for the English files
  2305. {
  2306. $s = str_replace(e_LANGUAGE, 'English', $s);
  2307. if (is_readable($s))
  2308. {
  2309. $ret = include_once($s);
  2310. return (isset($ret)) ? $ret : "";
  2311. }
  2312. }
  2313. return FALSE; // Nothing found
  2314. }
  2315. /**
  2316. * Prepare e107 environment
  2317. * This is done before e107_dirs initilization and [TODO] config include
  2318. * @param bool $checkS basic security check (0.7 like), will be extended in the future
  2319. * @return e107
  2320. */
  2321. public function prepare_request($checkS = true)
  2322. {
  2323. // Block common bad agents / queries / php issues.
  2324. array_walk($_SERVER, array('self', 'filter_request'), '_SERVER');
  2325. if (isset($_GET)) array_walk($_GET, array('self', 'filter_request'), '_GET');
  2326. if (isset($_POST))
  2327. {
  2328. array_walk($_POST, array('self', 'filter_request'), '_POST');
  2329. reset($_POST); // Change of behaviour in PHP 5.3.17?
  2330. }
  2331. if (isset($_COOKIE)) array_walk($_COOKIE, array('self', 'filter_request'), '_COOKIE');
  2332. if (isset($_REQUEST)) array_walk($_REQUEST, array('self', 'filter_request'), '_REQUEST');
  2333. // A better way to detect an AJAX request. No need for "ajax_used=1";
  2334. if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
  2335. {
  2336. define('e_AJAX_REQUEST', true);
  2337. }
  2338. else
  2339. {
  2340. define('e_AJAX_REQUEST', isset($_REQUEST['ajax_used']));
  2341. }
  2342. unset($_REQUEST['ajax_used']); // removed because it's auto-appended from JS (AJAX), could break something...
  2343. //$GLOBALS['_E107'] - minimal mode - here because of the e_AJAX_REQUEST
  2344. if(isset($GLOBALS['_E107']['minimal']) || e_AJAX_REQUEST || deftrue('e_MINIMAL'))
  2345. {
  2346. $_e107vars = array('forceuserupdate', 'online', 'theme', 'menus', 'prunetmp');
  2347. $GLOBALS['_E107']['minimal'] = true;
  2348. // lame but quick - allow online when ajax request only, additonal checks are made in e_online class
  2349. if(e_AJAX_REQUEST && !isset($GLOBALS['_E107']['online']) && !isset($GLOBALS['_E107']['minimal'])) unset($_e107vars[1]);
  2350. foreach($_e107vars as $v)
  2351. {
  2352. $noname = 'no_'.$v;
  2353. if(!isset($GLOBALS['_E107'][$v]))
  2354. {
  2355. $GLOBALS['_E107'][$noname] = 1;
  2356. }
  2357. unset($GLOBALS['_E107'][$v]);
  2358. }
  2359. }
  2360. // we can now start use $e107->_E107
  2361. if(isset($GLOBALS['_E107']) && is_array($GLOBALS['_E107'])) $this->_E107 = & $GLOBALS['_E107'];
  2362. // remove ajax_used=1 from query string to avoid SELF problems, ajax should always be detected via e_AJAX_REQUEST constant
  2363. $_SERVER['QUERY_STRING'] = trim(str_replace(array('ajax_used=1', '&&'), array('', '&'), $_SERVER['QUERY_STRING']), '&');
  2364. /* PathInfo doesn't break anything, URLs should be always absolute. Disabling the below forever.
  2365. // e107 uses relative url's, which are broken by "pretty" URL's. So for now we don't support / after .php
  2366. if(($pos = strpos($_SERVER['PHP_SELF'], '.php/')) !== false) // redirect bad URLs to the correct one.
  2367. {
  2368. $new_url = substr($_SERVER['PHP_SELF'], 0, $pos+4);
  2369. $new_loc = ($_SERVER['QUERY_STRING']) ? $new_url.'?'.$_SERVER['QUERY_STRING'] : $new_url;
  2370. header('Location: '.$new_loc);
  2371. exit();
  2372. }
  2373. */
  2374. // If url contains a .php in it, PHP_SELF is set wrong (imho), affecting all paths. We need to 'fix' it if it does.
  2375. $_SERVER['PHP_SELF'] = (($pos = stripos($_SERVER['PHP_SELF'], '.php')) !== false ? substr($_SERVER['PHP_SELF'], 0, $pos+4) : $_SERVER['PHP_SELF']);
  2376. // setup some php options
  2377. e107::ini_set('magic_quotes_runtime', 0);
  2378. e107::ini_set('magic_quotes_sybase', 0);
  2379. e107::ini_set('arg_separator.output', '&amp;');
  2380. e107::ini_set('session.use_only_cookies', 1);
  2381. e107::ini_set('session.use_trans_sid', 0);
  2382. // Ensure thet '.' is the first part of the include path
  2383. $inc_path = explode(PATH_SEPARATOR, ini_get('include_path'));
  2384. if($inc_path[0] != '.')
  2385. {
  2386. array_unshift($inc_path, '.');
  2387. $inc_path = implode(PATH_SEPARATOR, $inc_path);
  2388. e107::ini_set('include_path', $inc_path);
  2389. }
  2390. unset($inc_path);
  2391. return $this;
  2392. }
  2393. /**
  2394. * Filter User Input - used by array_walk in prepare_request method above.
  2395. * @param string $input array value
  2396. * @param string $key array key
  2397. * @param string $type array type _SESSION, _GET etc.
  2398. * @return
  2399. */
  2400. public static function filter_request($input,$key,$type,$base64=FALSE)
  2401. {
  2402. if(is_string($input) && trim($input)=="")
  2403. {
  2404. return;
  2405. }
  2406. if (is_array($input))
  2407. {
  2408. return array_walk($input, array('self', 'filter_request'), $type);
  2409. }
  2410. if($type == "_POST" || ($type == "_SERVER" && ($key == "QUERY_STRING")))
  2411. {
  2412. if($type == "_POST" && ($base64 == FALSE))
  2413. {
  2414. $input = preg_replace("/(\[code\])(.*?)(\[\/code\])/is","",$input);
  2415. }
  2416. $regex = "/(document\.location|document\.write|base64_decode|chr|php_uname|fwrite|fopen|fputs|passthru|popen|proc_open|shell_exec|exec|proc_nice|proc_terminate|proc_get_status|proc_close|pfsockopen|apache_child_terminate|posix_kill|posix_mkfifo|posix_setpgid|posix_setsid|posix_setuid|phpinfo) *?\((.*) ?\;?/i";
  2417. if(preg_match($regex,$input))
  2418. {
  2419. header('HTTP/1.0 400 Bad Request', true, 400);
  2420. exit();
  2421. }
  2422. if(preg_match("/system *?\((.*);.*\)/i",$input))
  2423. {
  2424. header('HTTP/1.0 400 Bad Request', true, 400);
  2425. exit();
  2426. }
  2427. $regex = "/(wget |curl -o |fetch |lwp-download|onmouse)/i";
  2428. if(preg_match($regex,$input))
  2429. {
  2430. header('HTTP/1.0 400 Bad Request', true, 400);
  2431. exit();
  2432. }
  2433. }
  2434. if($type == "_SERVER")
  2435. {
  2436. if(($key == "QUERY_STRING") && (
  2437. strpos(strtolower($input),"../../")!==FALSE
  2438. || strpos(strtolower($input),"=http")!==FALSE
  2439. || strpos(strtolower($input),strtolower("http%3A%2F%2F"))!==FALSE
  2440. || strpos(strtolower($input),"php:")!==FALSE
  2441. || strpos(strtolower($input),"data:")!==FALSE
  2442. || strpos(strtolower($input),strtolower("%3Cscript"))!==FALSE
  2443. ))
  2444. {
  2445. header('HTTP/1.0 400 Bad Request', true, 400);
  2446. exit();
  2447. }
  2448. if(($key == "HTTP_USER_AGENT") && strpos($input,"libwww-perl")!==FALSE)
  2449. {
  2450. header('HTTP/1.0 400 Bad Request', true, 400);
  2451. exit();
  2452. }
  2453. }
  2454. if(strpos(str_replace('.', '', $input), '22250738585072011') !== FALSE) // php-bug 53632
  2455. {
  2456. header('HTTP/1.0 400 Bad Request', true, 400);
  2457. exit();
  2458. }
  2459. if($base64 != TRUE)
  2460. {
  2461. self::filter_request(base64_decode($input),$key,$type,TRUE);
  2462. }
  2463. }
  2464. /**
  2465. * Set base system path
  2466. * @return e107
  2467. */
  2468. public function set_base_path($force = null)
  2469. {
  2470. $ssl_enabled = (null !== $force) ? $force : $this->isSecure();//(self::getPref('ssl_enabled') == 1);
  2471. $this->base_path = $ssl_enabled ? $this->https_path : $this->http_path;
  2472. return $this;
  2473. }
  2474. /**
  2475. * Set various system environment constants
  2476. * @return e107
  2477. */
  2478. public function set_constants()
  2479. {
  2480. define('MAGIC_QUOTES_GPC', (ini_get('magic_quotes_gpc') ? true : false));
  2481. define('MPREFIX', $this->getMySQLConfig('prefix')); // mysql prefix
  2482. define('CHARSET', 'utf-8'); // set CHARSET for backward compatibility
  2483. // Define the domain name and subdomain name.
  2484. if(is_numeric(str_replace(".","",$_SERVER['HTTP_HOST'])))
  2485. {
  2486. $domain = FALSE;
  2487. $subdomain = FALSE;
  2488. }
  2489. else
  2490. {
  2491. if(preg_match("/\.?([a-z0-9-]+)(\.(com|net|org|co|me|ltd|plc|gov)\.[a-z]{2})$/i", $_SERVER['HTTP_HOST'], $m)) //eg. mysite.co.uk
  2492. {
  2493. $domain = $m[1].$m[2];
  2494. }
  2495. elseif(preg_match("/\.?([a-z0-9-]+)(\.[a-z]{2,})$/i", $_SERVER['HTTP_HOST'], $m))// eg. .com/net/org/ws/biz/info
  2496. {
  2497. $domain = $m[1].$m[2];
  2498. }
  2499. else
  2500. {
  2501. $domain = FALSE; //invalid domain
  2502. }
  2503. $replace = array(".".$domain,"www.","www",$domain);
  2504. $subdomain = str_replace($replace,'',$_SERVER['HTTP_HOST']);
  2505. }
  2506. define("e_DOMAIN", $domain);
  2507. define("e_SUBDOMAIN",($subdomain) ? $subdomain : FALSE);
  2508. define('e_UC_PUBLIC', 0);
  2509. define('e_UC_MAINADMIN', 250);
  2510. define('e_UC_READONLY', 251);
  2511. define('e_UC_GUEST', 252);
  2512. define('e_UC_MEMBER', 253);
  2513. define('e_UC_ADMIN', 254);
  2514. define('e_UC_NOBODY', 255);
  2515. return $this;
  2516. }
  2517. /**
  2518. * Relaitve server path - set_path() helper
  2519. * @param string $dir
  2520. * @return string
  2521. */
  2522. public function get_override_rel($dir)
  2523. {
  2524. if(isset($this->e107_dirs[$dir.'_SERVER']))
  2525. {
  2526. return $this->e107_dirs[$dir.'_SERVER'];
  2527. }
  2528. $ret = e_BASE.$this->e107_dirs[$dir.'_DIRECTORY'];
  2529. return $ret;
  2530. }
  2531. /**
  2532. * Absolute HTTP path - set_path() helper
  2533. * @param string $dir
  2534. * @return string
  2535. */
  2536. public function get_override_http($dir)
  2537. {
  2538. if(isset($this->e107_dirs[$dir.'_HTTP']))
  2539. {
  2540. return $this->e107_dirs[$dir.'_HTTP'];
  2541. }
  2542. return e_HTTP.$this->e107_dirs[$dir.'_DIRECTORY'];
  2543. }
  2544. /**
  2545. * Set all environment vars and constants
  2546. * FIXME - remove globals
  2547. * @return e107
  2548. */
  2549. public function set_paths()
  2550. {
  2551. // ssl_enabled pref not needed anymore, scheme is auto-detected
  2552. $this->HTTP_SCHEME = 'http';
  2553. if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on')
  2554. {
  2555. $this->HTTP_SCHEME = 'https';
  2556. }
  2557. $path = ""; $i = 0;
  2558. // FIXME - Again, what if someone moves handlers under the webroot?
  2559. if(!self::isCli())
  2560. {
  2561. while (!file_exists("{$path}class2.php"))
  2562. {
  2563. $path .= "../";
  2564. $i++;
  2565. }
  2566. }
  2567. if($_SERVER['PHP_SELF'] == "") { $_SERVER['PHP_SELF'] = $_SERVER['SCRIPT_NAME']; }
  2568. $http_path = dirname($_SERVER['PHP_SELF']);
  2569. $http_path = explode("/", $http_path);
  2570. $http_path = array_reverse($http_path);
  2571. $j = 0;
  2572. while ($j < $i)
  2573. {
  2574. unset($http_path[$j]);
  2575. $j++;
  2576. }
  2577. $http_path = array_reverse($http_path);
  2578. $this->server_path = implode("/", $http_path)."/";
  2579. $this->server_path = $this->fix_windows_paths($this->server_path);
  2580. if ($this->server_path == "//")
  2581. {
  2582. $this->server_path = "/";
  2583. }
  2584. // Absolute file-path of directory containing class2.php
  2585. // define("e_ROOT", realpath(dirname(__FILE__)."/../")."/");
  2586. $e_ROOT = realpath(dirname(__FILE__)."/../");
  2587. if ((substr($e_ROOT,-1) != '/') && (substr($e_ROOT,-1) != '\\') )
  2588. {
  2589. $e_ROOT .= DIRECTORY_SEPARATOR; // Should function correctly on both windows and Linux now.
  2590. }
  2591. define('e_ROOT',$e_ROOT);
  2592. $this->relative_base_path = (!self::isCli()) ? $path : e_ROOT;
  2593. $this->http_path = "http://{$_SERVER['HTTP_HOST']}{$this->server_path}";
  2594. $this->https_path = "https://{$_SERVER['HTTP_HOST']}{$this->server_path}";
  2595. $this->file_path = $path;
  2596. if(!defined('e_HTTP') || !defined('e_ADMIN') )
  2597. {
  2598. define('e_HTTP', $this->server_path); // Directory of site root relative to HTML base directory
  2599. define('e_BASE', $this->relative_base_path);
  2600. // Base dir of web stuff in server terms. e_ROOT should always end with e_HTTP, even if e_HTTP = '/'
  2601. define('SERVERBASE', substr(e_ROOT, 0, -strlen(e_HTTP) + 1));
  2602. if(isset($_SERVER['DOCUMENT_ROOT']))
  2603. {
  2604. define('e_DOCROOT', $_SERVER['DOCUMENT_ROOT']."/");
  2605. }
  2606. else
  2607. {
  2608. define('e_DOCROOT', false);
  2609. }
  2610. //BC temporary fixes
  2611. if (!isset($this->e107_dirs['UPLOADS_SERVER']) && $this->e107_dirs['UPLOADS_DIRECTORY']{0} == "/")
  2612. {
  2613. $this->e107_dirs['UPLOADS_SERVER'] = $this->e107_dirs['UPLOADS_DIRECTORY'];
  2614. }
  2615. if (!isset($this->e107_dirs['DOWNLOADS_SERVER']) && $this->e107_dirs['DOWNLOADS_DIRECTORY']{0} == "/")
  2616. {
  2617. $this->e107_dirs['DOWNLOADS_SERVER'] = $this->e107_dirs['DOWNLOADS_DIRECTORY'];
  2618. }
  2619. //
  2620. // HTTP relative paths
  2621. //
  2622. define('e_ADMIN', $this->get_override_rel('ADMIN'));
  2623. define('e_IMAGE', $this->get_override_rel('IMAGES'));
  2624. define('e_THEME', $this->get_override_rel('THEMES'));
  2625. define('e_PLUGIN', $this->get_override_rel('PLUGINS'));
  2626. define('e_FILE', $this->get_override_rel('FILES'));
  2627. define('e_HANDLER', $this->get_override_rel('HANDLERS'));
  2628. define('e_LANGUAGEDIR', $this->get_override_rel('LANGUAGES'));
  2629. define('e_DOCS', $this->get_override_rel('HELP')); // WILL CHANGE SOON - $this->_get_override_rel('DOCS')
  2630. define('e_HELP', $this->get_override_rel('HELP'));
  2631. define('e_MEDIA', $this->get_override_rel('MEDIA'));
  2632. define('e_MEDIA_FILE', $this->get_override_rel('MEDIA_FILES'));
  2633. define('e_MEDIA_VIDEO', $this->get_override_rel('MEDIA_VIDEOS'));
  2634. define('e_MEDIA_IMAGE', $this->get_override_rel('MEDIA_IMAGES'));
  2635. define('e_MEDIA_ICON', $this->get_override_rel('MEDIA_ICONS'));
  2636. // define('e_MEDIA_AVATAR', $this->get_override_rel('MEDIA_AVATARS'));
  2637. define('e_DOWNLOAD', $this->get_override_rel('DOWNLOADS'));
  2638. define('e_UPLOAD', $this->get_override_rel('UPLOADS'));
  2639. define('e_CORE', $this->get_override_rel('CORE'));
  2640. define('e_SYSTEM', $this->get_override_rel('SYSTEM'));
  2641. define('e_WEB', $this->get_override_rel('WEB'));
  2642. define('e_WEB_JS', $this->get_override_rel('WEB_JS'));
  2643. define('e_WEB_CSS', $this->get_override_rel('WEB_CSS'));
  2644. define('e_WEB_IMAGE', $this->get_override_rel('WEB_IMAGES'));
  2645. // define('e_WEB_PACK', $this->get_override_rel('WEB_PACKS'));
  2646. define('e_CACHE', $this->get_override_rel('CACHE'));
  2647. define('e_CACHE_CONTENT', $this->get_override_rel('CACHE_CONTENT'));
  2648. define('e_CACHE_IMAGE', $this->get_override_rel('CACHE_IMAGE'));
  2649. define('e_CACHE_DB', $this->get_override_rel('CACHE_DB'));
  2650. define('e_CACHE_URL', $this->get_override_rel('CACHE_URL'));
  2651. define('e_LOG', $this->get_override_rel('LOGS'));
  2652. define('e_BACKUP', $this->get_override_rel('BACKUP'));
  2653. define('e_TEMP', $this->get_override_rel('TEMP'));
  2654. define('e_IMPORT', $this->get_override_rel('IMPORT'));
  2655. //
  2656. // HTTP absolute paths
  2657. //
  2658. define("e_ADMIN_ABS", $this->get_override_http('ADMIN'));
  2659. define("e_IMAGE_ABS", $this->get_override_http('IMAGES'));
  2660. define("e_THEME_ABS", $this->get_override_http('THEMES'));
  2661. define("e_PLUGIN_ABS", $this->get_override_http('PLUGINS'));
  2662. define("e_FILE_ABS", $this->get_override_http('FILES')); // Deprecated!
  2663. define("e_DOCS_ABS", $this->get_override_http('DOCS'));
  2664. define("e_HELP_ABS", $this->get_override_http('HELP'));
  2665. define("e_IMPORT_ABS", false);
  2666. // DEPRECATED - not a legal http query now!
  2667. //define("e_HANDLER_ABS", $this->get_override_http('HANDLERS'));
  2668. //define("e_LANGUAGEDIR_ABS", $this->get_override_http('LANGUAGES'));
  2669. //define("e_LOG_ABS", $this->get_override_http('LOGS'));
  2670. define("e_MEDIA_ABS", $this->get_override_http('MEDIA'));
  2671. define('e_MEDIA_FILE_ABS', $this->get_override_http('MEDIA_FILES'));
  2672. define('e_MEDIA_VIDEO_ABS', $this->get_override_http('MEDIA_VIDEOS'));
  2673. define('e_MEDIA_IMAGE_ABS', $this->get_override_http('MEDIA_IMAGES'));
  2674. define('e_MEDIA_ICON_ABS', $this->get_override_http('MEDIA_ICONS'));
  2675. // define('e_MEDIA_AVATAR_ABS', $this->get_override_http('MEDIA_AVATARS'));
  2676. // XXX DISCUSSS - e_JS_ABS, e_CSS_ABS etc is not following the naming standards but they're more usable.
  2677. // Example: e_JS_ABS vs e_WEB_JS_ABS
  2678. //XXX Absolute is assumed.
  2679. define('e_WEB_ABS', $this->get_override_http('WEB'));
  2680. define('e_JS_ABS', $this->get_override_http('WEB_JS'));
  2681. define('e_CSS_ABS', $this->get_override_http('WEB_CSS'));
  2682. // define('e_PACK_ABS', $this->get_override_http('WEB_PACKS'));
  2683. define('e_WEB_IMAGE_ABS', $this->get_override_http('WEB_IMAGES'));
  2684. define('e_JS', $this->get_override_http('WEB_JS')); // ABS Alias
  2685. define('e_CSS', $this->get_override_http('WEB_CSS')); // ABS Alias
  2686. define('e_AVATAR', $this->get_override_rel('AVATARS'));
  2687. define('e_AVATAR_UPLOAD', $this->get_override_rel('AVATARS_UPLOAD'));
  2688. define('e_AVATAR_DEFAULT', $this->get_override_rel('AVATARS_DEFAULT'));
  2689. define('e_AVATAR_ABS', $this->get_override_http('AVATARS'));
  2690. define('e_AVATAR_UPLOAD_ABS', $this->get_override_http('AVATARS_UPLOAD'));
  2691. define('e_AVATAR_DEFAULT_ABS', $this->get_override_http('AVATARS_DEFAULT'));
  2692. // Special
  2693. define('e_BOOTSTRAP', e_WEB."bootstrap/");
  2694. }
  2695. return $this;
  2696. }
  2697. /**
  2698. * Fix Windows server path
  2699. *
  2700. * @param string $path resolved server path
  2701. * @return string fixed path
  2702. */
  2703. function fix_windows_paths($path)
  2704. {
  2705. $fixed_path = str_replace(array('\\\\', '\\'), array('/', '/'), $path);
  2706. $fixed_path = (substr($fixed_path, 1, 2) == ":/" ? substr($fixed_path, 2) : $fixed_path);
  2707. return $fixed_path;
  2708. }
  2709. /**
  2710. * Define e_PAGE, e_SELF, e_ADMIN_AREA and USER_AREA;
  2711. * The following files are assumed to use admin theme:
  2712. * 1. Any file in the admin directory (check for non-plugin added to avoid mismatches)
  2713. * 2. any plugin file starting with 'admin_'
  2714. * 3. any plugin file in a folder called admin/
  2715. * 4. any file that specifies $eplug_admin = TRUE; or ADMIN_AREA = TRUE;
  2716. * NOTE: USER_AREA = true; will force e_ADMIN_AREA to FALSE
  2717. *
  2718. * @param boolean $no_cbrace remove curly brackets from the url
  2719. * @return e107
  2720. */
  2721. public function set_urls($no_cbrace = true)
  2722. {
  2723. //global $PLUGINS_DIRECTORY,$ADMIN_DIRECTORY, $eplug_admin;
  2724. $PLUGINS_DIRECTORY = $this->getFolder('plugins');
  2725. $ADMIN_DIRECTORY = $this->getFolder('admin');
  2726. // Outdated
  2727. /*$requestQry = '';
  2728. $requestUrl = $_SERVER['REQUEST_URI'];
  2729. if(strpos($_SERVER['REQUEST_URI'], '?') !== FALSE)
  2730. list($requestUrl, $requestQry) = explode("?", $_SERVER['REQUEST_URI'], 2); */
  2731. $eplug_admin = vartrue($GLOBALS['eplug_admin'], false);
  2732. // Leave e_SELF BC, use e_REQUEST_SELF instead
  2733. /*// moved after page check - e_PAGE is important for BC
  2734. if($requestUrl && $requestUrl != $_SERVER['PHP_SELF'])
  2735. {
  2736. $_SERVER['PHP_SELF'] = $requestUrl;
  2737. }*/
  2738. $eSelf = $_SERVER['PHP_SELF'] ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_FILENAME'];
  2739. $_self = $this->HTTP_SCHEME.'://'.$_SERVER['HTTP_HOST'].$eSelf;
  2740. if(!deftrue('e_SINGLE_ENTRY'))
  2741. {
  2742. $page = substr(strrchr($_SERVER['PHP_SELF'], '/'), 1);
  2743. define('e_PAGE', $page);
  2744. define('e_SELF', $_self);
  2745. }
  2746. // START New - request uri/url detection, XSS protection
  2747. // TODO - move it to a separate method
  2748. $requestUri = $requestUrl = '';
  2749. if (isset($_SERVER['HTTP_X_REWRITE_URL']))
  2750. {
  2751. // check this first so IIS will catch
  2752. $requestUri = $_SERVER['HTTP_X_REWRITE_URL'];
  2753. $requestUrl = $this->HTTP_SCHEME.'://'.$_SERVER['HTTP_HOST'].$requestUri;
  2754. // fix request uri
  2755. $_SERVER['REQUEST_URI'] = $requestUri;
  2756. }
  2757. elseif (isset($_SERVER['REQUEST_URI']))
  2758. {
  2759. $requestUri = $_SERVER['REQUEST_URI'];
  2760. $requestUrl = $this->HTTP_SCHEME.'://'.$_SERVER['HTTP_HOST'].$requestUri;
  2761. }
  2762. else
  2763. {
  2764. // go back to e_SELF
  2765. $requestUri = $eSelf;
  2766. $requestUrl = $_self;
  2767. if (e_QUERY)
  2768. {
  2769. $requestUri .= '?'.e_QUERY; // TODO e_SINGLE_ENTRY check, separate static method for cleaning QUERY_STRING
  2770. $requestUrl .= '?'.e_QUERY;
  2771. }
  2772. }
  2773. // FIXME - basic security - add url sanitize method to e_parse
  2774. $check = rawurldecode($requestUri); // urlencoded by default
  2775. // a bit aggressive XSS protection... convert to e.g. htmlentities if you are not a bad guy
  2776. $checkregx = $no_cbrace ? '[<>\{\}]' : '[<>]';
  2777. if(preg_match('/'.$checkregx.'/', $check))
  2778. {
  2779. header('HTTP/1.1 403 Forbidden');
  2780. exit;
  2781. }
  2782. // e_MENU fix
  2783. if(e_MENU)
  2784. {
  2785. $requestUri = str_replace('['.e_MENU.']', '', $requestUri);
  2786. $requestUrl = str_replace('['.e_MENU.']', '', $requestUrl);
  2787. parse_str(e_QUERY,$_GET);
  2788. }
  2789. // the last anti-XSS measure, XHTML compliant URL to be used in forms instead e_SELF
  2790. define('e_REQUEST_URL', str_replace(array("'", '"'), array('%27', '%22'), $requestUrl)); // full request url string (including domain)
  2791. define('e_REQUEST_SELF', array_shift(explode('?', e_REQUEST_URL))); // full URL without the QUERY string
  2792. define('e_REQUEST_URI', str_replace(array("'", '"'), array('%27', '%22'), $requestUri)); // absolute http path + query string
  2793. define('e_REQUEST_HTTP', array_shift(explode('?', e_REQUEST_URI))); // SELF URL without the QUERY string and leading domain part
  2794. unset($requestUrl, $requestUri);
  2795. // END request uri/url detection, XSS protection
  2796. // e_SELF has the full HTML path
  2797. $inAdminDir = FALSE;
  2798. $isPluginDir = strpos($_self,'/'.$PLUGINS_DIRECTORY) !== FALSE; // True if we're in a plugin
  2799. $e107Path = str_replace($this->base_path, '', $_self); // Knock off the initial bits
  2800. if (
  2801. (!$isPluginDir && strpos($e107Path, $ADMIN_DIRECTORY) === 0 ) // Core admin directory
  2802. || ($isPluginDir && (strpos(e_PAGE,'_admin.php') !== false || strpos(e_PAGE,'admin_') === 0 || strpos($e107Path, 'admin/') !== FALSE)) // Plugin admin file or directory
  2803. || (varsettrue($eplug_admin) || defsettrue('ADMIN_AREA')) // Admin forced
  2804. || (preg_match('/^\/(.*?)\/user(settings\.php|\/edit)(\?|\/)(\d+)$/i', $_SERVER['REQUEST_URI']) && ADMIN)
  2805. )
  2806. {
  2807. $inAdminDir = TRUE;
  2808. }
  2809. if ($isPluginDir)
  2810. {
  2811. $temp = substr($e107Path, strpos($e107Path, '/') +1);
  2812. $plugDir = substr($temp, 0, strpos($temp, '/'));
  2813. define('e_CURRENT_PLUGIN', $plugDir);
  2814. define('e_PLUGIN_DIR', e_PLUGIN.e_CURRENT_PLUGIN.'/');
  2815. define('e_PLUGIN_DIR_ABS', e_PLUGIN_ABS.e_CURRENT_PLUGIN.'/');
  2816. }
  2817. else
  2818. {
  2819. define('e_CURRENT_PLUGIN', '');
  2820. define('e_PLUGIN_DIR', '');
  2821. define('e_PLUGIN_DIR_ABS', '');
  2822. }
  2823. define('e_ADMIN_AREA', ($inAdminDir && !deftrue('USER_AREA')));
  2824. define('ADMINDIR', $ADMIN_DIRECTORY);
  2825. define('SITEURLBASE', $this->HTTP_SCHEME.'://'.$_SERVER['HTTP_HOST']);
  2826. define('SITEURL', SITEURLBASE.e_HTTP);
  2827. // login/signup
  2828. define('e_SIGNUP', SITEURL.(file_exists(e_BASE.'customsignup.php') ? 'customsignup.php' : 'signup.php'));
  2829. if(!defined('e_LOGIN'))
  2830. {
  2831. define('e_LOGIN', SITEURL.(file_exists(e_BASE.'customlogin.php') ? 'customlogin.php' : 'login.php'));
  2832. }
  2833. return $this;
  2834. }
  2835. /**
  2836. * Set request related constants
  2837. * @param boolean $no_cbrace remove curly brackets from the url
  2838. * @return e107
  2839. */
  2840. public function set_request($no_cbrace = true)
  2841. {
  2842. $inArray = array("'", ';', '/**/', '/UNION/', '/SELECT/', 'AS ');
  2843. if (strpos($_SERVER['PHP_SELF'], 'trackback') === false)
  2844. {
  2845. foreach($inArray as $res)
  2846. {
  2847. if(stristr($_SERVER['QUERY_STRING'], $res))
  2848. {
  2849. die('Access denied.');
  2850. }
  2851. }
  2852. }
  2853. if (strpos($_SERVER['QUERY_STRING'], ']') && preg_match('#\[(.*?)](.*)#', $_SERVER['QUERY_STRING'], $matches))
  2854. {
  2855. define('e_MENU', $matches[1]);
  2856. $e_QUERY = $matches[2];
  2857. }
  2858. else
  2859. {
  2860. define('e_MENU', '');
  2861. $e_QUERY = $_SERVER['QUERY_STRING'];
  2862. }
  2863. if ($no_cbrace) $e_QUERY = str_replace(array('{', '}', '%7B', '%7b', '%7D', '%7d'), '', rawurldecode($e_QUERY));
  2864. $e_QUERY = htmlentities(self::getParser()->post_toForm($e_QUERY));
  2865. // e_QUERY SHOULD NOT BE DEFINED IF IN SNIGLE ENTRY MODE OR ALL URLS WILL BE BROKEN - it's defined later within the the router
  2866. if(!deftrue("e_SINGLE_ENTRY"))
  2867. {
  2868. define('e_QUERY', $e_QUERY);
  2869. $_SERVER['QUERY_STRING'] = e_QUERY;
  2870. }
  2871. define('e_TBQS', $_SERVER['QUERY_STRING']);
  2872. }
  2873. /**
  2874. * Basic implementation of Browser cache control per user session. Awaiting improvement in future versions
  2875. * If no argument is passed it returns
  2876. * boolean (if current page is cacheable).
  2877. * If string is passed, it's asumed to be aboslute request path (e_REQUEST_URI alike)
  2878. * If true is passed, e_REQUEST_URI is registered
  2879. */
  2880. public static function canCache($set = null)
  2881. {
  2882. $_data = e107::getSession()->get('__sessionBrowserCache');
  2883. if(!is_array($_data)) $_data = array();
  2884. if(null === $set)
  2885. {
  2886. return in_array(e_REQUEST_URI, $_data);
  2887. }
  2888. // remove e_REQUEST_URI from the set
  2889. if(false === $set)
  2890. {
  2891. $check = array_search(e_REQUEST_URI, $_data);
  2892. if(false !== $check)
  2893. {
  2894. unset($_data[$check]);
  2895. e107::getSession()->set('__sessionBrowserCache', $_data);
  2896. return;
  2897. }
  2898. }
  2899. if(true === $set)
  2900. {
  2901. $set = e_REQUEST_URI;
  2902. }
  2903. if(empty($set) || !is_string($set) || in_array($set, $_data)) return;
  2904. $_data[] = $set;
  2905. e107::getSession()->set('__sessionBrowserCache', array_unique($_data));
  2906. }
  2907. /**
  2908. * Check if current request is secure (https)
  2909. * @return boolean TRUE if https, FALSE if http
  2910. */
  2911. public function isSecure()
  2912. {
  2913. return ($this->HTTP_SCHEME === 'https');
  2914. }
  2915. /**
  2916. * Check if current user is banned
  2917. *
  2918. * Generates the queries to interrogate the ban list, then calls $this->check_ban().
  2919. * If the user is banned, $check_ban() never returns - so a return from this routine indicates a non-banned user.
  2920. * FIXME - moved to ban helper, replace all calls
  2921. * @return void
  2922. */
  2923. /* No longer required - moved to eIPHelper class
  2924. public function ban()
  2925. {
  2926. } */
  2927. /**
  2928. * Check the banlist table. $query is used to determine the match.
  2929. * If $do_return, will always return with ban status - TRUE for OK, FALSE for banned.
  2930. * If return permitted, will never display a message for a banned user; otherwise will display any message then exit
  2931. * FIXME - moved to ban helper, replace all calls
  2932. *
  2933. *
  2934. * @param string $query
  2935. * @param boolean $show_error
  2936. * @param boolean $do_return
  2937. * @return boolean
  2938. */
  2939. /* No longer required - moved to eIPHelper class
  2940. public function check_ban($query, $show_error = TRUE, $do_return = FALSE)
  2941. {
  2942. } */
  2943. /**
  2944. * Add an entry to the banlist. $bantype = 1 for manual, 2 for flooding, 4 for multiple logins
  2945. * Returns TRUE if ban accepted.
  2946. * Returns FALSE if ban not accepted (i.e. because on whitelist, or invalid IP specified)
  2947. * FIXME - moved to IP handler, replace all calls
  2948. * @param string $bantype
  2949. * @param string $ban_message
  2950. * @param string $ban_ip
  2951. * @param integer $ban_user
  2952. * @param string $ban_notes
  2953. *
  2954. * @return boolean check result
  2955. */
  2956. /*
  2957. public function add_ban($bantype, $ban_message = '', $ban_ip = '', $ban_user = 0, $ban_notes = '')
  2958. {
  2959. return e107::getIPHandler()->add_ban($bantype, $ban_message, $ban_ip, $ban_user, $ban_notes);
  2960. } */
  2961. /**
  2962. * Get the current user's IP address
  2963. * returns the address in internal 'normalised' IPV6 format - so most code should continue to work provided the DB Field is big enougn
  2964. * FIXME - call ipHandler directly (done for core - left temporarily for BC)
  2965. * @return string
  2966. */
  2967. public function getip()
  2968. {
  2969. return e107::getIPHandler()->getIP(FALSE);
  2970. }
  2971. /**
  2972. * Encode an IP address to internal representation. Returns string if successful; FALSE on error
  2973. * Default separates fields with ':'; set $div='' to produce a 32-char packed hex string
  2974. * FIXME - moved to ipHandler - check for calls elsewhere
  2975. * @param string $ip
  2976. * @param string $div divider
  2977. * @return string encoded IP
  2978. */
  2979. public function ipEncode($ip, $div = ':')
  2980. {
  2981. return e107::getIPHandler()->ipEncode($ip);
  2982. }
  2983. /**
  2984. * Takes an encoded IP address - returns a displayable one
  2985. * Set $IP4Legacy TRUE to display 'old' (IPv4) addresses in the familiar dotted format,
  2986. * FALSE to display in standard IPV6 format
  2987. * Should handle most things that can be thrown at it.
  2988. * FIXME - moved to ipHandler - check for calls elsewhere - core done; left temporarily for BC
  2989. * @param string $ip encoded IP
  2990. * @param boolean $IP4Legacy
  2991. * @return string decoded IP
  2992. */
  2993. public function ipdecode($ip, $IP4Legacy = TRUE)
  2994. {
  2995. return e107::getIPHandler()->ipDecode($ip, $IP4Legacy);
  2996. }
  2997. /**
  2998. * Given a string which may be IP address, email address etc, tries to work out what it is
  2999. * Movet to eIPHandler class
  3000. * FIXME - moved to ipHandler - check for calls elsewhere
  3001. * @param string $string
  3002. * @return string ip|email|url|ftp|unknown
  3003. */
  3004. /*
  3005. public function whatIsThis($string)
  3006. {
  3007. //return e107::getIPHandler()->whatIsThis($string);
  3008. } */
  3009. /**
  3010. * Retrieve & cache host name
  3011. *
  3012. * @param string $ip_address
  3013. * @return string host name
  3014. * FIXME - moved to ipHandler - check for calls elsewhere
  3015. */
  3016. /*
  3017. public function get_host_name($ip_address)
  3018. {
  3019. } */
  3020. /**
  3021. * MOVED TO eHelper::parseMemorySize()
  3022. * FIXME - find all calls, replace with eHelper::parseMemorySize() (once eHelper lives in a separate file)
  3023. *
  3024. * @param integer $size
  3025. * @param integer $dp
  3026. * @return string formatted size
  3027. */
  3028. public function parseMemorySize($size, $dp = 2)
  3029. {
  3030. return eHelper::parseMemorySize($size, $dp);
  3031. }
  3032. /**
  3033. * Removed, see eHelper::getMemoryUsage()
  3034. * Get the current memory usage of the code
  3035. * If $separator argument is null, raw data (array) will be returned
  3036. *
  3037. * @param null|string $separator
  3038. * @return string|array memory usage
  3039. */
  3040. /*
  3041. public function get_memory_usage($separator = '/')
  3042. {
  3043. return eHelper::getMemoryUsage($separator);
  3044. }*/
  3045. /**
  3046. * Check if plugin is installed
  3047. * @param string $plugname
  3048. * @return boolean
  3049. */
  3050. public static function isInstalled($plugname)
  3051. {
  3052. // Could add more checks here later if appropriate
  3053. return self::getConfig()->isData('plug_installed/'.$plugname);
  3054. }
  3055. /**
  3056. * Safe way to set ini var
  3057. * @param string $var
  3058. * @param string $value
  3059. * @return TBD
  3060. */
  3061. public static function ini_set($var, $value)
  3062. {
  3063. if (function_exists('ini_set'))
  3064. {
  3065. return ini_set($var, $value);
  3066. }
  3067. return false;
  3068. }
  3069. /**
  3070. * Register autoload function (string) or static class method - array('ClassName', 'MethodName')
  3071. * @param string|array $function
  3072. */
  3073. public static function autoload_register($function, $prepend = false)
  3074. {
  3075. if(!$prepend || false === ($registered = spl_autoload_functions()))
  3076. {
  3077. return spl_autoload_register($function);
  3078. }
  3079. foreach ($registered as $r)
  3080. {
  3081. spl_autoload_unregister($r);
  3082. }
  3083. $result = spl_autoload_register($function);
  3084. foreach ($registered as $r)
  3085. {
  3086. if(!spl_autoload_register($r)) $result = false;
  3087. }
  3088. return $result;
  3089. }
  3090. /**
  3091. * Former __autoload, generic core autoload logic
  3092. *
  3093. * Magic class autoload.
  3094. * We are raising plugin structure standard here - plugin auto-loading works ONLY if
  3095. * classes live inside 'includes' folder.
  3096. * Example: plugin_myplug_admin_ui ->
  3097. * <code>
  3098. * <?php
  3099. * // __autoload() will look in e_PLUGIN.'myplug/includes/admin/ui.php for this class
  3100. * // e_admin_ui is core handler, so it'll be autoloaded as well
  3101. * class plugin_myplug_admin_ui extends e_admin_ui
  3102. * {
  3103. *
  3104. * }
  3105. *
  3106. * // __autoload() will look in e_PLUGIN.'myplug/shortcodes/my_shortcodes.php for this class
  3107. * // e_admin_ui is core handler, so it'll be autoloaded as well
  3108. * class plugin_myplug_my_shortcodes extends e_admin_ui
  3109. * {
  3110. *
  3111. * }
  3112. * </code>
  3113. * We use now spl_autoload[_*] for core autoloading (PHP5 > 5.1.2)
  3114. * TODO - at this time we could create e107 version of spl_autoload_register - e_event->register/trigger('autoload')
  3115. *
  3116. * @todo plugname/e_shortcode.php auto-detection (hard, near impossible at this time) - we need 'plugin_' prefix to
  3117. * distinguish them from the core batches
  3118. *
  3119. * @param string $className
  3120. * @return void
  3121. */
  3122. public static function autoload($className)
  3123. {
  3124. //Security...
  3125. if (strpos($className, '/') !== false)
  3126. {
  3127. return;
  3128. }
  3129. $tmp = explode('_', $className);
  3130. $filename = '';
  3131. //echo 'autoloding...'.$className.'<br />';
  3132. switch($tmp[0])
  3133. {
  3134. case 'plugin': // plugin handlers/shortcode batches
  3135. array_shift($tmp); // remove 'plugin'
  3136. $end = array_pop($tmp); // check for 'shortcodes' end phrase
  3137. if (!isset($tmp[0]) || !$tmp[0])
  3138. {
  3139. if($end)
  3140. {
  3141. // plugin root - e.g. plugin_myplug -> plugins/myplug/myplug.php, class plugin_myplug
  3142. $filename = e_PLUGIN.$end.'/'.$end.'.php';
  3143. break;
  3144. }
  3145. return; // In case we get an empty class part
  3146. }
  3147. // Currently only batches inside shortcodes/ folder are auto-detected,
  3148. // read the todo for e_shortcode.php related problems
  3149. if('shortcodes' == $end)
  3150. {
  3151. $filename = e_PLUGIN.$tmp[0].'/shortcodes/batch/'; // plugname/shortcodes/batch/
  3152. unset($tmp[0]);
  3153. $filename .= implode('_', $tmp).'_shortcodes.php'; // my_shortcodes.php
  3154. break;
  3155. }
  3156. if($end)
  3157. {
  3158. $tmp[] = $end; // not a shortcode batch - append the end phrase again
  3159. }
  3160. // Handler check
  3161. $tmp[0] .= '/includes'; //folder 'includes' is not part of the class name
  3162. $filename = e_PLUGIN.implode('/', $tmp).'.php';
  3163. //TODO add debug screen Auto-loaded classes - ['plugin: '.$filename.' - '.$className];
  3164. break;
  3165. default: //core libraries, core shortcode batches
  3166. // core SC batch check
  3167. $end = array_pop($tmp);
  3168. if('shortcodes' == $end)
  3169. {
  3170. $filename = e_CORE.'shortcodes/batch/'.$className.'.php'; // core shortcode batch
  3171. break;
  3172. }
  3173. $filename = e107::getHandlerPath($className, true);
  3174. //TODO add debug screen Auto-loaded classes - ['core: '.$filename.' - '.$className];
  3175. break;
  3176. }
  3177. if($filename && is_file($filename)) // Test with chatbox_menu
  3178. {
  3179. // autoload doesn't REQUIRE files, because this will break things like call_user_func()
  3180. include($filename);
  3181. }
  3182. }
  3183. public function __get($name)
  3184. {
  3185. switch ($name)
  3186. {
  3187. case 'tp':
  3188. $ret = e107::getParser();
  3189. break;
  3190. case 'sql':
  3191. $ret = e107::getDb();
  3192. break;
  3193. case 'ecache':
  3194. $ret = e107::getCache();
  3195. break;
  3196. case 'arrayStorage':
  3197. $ret = e107::getArrayStorage();
  3198. break;
  3199. case 'e_event':
  3200. $ret = e107::getEvent();
  3201. break;
  3202. case 'ns':
  3203. $ret = e107::getRender();
  3204. break;
  3205. case 'url':
  3206. $ret = e107::getUrl();
  3207. break;
  3208. case 'admin_log':
  3209. $ret = e107::getAdminLog();
  3210. break;
  3211. case 'override':
  3212. $ret = e107::getSingleton('override', e_HANDLER.'override_class.php');
  3213. break;
  3214. case 'notify':
  3215. $ret = e107::getNotify();
  3216. break;
  3217. case 'e_online':
  3218. $ret = e107::getOnline();
  3219. break;
  3220. case 'eIPHandler':
  3221. $ret = e107::getIPHandler();
  3222. break;
  3223. case 'user_class':
  3224. $ret = e107::getUserClass();
  3225. break;
  3226. default:
  3227. trigger_error('$e107->$'.$name.' not defined', E_USER_WARNING);
  3228. return null;
  3229. break;
  3230. }
  3231. $this->{$name} = $ret;
  3232. return $ret;
  3233. }
  3234. public function destruct()
  3235. {
  3236. if(null === self::$_instance) return;
  3237. $print = defined('E107_DBG_TIMEDETAILS') && E107_DBG_TIMEDETAILS;
  3238. !$print || print('Destructing $e107: <br />');
  3239. $vars = get_object_vars($this);
  3240. foreach ($vars as $name => $value)
  3241. {
  3242. if(is_object($value))
  3243. {
  3244. if(method_exists($value, '__destruct'))
  3245. {
  3246. !$print || print('object [property] using __destruct(): '.$path.' - '.get_class($value).'<br />');
  3247. $value->__destruct();
  3248. }
  3249. else !$print || print('object [property]: '.$name.' - '.get_class($value).'<br />');
  3250. $this->$name = null;
  3251. }
  3252. }
  3253. foreach (self::$_registry as $path => $reg)
  3254. {
  3255. if(is_object($reg))
  3256. {
  3257. if(method_exists($reg, '__destruct'))
  3258. {
  3259. !$print || print('object [registry] using __destruct(): '.$path.' - '.get_class($reg).'<br />');
  3260. $reg->__destruct();
  3261. }
  3262. else !$print || print('object [registry]: '.$path.' - '.get_class($reg).'<br />');
  3263. unset(self::$_registry[$path]);
  3264. }
  3265. }
  3266. self::$_registry = null;
  3267. self::$_instance = null;
  3268. }
  3269. }