/libraries/legacy/application/application.php
PHP | 1154 lines | 536 code | 142 blank | 476 comment | 68 complexity | 2c3cd123d82844084c66708690b9fc7b MD5 | raw file
Possible License(s): LGPL-2.1
1<?php 2/** 3 * @package Joomla.Legacy 4 * @subpackage Application 5 * 6 * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved. 7 * @license GNU General Public License version 2 or later; see LICENSE 8 */ 9 10defined('JPATH_PLATFORM') or die; 11 12jimport('joomla.environment.response'); 13 14/** 15 * Base class for a Joomla! application. 16 * 17 * Acts as a Factory class for application specific objects and provides many 18 * supporting API functions. Derived clases should supply the route(), dispatch() 19 * and render() functions. 20 * 21 * @package Joomla.Legacy 22 * @subpackage Application 23 * @since 11.1 24 */ 25class JApplication extends JApplicationBase 26{ 27 /** 28 * The client identifier. 29 * 30 * @var integer 31 * @since 11.1 32 */ 33 protected $_clientId = null; 34 35 /** 36 * The application message queue. 37 * 38 * @var array 39 * @since 11.1 40 */ 41 protected $_messageQueue = array(); 42 43 /** 44 * The name of the application. 45 * 46 * @var array 47 * @since 11.1 48 */ 49 protected $_name = null; 50 51 /** 52 * The scope of the application. 53 * 54 * @var string 55 * @since 11.1 56 */ 57 public $scope = null; 58 59 /** 60 * The time the request was made. 61 * 62 * @var date 63 * @since 11.1 64 */ 65 public $requestTime = null; 66 67 /** 68 * The time the request was made as Unix timestamp. 69 * 70 * @var integer 71 * @since 11.1 72 */ 73 public $startTime = null; 74 75 /** 76 * @var JApplicationWebClient The application client object. 77 * @since 12.2 78 */ 79 public $client; 80 81 /** 82 * @var array JApplication instances container. 83 * @since 11.3 84 */ 85 protected static $instances = array(); 86 87 /** 88 * Class constructor. 89 * 90 * @param array $config A configuration array including optional elements such as session 91 * session_name, clientId and others. This is not exhaustive. 92 * 93 * @since 11.1 94 */ 95 public function __construct($config = array()) 96 { 97 // Set the view name. 98 $this->_name = $this->getName(); 99 100 // Only set the clientId if available. 101 if (isset($config['clientId'])) 102 { 103 $this->_clientId = $config['clientId']; 104 } 105 106 // Enable sessions by default. 107 if (!isset($config['session'])) 108 { 109 $config['session'] = true; 110 } 111 112 // Create the input object 113 $this->input = new JInput; 114 115 $this->client = new JApplicationWebClient; 116 117 $this->loadDispatcher(); 118 119 // Set the session default name. 120 if (!isset($config['session_name'])) 121 { 122 $config['session_name'] = $this->_name; 123 } 124 125 // Set the default configuration file. 126 if (!isset($config['config_file'])) 127 { 128 $config['config_file'] = 'configuration.php'; 129 } 130 131 // Create the configuration object. 132 if (file_exists(JPATH_CONFIGURATION . '/' . $config['config_file'])) 133 { 134 $this->_createConfiguration(JPATH_CONFIGURATION . '/' . $config['config_file']); 135 } 136 137 // Create the session if a session name is passed. 138 if ($config['session'] !== false) 139 { 140 $this->_createSession(self::getHash($config['session_name'])); 141 } 142 143 $this->requestTime = gmdate('Y-m-d H:i'); 144 145 // Used by task system to ensure that the system doesn't go over time. 146 $this->startTime = JProfiler::getmicrotime(); 147 } 148 149 /** 150 * Returns the global JApplication object, only creating it if it 151 * doesn't already exist. 152 * 153 * @param mixed $client A client identifier or name. 154 * @param array $config An optional associative array of configuration settings. 155 * @param string $prefix A prefix for class names 156 * 157 * @return JApplication A JApplication object. 158 * 159 * @since 11.1 160 */ 161 public static function getInstance($client, $config = array(), $prefix = 'J') 162 { 163 if (empty(self::$instances[$client])) 164 { 165 // Load the router object. 166 $info = JApplicationHelper::getClientInfo($client, true); 167 168 $path = $info->path . '/includes/application.php'; 169 if (file_exists($path)) 170 { 171 include_once $path; 172 173 // Create a JApplication object. 174 $classname = $prefix . ucfirst($client); 175 $instance = new $classname($config); 176 } 177 else 178 { 179 $error = JError::raiseError(500, JText::sprintf('JLIB_APPLICATION_ERROR_APPLICATION_LOAD', $client)); 180 return $error; 181 } 182 183 self::$instances[$client] = $instance; 184 } 185 186 return self::$instances[$client]; 187 } 188 189 /** 190 * Initialise the application. 191 * 192 * @param array $options An optional associative array of configuration settings. 193 * 194 * @return void 195 * 196 * @since 11.1 197 */ 198 public function initialise($options = array()) 199 { 200 // Set the language in the class. 201 $config = JFactory::getConfig(); 202 203 // Check that we were given a language in the array (since by default may be blank). 204 if (isset($options['language'])) 205 { 206 $config->set('language', $options['language']); 207 } 208 209 // Set user specific editor. 210 $user = JFactory::getUser(); 211 $editor = $user->getParam('editor', $this->getCfg('editor')); 212 if (!JPluginHelper::isEnabled('editors', $editor)) 213 { 214 $editor = $this->getCfg('editor'); 215 if (!JPluginHelper::isEnabled('editors', $editor)) 216 { 217 $editor = 'none'; 218 } 219 } 220 221 $config->set('editor', $editor); 222 223 // Trigger the onAfterInitialise event. 224 JPluginHelper::importPlugin('system'); 225 $this->triggerEvent('onAfterInitialise'); 226 } 227 228 /** 229 * Route the application. 230 * 231 * Routing is the process of examining the request environment to determine which 232 * component should receive the request. The component optional parameters 233 * are then set in the request object to be processed when the application is being 234 * dispatched. 235 * 236 * @return void 237 * 238 * @since 11.1 239 */ 240 public function route() 241 { 242 // Get the full request URI. 243 $uri = clone JURI::getInstance(); 244 245 $router = $this->getRouter(); 246 $result = $router->parse($uri); 247 248 foreach ($result as $key => $value) 249 { 250 $this->input->def($key, $value); 251 } 252 253 // Trigger the onAfterRoute event. 254 JPluginHelper::importPlugin('system'); 255 $this->triggerEvent('onAfterRoute'); 256 } 257 258 /** 259 * Dispatch the application. 260 * 261 * Dispatching is the process of pulling the option from the request object and 262 * mapping them to a component. If the component does not exist, it handles 263 * determining a default component to dispatch. 264 * 265 * @param string $component The component to dispatch. 266 * 267 * @return void 268 * 269 * @since 11.1 270 */ 271 public function dispatch($component = null) 272 { 273 $document = JFactory::getDocument(); 274 275 $contents = JComponentHelper::renderComponent($component); 276 $document->setBuffer($contents, 'component'); 277 278 // Trigger the onAfterDispatch event. 279 JPluginHelper::importPlugin('system'); 280 $this->triggerEvent('onAfterDispatch'); 281 } 282 283 /** 284 * Render the application. 285 * 286 * Rendering is the process of pushing the document buffers into the template 287 * placeholders, retrieving data from the document and pushing it into 288 * the JResponse buffer. 289 * 290 * @return void 291 * 292 * @since 11.1 293 */ 294 public function render() 295 { 296 $params = array('template' => $this->getTemplate(), 'file' => 'index.php', 'directory' => JPATH_THEMES, 'params' => $template->params); 297 298 // Parse the document. 299 $document = JFactory::getDocument(); 300 $document->parse($params); 301 302 // Trigger the onBeforeRender event. 303 JPluginHelper::importPlugin('system'); 304 $this->triggerEvent('onBeforeRender'); 305 306 // Render the document. 307 $caching = ($this->getCfg('caching') >= 2) ? true : false; 308 JResponse::setBody($document->render($caching, $params)); 309 310 // Trigger the onAfterRender event. 311 $this->triggerEvent('onAfterRender'); 312 } 313 314 /** 315 * Redirect to another URL. 316 * 317 * Optionally enqueues a message in the system message queue (which will be displayed 318 * the next time a page is loaded) using the enqueueMessage method. If the headers have 319 * not been sent the redirect will be accomplished using a "301 Moved Permanently" 320 * code in the header pointing to the new location. If the headers have already been 321 * sent this will be accomplished using a JavaScript statement. 322 * 323 * @param string $url The URL to redirect to. Can only be http/https URL 324 * @param string $msg An optional message to display on redirect. 325 * @param string $msgType An optional message type. Defaults to message. 326 * @param boolean $moved True if the page is 301 Permanently Moved, otherwise 303 See Other is assumed. 327 * 328 * @return void Calls exit(). 329 * 330 * @since 11.1 331 * 332 * @see JApplication::enqueueMessage() 333 */ 334 public function redirect($url, $msg = '', $msgType = 'message', $moved = false) 335 { 336 // Check for relative internal links. 337 if (preg_match('#^index2?\.php#', $url)) 338 { 339 $url = JURI::base() . $url; 340 } 341 342 // Strip out any line breaks. 343 $url = preg_split("/[\r\n]/", $url); 344 $url = $url[0]; 345 346 /* 347 * If we don't start with a http we need to fix this before we proceed. 348 * We could validly start with something else (e.g. ftp), though this would 349 * be unlikely and isn't supported by this API. 350 */ 351 if (!preg_match('#^http#i', $url)) 352 { 353 $uri = JURI::getInstance(); 354 $prefix = $uri->toString(array('scheme', 'user', 'pass', 'host', 'port')); 355 356 if ($url[0] == '/') 357 { 358 // We just need the prefix since we have a path relative to the root. 359 $url = $prefix . $url; 360 } 361 else 362 { 363 // It's relative to where we are now, so lets add that. 364 $parts = explode('/', $uri->toString(array('path'))); 365 array_pop($parts); 366 $path = implode('/', $parts) . '/'; 367 $url = $prefix . $path . $url; 368 } 369 } 370 371 // If the message exists, enqueue it. 372 if (trim($msg)) 373 { 374 $this->enqueueMessage($msg, $msgType); 375 } 376 377 // Persist messages if they exist. 378 if (count($this->_messageQueue)) 379 { 380 $session = JFactory::getSession(); 381 $session->set('application.queue', $this->_messageQueue); 382 } 383 384 // If the headers have been sent, then we cannot send an additional location header 385 // so we will output a javascript redirect statement. 386 if (headers_sent()) 387 { 388 echo "<script>document.location.href='" . htmlspecialchars($url) . "';</script>\n"; 389 } 390 else 391 { 392 $document = JFactory::getDocument(); 393 394 jimport('phputf8.utils.ascii'); 395 if (($this->client->engine == JApplicationWebClient::TRIDENT) && !utf8_is_ascii($url)) 396 { 397 // MSIE type browser and/or server cause issues when url contains utf8 character,so use a javascript redirect method 398 echo '<html><head><meta http-equiv="content-type" content="text/html; charset=' . $document->getCharset() . '" />' 399 . '<script>document.location.href=\'' . htmlspecialchars($url) . '\';</script></head></html>'; 400 } 401 else 402 { 403 // All other browsers, use the more efficient HTTP header method 404 header($moved ? 'HTTP/1.1 301 Moved Permanently' : 'HTTP/1.1 303 See other'); 405 header('Location: ' . $url); 406 header('Content-Type: text/html; charset=' . $document->getCharset()); 407 } 408 } 409 $this->close(); 410 } 411 412 /** 413 * Enqueue a system message. 414 * 415 * @param string $msg The message to enqueue. 416 * @param string $type The message type. Default is message. 417 * 418 * @return void 419 * 420 * @since 11.1 421 */ 422 public function enqueueMessage($msg, $type = 'message') 423 { 424 // For empty queue, if messages exists in the session, enqueue them first. 425 if (!count($this->_messageQueue)) 426 { 427 $session = JFactory::getSession(); 428 $sessionQueue = $session->get('application.queue'); 429 430 if (count($sessionQueue)) 431 { 432 $this->_messageQueue = $sessionQueue; 433 $session->set('application.queue', null); 434 } 435 } 436 437 // Enqueue the message. 438 $this->_messageQueue[] = array('message' => $msg, 'type' => strtolower($type)); 439 } 440 441 /** 442 * Get the system message queue. 443 * 444 * @return array The system message queue. 445 * 446 * @since 11.1 447 */ 448 public function getMessageQueue() 449 { 450 // For empty queue, if messages exists in the session, enqueue them. 451 if (!count($this->_messageQueue)) 452 { 453 $session = JFactory::getSession(); 454 $sessionQueue = $session->get('application.queue'); 455 456 if (count($sessionQueue)) 457 { 458 $this->_messageQueue = $sessionQueue; 459 $session->set('application.queue', null); 460 } 461 } 462 463 return $this->_messageQueue; 464 } 465 466 /** 467 * Gets a configuration value. 468 * 469 * An example is in application/japplication-getcfg.php Getting a configuration 470 * 471 * @param string $varname The name of the value to get. 472 * @param string $default Default value to return 473 * 474 * @return mixed The user state. 475 * 476 * @since 11.1 477 */ 478 public function getCfg($varname, $default = null) 479 { 480 $config = JFactory::getConfig(); 481 return $config->get('' . $varname, $default); 482 } 483 484 /** 485 * Method to get the application name. 486 * 487 * The dispatcher name is by default parsed using the classname, or it can be set 488 * by passing a $config['name'] in the class constructor. 489 * 490 * @return string The name of the dispatcher. 491 * 492 * @since 11.1 493 */ 494 public function getName() 495 { 496 $name = $this->_name; 497 498 if (empty($name)) 499 { 500 $r = null; 501 if (!preg_match('/J(.*)/i', get_class($this), $r)) 502 { 503 JLog::add(JText::_('JLIB_APPLICATION_ERROR_APPLICATION_GET_NAME'), JLog::WARNING, 'jerror'); 504 } 505 $name = strtolower($r[1]); 506 } 507 508 return $name; 509 } 510 511 /** 512 * Gets a user state. 513 * 514 * @param string $key The path of the state. 515 * @param mixed $default Optional default value, returned if the internal value is null. 516 * 517 * @return mixed The user state or null. 518 * 519 * @since 11.1 520 */ 521 public function getUserState($key, $default = null) 522 { 523 $session = JFactory::getSession(); 524 $registry = $session->get('registry'); 525 526 if (!is_null($registry)) 527 { 528 return $registry->get($key, $default); 529 } 530 531 return $default; 532 } 533 534 /** 535 * Sets the value of a user state variable. 536 * 537 * @param string $key The path of the state. 538 * @param string $value The value of the variable. 539 * 540 * @return mixed The previous state, if one existed. 541 * 542 * @since 11.1 543 */ 544 public function setUserState($key, $value) 545 { 546 $session = JFactory::getSession(); 547 $registry = $session->get('registry'); 548 549 if (!is_null($registry)) 550 { 551 return $registry->set($key, $value); 552 } 553 554 return null; 555 } 556 557 /** 558 * Gets the value of a user state variable. 559 * 560 * @param string $key The key of the user state variable. 561 * @param string $request The name of the variable passed in a request. 562 * @param string $default The default value for the variable if not found. Optional. 563 * @param string $type Filter for the variable, for valid values see {@link JFilterInput::clean()}. Optional. 564 * 565 * @return The request user state. 566 * 567 * @since 11.1 568 */ 569 public function getUserStateFromRequest($key, $request, $default = null, $type = 'none') 570 { 571 $cur_state = $this->getUserState($key, $default); 572 $new_state = $this->input->get($request, null, $type); 573 574 // Save the new value only if it was set in this request. 575 if ($new_state !== null) 576 { 577 $this->setUserState($key, $new_state); 578 } 579 else 580 { 581 $new_state = $cur_state; 582 } 583 584 return $new_state; 585 } 586 587 /** 588 * Login authentication function. 589 * 590 * Username and encoded password are passed the onUserLogin event which 591 * is responsible for the user validation. A successful validation updates 592 * the current session record with the user's details. 593 * 594 * Username and encoded password are sent as credentials (along with other 595 * possibilities) to each observer (authentication plugin) for user 596 * validation. Successful validation will update the current session with 597 * the user details. 598 * 599 * @param array $credentials Array('username' => string, 'password' => string) 600 * @param array $options Array('remember' => boolean) 601 * 602 * @return boolean True on success. 603 * 604 * @since 11.1 605 */ 606 public function login($credentials, $options = array()) 607 { 608 // Get the global JAuthentication object. 609 jimport('joomla.user.authentication'); 610 611 $authenticate = JAuthentication::getInstance(); 612 $response = $authenticate->authenticate($credentials, $options); 613 614 if ($response->status === JAuthentication::STATUS_SUCCESS) 615 { 616 // Validate that the user should be able to login (different to being authenticated). 617 // This permits authentication plugins blocking the user 618 $authorisations = $authenticate->authorise($response, $options); 619 foreach ($authorisations as $authorisation) 620 { 621 $denied_states = array(JAuthentication::STATUS_EXPIRED, JAuthentication::STATUS_DENIED); 622 if (in_array($authorisation->status, $denied_states)) 623 { 624 // Trigger onUserAuthorisationFailure Event. 625 $this->triggerEvent('onUserAuthorisationFailure', array((array) $authorisation)); 626 627 // If silent is set, just return false. 628 if (isset($options['silent']) && $options['silent']) 629 { 630 return false; 631 } 632 633 // Return the error. 634 switch ($authorisation->status) 635 { 636 case JAuthentication::STATUS_EXPIRED: 637 return JError::raiseWarning('102002', JText::_('JLIB_LOGIN_EXPIRED')); 638 break; 639 case JAuthentication::STATUS_DENIED: 640 return JError::raiseWarning('102003', JText::_('JLIB_LOGIN_DENIED')); 641 break; 642 default: 643 return JError::raiseWarning('102004', JText::_('JLIB_LOGIN_AUTHORISATION')); 644 break; 645 } 646 } 647 } 648 649 // Import the user plugin group. 650 JPluginHelper::importPlugin('user'); 651 652 // OK, the credentials are authenticated and user is authorised. Lets fire the onLogin event. 653 $results = $this->triggerEvent('onUserLogin', array((array) $response, $options)); 654 655 /* 656 * If any of the user plugins did not successfully complete the login routine 657 * then the whole method fails. 658 * 659 * Any errors raised should be done in the plugin as this provides the ability 660 * to provide much more information about why the routine may have failed. 661 */ 662 663 if (!in_array(false, $results, true)) 664 { 665 // Set the remember me cookie if enabled. 666 if (isset($options['remember']) && $options['remember']) 667 { 668 // Create the encryption key, apply extra hardening using the user agent string. 669 $privateKey = self::getHash(@$_SERVER['HTTP_USER_AGENT']); 670 671 $key = new JCryptKey('simple', $privateKey, $privateKey); 672 $crypt = new JCrypt(new JCryptCipherSimple, $key); 673 $rcookie = $crypt->encrypt(serialize($credentials)); 674 $lifetime = time() + 365 * 24 * 60 * 60; 675 676 // Use domain and path set in config for cookie if it exists. 677 $cookie_domain = $this->getCfg('cookie_domain', ''); 678 $cookie_path = $this->getCfg('cookie_path', '/'); 679 setcookie(self::getHash('JLOGIN_REMEMBER'), $rcookie, $lifetime, $cookie_path, $cookie_domain); 680 } 681 682 return true; 683 } 684 } 685 686 // Trigger onUserLoginFailure Event. 687 $this->triggerEvent('onUserLoginFailure', array((array) $response)); 688 689 // If silent is set, just return false. 690 if (isset($options['silent']) && $options['silent']) 691 { 692 return false; 693 } 694 695 // If status is success, any error will have been raised by the user plugin 696 if ($response->status !== JAuthentication::STATUS_SUCCESS) 697 { 698 JLog::add($response->error_message, JLog::WARNING, 'jerror'); 699 } 700 701 return false; 702 } 703 704 /** 705 * Logout authentication function. 706 * 707 * Passed the current user information to the onUserLogout event and reverts the current 708 * session record back to 'anonymous' parameters. 709 * If any of the authentication plugins did not successfully complete 710 * the logout routine then the whole method fails. Any errors raised 711 * should be done in the plugin as this provides the ability to give 712 * much more information about why the routine may have failed. 713 * 714 * @param integer $userid The user to load - Can be an integer or string - If string, it is converted to ID automatically 715 * @param array $options Array('clientid' => array of client id's) 716 * 717 * @return boolean True on success 718 * 719 * @since 11.1 720 */ 721 public function logout($userid = null, $options = array()) 722 { 723 // Get a user object from the JApplication. 724 $user = JFactory::getUser($userid); 725 726 // Build the credentials array. 727 $parameters['username'] = $user->get('username'); 728 $parameters['id'] = $user->get('id'); 729 730 // Set clientid in the options array if it hasn't been set already. 731 if (!isset($options['clientid'])) 732 { 733 $options['clientid'] = $this->getClientId(); 734 } 735 736 // Import the user plugin group. 737 JPluginHelper::importPlugin('user'); 738 739 // OK, the credentials are built. Lets fire the onLogout event. 740 $results = $this->triggerEvent('onUserLogout', array($parameters, $options)); 741 742 // Check if any of the plugins failed. If none did, success. 743 744 if (!in_array(false, $results, true)) 745 { 746 // Use domain and path set in config for cookie if it exists. 747 $cookie_domain = $this->getCfg('cookie_domain', ''); 748 $cookie_path = $this->getCfg('cookie_path', '/'); 749 setcookie(self::getHash('JLOGIN_REMEMBER'), false, time() - 86400, $cookie_path, $cookie_domain); 750 751 return true; 752 } 753 754 // Trigger onUserLoginFailure Event. 755 $this->triggerEvent('onUserLogoutFailure', array($parameters)); 756 757 return false; 758 } 759 760 /** 761 * Gets the name of the current template. 762 * 763 * @param array $params An optional associative array of configuration settings 764 * 765 * @return string System is the fallback. 766 * 767 * @since 11.1 768 */ 769 public function getTemplate($params = array()) 770 { 771 return 'system'; 772 } 773 774 /** 775 * Returns the application JRouter object. 776 * 777 * @param string $name The name of the application. 778 * @param array $options An optional associative array of configuration settings. 779 * 780 * @return JRouter A JRouter object 781 * 782 * @since 11.1 783 */ 784 static public function getRouter($name = null, array $options = array()) 785 { 786 if (!isset($name)) 787 { 788 $app = JFactory::getApplication(); 789 $name = $app->getName(); 790 } 791 792 jimport('joomla.application.router'); 793 794 try 795 { 796 $router = JRouter::getInstance($name, $options); 797 } 798 catch (Exception $e) 799 { 800 return null; 801 } 802 803 return $router; 804 } 805 806 /** 807 * This method transliterates a string into an URL 808 * safe string or returns a URL safe UTF-8 string 809 * based on the global configuration 810 * 811 * @param string $string String to process 812 * 813 * @return string Processed string 814 * 815 * @since 11.1 816 */ 817 static public function stringURLSafe($string) 818 { 819 if (JFactory::getConfig()->get('unicodeslugs') == 1) 820 { 821 $output = JFilterOutput::stringURLUnicodeSlug($string); 822 } 823 else 824 { 825 $output = JFilterOutput::stringURLSafe($string); 826 } 827 828 return $output; 829 } 830 831 /** 832 * Returns the application JPathway object. 833 * 834 * @param string $name The name of the application. 835 * @param array $options An optional associative array of configuration settings. 836 * 837 * @return JPathway A JPathway object 838 * 839 * @since 11.1 840 */ 841 public function getPathway($name = null, $options = array()) 842 { 843 if (!isset($name)) 844 { 845 $name = $this->_name; 846 } 847 848 try 849 { 850 $pathway = JPathway::getInstance($name, $options); 851 } 852 catch (Exception $e) 853 { 854 return null; 855 } 856 857 return $pathway; 858 } 859 860 /** 861 * Returns the application JPathway object. 862 * 863 * @param string $name The name of the application/client. 864 * @param array $options An optional associative array of configuration settings. 865 * 866 * @return JMenu JMenu object. 867 * 868 * @since 11.1 869 */ 870 public function getMenu($name = null, $options = array()) 871 { 872 if (!isset($name)) 873 { 874 $name = $this->_name; 875 } 876 877 try 878 { 879 $menu = JMenu::getInstance($name, $options); 880 } 881 catch (Exception $e) 882 { 883 return null; 884 } 885 886 return $menu; 887 } 888 889 /** 890 * Provides a secure hash based on a seed 891 * 892 * @param string $seed Seed string. 893 * 894 * @return string A secure hash 895 * 896 * @since 11.1 897 */ 898 public static function getHash($seed) 899 { 900 return md5(JFactory::getConfig()->get('secret') . $seed); 901 } 902 903 /** 904 * Create the configuration registry. 905 * 906 * @param string $file The path to the configuration file 907 * 908 * @return JConfig A JConfig object 909 * 910 * @since 11.1 911 */ 912 protected function _createConfiguration($file) 913 { 914 JLoader::register('JConfig', $file); 915 916 // Create the JConfig object. 917 $config = new JConfig; 918 919 // Get the global configuration object. 920 $registry = JFactory::getConfig(); 921 922 // Load the configuration values into the registry. 923 $registry->loadObject($config); 924 925 return $config; 926 } 927 928 /** 929 * Create the user session. 930 * 931 * Old sessions are flushed based on the configuration value for the cookie 932 * lifetime. If an existing session, then the last access time is updated. 933 * If a new session, a session id is generated and a record is created in 934 * the #__sessions table. 935 * 936 * @param string $name The sessions name. 937 * 938 * @return JSession JSession on success. May call exit() on database error. 939 * 940 * @since 11.1 941 */ 942 protected function _createSession($name) 943 { 944 $options = array(); 945 $options['name'] = $name; 946 947 switch ($this->_clientId) 948 { 949 case 0: 950 if ($this->getCfg('force_ssl') == 2) 951 { 952 $options['force_ssl'] = true; 953 } 954 break; 955 956 case 1: 957 if ($this->getCfg('force_ssl') >= 1) 958 { 959 $options['force_ssl'] = true; 960 } 961 break; 962 } 963 964 $this->registerEvent('onAfterSessionStart', array($this, 'afterSessionStart')); 965 966 $session = JFactory::getSession($options); 967 $session->initialise($this->input, $this->dispatcher); 968 $session->start(); 969 970 // TODO: At some point we need to get away from having session data always in the db. 971 972 $db = JFactory::getDBO(); 973 974 // Remove expired sessions from the database. 975 $time = time(); 976 if ($time % 2) 977 { 978 // The modulus introduces a little entropy, making the flushing less accurate 979 // but fires the query less than half the time. 980 $query = $db->getQuery(true); 981 $query->delete($query->qn('#__session')) 982 ->where($query->qn('time') . ' < ' . $query->q((int) ($time - $session->getExpire()))); 983 984 $db->setQuery($query); 985 $db->execute(); 986 } 987 988 // Check to see the the session already exists. 989 $handler = $this->getCfg('session_handler'); 990 if (($handler != 'database' && ($time % 2 || $session->isNew())) 991 || ($handler == 'database' && $session->isNew())) 992 { 993 $this->checkSession(); 994 } 995 996 return $session; 997 } 998 999 /** 1000 * Checks the user session. 1001 * 1002 * If the session record doesn't exist, initialise it. 1003 * If session is new, create session variables 1004 * 1005 * @return void 1006 * 1007 * @since 11.1 1008 */ 1009 public function checkSession() 1010 { 1011 $db = JFactory::getDBO(); 1012 $session = JFactory::getSession(); 1013 $user = JFactory::getUser(); 1014 1015 $query = $db->getQuery(true); 1016 $query->select($query->qn('session_id')) 1017 ->from($query->qn('#__session')) 1018 ->where($query->qn('session_id') . ' = ' . $query->q($session->getId())); 1019 1020 $db->setQuery($query, 0, 1); 1021 $exists = $db->loadResult(); 1022 1023 // If the session record doesn't exist initialise it. 1024 if (!$exists) 1025 { 1026 $query->clear(); 1027 if ($session->isNew()) 1028 { 1029 $query->insert($query->qn('#__session')) 1030 ->columns($query->qn('session_id') . ', ' . $query->qn('client_id') . ', ' . $query->qn('time')) 1031 ->values($query->q($session->getId()) . ', ' . (int) $this->getClientId() . ', ' . $query->q((int) time())); 1032 $db->setQuery($query); 1033 } 1034 else 1035 { 1036 $query->insert($query->qn('#__session')) 1037 ->columns( 1038 $query->qn('session_id') . ', ' . $query->qn('client_id') . ', ' . $query->qn('guest') . ', ' . 1039 $query->qn('time') . ', ' . $query->qn('userid') . ', ' . $query->qn('username') 1040 ) 1041 ->values( 1042 $query->q($session->getId()) . ', ' . (int) $this->getClientId() . ', ' . (int) $user->get('guest') . ', ' . 1043 $query->q((int) $session->get('session.timer.start')) . ', ' . (int) $user->get('id') . ', ' . $query->q($user->get('username')) 1044 ); 1045 1046 $db->setQuery($query); 1047 } 1048 1049 // If the insert failed, exit the application. 1050 try 1051 { 1052 $db->execute(); 1053 } 1054 catch (RuntimeException $e) 1055 { 1056 jexit($e->getMessage()); 1057 } 1058 } 1059 } 1060 1061 /** 1062 * After the session has been started we need to populate it with some default values. 1063 * 1064 * @return void 1065 * 1066 * @since 12.2 1067 */ 1068 public function afterSessionStart() 1069 { 1070 $session = JFactory::getSession(); 1071 if ($session->isNew()) 1072 { 1073 $session->set('registry', new JRegistry('session')); 1074 $session->set('user', new JUser); 1075 } 1076 } 1077 1078 /** 1079 * Gets the client id of the current running application. 1080 * 1081 * @return integer A client identifier. 1082 * 1083 * @since 11.1 1084 */ 1085 public function getClientId() 1086 { 1087 return $this->_clientId; 1088 } 1089 1090 /** 1091 * Is admin interface? 1092 * 1093 * @return boolean True if this application is administrator. 1094 * 1095 * @since 11.1 1096 */ 1097 public function isAdmin() 1098 { 1099 return ($this->_clientId == 1); 1100 } 1101 1102 /** 1103 * Is site interface? 1104 * 1105 * @return boolean True if this application is site. 1106 * 1107 * @since 11.1 1108 */ 1109 public function isSite() 1110 { 1111 return ($this->_clientId == 0); 1112 } 1113 1114 /** 1115 * Method to determine if the host OS is Windows 1116 * 1117 * @return boolean True if Windows OS 1118 * 1119 * @since 11.1 1120 * @deprecated 13.3 Use the IS_WIN constant instead. 1121 */ 1122 public static function isWinOS() 1123 { 1124 JLog::add('JApplication::isWinOS() is deprecated. Use the IS_WIN constant instead.', JLog::WARNING, 'deprecated'); 1125 1126 return IS_WIN; 1127 } 1128 1129 /** 1130 * Determine if we are using a secure (SSL) connection. 1131 * 1132 * @return boolean True if using SSL, false if not. 1133 * 1134 * @since 12.2 1135 */ 1136 public function isSSLConnection() 1137 { 1138 return ((isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on')) || getenv('SSL_PROTOCOL_VERSION')); 1139 } 1140 1141 /** 1142 * Returns the response as a string. 1143 * 1144 * @return string The response 1145 * 1146 * @since 11.1 1147 */ 1148 public function __toString() 1149 { 1150 $compress = $this->getCfg('gzip', false); 1151 1152 return JResponse::toString($compress); 1153 } 1154}