Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found
in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 88
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 215
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 216
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 217
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 218
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 219
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 220
PK ! TÍe6 6 libraries/Typography.phpnu „[µü¤ tags
*
* @var string
*/
public $block_elements = 'address|blockquote|div|dl|fieldset|form|h\d|hr|noscript|object|ol|p|pre|script|table|ul';
/**
* Elements that should not have
and tags within them.
*
* @var string
*/
public $skip_elements = 'p|pre|ol|ul|dl|object|table|h\d';
/**
* Tags we want the parser to completely ignore when splitting the string.
*
* @var string
*/
public $inline_elements = 'a|abbr|acronym|b|bdo|big|br|button|cite|code|del|dfn|em|i|img|ins|input|label|map|kbd|q|samp|select|small|span|strong|sub|sup|textarea|tt|var';
/**
* array of block level elements that require inner content to be within another block level element
*
* @var array
*/
public $inner_block_required = array('blockquote');
/**
* the last block element parsed
*
* @var string
*/
public $last_block_element = '';
/**
* whether or not to protect quotes within { curly braces }
*
* @var bool
*/
public $protect_braced_quotes = FALSE;
/**
* Auto Typography
*
* This function converts text, making it typographically correct:
* - Converts double spaces into paragraphs.
* - Converts single line breaks into tags
* - Converts single and double quotes into correctly facing curly quote entities.
* - Converts three dots into ellipsis.
* - Converts double dashes into em-dashes.
* - Converts two spaces into entities
*
* @param string
* @param bool whether to reduce more then two consecutive newlines to two
* @return string
*/
public function auto_typography($str, $reduce_linebreaks = FALSE)
{
if ($str === '')
{
return '';
}
// Standardize Newlines to make matching easier
if (strpos($str, "\r") !== FALSE)
{
$str = str_replace(array("\r\n", "\r"), "\n", $str);
}
// Reduce line breaks. If there are more than two consecutive linebreaks
// we'll compress them down to a maximum of two since there's no benefit to more.
if ($reduce_linebreaks === TRUE)
{
$str = preg_replace("/\n\n+/", "\n\n", $str);
}
// HTML comment tags don't conform to patterns of normal tags, so pull them out separately, only if needed
$html_comments = array();
if (strpos($str, '\n";
}
return $r;
}
// --------------------------------------------------------------------
/**
* Executes the Method
*
* @param object
* @return mixed
*/
protected function _execute($m)
{
$methName = $m->method_name;
// Check to see if it is a system call
$system_call = (strpos($methName, 'system') === 0);
if ($this->xss_clean === FALSE)
{
$m->xss_clean = FALSE;
}
//-------------------------------------
// Valid Method
//-------------------------------------
if ( ! isset($this->methods[$methName]['function']))
{
return new XML_RPC_Response(0, $this->xmlrpcerr['unknown_method'], $this->xmlrpcstr['unknown_method']);
}
//-------------------------------------
// Check for Method (and Object)
//-------------------------------------
$method_parts = explode('.', $this->methods[$methName]['function']);
$objectCall = ! empty($method_parts[1]);
if ($system_call === TRUE)
{
if ( ! is_callable(array($this, $method_parts[1])))
{
return new XML_RPC_Response(0, $this->xmlrpcerr['unknown_method'], $this->xmlrpcstr['unknown_method']);
}
}
elseif (($objectCall && ! is_callable(array($method_parts[0], $method_parts[1])))
OR ( ! $objectCall && ! is_callable($this->methods[$methName]['function']))
)
{
return new XML_RPC_Response(0, $this->xmlrpcerr['unknown_method'], $this->xmlrpcstr['unknown_method']);
}
//-------------------------------------
// Checking Methods Signature
//-------------------------------------
if (isset($this->methods[$methName]['signature']))
{
$sig = $this->methods[$methName]['signature'];
for ($i = 0, $c = count($sig); $i < $c; $i++)
{
$current_sig = $sig[$i];
if (count($current_sig) === count($m->params)+1)
{
for ($n = 0, $mc = count($m->params); $n < $mc; $n++)
{
$p = $m->params[$n];
$pt = ($p->kindOf() === 'scalar') ? $p->scalarval() : $p->kindOf();
if ($pt !== $current_sig[$n+1])
{
$pno = $n+1;
$wanted = $current_sig[$n+1];
return new XML_RPC_Response(0,
$this->xmlrpcerr['incorrect_params'],
$this->xmlrpcstr['incorrect_params'] .
': Wanted '.$wanted.', got '.$pt.' at param '.$pno.')');
}
}
}
}
}
//-------------------------------------
// Calls the Function
//-------------------------------------
if ($objectCall === TRUE)
{
if ($method_parts[0] === 'this' && $system_call === TRUE)
{
return call_user_func(array($this, $method_parts[1]), $m);
}
elseif ($this->object === FALSE)
{
return get_instance()->{$method_parts[1]}($m);
}
return $this->object->{$method_parts[1]}($m);
}
return call_user_func($this->methods[$methName]['function'], $m);
}
// --------------------------------------------------------------------
/**
* Server Function: List Methods
*
* @param mixed
* @return object
*/
public function listMethods($m)
{
$v = new XML_RPC_Values();
$output = array();
foreach ($this->methods as $key => $value)
{
$output[] = new XML_RPC_Values($key, 'string');
}
foreach ($this->system_methods as $key => $value)
{
$output[] = new XML_RPC_Values($key, 'string');
}
$v->addArray($output);
return new XML_RPC_Response($v);
}
// --------------------------------------------------------------------
/**
* Server Function: Return Signature for Method
*
* @param mixed
* @return object
*/
public function methodSignature($m)
{
$parameters = $m->output_parameters();
$method_name = $parameters[0];
if (isset($this->methods[$method_name]))
{
if ($this->methods[$method_name]['signature'])
{
$sigs = array();
$signature = $this->methods[$method_name]['signature'];
for ($i = 0, $c = count($signature); $i < $c; $i++)
{
$cursig = array();
$inSig = $signature[$i];
for ($j = 0, $jc = count($inSig); $j < $jc; $j++)
{
$cursig[]= new XML_RPC_Values($inSig[$j], 'string');
}
$sigs[] = new XML_RPC_Values($cursig, 'array');
}
return new XML_RPC_Response(new XML_RPC_Values($sigs, 'array'));
}
return new XML_RPC_Response(new XML_RPC_Values('undef', 'string'));
}
return new XML_RPC_Response(0, $this->xmlrpcerr['introspect_unknown'], $this->xmlrpcstr['introspect_unknown']);
}
// --------------------------------------------------------------------
/**
* Server Function: Doc String for Method
*
* @param mixed
* @return object
*/
public function methodHelp($m)
{
$parameters = $m->output_parameters();
$method_name = $parameters[0];
if (isset($this->methods[$method_name]))
{
$docstring = isset($this->methods[$method_name]['docstring']) ? $this->methods[$method_name]['docstring'] : '';
return new XML_RPC_Response(new XML_RPC_Values($docstring, 'string'));
}
return new XML_RPC_Response(0, $this->xmlrpcerr['introspect_unknown'], $this->xmlrpcstr['introspect_unknown']);
}
// --------------------------------------------------------------------
/**
* Server Function: Multi-call
*
* @param mixed
* @return object
*/
public function multicall($m)
{
// Disabled
return new XML_RPC_Response(0, $this->xmlrpcerr['unknown_method'], $this->xmlrpcstr['unknown_method']);
$parameters = $m->output_parameters();
$calls = $parameters[0];
$result = array();
foreach ($calls as $value)
{
$m = new XML_RPC_Message($value[0]);
$plist = '';
for ($i = 0, $c = count($value[1]); $i < $c; $i++)
{
$m->addParam(new XML_RPC_Values($value[1][$i], 'string'));
}
$attempt = $this->_execute($m);
if ($attempt->faultCode() !== 0)
{
return $attempt;
}
$result[] = new XML_RPC_Values(array($attempt->value()), 'array');
}
return new XML_RPC_Response(new XML_RPC_Values($result, 'array'));
}
// --------------------------------------------------------------------
/**
* Multi-call Function: Error Handling
*
* @param mixed
* @return object
*/
public function multicall_error($err)
{
$str = is_string($err) ? $this->xmlrpcstr["multicall_${err}"] : $err->faultString();
$code = is_string($err) ? $this->xmlrpcerr["multicall_${err}"] : $err->faultCode();
$struct['faultCode'] = new XML_RPC_Values($code, 'int');
$struct['faultString'] = new XML_RPC_Values($str, 'string');
return new XML_RPC_Values($struct, 'struct');
}
// --------------------------------------------------------------------
/**
* Multi-call Function: Processes method
*
* @param mixed
* @return object
*/
public function do_multicall($call)
{
if ($call->kindOf() !== 'struct')
{
return $this->multicall_error('notstruct');
}
elseif ( ! $methName = $call->me['struct']['methodName'])
{
return $this->multicall_error('nomethod');
}
list($scalar_value, $scalar_type) = array(reset($methName->me), key($methName->me));
$scalar_type = $scalar_type === $this->xmlrpcI4 ? $this->xmlrpcInt : $scalar_type;
if ($methName->kindOf() !== 'scalar' OR $scalar_type !== 'string')
{
return $this->multicall_error('notstring');
}
elseif ($scalar_value === 'system.multicall')
{
return $this->multicall_error('recursion');
}
elseif ( ! $params = $call->me['struct']['params'])
{
return $this->multicall_error('noparams');
}
elseif ($params->kindOf() !== 'array')
{
return $this->multicall_error('notarray');
}
list($b, $a) = array(reset($params->me), key($params->me));
$msg = new XML_RPC_Message($scalar_value);
for ($i = 0, $numParams = count($b); $i < $numParams; $i++)
{
$msg->params[] = $params->me['array'][$i];
}
$result = $this->_execute($msg);
if ($result->faultCode() !== 0)
{
return $this->multicall_error($result);
}
return new XML_RPC_Values(array($result->value()), 'array');
}
}
PK ! ½·”ÏÓ Ó libraries/Parser.phpnu „[µü¤ CI =& get_instance();
log_message('info', 'Parser Class Initialized');
}
// --------------------------------------------------------------------
/**
* Parse a template
*
* Parses pseudo-variables contained in the specified template view,
* replacing them with the data in the second param
*
* @param string
* @param array
* @param bool
* @return string
*/
public function parse($template, $data, $return = FALSE)
{
$template = $this->CI->load->view($template, $data, TRUE);
return $this->_parse($template, $data, $return);
}
// --------------------------------------------------------------------
/**
* Parse a String
*
* Parses pseudo-variables contained in the specified string,
* replacing them with the data in the second param
*
* @param string
* @param array
* @param bool
* @return string
*/
public function parse_string($template, $data, $return = FALSE)
{
return $this->_parse($template, $data, $return);
}
// --------------------------------------------------------------------
/**
* Parse a template
*
* Parses pseudo-variables contained in the specified template,
* replacing them with the data in the second param
*
* @param string
* @param array
* @param bool
* @return string
*/
protected function _parse($template, $data, $return = FALSE)
{
if ($template === '')
{
return FALSE;
}
$replace = array();
foreach ($data as $key => $val)
{
$replace = array_merge(
$replace,
is_array($val)
? $this->_parse_pair($key, $val, $template)
: $this->_parse_single($key, (string) $val, $template)
);
}
unset($data);
$template = strtr($template, $replace);
if ($return === FALSE)
{
$this->CI->output->append_output($template);
}
return $template;
}
// --------------------------------------------------------------------
/**
* Set the left/right variable delimiters
*
* @param string
* @param string
* @return void
*/
public function set_delimiters($l = '{', $r = '}')
{
$this->l_delim = $l;
$this->r_delim = $r;
}
// --------------------------------------------------------------------
/**
* Parse a single key/value
*
* @param string
* @param string
* @param string
* @return string
*/
protected function _parse_single($key, $val, $string)
{
return array($this->l_delim.$key.$this->r_delim => (string) $val);
}
// --------------------------------------------------------------------
/**
* Parse a tag pair
*
* Parses tag pairs: {some_tag} string... {/some_tag}
*
* @param string
* @param array
* @param string
* @return string
*/
protected function _parse_pair($variable, $data, $string)
{
$replace = array();
preg_match_all(
'#'.preg_quote($this->l_delim.$variable.$this->r_delim).'(.+?)'.preg_quote($this->l_delim.'/'.$variable.$this->r_delim).'#s',
$string,
$matches,
PREG_SET_ORDER
);
foreach ($matches as $match)
{
$str = '';
foreach ($data as $row)
{
$temp = array();
foreach ($row as $key => $val)
{
if (is_array($val))
{
$pair = $this->_parse_pair($key, $val, $match[1]);
if ( ! empty($pair))
{
$temp = array_merge($temp, $pair);
}
continue;
}
$temp[$this->l_delim.$key.$this->r_delim] = $val;
}
$str .= strtr($match[1], $temp);
}
$replace[$match[0]] = $str;
}
return $replace;
}
}
PK ! ë4r]L L libraries/Driver.phpnu „[µü¤ load_driver($child);
}
/**
* Load driver
*
* Separate load_driver call to support explicit driver load by library or user
*
* @param string Driver name (w/o parent prefix)
* @return object Child class
*/
public function load_driver($child)
{
// Get CodeIgniter instance and subclass prefix
$prefix = config_item('subclass_prefix');
if ( ! isset($this->lib_name))
{
// Get library name without any prefix
$this->lib_name = str_replace(array('CI_', $prefix), '', get_class($this));
}
// The child will be prefixed with the parent lib
$child_name = $this->lib_name.'_'.$child;
// See if requested child is a valid driver
if ( ! in_array($child, $this->valid_drivers))
{
// The requested driver isn't valid!
$msg = 'Invalid driver requested: '.$child_name;
log_message('error', $msg);
show_error($msg);
}
// Get package paths and filename case variations to search
$CI = get_instance();
$paths = $CI->load->get_package_paths(TRUE);
// Is there an extension?
$class_name = $prefix.$child_name;
$found = class_exists($class_name, FALSE);
if ( ! $found)
{
// Check for subclass file
foreach ($paths as $path)
{
// Does the file exist?
$file = $path.'libraries/'.$this->lib_name.'/drivers/'.$prefix.$child_name.'.php';
if (file_exists($file))
{
// Yes - require base class from BASEPATH
$basepath = BASEPATH.'libraries/'.$this->lib_name.'/drivers/'.$child_name.'.php';
if ( ! file_exists($basepath))
{
$msg = 'Unable to load the requested class: CI_'.$child_name;
log_message('error', $msg);
show_error($msg);
}
// Include both sources and mark found
include_once($basepath);
include_once($file);
$found = TRUE;
break;
}
}
}
// Do we need to search for the class?
if ( ! $found)
{
// Use standard class name
$class_name = 'CI_'.$child_name;
if ( ! class_exists($class_name, FALSE))
{
// Check package paths
foreach ($paths as $path)
{
// Does the file exist?
$file = $path.'libraries/'.$this->lib_name.'/drivers/'.$child_name.'.php';
if (file_exists($file))
{
// Include source
include_once($file);
break;
}
}
}
}
// Did we finally find the class?
if ( ! class_exists($class_name, FALSE))
{
if (class_exists($child_name, FALSE))
{
$class_name = $child_name;
}
else
{
$msg = 'Unable to load the requested driver: '.$class_name;
log_message('error', $msg);
show_error($msg);
}
}
// Instantiate, decorate and add child
$obj = new $class_name();
$obj->decorate($this);
$this->$child = $obj;
return $this->$child;
}
}
// --------------------------------------------------------------------------
/**
* CodeIgniter Driver Class
*
* This class enables you to create drivers for a Library based on the Driver Library.
* It handles the drivers' access to the parent library
*
* @package CodeIgniter
* @subpackage Libraries
* @category Libraries
* @author EllisLab Dev Team
* @link
*/
class CI_Driver {
/**
* Instance of the parent class
*
* @var object
*/
protected $_parent;
/**
* List of methods in the parent class
*
* @var array
*/
protected $_methods = array();
/**
* List of properties in the parent class
*
* @var array
*/
protected $_properties = array();
/**
* Array of methods and properties for the parent class(es)
*
* @static
* @var array
*/
protected static $_reflections = array();
/**
* Decorate
*
* Decorates the child with the parent driver lib's methods and properties
*
* @param object
* @return void
*/
public function decorate($parent)
{
$this->_parent = $parent;
// Lock down attributes to what is defined in the class
// and speed up references in magic methods
$class_name = get_class($parent);
if ( ! isset(self::$_reflections[$class_name]))
{
$r = new ReflectionObject($parent);
foreach ($r->getMethods() as $method)
{
if ($method->isPublic())
{
$this->_methods[] = $method->getName();
}
}
foreach ($r->getProperties() as $prop)
{
if ($prop->isPublic())
{
$this->_properties[] = $prop->getName();
}
}
self::$_reflections[$class_name] = array($this->_methods, $this->_properties);
}
else
{
list($this->_methods, $this->_properties) = self::$_reflections[$class_name];
}
}
// --------------------------------------------------------------------
/**
* __call magic method
*
* Handles access to the parent driver library's methods
*
* @param string
* @param array
* @return mixed
*/
public function __call($method, $args = array())
{
if (in_array($method, $this->_methods))
{
return call_user_func_array(array($this->_parent, $method), $args);
}
throw new BadMethodCallException('No such method: '.$method.'()');
}
// --------------------------------------------------------------------
/**
* __get magic method
*
* Handles reading of the parent driver library's properties
*
* @param string
* @return mixed
*/
public function __get($var)
{
if (in_array($var, $this->_properties))
{
return $this->_parent->$var;
}
}
// --------------------------------------------------------------------
/**
* __set magic method
*
* Handles writing to the parent driver library's properties
*
* @param string
* @param array
* @return mixed
*/
public function __set($var, $val)
{
if (in_array($var, $this->_properties))
{
$this->_parent->$var = $val;
}
}
}
PK ! iüyYÎ[ Î[ libraries/Encryption.phpnu „[µü¤ array(
'cbc' => 'cbc',
'ecb' => 'ecb',
'ofb' => 'nofb',
'ofb8' => 'ofb',
'cfb' => 'ncfb',
'cfb8' => 'cfb',
'ctr' => 'ctr',
'stream' => 'stream'
),
'openssl' => array(
'cbc' => 'cbc',
'ecb' => 'ecb',
'ofb' => 'ofb',
'cfb' => 'cfb',
'cfb8' => 'cfb8',
'ctr' => 'ctr',
'stream' => '',
'xts' => 'xts'
)
);
/**
* List of supported HMAC algorithms
*
* name => digest size pairs
*
* @var array
*/
protected $_digests = array(
'sha224' => 28,
'sha256' => 32,
'sha384' => 48,
'sha512' => 64
);
/**
* mbstring.func_overload flag
*
* @var bool
*/
protected static $func_overload;
// --------------------------------------------------------------------
/**
* Class constructor
*
* @param array $params Configuration parameters
* @return void
*/
public function __construct(array $params = array())
{
$this->_drivers = array(
'mcrypt' => defined('MCRYPT_DEV_URANDOM'),
'openssl' => extension_loaded('openssl')
);
if ( ! $this->_drivers['mcrypt'] && ! $this->_drivers['openssl'])
{
show_error('Encryption: Unable to find an available encryption driver.');
}
isset(self::$func_overload) OR self::$func_overload = (extension_loaded('mbstring') && ini_get('mbstring.func_overload'));
$this->initialize($params);
if ( ! isset($this->_key) && self::strlen($key = config_item('encryption_key')) > 0)
{
$this->_key = $key;
}
log_message('info', 'Encryption Class Initialized');
}
// --------------------------------------------------------------------
/**
* Initialize
*
* @param array $params Configuration parameters
* @return CI_Encryption
*/
public function initialize(array $params)
{
if ( ! empty($params['driver']))
{
if (isset($this->_drivers[$params['driver']]))
{
if ($this->_drivers[$params['driver']])
{
$this->_driver = $params['driver'];
}
else
{
log_message('error', "Encryption: Driver '".$params['driver']."' is not available.");
}
}
else
{
log_message('error', "Encryption: Unknown driver '".$params['driver']."' cannot be configured.");
}
}
if (empty($this->_driver))
{
$this->_driver = ($this->_drivers['openssl'] === TRUE)
? 'openssl'
: 'mcrypt';
log_message('debug', "Encryption: Auto-configured driver '".$this->_driver."'.");
}
empty($params['cipher']) && $params['cipher'] = $this->_cipher;
empty($params['key']) OR $this->_key = $params['key'];
$this->{'_'.$this->_driver.'_initialize'}($params);
return $this;
}
// --------------------------------------------------------------------
/**
* Initialize MCrypt
*
* @param array $params Configuration parameters
* @return void
*/
protected function _mcrypt_initialize($params)
{
if ( ! empty($params['cipher']))
{
$params['cipher'] = strtolower($params['cipher']);
$this->_cipher_alias($params['cipher']);
if ( ! in_array($params['cipher'], mcrypt_list_algorithms(), TRUE))
{
log_message('error', 'Encryption: MCrypt cipher '.strtoupper($params['cipher']).' is not available.');
}
else
{
$this->_cipher = $params['cipher'];
}
}
if ( ! empty($params['mode']))
{
$params['mode'] = strtolower($params['mode']);
if ( ! isset($this->_modes['mcrypt'][$params['mode']]))
{
log_message('error', 'Encryption: MCrypt mode '.strtoupper($params['mode']).' is not available.');
}
else
{
$this->_mode = $this->_modes['mcrypt'][$params['mode']];
}
}
if (isset($this->_cipher, $this->_mode))
{
if (is_resource($this->_handle)
&& (strtolower(mcrypt_enc_get_algorithms_name($this->_handle)) !== $this->_cipher
OR strtolower(mcrypt_enc_get_modes_name($this->_handle)) !== $this->_mode)
)
{
mcrypt_module_close($this->_handle);
}
if ($this->_handle = mcrypt_module_open($this->_cipher, '', $this->_mode, ''))
{
log_message('info', 'Encryption: MCrypt cipher '.strtoupper($this->_cipher).' initialized in '.strtoupper($this->_mode).' mode.');
}
else
{
log_message('error', 'Encryption: Unable to initialize MCrypt with cipher '.strtoupper($this->_cipher).' in '.strtoupper($this->_mode).' mode.');
}
}
}
// --------------------------------------------------------------------
/**
* Initialize OpenSSL
*
* @param array $params Configuration parameters
* @return void
*/
protected function _openssl_initialize($params)
{
if ( ! empty($params['cipher']))
{
$params['cipher'] = strtolower($params['cipher']);
$this->_cipher_alias($params['cipher']);
$this->_cipher = $params['cipher'];
}
if ( ! empty($params['mode']))
{
$params['mode'] = strtolower($params['mode']);
if ( ! isset($this->_modes['openssl'][$params['mode']]))
{
log_message('error', 'Encryption: OpenSSL mode '.strtoupper($params['mode']).' is not available.');
}
else
{
$this->_mode = $this->_modes['openssl'][$params['mode']];
}
}
if (isset($this->_cipher, $this->_mode))
{
// This is mostly for the stream mode, which doesn't get suffixed in OpenSSL
$handle = empty($this->_mode)
? $this->_cipher
: $this->_cipher.'-'.$this->_mode;
if ( ! in_array($handle, openssl_get_cipher_methods(), TRUE))
{
$this->_handle = NULL;
log_message('error', 'Encryption: Unable to initialize OpenSSL with method '.strtoupper($handle).'.');
}
else
{
$this->_handle = $handle;
log_message('info', 'Encryption: OpenSSL initialized with method '.strtoupper($handle).'.');
}
}
}
// --------------------------------------------------------------------
/**
* Create a random key
*
* @param int $length Output length
* @return string
*/
public function create_key($length)
{
if (function_exists('random_bytes'))
{
try
{
return random_bytes((int) $length);
}
catch (Exception $e)
{
log_message('error', $e->getMessage());
return FALSE;
}
}
elseif (defined('MCRYPT_DEV_URANDOM'))
{
return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
}
$is_secure = NULL;
$key = openssl_random_pseudo_bytes($length, $is_secure);
return ($is_secure === TRUE)
? $key
: FALSE;
}
// --------------------------------------------------------------------
/**
* Encrypt
*
* @param string $data Input data
* @param array $params Input parameters
* @return string
*/
public function encrypt($data, array $params = NULL)
{
if (($params = $this->_get_params($params)) === FALSE)
{
return FALSE;
}
isset($params['key']) OR $params['key'] = $this->hkdf($this->_key, 'sha512', NULL, self::strlen($this->_key), 'encryption');
if (($data = $this->{'_'.$this->_driver.'_encrypt'}($data, $params)) === FALSE)
{
return FALSE;
}
$params['base64'] && $data = base64_encode($data);
if (isset($params['hmac_digest']))
{
isset($params['hmac_key']) OR $params['hmac_key'] = $this->hkdf($this->_key, 'sha512', NULL, NULL, 'authentication');
return hash_hmac($params['hmac_digest'], $data, $params['hmac_key'], ! $params['base64']).$data;
}
return $data;
}
// --------------------------------------------------------------------
/**
* Encrypt via MCrypt
*
* @param string $data Input data
* @param array $params Input parameters
* @return string
*/
protected function _mcrypt_encrypt($data, $params)
{
if ( ! is_resource($params['handle']))
{
return FALSE;
}
// The greater-than-1 comparison is mostly a work-around for a bug,
// where 1 is returned for ARCFour instead of 0.
$iv = (($iv_size = mcrypt_enc_get_iv_size($params['handle'])) > 1)
? $this->create_key($iv_size)
: NULL;
if (mcrypt_generic_init($params['handle'], $params['key'], $iv) < 0)
{
if ($params['handle'] !== $this->_handle)
{
mcrypt_module_close($params['handle']);
}
return FALSE;
}
// Use PKCS#7 padding in order to ensure compatibility with OpenSSL
// and other implementations outside of PHP.
if (in_array(strtolower(mcrypt_enc_get_modes_name($params['handle'])), array('cbc', 'ecb'), TRUE))
{
$block_size = mcrypt_enc_get_block_size($params['handle']);
$pad = $block_size - (self::strlen($data) % $block_size);
$data .= str_repeat(chr($pad), $pad);
}
// Work-around for yet another strange behavior in MCrypt.
//
// When encrypting in ECB mode, the IV is ignored. Yet
// mcrypt_enc_get_iv_size() returns a value larger than 0
// even if ECB is used AND mcrypt_generic_init() complains
// if you don't pass an IV with length equal to the said
// return value.
//
// This probably would've been fine (even though still wasteful),
// but OpenSSL isn't that dumb and we need to make the process
// portable, so ...
$data = (mcrypt_enc_get_modes_name($params['handle']) !== 'ECB')
? $iv.mcrypt_generic($params['handle'], $data)
: mcrypt_generic($params['handle'], $data);
mcrypt_generic_deinit($params['handle']);
if ($params['handle'] !== $this->_handle)
{
mcrypt_module_close($params['handle']);
}
return $data;
}
// --------------------------------------------------------------------
/**
* Encrypt via OpenSSL
*
* @param string $data Input data
* @param array $params Input parameters
* @return string
*/
protected function _openssl_encrypt($data, $params)
{
if (empty($params['handle']))
{
return FALSE;
}
$iv = ($iv_size = openssl_cipher_iv_length($params['handle']))
? $this->create_key($iv_size)
: NULL;
$data = openssl_encrypt(
$data,
$params['handle'],
$params['key'],
1, // DO NOT TOUCH!
$iv
);
if ($data === FALSE)
{
return FALSE;
}
return $iv.$data;
}
// --------------------------------------------------------------------
/**
* Decrypt
*
* @param string $data Encrypted data
* @param array $params Input parameters
* @return string
*/
public function decrypt($data, array $params = NULL)
{
if (($params = $this->_get_params($params)) === FALSE)
{
return FALSE;
}
if (isset($params['hmac_digest']))
{
// This might look illogical, but it is done during encryption as well ...
// The 'base64' value is effectively an inverted "raw data" parameter
$digest_size = ($params['base64'])
? $this->_digests[$params['hmac_digest']] * 2
: $this->_digests[$params['hmac_digest']];
if (self::strlen($data) <= $digest_size)
{
return FALSE;
}
$hmac_input = self::substr($data, 0, $digest_size);
$data = self::substr($data, $digest_size);
isset($params['hmac_key']) OR $params['hmac_key'] = $this->hkdf($this->_key, 'sha512', NULL, NULL, 'authentication');
$hmac_check = hash_hmac($params['hmac_digest'], $data, $params['hmac_key'], ! $params['base64']);
// Time-attack-safe comparison
$diff = 0;
for ($i = 0; $i < $digest_size; $i++)
{
$diff |= ord($hmac_input[$i]) ^ ord($hmac_check[$i]);
}
if ($diff !== 0)
{
return FALSE;
}
}
if ($params['base64'])
{
$data = base64_decode($data);
}
isset($params['key']) OR $params['key'] = $this->hkdf($this->_key, 'sha512', NULL, self::strlen($this->_key), 'encryption');
return $this->{'_'.$this->_driver.'_decrypt'}($data, $params);
}
// --------------------------------------------------------------------
/**
* Decrypt via MCrypt
*
* @param string $data Encrypted data
* @param array $params Input parameters
* @return string
*/
protected function _mcrypt_decrypt($data, $params)
{
if ( ! is_resource($params['handle']))
{
return FALSE;
}
// The greater-than-1 comparison is mostly a work-around for a bug,
// where 1 is returned for ARCFour instead of 0.
if (($iv_size = mcrypt_enc_get_iv_size($params['handle'])) > 1)
{
if (mcrypt_enc_get_modes_name($params['handle']) !== 'ECB')
{
$iv = self::substr($data, 0, $iv_size);
$data = self::substr($data, $iv_size);
}
else
{
// MCrypt is dumb and this is ignored, only size matters
$iv = str_repeat("\x0", $iv_size);
}
}
else
{
$iv = NULL;
}
if (mcrypt_generic_init($params['handle'], $params['key'], $iv) < 0)
{
if ($params['handle'] !== $this->_handle)
{
mcrypt_module_close($params['handle']);
}
return FALSE;
}
$data = mdecrypt_generic($params['handle'], $data);
// Remove PKCS#7 padding, if necessary
if (in_array(strtolower(mcrypt_enc_get_modes_name($params['handle'])), array('cbc', 'ecb'), TRUE))
{
$data = self::substr($data, 0, -ord($data[self::strlen($data)-1]));
}
mcrypt_generic_deinit($params['handle']);
if ($params['handle'] !== $this->_handle)
{
mcrypt_module_close($params['handle']);
}
return $data;
}
// --------------------------------------------------------------------
/**
* Decrypt via OpenSSL
*
* @param string $data Encrypted data
* @param array $params Input parameters
* @return string
*/
protected function _openssl_decrypt($data, $params)
{
if ($iv_size = openssl_cipher_iv_length($params['handle']))
{
$iv = self::substr($data, 0, $iv_size);
$data = self::substr($data, $iv_size);
}
else
{
$iv = NULL;
}
return empty($params['handle'])
? FALSE
: openssl_decrypt(
$data,
$params['handle'],
$params['key'],
1, // DO NOT TOUCH!
$iv
);
}
// --------------------------------------------------------------------
/**
* Get params
*
* @param array $params Input parameters
* @return array
*/
protected function _get_params($params)
{
if (empty($params))
{
return isset($this->_cipher, $this->_mode, $this->_key, $this->_handle)
? array(
'handle' => $this->_handle,
'cipher' => $this->_cipher,
'mode' => $this->_mode,
'key' => NULL,
'base64' => TRUE,
'hmac_digest' => 'sha512',
'hmac_key' => NULL
)
: FALSE;
}
elseif ( ! isset($params['cipher'], $params['mode'], $params['key']))
{
return FALSE;
}
if (isset($params['mode']))
{
$params['mode'] = strtolower($params['mode']);
if ( ! isset($this->_modes[$this->_driver][$params['mode']]))
{
return FALSE;
}
$params['mode'] = $this->_modes[$this->_driver][$params['mode']];
}
if (isset($params['hmac']) && $params['hmac'] === FALSE)
{
$params['hmac_digest'] = $params['hmac_key'] = NULL;
}
else
{
if ( ! isset($params['hmac_key']))
{
return FALSE;
}
elseif (isset($params['hmac_digest']))
{
$params['hmac_digest'] = strtolower($params['hmac_digest']);
if ( ! isset($this->_digests[$params['hmac_digest']]))
{
return FALSE;
}
}
else
{
$params['hmac_digest'] = 'sha512';
}
}
$params = array(
'handle' => NULL,
'cipher' => $params['cipher'],
'mode' => $params['mode'],
'key' => $params['key'],
'base64' => isset($params['raw_data']) ? ! $params['raw_data'] : FALSE,
'hmac_digest' => $params['hmac_digest'],
'hmac_key' => $params['hmac_key']
);
$this->_cipher_alias($params['cipher']);
$params['handle'] = ($params['cipher'] !== $this->_cipher OR $params['mode'] !== $this->_mode)
? $this->{'_'.$this->_driver.'_get_handle'}($params['cipher'], $params['mode'])
: $this->_handle;
return $params;
}
// --------------------------------------------------------------------
/**
* Get MCrypt handle
*
* @param string $cipher Cipher name
* @param string $mode Encryption mode
* @return resource
*/
protected function _mcrypt_get_handle($cipher, $mode)
{
return mcrypt_module_open($cipher, '', $mode, '');
}
// --------------------------------------------------------------------
/**
* Get OpenSSL handle
*
* @param string $cipher Cipher name
* @param string $mode Encryption mode
* @return string
*/
protected function _openssl_get_handle($cipher, $mode)
{
// OpenSSL methods aren't suffixed with '-stream' for this mode
return ($mode === 'stream')
? $cipher
: $cipher.'-'.$mode;
}
// --------------------------------------------------------------------
/**
* Cipher alias
*
* Tries to translate cipher names between MCrypt and OpenSSL's "dialects".
*
* @param string $cipher Cipher name
* @return void
*/
protected function _cipher_alias(&$cipher)
{
static $dictionary;
if (empty($dictionary))
{
$dictionary = array(
'mcrypt' => array(
'aes-128' => 'rijndael-128',
'aes-192' => 'rijndael-128',
'aes-256' => 'rijndael-128',
'des3-ede3' => 'tripledes',
'bf' => 'blowfish',
'cast5' => 'cast-128',
'rc4' => 'arcfour',
'rc4-40' => 'arcfour'
),
'openssl' => array(
'rijndael-128' => 'aes-128',
'tripledes' => 'des-ede3',
'blowfish' => 'bf',
'cast-128' => 'cast5',
'arcfour' => 'rc4-40',
'rc4' => 'rc4-40'
)
);
// Notes:
//
// - Rijndael-128 is, at the same time all three of AES-128,
// AES-192 and AES-256. The only difference between them is
// the key size. Rijndael-192, Rijndael-256 on the other hand
// also have different block sizes and are NOT AES-compatible.
//
// - Blowfish is said to be supporting key sizes between
// 4 and 56 bytes, but it appears that between MCrypt and
// OpenSSL, only those of 16 and more bytes are compatible.
// Also, don't know what MCrypt's 'blowfish-compat' is.
//
// - CAST-128/CAST5 produces a longer cipher when encrypted via
// OpenSSL, but (strangely enough) can be decrypted by either
// extension anyway.
// Also, it appears that OpenSSL uses 16 rounds regardless of
// the key size, while RFC2144 says that for key sizes lower
// than 11 bytes, only 12 rounds should be used. This makes
// it portable only with keys of between 11 and 16 bytes.
//
// - RC4 (ARCFour) has a strange implementation under OpenSSL.
// Its 'rc4-40' cipher method seems to work flawlessly, yet
// there's another one, 'rc4' that only works with a 16-byte key.
//
// - DES is compatible, but doesn't need an alias.
//
// Other seemingly matching ciphers between MCrypt, OpenSSL:
//
// - RC2 is NOT compatible and only an obscure forum post
// confirms that it is MCrypt's fault.
}
if (isset($dictionary[$this->_driver][$cipher]))
{
$cipher = $dictionary[$this->_driver][$cipher];
}
}
// --------------------------------------------------------------------
/**
* HKDF
*
* @link https://tools.ietf.org/rfc/rfc5869.txt
* @param $key Input key
* @param $digest A SHA-2 hashing algorithm
* @param $salt Optional salt
* @param $length Output length (defaults to the selected digest size)
* @param $info Optional context/application-specific info
* @return string A pseudo-random key
*/
public function hkdf($key, $digest = 'sha512', $salt = NULL, $length = NULL, $info = '')
{
if ( ! isset($this->_digests[$digest]))
{
return FALSE;
}
if (empty($length) OR ! is_int($length))
{
$length = $this->_digests[$digest];
}
elseif ($length > (255 * $this->_digests[$digest]))
{
return FALSE;
}
self::strlen($salt) OR $salt = str_repeat("\0", $this->_digests[$digest]);
$prk = hash_hmac($digest, $key, $salt, TRUE);
$key = '';
for ($key_block = '', $block_index = 1; self::strlen($key) < $length; $block_index++)
{
$key_block = hash_hmac($digest, $key_block.$info.chr($block_index), $prk, TRUE);
$key .= $key_block;
}
return self::substr($key, 0, $length);
}
// --------------------------------------------------------------------
/**
* __get() magic
*
* @param string $key Property name
* @return mixed
*/
public function __get($key)
{
// Because aliases
if ($key === 'mode')
{
return array_search($this->_mode, $this->_modes[$this->_driver], TRUE);
}
elseif (in_array($key, array('cipher', 'driver', 'drivers', 'digests'), TRUE))
{
return $this->{'_'.$key};
}
return NULL;
}
// --------------------------------------------------------------------
/**
* Byte-safe strlen()
*
* @param string $str
* @return int
*/
protected static function strlen($str)
{
return (self::$func_overload)
? mb_strlen($str, '8bit')
: strlen($str);
}
// --------------------------------------------------------------------
/**
* Byte-safe substr()
*
* @param string $str
* @param int $start
* @param int $length
* @return string
*/
protected static function substr($str, $start, $length = NULL)
{
if (self::$func_overload)
{
// mb_substr($str, $start, null, '8bit') returns an empty
// string on PHP 5.3
isset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start);
return mb_substr($str, $start, $length, '8bit');
}
return isset($length)
? substr($str, $start, $length)
: substr($str, $start);
}
}
PK ! 1ftæÚ’ Ú’ libraries/Form_validation.phpnu „[µü¤ ';
/**
* End tag for error wrapping
*
* @var string
*/
protected $_error_suffix = '
';
/**
* Custom error message
*
* @var string
*/
protected $error_string = '';
/**
* Whether the form data has been validated as safe
*
* @var bool
*/
protected $_safe_form_data = FALSE;
/**
* Custom data to validate
*
* @var array
*/
public $validation_data = array();
/**
* Initialize Form_Validation class
*
* @param array $rules
* @return void
*/
public function __construct($rules = array())
{
$this->CI =& get_instance();
// applies delimiters set in config file.
if (isset($rules['error_prefix']))
{
$this->_error_prefix = $rules['error_prefix'];
unset($rules['error_prefix']);
}
if (isset($rules['error_suffix']))
{
$this->_error_suffix = $rules['error_suffix'];
unset($rules['error_suffix']);
}
// Validation rules can be stored in a config file.
$this->_config_rules = $rules;
// Automatically load the form helper
$this->CI->load->helper('form');
log_message('info', 'Form Validation Class Initialized');
}
// --------------------------------------------------------------------
/**
* Set Rules
*
* This function takes an array of field names and validation
* rules as input, any custom error messages, validates the info,
* and stores it
*
* @param mixed $field
* @param string $label
* @param mixed $rules
* @param array $errors
* @return CI_Form_validation
*/
public function set_rules($field, $label = '', $rules = array(), $errors = array())
{
// No reason to set rules if we have no POST data
// or a validation array has not been specified
if ($this->CI->input->method() !== 'post' && empty($this->validation_data))
{
return $this;
}
// If an array was passed via the first parameter instead of individual string
// values we cycle through it and recursively call this function.
if (is_array($field))
{
foreach ($field as $row)
{
// Houston, we have a problem...
if ( ! isset($row['field'], $row['rules']))
{
continue;
}
// If the field label wasn't passed we use the field name
$label = isset($row['label']) ? $row['label'] : $row['field'];
// Add the custom error message array
$errors = (isset($row['errors']) && is_array($row['errors'])) ? $row['errors'] : array();
// Here we go!
$this->set_rules($row['field'], $label, $row['rules'], $errors);
}
return $this;
}
// No fields or no rules? Nothing to do...
if ( ! is_string($field) OR $field === '' OR empty($rules))
{
return $this;
}
elseif ( ! is_array($rules))
{
// BC: Convert pipe-separated rules string to an array
if ( ! is_string($rules))
{
return $this;
}
$rules = preg_split('/\|(?![^\[]*\])/', $rules);
}
// If the field label wasn't passed we use the field name
$label = ($label === '') ? $field : $label;
$indexes = array();
// Is the field name an array? If it is an array, we break it apart
// into its components so that we can fetch the corresponding POST data later
if (($is_array = (bool) preg_match_all('/\[(.*?)\]/', $field, $matches)) === TRUE)
{
sscanf($field, '%[^[][', $indexes[0]);
for ($i = 0, $c = count($matches[0]); $i < $c; $i++)
{
if ($matches[1][$i] !== '')
{
$indexes[] = $matches[1][$i];
}
}
}
// Build our master array
$this->_field_data[$field] = array(
'field' => $field,
'label' => $label,
'rules' => $rules,
'errors' => $errors,
'is_array' => $is_array,
'keys' => $indexes,
'postdata' => NULL,
'error' => ''
);
return $this;
}
// --------------------------------------------------------------------
/**
* By default, form validation uses the $_POST array to validate
*
* If an array is set through this method, then this array will
* be used instead of the $_POST array
*
* Note that if you are validating multiple arrays, then the
* reset_validation() function should be called after validating
* each array due to the limitations of CI's singleton
*
* @param array $data
* @return CI_Form_validation
*/
public function set_data(array $data)
{
if ( ! empty($data))
{
$this->validation_data = $data;
}
return $this;
}
// --------------------------------------------------------------------
/**
* Set Error Message
*
* Lets users set their own error messages on the fly. Note:
* The key name has to match the function name that it corresponds to.
*
* @param array
* @param string
* @return CI_Form_validation
*/
public function set_message($lang, $val = '')
{
if ( ! is_array($lang))
{
$lang = array($lang => $val);
}
$this->_error_messages = array_merge($this->_error_messages, $lang);
return $this;
}
// --------------------------------------------------------------------
/**
* Set The Error Delimiter
*
* Permits a prefix/suffix to be added to each error message
*
* @param string
* @param string
* @return CI_Form_validation
*/
public function set_error_delimiters($prefix = '
', $suffix = '
')
{
$this->_error_prefix = $prefix;
$this->_error_suffix = $suffix;
return $this;
}
// --------------------------------------------------------------------
/**
* Get Error Message
*
* Gets the error message associated with a particular field
*
* @param string $field Field name
* @param string $prefix HTML start tag
* @param string $suffix HTML end tag
* @return string
*/
public function error($field, $prefix = '', $suffix = '')
{
if (empty($this->_field_data[$field]['error']))
{
return '';
}
if ($prefix === '')
{
$prefix = $this->_error_prefix;
}
if ($suffix === '')
{
$suffix = $this->_error_suffix;
}
return $prefix.$this->_field_data[$field]['error'].$suffix;
}
// --------------------------------------------------------------------
/**
* Get Array of Error Messages
*
* Returns the error messages as an array
*
* @return array
*/
public function error_array()
{
return $this->_error_array;
}
// --------------------------------------------------------------------
/**
* Error String
*
* Returns the error messages as a string, wrapped in the error delimiters
*
* @param string
* @param string
* @return string
*/
public function error_string($prefix = '', $suffix = '')
{
// No errors, validation passes!
if (count($this->_error_array) === 0)
{
return '';
}
if ($prefix === '')
{
$prefix = $this->_error_prefix;
}
if ($suffix === '')
{
$suffix = $this->_error_suffix;
}
// Generate the error string
$str = '';
foreach ($this->_error_array as $val)
{
if ($val !== '')
{
$str .= $prefix.$val.$suffix."\n";
}
}
return $str;
}
// --------------------------------------------------------------------
/**
* Run the Validator
*
* This function does all the work.
*
* @param string $group
* @return bool
*/
public function run($group = '')
{
$validation_array = empty($this->validation_data)
? $_POST
: $this->validation_data;
// Does the _field_data array containing the validation rules exist?
// If not, we look to see if they were assigned via a config file
if (count($this->_field_data) === 0)
{
// No validation rules? We're done...
if (count($this->_config_rules) === 0)
{
return FALSE;
}
if (empty($group))
{
// Is there a validation rule for the particular URI being accessed?
$group = trim($this->CI->uri->ruri_string(), '/');
isset($this->_config_rules[$group]) OR $group = $this->CI->router->class.'/'.$this->CI->router->method;
}
$this->set_rules(isset($this->_config_rules[$group]) ? $this->_config_rules[$group] : $this->_config_rules);
// Were we able to set the rules correctly?
if (count($this->_field_data) === 0)
{
log_message('debug', 'Unable to find validation rules');
return FALSE;
}
}
// Load the language file containing error messages
$this->CI->lang->load('form_validation');
// Cycle through the rules for each field and match the corresponding $validation_data item
foreach ($this->_field_data as $field => &$row)
{
// Fetch the data from the validation_data array item and cache it in the _field_data array.
// Depending on whether the field name is an array or a string will determine where we get it from.
if ($row['is_array'] === TRUE)
{
$this->_field_data[$field]['postdata'] = $this->_reduce_array($validation_array, $row['keys']);
}
elseif (isset($validation_array[$field]))
{
$this->_field_data[$field]['postdata'] = $validation_array[$field];
}
}
// Execute validation rules
// Note: A second foreach (for now) is required in order to avoid false-positives
// for rules like 'matches', which correlate to other validation fields.
foreach ($this->_field_data as $field => &$row)
{
// Don't try to validate if we have no rules set
if (empty($row['rules']))
{
continue;
}
$this->_execute($row, $row['rules'], $row['postdata']);
}
// Did we end up with any errors?
$total_errors = count($this->_error_array);
if ($total_errors > 0)
{
$this->_safe_form_data = TRUE;
}
// Now we need to re-set the POST data with the new, processed data
empty($this->validation_data) && $this->_reset_post_array();
return ($total_errors === 0);
}
// --------------------------------------------------------------------
/**
* Prepare rules
*
* Re-orders the provided rules in order of importance, so that
* they can easily be executed later without weird checks ...
*
* "Callbacks" are given the highest priority (always called),
* followed by 'required' (called if callbacks didn't fail),
* and then every next rule depends on the previous one passing.
*
* @param array $rules
* @return array
*/
protected function _prepare_rules($rules)
{
$new_rules = array();
$callbacks = array();
foreach ($rules as &$rule)
{
// Let 'required' always be the first (non-callback) rule
if ($rule === 'required')
{
array_unshift($new_rules, 'required');
}
// 'isset' is a kind of a weird alias for 'required' ...
elseif ($rule === 'isset' && (empty($new_rules) OR $new_rules[0] !== 'required'))
{
array_unshift($new_rules, 'isset');
}
// The old/classic 'callback_'-prefixed rules
elseif (is_string($rule) && strncmp('callback_', $rule, 9) === 0)
{
$callbacks[] = $rule;
}
// Proper callables
elseif (is_callable($rule))
{
$callbacks[] = $rule;
}
// "Named" callables; i.e. array('name' => $callable)
elseif (is_array($rule) && isset($rule[0], $rule[1]) && is_callable($rule[1]))
{
$callbacks[] = $rule;
}
// Everything else goes at the end of the queue
else
{
$new_rules[] = $rule;
}
}
return array_merge($callbacks, $new_rules);
}
// --------------------------------------------------------------------
/**
* Traverse a multidimensional $_POST array index until the data is found
*
* @param array
* @param array
* @param int
* @return mixed
*/
protected function _reduce_array($array, $keys, $i = 0)
{
if (is_array($array) && isset($keys[$i]))
{
return isset($array[$keys[$i]]) ? $this->_reduce_array($array[$keys[$i]], $keys, ($i+1)) : NULL;
}
// NULL must be returned for empty fields
return ($array === '') ? NULL : $array;
}
// --------------------------------------------------------------------
/**
* Re-populate the _POST array with our finalized and processed data
*
* @return void
*/
protected function _reset_post_array()
{
foreach ($this->_field_data as $field => $row)
{
if ($row['postdata'] !== NULL)
{
if ($row['is_array'] === FALSE)
{
isset($_POST[$field]) && $_POST[$field] = is_array($row['postdata']) ? NULL : $row['postdata'];
}
else
{
// start with a reference
$post_ref =& $_POST;
// before we assign values, make a reference to the right POST key
if (count($row['keys']) === 1)
{
$post_ref =& $post_ref[current($row['keys'])];
}
else
{
foreach ($row['keys'] as $val)
{
$post_ref =& $post_ref[$val];
}
}
$post_ref = $row['postdata'];
}
}
}
}
// --------------------------------------------------------------------
/**
* Executes the Validation routines
*
* @param array
* @param array
* @param mixed
* @param int
* @return mixed
*/
protected function _execute($row, $rules, $postdata = NULL, $cycles = 0)
{
// If the $_POST data is an array we will run a recursive call
//
// Note: We MUST check if the array is empty or not!
// Otherwise empty arrays will always pass validation.
if (is_array($postdata) && ! empty($postdata))
{
foreach ($postdata as $key => $val)
{
$this->_execute($row, $rules, $val, $key);
}
return;
}
$rules = $this->_prepare_rules($rules);
foreach ($rules as $rule)
{
$_in_array = FALSE;
// We set the $postdata variable with the current data in our master array so that
// each cycle of the loop is dealing with the processed data from the last cycle
if ($row['is_array'] === TRUE && is_array($this->_field_data[$row['field']]['postdata']))
{
// We shouldn't need this safety, but just in case there isn't an array index
// associated with this cycle we'll bail out
if ( ! isset($this->_field_data[$row['field']]['postdata'][$cycles]))
{
continue;
}
$postdata = $this->_field_data[$row['field']]['postdata'][$cycles];
$_in_array = TRUE;
}
else
{
// If we get an array field, but it's not expected - then it is most likely
// somebody messing with the form on the client side, so we'll just consider
// it an empty field
$postdata = is_array($this->_field_data[$row['field']]['postdata'])
? NULL
: $this->_field_data[$row['field']]['postdata'];
}
// Is the rule a callback?
$callback = $callable = FALSE;
if (is_string($rule))
{
if (strpos($rule, 'callback_') === 0)
{
$rule = substr($rule, 9);
$callback = TRUE;
}
}
elseif (is_callable($rule))
{
$callable = TRUE;
}
elseif (is_array($rule) && isset($rule[0], $rule[1]) && is_callable($rule[1]))
{
// We have a "named" callable, so save the name
$callable = $rule[0];
$rule = $rule[1];
}
// Strip the parameter (if exists) from the rule
// Rules can contain a parameter: max_length[5]
$param = FALSE;
if ( ! $callable && preg_match('/(.*?)\[(.*)\]/', $rule, $match))
{
$rule = $match[1];
$param = $match[2];
}
// Ignore empty, non-required inputs with a few exceptions ...
if (
($postdata === NULL OR $postdata === '')
&& $callback === FALSE
&& $callable === FALSE
&& ! in_array($rule, array('required', 'isset', 'matches'), TRUE)
)
{
continue;
}
// Call the function that corresponds to the rule
if ($callback OR $callable !== FALSE)
{
if ($callback)
{
if ( ! method_exists($this->CI, $rule))
{
log_message('debug', 'Unable to find callback validation rule: '.$rule);
$result = FALSE;
}
else
{
// Run the function and grab the result
$result = $this->CI->$rule($postdata, $param);
}
}
else
{
$result = is_array($rule)
? $rule[0]->{$rule[1]}($postdata)
: $rule($postdata);
// Is $callable set to a rule name?
if ($callable !== FALSE)
{
$rule = $callable;
}
}
// Re-assign the result to the master data array
if ($_in_array === TRUE)
{
$this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;
}
else
{
$this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;
}
}
elseif ( ! method_exists($this, $rule))
{
// If our own wrapper function doesn't exist we see if a native PHP function does.
// Users can use any native PHP function call that has one param.
if (function_exists($rule))
{
// Native PHP functions issue warnings if you pass them more parameters than they use
$result = ($param !== FALSE) ? $rule($postdata, $param) : $rule($postdata);
if ($_in_array === TRUE)
{
$this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;
}
else
{
$this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;
}
}
else
{
log_message('debug', 'Unable to find validation rule: '.$rule);
$result = FALSE;
}
}
else
{
$result = $this->$rule($postdata, $param);
if ($_in_array === TRUE)
{
$this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;
}
else
{
$this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;
}
}
// Did the rule test negatively? If so, grab the error.
if ($result === FALSE)
{
// Callable rules might not have named error messages
if ( ! is_string($rule))
{
$line = $this->CI->lang->line('form_validation_error_message_not_set').'(Anonymous function)';
}
else
{
$line = $this->_get_error_message($rule, $row['field']);
}
// Is the parameter we are inserting into the error message the name
// of another field? If so we need to grab its "field label"
if (isset($this->_field_data[$param], $this->_field_data[$param]['label']))
{
$param = $this->_translate_fieldname($this->_field_data[$param]['label']);
}
// Build the error message
$message = $this->_build_error_msg($line, $this->_translate_fieldname($row['label']), $param);
// Save the error message
$this->_field_data[$row['field']]['error'] = $message;
if ( ! isset($this->_error_array[$row['field']]))
{
$this->_error_array[$row['field']] = $message;
}
return;
}
}
}
// --------------------------------------------------------------------
/**
* Get the error message for the rule
*
* @param string $rule The rule name
* @param string $field The field name
* @return string
*/
protected function _get_error_message($rule, $field)
{
// check if a custom message is defined through validation config row.
if (isset($this->_field_data[$field]['errors'][$rule]))
{
return $this->_field_data[$field]['errors'][$rule];
}
// check if a custom message has been set using the set_message() function
elseif (isset($this->_error_messages[$rule]))
{
return $this->_error_messages[$rule];
}
elseif (FALSE !== ($line = $this->CI->lang->line('form_validation_'.$rule)))
{
return $line;
}
// DEPRECATED support for non-prefixed keys, lang file again
elseif (FALSE !== ($line = $this->CI->lang->line($rule, FALSE)))
{
return $line;
}
return $this->CI->lang->line('form_validation_error_message_not_set').'('.$rule.')';
}
// --------------------------------------------------------------------
/**
* Translate a field name
*
* @param string the field name
* @return string
*/
protected function _translate_fieldname($fieldname)
{
// Do we need to translate the field name? We look for the prefix 'lang:' to determine this
// If we find one, but there's no translation for the string - just return it
if (sscanf($fieldname, 'lang:%s', $line) === 1 && FALSE === ($fieldname = $this->CI->lang->line($line, FALSE)))
{
return $line;
}
return $fieldname;
}
// --------------------------------------------------------------------
/**
* Build an error message using the field and param.
*
* @param string The error message line
* @param string A field's human name
* @param mixed A rule's optional parameter
* @return string
*/
protected function _build_error_msg($line, $field = '', $param = '')
{
// Check for %s in the string for legacy support.
if (strpos($line, '%s') !== FALSE)
{
return sprintf($line, $field, $param);
}
return str_replace(array('{field}', '{param}'), array($field, $param), $line);
}
// --------------------------------------------------------------------
/**
* Checks if the rule is present within the validator
*
* Permits you to check if a rule is present within the validator
*
* @param string the field name
* @return bool
*/
public function has_rule($field)
{
return isset($this->_field_data[$field]);
}
// --------------------------------------------------------------------
/**
* Get the value from a form
*
* Permits you to repopulate a form field with the value it was submitted
* with, or, if that value doesn't exist, with the default
*
* @param string the field name
* @param string
* @return string
*/
public function set_value($field = '', $default = '')
{
if ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))
{
return $default;
}
// If the data is an array output them one at a time.
// E.g: form_input('name[]', set_value('name[]');
if (is_array($this->_field_data[$field]['postdata']))
{
return array_shift($this->_field_data[$field]['postdata']);
}
return $this->_field_data[$field]['postdata'];
}
// --------------------------------------------------------------------
/**
* Set Select
*
* Enables pull-down lists to be set to the value the user
* selected in the event of an error
*
* @param string
* @param string
* @param bool
* @return string
*/
public function set_select($field = '', $value = '', $default = FALSE)
{
if ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))
{
return ($default === TRUE && count($this->_field_data) === 0) ? ' selected="selected"' : '';
}
$field = $this->_field_data[$field]['postdata'];
$value = (string) $value;
if (is_array($field))
{
// Note: in_array('', array(0)) returns TRUE, do not use it
foreach ($field as &$v)
{
if ($value === $v)
{
return ' selected="selected"';
}
}
return '';
}
elseif (($field === '' OR $value === '') OR ($field !== $value))
{
return '';
}
return ' selected="selected"';
}
// --------------------------------------------------------------------
/**
* Set Radio
*
* Enables radio buttons to be set to the value the user
* selected in the event of an error
*
* @param string
* @param string
* @param bool
* @return string
*/
public function set_radio($field = '', $value = '', $default = FALSE)
{
if ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))
{
return ($default === TRUE && count($this->_field_data) === 0) ? ' checked="checked"' : '';
}
$field = $this->_field_data[$field]['postdata'];
$value = (string) $value;
if (is_array($field))
{
// Note: in_array('', array(0)) returns TRUE, do not use it
foreach ($field as &$v)
{
if ($value === $v)
{
return ' checked="checked"';
}
}
return '';
}
elseif (($field === '' OR $value === '') OR ($field !== $value))
{
return '';
}
return ' checked="checked"';
}
// --------------------------------------------------------------------
/**
* Set Checkbox
*
* Enables checkboxes to be set to the value the user
* selected in the event of an error
*
* @param string
* @param string
* @param bool
* @return string
*/
public function set_checkbox($field = '', $value = '', $default = FALSE)
{
// Logic is exactly the same as for radio fields
return $this->set_radio($field, $value, $default);
}
// --------------------------------------------------------------------
/**
* Required
*
* @param string
* @return bool
*/
public function required($str)
{
return is_array($str)
? (empty($str) === FALSE)
: (trim($str) !== '');
}
// --------------------------------------------------------------------
/**
* Performs a Regular Expression match test.
*
* @param string
* @param string regex
* @return bool
*/
public function regex_match($str, $regex)
{
return (bool) preg_match($regex, $str);
}
// --------------------------------------------------------------------
/**
* Match one field to another
*
* @param string $str string to compare against
* @param string $field
* @return bool
*/
public function matches($str, $field)
{
return isset($this->_field_data[$field], $this->_field_data[$field]['postdata'])
? ($str === $this->_field_data[$field]['postdata'])
: FALSE;
}
// --------------------------------------------------------------------
/**
* Differs from another field
*
* @param string
* @param string field
* @return bool
*/
public function differs($str, $field)
{
return ! (isset($this->_field_data[$field]) && $this->_field_data[$field]['postdata'] === $str);
}
// --------------------------------------------------------------------
/**
* Is Unique
*
* Check if the input value doesn't already exist
* in the specified database field.
*
* @param string $str
* @param string $field
* @return bool
*/
public function is_unique($str, $field)
{
sscanf($field, '%[^.].%[^.]', $table, $field);
return isset($this->CI->db)
? ($this->CI->db->limit(1)->get_where($table, array($field => $str))->num_rows() === 0)
: FALSE;
}
// --------------------------------------------------------------------
/**
* Minimum Length
*
* @param string
* @param string
* @return bool
*/
public function min_length($str, $val)
{
if ( ! is_numeric($val))
{
return FALSE;
}
return ($val <= mb_strlen($str));
}
// --------------------------------------------------------------------
/**
* Max Length
*
* @param string
* @param string
* @return bool
*/
public function max_length($str, $val)
{
if ( ! is_numeric($val))
{
return FALSE;
}
return ($val >= mb_strlen($str));
}
// --------------------------------------------------------------------
/**
* Exact Length
*
* @param string
* @param string
* @return bool
*/
public function exact_length($str, $val)
{
if ( ! is_numeric($val))
{
return FALSE;
}
return (mb_strlen($str) === (int) $val);
}
// --------------------------------------------------------------------
/**
* Valid URL
*
* @param string $str
* @return bool
*/
public function valid_url($str)
{
if (empty($str))
{
return FALSE;
}
elseif (preg_match('/^(?:([^:]*)\:)?\/\/(.+)$/', $str, $matches))
{
if (empty($matches[2]))
{
return FALSE;
}
elseif ( ! in_array(strtolower($matches[1]), array('http', 'https'), TRUE))
{
return FALSE;
}
$str = $matches[2];
}
// Apparently, FILTER_VALIDATE_URL doesn't reject digit-only names for some reason ...
// See https://github.com/bcit-ci/CodeIgniter/issues/5755
if (ctype_digit($str))
{
return FALSE;
}
// PHP 7 accepts IPv6 addresses within square brackets as hostnames,
// but it appears that the PR that came in with https://bugs.php.net/bug.php?id=68039
// was never merged into a PHP 5 branch ... https://3v4l.org/8PsSN
if (preg_match('/^\[([^\]]+)\]/', $str, $matches) && ! is_php('7') && filter_var($matches[1], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== FALSE)
{
$str = 'ipv6.host'.substr($str, strlen($matches[1]) + 2);
}
return (filter_var('http://'.$str, FILTER_VALIDATE_URL) !== FALSE);
}
// --------------------------------------------------------------------
/**
* Valid Email
*
* @param string
* @return bool
*/
public function valid_email($str)
{
if (function_exists('idn_to_ascii') && preg_match('#\A([^@]+)@(.+)\z#', $str, $matches))
{
$domain = defined('INTL_IDNA_VARIANT_UTS46')
? idn_to_ascii($matches[2], 0, INTL_IDNA_VARIANT_UTS46)
: idn_to_ascii($matches[2]);
if ($domain !== FALSE)
{
$str = $matches[1].'@'.$domain;
}
}
return (bool) filter_var($str, FILTER_VALIDATE_EMAIL);
}
// --------------------------------------------------------------------
/**
* Valid Emails
*
* @param string
* @return bool
*/
public function valid_emails($str)
{
if (strpos($str, ',') === FALSE)
{
return $this->valid_email(trim($str));
}
foreach (explode(',', $str) as $email)
{
if (trim($email) !== '' && $this->valid_email(trim($email)) === FALSE)
{
return FALSE;
}
}
return TRUE;
}
// --------------------------------------------------------------------
/**
* Validate IP Address
*
* @param string
* @param string 'ipv4' or 'ipv6' to validate a specific IP format
* @return bool
*/
public function valid_ip($ip, $which = '')
{
return $this->CI->input->valid_ip($ip, $which);
}
// --------------------------------------------------------------------
/**
* Alpha
*
* @param string
* @return bool
*/
public function alpha($str)
{
return ctype_alpha($str);
}
// --------------------------------------------------------------------
/**
* Alpha-numeric
*
* @param string
* @return bool
*/
public function alpha_numeric($str)
{
return ctype_alnum((string) $str);
}
// --------------------------------------------------------------------
/**
* Alpha-numeric w/ spaces
*
* @param string
* @return bool
*/
public function alpha_numeric_spaces($str)
{
return (bool) preg_match('/^[A-Z0-9 ]+$/i', $str);
}
// --------------------------------------------------------------------
/**
* Alpha-numeric with underscores and dashes
*
* @param string
* @return bool
*/
public function alpha_dash($str)
{
return (bool) preg_match('/^[a-z0-9_-]+$/i', $str);
}
// --------------------------------------------------------------------
/**
* Numeric
*
* @param string
* @return bool
*/
public function numeric($str)
{
return (bool) preg_match('/^[\-+]?[0-9]*\.?[0-9]+$/', $str);
}
// --------------------------------------------------------------------
/**
* Integer
*
* @param string
* @return bool
*/
public function integer($str)
{
return (bool) preg_match('/^[\-+]?[0-9]+$/', $str);
}
// --------------------------------------------------------------------
/**
* Decimal number
*
* @param string
* @return bool
*/
public function decimal($str)
{
return (bool) preg_match('/^[\-+]?[0-9]+\.[0-9]+$/', $str);
}
// --------------------------------------------------------------------
/**
* Greater than
*
* @param string
* @param int
* @return bool
*/
public function greater_than($str, $min)
{
return is_numeric($str) ? ($str > $min) : FALSE;
}
// --------------------------------------------------------------------
/**
* Equal to or Greater than
*
* @param string
* @param int
* @return bool
*/
public function greater_than_equal_to($str, $min)
{
return is_numeric($str) ? ($str >= $min) : FALSE;
}
// --------------------------------------------------------------------
/**
* Less than
*
* @param string
* @param int
* @return bool
*/
public function less_than($str, $max)
{
return is_numeric($str) ? ($str < $max) : FALSE;
}
// --------------------------------------------------------------------
/**
* Equal to or Less than
*
* @param string
* @param int
* @return bool
*/
public function less_than_equal_to($str, $max)
{
return is_numeric($str) ? ($str <= $max) : FALSE;
}
// --------------------------------------------------------------------
/**
* Value should be within an array of values
*
* @param string
* @param string
* @return bool
*/
public function in_list($value, $list)
{
return in_array($value, explode(',', $list), TRUE);
}
// --------------------------------------------------------------------
/**
* Is a Natural number (0,1,2,3, etc.)
*
* @param string
* @return bool
*/
public function is_natural($str)
{
return ctype_digit((string) $str);
}
// --------------------------------------------------------------------
/**
* Is a Natural number, but not a zero (1,2,3, etc.)
*
* @param string
* @return bool
*/
public function is_natural_no_zero($str)
{
return ($str != 0 && ctype_digit((string) $str));
}
// --------------------------------------------------------------------
/**
* Valid Base64
*
* Tests a string for characters outside of the Base64 alphabet
* as defined by RFC 2045 http://www.faqs.org/rfcs/rfc2045
*
* @param string
* @return bool
*/
public function valid_base64($str)
{
return (base64_encode(base64_decode($str)) === $str);
}
// --------------------------------------------------------------------
/**
* Prep data for form
*
* This function allows HTML to be safely shown in a form.
* Special characters are converted.
*
* @deprecated 3.0.6 Not used anywhere within the framework and pretty much useless
* @param mixed $data Input data
* @return mixed
*/
public function prep_for_form($data)
{
if ($this->_safe_form_data === FALSE OR empty($data))
{
return $data;
}
if (is_array($data))
{
foreach ($data as $key => $val)
{
$data[$key] = $this->prep_for_form($val);
}
return $data;
}
return str_replace(array("'", '"', '<', '>'), array(''', '"', '<', '>'), stripslashes($data));
}
// --------------------------------------------------------------------
/**
* Prep URL
*
* @param string
* @return string
*/
public function prep_url($str = '')
{
if ($str === 'http://' OR $str === '')
{
return '';
}
if (strpos($str, 'http://') !== 0 && strpos($str, 'https://') !== 0)
{
return 'http://'.$str;
}
return $str;
}
// --------------------------------------------------------------------
/**
* Strip Image Tags
*
* @param string
* @return string
*/
public function strip_image_tags($str)
{
return $this->CI->security->strip_image_tags($str);
}
// --------------------------------------------------------------------
/**
* Convert PHP tags to entities
*
* @param string
* @return string
*/
public function encode_php_tags($str)
{
return str_replace(array('', '?>'), array('<?', '?>'), $str);
}
// --------------------------------------------------------------------
/**
* Reset validation vars
*
* Prevents subsequent validation routines from being affected by the
* results of any previous validation routine due to the CI singleton.
*
* @return CI_Form_validation
*/
public function reset_validation()
{
$this->_field_data = array();
$this->_error_array = array();
$this->_error_messages = array();
$this->error_string = '';
return $this;
}
}
PK ! Œé~¨ ¨ libraries/Image_lib.phpnu „[µü¤ 0)
{
$this->initialize($props);
}
/**
* A work-around for some improperly formatted, but
* usable JPEGs; known to be produced by Samsung
* smartphones' front-facing cameras.
*
* @see https://github.com/bcit-ci/CodeIgniter/issues/4967
* @see https://bugs.php.net/bug.php?id=72404
*/
ini_set('gd.jpeg_ignore_warning', 1);
log_message('info', 'Image Lib Class Initialized');
}
// --------------------------------------------------------------------
/**
* Initialize image properties
*
* Resets values in case this class is used in a loop
*
* @return void
*/
public function clear()
{
$props = array('thumb_marker', 'library_path', 'source_image', 'new_image', 'width', 'height', 'rotation_angle', 'x_axis', 'y_axis', 'wm_text', 'wm_overlay_path', 'wm_font_path', 'wm_shadow_color', 'source_folder', 'dest_folder', 'mime_type', 'orig_width', 'orig_height', 'image_type', 'size_str', 'full_src_path', 'full_dst_path');
foreach ($props as $val)
{
$this->$val = '';
}
$this->image_library = 'gd2';
$this->dynamic_output = FALSE;
$this->quality = 90;
$this->create_thumb = FALSE;
$this->thumb_marker = '_thumb';
$this->maintain_ratio = TRUE;
$this->master_dim = 'auto';
$this->wm_type = 'text';
$this->wm_x_transp = 4;
$this->wm_y_transp = 4;
$this->wm_font_size = 17;
$this->wm_vrt_alignment = 'B';
$this->wm_hor_alignment = 'C';
$this->wm_padding = 0;
$this->wm_hor_offset = 0;
$this->wm_vrt_offset = 0;
$this->wm_font_color = '#ffffff';
$this->wm_shadow_distance = 2;
$this->wm_opacity = 50;
$this->create_fnc = 'imagecreatetruecolor';
$this->copy_fnc = 'imagecopyresampled';
$this->error_msg = array();
$this->wm_use_drop_shadow = FALSE;
$this->wm_use_truetype = FALSE;
}
// --------------------------------------------------------------------
/**
* initialize image preferences
*
* @param array
* @return bool
*/
public function initialize($props = array())
{
// Convert array elements into class variables
if (count($props) > 0)
{
foreach ($props as $key => $val)
{
if (property_exists($this, $key))
{
if (in_array($key, array('wm_font_color', 'wm_shadow_color'), TRUE))
{
if (preg_match('/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i', $val, $matches))
{
/* $matches[1] contains our hex color value, but it might be
* both in the full 6-length format or the shortened 3-length
* value.
* We'll later need the full version, so we keep it if it's
* already there and if not - we'll convert to it. We can
* access string characters by their index as in an array,
* so we'll do that and use concatenation to form the final
* value:
*/
$val = (strlen($matches[1]) === 6)
? '#'.$matches[1]
: '#'.$matches[1][0].$matches[1][0].$matches[1][1].$matches[1][1].$matches[1][2].$matches[1][2];
}
else
{
continue;
}
}
elseif (in_array($key, array('width', 'height'), TRUE) && ! ctype_digit((string) $val))
{
continue;
}
$this->$key = $val;
}
}
}
// Is there a source image? If not, there's no reason to continue
if ($this->source_image === '')
{
$this->set_error('imglib_source_image_required');
return FALSE;
}
/* Is getimagesize() available?
*
* We use it to determine the image properties (width/height).
* Note: We need to figure out how to determine image
* properties using ImageMagick and NetPBM
*/
if ( ! function_exists('getimagesize'))
{
$this->set_error('imglib_gd_required_for_props');
return FALSE;
}
$this->image_library = strtolower($this->image_library);
/* Set the full server path
*
* The source image may or may not contain a path.
* Either way, we'll try use realpath to generate the
* full server path in order to more reliably read it.
*/
if (($full_source_path = realpath($this->source_image)) !== FALSE)
{
$full_source_path = str_replace('\\', '/', $full_source_path);
}
else
{
$full_source_path = $this->source_image;
}
$x = explode('/', $full_source_path);
$this->source_image = end($x);
$this->source_folder = str_replace($this->source_image, '', $full_source_path);
// Set the Image Properties
if ( ! $this->get_image_properties($this->source_folder.$this->source_image))
{
return FALSE;
}
/*
* Assign the "new" image name/path
*
* If the user has set a "new_image" name it means
* we are making a copy of the source image. If not
* it means we are altering the original. We'll
* set the destination filename and path accordingly.
*/
if ($this->new_image === '')
{
$this->dest_image = $this->source_image;
$this->dest_folder = $this->source_folder;
}
elseif (strpos($this->new_image, '/') === FALSE && strpos($this->new_image, '\\') === FALSE)
{
$this->dest_image = $this->new_image;
$this->dest_folder = $this->source_folder;
}
else
{
// Is there a file name?
if ( ! preg_match('#\.(jpg|jpeg|gif|png)$#i', $this->new_image))
{
$this->dest_image = $this->source_image;
$this->dest_folder = $this->new_image;
}
else
{
$x = explode('/', str_replace('\\', '/', $this->new_image));
$this->dest_image = end($x);
$this->dest_folder = str_replace($this->dest_image, '', $this->new_image);
}
$this->dest_folder = realpath($this->dest_folder).'/';
}
/* Compile the finalized filenames/paths
*
* We'll create two master strings containing the
* full server path to the source image and the
* full server path to the destination image.
* We'll also split the destination image name
* so we can insert the thumbnail marker if needed.
*/
if ($this->create_thumb === FALSE OR $this->thumb_marker === '')
{
$this->thumb_marker = '';
}
$xp = $this->explode_name($this->dest_image);
$filename = $xp['name'];
$file_ext = $xp['ext'];
$this->full_src_path = $this->source_folder.$this->source_image;
$this->full_dst_path = $this->dest_folder.$filename.$this->thumb_marker.$file_ext;
/* Should we maintain image proportions?
*
* When creating thumbs or copies, the target width/height
* might not be in correct proportion with the source
* image's width/height. We'll recalculate it here.
*/
if ($this->maintain_ratio === TRUE && ($this->width !== 0 OR $this->height !== 0))
{
$this->image_reproportion();
}
/* Was a width and height specified?
*
* If the destination width/height was not submitted we
* will use the values from the actual file
*/
if ($this->width === '')
{
$this->width = $this->orig_width;
}
if ($this->height === '')
{
$this->height = $this->orig_height;
}
// Set the quality
$this->quality = trim(str_replace('%', '', $this->quality));
if ($this->quality === '' OR $this->quality === 0 OR ! ctype_digit($this->quality))
{
$this->quality = 90;
}
// Set the x/y coordinates
is_numeric($this->x_axis) OR $this->x_axis = 0;
is_numeric($this->y_axis) OR $this->y_axis = 0;
// Watermark-related Stuff...
if ($this->wm_overlay_path !== '')
{
$this->wm_overlay_path = str_replace('\\', '/', realpath($this->wm_overlay_path));
}
if ($this->wm_shadow_color !== '')
{
$this->wm_use_drop_shadow = TRUE;
}
elseif ($this->wm_use_drop_shadow === TRUE && $this->wm_shadow_color === '')
{
$this->wm_use_drop_shadow = FALSE;
}
if ($this->wm_font_path !== '')
{
$this->wm_use_truetype = TRUE;
}
return TRUE;
}
// --------------------------------------------------------------------
/**
* Image Resize
*
* This is a wrapper function that chooses the proper
* resize function based on the protocol specified
*
* @return bool
*/
public function resize()
{
$protocol = ($this->image_library === 'gd2') ? 'image_process_gd' : 'image_process_'.$this->image_library;
return $this->$protocol('resize');
}
// --------------------------------------------------------------------
/**
* Image Crop
*
* This is a wrapper function that chooses the proper
* cropping function based on the protocol specified
*
* @return bool
*/
public function crop()
{
$protocol = ($this->image_library === 'gd2') ? 'image_process_gd' : 'image_process_'.$this->image_library;
return $this->$protocol('crop');
}
// --------------------------------------------------------------------
/**
* Image Rotate
*
* This is a wrapper function that chooses the proper
* rotation function based on the protocol specified
*
* @return bool
*/
public function rotate()
{
// Allowed rotation values
$degs = array(90, 180, 270, 'vrt', 'hor');
if ($this->rotation_angle === '' OR ! in_array($this->rotation_angle, $degs))
{
$this->set_error('imglib_rotation_angle_required');
return FALSE;
}
// Reassign the width and height
if ($this->rotation_angle === 90 OR $this->rotation_angle === 270)
{
$this->width = $this->orig_height;
$this->height = $this->orig_width;
}
else
{
$this->width = $this->orig_width;
$this->height = $this->orig_height;
}
// Choose resizing function
if ($this->image_library === 'imagemagick' OR $this->image_library === 'netpbm')
{
$protocol = 'image_process_'.$this->image_library;
return $this->$protocol('rotate');
}
return ($this->rotation_angle === 'hor' OR $this->rotation_angle === 'vrt')
? $this->image_mirror_gd()
: $this->image_rotate_gd();
}
// --------------------------------------------------------------------
/**
* Image Process Using GD/GD2
*
* This function will resize or crop
*
* @param string
* @return bool
*/
public function image_process_gd($action = 'resize')
{
$v2_override = FALSE;
// If the target width/height match the source, AND if the new file name is not equal to the old file name
// we'll simply make a copy of the original with the new name... assuming dynamic rendering is off.
if ($this->dynamic_output === FALSE && $this->orig_width === $this->width && $this->orig_height === $this->height)
{
if ($this->source_image !== $this->new_image && @copy($this->full_src_path, $this->full_dst_path))
{
chmod($this->full_dst_path, $this->file_permissions);
}
return TRUE;
}
// Let's set up our values based on the action
if ($action === 'crop')
{
// Reassign the source width/height if cropping
$this->orig_width = $this->width;
$this->orig_height = $this->height;
// GD 2.0 has a cropping bug so we'll test for it
if ($this->gd_version() !== FALSE)
{
$gd_version = str_replace('0', '', $this->gd_version());
$v2_override = ($gd_version == 2);
}
}
else
{
// If resizing the x/y axis must be zero
$this->x_axis = 0;
$this->y_axis = 0;
}
// Create the image handle
if ( ! ($src_img = $this->image_create_gd()))
{
return FALSE;
}
/* Create the image
*
* Old conditional which users report cause problems with shared GD libs who report themselves as "2.0 or greater"
* it appears that this is no longer the issue that it was in 2004, so we've removed it, retaining it in the comment
* below should that ever prove inaccurate.
*
* if ($this->image_library === 'gd2' && function_exists('imagecreatetruecolor') && $v2_override === FALSE)
*/
if ($this->image_library === 'gd2' && function_exists('imagecreatetruecolor'))
{
$create = 'imagecreatetruecolor';
$copy = 'imagecopyresampled';
}
else
{
$create = 'imagecreate';
$copy = 'imagecopyresized';
}
$dst_img = $create($this->width, $this->height);
if ($this->image_type === 3) // png we can actually preserve transparency
{
imagealphablending($dst_img, FALSE);
imagesavealpha($dst_img, TRUE);
}
$copy($dst_img, $src_img, 0, 0, $this->x_axis, $this->y_axis, $this->width, $this->height, $this->orig_width, $this->orig_height);
// Show the image
if ($this->dynamic_output === TRUE)
{
$this->image_display_gd($dst_img);
}
elseif ( ! $this->image_save_gd($dst_img)) // Or save it
{
return FALSE;
}
// Kill the file handles
imagedestroy($dst_img);
imagedestroy($src_img);
if ($this->dynamic_output !== TRUE)
{
chmod($this->full_dst_path, $this->file_permissions);
}
return TRUE;
}
// --------------------------------------------------------------------
/**
* Image Process Using ImageMagick
*
* This function will resize, crop or rotate
*
* @param string
* @return bool
*/
public function image_process_imagemagick($action = 'resize')
{
// Do we have a vaild library path?
if ($this->library_path === '')
{
$this->set_error('imglib_libpath_invalid');
return FALSE;
}
if ( ! preg_match('/convert$/i', $this->library_path))
{
$this->library_path = rtrim($this->library_path, '/').'/convert';
}
// Execute the command
$cmd = $this->library_path.' -quality '.$this->quality;
if ($action === 'crop')
{
$cmd .= ' -crop '.$this->width.'x'.$this->height.'+'.$this->x_axis.'+'.$this->y_axis;
}
elseif ($action === 'rotate')
{
$cmd .= ($this->rotation_angle === 'hor' OR $this->rotation_angle === 'vrt')
? ' -flop'
: ' -rotate '.$this->rotation_angle;
}
else // Resize
{
if($this->maintain_ratio === TRUE)
{
$cmd .= ' -resize '.$this->width.'x'.$this->height;
}
else
{
$cmd .= ' -resize '.$this->width.'x'.$this->height.'\!';
}
}
$cmd .= ' '.escapeshellarg($this->full_src_path).' '.escapeshellarg($this->full_dst_path).' 2>&1';
$retval = 1;
// exec() might be disabled
if (function_usable('exec'))
{
@exec($cmd, $output, $retval);
}
// Did it work?
if ($retval > 0)
{
$this->set_error('imglib_image_process_failed');
return FALSE;
}
chmod($this->full_dst_path, $this->file_permissions);
return TRUE;
}
// --------------------------------------------------------------------
/**
* Image Process Using NetPBM
*
* This function will resize, crop or rotate
*
* @param string
* @return bool
*/
public function image_process_netpbm($action = 'resize')
{
if ($this->library_path === '')
{
$this->set_error('imglib_libpath_invalid');
return FALSE;
}
// Build the resizing command
switch ($this->image_type)
{
case 1 :
$cmd_in = 'giftopnm';
$cmd_out = 'ppmtogif';
break;
case 2 :
$cmd_in = 'jpegtopnm';
$cmd_out = 'ppmtojpeg';
break;
case 3 :
$cmd_in = 'pngtopnm';
$cmd_out = 'ppmtopng';
break;
}
if ($action === 'crop')
{
$cmd_inner = 'pnmcut -left '.$this->x_axis.' -top '.$this->y_axis.' -width '.$this->width.' -height '.$this->height;
}
elseif ($action === 'rotate')
{
switch ($this->rotation_angle)
{
case 90: $angle = 'r270';
break;
case 180: $angle = 'r180';
break;
case 270: $angle = 'r90';
break;
case 'vrt': $angle = 'tb';
break;
case 'hor': $angle = 'lr';
break;
}
$cmd_inner = 'pnmflip -'.$angle.' ';
}
else // Resize
{
$cmd_inner = 'pnmscale -xysize '.$this->width.' '.$this->height;
}
$cmd = $this->library_path.$cmd_in.' '.escapeshellarg($this->full_src_path).' | '.$cmd_inner.' | '.$cmd_out.' > '.$this->dest_folder.'netpbm.tmp';
$retval = 1;
// exec() might be disabled
if (function_usable('exec'))
{
@exec($cmd, $output, $retval);
}
// Did it work?
if ($retval > 0)
{
$this->set_error('imglib_image_process_failed');
return FALSE;
}
// With NetPBM we have to create a temporary image.
// If you try manipulating the original it fails so
// we have to rename the temp file.
copy($this->dest_folder.'netpbm.tmp', $this->full_dst_path);
unlink($this->dest_folder.'netpbm.tmp');
chmod($this->full_dst_path, $this->file_permissions);
return TRUE;
}
// --------------------------------------------------------------------
/**
* Image Rotate Using GD
*
* @return bool
*/
public function image_rotate_gd()
{
// Create the image handle
if ( ! ($src_img = $this->image_create_gd()))
{
return FALSE;
}
// Set the background color
// This won't work with transparent PNG files so we are
// going to have to figure out how to determine the color
// of the alpha channel in a future release.
$white = imagecolorallocate($src_img, 255, 255, 255);
// Rotate it!
$dst_img = imagerotate($src_img, $this->rotation_angle, $white);
// Show the image
if ($this->dynamic_output === TRUE)
{
$this->image_display_gd($dst_img);
}
elseif ( ! $this->image_save_gd($dst_img)) // ... or save it
{
return FALSE;
}
// Kill the file handles
imagedestroy($dst_img);
imagedestroy($src_img);
chmod($this->full_dst_path, $this->file_permissions);
return TRUE;
}
// --------------------------------------------------------------------
/**
* Create Mirror Image using GD
*
* This function will flip horizontal or vertical
*
* @return bool
*/
public function image_mirror_gd()
{
if ( ! $src_img = $this->image_create_gd())
{
return FALSE;
}
$width = $this->orig_width;
$height = $this->orig_height;
if ($this->rotation_angle === 'hor')
{
for ($i = 0; $i < $height; $i++)
{
$left = 0;
$right = $width - 1;
while ($left < $right)
{
$cl = imagecolorat($src_img, $left, $i);
$cr = imagecolorat($src_img, $right, $i);
imagesetpixel($src_img, $left, $i, $cr);
imagesetpixel($src_img, $right, $i, $cl);
$left++;
$right--;
}
}
}
else
{
for ($i = 0; $i < $width; $i++)
{
$top = 0;
$bottom = $height - 1;
while ($top < $bottom)
{
$ct = imagecolorat($src_img, $i, $top);
$cb = imagecolorat($src_img, $i, $bottom);
imagesetpixel($src_img, $i, $top, $cb);
imagesetpixel($src_img, $i, $bottom, $ct);
$top++;
$bottom--;
}
}
}
// Show the image
if ($this->dynamic_output === TRUE)
{
$this->image_display_gd($src_img);
}
elseif ( ! $this->image_save_gd($src_img)) // ... or save it
{
return FALSE;
}
// Kill the file handles
imagedestroy($src_img);
chmod($this->full_dst_path, $this->file_permissions);
return TRUE;
}
// --------------------------------------------------------------------
/**
* Image Watermark
*
* This is a wrapper function that chooses the type
* of watermarking based on the specified preference.
*
* @return bool
*/
public function watermark()
{
return ($this->wm_type === 'overlay') ? $this->overlay_watermark() : $this->text_watermark();
}
// --------------------------------------------------------------------
/**
* Watermark - Graphic Version
*
* @return bool
*/
public function overlay_watermark()
{
if ( ! function_exists('imagecolortransparent'))
{
$this->set_error('imglib_gd_required');
return FALSE;
}
// Fetch source image properties
$this->get_image_properties();
// Fetch watermark image properties
$props = $this->get_image_properties($this->wm_overlay_path, TRUE);
$wm_img_type = $props['image_type'];
$wm_width = $props['width'];
$wm_height = $props['height'];
// Create two image resources
$wm_img = $this->image_create_gd($this->wm_overlay_path, $wm_img_type);
$src_img = $this->image_create_gd($this->full_src_path);
// Reverse the offset if necessary
// When the image is positioned at the bottom
// we don't want the vertical offset to push it
// further down. We want the reverse, so we'll
// invert the offset. Same with the horizontal
// offset when the image is at the right
$this->wm_vrt_alignment = strtoupper($this->wm_vrt_alignment[0]);
$this->wm_hor_alignment = strtoupper($this->wm_hor_alignment[0]);
if ($this->wm_vrt_alignment === 'B')
$this->wm_vrt_offset = $this->wm_vrt_offset * -1;
if ($this->wm_hor_alignment === 'R')
$this->wm_hor_offset = $this->wm_hor_offset * -1;
// Set the base x and y axis values
$x_axis = $this->wm_hor_offset + $this->wm_padding;
$y_axis = $this->wm_vrt_offset + $this->wm_padding;
// Set the vertical position
if ($this->wm_vrt_alignment === 'M')
{
$y_axis += ($this->orig_height / 2) - ($wm_height / 2);
}
elseif ($this->wm_vrt_alignment === 'B')
{
$y_axis += $this->orig_height - $wm_height;
}
// Set the horizontal position
if ($this->wm_hor_alignment === 'C')
{
$x_axis += ($this->orig_width / 2) - ($wm_width / 2);
}
elseif ($this->wm_hor_alignment === 'R')
{
$x_axis += $this->orig_width - $wm_width;
}
// Build the finalized image
if ($wm_img_type === 3 && function_exists('imagealphablending'))
{
@imagealphablending($src_img, TRUE);
}
// Set RGB values for text and shadow
$rgba = imagecolorat($wm_img, $this->wm_x_transp, $this->wm_y_transp);
$alpha = ($rgba & 0x7F000000) >> 24;
// make a best guess as to whether we're dealing with an image with alpha transparency or no/binary transparency
if ($alpha > 0)
{
// copy the image directly, the image's alpha transparency being the sole determinant of blending
imagecopy($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height);
}
else
{
// set our RGB value from above to be transparent and merge the images with the specified opacity
imagecolortransparent($wm_img, imagecolorat($wm_img, $this->wm_x_transp, $this->wm_y_transp));
imagecopymerge($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height, $this->wm_opacity);
}
// We can preserve transparency for PNG images
if ($this->image_type === 3)
{
imagealphablending($src_img, FALSE);
imagesavealpha($src_img, TRUE);
}
// Output the image
if ($this->dynamic_output === TRUE)
{
$this->image_display_gd($src_img);
}
elseif ( ! $this->image_save_gd($src_img)) // ... or save it
{
return FALSE;
}
imagedestroy($src_img);
imagedestroy($wm_img);
return TRUE;
}
// --------------------------------------------------------------------
/**
* Watermark - Text Version
*
* @return bool
*/
public function text_watermark()
{
if ( ! ($src_img = $this->image_create_gd()))
{
return FALSE;
}
if ($this->wm_use_truetype === TRUE && ! file_exists($this->wm_font_path))
{
$this->set_error('imglib_missing_font');
return FALSE;
}
// Fetch source image properties
$this->get_image_properties();
// Reverse the vertical offset
// When the image is positioned at the bottom
// we don't want the vertical offset to push it
// further down. We want the reverse, so we'll
// invert the offset. Note: The horizontal
// offset flips itself automatically
if ($this->wm_vrt_alignment === 'B')
{
$this->wm_vrt_offset = $this->wm_vrt_offset * -1;
}
if ($this->wm_hor_alignment === 'R')
{
$this->wm_hor_offset = $this->wm_hor_offset * -1;
}
// Set font width and height
// These are calculated differently depending on
// whether we are using the true type font or not
if ($this->wm_use_truetype === TRUE)
{
if (empty($this->wm_font_size))
{
$this->wm_font_size = 17;
}
if (function_exists('imagettfbbox'))
{
$temp = imagettfbbox($this->wm_font_size, 0, $this->wm_font_path, $this->wm_text);
$temp = $temp[2] - $temp[0];
$fontwidth = $temp / strlen($this->wm_text);
}
else
{
$fontwidth = $this->wm_font_size - ($this->wm_font_size / 4);
}
$fontheight = $this->wm_font_size;
$this->wm_vrt_offset += $this->wm_font_size;
}
else
{
$fontwidth = imagefontwidth($this->wm_font_size);
$fontheight = imagefontheight($this->wm_font_size);
}
// Set base X and Y axis values
$x_axis = $this->wm_hor_offset + $this->wm_padding;
$y_axis = $this->wm_vrt_offset + $this->wm_padding;
if ($this->wm_use_drop_shadow === FALSE)
{
$this->wm_shadow_distance = 0;
}
$this->wm_vrt_alignment = strtoupper($this->wm_vrt_alignment[0]);
$this->wm_hor_alignment = strtoupper($this->wm_hor_alignment[0]);
// Set vertical alignment
if ($this->wm_vrt_alignment === 'M')
{
$y_axis += ($this->orig_height / 2) + ($fontheight / 2);
}
elseif ($this->wm_vrt_alignment === 'B')
{
$y_axis += $this->orig_height - $fontheight - $this->wm_shadow_distance - ($fontheight / 2);
}
// Set horizontal alignment
if ($this->wm_hor_alignment === 'R')
{
$x_axis += $this->orig_width - ($fontwidth * strlen($this->wm_text)) - $this->wm_shadow_distance;
}
elseif ($this->wm_hor_alignment === 'C')
{
$x_axis += floor(($this->orig_width - ($fontwidth * strlen($this->wm_text))) / 2);
}
if ($this->wm_use_drop_shadow)
{
// Offset from text
$x_shad = $x_axis + $this->wm_shadow_distance;
$y_shad = $y_axis + $this->wm_shadow_distance;
/* Set RGB values for shadow
*
* First character is #, so we don't really need it.
* Get the rest of the string and split it into 2-length
* hex values:
*/
$drp_color = str_split(substr($this->wm_shadow_color, 1, 6), 2);
$drp_color = imagecolorclosest($src_img, hexdec($drp_color[0]), hexdec($drp_color[1]), hexdec($drp_color[2]));
// Add the shadow to the source image
if ($this->wm_use_truetype)
{
imagettftext($src_img, $this->wm_font_size, 0, $x_shad, $y_shad, $drp_color, $this->wm_font_path, $this->wm_text);
}
else
{
imagestring($src_img, $this->wm_font_size, $x_shad, $y_shad, $this->wm_text, $drp_color);
}
}
/* Set RGB values for text
*
* First character is #, so we don't really need it.
* Get the rest of the string and split it into 2-length
* hex values:
*/
$txt_color = str_split(substr($this->wm_font_color, 1, 6), 2);
$txt_color = imagecolorclosest($src_img, hexdec($txt_color[0]), hexdec($txt_color[1]), hexdec($txt_color[2]));
// Add the text to the source image
if ($this->wm_use_truetype)
{
imagettftext($src_img, $this->wm_font_size, 0, $x_axis, $y_axis, $txt_color, $this->wm_font_path, $this->wm_text);
}
else
{
imagestring($src_img, $this->wm_font_size, $x_axis, $y_axis, $this->wm_text, $txt_color);
}
// We can preserve transparency for PNG images
if ($this->image_type === 3)
{
imagealphablending($src_img, FALSE);
imagesavealpha($src_img, TRUE);
}
// Output the final image
if ($this->dynamic_output === TRUE)
{
$this->image_display_gd($src_img);
}
else
{
$this->image_save_gd($src_img);
}
imagedestroy($src_img);
return TRUE;
}
// --------------------------------------------------------------------
/**
* Create Image - GD
*
* This simply creates an image resource handle
* based on the type of image being processed
*
* @param string
* @param string
* @return resource
*/
public function image_create_gd($path = '', $image_type = '')
{
if ($path === '')
{
$path = $this->full_src_path;
}
if ($image_type === '')
{
$image_type = $this->image_type;
}
switch ($image_type)
{
case 1:
if ( ! function_exists('imagecreatefromgif'))
{
$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));
return FALSE;
}
return imagecreatefromgif($path);
case 2:
if ( ! function_exists('imagecreatefromjpeg'))
{
$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));
return FALSE;
}
return imagecreatefromjpeg($path);
case 3:
if ( ! function_exists('imagecreatefrompng'))
{
$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));
return FALSE;
}
return imagecreatefrompng($path);
default:
$this->set_error(array('imglib_unsupported_imagecreate'));
return FALSE;
}
}
// --------------------------------------------------------------------
/**
* Write image file to disk - GD
*
* Takes an image resource as input and writes the file
* to the specified destination
*
* @param resource
* @return bool
*/
public function image_save_gd($resource)
{
switch ($this->image_type)
{
case 1:
if ( ! function_exists('imagegif'))
{
$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));
return FALSE;
}
if ( ! @imagegif($resource, $this->full_dst_path))
{
$this->set_error('imglib_save_failed');
return FALSE;
}
break;
case 2:
if ( ! function_exists('imagejpeg'))
{
$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));
return FALSE;
}
if ( ! @imagejpeg($resource, $this->full_dst_path, $this->quality))
{
$this->set_error('imglib_save_failed');
return FALSE;
}
break;
case 3:
if ( ! function_exists('imagepng'))
{
$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));
return FALSE;
}
if ( ! @imagepng($resource, $this->full_dst_path))
{
$this->set_error('imglib_save_failed');
return FALSE;
}
break;
default:
$this->set_error(array('imglib_unsupported_imagecreate'));
return FALSE;
break;
}
return TRUE;
}
// --------------------------------------------------------------------
/**
* Dynamically outputs an image
*
* @param resource
* @return void
*/
public function image_display_gd($resource)
{
header('Content-Disposition: filename='.$this->source_image.';');
header('Content-Type: '.$this->mime_type);
header('Content-Transfer-Encoding: binary');
header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT');
switch ($this->image_type)
{
case 1 : imagegif($resource);
break;
case 2 : imagejpeg($resource, NULL, $this->quality);
break;
case 3 : imagepng($resource);
break;
default: echo 'Unable to display the image';
break;
}
}
// --------------------------------------------------------------------
/**
* Re-proportion Image Width/Height
*
* When creating thumbs, the desired width/height
* can end up warping the image due to an incorrect
* ratio between the full-sized image and the thumb.
*
* This function lets us re-proportion the width/height
* if users choose to maintain the aspect ratio when resizing.
*
* @return void
*/
public function image_reproportion()
{
if (($this->width === 0 && $this->height === 0) OR $this->orig_width === 0 OR $this->orig_height === 0
OR ( ! ctype_digit((string) $this->width) && ! ctype_digit((string) $this->height))
OR ! ctype_digit((string) $this->orig_width) OR ! ctype_digit((string) $this->orig_height))
{
return;
}
// Sanitize
$this->width = (int) $this->width;
$this->height = (int) $this->height;
if ($this->master_dim !== 'width' && $this->master_dim !== 'height')
{
if ($this->width > 0 && $this->height > 0)
{
$this->master_dim = ((($this->orig_height/$this->orig_width) - ($this->height/$this->width)) < 0)
? 'width' : 'height';
}
else
{
$this->master_dim = ($this->height === 0) ? 'width' : 'height';
}
}
elseif (($this->master_dim === 'width' && $this->width === 0)
OR ($this->master_dim === 'height' && $this->height === 0))
{
return;
}
if ($this->master_dim === 'width')
{
$this->height = (int) ceil($this->width*$this->orig_height/$this->orig_width);
}
else
{
$this->width = (int) ceil($this->orig_width*$this->height/$this->orig_height);
}
}
// --------------------------------------------------------------------
/**
* Get image properties
*
* A helper function that gets info about the file
*
* @param string
* @param bool
* @return mixed
*/
public function get_image_properties($path = '', $return = FALSE)
{
// For now we require GD but we should
// find a way to determine this using IM or NetPBM
if ($path === '')
{
$path = $this->full_src_path;
}
if ( ! file_exists($path))
{
$this->set_error('imglib_invalid_path');
return FALSE;
}
$vals = getimagesize($path);
if ($vals === FALSE)
{
$this->set_error('imglib_invalid_image');
return FALSE;
}
$types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');
$mime = isset($types[$vals[2]]) ? 'image/'.$types[$vals[2]] : 'image/jpg';
if ($return === TRUE)
{
return array(
'width' => $vals[0],
'height' => $vals[1],
'image_type' => $vals[2],
'size_str' => $vals[3],
'mime_type' => $mime
);
}
$this->orig_width = $vals[0];
$this->orig_height = $vals[1];
$this->image_type = $vals[2];
$this->size_str = $vals[3];
$this->mime_type = $mime;
return TRUE;
}
// --------------------------------------------------------------------
/**
* Size calculator
*
* This function takes a known width x height and
* recalculates it to a new size. Only one
* new variable needs to be known
*
* $props = array(
* 'width' => $width,
* 'height' => $height,
* 'new_width' => 40,
* 'new_height' => ''
* );
*
* @param array
* @return array
*/
public function size_calculator($vals)
{
if ( ! is_array($vals))
{
return;
}
$allowed = array('new_width', 'new_height', 'width', 'height');
foreach ($allowed as $item)
{
if (empty($vals[$item]))
{
$vals[$item] = 0;
}
}
if ($vals['width'] === 0 OR $vals['height'] === 0)
{
return $vals;
}
if ($vals['new_width'] === 0)
{
$vals['new_width'] = ceil($vals['width']*$vals['new_height']/$vals['height']);
}
elseif ($vals['new_height'] === 0)
{
$vals['new_height'] = ceil($vals['new_width']*$vals['height']/$vals['width']);
}
return $vals;
}
// --------------------------------------------------------------------
/**
* Explode source_image
*
* This is a helper function that extracts the extension
* from the source_image. This function lets us deal with
* source_images with multiple periods, like: my.cool.jpg
* It returns an associative array with two elements:
* $array['ext'] = '.jpg';
* $array['name'] = 'my.cool';
*
* @param array
* @return array
*/
public function explode_name($source_image)
{
$ext = strrchr($source_image, '.');
$name = ($ext === FALSE) ? $source_image : substr($source_image, 0, -strlen($ext));
return array('ext' => $ext, 'name' => $name);
}
// --------------------------------------------------------------------
/**
* Is GD Installed?
*
* @return bool
*/
public function gd_loaded()
{
if ( ! extension_loaded('gd'))
{
/* As it is stated in the PHP manual, dl() is not always available
* and even if so - it could generate an E_WARNING message on failure
*/
return (function_exists('dl') && @dl('gd.so'));
}
return TRUE;
}
// --------------------------------------------------------------------
/**
* Get GD version
*
* @return mixed
*/
public function gd_version()
{
if (function_exists('gd_info'))
{
$gd_version = @gd_info();
return preg_replace('/\D/', '', $gd_version['GD Version']);
}
return FALSE;
}
// --------------------------------------------------------------------
/**
* Set error message
*
* @param string
* @return void
*/
public function set_error($msg)
{
$CI =& get_instance();
$CI->lang->load('imglib');
if (is_array($msg))
{
foreach ($msg as $val)
{
$msg = ($CI->lang->line($val) === FALSE) ? $val : $CI->lang->line($val);
$this->error_msg[] = $msg;
log_message('error', $msg);
}
}
else
{
$msg = ($CI->lang->line($msg) === FALSE) ? $msg : $CI->lang->line($msg);
$this->error_msg[] = $msg;
log_message('error', $msg);
}
}
// --------------------------------------------------------------------
/**
* Show error messages
*
* @param string
* @param string
* @return string
*/
public function display_errors($open = '
', $close = '
')
{
return (count($this->error_msg) > 0) ? $open.implode($close.$open, $this->error_msg).$close : '';
}
}
PK ! »Çø
á á + libraries/Cache/drivers/Cache_memcached.phpnu „[µü¤ array(
'host' => '127.0.0.1',
'port' => 11211,
'weight' => 1
)
);
// ------------------------------------------------------------------------
/**
* Class constructor
*
* Setup Memcache(d)
*
* @return void
*/
public function __construct()
{
// Try to load memcached server info from the config file.
$CI =& get_instance();
$defaults = $this->_config['default'];
if ($CI->config->load('memcached', TRUE, TRUE))
{
$this->_config = $CI->config->config['memcached'];
}
if (class_exists('Memcached', FALSE))
{
$this->_memcached = new Memcached();
}
elseif (class_exists('Memcache', FALSE))
{
$this->_memcached = new Memcache();
}
else
{
log_message('error', 'Cache: Failed to create Memcache(d) object; extension not loaded?');
return;
}
foreach ($this->_config as $cache_server)
{
isset($cache_server['hostname']) OR $cache_server['hostname'] = $defaults['host'];
isset($cache_server['port']) OR $cache_server['port'] = $defaults['port'];
isset($cache_server['weight']) OR $cache_server['weight'] = $defaults['weight'];
if ($this->_memcached instanceof Memcache)
{
// Third parameter is persistence and defaults to TRUE.
$this->_memcached->addServer(
$cache_server['hostname'],
$cache_server['port'],
TRUE,
$cache_server['weight']
);
}
elseif ($this->_memcached instanceof Memcached)
{
$this->_memcached->addServer(
$cache_server['hostname'],
$cache_server['port'],
$cache_server['weight']
);
}
}
}
// ------------------------------------------------------------------------
/**
* Fetch from cache
*
* @param string $id Cache ID
* @return mixed Data on success, FALSE on failure
*/
public function get($id)
{
$data = $this->_memcached->get($id);
return is_array($data) ? $data[0] : $data;
}
// ------------------------------------------------------------------------
/**
* Save
*
* @param string $id Cache ID
* @param mixed $data Data being cached
* @param int $ttl Time to live
* @param bool $raw Whether to store the raw value
* @return bool TRUE on success, FALSE on failure
*/
public function save($id, $data, $ttl = 60, $raw = FALSE)
{
if ($raw !== TRUE)
{
$data = array($data, time(), $ttl);
}
if ($this->_memcached instanceof Memcached)
{
return $this->_memcached->set($id, $data, $ttl);
}
elseif ($this->_memcached instanceof Memcache)
{
return $this->_memcached->set($id, $data, 0, $ttl);
}
return FALSE;
}
// ------------------------------------------------------------------------
/**
* Delete from Cache
*
* @param mixed $id key to be deleted.
* @return bool true on success, false on failure
*/
public function delete($id)
{
return $this->_memcached->delete($id);
}
// ------------------------------------------------------------------------
/**
* Increment a raw value
*
* @param string $id Cache ID
* @param int $offset Step/value to add
* @return mixed New value on success or FALSE on failure
*/
public function increment($id, $offset = 1)
{
if (($result = $this->_memcached->increment($id, $offset)) === FALSE)
{
return $this->_memcached->add($id, $offset) ? $offset : FALSE;
}
return $result;
}
// ------------------------------------------------------------------------
/**
* Decrement a raw value
*
* @param string $id Cache ID
* @param int $offset Step/value to reduce by
* @return mixed New value on success or FALSE on failure
*/
public function decrement($id, $offset = 1)
{
if (($result = $this->_memcached->decrement($id, $offset)) === FALSE)
{
return $this->_memcached->add($id, 0) ? 0 : FALSE;
}
return $result;
}
// ------------------------------------------------------------------------
/**
* Clean the Cache
*
* @return bool false on failure/true on success
*/
public function clean()
{
return $this->_memcached->flush();
}
// ------------------------------------------------------------------------
/**
* Cache Info
*
* @return mixed array on success, false on failure
*/
public function cache_info()
{
return $this->_memcached->getStats();
}
// ------------------------------------------------------------------------
/**
* Get Cache Metadata
*
* @param mixed $id key to get cache metadata on
* @return mixed FALSE on failure, array on success.
*/
public function get_metadata($id)
{
$stored = $this->_memcached->get($id);
if (count($stored) !== 3)
{
return FALSE;
}
list($data, $time, $ttl) = $stored;
return array(
'expire' => $time + $ttl,
'mtime' => $time,
'data' => $data
);
}
// ------------------------------------------------------------------------
/**
* Is supported
*
* Returns FALSE if memcached is not supported on the system.
* If it is, we setup the memcached object & return TRUE
*
* @return bool
*/
public function is_supported()
{
return (extension_loaded('memcached') OR extension_loaded('memcache'));
}
// ------------------------------------------------------------------------
/**
* Class destructor
*
* Closes the connection to Memcache(d) if present.
*
* @return void
*/
public function __destruct()
{
if ($this->_memcached instanceof Memcache)
{
$this->_memcached->close();
}
elseif ($this->_memcached instanceof Memcached && method_exists($this->_memcached, 'quit'))
{
$this->_memcached->quit();
}
}
}
PK ! ܰJ'ó ó ' libraries/Cache/drivers/Cache_dummy.phpnu „[µü¤ load->helper('file');
$path = $CI->config->item('cache_path');
$this->_cache_path = ($path === '') ? APPPATH.'cache/' : $path;
}
// ------------------------------------------------------------------------
/**
* Fetch from cache
*
* @param string $id Cache ID
* @return mixed Data on success, FALSE on failure
*/
public function get($id)
{
$data = $this->_get($id);
return is_array($data) ? $data['data'] : FALSE;
}
// ------------------------------------------------------------------------
/**
* Save into cache
*
* @param string $id Cache ID
* @param mixed $data Data to store
* @param int $ttl Time to live in seconds
* @param bool $raw Whether to store the raw value (unused)
* @return bool TRUE on success, FALSE on failure
*/
public function save($id, $data, $ttl = 60, $raw = FALSE)
{
$contents = array(
'time' => time(),
'ttl' => $ttl,
'data' => $data
);
if (write_file($this->_cache_path.$id, serialize($contents)))
{
chmod($this->_cache_path.$id, 0640);
return TRUE;
}
return FALSE;
}
// ------------------------------------------------------------------------
/**
* Delete from Cache
*
* @param mixed unique identifier of item in cache
* @return bool true on success/false on failure
*/
public function delete($id)
{
return is_file($this->_cache_path.$id) ? unlink($this->_cache_path.$id) : FALSE;
}
// ------------------------------------------------------------------------
/**
* Increment a raw value
*
* @param string $id Cache ID
* @param int $offset Step/value to add
* @return New value on success, FALSE on failure
*/
public function increment($id, $offset = 1)
{
$data = $this->_get($id);
if ($data === FALSE)
{
$data = array('data' => 0, 'ttl' => 60);
}
elseif ( ! is_int($data['data']))
{
return FALSE;
}
$new_value = $data['data'] + $offset;
return $this->save($id, $new_value, $data['ttl'])
? $new_value
: FALSE;
}
// ------------------------------------------------------------------------
/**
* Decrement a raw value
*
* @param string $id Cache ID
* @param int $offset Step/value to reduce by
* @return New value on success, FALSE on failure
*/
public function decrement($id, $offset = 1)
{
$data = $this->_get($id);
if ($data === FALSE)
{
$data = array('data' => 0, 'ttl' => 60);
}
elseif ( ! is_int($data['data']))
{
return FALSE;
}
$new_value = $data['data'] - $offset;
return $this->save($id, $new_value, $data['ttl'])
? $new_value
: FALSE;
}
// ------------------------------------------------------------------------
/**
* Clean the Cache
*
* @return bool false on failure/true on success
*/
public function clean()
{
return delete_files($this->_cache_path, FALSE, TRUE);
}
// ------------------------------------------------------------------------
/**
* Cache Info
*
* Not supported by file-based caching
*
* @param string user/filehits
* @return mixed FALSE
*/
public function cache_info($type = NULL)
{
return get_dir_file_info($this->_cache_path);
}
// ------------------------------------------------------------------------
/**
* Get Cache Metadata
*
* @param mixed key to get cache metadata on
* @return mixed FALSE on failure, array on success.
*/
public function get_metadata($id)
{
if ( ! is_file($this->_cache_path.$id))
{
return FALSE;
}
$data = unserialize(file_get_contents($this->_cache_path.$id));
if (is_array($data))
{
$mtime = filemtime($this->_cache_path.$id);
if ( ! isset($data['ttl'], $data['time']))
{
return FALSE;
}
return array(
'expire' => $data['time'] + $data['ttl'],
'mtime' => $mtime
);
}
return FALSE;
}
// ------------------------------------------------------------------------
/**
* Is supported
*
* In the file driver, check to see that the cache directory is indeed writable
*
* @return bool
*/
public function is_supported()
{
return is_really_writable($this->_cache_path);
}
// ------------------------------------------------------------------------
/**
* Get all data
*
* Internal method to get all the relevant data about a cache item
*
* @param string $id Cache ID
* @return mixed Data array on success or FALSE on failure
*/
protected function _get($id)
{
if ( ! is_file($this->_cache_path.$id))
{
return FALSE;
}
$data = unserialize(file_get_contents($this->_cache_path.$id));
if ($data['ttl'] > 0 && time() > $data['time'] + $data['ttl'])
{
file_exists($this->_cache_path.$id) && unlink($this->_cache_path.$id);
return FALSE;
}
return $data;
}
}
PK ! õ¶™Óû û ' libraries/Cache/drivers/Cache_redis.phpnu „[µü¤
* @link
*/
class CI_Cache_redis extends CI_Driver
{
/**
* Default config
*
* @static
* @var array
*/
protected static $_default_config = array(
'socket_type' => 'tcp',
'host' => '127.0.0.1',
'password' => NULL,
'port' => 6379,
'timeout' => 0
);
/**
* Redis connection
*
* @var Redis
*/
protected $_redis;
/**
* An internal cache for storing keys of serialized values.
*
* @var array
*/
protected $_serialized = array();
/**
* del()/delete() method name depending on phpRedis version
*
* @var string
*/
protected static $_delete_name;
// ------------------------------------------------------------------------
/**
* Class constructor
*
* Setup Redis
*
* Loads Redis config file if present. Will halt execution
* if a Redis connection can't be established.
*
* @return void
* @see Redis::connect()
*/
public function __construct()
{
if ( ! $this->is_supported())
{
log_message('error', 'Cache: Failed to create Redis object; extension not loaded?');
return;
}
isset(static::$_delete_name) OR static::$_delete_name = version_compare(phpversion('phpredis'), '5', '>=')
? 'del'
: 'delete';
$CI =& get_instance();
if ($CI->config->load('redis', TRUE, TRUE))
{
$config = array_merge(self::$_default_config, $CI->config->item('redis'));
}
else
{
$config = self::$_default_config;
}
$this->_redis = new Redis();
try
{
if ($config['socket_type'] === 'unix')
{
$success = $this->_redis->connect($config['socket']);
}
else // tcp socket
{
$success = $this->_redis->connect($config['host'], $config['port'], $config['timeout']);
}
if ( ! $success)
{
log_message('error', 'Cache: Redis connection failed. Check your configuration.');
}
if (isset($config['password']) && ! $this->_redis->auth($config['password']))
{
log_message('error', 'Cache: Redis authentication failed.');
}
}
catch (RedisException $e)
{
log_message('error', 'Cache: Redis connection refused ('.$e->getMessage().')');
}
}
// ------------------------------------------------------------------------
/**
* Get cache
*
* @param string $key Cache ID
* @return mixed
*/
public function get($key)
{
$value = $this->_redis->get($key);
if ($value !== FALSE && $this->_redis->sIsMember('_ci_redis_serialized', $key))
{
return unserialize($value);
}
return $value;
}
// ------------------------------------------------------------------------
/**
* Save cache
*
* @param string $id Cache ID
* @param mixed $data Data to save
* @param int $ttl Time to live in seconds
* @param bool $raw Whether to store the raw value (unused)
* @return bool TRUE on success, FALSE on failure
*/
public function save($id, $data, $ttl = 60, $raw = FALSE)
{
if (is_array($data) OR is_object($data))
{
if ( ! $this->_redis->sIsMember('_ci_redis_serialized', $id) && ! $this->_redis->sAdd('_ci_redis_serialized', $id))
{
return FALSE;
}
isset($this->_serialized[$id]) OR $this->_serialized[$id] = TRUE;
$data = serialize($data);
}
else
{
$this->_redis->sRemove('_ci_redis_serialized', $id);
}
return $this->_redis->set($id, $data, $ttl);
}
// ------------------------------------------------------------------------
/**
* Delete from cache
*
* @param string $key Cache key
* @return bool
*/
public function delete($key)
{
if ($this->_redis->{static::$_delete_name}($key) !== 1)
{
return FALSE;
}
$this->_redis->sRemove('_ci_redis_serialized', $key);
return TRUE;
}
// ------------------------------------------------------------------------
/**
* Increment a raw value
*
* @param string $id Cache ID
* @param int $offset Step/value to add
* @return mixed New value on success or FALSE on failure
*/
public function increment($id, $offset = 1)
{
return $this->_redis->incrBy($id, $offset);
}
// ------------------------------------------------------------------------
/**
* Decrement a raw value
*
* @param string $id Cache ID
* @param int $offset Step/value to reduce by
* @return mixed New value on success or FALSE on failure
*/
public function decrement($id, $offset = 1)
{
return $this->_redis->decrBy($id, $offset);
}
// ------------------------------------------------------------------------
/**
* Clean cache
*
* @return bool
* @see Redis::flushDB()
*/
public function clean()
{
return $this->_redis->flushDB();
}
// ------------------------------------------------------------------------
/**
* Get cache driver info
*
* @param string $type Not supported in Redis.
* Only included in order to offer a
* consistent cache API.
* @return array
* @see Redis::info()
*/
public function cache_info($type = NULL)
{
return $this->_redis->info();
}
// ------------------------------------------------------------------------
/**
* Get cache metadata
*
* @param string $key Cache key
* @return array
*/
public function get_metadata($key)
{
$value = $this->get($key);
if ($value !== FALSE)
{
return array(
'expire' => time() + $this->_redis->ttl($key),
'data' => $value
);
}
return FALSE;
}
// ------------------------------------------------------------------------
/**
* Check if Redis driver is supported
*
* @return bool
*/
public function is_supported()
{
return extension_loaded('redis');
}
// ------------------------------------------------------------------------
/**
* Class destructor
*
* Closes the connection to Redis if present.
*
* @return void
*/
public function __destruct()
{
if ($this->_redis)
{
$this->_redis->close();
}
}
}
PK ! ¤Hù % libraries/Cache/drivers/Cache_apc.phpnu „[µü¤ is_supported())
{
log_message('error', 'Cache: Failed to initialize APC; extension not loaded/enabled?');
}
}
// ------------------------------------------------------------------------
/**
* Get
*
* Look for a value in the cache. If it exists, return the data
* if not, return FALSE
*
* @param string
* @return mixed value that is stored/FALSE on failure
*/
public function get($id)
{
$success = FALSE;
$data = apc_fetch($id, $success);
return ($success === TRUE) ? $data : FALSE;
}
// ------------------------------------------------------------------------
/**
* Cache Save
*
* @param string $id Cache ID
* @param mixed $data Data to store
* @param int $ttl Length of time (in seconds) to cache the data
* @param bool $raw Whether to store the raw value (unused)
* @return bool TRUE on success, FALSE on failure
*/
public function save($id, $data, $ttl = 60, $raw = FALSE)
{
return apc_store($id, $data, (int) $ttl);
}
// ------------------------------------------------------------------------
/**
* Delete from Cache
*
* @param mixed unique identifier of the item in the cache
* @return bool true on success/false on failure
*/
public function delete($id)
{
return apc_delete($id);
}
// ------------------------------------------------------------------------
/**
* Increment a raw value
*
* @param string $id Cache ID
* @param int $offset Step/value to add
* @return mixed New value on success or FALSE on failure
*/
public function increment($id, $offset = 1)
{
return apc_inc($id, $offset);
}
// ------------------------------------------------------------------------
/**
* Decrement a raw value
*
* @param string $id Cache ID
* @param int $offset Step/value to reduce by
* @return mixed New value on success or FALSE on failure
*/
public function decrement($id, $offset = 1)
{
return apc_dec($id, $offset);
}
// ------------------------------------------------------------------------
/**
* Clean the cache
*
* @return bool false on failure/true on success
*/
public function clean()
{
return apc_clear_cache('user');
}
// ------------------------------------------------------------------------
/**
* Cache Info
*
* @param string user/filehits
* @return mixed array on success, false on failure
*/
public function cache_info($type = NULL)
{
return apc_cache_info($type);
}
// ------------------------------------------------------------------------
/**
* Get Cache Metadata
*
* @param mixed key to get cache metadata on
* @return mixed array on success/false on failure
*/
public function get_metadata($id)
{
$cache_info = apc_cache_info('user', FALSE);
if (empty($cache_info) OR empty($cache_info['cache_list']))
{
return FALSE;
}
foreach ($cache_info['cache_list'] as &$entry)
{
if ($entry['info'] !== $id)
{
continue;
}
$success = FALSE;
$metadata = array(
'expire' => ($entry['ttl'] ? $entry['mtime'] + $entry['ttl'] : 0),
'mtime' => $entry['ttl'],
'data' => apc_fetch($id, $success)
);
return ($success === TRUE) ? $metadata : FALSE;
}
return FALSE;
}
// ------------------------------------------------------------------------
/**
* is_supported()
*
* Check to see if APC is available on this system, bail if it isn't.
*
* @return bool
*/
public function is_supported()
{
return (extension_loaded('apc') && ini_get('apc.enabled'));
}
}
PK ! ‹‰Kà à * libraries/Cache/drivers/Cache_wincache.phpnu „[µü¤ is_supported())
{
log_message('error', 'Cache: Failed to initialize Wincache; extension not loaded/enabled?');
}
}
// ------------------------------------------------------------------------
/**
* Get
*
* Look for a value in the cache. If it exists, return the data,
* if not, return FALSE
*
* @param string $id Cache Ide
* @return mixed Value that is stored/FALSE on failure
*/
public function get($id)
{
$success = FALSE;
$data = wincache_ucache_get($id, $success);
// Success returned by reference from wincache_ucache_get()
return ($success) ? $data : FALSE;
}
// ------------------------------------------------------------------------
/**
* Cache Save
*
* @param string $id Cache ID
* @param mixed $data Data to store
* @param int $ttl Time to live (in seconds)
* @param bool $raw Whether to store the raw value (unused)
* @return bool true on success/false on failure
*/
public function save($id, $data, $ttl = 60, $raw = FALSE)
{
return wincache_ucache_set($id, $data, $ttl);
}
// ------------------------------------------------------------------------
/**
* Delete from Cache
*
* @param mixed unique identifier of the item in the cache
* @return bool true on success/false on failure
*/
public function delete($id)
{
return wincache_ucache_delete($id);
}
// ------------------------------------------------------------------------
/**
* Increment a raw value
*
* @param string $id Cache ID
* @param int $offset Step/value to add
* @return mixed New value on success or FALSE on failure
*/
public function increment($id, $offset = 1)
{
$success = FALSE;
$value = wincache_ucache_inc($id, $offset, $success);
return ($success === TRUE) ? $value : FALSE;
}
// ------------------------------------------------------------------------
/**
* Decrement a raw value
*
* @param string $id Cache ID
* @param int $offset Step/value to reduce by
* @return mixed New value on success or FALSE on failure
*/
public function decrement($id, $offset = 1)
{
$success = FALSE;
$value = wincache_ucache_dec($id, $offset, $success);
return ($success === TRUE) ? $value : FALSE;
}
// ------------------------------------------------------------------------
/**
* Clean the cache
*
* @return bool false on failure/true on success
*/
public function clean()
{
return wincache_ucache_clear();
}
// ------------------------------------------------------------------------
/**
* Cache Info
*
* @return mixed array on success, false on failure
*/
public function cache_info()
{
return wincache_ucache_info(TRUE);
}
// ------------------------------------------------------------------------
/**
* Get Cache Metadata
*
* @param mixed key to get cache metadata on
* @return mixed array on success/false on failure
*/
public function get_metadata($id)
{
if ($stored = wincache_ucache_info(FALSE, $id))
{
$age = $stored['ucache_entries'][1]['age_seconds'];
$ttl = $stored['ucache_entries'][1]['ttl_seconds'];
$hitcount = $stored['ucache_entries'][1]['hitcount'];
return array(
'expire' => $ttl - $age,
'hitcount' => $hitcount,
'age' => $age,
'ttl' => $ttl
);
}
return FALSE;
}
// ------------------------------------------------------------------------
/**
* is_supported()
*
* Check to see if WinCache is available on this system, bail if it isn't.
*
* @return bool
*/
public function is_supported()
{
return (extension_loaded('wincache') && ini_get('wincache.ucenabled'));
}
}
PK ! ®ò(ƒ ƒ " libraries/Cache/drivers/index.htmlnu „[µü¤
403 Forbidden
Directory access is forbidden.
PK ! ”F¡ƒ ƒ libraries/Cache/Cache.phpnu „[µü¤ _adapter = $config['adapter'];
isset($config['backup']) && $this->_backup_driver = $config['backup'];
isset($config['key_prefix']) && $this->key_prefix = $config['key_prefix'];
// If the specified adapter isn't available, check the backup.
if ( ! $this->is_supported($this->_adapter))
{
if ( ! $this->is_supported($this->_backup_driver))
{
// Backup isn't supported either. Default to 'Dummy' driver.
log_message('error', 'Cache adapter "'.$this->_adapter.'" and backup "'.$this->_backup_driver.'" are both unavailable. Cache is now using "Dummy" adapter.');
$this->_adapter = 'dummy';
}
else
{
// Backup is supported. Set it to primary.
log_message('debug', 'Cache adapter "'.$this->_adapter.'" is unavailable. Falling back to "'.$this->_backup_driver.'" backup adapter.');
$this->_adapter = $this->_backup_driver;
}
}
}
// ------------------------------------------------------------------------
/**
* Get
*
* Look for a value in the cache. If it exists, return the data
* if not, return FALSE
*
* @param string $id
* @return mixed value matching $id or FALSE on failure
*/
public function get($id)
{
return $this->{$this->_adapter}->get($this->key_prefix.$id);
}
// ------------------------------------------------------------------------
/**
* Cache Save
*
* @param string $id Cache ID
* @param mixed $data Data to store
* @param int $ttl Cache TTL (in seconds)
* @param bool $raw Whether to store the raw value
* @return bool TRUE on success, FALSE on failure
*/
public function save($id, $data, $ttl = 60, $raw = FALSE)
{
return $this->{$this->_adapter}->save($this->key_prefix.$id, $data, $ttl, $raw);
}
// ------------------------------------------------------------------------
/**
* Delete from Cache
*
* @param string $id Cache ID
* @return bool TRUE on success, FALSE on failure
*/
public function delete($id)
{
return $this->{$this->_adapter}->delete($this->key_prefix.$id);
}
// ------------------------------------------------------------------------
/**
* Increment a raw value
*
* @param string $id Cache ID
* @param int $offset Step/value to add
* @return mixed New value on success or FALSE on failure
*/
public function increment($id, $offset = 1)
{
return $this->{$this->_adapter}->increment($this->key_prefix.$id, $offset);
}
// ------------------------------------------------------------------------
/**
* Decrement a raw value
*
* @param string $id Cache ID
* @param int $offset Step/value to reduce by
* @return mixed New value on success or FALSE on failure
*/
public function decrement($id, $offset = 1)
{
return $this->{$this->_adapter}->decrement($this->key_prefix.$id, $offset);
}
// ------------------------------------------------------------------------
/**
* Clean the cache
*
* @return bool TRUE on success, FALSE on failure
*/
public function clean()
{
return $this->{$this->_adapter}->clean();
}
// ------------------------------------------------------------------------
/**
* Cache Info
*
* @param string $type = 'user' user/filehits
* @return mixed array containing cache info on success OR FALSE on failure
*/
public function cache_info($type = 'user')
{
return $this->{$this->_adapter}->cache_info($type);
}
// ------------------------------------------------------------------------
/**
* Get Cache Metadata
*
* @param string $id key to get cache metadata on
* @return mixed cache item metadata
*/
public function get_metadata($id)
{
return $this->{$this->_adapter}->get_metadata($this->key_prefix.$id);
}
// ------------------------------------------------------------------------
/**
* Is the requested driver supported in this environment?
*
* @param string $driver The driver to test
* @return array
*/
public function is_supported($driver)
{
static $support;
if ( ! isset($support, $support[$driver]))
{
$support[$driver] = $this->{$driver}->is_supported();
}
return $support[$driver];
}
}
PK ! ®ò(ƒ ƒ libraries/Cache/index.htmlnu „[µü¤
403 Forbidden
Directory access is forbidden.
PK ! ⟧9'Û 'Û libraries/Email.phpnu „[µü¤ '1 (Highest)',
2 => '2 (High)',
3 => '3 (Normal)',
4 => '4 (Low)',
5 => '5 (Lowest)'
);
/**
* mbstring.func_overload flag
*
* @var bool
*/
protected static $func_overload;
// --------------------------------------------------------------------
/**
* Constructor - Sets Email Preferences
*
* The constructor can be passed an array of config values
*
* @param array $config = array()
* @return void
*/
public function __construct(array $config = array())
{
$this->charset = config_item('charset');
$this->initialize($config);
$this->_safe_mode = ( ! is_php('5.4') && ini_get('safe_mode'));
isset(self::$func_overload) OR self::$func_overload = (extension_loaded('mbstring') && ini_get('mbstring.func_overload'));
log_message('info', 'Email Class Initialized');
}
// --------------------------------------------------------------------
/**
* Initialize preferences
*
* @param array $config
* @return CI_Email
*/
public function initialize(array $config = array())
{
$this->clear();
foreach ($config as $key => $val)
{
if (isset($this->$key))
{
$method = 'set_'.$key;
if (method_exists($this, $method))
{
$this->$method($val);
}
else
{
$this->$key = $val;
}
}
}
$this->charset = strtoupper($this->charset);
$this->_smtp_auth = isset($this->smtp_user[0], $this->smtp_pass[0]);
return $this;
}
// --------------------------------------------------------------------
/**
* Initialize the Email Data
*
* @param bool
* @return CI_Email
*/
public function clear($clear_attachments = FALSE)
{
$this->_subject = '';
$this->_body = '';
$this->_finalbody = '';
$this->_header_str = '';
$this->_replyto_flag = FALSE;
$this->_recipients = array();
$this->_cc_array = array();
$this->_bcc_array = array();
$this->_headers = array();
$this->_debug_msg = array();
$this->set_header('Date', $this->_set_date());
if ($clear_attachments !== FALSE)
{
$this->_attachments = array();
}
return $this;
}
// --------------------------------------------------------------------
/**
* Set FROM
*
* @param string $from
* @param string $name
* @param string $return_path = NULL Return-Path
* @return CI_Email
*/
public function from($from, $name = '', $return_path = NULL)
{
if (preg_match('/\<(.*)\>/', $from, $match))
{
$from = $match[1];
}
if ($this->validate)
{
$this->validate_email($this->_str_to_array($from));
if ($return_path)
{
$this->validate_email($this->_str_to_array($return_path));
}
}
// prepare the display name
if ($name !== '')
{
// only use Q encoding if there are characters that would require it
if ( ! preg_match('/[\200-\377]/', $name))
{
// add slashes for non-printing characters, slashes, and double quotes, and surround it in double quotes
$name = '"'.addcslashes($name, "\0..\37\177'\"\\").'"';
}
else
{
$name = $this->_prep_q_encoding($name);
}
}
$this->set_header('From', $name.' <'.$from.'>');
isset($return_path) OR $return_path = $from;
$this->set_header('Return-Path', '<'.$return_path.'>');
return $this;
}
// --------------------------------------------------------------------
/**
* Set Reply-to
*
* @param string
* @param string
* @return CI_Email
*/
public function reply_to($replyto, $name = '')
{
if (preg_match('/\<(.*)\>/', $replyto, $match))
{
$replyto = $match[1];
}
if ($this->validate)
{
$this->validate_email($this->_str_to_array($replyto));
}
if ($name !== '')
{
// only use Q encoding if there are characters that would require it
if ( ! preg_match('/[\200-\377]/', $name))
{
// add slashes for non-printing characters, slashes, and double quotes, and surround it in double quotes
$name = '"'.addcslashes($name, "\0..\37\177'\"\\").'"';
}
else
{
$name = $this->_prep_q_encoding($name);
}
}
$this->set_header('Reply-To', $name.' <'.$replyto.'>');
$this->_replyto_flag = TRUE;
return $this;
}
// --------------------------------------------------------------------
/**
* Set Recipients
*
* @param string
* @return CI_Email
*/
public function to($to)
{
$to = $this->_str_to_array($to);
$to = $this->clean_email($to);
if ($this->validate)
{
$this->validate_email($to);
}
if ($this->_get_protocol() !== 'mail')
{
$this->set_header('To', implode(', ', $to));
}
$this->_recipients = $to;
return $this;
}
// --------------------------------------------------------------------
/**
* Set CC
*
* @param string
* @return CI_Email
*/
public function cc($cc)
{
$cc = $this->clean_email($this->_str_to_array($cc));
if ($this->validate)
{
$this->validate_email($cc);
}
$this->set_header('Cc', implode(', ', $cc));
if ($this->_get_protocol() === 'smtp')
{
$this->_cc_array = $cc;
}
return $this;
}
// --------------------------------------------------------------------
/**
* Set BCC
*
* @param string
* @param string
* @return CI_Email
*/
public function bcc($bcc, $limit = '')
{
if ($limit !== '' && is_numeric($limit))
{
$this->bcc_batch_mode = TRUE;
$this->bcc_batch_size = $limit;
}
$bcc = $this->clean_email($this->_str_to_array($bcc));
if ($this->validate)
{
$this->validate_email($bcc);
}
if ($this->_get_protocol() === 'smtp' OR ($this->bcc_batch_mode && count($bcc) > $this->bcc_batch_size))
{
$this->_bcc_array = $bcc;
}
else
{
$this->set_header('Bcc', implode(', ', $bcc));
}
return $this;
}
// --------------------------------------------------------------------
/**
* Set Email Subject
*
* @param string
* @return CI_Email
*/
public function subject($subject)
{
$subject = $this->_prep_q_encoding($subject);
$this->set_header('Subject', $subject);
return $this;
}
// --------------------------------------------------------------------
/**
* Set Body
*
* @param string
* @return CI_Email
*/
public function message($body)
{
$this->_body = rtrim(str_replace("\r", '', $body));
/* strip slashes only if magic quotes is ON
if we do it with magic quotes OFF, it strips real, user-inputted chars.
NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and
it will probably not exist in future versions at all.
*/
if ( ! is_php('5.4') && get_magic_quotes_gpc())
{
$this->_body = stripslashes($this->_body);
}
return $this;
}
// --------------------------------------------------------------------
/**
* Assign file attachments
*
* @param string $file Can be local path, URL or buffered content
* @param string $disposition = 'attachment'
* @param string $newname = NULL
* @param string $mime = ''
* @return CI_Email
*/
public function attach($file, $disposition = '', $newname = NULL, $mime = '')
{
if ($mime === '')
{
if (strpos($file, '://') === FALSE && ! file_exists($file))
{
$this->_set_error_message('lang:email_attachment_missing', $file);
return FALSE;
}
if ( ! $fp = @fopen($file, 'rb'))
{
$this->_set_error_message('lang:email_attachment_unreadable', $file);
return FALSE;
}
$file_content = stream_get_contents($fp);
$mime = $this->_mime_types(pathinfo($file, PATHINFO_EXTENSION));
fclose($fp);
}
else
{
$file_content =& $file; // buffered file
}
$this->_attachments[] = array(
'name' => array($file, $newname),
'disposition' => empty($disposition) ? 'attachment' : $disposition, // Can also be 'inline' Not sure if it matters
'type' => $mime,
'content' => chunk_split(base64_encode($file_content)),
'multipart' => 'mixed'
);
return $this;
}
// --------------------------------------------------------------------
/**
* Set and return attachment Content-ID
*
* Useful for attached inline pictures
*
* @param string $filename
* @return string
*/
public function attachment_cid($filename)
{
for ($i = 0, $c = count($this->_attachments); $i < $c; $i++)
{
if ($this->_attachments[$i]['name'][0] === $filename)
{
$this->_attachments[$i]['multipart'] = 'related';
$this->_attachments[$i]['cid'] = uniqid(basename($this->_attachments[$i]['name'][0]).'@');
return $this->_attachments[$i]['cid'];
}
}
return FALSE;
}
// --------------------------------------------------------------------
/**
* Add a Header Item
*
* @param string
* @param string
* @return CI_Email
*/
public function set_header($header, $value)
{
$this->_headers[$header] = str_replace(array("\n", "\r"), '', $value);
return $this;
}
// --------------------------------------------------------------------
/**
* Convert a String to an Array
*
* @param string
* @return array
*/
protected function _str_to_array($email)
{
if ( ! is_array($email))
{
return (strpos($email, ',') !== FALSE)
? preg_split('/[\s,]/', $email, -1, PREG_SPLIT_NO_EMPTY)
: (array) trim($email);
}
return $email;
}
// --------------------------------------------------------------------
/**
* Set Multipart Value
*
* @param string
* @return CI_Email
*/
public function set_alt_message($str)
{
$this->alt_message = (string) $str;
return $this;
}
// --------------------------------------------------------------------
/**
* Set Mailtype
*
* @param string
* @return CI_Email
*/
public function set_mailtype($type = 'text')
{
$this->mailtype = ($type === 'html') ? 'html' : 'text';
return $this;
}
// --------------------------------------------------------------------
/**
* Set Wordwrap
*
* @param bool
* @return CI_Email
*/
public function set_wordwrap($wordwrap = TRUE)
{
$this->wordwrap = (bool) $wordwrap;
return $this;
}
// --------------------------------------------------------------------
/**
* Set Protocol
*
* @param string
* @return CI_Email
*/
public function set_protocol($protocol = 'mail')
{
$this->protocol = in_array($protocol, $this->_protocols, TRUE) ? strtolower($protocol) : 'mail';
return $this;
}
// --------------------------------------------------------------------
/**
* Set Priority
*
* @param int
* @return CI_Email
*/
public function set_priority($n = 3)
{
$this->priority = preg_match('/^[1-5]$/', $n) ? (int) $n : 3;
return $this;
}
// --------------------------------------------------------------------
/**
* Set Newline Character
*
* @param string
* @return CI_Email
*/
public function set_newline($newline = "\n")
{
$this->newline = in_array($newline, array("\n", "\r\n", "\r")) ? $newline : "\n";
return $this;
}
// --------------------------------------------------------------------
/**
* Set CRLF
*
* @param string
* @return CI_Email
*/
public function set_crlf($crlf = "\n")
{
$this->crlf = ($crlf !== "\n" && $crlf !== "\r\n" && $crlf !== "\r") ? "\n" : $crlf;
return $this;
}
// --------------------------------------------------------------------
/**
* Get the Message ID
*
* @return string
*/
protected function _get_message_id()
{
$from = str_replace(array('>', '<'), '', $this->_headers['Return-Path']);
return '<'.uniqid('').strstr($from, '@').'>';
}
// --------------------------------------------------------------------
/**
* Get Mail Protocol
*
* @return mixed
*/
protected function _get_protocol()
{
$this->protocol = strtolower($this->protocol);
in_array($this->protocol, $this->_protocols, TRUE) OR $this->protocol = 'mail';
return $this->protocol;
}
// --------------------------------------------------------------------
/**
* Get Mail Encoding
*
* @return string
*/
protected function _get_encoding()
{
in_array($this->_encoding, $this->_bit_depths) OR $this->_encoding = '8bit';
foreach ($this->_base_charsets as $charset)
{
if (strpos($this->charset, $charset) === 0)
{
$this->_encoding = '7bit';
}
}
return $this->_encoding;
}
// --------------------------------------------------------------------
/**
* Get content type (text/html/attachment)
*
* @return string
*/
protected function _get_content_type()
{
if ($this->mailtype === 'html')
{
return empty($this->_attachments) ? 'html' : 'html-attach';
}
elseif ($this->mailtype === 'text' && ! empty($this->_attachments))
{
return 'plain-attach';
}
return 'plain';
}
// --------------------------------------------------------------------
/**
* Set RFC 822 Date
*
* @return string
*/
protected function _set_date()
{
$timezone = date('Z');
$operator = ($timezone[0] === '-') ? '-' : '+';
$timezone = abs($timezone);
$timezone = floor($timezone/3600) * 100 + ($timezone % 3600) / 60;
return sprintf('%s %s%04d', date('D, j M Y H:i:s'), $operator, $timezone);
}
// --------------------------------------------------------------------
/**
* Mime message
*
* @return string
*/
protected function _get_mime_message()
{
return 'This is a multi-part message in MIME format.'.$this->newline.'Your email application may not support this format.';
}
// --------------------------------------------------------------------
/**
* Validate Email Address
*
* @param string
* @return bool
*/
public function validate_email($email)
{
if ( ! is_array($email))
{
$this->_set_error_message('lang:email_must_be_array');
return FALSE;
}
foreach ($email as $val)
{
if ( ! $this->valid_email($val))
{
$this->_set_error_message('lang:email_invalid_address', $val);
return FALSE;
}
}
return TRUE;
}
// --------------------------------------------------------------------
/**
* Email Validation
*
* @param string
* @return bool
*/
public function valid_email($email)
{
if (function_exists('idn_to_ascii') && strpos($email, '@'))
{
list($account, $domain) = explode('@', $email, 2);
$domain = defined('INTL_IDNA_VARIANT_UTS46')
? idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46)
: idn_to_ascii($domain);
if ($domain !== FALSE)
{
$email = $account.'@'.$domain;
}
}
return (bool) filter_var($email, FILTER_VALIDATE_EMAIL);
}
// --------------------------------------------------------------------
/**
* Clean Extended Email Address: Joe Smith
*
* @param string
* @return string
*/
public function clean_email($email)
{
if ( ! is_array($email))
{
return preg_match('/\<(.*)\>/', $email, $match) ? $match[1] : $email;
}
$clean_email = array();
foreach ($email as $addy)
{
$clean_email[] = preg_match('/\<(.*)\>/', $addy, $match) ? $match[1] : $addy;
}
return $clean_email;
}
// --------------------------------------------------------------------
/**
* Build alternative plain text message
*
* Provides the raw message for use in plain-text headers of
* HTML-formatted emails.
* If the user hasn't specified his own alternative message
* it creates one by stripping the HTML
*
* @return string
*/
protected function _get_alt_message()
{
if ( ! empty($this->alt_message))
{
return ($this->wordwrap)
? $this->word_wrap($this->alt_message, 76)
: $this->alt_message;
}
$body = preg_match('/\(.*)\<\/body\>/si', $this->_body, $match) ? $match[1] : $this->_body;
$body = str_replace("\t", '', preg_replace('# '.$message.PHP_EOL;
}
// --------------------------------------------------------------------
/**
* Byte-safe strlen()
*
* @param string $str
* @return int
*/
protected static function strlen($str)
{
return (self::$func_overload)
? mb_strlen($str, '8bit')
: strlen($str);
}
// --------------------------------------------------------------------
/**
* Byte-safe substr()
*
* @param string $str
* @param int $start
* @param int $length
* @return string
*/
protected static function substr($str, $start, $length = NULL)
{
if (self::$func_overload)
{
// mb_substr($str, $start, null, '8bit') returns an empty
// string on PHP 5.3
isset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start);
return mb_substr($str, $start, $length, '8bit');
}
return isset($length)
? substr($str, $start, $length)
: substr($str, $start);
}
}
PK ! (@Ëõa3 a3 core/Router.phpnu „[µü¤ config =& load_class('Config', 'core');
$this->uri =& load_class('URI', 'core');
$this->enable_query_strings = ( ! is_cli() && $this->config->item('enable_query_strings') === TRUE);
// If a directory override is configured, it has to be set before any dynamic routing logic
is_array($routing) && isset($routing['directory']) && $this->set_directory($routing['directory']);
$this->_set_routing();
// Set any routing overrides that may exist in the main index file
if (is_array($routing))
{
empty($routing['controller']) OR $this->set_class($routing['controller']);
empty($routing['function']) OR $this->set_method($routing['function']);
}
log_message('info', 'Router Class Initialized');
}
// --------------------------------------------------------------------
/**
* Set route mapping
*
* Determines what should be served based on the URI request,
* as well as any "routes" that have been set in the routing config file.
*
* @return void
*/
protected function _set_routing()
{
// Load the routes.php file. It would be great if we could
// skip this for enable_query_strings = TRUE, but then
// default_controller would be empty ...
if (file_exists(APPPATH.'config/routes.php'))
{
include(APPPATH.'config/routes.php');
}
if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/routes.php'))
{
include(APPPATH.'config/'.ENVIRONMENT.'/routes.php');
}
// Validate & get reserved routes
if (isset($route) && is_array($route))
{
isset($route['default_controller']) && $this->default_controller = $route['default_controller'];
isset($route['translate_uri_dashes']) && $this->translate_uri_dashes = $route['translate_uri_dashes'];
unset($route['default_controller'], $route['translate_uri_dashes']);
$this->routes = $route;
}
// Are query strings enabled in the config file? Normally CI doesn't utilize query strings
// since URI segments are more search-engine friendly, but they can optionally be used.
// If this feature is enabled, we will gather the directory/class/method a little differently
if ($this->enable_query_strings)
{
// If the directory is set at this time, it means an override exists, so skip the checks
if ( ! isset($this->directory))
{
$_d = $this->config->item('directory_trigger');
$_d = isset($_GET[$_d]) ? trim($_GET[$_d], " \t\n\r\0\x0B/") : '';
if ($_d !== '')
{
$this->uri->filter_uri($_d);
$this->set_directory($_d);
}
}
$_c = trim($this->config->item('controller_trigger'));
if ( ! empty($_GET[$_c]))
{
$this->uri->filter_uri($_GET[$_c]);
$this->set_class($_GET[$_c]);
$_f = trim($this->config->item('function_trigger'));
if ( ! empty($_GET[$_f]))
{
$this->uri->filter_uri($_GET[$_f]);
$this->set_method($_GET[$_f]);
}
$this->uri->rsegments = array(
1 => $this->class,
2 => $this->method
);
}
else
{
$this->_set_default_controller();
}
// Routing rules don't apply to query strings and we don't need to detect
// directories, so we're done here
return;
}
// Is there anything to parse?
if ($this->uri->uri_string !== '')
{
$this->_parse_routes();
}
else
{
$this->_set_default_controller();
}
}
// --------------------------------------------------------------------
/**
* Set request route
*
* Takes an array of URI segments as input and sets the class/method
* to be called.
*
* @used-by CI_Router::_parse_routes()
* @param array $segments URI segments
* @return void
*/
protected function _set_request($segments = array())
{
$segments = $this->_validate_request($segments);
// If we don't have any segments left - try the default controller;
// WARNING: Directories get shifted out of the segments array!
if (empty($segments))
{
$this->_set_default_controller();
return;
}
if ($this->translate_uri_dashes === TRUE)
{
$segments[0] = str_replace('-', '_', $segments[0]);
if (isset($segments[1]))
{
$segments[1] = str_replace('-', '_', $segments[1]);
}
}
$this->set_class($segments[0]);
if (isset($segments[1]))
{
$this->set_method($segments[1]);
}
else
{
$segments[1] = 'index';
}
array_unshift($segments, NULL);
unset($segments[0]);
$this->uri->rsegments = $segments;
}
// --------------------------------------------------------------------
/**
* Set default controller
*
* @return void
*/
protected function _set_default_controller()
{
if (empty($this->default_controller))
{
show_error('Unable to determine what should be displayed. A default route has not been specified in the routing file.');
}
// Is the method being specified?
if (sscanf($this->default_controller, '%[^/]/%s', $class, $method) !== 2)
{
$method = 'index';
}
if ( ! file_exists(APPPATH.'controllers/'.$this->directory.ucfirst($class).'.php'))
{
// This will trigger 404 later
return;
}
$this->set_class($class);
$this->set_method($method);
// Assign routed segments, index starting from 1
$this->uri->rsegments = array(
1 => $class,
2 => $method
);
log_message('debug', 'No URI present. Default controller set.');
}
// --------------------------------------------------------------------
/**
* Validate request
*
* Attempts validate the URI request and determine the controller path.
*
* @used-by CI_Router::_set_request()
* @param array $segments URI segments
* @return mixed URI segments
*/
protected function _validate_request($segments)
{
$c = count($segments);
$directory_override = isset($this->directory);
// Loop through our segments and return as soon as a controller
// is found or when such a directory doesn't exist
while ($c-- > 0)
{
$test = $this->directory
.ucfirst($this->translate_uri_dashes === TRUE ? str_replace('-', '_', $segments[0]) : $segments[0]);
if ( ! file_exists(APPPATH.'controllers/'.$test.'.php')
&& $directory_override === FALSE
&& is_dir(APPPATH.'controllers/'.$this->directory.$segments[0])
)
{
$this->set_directory(array_shift($segments), TRUE);
continue;
}
return $segments;
}
// This means that all segments were actually directories
return $segments;
}
// --------------------------------------------------------------------
/**
* Parse Routes
*
* Matches any routes that may exist in the config/routes.php file
* against the URI to determine if the class/method need to be remapped.
*
* @return void
*/
protected function _parse_routes()
{
// Turn the segment array into a URI string
$uri = implode('/', $this->uri->segments);
// Get HTTP verb
$http_verb = isset($_SERVER['REQUEST_METHOD']) ? strtolower($_SERVER['REQUEST_METHOD']) : 'cli';
// Loop through the route array looking for wildcards
foreach ($this->routes as $key => $val)
{
// Check if route format is using HTTP verbs
if (is_array($val))
{
$val = array_change_key_case($val, CASE_LOWER);
if (isset($val[$http_verb]))
{
$val = $val[$http_verb];
}
else
{
continue;
}
}
// Convert wildcards to RegEx
$key = str_replace(array(':any', ':num'), array('[^/]+', '[0-9]+'), $key);
// Does the RegEx match?
if (preg_match('#^'.$key.'$#', $uri, $matches))
{
// Are we using callbacks to process back-references?
if ( ! is_string($val) && is_callable($val))
{
// Remove the original string from the matches array.
array_shift($matches);
// Execute the callback using the values in matches as its parameters.
$val = call_user_func_array($val, $matches);
}
// Are we using the default routing method for back-references?
elseif (strpos($val, '$') !== FALSE && strpos($key, '(') !== FALSE)
{
$val = preg_replace('#^'.$key.'$#', $val, $uri);
}
$this->_set_request(explode('/', $val));
return;
}
}
// If we got this far it means we didn't encounter a
// matching route so we'll set the site default route
$this->_set_request(array_values($this->uri->segments));
}
// --------------------------------------------------------------------
/**
* Set class name
*
* @param string $class Class name
* @return void
*/
public function set_class($class)
{
$this->class = str_replace(array('/', '.'), '', $class);
}
// --------------------------------------------------------------------
/**
* Fetch the current class
*
* @deprecated 3.0.0 Read the 'class' property instead
* @return string
*/
public function fetch_class()
{
return $this->class;
}
// --------------------------------------------------------------------
/**
* Set method name
*
* @param string $method Method name
* @return void
*/
public function set_method($method)
{
$this->method = $method;
}
// --------------------------------------------------------------------
/**
* Fetch the current method
*
* @deprecated 3.0.0 Read the 'method' property instead
* @return string
*/
public function fetch_method()
{
return $this->method;
}
// --------------------------------------------------------------------
/**
* Set directory name
*
* @param string $dir Directory name
* @param bool $append Whether we're appending rather than setting the full value
* @return void
*/
public function set_directory($dir, $append = FALSE)
{
if ($append !== TRUE OR empty($this->directory))
{
$this->directory = str_replace('.', '', trim($dir, '/')).'/';
}
else
{
$this->directory .= str_replace('.', '', trim($dir, '/')).'/';
}
}
// --------------------------------------------------------------------
/**
* Fetch directory
*
* Feches the sub-directory (if any) that contains the requested
* controller class.
*
* @deprecated 3.0.0 Read the 'directory' property instead
* @return string
*/
public function fetch_directory()
{
return $this->directory;
}
}
PK ! Èã¨Þq Þq core/Security.phpnu „[µü¤ ', '<', '>',
"'", '"', '&', '$', '#',
'{', '}', '[', ']', '=',
';', '?', '%20', '%22',
'%3c', // <
'%253c', // <
'%3e', // >
'%0e', // >
'%28', // (
'%29', // )
'%2528', // (
'%26', // &
'%24', // $
'%3f', // ?
'%3b', // ;
'%3d' // =
);
/**
* Character set
*
* Will be overridden by the constructor.
*
* @var string
*/
public $charset = 'UTF-8';
/**
* XSS Hash
*
* Random Hash for protecting URLs.
*
* @var string
*/
protected $_xss_hash;
/**
* CSRF Hash
*
* Random hash for Cross Site Request Forgery protection cookie
*
* @var string
*/
protected $_csrf_hash;
/**
* CSRF Expire time
*
* Expiration time for Cross Site Request Forgery protection cookie.
* Defaults to two hours (in seconds).
*
* @var int
*/
protected $_csrf_expire = 7200;
/**
* CSRF Token name
*
* Token name for Cross Site Request Forgery protection cookie.
*
* @var string
*/
protected $_csrf_token_name = 'ci_csrf_token';
/**
* CSRF Cookie name
*
* Cookie name for Cross Site Request Forgery protection cookie.
*
* @var string
*/
protected $_csrf_cookie_name = 'ci_csrf_token';
/**
* List of never allowed strings
*
* @var array
*/
protected $_never_allowed_str = array(
'document.cookie' => '[removed]',
'(document).cookie' => '[removed]',
'document.write' => '[removed]',
'(document).write' => '[removed]',
'.parentNode' => '[removed]',
'.innerHTML' => '[removed]',
'-moz-binding' => '[removed]',
'' => '-->',
' '<![CDATA[',
'' => '<comment>',
'<%' => '<%'
);
/**
* List of never allowed regex replacements
*
* @var array
*/
protected $_never_allowed_regex = array(
'javascript\s*:',
'(\(?document\)?|\(?window\)?(\.document)?)\.(location|on\w*)',
'expression\s*(\(|&\#40;)', // CSS and IE
'vbscript\s*:', // IE, surprise!
'wscript\s*:', // IE
'jscript\s*:', // IE
'vbs\s*:', // IE
'Redirect\s+30\d',
"([\"'])?data\s*:[^\\1]*?base64[^\\1]*?,[^\\1]*?\\1?"
);
/**
* Class constructor
*
* @return void
*/
public function __construct()
{
// Is CSRF protection enabled?
if (config_item('csrf_protection'))
{
// CSRF config
foreach (array('csrf_expire', 'csrf_token_name', 'csrf_cookie_name') as $key)
{
if (NULL !== ($val = config_item($key)))
{
$this->{'_'.$key} = $val;
}
}
// Append application specific cookie prefix
if ($cookie_prefix = config_item('cookie_prefix'))
{
$this->_csrf_cookie_name = $cookie_prefix.$this->_csrf_cookie_name;
}
// Set the CSRF hash
$this->_csrf_set_hash();
}
$this->charset = strtoupper(config_item('charset'));
log_message('info', 'Security Class Initialized');
}
// --------------------------------------------------------------------
/**
* CSRF Verify
*
* @return CI_Security
*/
public function csrf_verify()
{
// If it's not a POST request we will set the CSRF cookie
if (strtoupper($_SERVER['REQUEST_METHOD']) !== 'POST')
{
return $this->csrf_set_cookie();
}
// Check if URI has been whitelisted from CSRF checks
if ($exclude_uris = config_item('csrf_exclude_uris'))
{
$uri = load_class('URI', 'core');
foreach ($exclude_uris as $excluded)
{
if (preg_match('#^'.$excluded.'$#i'.(UTF8_ENABLED ? 'u' : ''), $uri->uri_string()))
{
return $this;
}
}
}
// Check CSRF token validity, but don't error on mismatch just yet - we'll want to regenerate
$valid = isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name])
&& is_string($_POST[$this->_csrf_token_name]) && is_string($_COOKIE[$this->_csrf_cookie_name])
&& hash_equals($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name]);
// We kill this since we're done and we don't want to pollute the _POST array
unset($_POST[$this->_csrf_token_name]);
// Regenerate on every submission?
if (config_item('csrf_regenerate'))
{
// Nothing should last forever
unset($_COOKIE[$this->_csrf_cookie_name]);
$this->_csrf_hash = NULL;
}
$this->_csrf_set_hash();
$this->csrf_set_cookie();
if ($valid !== TRUE)
{
$this->csrf_show_error();
}
log_message('info', 'CSRF token verified');
return $this;
}
// --------------------------------------------------------------------
/**
* CSRF Set Cookie
*
* @codeCoverageIgnore
* @return CI_Security
*/
public function csrf_set_cookie()
{
$expire = time() + $this->_csrf_expire;
$secure_cookie = (bool) config_item('cookie_secure');
if ($secure_cookie && ! is_https())
{
return FALSE;
}
setcookie(
$this->_csrf_cookie_name,
$this->_csrf_hash,
$expire,
config_item('cookie_path'),
config_item('cookie_domain'),
$secure_cookie,
config_item('cookie_httponly')
);
log_message('info', 'CSRF cookie sent');
return $this;
}
// --------------------------------------------------------------------
/**
* Show CSRF Error
*
* @return void
*/
public function csrf_show_error()
{
show_error('The action you have requested is not allowed.', 403);
}
// --------------------------------------------------------------------
/**
* Get CSRF Hash
*
* @see CI_Security::$_csrf_hash
* @return string CSRF hash
*/
public function get_csrf_hash()
{
return $this->_csrf_hash;
}
// --------------------------------------------------------------------
/**
* Get CSRF Token Name
*
* @see CI_Security::$_csrf_token_name
* @return string CSRF token name
*/
public function get_csrf_token_name()
{
return $this->_csrf_token_name;
}
// --------------------------------------------------------------------
/**
* XSS Clean
*
* Sanitizes data so that Cross Site Scripting Hacks can be
* prevented. This method does a fair amount of work but
* it is extremely thorough, designed to prevent even the
* most obscure XSS attempts. Nothing is ever 100% foolproof,
* of course, but I haven't been able to get anything passed
* the filter.
*
* Note: Should only be used to deal with data upon submission.
* It's not something that should be used for general
* runtime processing.
*
* @link http://channel.bitflux.ch/wiki/XSS_Prevention
* Based in part on some code and ideas from Bitflux.
*
* @link http://ha.ckers.org/xss.html
* To help develop this script I used this great list of
* vulnerabilities along with a few other hacks I've
* harvested from examining vulnerabilities in other programs.
*
* @param string|string[] $str Input data
* @param bool $is_image Whether the input is an image
* @return string
*/
public function xss_clean($str, $is_image = FALSE)
{
// Is the string an array?
if (is_array($str))
{
foreach ($str as $key => &$value)
{
$str[$key] = $this->xss_clean($value);
}
return $str;
}
// Remove Invisible Characters
$str = remove_invisible_characters($str);
/*
* URL Decode
*
* Just in case stuff like this is submitted:
*
* Google
*
* Note: Use rawurldecode() so it does not remove plus signs
*/
if (stripos($str, '%') !== false)
{
do
{
$oldstr = $str;
$str = rawurldecode($str);
$str = preg_replace_callback('#%(?:\s*[0-9a-f]){2,}#i', array($this, '_urldecodespaces'), $str);
}
while ($oldstr !== $str);
unset($oldstr);
}
/*
* Convert character entities to ASCII
*
* This permits our tests below to work reliably.
* We only convert entities that are within tags since
* these are the ones that will pose security problems.
*/
$str = preg_replace_callback("/[^a-z0-9>]+[a-z0-9]+=([\'\"]).*?\\1/si", array($this, '_convert_attribute'), $str);
$str = preg_replace_callback('/<\w+.*/si', array($this, '_decode_entity'), $str);
// Remove Invisible Characters Again!
$str = remove_invisible_characters($str);
/*
* Convert all tabs to spaces
*
* This prevents strings like this: ja vascript
* NOTE: we deal with spaces between characters later.
* NOTE: preg_replace was found to be amazingly slow here on
* large blocks of data, so we use str_replace.
*/
$str = str_replace("\t", ' ', $str);
// Capture converted string for later comparison
$converted_string = $str;
// Remove Strings that are never allowed
$str = $this->_do_never_allowed($str);
/*
* Makes PHP tags safe
*
* Note: XML tags are inadvertently replaced too:
*
* '), array('<?', '?>'), $str);
}
/*
* Compact any exploded words
*
* This corrects words like: j a v a s c r i p t
* These words are compacted back to their correct state.
*/
$words = array(
'javascript', 'expression', 'vbscript', 'jscript', 'wscript',
'vbs', 'script', 'base64', 'applet', 'alert', 'document',
'write', 'cookie', 'window', 'confirm', 'prompt', 'eval'
);
foreach ($words as $word)
{
$word = implode('\s*', str_split($word)).'\s*';
// We only want to do this when it is followed by a non-word character
// That way valid stuff like "dealer to" does not become "dealerto"
$str = preg_replace_callback('#('.substr($word, 0, -3).')(\W)#is', array($this, '_compact_exploded_words'), $str);
}
/*
* Remove disallowed Javascript in links or img tags
* We used to do some version comparisons and use of stripos(),
* but it is dog slow compared to these simplified non-capturing
* preg_match(), especially if the pattern exists in the string
*
* Note: It was reported that not only space characters, but all in
* the following pattern can be parsed as separators between a tag name
* and its attributes: [\d\s"\'`;,\/\=\(\x00\x0B\x09\x0C]
* ... however, remove_invisible_characters() above already strips the
* hex-encoded ones, so we'll skip them below.
*/
do
{
$original = $str;
if (preg_match('/]+([^>]*?)(?:>|$)#si', array($this, '_js_link_removal'), $str);
}
if (preg_match('/]*?)(?:\s?/?>|$)#si', array($this, '_js_img_removal'), $str);
}
if (preg_match('/script|xss/i', $str))
{
$str = preg_replace('#*(?:script|xss).*?>#si', '[removed]', $str);
}
}
while ($original !== $str);
unset($original);
/*
* Sanitize naughty HTML elements
*
* If a tag containing any of the words in the list
* below is found, the tag gets converted to entities.
*
* So this: