getting cakephp set up with its own web server(s) and docroot
This commit is contained in:
36
web-cake/html/cake/libs/controller/app_controller.php
Normal file
36
web-cake/html/cake/libs/controller/app_controller.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* Application level Controller
|
||||
*
|
||||
* This file is application-wide controller file. You can put all
|
||||
* application-wide controller-related methods here.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller
|
||||
* @since CakePHP(tm) v 0.2.9
|
||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a placeholder class.
|
||||
* Create the same file in app/app_controller.php
|
||||
*
|
||||
* Add your application-wide methods in the class below, your controllers
|
||||
* will inherit them.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller
|
||||
* @link http://book.cakephp.org/view/957/The-App-Controller
|
||||
*/
|
||||
class AppController extends Controller {
|
||||
}
|
263
web-cake/html/cake/libs/controller/component.php
Normal file
263
web-cake/html/cake/libs/controller/component.php
Normal file
@@ -0,0 +1,263 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller
|
||||
* @since CakePHP(tm) v TBD
|
||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handler for Controller::$components
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller
|
||||
* @link http://book.cakephp.org/view/993/Components
|
||||
*/
|
||||
class Component extends Object {
|
||||
|
||||
/**
|
||||
* Contains various controller variable information (plugin, name, base).
|
||||
*
|
||||
* @var object
|
||||
* @access private
|
||||
*/
|
||||
var $__controllerVars = array('plugin' => null, 'name' => null, 'base' => null);
|
||||
|
||||
/**
|
||||
* List of loaded components.
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
var $_loaded = array();
|
||||
|
||||
/**
|
||||
* List of components attached directly to the controller, which callbacks
|
||||
* should be executed on.
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
var $_primary = array();
|
||||
|
||||
/**
|
||||
* Settings for loaded components.
|
||||
*
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
var $__settings = array();
|
||||
|
||||
/**
|
||||
* Used to initialize the components for current controller.
|
||||
*
|
||||
* @param object $controller Controller with components to load
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function init(&$controller) {
|
||||
if (!is_array($controller->components)) {
|
||||
return;
|
||||
}
|
||||
$this->__controllerVars = array(
|
||||
'plugin' => $controller->plugin, 'name' => $controller->name,
|
||||
'base' => $controller->base
|
||||
);
|
||||
|
||||
$this->_loadComponents($controller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before the Controller::beforeFilter().
|
||||
*
|
||||
* @param object $controller Controller with components to initialize
|
||||
* @return void
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/998/MVC-Class-Access-Within-Components
|
||||
*/
|
||||
function initialize(&$controller) {
|
||||
foreach (array_keys($this->_loaded) as $name) {
|
||||
$component =& $this->_loaded[$name];
|
||||
|
||||
if (method_exists($component,'initialize') && $component->enabled === true) {
|
||||
$settings = array();
|
||||
if (isset($this->__settings[$name])) {
|
||||
$settings = $this->__settings[$name];
|
||||
}
|
||||
$component->initialize($controller, $settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the Controller::beforeFilter() and before the controller action
|
||||
*
|
||||
* @param object $controller Controller with components to startup
|
||||
* @return void
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/998/MVC-Class-Access-Within-Components
|
||||
* @deprecated See Component::triggerCallback()
|
||||
*/
|
||||
function startup(&$controller) {
|
||||
$this->triggerCallback('startup', $controller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the Controller::beforeRender(), after the view class is loaded, and before the
|
||||
* Controller::render()
|
||||
*
|
||||
* @param object $controller Controller with components to beforeRender
|
||||
* @return void
|
||||
* @access public
|
||||
* @deprecated See Component::triggerCallback()
|
||||
*/
|
||||
function beforeRender(&$controller) {
|
||||
$this->triggerCallback('beforeRender', $controller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before Controller::redirect().
|
||||
*
|
||||
* @param object $controller Controller with components to beforeRedirect
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function beforeRedirect(&$controller, $url, $status = null, $exit = true) {
|
||||
$response = array();
|
||||
|
||||
foreach ($this->_primary as $name) {
|
||||
$component =& $this->_loaded[$name];
|
||||
|
||||
if ($component->enabled === true && method_exists($component, 'beforeRedirect')) {
|
||||
$resp = $component->beforeRedirect($controller, $url, $status, $exit);
|
||||
if ($resp === false) {
|
||||
return false;
|
||||
}
|
||||
$response[] = $resp;
|
||||
}
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after Controller::render() and before the output is printed to the browser.
|
||||
*
|
||||
* @param object $controller Controller with components to shutdown
|
||||
* @return void
|
||||
* @access public
|
||||
* @deprecated See Component::triggerCallback()
|
||||
*/
|
||||
function shutdown(&$controller) {
|
||||
$this->triggerCallback('shutdown', $controller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a callback on all primary components. Will fire $callback on all components
|
||||
* that have such a method. You can implement and fire custom callbacks in addition to the
|
||||
* standard ones.
|
||||
*
|
||||
* example use, from inside a controller:
|
||||
*
|
||||
* `$this->Component->triggerCallback('beforeFilter', $this);`
|
||||
*
|
||||
* will trigger the beforeFilter callback on all components that have implemented one. You
|
||||
* can trigger any method in this fashion.
|
||||
*
|
||||
* @param Controller $controller Controller instance
|
||||
* @param string $callback Callback to trigger.
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function triggerCallback($callback, &$controller) {
|
||||
foreach ($this->_primary as $name) {
|
||||
$component =& $this->_loaded[$name];
|
||||
if (method_exists($component, $callback) && $component->enabled === true) {
|
||||
$component->{$callback}($controller);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads components used by this component.
|
||||
*
|
||||
* @param object $object Object with a Components array
|
||||
* @param object $parent the parent of the current object
|
||||
* @return void
|
||||
* @access protected
|
||||
*/
|
||||
function _loadComponents(&$object, $parent = null) {
|
||||
$base = $this->__controllerVars['base'];
|
||||
$normal = Set::normalize($object->components);
|
||||
foreach ((array)$normal as $component => $config) {
|
||||
$plugin = isset($this->__controllerVars['plugin']) ? $this->__controllerVars['plugin'] . '.' : null;
|
||||
list($plugin, $component) = pluginSplit($component, true, $plugin);
|
||||
$componentCn = $component . 'Component';
|
||||
|
||||
if (!class_exists($componentCn)) {
|
||||
if (is_null($plugin) || !App::import('Component', $plugin . $component)) {
|
||||
if (!App::import('Component', $component)) {
|
||||
$this->cakeError('missingComponentFile', array(array(
|
||||
'className' => $this->__controllerVars['name'],
|
||||
'component' => $component,
|
||||
'file' => Inflector::underscore($component) . '.php',
|
||||
'base' => $base,
|
||||
'code' => 500
|
||||
)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!class_exists($componentCn)) {
|
||||
$this->cakeError('missingComponentClass', array(array(
|
||||
'className' => $this->__controllerVars['name'],
|
||||
'component' => $component,
|
||||
'file' => Inflector::underscore($component) . '.php',
|
||||
'base' => $base,
|
||||
'code' => 500
|
||||
)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($parent === null) {
|
||||
$this->_primary[] = $component;
|
||||
}
|
||||
|
||||
if (isset($this->_loaded[$component])) {
|
||||
$object->{$component} =& $this->_loaded[$component];
|
||||
|
||||
if (!empty($config) && isset($this->__settings[$component])) {
|
||||
$this->__settings[$component] = array_merge($this->__settings[$component], $config);
|
||||
} elseif (!empty($config)) {
|
||||
$this->__settings[$component] = $config;
|
||||
}
|
||||
} else {
|
||||
if ($componentCn === 'SessionComponent') {
|
||||
$object->{$component} =& new $componentCn($base);
|
||||
} else {
|
||||
$object->{$component} =& new $componentCn();
|
||||
}
|
||||
$object->{$component}->enabled = true;
|
||||
$this->_loaded[$component] =& $object->{$component};
|
||||
if (!empty($config)) {
|
||||
$this->__settings[$component] = $config;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($object->{$component}->components) && is_array($object->{$component}->components) && (!isset($object->{$component}->{$parent}))) {
|
||||
$this->_loadComponents($object->{$component}, $component);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
638
web-cake/html/cake/libs/controller/components/acl.php
Normal file
638
web-cake/html/cake/libs/controller/components/acl.php
Normal file
@@ -0,0 +1,638 @@
|
||||
<?php
|
||||
/**
|
||||
* Access Control List factory class.
|
||||
*
|
||||
* Permissions system.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller.components
|
||||
* @since CakePHP(tm) v 0.10.0.1076
|
||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Access Control List factory class.
|
||||
*
|
||||
* Uses a strategy pattern to allow custom ACL implementations to be used with the same component interface.
|
||||
* You can define by changing `Configure::write('Acl.classname', 'DbAcl');` in your core.php. Concrete ACL
|
||||
* implementations should extend `AclBase` and implement the methods it defines.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller.components
|
||||
* @link http://book.cakephp.org/view/1242/Access-Control-Lists
|
||||
*/
|
||||
class AclComponent extends Object {
|
||||
|
||||
/**
|
||||
* Instance of an ACL class
|
||||
*
|
||||
* @var object
|
||||
* @access protected
|
||||
*/
|
||||
var $_Instance = null;
|
||||
|
||||
/**
|
||||
* Constructor. Will return an instance of the correct ACL class as defined in `Configure::read('Acl.classname')`
|
||||
*
|
||||
*/
|
||||
function __construct() {
|
||||
$name = Inflector::camelize(strtolower(Configure::read('Acl.classname')));
|
||||
if (!class_exists($name)) {
|
||||
if (App::import('Component', $name)) {
|
||||
list($plugin, $name) = pluginSplit($name);
|
||||
$name .= 'Component';
|
||||
} else {
|
||||
trigger_error(sprintf(__('Could not find %s.', true), $name), E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
$this->_Instance =& new $name();
|
||||
$this->_Instance->initialize($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Startup is not used
|
||||
*
|
||||
* @param object $controller Controller using this component
|
||||
* @return boolean Proceed with component usage (true), or fail (false)
|
||||
* @access public
|
||||
*/
|
||||
function startup(&$controller) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty class defintion, to be overridden in subclasses.
|
||||
*
|
||||
* @access protected
|
||||
*/
|
||||
function _initACL() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass-thru function for ACL check instance. Check methods
|
||||
* are used to check whether or not an ARO can access an ACO
|
||||
*
|
||||
* @param string $aro ARO The requesting object identifier.
|
||||
* @param string $aco ACO The controlled object identifier.
|
||||
* @param string $action Action (defaults to *)
|
||||
* @return boolean Success
|
||||
* @access public
|
||||
*/
|
||||
function check($aro, $aco, $action = "*") {
|
||||
return $this->_Instance->check($aro, $aco, $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass-thru function for ACL allow instance. Allow methods
|
||||
* are used to grant an ARO access to an ACO.
|
||||
*
|
||||
* @param string $aro ARO The requesting object identifier.
|
||||
* @param string $aco ACO The controlled object identifier.
|
||||
* @param string $action Action (defaults to *)
|
||||
* @return boolean Success
|
||||
* @access public
|
||||
*/
|
||||
function allow($aro, $aco, $action = "*") {
|
||||
return $this->_Instance->allow($aro, $aco, $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass-thru function for ACL deny instance. Deny methods
|
||||
* are used to remove permission from an ARO to access an ACO.
|
||||
*
|
||||
* @param string $aro ARO The requesting object identifier.
|
||||
* @param string $aco ACO The controlled object identifier.
|
||||
* @param string $action Action (defaults to *)
|
||||
* @return boolean Success
|
||||
* @access public
|
||||
*/
|
||||
function deny($aro, $aco, $action = "*") {
|
||||
return $this->_Instance->deny($aro, $aco, $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass-thru function for ACL inherit instance. Inherit methods
|
||||
* modify the permission for an ARO to be that of its parent object.
|
||||
*
|
||||
* @param string $aro ARO The requesting object identifier.
|
||||
* @param string $aco ACO The controlled object identifier.
|
||||
* @param string $action Action (defaults to *)
|
||||
* @return boolean Success
|
||||
* @access public
|
||||
*/
|
||||
function inherit($aro, $aco, $action = "*") {
|
||||
return $this->_Instance->inherit($aro, $aco, $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass-thru function for ACL grant instance. An alias for AclComponent::allow()
|
||||
*
|
||||
* @param string $aro ARO The requesting object identifier.
|
||||
* @param string $aco ACO The controlled object identifier.
|
||||
* @param string $action Action (defaults to *)
|
||||
* @return boolean Success
|
||||
* @access public
|
||||
*/
|
||||
function grant($aro, $aco, $action = "*") {
|
||||
return $this->_Instance->grant($aro, $aco, $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass-thru function for ACL grant instance. An alias for AclComponent::deny()
|
||||
*
|
||||
* @param string $aro ARO The requesting object identifier.
|
||||
* @param string $aco ACO The controlled object identifier.
|
||||
* @param string $action Action (defaults to *)
|
||||
* @return boolean Success
|
||||
* @access public
|
||||
*/
|
||||
function revoke($aro, $aco, $action = "*") {
|
||||
return $this->_Instance->revoke($aro, $aco, $action);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Access Control List abstract class. Not to be instantiated.
|
||||
* Subclasses of this class are used by AclComponent to perform ACL checks in Cake.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller.components
|
||||
* @abstract
|
||||
*/
|
||||
class AclBase extends Object {
|
||||
|
||||
/**
|
||||
* This class should never be instantiated, just subclassed.
|
||||
*
|
||||
*/
|
||||
function __construct() {
|
||||
if (strcasecmp(get_class($this), "AclBase") == 0 || !is_subclass_of($this, "AclBase")) {
|
||||
trigger_error(__("[acl_base] The AclBase class constructor has been called, or the class was instantiated. This class must remain abstract. Please refer to the Cake docs for ACL configuration.", true), E_USER_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty method to be overridden in subclasses
|
||||
*
|
||||
* @param string $aro ARO The requesting object identifier.
|
||||
* @param string $aco ACO The controlled object identifier.
|
||||
* @param string $action Action (defaults to *)
|
||||
* @access public
|
||||
*/
|
||||
function check($aro, $aco, $action = "*") {
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty method to be overridden in subclasses
|
||||
*
|
||||
* @param object $component Component
|
||||
* @access public
|
||||
*/
|
||||
function initialize(&$component) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DbAcl implements an ACL control system in the database. ARO's and ACO's are
|
||||
* structured into trees and a linking table is used to define permissions. You
|
||||
* can install the schema for DbAcl with the Schema Shell.
|
||||
*
|
||||
* `$aco` and `$aro` parameters can be slash delimited paths to tree nodes.
|
||||
*
|
||||
* eg. `controllers/Users/edit`
|
||||
*
|
||||
* Would point to a tree structure like
|
||||
*
|
||||
* {{{
|
||||
* controllers
|
||||
* Users
|
||||
* edit
|
||||
* }}}
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.model
|
||||
*/
|
||||
class DbAcl extends AclBase {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
*/
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
if (!class_exists('AclNode')) {
|
||||
require LIBS . 'model' . DS . 'db_acl.php';
|
||||
}
|
||||
$this->Aro =& ClassRegistry::init(array('class' => 'Aro', 'alias' => 'Aro'));
|
||||
$this->Aco =& ClassRegistry::init(array('class' => 'Aco', 'alias' => 'Aco'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the containing component and sets the Aro/Aco objects to it.
|
||||
*
|
||||
* @param AclComponent $component
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function initialize(&$component) {
|
||||
$component->Aro =& $this->Aro;
|
||||
$component->Aco =& $this->Aco;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given $aro has access to action $action in $aco
|
||||
*
|
||||
* @param string $aro ARO The requesting object identifier.
|
||||
* @param string $aco ACO The controlled object identifier.
|
||||
* @param string $action Action (defaults to *)
|
||||
* @return boolean Success (true if ARO has access to action in ACO, false otherwise)
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1249/Checking-Permissions-The-ACL-Component
|
||||
*/
|
||||
function check($aro, $aco, $action = "*") {
|
||||
if ($aro == null || $aco == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$permKeys = $this->_getAcoKeys($this->Aro->Permission->schema());
|
||||
$aroPath = $this->Aro->node($aro);
|
||||
$acoPath = $this->Aco->node($aco);
|
||||
|
||||
if (empty($aroPath) || empty($acoPath)) {
|
||||
trigger_error(__("DbAcl::check() - Failed ARO/ACO node lookup in permissions check. Node references:\nAro: ", true) . print_r($aro, true) . "\nAco: " . print_r($aco, true), E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($acoPath == null || $acoPath == array()) {
|
||||
trigger_error(__("DbAcl::check() - Failed ACO node lookup in permissions check. Node references:\nAro: ", true) . print_r($aro, true) . "\nAco: " . print_r($aco, true), E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
$aroNode = $aroPath[0];
|
||||
$acoNode = $acoPath[0];
|
||||
|
||||
if ($action != '*' && !in_array('_' . $action, $permKeys)) {
|
||||
trigger_error(sprintf(__("ACO permissions key %s does not exist in DbAcl::check()", true), $action), E_USER_NOTICE);
|
||||
return false;
|
||||
}
|
||||
|
||||
$inherited = array();
|
||||
$acoIDs = Set::extract($acoPath, '{n}.' . $this->Aco->alias . '.id');
|
||||
|
||||
$count = count($aroPath);
|
||||
for ($i = 0 ; $i < $count; $i++) {
|
||||
$permAlias = $this->Aro->Permission->alias;
|
||||
|
||||
$perms = $this->Aro->Permission->find('all', array(
|
||||
'conditions' => array(
|
||||
"{$permAlias}.aro_id" => $aroPath[$i][$this->Aro->alias]['id'],
|
||||
"{$permAlias}.aco_id" => $acoIDs
|
||||
),
|
||||
'order' => array($this->Aco->alias . '.lft' => 'desc'),
|
||||
'recursive' => 0
|
||||
));
|
||||
|
||||
if (empty($perms)) {
|
||||
continue;
|
||||
} else {
|
||||
$perms = Set::extract($perms, '{n}.' . $this->Aro->Permission->alias);
|
||||
foreach ($perms as $perm) {
|
||||
if ($action == '*') {
|
||||
|
||||
foreach ($permKeys as $key) {
|
||||
if (!empty($perm)) {
|
||||
if ($perm[$key] == -1) {
|
||||
return false;
|
||||
} elseif ($perm[$key] == 1) {
|
||||
$inherited[$key] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($inherited) === count($permKeys)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
switch ($perm['_' . $action]) {
|
||||
case -1:
|
||||
return false;
|
||||
case 0:
|
||||
continue;
|
||||
break;
|
||||
case 1:
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow $aro to have access to action $actions in $aco
|
||||
*
|
||||
* @param string $aro ARO The requesting object identifier.
|
||||
* @param string $aco ACO The controlled object identifier.
|
||||
* @param string $actions Action (defaults to *)
|
||||
* @param integer $value Value to indicate access type (1 to give access, -1 to deny, 0 to inherit)
|
||||
* @return boolean Success
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1248/Assigning-Permissions
|
||||
*/
|
||||
function allow($aro, $aco, $actions = "*", $value = 1) {
|
||||
$perms = $this->getAclLink($aro, $aco);
|
||||
$permKeys = $this->_getAcoKeys($this->Aro->Permission->schema());
|
||||
$save = array();
|
||||
|
||||
if ($perms == false) {
|
||||
trigger_error(__('DbAcl::allow() - Invalid node', true), E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
if (isset($perms[0])) {
|
||||
$save = $perms[0][$this->Aro->Permission->alias];
|
||||
}
|
||||
|
||||
if ($actions == "*") {
|
||||
$permKeys = $this->_getAcoKeys($this->Aro->Permission->schema());
|
||||
$save = array_combine($permKeys, array_pad(array(), count($permKeys), $value));
|
||||
} else {
|
||||
if (!is_array($actions)) {
|
||||
$actions = array('_' . $actions);
|
||||
}
|
||||
if (is_array($actions)) {
|
||||
foreach ($actions as $action) {
|
||||
if ($action{0} != '_') {
|
||||
$action = '_' . $action;
|
||||
}
|
||||
if (in_array($action, $permKeys)) {
|
||||
$save[$action] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
list($save['aro_id'], $save['aco_id']) = array($perms['aro'], $perms['aco']);
|
||||
|
||||
if ($perms['link'] != null && !empty($perms['link'])) {
|
||||
$save['id'] = $perms['link'][0][$this->Aro->Permission->alias]['id'];
|
||||
} else {
|
||||
unset($save['id']);
|
||||
$this->Aro->Permission->id = null;
|
||||
}
|
||||
return ($this->Aro->Permission->save($save) !== false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deny access for $aro to action $action in $aco
|
||||
*
|
||||
* @param string $aro ARO The requesting object identifier.
|
||||
* @param string $aco ACO The controlled object identifier.
|
||||
* @param string $actions Action (defaults to *)
|
||||
* @return boolean Success
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1248/Assigning-Permissions
|
||||
*/
|
||||
function deny($aro, $aco, $action = "*") {
|
||||
return $this->allow($aro, $aco, $action, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Let access for $aro to action $action in $aco be inherited
|
||||
*
|
||||
* @param string $aro ARO The requesting object identifier.
|
||||
* @param string $aco ACO The controlled object identifier.
|
||||
* @param string $actions Action (defaults to *)
|
||||
* @return boolean Success
|
||||
* @access public
|
||||
*/
|
||||
function inherit($aro, $aco, $action = "*") {
|
||||
return $this->allow($aro, $aco, $action, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow $aro to have access to action $actions in $aco
|
||||
*
|
||||
* @param string $aro ARO The requesting object identifier.
|
||||
* @param string $aco ACO The controlled object identifier.
|
||||
* @param string $actions Action (defaults to *)
|
||||
* @return boolean Success
|
||||
* @see allow()
|
||||
* @access public
|
||||
*/
|
||||
function grant($aro, $aco, $action = "*") {
|
||||
return $this->allow($aro, $aco, $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deny access for $aro to action $action in $aco
|
||||
*
|
||||
* @param string $aro ARO The requesting object identifier.
|
||||
* @param string $aco ACO The controlled object identifier.
|
||||
* @param string $actions Action (defaults to *)
|
||||
* @return boolean Success
|
||||
* @see deny()
|
||||
* @access public
|
||||
*/
|
||||
function revoke($aro, $aco, $action = "*") {
|
||||
return $this->deny($aro, $aco, $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of access-control links between the given Aro and Aco
|
||||
*
|
||||
* @param string $aro ARO The requesting object identifier.
|
||||
* @param string $aco ACO The controlled object identifier.
|
||||
* @return array Indexed array with: 'aro', 'aco' and 'link'
|
||||
* @access public
|
||||
*/
|
||||
function getAclLink($aro, $aco) {
|
||||
$obj = array();
|
||||
$obj['Aro'] = $this->Aro->node($aro);
|
||||
$obj['Aco'] = $this->Aco->node($aco);
|
||||
|
||||
if (empty($obj['Aro']) || empty($obj['Aco'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return array(
|
||||
'aro' => Set::extract($obj, 'Aro.0.'.$this->Aro->alias.'.id'),
|
||||
'aco' => Set::extract($obj, 'Aco.0.'.$this->Aco->alias.'.id'),
|
||||
'link' => $this->Aro->Permission->find('all', array('conditions' => array(
|
||||
$this->Aro->Permission->alias . '.aro_id' => Set::extract($obj, 'Aro.0.'.$this->Aro->alias.'.id'),
|
||||
$this->Aro->Permission->alias . '.aco_id' => Set::extract($obj, 'Aco.0.'.$this->Aco->alias.'.id')
|
||||
)))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the keys used in an ACO
|
||||
*
|
||||
* @param array $keys Permission model info
|
||||
* @return array ACO keys
|
||||
* @access protected
|
||||
*/
|
||||
function _getAcoKeys($keys) {
|
||||
$newKeys = array();
|
||||
$keys = array_keys($keys);
|
||||
foreach ($keys as $key) {
|
||||
if (!in_array($key, array('id', 'aro_id', 'aco_id'))) {
|
||||
$newKeys[] = $key;
|
||||
}
|
||||
}
|
||||
return $newKeys;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* IniAcl implements an access control system using an INI file. An example
|
||||
* of the ini file used can be found in /config/acl.ini.php.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.model.iniacl
|
||||
*/
|
||||
class IniAcl extends AclBase {
|
||||
|
||||
/**
|
||||
* Array with configuration, parsed from ini file
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $config = null;
|
||||
|
||||
/**
|
||||
* The constructor must be overridden, as AclBase is abstract.
|
||||
*
|
||||
*/
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Main ACL check function. Checks to see if the ARO (access request object) has access to the
|
||||
* ACO (access control object).Looks at the acl.ini.php file for permissions
|
||||
* (see instructions in /config/acl.ini.php).
|
||||
*
|
||||
* @param string $aro ARO
|
||||
* @param string $aco ACO
|
||||
* @param string $aco_action Action
|
||||
* @return boolean Success
|
||||
* @access public
|
||||
*/
|
||||
function check($aro, $aco, $aco_action = null) {
|
||||
if ($this->config == null) {
|
||||
$this->config = $this->readConfigFile(CONFIGS . 'acl.ini.php');
|
||||
}
|
||||
$aclConfig = $this->config;
|
||||
|
||||
if (isset($aclConfig[$aro]['deny'])) {
|
||||
$userDenies = $this->arrayTrim(explode(",", $aclConfig[$aro]['deny']));
|
||||
|
||||
if (array_search($aco, $userDenies)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($aclConfig[$aro]['allow'])) {
|
||||
$userAllows = $this->arrayTrim(explode(",", $aclConfig[$aro]['allow']));
|
||||
|
||||
if (array_search($aco, $userAllows)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($aclConfig[$aro]['groups'])) {
|
||||
$userGroups = $this->arrayTrim(explode(",", $aclConfig[$aro]['groups']));
|
||||
|
||||
foreach ($userGroups as $group) {
|
||||
if (array_key_exists($group, $aclConfig)) {
|
||||
if (isset($aclConfig[$group]['deny'])) {
|
||||
$groupDenies=$this->arrayTrim(explode(",", $aclConfig[$group]['deny']));
|
||||
|
||||
if (array_search($aco, $groupDenies)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($aclConfig[$group]['allow'])) {
|
||||
$groupAllows = $this->arrayTrim(explode(",", $aclConfig[$group]['allow']));
|
||||
|
||||
if (array_search($aco, $groupAllows)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an INI file and returns an array that reflects the INI file's section structure. Double-quote friendly.
|
||||
*
|
||||
* @param string $fileName File
|
||||
* @return array INI section structure
|
||||
* @access public
|
||||
*/
|
||||
function readConfigFile($fileName) {
|
||||
$fileLineArray = file($fileName);
|
||||
|
||||
foreach ($fileLineArray as $fileLine) {
|
||||
$dataLine = trim($fileLine);
|
||||
$firstChar = substr($dataLine, 0, 1);
|
||||
|
||||
if ($firstChar != ';' && $dataLine != '') {
|
||||
if ($firstChar == '[' && substr($dataLine, -1, 1) == ']') {
|
||||
$sectionName = preg_replace('/[\[\]]/', '', $dataLine);
|
||||
} else {
|
||||
$delimiter = strpos($dataLine, '=');
|
||||
|
||||
if ($delimiter > 0) {
|
||||
$key = strtolower(trim(substr($dataLine, 0, $delimiter)));
|
||||
$value = trim(substr($dataLine, $delimiter + 1));
|
||||
|
||||
if (substr($value, 0, 1) == '"' && substr($value, -1) == '"') {
|
||||
$value = substr($value, 1, -1);
|
||||
}
|
||||
|
||||
$iniSetting[$sectionName][$key]=stripcslashes($value);
|
||||
} else {
|
||||
if (!isset($sectionName)) {
|
||||
$sectionName = '';
|
||||
}
|
||||
|
||||
$iniSetting[$sectionName][strtolower(trim($dataLine))]='';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $iniSetting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes trailing spaces on all array elements (to prepare for searching)
|
||||
*
|
||||
* @param array $array Array to trim
|
||||
* @return array Trimmed array
|
||||
* @access public
|
||||
*/
|
||||
function arrayTrim($array) {
|
||||
foreach ($array as $key => $value) {
|
||||
$array[$key] = trim($value);
|
||||
}
|
||||
array_unshift($array, "");
|
||||
return $array;
|
||||
}
|
||||
}
|
958
web-cake/html/cake/libs/controller/components/auth.php
Normal file
958
web-cake/html/cake/libs/controller/components/auth.php
Normal file
@@ -0,0 +1,958 @@
|
||||
<?php
|
||||
/**
|
||||
* Authentication component
|
||||
*
|
||||
* Manages user logins and permissions.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller.components
|
||||
* @since CakePHP(tm) v 0.10.0.1076
|
||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
|
||||
App::import('Core', array('Router', 'Security'), false);
|
||||
|
||||
/**
|
||||
* Authentication control component class
|
||||
*
|
||||
* Binds access control with user authentication and session management.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller.components
|
||||
* @link http://book.cakephp.org/view/1250/Authentication
|
||||
*/
|
||||
class AuthComponent extends Object {
|
||||
|
||||
/**
|
||||
* Maintains current user login state.
|
||||
*
|
||||
* @var boolean
|
||||
* @access private
|
||||
*/
|
||||
var $_loggedIn = false;
|
||||
|
||||
/**
|
||||
* Other components utilized by AuthComponent
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $components = array('Session', 'RequestHandler');
|
||||
|
||||
/**
|
||||
* A reference to the object used for authentication
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1278/authenticate
|
||||
*/
|
||||
var $authenticate = null;
|
||||
|
||||
/**
|
||||
* The name of the component to use for Authorization or set this to
|
||||
* 'controller' will validate against Controller::isAuthorized()
|
||||
* 'actions' will validate Controller::action against an AclComponent::check()
|
||||
* 'crud' will validate mapActions against an AclComponent::check()
|
||||
* array('model'=> 'name'); will validate mapActions against model $name::isAuthorized(user, controller, mapAction)
|
||||
* 'object' will validate Controller::action against object::isAuthorized(user, controller, action)
|
||||
*
|
||||
* @var mixed
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1275/authorize
|
||||
*/
|
||||
var $authorize = false;
|
||||
|
||||
/**
|
||||
* The name of an optional view element to render when an Ajax request is made
|
||||
* with an invalid or expired session
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1277/ajaxLogin
|
||||
*/
|
||||
var $ajaxLogin = null;
|
||||
|
||||
/**
|
||||
* The name of the element used for SessionComponent::setFlash
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $flashElement = 'default';
|
||||
|
||||
/**
|
||||
* The name of the model that represents users which will be authenticated. Defaults to 'User'.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1266/userModel
|
||||
*/
|
||||
var $userModel = 'User';
|
||||
|
||||
/**
|
||||
* Additional query conditions to use when looking up and authenticating users,
|
||||
* i.e. array('User.is_active' => 1).
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1268/userScope
|
||||
*/
|
||||
var $userScope = array();
|
||||
|
||||
/**
|
||||
* Allows you to specify non-default login name and password fields used in
|
||||
* $userModel, i.e. array('username' => 'login_name', 'password' => 'passwd').
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1267/fields
|
||||
*/
|
||||
var $fields = array('username' => 'username', 'password' => 'password');
|
||||
|
||||
/**
|
||||
* The session key name where the record of the current user is stored. If
|
||||
* unspecified, it will be "Auth.{$userModel name}".
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1276/sessionKey
|
||||
*/
|
||||
var $sessionKey = null;
|
||||
|
||||
/**
|
||||
* If using action-based access control, this defines how the paths to action
|
||||
* ACO nodes is computed. If, for example, all controller nodes are nested
|
||||
* under an ACO node named 'Controllers', $actionPath should be set to
|
||||
* "Controllers/".
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1279/actionPath
|
||||
*/
|
||||
var $actionPath = null;
|
||||
|
||||
/**
|
||||
* A URL (defined as a string or array) to the controller action that handles
|
||||
* logins.
|
||||
*
|
||||
* @var mixed
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1269/loginAction
|
||||
*/
|
||||
var $loginAction = null;
|
||||
|
||||
/**
|
||||
* Normally, if a user is redirected to the $loginAction page, the location they
|
||||
* were redirected from will be stored in the session so that they can be
|
||||
* redirected back after a successful login. If this session value is not
|
||||
* set, the user will be redirected to the page specified in $loginRedirect.
|
||||
*
|
||||
* @var mixed
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1270/loginRedirect
|
||||
*/
|
||||
var $loginRedirect = null;
|
||||
|
||||
/**
|
||||
* The default action to redirect to after the user is logged out. While AuthComponent does
|
||||
* not handle post-logout redirection, a redirect URL will be returned from AuthComponent::logout().
|
||||
* Defaults to AuthComponent::$loginAction.
|
||||
*
|
||||
* @var mixed
|
||||
* @access public
|
||||
* @see AuthComponent::$loginAction
|
||||
* @see AuthComponent::logout()
|
||||
* @link http://book.cakephp.org/view/1271/logoutRedirect
|
||||
*/
|
||||
var $logoutRedirect = null;
|
||||
|
||||
/**
|
||||
* The name of model or model object, or any other object has an isAuthorized method.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $object = null;
|
||||
|
||||
/**
|
||||
* Error to display when user login fails. For security purposes, only one error is used for all
|
||||
* login failures, so as not to expose information on why the login failed.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1272/loginError
|
||||
*/
|
||||
var $loginError = null;
|
||||
|
||||
/**
|
||||
* Error to display when user attempts to access an object or action to which they do not have
|
||||
* acccess.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1273/authError
|
||||
*/
|
||||
var $authError = null;
|
||||
|
||||
/**
|
||||
* Determines whether AuthComponent will automatically redirect and exit if login is successful.
|
||||
*
|
||||
* @var boolean
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1274/autoRedirect
|
||||
*/
|
||||
var $autoRedirect = true;
|
||||
|
||||
/**
|
||||
* Controller actions for which user validation is not required.
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
* @see AuthComponent::allow()
|
||||
* @link http://book.cakephp.org/view/1251/Setting-Auth-Component-Variables
|
||||
*/
|
||||
var $allowedActions = array();
|
||||
|
||||
/**
|
||||
* Maps actions to CRUD operations. Used for controller-based validation ($validate = 'controller').
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
* @see AuthComponent::mapActions()
|
||||
*/
|
||||
var $actionMap = array(
|
||||
'index' => 'read',
|
||||
'add' => 'create',
|
||||
'edit' => 'update',
|
||||
'view' => 'read',
|
||||
'remove' => 'delete'
|
||||
);
|
||||
|
||||
/**
|
||||
* Form data from Controller::$data
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $data = array();
|
||||
|
||||
/**
|
||||
* Parameter data from Controller::$params
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $params = array();
|
||||
|
||||
/**
|
||||
* Method list for bound controller
|
||||
*
|
||||
* @var array
|
||||
* @access protected
|
||||
*/
|
||||
var $_methods = array();
|
||||
|
||||
/**
|
||||
* Initializes AuthComponent for use in the controller
|
||||
*
|
||||
* @param object $controller A reference to the instantiating controller object
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function initialize(&$controller, $settings = array()) {
|
||||
$this->params = $controller->params;
|
||||
$crud = array('create', 'read', 'update', 'delete');
|
||||
$this->actionMap = array_merge($this->actionMap, array_combine($crud, $crud));
|
||||
$this->_methods = $controller->methods;
|
||||
|
||||
$prefixes = Router::prefixes();
|
||||
if (!empty($prefixes)) {
|
||||
foreach ($prefixes as $prefix) {
|
||||
$this->actionMap = array_merge($this->actionMap, array(
|
||||
$prefix . '_index' => 'read',
|
||||
$prefix . '_add' => 'create',
|
||||
$prefix . '_edit' => 'update',
|
||||
$prefix . '_view' => 'read',
|
||||
$prefix . '_remove' => 'delete',
|
||||
$prefix . '_create' => 'create',
|
||||
$prefix . '_read' => 'read',
|
||||
$prefix . '_update' => 'update',
|
||||
$prefix . '_delete' => 'delete'
|
||||
));
|
||||
}
|
||||
}
|
||||
$this->_set($settings);
|
||||
if (Configure::read() > 0) {
|
||||
App::import('Debugger');
|
||||
Debugger::checkSecurityKeys();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main execution method. Handles redirecting of invalid users, and processing
|
||||
* of login form data.
|
||||
*
|
||||
* @param object $controller A reference to the instantiating controller object
|
||||
* @return boolean
|
||||
* @access public
|
||||
*/
|
||||
function startup(&$controller) {
|
||||
$isErrorOrTests = (
|
||||
strtolower($controller->name) == 'cakeerror' ||
|
||||
(strtolower($controller->name) == 'tests' && Configure::read() > 0)
|
||||
);
|
||||
if ($isErrorOrTests) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$methods = array_flip($controller->methods);
|
||||
$action = strtolower($controller->params['action']);
|
||||
$isMissingAction = (
|
||||
$controller->scaffold === false &&
|
||||
!isset($methods[$action])
|
||||
);
|
||||
|
||||
if ($isMissingAction) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!$this->__setDefaults()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->data = $controller->data = $this->hashPasswords($controller->data);
|
||||
$url = '';
|
||||
|
||||
if (isset($controller->params['url']['url'])) {
|
||||
$url = $controller->params['url']['url'];
|
||||
}
|
||||
$url = Router::normalize($url);
|
||||
$loginAction = Router::normalize($this->loginAction);
|
||||
|
||||
$allowedActions = array_map('strtolower', $this->allowedActions);
|
||||
$isAllowed = (
|
||||
$this->allowedActions == array('*') ||
|
||||
in_array($action, $allowedActions)
|
||||
);
|
||||
|
||||
if ($loginAction != $url && $isAllowed) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($loginAction == $url) {
|
||||
$model =& $this->getModel();
|
||||
if (empty($controller->data) || !isset($controller->data[$model->alias])) {
|
||||
if (!$this->Session->check('Auth.redirect') && !$this->loginRedirect && env('HTTP_REFERER')) {
|
||||
$this->Session->write('Auth.redirect', $controller->referer(null, true));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$isValid = !empty($controller->data[$model->alias][$this->fields['username']]) &&
|
||||
!empty($controller->data[$model->alias][$this->fields['password']]);
|
||||
|
||||
if ($isValid) {
|
||||
$username = $controller->data[$model->alias][$this->fields['username']];
|
||||
$password = $controller->data[$model->alias][$this->fields['password']];
|
||||
|
||||
$data = array(
|
||||
$model->alias . '.' . $this->fields['username'] => $username,
|
||||
$model->alias . '.' . $this->fields['password'] => $password
|
||||
);
|
||||
|
||||
if ($this->login($data)) {
|
||||
if ($this->autoRedirect) {
|
||||
$controller->redirect($this->redirect(), null, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$this->Session->setFlash($this->loginError, $this->flashElement, array(), 'auth');
|
||||
$controller->data[$model->alias][$this->fields['password']] = null;
|
||||
return false;
|
||||
} else {
|
||||
if (!$this->user()) {
|
||||
if (!$this->RequestHandler->isAjax()) {
|
||||
$this->Session->setFlash($this->authError, $this->flashElement, array(), 'auth');
|
||||
if (!empty($controller->params['url']) && count($controller->params['url']) >= 2) {
|
||||
$query = $controller->params['url'];
|
||||
unset($query['url'], $query['ext']);
|
||||
$url .= Router::queryString($query, array());
|
||||
}
|
||||
$this->Session->write('Auth.redirect', $url);
|
||||
$controller->redirect($loginAction);
|
||||
return false;
|
||||
} elseif (!empty($this->ajaxLogin)) {
|
||||
$controller->viewPath = 'elements';
|
||||
echo $controller->render($this->ajaxLogin, $this->RequestHandler->ajaxLayout);
|
||||
$this->_stop();
|
||||
return false;
|
||||
} else {
|
||||
$controller->redirect(null, 403);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->authorize) {
|
||||
return true;
|
||||
}
|
||||
|
||||
extract($this->__authType());
|
||||
switch ($type) {
|
||||
case 'controller':
|
||||
$this->object =& $controller;
|
||||
break;
|
||||
case 'crud':
|
||||
case 'actions':
|
||||
if (isset($controller->Acl)) {
|
||||
$this->Acl =& $controller->Acl;
|
||||
} else {
|
||||
trigger_error(__('Could not find AclComponent. Please include Acl in Controller::$components.', true), E_USER_WARNING);
|
||||
}
|
||||
break;
|
||||
case 'model':
|
||||
if (!isset($object)) {
|
||||
$hasModel = (
|
||||
isset($controller->{$controller->modelClass}) &&
|
||||
is_object($controller->{$controller->modelClass})
|
||||
);
|
||||
$isUses = (
|
||||
!empty($controller->uses) && isset($controller->{$controller->uses[0]}) &&
|
||||
is_object($controller->{$controller->uses[0]})
|
||||
);
|
||||
|
||||
if ($hasModel) {
|
||||
$object = $controller->modelClass;
|
||||
} elseif ($isUses) {
|
||||
$object = $controller->uses[0];
|
||||
}
|
||||
}
|
||||
$type = array('model' => $object);
|
||||
break;
|
||||
}
|
||||
|
||||
if ($this->isAuthorized($type)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->Session->setFlash($this->authError, $this->flashElement, array(), 'auth');
|
||||
$controller->redirect($controller->referer(), null, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to introspect the correct values for object properties including
|
||||
* $userModel and $sessionKey.
|
||||
*
|
||||
* @param object $controller A reference to the instantiating controller object
|
||||
* @return boolean
|
||||
* @access private
|
||||
*/
|
||||
function __setDefaults() {
|
||||
if (empty($this->userModel)) {
|
||||
trigger_error(__("Could not find \$userModel. Please set AuthComponent::\$userModel in beforeFilter().", true), E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
list($plugin, $model) = pluginSplit($this->userModel);
|
||||
$defaults = array(
|
||||
'loginAction' => array(
|
||||
'controller' => Inflector::underscore(Inflector::pluralize($model)),
|
||||
'action' => 'login',
|
||||
'plugin' => Inflector::underscore($plugin),
|
||||
),
|
||||
'sessionKey' => 'Auth.' . $model,
|
||||
'logoutRedirect' => $this->loginAction,
|
||||
'loginError' => __('Login failed. Invalid username or password.', true),
|
||||
'authError' => __('You are not authorized to access that location.', true)
|
||||
);
|
||||
foreach ($defaults as $key => $value) {
|
||||
if (empty($this->{$key})) {
|
||||
$this->{$key} = $value;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given user is authorized to perform an action. The type of
|
||||
* authorization used is based on the value of AuthComponent::$authorize or the
|
||||
* passed $type param.
|
||||
*
|
||||
* Types:
|
||||
* 'controller' will validate against Controller::isAuthorized() if controller instance is
|
||||
* passed in $object
|
||||
* 'actions' will validate Controller::action against an AclComponent::check()
|
||||
* 'crud' will validate mapActions against an AclComponent::check()
|
||||
* array('model'=> 'name'); will validate mapActions against model
|
||||
* $name::isAuthorized(user, controller, mapAction)
|
||||
* 'object' will validate Controller::action against
|
||||
* object::isAuthorized(user, controller, action)
|
||||
*
|
||||
* @param string $type Type of authorization
|
||||
* @param mixed $object object, model object, or model name
|
||||
* @param mixed $user The user to check the authorization of
|
||||
* @return boolean True if $user is authorized, otherwise false
|
||||
* @access public
|
||||
*/
|
||||
function isAuthorized($type = null, $object = null, $user = null) {
|
||||
if (empty($user) && !$this->user()) {
|
||||
return false;
|
||||
} elseif (empty($user)) {
|
||||
$user = $this->user();
|
||||
}
|
||||
|
||||
extract($this->__authType($type));
|
||||
|
||||
if (!$object) {
|
||||
$object = $this->object;
|
||||
}
|
||||
|
||||
$valid = false;
|
||||
switch ($type) {
|
||||
case 'controller':
|
||||
$valid = $object->isAuthorized();
|
||||
break;
|
||||
case 'actions':
|
||||
$valid = $this->Acl->check($user, $this->action());
|
||||
break;
|
||||
case 'crud':
|
||||
if (!isset($this->actionMap[$this->params['action']])) {
|
||||
trigger_error(
|
||||
sprintf(__('Auth::startup() - Attempted access of un-mapped action "%1$s" in controller "%2$s"', true), $this->params['action'], $this->params['controller']),
|
||||
E_USER_WARNING
|
||||
);
|
||||
} else {
|
||||
$valid = $this->Acl->check(
|
||||
$user,
|
||||
$this->action(':controller'),
|
||||
$this->actionMap[$this->params['action']]
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'model':
|
||||
$action = $this->params['action'];
|
||||
if (isset($this->actionMap[$action])) {
|
||||
$action = $this->actionMap[$action];
|
||||
}
|
||||
if (is_string($object)) {
|
||||
$object = $this->getModel($object);
|
||||
}
|
||||
case 'object':
|
||||
if (!isset($action)) {
|
||||
$action = $this->action(':action');
|
||||
}
|
||||
if (empty($object)) {
|
||||
trigger_error(sprintf(__('Could not find %s. Set AuthComponent::$object in beforeFilter() or pass a valid object', true), get_class($object)), E_USER_WARNING);
|
||||
return;
|
||||
}
|
||||
if (method_exists($object, 'isAuthorized')) {
|
||||
$valid = $object->isAuthorized($user, $this->action(':controller'), $action);
|
||||
} elseif ($object) {
|
||||
trigger_error(sprintf(__('%s::isAuthorized() is not defined.', true), get_class($object)), E_USER_WARNING);
|
||||
}
|
||||
break;
|
||||
case null:
|
||||
case false:
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
trigger_error(__('Auth::isAuthorized() - $authorize is set to an incorrect value. Allowed settings are: "actions", "crud", "model" or null.', true), E_USER_WARNING);
|
||||
break;
|
||||
}
|
||||
return $valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get authorization type
|
||||
*
|
||||
* @param string $auth Type of authorization
|
||||
* @return array Associative array with: type, object
|
||||
* @access private
|
||||
*/
|
||||
function __authType($auth = null) {
|
||||
if ($auth == null) {
|
||||
$auth = $this->authorize;
|
||||
}
|
||||
$object = null;
|
||||
if (is_array($auth)) {
|
||||
$type = key($auth);
|
||||
$object = $auth[$type];
|
||||
} else {
|
||||
$type = $auth;
|
||||
return compact('type');
|
||||
}
|
||||
return compact('type', 'object');
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a list of actions in the current controller for which authentication is not required, or
|
||||
* no parameters to allow all actions.
|
||||
*
|
||||
* @param mixed $action Controller action name or array of actions
|
||||
* @param string $action Controller action name
|
||||
* @param string ... etc.
|
||||
* @return void
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1257/allow
|
||||
*/
|
||||
function allow() {
|
||||
$args = func_get_args();
|
||||
if (empty($args) || $args == array('*')) {
|
||||
$this->allowedActions = $this->_methods;
|
||||
} else {
|
||||
if (isset($args[0]) && is_array($args[0])) {
|
||||
$args = $args[0];
|
||||
}
|
||||
$this->allowedActions = array_merge($this->allowedActions, array_map('strtolower', $args));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes items from the list of allowed actions.
|
||||
*
|
||||
* @param mixed $action Controller action name or array of actions
|
||||
* @param string $action Controller action name
|
||||
* @param string ... etc.
|
||||
* @return void
|
||||
* @see AuthComponent::allow()
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1258/deny
|
||||
*/
|
||||
function deny() {
|
||||
$args = func_get_args();
|
||||
if (isset($args[0]) && is_array($args[0])) {
|
||||
$args = $args[0];
|
||||
}
|
||||
foreach ($args as $arg) {
|
||||
$i = array_search(strtolower($arg), $this->allowedActions);
|
||||
if (is_int($i)) {
|
||||
unset($this->allowedActions[$i]);
|
||||
}
|
||||
}
|
||||
$this->allowedActions = array_values($this->allowedActions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps action names to CRUD operations. Used for controller-based authentication.
|
||||
*
|
||||
* @param array $map Actions to map
|
||||
* @return void
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1260/mapActions
|
||||
*/
|
||||
function mapActions($map = array()) {
|
||||
$crud = array('create', 'read', 'update', 'delete');
|
||||
foreach ($map as $action => $type) {
|
||||
if (in_array($action, $crud) && is_array($type)) {
|
||||
foreach ($type as $typedAction) {
|
||||
$this->actionMap[$typedAction] = $action;
|
||||
}
|
||||
} else {
|
||||
$this->actionMap[$action] = $type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually log-in a user with the given parameter data. The $data provided can be any data
|
||||
* structure used to identify a user in AuthComponent::identify(). If $data is empty or not
|
||||
* specified, POST data from Controller::$data will be used automatically.
|
||||
*
|
||||
* After (if) login is successful, the user record is written to the session key specified in
|
||||
* AuthComponent::$sessionKey.
|
||||
*
|
||||
* @param mixed $data User object
|
||||
* @return boolean True on login success, false on failure
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1261/login
|
||||
*/
|
||||
function login($data = null) {
|
||||
$this->__setDefaults();
|
||||
$this->_loggedIn = false;
|
||||
|
||||
if (empty($data)) {
|
||||
$data = $this->data;
|
||||
}
|
||||
|
||||
if ($user = $this->identify($data)) {
|
||||
$this->Session->write($this->sessionKey, $user);
|
||||
$this->_loggedIn = true;
|
||||
}
|
||||
return $this->_loggedIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a user out, and returns the login action to redirect to.
|
||||
*
|
||||
* @param mixed $url Optional URL to redirect the user to after logout
|
||||
* @return string AuthComponent::$loginAction
|
||||
* @see AuthComponent::$loginAction
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1262/logout
|
||||
*/
|
||||
function logout() {
|
||||
$this->__setDefaults();
|
||||
$this->Session->delete($this->sessionKey);
|
||||
$this->Session->delete('Auth.redirect');
|
||||
$this->_loggedIn = false;
|
||||
return Router::normalize($this->logoutRedirect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current user from the session.
|
||||
*
|
||||
* @param string $key field to retrive. Leave null to get entire User record
|
||||
* @return mixed User record. or null if no user is logged in.
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1264/user
|
||||
*/
|
||||
function user($key = null) {
|
||||
$this->__setDefaults();
|
||||
if (!$this->Session->check($this->sessionKey)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($key == null) {
|
||||
$model =& $this->getModel();
|
||||
return array($model->alias => $this->Session->read($this->sessionKey));
|
||||
} else {
|
||||
$user = $this->Session->read($this->sessionKey);
|
||||
if (isset($user[$key])) {
|
||||
return $user[$key];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If no parameter is passed, gets the authentication redirect URL.
|
||||
*
|
||||
* @param mixed $url Optional URL to write as the login redirect URL.
|
||||
* @return string Redirect URL
|
||||
* @access public
|
||||
*/
|
||||
function redirect($url = null) {
|
||||
if (!is_null($url)) {
|
||||
$redir = $url;
|
||||
$this->Session->write('Auth.redirect', $redir);
|
||||
} elseif ($this->Session->check('Auth.redirect')) {
|
||||
$redir = $this->Session->read('Auth.redirect');
|
||||
$this->Session->delete('Auth.redirect');
|
||||
|
||||
if (Router::normalize($redir) == Router::normalize($this->loginAction)) {
|
||||
$redir = $this->loginRedirect;
|
||||
}
|
||||
} else {
|
||||
$redir = $this->loginRedirect;
|
||||
}
|
||||
return Router::normalize($redir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a user against an abstract object.
|
||||
*
|
||||
* @param mixed $object The object to validate the user against.
|
||||
* @param mixed $user Optional. The identity of the user to be validated.
|
||||
* Uses the current user session if none specified. For
|
||||
* valid forms of identifying users, see
|
||||
* AuthComponent::identify().
|
||||
* @param string $action Optional. The action to validate against.
|
||||
* @see AuthComponent::identify()
|
||||
* @return boolean True if the user validates, false otherwise.
|
||||
* @access public
|
||||
*/
|
||||
function validate($object, $user = null, $action = null) {
|
||||
if (empty($user)) {
|
||||
$user = $this->user();
|
||||
}
|
||||
if (empty($user)) {
|
||||
return false;
|
||||
}
|
||||
return $this->Acl->check($user, $object, $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the ACO node bound to a controller/action.
|
||||
*
|
||||
* @param string $action Optional. The controller/action path to validate the
|
||||
* user against. The current request action is used if
|
||||
* none is specified.
|
||||
* @return boolean ACO node path
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1256/action
|
||||
*/
|
||||
function action($action = ':plugin/:controller/:action') {
|
||||
$plugin = empty($this->params['plugin']) ? null : Inflector::camelize($this->params['plugin']) . '/';
|
||||
return str_replace(
|
||||
array(':controller', ':action', ':plugin/'),
|
||||
array(Inflector::camelize($this->params['controller']), $this->params['action'], $plugin),
|
||||
$this->actionPath . $action
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the model object specified, and attempts
|
||||
* to load it if it is not found.
|
||||
*
|
||||
* @param string $name Model name (defaults to AuthComponent::$userModel)
|
||||
* @return object A reference to a model object
|
||||
* @access public
|
||||
*/
|
||||
function &getModel($name = null) {
|
||||
$model = null;
|
||||
if (!$name) {
|
||||
$name = $this->userModel;
|
||||
}
|
||||
|
||||
if (PHP5) {
|
||||
$model = ClassRegistry::init($name);
|
||||
} else {
|
||||
$model =& ClassRegistry::init($name);
|
||||
}
|
||||
|
||||
if (empty($model)) {
|
||||
trigger_error(__('Auth::getModel() - Model is not set or could not be found', true), E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies a user based on specific criteria.
|
||||
*
|
||||
* @param mixed $user Optional. The identity of the user to be validated.
|
||||
* Uses the current user session if none specified.
|
||||
* @param array $conditions Optional. Additional conditions to a find.
|
||||
* @return array User record data, or null, if the user could not be identified.
|
||||
* @access public
|
||||
*/
|
||||
function identify($user = null, $conditions = null) {
|
||||
if ($conditions === false) {
|
||||
$conditions = null;
|
||||
} elseif (is_array($conditions)) {
|
||||
$conditions = array_merge((array)$this->userScope, $conditions);
|
||||
} else {
|
||||
$conditions = $this->userScope;
|
||||
}
|
||||
$model =& $this->getModel();
|
||||
if (empty($user)) {
|
||||
$user = $this->user();
|
||||
if (empty($user)) {
|
||||
return null;
|
||||
}
|
||||
} elseif (is_object($user) && is_a($user, 'Model')) {
|
||||
if (!$user->exists()) {
|
||||
return null;
|
||||
}
|
||||
$user = $user->read();
|
||||
$user = $user[$model->alias];
|
||||
} elseif (is_array($user) && isset($user[$model->alias])) {
|
||||
$user = $user[$model->alias];
|
||||
}
|
||||
|
||||
if (is_array($user) && (isset($user[$this->fields['username']]) || isset($user[$model->alias . '.' . $this->fields['username']]))) {
|
||||
if (isset($user[$this->fields['username']]) && !empty($user[$this->fields['username']]) && !empty($user[$this->fields['password']])) {
|
||||
if (trim($user[$this->fields['username']]) == '=' || trim($user[$this->fields['password']]) == '=') {
|
||||
return false;
|
||||
}
|
||||
$find = array(
|
||||
$model->alias.'.'.$this->fields['username'] => $user[$this->fields['username']],
|
||||
$model->alias.'.'.$this->fields['password'] => $user[$this->fields['password']]
|
||||
);
|
||||
} elseif (isset($user[$model->alias . '.' . $this->fields['username']]) && !empty($user[$model->alias . '.' . $this->fields['username']])) {
|
||||
if (trim($user[$model->alias . '.' . $this->fields['username']]) == '=' || trim($user[$model->alias . '.' . $this->fields['password']]) == '=') {
|
||||
return false;
|
||||
}
|
||||
$find = array(
|
||||
$model->alias.'.'.$this->fields['username'] => $user[$model->alias . '.' . $this->fields['username']],
|
||||
$model->alias.'.'.$this->fields['password'] => $user[$model->alias . '.' . $this->fields['password']]
|
||||
);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
$data = $model->find('first', array(
|
||||
'conditions' => array_merge($find, $conditions),
|
||||
'recursive' => 0
|
||||
));
|
||||
if (empty($data) || empty($data[$model->alias])) {
|
||||
return null;
|
||||
}
|
||||
} elseif (!empty($user) && is_string($user)) {
|
||||
$data = $model->find('first', array(
|
||||
'conditions' => array_merge(array($model->escapeField() => $user), $conditions),
|
||||
));
|
||||
if (empty($data) || empty($data[$model->alias])) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($data)) {
|
||||
if (!empty($data[$model->alias][$this->fields['password']])) {
|
||||
unset($data[$model->alias][$this->fields['password']]);
|
||||
}
|
||||
return $data[$model->alias];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash any passwords found in $data using $userModel and $fields['password']
|
||||
*
|
||||
* @param array $data Set of data to look for passwords
|
||||
* @return array Data with passwords hashed
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1259/hashPasswords
|
||||
*/
|
||||
function hashPasswords($data) {
|
||||
if (is_object($this->authenticate) && method_exists($this->authenticate, 'hashPasswords')) {
|
||||
return $this->authenticate->hashPasswords($data);
|
||||
}
|
||||
|
||||
if (is_array($data)) {
|
||||
$model =& $this->getModel();
|
||||
|
||||
if(isset($data[$model->alias])) {
|
||||
if (isset($data[$model->alias][$this->fields['username']]) && isset($data[$model->alias][$this->fields['password']])) {
|
||||
$data[$model->alias][$this->fields['password']] = $this->password($data[$model->alias][$this->fields['password']]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash a password with the application's salt value (as defined with Configure::write('Security.salt');
|
||||
*
|
||||
* @param string $password Password to hash
|
||||
* @return string Hashed password
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1263/password
|
||||
*/
|
||||
function password($password) {
|
||||
return Security::hash($password, null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Component shutdown. If user is logged in, wipe out redirect.
|
||||
*
|
||||
* @param object $controller Instantiating controller
|
||||
* @access public
|
||||
*/
|
||||
function shutdown(&$controller) {
|
||||
if ($this->_loggedIn) {
|
||||
$this->Session->delete('Auth.redirect');
|
||||
}
|
||||
}
|
||||
}
|
471
web-cake/html/cake/libs/controller/components/cookie.php
Normal file
471
web-cake/html/cake/libs/controller/components/cookie.php
Normal file
@@ -0,0 +1,471 @@
|
||||
<?php
|
||||
/**
|
||||
* Cookie Component
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller.components
|
||||
* @since CakePHP(tm) v 1.2.0.4213
|
||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Load Security class
|
||||
*/
|
||||
App::import('Core', 'Security');
|
||||
|
||||
/**
|
||||
* Cookie Component.
|
||||
*
|
||||
* Cookie handling for the controller.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller.components
|
||||
* @link http://book.cakephp.org/view/1280/Cookies
|
||||
*
|
||||
*/
|
||||
class CookieComponent extends Object {
|
||||
|
||||
/**
|
||||
* The name of the cookie.
|
||||
*
|
||||
* Overridden with the controller beforeFilter();
|
||||
* $this->Cookie->name = 'CookieName';
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $name = 'CakeCookie';
|
||||
|
||||
/**
|
||||
* The time a cookie will remain valid.
|
||||
*
|
||||
* Can be either integer Unix timestamp or a date string.
|
||||
*
|
||||
* Overridden with the controller beforeFilter();
|
||||
* $this->Cookie->time = '5 Days';
|
||||
*
|
||||
* @var mixed
|
||||
* @access public
|
||||
*/
|
||||
var $time = null;
|
||||
|
||||
/**
|
||||
* Cookie path.
|
||||
*
|
||||
* Overridden with the controller beforeFilter();
|
||||
* $this->Cookie->path = '/';
|
||||
*
|
||||
* The path on the server in which the cookie will be available on.
|
||||
* If var $cookiePath is set to '/foo/', the cookie will only be available
|
||||
* within the /foo/ directory and all sub-directories such as /foo/bar/ of domain.
|
||||
* The default value is the entire domain.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $path = '/';
|
||||
|
||||
/**
|
||||
* Domain path.
|
||||
*
|
||||
* The domain that the cookie is available.
|
||||
*
|
||||
* Overridden with the controller beforeFilter();
|
||||
* $this->Cookie->domain = '.example.com';
|
||||
*
|
||||
* To make the cookie available on all subdomains of example.com.
|
||||
* Set $this->Cookie->domain = '.example.com'; in your controller beforeFilter
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $domain = '';
|
||||
|
||||
/**
|
||||
* Secure HTTPS only cookie.
|
||||
*
|
||||
* Overridden with the controller beforeFilter();
|
||||
* $this->Cookie->secure = true;
|
||||
*
|
||||
* Indicates that the cookie should only be transmitted over a secure HTTPS connection.
|
||||
* When set to true, the cookie will only be set if a secure connection exists.
|
||||
*
|
||||
* @var boolean
|
||||
* @access public
|
||||
*/
|
||||
var $secure = false;
|
||||
|
||||
/**
|
||||
* Encryption key.
|
||||
*
|
||||
* Overridden with the controller beforeFilter();
|
||||
* $this->Cookie->key = 'SomeRandomString';
|
||||
*
|
||||
* @var string
|
||||
* @access protected
|
||||
*/
|
||||
var $key = null;
|
||||
|
||||
/**
|
||||
* Values stored in the cookie.
|
||||
*
|
||||
* Accessed in the controller using $this->Cookie->read('Name.key');
|
||||
*
|
||||
* @see CookieComponent::read();
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $__values = array();
|
||||
|
||||
/**
|
||||
* Type of encryption to use.
|
||||
*
|
||||
* Currently only one method is available
|
||||
* Defaults to Security::cipher();
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
* @todo add additional encryption methods
|
||||
*/
|
||||
var $__type = 'cipher';
|
||||
|
||||
/**
|
||||
* Used to reset cookie time if $expire is passed to CookieComponent::write()
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $__reset = null;
|
||||
|
||||
/**
|
||||
* Expire time of the cookie
|
||||
*
|
||||
* This is controlled by CookieComponent::time;
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $__expires = 0;
|
||||
|
||||
/**
|
||||
* Main execution method.
|
||||
*
|
||||
* @param object $controller A reference to the instantiating controller object
|
||||
* @access public
|
||||
*/
|
||||
function initialize(&$controller, $settings) {
|
||||
$this->key = Configure::read('Security.salt');
|
||||
$this->_set($settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start CookieComponent for use in the controller
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
function startup() {
|
||||
$this->__expire($this->time);
|
||||
|
||||
if (isset($_COOKIE[$this->name])) {
|
||||
$this->__values = $this->__decrypt($_COOKIE[$this->name]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a value to the $_COOKIE[$key];
|
||||
*
|
||||
* Optional [Name.], reguired key, optional $value, optional $encrypt, optional $expires
|
||||
* $this->Cookie->write('[Name.]key, $value);
|
||||
*
|
||||
* By default all values are encrypted.
|
||||
* You must pass $encrypt false to store values in clear test
|
||||
*
|
||||
* You must use this method before any output is sent to the browser.
|
||||
* Failure to do so will result in header already sent errors.
|
||||
*
|
||||
* @param mixed $key Key for the value
|
||||
* @param mixed $value Value
|
||||
* @param boolean $encrypt Set to true to encrypt value, false otherwise
|
||||
* @param string $expires Can be either Unix timestamp, or date string
|
||||
* @access public
|
||||
*/
|
||||
function write($key, $value = null, $encrypt = true, $expires = null) {
|
||||
if (is_null($encrypt)) {
|
||||
$encrypt = true;
|
||||
}
|
||||
$this->__encrypted = $encrypt;
|
||||
$this->__expire($expires);
|
||||
|
||||
if (!is_array($key)) {
|
||||
$key = array($key => $value);
|
||||
}
|
||||
|
||||
foreach ($key as $name => $value) {
|
||||
if (strpos($name, '.') === false) {
|
||||
$this->__values[$name] = $value;
|
||||
$this->__write("[$name]", $value);
|
||||
|
||||
} else {
|
||||
$names = explode('.', $name, 2);
|
||||
if (!isset($this->__values[$names[0]])) {
|
||||
$this->__values[$names[0]] = array();
|
||||
}
|
||||
$this->__values[$names[0]] = Set::insert($this->__values[$names[0]], $names[1], $value);
|
||||
$this->__write('[' . implode('][', $names) . ']', $value);
|
||||
}
|
||||
}
|
||||
$this->__encrypted = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the value of the $_COOKIE[$key];
|
||||
*
|
||||
* Optional [Name.], reguired key
|
||||
* $this->Cookie->read(Name.key);
|
||||
*
|
||||
* @param mixed $key Key of the value to be obtained. If none specified, obtain map key => values
|
||||
* @return string or null, value for specified key
|
||||
* @access public
|
||||
*/
|
||||
function read($key = null) {
|
||||
if (empty($this->__values) && isset($_COOKIE[$this->name])) {
|
||||
$this->__values = $this->__decrypt($_COOKIE[$this->name]);
|
||||
}
|
||||
|
||||
if (is_null($key)) {
|
||||
return $this->__values;
|
||||
}
|
||||
|
||||
if (strpos($key, '.') !== false) {
|
||||
$names = explode('.', $key, 2);
|
||||
$key = $names[0];
|
||||
}
|
||||
if (!isset($this->__values[$key])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!empty($names[1])) {
|
||||
return Set::extract($this->__values[$key], $names[1]);
|
||||
}
|
||||
return $this->__values[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a cookie value
|
||||
*
|
||||
* Optional [Name.], reguired key
|
||||
* $this->Cookie->read('Name.key);
|
||||
*
|
||||
* You must use this method before any output is sent to the browser.
|
||||
* Failure to do so will result in header already sent errors.
|
||||
*
|
||||
* @param string $key Key of the value to be deleted
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function delete($key) {
|
||||
if (empty($this->__values)) {
|
||||
$this->read();
|
||||
}
|
||||
if (strpos($key, '.') === false) {
|
||||
unset($this->__values[$key]);
|
||||
$this->__delete("[$key]");
|
||||
return;
|
||||
}
|
||||
$names = explode('.', $key, 2);
|
||||
$this->__values[$names[0]] = Set::remove($this->__values[$names[0]], $names[1]);
|
||||
$this->__delete('[' . implode('][', $names) . ']');
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy current cookie
|
||||
*
|
||||
* You must use this method before any output is sent to the browser.
|
||||
* Failure to do so will result in header already sent errors.
|
||||
*
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function destroy() {
|
||||
if (isset($_COOKIE[$this->name])) {
|
||||
$this->__values = $this->__decrypt($_COOKIE[$this->name]);
|
||||
}
|
||||
|
||||
foreach ($this->__values as $name => $value) {
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $key => $val) {
|
||||
unset($this->__values[$name][$key]);
|
||||
$this->__delete("[$name][$key]");
|
||||
}
|
||||
}
|
||||
unset($this->__values[$name]);
|
||||
$this->__delete("[$name]");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Will allow overriding default encryption method.
|
||||
*
|
||||
* @param string $type Encryption method
|
||||
* @access public
|
||||
* @todo NOT IMPLEMENTED
|
||||
*/
|
||||
function type($type = 'cipher') {
|
||||
$this->__type = 'cipher';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the expire time for a session variable.
|
||||
*
|
||||
* Creates a new expire time for a session variable.
|
||||
* $expire can be either integer Unix timestamp or a date string.
|
||||
*
|
||||
* Used by write()
|
||||
* CookieComponent::write(string, string, boolean, 8400);
|
||||
* CookieComponent::write(string, string, boolean, '5 Days');
|
||||
*
|
||||
* @param mixed $expires Can be either Unix timestamp, or date string
|
||||
* @return int Unix timestamp
|
||||
* @access private
|
||||
*/
|
||||
function __expire($expires = null) {
|
||||
$now = time();
|
||||
if (is_null($expires)) {
|
||||
return $this->__expires;
|
||||
}
|
||||
$this->__reset = $this->__expires;
|
||||
|
||||
if ($expires == 0) {
|
||||
return $this->__expires = 0;
|
||||
}
|
||||
|
||||
if (is_integer($expires) || is_numeric($expires)) {
|
||||
return $this->__expires = $now + intval($expires);
|
||||
}
|
||||
return $this->__expires = strtotime($expires, $now);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cookie
|
||||
*
|
||||
* @param string $name Name for cookie
|
||||
* @param string $value Value for cookie
|
||||
* @access private
|
||||
*/
|
||||
function __write($name, $value) {
|
||||
setcookie($this->name . $name, $this->__encrypt($value), $this->__expires, $this->path, $this->domain, $this->secure);
|
||||
|
||||
if (!is_null($this->__reset)) {
|
||||
$this->__expires = $this->__reset;
|
||||
$this->__reset = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a cookie expire time to remove cookie value
|
||||
*
|
||||
* @param string $name Name of cookie
|
||||
* @access private
|
||||
*/
|
||||
function __delete($name) {
|
||||
setcookie($this->name . $name, '', time() - 42000, $this->path, $this->domain, $this->secure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts $value using var $type method in Security class
|
||||
*
|
||||
* @param string $value Value to encrypt
|
||||
* @return string encrypted string
|
||||
* @access private
|
||||
*/
|
||||
function __encrypt($value) {
|
||||
if (is_array($value)) {
|
||||
$value = $this->__implode($value);
|
||||
}
|
||||
|
||||
if ($this->__encrypted === true) {
|
||||
$type = $this->__type;
|
||||
$value = "Q2FrZQ==." .base64_encode(Security::$type($value, $this->key));
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts $value using var $type method in Security class
|
||||
*
|
||||
* @param array $values Values to decrypt
|
||||
* @return string decrypted string
|
||||
* @access private
|
||||
*/
|
||||
function __decrypt($values) {
|
||||
$decrypted = array();
|
||||
$type = $this->__type;
|
||||
|
||||
foreach ($values as $name => $value) {
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $key => $val) {
|
||||
$pos = strpos($val, 'Q2FrZQ==.');
|
||||
$decrypted[$name][$key] = $this->__explode($val);
|
||||
|
||||
if ($pos !== false) {
|
||||
$val = substr($val, 8);
|
||||
$decrypted[$name][$key] = $this->__explode(Security::$type(base64_decode($val), $this->key));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$pos = strpos($value, 'Q2FrZQ==.');
|
||||
$decrypted[$name] = $this->__explode($value);
|
||||
|
||||
if ($pos !== false) {
|
||||
$value = substr($value, 8);
|
||||
$decrypted[$name] = $this->__explode(Security::$type(base64_decode($value), $this->key));
|
||||
}
|
||||
}
|
||||
}
|
||||
return $decrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implode method to keep keys are multidimensional arrays
|
||||
*
|
||||
* @param array $array Map of key and values
|
||||
* @return string String in the form key1|value1,key2|value2
|
||||
* @access private
|
||||
*/
|
||||
function __implode($array) {
|
||||
$string = '';
|
||||
foreach ($array as $key => $value) {
|
||||
$string .= ',' . $key . '|' . $value;
|
||||
}
|
||||
return substr($string, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Explode method to return array from string set in CookieComponent::__implode()
|
||||
*
|
||||
* @param string $string String in the form key1|value1,key2|value2
|
||||
* @return array Map of key and values
|
||||
* @access private
|
||||
*/
|
||||
function __explode($string) {
|
||||
$array = array();
|
||||
foreach (explode(',', $string) as $pair) {
|
||||
$key = explode('|', $pair);
|
||||
if (!isset($key[1])) {
|
||||
return $key[0];
|
||||
}
|
||||
$array[$key[0]] = $key[1];
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
}
|
962
web-cake/html/cake/libs/controller/components/email.php
Executable file
962
web-cake/html/cake/libs/controller/components/email.php
Executable file
@@ -0,0 +1,962 @@
|
||||
<?php
|
||||
/**
|
||||
* Email Component
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller.components
|
||||
* @since CakePHP(tm) v 1.2.0.3467
|
||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
App::import('Core', 'Multibyte');
|
||||
|
||||
/**
|
||||
* EmailComponent
|
||||
*
|
||||
* This component is used for handling Internet Message Format based
|
||||
* based on the standard outlined in http://www.rfc-editor.org/rfc/rfc2822.txt
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller.components
|
||||
* @link http://book.cakephp.org/view/1283/Email
|
||||
*
|
||||
*/
|
||||
class EmailComponent extends Object{
|
||||
|
||||
/**
|
||||
* Recipient of the email
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $to = null;
|
||||
|
||||
/**
|
||||
* The mail which the email is sent from
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $from = null;
|
||||
|
||||
/**
|
||||
* The email the recipient will reply to
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $replyTo = null;
|
||||
|
||||
/**
|
||||
* The read receipt email
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $readReceipt = null;
|
||||
|
||||
/**
|
||||
* The mail that will be used in case of any errors like
|
||||
* - Remote mailserver down
|
||||
* - Remote user has exceeded his quota
|
||||
* - Unknown user
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $return = null;
|
||||
|
||||
/**
|
||||
* Carbon Copy
|
||||
*
|
||||
* List of email's that should receive a copy of the email.
|
||||
* The Recipient WILL be able to see this list
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $cc = array();
|
||||
|
||||
/**
|
||||
* Blind Carbon Copy
|
||||
*
|
||||
* List of email's that should receive a copy of the email.
|
||||
* The Recipient WILL NOT be able to see this list
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $bcc = array();
|
||||
|
||||
/**
|
||||
* The subject of the email
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $subject = null;
|
||||
|
||||
/**
|
||||
* Associative array of a user defined headers
|
||||
* Keys will be prefixed 'X-' as per RFC2822 Section 4.7.5
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $headers = array();
|
||||
|
||||
/**
|
||||
* List of additional headers
|
||||
*
|
||||
* These will NOT be used if you are using safemode and mail()
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $additionalParams = null;
|
||||
|
||||
/**
|
||||
* Layout for the View
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $layout = 'default';
|
||||
|
||||
/**
|
||||
* Template for the view
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $template = null;
|
||||
|
||||
/**
|
||||
* as per RFC2822 Section 2.1.1
|
||||
*
|
||||
* @var integer
|
||||
* @access public
|
||||
*/
|
||||
var $lineLength = 70;
|
||||
|
||||
/**
|
||||
* @deprecated see lineLength
|
||||
*/
|
||||
var $_lineLength = null;
|
||||
|
||||
/**
|
||||
* What format should the email be sent in
|
||||
*
|
||||
* Supported formats:
|
||||
* - text
|
||||
* - html
|
||||
* - both
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $sendAs = 'text';
|
||||
|
||||
/**
|
||||
* What method should the email be sent by
|
||||
*
|
||||
* Supported methods:
|
||||
* - mail
|
||||
* - smtp
|
||||
* - debug
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $delivery = 'mail';
|
||||
|
||||
/**
|
||||
* charset the email is sent in
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $charset = 'utf-8';
|
||||
|
||||
/**
|
||||
* List of files that should be attached to the email.
|
||||
*
|
||||
* Can be both absolute and relative paths
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $attachments = array();
|
||||
|
||||
/**
|
||||
* What mailer should EmailComponent identify itself as
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $xMailer = 'CakePHP Email Component';
|
||||
|
||||
/**
|
||||
* The list of paths to search if an attachment isnt absolute
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $filePaths = array();
|
||||
|
||||
/**
|
||||
* List of options to use for smtp mail method
|
||||
*
|
||||
* Options is:
|
||||
* - port
|
||||
* - host
|
||||
* - timeout
|
||||
* - username
|
||||
* - password
|
||||
* - client
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1290/Sending-A-Message-Using-SMTP
|
||||
*/
|
||||
var $smtpOptions = array();
|
||||
|
||||
/**
|
||||
* Placeholder for any errors that might happen with the
|
||||
* smtp mail methods
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $smtpError = null;
|
||||
|
||||
/**
|
||||
* Contains the rendered plain text message if one was sent.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $textMessage = null;
|
||||
|
||||
/**
|
||||
* Contains the rendered HTML message if one was sent.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $htmlMessage = null;
|
||||
|
||||
/**
|
||||
* Whether to generate a Message-ID header for the
|
||||
* e-mail. True to generate a Message-ID, False to let
|
||||
* it be handled by sendmail (or similar) or a string
|
||||
* to completely override the Message-ID.
|
||||
*
|
||||
* @var mixed
|
||||
* @access public
|
||||
*/
|
||||
var $messageId = true;
|
||||
|
||||
/**
|
||||
* Temporary store of message header lines
|
||||
*
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
var $__header = array();
|
||||
|
||||
/**
|
||||
* If set, boundary to use for multipart mime messages
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $__boundary = null;
|
||||
|
||||
/**
|
||||
* Temporary store of message lines
|
||||
*
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
var $__message = array();
|
||||
|
||||
/**
|
||||
* Variable that holds SMTP connection
|
||||
*
|
||||
* @var resource
|
||||
* @access private
|
||||
*/
|
||||
var $__smtpConnection = null;
|
||||
|
||||
/**
|
||||
* Initialize component
|
||||
*
|
||||
* @param object $controller Instantiating controller
|
||||
* @access public
|
||||
*/
|
||||
function initialize(&$controller, $settings = array()) {
|
||||
$this->Controller =& $controller;
|
||||
if (Configure::read('App.encoding') !== null) {
|
||||
$this->charset = Configure::read('App.encoding');
|
||||
}
|
||||
$this->_set($settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Startup component
|
||||
*
|
||||
* @param object $controller Instantiating controller
|
||||
* @access public
|
||||
*/
|
||||
function startup(&$controller) {}
|
||||
|
||||
/**
|
||||
* Send an email using the specified content, template and layout
|
||||
*
|
||||
* @param mixed $content Either an array of text lines, or a string with contents
|
||||
* If you are rendering a template this variable will be sent to the templates as `$content`
|
||||
* @param string $template Template to use when sending email
|
||||
* @param string $layout Layout to use to enclose email body
|
||||
* @return boolean Success
|
||||
* @access public
|
||||
*/
|
||||
function send($content = null, $template = null, $layout = null) {
|
||||
$this->_createHeader();
|
||||
|
||||
if ($template) {
|
||||
$this->template = $template;
|
||||
}
|
||||
|
||||
if ($layout) {
|
||||
$this->layout = $layout;
|
||||
}
|
||||
|
||||
if (is_array($content)) {
|
||||
$content = implode("\n", $content) . "\n";
|
||||
}
|
||||
|
||||
$this->htmlMessage = $this->textMessage = null;
|
||||
if ($content) {
|
||||
if ($this->sendAs === 'html') {
|
||||
$this->htmlMessage = $content;
|
||||
} elseif ($this->sendAs === 'text') {
|
||||
$this->textMessage = $content;
|
||||
} else {
|
||||
$this->htmlMessage = $this->textMessage = $content;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->sendAs === 'text') {
|
||||
$message = $this->_wrap($content);
|
||||
} else {
|
||||
$message = $this->_wrap($content, 998);
|
||||
}
|
||||
|
||||
if ($this->template === null) {
|
||||
$message = $this->_formatMessage($message);
|
||||
} else {
|
||||
$message = $this->_render($message);
|
||||
}
|
||||
|
||||
$message[] = '';
|
||||
$this->__message = $message;
|
||||
|
||||
if (!empty($this->attachments)) {
|
||||
$this->_attachFiles();
|
||||
}
|
||||
|
||||
if (!is_null($this->__boundary)) {
|
||||
$this->__message[] = '';
|
||||
$this->__message[] = '--' . $this->__boundary . '--';
|
||||
$this->__message[] = '';
|
||||
}
|
||||
|
||||
|
||||
$_method = '_' . $this->delivery;
|
||||
$sent = $this->$_method();
|
||||
|
||||
$this->__header = array();
|
||||
$this->__message = array();
|
||||
|
||||
return $sent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all EmailComponent internal variables to be able to send out a new email.
|
||||
*
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1285/Sending-Multiple-Emails-in-a-loop
|
||||
*/
|
||||
function reset() {
|
||||
$this->template = null;
|
||||
$this->to = array();
|
||||
$this->from = null;
|
||||
$this->replyTo = null;
|
||||
$this->return = null;
|
||||
$this->cc = array();
|
||||
$this->bcc = array();
|
||||
$this->subject = null;
|
||||
$this->additionalParams = null;
|
||||
$this->smtpError = null;
|
||||
$this->attachments = array();
|
||||
$this->htmlMessage = null;
|
||||
$this->textMessage = null;
|
||||
$this->messageId = true;
|
||||
$this->__header = array();
|
||||
$this->__boundary = null;
|
||||
$this->__message = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the contents using the current layout and template.
|
||||
*
|
||||
* @param string $content Content to render
|
||||
* @return array Email ready to be sent
|
||||
* @access private
|
||||
*/
|
||||
function _render($content) {
|
||||
$viewClass = $this->Controller->view;
|
||||
|
||||
if ($viewClass != 'View') {
|
||||
list($plugin, $viewClass) = pluginSplit($viewClass);
|
||||
$viewClass = $viewClass . 'View';
|
||||
App::import('View', $this->Controller->view);
|
||||
}
|
||||
|
||||
$View = new $viewClass($this->Controller, false);
|
||||
$View->layout = $this->layout;
|
||||
$msg = array();
|
||||
|
||||
$content = implode("\n", $content);
|
||||
|
||||
if ($this->sendAs === 'both') {
|
||||
$htmlContent = $content;
|
||||
if (!empty($this->attachments)) {
|
||||
$msg[] = '--' . $this->__boundary;
|
||||
$msg[] = 'Content-Type: multipart/alternative; boundary="alt-' . $this->__boundary . '"';
|
||||
$msg[] = '';
|
||||
}
|
||||
$msg[] = '--alt-' . $this->__boundary;
|
||||
$msg[] = 'Content-Type: text/plain; charset=' . $this->charset;
|
||||
$msg[] = 'Content-Transfer-Encoding: 7bit';
|
||||
$msg[] = '';
|
||||
|
||||
$content = $View->element('email' . DS . 'text' . DS . $this->template, array('content' => $content), true);
|
||||
$View->layoutPath = 'email' . DS . 'text';
|
||||
$content = explode("\n", $this->textMessage = str_replace(array("\r\n", "\r"), "\n", $View->renderLayout($content)));
|
||||
|
||||
$msg = array_merge($msg, $content);
|
||||
|
||||
$msg[] = '';
|
||||
$msg[] = '--alt-' . $this->__boundary;
|
||||
$msg[] = 'Content-Type: text/html; charset=' . $this->charset;
|
||||
$msg[] = 'Content-Transfer-Encoding: 7bit';
|
||||
$msg[] = '';
|
||||
|
||||
$htmlContent = $View->element('email' . DS . 'html' . DS . $this->template, array('content' => $htmlContent), true);
|
||||
$View->layoutPath = 'email' . DS . 'html';
|
||||
$htmlContent = explode("\n", $this->htmlMessage = str_replace(array("\r\n", "\r"), "\n", $View->renderLayout($htmlContent)));
|
||||
$msg = array_merge($msg, $htmlContent);
|
||||
$msg[] = '';
|
||||
$msg[] = '--alt-' . $this->__boundary . '--';
|
||||
$msg[] = '';
|
||||
|
||||
return $msg;
|
||||
}
|
||||
|
||||
if (!empty($this->attachments)) {
|
||||
if ($this->sendAs === 'html') {
|
||||
$msg[] = '';
|
||||
$msg[] = '--' . $this->__boundary;
|
||||
$msg[] = 'Content-Type: text/html; charset=' . $this->charset;
|
||||
$msg[] = 'Content-Transfer-Encoding: 7bit';
|
||||
$msg[] = '';
|
||||
} else {
|
||||
$msg[] = '--' . $this->__boundary;
|
||||
$msg[] = 'Content-Type: text/plain; charset=' . $this->charset;
|
||||
$msg[] = 'Content-Transfer-Encoding: 7bit';
|
||||
$msg[] = '';
|
||||
}
|
||||
}
|
||||
|
||||
$content = $View->element('email' . DS . $this->sendAs . DS . $this->template, array('content' => $content), true);
|
||||
$View->layoutPath = 'email' . DS . $this->sendAs;
|
||||
$content = explode("\n", $rendered = str_replace(array("\r\n", "\r"), "\n", $View->renderLayout($content)));
|
||||
|
||||
if ($this->sendAs === 'html') {
|
||||
$this->htmlMessage = $rendered;
|
||||
} else {
|
||||
$this->textMessage = $rendered;
|
||||
}
|
||||
|
||||
$msg = array_merge($msg, $content);
|
||||
|
||||
return $msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create unique boundary identifier
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
function _createboundary() {
|
||||
$this->__boundary = md5(uniqid(time()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets headers for the message
|
||||
*
|
||||
* @access public
|
||||
* @param array Associative array containing headers to be set.
|
||||
*/
|
||||
function header($headers) {
|
||||
foreach ($headers as $header => $value) {
|
||||
$this->__header[] = sprintf('%s: %s', trim($header), trim($value));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Create emails headers including (but not limited to) from email address, reply to,
|
||||
* bcc and cc.
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
function _createHeader() {
|
||||
$headers = array();
|
||||
|
||||
if ($this->delivery == 'smtp') {
|
||||
if (is_array($this->to)) {
|
||||
$headers['To'] = implode(', ', array_map(array($this, '_formatAddress'), $this->to));
|
||||
} else {
|
||||
$headers['To'] = $this->_formatAddress($this->to);
|
||||
}
|
||||
}
|
||||
$headers['From'] = $this->_formatAddress($this->from);
|
||||
|
||||
if (!empty($this->replyTo)) {
|
||||
$headers['Reply-To'] = $this->_formatAddress($this->replyTo);
|
||||
}
|
||||
if (!empty($this->return)) {
|
||||
$headers['Return-Path'] = $this->_formatAddress($this->return);
|
||||
}
|
||||
if (!empty($this->readReceipt)) {
|
||||
$headers['Disposition-Notification-To'] = $this->_formatAddress($this->readReceipt);
|
||||
}
|
||||
|
||||
if (!empty($this->cc)) {
|
||||
$headers['cc'] = implode(', ', array_map(array($this, '_formatAddress'), $this->cc));
|
||||
}
|
||||
|
||||
if (!empty($this->bcc) && $this->delivery != 'smtp') {
|
||||
$headers['Bcc'] = implode(', ', array_map(array($this, '_formatAddress'), $this->bcc));
|
||||
}
|
||||
if ($this->delivery == 'smtp') {
|
||||
$headers['Subject'] = $this->_encode($this->subject);
|
||||
}
|
||||
|
||||
if ($this->messageId !== false) {
|
||||
if ($this->messageId === true) {
|
||||
$headers['Message-ID'] = '<' . String::UUID() . '@' . env('HTTP_HOST') . '>';
|
||||
} else {
|
||||
$headers['Message-ID'] = $this->messageId;
|
||||
}
|
||||
}
|
||||
|
||||
$headers['X-Mailer'] = $this->xMailer;
|
||||
|
||||
if (!empty($this->headers)) {
|
||||
foreach ($this->headers as $key => $val) {
|
||||
$headers['X-' . $key] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->attachments)) {
|
||||
$this->_createBoundary();
|
||||
$headers['MIME-Version'] = '1.0';
|
||||
$headers['Content-Type'] = 'multipart/mixed; boundary="' . $this->__boundary . '"';
|
||||
$headers[] = 'This part of the E-mail should never be seen. If';
|
||||
$headers[] = 'you are reading this, consider upgrading your e-mail';
|
||||
$headers[] = 'client to a MIME-compatible client.';
|
||||
} elseif ($this->sendAs === 'text') {
|
||||
$headers['Content-Type'] = 'text/plain; charset=' . $this->charset;
|
||||
} elseif ($this->sendAs === 'html') {
|
||||
$headers['Content-Type'] = 'text/html; charset=' . $this->charset;
|
||||
} elseif ($this->sendAs === 'both') {
|
||||
$headers['Content-Type'] = 'multipart/alternative; boundary="alt-' . $this->__boundary . '"';
|
||||
}
|
||||
|
||||
$headers['Content-Transfer-Encoding'] = '7bit';
|
||||
|
||||
$this->header($headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the message by seeing if it has attachments.
|
||||
*
|
||||
* @param string $message Message to format
|
||||
* @access private
|
||||
*/
|
||||
function _formatMessage($message) {
|
||||
if (!empty($this->attachments)) {
|
||||
$prefix = array('--' . $this->__boundary);
|
||||
if ($this->sendAs === 'text') {
|
||||
$prefix[] = 'Content-Type: text/plain; charset=' . $this->charset;
|
||||
} elseif ($this->sendAs === 'html') {
|
||||
$prefix[] = 'Content-Type: text/html; charset=' . $this->charset;
|
||||
} elseif ($this->sendAs === 'both') {
|
||||
$prefix[] = 'Content-Type: multipart/alternative; boundary="alt-' . $this->__boundary . '"';
|
||||
}
|
||||
$prefix[] = 'Content-Transfer-Encoding: 7bit';
|
||||
$prefix[] = '';
|
||||
$message = array_merge($prefix, $message);
|
||||
}
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach files by adding file contents inside boundaries.
|
||||
*
|
||||
* @access private
|
||||
* @TODO: modify to use the core File class?
|
||||
*/
|
||||
function _attachFiles() {
|
||||
$files = array();
|
||||
foreach ($this->attachments as $filename => $attachment) {
|
||||
$file = $this->_findFiles($attachment);
|
||||
if (!empty($file)) {
|
||||
if (is_int($filename)) {
|
||||
$filename = basename($file);
|
||||
}
|
||||
$files[$filename] = $file;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($files as $filename => $file) {
|
||||
$handle = fopen($file, 'rb');
|
||||
$data = fread($handle, filesize($file));
|
||||
$data = chunk_split(base64_encode($data)) ;
|
||||
fclose($handle);
|
||||
|
||||
$this->__message[] = '--' . $this->__boundary;
|
||||
$this->__message[] = 'Content-Type: application/octet-stream';
|
||||
$this->__message[] = 'Content-Transfer-Encoding: base64';
|
||||
$this->__message[] = 'Content-Disposition: attachment; filename="' . basename($filename) . '"';
|
||||
$this->__message[] = '';
|
||||
$this->__message[] = $data;
|
||||
$this->__message[] = '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the specified attachment in the list of file paths
|
||||
*
|
||||
* @param string $attachment Attachment file name to find
|
||||
* @return string Path to located file
|
||||
* @access private
|
||||
*/
|
||||
function _findFiles($attachment) {
|
||||
if (file_exists($attachment)) {
|
||||
return $attachment;
|
||||
}
|
||||
foreach ($this->filePaths as $path) {
|
||||
if (file_exists($path . DS . $attachment)) {
|
||||
$file = $path . DS . $attachment;
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the message using EmailComponent::$lineLength
|
||||
*
|
||||
* @param string $message Message to wrap
|
||||
* @param integer $lineLength Max length of line
|
||||
* @return array Wrapped message
|
||||
* @access protected
|
||||
*/
|
||||
function _wrap($message, $lineLength = null) {
|
||||
$message = $this->_strip($message, true);
|
||||
$message = str_replace(array("\r\n","\r"), "\n", $message);
|
||||
$lines = explode("\n", $message);
|
||||
$formatted = array();
|
||||
|
||||
if ($this->_lineLength !== null) {
|
||||
trigger_error(__('_lineLength cannot be accessed please use lineLength', true), E_USER_WARNING);
|
||||
$this->lineLength = $this->_lineLength;
|
||||
}
|
||||
|
||||
if (!$lineLength) {
|
||||
$lineLength = $this->lineLength;
|
||||
}
|
||||
|
||||
foreach ($lines as $line) {
|
||||
if (substr($line, 0, 1) == '.') {
|
||||
$line = '.' . $line;
|
||||
}
|
||||
$formatted = array_merge($formatted, explode("\n", wordwrap($line, $lineLength, "\n", true)));
|
||||
}
|
||||
$formatted[] = '';
|
||||
return $formatted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the specified string using the current charset
|
||||
*
|
||||
* @param string $subject String to encode
|
||||
* @return string Encoded string
|
||||
* @access private
|
||||
*/
|
||||
function _encode($subject) {
|
||||
$subject = $this->_strip($subject);
|
||||
|
||||
$nl = "\r\n";
|
||||
if ($this->delivery == 'mail') {
|
||||
$nl = '';
|
||||
}
|
||||
$internalEncoding = function_exists('mb_internal_encoding');
|
||||
if ($internalEncoding) {
|
||||
$restore = mb_internal_encoding();
|
||||
mb_internal_encoding($this->charset);
|
||||
}
|
||||
$return = mb_encode_mimeheader($subject, $this->charset, 'B', $nl);
|
||||
if ($internalEncoding) {
|
||||
mb_internal_encoding($restore);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a string as an email address
|
||||
*
|
||||
* @param string $string String representing an email address
|
||||
* @return string Email address suitable for email headers or smtp pipe
|
||||
* @access private
|
||||
*/
|
||||
function _formatAddress($string, $smtp = false) {
|
||||
$hasAlias = preg_match('/((.*)\s)?<(.+)>/', $string, $matches);
|
||||
if ($smtp && $hasAlias) {
|
||||
return $this->_strip('<' . $matches[3] . '>');
|
||||
} elseif ($smtp) {
|
||||
return $this->_strip('<' . $string . '>');
|
||||
}
|
||||
if ($hasAlias && !empty($matches[2])) {
|
||||
return $this->_strip($matches[2] . ' <' . $matches[3] . '>');
|
||||
}
|
||||
return $this->_strip($string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove certain elements (such as bcc:, to:, %0a) from given value.
|
||||
* Helps prevent header injection / mainipulation on user content.
|
||||
*
|
||||
* @param string $value Value to strip
|
||||
* @param boolean $message Set to true to indicate main message content
|
||||
* @return string Stripped value
|
||||
* @access private
|
||||
*/
|
||||
function _strip($value, $message = false) {
|
||||
$search = '%0a|%0d|Content-(?:Type|Transfer-Encoding)\:';
|
||||
$search .= '|charset\=|mime-version\:|multipart/mixed|(?:[^a-z]to|b?cc)\:.*';
|
||||
|
||||
if ($message !== true) {
|
||||
$search .= '|\r|\n';
|
||||
}
|
||||
$search = '#(?:' . $search . ')#i';
|
||||
while (preg_match($search, $value)) {
|
||||
$value = preg_replace($search, '', $value);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for PHP mail function used for sending out emails
|
||||
*
|
||||
* @return bool Success
|
||||
* @access private
|
||||
*/
|
||||
function _mail() {
|
||||
$header = implode("\r\n", $this->__header);
|
||||
$message = implode("\r\n", $this->__message);
|
||||
if (is_array($this->to)) {
|
||||
$to = implode(', ', array_map(array($this, '_formatAddress'), $this->to));
|
||||
} else {
|
||||
$to = $this->to;
|
||||
}
|
||||
if (ini_get('safe_mode')) {
|
||||
return @mail($to, $this->_encode($this->subject), $message, $header);
|
||||
}
|
||||
return @mail($to, $this->_encode($this->subject), $message, $header, $this->additionalParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends out email via SMTP
|
||||
*
|
||||
* @return bool Success
|
||||
* @access private
|
||||
*/
|
||||
function _smtp() {
|
||||
App::import('Core', array('CakeSocket'));
|
||||
|
||||
$defaults = array(
|
||||
'host' => 'localhost',
|
||||
'port' => 25,
|
||||
'protocol' => 'smtp',
|
||||
'timeout' => 30
|
||||
);
|
||||
$this->smtpOptions = array_merge($defaults, $this->smtpOptions);
|
||||
$this->__smtpConnection =& new CakeSocket($this->smtpOptions);
|
||||
|
||||
if (!$this->__smtpConnection->connect()) {
|
||||
$this->smtpError = $this->__smtpConnection->lastError();
|
||||
return false;
|
||||
} elseif (!$this->_smtpSend(null, '220')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$httpHost = env('HTTP_HOST');
|
||||
|
||||
if (isset($this->smtpOptions['client'])) {
|
||||
$host = $this->smtpOptions['client'];
|
||||
} elseif (!empty($httpHost)) {
|
||||
$host = $httpHost;
|
||||
} else {
|
||||
$host = 'localhost';
|
||||
}
|
||||
|
||||
if (!$this->_smtpSend("EHLO {$host}", '250') && !$this->_smtpSend("HELO {$host}", '250')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($this->smtpOptions['username']) && isset($this->smtpOptions['password'])) {
|
||||
$authRequired = $this->_smtpSend('AUTH LOGIN', '334|503');
|
||||
if ($authRequired == '334') {
|
||||
if (!$this->_smtpSend(base64_encode($this->smtpOptions['username']), '334')) {
|
||||
return false;
|
||||
}
|
||||
if (!$this->_smtpSend(base64_encode($this->smtpOptions['password']), '235')) {
|
||||
return false;
|
||||
}
|
||||
} elseif ($authRequired != '503') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->_smtpSend('MAIL FROM: ' . $this->_formatAddress($this->from, true))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_array($this->to)) {
|
||||
$tos = array($this->to);
|
||||
} else {
|
||||
$tos = $this->to;
|
||||
}
|
||||
foreach ($tos as $to) {
|
||||
if (!$this->_smtpSend('RCPT TO: ' . $this->_formatAddress($to, true))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->cc as $cc) {
|
||||
if (!$this->_smtpSend('RCPT TO: ' . $this->_formatAddress($cc, true))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
foreach ($this->bcc as $bcc) {
|
||||
if (!$this->_smtpSend('RCPT TO: ' . $this->_formatAddress($bcc, true))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->_smtpSend('DATA', '354')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$header = implode("\r\n", $this->__header);
|
||||
$message = implode("\r\n", $this->__message);
|
||||
if (!$this->_smtpSend($header . "\r\n\r\n" . $message . "\r\n\r\n\r\n.")) {
|
||||
return false;
|
||||
}
|
||||
$this->_smtpSend('QUIT', false);
|
||||
|
||||
$this->__smtpConnection->disconnect();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected method for sending data to SMTP connection
|
||||
*
|
||||
* @param string $data data to be sent to SMTP server
|
||||
* @param mixed $checkCode code to check for in server response, false to skip
|
||||
* @return bool Success
|
||||
* @access protected
|
||||
*/
|
||||
function _smtpSend($data, $checkCode = '250') {
|
||||
if (!is_null($data)) {
|
||||
$this->__smtpConnection->write($data . "\r\n");
|
||||
}
|
||||
while ($checkCode !== false) {
|
||||
$response = '';
|
||||
$startTime = time();
|
||||
while (substr($response, -2) !== "\r\n" && ((time() - $startTime) < $this->smtpOptions['timeout'])) {
|
||||
$response .= $this->__smtpConnection->read();
|
||||
}
|
||||
if (substr($response, -2) !== "\r\n") {
|
||||
$this->smtpError = 'timeout';
|
||||
return false;
|
||||
}
|
||||
$response = end(explode("\r\n", rtrim($response, "\r\n")));
|
||||
|
||||
if (preg_match('/^(' . $checkCode . ')(.)/', $response, $code)) {
|
||||
if ($code[2] === '-') {
|
||||
continue;
|
||||
}
|
||||
return $code[1];
|
||||
}
|
||||
$this->smtpError = $response;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set as controller flash message a debug message showing current settings in component
|
||||
*
|
||||
* @return boolean Success
|
||||
* @access private
|
||||
*/
|
||||
function _debug() {
|
||||
$nl = "\n";
|
||||
$header = implode($nl, $this->__header);
|
||||
$message = implode($nl, $this->__message);
|
||||
$fm = '<pre>';
|
||||
|
||||
if (is_array($this->to)) {
|
||||
$to = implode(', ', array_map(array($this, '_formatAddress'), $this->to));
|
||||
} else {
|
||||
$to = $this->to;
|
||||
}
|
||||
$fm .= sprintf('%s %s%s', 'To:', $to, $nl);
|
||||
$fm .= sprintf('%s %s%s', 'From:', $this->from, $nl);
|
||||
$fm .= sprintf('%s %s%s', 'Subject:', $this->_encode($this->subject), $nl);
|
||||
$fm .= sprintf('%s%3$s%3$s%s', 'Header:', $header, $nl);
|
||||
$fm .= sprintf('%s%3$s%3$s%s', 'Parameters:', $this->additionalParams, $nl);
|
||||
$fm .= sprintf('%s%3$s%3$s%s', 'Message:', $message, $nl);
|
||||
$fm .= '</pre>';
|
||||
|
||||
if (isset($this->Controller->Session)) {
|
||||
$this->Controller->Session->setFlash($fm, 'default', null, 'email');
|
||||
return true;
|
||||
}
|
||||
return $fm;
|
||||
}
|
||||
}
|
@@ -0,0 +1,826 @@
|
||||
<?php
|
||||
/**
|
||||
* Request object for handling alternative HTTP requests
|
||||
*
|
||||
* Alternative HTTP requests can come from wireless units like mobile phones, palmtop computers,
|
||||
* and the like. These units have no use for Ajax requests, and this Component can tell how Cake
|
||||
* should respond to the different needs of a handheld computer and a desktop machine.
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller.components
|
||||
* @since CakePHP(tm) v 0.10.4.1076
|
||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Request object for handling HTTP requests
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller.components
|
||||
* @link http://book.cakephp.org/view/1291/Request-Handling
|
||||
*
|
||||
*/
|
||||
class RequestHandlerComponent extends Object {
|
||||
|
||||
/**
|
||||
* The layout that will be switched to for Ajax requests
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
* @see RequestHandler::setAjax()
|
||||
*/
|
||||
var $ajaxLayout = 'ajax';
|
||||
|
||||
/**
|
||||
* Determines whether or not callbacks will be fired on this component
|
||||
*
|
||||
* @var boolean
|
||||
* @access public
|
||||
*/
|
||||
var $enabled = true;
|
||||
|
||||
/**
|
||||
* Holds the content-type of the response that is set when using
|
||||
* RequestHandler::respondAs()
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $__responseTypeSet = null;
|
||||
|
||||
/**
|
||||
* Holds the copy of Controller::$params
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $params = array();
|
||||
|
||||
/**
|
||||
* Friendly content-type mappings used to set response types and determine
|
||||
* request types. Can be modified with RequestHandler::setContent()
|
||||
*
|
||||
* @var array
|
||||
* @access private
|
||||
* @see RequestHandlerComponent::setContent
|
||||
*/
|
||||
var $__requestContent = array(
|
||||
'javascript' => 'text/javascript',
|
||||
'js' => 'text/javascript',
|
||||
'json' => 'application/json',
|
||||
'css' => 'text/css',
|
||||
'html' => array('text/html', '*/*'),
|
||||
'text' => 'text/plain',
|
||||
'txt' => 'text/plain',
|
||||
'csv' => array('application/vnd.ms-excel', 'text/plain'),
|
||||
'form' => 'application/x-www-form-urlencoded',
|
||||
'file' => 'multipart/form-data',
|
||||
'xhtml' => array('application/xhtml+xml', 'application/xhtml', 'text/xhtml'),
|
||||
'xhtml-mobile' => 'application/vnd.wap.xhtml+xml',
|
||||
'xml' => array('application/xml', 'text/xml'),
|
||||
'rss' => 'application/rss+xml',
|
||||
'atom' => 'application/atom+xml',
|
||||
'amf' => 'application/x-amf',
|
||||
'wap' => array(
|
||||
'text/vnd.wap.wml',
|
||||
'text/vnd.wap.wmlscript',
|
||||
'image/vnd.wap.wbmp'
|
||||
),
|
||||
'wml' => 'text/vnd.wap.wml',
|
||||
'wmlscript' => 'text/vnd.wap.wmlscript',
|
||||
'wbmp' => 'image/vnd.wap.wbmp',
|
||||
'pdf' => 'application/pdf',
|
||||
'zip' => 'application/x-zip',
|
||||
'tar' => 'application/x-tar'
|
||||
);
|
||||
|
||||
/**
|
||||
* List of regular expressions for matching mobile device's user agent string
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $mobileUA = array(
|
||||
'Android',
|
||||
'AvantGo',
|
||||
'BlackBerry',
|
||||
'DoCoMo',
|
||||
'iPod',
|
||||
'iPhone',
|
||||
'J2ME',
|
||||
'MIDP',
|
||||
'NetFront',
|
||||
'Nokia',
|
||||
'Opera Mini',
|
||||
'PalmOS',
|
||||
'PalmSource',
|
||||
'portalmmm',
|
||||
'Plucker',
|
||||
'ReqwirelessWeb',
|
||||
'SonyEricsson',
|
||||
'Symbian',
|
||||
'UP\.Browser',
|
||||
'webOS',
|
||||
'Windows CE',
|
||||
'Xiino'
|
||||
);
|
||||
|
||||
/**
|
||||
* Content-types accepted by the client. If extension parsing is enabled in the
|
||||
* Router, and an extension is detected, the corresponding content-type will be
|
||||
* used as the overriding primary content-type accepted.
|
||||
*
|
||||
* @var array
|
||||
* @access private
|
||||
* @see Router::parseExtensions()
|
||||
*/
|
||||
var $__acceptTypes = array();
|
||||
|
||||
/**
|
||||
* The template to use when rendering the given content type.
|
||||
*
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
var $__renderType = null;
|
||||
|
||||
/**
|
||||
* Contains the file extension parsed out by the Router
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
* @see Router::parseExtensions()
|
||||
*/
|
||||
var $ext = null;
|
||||
|
||||
/**
|
||||
* Flag set when MIME types have been initialized
|
||||
*
|
||||
* @var boolean
|
||||
* @access private
|
||||
* @see RequestHandler::__initializeTypes()
|
||||
*/
|
||||
var $__typesInitialized = false;
|
||||
|
||||
/**
|
||||
* Constructor. Parses the accepted content types accepted by the client using HTTP_ACCEPT
|
||||
*
|
||||
*/
|
||||
function __construct() {
|
||||
$this->__acceptTypes = explode(',', env('HTTP_ACCEPT'));
|
||||
|
||||
foreach ($this->__acceptTypes as $i => $type) {
|
||||
if (strpos($type, ';')) {
|
||||
$type = explode(';', $type);
|
||||
$this->__acceptTypes[$i] = $type[0];
|
||||
}
|
||||
}
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the component, gets a reference to Controller::$parameters, and
|
||||
* checks to see if a file extension has been parsed by the Router. If yes, the
|
||||
* corresponding content-type is pushed onto the list of accepted content-types
|
||||
* as the first item.
|
||||
*
|
||||
* @param object $controller A reference to the controller
|
||||
* @param array $settings Array of settings to _set().
|
||||
* @return void
|
||||
* @see Router::parseExtensions()
|
||||
* @access public
|
||||
*/
|
||||
function initialize(&$controller, $settings = array()) {
|
||||
if (isset($controller->params['url']['ext'])) {
|
||||
$this->ext = $controller->params['url']['ext'];
|
||||
}
|
||||
$this->_set($settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* The startup method of the RequestHandler enables several automatic behaviors
|
||||
* related to the detection of certain properties of the HTTP request, including:
|
||||
*
|
||||
* - Disabling layout rendering for Ajax requests (based on the HTTP_X_REQUESTED_WITH header)
|
||||
* - If Router::parseExtensions() is enabled, the layout and template type are
|
||||
* switched based on the parsed extension. For example, if controller/action.xml
|
||||
* is requested, the view path becomes <i>app/views/controller/xml/action.ctp</i>.
|
||||
* - If a helper with the same name as the extension exists, it is added to the controller.
|
||||
* - If the extension is of a type that RequestHandler understands, it will set that
|
||||
* Content-type in the response header.
|
||||
* - If the XML data is POSTed, the data is parsed into an XML object, which is assigned
|
||||
* to the $data property of the controller, which can then be saved to a model object.
|
||||
*
|
||||
* @param object $controller A reference to the controller
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function startup(&$controller) {
|
||||
if (!$this->enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->__initializeTypes();
|
||||
$controller->params['isAjax'] = $this->isAjax();
|
||||
$isRecognized = (
|
||||
!in_array($this->ext, array('html', 'htm')) &&
|
||||
in_array($this->ext, array_keys($this->__requestContent))
|
||||
);
|
||||
|
||||
if (!empty($this->ext) && $isRecognized) {
|
||||
$this->renderAs($controller, $this->ext);
|
||||
} elseif ($this->isAjax()) {
|
||||
$this->renderAs($controller, 'ajax');
|
||||
} elseif (empty($this->ext) || in_array($this->ext, array('html', 'htm'))) {
|
||||
$this->respondAs('html', array('charset' => Configure::read('App.encoding')));
|
||||
}
|
||||
|
||||
if ($this->requestedWith('xml')) {
|
||||
if (!class_exists('XmlNode')) {
|
||||
App::import('Core', 'Xml');
|
||||
}
|
||||
$xml = new Xml(trim(file_get_contents('php://input')));
|
||||
|
||||
if (count($xml->children) == 1 && is_object($dataNode = $xml->child('data'))) {
|
||||
$controller->data = $dataNode->toArray();
|
||||
} else {
|
||||
$controller->data = $xml->toArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles (fakes) redirects for Ajax requests using requestAction()
|
||||
*
|
||||
* @param object $controller A reference to the controller
|
||||
* @param mixed $url A string or array containing the redirect location
|
||||
* @param mixed HTTP Status for redirect
|
||||
* @access public
|
||||
*/
|
||||
function beforeRedirect(&$controller, $url, $status = null) {
|
||||
if (!$this->isAjax()) {
|
||||
return;
|
||||
}
|
||||
foreach ($_POST as $key => $val) {
|
||||
unset($_POST[$key]);
|
||||
}
|
||||
if (is_array($url)) {
|
||||
$url = Router::url($url + array('base' => false));
|
||||
}
|
||||
if (!empty($status)) {
|
||||
$statusCode = $controller->httpCodes($status);
|
||||
$code = key($statusCode);
|
||||
$msg = $statusCode[$code];
|
||||
$controller->header("HTTP/1.1 {$code} {$msg}");
|
||||
}
|
||||
echo $this->requestAction($url, array('return', 'bare' => false));
|
||||
$this->_stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current HTTP request is Ajax, false otherwise
|
||||
*
|
||||
* @return boolean True if call is Ajax
|
||||
* @access public
|
||||
*/
|
||||
function isAjax() {
|
||||
return env('HTTP_X_REQUESTED_WITH') === "XMLHttpRequest";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current HTTP request is coming from a Flash-based client
|
||||
*
|
||||
* @return boolean True if call is from Flash
|
||||
* @access public
|
||||
*/
|
||||
function isFlash() {
|
||||
return (preg_match('/^(Shockwave|Adobe) Flash/', env('HTTP_USER_AGENT')) == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current request is over HTTPS, false otherwise.
|
||||
*
|
||||
* @return bool True if call is over HTTPS
|
||||
* @access public
|
||||
*/
|
||||
function isSSL() {
|
||||
return env('HTTPS');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current call accepts an XML response, false otherwise
|
||||
*
|
||||
* @return boolean True if client accepts an XML response
|
||||
* @access public
|
||||
*/
|
||||
function isXml() {
|
||||
return $this->prefers('xml');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current call accepts an RSS response, false otherwise
|
||||
*
|
||||
* @return boolean True if client accepts an RSS response
|
||||
* @access public
|
||||
*/
|
||||
function isRss() {
|
||||
return $this->prefers('rss');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current call accepts an Atom response, false otherwise
|
||||
*
|
||||
* @return boolean True if client accepts an RSS response
|
||||
* @access public
|
||||
*/
|
||||
function isAtom() {
|
||||
return $this->prefers('atom');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if user agent string matches a mobile web browser, or if the
|
||||
* client accepts WAP content.
|
||||
*
|
||||
* @return boolean True if user agent is a mobile web browser
|
||||
* @access public
|
||||
* @deprecated Use of constant REQUEST_MOBILE_UA is deprecated and will be removed in future versions
|
||||
*/
|
||||
function isMobile() {
|
||||
if (defined('REQUEST_MOBILE_UA')) {
|
||||
$regex = '/' . REQUEST_MOBILE_UA . '/i';
|
||||
} else {
|
||||
$regex = '/' . implode('|', $this->mobileUA) . '/i';
|
||||
}
|
||||
|
||||
if (preg_match($regex, env('HTTP_USER_AGENT')) || $this->accepts('wap')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the client accepts WAP content
|
||||
*
|
||||
* @return bool
|
||||
* @access public
|
||||
*/
|
||||
function isWap() {
|
||||
return $this->prefers('wap');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current call a POST request
|
||||
*
|
||||
* @return boolean True if call is a POST
|
||||
* @access public
|
||||
*/
|
||||
function isPost() {
|
||||
return (strtolower(env('REQUEST_METHOD')) == 'post');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current call a PUT request
|
||||
*
|
||||
* @return boolean True if call is a PUT
|
||||
* @access public
|
||||
*/
|
||||
function isPut() {
|
||||
return (strtolower(env('REQUEST_METHOD')) == 'put');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current call a GET request
|
||||
*
|
||||
* @return boolean True if call is a GET
|
||||
* @access public
|
||||
*/
|
||||
function isGet() {
|
||||
return (strtolower(env('REQUEST_METHOD')) == 'get');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current call a DELETE request
|
||||
*
|
||||
* @return boolean True if call is a DELETE
|
||||
* @access public
|
||||
*/
|
||||
function isDelete() {
|
||||
return (strtolower(env('REQUEST_METHOD')) == 'delete');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets Prototype version if call is Ajax, otherwise empty string.
|
||||
* The Prototype library sets a special "Prototype version" HTTP header.
|
||||
*
|
||||
* @return string Prototype version of component making Ajax call
|
||||
* @access public
|
||||
*/
|
||||
function getAjaxVersion() {
|
||||
if (env('HTTP_X_PROTOTYPE_VERSION') != null) {
|
||||
return env('HTTP_X_PROTOTYPE_VERSION');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds/sets the Content-type(s) for the given name. This method allows
|
||||
* content-types to be mapped to friendly aliases (or extensions), which allows
|
||||
* RequestHandler to automatically respond to requests of that type in the
|
||||
* startup method.
|
||||
*
|
||||
* @param string $name The name of the Content-type, i.e. "html", "xml", "css"
|
||||
* @param mixed $type The Content-type or array of Content-types assigned to the name,
|
||||
* i.e. "text/html", or "application/xml"
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function setContent($name, $type = null) {
|
||||
if (is_array($name)) {
|
||||
$this->__requestContent = array_merge($this->__requestContent, $name);
|
||||
return;
|
||||
}
|
||||
$this->__requestContent[$name] = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the server name from which this request was referred
|
||||
*
|
||||
* @return string Server address
|
||||
* @access public
|
||||
*/
|
||||
function getReferer() {
|
||||
if (env('HTTP_HOST') != null) {
|
||||
$sessHost = env('HTTP_HOST');
|
||||
}
|
||||
|
||||
if (env('HTTP_X_FORWARDED_HOST') != null) {
|
||||
$sessHost = env('HTTP_X_FORWARDED_HOST');
|
||||
}
|
||||
return trim(preg_replace('/(?:\:.*)/', '', $sessHost));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets remote client IP
|
||||
*
|
||||
* @return string Client IP address
|
||||
* @access public
|
||||
*/
|
||||
function getClientIP($safe = true) {
|
||||
if (!$safe && env('HTTP_X_FORWARDED_FOR') != null) {
|
||||
$ipaddr = preg_replace('/(?:,.*)/', '', env('HTTP_X_FORWARDED_FOR'));
|
||||
} else {
|
||||
if (env('HTTP_CLIENT_IP') != null) {
|
||||
$ipaddr = env('HTTP_CLIENT_IP');
|
||||
} else {
|
||||
$ipaddr = env('REMOTE_ADDR');
|
||||
}
|
||||
}
|
||||
|
||||
if (env('HTTP_CLIENTADDRESS') != null) {
|
||||
$tmpipaddr = env('HTTP_CLIENTADDRESS');
|
||||
|
||||
if (!empty($tmpipaddr)) {
|
||||
$ipaddr = preg_replace('/(?:,.*)/', '', $tmpipaddr);
|
||||
}
|
||||
}
|
||||
return trim($ipaddr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines which content types the client accepts. Acceptance is based on
|
||||
* the file extension parsed by the Router (if present), and by the HTTP_ACCEPT
|
||||
* header.
|
||||
*
|
||||
* @param mixed $type Can be null (or no parameter), a string type name, or an
|
||||
* array of types
|
||||
* @return mixed If null or no parameter is passed, returns an array of content
|
||||
* types the client accepts. If a string is passed, returns true
|
||||
* if the client accepts it. If an array is passed, returns true
|
||||
* if the client accepts one or more elements in the array.
|
||||
* @access public
|
||||
* @see RequestHandlerComponent::setContent()
|
||||
*/
|
||||
function accepts($type = null) {
|
||||
$this->__initializeTypes();
|
||||
|
||||
if ($type == null) {
|
||||
return $this->mapType($this->__acceptTypes);
|
||||
|
||||
} elseif (is_array($type)) {
|
||||
foreach ($type as $t) {
|
||||
if ($this->accepts($t) == true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} elseif (is_string($type)) {
|
||||
|
||||
if (!isset($this->__requestContent[$type])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$content = $this->__requestContent[$type];
|
||||
|
||||
if (is_array($content)) {
|
||||
foreach ($content as $c) {
|
||||
if (in_array($c, $this->__acceptTypes)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (in_array($content, $this->__acceptTypes)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the content type of the data the client has sent (i.e. in a POST request)
|
||||
*
|
||||
* @param mixed $type Can be null (or no parameter), a string type name, or an array of types
|
||||
* @return mixed
|
||||
* @access public
|
||||
*/
|
||||
function requestedWith($type = null) {
|
||||
if (!$this->isPost() && !$this->isPut()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
list($contentType) = explode(';', env('CONTENT_TYPE'));
|
||||
if ($type == null) {
|
||||
return $this->mapType($contentType);
|
||||
} elseif (is_array($type)) {
|
||||
foreach ($type as $t) {
|
||||
if ($this->requestedWith($t)) {
|
||||
return $this->mapType($t);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} elseif (is_string($type)) {
|
||||
return ($type == $this->mapType($contentType));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines which content-types the client prefers. If no parameters are given,
|
||||
* the content-type that the client most likely prefers is returned. If $type is
|
||||
* an array, the first item in the array that the client accepts is returned.
|
||||
* Preference is determined primarily by the file extension parsed by the Router
|
||||
* if provided, and secondarily by the list of content-types provided in
|
||||
* HTTP_ACCEPT.
|
||||
*
|
||||
* @param mixed $type An optional array of 'friendly' content-type names, i.e.
|
||||
* 'html', 'xml', 'js', etc.
|
||||
* @return mixed If $type is null or not provided, the first content-type in the
|
||||
* list, based on preference, is returned.
|
||||
* @access public
|
||||
* @see RequestHandlerComponent::setContent()
|
||||
*/
|
||||
function prefers($type = null) {
|
||||
$this->__initializeTypes();
|
||||
$accept = $this->accepts();
|
||||
|
||||
if ($type == null) {
|
||||
if (empty($this->ext)) {
|
||||
if (is_array($accept)) {
|
||||
return $accept[0];
|
||||
}
|
||||
return $accept;
|
||||
}
|
||||
return $this->ext;
|
||||
}
|
||||
|
||||
$types = $type;
|
||||
if (is_string($type)) {
|
||||
$types = array($type);
|
||||
}
|
||||
|
||||
if (count($types) === 1) {
|
||||
if (!empty($this->ext)) {
|
||||
return ($types[0] == $this->ext);
|
||||
}
|
||||
return ($types[0] == $accept[0]);
|
||||
}
|
||||
$accepts = array();
|
||||
|
||||
foreach ($types as $type) {
|
||||
if (in_array($type, $accept)) {
|
||||
$accepts[] = $type;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($accepts) === 0) {
|
||||
return false;
|
||||
} elseif (count($types) === 1) {
|
||||
return ($types[0] === $accepts[0]);
|
||||
} elseif (count($accepts) === 1) {
|
||||
return $accepts[0];
|
||||
}
|
||||
|
||||
$acceptedTypes = array();
|
||||
foreach ($this->__acceptTypes as $type) {
|
||||
$acceptedTypes[] = $this->mapType($type);
|
||||
}
|
||||
$accepts = array_intersect($acceptedTypes, $accepts);
|
||||
return $accepts[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the layout and template paths for the content type defined by $type.
|
||||
*
|
||||
* @param object $controller A reference to a controller object
|
||||
* @param string $type Type of response to send (e.g: 'ajax')
|
||||
* @return void
|
||||
* @access public
|
||||
* @see RequestHandlerComponent::setContent()
|
||||
* @see RequestHandlerComponent::respondAs()
|
||||
*/
|
||||
function renderAs(&$controller, $type) {
|
||||
$this->__initializeTypes();
|
||||
$options = array('charset' => 'UTF-8');
|
||||
|
||||
if (Configure::read('App.encoding') !== null) {
|
||||
$options = array('charset' => Configure::read('App.encoding'));
|
||||
}
|
||||
|
||||
if ($type == 'ajax') {
|
||||
$controller->layout = $this->ajaxLayout;
|
||||
return $this->respondAs('html', $options);
|
||||
}
|
||||
$controller->ext = '.ctp';
|
||||
|
||||
if (empty($this->__renderType)) {
|
||||
$controller->viewPath .= DS . $type;
|
||||
} else {
|
||||
$remove = preg_replace("/([\/\\\\]{$this->__renderType})$/", DS . $type, $controller->viewPath);
|
||||
$controller->viewPath = $remove;
|
||||
}
|
||||
$this->__renderType = $type;
|
||||
$controller->layoutPath = $type;
|
||||
|
||||
if (isset($this->__requestContent[$type])) {
|
||||
$this->respondAs($type, $options);
|
||||
}
|
||||
|
||||
$helper = ucfirst($type);
|
||||
$isAdded = (
|
||||
in_array($helper, $controller->helpers) ||
|
||||
array_key_exists($helper, $controller->helpers)
|
||||
);
|
||||
|
||||
if (!$isAdded) {
|
||||
if (App::import('Helper', $helper)) {
|
||||
$controller->helpers[] = $helper;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the response header based on type map index name. If DEBUG is greater than 2, the header
|
||||
* is not set.
|
||||
*
|
||||
* @param mixed $type Friendly type name, i.e. 'html' or 'xml', or a full content-type,
|
||||
* like 'application/x-shockwave'.
|
||||
* @param array $options If $type is a friendly type name that is associated with
|
||||
* more than one type of content, $index is used to select which content-type to use.
|
||||
* @return boolean Returns false if the friendly type name given in $type does
|
||||
* not exist in the type map, or if the Content-type header has
|
||||
* already been set by this method.
|
||||
* @access public
|
||||
* @see RequestHandlerComponent::setContent()
|
||||
*/
|
||||
function respondAs($type, $options = array()) {
|
||||
$this->__initializeTypes();
|
||||
if (!array_key_exists($type, $this->__requestContent) && strpos($type, '/') === false) {
|
||||
return false;
|
||||
}
|
||||
$defaults = array('index' => 0, 'charset' => null, 'attachment' => false);
|
||||
$options = array_merge($defaults, $options);
|
||||
|
||||
if (strpos($type, '/') === false && isset($this->__requestContent[$type])) {
|
||||
$cType = null;
|
||||
if (is_array($this->__requestContent[$type]) && isset($this->__requestContent[$type][$options['index']])) {
|
||||
$cType = $this->__requestContent[$type][$options['index']];
|
||||
} elseif (is_array($this->__requestContent[$type]) && isset($this->__requestContent[$type][0])) {
|
||||
$cType = $this->__requestContent[$type][0];
|
||||
} elseif (isset($this->__requestContent[$type])) {
|
||||
$cType = $this->__requestContent[$type];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_array($cType)) {
|
||||
if ($this->prefers($cType)) {
|
||||
$cType = $this->prefers($cType);
|
||||
} else {
|
||||
$cType = $cType[0];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$cType = $type;
|
||||
}
|
||||
|
||||
if ($cType != null) {
|
||||
$header = 'Content-type: ' . $cType;
|
||||
|
||||
if (!empty($options['charset'])) {
|
||||
$header .= '; charset=' . $options['charset'];
|
||||
}
|
||||
if (!empty($options['attachment'])) {
|
||||
$this->_header("Content-Disposition: attachment; filename=\"{$options['attachment']}\"");
|
||||
}
|
||||
if (Configure::read() < 2 && !defined('CAKEPHP_SHELL')) {
|
||||
$this->_header($header);
|
||||
}
|
||||
$this->__responseTypeSet = $cType;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for header() so calls can be easily tested.
|
||||
*
|
||||
* @param string $header The header to be sent.
|
||||
* @return void
|
||||
* @access protected
|
||||
*/
|
||||
function _header($header) {
|
||||
header($header);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current response type (Content-type header), or null if none has been set
|
||||
*
|
||||
* @return mixed A string content type alias, or raw content type if no alias map exists,
|
||||
* otherwise null
|
||||
* @access public
|
||||
*/
|
||||
function responseType() {
|
||||
if ($this->__responseTypeSet == null) {
|
||||
return null;
|
||||
}
|
||||
return $this->mapType($this->__responseTypeSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a content-type back to an alias
|
||||
*
|
||||
* @param mixed $type Content type
|
||||
* @return mixed Alias
|
||||
* @access public
|
||||
*/
|
||||
function mapType($ctype) {
|
||||
if (is_array($ctype)) {
|
||||
$out = array();
|
||||
foreach ($ctype as $t) {
|
||||
$out[] = $this->mapType($t);
|
||||
}
|
||||
return $out;
|
||||
} else {
|
||||
$keys = array_keys($this->__requestContent);
|
||||
$count = count($keys);
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$name = $keys[$i];
|
||||
$type = $this->__requestContent[$name];
|
||||
|
||||
if (is_array($type) && in_array($ctype, $type)) {
|
||||
return $name;
|
||||
} elseif (!is_array($type) && $type == $ctype) {
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
return $ctype;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes MIME types
|
||||
*
|
||||
* @return void
|
||||
* @access private
|
||||
*/
|
||||
function __initializeTypes() {
|
||||
if ($this->__typesInitialized) {
|
||||
return;
|
||||
}
|
||||
if (isset($this->__requestContent[$this->ext])) {
|
||||
$content = $this->__requestContent[$this->ext];
|
||||
if (is_array($content)) {
|
||||
$content = $content[0];
|
||||
}
|
||||
array_unshift($this->__acceptTypes, $content);
|
||||
}
|
||||
$this->__typesInitialized = true;
|
||||
}
|
||||
}
|
751
web-cake/html/cake/libs/controller/components/security.php
Normal file
751
web-cake/html/cake/libs/controller/components/security.php
Normal file
@@ -0,0 +1,751 @@
|
||||
<?php
|
||||
/**
|
||||
* Security Component
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller.components
|
||||
* @since CakePHP(tm) v 0.10.8.2156
|
||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
App::import('Core', array('String', 'Security'));
|
||||
|
||||
/**
|
||||
* SecurityComponent
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller.components
|
||||
* @link http://book.cakephp.org/view/1296/Security-Component
|
||||
*/
|
||||
class SecurityComponent extends Object {
|
||||
|
||||
/**
|
||||
* The controller method that will be called if this request is black-hole'd
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $blackHoleCallback = null;
|
||||
|
||||
/**
|
||||
* List of controller actions for which a POST request is required
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
* @see SecurityComponent::requirePost()
|
||||
*/
|
||||
var $requirePost = array();
|
||||
|
||||
/**
|
||||
* List of controller actions for which a GET request is required
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
* @see SecurityComponent::requireGet()
|
||||
*/
|
||||
var $requireGet = array();
|
||||
|
||||
/**
|
||||
* List of controller actions for which a PUT request is required
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
* @see SecurityComponent::requirePut()
|
||||
*/
|
||||
var $requirePut = array();
|
||||
|
||||
/**
|
||||
* List of controller actions for which a DELETE request is required
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
* @see SecurityComponent::requireDelete()
|
||||
*/
|
||||
var $requireDelete = array();
|
||||
|
||||
/**
|
||||
* List of actions that require an SSL-secured connection
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
* @see SecurityComponent::requireSecure()
|
||||
*/
|
||||
var $requireSecure = array();
|
||||
|
||||
/**
|
||||
* List of actions that require a valid authentication key
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
* @see SecurityComponent::requireAuth()
|
||||
*/
|
||||
var $requireAuth = array();
|
||||
|
||||
/**
|
||||
* List of actions that require an HTTP-authenticated login (basic or digest)
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
* @see SecurityComponent::requireLogin()
|
||||
*/
|
||||
var $requireLogin = array();
|
||||
|
||||
/**
|
||||
* Login options for SecurityComponent::requireLogin()
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
* @see SecurityComponent::requireLogin()
|
||||
*/
|
||||
var $loginOptions = array('type' => '', 'prompt' => null);
|
||||
|
||||
/**
|
||||
* An associative array of usernames/passwords used for HTTP-authenticated logins.
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
* @see SecurityComponent::requireLogin()
|
||||
*/
|
||||
var $loginUsers = array();
|
||||
|
||||
/**
|
||||
* Controllers from which actions of the current controller are allowed to receive
|
||||
* requests.
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
* @see SecurityComponent::requireAuth()
|
||||
*/
|
||||
var $allowedControllers = array();
|
||||
|
||||
/**
|
||||
* Actions from which actions of the current controller are allowed to receive
|
||||
* requests.
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
* @see SecurityComponent::requireAuth()
|
||||
*/
|
||||
var $allowedActions = array();
|
||||
|
||||
/**
|
||||
* Form fields to disable
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $disabledFields = array();
|
||||
|
||||
/**
|
||||
* Whether to validate POST data. Set to false to disable for data coming from 3rd party
|
||||
* services, etc.
|
||||
*
|
||||
* @var boolean
|
||||
* @access public
|
||||
*/
|
||||
var $validatePost = true;
|
||||
|
||||
/**
|
||||
* Other components used by the Security component
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $components = array('RequestHandler', 'Session');
|
||||
|
||||
/**
|
||||
* Holds the current action of the controller
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
var $_action = null;
|
||||
|
||||
/**
|
||||
* Initialize the SecurityComponent
|
||||
*
|
||||
* @param object $controller Controller instance for the request
|
||||
* @param array $settings Settings to set to the component
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function initialize(&$controller, $settings = array()) {
|
||||
$this->_set($settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Component startup. All security checking happens here.
|
||||
*
|
||||
* @param object $controller Instantiating controller
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function startup(&$controller) {
|
||||
$this->_action = strtolower($controller->action);
|
||||
$this->_methodsRequired($controller);
|
||||
$this->_secureRequired($controller);
|
||||
$this->_authRequired($controller);
|
||||
$this->_loginRequired($controller);
|
||||
|
||||
$isPost = ($this->RequestHandler->isPost() || $this->RequestHandler->isPut());
|
||||
$isRequestAction = (
|
||||
!isset($controller->params['requested']) ||
|
||||
$controller->params['requested'] != 1
|
||||
);
|
||||
|
||||
if ($isPost && $isRequestAction && $this->validatePost) {
|
||||
if ($this->_validatePost($controller) === false) {
|
||||
if (!$this->blackHole($controller, 'auth')) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->_generateToken($controller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the actions that require a POST request, or empty for all actions
|
||||
*
|
||||
* @return void
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1299/requirePost
|
||||
*/
|
||||
function requirePost() {
|
||||
$args = func_get_args();
|
||||
$this->_requireMethod('Post', $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the actions that require a GET request, or empty for all actions
|
||||
*
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function requireGet() {
|
||||
$args = func_get_args();
|
||||
$this->_requireMethod('Get', $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the actions that require a PUT request, or empty for all actions
|
||||
*
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function requirePut() {
|
||||
$args = func_get_args();
|
||||
$this->_requireMethod('Put', $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the actions that require a DELETE request, or empty for all actions
|
||||
*
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function requireDelete() {
|
||||
$args = func_get_args();
|
||||
$this->_requireMethod('Delete', $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the actions that require a request that is SSL-secured, or empty for all actions
|
||||
*
|
||||
* @return void
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1300/requireSecure
|
||||
*/
|
||||
function requireSecure() {
|
||||
$args = func_get_args();
|
||||
$this->_requireMethod('Secure', $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the actions that require an authenticated request, or empty for all actions
|
||||
*
|
||||
* @return void
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1301/requireAuth
|
||||
*/
|
||||
function requireAuth() {
|
||||
$args = func_get_args();
|
||||
$this->_requireMethod('Auth', $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the actions that require an HTTP-authenticated request, or empty for all actions
|
||||
*
|
||||
* @return void
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1302/requireLogin
|
||||
*/
|
||||
function requireLogin() {
|
||||
$args = func_get_args();
|
||||
$base = $this->loginOptions;
|
||||
|
||||
foreach ($args as $i => $arg) {
|
||||
if (is_array($arg)) {
|
||||
$this->loginOptions = $arg;
|
||||
unset($args[$i]);
|
||||
}
|
||||
}
|
||||
$this->loginOptions = array_merge($base, $this->loginOptions);
|
||||
$this->_requireMethod('Login', $args);
|
||||
|
||||
if (isset($this->loginOptions['users'])) {
|
||||
$this->loginUsers =& $this->loginOptions['users'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to validate the login credentials for an HTTP-authenticated request
|
||||
*
|
||||
* @param string $type Either 'basic', 'digest', or null. If null/empty, will try both.
|
||||
* @return mixed If successful, returns an array with login name and password, otherwise null.
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1303/loginCredentials-string-type
|
||||
*/
|
||||
function loginCredentials($type = null) {
|
||||
switch (strtolower($type)) {
|
||||
case 'basic':
|
||||
$login = array('username' => env('PHP_AUTH_USER'), 'password' => env('PHP_AUTH_PW'));
|
||||
if (!empty($login['username'])) {
|
||||
return $login;
|
||||
}
|
||||
break;
|
||||
case 'digest':
|
||||
default:
|
||||
$digest = null;
|
||||
|
||||
if (version_compare(PHP_VERSION, '5.1') != -1) {
|
||||
$digest = env('PHP_AUTH_DIGEST');
|
||||
} elseif (function_exists('apache_request_headers')) {
|
||||
$headers = apache_request_headers();
|
||||
if (isset($headers['Authorization']) && !empty($headers['Authorization']) && substr($headers['Authorization'], 0, 7) == 'Digest ') {
|
||||
$digest = substr($headers['Authorization'], 7);
|
||||
}
|
||||
} else {
|
||||
// Server doesn't support digest-auth headers
|
||||
trigger_error(__('SecurityComponent::loginCredentials() - Server does not support digest authentication', true), E_USER_WARNING);
|
||||
}
|
||||
|
||||
if (!empty($digest)) {
|
||||
return $this->parseDigestAuthData($digest);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the text of an HTTP-authentication request header from an array of options.
|
||||
*
|
||||
* @param array $options Set of options for header
|
||||
* @return string HTTP-authentication request header
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1304/loginRequest-array-options
|
||||
*/
|
||||
function loginRequest($options = array()) {
|
||||
$options = array_merge($this->loginOptions, $options);
|
||||
$this->_setLoginDefaults($options);
|
||||
$auth = 'WWW-Authenticate: ' . ucfirst($options['type']);
|
||||
$out = array('realm="' . $options['realm'] . '"');
|
||||
|
||||
if (strtolower($options['type']) == 'digest') {
|
||||
$out[] = 'qop="auth"';
|
||||
$out[] = 'nonce="' . uniqid("") . '"';
|
||||
$out[] = 'opaque="' . md5($options['realm']) . '"';
|
||||
}
|
||||
|
||||
return $auth . ' ' . implode(',', $out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an HTTP digest authentication response, and returns an array of the data, or null on failure.
|
||||
*
|
||||
* @param string $digest Digest authentication response
|
||||
* @return array Digest authentication parameters
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1305/parseDigestAuthData-string-digest
|
||||
*/
|
||||
function parseDigestAuthData($digest) {
|
||||
if (substr($digest, 0, 7) == 'Digest ') {
|
||||
$digest = substr($digest, 7);
|
||||
}
|
||||
$keys = array();
|
||||
$match = array();
|
||||
$req = array('nonce' => 1, 'nc' => 1, 'cnonce' => 1, 'qop' => 1, 'username' => 1, 'uri' => 1, 'response' => 1);
|
||||
preg_match_all('/(\w+)=([\'"]?)([a-zA-Z0-9@=.\/_-]+)\2/', $digest, $match, PREG_SET_ORDER);
|
||||
|
||||
foreach ($match as $i) {
|
||||
$keys[$i[1]] = $i[3];
|
||||
unset($req[$i[1]]);
|
||||
}
|
||||
|
||||
if (empty($req)) {
|
||||
return $keys;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a hash to be compared with an HTTP digest-authenticated response
|
||||
*
|
||||
* @param array $data HTTP digest response data, as parsed by SecurityComponent::parseDigestAuthData()
|
||||
* @return string Digest authentication hash
|
||||
* @access public
|
||||
* @see SecurityComponent::parseDigestAuthData()
|
||||
* @link http://book.cakephp.org/view/1306/generateDigestResponseHash-array-data
|
||||
*/
|
||||
function generateDigestResponseHash($data) {
|
||||
return md5(
|
||||
md5($data['username'] . ':' . $this->loginOptions['realm'] . ':' . $this->loginUsers[$data['username']]) .
|
||||
':' . $data['nonce'] . ':' . $data['nc'] . ':' . $data['cnonce'] . ':' . $data['qop'] . ':' .
|
||||
md5(env('REQUEST_METHOD') . ':' . $data['uri'])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Black-hole an invalid request with a 404 error or custom callback. If SecurityComponent::$blackHoleCallback
|
||||
* is specified, it will use this callback by executing the method indicated in $error
|
||||
*
|
||||
* @param object $controller Instantiating controller
|
||||
* @param string $error Error method
|
||||
* @return mixed If specified, controller blackHoleCallback's response, or no return otherwise
|
||||
* @access public
|
||||
* @see SecurityComponent::$blackHoleCallback
|
||||
* @link http://book.cakephp.org/view/1307/blackHole-object-controller-string-error
|
||||
*/
|
||||
function blackHole(&$controller, $error = '') {
|
||||
if ($this->blackHoleCallback == null) {
|
||||
$code = 404;
|
||||
if ($error == 'login') {
|
||||
$code = 401;
|
||||
$controller->header($this->loginRequest());
|
||||
}
|
||||
$controller->redirect(null, $code, true);
|
||||
} else {
|
||||
return $this->_callback($controller, $this->blackHoleCallback, array($error));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the actions that require a $method HTTP request, or empty for all actions
|
||||
*
|
||||
* @param string $method The HTTP method to assign controller actions to
|
||||
* @param array $actions Controller actions to set the required HTTP method to.
|
||||
* @return void
|
||||
* @access protected
|
||||
*/
|
||||
function _requireMethod($method, $actions = array()) {
|
||||
if (isset($actions[0]) && is_array($actions[0])) {
|
||||
$actions = $actions[0];
|
||||
}
|
||||
$this->{'require' . $method} = (empty($actions)) ? array('*'): $actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if HTTP methods are required
|
||||
*
|
||||
* @param object $controller Instantiating controller
|
||||
* @return bool true if $method is required
|
||||
* @access protected
|
||||
*/
|
||||
function _methodsRequired(&$controller) {
|
||||
foreach (array('Post', 'Get', 'Put', 'Delete') as $method) {
|
||||
$property = 'require' . $method;
|
||||
if (is_array($this->$property) && !empty($this->$property)) {
|
||||
$require = array_map('strtolower', $this->$property);
|
||||
|
||||
if (in_array($this->_action, $require) || $this->$property == array('*')) {
|
||||
if (!$this->RequestHandler->{'is' . $method}()) {
|
||||
if (!$this->blackHole($controller, strtolower($method))) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if access requires secure connection
|
||||
*
|
||||
* @param object $controller Instantiating controller
|
||||
* @return bool true if secure connection required
|
||||
* @access protected
|
||||
*/
|
||||
function _secureRequired(&$controller) {
|
||||
if (is_array($this->requireSecure) && !empty($this->requireSecure)) {
|
||||
$requireSecure = array_map('strtolower', $this->requireSecure);
|
||||
|
||||
if (in_array($this->_action, $requireSecure) || $this->requireSecure == array('*')) {
|
||||
if (!$this->RequestHandler->isSSL()) {
|
||||
if (!$this->blackHole($controller, 'secure')) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if authentication is required
|
||||
*
|
||||
* @param object $controller Instantiating controller
|
||||
* @return bool true if authentication required
|
||||
* @access protected
|
||||
*/
|
||||
function _authRequired(&$controller) {
|
||||
if (is_array($this->requireAuth) && !empty($this->requireAuth) && !empty($controller->data)) {
|
||||
$requireAuth = array_map('strtolower', $this->requireAuth);
|
||||
|
||||
if (in_array($this->_action, $requireAuth) || $this->requireAuth == array('*')) {
|
||||
if (!isset($controller->data['_Token'] )) {
|
||||
if (!$this->blackHole($controller, 'auth')) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->Session->check('_Token')) {
|
||||
$tData = unserialize($this->Session->read('_Token'));
|
||||
|
||||
if (!empty($tData['allowedControllers']) && !in_array($controller->params['controller'], $tData['allowedControllers']) || !empty($tData['allowedActions']) && !in_array($controller->params['action'], $tData['allowedActions'])) {
|
||||
if (!$this->blackHole($controller, 'auth')) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!$this->blackHole($controller, 'auth')) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if login is required
|
||||
*
|
||||
* @param object $controller Instantiating controller
|
||||
* @return bool true if login is required
|
||||
* @access protected
|
||||
*/
|
||||
function _loginRequired(&$controller) {
|
||||
if (is_array($this->requireLogin) && !empty($this->requireLogin)) {
|
||||
$requireLogin = array_map('strtolower', $this->requireLogin);
|
||||
|
||||
if (in_array($this->_action, $requireLogin) || $this->requireLogin == array('*')) {
|
||||
$login = $this->loginCredentials($this->loginOptions['type']);
|
||||
|
||||
if ($login == null) {
|
||||
$controller->header($this->loginRequest());
|
||||
|
||||
if (!empty($this->loginOptions['prompt'])) {
|
||||
$this->_callback($controller, $this->loginOptions['prompt']);
|
||||
} else {
|
||||
$this->blackHole($controller, 'login');
|
||||
}
|
||||
} else {
|
||||
if (isset($this->loginOptions['login'])) {
|
||||
$this->_callback($controller, $this->loginOptions['login'], array($login));
|
||||
} else {
|
||||
if (strtolower($this->loginOptions['type']) == 'digest') {
|
||||
if ($login && isset($this->loginUsers[$login['username']])) {
|
||||
if ($login['response'] == $this->generateDigestResponseHash($login)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
$this->blackHole($controller, 'login');
|
||||
} else {
|
||||
if (
|
||||
!(in_array($login['username'], array_keys($this->loginUsers)) &&
|
||||
$this->loginUsers[$login['username']] == $login['password'])
|
||||
) {
|
||||
$this->blackHole($controller, 'login');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate submitted form
|
||||
*
|
||||
* @param object $controller Instantiating controller
|
||||
* @return bool true if submitted form is valid
|
||||
* @access protected
|
||||
*/
|
||||
function _validatePost(&$controller) {
|
||||
if (empty($controller->data)) {
|
||||
return true;
|
||||
}
|
||||
$data = $controller->data;
|
||||
|
||||
if (!isset($data['_Token']) || !isset($data['_Token']['fields']) || !isset($data['_Token']['key'])) {
|
||||
return false;
|
||||
}
|
||||
$token = $data['_Token']['key'];
|
||||
|
||||
if ($this->Session->check('_Token')) {
|
||||
$tokenData = unserialize($this->Session->read('_Token'));
|
||||
|
||||
if ($tokenData['expires'] < time() || $tokenData['key'] !== $token) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$locked = null;
|
||||
$check = $controller->data;
|
||||
$token = urldecode($check['_Token']['fields']);
|
||||
|
||||
if (strpos($token, ':')) {
|
||||
list($token, $locked) = explode(':', $token, 2);
|
||||
}
|
||||
unset($check['_Token']);
|
||||
|
||||
$locked = str_rot13($locked);
|
||||
if (preg_match('/(\A|;|{|})O\:[0-9]+/', $locked)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$lockedFields = array();
|
||||
$fields = Set::flatten($check);
|
||||
$fieldList = array_keys($fields);
|
||||
$locked = unserialize($locked);
|
||||
$multi = array();
|
||||
|
||||
foreach ($fieldList as $i => $key) {
|
||||
if (preg_match('/\.\d+$/', $key)) {
|
||||
$multi[$i] = preg_replace('/\.\d+$/', '', $key);
|
||||
unset($fieldList[$i]);
|
||||
}
|
||||
}
|
||||
if (!empty($multi)) {
|
||||
$fieldList += array_unique($multi);
|
||||
}
|
||||
|
||||
foreach ($fieldList as $i => $key) {
|
||||
$isDisabled = false;
|
||||
$isLocked = (is_array($locked) && in_array($key, $locked));
|
||||
|
||||
if (!empty($this->disabledFields)) {
|
||||
foreach ((array)$this->disabledFields as $disabled) {
|
||||
$disabled = explode('.', $disabled);
|
||||
$field = array_values(array_intersect(explode('.', $key), $disabled));
|
||||
$isDisabled = ($field === $disabled);
|
||||
if ($isDisabled) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($isDisabled || $isLocked) {
|
||||
unset($fieldList[$i]);
|
||||
if ($isLocked) {
|
||||
$lockedFields[$key] = $fields[$key];
|
||||
}
|
||||
}
|
||||
}
|
||||
sort($fieldList, SORT_STRING);
|
||||
ksort($lockedFields, SORT_STRING);
|
||||
|
||||
$fieldList += $lockedFields;
|
||||
$check = Security::hash(serialize($fieldList) . Configure::read('Security.salt'));
|
||||
return ($token === $check);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add authentication key for new form posts
|
||||
*
|
||||
* @param object $controller Instantiating controller
|
||||
* @return bool Success
|
||||
* @access protected
|
||||
*/
|
||||
function _generateToken(&$controller) {
|
||||
if (isset($controller->params['requested']) && $controller->params['requested'] === 1) {
|
||||
if ($this->Session->check('_Token')) {
|
||||
$tokenData = unserialize($this->Session->read('_Token'));
|
||||
$controller->params['_Token'] = $tokenData;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
$authKey = Security::generateAuthKey();
|
||||
$expires = strtotime('+' . Security::inactiveMins() . ' minutes');
|
||||
$token = array(
|
||||
'key' => $authKey,
|
||||
'expires' => $expires,
|
||||
'allowedControllers' => $this->allowedControllers,
|
||||
'allowedActions' => $this->allowedActions,
|
||||
'disabledFields' => $this->disabledFields
|
||||
);
|
||||
|
||||
if (!isset($controller->data)) {
|
||||
$controller->data = array();
|
||||
}
|
||||
|
||||
if ($this->Session->check('_Token')) {
|
||||
$tokenData = unserialize($this->Session->read('_Token'));
|
||||
$valid = (
|
||||
isset($tokenData['expires']) &&
|
||||
$tokenData['expires'] > time() &&
|
||||
isset($tokenData['key'])
|
||||
);
|
||||
|
||||
if ($valid) {
|
||||
$token['key'] = $tokenData['key'];
|
||||
}
|
||||
}
|
||||
$controller->params['_Token'] = $token;
|
||||
$this->Session->write('_Token', serialize($token));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default login options for an HTTP-authenticated request
|
||||
*
|
||||
* @param array $options Default login options
|
||||
* @return void
|
||||
* @access protected
|
||||
*/
|
||||
function _setLoginDefaults(&$options) {
|
||||
$options = array_merge(array(
|
||||
'type' => 'basic',
|
||||
'realm' => env('SERVER_NAME'),
|
||||
'qop' => 'auth',
|
||||
'nonce' => String::uuid()
|
||||
), array_filter($options));
|
||||
$options = array_merge(array('opaque' => md5($options['realm'])), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls a controller callback method
|
||||
*
|
||||
* @param object $controller Controller to run callback on
|
||||
* @param string $method Method to execute
|
||||
* @param array $params Parameters to send to method
|
||||
* @return mixed Controller callback method's response
|
||||
* @access protected
|
||||
*/
|
||||
function _callback(&$controller, $method, $params = array()) {
|
||||
if (is_callable(array($controller, $method))) {
|
||||
return call_user_func_array(array(&$controller, $method), empty($params) ? null : $params);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
295
web-cake/html/cake/libs/controller/components/session.php
Normal file
295
web-cake/html/cake/libs/controller/components/session.php
Normal file
@@ -0,0 +1,295 @@
|
||||
<?php
|
||||
/**
|
||||
* SessionComponent. Provides access to Sessions from the Controller layer
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller.components
|
||||
* @since CakePHP(tm) v 0.10.0.1232
|
||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
if (!class_exists('cakesession')) {
|
||||
require LIBS . 'cake_session.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Session Component.
|
||||
*
|
||||
* Session handling from the controller.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller.components
|
||||
* @link http://book.cakephp.org/view/1310/Sessions
|
||||
*
|
||||
*/
|
||||
class SessionComponent extends CakeSession {
|
||||
|
||||
/**
|
||||
* Used to determine if methods implementation is used, or bypassed
|
||||
*
|
||||
* @var boolean
|
||||
* @access private
|
||||
*/
|
||||
var $__active = true;
|
||||
|
||||
/**
|
||||
* Used to determine if request are from an Ajax request
|
||||
*
|
||||
* @var boolean
|
||||
* @access private
|
||||
*/
|
||||
var $__bare = 0;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param string $base The base path for the Session
|
||||
*/
|
||||
function __construct($base = null) {
|
||||
if (Configure::read('Session.start') === true) {
|
||||
parent::__construct($base);
|
||||
} else {
|
||||
$this->__active = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Startup method.
|
||||
*
|
||||
* @param object $controller Instantiating controller
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function startup(&$controller) {
|
||||
if ($this->started() === false && $this->__active === true) {
|
||||
$this->__start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts Session on if 'Session.start' is set to false in core.php
|
||||
*
|
||||
* @param string $base The base path for the Session
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function activate($base = null) {
|
||||
if ($this->__active === true) {
|
||||
return;
|
||||
}
|
||||
parent::__construct($base);
|
||||
$this->__active = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to write a value to a session key.
|
||||
*
|
||||
* In your controller: $this->Session->write('Controller.sessKey', 'session value');
|
||||
*
|
||||
* @param string $name The name of the key your are setting in the session.
|
||||
* This should be in a Controller.key format for better organizing
|
||||
* @param string $value The value you want to store in a session.
|
||||
* @return boolean Success
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1312/write
|
||||
*/
|
||||
function write($name, $value = null) {
|
||||
if ($this->__active === true) {
|
||||
$this->__start();
|
||||
if (is_array($name)) {
|
||||
foreach ($name as $key => $value) {
|
||||
if (parent::write($key, $value) === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (parent::write($name, $value) === false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to read a session values for a key or return values for all keys.
|
||||
*
|
||||
* In your controller: $this->Session->read('Controller.sessKey');
|
||||
* Calling the method without a param will return all session vars
|
||||
*
|
||||
* @param string $name the name of the session key you want to read
|
||||
* @return mixed value from the session vars
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1314/read
|
||||
*/
|
||||
function read($name = null) {
|
||||
if ($this->__active === true) {
|
||||
$this->__start();
|
||||
return parent::read($name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for SessionComponent::del();
|
||||
*
|
||||
* In your controller: $this->Session->delete('Controller.sessKey');
|
||||
*
|
||||
* @param string $name the name of the session key you want to delete
|
||||
* @return boolean true is session variable is set and can be deleted, false is variable was not set.
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1316/delete
|
||||
*/
|
||||
function delete($name) {
|
||||
if ($this->__active === true) {
|
||||
$this->__start();
|
||||
return parent::delete($name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to check if a session variable is set
|
||||
*
|
||||
* In your controller: $this->Session->check('Controller.sessKey');
|
||||
*
|
||||
* @param string $name the name of the session key you want to check
|
||||
* @return boolean true is session variable is set, false if not
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1315/check
|
||||
*/
|
||||
function check($name) {
|
||||
if ($this->__active === true) {
|
||||
$this->__start();
|
||||
return parent::check($name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine the last error in a session.
|
||||
*
|
||||
* In your controller: $this->Session->error();
|
||||
*
|
||||
* @return string Last session error
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1318/error
|
||||
*/
|
||||
function error() {
|
||||
if ($this->__active === true) {
|
||||
$this->__start();
|
||||
return parent::error();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to set a session variable that can be used to output messages in the view.
|
||||
*
|
||||
* In your controller: $this->Session->setFlash('This has been saved');
|
||||
*
|
||||
* Additional params below can be passed to customize the output, or the Message.[key]
|
||||
*
|
||||
* @param string $message Message to be flashed
|
||||
* @param string $element Element to wrap flash message in.
|
||||
* @param array $params Parameters to be sent to layout as view variables
|
||||
* @param string $key Message key, default is 'flash'
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1313/setFlash
|
||||
*/
|
||||
function setFlash($message, $element = 'default', $params = array(), $key = 'flash') {
|
||||
if ($this->__active === true) {
|
||||
$this->__start();
|
||||
$this->write('Message.' . $key, compact('message', 'element', 'params'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to renew a session id
|
||||
*
|
||||
* In your controller: $this->Session->renew();
|
||||
*
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function renew() {
|
||||
if ($this->__active === true) {
|
||||
$this->__start();
|
||||
parent::renew();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to check for a valid session.
|
||||
*
|
||||
* In your controller: $this->Session->valid();
|
||||
*
|
||||
* @return boolean true is session is valid, false is session is invalid
|
||||
* @access public
|
||||
*/
|
||||
function valid() {
|
||||
if ($this->__active === true) {
|
||||
$this->__start();
|
||||
return parent::valid();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to destroy sessions
|
||||
*
|
||||
* In your controller: $this->Session->destroy();
|
||||
*
|
||||
* @return void
|
||||
* @access public
|
||||
* @link http://book.cakephp.org/view/1317/destroy
|
||||
*/
|
||||
function destroy() {
|
||||
if ($this->__active === true) {
|
||||
$this->__start();
|
||||
parent::destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Session id
|
||||
*
|
||||
* If $id is passed in a beforeFilter, the Session will be started
|
||||
* with the specified id
|
||||
*
|
||||
* @param $id string
|
||||
* @return string
|
||||
* @access public
|
||||
*/
|
||||
function id($id = null) {
|
||||
return parent::id($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts Session if SessionComponent is used in Controller::beforeFilter(),
|
||||
* or is called from
|
||||
*
|
||||
* @return boolean
|
||||
* @access private
|
||||
*/
|
||||
function __start() {
|
||||
if ($this->started() === false) {
|
||||
if (!$this->id() && parent::start()) {
|
||||
parent::_checkValid();
|
||||
} else {
|
||||
parent::start();
|
||||
}
|
||||
}
|
||||
return $this->started();
|
||||
}
|
||||
}
|
1324
web-cake/html/cake/libs/controller/controller.php
Normal file
1324
web-cake/html/cake/libs/controller/controller.php
Normal file
File diff suppressed because it is too large
Load Diff
85
web-cake/html/cake/libs/controller/pages_controller.php
Normal file
85
web-cake/html/cake/libs/controller/pages_controller.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/**
|
||||
* Static content controller.
|
||||
*
|
||||
* This file will render views from views/pages/
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller
|
||||
* @since CakePHP(tm) v 0.2.9
|
||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Static content controller
|
||||
*
|
||||
* Override this controller by placing a copy in controllers directory of an application
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller
|
||||
* @link http://book.cakephp.org/view/958/The-Pages-Controller
|
||||
*/
|
||||
class PagesController extends AppController {
|
||||
|
||||
/**
|
||||
* Controller name
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $name = 'Pages';
|
||||
|
||||
/**
|
||||
* Default helper
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $helpers = array('Html', 'Session');
|
||||
|
||||
/**
|
||||
* This controller does not use a model
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $uses = array();
|
||||
|
||||
/**
|
||||
* Displays a view
|
||||
*
|
||||
* @param mixed What page to display
|
||||
* @access public
|
||||
*/
|
||||
function display() {
|
||||
$path = func_get_args();
|
||||
|
||||
$count = count($path);
|
||||
if (!$count) {
|
||||
$this->redirect('/');
|
||||
}
|
||||
$page = $subpage = $title_for_layout = null;
|
||||
|
||||
if (!empty($path[0])) {
|
||||
$page = $path[0];
|
||||
}
|
||||
if (!empty($path[1])) {
|
||||
$subpage = $path[1];
|
||||
}
|
||||
if (!empty($path[$count - 1])) {
|
||||
$title_for_layout = Inflector::humanize($path[$count - 1]);
|
||||
}
|
||||
$this->set(compact('page', 'subpage', 'title_for_layout'));
|
||||
$this->render(implode('/', $path));
|
||||
}
|
||||
}
|
613
web-cake/html/cake/libs/controller/scaffold.php
Normal file
613
web-cake/html/cake/libs/controller/scaffold.php
Normal file
@@ -0,0 +1,613 @@
|
||||
<?php
|
||||
/**
|
||||
* Scaffold.
|
||||
*
|
||||
* Automatic forms and actions generation for rapid web application development.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
* @link http://cakephp.org CakePHP(tm) Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller
|
||||
* @since Cake v 0.10.0.1076
|
||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Scaffolding is a set of automatic actions for starting web development work faster.
|
||||
*
|
||||
* Scaffold inspects your database tables, and making educated guesses, sets up a
|
||||
* number of pages for each of your Models. These pages have data forms that work,
|
||||
* and afford the web developer an early look at the data, and the possibility to over-ride
|
||||
* scaffolded actions with custom-made ones.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller
|
||||
*/
|
||||
class Scaffold extends Object {
|
||||
|
||||
/**
|
||||
* Controller object
|
||||
*
|
||||
* @var Controller
|
||||
* @access public
|
||||
*/
|
||||
var $controller = null;
|
||||
|
||||
/**
|
||||
* Name of the controller to scaffold
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $name = null;
|
||||
|
||||
/**
|
||||
* Action to be performed.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $action = null;
|
||||
|
||||
/**
|
||||
* Name of current model this view context is attached to
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $model = null;
|
||||
|
||||
/**
|
||||
* Path to View.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $viewPath;
|
||||
|
||||
/**
|
||||
* Path parts for creating links in views.
|
||||
*
|
||||
* @var string Base URL
|
||||
* @access public
|
||||
*/
|
||||
var $base = null;
|
||||
|
||||
/**
|
||||
* Name of layout to use with this View.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $layout = 'default';
|
||||
|
||||
/**
|
||||
* Array of parameter data
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $params;
|
||||
|
||||
/**
|
||||
* File extension. Defaults to Cake's template ".ctp".
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $ext = '.ctp';
|
||||
|
||||
/**
|
||||
* Sub-directory for this view file.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $subDir = null;
|
||||
|
||||
/**
|
||||
* Plugin name.
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $plugin = null;
|
||||
|
||||
/**
|
||||
* valid session.
|
||||
*
|
||||
* @var boolean
|
||||
* @access public
|
||||
*/
|
||||
var $_validSession = null;
|
||||
|
||||
/**
|
||||
* List of variables to collect from the associated controller
|
||||
*
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
var $__passedVars = array(
|
||||
'action', 'base', 'webroot', 'layout', 'name',
|
||||
'viewPath', 'ext', 'params', 'data', 'plugin', 'cacheAction'
|
||||
);
|
||||
|
||||
/**
|
||||
* Title HTML element for current scaffolded view
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
var $scaffoldTitle = null;
|
||||
|
||||
/**
|
||||
* Construct and set up given controller with given parameters.
|
||||
*
|
||||
* @param string $controller_class Name of controller
|
||||
* @param array $params Parameters for scaffolding
|
||||
*/
|
||||
function __construct(&$controller, $params) {
|
||||
$this->controller =& $controller;
|
||||
|
||||
$count = count($this->__passedVars);
|
||||
for ($j = 0; $j < $count; $j++) {
|
||||
$var = $this->__passedVars[$j];
|
||||
$this->{$var} = $controller->{$var};
|
||||
}
|
||||
|
||||
$this->redirect = array('action' => 'index');
|
||||
|
||||
$this->modelClass = $controller->modelClass;
|
||||
$this->modelKey = $controller->modelKey;
|
||||
|
||||
if (!is_object($this->controller->{$this->modelClass})) {
|
||||
return $this->cakeError('missingModel', array(array(
|
||||
'className' => $this->modelClass, 'webroot' => '', 'base' => $controller->base
|
||||
)));
|
||||
}
|
||||
|
||||
$this->ScaffoldModel =& $this->controller->{$this->modelClass};
|
||||
$this->scaffoldTitle = Inflector::humanize($this->viewPath);
|
||||
$this->scaffoldActions = $controller->scaffold;
|
||||
$title_for_layout = __('Scaffold :: ', true) . Inflector::humanize($this->action) . ' :: ' . $this->scaffoldTitle;
|
||||
$modelClass = $this->controller->modelClass;
|
||||
$primaryKey = $this->ScaffoldModel->primaryKey;
|
||||
$displayField = $this->ScaffoldModel->displayField;
|
||||
$singularVar = Inflector::variable($modelClass);
|
||||
$pluralVar = Inflector::variable($this->controller->name);
|
||||
$singularHumanName = Inflector::humanize(Inflector::underscore($modelClass));
|
||||
$pluralHumanName = Inflector::humanize(Inflector::underscore($this->controller->name));
|
||||
$scaffoldFields = array_keys($this->ScaffoldModel->schema());
|
||||
$associations = $this->__associations();
|
||||
|
||||
$this->controller->set(compact(
|
||||
'title_for_layout', 'modelClass', 'primaryKey', 'displayField', 'singularVar', 'pluralVar',
|
||||
'singularHumanName', 'pluralHumanName', 'scaffoldFields', 'associations'
|
||||
));
|
||||
|
||||
if ($this->controller->view) {
|
||||
$this->controller->view = 'Scaffold';
|
||||
}
|
||||
$this->_validSession = (
|
||||
isset($this->controller->Session) && $this->controller->Session->valid() != false
|
||||
);
|
||||
$this->__scaffold($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the content of a scaffold method passing it through the Controller::afterFilter()
|
||||
*
|
||||
* @return void
|
||||
* @access protected
|
||||
*/
|
||||
function _output() {
|
||||
$this->controller->afterFilter();
|
||||
echo($this->controller->output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a view action of scaffolded model.
|
||||
*
|
||||
* @param array $params Parameters for scaffolding
|
||||
* @return mixed A rendered view of a row from Models database table
|
||||
* @access private
|
||||
*/
|
||||
function __scaffoldView($params) {
|
||||
if ($this->controller->_beforeScaffold('view')) {
|
||||
|
||||
$message = __(sprintf("No id set for %s::view()", Inflector::humanize($this->modelKey)), true);
|
||||
if (isset($params['pass'][0])) {
|
||||
$this->ScaffoldModel->id = $params['pass'][0];
|
||||
} elseif ($this->_validSession) {
|
||||
$this->controller->Session->setFlash($message);
|
||||
$this->controller->redirect($this->redirect);
|
||||
} else {
|
||||
return $this->controller->flash($message, '/' . Inflector::underscore($this->controller->viewPath));
|
||||
}
|
||||
$this->ScaffoldModel->recursive = 1;
|
||||
$this->controller->data = $this->ScaffoldModel->read();
|
||||
$this->controller->set(
|
||||
Inflector::variable($this->controller->modelClass), $this->controller->data
|
||||
);
|
||||
$this->controller->render($this->action, $this->layout);
|
||||
$this->_output();
|
||||
} elseif ($this->controller->_scaffoldError('view') === false) {
|
||||
return $this->__scaffoldError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders index action of scaffolded model.
|
||||
*
|
||||
* @param array $params Parameters for scaffolding
|
||||
* @return mixed A rendered view listing rows from Models database table
|
||||
* @access private
|
||||
*/
|
||||
function __scaffoldIndex($params) {
|
||||
if ($this->controller->_beforeScaffold('index')) {
|
||||
$this->ScaffoldModel->recursive = 0;
|
||||
$this->controller->set(
|
||||
Inflector::variable($this->controller->name), $this->controller->paginate()
|
||||
);
|
||||
$this->controller->render($this->action, $this->layout);
|
||||
$this->_output();
|
||||
} elseif ($this->controller->_scaffoldError('index') === false) {
|
||||
return $this->__scaffoldError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders an add or edit action for scaffolded model.
|
||||
*
|
||||
* @param string $action Action (add or edit)
|
||||
* @return mixed A rendered view with a form to edit or add a record in the Models database table
|
||||
* @access private
|
||||
*/
|
||||
function __scaffoldForm($action = 'edit') {
|
||||
$this->controller->viewVars['scaffoldFields'] = array_merge(
|
||||
$this->controller->viewVars['scaffoldFields'],
|
||||
array_keys($this->ScaffoldModel->hasAndBelongsToMany)
|
||||
);
|
||||
$this->controller->render($action, $this->layout);
|
||||
$this->_output();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves or updates the scaffolded model.
|
||||
*
|
||||
* @param array $params Parameters for scaffolding
|
||||
* @param string $action add or edt
|
||||
* @return mixed Success on save/update, add/edit form if data is empty or error if save or update fails
|
||||
* @access private
|
||||
*/
|
||||
function __scaffoldSave($params = array(), $action = 'edit') {
|
||||
$formAction = 'edit';
|
||||
$success = __('updated', true);
|
||||
if ($action === 'add') {
|
||||
$formAction = 'add';
|
||||
$success = __('saved', true);
|
||||
}
|
||||
|
||||
if ($this->controller->_beforeScaffold($action)) {
|
||||
if ($action == 'edit') {
|
||||
if (isset($params['pass'][0])) {
|
||||
$this->ScaffoldModel->id = $params['pass'][0];
|
||||
}
|
||||
|
||||
if (!$this->ScaffoldModel->exists()) {
|
||||
$message = __(sprintf("Invalid id for %s::edit()", Inflector::humanize($this->modelKey), true));
|
||||
if ($this->_validSession) {
|
||||
$this->controller->Session->setFlash($message);
|
||||
$this->controller->redirect($this->redirect);
|
||||
} else {
|
||||
$this->controller->flash($message, $this->redirect);
|
||||
$this->_output();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->controller->data)) {
|
||||
if ($action == 'create') {
|
||||
$this->ScaffoldModel->create();
|
||||
}
|
||||
|
||||
if ($this->ScaffoldModel->save($this->controller->data)) {
|
||||
if ($this->controller->_afterScaffoldSave($action)) {
|
||||
$message = __(
|
||||
sprintf('The %1$s has been %2$s', Inflector::humanize($this->modelKey), $success),
|
||||
true
|
||||
);
|
||||
if ($this->_validSession) {
|
||||
$this->controller->Session->setFlash($message);
|
||||
$this->controller->redirect($this->redirect);
|
||||
} else {
|
||||
$this->controller->flash($message, $this->redirect);
|
||||
return $this->_output();
|
||||
}
|
||||
} else {
|
||||
return $this->controller->_afterScaffoldSaveError($action);
|
||||
}
|
||||
} else {
|
||||
if ($this->_validSession) {
|
||||
$this->controller->Session->setFlash(__('Please correct errors below.', true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($this->controller->data)) {
|
||||
if ($this->ScaffoldModel->id) {
|
||||
$this->controller->data = $this->ScaffoldModel->read();
|
||||
} else {
|
||||
$this->controller->data = $this->ScaffoldModel->create();
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->ScaffoldModel->belongsTo as $assocName => $assocData) {
|
||||
$varName = Inflector::variable(Inflector::pluralize(
|
||||
preg_replace('/(?:_id)$/', '', $assocData['foreignKey'])
|
||||
));
|
||||
$this->controller->set($varName, $this->ScaffoldModel->{$assocName}->find('list'));
|
||||
}
|
||||
foreach ($this->ScaffoldModel->hasAndBelongsToMany as $assocName => $assocData) {
|
||||
$varName = Inflector::variable(Inflector::pluralize($assocName));
|
||||
$this->controller->set($varName, $this->ScaffoldModel->{$assocName}->find('list'));
|
||||
}
|
||||
|
||||
return $this->__scaffoldForm($formAction);
|
||||
} elseif ($this->controller->_scaffoldError($action) === false) {
|
||||
return $this->__scaffoldError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a delete on given scaffolded Model.
|
||||
*
|
||||
* @param array $params Parameters for scaffolding
|
||||
* @return mixed Success on delete, error if delete fails
|
||||
* @access private
|
||||
*/
|
||||
function __scaffoldDelete($params = array()) {
|
||||
if ($this->controller->_beforeScaffold('delete')) {
|
||||
$message = __(
|
||||
sprintf("No id set for %s::delete()", Inflector::humanize($this->modelKey)), true
|
||||
);
|
||||
if (isset($params['pass'][0])) {
|
||||
$id = $params['pass'][0];
|
||||
} elseif ($this->_validSession) {
|
||||
$this->controller->Session->setFlash($message);
|
||||
$this->controller->redirect($this->redirect);
|
||||
} else {
|
||||
$this->controller->flash($message, $this->redirect);
|
||||
return $this->_output();
|
||||
}
|
||||
|
||||
if ($this->ScaffoldModel->delete($id)) {
|
||||
$message = __(
|
||||
sprintf('The %1$s with id: %2$d has been deleted.', Inflector::humanize($this->modelClass), $id),
|
||||
true
|
||||
);
|
||||
if ($this->_validSession) {
|
||||
$this->controller->Session->setFlash($message);
|
||||
$this->controller->redirect($this->redirect);
|
||||
} else {
|
||||
$this->controller->flash($message, $this->redirect);
|
||||
return $this->_output();
|
||||
}
|
||||
} else {
|
||||
$message = __(sprintf(
|
||||
'There was an error deleting the %1$s with id: %2$d',
|
||||
Inflector::humanize($this->modelClass), $id
|
||||
), true);
|
||||
if ($this->_validSession) {
|
||||
$this->controller->Session->setFlash($message);
|
||||
$this->controller->redirect($this->redirect);
|
||||
} else {
|
||||
$this->controller->flash($message, $this->redirect);
|
||||
return $this->_output();
|
||||
}
|
||||
}
|
||||
} elseif ($this->controller->_scaffoldError('delete') === false) {
|
||||
return $this->__scaffoldError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a scaffold error
|
||||
*
|
||||
* @return mixed A rendered view showing the error
|
||||
* @access private
|
||||
*/
|
||||
function __scaffoldError() {
|
||||
return $this->controller->render('error', $this->layout);
|
||||
$this->_output();
|
||||
}
|
||||
|
||||
/**
|
||||
* When methods are now present in a controller
|
||||
* scaffoldView is used to call default Scaffold methods if:
|
||||
* `var $scaffold;` is placed in the controller's class definition.
|
||||
*
|
||||
* @param array $params Parameters for scaffolding
|
||||
* @return mixed A rendered view of scaffold action, or showing the error
|
||||
* @access private
|
||||
*/
|
||||
function __scaffold($params) {
|
||||
$db = &ConnectionManager::getDataSource($this->ScaffoldModel->useDbConfig);
|
||||
$prefixes = Configure::read('Routing.prefixes');
|
||||
$scaffoldPrefix = $this->scaffoldActions;
|
||||
|
||||
if (isset($db)) {
|
||||
if (empty($this->scaffoldActions)) {
|
||||
$this->scaffoldActions = array(
|
||||
'index', 'list', 'view', 'add', 'create', 'edit', 'update', 'delete'
|
||||
);
|
||||
} elseif (!empty($prefixes) && in_array($scaffoldPrefix, $prefixes)) {
|
||||
$this->scaffoldActions = array(
|
||||
$scaffoldPrefix . '_index',
|
||||
$scaffoldPrefix . '_list',
|
||||
$scaffoldPrefix . '_view',
|
||||
$scaffoldPrefix . '_add',
|
||||
$scaffoldPrefix . '_create',
|
||||
$scaffoldPrefix . '_edit',
|
||||
$scaffoldPrefix . '_update',
|
||||
$scaffoldPrefix . '_delete'
|
||||
);
|
||||
}
|
||||
|
||||
if (in_array($params['action'], $this->scaffoldActions)) {
|
||||
if (!empty($prefixes)) {
|
||||
$params['action'] = str_replace($scaffoldPrefix . '_', '', $params['action']);
|
||||
}
|
||||
switch ($params['action']) {
|
||||
case 'index':
|
||||
case 'list':
|
||||
$this->__scaffoldIndex($params);
|
||||
break;
|
||||
case 'view':
|
||||
$this->__scaffoldView($params);
|
||||
break;
|
||||
case 'add':
|
||||
case 'create':
|
||||
$this->__scaffoldSave($params, 'add');
|
||||
break;
|
||||
case 'edit':
|
||||
case 'update':
|
||||
$this->__scaffoldSave($params, 'edit');
|
||||
break;
|
||||
case 'delete':
|
||||
$this->__scaffoldDelete($params);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return $this->cakeError('missingAction', array(array(
|
||||
'className' => $this->controller->name . "Controller",
|
||||
'base' => $this->controller->base,
|
||||
'action' => $this->action,
|
||||
'webroot' => $this->controller->webroot
|
||||
)));
|
||||
}
|
||||
} else {
|
||||
return $this->cakeError('missingDatabase', array(array(
|
||||
'webroot' => $this->controller->webroot
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns associations for controllers models.
|
||||
*
|
||||
* @return array Associations for model
|
||||
* @access private
|
||||
*/
|
||||
function __associations() {
|
||||
$keys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
|
||||
$associations = array();
|
||||
|
||||
foreach ($keys as $key => $type) {
|
||||
foreach ($this->ScaffoldModel->{$type} as $assocKey => $assocData) {
|
||||
$associations[$type][$assocKey]['primaryKey'] =
|
||||
$this->ScaffoldModel->{$assocKey}->primaryKey;
|
||||
|
||||
$associations[$type][$assocKey]['displayField'] =
|
||||
$this->ScaffoldModel->{$assocKey}->displayField;
|
||||
|
||||
$associations[$type][$assocKey]['foreignKey'] =
|
||||
$assocData['foreignKey'];
|
||||
|
||||
$associations[$type][$assocKey]['controller'] =
|
||||
Inflector::pluralize(Inflector::underscore($assocData['className']));
|
||||
|
||||
if ($type == 'hasAndBelongsToMany') {
|
||||
$associations[$type][$assocKey]['with'] = $assocData['with'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $associations;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scaffold View.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.controller
|
||||
*/
|
||||
if (!class_exists('ThemeView')) {
|
||||
App::import('View', 'Theme');
|
||||
}
|
||||
|
||||
/**
|
||||
* ScaffoldView provides specific view file loading features for scaffolded views.
|
||||
*
|
||||
* @package cake.libs.view
|
||||
*/
|
||||
class ScaffoldView extends ThemeView {
|
||||
|
||||
/**
|
||||
* Override _getViewFileName Appends special scaffolding views in.
|
||||
*
|
||||
* @param string $name name of the view file to get.
|
||||
* @return string action
|
||||
* @access protected
|
||||
*/
|
||||
function _getViewFileName($name = null) {
|
||||
if ($name === null) {
|
||||
$name = $this->action;
|
||||
}
|
||||
$name = Inflector::underscore($name);
|
||||
$prefixes = Configure::read('Routing.prefixes');
|
||||
|
||||
if (!empty($prefixes)) {
|
||||
foreach ($prefixes as $prefix) {
|
||||
if (strpos($name, $prefix . '_') !== false) {
|
||||
$name = substr($name, strlen($prefix) + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($name === 'add') {
|
||||
$name = 'edit';
|
||||
}
|
||||
|
||||
$scaffoldAction = 'scaffold.' . $name;
|
||||
|
||||
if (!is_null($this->subDir)) {
|
||||
$subDir = strtolower($this->subDir) . DS;
|
||||
} else {
|
||||
$subDir = null;
|
||||
}
|
||||
|
||||
$names[] = $this->viewPath . DS . $subDir . $scaffoldAction;
|
||||
$names[] = 'scaffolds' . DS . $subDir . $name;
|
||||
|
||||
$paths = $this->_paths($this->plugin);
|
||||
$exts = array($this->ext);
|
||||
if ($this->ext !== '.ctp') {
|
||||
array_push($exts, '.ctp');
|
||||
}
|
||||
foreach ($exts as $ext) {
|
||||
foreach ($paths as $path) {
|
||||
foreach ($names as $name) {
|
||||
if (file_exists($path . $name . $ext)) {
|
||||
return $path . $name . $ext;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($name === 'scaffolds' . DS . $subDir . 'error') {
|
||||
return LIBS . 'view' . DS . 'errors' . DS . 'scaffold_error.ctp';
|
||||
}
|
||||
|
||||
return $this->_missingView($paths[0] . $name . $this->ext, 'missingView');
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user