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 15if (!defined('e107_INIT')) { exit; } 16 17 18/** 19 * 20 * @package e107 21 * @category e107_handlers 22 * @version $Id$ 23 * @author e107inc 24 * 25 * e107_class - core class with many system-related methods 26 */ 27 28class e107 29{ 30 /** 31 * IPV6 string for localhost - as stored in DB 32 */ 33 const LOCALHOST_IP = '0000:0000:0000:0000:0000:ffff:7f00:0001'; 34 const LOCALHOST_IP2 = '0000:0000:0000:0000:0000:0000:0000:0001'; 35 36 public $server_path; 37 38 public $e107_dirs = array(); 39 40 /** 41 * @var array SQL connection data 42 */ 43 protected $e107_config_mysql_info = array(); 44 45 public $http_path; 46 public $https_path; 47 public $base_path; 48 public $file_path; 49 public $site_path; 50 public $relative_base_path; 51 public $_ip_cache; 52 public $_host_name_cache; 53 54 public $site_theme; // class2 -> check valid theme 55 public $http_theme_dir; // class2 -> check valid theme 56 57 /** 58 * Contains reference to global $_E107 array 59 * Assignment is done inside prepare_request() method 60 * 61 * @var array 62 */ 63 protected $_E107 = array(); 64 65 /** 66 * @var string Current request type (http or https) 67 */ 68 protected $HTTP_SCHEME; 69 70 /** 71 * Used for runtime caching of user extended struct 72 * 73 * @var array 74 * @see e107::user() 75 */ 76 public $extended_struct; 77 78 /** 79 * User login name 80 * 81 * @var array 82 * @see init_session() 83 */ 84 public $currentUser; 85 86 /** 87 * Run once load core shortcodes 88 * while initialize SC parser 89 * 90 * @var boolean 91 */ 92 protected static $_sc_core_loaded = false; 93 94 /** 95 * Singleton instance 96 * Allow class extends - override {@link getInstance()} 97 * 98 * @var e107 99 */ 100 protected static $_instance = null; 101 102 /** 103 * e107 registry 104 * 105 * @var array 106 */ 107 private static $_registry = array(); 108 109 /** 110 * e107 core config object storage 111 * 112 * @var array 113 */ 114 protected static $_core_config_arr = array(); 115 116 /** 117 * e107 plugin config object storage 118 * 119 * @var array 120 */ 121 protected static $_plug_config_arr = array(); 122 123 /** 124 * e107 theme config object storage 125 * 126 * @var array 127 */ 128 protected static $_theme_config_arr = array(); 129 130 131 132 /** 133 * e107 e107::css() on/off flag. 134 * 135 * @var bool 136 */ 137 protected static $_css_enabled = true; 138 139 /** 140 * e107 e107::js() on/off flag. 141 * 142 * @var bool 143 */ 144 protected static $_js_enabled = true; 145 146 147 148 149 protected static $_breadcrumb = array(); 150 151 /** 152 * Core handlers array 153 * For new/missing handler add 154 * 'class name' => 'path' pair 155 * 156 * Used to auto-load core/plugin handlers 157 * NOTE: aplhabetically sorted! (by class name) 158 * 159 * @see addHandler() 160 * @see setHandlerOverload() 161 * @see getSingleton() 162 * @see getObject() 163 * @var array 164 */ 165 protected static $_known_handlers = array( 166 'UserHandler' => '{e_HANDLER}user_handler.php', 167 'comment' => '{e_HANDLER}comment_class.php', 168 'e_date' => '{e_HANDLER}date_handler.php', 169 'convert' => '{e_HANDLER}date_handler.php', // BC Fix. 170 'db' => '{e_HANDLER}e_db_pdo_class.php', 171 // 'db' => '{e_HANDLER}mysql_class.php', 172 'e107Email' => '{e_HANDLER}mail.php', 173 'e107_event' => '{e_HANDLER}event_class.php', 174 'e107_db_debug' => '{e_HANDLER}db_debug_class.php', 175 'e107_traffic' => '{e_HANDLER}traffic_class.php', 176 'e107_user_extended' => '{e_HANDLER}user_extended_class.php', 177 'e107plugin' => '{e_HANDLER}plugin_class.php', 178 'e_chart' => '{e_HANDLER}chart_class.php', 179 'e_core_session' => '{e_HANDLER}session_handler.php', 180 'e_admin_controller' => '{e_HANDLER}admin_ui.php', 181 'e_admin_controller_ui' => '{e_HANDLER}admin_ui.php', 182 'e_admin_dispatcher' => '{e_HANDLER}admin_ui.php', 183 'e_admin_form_ui' => '{e_HANDLER}admin_ui.php', 184 'e_admin_log' => '{e_HANDLER}admin_log_class.php', 185 'e_front_model' => '{e_HANDLER}model_class.php', 186 'e_admin_model' => '{e_HANDLER}model_class.php', 187 'e_admin_request' => '{e_HANDLER}admin_ui.php', 188 'e_admin_response' => '{e_HANDLER}admin_ui.php', 189 'e_admin_ui' => '{e_HANDLER}admin_ui.php', 190 'e_ajax' => '{e_HANDLER}e_ajax_class.php', 191 'e_array' => '{e_HANDLER}core_functions.php', // Old ArrayStorage. 192 'e_bbcode' => '{e_HANDLER}bbcode_handler.php', 193 'e_bb_base' => '{e_HANDLER}bbcode_handler.php', 194 'e_customfields' => '{e_HANDLER}e_customfields_class.php', 195 'e_file' => '{e_HANDLER}file_class.php', 196 'e_file_inspector_json_phar' => '{e_HANDLER}e_file_inspector_json_phar.php', 197 'e_form' => '{e_HANDLER}form_handler.php', 198 'e_jshelper' => '{e_HANDLER}js_helper.php', 199 'e_media' => '{e_HANDLER}media_class.php', 200 'e_menu' => '{e_HANDLER}menu_class.php', 201 'e_model' => '{e_HANDLER}model_class.php', 202 'e_navigation' => '{e_HANDLER}sitelinks_class.php', 203 'e_news_item' => '{e_HANDLER}news_class.php', 204 'e_news_tree' => '{e_HANDLER}news_class.php', 205 'e_news_category_tree' => '{e_HANDLER}news_class.php', 206 'e_object' => '{e_HANDLER}model_class.php', 207 'e_online' => '{e_HANDLER}online_class.php', 208 'e_parse' => '{e_HANDLER}e_parse_class.php', 209 'e_parser' => '{e_HANDLER}e_parse_class.php', 210 'e_parse_shortcode' => '{e_HANDLER}shortcode_handler.php', 211 'e_plugin' => '{e_HANDLER}plugin_class.php', 212 'e_ranks' => '{e_HANDLER}e_ranks_class.php', 213 'e_shortcode' => '{e_HANDLER}shortcode_handler.php', 214 'e_system_user' => '{e_HANDLER}user_model.php', 215 'e_theme' => '{e_HANDLER}theme_handler.php', 216 'e_upgrade' => '{e_HANDLER}e_upgrade_class.php', 217 'e_user_model' => '{e_HANDLER}user_model.php', 218 'e_user' => '{e_HANDLER}user_model.php', 219 'e_user_extended_structure_tree' => '{e_HANDLER}user_model.php', 220 'e_user_provider' => '{e_HANDLER}user_handler.php', 221 'e_userperms' => '{e_HANDLER}user_handler.php', 222 'e_validator' => '{e_HANDLER}validator_class.php', 223 'e_vars' => '{e_HANDLER}model_class.php', 224 'e_url' => '{e_HANDLER}application.php', 225 'ecache' => '{e_HANDLER}cache_handler.php', 226 'eController' => '{e_HANDLER}application.php', 227 'eDispatcher' => '{e_HANDLER}application.php', 228 'eException' => '{e_HANDLER}application.php', 229 'eFront' => '{e_HANDLER}application.php', 230 'eHelper' => '{e_HANDLER}application.php', 231 'eIPHandler' => '{e_HANDLER}iphandler_class.php', 232 'email_validation_class' => '{e_HANDLER}mail_validation_class.php', 233 'eMessage' => '{e_HANDLER}message_handler.php', 234 'eRequest' => '{e_HANDLER}application.php', 235 'eResponse' => '{e_HANDLER}application.php', 236 'eRouter' => '{e_HANDLER}application.php', 237 'eShims' => '{e_HANDLER}Shims/eShims.php', 238 'eUrl' => '{e_HANDLER}e107Url.php', 239 'eUrlConfig' => '{e_HANDLER}application.php', 240 'eUrlRule' => '{e_HANDLER}application.php', 241 'language' => '{e_HANDLER}language_class.php', 242 'news' => '{e_HANDLER}news_class.php', 243 'notify' => '{e_HANDLER}notify_class.php', 244 'override' => '{e_HANDLER}override_class.php', 245 'rater' => '{e_HANDLER}rate_class.php', 246 'redirection' => '{e_HANDLER}redirection_class.php', 247 'secure_image' => '{e_HANDLER}secure_img_handler.php', 248 'sitelinks' => '{e_HANDLER}sitelinks_class.php', 249 'themeHandler' => '{e_HANDLER}theme_handler.php', 250 'user_class' => '{e_HANDLER}userclass_class.php', 251 'user_class_admin' => '{e_HANDLER}userclass_class.php', 252 'userlogin' => '{e_HANDLER}login.php', 253 'validatorClass' => '{e_HANDLER}validator_class.php', 254 'xmlClass' => '{e_HANDLER}xml_class.php', 255 'e107MailManager' => '{e_HANDLER}mail_manager_class.php', 256 'e_library_manager' => '{e_HANDLER}library_manager.php', 257 'error_page' => '{e_HANDLER}error_page_class.php', 258 ); 259 260 /** 261 * Overload core handlers array 262 * Format: 'core_class' => array('overload_class', 'overload_path'); 263 * 264 * NOTE: to overload core singleton objects, you have to add record to 265 * $_overload_handlers before the first singleton call. 266 * 267 * Example: 268 * <code> array('e_form' => array('plugin_myplugin_form_handler' => '{e_PLUGIN}myplugin/includes/form/handler.php'));</code> 269 * 270 * Used to auto-load core handlers 271 * 272 * @var array 273 */ 274 protected static $_overload_handlers = array(); 275 276 277 /** 278 * Constructor 279 * 280 * Use {@link getInstance()}, direct instantiating 281 * is not possible for singleton objects 282 * 283 */ 284 protected function __construct() 285 { 286 /* if(defined('e_PDO') && e_PDO === false) // TODO 287 { 288 self::$_known_handlers['db'] = '{e_HANDLER}mysql_class.php'; 289 }*/ 290 // FIXME registered shutdown functions not executed after the $page output in footer - investigate 291 // Currently manually called in front-end/admin footer 292 //register_shutdown_function(array($this, 'destruct')); 293 } 294 295 private static function die_http_400() 296 { 297 header('HTTP/1.0 400 Bad Request', true, 400); 298 header('Content-Type: text/plain'); 299 if (deftrue('e_DEBUG')) 300 { 301 echo "Bad Request: "; 302 debug_print_backtrace(0, 1); 303 } 304 exit(); 305 } 306 307 /** 308 * Cloning is not allowed 309 * 310 */ 311 private function __clone() 312 { 313 } 314 315 /** 316 * Get singleton instance (php4 no more supported) 317 * 318 * @return e107 319 */ 320 public static function getInstance() 321 { 322 if(null == self::$_instance) 323 { 324 self::$_instance = new self(); 325 } 326 return self::$_instance; 327 } 328 329 /** 330 * Initialize environment path constants 331 * Public proxy to the protected method {@link _init()} 332 * 333 * @param $e107_paths 334 * @param $e107_root_path 335 * @param $e107_config_mysql_info 336 * @param array $e107_config_override 337 * @return e107 338 */ 339 public function initCore($e107_paths, $e107_root_path, $e107_config_mysql_info, $e107_config_override = array()) 340 { 341 342 return $this->_init($e107_paths, $e107_root_path, $e107_config_mysql_info, $e107_config_override); 343 } 344 345 /** 346 * Initialize environment path constants while installing e107 347 * 348 * @param $e107_paths 349 * @param $e107_root_path 350 * @param array $e107_config_override 351 * @return object|boolean e107 352 */ 353 public function initInstall($e107_paths, $e107_root_path, $e107_config_override = array()) 354 { 355 356 $e107_config = 'e107_config.php'; 357 if (!file_exists($e107_config)) // prevent blank-page with missing file during install. 358 { 359 if(file_put_contents($e107_config, '')===false) 360 { 361 return false; 362 } 363 } 364 365 // Do some security checks/cleanup, prepare the environment 366 $this->prepare_request(); 367 368 //generated from mysql data at stage 5 of install. 369 $this->site_path = isset($e107_config_override['site_path']) ? $e107_config_override['site_path'] : "[hash]"; // placeholder 370 371 // folder info 372 //$this->e107_dirs = $e107_paths; 373 $this->setDirs($e107_paths, $e107_config_override); 374 375 // build all paths 376 $this->set_paths(); 377 $this->file_path = $this->fix_windows_paths($e107_root_path)."/"; 378 379 // set base path, SSL is auto-detected 380 $this->set_base_path(); 381 382 // cleanup QUERY_STRING and friends, set related constants 383 $this->set_request(); 384 385 // set some core URLs (e_LOGIN/SIGNUP) 386 $this->set_urls(); 387 388 return $this; 389 } 390 391 /** 392 * Resolve paths, will run only once 393 * 394 * @param $e107_paths 395 * @param $e107_root_path 396 * @param $e107_config_mysql_info 397 * @param array $e107_config_override 398 * @return e107 399 */ 400 protected function _init($e107_paths, $e107_root_path, $e107_config_mysql_info, $e107_config_override = array()) 401 { 402 if(!empty($this->e107_dirs)) return $this; 403 404 // Do some security checks/cleanup, prepare the environment 405 $this->prepare_request(); 406 407 // mysql connection info 408 $this->e107_config_mysql_info = $e107_config_mysql_info; 409 410 // unique folder for e_MEDIA - support for multiple websites from single-install. Must be set before setDirs() 411 /* if (!empty($e107_config_override['site_path'])) 412 { 413 // $E107_CONFIG['site_path'] 414 $this->site_path = $e107_config_override['site_path']; 415 }*/ 416 417 if(empty($e107_config_override['site_path'])) 418 { 419 $this->site_path = $this->makeSiteHash($e107_config_mysql_info['mySQLdefaultdb'], $e107_config_mysql_info['mySQLprefix']); 420 } 421 422 // Set default folder (and override paths) if missing from e107_config.php 423 $this->setDirs($e107_paths, $e107_config_override); 424 425 // various constants - MAGIC_QUOTES_GPC, MPREFIX, ... 426 $this->set_constants(); 427 428 // build all paths 429 $this->set_paths(); 430 $this->file_path = $this->fix_windows_paths($e107_root_path); 431 432 // set base path, SSL is auto-detected 433 $this->set_base_path(); 434 435 // cleanup QUERY_STRING and friends, set related constants 436 $this->set_request(); 437 438 // set some core URLs (e_LOGIN/SIGNUP) 439 $this->set_urls(); 440 441 if(!is_dir(e_SYSTEM)) 442 { 443 mkdir(e_SYSTEM, 0755, true); 444 } 445 446 if(!is_dir(e_CACHE_IMAGE)) 447 { 448 mkdir(e_CACHE_IMAGE, 0755, true); 449 } 450 451 // Prepare essential directories. 452 $this->prepareDirs(); 453 454 return $this; 455 } 456 457 /** 458 * Create a unique hash for each database configuration (multi-site support). 459 */ 460 function makeSiteHash($db, $prefix) // also used by install. 461 { 462 return substr(md5($db . "." . $prefix), 0, 10); 463 } 464 465 /** 466 * Set system folders and override paths 467 * $e107_paths is the 'compact' version of e107_config folder vars ($ADMIN_DIRECTORY, $IMAGES_DIRECTORY, etc) 468 * $e107_config_override is the new override method - it can do it for all server and http paths via 469 * the newly introduced $E107_CONFIG array. 470 * 471 * Overriding just replace _DIRECTORY with _SERVER or _HTTP: 472 * - override server path example: 473 * <code>$E107_CONFIG['SYSTEM_SERVER'] = '/home/user/system/';</code> 474 * 475 * - override http path example: 476 * <code>$E107_CONFIG['MEDIA_VIDEOS_HTTP'] = 'http://static.mydomain.com/videos/';</code> 477 * 478 * @param array $e107_dirs Override folder instructions (*_DIRECTORY vars - e107_config.php) 479 * @param array $e107_config_override Override path insructions ($E107_CONFIG array - e107_config.php) 480 * @return e107 481 */ 482 public function setDirs($e107_dirs, $e107_config_override = array()) 483 { 484 if(!empty($e107_config_override['site_path'])) // $E107_CONFIG['site_path'] 485 { 486 $this->site_path = $e107_config_override['site_path']; 487 } 488 489 $override = array_merge((array) $e107_dirs, (array) $e107_config_override); 490 491 // override all 492 $this->e107_dirs = array_merge($this->defaultDirs($override), $override); 493 494 // Required for e_MEDIA_BASE, e_SYSTEM_BASE (free of site path constants); 495 // $this->e107_dirs['MEDIA_BASE_DIRECTORY'] = $this->e107_dirs['MEDIA_DIRECTORY']; 496 // $this->e107_dirs['SYSTEM_BASE_DIRECTORY'] = $this->e107_dirs['SYSTEM_BASE_DIRECTORY']; 497 498 // FIXME - remove this condition because: 499 // $this->site_path is appended to MEDIA_DIRECTORY in defaultDirs(), which is called above. 500 if(strpos($this->e107_dirs['MEDIA_DIRECTORY'],$this->site_path) === false) 501 { 502 $this->e107_dirs['MEDIA_DIRECTORY'] .= $this->site_path."/"; // multisite support. 503 } 504 505 // FIXME - remove this condition because: 506 // $this->site_path is appended to SYSTEM_DIRECTORY in defaultDirs(), which is called above. 507 if(strpos($this->e107_dirs['SYSTEM_DIRECTORY'],$this->site_path) === false) 508 { 509 $this->e107_dirs['SYSTEM_DIRECTORY'] .= $this->site_path."/"; // multisite support. 510 } 511 512 // FIXME Quick fix - override base cache folder for legacy configs (e.g. e107_files/cache), discuss 513 if(strpos($this->e107_dirs['CACHE_DIRECTORY'], $this->site_path) === false) 514 { 515 $this->e107_dirs['CACHE_DIRECTORY'] = $this->e107_dirs['SYSTEM_DIRECTORY']."cache/"; // multisite support. 516 } 517 518 return $this; 519 } 520 521 /** 522 * Prepares essential directories. 523 */ 524 public function prepareDirs() 525 { 526 $file = e107::getFile(); 527 528 // Essential directories which should be created and writable. 529 $essential_directories = array( 530 'MEDIA_DIRECTORY', 531 'SYSTEM_DIRECTORY', 532 'CACHE_DIRECTORY', 533 534 'CACHE_CONTENT_DIRECTORY', 535 'CACHE_IMAGE_DIRECTORY', 536 'CACHE_DB_DIRECTORY', 537 'CACHE_URL_DIRECTORY', 538 539 'LOGS_DIRECTORY', 540 'BACKUP_DIRECTORY', 541 'TEMP_DIRECTORY', 542 'IMPORT_DIRECTORY', 543 ); 544 545 // Create directories which don't exist. 546 foreach($essential_directories as $directory) 547 { 548 if (!isset($this->e107_dirs[$directory])) { 549 continue; 550 } 551 552 $path = e_ROOT . $this->e107_dirs[$directory]; 553 $file->prepareDirectory($path, FILE_CREATE_DIRECTORY); 554 } 555 } 556 557 /** 558 * Get default e107 folders, root folders can be overridden by passed override array 559 * 560 * @param array $override_root 561 * @param boolean $return_root 562 * @return array 563 */ 564 public function defaultDirs($override_root = array(), $return_root = false) 565 { 566 $ret = array_merge(array( 567 'ADMIN_DIRECTORY' => 'e107_admin/', 568 'IMAGES_DIRECTORY' => 'e107_images/', 569 'THEMES_DIRECTORY' => 'e107_themes/', 570 'PLUGINS_DIRECTORY' => 'e107_plugins/', 571 'FILES_DIRECTORY' => 'e107_files/', // DEPRECATED!!! 572 'HANDLERS_DIRECTORY' => 'e107_handlers/', 573 'LANGUAGES_DIRECTORY' => 'e107_languages/', 574 'DOCS_DIRECTORY' => 'e107_docs/', 575 'MEDIA_DIRECTORY' => 'e107_media/', 576 'SYSTEM_DIRECTORY' => 'e107_system/', 577 'CORE_DIRECTORY' => 'e107_core/', 578 'WEB_DIRECTORY' => 'e107_web/', 579 ), (array) $override_root); 580 581 $ret['MEDIA_BASE_DIRECTORY'] = $ret['MEDIA_DIRECTORY']; 582 $ret['SYSTEM_BASE_DIRECTORY'] = $ret['SYSTEM_DIRECTORY']; 583 $ret['MEDIA_DIRECTORY'] .= $this->site_path."/"; // multisite support. 584 $ret['SYSTEM_DIRECTORY'] .= $this->site_path."/"; // multisite support. 585 586 if($return_root) return $ret; 587 588 $ret['HELP_DIRECTORY'] = $ret['DOCS_DIRECTORY'].'help/'; 589 590 $ret['MEDIA_IMAGES_DIRECTORY'] = $ret['MEDIA_DIRECTORY'].'images/'; 591 $ret['MEDIA_ICONS_DIRECTORY'] = $ret['MEDIA_DIRECTORY'].'icons/'; 592 593 $ret['MEDIA_VIDEOS_DIRECTORY'] = $ret['MEDIA_DIRECTORY'].'videos/'; 594 $ret['MEDIA_FILES_DIRECTORY'] = $ret['MEDIA_DIRECTORY'].'files/'; 595 $ret['MEDIA_UPLOAD_DIRECTORY'] = $ret['SYSTEM_DIRECTORY'].'temp/'; // security measure. Media is public, system is private. 596 $ret['AVATARS_DIRECTORY'] = $ret['MEDIA_DIRECTORY'].'avatars/'; 597 598 $ret['WEB_JS_DIRECTORY'] = $ret['WEB_DIRECTORY'].'js/'; 599 // $ret['WEB_JS_DIRECTORY'] = $ret['FILES_DIRECTORY'].'jslib/'; 600 601 602 $ret['WEB_CSS_DIRECTORY'] = $ret['WEB_DIRECTORY'].'css/'; 603 $ret['WEB_IMAGES_DIRECTORY'] = $ret['WEB_DIRECTORY'].'images/'; 604 // $ret['WEB_PACKS_DIRECTORY'] = $ret['WEB_DIRECTORY'].'packages/'; 605 606 $ret['DOWNLOADS_DIRECTORY'] = $ret['MEDIA_FILES_DIRECTORY']; 607 $ret['UPLOADS_DIRECTORY'] = $ret['MEDIA_UPLOAD_DIRECTORY']; 608 609 $ret['CACHE_DIRECTORY'] = $ret['SYSTEM_DIRECTORY'].'cache/'; 610 $ret['CACHE_CONTENT_DIRECTORY'] = $ret['CACHE_DIRECTORY'].'content/'; 611 612 if(defined('e_MEDIA_STATIC')) // experimental - subject to change. 613 { 614 $ret['CACHE_IMAGE_DIRECTORY'] = $ret['MEDIA_IMAGES_DIRECTORY'].'cache/'; 615 } 616 else 617 { 618 $ret['CACHE_IMAGE_DIRECTORY'] = $ret['CACHE_DIRECTORY'].'images/'; 619 } 620 621 $ret['CACHE_DB_DIRECTORY'] = $ret['CACHE_DIRECTORY'].'db/'; 622 $ret['CACHE_URL_DIRECTORY'] = $ret['CACHE_DIRECTORY'].'url/'; 623 624 $ret['AVATARS_UPLOAD_DIRECTORY'] = $ret['AVATARS_DIRECTORY'].'upload/'; 625 $ret['AVATARS_DEFAULT_DIRECTORY'] = $ret['AVATARS_DIRECTORY'].'default/'; 626 627 $ret['LOGS_DIRECTORY'] = $ret['SYSTEM_DIRECTORY'].'logs/'; 628 $ret['BACKUP_DIRECTORY'] = $ret['SYSTEM_DIRECTORY'].'backup/'; 629 $ret['TEMP_DIRECTORY'] = $ret['SYSTEM_DIRECTORY'].'temp/'; 630 $ret['IMPORT_DIRECTORY'] = $ret['SYSTEM_DIRECTORY'].'import/'; 631 632 return $ret; 633 } 634 635 /** 636 * Set mysql data 637 * 638 * @param $e107_config_mysql_info 639 * @return e107 640 */ 641 public function initInstallSql($e107_config_mysql_info) 642 { 643 // mysql connection info 644 $this->e107_config_mysql_info = $e107_config_mysql_info; 645 646 // various constants - MAGIC_QUOTES_GPC, MPREFIX, ... 647 $this->set_constants(); 648 649 return $this; 650 } 651 652 /** 653 * Get data from the registry 654 * Returns $default if data not found 655 * Replacement of cachevar() 656 * 657 * @param string $id 658 * @param null $default 659 * @return mixed 660 */ 661 public static function getRegistry($id, $default = null) 662 { 663 if(isset(self::$_registry[$id])) 664 { 665 return self::$_registry[$id]; 666 } 667 668 if($id === '_all_') 669 { 670 return self::$_registry; 671 } 672 673 return $default; 674 } 675 676 /** 677 * Add data to the registry - replacement of getcachedvars(). 678 * $id is path-like unique id bind to the passed data. 679 * If $data argument is null, $id will be removed from the registry. 680 * When removing objects from the registry, __destruct() method will be auto-executed 681 * if available 682 * 683 * Naming standards (namespaces): 684 * 'area/area_id/storage_type'<br> 685 * where <br> 686 * - area = 'core'|'plugin'|'external' (everything else) 687 * - area_id = core handler id|plugin name (depends on area) 688 * - (optional) storage_type = current data storage stack 689 * 690 * Examples: 691 * - 'core/e107/' - reserved for this class 692 * - 'core/e107/singleton/' - singleton objects repo {@link getSingleton()} 693 * 694 * @param string $id 695 * @param mixed|null $data 696 * @param bool $allow_override 697 */ 698 public static function setRegistry($id, $data = null, $allow_override = true) 699 { 700 if(null === $data) 701 { 702 if(isset(self::$_registry[$id]) && is_object(self::$_registry[$id]) && method_exists(self::$_registry[$id], '__destruct')) 703 { 704 self::$_registry[$id]->__destruct(); 705 } 706 unset(self::$_registry[$id]); 707 return; 708 } 709 710 if(!$allow_override && null !== self::getRegistry($id)) 711 { 712 return; 713 } 714 715 self::$_registry[$id] = $data; 716 } 717 718 /** 719 * Get folder name (e107_config) 720 * Replaces all $(*)_DIRECTORY globals 721 * Example: <code>$e107->getFolder('images')</code>; 722 * 723 * @param string $for 724 * @return string 725 */ 726 public static function getFolder($for) 727 { 728 $key = strtoupper($for).'_DIRECTORY'; 729 $self = self::getInstance(); 730 return (isset($self->e107_dirs[$key]) ? $self->e107_dirs[$key] : ''); 731 } 732 733 /** 734 * Get value from $_E107 config array 735 * Note: will always return false if called before prepare_request() method! 736 * 737 * @param string $key 738 * @return boolean 739 */ 740 public static function getE107($key = null) 741 { 742 $self = self::getInstance(); 743 if(null === $key) return $self->_E107; 744 return (isset($self->_E107[$key]) && $self->_E107[$key] ? true : false); 745 } 746 747 /** 748 * Convenient proxy to $_E107 getter - check if 749 * the system is currently running in cli mode 750 * Note: will always return false if called before prepare_request() method! 751 * 752 * @return boolean 753 */ 754 public static function isCli() 755 { 756 return self::getE107('cli'); 757 } 758 759 /** 760 * Get mysql config var (e107_config.php) 761 * Replaces all $mySQL(*) globals 762 * Example: <code>$e107->getMySQLConfig('prefix');</code> 763 * 764 * @param string $for prefix|server|user|password|defaultdb - leave blank for full array. 765 * @return string|array 766 */ 767 public static function getMySQLConfig($for='') 768 { 769 $key = 'mySQL'.$for; 770 $self = self::getInstance(); 771 772 if($for == '') 773 { 774 return $self->e107_config_mysql_info; 775 } 776 777 return (isset($self->e107_config_mysql_info[$key]) ? $self->e107_config_mysql_info[$key] : ''); 778 } 779 780 781 /** 782 * Return a unique path based on database used. ie. multi-site support from single install. 783 * 784 * @return string 785 * @author 786 */ 787 function getSitePath() 788 { 789 $self = self::getInstance(); 790 return $self->site_path; 791 } 792 793 /** 794 * Get known handler path 795 * 796 * @param string $class_name 797 * @param boolean $parse_path [optional] parse path shortcodes 798 * @return string|null 799 */ 800 public static function getHandlerPath($class_name, $parse_path = true) 801 { 802 $ret = isset(self::$_known_handlers[$class_name]) ? self::$_known_handlers[$class_name] : null; 803 if($parse_path && $ret) 804 { 805 $ret = self::getParser()->replaceConstants($ret); 806 } 807 808 return $ret; 809 } 810 811 /** 812 * Add handler to $_known_handlers array on runtime 813 * If class name is array, method will add it (recursion) and ignore $path argument 814 * 815 * @param array|string $class_name 816 * @param string $path [optional] 817 * @return void 818 */ 819 public static function addHandler($class_name, $path = '') 820 { 821 if(is_array($class_name)) 822 { 823 foreach ($class_name as $cname => $path) 824 { 825 self::addHandler($cname, $path); 826 } 827 return; 828 } 829 if(!self::isHandler($class_name)) 830 { 831 self::$_known_handlers[$class_name] = $path; 832 } 833 } 834 835 /** 836 * Check handler presence 837 * 838 * @param string $class_name 839 * @return boolean 840 */ 841 public static function isHandler($class_name) 842 { 843 return isset(self::$_known_handlers[$class_name]); 844 } 845 846 /** 847 * Get overlod class and path (if any) 848 * 849 * @param string $class_name 850 * @param bool|object $default_handler [optional] return data from $_known_handlers if no overload data available 851 * @param bool|object $parse_path [optional] parse path shortcodes 852 * @return array 853 */ 854 public static function getHandlerOverload($class_name, $default_handler = true, $parse_path = true) 855 { 856 $ret = (isset(self::$_overload_handlers[$class_name]) ? self::$_overload_handlers[$class_name] : ($default_handler ? array($class_name, self::getHandlerPath($class_name, false)) : array())); 857 if ($parse_path && isset($ret[1])) 858 { 859 $ret[1] = self::getParser()->replaceConstants($ret[1]); 860 } 861 862 return $ret; 863 } 864 865 /** 866 * Overload present handler. 867 * If class name is array, method will add it (recursion) and 868 * ignore $overload_class_name and $overload_path arguments 869 * 870 * @param string $class_name 871 * @param string $overload_class_name [optional] 872 * @param string $overload_path [optional] 873 * @return void 874 */ 875 public static function setHandlerOverload($class_name, $overload_class_name = '', $overload_path = '') 876 { 877 if(is_array($class_name)) 878 { 879 foreach ($class_name as $cname => $overload_array) 880 { 881 self::setHandlerOverload($cname, $overload_array[0], $overload_array[1]); 882 } 883 return; 884 } 885 if(self::isHandler($class_name) && !self::isHandlerOverloadable($class_name)) 886 { 887 self::$_overload_handlers[$class_name] = array($overload_class_name, $overload_path); 888 } 889 } 890 891 /** 892 * Check if handler is already overloaded 893 * 894 * @param string $class_name 895 * @return boolean 896 */ 897 public static function isHandlerOverloadable($class_name) 898 { 899 return isset(self::$_overload_handlers[$class_name]); 900 } 901 902 /** 903 * Retrieve singleton object 904 * 905 * @param string $class_name 906 * @param string|boolean $path optional script path 907 * @param string $regpath additional registry path 908 * @return Object 909 */ 910 public static function getSingleton($class_name, $path = true, $regpath = '',$vars=null) 911 { 912 913 $id = 'core/e107/singleton/'.$class_name.$regpath; 914 915 if(!empty($vars)) 916 { 917 $id .= '/'; 918 $id .= is_array($vars) ? crc32(serialize($vars)): crc32($vars); 919 } 920 921 //singleton object found - overload not possible 922 if(self::getRegistry($id)) 923 { 924 return self::getRegistry($id); 925 } 926 927 //auto detection + overload check 928 if(is_bool($path)) 929 { 930 //overload allowed 931 if(true === $path && self::isHandlerOverloadable($class_name)) 932 { 933 $tmp = self::getHandlerOverload($class_name); 934 $class_name = $tmp[0]; 935 $path = $tmp[1]; 936 } 937 //overload not allowed 938 else 939 { 940 $path = self::getHandlerPath($class_name); 941 } 942 } 943 944 if($path && is_string($path) && !class_exists($class_name, false)) 945 { 946 global $_E107; 947 948 if((!empty($_E107['debug']) || (defined('e_DEBUG') && e_DEBUG === true) )) 949 { 950 require_once($path); 951 } 952 else 953 { 954 @require_once($path); 955 } 956 957 // remove the need for external function. 958 //e107_require_once() is available without class2.php. - see core_functions.php 959 } 960 if(class_exists($class_name, false)) 961 { 962 self::setRegistry($id, new $class_name($vars)); 963 } 964 965 return self::getRegistry($id); 966 } 967 968 /** 969 * Retrieve object 970 * Prepare for __autoload 971 * 972 * @param string $class_name 973 * @param mixed $arguments 974 * @param string|boolean $path optional script path 975 * @return object|null 976 */ 977 public static function getObject($class_name, $arguments = null, $path = true) 978 { 979 if(true === $path) 980 { 981 if(isset(self::$_known_handlers[$class_name])) 982 { 983 $path = self::getParser()->replaceConstants(self::$_known_handlers[$class_name]); 984 } 985 } 986 987 //auto detection + overload check 988 if(is_bool($path)) 989 { 990 //overload allowed 991 if(true === $path && self::isHandlerOverloadable($class_name)) 992 { 993 $tmp = self::getHandlerOverload($class_name); 994 $class_name = $tmp[0]; 995 $path = $tmp[1]; 996 } 997 //overload not allowed 998 else 999 { 1000 $path = self::getHandlerPath($class_name); 1001 } 1002 } 1003 1004 if($path && is_string($path) && !class_exists($class_name, false)) 1005 { 1006 e107_require_once($path); //no existence/security checks here! 1007 } 1008 1009 if(class_exists($class_name, false)) 1010 { 1011 if(null !== $arguments) return new $class_name($arguments); 1012 return new $class_name(); 1013 } 1014 1015 trigger_error("Class {$class_name} not found!", E_USER_ERROR); 1016 return null; 1017 } 1018 1019 /** 1020 * Retrieve core config handlers. 1021 * List of allowed $name values (aliases) could be found 1022 * in {@link e_core_pref} class 1023 * 1024 * @param string $name core|core_backup|emote|menu|search|notify 1025 * @param bool $load 1026 * @param bool $refresh 1027 * @return e_core_pref 1028 */ 1029 public static function getConfig($name = 'core', $load = true, $refresh=false) 1030 { 1031 1032 if(isset(self::$_plug_config_arr[$name])) //FIXME Load pluginPref Object instead - Not quite working with calendar_menu. 1033 { 1034 return self::getPlugConfig($name); 1035 } 1036 1037 if(!isset(self::$_core_config_arr[$name]) || ($refresh == true)) // required by update_routines to clear out earlier values. 1038 { 1039 e107_require_once(e_HANDLER.'pref_class.php'); 1040 self::$_core_config_arr[$name] = new e_core_pref($name, $load); 1041 1042 if($name === 'core') // prevent loop between pref and cache handlers. 1043 { 1044 self::getCache()->UserCacheActive = self::getPref('cachestatus'); 1045 self::getCache()->SystemCacheActive = self::getPref('syscachestatus'); 1046 } 1047 } 1048 1049 return self::$_core_config_arr[$name]; 1050 } 1051 1052 /** 1053 * Retrieve core config handler preference value or the core preference array 1054 * Shorthand of self::getConfig()->get() 1055 * 1056 * @see e_core_pref::get() 1057 * @param string $pref_name 1058 * @param mixed $default default value if preference is not found 1059 * @return mixed 1060 */ 1061 public static function getPref($pref_name = '', $default = null) 1062 { 1063 return empty($pref_name) ? self::getConfig()->getPref() : self::getConfig()->get($pref_name, $default); 1064 } 1065 1066 /** 1067 * Advanced version of self::getPref(). $pref_name is parsed, 1068 * so that $pref_name = 'x/y/z' will search for value pref_data[x][y][z] 1069 * Shorthand of self::getConfig()->getPref() 1070 * 1071 * @see e_core_pref::getPref() 1072 * @param string $pref_name 1073 * @param mixed $default default value if preference is not found 1074 * @param null $index 1075 * @return mixed 1076 */ 1077 public static function findPref($pref_name, $default = null, $index = null) 1078 { 1079 return self::getConfig()->getPref($pref_name, $default, $index); 1080 } 1081 1082 /** 1083 * Retrieve plugin config handlers. 1084 * Multiple plugin preference DB rows are supported 1085 * Class overload is supported. 1086 * Examples: 1087 * - <code>e107::getPluginConfig('myplug');</code> 1088 * will search for e107_plugins/myplug/e_pref/myplug_pref.php which 1089 * should contain class 'e_plugin_myplug_pref' class (child of e_plugin_pref) 1090 * - <code>e107::getPluginConfig('myplug', 'row2');</code> 1091 * will search for e107_plugins/myplug/e_pref/myplug_row2_pref.php which 1092 * should contain class 'e_plugin_myplug_row2_pref' class (child of e_plugin_pref) 1093 * 1094 * @param string $plug_name 1095 * @param string $multi_row 1096 * @param boolean $load load from DB on startup 1097 * @return e_plugin_pref 1098 */ 1099 public static function getPlugConfig($plug_name, $multi_row = '', $load = true) 1100 { 1101 if(!isset(self::$_plug_config_arr[$plug_name.$multi_row])) 1102 { 1103 e107_require_once(e_HANDLER.'pref_class.php'); 1104 $override_id = $plug_name.($multi_row ? "_{$multi_row}" : ''); 1105 1106 //check (once) for custom plugin pref handler 1107 if(is_readable(e_PLUGIN.$plug_name.'/e_pref/'.$override_id.'_pref.php')) 1108 { 1109 require_once(e_PLUGIN.$plug_name.'/e_pref/'.$override_id.'_pref.php'); 1110 $class_name = 'e_plugin_'.$override_id.'_pref'; 1111 1112 //PHPVER: string parameter for is_subclass_of require PHP 5.0.3+ 1113 if(class_exists($class_name, false) && is_subclass_of('e_plugin_pref', $class_name)) //or e_pref ? 1114 { 1115 self::$_plug_config_arr[$plug_name.$multi_row] = new $class_name($load); 1116 return self::$_plug_config_arr[$plug_name.$multi_row]; 1117 } 1118 } 1119 1120 self::$_plug_config_arr[$plug_name.$multi_row] = new e_plugin_pref($plug_name, $multi_row, $load); 1121 } 1122 1123 return self::$_plug_config_arr[$plug_name.$multi_row]; 1124 } 1125 1126 1127 1128 /** 1129 * Retrieve the global LAN for a specific plugin. 1130 * @param $dir 1131 * @param string $type 1132 * @return mixed 1133 */ 1134 public static function getPlugLan($dir, $type='name') 1135 { 1136 $lan = "LAN_PLUGIN_".strtoupper($dir)."_".strtoupper($type); 1137 1138 return defset($lan,false); 1139 } 1140 1141 /** 1142 * Retrieve plugin preference value. 1143 * Shorthand of self::getPluginConfig()->get() 1144 * NOTE: Multiple plugin preference DB rows are NOT supported 1145 * This will only look for your default plugin config (empty $milti_row) 1146 * 1147 * @see e_plugin_pref::get() 1148 * @param string $plug_name 1149 * @param string $pref_name 1150 * @param mixed $default default value if preference is not found 1151 * @return mixed 1152 */ 1153 public static function getPlugPref($plug_name, $pref_name = '', $default = null) 1154 { 1155 return empty($pref_name) ? self::getPlugConfig($plug_name)->getPref() : self::getPlugConfig($plug_name)->get($pref_name, $default); 1156 } 1157 1158 /** 1159 * Advanced version of self::getPlugPref(). $pref_name is parsed, 1160 * so that $pref_name = 'x/y/z' will search for value pref_data[x][y][z] 1161 * Shorthand of self::getPluginConfig()->getPref() 1162 * 1163 * @see e_core_pref::getPref() 1164 * @param $plug_name 1165 * @param string $pref_name 1166 * @param mixed $default default value if preference is not found 1167 * @param null $index 1168 * @return mixed 1169 */ 1170 public static function findPlugPref($plug_name, $pref_name, $default = null, $index = null) 1171 { 1172 return self::getPlugConfig($plug_name)->getPref($pref_name, $default, $index); 1173 } 1174 1175 1176 /** 1177 * Retrieve theme config handlers. 1178 * Multiple theme preference DB rows are supported 1179 * Class overload is supported. 1180 * Examples: 1181 * - <code>e107::getTHemeConfig('mytheme');</code> 1182 * will search for e107_plugins/myplug/e_pref/myplug_pref.php which 1183 * should contain class 'e_plugin_myplug_pref' class (child of e_plugin_pref) 1184 * - <code>e107::getPluginConfig('myplug', 'row2');</code> 1185 * will search for e107_plugins/myplug/e_pref/myplug_row2_pref.php which 1186 * should contain class 'e_plugin_myplug_row2_pref' class (child of e_plugin_pref) 1187 * 1188 * @param string $theme_name 1189 * @param string $multi_row 1190 * @param boolean $load load from DB on startup 1191 * @return e_plugin_pref 1192 */ 1193 public static function getThemeConfig($theme_name=null, $multi_row = '', $load = true) 1194 { 1195 1196 if(empty($theme_name)) 1197 { 1198 $theme_name = self::getPref('sitetheme'); 1199 } 1200 1201 if(!isset(self::$_theme_config_arr[$theme_name.$multi_row])) 1202 { 1203 e107_require_once(e_HANDLER.'pref_class.php'); 1204 1205 self::$_theme_config_arr[$theme_name.$multi_row] = new e_theme_pref($theme_name, $multi_row, $load); 1206 } 1207 1208 return self::$_theme_config_arr[$theme_name.$multi_row]; 1209 } 1210 1211 1212 1213 1214 /** 1215 * Get current theme preference. $pref_name is parsed, 1216 * so that $pref_name = 'x/y/z' will search for value pref_data[x][y][z] 1217 * Shorthand of self::getConfig()->getPref('current_theme/sitetheme_pref/pref_name') 1218 * 1219 * @see e_core_pref::getPref() 1220 * @param string $pref_name 1221 * @param mixed $default default value if preference is not found 1222 * @param null $index 1223 * @return mixed 1224 */ 1225 public static function getThemePref($pref_name = '', $default = null, $index = null) 1226 { 1227 // new storage method in it's own core table row. eg. theme_bootstrap3 1228 $theme_name = self::getPref('sitetheme'); 1229 1230 if(self::getThemeConfig($theme_name)->hasData() === true) 1231 { 1232 return empty($pref_name) ? self::getThemeConfig($theme_name)->getPref() : self::getThemeConfig($theme_name)->get($pref_name, $default); 1233 } 1234 1235 // old storage method in core prefs. 1236 1237 $legacy_pref_name = ($pref_name) ? $pref_name = '/'.$pref_name : ''; 1238 $tprefs = self::getConfig()->getPref('sitetheme_pref'.$legacy_pref_name, $default, $index); 1239 1240 return !empty($tprefs) ? $tprefs : $default; 1241 1242 } 1243 1244 /** 1245 * Set current theme preference. $pref_name is parsed, 1246 * so that $pref_name = 'x/y/z' will set value pref_data[x][y][z] 1247 * 1248 * @param string|array $pref_name 1249 * @param mixed $pref_value 1250 * @return e_pref 1251 */ 1252 public static function setThemePref($pref_name, $pref_value = null) 1253 { 1254 if(is_array($pref_name)) return self::getConfig()->set('sitetheme_pref', $pref_name); 1255 return self::getConfig()->updatePref('sitetheme_pref/'.$pref_name, $pref_value, false); 1256 } 1257 1258 1259 public static function getThemeGlyphs() 1260 { 1261 1262 $custom = self::getConfig()->getPref('sitetheme_glyphicons', false); 1263 $theme = self::getConfig()->getPref('sitetheme', false); 1264 1265 $arr = array(); 1266 1267 if(!empty($custom)) 1268 { 1269 1270 foreach($custom as $glyphConfig) 1271 { 1272 1273 if(substr($glyphConfig['path'],0,4) !== 'http') 1274 { 1275 $glyphConfig['path'] = e_THEME."$theme/".$glyphConfig['path']; 1276 } 1277 1278 $arr[] = $glyphConfig; 1279 1280 if(E107_DBG_INCLUDES) 1281 { 1282 e107::getDebug()->log("Loading Glyph Icons: ".print_a($glyphConfig,true)); 1283 } 1284 } 1285 1286 } 1287 1288 return $arr; 1289 1290 } 1291 1292 1293 1294 1295 /** 1296 * Retrieve text parser singleton object 1297 * 1298 * @return e_parse 1299 */ 1300 public static function getParser() 1301 { 1302 return self::getSingleton('e_parse', e_HANDLER.'e_parse_class.php'); //WARNING - don't change this - infinite loop!!! 1303 } 1304 1305 /** 1306 * Retrieve sc parser singleton object 1307 * 1308 * @return e_parse_shortcode 1309 */ 1310 public static function getScParser() 1311 { 1312 return self::getSingleton('e_parse_shortcode', true); 1313 } 1314 1315 1316 /** 1317 * Retrieve secure_image singleton object 1318 * 1319 * @return secure_image 1320 */ 1321 public static function getSecureImg() 1322 { 1323 return self::getSingleton('secure_image', true); // more flexible. 1324 // return self::getObject('secure_image'); 1325 } 1326 1327 /** 1328 * Retrieve registered sc object (batch) by class name 1329 * Note - '_shortcodes' part of the class/override is added by the method 1330 * Override is possible only if class is not already instantiated by shortcode parser 1331 * 1332 * <code><?php 1333 * 1334 * // Core news shortcodes (news_shortcodes.php using class news_shortcodes ) 1335 * e107::getScObject('news'); 1336 * 1337 * // Core page shortcodes (page_shortcodes.php.php with class cpage_shortcode) 1338 * e107::getScObject('page', null,'cpage'); 1339 * 1340 * // object of plugin_myplugin_my_shortcodes class -> myplugin/shortcodes/batch/my_shortcodes.php 1341 * e107::getScObject('my', 'myplugin'); 1342 * 1343 * // news override - plugin_myplugin_news_shortcodes extends news_shortcodes -> myplugin/shortcodes/batch/news_shortcodes.php 1344 * e107::getScObject('news', 'myplugin', true); 1345 * 1346 * // news override - plugin_myplugin_mynews_shortcodes extends news_shortcodes -> myplugin/shortcodes/batch/mynews_shortcodes.php 1347 * e107::getScObject('news', 'myplugin', 'mynews'); 1348 * </code> 1349 * 1350 * @param string $className 1351 * @param string $pluginName 1352 * @param string|true $overrideClass 1353 * @return e_shortcode 1354 */ 1355 public static function getScBatch($className, $pluginName = null, $overrideClass = null) 1356 { 1357 if(is_string($overrideClass)) $overrideClass .= '_shortcodes'; 1358 return self::getScParser()->getScObject($className.'_shortcodes', $pluginName, $overrideClass); 1359 } 1360 1361 /** 1362 * Retrieve DB singleton object based on the 1363 * $instance_id 1364 * 1365 * @param string $instance_id 1366 * @return e_db 1367 */ 1368 public static function getDb($instance_id = '') 1369 { 1370 return self::getSingleton('db', true, $instance_id); 1371 } 1372 1373 /** 1374 * Retrieve cache singleton object 1375 * 1376 * @return ecache 1377 */ 1378 public static function getCache() 1379 { 1380 return self::getSingleton('ecache', true); 1381 } 1382 1383 /** 1384 * Retrieve bbcode singleton object 1385 * 1386 * @return e_bbcode 1387 */ 1388 public static function getBB() 1389 { 1390 return self::getSingleton('e_bbcode', true); 1391 } 1392 1393 /** 1394 * Retrieve user-session singleton object 1395 * 1396 * @return UserHandler 1397 */ 1398 public static function getUserSession() 1399 { 1400 return self::getSingleton('UserHandler', true); 1401 } 1402 1403 /** 1404 * Retrieve core session singleton object(s) 1405 * 1406 * @param null $namespace 1407 * @return e_core_session 1408 */ 1409 public static function getSession($namespace = null) 1410 { 1411 $id = 'core/e107/session/'.(null === $namespace ? 'e107' : $namespace); 1412 if(self::getRegistry($id)) 1413 { 1414 return self::getRegistry($id); 1415 } 1416 $session = self::getObject('e_core_session', array('namespace' => $namespace), true); 1417 self::setRegistry($id, $session); 1418 return $session; 1419 } 1420 1421 /** 1422 * Retrieve redirection singleton object 1423 * 1424 * @return redirection 1425 */ 1426 public static function getRedirect() 1427 { 1428 return self::getSingleton('redirection', true); 1429 } 1430 1431 1432 /** 1433 * Retrieve rater singleton object 1434 * 1435 * @return rater 1436 */ 1437 public static function getRate() 1438 { 1439 return self::getSingleton('rater', true); 1440 } 1441 1442 /** 1443 * Retrieve sitelinks singleton object 1444 * 1445 * @return sitelinks 1446 */ 1447 public static function getSitelinks() 1448 { 1449 return self::getSingleton('sitelinks', true); 1450 } 1451 1452 1453 /** 1454 * Retrieve render singleton object 1455 * 1456 * @return e107table 1457 */ 1458 public static function getRender() 1459 { 1460 return self::getSingleton('e107table'); 1461 } 1462 1463 /** 1464 * Retrieve e107Email singleton object 1465 * 1466 * @return e107Email 1467 */ 1468 public static function getEmail($overrides=null) 1469 { 1470 return self::getSingleton('e107Email', true, null, $overrides); 1471 } 1472 1473 1474 /** 1475 * Retrieves PhpThumbFactory object 1476 * 1477 * @param $src 1478 * @return bool|GdThumb 1479 */ 1480 public static function getThumb($src) 1481 { 1482 require_once(e_HANDLER.'phpthumb/ThumbLib.inc.php'); 1483 try 1484 { 1485 return PhpThumbFactory::create($src); 1486 } 1487 catch (Exception $e) 1488 { 1489 return false; 1490 } 1491 1492 } 1493 1494 1495 /** 1496 * Retrieve e107Email mail mailer object. 1497 * 1498 * @return e107MailManager 1499 */ 1500 public static function getBulkEmail() 1501 { 1502 return self::getSingleton('e107MailManager', true); 1503 } 1504 1505 /** 1506 * Retrieve event singleton object 1507 * 1508 * @return e107_event 1509 */ 1510 public static function getEvent() 1511 { 1512 return self::getSingleton('e107_event', true); 1513 } 1514 1515 /** 1516 * Retrieve array storage singleton object 1517 * 1518 * @return e_array 1519 */ 1520 public static function getArrayStorage() 1521 { 1522 return self::getSingleton('e_array', true); 1523 } 1524 1525 /** 1526 * Retrieve menu handler singleton object 1527 * 1528 * @return e_menu 1529 */ 1530 public static function getMenu() 1531 { 1532 return self::getSingleton('e_menu', true); 1533 } 1534 1535 1536 /** 1537 * Retrieve e_theme singleton object 1538 * @return e_theme 1539 */ 1540 public static function getTheme($themedir='front', $clearCache=false) 1541 { 1542 1543 if(!defined('E107_INSTALL')) 1544 { 1545 if($themedir === 'front') 1546 { 1547 $themedir= self::getPref('sitetheme'); 1548 } 1549 1550 if($themedir === 'admin') 1551 { 1552 $themedir = self::getPref('admintheme'); 1553 } 1554 } 1555 1556 // Get the currently used theme. 1557 if ($themedir == 'current') 1558 { 1559 // If we are in the admin area. 1560 if (deftrue('e_ADMIN_AREA', false)) 1561 { 1562 $themedir = self::getPref('admintheme'); 1563 } 1564 else 1565 { 1566 $themedir= self::getPref('sitetheme'); 1567 } 1568 } 1569 1570 // e107::getDb()->db_Mark_time('start e_theme'); 1571 /** @var e_theme $ret */ 1572 $ret = self::getSingleton('e_theme', true, null, array('themedir'=> $themedir, 'force'=> $clearCache)); 1573 1574 // e107::getDb()->db_Mark_time('end e_theme'); 1575 /* echo "<pre>"; 1576 debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); 1577 echo "</pre>";*/ 1578 1579 return $ret; 1580 } 1581 1582 1583 1584 /** 1585 * Retrieve URL singleton object 1586 * 1587 * @return eURL 1588 */ 1589 public static function getUrl() 1590 { 1591 return self::getSingleton('eUrl', true); 1592 } 1593 1594 /** 1595 * Retrieve file handler singleton or new fresh object 1596 * 1597 * @param boolean $singleton default true 1598 * @return e_file 1599 */ 1600 public static function getFile($singleton = false) 1601 { 1602 if($singleton) 1603 { 1604 return self::getSingleton('e_file', true); 1605 } 1606 return self::getObject('e_file', null, true); 1607 } 1608 1609 /** 1610 * Create a new file inspector object 1611 * 1612 * Note: Only the core file inspector is supported right now. 1613 * 1614 * @return e_file_inspector 1615 */ 1616 public static function getFileInspector($type = 'core') 1617 { 1618 $fileInspectorPath = realpath(e_SYSTEM_BASE . "core_image.phar"); 1619 /** @var e_file_inspector $fileInspector */ 1620 $fileInspector = self::getObject('e_file_inspector_json_phar', $fileInspectorPath); 1621 1622 try 1623 { 1624 $fileInspector->loadDatabase(); 1625 } 1626 catch (Exception $e) 1627 { 1628 // TODO: LAN 1629 self::getMessage()->addWarning( 1630 "The core integrity image is corrupt. " . 1631 "File Inspector will be inoperative. " . 1632 "Resolve this issue by uploading a good copy of the core image to " . 1633 escapeshellarg($fileInspectorPath) . ". " . 1634 "If uploading with FTP, use binary transfer mode. " . 1635 "Error message: " . 1636 $e->getMessage() 1637 ); 1638 } 1639 1640 return $fileInspector; 1641 } 1642 1643 /** 1644 * Retrieve form handler singleton or new fresh object 1645 * 1646 * @param boolean $singleton default false 1647 * @param boolean $tabindex passed to e_form when initialized as an object (not singleton) 1648 * @return e_form 1649 */ 1650 public static function getForm($singleton = false, $tabindex = false) 1651 { 1652 if($singleton) 1653 { 1654 return self::getSingleton('e_form', true); 1655 } 1656 return self::getObject('e_form', $tabindex, true); 1657 } 1658 1659 /** 1660 * Retrieve admin log singleton object 1661 * @Deprecated - use e107::getLog(); 1662 * @return e_admin_log 1663 */ 1664 public static function getAdminLog() 1665 { 1666 return self::getSingleton('e_admin_log', true); 1667 } 1668 1669 /** 1670 * Retrieve admin log singleton object 1671 * 1672 * @return e_admin_log 1673 */ 1674 public static function getLog() 1675 { 1676 return self::getSingleton('e_admin_log', true); 1677 } 1678 1679 /** 1680 * Retrieve date handler singleton object 1681 * 1682 * @return convert 1683 */ 1684 public static function getDateConvert() 1685 { 1686 return self::getSingleton('e_date', true); 1687 } 1688 1689 /** 1690 * Retrieve date handler singleton object - preferred method. 1691 * 1692 * @return convert 1693 */ 1694 public static function getDate() 1695 { 1696 return self::getSingleton('e_date', true); 1697 } 1698 1699 1700 /** 1701 * Retrieve date handler singleton object - preferred method. 1702 * 1703 * @return e107_db_debug 1704 */ 1705 public static function getDebug() 1706 { 1707 return self::getSingleton('e107_db_debug', true); 1708 } 1709 1710 /** 1711 * Retrieve notify handler singleton object 1712 * 1713 * @return notify 1714 */ 1715 public static function getNotify() 1716 { 1717 return self::getSingleton('notify', true); 1718 } 1719 1720 1721 /** 1722 * Retrieve override handler singleton object 1723 * 1724 * @return override 1725 */ 1726 public static function getOverride() 1727 { 1728 return self::getSingleton('override', true); 1729 } 1730 1731 1732 1733 /** 1734 * Retrieve Language handler singleton object 1735 * 1736 * @return language 1737 */ 1738 public static function getLanguage() 1739 { 1740 return self::getSingleton('language', true); 1741 } 1742 1743 /** 1744 * Retrieve IP/ban handler singleton object 1745 * 1746 * @return eIPHandler 1747 */ 1748 public static function getIPHandler() 1749 { 1750 return self::getSingleton('eIPHandler', true); 1751 } 1752 1753 /** 1754 * Retrieve Xml handler singleton or new instance object 1755 * @param mixed $singleton false - new instance, true - singleton from default registry location, 'string' - registry path 1756 * @return xmlClass 1757 */ 1758 public static function getXml($singleton = true) 1759 { 1760 if($singleton) 1761 { 1762 return self::getSingleton('xmlClass', true, (true === $singleton ? '' : $singleton)); 1763 } 1764 return self::getObject('xmlClass', null, true); 1765 } 1766 1767 /** 1768 * Create a new Hybridauth object based on the provided configuration 1769 * 1770 * @return Hybridauth\Hybridauth 1771 * @throws \Hybridauth\Exception\InvalidArgumentException if Hybridauth rejects the provided config 1772 * @throws ReflectionException if this method is unintentionally broken 1773 * @deprecated v2.3.0 Use the e_user_provider interfaces instead (e107::getUserProvider()). 1774 * It's the e107 wrapper around Hybridauth. 1775 * @see e_user_provider for social login features. 1776 * @see e107::getUser() for getting a user object that may or may not have a social login. 1777 */ 1778 public static function getHybridAuth($config = null) 1779 { 1780 $e_user_provider = new e_user_provider(null, $config); 1781 $reflection = new ReflectionClass('e_user_provider'); 1782 $reflection_property = $reflection->getProperty('hybridauth'); 1783 $reflection_property->setAccessible(true); 1784 return $reflection_property->getValue($e_user_provider); 1785 } 1786 1787 /** 1788 * Create a new social login handler 1789 * @param string|null $providerName 1790 * @return e_user_provider 1791 */ 1792 public static function getUserProvider($providerName = null) 1793 { 1794 return self::getObject('e_user_provider', $providerName); 1795 } 1796 1797 /** 1798 * Retrieve userclass singleton object 1799 * 1800 * @return user_class 1801 */ 1802 public static function getUserClass() 1803 { 1804 return self::getSingleton('user_class', true); 1805 } 1806 1807 /** 1808 * Retrieve user model object. 1809 * 1810 * @param integer $user_id target user 1811 * @param boolean $checkIfCurrent if tru user_id will be compared to current user, if there is a match 1812 * current user object will be returned 1813 * @return e_system_user 1814 */ 1815 public static function getSystemUser($user_id, $checkIfCurrent = true) 1816 { 1817 if($checkIfCurrent && $user_id && $user_id === self::getUser()->getId()) 1818 { 1819 return self::getUser(); 1820 } 1821 1822 if(!$user_id) return self::getObject('e_system_user'); 1823 1824 $user = self::getRegistry('core/e107/user/'.$user_id); 1825 if(null === $user) 1826 { 1827 $user = self::getObject('e_system_user'); 1828 if($user_id) $user->load($user_id); // self registered on load 1829 } 1830 return $user; 1831 } 1832 1833 /** 1834 * Simple replacement for deprecated get_user_data(). e107::user(); 1835 * @param $uid integer user_id or leave empty for currently logged in user. 1836 * @return array of user data 1837 */ 1838 public static function user($uid=null) 1839 { 1840 $uid = intval($uid); 1841 1842 if(empty($uid)){ return false; } 1843 1844 $user = self::getSystemUser($uid, true); 1845 $var = array(); 1846 if($user) 1847 { 1848 $var = $user->getUserData(); 1849 } 1850 1851 return $var; 1852 } 1853 1854 1855 /** 1856 * Return a string containg exported array data. - preferred. 1857 * 1858 * @param array $ArrayData array to be stored 1859 * @param bool|string $mode true = var_export with addedslashes, false = var_export (default), 'json' = json encoded 1860 * @return array|string 1861 */ 1862 public static function serialize($ArrayData, $mode = false) 1863 { 1864 return self::getArrayStorage()->serialize($ArrayData, $mode); 1865 } 1866 1867 /** 1868 * Returns an array from stored array data. 1869 * 1870 * @param string $ArrayData 1871 * @return array stored data 1872 */ 1873 public static function unserialize($ArrayData) 1874 { 1875 if(empty($ArrayData)) 1876 { 1877 return array(); 1878 } 1879 1880 return self::getArrayStorage()->unserialize($ArrayData); 1881 } 1882 1883 1884 /** 1885 * Retrieve current user model object. 1886 * 1887 * @return e_user 1888 */ 1889 public static function getUser() 1890 { 1891 $user = self::getRegistry('core/e107/current_user'); 1892 if(null === $user) 1893 { 1894 $user = self::getObject('e_user'); 1895 self::setRegistry('core/e107/current_user', $user); 1896 } 1897 return $user; 1898 } 1899 1900 1901 /** 1902 * Retrieve front or admin Model. 1903 * @param string $type 1904 * @return object e_front_model or e_admin_model; 1905 */ 1906 public static function getModel($type='front') 1907 { 1908 if($type === 'front') 1909 { 1910 return self::getObject('e_front_model'); 1911 } 1912 1913 return self::getObject('e_admin_model'); 1914 } 1915 1916 /** 1917 * Retrieve user model object. 1918 * 1919 * @param integer $user_id target user 1920 * @return e_user_extended_structure_tree 1921 */ 1922 public static function getUserStructure() 1923 { 1924 return self::getSingleton('e_user_extended_structure_tree', true); 1925 } 1926 1927 /** 1928 * Retrieve User Extended handler singleton object 1929 * @return e107_user_extended 1930 */ 1931 public static function getUserExt() 1932 { 1933 return self::getSingleton('e107_user_extended', true); 1934 } 1935 1936 /** 1937 * Retrieve User Perms (admin perms) handler singleton object 1938 * @return e_userperms 1939 */ 1940 public static function getUserPerms() 1941 { 1942 return self::getSingleton('e_userperms', true); 1943 } 1944 1945 /** 1946 * Retrieve online users handler singleton object 1947 * @return e_ranks 1948 */ 1949 public static function getRank() 1950 { 1951 return self::getSingleton('e_ranks', true); 1952 } 1953 1954 /** 1955 * Retrieve plugin handler singleton object 1956 * @return e107plugin 1957 */ 1958 public static function getPlugin() 1959 { 1960 return self::getSingleton('e107plugin', true); 1961 } 1962 1963 1964 1965 /** 1966 * Retrieve plugin class singleton object 1967 * @return e_plugin 1968 */ 1969 public static function getPlug() 1970 { 1971 return self::getSingleton('e_plugin', true); 1972 } 1973 1974 /** 1975 * Retrieve online users handler singleton object 1976 * @return e_online 1977 */ 1978 public static function getOnline() 1979 { 1980 return self::getSingleton('e_online', true); 1981 } 1982 1983 1984 /** 1985 * Retrieve chart handler singleton object 1986 * @return e_chart 1987 */ 1988 public static function getChart() 1989 { 1990 return self::getObject('e_chart', null, true); 1991 } 1992 1993 1994 /** 1995 * Retrieve comments handler singleton object 1996 * @return comment 1997 */ 1998 public static function getComment() 1999 { 2000 return self::getSingleton('comment', true); 2001 } 2002 2003 /** 2004 * Retrieve comments handler singleton object 2005 * @return e_customfields 2006 */ 2007 public static function getCustomFields() 2008 { 2009 return self::getSingleton('e_customfields', true); 2010 } 2011 2012 /** 2013 * Retrieve Media handler singleton object 2014 * @return e_media 2015 */ 2016 public static function getMedia() 2017 { 2018 return self::getSingleton('e_media', true); 2019 } 2020 2021 /** 2022 * Retrieve Navigation Menu handler singleton object 2023 * @return e_navigation 2024 */ 2025 public static function getNav() 2026 { 2027 return self::getSingleton('e_navigation', true); 2028 } 2029 2030 /** 2031 * Retrieve message handler singleton 2032 * @return eMessage 2033 */ 2034 public static function getMessage() 2035 { 2036 // static $included = false; 2037 // if(!$included) 2038 // { 2039 // e107_require_once(e_HANDLER.'message_handler.php'); 2040 // $included = true; 2041 // } 2042 // return eMessage::getInstance(); 2043 return self::getSingleton('eMessage', true); 2044 } 2045 2046 /** 2047 * Retrieve ajax singleton object 2048 * 2049 * @return e_ajax 2050 */ 2051 public static function getAjax() 2052 { 2053 return self::getSingleton('e_ajax', true); 2054 } 2055 2056 /** 2057 * Retrieve Library Manager singleton object (internal use only. Use e107::library()) 2058 * 2059 * @return e_library_manager 2060 */ 2061 public static function getLibrary() 2062 { 2063 return self::getSingleton('e_library_manager', true); 2064 } 2065 2066 /** 2067 * Library Common Public Function. 2068 * 2069 * @param string $action 2070 * - 'detect': Tries to detect a library and its installed version. 2071 * - 'load': Loads a library. 2072 * @param string $library 2073 * The name of the library to detect/load. 2074 * @param string $variant 2075 * (Optional for 'load') The name of the variant to load. Note that only one variant of a library can be loaded 2076 * within a single request. The variant that has been passed first is used; different variant names in subsequent 2077 * calls are ignored. 2078 * 2079 * @return array|boolean 2080 * - In case of 'detect': An associative array containing registered information for the library specified by 2081 * $name, or FALSE if the library $name is not registered. 2082 * - In case of 'load': An associative array of the library information. 2083 * - In case of 'info': An associative array containing registered information for all libraries, the registered 2084 * information for the library specified by $name, or FALSE if the library $name is not registered. 2085 */ 2086 public static function library($action = '', $library = null, $variant = null) 2087 { 2088 $libraryHandler = self::getLibrary(); 2089 2090 switch($action) 2091 { 2092 case 'detect': 2093 return $libraryHandler->detect($library); 2094 break; 2095 2096 case 'load': 2097 $cdn = (bool) self::getPref('e_jslib_cdn', true); 2098 $debug = (bool) deftrue('e_DEBUG'); 2099 $admin = (bool) defset('e_ADMIN_AREA', false); 2100 2101 // Try to detect and load CDN version. 2102 if(!$admin && $cdn && strpos($library, 'cdn.') !== 0) 2103 { 2104 $lib = $libraryHandler->detect('cdn.' . $library); 2105 2106 // If CDN version is available. 2107 if($lib && !empty($lib['installed'])) 2108 { 2109 // If a variant is specified, we need to check if it's installed. 2110 if(!empty($variant) && !empty($lib['variants'][$variant]['installed'])) 2111 { 2112 // Load CDN version with the variant. 2113 return $libraryHandler->load('cdn.' . $library, $variant); 2114 } 2115 2116 // If CDN version is available, but no variant is specified, 2117 // and debug mode is on, try to load 'debug' variant. 2118 if(empty($variant) && $debug && !empty($lib['variants']['dev']['installed'])) 2119 { 2120 // Load CDN version with 'debug' variant. 2121 return $libraryHandler->load('cdn.' . $library, 'dev'); 2122 } 2123 2124 // Load CDN version without variant. 2125 return $libraryHandler->load('cdn.' . $library, $variant); 2126 } 2127 } 2128 2129 // If no variant is specified, and CDN version is not available, and debug mode is on. 2130 if(empty($variant) && $debug) 2131 { 2132 $lib = $libraryHandler->detect($library); 2133 2134 // If 'debug' variant is available. 2135 if($lib && !empty($lib['variants']['dev']['installed'])) 2136 { 2137 // Load library with 'debug' variant. 2138 return $libraryHandler->load($library, 'dev'); 2139 } 2140 } 2141 2142 return $libraryHandler->load($library, $variant); 2143 break; 2144 2145 case 'info': 2146 return $libraryHandler->info($library); 2147 break; 2148 } 2149 } 2150 2151 /** 2152 * Retrieve JS Manager singleton object 2153 * 2154 * @return e_jsmanager 2155 */ 2156 public static function getJs() 2157 { 2158 static $included = false; 2159 if(!$included) 2160 { 2161 e107_require_once(e_HANDLER.'js_manager.php'); 2162 $included = true; 2163 } 2164 return e_jsmanager::getInstance(); 2165 } 2166 2167 2168 public static function set($type=null, $val=true) 2169 { 2170 if($type === 'js_enabled') 2171 { 2172 self::$_js_enabled = (bool) $val; 2173 } 2174 2175 if($type === 'css_enabled') 2176 { 2177 self::$_css_enabled = (bool) $val; 2178 } 2179 } 2180 2181 2182 2183 /** 2184 * JS Common Public Function. Prefered is shortcode script path 2185 * @param string $type core|theme|footer|inline|footer-inline|url or any existing plugin_name 2186 * @param string|array $data depends on the type - path/url or inline js source 2187 * @param integer $zone [optional] leave it null for default zone 2188 * @param string $dep dependence : null | prototype | jquery 2189 */ 2190 public static function js($type, $data, $dep = null, $zone = null, $pre = '', $post = '') 2191 { 2192 if(self::$_js_enabled === false) 2193 { 2194 return null; 2195 } 2196 2197 $jshandler = self::getJs(); 2198 $jshandler->setDependency($dep); 2199 2200 switch ($type) 2201 { 2202 case 'settings': 2203 $jshandler->jsSettings($data); 2204 break; 2205 2206 case 'core': 2207 // data is e.g. 'core/tabs.js' 2208 if(null !== $zone) $jshandler->requireCoreLib($data, $zone); 2209 else $jshandler->requireCoreLib($data); 2210 break; 2211 2212 case 'bootstrap': //TODO Eventually add own method and render for bootstrap. 2213 if(null !== $zone) $jshandler->requireCoreLib('bootstrap/js/'.$data, $zone); 2214 else $jshandler->requireCoreLib('bootstrap/js/'.$data); 2215 break; 2216 2217 case 'theme': 2218 // data is e.g. 'jslib/mytheme.js' 2219 if(null !== $zone) $jshandler->headerTheme($data, $zone, $pre, $post); 2220 else $jshandler->footerTheme($data, 5, $pre, $post); 2221 break; 2222 2223 case 'inline': 2224 // data is JS source (without script tags) 2225 if(null !== $zone) $jshandler->headerInline($data, $zone); 2226 else $jshandler->headerInline($data); 2227 break; 2228 2229 case 'footer-inline': 2230 // data is JS source (without script tags) 2231 if(null !== $zone) $jshandler->footerInline($data, $zone); 2232 else $jshandler->footerInline($data); 2233 break; 2234 2235 case 'url': 2236 // data is e.g. 'http://cdn.somesite.com/some.js' 2237 if(null !== $zone) $jshandler->headerFile($data, $zone, $pre, $post); 2238 else $jshandler->headerFile($data, 5, $pre, $post); 2239 break; 2240 2241 case 'footer': 2242 // data is e.g. '{e_PLUGIN}myplugin/jslib/myplug.js' 2243 if(null !== $zone) $jshandler->footerFile($data, $zone, $pre, $post); 2244 else $jshandler->footerFile($data, 5, $pre, $post); 2245 break; 2246 2247 // $type is plugin name 2248 default: 2249 // data is e.g. 'jslib/myplug.js' 2250 if(!self::isInstalled($type)) return; 2251 if(null !== $zone) $jshandler->requirePluginLib($type, $data, $zone); 2252 else $jshandler->requirePluginLib($type, $data); 2253 break; 2254 } 2255 2256 $jshandler->resetDependency(); 2257 } 2258 2259 2260 /** 2261 * Add a <link> tag to the head of the html document. 2262 * @param array $attributes 2263 * @example e107::link(array('rel'=>"dns-prefetch", "href" => "http://example-domain.com/")); 2264 */ 2265 public static function link($attributes=array()) 2266 { 2267 self::getJs()->addLink($attributes); 2268 } 2269 2270 2271 2272 2273 /** 2274 * CSS Common Public Function. Prefered is shortcode script path 2275 * @param string $type core|theme|footer|inline|footer-inline|url or any existing plugin_name 2276 * @param string $data depends on the type - path/url or inline js source 2277 * @param null $dep 2278 * @param string $media any valid media attribute string - http://www.w3schools.com/TAGS/att_link_media.asp 2279 * @param string $preComment possible comment e.g. <!--[if lt IE 7]> 2280 * @param string $postComment possible comment e.g. <![endif]--> 2281 * @param null $dependence 2282 */ 2283 public static function css($type, $data, $dep = null, $media = 'all', $preComment = '', $postComment = '', $dependence = null) 2284 { 2285 2286 /* if((strpos($data,'bootstrap.css')!==false || strpos($data,'bootstrap.min.css')!==false) && !defined("BOOTSTRAP")) // detect bootstrap is enabled. - used in nextprev.sc and forum currently. 2287 { 2288 define("BOOTSTRAP", true); 2289 }*/ 2290 2291 if(self::$_css_enabled === false) 2292 { 2293 return null; 2294 } 2295 2296 $jshandler = self::getJs(); 2297 $jshandler->setDependency($dep); 2298 2299 if(strpos($data,'http')===0) 2300 { 2301 $type = 'url'; 2302 } 2303 2304 switch ($type) 2305 { 2306 case 'core': 2307 // data is path relative to e_FILE/jslib/ 2308 $jshandler->coreCSS($data, $media, $preComment, $postComment); 2309 break; 2310 2311 case 'bootstrap': 2312 // data is path relative to e_FILE/jslib/ 2313 $jshandler->coreCSS('bootstrap/css/'.$data, $media, $preComment, $postComment); 2314 break; 2315 2316 case 'theme': 2317 // data is path relative to current theme 2318 $jshandler->themeCSS($data, $media, $preComment, $postComment); 2319 break; 2320 2321 case 'inline': 2322 // data is CSS source (without style tags) 2323 $jshandler->inlineCSS($data, $media); 2324 break; 2325 2326 case 'url': 2327 // data is e.g. 'http://cdn.somesite.com/some.css' 2328 $jshandler->otherCSS($data, $media, $preComment, $postComment); 2329 break; 2330 2331 // $type is plugin name 2332 default: 2333 // data is e.g. 'css/myplug.css' 2334 if(self::isInstalled($type)) $jshandler->pluginCSS($type, $data, $media, $preComment, $postComment); 2335 break; 2336 } 2337 $jshandler->resetDependency(); 2338 } 2339 2340 2341 /** 2342 * Throw log/info/warnings/errors to the Chrome/Firefox Console. 2343 * @param $name 2344 * @param null $var 2345 * @param string $type 2346 */ 2347 public static function debug($name, $var = null, $type = 'log') 2348 { 2349 2350 $nl = "\r\n"; 2351 // echo "alert('hi');"; 2352 $text = ''; 2353 2354 switch($type) { 2355 case 'log': 2356 $text .= 'console.log("'.$name.'");'.$nl; 2357 break; 2358 case 'info': 2359 $text .= 'console.info("'.$name.'");'.$nl; 2360 break; 2361 case 'warning': 2362 $text .= 'console.warn("'.$name.'");'.$nl; 2363 break; 2364 case 'error': 2365 $text .= 'console.error("'.$name.'");'.$nl; 2366 break; 2367 } 2368 2369 if (!empty($var)) 2370 { 2371 if (is_object($var) || is_array($var)) 2372 { 2373 $object = json_encode($var); 2374 2375 $text .= 'var object'.preg_replace('~[^A-Z|0-9]~i',"_",$name).' = \''.str_replace("'","\'",$object).'\';'.$nl; 2376 $text .= 'var val'.preg_replace('~[^A-Z|0-9]~i',"_",$name).' = eval("(" + object'.preg_replace('~[^A-Z|0-9]~i',"_",$name).' + ")" );'.$nl; 2377 2378 switch($type) 2379 { 2380 case 'log': 2381 $text .= 'console.debug(val'.preg_replace('~[^A-Z|0-9]~i',"_",$name).');'.$nl; 2382 break; 2383 case 'info': 2384 $text .= 'console.info(val'.preg_replace('~[^A-Z|0-9]~i',"_",$name).');'.$nl; 2385 break; 2386 case 'warning': 2387 $text .= 'console.warn(val'.preg_replace('~[^A-Z|0-9]~i',"_",$name).');'.$nl; 2388 break; 2389 case 'error': 2390 $text .= 'console.error(val'.preg_replace('~[^A-Z|0-9]~i',"_",$name).');'.$nl; 2391 break; 2392 } 2393 } 2394 else 2395 { 2396 switch($type) 2397 { 2398 case 'log': 2399 $text .= 'console.debug("'.str_replace('"','\\"',$var).'");'.$nl; 2400 break; 2401 case 'info': 2402 $text .= 'console.info("'.str_replace('"','\\"',$var).'");'.$nl; 2403 break; 2404 case 'warning': 2405 $text .= 'console.warn("'.str_replace('"','\\"',$var).'");'.$nl; 2406 break; 2407 case 'error': 2408 $text .= 'console.error("'.str_replace('"','\\"',$var).'");'.$nl; 2409 break; 2410 } 2411 } 2412 } 2413 2414 2415 self::js('footer-inline', $text); 2416 2417 } 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 /** 2428 * Retrieve JS Helper object 2429 * 2430 * @param boolean|string $singleton if true return singleton, if string return singleton object, use string as namespace, default false 2431 * @return e_jshelper 2432 */ 2433 public static function getJshelper($singleton = false) 2434 { 2435 if($singleton) 2436 { 2437 return self::getSingleton('e_jshelper', true, (true === $singleton ? '' : $singleton)); 2438 } 2439 return self::getObject('e_jshelper', null, true); 2440 } 2441 2442 /** 2443 * @see eResponse::addMeta() 2444 * @param null $name 2445 * @param null $content 2446 * @param array $extended 2447 * @return eResponse 2448 */ 2449 public static function meta($name = null, $content = null, $extended = array()) 2450 { 2451 /** @var eResponse $response */ 2452 $response = self::getSingleton('eResponse'); 2453 2454 if($name === 'description') 2455 { 2456 $response->addMetaDescription($content); //Cam: TBD 2457 } 2458 2459 if($name === 'keywords') 2460 { 2461 $response->addMetaKeywords($content); //Cam: TBD 2462 } 2463 2464 return $response->addMeta($name, $content, $extended); 2465 // return self::getUrl()->response()->addMeta($name, $content, $extended); 2466 } 2467 2468 /** 2469 * Retrieve admin dispatcher instance. 2470 * It's instance is self registered (for now, this could change in the future) on initialization (__construct()) 2471 * 2472 * @see e_admin_dispatcher 2473 * @return e_admin_dispatcher 2474 */ 2475 public static function getAdminUI() 2476 { 2477 return self::getRegistry('admin/ui/dispatcher'); 2478 } 2479 2480 /** 2481 * Retrieves class Object for specific plugin's addon such as e_url.php, e_cron.php, e_sitelink.php 2482 * FIXME override from e.g. core/override/addons/ 2483 * 2484 * @param string $pluginName e.g. faq, page 2485 * @param string $addonName eg. e_cron, e_url, e_module 2486 * @param mixed $className [optional] true - use default name, false - no object is returned (include only), any string will be used as class name 2487 * @param mixed $param [optional] construct() param 2488 * @return object 2489 */ 2490 public static function getAddon($pluginName, $addonName, $className = true) 2491 { 2492 $filename = $addonName; // e.g. 'e_cron'; 2493 2494 // fixme, temporary adding 's' to className, should be core fixed, better naming 2495 if(true === $className) $className = $pluginName.'_'.substr($addonName, 2); // remove 'e_' 2496 2497 $elist = self::getPref($filename.'_list'); 2498 2499 if($filename === 'e_menu') 2500 { 2501 if(!in_array($pluginName, $elist)) return null; 2502 } 2503 else 2504 { 2505 if(!isset($elist[$pluginName])) return null; 2506 } 2507 2508 // TODO override check comes here 2509 $path = e_PLUGIN.$pluginName.'/'.$filename.'.php'; 2510 // e.g. include e_module, e_meta etc 2511 if(false === $className) return include_once($path); 2512 2513 if(!class_exists($className, false)) 2514 { 2515 include_once($path); 2516 } 2517 2518 if(!class_exists($className, false)) 2519 { 2520 return null; 2521 } 2522 return new $className; 2523 } 2524 2525 /** 2526 * Retrieves config() from all plugins for addons such as e_url.php, e_cron.php, e_sitelink.php 2527 * @param string $addonName eg. e_cron, e_url 2528 * @param string $className [optional] (if different from addonName) 2529 * @param string $methodName [optional] (if different from 'config') 2530 * @return array 2531 */ 2532 public static function getAddonConfig($addonName, $className = '', $methodName='config', $param=null,$param2=null ) 2533 { 2534 $new_addon = array(); 2535 2536 $sql = self::getDb(); // Might be used by older plugins. 2537 2538 $filename = $addonName; // e.g. 'e_cron'; 2539 if(!$className) 2540 { 2541 $className = substr($filename, 2); // remove 'e_' 2542 } 2543 2544 $elist = self::getPref($filename.'_list'); 2545 2546 if(!empty($elist)) 2547 { 2548 foreach(array_keys($elist) as $key) 2549 { 2550 if(is_readable(e_PLUGIN.$key.'/'.$filename.'.php')) 2551 { 2552 include_once(e_PLUGIN.$key.'/'.$filename.'.php'); 2553 2554 $class_name = $key.'_'.$className; 2555 $array = self::callMethod($class_name, $methodName,$param,$param2); 2556 2557 if($array) 2558 { 2559 $new_addon[$key] = $array; 2560 } 2561 2562 } 2563 } 2564 } 2565 2566 return $new_addon; 2567 } 2568 2569 2570 /** 2571 * Safe way to call user methods. 2572 * @param string|object $class_name 2573 * @param string $method_name 2574 * @param mixed $param -1st parameter sent to method 2575 * @param mixed $param2 - 2nd parameter sent to method 2576 * @return array|bool FALSE 2577 */ 2578 public static function callMethod($class_name, $method_name, $param=null, $param2=null) 2579 { 2580 $mes = self::getMessage(); 2581 2582 if(is_object($class_name) || class_exists($class_name)) 2583 { 2584 2585 if(is_object($class_name)) 2586 { 2587 $obj = $class_name; 2588 $class_name = get_class($obj); 2589 } 2590 else 2591 { 2592 $obj = new $class_name; 2593 } 2594 2595 if(method_exists($obj, $method_name)) 2596 { 2597 if(E107_DBG_INCLUDES) 2598 { 2599 //$debug_backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 6); 2600 $mes->addDebug('Executing <strong>'.$class_name.' :: '.$method_name.'()</strong>'); 2601 } 2602 return call_user_func(array($obj, $method_name),$param, $param2); 2603 } 2604 else 2605 { 2606 // $mes->addDebug('Function <strong>'.$class_name.' :: '.$method_name.'()</strong> NOT found.'); 2607 } 2608 } 2609 return FALSE; 2610 } 2611 2612 /** 2613 * Retrieves the e_url config - new v2.1.6 2614 * @param string $mode config | alias | profile 2615 * @return array 2616 */ 2617 public static function getUrlConfig($mode='config') 2618 { 2619 $new_addon = array(); 2620 2621 $filename = 'e_url'; 2622 $elist = self::getPref($filename.'_list'); 2623 $className = substr($filename, 2); // remove 'e_' 2624 $methodName = 'config'; 2625 2626 $url_profiles = e107::getPref('url_profiles'); 2627 2628 if(!empty($elist)) 2629 { 2630 foreach(array_keys($elist) as $key) 2631 { 2632 if(is_readable(e_PLUGIN.$key.'/'.$filename.'.php')) 2633 { 2634 2635 2636 include_once(e_PLUGIN.$key.'/'.$filename.'.php'); 2637 2638 $class_name = $key.'_'.$className; 2639 2640 if(is_object($class_name)) 2641 { 2642 $obj = $class_name; 2643 $class_name = get_class($obj); 2644 } 2645 elseif(class_exists($class_name)) 2646 { 2647 $obj = new $class_name; 2648 } 2649 else 2650 { 2651 continue; 2652 } 2653 2654 if($mode === 'alias') 2655 { 2656 if(!empty($obj->alias)) 2657 { 2658 $new_addon[$key] = $obj->alias; 2659 } 2660 2661 continue; 2662 } 2663 2664 if($mode === 'profiles') 2665 { 2666 if(!empty($obj->profiles)) 2667 { 2668 $new_addon[$key] = $obj->profiles; 2669 } 2670 2671 continue; 2672 } 2673 2674 if($mode === 'generate') 2675 { 2676 if(!empty($obj->generate)) 2677 { 2678 $new_addon[$key] = $obj->generate; 2679 } 2680 2681 continue; 2682 } 2683 2684 $profile = !empty($url_profiles[$key]) ? $url_profiles[$key] : null; 2685 2686 $array = self::callMethod($obj, $methodName,$profile); 2687 2688 if($array) 2689 { 2690 foreach($array as $k=>$v) 2691 { 2692 if(empty($v['alias']) && !empty($obj->alias)) 2693 { 2694 $v['alias'] = $obj->alias; 2695 } 2696 $new_addon[$key][$k] = $v; 2697 2698 } 2699 2700 } 2701 2702 } 2703 } 2704 } 2705 2706 return $new_addon; 2707 } 2708 2709 /** 2710 * Get theme name or path. 2711 * 2712 * @param mixed $for true (default) - auto-detect (current), admin - admin theme, front - site theme 2713 * @param string $path default empty string (return name only), 'abs' - absolute url path, 'rel' - relative server path 2714 * @return string 2715 */ 2716 public static function getThemeInfo($for = true, $path = '') 2717 { 2718 // global $user_pref; // FIXME - user model, kill user_pref global 2719 2720 if(true === $for) 2721 { 2722 $for = e_ADMIN_AREA ? 'admin' : 'front'; 2723 } 2724 switch($for ) 2725 { 2726 case 'admin': 2727 $for = self::getPref('admintheme'); 2728 break; 2729 2730 case 'front': 2731 2732 if(defined('USERTHEME') && USERTHEME !==false) 2733 { 2734 $for = USERTHEME; 2735 } 2736 else 2737 { 2738 $user_pref = self::getUser()->getPref(); 2739 $for = !empty($user_pref['sitetheme']) ? $user_pref['sitetheme'] : self::getPref('sitetheme'); 2740 } 2741 2742 break; 2743 } 2744 if(!$path) return $for; 2745 2746 switch($path) 2747 { 2748 case 'abs': 2749 $path = e_THEME_ABS.$for.'/'; 2750 break; 2751 2752 case 'rel': 2753 default: 2754 $path = e_THEME.$for.'/'; 2755 break; 2756 } 2757 return $path; 2758 } 2759 2760 /** 2761 * Retrieve core template path 2762 * Example: <code>echo e107::coreTemplatePath('admin_icons');</code> 2763 * 2764 * @see getThemeInfo() 2765 * @param string $id part of the path/file name without _template.php part 2766 * @param boolean $override default true 2767 * @return string relative path 2768 */ 2769 public static function coreTemplatePath($id, $override = true) 2770 { 2771 $id = str_replace('..', '', $id); //simple security, '/' is allowed 2772 $curTheme = self::getThemeInfo($override, 'rel'); 2773 2774 $override_path = $override ? $curTheme.'templates/'.$id.'_template.php' : null; 2775 $legacy_override_path = $override ? $curTheme.$id.'_template.php' : null; 2776 2777 $core_path = e_CORE.'templates/'.$id.'_template.php'; // default 2778 $core_path_legacy = e_CORE.'templates/legacy/'.$id.'_template.php'; 2779 $core_path_bs4 = e_CORE.'templates/bootstrap4/'.$id.'_template.php'; 2780 2781 if($override_path && is_readable($override_path)) // v2 override template. 2782 { 2783 return $override_path; 2784 } 2785 elseif($legacy_override_path && is_readable($legacy_override_path)) //v1 override template. 2786 { 2787 return $legacy_override_path; 2788 } 2789 elseif(THEME_LEGACY === true && is_readable($core_path_legacy)) //v1 core template. 2790 { 2791 return $core_path_legacy; 2792 } 2793 elseif(defset('BOOTSTRAP') === 4 && is_readable($core_path_bs4)) 2794 { 2795 return $core_path_bs4; 2796 } 2797 2798 return $core_path; 2799 } 2800 2801 /** 2802 * Retrieve plugin template path 2803 * Override path could be forced to front- or back-end via 2804 * the $override parameter e.g. <code> e107::templatePath(plug_name, 'my', 'front')</code> 2805 * Example: 2806 * <code> 2807 * echo e107::templatePath(plug_name, 'my'); 2808 * // result is something like: 2809 * // e107_themes/current_theme/templates/plug_name/my_template.php 2810 * // or if not found 2811 * // e107_plugins/plug_name/templates/my_template.php 2812 * </code> 2813 * 2814 * @see getThemeInfo() 2815 * @param string $plug_name plugin name 2816 * @param string $id part of the path/file name without _template.php part 2817 * @param boolean|string $override default true 2818 * @return string relative path 2819 */ 2820 public static function templatePath($plug_name, $id, $override = true) 2821 { 2822 $id = str_replace('..', '', $id); //simple security, '/' is allowed 2823 $plug_name = preg_replace('#[^a-z0-9_]#i', '', $plug_name); // only latin allowed, so \w not a solution since PHP5.3 2824 $override_path = $override ? self::getThemeInfo($override, 'rel').'templates/'.$plug_name.'/'.$id.'_template.php' : null; 2825 $default_path = e_PLUGIN.$plug_name.'/templates/'.$id.'_template.php'; 2826 2827 return ($override_path && is_readable($override_path) ? $override_path : $default_path); 2828 } 2829 2830 /** 2831 * Get core template. Use this method for templates, which are following the 2832 * new template standards: 2833 * - template variables naming conventions 2834 * - one array variable per template only 2835 * - theme override is made now by current_theme/templates/ folder 2836 * 2837 * <br><br>Results are cached (depending on $id and $override so it's safe to use 2838 * this method e.g. in loop for retrieving a template string. If template (or template key) is not 2839 * found, <b>NULL</b> is returned.<br><br> 2840 * 2841 * Example usage: <code>e107::getCoreTemplate('user', 'short_start');</code> 2842 * Will search for: 2843 * - e107_themes/current_frontend_theme/templates/user_template.php (if $override is true) 2844 * - e107_themes/templates/user_template.php (if override not found or $override is false) 2845 * - $USER_TEMPLATE array which contains all user templates 2846 * - $USER_TEMPLATE['short_start'] (if key is null, $USER_TEMPLATE will be returned) 2847 * 2848 * @param string $id - file prefix, e.g. user for user_template.php 2849 * @param string|null $key 2850 * @param mixed $override see {@link getThemeInfo()} true/false, front or admin. 2851 * @param boolean $merge merge theme with core templates, default is false 2852 * @param boolean $info retrieve template info only 2853 * @return string|array 2854 */ 2855 public static function getCoreTemplate($id, $key = null, $override = true, $merge = false, $info = false) 2856 { 2857 $reg_path = 'core/e107/templates/'.$id.($override ? '/ext' : ''); 2858 $path = self::coreTemplatePath($id, $override); 2859 $id = str_replace('/', '_', $id); 2860 $ret = self::_getTemplate($id, $key, $reg_path, $path, $info); 2861 2862 ### Attempt to fix merge issues; in case we override - template array not found in theme, 2863 ### so we need to continue and merge with core templates 2864 if($merge && $override && empty($ret)) 2865 { 2866 $ret = array(); 2867 } 2868 2869 if((!$merge && !$override) || is_string($ret)) 2870 { 2871 return $ret; 2872 } 2873 2874 // merge 2875 $reg_path = 'core/e107/templates/'.$id; 2876 $path = self::coreTemplatePath($id, false); 2877 $id = str_replace('/', '_', $id); 2878 // Introducing noWrapper when merging 2879 $ret_core = self::_getTemplate($id, $key, $reg_path, $path, $info, true); 2880 2881 return (is_array($ret_core) ? array_merge($ret_core, $ret) : $ret); 2882 } 2883 2884 /** 2885 * Get plugin template. Use this method for plugin templates, which are following the 2886 * new template standards: 2887 * - template variables naming conventions ie. ${NAME IN CAPS}_TEMPLATE['{ID}'] = "<div>...</div>"; 2888 * - one array variable per template only 2889 * - theme override is made now by current_theme/templates/plugin_name/ folder 2890 * 2891 * <br><br>Results are cached (depending on $id and $override so it's safe to use 2892 * this method e.g. in loop for retrieving a template string. If template (or template key) is not 2893 * found, <b>NULL</b> is returned.<br><br> 2894 * 2895 * Example usage: <code>e107::getTemplate('user', 'short_start');</code> 2896 * Will search for: 2897 * - e107_themes/{current_frontend_theme}/templates/user_template.php (if $override is true) - this is the default. 2898 * - e107_core/templates/user_template.php (if override not found or $override is false) 2899 * - $USER_TEMPLATE array which contains all user templates 2900 * - $USER_TEMPLATE['short_start'] (if key is null, $USER_TEMPLATE will be returned) 2901 * 2902 * @param string $plug_name if null getCoreTemplate method will be called 2903 * @param string $id - file prefix, e.g. calendar for calendar_template.php 2904 * @param string|null $key 2905 * @param boolean $override see {@link getThemeInfo()} 2906 * @param boolean $merge merge theme with plugin templates, default is false 2907 * @param boolean $info retrieve template info only 2908 * @return string|array 2909 */ 2910 public static function getTemplate($plug_name, $id = null, $key = null, $override = true, $merge = false, $info = false) 2911 { 2912 if(!$plug_name) 2913 { 2914 return self::getCoreTemplate($id, $key, $override, $merge, $info); 2915 } 2916 if(null == $id || true === $id) // loads {$plug_name}/templates/{$plug_name}_template.php and an array ${PLUG_NAME}_TEMPLATE 2917 { 2918 $id = $plug_name; 2919 } 2920 $reg_path = 'plugin/'.$plug_name.'/templates/'.$id.($override ? '/ext' : ''); 2921 $path = self::templatePath($plug_name, $id, $override); 2922 2923 if(ADMIN && E107_DBG_INCLUDES) 2924 { 2925 self::getMessage()->addDebug( "Attempting to load Template File: ".$path ); 2926 } 2927 2928 /** 2929 * "front" and "global" LANs might not be loaded come self::_getTemplate(), 2930 * so the following calls to self::plugLan() fix that. 2931 */ 2932 self::plugLan($plug_name, null, true); 2933 self::plugLan($plug_name, null, false); 2934 self::plugLan($plug_name, 'global', true); 2935 self::plugLan($plug_name, 'global', false); 2936 2937 $id = str_replace('/', '_', $id); 2938 $ret = self::_getTemplate($id, $key, $reg_path, $path, $info); 2939 2940 if($merge === false || $override === false) 2941 { 2942 return ($ret === false) ? '' : $ret; 2943 } 2944 2945 // merge 2946 $reg_path = 'plugin/'.$plug_name.'/templates/'.$id; 2947 $path = self::templatePath($plug_name, $id, false); 2948 2949 $id = str_replace('/', '_', $id); 2950 // Introduced noWrapper when merging 2951 $ret_plug = self::_getTemplate($id, $key, $reg_path, $path, $info, true); 2952 2953 if($merge === true && $key !== null && $ret === false) // key not set, so send 'core' version instead. 2954 { 2955 return $ret_plug; 2956 } 2957 2958 if($ret === false) 2959 { 2960 return ''; 2961 } 2962 2963 return (is_array($ret_plug) ? array_merge($ret_plug, $ret) : $ret); 2964 } 2965 2966 /** 2967 * Register sc_style registry 2968 * @param string $templateId e.g. 'contact/form' or 'contact' for all contact template wrappers 2969 * @param string $scName [optional] shortcode name - if provided, wrapper (string) for the corresponding code will be returned 2970 * @return array|string 2971 */ 2972 public static function templateWrapper($templateId, $scName = null) 2973 { 2974 if(!$templateId) return array(); 2975 2976 list($templateId, $templateKey) = explode('/', $templateId, 2); 2977 2978 $wrapperRegPath = 'templates/wrapper/'.$templateId; 2979 2980 $wrapper = self::getRegistry($wrapperRegPath); 2981 2982 if(empty($wrapper) || !is_array($wrapper)) $wrapper = array(); 2983 2984 if(strpos($templateKey,'/')!==false) // quick fix support for 3 keys eg. news/view/item 2985 { 2986 list($templateKey,$templateKey2) = explode("/", $templateKey, 2); 2987 if($templateKey && $templateKey2) 2988 { 2989 $wrapper = (isset($wrapper[$templateKey][$templateKey2]) ? $wrapper[$templateKey][$templateKey2] : array()); 2990 } 2991 } 2992 else // support for 2 keys. eg. contact/form 2993 { 2994 if($templateKey) $wrapper = (isset($wrapper[$templateKey]) ? $wrapper[$templateKey] : array()); 2995 } 2996 2997 if(null !== $scName) 2998 { 2999 $scName = strtoupper($scName); 3000 return isset($wrapper[$scName]) ? $wrapper[$scName] : ''; 3001 } 3002 3003 return $wrapper; 3004 } 3005 3006 /** 3007 * Retrieve/set sc_style array (global shortcode wrapper) 3008 * @param array $set template defined $sc_style, will be merged with current registry content 3009 * @return array 3010 */ 3011 public static function scStyle($set = null) 3012 { 3013 $_sc_style = self::getRegistry('shortcodes/sc_style'); 3014 if(!is_array($_sc_style)) $_sc_style = array(); 3015 if(is_array($set) && !empty($set)) 3016 { 3017 self::setRegistry('shortcodes/sc_style', array_merge($_sc_style, $set)); 3018 } 3019 3020 return $_sc_style; 3021 } 3022 3023 /** 3024 * Get Template Info array. 3025 * Note: Available only after getTemplate()/getCoreTemplate() call 3026 * 3027 * @param string $plug_name if null - search for core template 3028 * @param string $id 3029 * @param string $key 3030 * @param boolean $override 3031 * @param boolean $merge 3032 * @return array 3033 */ 3034 public static function getTemplateInfo($plug_name = null, $id, $key = null, $override = true, $merge = false) 3035 { 3036 if($plug_name) 3037 { 3038 $ret = self::getTemplate($plug_name, $id, null, $override, $merge, true); 3039 } 3040 else 3041 { 3042 $ret = self::getCoreTemplate($id, null, $override, $merge, true); 3043 } 3044 if($key && isset($ret[$key]) && is_array($ret[$key])) 3045 { 3046 return $ret[$key]; 3047 } 3048 return $ret; 3049 } 3050 3051 /** 3052 * Return a list of available template IDs for a plugin(eg. $MYTEMPLATE['my_id'] -> array('id' => 'My Id')) 3053 * 3054 * FIXME - the format of $allinfo=true array is not usable at all, convert it so that it's compatible with e_form::selectbox() method 3055 * 3056 * @param string $plugin_name 3057 * @param string $template_id [optional] if different from $plugin_name; 3058 * @param mixed $where true - current theme, 'admin' - admin theme, 'front' (default) - front theme 3059 * @param string $filter_mask 3060 * @param boolean $merge merge theme with core/plugin layouts, default is false 3061 * @param boolean $allinfo reutrn nimerical array of templates and all available template information 3062 * @return array 3063 */ 3064 public static function getLayouts($plugin_name, $template_id = '', $where = 'front', $filter_mask = '', $merge = false, $allinfo = true) 3065 { 3066 if(!$plugin_name) // Core template 3067 { 3068 $tmp = self::getCoreTemplate($template_id, null, $where, $merge); 3069 $tmp_info = self::getTemplateInfo(null, $template_id, null, $where, $merge); 3070 } 3071 else // Plugin template 3072 { 3073 $id = (!$template_id) ? $plugin_name : $template_id; 3074 $tmp = self::getTemplate($plugin_name, $id, null, $where, $merge); 3075 $tmp_info = self::getTemplateInfo($plugin_name, $id, null, $where, $merge); 3076 } 3077 3078 $templates = array(); 3079 if(!$filter_mask) 3080 { 3081 $filter_mask = array(); 3082 } 3083 elseif(!is_array($filter_mask)) 3084 { 3085 $filter_mask = array($filter_mask); 3086 } 3087 foreach($tmp as $key => $val) 3088 { 3089 $match = true; 3090 if($filter_mask) 3091 { 3092 $match = false; 3093 foreach ($filter_mask as $mask) 3094 { 3095 if(preg_match($mask, $key)) //e.g. retrieve only keys starting with 'layout_' 3096 { 3097 $match = true; 3098 break; 3099 } 3100 } 3101 if(!$match) continue; 3102 } 3103 if(isset($tmp_info[$key])) 3104 { 3105 $templates[$key] = defset($tmp_info[$key]['title'], $tmp_info[$key]['title']); 3106 continue; 3107 } 3108 $templates[$key] = implode(' ', array_map('ucfirst', explode('_', $key))); //TODO add LANS? 3109 } 3110 return ($allinfo ? array($templates, $tmp_info) : $templates); 3111 } 3112 3113 /** 3114 * More abstsract template loader, used 3115 * internal in {@link getTemplate()} and {@link getCoreTemplate()} methods 3116 * If $info is set to true, only template informational array will be returned 3117 * 3118 * @param string $id 3119 * @param string|null $key 3120 * @param string $reg_path 3121 * @param string $path 3122 * @param boolean $info 3123 * @param boolean $noWrapper 3124 * @return string|array 3125 */ 3126 public static function _getTemplate($id, $key, $reg_path, $path, $info = false, $noWrapper = false) 3127 { 3128 $regPath = $reg_path; 3129 $var = strtoupper($id).'_TEMPLATE'; 3130 $regPathInfo = $reg_path.'/info'; 3131 $var_info = strtoupper($id).'_INFO'; 3132 3133 $wrapper = strtoupper($id).'_WRAPPER'; // see contact_template.php 3134 $wrapperRegPath = 'templates/wrapper/'.$id; 3135 3136 // Use: list($pre,$post) = explode("{---}",$text,2); 3137 3138 $tp = self::getParser(); // BC FIx - avoid breaking old templates due to missing globals. 3139 3140 if(null === self::getRegistry($regPath)) 3141 { 3142 (deftrue('E107_DEBUG_LEVEL') ? include_once($path) : @include_once($path)); 3143 self::setRegistry($regPath, (isset($$var) ? $$var : array())); 3144 3145 // sc_style not a global anymore and uppercase 3146 3147 // Fix template merge issue - no-wrapper sent to avoid sc wrappers confusions 3148 if(!$noWrapper) 3149 { 3150 if(isset($SC_WRAPPER)) 3151 { 3152 if(E107_DBG_BBSC) 3153 { 3154 self::getMessage()->addDebug("Found wrapper: ".$SC_WRAPPER); 3155 } 3156 self::scStyle($SC_WRAPPER); 3157 } 3158 3159 // ID_WRAPPER support 3160 if(isset($$wrapper) && !empty($$wrapper) && is_array($$wrapper)) 3161 { 3162 if(E107_DBG_BBSC) 3163 { 3164 self::getMessage()->addDebug("Found ID wrapper: ".$wrapper); 3165 } 3166 self::setRegistry($wrapperRegPath, $$wrapper); 3167 } 3168 } 3169 } 3170 if(null === self::getRegistry($regPathInfo)) 3171 { 3172 self::setRegistry($regPathInfo, (isset($$var_info) && is_array($$var_info) ? $$var_info : array())); 3173 } 3174 3175 $ret = (!$info ? self::getRegistry($regPath) : self::getRegistry($regPathInfo)); 3176 3177 if(!$key) 3178 { 3179 return $ret; 3180 } 3181 3182 return ($ret && is_array($ret) && isset($ret[$key]) ? $ret[$key] : false); 3183 } 3184 3185 /** 3186 * Load language file, replacement of include_lan() 3187 * @outdated use e107::lan() or e107::coreLan(), e107::plugLan(), e107::themeLan() 3188 * @param string $path 3189 * @param boolean $force 3190 * @return string 3191 */ 3192 public static function includeLan($path, $force = false) 3193 { 3194 if (!is_readable($path)) 3195 { 3196 if (self::getPref('noLanguageSubs') || (e_LANGUAGE === 'English')) 3197 { 3198 return false; 3199 } 3200 3201 self::getDebug()->log("Couldn't load language file: " . $path); 3202 3203 $path = str_replace(e_LANGUAGE, 'English', $path); 3204 3205 self::getDebug()->log("Attempts to load default language file: " . $path); 3206 3207 if(!is_readable($path)) 3208 { 3209 self::getDebug()->log("Couldn't load default language file: " . $path); 3210 return false; 3211 } 3212 } 3213 3214 $adminLanguage = self::getPref('adminlanguage'); 3215 3216 if(e_ADMIN_AREA && vartrue($adminLanguage)) 3217 { 3218 $path = str_replace(e_LANGUAGE, $adminLanguage, $path); 3219 } 3220 3221 $ret = ($force) ? include($path) : include_once($path); 3222 return (isset($ret)) ? $ret : ""; 3223 } 3224 3225 /** 3226 * Simplify importing of core Language files. 3227 * All inputs are sanitized. 3228 * Core Exceptions as e_LANGUAGE.'.php' and e_LANGUAGE.'_custom.php' are manually loaded. (see class2.php) 3229 * 3230 * Examples: 3231 * <code><?php 3232 * // import defeinitions from /e107_languages/[CurrentLanguage]/lan_comment.php</code> 3233 * e107::coreLan('comment'); 3234 * 3235 * // import defeinitions from /e107_languages/[CurrentLanguage]/admin/lan_banlist.php 3236 * self::coreLan('banlist', true); 3237 * </code> 3238 * 3239 * @param string $fname filename without the extension part (e.g. 'comment') 3240 * @param boolean $admin true if it's an administration language file 3241 * @return bool 3242 */ 3243 public static function coreLan($fname, $admin = false) 3244 { 3245 if ($admin) 3246 { 3247 e107::includeLan(e_LANGUAGEDIR.e_LANGUAGE.'/admin/lan_admin.php'); 3248 } 3249 3250 $cstring = 'corelan/'.e_LANGUAGE.'_'.$fname.($admin ? '_admin' : '_front'); 3251 if(self::getRegistry($cstring)) return; 3252 3253 $fname = ($admin ? 'admin/' : '').'lan_'.preg_replace('/[^\w]/', '', trim($fname, '/')).'.php'; 3254 $path = e_LANGUAGEDIR.e_LANGUAGE.'/'.$fname; 3255 3256 self::setRegistry($cstring, true); 3257 3258 return self::includeLan($path, false); 3259 } 3260 3261 /** 3262 * Simplify importing of plugin Language files (following e107 plugin structure standards). 3263 * All inputs are sanitized. 3264 * 3265 * Examples: 3266 * <code><?php 3267 * // import defeinitions from /e107_plugins/forum/languages/[CurrentLanguage]/lan_forum.php 3268 * e107::plugLan('forum', 'lan_forum'); 3269 * 3270 * // import defeinitions from /e107_plugins/featurebox/languages/[CurrentLanguage]_admin_featurebox.php 3271 * // OR /e107_plugins/featurebox/languages/[CurrentLanguage]/[CurrentLanguage]_admin_featurebox.php (auto-detected) 3272 * e107::plugLan('featurebox', 'admin_featurebox', true); 3273 * 3274 * // import defeinitions from /e107_plugins/myplug/languages/[CurrentLanguage]_front.php 3275 * e107::plugLan('myplug'); 3276 * 3277 * // import defeinitions from /e107_plugins/myplug/languages/[CurrentLanguage]_admin.php 3278 * e107::plugLan('myplug', true); 3279 * 3280 * // import defeinitions from /e107_plugins/myplug/languages/[CurrentLanguage]/admin/common.php 3281 * e107::plugLan('myplug', 'admin/common'); 3282 * </code> 3283 * 3284 * @param string $plugin plugin name 3285 * @param string $fname filename without the extension part (e.g. 'common') 3286 * @param boolean $flat false (default, preferred) Language folder structure; true - prepend Language to file name 3287 * @return bool 3288 */ 3289 public static function plugLan($plugin, $fname = '', $flat = false) 3290 { 3291 $cstring = 'pluglan/'.e_LANGUAGE.'_'.$plugin.'_'.$fname.($flat ? '_1' : '_0'); 3292 if(self::getRegistry($cstring)) return; 3293 3294 $plugin = preg_replace('/[^\w]/', '', $plugin); 3295 3296 if($fname === 'global') // fix ambiguity 3297 { 3298 $fname = e_LANGUAGE."_global"; 3299 } 3300 elseif($fname && is_string($fname)) 3301 { 3302 $fname = e_LANGUAGE.($flat ? '_' : '/').preg_replace('#[^\w/]#', '', trim($fname, '/')); 3303 } 3304 elseif($fname === true) // admin file. 3305 { 3306 //$fname = "admin/".e_LANGUAGE; 3307 $fname = e_LANGUAGE."_admin"; 3308 } 3309 else 3310 { 3311 // $fname = e_LANGUAGE; 3312 $fname = e_LANGUAGE."_front"; 3313 } 3314 3315 if($flat === true) // support for alt_auth/languages/English/English_log.php etc. 3316 { 3317 $path = e_PLUGIN.$plugin.'/languages/'.e_LANGUAGE.'/'.$fname.'.php'; 3318 } 3319 else 3320 { 3321 $path = e_PLUGIN.$plugin.'/languages/'.$fname.'.php'; 3322 } 3323 3324 if(deftrue('E107_DBG_INCLUDES')) 3325 { 3326 $adminLanguage = self::getPref('adminlanguage'); 3327 3328 if(e_ADMIN_AREA && !empty($adminLanguage)) 3329 { 3330 $path = str_replace(e_LANGUAGE, $adminLanguage, $path); 3331 } 3332 3333 self::getMessage()->addDebug("Attempting to Load: ".$path); 3334 } 3335 3336 3337 self::setRegistry($cstring, true); 3338 3339 return self::includeLan($path, false); 3340 } 3341 3342 /** 3343 * Simplify importing of theme Language files (following e107 plugin structure standards). 3344 * All inputs are sanitized. 3345 * 3346 * Examples: 3347 * <code><?php 3348 * // import defeinitions from /e107_themes/[CurrentTheme]/languages/[CurrentLanguage]/lan.php 3349 * e107::themeLan('lan'); 3350 * 3351 * // import defeinitions from /e107_themes/[currentTheme]/languages/[CurrentLanguage].php 3352 * e107::themeLan(); 3353 * 3354 * // import defeinitions from /e107_themes/[currentTheme]/languages/[CurrentLanguage]_lan.php 3355 * e107::themeLan('lan', null, true); 3356 * 3357 * // import defeinitions from /e107_themes/[currentTheme]/languages/[CurrentLanguage]/admin/lan.php 3358 * e107::themeLan('admin/lan'); 3359 * 3360 * // import defeinitions from /e107_themes/some_theme/languages/[CurrentLanguage].php 3361 * e107::themeLan('', 'some_theme'); 3362 * </code> 3363 * 3364 * @param string $fname filename without the extension part (e.g. 'common' for common.php) 3365 * @param string $theme theme name, if null current theme will be used 3366 * @param boolean $flat false (default, preferred) Language folder structure; true - prepend Language to file name 3367 * @return bool 3368 */ 3369 public static function themeLan($fname = '', $theme = null, $flat = false) 3370 { 3371 if(null === $theme) $theme = THEME.'languages/'; 3372 else $theme = e_THEME.preg_replace('#[^\w/]#', '', $theme).'/languages/'; 3373 3374 $cstring = 'themelan/'.$theme.$fname.($flat ? '_1' : '_0'); 3375 if(self::getRegistry($cstring)) return; 3376 3377 if($fname) $fname = e_LANGUAGE.($flat ? '_' : '/').preg_replace('#[^\w/]#', '', trim($fname, '/')); 3378 else $fname = e_LANGUAGE; 3379 3380 $path = $theme.$fname.'.php'; 3381 3382 if(deftrue('E107_DBG_INCLUDES')) 3383 { 3384 self::getMessage()->addDebug("Attempting to Load: ".$path); 3385 } 3386 3387 self::setRegistry($cstring, true); 3388 3389 return self::includeLan($path, false); 3390 } 3391 3392 3393 3394 /** 3395 * PREFERRED Generic Language File Loading Function for use by theme and plugin developers. 3396 * Language-file equivalent to e107::js, e107::meta and e107::css 3397 * 3398 * FIXME disallow themes and plugins named 'core' and 'theme' 3399 * 3400 * @param string $type 3401 * 'theme' or plugin name 3402 * @param string $fname 3403 * (optional): relative path to the theme or plugin language folder. (same as in the other functions) 3404 * when missing, [e_LANGUAGE]_front.php will be used, when true [e_LANGUAGE]_admin.php will be used 3405 * @param $options 3406 * Set to True for admin. 3407 * 3408 * @example e107::lan('theme'); // Loads THEME."languages/English.php (if English is the current language) 3409 * @example e107::lan('gallery'); // Loads e_PLUGIN."gallery/languages/English_front.php (if English is the current language) 3410 * @example e107::lan('gallery', 'admin'); // Loads e_PLUGIN."gallery/languages/English/admin.php (if English is the current language) 3411 * @example e107::lan('gallery', 'admin', true); // Loads e_PLUGIN."gallery/languages/English_admin.php (if English is the current language) 3412 * @example e107::lan('gallery', 'admin/example'); // Loads e_PLUGIN."gallery/languages/English/admin/example.php (if English is the current language) 3413 * @example e107::lan('gallery', true); // Loads e_PLUGIN."gallery/languages/English_admin.php (if English is the current language) 3414 * @example e107::lan('gallery', "something", true); // Loads e_PLUGIN."gallery/languages/English_something.php (if English is the current language) 3415 * @example e107::lan('gallery', true, true); // Loads e_PLUGIN."gallery/languages/English/English_admin.php (if English is the current language) 3416 * @example e107::lan('gallery', false, true); // Loads e_PLUGIN."gallery/languages/English/English_front.php (if English is the current language) 3417 */ 3418 public static function lan($type, $fname = null, $options = null) 3419 { 3420 $options = $options ? true : false; 3421 switch ($type) 3422 { 3423 case 'core' : 3424 self::coreLan($fname, $options); 3425 break; 3426 3427 case 'theme' : 3428 self::themeLan($fname, null, $options); 3429 break; 3430 default : 3431 self::plugLan($type, $fname, $options); 3432 break; 3433 } 3434 3435 } 3436 3437 3438 /** 3439 * Generic PREF retrieval Method for use by theme and plugin developers. 3440 * @param string $type : 'core', 'theme', plugin-name 3441 * @param $pname : name of specific preference, or leave blank for full array. 3442 * @param null $default 3443 * @return mixed 3444 */ 3445 public static function pref($type = 'core', $pname = null, $default = null) 3446 { 3447 3448 switch ($type) 3449 { 3450 case 'core' : 3451 return self::getPref($pname, $default); 3452 break; 3453 3454 case 'theme' : 3455 return self::getThemePref($pname, $default); 3456 break; 3457 3458 default: 3459 return self::getPlugPref($type, $pname, $default); 3460 break; 3461 } 3462 3463 } 3464 3465 3466 /** 3467 * Set or Get the current breadcrumb array. 3468 * @param array $array 3469 * @return array|null 3470 */ 3471 public static function breadcrumb($array = array()) 3472 { 3473 3474 if(empty($array)) // read 3475 { 3476 3477 if(empty(self::$_breadcrumb)) //Guess what it should be.. 3478 { 3479 if(defined('PAGE_NAME')) // BC search for "PAGE_NAME" 3480 { 3481 return array(0=> array('text'=>PAGE_NAME, 'url'=>null)); 3482 } 3483 elseif($caption = e107::getRender()->getMainCaption()) // BC search for primary render caption 3484 { 3485 return array(0=> array('text'=>$caption, 'url'=>null)); 3486 } 3487 3488 } 3489 3490 return self::$_breadcrumb; 3491 } 3492 3493 3494 3495 3496 3497 self::$_breadcrumb = $array; // write. 3498 3499 return null; 3500 } 3501 3502 /** 3503 * Generate a plugin's search engine-friendly URL with HTML special characters escaped 3504 * 3505 * Can be spliced directly into HTML code like <a href="…"></a> 3506 * 3507 * Output is generated based on the plugin's e_url.php configuration 3508 * 3509 * @param string $plugin - plugin folder name 3510 * @param string $key assigned in e_url.php configuration. 3511 * @param array $row Array of variables in url config. 3512 * @param array $options = [ // (optional) An associative array of additional options 3513 * 'mode' => 'abs | full', // @see e_parse::replaceConstants() 3514 * 'query' => [], // An array of query key/value-pairs (without any URL encoding) to append to the URL 3515 * 'fragment' => '', // A fragment identifier (named anchor) to append to the URL. Do not include the leading '#' character 3516 * 'legacy' => false, // When true, legacy URLs will be generated regardless of mod_rewrite status 3517 * ] 3518 * @return string The SEF URL with HTML special characters escaped 3519 * (equivalent to the htmlspecialchars() output) 3520 */ 3521 public static function url($plugin = '', $key = null, $row = array(), $options = array()) 3522 { 3523 3524 /* backward compat - core keys. ie. news/xxx/xxx user/xxx/xxx etc, */ 3525 $legacy = array('news', 'page', 'search', 'user', 'download', 'gallery'); 3526 3527 if (strpos($plugin, '/') !== false) 3528 { 3529 $tmp = explode("/", $plugin, 2); 3530 3531 if (in_array($tmp[0], $legacy)) 3532 { 3533 return self::getUrl()->create($plugin, $key, $row); 3534 } 3535 3536 // shorthand - for internal use. 3537 $plugin = $tmp[0]; 3538 $row = $key; 3539 $key = $tmp[1]; 3540 } 3541 3542 if (!$tmp = self::getRegistry('core/e107/addons/e_url')) 3543 { 3544 $tmp = self::getUrlConfig(); 3545 self::setRegistry('core/e107/addons/e_url', $tmp); 3546 } 3547 3548 $tp = self::getParser(); 3549 3550 $pref = self::getPref('e_url_alias'); 3551 $sefActive = self::getPref('e_url_list'); 3552 $rootNamespace = self::getPref('url_main_module'); 3553 3554 3555 if (is_string($options)) // backwards compat. 3556 { 3557 $options = array( 3558 'mode' => $options, 3559 ); 3560 } 3561 3562 // Merge in defaults. 3563 $options += array( 3564 'mode' => 'abs', 3565 'fragment' => '', 3566 'query' => array(), 3567 ); 3568 3569 if (isset($options['fragment']) && $options['fragment'] !== '') 3570 { 3571 $options['fragment'] = '#' . $options['fragment']; 3572 } 3573 3574 if (!empty($plugin) && empty($tmp[$plugin][$key]['sef'])) 3575 { 3576 self::getMessage()->addDebug("e_url.php in <b>" . e_PLUGIN . $plugin . "</b> is missing the key: <b>" . $key . "</b>. Or, you may need to <a href='" . e_ADMIN . "db.php?mode=plugin_scan'>scan your plugin directories</a> to register e_url.php"); 3577 return false; 3578 } 3579 3580 if (!empty($tmp[$plugin][$key]['alias'])) 3581 { 3582 $alias = (!empty($pref[e_LAN][$plugin][$key])) ? $pref[e_LAN][$plugin][$key] : $tmp[$plugin][$key]['alias']; 3583 3584 if (!empty($rootNamespace) && $rootNamespace === $plugin) 3585 { 3586 $replaceAlias = array('{alias}\/', '{alias}/'); 3587 $tmp[$plugin][$key]['sef'] = str_replace($replaceAlias, '', $tmp[$plugin][$key]['sef']); 3588 } 3589 else 3590 { 3591 $tmp[$plugin][$key]['sef'] = str_replace('{alias}', $alias, $tmp[$plugin][$key]['sef']); 3592 } 3593 3594 } 3595 3596 3597 preg_match_all('#{([a-z_]*)}#', $tmp[$plugin][$key]['sef'], $matches); 3598 3599 $active = true; 3600 3601 foreach ($matches[1] as $k => $v) // check if a field value is missing, if so, revert to legacy url. 3602 { 3603 if (!isset($row[$v])) 3604 { 3605 self::getMessage()->addDebug("Missing value for " . $v . " in " . $plugin . "/e_url.php - '" . $key . "'"); 3606 $active = false; 3607 break; 3608 } 3609 } 3610 3611 if (empty($sefActive[$plugin])) // SEF disabled. 3612 { 3613 self::getDebug()->log('SEF URL for <b>' . $plugin . '</b> disabled.'); 3614 $active = false; 3615 } 3616 3617 $e_MOD_REWRITE = (self::isCli() !==true) ? deftrue('e_MOD_REWRITE') : true; 3618 3619 if ($e_MOD_REWRITE && ($active == true) && empty($options['legacy'])) // Search-Engine-Friendly URLs active. 3620 { 3621 $rawUrl = $tp->simpleParse($tmp[$plugin][$key]['sef'], $row); 3622 3623 if ($options['mode'] === 'full') 3624 { 3625 $sefUrl = SITEURL . $rawUrl; 3626 } 3627 elseif ($options['mode'] === 'raw') 3628 { 3629 $sefUrl = $rawUrl; 3630 } 3631 else 3632 { 3633 $sefUrl = e_HTTP . $rawUrl; 3634 } 3635 } 3636 else // Legacy URL. 3637 { 3638 3639 $srch = array(); 3640 $repl = array(); 3641 3642 foreach ($matches[0] as $k => $val) 3643 { 3644 $srch[] = '$' . ($k + 1); 3645 $repl[] = $val; 3646 } 3647 3648 $template = isset($tmp[$plugin][$key]['legacy']) ? $tmp[$plugin][$key]['legacy'] : $tmp[$plugin][$key]['redirect']; 3649 3650 $urlTemplate = str_replace($srch, $repl, $template); 3651 $urlTemplate = $tp->replaceConstants($urlTemplate, $options['mode']); 3652 $legacyUrl = $tp->simpleParse($urlTemplate, $row); 3653 3654 $legacyUrl = preg_replace('/&?\$[\d]/i', "", $legacyUrl); // remove any left-over $x (including prefix of '&') 3655 3656 3657 // Avoid duplicate query keys. eg. URL has ?id=x and $options['query']['id'] exists. 3658 // @see forum/e_url.php - topic/redirect and forum/view_shortcodes.php sc_post_url() 3659 list($legacyUrl, $tmp) = array_pad(explode("?", $legacyUrl), 2, null); 3660 3661 if (!empty($tmp)) 3662 { 3663 if (strpos($tmp, '=') === false) 3664 { 3665 // required for legacy urls of type "request.php?download.43" 3666 // @see: issue #3275 3667 $legacyUrl .= '?' . $tmp; 3668 $options['query'] = null; 3669 } 3670 else 3671 { 3672 3673 parse_str($tmp, $qry); 3674 3675 foreach ($qry as $k => $v) 3676 { 3677 if (!isset($options['query'][$k])) // $options['query'] overrides any in the original URL. 3678 { 3679 $options['query'][$k] = $v; 3680 } 3681 } 3682 3683 } 3684 } 3685 $sefUrl = $legacyUrl; 3686 } 3687 3688 // Append the query. 3689 if (is_array($options['query']) && !empty($options['query'])) 3690 { 3691 $sefUrl .= (strpos($sefUrl, '?') !== FALSE ? '&' : '?') . self::httpBuildQuery($options['query']); 3692 } 3693 3694 return htmlspecialchars($sefUrl . $options['fragment'], ENT_QUOTES, 'UTF-8'); 3695 } 3696 3697 3698 /** 3699 * Simple redirect method for developers. 3700 * 3701 * @param string $url 3702 * 'admin' to redirect to admin entry page or leave blank to go to home page 3703 * (SITEURL). 3704 * @param int $http_response_code 3705 * The HTTP status code to use for the redirection, defaults to 302. 3706 * The valid values for 3xx redirection status codes are defined in RFC 2616 3707 * and the draft for the new HTTP status codes: 3708 * - 301: Moved Permanently (the recommended value for most redirects). 3709 * - 302: Found (default in PHP, sometimes used for spamming search engines). 3710 * - 303: See Other. 3711 * - 304: Not Modified. 3712 * - 305: Use Proxy. 3713 * - 307: Temporary Redirect. 3714 * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3 3715 * @see https://tools.ietf.org/html/draft-reschke-http-status-308-07 3716 */ 3717 public static function redirect($url = '', $http_response_code = 301) 3718 { 3719 self::getRedirect()->go($url, true, $http_response_code); 3720 } 3721 3722 3723 /** 3724 * Retrieve error page handler. 3725 * 3726 * @return error_page 3727 */ 3728 public static function getError() 3729 { 3730 return self::getSingleton('error_page', true); 3731 } 3732 3733 3734 /** 3735 * Parses an array into a valid, rawurlencoded query string. This differs from http_build_query() as we need to 3736 * rawurlencode() (instead of urlencode()) all query parameters. 3737 * @param array $query The query parameter array to be processed, e.g. $_GET. 3738 * @param string $parent Internal use only. Used to build the $query array key for nested items. 3739 * @return string A rawurlencoded string which can be used as or appended to the URL query string. 3740 */ 3741 public static function httpBuildQuery(array $query, $parent = '') 3742 { 3743 $params = array(); 3744 3745 foreach($query as $key => $value) 3746 { 3747 $key = ($parent ? $parent . '[' . rawurlencode($key) . ']' : rawurlencode($key)); 3748 3749 // Recurse into children. 3750 if(is_array($value)) 3751 { 3752 $params [] = self::httpBuildQuery($value, $key); 3753 } 3754 // If a query parameter value is NULL, only append its key. 3755 elseif(!isset($value)) 3756 { 3757 $params [] = $key; 3758 } 3759 else 3760 { 3761 // For better readability of paths in query strings, we decode slashes. 3762 $params [] = $key . '=' . str_replace('%2F', '/', rawurlencode($value)); 3763 } 3764 } 3765 3766 return implode('&', $params); 3767 } 3768 3769 3770 public static function minify($js,$options=array()) 3771 { 3772 if(empty($js)) 3773 { 3774 return null; 3775 } 3776 3777 // require_once(e_HANDLER."jsshrink/Minifier.php"); 3778 try 3779 { 3780 $minified = JShrink\Minifier::minify($js,$options); 3781 } 3782 catch(Exception $e) 3783 { 3784 $minified = $js; 3785 } 3786 3787 return $minified; 3788 } 3789 3790 3791 3792 /** 3793 * Set or Retrieve WYSIWYG active status. (replaces constant e_WYSIWYG) 3794 * 3795 * @param bool/string $val if null, return current value, otherwise define editor to use 3796 * @param bool $returnEditor true = return name of active editor, false = return "false" for non wysiwyg editor, return "true" if wysiwyg editor should be used 3797 * @return bool|mixed 3798 */ 3799 public static function wysiwyg($val=null, $returnEditor=false) 3800 { 3801 static $editor = 'bbcode'; 3802 static $availEditors; 3803 $fallbackEditor = 'bbcode'; 3804 3805 if (self::getPref('wysiwyg',false) != true) 3806 { 3807 // wysiwyg disabled by global pref 3808 $editor = $fallbackEditor; 3809 } 3810 else 3811 { 3812 if(!isset($availEditors)) 3813 { 3814 // init list of installed wysiwyg editors 3815 $availEditors = array_keys(e107::getPlug()->getInstalledWysiwygEditors()); 3816 } 3817 3818 if(!is_null($val)) 3819 { 3820 // set editor if value given 3821 $editor = empty($val) ? $fallbackEditor : ($val === 'default' ? true : $val); 3822 } 3823 3824 3825 // check if choosen editor is installed, 3826 // if not, but a different editor is available use that one (e.g. tinymce4 choosen, but only simplemde available available, use simplemde) 3827 // if no wysiwyg editor available, use fallback editor (bbcode) 3828 if(is_bool($editor) || ($editor !== $fallbackEditor && !in_array($editor, $availEditors))) 3829 { 3830 $editor = count($availEditors) > 0 ? $availEditors[0] : $fallbackEditor; 3831 } 3832 } 3833 // $returnEditor => false: 3834 // false => fallback editor (bbcode) 3835 // true => default wysiwyg editor 3836 // $returnEditor => true: 3837 // return name of the editor 3838 //return $returnEditor ? $editor : ($editor === $fallbackEditor || $editor === false ? false : true); 3839 return $returnEditor ? $editor : ($editor !== $fallbackEditor); 3840 } 3841 3842 3843 /** 3844 * Routine looks in standard paths for language files associated with a plugin or 3845 * theme - primarily for core routines, which won't know for sure where the author has put them. 3846 * $unitName is the name (directory path) of the plugin or theme 3847 * $type determines what is to be loaded: 3848 * - 'runtime' - the standard runtime language file for a plugin 3849 * - 'admin' - the standard admin language file for a plugin 3850 * - 'theme' - the standard language file for a plugin (these are usually pretty small, so one is enough) 3851 * Otherwise, $type is treated as part of a filename within the plugin's language directory, 3852 * prefixed with the current language. 3853 * Returns FALSE on failure (not found). 3854 * Returns the include_once error return if there is one 3855 * Otherwise returns an empty string. 3856 * Note - if the code knows precisely where the language file is located, use {@link getLan()} 3857 * $pref['noLanguageSubs'] can be set TRUE to prevent searching for the English files if 3858 * the files for the current site language don't exist. 3859 * 3860 * @param string $unitName 3861 * @param string $type predefined types are runtime|admin|theme 3862 * @return boolean|string 3863 */ 3864 public static function loadLanFiles($unitName, $type='runtime') 3865 { 3866 //global $pref; 3867 switch ($type) 3868 { 3869 case 'runtime' : 3870 $searchPath[1] = e_PLUGIN.$unitName.'/languages/'.e_LANGUAGE.'_'.$unitName.'.php'; 3871 $searchPath[2] = e_PLUGIN.$unitName.'/languages/'.e_LANGUAGE.'/'.$unitName.'.php'; 3872 $searchPath[3] = e_PLUGIN.$unitName.'/languages/'.e_LANGUAGE.'.php'; // menu language file. 3873 break; 3874 case 'admin' : 3875 3876 $aLangPref = self::getPref('adminlanguage'); 3877 $adminLan = vartrue($aLangPref, e_LANGUAGE); 3878 3879 $searchPath[1] = e_PLUGIN.$unitName.'/languages/'.$adminLan.'_admin_'.$unitName.'.php'; 3880 $searchPath[2] = e_PLUGIN.$unitName.'/languages/'.$adminLan.'/'.'admin_'.$unitName.'.php'; 3881 $searchPath[3] = e_PLUGIN.$unitName.'/languages/'.$adminLan.'/admin/'.$adminLan.'.php'; 3882 $searchPath[4] = e_PLUGIN.$unitName.'/languages/'.$adminLan.'/'.$adminLan.'_admin.php'; // Preferred. 3883 $searchPath[5] = e_PLUGIN.$unitName.'/languages/'.$adminLan.'_admin.php'; // consistent with English_global.php, English_log.php etc. 3884 3885 break; 3886 case 'theme' : 3887 $searchPath[1] = e_THEME.$unitName.'/languages/'.e_LANGUAGE.'_'.$unitName.'.php'; 3888 $searchPath[2] = e_THEME.$unitName.'/languages/'.e_LANGUAGE.'/'.$unitName.'.php'; 3889 break; 3890 default : 3891 $searchPath[1] = e_PLUGIN.$unitName.'/languages/'.e_LANGUAGE.'_'.$type.'.php'; 3892 $searchPath[2] = e_PLUGIN.$unitName.'/languages/'.e_LANGUAGE.'/'.$type.'.php'; 3893 } 3894 foreach ($searchPath as $s) // Look for files in current language first - should usually be found 3895 { 3896 if (is_readable($s)) 3897 { 3898 $ret = include_once($s); 3899 return (isset($ret)) ? $ret : ""; 3900 } 3901 } 3902 if (self::getPref('noLanguageSubs') || (e_LANGUAGE === 'English')) 3903 { 3904 return FALSE; // No point looking for the English files twice 3905 } 3906 3907 foreach ($searchPath as $s) // Now look for the English files 3908 { 3909 $s = str_replace(e_LANGUAGE, 'English', $s); 3910 if (is_readable($s)) 3911 { 3912 $ret = include_once($s); 3913 return (isset($ret)) ? $ret : ""; 3914 } 3915 } 3916 return FALSE; // Nothing found 3917 } 3918 3919 3920 /** 3921 * Prepare e107 environment 3922 * This is done before e107_dirs initilization and config include 3923 * @param bool $checkS basic security check (0.7 like), will be extended in the future 3924 * @return e107 3925 */ 3926 public function prepare_request($checkS = true) 3927 { 3928 3929 // Block common bad agents / queries / php issues. 3930 array_walk($_SERVER, array('self', 'filter_request'), '_SERVER'); 3931 if (isset($_GET)) array_walk($_GET, array('self', 'filter_request'), '_GET'); 3932 if (isset($_POST)) 3933 { 3934 array_walk($_POST, array('self', 'filter_request'), '_POST'); 3935 reset($_POST); // Change of behaviour in PHP 5.3.17? 3936 } 3937 if (isset($_COOKIE)) array_walk($_COOKIE, array('self', 'filter_request'), '_COOKIE'); 3938 if (isset($_REQUEST)) array_walk($_REQUEST, array('self', 'filter_request'), '_REQUEST'); 3939 3940 // A better way to detect an AJAX request. No need for "ajax_used=1"; 3941 if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') 3942 { 3943 define('e_AJAX_REQUEST', true); 3944 } 3945 else 3946 { 3947 define('e_AJAX_REQUEST', isset($_REQUEST['ajax_used'])); 3948 } 3949 3950 unset($_REQUEST['ajax_used']); // removed because it's auto-appended from JS (AJAX), could break something... 3951 3952 //$GLOBALS['_E107'] - minimal mode - here because of the e_AJAX_REQUEST 3953 if(isset($GLOBALS['_E107']['minimal']) || e_AJAX_REQUEST || deftrue('e_MINIMAL')) 3954 { 3955 $_e107vars = array('forceuserupdate', 'online', 'theme', 'menus', 'prunetmp'); 3956 $GLOBALS['_E107']['minimal'] = true; 3957 // lame but quick - allow online when ajax request only, additonal checks are made in e_online class 3958 if(e_AJAX_REQUEST && !isset($GLOBALS['_E107']['online']) && !isset($GLOBALS['_E107']['minimal'])) unset($_e107vars[1]); 3959 3960 foreach($_e107vars as $v) 3961 { 3962 $noname = 'no_'.$v; 3963 if(!isset($GLOBALS['_E107'][$v])) 3964 { 3965 $GLOBALS['_E107'][$noname] = 1; 3966 } 3967 unset($GLOBALS['_E107'][$v]); 3968 } 3969 } 3970 3971 // we can now start use $e107->_E107 3972 if(isset($GLOBALS['_E107']) && is_array($GLOBALS['_E107'])) $this->_E107 = & $GLOBALS['_E107']; 3973 3974 // remove ajax_used=1 from query string to avoid SELF problems, ajax should always be detected via e_AJAX_REQUEST constant 3975 $_SERVER['QUERY_STRING'] = trim( 3976 str_replace( 3977 array('ajax_used=1', '&&'), 3978 array('', '&'), 3979 (isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '') 3980 ), '&'); 3981 3982 /* PathInfo doesn't break anything, URLs should be always absolute. Disabling the below forever. 3983 // e107 uses relative url's, which are broken by "pretty" URL's. So for now we don't support / after .php 3984 if(($pos = strpos($_SERVER['PHP_SELF'], '.php/')) !== false) // redirect bad URLs to the correct one. 3985 { 3986 $new_url = substr($_SERVER['PHP_SELF'], 0, $pos+4); 3987 $new_loc = ($_SERVER['QUERY_STRING']) ? $new_url.'?'.$_SERVER['QUERY_STRING'] : $new_url; 3988 header('Location: '.$new_loc); 3989 exit(); 3990 } 3991 */ 3992 3993 // If url contains a .php in it, PHP_SELF is set wrong (imho), affecting all paths. We need to 'fix' it if it does. 3994 $_SERVER['PHP_SELF'] = (($pos = stripos($_SERVER['PHP_SELF'], '.php')) !== false ? substr($_SERVER['PHP_SELF'], 0, $pos+4) : $_SERVER['PHP_SELF']); 3995 3996 // setup some php options 3997 self::ini_set('magic_quotes_runtime', 0); 3998 self::ini_set('magic_quotes_sybase', 0); 3999 // self::ini_set('arg_separator.output', '&'); // non-standard and bad for third-party script compatibility. @see https://github.com/e107inc/e107/issues/3116 4000 self::ini_set('session.use_only_cookies', 1); 4001 self::ini_set('session.use_trans_sid', 0); 4002 self::ini_set('session.cookie_httponly', 1); // cookie won't be accessible by scripting languages, such as JavaScript. Can effectively help to reduce identity theft through XSS attacks 4003 4004 // Ensure thet '.' is the first part of the include path 4005 $inc_path = explode(PATH_SEPARATOR, ini_get('include_path')); 4006 if($inc_path[0] != '.') 4007 { 4008 array_unshift($inc_path, '.'); 4009 $inc_path = implode(PATH_SEPARATOR, $inc_path); 4010 self::ini_set('include_path', $inc_path); 4011 } 4012 unset($inc_path); 4013 4014 return $this; 4015 } 4016 4017 /** 4018 * Filter User Input - used by array_walk in prepare_request method above. 4019 * @param string $input array value 4020 * @param string $key array key 4021 * @param string $type array type _SESSION, _GET etc. 4022 * @param bool $base64 4023 * @return bool|null 4024 */ 4025 public static function filter_request($input,$key,$type,$base64=FALSE) 4026 { 4027 if(is_string($input) && trim($input)=="") 4028 { 4029 return ''; 4030 } 4031 4032 if (is_array($input)) 4033 { 4034 return array_walk($input, array('self', 'filter_request'), $type); 4035 } 4036 4037 4038 if($type == "_POST" || ($type == "_SERVER" && ($key == "QUERY_STRING"))) 4039 { 4040 if($type == "_POST" && ($base64 === false)) 4041 { 4042 $input = preg_replace("/(\[code\])(.*?)(\[\/code\])/is","",$input); 4043 } 4044 4045 $regex = "/(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"; 4046 if(preg_match($regex,$input)) 4047 { 4048 self::die_http_400(); 4049 } 4050 4051 // Check for XSS JS 4052 $regex = "/(document\.location|document\.write|document\.cookie)/i"; 4053 if(preg_match($regex,$input)) 4054 { 4055 self::die_http_400(); 4056 } 4057 4058 4059 // Suspicious HTML. 4060 if(strpos($input, '<body/onload')!==false) 4061 { 4062 self::die_http_400(); 4063 } 4064 4065 if(preg_match("/system\((.*);.*\)/i",$input)) 4066 { 4067 self::die_http_400(); 4068 } 4069 4070 $regex = "/(wget |curl -o |lwp-download|onmouse)/i"; 4071 if(preg_match($regex,$input)) 4072 { 4073 self::die_http_400(); 4074 } 4075 4076 } 4077 4078 if($type === '_GET') // Basic XSS check. 4079 { 4080 if(stripos($input, "<script")!==false || stripos($input, "%3Cscript")!==false) 4081 { 4082 self::die_http_400(); 4083 } 4084 4085 } 4086 4087 if($type == "_SERVER") 4088 { 4089 4090 if(($key == "QUERY_STRING") && ( 4091 strpos(strtolower($input),"../../")!==FALSE 4092 || stripos($input,"php:")!==FALSE 4093 || stripos($input,"data:")!==FALSE 4094 || stripos($input,"%3cscript")!==FALSE 4095 )) 4096 { 4097 self::die_http_400(); 4098 } 4099 4100 if(($key == "HTTP_USER_AGENT") && strpos($input,"libwww-perl")!==FALSE) 4101 { 4102 self::die_http_400(); 4103 } 4104 4105 4106 } 4107 4108 if(strpos(str_replace('.', '', $input), '22250738585072011') !== FALSE) // php-bug 53632 4109 { 4110 self::die_http_400(); 4111 } 4112 4113 if($base64 != true) 4114 { 4115 self::filter_request(base64_decode($input, true),$key,$type,true); 4116 } 4117 4118 4119 4120 } 4121 4122 4123 4124 /** 4125 * Set base system path 4126 * @return e107 4127 */ 4128 public function set_base_path($force = null) 4129 { 4130 $ssl_enabled = (null !== $force) ? $force : $this->isSecure();//(self::getPref('ssl_enabled') == 1); 4131 $this->base_path = $ssl_enabled ? $this->https_path : $this->http_path; 4132 return $this; 4133 } 4134 4135 /** 4136 * Set various system environment constants 4137 * @return e107 4138 */ 4139 public function set_constants() 4140 { 4141 if(!defined('MAGIC_QUOTES_GPC')) 4142 { 4143 define('MAGIC_QUOTES_GPC', (ini_get('magic_quotes_gpc') ? true : false)); 4144 } 4145 4146 define('MPREFIX', self::getMySQLConfig('prefix')); // mysql prefix 4147 4148 define('CHARSET', 'utf-8'); // set CHARSET for backward compatibility 4149 4150 if(!defined('e_MOD_REWRITE')) // Allow e107_config.php to override. 4151 { 4152 define('e_MOD_REWRITE', (getenv('HTTP_MOD_REWRITE')=='On'|| getenv('REDIRECT_HTTP_MOD_REWRITE')=='On' ? true : false)); 4153 } 4154 4155 if(!defined('e_MOD_REWRITE_MEDIA')) // Allow e107_config.php to override. 4156 { 4157 define('e_MOD_REWRITE_MEDIA', (getenv('HTTP_MOD_REWRITE_MEDIA')=='On' || getenv('REDIRECT_HTTP_MOD_REWRITE_MEDIA')=='On' ? true : false)); 4158 } 4159 4160 if(!defined('e_MOD_REWRITE_STATIC')) // Allow e107_config.php to override. 4161 { 4162 define('e_MOD_REWRITE_STATIC', (getenv('HTTP_MOD_REWRITE_STATIC')=='On' || getenv('REDIRECT_HTTP_MOD_REWRITE_STATIC')=='On' ? true : false)); 4163 } 4164 4165 $subdomain = false; 4166 4167 // Define the domain name and subdomain name. 4168 if (is_numeric(str_replace(".", "", 4169 (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '') 4170 ))) 4171 { 4172 $domain = false; 4173 $subdomain = false; 4174 } 4175 else 4176 { 4177 $_SERVER['SERVER_NAME'] = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : ''; 4178 $host = !empty($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME']; 4179 $domain = preg_replace('/^www\.|:\d*$/', '', $host); // remove www. and port numbers. 4180 4181 $dtemp = explode(".", $domain); 4182 4183 if(count($dtemp) > 2 && strlen($dtemp[0]) === 2) // eg. fr.mysite.com or fr.mysite.com.fr 4184 { 4185 $subdomain = $dtemp[0]; 4186 unset($dtemp[0]); 4187 $domain = implode('.',$dtemp); // remove subdomain because it's a language-code. 4188 } 4189 4190 } 4191 4192 if($domain === 'localhost') // Fix for chrome. 4193 { 4194 $domain = false; 4195 } 4196 4197 define("e_DOMAIN", $domain); 4198 define("e_SUBDOMAIN", ($subdomain) ? $subdomain : false); 4199 4200 define('e_UC_PUBLIC', 0); 4201 define('e_UC_MAINADMIN', 250); 4202 define('e_UC_READONLY', 251); 4203 define('e_UC_GUEST', 252); 4204 define('e_UC_MEMBER', 253); 4205 define('e_UC_ADMIN', 254); 4206 define('e_UC_NOBODY', 255); 4207 4208 4209 return $this; 4210 } 4211 4212 /** 4213 * Relaitve server path - set_path() helper 4214 * @param string $dir 4215 * @return string 4216 */ 4217 public function get_override_rel($dir) 4218 { 4219 if(isset($this->e107_dirs[$dir.'_SERVER'])) 4220 { 4221 return $this->e107_dirs[$dir.'_SERVER']; 4222 } 4223 $ret = e_BASE.$this->e107_dirs[$dir.'_DIRECTORY']; 4224 4225 4226 return $ret; 4227 } 4228 4229 /** 4230 * Absolute HTTP path - set_path() helper 4231 * @param string $dir 4232 * @return string 4233 */ 4234 public function get_override_http($dir) 4235 { 4236 if(isset($this->e107_dirs[$dir.'_HTTP'])) 4237 { 4238 return $this->e107_dirs[$dir.'_HTTP']; 4239 } 4240 4241 return e_HTTP.$this->e107_dirs[$dir.'_DIRECTORY']; 4242 } 4243 4244 /** 4245 * Set all environment vars and constants 4246 * FIXME - remove globals 4247 * @return e107 4248 */ 4249 public function set_paths() 4250 { 4251 // ssl_enabled pref not needed anymore, scheme is auto-detected 4252 $this->HTTP_SCHEME = 'http'; 4253 if ( 4254 (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || 4255 (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) 4256 ) 4257 { 4258 $this->HTTP_SCHEME = 'https'; 4259 } 4260 4261 $path = ""; $i = 0; 4262 4263 // FIXME - Again, what if someone moves handlers under the webroot? 4264 if(!self::isCli()) 4265 { 4266 while (!file_exists("{$path}class2.php")) 4267 { 4268 $path .= "../"; 4269 $i++; 4270 } 4271 } 4272 4273 if ($_SERVER['PHP_SELF'] == "" && !empty($_SERVER['SCRIPT_NAME'])) 4274 { 4275 $_SERVER['PHP_SELF'] = $_SERVER['SCRIPT_NAME']; 4276 } 4277 4278 $http_path = dirname($_SERVER['PHP_SELF']); 4279 $http_path = explode("/", $http_path); 4280 $http_path = array_reverse($http_path); 4281 $j = 0; 4282 while ($j < $i) 4283 { 4284 unset($http_path[$j]); 4285 $j++; 4286 } 4287 $http_path = array_reverse($http_path); 4288 4289 4290 4291 $this->server_path = implode("/", $http_path)."/"; 4292 $this->server_path = $this->fix_windows_paths($this->server_path); 4293 4294//var_dump($this->server_path); 4295//exit; 4296 4297 if ($this->server_path == "//") 4298 { 4299 $this->server_path = "/"; 4300 } 4301 4302 // Absolute file-path of directory containing class2.php 4303 // define("e_ROOT", realpath(dirname(__FILE__)."/../")."/"); 4304 4305 4306 4307 4308 $this->relative_base_path = (!self::isCli()) ? $path : e_ROOT; 4309 $_SERVER['HTTP_HOST'] = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost'; 4310 $this->http_path = filter_var("http://{$_SERVER['HTTP_HOST']}{$this->server_path}", FILTER_SANITIZE_URL); 4311 $this->https_path = filter_var("https://{$_SERVER['HTTP_HOST']}{$this->server_path}", FILTER_SANITIZE_URL); 4312 4313 $this->file_path = $path; 4314 4315 if(defined('e_HTTP') && defined('e_ADMIN')) return $this; 4316 4317 if(!defined('e_HTTP')) 4318 { 4319 define('e_HTTP', $this->server_path); // Directory of site root relative to HTML base directory 4320 } 4321 4322 define('e_BASE', $this->relative_base_path); 4323 4324 // Base dir of web stuff in server terms. e_ROOT should always end with e_HTTP, even if e_HTTP = '/' 4325 define('SERVERBASE', substr(e_ROOT, 0, -strlen(e_HTTP) + 1)); 4326 4327 if(isset($_SERVER['DOCUMENT_ROOT'])) 4328 { 4329 define('e_DOCROOT', $_SERVER['DOCUMENT_ROOT']."/"); 4330 } 4331 else 4332 { 4333 define('e_DOCROOT', false); 4334 } 4335 4336 //BC temporary fixes 4337 if (!isset($this->e107_dirs['UPLOADS_SERVER']) && $this->e107_dirs['UPLOADS_DIRECTORY'][0] == "/") 4338 { 4339 $this->e107_dirs['UPLOADS_SERVER'] = $this->e107_dirs['UPLOADS_DIRECTORY']; 4340 } 4341 if (!isset($this->e107_dirs['DOWNLOADS_SERVER']) && $this->e107_dirs['DOWNLOADS_DIRECTORY'][0] == "/") 4342 { 4343 $this->e107_dirs['DOWNLOADS_SERVER'] = $this->e107_dirs['DOWNLOADS_DIRECTORY']; 4344 } 4345 4346 // 4347 // HTTP relative paths 4348 // 4349 define('e_ADMIN', $this->get_override_rel('ADMIN')); 4350 define('e_IMAGE', $this->get_override_rel('IMAGES')); 4351 define('e_THEME', $this->get_override_rel('THEMES')); 4352 define('e_PLUGIN', $this->get_override_rel('PLUGINS')); 4353 define('e_FILE', $this->get_override_rel('FILES')); 4354 define('e_HANDLER', $this->get_override_rel('HANDLERS')); 4355 define('e_LANGUAGEDIR', $this->get_override_rel('LANGUAGES')); 4356 4357 define('e_DOCS', $this->get_override_rel('HELP')); // WILL CHANGE SOON - $this->_get_override_rel('DOCS') 4358 define('e_HELP', $this->get_override_rel('HELP')); 4359 4360 define('e_MEDIA', $this->get_override_rel('MEDIA')); 4361 define('e_MEDIA_BASE', $this->get_override_rel('MEDIA_BASE')); 4362 define('e_MEDIA_FILE', $this->get_override_rel('MEDIA_FILES')); 4363 define('e_MEDIA_VIDEO', $this->get_override_rel('MEDIA_VIDEOS')); 4364 define('e_MEDIA_IMAGE', $this->get_override_rel('MEDIA_IMAGES')); 4365 define('e_MEDIA_ICON', $this->get_override_rel('MEDIA_ICONS')); 4366 // define('e_MEDIA_AVATAR', $this->get_override_rel('MEDIA_AVATARS')); 4367 4368 define('e_DOWNLOAD', $this->get_override_rel('DOWNLOADS')); 4369 define('e_UPLOAD', $this->get_override_rel('UPLOADS')); 4370 4371 define('e_CORE', $this->get_override_rel('CORE')); 4372 define('e_SYSTEM', $this->get_override_rel('SYSTEM')); 4373 define('e_SYSTEM_BASE', $this->get_override_rel('SYSTEM_BASE')); 4374 4375 define('e_WEB', $this->get_override_rel('WEB')); 4376 define('e_WEB_JS', $this->get_override_rel('WEB_JS')); 4377 define('e_WEB_CSS', $this->get_override_rel('WEB_CSS')); 4378 define('e_WEB_IMAGE', $this->get_override_rel('WEB_IMAGES')); 4379// define('e_WEB_PACK', $this->get_override_rel('WEB_PACKS')); 4380 4381 define('e_CACHE', $this->get_override_rel('CACHE')); 4382 define('e_CACHE_CONTENT', $this->get_override_rel('CACHE_CONTENT')); 4383 define('e_CACHE_IMAGE', $this->get_override_rel('CACHE_IMAGE')); 4384 define('e_CACHE_DB', $this->get_override_rel('CACHE_DB')); 4385 define('e_CACHE_URL', $this->get_override_rel('CACHE_URL')); 4386 4387 define('e_LOG', $this->get_override_rel('LOGS')); 4388 define('e_BACKUP', $this->get_override_rel('BACKUP')); 4389 define('e_TEMP', $this->get_override_rel('TEMP')); 4390 define('e_IMPORT', $this->get_override_rel('IMPORT')); 4391 // 4392 // HTTP absolute paths 4393 // 4394 define("e_ADMIN_ABS", $this->get_override_http('ADMIN')); 4395 define("e_IMAGE_ABS", $this->get_override_http('IMAGES')); 4396 define("e_THEME_ABS", $this->get_override_http('THEMES')); 4397 define("e_PLUGIN_ABS", $this->get_override_http('PLUGINS')); 4398 define("e_FILE_ABS", $this->get_override_http('FILES')); // Deprecated! 4399 define("e_DOCS_ABS", $this->get_override_http('DOCS')); 4400 define("e_HELP_ABS", $this->get_override_http('HELP')); 4401 define("e_IMPORT_ABS", false); 4402 4403 // DEPRECATED - not a legal http query now! 4404 //define("e_HANDLER_ABS", $this->get_override_http('HANDLERS')); 4405 //define("e_LANGUAGEDIR_ABS", $this->get_override_http('LANGUAGES')); 4406 //define("e_LOG_ABS", $this->get_override_http('LOGS')); 4407 4408 define("e_MEDIA_ABS", $this->get_override_http('MEDIA')); 4409 define('e_MEDIA_FILE_ABS', $this->get_override_http('MEDIA_FILES')); 4410 define('e_MEDIA_VIDEO_ABS', $this->get_override_http('MEDIA_VIDEOS')); 4411 define('e_MEDIA_IMAGE_ABS', $this->get_override_http('MEDIA_IMAGES')); 4412 define('e_MEDIA_ICON_ABS', $this->get_override_http('MEDIA_ICONS')); 4413// define('e_MEDIA_AVATAR_ABS', $this->get_override_http('MEDIA_AVATARS')); 4414 4415 // XXX DISCUSSS - e_JS_ABS, e_CSS_ABS etc is not following the naming standards but they're more usable. 4416 // Example: e_JS_ABS vs e_WEB_JS_ABS 4417 4418 //XXX Absolute is assumed. 4419 define('e_WEB_ABS', $this->get_override_http('WEB')); 4420 define('e_JS_ABS', $this->get_override_http('WEB_JS')); 4421 define('e_CSS_ABS', $this->get_override_http('WEB_CSS')); 4422// define('e_PACK_ABS', $this->get_override_http('WEB_PACKS')); 4423 define('e_WEB_IMAGE_ABS', $this->get_override_http('WEB_IMAGES')); 4424 4425 define('e_JS', $this->get_override_http('WEB_JS')); // ABS Alias 4426 define('e_CSS', $this->get_override_http('WEB_CSS')); // ABS Alias 4427 4428 define('e_AVATAR', $this->get_override_rel('AVATARS')); 4429 define('e_AVATAR_UPLOAD', $this->get_override_rel('AVATARS_UPLOAD')); 4430 define('e_AVATAR_DEFAULT', $this->get_override_rel('AVATARS_DEFAULT')); 4431 4432 define('e_AVATAR_ABS', $this->get_override_http('AVATARS')); 4433 define('e_AVATAR_UPLOAD_ABS', $this->get_override_http('AVATARS_UPLOAD')); 4434 define('e_AVATAR_DEFAULT_ABS', $this->get_override_http('AVATARS_DEFAULT')); 4435 4436 if(defined('e_MEDIA_STATIC')) // experimental - subject to change. 4437 { 4438 define('e_CACHE_IMAGE_ABS', $this->get_override_http('CACHE_IMAGE')); 4439 } 4440 4441 // Special 4442 4443 define('e_BOOTSTRAP', e_WEB."bootstrap/"); 4444 4445 return $this; 4446 } 4447 4448 /** 4449 * Fix Windows server path 4450 * 4451 * @param string $path resolved server path 4452 * @return string fixed path 4453 */ 4454 function fix_windows_paths($path) 4455 { 4456 $fixed_path = str_replace(array('\\\\', '\\'), array('/', '/'), $path); 4457 $fixed_path = (substr($fixed_path, 1, 2) == ":/" ? substr($fixed_path, 2) : $fixed_path); 4458 return $fixed_path; 4459 } 4460 4461 /** 4462 * Define e_PAGE, e_SELF, e_ADMIN_AREA and USER_AREA; 4463 * The following files are assumed to use admin theme: 4464 * 1. Any file in the admin directory (check for non-plugin added to avoid mismatches) 4465 * 2. any plugin file starting with 'admin_' 4466 * 3. any plugin file in a folder called admin/ 4467 * 4. any file that specifies $eplug_admin = TRUE; or ADMIN_AREA = TRUE; 4468 * NOTE: USER_AREA = true; will force e_ADMIN_AREA to FALSE 4469 * 4470 * @param boolean $no_cbrace remove curly brackets from the url 4471 * @return e107 4472 */ 4473 public function set_urls($no_cbrace = true) 4474 { 4475 //global $PLUGINS_DIRECTORY,$ADMIN_DIRECTORY, $eplug_admin; 4476 $PLUGINS_DIRECTORY = $this->getFolder('plugins'); 4477 $ADMIN_DIRECTORY = $this->getFolder('admin'); 4478 4479 // Outdated 4480 /*$requestQry = ''; 4481 $requestUrl = $_SERVER['REQUEST_URI']; 4482 if(strpos($_SERVER['REQUEST_URI'], '?') !== FALSE) 4483 list($requestUrl, $requestQry) = explode("?", $_SERVER['REQUEST_URI'], 2); */ 4484 4485 $eplug_admin = vartrue($GLOBALS['eplug_admin'], false); 4486 4487 // Leave e_SELF BC, use e_REQUEST_SELF instead 4488 /*// moved after page check - e_PAGE is important for BC 4489 if($requestUrl && $requestUrl != $_SERVER['PHP_SELF']) 4490 { 4491 $_SERVER['PHP_SELF'] = $requestUrl; 4492 }*/ 4493 4494 if(self::isCli() && !empty($_SERVER['_']) && empty($_SERVER['SCRIPT_FILENAME'])) 4495 { 4496 $_SERVER['SCRIPT_FILENAME'] = $_SERVER['_']; 4497 } 4498 4499 $eSelf = !empty($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_FILENAME']; 4500 $_self = $this->HTTP_SCHEME.'://'.$_SERVER['HTTP_HOST'].$eSelf; 4501 4502 4503 4504 // START New - request uri/url detection, XSS protection 4505 // TODO - move it to a separate method 4506 $requestUri = $requestUrl = ''; 4507 if (isset($_SERVER['HTTP_X_REWRITE_URL'])) 4508 { 4509 // check this first so IIS will catch 4510 $requestUri = $_SERVER['HTTP_X_REWRITE_URL']; 4511 $requestUrl = $this->HTTP_SCHEME.'://'.$_SERVER['HTTP_HOST'].$requestUri; 4512 // fix request uri 4513 $_SERVER['REQUEST_URI'] = $requestUri; 4514 } 4515 elseif (isset($_SERVER['REQUEST_URI'])) 4516 { 4517 $requestUri = $_SERVER['REQUEST_URI']; 4518 $requestUrl = $this->HTTP_SCHEME.'://'.$_SERVER['HTTP_HOST'].$requestUri; 4519 } 4520 else 4521 { 4522 // go back to e_SELF 4523 $requestUri = $eSelf; 4524 $requestUrl = $_self; 4525 if(defset('e_QUERY')) 4526 { 4527 $requestUri .= '?'.e_QUERY; // TODO e_SINGLE_ENTRY check, separate static method for cleaning QUERY_STRING 4528 $requestUrl .= '?'.e_QUERY; 4529 } 4530 } 4531 // FIXME - basic security - add url sanitize method to e_parse 4532 $check = rawurldecode($requestUri); // urlencoded by default 4533 4534 // a bit aggressive XSS protection... convert to e.g. htmlentities if you are not a bad guy 4535 $checkregx = $no_cbrace ? '[<>\{\}]' : '[<>]'; 4536 if(preg_match('/'.$checkregx.'/', $check)) 4537 { 4538 // header('HTTP/1.1 403 Forbidden'); 4539 $requestUri = filter_var($requestUri, FILTER_SANITIZE_URL); 4540 // exit; 4541 } 4542 4543 // e_MENU fix 4544 if(e_MENU) 4545 { 4546 $requestUri = str_replace('['.e_MENU.']', '', $requestUri); 4547 $requestUrl = str_replace('['.e_MENU.']', '', $requestUrl); 4548 if(defset('e_QUERY')) parse_str(e_QUERY,$_GET); 4549 } 4550 4551 define('e_REQUEST_URL', str_replace(array("'", '"'), array('%27', '%22'), $requestUrl)); // full request url string (including domain) 4552 4553 $tmp = explode('?', e_REQUEST_URL); 4554 $requestSelf = array_shift($tmp); 4555 4556 if(substr($requestSelf,-4) !== '.php' && substr($requestSelf,-1) !== '/') 4557 { 4558 $requestSelf .= '/'; // Always include a trailing slash on SEF Urls so that e_REQUEST_SELF."?".e_QUERY doesn't break. 4559 } 4560 4561 // the last anti-XSS measure, XHTML compliant URL to be used in forms instead e_SELF 4562 4563 define('e_REQUEST_SELF', filter_var($requestSelf, FILTER_SANITIZE_URL)); // full URL without the QUERY string 4564 define('e_REQUEST_URI', str_replace(array("'", '"'), array('%27', '%22'), $requestUri)); // absolute http path + query string 4565 $tmp2 = explode('?', e_REQUEST_URI); 4566 define('e_REQUEST_HTTP', array_shift($tmp2)); // SELF URL without the QUERY string and leading domain part 4567 4568 if(!deftrue('e_SINGLE_ENTRY') && !deftrue('e_SELF_OVERRIDE') ) 4569 { 4570 $page = substr(strrchr($_SERVER['PHP_SELF'], '/'), 1); 4571 4572 if(self::isCli() && !empty($_SERVER['_'])) 4573 { 4574 $page = basename($_SERVER['_']); 4575 } 4576 4577 4578 define('e_PAGE', $page); 4579 define('e_SELF', filter_var($_self, FILTER_SANITIZE_URL)); 4580 } 4581 else 4582 { 4583 define('e_SELF', e_REQUEST_SELF); 4584 4585 if(deftrue('e_SELF_OVERRIDE')) // see multisite plugin. 4586 { 4587 define('e_PAGE', basename($_SERVER['SCRIPT_FILENAME'])); 4588 } 4589 } 4590 4591 4592 4593 unset($requestUrl, $requestUri); 4594 // END request uri/url detection, XSS protection 4595 4596 // e_SELF has the full HTML path 4597 $inAdminDir = FALSE; 4598 $isPluginDir = strpos($_self,'/'.$PLUGINS_DIRECTORY) !== FALSE; // True if we're in a plugin 4599 $e107Path = str_replace($this->base_path, '', $_self); // Knock off the initial bits 4600 $curPage = !empty($_SERVER['SCRIPT_FILENAME']) ? basename($_SERVER['SCRIPT_FILENAME']) : ''; 4601 $_SERVER['REQUEST_URI'] = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''; 4602 4603 if ( 4604 (!$isPluginDir && strpos($e107Path, $ADMIN_DIRECTORY) === 0 ) // Core admin directory 4605 || ($isPluginDir && (strpos($curPage,'_admin.php') !== false || strpos($curPage,'admin_') === 0 || strpos($e107Path, 'admin/') !== FALSE)) // Plugin admin file or directory 4606 || (vartrue($eplug_admin) || deftrue('ADMIN_AREA')) // Admin forced 4607 || (preg_match('/^\/(.*?)\/user(settings\.php|\/edit)(\?|\/)(\d+)$/i', $_SERVER['REQUEST_URI']) && ADMIN) 4608 || ($isPluginDir && $curPage === 'prefs.php') //BC Fix for old plugins 4609 || ($isPluginDir && $curPage === 'config.php') // BC Fix for old plugins 4610 || ($isPluginDir && strpos($curPage,'_config.php')!==false) // BC Fix for old plugins eg. dtree_menu 4611 ) 4612 { 4613 $inAdminDir = TRUE; 4614 } 4615 if ($isPluginDir) 4616 { 4617 $temp = substr($e107Path, strpos($e107Path, '/') +1); 4618 $plugDir = substr($temp, 0, strpos($temp, '/')); 4619 define('e_CURRENT_PLUGIN', rtrim($plugDir,'/')); 4620 define('e_PLUGIN_DIR', e_PLUGIN.e_CURRENT_PLUGIN.'/'); 4621 define('e_PLUGIN_DIR_ABS', e_PLUGIN_ABS.e_CURRENT_PLUGIN.'/'); 4622 } 4623 else 4624 { 4625 // define('e_CURRENT_PLUGIN', ''); // leave it undefined so it can be added later during sef-url detection. 4626 define('e_PLUGIN_DIR', ''); 4627 define('e_PLUGIN_DIR_ABS', ''); 4628 } 4629 4630 4631 if(!defined('e_ADMIN_AREA')) 4632 { 4633 define('e_ADMIN_AREA', ($inAdminDir && !deftrue('USER_AREA'))); 4634 } 4635 4636 define('ADMINDIR', $ADMIN_DIRECTORY); 4637 4638 return $this; 4639 } 4640 4641 /** 4642 * The second part of e107::set_urls() 4643 * Supposed to load after database has been initialized 4644 * 4645 * Implemented out of necessity due to 4646 * https://github.com/e107inc/e107/issues/3033 4647 * 4648 * @return e107 4649 */ 4650 public function set_urls_deferred() 4651 { 4652 if(self::isCli()) 4653 { 4654 define('SITEURL', self::getPref('siteurl')); 4655 define('SITEURLBASE', rtrim(SITEURL,'/')); 4656 } 4657 else 4658 { 4659 define('SITEURLBASE', $this->HTTP_SCHEME.'://'. filter_var($_SERVER['HTTP_HOST'], FILTER_SANITIZE_URL)); 4660 define('SITEURL', SITEURLBASE.e_HTTP); 4661 } 4662 4663 4664 // login/signup 4665 define('e_SIGNUP', SITEURL.(file_exists(e_BASE.'customsignup.php') ? 'customsignup.php' : 'signup.php')); 4666 4667 if(!defined('e_LOGIN')) 4668 { 4669 define('e_LOGIN', SITEURL.(file_exists(e_BASE.'customlogin.php') ? 'customlogin.php' : 'login.php')); 4670 } 4671 4672 return $this; 4673 } 4674 4675 /** 4676 * Set request related constants 4677 * @param boolean $no_cbrace remove curly brackets from the url 4678 * @return e107 4679 */ 4680 public function set_request($no_cbrace = true) 4681 { 4682 4683 $inArray = array("'", '/**/', '/UNION/', '/SELECT/', 'AS '); 4684 if (strpos($_SERVER['PHP_SELF'], 'trackback') === false) 4685 { 4686 foreach($inArray as $res) 4687 { 4688 if(stristr($_SERVER['QUERY_STRING'], $res)) 4689 { 4690 die('Access denied.'); 4691 } 4692 } 4693 } 4694 4695 $eMENUQry = str_replace(array('%5B','%5D'),array('[',']'),$_SERVER['QUERY_STRING']); //FIX for urlencoded QUERY_STRING without breaking the '+' used by debug. 4696 if (strpos($eMENUQry, ']') && preg_match('#\[(.*?)](.*)#', $eMENUQry, $matches)) 4697 { 4698 define('e_MENU', $matches[1]); 4699 $e_QUERY = $matches[2]; 4700 } 4701 else 4702 { 4703 define('e_MENU', ''); 4704 $e_QUERY = $_SERVER['QUERY_STRING']; 4705 } 4706 4707 if ($no_cbrace) $e_QUERY = str_replace(array('{', '}', '%7B', '%7b', '%7D', '%7d'), '', rawurldecode($e_QUERY)); 4708 4709 // $e_QUERY = htmlentities(self::getParser()->post_toForm($e_QUERY)); //@see https://github.com/e107inc/e107/issues/719 4710 $e_QUERY = htmlspecialchars(self::getParser()->post_toForm($e_QUERY)); 4711 4712 // 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 4713 if(!deftrue("e_SINGLE_ENTRY")) 4714 { 4715 define('e_QUERY', filter_var($e_QUERY, FILTER_SANITIZE_URL)); 4716 $_SERVER['QUERY_STRING'] = e_QUERY; 4717 } 4718 else 4719 { 4720 // define('e_QUERY', ''); // breaks news sef-urls and possibly others. Moved to index.php. 4721 } 4722 4723 4724 define('e_TBQS', $_SERVER['QUERY_STRING']); 4725 } 4726 4727 /** 4728 * Basic implementation of Browser cache control per user session. Awaiting improvement in future versions 4729 * If no argument is passed it returns 4730 * boolean (if current page is cacheable). 4731 * If string is passed, it's asumed to be aboslute request path (e_REQUEST_URI alike) 4732 * If true is passed, e_REQUEST_URI is registered 4733 * @param null $set 4734 * @return bool|null 4735 */ 4736 public static function canCache($set = null) 4737 { 4738 $_data = self::getSession()->get('__sessionBrowserCache'); 4739 if(!is_array($_data)) $_data = array(); 4740 4741 if(null === $set) 4742 { 4743 return in_array(e_REQUEST_URI, $_data); 4744 } 4745 4746 // remove e_REQUEST_URI from the set 4747 if(false === $set) 4748 { 4749 $check = array_search(e_REQUEST_URI, $_data); 4750 if(false !== $check) 4751 { 4752 unset($_data[$check]); 4753 self::getSession()->set('__sessionBrowserCache', $_data); 4754 return; 4755 } 4756 } 4757 4758 if(true === $set) 4759 { 4760 $set = e_REQUEST_URI; 4761 } 4762 4763 if(empty($set) || !is_string($set) || in_array($set, $_data)) return; 4764 4765 $_data[] = $set; 4766 self::getSession()->set('__sessionBrowserCache', array_unique($_data)); 4767 } 4768 4769 /** 4770 * Check if current request is secure (https) 4771 * @return boolean TRUE if https, FALSE if http 4772 */ 4773 public function isSecure() 4774 { 4775 return ($this->HTTP_SCHEME === 'https'); 4776 } 4777 4778 /** 4779 * Check if current user is banned 4780 * 4781 * Generates the queries to interrogate the ban list, then calls $this->check_ban(). 4782 * If the user is banned, $check_ban() never returns - so a return from this routine indicates a non-banned user. 4783 * FIXME - moved to ban helper, replace all calls 4784 * @return void 4785 */ 4786 /* No longer required - moved to eIPHelper class 4787 public function ban() 4788 { 4789 } */ 4790 4791 /** 4792 * Check the banlist table. $query is used to determine the match. 4793 * If $do_return, will always return with ban status - TRUE for OK, FALSE for banned. 4794 * If return permitted, will never display a message for a banned user; otherwise will display any message then exit 4795 * FIXME - moved to ban helper, replace all calls 4796 * 4797 * 4798 * @param string $query 4799 * @param boolean $show_error 4800 * @param boolean $do_return 4801 * @return boolean 4802 */ 4803 /* No longer required - moved to eIPHelper class 4804 public function check_ban($query, $show_error = TRUE, $do_return = FALSE) 4805 { 4806 } */ 4807 4808 4809 /** 4810 * Add an entry to the banlist. $bantype = 1 for manual, 2 for flooding, 4 for multiple logins 4811 * Returns TRUE if ban accepted. 4812 * Returns FALSE if ban not accepted (i.e. because on whitelist, or invalid IP specified) 4813 * FIXME - moved to IP handler, replace all calls 4814 * @param string $bantype 4815 * @param string $ban_message 4816 * @param string $ban_ip 4817 * @param integer $ban_user 4818 * @param string $ban_notes 4819 * 4820 * @return boolean check result 4821 */ 4822 /* 4823 public function add_ban($bantype, $ban_message = '', $ban_ip = '', $ban_user = 0, $ban_notes = '') 4824 { 4825 return e107::getIPHandler()->add_ban($bantype, $ban_message, $ban_ip, $ban_user, $ban_notes); 4826 } */ 4827 4828 /** 4829 * Get the current user's IP address 4830 * returns the address in internal 'normalised' IPV6 format - so most code should continue to work provided the DB Field is big enougn 4831 * FIXME - call ipHandler directly (done for core - left temporarily for BC) 4832 * @return string 4833 */ 4834 public function getip() 4835 { 4836 return self::getIPHandler()->getIP(FALSE); 4837 } 4838 4839 /** 4840 * Encode an IP address to internal representation. Returns string if successful; FALSE on error 4841 * Default separates fields with ':'; set $div='' to produce a 32-char packed hex string 4842 * FIXME - moved to ipHandler - check for calls elsewhere 4843 * @param string $ip 4844 * @param string $div divider 4845 * @return string encoded IP 4846 */ 4847 4848 public function ipEncode($ip, $div = ':') 4849 { 4850 return self::getIPHandler()->ipEncode($ip); 4851 } 4852 4853 /** 4854 * Takes an encoded IP address - returns a displayable one 4855 * Set $IP4Legacy TRUE to display 'old' (IPv4) addresses in the familiar dotted format, 4856 * FALSE to display in standard IPV6 format 4857 * Should handle most things that can be thrown at it. 4858 * FIXME - moved to ipHandler - check for calls elsewhere - core done; left temporarily for BC 4859 * @param string $ip encoded IP 4860 * @param boolean $IP4Legacy 4861 * @return string decoded IP 4862 */ 4863 public function ipdecode($ip, $IP4Legacy = TRUE) 4864 { 4865 return self::getIPHandler()->ipDecode($ip, $IP4Legacy); 4866 } 4867 4868 /** 4869 * Given a string which may be IP address, email address etc, tries to work out what it is 4870 * Movet to eIPHandler class 4871 * FIXME - moved to ipHandler - check for calls elsewhere 4872 * @param string $string 4873 * @return string ip|email|url|ftp|unknown 4874 */ 4875 /* 4876 public function whatIsThis($string) 4877 { 4878 //return e107::getIPHandler()->whatIsThis($string); 4879 } */ 4880 4881 /** 4882 * Retrieve & cache host name 4883 * @deprecated but needed by some old plugins/menus. 4884 * @todo Find old calls and replace with code within. 4885 * @param string $ip_address 4886 * @return string host name 4887 */ 4888 public function get_host_name($ip_address) 4889 { 4890 return self::getIPHandler()->get_host_name($ip_address); 4891 } 4892 4893 /** 4894 * MOVED TO eHelper::parseMemorySize() 4895 * FIXME - find all calls, replace with eHelper::parseMemorySize() (once eHelper lives in a separate file) 4896 * 4897 * @param integer $size 4898 * @param integer $dp 4899 * @return string formatted size 4900 */ 4901 public function parseMemorySize($size, $dp = 2) 4902 { 4903 return eHelper::parseMemorySize($size, $dp); 4904 } 4905 4906 4907 /** 4908 * Removed, see eHelper::getMemoryUsage() 4909 * Get the current memory usage of the code 4910 * If $separator argument is null, raw data (array) will be returned 4911 * 4912 * @param null|string $separator 4913 * @return string|array memory usage 4914 */ 4915 /* 4916 public function get_memory_usage($separator = '/') 4917 { 4918 return eHelper::getMemoryUsage($separator); 4919 }*/ 4920 4921 4922 /** 4923 * Check if plugin is installed 4924 * @param string $plugname 4925 * @return boolean 4926 */ 4927 public static function isInstalled($plugname) 4928 { 4929 // Could add more checks here later if appropriate 4930 return self::getConfig()->isData('plug_installed/'.$plugname); 4931 } 4932 4933 /** 4934 * Safe way to set ini var 4935 * @param string $var 4936 * @param string $value 4937 * @return mixed 4938 */ 4939 public static function ini_set($var, $value) 4940 { 4941 if (function_exists('ini_set')) 4942 { 4943 return ini_set($var, $value); 4944 } 4945 return false; 4946 } 4947 4948 /** 4949 * Register autoload function (string) or static class method - array('ClassName', 'MethodName') 4950 * @param string|array $function 4951 * @param bool $prepend 4952 * @return bool 4953 */ 4954 public static function autoload_register($function, $prepend = false) 4955 { 4956 ### NEW Register Autoload - do it asap 4957 if(!function_exists('spl_autoload_register')) 4958 { 4959 // PHP >= 5.1.2 required 4960 die_fatal_error('Fatal exception - spl_autoload_* required.'); 4961 } 4962 4963 if(!$prepend || false === ($registered = spl_autoload_functions())) 4964 { 4965 return spl_autoload_register($function); 4966 } 4967 4968 foreach ($registered as $r) 4969 { 4970 spl_autoload_unregister($r); 4971 } 4972 4973 $result = spl_autoload_register($function); 4974 foreach ($registered as $r) 4975 { 4976 if(!spl_autoload_register($r)) $result = false; 4977 } 4978 return $result; 4979 } 4980 4981 /** 4982 * Former __autoload, generic core autoload logic 4983 * 4984 * Magic class autoload. 4985 * We are raising plugin structure standard here - plugin auto-loading works ONLY if 4986 * classes live inside 'includes' folder. 4987 * Example: plugin_myplug_admin_ui -> 4988 * <code> 4989 * <?php 4990 * // __autoload() will look in e_PLUGIN.'myplug/includes/admin/ui.php for this class 4991 * // e_admin_ui is core handler, so it'll be autoloaded as well 4992 * class plugin_myplug_admin_ui extends e_admin_ui 4993 * { 4994 * 4995 * } 4996 * 4997 * // __autoload() will look in e_PLUGIN.'myplug/shortcodes/my_shortcodes.php for this class 4998 * // e_admin_ui is core handler, so it'll be autoloaded as well 4999 * class plugin_myplug_my_shortcodes extends e_admin_ui 5000 * { 5001 * 5002 * } 5003 * </code> 5004 * We use now spl_autoload[_*] for core autoloading (PHP5 > 5.1.2) 5005 * TODO - at this time we could create e107 version of spl_autoload_register - e_event->register/trigger('autoload') 5006 * 5007 * @todo plugname/e_shortcode.php auto-detection (hard, near impossible at this time) - we need 'plugin_' prefix to 5008 * distinguish them from the core batches 5009 * 5010 * @param string $className 5011 * @return void 5012 */ 5013 public static function autoload($className) 5014 { 5015 //Security... 5016 if (strpos($className, '/') !== false) 5017 { 5018 return; 5019 } 5020 5021 // Detect namespaced class 5022 if (strpos($className, '\\') !== false) 5023 { 5024 self::autoload_namespaced($className); 5025 return; 5026 } 5027 5028 $tmp = explode('_', $className); 5029 5030 //echo 'autoloding...'.$className.'<br />'; 5031 switch($tmp[0]) 5032 { 5033 case 'plugin': // plugin handlers/shortcode batches 5034 array_shift($tmp); // remove 'plugin' 5035 $end = array_pop($tmp); // check for 'shortcodes' end phrase 5036 5037 if (!isset($tmp[0]) || !$tmp[0]) 5038 { 5039 if($end) 5040 { 5041 // plugin root - e.g. plugin_myplug -> plugins/myplug/myplug.php, class plugin_myplug 5042 $filename = e_PLUGIN.$end.'/'.$end.'.php'; 5043 break; 5044 } 5045 return; // In case we get an empty class part 5046 } 5047 5048 // Currently only batches inside shortcodes/ folder are auto-detected, 5049 // read the todo for e_shortcode.php related problems 5050 if('shortcodes' == $end) 5051 { 5052 $filename = e_PLUGIN.$tmp[0].'/shortcodes/batch/'; // plugname/shortcodes/batch/ 5053 unset($tmp[0]); 5054 $filename .= implode('_', $tmp).'_shortcodes.php'; // my_shortcodes.php 5055 break; 5056 } 5057 if($end) 5058 { 5059 $tmp[] = $end; // not a shortcode batch - append the end phrase again 5060 } 5061 5062 // Handler check 5063 $tmp[0] .= '/includes'; //folder 'includes' is not part of the class name 5064 $filename = e_PLUGIN.implode('/', $tmp).'.php'; 5065 //TODO add debug screen Auto-loaded classes - ['plugin: '.$filename.' - '.$className]; 5066 break; 5067 5068 default: //core libraries, core shortcode batches 5069 // core SC batch check 5070 $end = array_pop($tmp); 5071 if('shortcodes' == $end) 5072 { 5073 $filename = e_CORE.'shortcodes/batch/'.$className.'.php'; // core shortcode batch 5074 break; 5075 } 5076 5077 $filename = self::getHandlerPath($className, true); 5078 //TODO add debug screen Auto-loaded classes - ['core: '.$filename.' - '.$className]; 5079 break; 5080 } 5081 5082 if(!empty($filename) && is_file($filename)) // Test with chatbox_menu 5083 { 5084 // autoload doesn't REQUIRE files, because this will break things like call_user_func() 5085 include($filename); 5086 } 5087 } 5088 5089 /** 5090 * Autoloading logic for namespaced classes 5091 * 5092 * @param $className 5093 * @return void 5094 */ 5095 private static function autoload_namespaced($className) 5096 { 5097 $levels = explode('\\', $className); 5098 5099 // Guard against classes that are not ours 5100 if ($levels[0] != 'e107') return; 5101 5102 $levels[0] = e_HANDLER; 5103 $classPath = implode('/', $levels).'.php'; 5104 if (is_file($classPath) && is_readable($classPath)) 5105 { 5106 include($classPath); 5107 } 5108 } 5109 5110 public function __get($name) 5111 { 5112 switch ($name) 5113 { 5114 case 'tp': 5115 $ret = self::getParser(); 5116 break; 5117 5118 case 'sql': 5119 $ret = self::getDb(); 5120 break; 5121 5122 case 'ecache': 5123 $ret = self::getCache(); 5124 break; 5125 5126 case 'arrayStorage': 5127 $ret = self::getArrayStorage(); 5128 break; 5129 5130 case 'e_event': 5131 $ret = self::getEvent(); 5132 break; 5133 5134 case 'ns': 5135 $ret = self::getRender(); 5136 break; 5137 5138 case 'url': 5139 $ret = self::getUrl(); 5140 break; 5141 5142 case 'admin_log': 5143 $ret = self::getAdminLog(); 5144 break; 5145 5146 case 'override': 5147 $ret = self::getSingleton('override', e_HANDLER.'override_class.php'); 5148 break; 5149 5150 case 'notify': 5151 $ret = self::getNotify(); 5152 break; 5153 5154 case 'e_online': 5155 $ret = self::getOnline(); 5156 break; 5157 5158 case 'eIPHandler': 5159 $ret = self::getIPHandler(); 5160 break; 5161 5162 case 'user_class': 5163 $ret = self::getUserClass(); 5164 break; 5165 5166 default: 5167 trigger_error('$e107->$'.$name.' not defined', E_USER_WARNING); 5168 return null; 5169 break; 5170 } 5171 5172 $this->$name = $ret; 5173 return $ret; 5174 } 5175 5176 5177 /** 5178 * 5179 */ 5180 public function destruct() //FIXME $path is not defined anywhere. 5181 { 5182 if(null === self::$_instance) return; 5183 5184 $print = defined('E107_DBG_TIMEDETAILS') && E107_DBG_TIMEDETAILS; 5185 5186 !$print || print('<table class="table table-striped table-condensed"><tr><td colspan="3"><b>Destructing $e107</b></td></tr>'); 5187 $vars = get_object_vars($this); 5188 foreach ($vars as $name => $value) 5189 { 5190 if(is_object($value)) 5191 { 5192 if(method_exists($value, '__destruct')) 5193 { 5194 !$print || print('<tr><td>object [property] using __destruct()</td><td>'.$name.'</td><td>'.get_class($value).'</td></tr>'); 5195 $value->__destruct(); 5196 } 5197 else !$print || print('<tr><td>object [property]</td><td>'.$name.'</td><td>'.get_class($value).'</td></tr>'); 5198 $this->$name = null; 5199 } 5200 } 5201 foreach (self::$_registry as $path => $reg) 5202 { 5203 if(is_object($reg)) 5204 { 5205 if(method_exists($reg, '__destruct')) 5206 { 5207 !$print || print('<tr><td>object [registry] using __destruct()</td><td>'.$path.'</td><td>'.get_class($reg).'</td></tr>'); 5208 $reg->__destruct(); 5209 } 5210 else !$print || print('<tr><td>object [registry]</td><td>'.$path.'</td><td>'.get_class($reg).'</td></tr>'); 5211 unset(self::$_registry[$path]); 5212 } 5213 5214 5215 } 5216 5217 if($print) 5218 { 5219 echo "</table>"; 5220 } 5221 5222 self::$_registry = null; 5223 self::$_instance = null; 5224 } 5225 5226 5227 /** 5228 * Check if there's a core e107 release available 5229 * @return array|bool - return array of data or false if no update available. 5230 */ 5231 public static function coreUpdateAvailable() 5232 { 5233 5234 // Get site version 5235 $e107info= array(); 5236 5237 if(is_readable(e_ADMIN."ver.php")) 5238 { 5239 include(e_ADMIN."ver.php"); // $e107info['e107_version']; 5240 } 5241 else 5242 { 5243 return false; 5244 } 5245 5246 $xml = self::getXml(); 5247 $file = "https://e107.org/releases.php"; 5248 if(!$xdata = $xml->loadXMLfile($file,true,false)) 5249 { 5250 return false; 5251 } 5252 5253 $curVersion = str_replace(' (git)', '', $e107info['e107_version']); 5254 5255 if(empty($xdata['core'][0]['@attributes']['version'])) 5256 { 5257 return false; 5258 } 5259 else 5260 { 5261 $newVersion = $xdata['core'][0]['@attributes']['version']; 5262 } 5263 5264 5265 self::getDebug()->log("New Version:".$newVersion); 5266 5267 if(version_compare($curVersion,$newVersion) === -1) 5268 { 5269 $data = array( 5270 'name' => $xdata['core'][0]['@attributes']['name'], 5271 'url' => $xdata['core'][0]['@attributes']['url'], 5272 'date' => $xdata['core'][0]['@attributes']['date'], 5273 'version' => $xdata['core'][0]['@attributes']['version'], 5274 'infourl' => $xdata['core'][0]['@attributes']['infourl'], 5275 'description' => $xdata['core'][0]['description'], 5276 ); 5277 5278 return $data; 5279 } 5280 5281 return false; 5282 5283 } 5284 5285 5286 5287} 5288 5289e107::autoload_register(array(e107::class, 'autoload')); 5290 5291// Forward compatibility with e107 v3 Composer autoloading 5292$vendor_autoload_file = __DIR__."/vendor/autoload.php"; 5293if (file_exists($vendor_autoload_file)) 5294{ 5295 include_once($vendor_autoload_file); 5296} 5297 5298/** 5299 * Interface e_admin_addon_interface @move to separate addons file? 5300 */ 5301interface e_admin_addon_interface 5302{ 5303 5304 /** 5305 * Return a list of values for the currently viewed list page. 5306 * @param string $event 5307 * @param string $ids comma separated primary ids to return in the array. 5308 * @return array with primary id as keys and array of fields key/pair values. 5309 */ 5310 public function load($event, $ids); 5311 5312 5313 /** 5314 * Extend Admin-ui Parameters 5315 * @param $ui admin-ui object 5316 * @return array 5317 */ 5318 public function config(e_admin_ui $ui); 5319 5320 5321 /** 5322 * Process Posted Data. 5323 * @param $ui admin-ui object 5324 * @param int $id 5325 */ 5326 public function process(e_admin_ui $ui, $id=0); 5327 5328 5329 5330} 5331